|
Hello there! I've been stuck with this problem for a long time and i hope you can help me a bit with it, i'll be very grateful. By the way, i'm kind of new working with embedded systems so please be patient with me. I'm working with an AT91SAM7S256. The thing is that i'm trying to run a boot program, with c initialization and then the main program, but seems that after the c initialization is called (with B instruction) and finished, somehow the PC gets lost or maybe the destination address change, and whatever is happening makes that my boot program doesn't follow the next instruction that should be executed. Can anyone tell me why this happens??
I forgot to say that i use the arm-elf-gcc cross compiler
my boot code is the next. I must say that i took it from an example, and then i modified it for my purpose. The problem occurs when the low_level_init function is called with B instruction /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
.equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */ .equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */
.equ USR_MODE, 0x10 .equ FIQ_MODE, 0x11 .equ IRQ_MODE, 0x12 .equ SVC_MODE, 0x13 .equ ABT_MODE, 0x17 .equ UND_MODE, 0x1B .equ SYS_MODE, 0x1F
/* constant to pre-fill the stack */ .equ STACK_FILL, 0xAAAAAAAA
/* for PaRTiKle*/ #define PsrMask 0x1F
/***************************************************************************** * The starupt code must be linked at the start of ROM, which is NOT * necessarily address zero. */ .text .code 32
.global _start .func _start
_start:
/* Vector table * NOTE: used only very briefly until RAM is remapped to address zero */ B _reset /* Reset: relative branch allows remap */ B . /* Undefined Instruction */ B . /* Software Interrupt */ B . /* Prefetch Abort */ B . /* Data Abort */ B . /* Reserved */ B . /* IRQ */ B . /* FIQ */
/* The copyright notice embedded prominently at the begining of the ROM */ .string "NXT @ PaRTiKle by Luis Guerra" .align 4 /* re-align to the word boundary */
/***************************************************************************** * _reset */ _reset:
/* Call the platform-specific low-level initialization routine * * NOTE: The ROM is typically NOT at its linked address before the remap, * so the branch to low_level_init() must be relative (position * independent code). The low_level_init() function must continue to * execute in ARM state. Also, the function low_level_init() cannot rely * on uninitialized data being cleared and cannot use any initialized * data, because the .bss and .data sections have not been initialized yet. */ LDR r0,=_reset /* pass the reset address as the 1st argument */ LDR r1,=_cstartup /* pass the return address as the 2nd argument */ MOV lr,r1 /* set the return address after the remap */ LDR sp,=__stack_end__ /* set the temporary stack pointer */ B low_level_init /* relative branch enables remap */ /*************************** here is the branch, but when it returns, it seems that doesn't take _cstartup as the next address to go /
/* NOTE: after the return from low_level_init() the ROM is remapped * to its linked address so the rest of the code executes at its linked * address. */
_cstartup:
LLDR r0,=_cstartup LDR r1,=_cstartup1 MOV lr,r1 B turnoff /************************************************************** this functions is never called, what tells me the execution never reach here/
_cstartup1:
/* Relocate .fastcode section (copy from ROM to RAM) */ LDR r0,=__fastcode_load LDR r1,=__fastcode_start LDR r2,=__fastcode_end 1: CMP r1,r2 LDMLTIA r0!,{r3} STMLTIA r1!,{r3} BLT 1b
/*more continues, but i don't believe is necessary to post it all*/ /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
Now, the c_initialization. I tested this code and seems to work fine.
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #include "AT91SAM7S256.h"
/*The next type definitions are supposed to be in the stdlib.h, but since i cannot use it here, i put this ones*/ typedef unsigned long int uint32_t; typedef unsigned char uint8_t;
/*modified for the use with NXT*/
extern void AT91F_Spurious_handler(void);
extern void AT91F_Default_IRQ_handler(void);
extern void AT91F_Default_FIQ_handler(void);
void low_level_init(void (*reset_addr)(), void (*return_addr)()) { extern uint8_t __ram_start; static uint32_t const LDR_PC_PC = 0xE59FF000U; static uint32_t const MAGIC = 0xDEADBEEFU;
int i;
AT91PS_PMC pPMC = AT91C_BASE_PMC;
/*for correct debbuging*/ pPMC->PMC_MCKR &= ~0x03; while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY)); /*end debbug instructions*/
//* Set Flash Waite sate
// Single Cycle Access at Up to 30 MHz, or 40
// if MCK = 47923200 I have 72 Cycle for 1,5 usecond ( flied MC_FMR->FMCN
AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(72 <<16)) | AT91C_MC_FWS_1FWS ;
//* Watchdog Disable
AT91C_BASE_WDTC->WDTC_WDMR= AT91C_WDTC_WDDIS;
//* Set MCK at 47 923 200
// 1 Enabling the Main Oscillator:
// SCK = 1/32768 = 30.51 uSecond
// Start up time = 8 * 6 / SCK = 56 * 30.51 = 1,46484375 ms
pPMC->PMC_MOR = (( AT91C_CKGR_OSCOUNT & (0x06 <<8) | AT91C_CKGR_MOSCEN ));
// Wait the startup time
while(!(pPMC->PMC_SR & AT91C_PMC_MOSCS));
// 2 Checking the Main Oscillator Frequency (Optional)
// 3 Setting PLL and divider:
// - div by 14 Fin = 1.3165 =(18,432 / 14)
// - Mul 72+1: Fout = 96.1097 =(3,6864 *73)
// for 96 MHz the erroe is 0.11%
// Field out NOT USED = 0
// PLLCOUNT pll startup time estimate at : 0.844 ms
// PLLCOUNT 28 = 0.000844 /(1/32768)
pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 14) |
(AT91C_CKGR_PLLCOUNT & (28<<8)) |
(AT91C_CKGR_MUL & (72<<16)));
// Wait the startup time
while(!(pPMC->PMC_SR & AT91C_PMC_LOCK));
while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
// 4. Selection of Master Clock and Processor Clock
// select the PLL clock divided by 2
pPMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 ;
while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ;
while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
// Set up the default interrupts handler vectors
AT91C_BASE_AIC->AIC_SVR[0] = (int) AT91F_Default_FIQ_handler ;
for (i=1;i < 31; i++)
{
AT91C_BASE_AIC->AIC_SVR[i] = (int) AT91F_Default_IRQ_handler ;
}
AT91C_BASE_AIC->AIC_SPU = (int) AT91F_Spurious_handler ; } /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
program for test. This turn off a led that always turn on on reset
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ void turnoff() { *AT91C_PIOA_PER = (1<<23); *AT91C_PIOA_OER = (1<<23); *AT91C_PIOA_CODR =(1<<23); } /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
Is the method used for B instruction the correct one? why it seems that after the low_level_int function, the program never return to the boot code?
Thanks a lot for your help ^_^
|