walnutcy

FreeRTOS 到ARM7的移植(原创),送官方说明文档

0
阅读(39507)
在网上找到一个官方的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
再附张原打算要上传的文档目录图: