|
|
  |
Проблема с размещением массивов констан, LPC2368, Yagarto (4.3.2) |
|
|
|
May 12 2010, 21:50
|
Гуру
     
Группа: Свой
Сообщений: 2 318
Регистрация: 13-02-05
Из: Липецкая область
Пользователь №: 2 613

|
Взял свой тестовый проект двухгодичной давности за основу, при выводе на графический экран (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; } Код еще бессмысленный, переменные во "вне" еще не изменяются.
|
|
|
|
|
May 13 2010, 05:59
|
Гуру
     
Группа: Свой
Сообщений: 2 318
Регистрация: 13-02-05
Из: Липецкая область
Пользователь №: 2 613

|
Цитата(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.
Прикрепленные файлы
main.zip ( 5.31 килобайт )
Кол-во скачиваний: 16
|
|
|
|
|
May 13 2010, 11:22
|
Гуру
     
Группа: Свой
Сообщений: 2 318
Регистрация: 13-02-05
Из: Липецкая область
Пользователь №: 2 613

|
Цитата(Сергей Борщ @ May 13 2010, 13:57)  А не может быть проблем из-за нехватки стека? Я у вас в .map увидел только один стек - вы исключения/прерывания не используете вообще? Постоянно работающий Таймер на IRQ 100 мкс и прерывание FIQ на EINT2, но оно еще не задействовано, да и будет работать по редкому событию. В общем, размещение массивов не кратно 4 байтам. Посмотрел внимательно, выравнивает он в самом конце, и дело совсем не в этом.
|
|
|
|
|
May 13 2010, 12:54
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(gte @ May 13 2010, 14:22)  Постоянно работающий Таймер на IRQ 100 мкс и прерывание FIQ на EINT2, но оно еще не задействовано, да и будет работать по редкому событию. У ARM для каждого режима свой стек. Я увидел у вас в .map всего один стек. Поэтому попросил показать стартап-код, ибо неясно - где расположены остальные стеки. Если вы все три стека проинициализировали на оду область - непонятно, как у вас вообще что-то работает. Цитата(gte @ May 13 2010, 14:22)  В общем, размещение массивов не кратно 4 байтам Каждый отдельно взятый массив выравнивает компилятор исходя из размера элементов. Линкер выравнивает начало секции, чтобы все массивы скопировать в ОЗУ одним циклом кусками по 32 бита. У вас выравнивание секции .rodata получается автоматически, потому что предыдущии секции состоят из 32-битных элементов.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 13 2010, 13:46
|
Гуру
     
Группа: Свой
Сообщений: 2 318
Регистрация: 13-02-05
Из: Липецкая область
Пользователь №: 2 613

|
Цитата(Сергей Борщ @ May 13 2010, 16:54)  У ARM для каждого режима свой стек. Я увидел у вас в .map всего один стек. Поэтому попросил показать стартап-код, ибо неясно - где расположены остальные стеки. Если вы все три стека проинициализировали на оду область - непонятно, как у вас вообще что-то работает. Да, видимо дело в стеке. Если поставить останов на программу обработки 0 таймера, то он очень быстро переполняется прямо на глазах. Стартап в приложении. Я еще ко всему перенес 0 таймер с FIQ на IRQ, а на FIQ поставил EINT2. А за два года выветрились остатки того, в чем тогда разобрался :-(. Процедура обслуживания EINT2 определена как void EINT2ISR (void)__attribute__ ((interrupt("FIQ"))); // обслуживание прерывания EINT2
Startup.S.txt ( 10.35 килобайт )
Кол-во скачиваний: 762Цитата Каждый отдельно взятый массив выравнивает компилятор исходя из размера элементов. Линкер выравнивает начало секции, чтобы все массивы скопировать в ОЗУ одним циклом кусками по 32 бита. У вас выравнивание секции .rodata получается автоматически, потому что предыдущии секции состоят из 32-битных элементов. На счет линкера уже понял, а почему у меня отдельные массивы компилятор не выравнивает? Или это роли не играет?
|
|
|
|
|
May 13 2010, 14:08
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(gte @ May 13 2010, 16:46)  Стартап в приложении. Да, все нормально - он их просто подряд располагает в одной секции. Но вот 512 байт на стек основной программы мне кажется маловато. Вам жалко памяти?  Цитата(gte @ May 13 2010, 16:46)  На счет линкера уже понял, а почему у меня отдельные массивы компилятор не выравнивает? Или это роли не играет? Выравнивает. Байтовые - на границу байта, двухбайтовые - на границу двух байтов, четырехбайтовые - на границу 4 байт. Структуры - в зависимости от типов членов.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 13 2010, 15:04
|
Гуру
     
Группа: Свой
Сообщений: 2 318
Регистрация: 13-02-05
Из: Липецкая область
Пользователь №: 2 613

|
Цитата(Сергей Борщ @ May 13 2010, 18:08)  Да, все нормально - он их просто подряд располагает в одной секции. Но вот 512 байт на стек основной программы мне кажется маловато. Вам жалко памяти?  Да нет, но что то ее ест. Поставил по 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
|
|
|
|
|
May 13 2010, 17:43
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Diz @ May 13 2010, 17:41)  Да, еще. У GCC был косяк с IRQ (до сих пор не исправленный, насколько знаю) Исправленый. В Yagarto уже больше года как. Можно пользовать смело - "личный" пролог у каждого обработчика IRQ эффективнее одного общего. Цитата(gte @ May 13 2010, 18:04)  Ставлю точку останова на 0 таймере sp показывает около 4 килобайт. Начинаю продолжить, возвращается на туже точку, но sp уменьшился. Поставьте точку останова на адресе 18 (вектор IRQ) и пройдите обработчик по шагам. Кроме обработчика никто sp_irq трогать не должен, да и не добраться до него так просто из других режимов - остается грешить на обработчик.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 13 2010, 18:47
|
Гуру
     
Группа: Свой
Сообщений: 2 318
Регистрация: 13-02-05
Из: Липецкая область
Пользователь №: 2 613

|
Цитата(Сергей Борщ @ May 13 2010, 21:43)  Исправленый. В Yagarto уже больше года как. Можно пользовать смело - "личный" пролог у каждого обработчика IRQ эффективнее одного общего. Большое спасибо, сейчас скачаю свежий Yagarto, у меня 4.3.2. А то я с ассемблером закончил на PDP11 и то изучал достаточно поверхностно, специальный человек был для этого. Цитата Поставьте точку останова на адресе 18 (вектор IRQ) и пройдите обработчик по шагам. Кроме обработчика никто sp_irq трогать не должен, да и не добраться до него так просто из других режимов - остается грешить на обработчик. Спасибо. Вероятно, нашел причину, завтра проверю в отладчике. Раньше использовал SSP0 с прерыванием по Recieve timeout. При правке не заметил. Сейчас АЦП AD7367 читается без всяких прерываний. При остановах программы, видимо, стек и заполнялся. Проверил, теперь стек не портится, позже проверю явилось ли это источником всех проблем.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|