Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: USB загрузчик для LPC2368
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Alex_akn
Доброго времени суток.
Возникла потребность в USB загрузчике для LPC.
Может есть аналог SAM-BA для NXP-ых продуктов?
Подскажите пожалуйста в какую сторону смотреть.
DmitryV
Цитата(Alex_akn @ Jul 4 2008, 19:01) *
Доброго времени суток.
Возникла потребность в USB загрузчике для LPC.
Может есть аналог SAM-BA для NXP-ых продуктов?
Подскажите пожалуйста в какую сторону смотреть.

На данный момент такой загрузчик существует (по крайней мере, для LPC2148)
и находится в стадии тестирования. Скоро появится в доступе и будет
прошиваться при производстве новых чипов. Вроде бы для 23хх тоже будет.
Работает методом заливки HEX на USB Mass Storage Device, коим будет
являтся контроллер с прошитым загрузчиком, т.е. даже без дополнительного
софта.
gte
А скоро это в месяцах, кварталах или годах?
DmitryV
Цитата(gte @ Jul 5 2008, 10:14) *
А скоро это в месяцах, кварталах или годах?

Скоро - это скоро.
Направил запрос компетентным органам.
Ответят - сообщу тут.
gte
Спасибо. Мой вопрос был без подвоха, учитывая скорое появление ATXMEGA.
Alex_akn
Вот это вещь - http://www.tnkernel.com/usb_fw_upgrader.html!
Кто-то уже может запускал это для LPC23xx? Если запускали, опишите какие изменения требуются.
zltigo
Цитата(Alex_akn @ Jul 6 2008, 11:45) *
..какие изменения требуются.

В первом приближении контроллер прерываний другой.
Alex_akn
Цитата(zltigo @ Jul 6 2008, 15:54) *
В первом приближении контроллер прерываний другой.

Это понятно. Сделано. А в остальных приближениях?
zltigo
Цитата(Alex_akn @ Jul 6 2008, 12:06) *
Это понятно. Сделано. А в остальных приближениях?

USB хидеры править (или не использовать от TN вообще ) - адреса поменялисть, и имена немного.
Alex_akn
Цитата(zltigo @ Jul 6 2008, 16:18) *
USB хидеры править (или не использовать от TN вообще ) - адреса поменялисть, и имена немного.

Всё. Понял.
Еще вопрос. Кусок кода из модуля fwu.c:
int main()
{
unsigned int * ptr;
int state;

rMEMMAP = 0x1;

tn_arm_disable_interrupts();

Init_CRC32_Table();

state = flash_pcell; //-- For IAR linker only
//---- Set interrupts vectors
ptr = (unsigned int *)IRQ_RAM_ADDR;
*ptr = 0xE59FF018; //-- ldr pc, [pc, #24]
ptr = (unsigned int *)FIQ_RAM_ADDR;
*ptr = 0xE59FF018; //-- ldr pc, [pc, #24]

//--- Put IRQ & FIQ vectors in RAM
ptr = (unsigned int *)IRQ_RAM_FUNC_ADDR;
*ptr = (unsigned int)&cpu_irq_isr;
ptr = (unsigned int *)FIQ_RAM_FUNC_ADDR;
*ptr = (unsigned int)&cpu_fiq_isr;

#ifndef RUN_FW_ALWAYS

//--- Check 'Run as Loader' mark
ptr =(unsigned int *)RAM_START_ADDR;
if(!(*ptr == 0x12345678 && *(ptr+1) == 0x43211234))
{
do_switch_to_firmware(); //-- Never returns
}
#else
start_firmware(); //-- Never returns
#endif
...
...
}
Откуда в раме появляется два числа 0x12345678 и 0x43211234 если программа еще не использовала вообще эти адреса?
Или я не туда смотрю?

Цитата(zltigo @ Jul 6 2008, 16:18) *
USB хидеры править (или не использовать от TN вообще ) - адреса поменялисть, и имена немного.

Еще есть один наглый вопрос. Если вы запускали это дело под lpc23xx можете выложить? Поменять всё и сам могу, но хочу сэкономить время хоть чуток.
zltigo
Цитата(Alex_akn @ Jul 6 2008, 12:44) *
Откуда в раме появляется два числа 0x12345678 и 0x43211234 если программа еще не использовала вообще эти адреса?

Выставятся, когда уже из работающей программы будет запрошен загрузчик, после чего будет через watchdog изображен reset...
Цитата
Если вы запускали это дело...

Не запускал ни под чем, посто читал в свое время для общего развития и работал с обеими контроллерами.
И не сочтите за труд, для исходников пользоваться опциями форматирования.
Alex_akn
Цитата(zltigo @ Jul 6 2008, 16:56) *
Выставятся, когда уже из работающей программы будет запрошен загрузчик, после чего будет через watcdog изображен reset...

Не запускал ни под чем, посто читал в свое время для общего развития и работал с обеими контроллерами.
И не сочтите за труд, для исходников пользоваться опциями форматирования.

"И не сочтите за труд, для исходников пользоваться опциями форматирования." - ОК smile.gif
Что значит "после чего будет через watcdog изображен reset..."?
zltigo
Цитата(Alex_akn @ Jul 6 2008, 13:10) *
Что значит "после чего будет через watcdog изображен reset..."?

Ну.. то и значит - reset будет инициализирован watchdog-ом, попадете на main(), где прочитаете ранее занесенные магические цифры и пойдете в загрузчик....
Alex_akn
Цитата(zltigo @ Jul 6 2008, 16:56) *
Выставятся, когда уже из работающей программы будет запрошен загрузчик, после чего будет через watchdog изображен reset...

Не запускал ни под чем, посто читал в свое время для общего развития и работал с обеими контроллерами.
И не сочтите за труд, для исходников пользоваться опциями форматирования.

Всё! Разобрался! Спасибо огромное за ответы smile.gif
zltigo
Цитата(DmitryV @ Jul 4 2008, 21:02) *
На данный момент такой загрузчик существует (по крайней мере, для LPC2148)
и находится в стадии тестирования. Скоро появится в доступе...

Доступен уже с 20 мая - AN10711 USB Secondary ISP Bootloader with Source Files
Alex_akn
Вопрос по TNK-loader:
Код
...
//---- Set interrupts vectors
ptr = (unsigned int *)IRQ_RAM_ADDR;
*ptr = 0xE59FF018;                //-- ldr pc, [pc, #24]
ptr = (unsigned int *)FIQ_RAM_ADDR;
*ptr = 0xE59FF018;    
...


Зачем по адресу IRQ_RAM_ADDR(FIQ_RAM_ADDR) кладется число 0xE59FF018?


И попутный вопрос:
Код
void  tn_usb_lpc_cmd_write(int cmd, int data)
{
       E1A0C00D   mov r12, sp
       E92DD800   stmfd sp!, {r11-r12, lr-pc}
       E24CB004   sub r11, r12, #0x00000004
       E24DD008   sub sp, sp, #0x00000008
       E50B0010   str r0, [r11, #-0x010]
       E50B1014   str r1, [r11, #-0x014]
   USBDevIntClr = CDFULL | CCEMTY;            // clear CDFULL/CCEMTY
       E3A0328F   mov r3, #0xF0000008
       E28336FE   add r3, r3, #0x0FE00000
       E2833CC2   add r3, r3, #0x0000C200
       E3A02030   mov r2, #0x00000030
       E5832000   str r2, [r3]
   USBCmdCode = 0x00000500 | (cmd << 16);    // write command code
       E59F208C   ldr r2, [pc, #+0x08C]
       E51B3010   ldr r3, [r11, #-0x010]
       E1A03803   mov r3, r3, lsl #0x10
       E3833C05   orr r3, r3, #0x00000500
[color=#FF0000]===>>>E5823000   str r3, [r2]  <<<<<<=============[/color]
   while(!(USBDevIntSt & CCEMTY));
       E3A034FF   mov r3, #0xFF000000
       E283360E   add r3, r3, #0x00E00000
       E2833CC2   add r3, r3, #0x0000C200
       E5933000   ldr r3, [r3]
       E2033010   and r3, r3, #0x00000010
       E3530000   cmp r3, #0x00000000
       0AFFFFF8   beq 0x000032E0
...

До выполнения указанной строчки регистры:
r0 = 0xfe
r1 = 0x00
r2 = 0xffe0c210
r3 = 0x00fe0500
c r4 по r10 = 0x00
r11 = 0x4000209c
r12 = 0x400020a0
r13(sp) = 0x40002088
r14 = 0x00000db0
r15 = 0x000032dc
cpsr = 0xa00000df
данные:
data = 0x00
cmd = 0x000000fe

После выполнения указанной строчки проваливаемся в dabort_handler.
Может кто-то сможет пояснить?
Сергей Борщ
Цитата(Alex_akn @ Jul 15 2008, 01:27) *
Зачем по адресу IRQ_RAM_ADDR(FIQ_RAM_ADDR) кладется число 0xE59FF018?
Там же в коментариях написано: это код команды ldr pc, [pc, #24]
Alex_akn
Цитата(Сергей Борщ @ Jul 15 2008, 12:51) *
Там же в коментариях написано: это код команды ldr pc, [pc, #24]

Сергей. Я прекрасно вижу, что написано в коментариях. Лучше скажите зачем это нужно!
HARMHARM
Цитата(Alex_akn @ Jul 15 2008, 10:46) *
Сергей. Я прекрасно вижу, что написано в коментариях. Лучше скажите зачем это нужно!

Это инициализация векторов прерываний (таблица в RAM), делается перед remap (MEMMAP =0x2).
Alex_akn
Цитата(Сергей Борщ @ Jul 15 2008, 12:51) *
Там же в коментариях написано: это код команды ldr pc, [pc, #24]

Смысл какой? Просто увеличить PC? Или же, всё-таки, разместить по адресу IRQ_RAM_ADDR число 0xe59ff018? Если же просто увеличить PC, то я смысл этого действия вообще не вижу.
Может сможет кто объяснить?

Цитата(HARMHARM @ Jul 15 2008, 14:20) *
Это инициализация векторов прерываний (таблица в RAM), делается перед remap (MEMMAP =0x2).

Код
int main()
{
    unsigned int * ptr;
    int state;
    
    MEMMAP = 0x1;
    
    //tn_arm_disable_interrupts();
        ctl_global_interrupts_disable();
    
    Init_CRC32_Table();
    
    //---- Set interrupts vectors
    ptr = (unsigned int *)IRQ_RAM_ADDR;
    *ptr = 0xE59FF018;                //-- ldr pc, [pc, #24]
    ptr = (unsigned int *)FIQ_RAM_ADDR;
    *ptr = 0xE59FF018;                //-- ldr pc, [pc, #24]
    
    //--- Put IRQ & FIQ vectors in RAM
    ptr = (unsigned int *)IRQ_RAM_FUNC_ADDR;
    *ptr = (unsigned int)&cpu_irq_isr;
    ptr = (unsigned int *)FIQ_RAM_FUNC_ADDR;
    *ptr = (unsigned int)&cpu_fiq_isr;
    
    #ifndef RUN_FW_ALWAYS
    
    //--- Check 'Run as Loader' mark
    ptr =(unsigned int *)RAM_START_ADDR;
    if(!(*ptr == 0x12345678 && *(ptr+1) == 0x43211234))
    {
        do_switch_to_firmware();   //-- Never returns
    }
    #else
    start_firmware(); //-- Never returns
    #endif
    
    //------ Clear FW loader marks
    ptr =(unsigned int *)RAM_START_ADDR;
    *ptr = 0;
    ptr++;
    *ptr = 0;
    
    HardwareInit(); и т.д. и т.п.........

(В курсе: MEMMAP =0x2 -> User RAM Mode. Interrupt vectors are re-mapped to Static RAM).
Вектора IRQ, FIQ он явно кладет по нужным адресам.
MEMMAP же нигде в программе больше не трогается.
???
aaarrr
Цитата(Alex_akn @ Jul 15 2008, 12:31) *
Смысл какой? Просто увеличить PC? Или же, всё-таки, разместить по адресу IRQ_RAM_ADDR число 0xe59ff018? Если же просто увеличить PC, то я смысл этого действия вообще не вижу.
Может сможет кто объяснить?

ldr pc, [pc, #24] - это не увеличить PC, а загрузить его из ячейки по адресу PC+24+8.
Alex_akn
Цитата(aaarrr @ Jul 15 2008, 14:53) *
ldr pc, [pc, #24] - это не увеличить PC, а загрузить его из ячейки по адресу PC+24+8.

Вот код этого дела.
Код
    //---- Set interrupts vectors
    ptr = (unsigned int *)IRQ_RAM_ADDR;
       E3A03161   mov r3, #0x40000018
       E50B3014   str r3, [r11, #-0x014]
    *ptr = 0xE59FF018;                //-- ldr pc, [pc, #24]
       E51B2014   ldr r2, [r11, #-0x014]
       E3E03EFE   mvn r3, #0x00000FE0
       E2433271   sub r3, r3, #0x10000007
       E24336A6   sub r3, r3, #0x0A600000
       E5823000   str r3, [r2]
    ptr = (unsigned int *)FIQ_RAM_ADDR;
       E3A03171   mov r3, #0x4000001C
       E50B3014   str r3, [r11, #-0x014]
    *ptr = 0xE59FF018;                //-- ldr pc, [pc, #24]
       E51B2014   ldr r2, [r11, #-0x014]
       E3E03EFE   mvn r3, #0x00000FE0
       E2433271   sub r3, r3, #0x10000007
       E24336A6   sub r3, r3, #0x0A600000
       E5823000   str r3, [r2]

Может поможете увидеть где здесь загрузка из ячейки по адресу PC+24+8?
vet
после выполнения вышеприведенного кода пресловутая команда загрузки будет лежать в ОЗУ по адресу вектора IRQ.
HARMHARM
Цитата(Alex_akn @ Jul 15 2008, 11:31) *
(В курсе: MEMMAP =0x2 -> User RAM Mode. Interrupt vectors are re-mapped to Static RAM).
Вектора IRQ, FIQ он явно кладет по нужным адресам.
MEMMAP же нигде в программе больше не трогается.
???

Здесь MEMMAP не используется. Если вы посмотрите в fwu_startup_iar.s79 :
Код
reset           ldr     pc, ?vect_entry
                ldr     pc, ?vect_entry +  4
                ldr     pc, ?vect_entry +  8
                ldr     pc, ?vect_entry + 12
                ldr     pc, ?vect_entry + 16
                DC32    0xB8A06F58          /* 0 - (sum of other vectors instructions) */
                ldr     pc, ?vect_entry + 24
                ldr     pc, ?vect_entry + 28

?vect_entry:
                DC32    ?cstartup; RES    (  0)
                DC32    ?cstartup; UND    ( +4)
                DC32    ?cstartup; SWI    ( +8)
                DC32    ?cstartup; P_ABT  (+12)
                DC32    ?cstartup; D_ABT  (+16)
                DC32    0; ARM-reserved vector  (+20)
                DC32    0x40000018; cpu_irq_isr; IRQ    (+24)
                DC32    0x4000001C; cpu_fiq_isr; FRQ    (+28)

видно, что 0x40000018 и 0x4000001C - адреса, по которым будет передаваться управление при IRQ и FIQ. Фактически комбинация ldr pc,xxx и собственно ячейки xxx,например
Код
ldr     pc, ?vect_entry
?vect_entry:
DC32    ?cstartup; RES    (  0)

это branch, то есть безусловный переход в любое место в пределах адресного пространства.
В tnkernel таким образом сделаны векторы прерываний для того, чтобы проложение могло установить свой вектор (в flash-то лежат векторы загрузчика). Совершенно нормальный подход. Хотя я в своем загрузчике использую немного другой подход, по мотивам кода уважаемого Zltigo.
Код
__program_start:
                ldr     pc,(?vect_entry + 4*0)  // 00
                ldr     pc,(?vect_entry + 4*1)  // 04
                ldr     pc,(?vect_entry + 4*2)  // 08
                ldr     pc,(?vect_entry + 4*3)  // 0C
                ldr     pc,(?vect_entry + 4*4)  // 10
                dc32    0                       // 14 Summ of other vectors instructions
                ldr     pc,[pc,#-0x0120]        // 18 Jump directly to the address given by the VIC
                                                // from [0xFFFFFF00] Curent 18h +8(conveyer)=20h
                ldr     pc,(?vect_entry + 4*7)  // 1C
//---------------------------------------------------------------------------
                ORG     0x20       // Constant table entries (for ldr pc) will be placed at 0x20
?vect_entry:
                dc32    ?cstartup               // Reset
                dc32    ?cstartup               // UND
                dc32    Application_SWI         // SWI
                dc32    PABT_handler            // P_ABT
                dc32    DABT_handler            // D_ABT
                dc32    0                       // ARM-reserved vector
                dc32    0                       // IRQ (Jump directly!)
                dc32    Application_FIQ         // FIQ

Здесь адрес обработчика IRQ берется непосредственно из VIC, reset в начало загрузчика, SWI и FIQ берутся из заголовка приложения по адресу, где приложение будет располагаться. Вот заголовок приложения:
Код
//== With Loader
        dc8    Hardware_Version        // 00 Hardware revision
        dc8    Bootloader_Version       // 01
        dc8    Application_VersionL       // 02
        dc8    Application_VersionH        // 03
        dc32    SFB(CHECKSUM)           // 04 End of code         address
        ldr     pc,[pc,#-0x4]           // 08 Start Entry Point
        dc32    ?cstartup               // 0C *Reset
        ldr     pc,[pc,#-0x4]           // 10 SWI
        dc32    ?cstartup  //vPortYieldProcessor     // 14 *SWI
// Place for FIQ Handler ----------------------------------------------------
        ldr     pc,[pc,#-0x4]        // 18 FIQ
        dc32    FIQ_ISR_handler         // 1C *FIQ

То есть при SWI будет сначала переход в заголовок загрузчика, потом уже в собственно обработчик. RAM при этом не используется вообще. Правда есть дополнительный переход.
Единственное что, поскольку в загрузчике жестко прописан переход по SWI в приложение, при необходимости использования SWI (или FIQ) в загрузчике приходится использовать MEMMAP=2.
Здесь ldr pc,[pc,#-0x4] грузит в pc на самом деле константу из следующих четырех байт, из-за конвеера тут -4(+8) а не +4.
Уфф.
Alex_akn
Спасибо за ответы. Кое-что стало понятно.
Как команду "ldr pc, [pc, #24]" перевели в число "0xE59FF018"?
И наоборот из числа в команду?
HARMHARM
Цитата(Alex_akn @ Jul 16 2008, 09:24) *
Спасибо за ответы. Кое-что стало понятно.
Как команду "ldr pc, [pc, #24]" перевели в число "0xE59FF018"?
И наоборот из числа в команду?

Можно с помощью ассемблера, посмотрев листинг. А обратно - где-то в интернете видел. Можно использовать дизассемблер, или почитать документацию от ARM.
Alex_akn
Цитата(HARMHARM @ Jul 16 2008, 14:23) *
Можно с помощью ассемблера, посмотрев листинг. А обратно - где-то в интернете видел. Можно использовать дизассемблер, или почитать документацию от ARM.

Спасибо! smile.gif
Alex_akn
Загрузчик заработал, но выяснилась такая вещь:
в главной функции завел статическую переменную
И эта переменная располагается по адресу 0x40000000.
В этой же ячейке у меня хранится информация для загрузчика, которая туда записывается принудительно.
Как в кросс ворксе сделать так, чтобы эта статическая переменная лежала за адресом, допустим, 0x40000100?
dmtr
А нет ли загрузчика, чтобы грузил программу через usb в озу процессора?
Axel
Цитата(Alex_akn @ Jul 20 2008, 13:39) *
Как в кросс ворксе сделать так, чтобы эта статическая переменная лежала за адресом, допустим, 0x40000100?


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