Benny_Cen
上几周移植ucos到44B0 去,免得受“裸奔”之苦,折磨了一天后终于成功 ,主要是想能在BootLoader下在到SDRAM中也能跑,网上盛传的程序我看过,应该是可以在FLASH中跑,但在SDRAM中跑就会停掉,其实只是少了几句话而已
1.移植底层文件:
包括OS_CPU.H,OS_CPU_C.C,OS_CPU_A.S
OS_CPU.H
开头定义了一写数据类型:
/* ***************************************************************************** * DATA TYPES * (Compiler Specific) ***************************************************************************** */ typedef unsigned char BOOLEAN; typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ typedef signed char INT8S; /* Signed 8 bit quantity */ typedef unsigned short INT16U; /* Unsigned 16 bit */ typedef signed short INT16S; /* Signed 16 bit */ typedef unsigned int INT32U; /* Unsigned 32 bit */ typedef signed int INT32S; /* Signed 32 bit */ typedef float FP32; /* floating point */ typedef double FP64; /* floating point */ typedef unsigned int OS_STK; /* Each stack entry */ typedef unsigned int OS_CPU_SR; /* 定义CPU状态寄存器数据宽度 #define BYTE INT8S /* Define data types */ #define UBYTE INT8U /* ... to uC/OS V1.xx.*/ #define WORD INT16S /* ... uC/OSII. */ #define UWORD INT16U #define LONG INT32S #define ULONG INT32U
接着是与 ARM 体系结构相关的一些定义:
#define OS_CRITICAL_METHOD 2 /* 选择开、关中断的方式. */ #if OS_CRITICAL_METHOD == 2 #define OS_ENTER_CRITICAL() ARMDisableInt() /*进入临界区*/ #define OS_EXIT_CRITICAL() ARMEnableInt() /*退出临界区*/ #endif #if OS_CRITICAL_METHOD == 3 #define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) #define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) #endif #define OS_TASK_SW OSCtxSw /*上下文切换*/ /* * Definitions specific to ARM/uHAL */ #define SVC32MODE 0x13 /* stack stuff */ #define OS_STK_GROWTH 1 /* 方向 堆栈是从上往下长的 */ /* angel takes up stack */ #define SEMIHOSTED_STACK_NEEDS 1024 /* idle task stack size (words) */ #ifdef SEMIHOSTED #define OS_IDLE_STK_SIZE (32+SEMIHOSTED_STACK_NEEDS) #else #define OS_IDLE_STK_SIZE 256 #endif
这里注意的是OS_CRITICAL_METHOD ,ucos提供了3种方法实现,第一种方法是直接简单的开关中断方式,但是一旦嵌套会发生意外,比如:
void Task (void *data) { ......... OS_ENTER_CRITICAL(); //进入临界区1 //调用了某一函数,该函数也需要进入临界区: { OS_ENTER_CRITICAL(); ................ OS_EXIT_CRITICAL(); } //这里就自然变成废墟了 ........... //临界区切掉 OS_EXIT_CRITICAL(); }
此方法太多弊端,所以新内核中看不到她的影子了
于是出现第二种方法,执行OS_ENTER_CRITICAL()时首先保存中断状态到堆栈中,然后关中断,执行OS_EXIT_CRITICAL()时,再从堆栈中恢复原来的中断开/关状态。这种方法不会改变中断状态,由于用到堆栈,这样会带来隐忧,看邵贝贝翻译的有这样说:
“但是,用户在使用这种方法的时候还得十分小心,因为如果用户在调用象OSTimeDly()之类的服务之前就禁止中断,很有可能用户的应用程序会崩溃。发生这种情况的原因是任务被挂起直到时间期满,而中断是禁止的,因而用户不可能获得节拍中断!很明显,所有的PEND调用都会涉及到这个问题,用户得十分小心。一个通用的办法是用户应该在中断允许的情况下调用µC/OS-Ⅱ的系统服务!”
第3种方法直接保存到任务局部变量中去
#if OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR())
#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr))
#endif
避免了使用堆栈
接着声明在os_cpu_a.s里定义的函数
extern void OSCtxSw(void); // task switch routine extern void OSIntCtxSw(void); // interrupt context switch extern void ARMDisableInt(void); // disable global interrupts extern void ARMEnableInt(void); // enable global interrupts extern void OSTickISR(void); // timer interrupt routine OS_CPU_SR OSCPUSaveSR(void); void OSCPURestoreSR(OS_CPU_SR cpu_sr);
时间到了,先写到这