Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Расположение массивов
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
SasaVitebsk
Столкнулся с проблемой. Сразу отмечу, что понимаю её корни и вижу несколько способов решения, но мне непонятно почему компилятор так поступает. Кто объяснит.

Смысл следующий. Я размещаю несколько массивов типа
Код
const    uint8_t        __rom        Roll0[]    =
{
  0xDA, 0x54, 0x00, 0x00, 0x01, 0x60, 0xea, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x23, 0x31, 0x5E,    //
  0xF7, 0x5E, 0x3A, 0x5E, 0xEC, 0x2E, 0x5E, 0xF1, 0x00, 0xDA, 0x54, 0x00, 0x00, 0x01, 0x60, 0xEA,    //
  0x08, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x23, 0x31, 0x5E, 0xC4, 0x2E, 0x5E, 0xCC, 0x2E, 0x5E, 0xC3,    //
  0x00, 0xDA, 0x45, 0x5F, 0xEA    //
};

const    uint8_t        __rom        Roll1[]    =
{
  0xDA, 0x54, 0x00, 0x00, 0x01, 0x70, 0x17, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x23, 0x43, 0x01,    //
  0x23, 0x31, 0x5E, 0xF7, 0x5E, 0x3A, 0x5E, 0xEC, 0x2E, 0x23, 0x43, 0x03, 0x5E, 0xF1, 0x00, 0xDA,    //
  0x54, 0x00, 0x00, 0x01, 0x60, 0xEA, 0x08, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x23, 0x31, 0x23, 0x43,    //
  0x01, 0x5E, 0xC4, 0x2E, 0x5E, 0xCC, 0x2E, 0x5E, 0xC3, 0x00, 0xDA, 0x45, 0x5F, 0xEA    //
};


и так далее ...
Потом объявляю массив ...
Код
const    uint8_t    __rom *    const __rom AdrRoll[] =
{
  (const    uint8_t    __rom *)&Roll0, (const    uint8_t    __rom *)&Roll1, (const    uint8_t    __rom *)&Roll2,
  (const    uint8_t    __rom *)&Roll3, (const    uint8_t    __rom *)&Roll4, (const    uint8_t    __rom *)&Roll5,
  (const    uint8_t    __rom *)&Roll6, (const    uint8_t    __rom *)&Roll7
};


Поскольку массивы идут попорядку, то я ожидал, что компилятор их и разместит попорядку во флэши. Причём в результирующем HEXе для AVR так и происходит. А для ARM7 компилятор разбрасывает массивы как хочет.

Почему это происходит?

Я бы хотел, чтобы они шли подряд. Как вариант вижу объединить их в структуру. Но непонятен мотив компилятора. Он что так место пытается экономить? Типа дырки забивает - так вроде не видно...

Кто подскажет?

PS: Проблема несколько сложнее чем показалось с первого взгляда. Размеры массивов разные и объединить их в структуру не очень удобно. Придётся явно объявлять их длину. А мне это делать очень неудобно. Они будут меняться от реализации к реализации. Высчитывать - нет желания. Хотелось бы простое и крассивое решение. Как компилятор заставить распологать массивы по порядку?
_Pasha
Есть предположение, что виноваты оптимально размещенные stubs
HARMHARM
А что если вынести в отдельную единицу компиляции, и выключить отпимизацию?
Andy Mozzhevilov
Цитата(SasaVitebsk @ Oct 28 2009, 02:00) *
Столкнулся с проблемой. Сразу отмечу, что понимаю её корни и вижу несколько способов решения, но мне непонятно почему компилятор так поступает. Кто объяснит.

Потому что стандарт С не обязывает компилятор к размещению переменных в порядке их объявления.



Цитата(HARMHARM @ Oct 28 2009, 09:06) *
А что если вынести в отдельную единицу компиляции, и выключить отпимизацию?

Помочь может, но это будет частный случай. В общем случае гарантии нет.
SasaVitebsk
Цитата(Andy Mozzhevilov @ Oct 28 2009, 09:44) *
Потому что стандарт С не обязывает компилятор к размещению переменных в порядке их объявления.

Это понятно - претензий нет. А зачем он это делает? Дырки оптимизирует, которые при выравнивании остаются?
Может тогда достаточно сделать выравнивание на границу байта в начале массивов и вернуть к исходному в конце?

Ладно. Зайдём с другого конца. Может кто-нибудь предложит решение красивое.
Задача такова.
Имеется несколько массивов. Они находятся во флэш, но в то же время я их меняю иногда. Не хотелось бы чтобы изменение массивов в тексте программы требовало вмешательство ещё куда-нибудь. Массивы разной длины. В программе мне надо знать начало этого массива и его конец. Я брал указатель на начало массива 1, а в качестве конца использовал указатель на начало массива 2. Дырка, заполненная 0 или ff, к примеру, меня не беспокоит.

Как красиво и правильно это реализовать? Так чтобы я поменял, к примеру, массив в готовой проге, и она осталась полностью работоспособной.
HARMHARM
Например, так (С++):
Код
TTrackerCanMsgParser* const TTrackerCanMsgParserJ1939::messages[] =
{
    &SPEED,    
    ...
    &NHFUELLEVELltr
};

const unsigned int CAN_J1939_TAG_COUNT = sizeof( TTrackerCanMsgParserJ1939::messages ) / sizeof ( TTrackerCanMsgParser* );

При этом CAN_J1939_TAG_COUNT - это константа во flash.
Если она нужна только в этой единице компиляции, то можно сделать static, и она будет прямо подставлена. Или используйте extern из других файлов.
jorikdima
по моему структура самое правильное решение тут
_Pasha
Глянул - массивы ведь не выровненные на 32 бита. А дырки какого размера?
Andy Mozzhevilov
Почему бы просто дополнительно не хранить длину массива? Жалко 2 байта во флеш?
Ну можно поизвращаться:
Код
#define SLON1_INIT 1, 2, 3, 4
#define SLON2_INIT 5, 6, 7, 8, 9, 10
#define SLON3_INIT 11, 12

extern const uint8_t *pSlon1;
extern const uint8_t *pSlon2;
extern const uint8_t *pSlon3;
extern const uint8_t *pSlonEnd;

static const uint8_t Slon1_Init[] = { SLON1_INIT };
static const uint8_t Slon2_Init[] = { SLON2_INIT };
static const uint8_t Slon3_Init[] = { SLON3_INIT };

const uint8_t Slon[] = { SLON1_INIT, SLON2_INIT, SLON3_INIT };

const uint8_t *pSlon1   = Slon;
const uint8_t *pSlon2   = pSlon1 + sizeof(Slon1_Init);
const uint8_t *pSlon3   = pSlon2 + sizeof(Slon2_Init);
const uint8_t *pSlonEnd = pSlon3 + sizeof(Slon3_Init);
KRS
Цитата(SasaVitebsk @ Oct 28 2009, 13:04) *
Как красиво и правильно это реализовать? Так чтобы я поменял, к примеру, массив в готовой проге, и она осталась полностью работоспособной.

Вы же все равно прогу перекомпилируете?
Тогда почему нельзя использовать sizeof?
SasaVitebsk
Цитата(Andy Mozzhevilov @ Oct 28 2009, 14:06) *
Почему бы просто дополнительно не хранить длину массива? Жалко 2 байта во флеш?

Наверное так и сделаю. Прогу придётся править.
Цитата
Ну можно поизвращаться:

rolleyes.gif
Любопытно. Так вроде как дважды память будет выделена. Или static не даст? В смысле, если эти массивы не будут в данном файле использованы?
Andy Mozzhevilov
Цитата(SasaVitebsk @ Oct 28 2009, 14:36) *
Любопытно. Так вроде как дважды память будет выделена. Или static не даст? В смысле, если эти массивы не будут в данном файле использованы?

В общем случае это от компилятора зависит. Iar это оптимизирует, большинство других современных тоже скорее всего.
Возникает только warning , который можно в принципе прибить через #pragma
Но, имхо это извращения какие-то.
Я бы создал структуру, состоящую из указатетеля на массив и длины.
А потом бы создал и проинициализировал массив таких структур. Ну или просто, как рекомендовали выше, sizeof() для определения длины.
Dog Pawlowa
Мне кажется, проблема надумана.
Желание не указывать длину массива и при этом сохранить работоспособность программы при смене массива как-то не вяжется.
Объявить длины массивов, уложить в структуру. Массив указателей тогда не нужен.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.