Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC11C24 проблема с большим массивом
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
yanvasiij
Доброго времени суток!

Суть проблемы в следующем. Использую проц 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
Цитата(yanvasiij @ Sep 8 2014, 16:57) *
А нельзя ли всё это хозяйство разместить во flash?
Покажите прототип функции в которую вы передаёте указатель на этот массив...
Integro
Нужно больше инфы, типовая ошибка при hard_fault это выход за пределы массива(стека).
Приведите пример использования.
Массив инициализируется однажды?
KRS
Цитата(demiurg_spb @ Sep 8 2014, 17:40) *
А нельзя ли всё это хозяйство разместить во flash?

Так в общем и должно во флеше лежать.
можно как const эти структуры объявлять.
yanvasiij
Нет во флеше хранить нельзя. Объектный словарь содержит переменные, которые меняются (показания ацп, коэффициенты фильтров настраиваемые пользоваетелем и т.д.).
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
Цитата(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;


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

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


каждый value_pointer ссылается на 4 байта данных, данных много да, но величина данных на которые ссылается указатель никак не влияет на размер массива указателей. Массив указателей большой (точнее это с структура с указателями, но не суть), это да, данных на которые ссылаются указатели тоже много. Но в память проца все влезает, я проверял. Тем более, что кейл, если не использовать динамическое выделение памяти, сразу выдасть ошибку, если памяти не хватит. Или я чего неправильно понимаю? А вот критично или нет размер массива вот это тот самый вопрос, который меня сейчас занимает. Если да критично, то где про размер этого самого критичного можно почитать?
yanvasiij
demiurg_spb

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

Я конечно могу выложить исходники, но я не готов оплатить лечение от рака мозга, которым можно будет заболеть при их просмотре.
demiurg_spb
Компилятор вам не сможет дать никаких сообщений если вы явно не резервируете достаточно место под стек (бывает в опциях проекта или makefile)
и фактически место для стека становится недостаточно из-за раздувания секции BSS.
Для локализации проблемы вы можете использовать отладчик и исполнять программу в шаговом режиме, либо написать обработчик прерывания hard_fault и вывести в консоль состояния регистров в момент исключения....
yanvasiij
Цитата(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.
Dejmos
Цитата(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. Хотя я упустил один момент - куда эти структуры передаются и сможет ли этот код работать с невыровненной структурой. Но это уже отдельный вопрос.
KRS
Цитата(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 байт

adnega
Цитата(yanvasiij @ Sep 9 2014, 15:50) *
Что же, последую Вашему совету попробую написать обработчик hard_fault.

Написали обработчик HardFault?
А что с другими прерываниями? Разрешены/запрещены на момент конфигурирования?
Может возникает прерывание при неполной загрузке структуры? Линия активна, есть другие передающие узлы в сети?
yanvasiij
Вообщем дело было не в бобине... У этого проца ограничение на количество ячеек в железном объетном словаре. Я упустил этот момент в аппноте. Прошу прощения blush.gif . Спасибо всем, кто откликнулся.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.