ucos-ii移植笔记3(ARM7平台)--加入机器代码实现BootLoader下到SDRAM运行

把ucos底层代码做好后,接下来应该搭建控制台程序完成整个内核的平台实现,一般就是目标板的GPIO初始化,Uart,时钟初始,以及中断初始等

这里最重要一点是时钟中断的实现!


首先实现目标板初始

 void ARMTargetInit(void) { //配置Cache rSYSCFG = SYSCFG_8KB ; //使用8K字节的指令缓存 rNCACHBE0=((unsigned int)(Non_Cache_End>>12)<<16)|(Non_Cache_Start>>12); Port_Init(); //初始化端口 Delay( 200 ) ; //delay some time Led_Set( 0x0f ); //LED全亮 Delay( 500 ) ; //delay some time Led_Set( 0x00 ); //LED全亮 ChangePllValue( 58, 3, 1 ) ; //设置CPU频率为66M Uart_Init( 0, 115200 ); //设置串口0的速率为115200bps Uart_Select(0); //选择串口0 ARMInitInterrupts(); //初始化中断,设置中断服务程序 Delay(0); //调整延时 }

中断初始化:首先要知道在SDRAM里中断和在FLash是不同的,ARM响应中断时,会跳至开头的几个地址,这个在启动代码中有详细说明:
ResetEntry
    b ResetHandler    ;0x00000000
    b HandlerUndef    ;0x00000004
    b HandlerSWI    ;0x00000008
    b HandlerPabort    ;0x0000000C
    b HandlerDabort    ;0x00000010
    b .      ;0x00000014
    b HandlerIRQ    ;0x00000018
    b HandlerFIQ    ;0x0000001C

比如现在我实现的是IRQ中断,那么ARM响应中断时候会先跳至0x00000018,然后在0x00000018地址的内容读取二次跳转地址,如果是FLash中实现中断,那么会直接运行,中断正常;但如果在BootLoader下,由于BootLoader占据了FLash的开头的空间,所以要想实现
BootLoader下到SDRAM运行,首先确认BootLoader支持中断,一般UBoot是支持的,如果你在BootLoader下到SDRAM运行中断测试程序正常,那么可以确认BootLoader是支持中断。

 

/******************************************************************************************************** * 中断初始化,设置中断服务程序 * ********************************************************************************************************/ void ARMInitInterrupts(void) { int i; /*映射*/ for(i=_RAM_STARTADDRESS;i<(_RAM_STARTADDRESS+0x20);i+=4) { *((volatile unsigned *)i)=0xEA000000+0x1FFE; } // Non-vectored,IRQ disable,FIQ disable rINTCON = 0x05 ; // All=IRQ mode rINTMOD = 0x0 ; // All interrupt is masked. rINTMSK |= BIT_GLOBAL|BIT_EINT4567; //set interrupt vector routine // pISR_RESET //reserved pISR_UNDEF = (unsigned) DebugUNDEF; pISR_SWI = (unsigned) DebugSWI; pISR_PABORT = (unsigned) DebugPABORT; pISR_DABORT = (unsigned) DebugDABORT; // pISR_RESERVED = (unsigned) BreakPoint; //not used // pISR_IRQ = (unsigned) 0; //reserved pISR_FIQ = (unsigned) DebugFIQ; pISR_ADC= (unsigned) BreakPoint; pISR_RTC= (unsigned) BreakPoint; pISR_UTXD1= (unsigned) BreakPoint; pISR_UTXD0= (unsigned) BreakPoint; pISR_SIO= (unsigned) BreakPoint; pISR_IIC= (unsigned) BreakPoint; pISR_URXD1= (unsigned) BreakPoint; pISR_URXD0= (unsigned) BreakPoint; pISR_TIMER5= (unsigned) BreakPoint; pISR_TIMER4= (unsigned) BreakPoint; pISR_TIMER3= (unsigned) BreakPoint; pISR_TIMER2= (unsigned) BreakPoint; pISR_TIMER1= (unsigned) BreakPoint; pISR_TIMER0= (unsigned) BreakPoint; pISR_UERR01= (unsigned) BreakPoint; pISR_WDT= (unsigned) BreakPoint; pISR_BDMA1= (unsigned) BreakPoint; pISR_BDMA0= (unsigned) BreakPoint; pISR_ZDMA1= (unsigned) BreakPoint; pISR_ZDMA0= (unsigned) BreakPoint; pISR_TICK= (unsigned) BreakPoint; // pISR_EINT4567= (unsigned) OSEINT4567ISR; pISR_EINT4567= (unsigned)Key_Int; pISR_EINT3= (unsigned) BreakPoint; pISR_EINT2= (unsigned) BreakPoint; pISR_EINT1= (unsigned) BreakPoint; pISR_EINT0= (unsigned) BreakPoint; pISR_TIMER0= (unsigned) OSTickISR; rINTMSK =~( BIT_GLOBAL|BIT_EINT4567); }  

这里注意一句话:

for(i=_RAM_STARTADDRESS;i<(_RAM_STARTADDRESS+0x20);i+=4) { *((volatile unsigned *)i)=0xEA000000+0x1FFE; }

这是移植的关键,首先看跳转码,这里引用hitlerisyou的大作:

“跳转指令的格式为

31  282725 24 23                       0
 __________________________
|cond |101| L |Signed_immed_24|
|___  |___|_  |______________ |

其中cond为该条指令执行的条件码
    101 是25,26,27三位的固定值
    L   决定是非保存返回地址,以便返回使用
    signed_immed_24是跟跳转目标地址有关的值,呆会讲该值的计算方法


那么
0xEA000000+0x1FFE
就是一条跳转指令,它的条件码为1110,表示无条件跳转;L为0表示不保存返回值(因为这里修改的是异常处理入口,不用返回值);0x1FFE指定跳转目的地址。

下面我们看看signed_immed_24的计算方法:
1.将PC寄存器作为该条跳转指令的基地址;
2.用目标地址减去基地址,生成跳转偏移量(程序要保证该偏移量小于33554432);
3.将这个值的bit[25:2]填入signed_immed_24中。
因此0x1FFE的意义就是目标地址相对当前地址为 0x1FFE*4+8=0x8000

现在我们就明白了这段代码是将RAM开始的32个字节中填入了8个跳转指令,跳转的目标地址为当前指令地址+0x8000
如果你把你的程序加载到_RAM_STARTADDRESS+0x8000(在这块板子上就是0x0C008000),那么这几个异常中断都会跳转到你自己程序中的异常中断处理处,执行你自己的处理过程。”

 

/******************************************************************************************************** * Initialize timer that is used OS * ********************************************************************************************************/ void ARMInitTimers(void) { /*IRQ中断*/ rINTCON = 5; /*全部为IRQ中断*/ rINTMOD = 0; /*屏蔽*/ rINTMSK=(BIT_GLOBAL|BIT_TIMER0); pISR_TIMER0= (unsigned int)OSTickISR; //dead zone=0, pre0= 150 /*分频150*/ rTCFG0= 0x00000095; //all interrupt, mux0= 1/16 rTCFG1= 0x00000003; //set T0 count rTCNTB0= _CLOCK; rTCON |=0x00000002; rTCON &= 0xfffffff0; rTCON |= 0x0000000d; } /******************************************************************************************************** * enable the interrupt * ********************************************************************************************************/ void ARMInstallSystemTimer(void) { rINTMSK=~( BIT_TIMER0 | BIT_GLOBAL ); //Default value=0x7ffffff } void Main(void) { U16 ver ; ARMTargetInit(); //目标板初始化 OSInit(); //uCOS-II初始化 Uart_Printf("OS Initing/n"); OSTimeSet(0); //创建主任务 OSTaskCreate( Main_Task, (void *)0, (OS_STK *)&Main_Task_Stack[TASK_STACK_SIZE-1], Main_Task_PRIO ) ; Uart_Printf("OS Starting/n/n"); OSStart(); //Start uCOS-II /* never reached */ }

注意ARMInitTimers时钟开启要在创建任务后再在任务开,不然可能会引起崩溃

 

你可能感兴趣的:(timer,cache,Flash,任务,平台,delay)