Перейти к содержанию
    

LPC11C24 проблема с большим массивом

Доброго времени суток!

 

Суть проблемы в следующем. Использую проц 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 в этом проекте не использую. Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А нельзя ли всё это хозяйство разместить во flash?

Покажите прототип функции в которую вы передаёте указатель на этот массив...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно больше инфы, типовая ошибка при hard_fault это выход за пределы массива(стека).

Приведите пример использования.

Массив инициализируется однажды?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А нельзя ли всё это хозяйство разместить во flash?

Так в общем и должно во флеше лежать.

можно как const эти структуры объявлять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет во флеше хранить нельзя. Объектный словарь содержит переменные, которые меняются (показания ацп, коэффициенты фильтров настраиваемые пользоваетелем и т.д.).

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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет во флеше хранить нельзя. Объектный словарь содержит переменные, которые меняются (показания ацп, коэффициенты фильтров настраиваемые пользоваетелем и т.д.).

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;

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Нет, не помогло. Дело не в этом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, не помогло. Дело не в этом.
Что значит не помогло?

Сколько ОЗУ было использовано до и сколько стало после?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

demiurg_spb

 

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

 

Я конечно могу выложить исходники, но я не готов оплатить лечение от рака мозга, которым можно будет заболеть при их просмотре.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Компилятор вам не сможет дать никаких сообщений если вы явно не резервируете достаточно место под стек (бывает в опциях проекта или makefile)

и фактически место для стека становится недостаточно из-за раздувания секции BSS.

Для локализации проблемы вы можете использовать отладчик и исполнять программу в шаговом режиме, либо написать обработчик прерывания hard_fault и вывести в консоль состояния регистров в момент исключения....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Компилятор вам не сможет дать никаких сообщений если вы явно не резервируете достаточно место под стек (бывает в опциях проекта или 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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

каждый 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я имел в виду то, что каждое поле структуры может занимать по 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 байт

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...