Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема с размещением массивов констан
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
gte
Взял свой тестовый проект двухгодичной давности за основу, при выводе на графический экран (wg19232) по мере наращивания и добавления массивов получил зависание программы. Такое ощущение, что попадает не по тому адресу.
Ради интереса из const перевел массивы в static. Программа начала работать нормально, но при наращивании текста в подпрограмме обработки 0 таймера получил опять вылеты. Да еще 2 года не пользовал Эклипс+АРМ :-(.

Размещение массивов в качестве const.
Код
*(.gcc_except_table)
*(.rodata)
*(.rodata*)
.rodata.gte8   0x00004228      0x300 lcd_wg19232b.o
                0x00004228                gte8
.rodata.hv_on  0x00004528       0xb4 lcd_wg19232b.o
                0x00004528                hv_on
.rodata.hv_off
                0x000045dc       0xb4 lcd_wg19232b.o
                0x000045dc                hv_off
.rodata.hv_0_9_16x25
                0x00004690      0x1f4 lcd_wg19232b.o
                0x00004690                hv_0_9_16x25
.rodata.zpt_5x25
                0x00004884       0x19 lcd_wg19232b.o
                0x00004884                zpt_5x25
.rodata.kv_x25
                0x0000489d       0x64 lcd_wg19232b.o
                0x0000489d                kv_x25
.rodata.hv_1_12x25.1360
                0x00004901       0x32 lcd_wg19232b.o
.rodata.C.0.1460
                0x00004933        0x6 lcd_wg19232b.o
*(.gnu.linkonce.r.*)

Как Вы думаете. Проблема с размещением массивов, или это всего лишь выявило ошибку?
Что смотреть в первую очередь?
Ниже код, добавления которого сбивает программу с массивами static, переменные volatile uint8_t.

Код
breakdown_time++;                            
  if (breakdown_time >= 100)                                
    {                        
      breakdown_integrator = breakdown_integrator << N_impuls;
      N_impuls =0;                              
      breakdown_time =0;
      breakdown_time_minus++;
    }  
  if (breakdown_integrator > 20)
    {
      FIO2CLR = (1 << 11);        .  
      breakdown_fault =1;      
    }
  if (breakdown_time_minus > 10)
    {
      breakdown_integrator = breakdown_integrator >> 0x01;
      breakdown_time_minus =0;
    }

Код еще бессмысленный, переменные во "вне" еще не изменяются.
Diz
Те массивы констант, которые легли не на границу слова - char ?
gte
Цитата(Diz @ May 13 2010, 03:14) *
Те массивы констант, которые легли не на границу слова - char ?

Я не очень понял. В map вроде все нормально (файл вложил), а программа улетает не на обращении к массивам, по крайней мере во время отладки. В что интересно, при переброске массивов в ОЗУ отображение на ЖКИ начинало изменяться, но с глюками части выводов. При полной переброске все заработало нормально.

Или Вы имеете ввиду вот это
Код
.rodata.zpt_5x25
                0x00004884       0x19 lcd_wg19232b.o
                0x00004884                zpt_5x25
.rodata.kv_x25
                0x0000489d       0x64 lcd_wg19232b.o
                0x0000489d                kv_x25


, где zpt_5x25 массив из 25 байт?
Все массивы uint8_t.
Сергей Борщ
А не может быть проблем из-за нехватки стека? Я у вас в .map увидел только один стек - вы исключения/прерывания не используете вообще?
gte
Цитата(Сергей Борщ @ May 13 2010, 13:57) *
А не может быть проблем из-за нехватки стека? Я у вас в .map увидел только один стек - вы исключения/прерывания не используете вообще?

Постоянно работающий Таймер на IRQ 100 мкс и прерывание FIQ на EINT2, но оно еще не задействовано, да и будет работать по редкому событию.
В общем, размещение массивов не кратно 4 байтам.
Посмотрел внимательно, выравнивает он в самом конце, и дело совсем не в этом.
Сергей Борщ
Цитата(gte @ May 13 2010, 14:22) *
Постоянно работающий Таймер на IRQ 100 мкс и прерывание FIQ на EINT2, но оно еще не задействовано, да и будет работать по редкому событию.
У ARM для каждого режима свой стек. Я увидел у вас в .map всего один стек. Поэтому попросил показать стартап-код, ибо неясно - где расположены остальные стеки. Если вы все три стека проинициализировали на оду область - непонятно, как у вас вообще что-то работает.
Цитата(gte @ May 13 2010, 14:22) *
В общем, размещение массивов не кратно 4 байтам
Каждый отдельно взятый массив выравнивает компилятор исходя из размера элементов. Линкер выравнивает начало секции, чтобы все массивы скопировать в ОЗУ одним циклом кусками по 32 бита. У вас выравнивание секции .rodata получается автоматически, потому что предыдущии секции состоят из 32-битных элементов.
gte
Цитата(Сергей Борщ @ May 13 2010, 16:54) *
У ARM для каждого режима свой стек. Я увидел у вас в .map всего один стек. Поэтому попросил показать стартап-код, ибо неясно - где расположены остальные стеки. Если вы все три стека проинициализировали на оду область - непонятно, как у вас вообще что-то работает.

Да, видимо дело в стеке. Если поставить останов на программу обработки 0 таймера, то он очень быстро переполняется прямо на глазах.
Стартап в приложении. Я еще ко всему перенес 0 таймер с FIQ на IRQ, а на FIQ поставил EINT2. А за два года выветрились остатки того, в чем тогда разобрался :-(.
Процедура обслуживания EINT2 определена как
void EINT2ISR (void)__attribute__ ((interrupt("FIQ"))); // обслуживание прерывания EINT2
Нажмите для просмотра прикрепленного файла
Цитата
Каждый отдельно взятый массив выравнивает компилятор исходя из размера элементов. Линкер выравнивает начало секции, чтобы все массивы скопировать в ОЗУ одним циклом кусками по 32 бита. У вас выравнивание секции .rodata получается автоматически, потому что предыдущии секции состоят из 32-битных элементов.

На счет линкера уже понял, а почему у меня отдельные массивы компилятор не выравнивает? Или это роли не играет?
Сергей Борщ
Цитата(gte @ May 13 2010, 16:46) *
Стартап в приложении.
Да, все нормально - он их просто подряд располагает в одной секции. Но вот 512 байт на стек основной программы мне кажется маловато. Вам жалко памяти? wink.gif
Цитата(gte @ May 13 2010, 16:46) *
На счет линкера уже понял, а почему у меня отдельные массивы компилятор не выравнивает? Или это роли не играет?
Выравнивает. Байтовые - на границу байта, двухбайтовые - на границу двух байтов, четырехбайтовые - на границу 4 байт. Структуры - в зависимости от типов членов.
Diz
Да, еще. У GCC был косяк с IRQ (до сих пор не исправленный, насколько знаю) - при достаточно большом обработчике
прерывания (когда свободные регистры кончаются) генерит кривой пролог/эпилог. Или дважды вычитает 4 из lr, или что-то в этом духе - соответственно, программа может улетать в неведомые дали. Посмотрите листинг внимательнее.
Я отказался от использования __attribute__ ((interrupt("IRQ"))) и пишу пролог/эпилог вручную.
gte
Цитата(Сергей Борщ @ May 13 2010, 18:08) *
Да, все нормально - он их просто подряд располагает в одной секции. Но вот 512 байт на стек основной программы мне кажется маловато. Вам жалко памяти? wink.gif

Да нет, но что то ее ест.
Поставил по 2 килобайта, в сумме 8.
Ставлю точку останова на 0 таймере sp показывает около 4 килобайт. Начинаю продолжить, возвращается на туже точку, но sp уменьшился. Если шагнуть 180 раз, sp обнулится, программа повиснет, при останове показывает
DAbt_Handler: B DAbt_Handler.

Если просто запустить, то работает и не виснет.
Как посмотреть кто отъедает sp?


Цитата(Diz @ May 13 2010, 18:41) *
Да, еще. У GCC был косяк с IRQ (до сих пор не исправленный, насколько знаю) - при достаточно большом обработчике
прерывания (когда свободные регистры кончаются) генерит кривой пролог/эпилог. Или дважды вычитает 4 из lr, или что-то в этом духе - соответственно, программа может улетать в неведомые дали. Посмотрите листинг внимательнее.
Я отказался от использования __attribute__ ((interrupt("IRQ"))) и пишу пролог/эпилог вручную.

Так у меня
void EINT2ISR (void)__attribute__ ((interrupt("FIQ")));
Или для FIQ та же проблема?

А для IRQ сохранение в стартап, а при инициализации указываю
Код
DWORD regVal;
  timer0_counter = 0;

  PCONP |= 1<<PCTIM0;                        // Включить периферийный блок
  PCLKSEL0 |= (0<<2);// CCLK/4 =0x00                 //PCLK_TIMER0 = 0x00//
  regVal = T0TCR;
  regVal |= 0x02;
  T0TCR = regVal;                        // timer0 reset
  T0MR0 = TIME0_INTERVAL;
  T0MCR = 3;                            // Interrupt and Reset on MR0

////// 11.05.2010 осталось от прерывания FIQ                    VICIntSelect |= (0x01 << 4); // Timer0 Interrupt is FIQ Type
  VICVectCntl4 = TIMER0_INT;                              // Channel0 on Source#10 ... enabled
  VICVectAddr4 = (unsigned int) Timer0ISR;            //

  VICIntSelect &= ~(0x01 << TIMER0_INT);            // 11.05.2010 timer0 прерывание - IRQ прерывание
  VICIntEnable = (0x01 << 4);                      // Enable Timer0 Interrupt
  T0IR = 0xff;
  T0TCR = 0;                                         //=1 Timer0 enable
Сергей Борщ
Цитата(Diz @ May 13 2010, 17:41) *
Да, еще. У GCC был косяк с IRQ (до сих пор не исправленный, насколько знаю)
Исправленый. В Yagarto уже больше года как. Можно пользовать смело - "личный" пролог у каждого обработчика IRQ эффективнее одного общего.

Цитата(gte @ May 13 2010, 18:04) *
Ставлю точку останова на 0 таймере sp показывает около 4 килобайт. Начинаю продолжить, возвращается на туже точку, но sp уменьшился.
Поставьте точку останова на адресе 18 (вектор IRQ) и пройдите обработчик по шагам. Кроме обработчика никто sp_irq трогать не должен, да и не добраться до него так просто из других режимов - остается грешить на обработчик.
gte
Цитата(Сергей Борщ @ May 13 2010, 21:43) *
Исправленый. В Yagarto уже больше года как. Можно пользовать смело - "личный" пролог у каждого обработчика IRQ эффективнее одного общего.

Большое спасибо, сейчас скачаю свежий Yagarto, у меня 4.3.2. А то я с ассемблером закончил на PDP11 и то изучал достаточно поверхностно, специальный человек был для этого.

Цитата
Поставьте точку останова на адресе 18 (вектор IRQ) и пройдите обработчик по шагам. Кроме обработчика никто sp_irq трогать не должен, да и не добраться до него так просто из других режимов - остается грешить на обработчик.

Спасибо.
Вероятно, нашел причину, завтра проверю в отладчике.
Раньше использовал SSP0 с прерыванием по Recieve timeout. При правке не заметил. Сейчас АЦП AD7367 читается без всяких прерываний. При остановах программы, видимо, стек и заполнялся.

Проверил, теперь стек не портится, позже проверю явилось ли это источником всех проблем.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.