yanvasilij 0 8 сентября, 2014 Опубликовано 8 сентября, 2014 · Жалоба Доброго времени суток! Суть проблемы в следующем. Использую проц 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 в этом проекте не использую. Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 8 сентября, 2014 Опубликовано 8 сентября, 2014 · Жалоба А нельзя ли всё это хозяйство разместить во flash? Покажите прототип функции в которую вы передаёте указатель на этот массив... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 8 сентября, 2014 Опубликовано 8 сентября, 2014 · Жалоба Нужно больше инфы, типовая ошибка при hard_fault это выход за пределы массива(стека). Приведите пример использования. Массив инициализируется однажды? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 0 8 сентября, 2014 Опубликовано 8 сентября, 2014 · Жалоба А нельзя ли всё это хозяйство разместить во flash? Так в общем и должно во флеше лежать. можно как const эти структуры объявлять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба Нет во флеше хранить нельзя. Объектный словарь содержит переменные, которые меняются (показания ацп, коэффициенты фильтров настраиваемые пользоваетелем и т.д.). 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба Нет во флеше хранить нельзя. Объектный словарь содержит переменные, которые меняются (показания ацп, коэффициенты фильтров настраиваемые пользоваетелем и т.д.). 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба demiurg_spb Справедливое замечание, не подумал об этом. Спасибо! Сейчас по-пробую... Нет, не помогло. Дело не в этом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dejmos 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба Keil'ом не пользуюсь, но все таки... какое выравнивание задано при объявлении структуры? Если там вдруг 4 байта, то каждый элемент получится по 16 байт, итого у вас массив займет примерно 4кб, что для контроллера с 8кб RAM может быть очень критично. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба Нет, не помогло. Дело не в этом.Что значит не помогло? Сколько ОЗУ было использовано до и сколько стало после? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба Keil'ом не пользуюсь, но все таки... какое выравнивание задано при объявлении структуры? Если там вдруг 4 байта, то каждый элемент получится по 16 байт, итого у вас массив займет примерно 4кб, что для контроллера с 8кб RAM может быть очень критично. каждый value_pointer ссылается на 4 байта данных, данных много да, но величина данных на которые ссылается указатель никак не влияет на размер массива указателей. Массив указателей большой (точнее это с структура с указателями, но не суть), это да, данных на которые ссылаются указатели тоже много. Но в память проца все влезает, я проверял. Тем более, что кейл, если не использовать динамическое выделение памяти, сразу выдасть ошибку, если памяти не хватит. Или я чего неправильно понимаю? А вот критично или нет размер массива вот это тот самый вопрос, который меня сейчас занимает. Если да критично, то где про размер этого самого критичного можно почитать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба demiurg_spb Освободилось 2072 байт ОЗУ. И это здорово! Спасибо, замечание действительно было уместное! Однако программа все равно не стартует, если размер массива больше 243 элементов. Я конечно могу выложить исходники, но я не готов оплатить лечение от рака мозга, которым можно будет заболеть при их просмотре. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба Компилятор вам не сможет дать никаких сообщений если вы явно не резервируете достаточно место под стек (бывает в опциях проекта или makefile) и фактически место для стека становится недостаточно из-за раздувания секции BSS. Для локализации проблемы вы можете использовать отладчик и исполнять программу в шаговом режиме, либо написать обработчик прерывания hard_fault и вывести в консоль состояния регистров в момент исключения.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба Компилятор вам не сможет дать никаких сообщений если вы явно не резервируете достаточно место под стек (бывает в опциях проекта или 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dejmos 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 (изменено) · Жалоба каждый 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. Хотя я упустил один момент - куда эти структуры передаются и сможет ли этот код работать с невыровненной структурой. Но это уже отдельный вопрос. Изменено 9 сентября, 2014 пользователем Dejmos Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 0 9 сентября, 2014 Опубликовано 9 сентября, 2014 · Жалоба Я имел в виду то, что каждое поле структуры может занимать по 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 байт Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться