Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Bootloader. Не работают прерывания.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Jhohn
Здравствуйте, уважаемые форумчание!
Пишу загрузчик в 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);
    }
}


Когда код идет с нулевого адреса, все нормально прерывание проходит, светодиод мигает. При переносе кода в загрузчик, выполнение программы "сваливается" куда-то непонятно куда.

Что я делаю не так?

Спасибо
kolobok0
Цитата(Jhohn @ Sep 9 2010, 18:09) *
Вектора и код переместил в загрузочную область...Когда код идет с нулевого адреса, все нормально...При переносе кода в загрузчик, выполнение программы "сваливается"...


тупой вопрос:
при программировании кристалла фьюзы выставляете правильно? адресс RESET вектора совпадает с вашим значением в .org ?


(круглый)
Jhohn
Цитата(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) программа "сваливается".
Палыч
Почему это BOOTRST не влияет на выполнение Вашей программы? Программа с какого адреса зашита?
По какому адресу Вы ожидаете передачу управления при прерывании и в каком состоянии находится IVSEL?
xelax
Стартовый адрес линкерного скрипта для бутлоадера совпадает с физическим адресом, который получается с установлением фьюзами размера бутлоадера?

Код
    MCUCR |= (1 << IVCE);          // для записи IVSEL
    MCUCR = (1 << IVSEL);          // вектора в загрузочной области


И ещё есть большое подозрение, что проблема здесь. Вы смотрели дизасмом после установки IVCE вы успеваете за 4 такта установить IVSEL?
Палыч
Цитата(xelax @ Sep 10 2010, 17:19) *
И ещё есть большое подозрение, что проблема здесь. Вы смотрели дизасмом после установки IVCE вы успеваете за 4 такта установить IVSEL?
Скорее всего, проблема не в этом... Наверное, программа прошита не в области бута, а с нулевого адреса. Поэтому она (программа) и стартует при любом BOOTRST: в одном случае - и должна, в другом - пытаются выполниться команды FFFF до тех пор, пока указатель не сбросится в ноль.
При выполнении программы перемещаются вектора (изменяется IVSEL) в бут, но поскольку бут пуст, то по прерыванию опять выполняются команды FFFF до сброса указателя в ноль - на начало программы; программа начинает выполняться - и всё заново по кругу...
Jhohn
Цитата(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
Чтение памяти Flash - см. ПРИКРЕПЛЕННЫЙ ФАЙЛ
IJAR
Цитата(Jhohn @ Sep 14 2010, 16:07) *
Чтение памяти Flash - см. ПРИКРЕПЛЕННЫЙ ФАЙЛ


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

Хм, как же в середину? В прикрепленном файле вся Flash (последняя строка оканчивается командой с адресом 0xFFFF = 65к), по расположению загрузчика в файле видно, что он никак не в середине.

В опциях стоит Intel-Extended.
IJAR
Цитата(Jhohn @ Sep 14 2010, 17:28) *
Хм, как же в середину? В прикрепленном файле вся Flash (последняя строка оканчивается командой с адресом 0xFFFF = 65к), по расположению загрузчика в файле видно, что он никак не в середине.

В опциях стоит Intel-Extended.


А Вы можете показать hex файл созданный компилятором?
Jhohn
Цитата(IJAR @ Sep 14 2010, 17:39) *
А Вы можете показать hex файл созданный компилятором?

Сделано.

ИЗВИНЯЮСЬ ТУТ АДЕРСА С 0XFC00
IJAR
И еще
/* Code (flash) segments */
-D_..X_INTVEC_SIZE=F098 /* 4 bytes * 38 vectors */
.
.
.
/* Code memory */
-Z(CODE)INTVEC=F000-(_..X_INTVEC_SIZE-1)

Здесь адреса задаются в байтах т.е. должно быть

/* Code memory */
-Z(CODE)INTVEC=1E000-(_..X_INTVEC_SIZE-1)
Jhohn
Попробовал исправить на 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.

Файл линковки ниже
IJAR
Цитата(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) и все что это тянет за собой
Jhohn
Цитата(IJAR @ Sep 14 2010, 18:09) *
Так, я кажется понял - Вы либо Fuse биты исправте на начало секции загрузчика с 0xF000 или
в xcl файле укажите правильный адрес начала FLASH (0xFC00) и все что это тянет за собой


Извиняюсь, тот файл, что подсунул, это уже с экспериментами был.

Изменил адреса.
Прерывания, как прежде сваливаются не понятно куда. Проверяю следующим образом: в прерывании мигание светотдиода, при разрешении этого прерывания программа выходит с главного цикла (в главном цикле мигание с значительно меньшей частотой чем в прерывании). При переносе кода в начало памяти прерывания проходят успешно - светодиод мигает часто.

Файл линковки: с адреса 0хFC00
Файл *.hex - генерируемый с iar
Файл чтения памяти из микроконтроллера.
IJAR
Цитата(Jhohn @ Sep 14 2010, 18:21) *
Извиняюсь, тот файл, что подсунул, это уже с экспериментами был.

Изменил адреса.
Прерывания, как прежде сваливаются не понятно куда. Проверяю следующим образом: в прерывании мигание светотдиода, при разрешении этого прерывания программа выходит с главного цикла (в главном цикле мигание с значительно меньшей частотой чем в прерывании). При переносе кода в начало памяти прерывания проходят успешно - светодиод мигает часто.

Файл линковки: с адреса 0хFC00
Файл *.hex - генерируемый с iar
Файл чтения памяти из микроконтроллера.

Только что проверил Ваш hex файл в симуляторе AVR STUDIO
при стрте программы с адреса 0xFC00 - прерывания
прекрасно генерится и приходит на 0x7E02(word) или 0xFC04 (byte)
У Вас точно Fuse битами установлено начало загрузчика с адреса 0x7E00 ???
Jhohn
Цитата(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"
Jhohn
Цитата(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"

Почему именно так прошиваются фьюзы, так и не понял. Только в этом случае прерывания пошли успешно.
xelax
Потому что в линкере адресация байтовая, а при установке фьюзов адресация пословная указывается.
для avr 1 word = 2 bytes.

отсюда адрес из линкерного скрипта делите пополам и получаете адрес который предлагает AVRStudio при установки фьюзов.
mdmitry
Цитата(xelax @ Sep 16 2010, 18:37) *
Потому что в линкере адресация байтовая, а при установке фьюзов адресация пословная указывается.
для avr 1 word = 2 bytes.

отсюда адрес из линкерного скрипта делите пополам и получаете адрес который предлагает AVRStudio при установки фьюзов.

Об этом уже где-то писал Сергей Борщ. Может пора это в FAQ?
Jhohn
Цитата(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=$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)
Jhohn
Цитата(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 и прозрел разницу: 1111493779.gif

AvrStudio: [BOOTSZ1, BOOTSZ0] - [1, 1] - "boot Flash size=512 words start address=$7F00"
datasheet: [BOOTSZ1, BOOTSZ0] - [1, 1] - "Boot Size = 512", "Boot Reset Address (Start Boot Loader Section) = 0x7E00"
и т.д.

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 * 0x7E00
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.