реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> LPC11C24 проблема с большим массивом, Программа выпадает в hardfault при работе с большим массивом
yanvasiij
сообщение Sep 8 2014, 12:57
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 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 в этом проекте не использую. Спасибо!
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 8 2014, 13:40
Сообщение #2


неотягощённый злом
******

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



Цитата(yanvasiij @ Sep 8 2014, 16:57) *
А нельзя ли всё это хозяйство разместить во flash?
Покажите прототип функции в которую вы передаёте указатель на этот массив...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Integro
сообщение Sep 8 2014, 14:05
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 167
Регистрация: 25-12-09
Из: Минск
Пользователь №: 54 460



Нужно больше инфы, типовая ошибка при hard_fault это выход за пределы массива(стека).
Приведите пример использования.
Массив инициализируется однажды?
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 8 2014, 17:05
Сообщение #4


Профессионал
*****

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



Цитата(demiurg_spb @ Sep 8 2014, 17:40) *
А нельзя ли всё это хозяйство разместить во flash?

Так в общем и должно во флеше лежать.
можно как const эти структуры объявлять.
Go to the top of the page
 
+Quote Post
yanvasiij
сообщение Sep 9 2014, 04:16
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 9 2014, 07:18
Сообщение #6


неотягощённый злом
******

Группа: Свой
Сообщений: 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;




--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
yanvasiij
сообщение Sep 9 2014, 09:28
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



demiurg_spb Справедливое замечание, не подумал об этом. Спасибо! Сейчас по-пробую...

Нет, не помогло. Дело не в этом.
Go to the top of the page
 
+Quote Post
Dejmos
сообщение Sep 9 2014, 09:57
Сообщение #8


Частый гость
**

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



Keil'ом не пользуюсь, но все таки... какое выравнивание задано при объявлении структуры? Если там вдруг 4 байта, то каждый элемент получится по 16 байт, итого у вас массив займет примерно 4кб, что для контроллера с 8кб RAM может быть очень критично.


--------------------
* работаю так, что лошади оборачиваются *
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 9 2014, 11:16
Сообщение #9


неотягощённый злом
******

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



Цитата(yanvasiij @ Sep 9 2014, 13:28) *
Нет, не помогло. Дело не в этом.
Что значит не помогло?
Сколько ОЗУ было использовано до и сколько стало после?


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
yanvasiij
сообщение Sep 9 2014, 11:21
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



Цитата(Dejmos @ Sep 9 2014, 15:57) *
Keil'ом не пользуюсь, но все таки... какое выравнивание задано при объявлении структуры? Если там вдруг 4 байта, то каждый элемент получится по 16 байт, итого у вас массив займет примерно 4кб, что для контроллера с 8кб RAM может быть очень критично.


каждый value_pointer ссылается на 4 байта данных, данных много да, но величина данных на которые ссылается указатель никак не влияет на размер массива указателей. Массив указателей большой (точнее это с структура с указателями, но не суть), это да, данных на которые ссылаются указатели тоже много. Но в память проца все влезает, я проверял. Тем более, что кейл, если не использовать динамическое выделение памяти, сразу выдасть ошибку, если памяти не хватит. Или я чего неправильно понимаю? А вот критично или нет размер массива вот это тот самый вопрос, который меня сейчас занимает. Если да критично, то где про размер этого самого критичного можно почитать?
Go to the top of the page
 
+Quote Post
yanvasiij
сообщение Sep 9 2014, 11:21
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



demiurg_spb

Освободилось 2072 байт ОЗУ. И это здорово! Спасибо, замечание действительно было уместное! Однако программа все равно не стартует, если размер массива больше 243 элементов.

Я конечно могу выложить исходники, но я не готов оплатить лечение от рака мозга, которым можно будет заболеть при их просмотре.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 9 2014, 11:30
Сообщение #12


неотягощённый злом
******

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



Компилятор вам не сможет дать никаких сообщений если вы явно не резервируете достаточно место под стек (бывает в опциях проекта или makefile)
и фактически место для стека становится недостаточно из-за раздувания секции BSS.
Для локализации проблемы вы можете использовать отладчик и исполнять программу в шаговом режиме, либо написать обработчик прерывания hard_fault и вывести в консоль состояния регистров в момент исключения....


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
yanvasiij
сообщение Sep 9 2014, 11:50
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
Dejmos
сообщение Sep 9 2014, 17:54
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 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


--------------------
* работаю так, что лошади оборачиваются *
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 9 2014, 20:53
Сообщение #15


Профессионал
*****

Группа: Модераторы
Сообщений: 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 байт

Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 18:09
Рейтинг@Mail.ru


Страница сгенерированна за 0.01483 секунд с 7
ELECTRONIX ©2004-2016