转载于:http://blog.sina.com.cn/s/blog_a092aeab0101ad8v.html
在网上找到一个官方的PDF说明文档,不敢独享,与兄弟们分享.(文件太大--3.4Mb,压缩后仍有1Mb,有哪位朋友需要的留下email地址,隔天就发送.)
移植OS,主要需处理的有:
1) 现场的保护与恢复;
2) 系统时钟节拍的处理;
3) OS运行的模式与中断处理等;
(1) 这里首先考虑现场的保护与恢复,这里利用ARM7的SWI来触发任务切换,主要代码如下:
vPortYieldProcessor ;;walter 20080816
ADD LR, LR, #4
portSAVE_CONTEXT ; Save the context (宏)
LDR R0, =vTaskSwitchContext ; selecting the next task
MOV LR, PC
BX R0
portRESTORE_CONTEXT ; Restore the context (宏)
MACRO
portSAVE_CONTEXT ;;;保存当前场景
STMDB SP!, {R0}
; Set R0 to point to the task stack pointer.
STMDB SP, {SP}^
SUB SP, SP, #4
LDMIA SP!, {R0}
STMDB R0!, {LR}
MOV LR, R0
; Pop R0 so we can save it onto the system mode stack.
LDMIA SP!, {R0}
; Push all the system mode registers onto the task stack.
STMDB LR, {R0-LR}^
SUB LR, LR, #60
; Push the SPSR onto the task stack.
MRS R0, SPSR
STMDB LR!, {R0}
LDR R0, =ulCriticalNesting
LDR R0, [R0]
STMDB LR!, {R0}
; Store the new top of stack for the task.
LDR R1, =pxCurrentTCB
LDR R0, [R1]
STR LR, [R0]
MEND
MACRO
portRESTORE_CONTEXT ;;恢复现场
; Set the LR to the task stack.
LDR R1, =pxCurrentTCB
LDR R0, [R1]
LDR LR, [R0]
; The critical nesting depth is the first item on the stack.
; Load it into the ulCriticalNesting variable.
LDR R0, =ulCriticalNesting
LDMFD LR!, {R1}
STR R1, [R0]
; Get the SPSR from the stack.
LDMFD LR!, {R0}
MSR SPSR_cxsf, R0
; Restore all system mode registers for the task.
LDMFD LR, {R0-R14}^
NOP
; Restore the return address.
LDR LR, [LR, #+60]
; And return - correcting the offset in the LR to obtain the
; correct address.
SUBS PC, LR, #4
MEND
这里注意:要将vPortYieldProcessor注册为SWI中断响应
;; LDR R0, =Handler_SWI ;;替换以前的SWI中断
LDR R0, =vPortYieldProcessor
STR R0, [R1, #0x04] ;SWI
开始时启动任务切换,直接采用恢复现场的宏:
vPortStartFirstTask
portRESTORE_CONTEXT
(2) 系统时钟节拍处理,FreeRTOS提供的时钟节拍函数为: vTaskIncrementTick();
根据我的芯片特点,如下设置我的时钟中断:
MCU_REG_RW_PERI_CLKCON |= dMCU_CLK_ENABLE_TIMER;
ExceptionSetISRHandler (dMCU_INT_INDEX_TIMER2,vPortOSSystemTick);
MCU_REG_RW_T2DATA = (12000000/1000/32); // 1ms 的时钟节拍
MCU_REG_RW_T2MOD = (0x4<<4) | (0<<2) | (1<<0); //Timer 2 Match Interrupt
MCU_REG_RW_TCON |= (3<<4); //Timer 2 Clear & Run
extern void LtCheckYield(void); // Add by Walter 20080818
void vPortOSSystemTick( void ) // walter 20080816
{
vTaskIncrementTick();
#if (configUSE_PREEMPTION == 1)
//这里为我自己添加的,用以在配置为可剥夺型内核时,
//若检查到有高优先级的任务进入RDY状态,则进行调度
//也是移植的一部分,只是和官方给的移植方式不一样,目前运行良好
LtCheckYield(); // Add by Walter 20080818
#endif
}
3) OS运行的模式与中断处理等; 这里采用SYS模式运行,FIQ中断,ARM-code
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
{
portSTACK_TYPE *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE; // PC
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xaaaaaaaa; /* R14 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS;
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x12121212; /* R12 */
…………………………………………
…………………………………………
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x9F;/* SYS,ARM,FIQ */
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack;
}
同时要注意中断允许的处理:
vPortEnableInterruptsFromARM
STMDB SP!, {R0}
MRS R0, CPSR
BIC R0, R0, #0x40 ;;20080818 only use fiq int--;#0xC0
MSR CPSR_cxsf,R0
LDMIA SP!, {R0}
MOV PC, LR
END