业余时间想研究一下RTOS,但是现有的嵌入式系统很多,代码量也很大,厚厚的一本书,又是任务控制块,又是链表又是指针的指来指去,让人不耐心点根本看不下去,也没太多时间去研究。于是有了自己动手去做的想法,这样可以提高兴趣.比看书有意思。慢慢的发现,操作系统也没有那么神秘。触发软中断,保存堆栈,开始进行任务切换。于是一个多任务出来了,但是一个完整的操作系统并不简单,涉及到一系列的算法和数据结构的运用,还有系统的引导程序bootloader,内存管理,文件系统,网络管理,IO驱动管理等模块。

  有了想法,接下来是付诸行动。但是还得学习汇编,这成了大阻碍,工作任务多,下班后,没太多精力去学习它。不过只要能看的懂可以。于是把ucos/II在stm32上移植部分的汇编代码招搬过来直接利用。这样可以把主要精力放在任务调度和任务间的同步和通讯上。这次任务创建和调度的原理很简单,效率肯定也不高。以后有更好的想法了,打算改进一下任务的调度算法,比如可以利用linux内核中的list_head双向循环链表,加入绪队列和任务延时队列。利用keilRTX系统中的内存分配机制,动态allox()分配任务的TCB控制块,总之,多学习好的系统中的思想。

  以下是汇编的代码OS_CPU_A.ASM,完成任务之间的切换和堆栈的保存。

  主要是两个堆栈指针OSCurTCB,OSNewTCB。可以把主要精力放在用c写任务调度和任务间的同步与通信,

  利用以下汇编代码,可以暂时不管汇编部分,该任务调度时调用OSCtxSw(),传递高优先级任务的堆栈指针给OSNewTCB,完成两个任务切换。

;/*********************** (C) COPYRIGHT 2010 Libraworks *************************
;* File Name : os_cpu_a.asm
;* Author  : Librae
;* Version  : V1.0
;* Date   : 06/10/2010
;* Description : μCOS-II asm port for STM32
;*******************************************************************************/
  IMPORT  OSCurTCB                    ; External references
  IMPORT  OSNewTCB
  IMPORT  OSTaskSwHook
                 
  EXPORT  OSStartTask
  EXPORT  OSCtxSw
  EXPORT  OSIntCtxSw
  EXPORT  OS_CPU_SR_Save                       ; Functions declared in this file
  EXPORT  OS_CPU_SR_Restore     
  EXPORT  PendSV_Handler
   
NVIC_PENDSV_PRI  EQU     0xFFFF0000               ; PendSV priority value (lowest)
NVIC_PENDSVSET   EQU     0x10000000               ; value to trigger PendSV exception
NVIC_INT_CTRL    EQU     0xE000ED04               ; interrupt control state register
NVIC_SYSPRI2     EQU     0xE000ED20               ; system priority register (2)

  PRESERVE8
 
  AREA    |.text|, CODE, READONLY
        THUMB
  
         
;********************************************************************************************************
;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
;
;********************************************************************************************************
OS_CPU_SR_Save
    MRS     R0, PRIMASK   ;读取PRIMASK到R0,R0为返回值
    CPSID   I    ;PRIMASK=1,关中断(NMI和硬件FAULT可以响应)
    BX      LR       ;返回
OS_CPU_SR_Restore
    MSR     PRIMASK, R0     ;读取R0到PRIMASK中,R0为参数;open interrupt
    BX      LR    ;返回

;/**************************************************************************************
;* 函数名称: OSStartTask
;*
;* 功能描述: 使用调度器运行第一个任务
;*
;* 参    数: None
;*
;* 返 回 值: None
;**************************************************************************************/
OSStartTask
        LDR     R4, =NVIC_SYSPRI2      ; set the PendSV exception priority
        LDR     R5, =NVIC_PENDSV_PRI
        STR     R5, [R4]
        MOV     R4, #0                 ; set the PSP to 0 for initial context switch call
        MSR     PSP, R4
                                       ;切换到高优先级的任务
        LDR     R4, =NVIC_INT_CTRL     ;rigger the PendSV exception (causes context switch)
        LDR     R5, =NVIC_PENDSVSET    ;触发PendSV异常 (causes context switch)
        STR     R5, [R4]
        CPSIE   I                      ;enable interrupts at processor level
OSStartHang
        B       OSStartHang            ;should never get here
;/**************************************************************************************
;* 函数名称: OSCtxSw
;*
;* 功能描述: 任务级上下文切换       
;*
;* 参    数: None
;*
;* 返 回 值: None
;***************************************************************************************/
 
OSCtxSw
  PUSH    {R4, R5}
        LDR     R4, =NVIC_INT_CTRL   ;触发PendSV异常 (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]
  POP     {R4, R5}
        BX      LR
  NOP