硬件调好之后,俺就开始准备把UCOS移上来,由于以前在LPC2132上移植过,所以要做工作量不是很大,主要是重新配置下系统的资源如: PLL,MAM,VIC中断系统,和Timer,并重写中断处理函数。
PLL的配置,我采用了逐一试探的方法,先确定晶体的分频值N,然后根据输入的系统运行频率求出PLL的倍频值M,并使PLL Synthesizer 输出的频率介于 275—550MHz之间。程序如下:
INT8U Config_Clock(CLKSEL clksrc, INT32U fosc, INT32U clk)
{
INT16U i;
INT32U clkdiv;
if(clk>F72MHZ || fosc>F50MHZ)
return 0;
//STEP 1
PLLCON_bit.PLLC = 0;
PLLFEED = 0xAA;
PLLFEED = 0x55;
SCS |= 0x20;
//while( !(SCS & 0x40) );
//STEP 2
PLLCON_bit.PLLE = 0;
PLLFEED = 0xAA;
PLLFEED = 0x55;
//STEP 3
switch (clksrc)
{
case RC:
CLKSRCSEL_bit.CLKSRC = RC;
break;
case OSC:
CLKSRCSEL_bit.CLKSRC = OSC;
break;
case RTC:
CLKSRCSEL_bit.CLKSRC = RTC;
break;
default: return 0;
}
//STEP 5, assume N="1"
for(i=6;i<513;i++)
{
clkdiv = (fosc*(i+1)*2)%clk;
if(clkdiv==0)
{
clkdiv = (fosc*(i+1)*2)/clk;
if(clkdiv%2==0)
break;
}
if(i==514)
return 0;
}
PLLCFG_bit.MSEL = i;
PLLCFG_bit.NSEL = 0;
PLLFEED = 0xAA;
PLLFEED = 0x55;
//STEP 6
PLLCON_bit.PLLE = 1;
PLLFEED = 0xAA;
PLLFEED = 0x55;
//STEP 7
CCLKCFG = clkdiv-1;
//STEP 8
//while(PLLSTAT_bit.PLOCK!=1);
//STEP 9
PLLCON_bit.PLLC = 1;
PLLFEED = 0xAA;
PLLFEED = 0x55;
return 1;
}
存储器加速模块MAM可以提高系统运行的速度,避免CPU在每个时钟周期都跑到
FLASH区去取指令和数据,从而加快系统运行速度。MAM配置的根据是系统的运
行频率,还要注意的是,MAM必须先关闭,然后才可以对其进行配置,配置完毕
后在使能MAM,如果在MAM打开的状态下去修改MAM Reg的值会导致CPU取指混
乱,程序自然会跑飞,俺可是体验过的。
MAM的配置程序如下:
void MAM_Config(INT32U clk)
{
//disable Memory acceleratolr
MAMCR_bit.MODECTRL = 0;
if(clk
MAMTIM_bit.CYCLES = 1;
else if(clk>F20MHZ && clk
MAMTIM_bit.CYCLES = 2;
else if(clk>F40MHZ)
MAMTIM_bit.CYCLES = 3;
//MAM REG must be disable first
MAMCR_bit.MODECTRL= 2;
}
最关键的部分还是中断处理程序,这部分由于LPC2368的VIC和2132的差别还蛮大的,所以要重写了,2368没有非向量中断这一说,只有IRQ,和FIQ。2132里设置IRQ的优先级是把中断向量等级SLOT赋给VICVECTCtrl0—15的低5位,SLOT为0,优先级最高。2368是把SLOT赋给32个PRIOTY积存器,每个PORITY积存器代表对应的中断源的中断向量通道,同样SLOT为0是最高优先级。
配置程序如下:
void VIC_Config(INT8U Mode, INT32U IntNum, INT8U slot, INT32U ISRAddr)
{
INT32U * pADR;
if(Mode==2)
VICINTSELECT |= 1< //config as FIQ
if(Mode==1) //config as IRQ
{
pADR = (INT32U *)(BaseIRQPRO + 4*IntNum);
* pADR &= slot;
pADR = (INT32U*)(BaseVECTADDR + 4*IntNum);
* pADR = ISRAddr;
}
/*#if SIMULATOR_EN
VICADDRESS = *pADR;
#endif */
}
UCOS的中断处理函数如下:根据不同中断方式IRQ/FIQ,对应不同的处理方法。
void OS_CPU_ExceptHndlr(INT32U except_type)
{
INT32U status;
void (* pISR)(void);
if(except_type==OS_CPU_ARM_EXCEPT_IRQ)
{
#if SIMULATOR_EN
VICADDRESS = (INT32U)(&OSTickISR);
#endif
pISR = (void (*)(void))VIC_IRQ;
(* pISR)();
VICADDRESS = 0;
}
else if(except_type==OS_CPU_ARM_EXCEPT_FIQ)
{
status = GetFIQStatus();
switch (status)
{
case 1<
//Process the fiq interrupt here
break;
case 1<
//process the fiq interrupt here
break;
default: break;
}
}
else;
}
最后再配置下定时器,并在定时器中断处理函数中调用UCOS的OSTimeTick()函数就行了。
void OSTickISR(void)
{
Clear_ISRFlag(TIMER0, MRCH0);
OSTimeTick();
}
<><>
用户1328398 2008-6-14 09:27