2006-04-25 06:16 PM
IAP-Loader and own application at 0x40002000
2006-04-24 09:41 PM
Hello to all,
Has anyone a working application loaded with the IAP-Loader and using KEIL UVision and RVCT 3.0. Until the present moment my application (using interrupts) was not working when starting the program at address 0x40002000. Has anyone experience how to modify the startup-programs and the compilertools for running such an application. I have asked Keil for this problem, but up to now they have only modified the IAP-Driver using with Keil UVision and RVCT3.0. (can be downloaded from Keil) needing help urgently. thanks maenni2006-04-25 05:09 AM
I've done a bootloader for the STR710, like you describe. I'll describe you all that you need to do to create your own bootloader. Actually i've done it under RVDS, but Keil use the same compiler since it's ARM company.
Basicly my bootloader is stored at 0x4000 0000, in the first sector. This loader is start at the reset. First it check if the program (next sectors) are ok (check for a magic number), and optionnaly if a GPIO is tied high ( to tell to stay in loader program). 1/ Relocate your program : a) You need to adapt the scatter file like this: PROGRAM 0x40002000 { FLASH_INT32 0x40002000 PADVALUE 0xFFffFFff 0x3E000 { 71x_vect.o (Vect, +First) 71x_init.o (Init) * (+RO) } RAM_INT32 0x20000000 0x10000 { * (+RW) * (+ZI) } } LOADER 0x40000000 { LOADER 0x40000000 PADVALUE 0xFFffFFff 0x02000 { wrapper.o (Vector,+First) loader.o } } This scatter has two program : The loader @ 0x4000 0000 The programm @ 0x4000 2000 b) The wrapper: it is an asm part that redirect all call to the vectors to the vectors @ 0x40002000, excet for the reset handler, it call a small part of the loader to check the GPIO etc. PRESERVE8 AREA Vector, CODE, READONLY CODE32 ENTRY Mode_SVC EQU 0x13 I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled Stack_Base EQU 0x20010000 IMPORT loader_resethandler IMPORT loader_upgrade ;******************************************************************************* ; Exception vectors ;******************************************************************************* LDR PC, =Loader_init LDR PC, Load_Undefined_Addr LDR PC, Load_SWI_Addr LDR PC, Load_Prefetch_Addr LDR PC, Load_Abort_Addr NOP ; Reserved vector LDR PC, Load_IRQ_Addr LDR PC, Load_FIQ_Addr ;******************************************************************************* ; Exception handlers address table ;******************************************************************************* Load_Reset_Addr DCD &40002000 Load_Undefined_Addr DCD &40002004 Load_SWI_Addr DCD &40002008 Load_Prefetch_Addr DCD &4000200C Load_Abort_Addr DCD &40002010 Load_IRQ_Addr DCD &40002018 Load_FIQ_Addr DCD &4000201C UPGRADE DCD loader_upgrade Loader_init MSR CPSR_c, #Mode_SVC:OR:F_Bit:OR:I_Bit LDR SP, =Stack_Base ; jmp to loader in 'C' BL loader_resethandler LDR PC,Load_Reset_Addr END c) The STR710 library has to be modified to be able to run @ 0x40002000: in eic.c: /******************************************************************************* * Function Name : EIC_Init * Description : Initialise the EIC using the load PC instruction * (PC = PC +offset) * Input : None * Output : None * Return : None *******************************************************************************/ void EIC_Init(void) { extern u32 T0TIMI_Addr; u8 bCounter; u32 dOffset=((u32)&T0TIMI_Addr); /* Disable FIQ and IRQ interrupts */ EIC->ICR = 0x00000000; /* Disable all channels interrupts */ EIC->IER = 0x00000000; /* Clear all pending bits */ EIC->IPR = 0xFFFFFFFF; /* Disable all FIQ channels interrupts and clear FIQ */ EIC->FIR = 0x0000000C; /* channels pending bits */ /* Ste the current priority level to zero */ EIC->CIPR = 0x00000000; // LIBLOADER (IVR is adr directly) EIC->IVR = dOffset&0xFFff0000; dOffset <<=16; /* Initialize SIRn registers*/ for(bCounter=0; bCounter { EIC->SIR[bCounter] = dOffset; dOffset += 0x00000004 << 16; } } and in 71x_vect.s in the irq handler : ;ADD pc,r0,r1 ; Branch to the IRQ handler. LDR r1,[R0,R1] LDR PC,[r1] d) write your loadder in the c file nammed loader.c in this file for me there is two void functions : - one named loader_resethandler which do the check for GPIO, test the magic number, and then call the update program if something wrong or, exit to let the real program boot if it is ok. - the loader (loader_upgrade) that use an uart and our protocol to do the upgarde of the flash. This function are restricted : - no use of other function ( everything need to be IN this file loader.o), for example to check the GPIO you need to use directly the register of the SRT710 or create your functions but you can't share the SRT710 library with your application... - no use of interrupt, you need to disable interrupts to be sure that you will not exit of the loader - you need to copy manually the flash routine to ram, because the STR710 can only erase/program his bank0 if the program that write is located outside this bank... - You need to NEVER change this first sector, if you want to be sure that the loader is present all the time. And with this, if you want to call the loader in you application you have just to add : ((void(*)(void))*(int*)0x4000003C)(); I hope that will help you. Sincerely Chris.2006-04-25 06:10 PM
Loader :
DATA (0x20000000-0x2000FFFF), CODE (0x40000000-0x40001FFF), CONST (0x40000000-0x40001FFF), CODE_IRQ (0x40000000-0x40001FFF) void main (void) { u8 CheckAppResult; InitDevice(); //RXD is Break, Boot will be excuted if ((GPIO0->PD & RX_PIN) == 0) { Delayms(100); if ((GPIO0->PD & (RX_PIN)) == 0) { while ((GPIO0->PD & (RX_PIN)) == 0); ExecBoot(); } } //Check Application // OK -- Run Application // Fail -- Run Boot to get new application CheckAppResult = CheckApp(); if (!CheckAppResult) ExecBoot(); else ExecApp(); } u8 Application[32768] __at 0x20000000; void LoadApplication(void) { // Some Var ........... while(1) { GetChar(&AByte, 0xffffffff); PutChar(AByte); ByteCount = AByte; GetChar(&AByte, 0xffffffff); PutChar(AByte); ByteCount += (((u16)AByte) << 8); CS = 0; for (i=0;i { GetChar(&AByte, 0xffffffff); PutChar(AByte); Application[i] = AByte; CS += AByte; } GetChar(&AByte, 0xffffffff); if (CS != AByte) { PutChar(0xAA); continue; } PutChar(0x55); break; } } void RunApplication(void) __arm { EIC_IRQConfig(DISABLE); EIC_FIQConfig( DISABLE ); __asm { MOV R1, #0x02 LDR R0, =0xA0000050 LDRH R2, [R0] BIC R2, R2, #0x03 ORR R2, R2, R1 STRH R2, [R0] MOV PC, #0 } } //Download code to RAM, run code from RAM to program Flash // and something ... void ExecBoot(void) { InitUART(115200, UART_NO_PARITY, UART_1_StopBits, UARTM_8D); WaitPassword(); LoadApplication(); RunApplication(); while(1); } //Application is OK //Copy Application IVT to 0x20000000 //Remap RAM to 0x00000000 //PC = 0x00000000 void ExecApp(void) __arm { EIC_IRQConfig(DISABLE); EIC_FIQConfig( DISABLE ); __asm { LDR R0, =0x40002000 LDR R1, =0x20000000 LDMIA R0!, {R4-R11} STMIA R1!, {R4-R11} LDMIA R0!, {R4-R11} STMIA R1!, {R4-R11} MOV R1, #0x02 LDR R0, =0xA0000050 LDRH R2, [R0] BIC R2, R2, #0x03 ORR R2, R2, R1 STRH R2, [R0] MOV PC, #0 } }2006-04-25 06:14 PM
Application :
DATA (0x20000040-0x2000FFFF), CODE (0x40002000-0x4003FFFF), CONST (0x40002000-0x4003FFFF), CONST (0x400C0000-0x400C3FFF), CODE_IRQ (0x40002000-0x4000FFFF) STARTUPCODE (0x40002000) Flash Bank0 : as Code Flash Bank1 : as Data/Const RAM : 0x20000000..0x2000003F : Boot will copy Applicaton's IVT to here void main (void) { InitDevice(); while(1) { } }2006-04-25 06:16 PM
Contact me :
MSN/GoogleTalk/email : shangdawei%gmail.com [ This message was edited by: shangdawei on 27-04-2006 14:57 ]