|
Bootloader. Не работают прерывания. |
|
|
|
Sep 9 2010, 14:09
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Здравствуйте, уважаемые форумчание! Пишу загрузчик в IAR 5.5. Загрузчик, как положено, отдельным проектом. Вектора и код переместил в загрузочную область: Файл lnkusb647s.xclКод . . . /* Code (flash) segments */ -D_..X_INTVEC_SIZE=F098 /* 4 bytes * 38 vectors */ . . . /* Code memory */ -Z(CODE)INTVEC=F000-(_..X_INTVEC_SIZE-1)
/* Fill unused interrupt vector's with RETI */ -H1895 -h(CODE)F000-_..X_INTVEC_SIZE . . . Код и вектора переместились, это видно из чтения памяти программ. Начало векторов расположено с адреса 0хF000, следом идет код. Код программы: Код . . . int main(void) { __enable_interrupt(); // разрешение прерываний (sei) DDRD |= (1 << PD7); // управление светодиодом EIMSK |= (1 << INT0); // разрешение прерывания MCUCR |= (1 << IVCE); // для записи IVSEL MCUCR = (1 << IVSEL); // вектора в загрузочной области
for(;;) {
} return 0; } #pragma vector = INT0_vect __interrupt void INT0_interrupt() { for(;;) { PORTD |= (1 << PD7); __delay_cycles(4000000);
PORTD &= ~(1 << PD7); __delay_cycles(4000000); } } Когда код идет с нулевого адреса, все нормально прерывание проходит, светодиод мигает. При переносе кода в загрузчик, выполнение программы "сваливается" куда-то непонятно куда. Что я делаю не так? Спасибо
|
|
|
|
|
Sep 9 2010, 15:07
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(Jhohn @ Sep 9 2010, 18:09)  Вектора и код переместил в загрузочную область...Когда код идет с нулевого адреса, все нормально...При переносе кода в загрузчик, выполнение программы "сваливается"... тупой вопрос: при программировании кристалла фьюзы выставляете правильно? адресс RESET вектора совпадает с вашим значением в .org ? (круглый)
|
|
|
|
|
Sep 10 2010, 09:48
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Цитата(kolobok0 @ Sep 9 2010, 19:07)  тупой вопрос: при программировании кристалла фьюзы выставляете правильно? адресс RESET вектора совпадает с вашим значением в .org ? Микроконтроллер at90usb. Вне зависимости от значения fuses bit BOOTRST программа стартует в main(), я это проверял с помощью следующего кода: Код int main(void) { __enable_interrupt(); // разрешение прерываний (sei) DDRD |= (1 << PD7); // управление светодиодом EIMSK |= (1 << INT0); // разрешение прерывания MCUCR |= (1 << IVCE); // для записи IVSEL MCUCR = (1 << IVSEL); // вектора в загрузочной области
for(;;) { PORTD |= (1 << PD7); __delay_cycles(400000);
PORTD &= ~(1 << PD7); __delay_cycles(400000); } return 0; } Не важно выставлен или сброшен бит BOOTRST программа стартует с адекватно с загрузочной области - светодиод мигает, когда запрещены все прерывания, при разрешении прерываний (sei) программа "сваливается".
|
|
|
|
|
Sep 10 2010, 13:19
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Стартовый адрес линкерного скрипта для бутлоадера совпадает с физическим адресом, который получается с установлением фьюзами размера бутлоадера? Код MCUCR |= (1 << IVCE); // для записи IVSEL MCUCR = (1 << IVSEL); // вектора в загрузочной области И ещё есть большое подозрение, что проблема здесь. Вы смотрели дизасмом после установки IVCE вы успеваете за 4 такта установить IVSEL?
|
|
|
|
|
Sep 10 2010, 14:12
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(xelax @ Sep 10 2010, 17:19)  И ещё есть большое подозрение, что проблема здесь. Вы смотрели дизасмом после установки IVCE вы успеваете за 4 такта установить IVSEL? Скорее всего, проблема не в этом... Наверное, программа прошита не в области бута, а с нулевого адреса. Поэтому она (программа) и стартует при любом BOOTRST: в одном случае - и должна, в другом - пытаются выполниться команды FFFF до тех пор, пока указатель не сбросится в ноль. При выполнении программы перемещаются вектора (изменяется IVSEL) в бут, но поскольку бут пуст, то по прерыванию опять выполняются команды FFFF до сброса указателя в ноль - на начало программы; программа начинает выполняться - и всё заново по кругу...
|
|
|
|
|
Sep 14 2010, 06:59
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Цитата(xelax @ Sep 10 2010, 17:19)  Стартовый адрес линкерного скрипта для бутлоадера совпадает с физическим адресом, который получается с установлением фьюзами размера бутлоадера? Да, совпадают: fuses выставлены words start address=$7800, физически (реально) располагается код, как писал выше, с адреса $F000. Цитата(xelax @ Sep 10 2010, 17:19)  Код MCUCR |= (1 << IVCE); // для записи IVSEL MCUCR = (1 << IVSEL); // вектора в загрузочной области И ещё есть большое подозрение, что проблема здесь. Вы смотрели дизасмом после установки IVCE вы успеваете за 4 такта установить IVSEL? Посмотрел на интерпретацию этих двух команд в ассемлере, приминала не нашел. Дополнительно проделал следующий тест: Код #define CHECK_BIT(ADDRESS,BIT) (ADDRESS & (1<<BIT)) int main(void) { //__enable_interrupt(); DDRD |= (1 << PD7);
EIMSK |= (1 << INT0); MCUCR |= (1 << IVCE); MCUCR = (1 << IVSEL); for(;;) { if(CHECK_BIT(MCUCR, IVSEL)) { PORTD |= (1 << PD7); __delay_cycles(2000000);
PORTD &= ~(1 << PD7); __delay_cycles(2000000); } } //wdtdrv_disable(); //Clear_prescaler(); //scheduler(); return 0; } Светодиод мигает, следовательно выставляется бит IVSEL, но прерывания не проходят. Таки куда-то сваливается.
Сообщение отредактировал Jhohn - Sep 14 2010, 12:08
|
|
|
|
|
Sep 14 2010, 12:07
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Чтение памяти Flash - см. ПРИКРЕПЛЕННЫЙ ФАЙЛ
|
|
|
|
|
Sep 14 2010, 13:21
|

Местный
  
Группа: Свой
Сообщений: 232
Регистрация: 26-02-07
Из: г. Зеленоград
Пользователь №: 25 669

|
Цитата(Jhohn @ Sep 14 2010, 16:07)  Чтение памяти Flash - см. ПРИКРЕПЛЕННЫЙ ФАЙЛ >:10F000000C9462790C946E7818951895189518954B это 1-я строка кода Вашей программы она заносится начиная с адреса 0xF000 (байтовый адрес) что соответствует адресу в словах = 0x7800 т.е. куда то в середину Flash. Скорее всего Вы в Linker - задали формат выходного файла Intel а надо Intel-Extended
--------------------
Вяжешь - вой, а поедешь - песни пой. Между "хочу" и "можно" всегда есть дистанция
|
|
|
|
|
Sep 14 2010, 13:28
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Цитата(IJAR @ Sep 14 2010, 17:21)  >:10F000000C9462790C946E7818951895189518954B это 1-я строка кода Вашей программы она заносится начиная с адреса 0xF000 (байтовый адрес) что соответствует адресу в словах = 0x7800 т.е. куда то в середину Flash. Скорее всего Вы в Linker - задали формат выходного файла Intel а надо Intel-Extended Хм, как же в середину? В прикрепленном файле вся Flash (последняя строка оканчивается командой с адресом 0xFFFF = 65к), по расположению загрузчика в файле видно, что он никак не в середине. В опциях стоит Intel-Extended.
|
|
|
|
|
Sep 14 2010, 13:39
|

Местный
  
Группа: Свой
Сообщений: 232
Регистрация: 26-02-07
Из: г. Зеленоград
Пользователь №: 25 669

|
Цитата(Jhohn @ Sep 14 2010, 17:28)  Хм, как же в середину? В прикрепленном файле вся Flash (последняя строка оканчивается командой с адресом 0xFFFF = 65к), по расположению загрузчика в файле видно, что он никак не в середине.
В опциях стоит Intel-Extended. А Вы можете показать hex файл созданный компилятором?
--------------------
Вяжешь - вой, а поедешь - песни пой. Между "хочу" и "можно" всегда есть дистанция
|
|
|
|
|
Sep 14 2010, 13:44
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Цитата(IJAR @ Sep 14 2010, 17:39)  А Вы можете показать hex файл созданный компилятором? Сделано. ИЗВИНЯЮСЬ ТУТ АДЕРСА С 0XFC00
Сообщение отредактировал Jhohn - Sep 14 2010, 13:50
|
|
|
|
|
Sep 14 2010, 13:50
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Попробовал исправить на 1Е000 комилятор ругается. CODE Fatal Error[e140]: The range declaration used in D:\...lnkusb647s.xcl 91 -Z(CODE)NEAR_F,SWITCH,DIFUNCT=_..X_INTVEC_SIZE-_..X_FLASH_NEND is illegal since 0x1e098 > 0xffff.
Максимум в этом контроллере 0xFFFF. Файл линковки ниже
Сообщение отредактировал Jhohn - Sep 14 2010, 13:59
|
|
|
|
|
Sep 14 2010, 14:09
|

Местный
  
Группа: Свой
Сообщений: 232
Регистрация: 26-02-07
Из: г. Зеленоград
Пользователь №: 25 669

|
Цитата(Jhohn @ Sep 14 2010, 17:50)  Попробовал исправить на 1Е000 комилятор ругается. CODE Fatal Error[e140]: The range declaration used in D:\...lnkusb647s.xcl 91 -Z(CODE)NEAR_F,SWITCH,DIFUNCT=_..X_INTVEC_SIZE-_..X_FLASH_NEND is illegal since 0x1e098 > 0xffff.
Максимум в этом контроллере 0xFFFF. Файл линковки ниже Извиняюсь - на счет 0x1e000 - это я загнул в кристалле 64К должно быть 0xFC00 поскольку Ваш программа грузится с этого байтового адреса Цитата(Jhohn @ Sep 14 2010, 17:50)  Попробовал исправить на 1Е000 комилятор ругается. CODE Fatal Error[e140]: The range declaration used in D:\...lnkusb647s.xcl 91 -Z(CODE)NEAR_F,SWITCH,DIFUNCT=_..X_INTVEC_SIZE-_..X_FLASH_NEND is illegal since 0x1e098 > 0xffff.
Максимум в этом контроллере 0xFFFF. Файл линковки ниже Так, я кажется понял - Вы либо Fuse биты исправте на начало секции загрузчика с 0xF000 или в xcl файле укажите правильный адрес начала FLASH (0xFC00) и все что это тянет за собой
--------------------
Вяжешь - вой, а поедешь - песни пой. Между "хочу" и "можно" всегда есть дистанция
|
|
|
|
|
Sep 14 2010, 14:21
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Цитата(IJAR @ Sep 14 2010, 18:09)  Так, я кажется понял - Вы либо Fuse биты исправте на начало секции загрузчика с 0xF000 или в xcl файле укажите правильный адрес начала FLASH (0xFC00) и все что это тянет за собой Извиняюсь, тот файл, что подсунул, это уже с экспериментами был. Изменил адреса. Прерывания, как прежде сваливаются не понятно куда. Проверяю следующим образом: в прерывании мигание светотдиода, при разрешении этого прерывания программа выходит с главного цикла (в главном цикле мигание с значительно меньшей частотой чем в прерывании). При переносе кода в начало памяти прерывания проходят успешно - светодиод мигает часто. Файл линковки: с адреса 0хFC00Файл *.hex - генерируемый с iar Файл чтения памяти из микроконтроллера.
Сообщение отредактировал Jhohn - Sep 14 2010, 14:23
|
|
|
|
|
Sep 14 2010, 14:33
|

Местный
  
Группа: Свой
Сообщений: 232
Регистрация: 26-02-07
Из: г. Зеленоград
Пользователь №: 25 669

|
Цитата(Jhohn @ Sep 14 2010, 18:21)  Извиняюсь, тот файл, что подсунул, это уже с экспериментами был.
Изменил адреса. Прерывания, как прежде сваливаются не понятно куда. Проверяю следующим образом: в прерывании мигание светотдиода, при разрешении этого прерывания программа выходит с главного цикла (в главном цикле мигание с значительно меньшей частотой чем в прерывании). При переносе кода в начало памяти прерывания проходят успешно - светодиод мигает часто.
Файл линковки: с адреса 0хFC00 Файл *.hex - генерируемый с iar Файл чтения памяти из микроконтроллера. Только что проверил Ваш hex файл в симуляторе AVR STUDIO при стрте программы с адреса 0xFC00 - прерывания прекрасно генерится и приходит на 0x7E02(word) или 0xFC04 (byte) У Вас точно Fuse битами установлено начало загрузчика с адреса 0x7E00 ???
--------------------
Вяжешь - вой, а поедешь - песни пой. Между "хочу" и "можно" всегда есть дистанция
|
|
|
|
|
Sep 14 2010, 14:46
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Цитата(IJAR @ Sep 14 2010, 18:33)  Только что проверил Ваш hex файл в симуляторе AVR STUDIO при стрте программы с адреса 0xFC00 - прерывания прекрасно генерится и приходит на 0x7E02(word) или 0xFC04 (byte) Спасибо большое. Это хорошая информация. Цитата(IJAR @ Sep 14 2010, 18:33)  У Вас точно Fuse битами установлено начало загрузчика с адреса 0x7E00 ??? Да. "boot Flash size=1024 words start address=$7E00"
|
|
|
|
|
Sep 16 2010, 13:53
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Цитата(IJAR @ Sep 14 2010, 18:33)  У Вас точно Fuse битами установлено начало загрузчика с адреса 0x7E00 ??? Решил проблему Fuses: "boot Flash size=512 words start address=$7F00" бут должен начинаться с $FC00 = 2*$7E00 "boot Flash size=1024 words start address=$7E00" бут должен начинаться с $F800 = 2*$7С00 "boot Flash size=2048 words start address=$7C00" бут должен начинаться с $F000 = 2*$7800 "boot Flash size=4096 words start address=$7800" Почему именно так прошиваются фьюзы, так и не понял. Только в этом случае прерывания пошли успешно.
|
|
|
|
|
Sep 17 2010, 06:01
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Цитата(xelax @ Sep 16 2010, 18:37)  Потому что в линкере адресация байтовая, а при установке фьюзов адресация пословная указывается. для avr 1 word = 2 bytes.
отсюда адрес из линкерного скрипта делите пополам и получаете адрес который предлагает AVRStudio при установки фьюзов. Все верно, об этом писал arttab в "bootloader_IAR.pdf" см. тему ( http://electronix.ru/forum/index.php?showt...8301&st=45)Проделаю, вышесказанное xelax: "адрес из линкерного скрипта делите пополам"0xF000 / 2 = 0x7800 "получаете адрес который предлагает AVRStudio при установки фьюзов"т.е. выставлять должен "boot Flash size=4096 words start address=$7800" при адресе в линкере 0xF000. Именно так как вы описали я и выставлял fuses, и при этом прерывания не проходили. Мне не понятно следующее (выставив fuses как описано ниже прерывания стали проходить нормально) : Fuses: "boot Flash size=512 words start address=$7 F00" адрес в линкере (бут должен начинаться с) $FC00 = 2*$7 E00 "boot Flash size=1024 words start address=$7 E00" адрес в линкере (бут должен начинаться с) $F800 = 2*$7 С00 "boot Flash size=2048 words start address=$7 C00" адрес в линкере (бут должен начинаться с) $F000 = 2*$7 800 "boot Flash size=4096 words start address=$7800" AVRStudio 4.18 build 700 IAR C/C++ Compiler for AVR 5.50.0 (5.50.0.50277)
Сообщение отредактировал Jhohn - Sep 17 2010, 09:45
|
|
|
|
|
Oct 4 2010, 09:40
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 12-11-08
Пользователь №: 41 579

|
Цитата(Jhohn @ Sep 17 2010, 10:01)  Мне не понятно следующее (выставив fuses как описано ниже прерывания стали проходить нормально) :
Fuses: "boot Flash size=512 words start address=$7F00" адрес в линкере (бут должен начинаться с) $FC00 = 2*$7E00 "boot Flash size=1024 words start address=$7E00" адрес в линкере (бут должен начинаться с) $F800 = 2*$7С00 "boot Flash size=2048 words start address=$7C00" адрес в линкере (бут должен начинаться с) $F000 = 2*$7800 "boot Flash size=4096 words start address=$7800"
AVRStudio 4.18 build 700 IAR C/C++ Compiler for AVR 5.50.0 (5.50.0.50277) После решения более насущных проблем в другом проекте, взявшись с новыми силами, решил-таки в чем был косяк. Посылка: вышеописанная цитата не укладывается в логику - значит есть ошибка. Решение: сравнил биты размера (BOOTSZ1, BOOTSZ0) как их отображает (расшифровывает) AvrStudio, c тем как расшифровывает datasheet T90usb647.pdf и прозрел разницу: AvrStudio: [BOOTSZ1, BOOTSZ0] - [1, 1] - "boot Flash size=512 words start address=$7 F00" datasheet: [BOOTSZ1, BOOTSZ0] - [1, 1] - "Boot Size = 512", "Boot Reset Address (Start Boot Loader Section) = 0x7 E00" и т.д. AVRStudio 4.18 build 700 AVRStudio 4.18 build 716 В общем, размер указывается правильно (это видно выше: boot Flash size=512) от него и нужно отталкиваться: Размер_лоадера = 512 words = 1024 byte Вся_флеш = 65536 byte Стартовый_адрес_лоадера = Вся_флеш - Размер_лоадера = 65536 - 1024 = 64512 byte = 0xFC00 = 2 * 0x7 E00
Сообщение отредактировал Jhohn - Oct 4 2010, 09:43
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|