|
LPC11C24 проблема с большим массивом, Программа выпадает в hardfault при работе с большим массивом |
|
|
|
Sep 8 2014, 12:57
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Доброго времени суток! Суть проблемы в следующем. Использую проц lpc11c24 и его встроенный CANopen. Для инициализации этого CANopen его железным API нужно передать многомерную структуру, в которой находится объектный словарь устройства: Код typedef struct _CAN_ODENTRY { uint16_t index; uint8_t subindex; uint8_t entrytype_len; uint8_t *val; }CAN_ODENTRY; Мне потребовался очень большой объектный словарь. Он все рос и рос, пока в один определенный момент все не перестало работать. В этот момент общее число членов многомерной структуры превысило 243. Что делать, а? Пробовал увеличить стек в startup_LPC11xx.s, но при любых увеличениях значения Stack_Size ничего вообще не стартует, а так рушится при инициализации CANopen. Компилятор keil. RTOS в этом проекте не использую. Спасибо!
|
|
|
|
|
Sep 9 2014, 04:16
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Нет во флеше хранить нельзя. Объектный словарь содержит переменные, которые меняются (показания ацп, коэффициенты фильтров настраиваемые пользоваетелем и т.д.). Integro да массив инициализируется: Код CAN_ODENTRY objDic [] = { /* index, subindex access_type | length, value_pointer */ { 0x1000, 0x00, OD_EXP_RO | 4, (uint8_t *)&deviceType }, { 0x1800, 0x02, OD_EXP_RW | 4, (uint8_t *)&transmitionType }, { 0x1800, 0x03, OD_EXP_RW | 4, (uint8_t *)&inhibitTime },
{ SE_1_INDEX, 0x00, OD_EXP_RO | 4, (uint8_t *)&numOfSeSubIndexes }, { SE_1_INDEX, SE_ON_SUBINDEX, OD_EXP_RW | 4, (uint8_t *)&se1Enable }, { SE_1_INDEX, SE_GAIN_SUBINDEX, OD_EXP_RW | 4, (uint8_t *)&se1Gain }, { SE_1_INDEX, SE_CURRENT_OPTION, OD_EXP_RW | 4, (uint8_t *)&se1CurrentOption }, { SE_1_INDEX, SE_SAMPLING_TIME, OD_EXP_RW | 4, (uint8_t *)&se1SamplingTimeUs }, { SE_1_INDEX, USE_IIR_SUBINDEX, OD_EXP_RW | 4, (uint8_t *)&se1UseIir }, { SE_1_INDEX, IIR_A0, OD_EXP_RW | 4, (uint8_t *)&se1A0 }, { SE_1_INDEX, IIR_A1, OD_EXP_RW | 4, (uint8_t *)&se1A1 }, { SE_1_INDEX, IIR_A2, OD_EXP_RW | 4, (uint8_t *)&se1A2 }, { SE_1_INDEX, IIR_A3, OD_EXP_RW | 4, (uint8_t *)&se1A3 }, { SE_1_INDEX, IIR_B0, OD_EXP_RW | 4, (uint8_t *)&se1B0 }, { SE_1_INDEX, IIR_B1, OD_EXP_RW | 4, (uint8_t *)&se1B1 }, { SE_1_INDEX, IIR_B2, OD_EXP_RW | 4, (uint8_t *)&se1B2 }, ... и так далее всего 259 элементов. } Потом вся эта штука помещается в другую структуру: Код CAN_CANOPENCFG canOpenConfigStruct = { 1, // node_id 5, // msgobj_rx 6, // msgobj_tx 1, // isr_handled sizeof(constObjDic)/sizeof(constObjDic[0]), // od_const_num (CAN_ODCONSTENTRY *)constObjDic, // od_const_table sizeof(objDic)/sizeof(objDic[0]), // od_num (CAN_ODENTRY *)objDic, // od_table }; Последняя структура передается железной API как параметр: Код ROM **rom = (ROM **)0x1fff1ff8; ... (*rom)->pCAND->config_canopen((CAN_CANOPENCFG *)&canOpenConfigStruct); ... Так вот эта функция вызывает крах программы при вызове, что там внутри происходит отладить возможности нет (во-первых нет отладчика, во вторых она железная, находится где-то внутри проца). Крах появляется, когда общее число элементов в структуре CAN_ODENTRY objDic [] становится больше 243.
|
|
|
|
|
Sep 9 2014, 07:18
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(yanvasiij @ Sep 9 2014, 08:16)  Нет во флеше хранить нельзя. Объектный словарь содержит переменные, которые меняются (показания ацп, коэффициенты фильтров настраиваемые пользоваетелем и т.д.). Integro да массив инициализируется: Код CAN_ODENTRY objDic [] = { /* index, subindex access_type | length, value_pointer */ { 0x1000, 0x00, OD_EXP_RO | 4, (uint8_t *)&deviceType }, { 0x1800, 0x02, OD_EXP_RW | 4, (uint8_t *)&transmitionType }, { 0x1800, 0x03, OD_EXP_RW | 4, (uint8_t *)&inhibitTime }, ... Но я не вижу тут переменных. Тут лишь указатели на них, а они могут быть константными указателями на переменную: Код int var; int* const ptr = &var;
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 9 2014, 11:21
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(Dejmos @ Sep 9 2014, 15:57)  Keil'ом не пользуюсь, но все таки... какое выравнивание задано при объявлении структуры? Если там вдруг 4 байта, то каждый элемент получится по 16 байт, итого у вас массив займет примерно 4кб, что для контроллера с 8кб RAM может быть очень критично. каждый value_pointer ссылается на 4 байта данных, данных много да, но величина данных на которые ссылается указатель никак не влияет на размер массива указателей. Массив указателей большой (точнее это с структура с указателями, но не суть), это да, данных на которые ссылаются указатели тоже много. Но в память проца все влезает, я проверял. Тем более, что кейл, если не использовать динамическое выделение памяти, сразу выдасть ошибку, если памяти не хватит. Или я чего неправильно понимаю? А вот критично или нет размер массива вот это тот самый вопрос, который меня сейчас занимает. Если да критично, то где про размер этого самого критичного можно почитать?
|
|
|
|
|
Sep 9 2014, 11:50
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(demiurg_spb @ Sep 9 2014, 17:30)  Компилятор вам не сможет дать никаких сообщений если вы явно не резервируете достаточно место под стек (бывает в опциях проекта или makefile) и фактически место для стека становится недостаточно из-за раздувания секции BSS. Для локализации проблемы вы можете использовать отладчик и исполнять программу в шаговом режиме, либо написать обработчик прерывания hard_fault и вывести в консоль состояния регистров в момент исключения.... Вот что говорит компилятор до переноса во флеш: Код Program Size: Code=16872 RO-data=492 RW-data=2820 ZI-data=4924 А вот, что после (написал const перед многомерной структурой): Код Program Size: Code=16872 RO-data=2308 RW-data=1004 ZI-data=4924 Итого порядка 2 кБ. Место под стек я резервирую в файле startup_LPC11xx.s (если я правильно понимаю). Он при компиляции он "откусит" общей памяти кусочек для стека. Просто, если грешить на стек, то логично попробовать его увеличить, а у меня все рушится при увеличении его в startup_LPC11xx.s. Что же, последую Вашему совету попробую написать обработчик hard_fault.
|
|
|
|
|
Sep 9 2014, 17:54
|

Частый гость
 
Группа: Свой
Сообщений: 100
Регистрация: 4-11-11
Из: Смоленск
Пользователь №: 68 137

|
Цитата(yanvasiij @ Sep 9 2014, 15:21)  каждый value_pointer ссылается на 4 байта данных, данных много да, но величина данных на которые ссылается указатель никак не влияет на размер массива указателей. Массив указателей большой (точнее это с структура с указателями, но не суть), это да, данных на которые ссылаются указатели тоже много. Но в память проца все влезает, я проверял. Тем более, что кейл, если не использовать динамическое выделение памяти, сразу выдасть ошибку, если памяти не хватит. Или я чего неправильно понимаю? А вот критично или нет размер массива вот это тот самый вопрос, который меня сейчас занимает. Если да критично, то где про размер этого самого критичного можно почитать? Я имел в виду то, что каждое поле структуры может занимать по 4 байта. Попробуйте проверить что выдаст sizeof(CAN_ODENTRY). Если выдаст больше восьми, то попробовать так: Код #pragma pack(push,1) typedef struct _CAN_ODENTRY { uint16_t index; uint8_t subindex; uint8_t entrytype_len; uint8_t *val; }CAN_ODENTRY; #pragma pack (pop) P.S. Хотя я упустил один момент - куда эти структуры передаются и сможет ли этот код работать с невыровненной структурой. Но это уже отдельный вопрос.
Сообщение отредактировал Dejmos - Sep 9 2014, 18:06
--------------------
* работаю так, что лошади оборачиваются *
|
|
|
|
|
Sep 9 2014, 20:53
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(Dejmos @ Sep 9 2014, 21:54)  Я имел в виду то, что каждое поле структуры может занимать по 4 байта. не может! они нормально описаны, выравнивание ничего не даст! Код #pragma pack(push,1) typedef struct _CAN_ODENTRY { uint16_t index; uint8_t subindex; uint8_t entrytype_len; uint8_t *val; }CAN_ODENTRY; #pragma pack (pop) размер этой структуры при любом выравнивании будет 8 байт
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|