|
Bootloader. Подскажите., Проблема наверно в языке... |
|
|
|
Nov 11 2009, 08:53
|

Участник

Группа: Участник
Сообщений: 39
Регистрация: 24-08-09
Пользователь №: 52 013

|
Написал загрузчик для XMega128, IAR5.20. Переделал его из примера Атмела 1605. Загрузчик расположен в одном проекте с основным приложением в секции #ifdef. По сбросу стартует загрузчик и проверяет наличие программы в FRAM, если есть заливает ее во флеш. Определил сегмент в XCL: -D_..X_FLASH_HUGE_END=21FFF -D_..X_BOOTSEC_SIZE=2000 -Z(CODE)BOOT_SEGMENT=(_..X_FLASH_HUGE_END-_..X_BOOTSEC_SIZE+1)-_..X_FLASH_HUGE_END Сам загрузчик: Код #pragma segment = "BOOT_SEGMENT" #pragma location="BOOT_SEGMENT"
#include <eeprom_driver.h> #include <sp_driver.h> #include <defines.h>
#define BOOT_F_CPU 2000000UL
........ // определение типов и констант для I2C
boot_TWI_Master_t twiMaster; // структура для работы с I2C uint8_t boot_sBuf[32];
// объявление функций для I2C __root bool boot_TWI_MasterWriteRead(boot_TWI_Master_t *twi, uint8_t address, uint8_t *writeData, uint8_t bytesToWrite, uint8_t bytesToRead) @ "BOOT_SEGMENT"; __root void boot_TWI_MasterInterruptHandler(boot_TWI_Master_t *twi) @ "BOOT_SEGMENT";
.........
__root void boot(void) @ "BOOT_SEGMENT"; // тело загрузчика __root void GoToApplication(void) @ "BOOT_SEGMENT"; // переход в приложение
__root void boot(void) @ "BOOT_SEGMENT" { boot_TWI_MasterInit(&twiMaster, // инициализирую I2C &TWIF, TWI_MASTER_INTLVL_HI_gc, BOOT_TWI_BAUDSETTING); PMIC.CTRL |= PMIC_HILVLEN_bm; boot_sBuf[0] = 0x00; // читаю из FRAM 6 байтов boot_sBuf[1] = 0x40; boot_TWI_MasterWriteRead(&twiMaster, 0xA0, &boot_sBuf[0], 2, 6);
while (twiMaster.status != boot_TWIM_STATUS_READY) // пишу и читаю пока надо { if ((TWIF.MASTER.STATUS & 0xCC) != 0x00) { boot_TWI_MasterInterruptHandler(&twiMaster); } } // в зависимости от результата что-то делаю ............ GoToApplication(); }
__root void GoToApplication(void) @ "BOOT_SEGMENT" { cli(); PMIC.CTRL = 0; SP_WaitForSPM(); SP_LockSPM(); EIND = 0x00; void (*funcptr)( void ) = 0x0000; // Set up function pointer to RESET vector. funcptr(); // Jump to Reset vector 0x0000 in Application Section. }
__root bool boot_TWI_MasterWriteRead(boot_TWI_Master_t *twi, uint8_t address, uint8_t *writeData, uint8_t bytesToWrite, uint8_t bytesToRead) @ "BOOT_SEGMENT" { /*Parameter sanity check. */ if (bytesToWrite > boot_TWIM_WRITE_BUFFER_SIZE) { return false; } if (bytesToRead > boot_TWIM_READ_BUFFER_SIZE) { return false; }
.......................... } Загрузчик стартует как надо, переход в тело работает. Теперь собственно в чем проблема: Инициализация I2C проходит нормально, регистры принимают нужное значение. При вызове boot_TWI_MasterWriteRead(...) смотрю в отладчике, а там параметр bytesToRead всегда равен 0. Пробовал убрать параметр address, тогда bytesToRead передается как надо. Т.е получается не может передать большое количество параметров. Но дальше все равно не работает чтение из FRAM. Пробовал вставлять этот кусок в основное тело приложения, там все работает хорошо. Мне кажется или что-то со стеком при работе в области загрузчика или не знаю. Помогите пожалуйста И еще: может проблема быть связана с __root, #pragma и т.д.? Может чего-то не хватает? Просто я в них не особо шарю...
|
|
|
|
|
Nov 11 2009, 09:25
|

Профессионал
    
Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955

|
Цитата(KRS @ Nov 11 2009, 19:15)  А как вы рабоаете с прерываниями в бутлоадере? Какой cstartup используете? IMHO в данном случае лучше работать полингом! Пардон, вопрос не ко мне, но отвечу про себя. У меня в бутлоадерах традиционно запрещены все прерывания, работа с компортом по опросу состояния (polling). Ну, и на ассемблере работаю. Одна из попыток перейти на Си в микроконтроллерах как раз и завершилась кривым бутлоадером, полностью ручками перепер его на ассемблер, и с тех пор ему (ассемблеру) не изменяю. А на С, С++ пишу программы под винду, которые общаются с моими же программами из микроконтроллеров.
|
|
|
|
|
Nov 11 2009, 10:40
|

Участник

Группа: Участник
Сообщений: 39
Регистрация: 24-08-09
Пользователь №: 52 013

|
А я тут и использую полинг. С прерываниями я так и не разобрался (вроде как надо вторую таблицу создавать, а как ее создавать х.з.  ). А про startup можно поподробнее? Че как инициализировать? Просто я в общем язык и структуру понимаю, а в такие дебри еще не лазил. Надо взять готовый стартап и изменить его или свой новый создавать? За сегменты спасибо
|
|
|
|
|
Nov 11 2009, 11:25
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
примерно так Код EXTERN boot RSEG CSTACK:DATA:NOROOT(0) RSEG RSTACK:DATA:NOROOT(0) RSEG BOOTENTRY:CODE:ROOT(1)
LDI R17,LOW(SFE(RSTACK)-1) OUT SPL,R17 LDI R17,HIGH(SFE(RSTACK)-1) OUT SPH,R17 LDI YL,LOW(SFE(CSTACK)-1) LDI YH,HIGH(SFE(CSTACK)-1)
rjmp boot кстати на rjmp boot можно сэкономить, если расположить boot сразу за BOOT_ENTRY. Да здесь не инициализируются переменные! Если надо зполнять 0 и/или копировать контстанты можно добавить (кстати если переменных нет код автоматически уберется). Общий код примерно такой Код EXTERN boot RSEG CSTACK:DATA:NOROOT(0) RSEG RSTACK:DATA:NOROOT(0) RSEG BOOTENTRY:CODE:ROOT(1)
LDI R17,LOW(SFE(RSTACK)-1) OUT SPL,R17 LDI R17,HIGH(SFE(RSTACK)-1) OUT SPH,R17 LDI YL,LOW(SFE(CSTACK)-1) LDI YH,HIGH(SFE(CSTACK)-1) //NEAR_Z initialization RSEG STARTUPCODE:CODE:NOROOT(1) PUBLIC `?<Segment init: NEAR_Z>` `?<Segment init: NEAR_Z>`: lda Z, SFB(NEAR_Z) lda X, SIZEOF(NEAR_Z) clr r16 filloop: st Z+, r16 sbiw XL, 1 brne filloop
//NEAR_I initialization RSEG STARTUPCODE:CODE:NOROOT(1) PUBLIC `?<Segment init: NEAR_I>` `?<Segment init: NEAR_I>`: lda Z, SFB(NEAR_ID) lda Y, SFB(NEAR_I) lda X, SIZEOF(NEAR_I) moveloop: lpm r0, Z+ st Y+, r0 sbiw XL, 1 brne moveloop
RSEG BOOTENTRY:CODE:ROOT(1) rjmp boot
|
|
|
|
|
Nov 11 2009, 11:59
|

Участник

Группа: Участник
Сообщений: 39
Регистрация: 24-08-09
Пользователь №: 52 013

|
На всякий случай прошу прощения за возможно глупый вопрос А BOOTENTRY (в строке RSEG BOOTENTRY:CODE:ROOT(1)) это то же, что и BOOT_ENTY в вашем первом посте? И че вообще с этим кодом надо сделать? Его надо впихнуть в CSTARTUP, который я взял из avr\src\lib и подключил к своему проекту?
|
|
|
|
|
Nov 11 2009, 12:07
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(vitek101 @ Nov 11 2009, 14:59)  На всякий случай прошу прощения за возможно глупый вопрос А BOOTENTRY (в строке RSEG BOOTENTRY:CODE:ROOT(1)) это то же, что и BOOT_ENTY в вашем первом посте? И че вообще с этим кодом надо сделать? Его надо впихнуть в CSTARTUP, который я взял из avr\src\lib и подключил к своему проекту? Да это BOOT_ENTRY, там еще, елси переменные инициализировать STARTUPCODE надо на BOOT_ENTRY заменить. его надо вместо CSTARTUP. Да boot надо остваить в BOOTCODE.
|
|
|
|
|
Nov 11 2009, 12:33
|

Участник

Группа: Участник
Сообщений: 39
Регистрация: 24-08-09
Пользователь №: 52 013

|
Сделал так: Код EXTERN boot RSEG CSTACK:DATA:NOROOT(0) RSEG RSTACK:DATA:NOROOT(0) RSEG BOOT_ENTRY:CODE:ROOT(1)
LDI R17,LOW(SFE(RSTACK)-1) OUT SPL,R17 LDI R17,HIGH(SFE(RSTACK)-1) OUT SPH,R17 LDI YL,LOW(SFE(CSTACK)-1) // тут ругается: illegal effective address LDI YH,HIGH(SFE(CSTACK)-1) // тут ругается: illegal effective address //NEAR_Z initialization RSEG BOOT_ENTRY:CODE:NOROOT(1) // тут заменил STARUPCODE на BOOT_ENTRY PUBLIC `?<Segment init: NEAR_Z>` `?<Segment init: NEAR_Z>`: lda Z, SFB(NEAR_Z) // тут ругается: bad instruction lda X, SIZEOF(NEAR_Z) // тут ругается: bad instruction clr r16 filloop: st Z+, r16 sbiw XL, 1 // тут ругается: illegal effective address brne filloop
//NEAR_I initialization RSEG BOOT_ENTRY:CODE:NOROOT(1) // тут заменил STARUPCODE на BOOT_ENTRY PUBLIC `?<Segment init: NEAR_I>` `?<Segment init: NEAR_I>`: lda Z, SFB(NEAR_ID) // тут ругается: bad instruction lda Y, SFB(NEAR_I) // тут ругается: bad instruction lda X, SIZEOF(NEAR_I) // тут ругается: bad instruction moveloop: lpm r0, Z+ st Y+, r0 sbiw XL, 1 // тут ругается: illegal effective address brne moveloop
RSEG BOOT_ENTRY:CODE:ROOT(1) rjmp boot // тут ругается unexpected end of file encountered Это все вставил вместо содержимого стандартного CSTARTUP. Что делаю не так?
|
|
|
|
|
Nov 11 2009, 12:43
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(vitek101 @ Nov 11 2009, 15:33)  Это все вставил вместо содержимого стандартного CSTARTUP. Что делаю не так? так надо Код END в конце написать
|
|
|
|
|
Nov 11 2009, 13:51
|

Участник

Группа: Участник
Сообщений: 39
Регистрация: 24-08-09
Пользователь №: 52 013

|
А можно заменить Код lda Z, SFB(NEAR_Z) на Код LD[b]A[/b] ZL,LOW(SF[b]B[/b](NEAR_Z)-1) LD[b]A[/b] ZH,HIGH(SF[b]B[/b](NEAR_Z)-1) ? illegal effective address убрались  Спросил, а потом увидел ответ  Вроде собрал, правда только первую часть (без инициализации переменных. Там ругается invalid syntax на строки с макросом). Только он теперь говорит undefined external "boot" referred in cstatup  Все, запустил. Но в отладчике нашего стартапа не видно и все не работает по-старому...
|
|
|
|
|
Nov 11 2009, 14:24
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(vitek101 @ Nov 11 2009, 16:51)  Все, запустил. Но в отладчике нашего стартапа не видно и все не работает по-старому... Это значит startup взялся стандартный из библиотеки! Для начала можно вообще библиотеку отключить! (она тут скорее всего не нужна) А откуда стартует проц? (под отладчиком) По исходнику Код RSEG BOOT_ENTRY:CODE:ROOT(1)
LDI R17,LOW(SFE(RSTACK)-1) т.е. по адресу начала BOOT_ENTRY должны быть эти данные! что бы отключить стандартный стартап из библиотеки, надо в настройках линкера поставить override default program entry и вписать метку __program_start а код модифицировать Код RSEG BOOT_ENTRY:CODE:ROOT(1) PUBLIC __program_start __program_start: LDI R17,LOW(SFE(RSTACK)-1) Но это надо проверить я в основном 3 версию иар использую. В новой были пробелмы что не хотел он стартап стандартный убирать, приходилось ручками из библиотеки моуль удалять! Вообще надо map файл смотреть - что линкер напихал и куда!
Сообщение отредактировал KRS - Nov 11 2009, 14:24
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|