一个极简单的RTOS代码 STM32 借鉴UCOSII ----汇编代码的注释有错误,仅仅是注释

;/*********************** (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
;*******************************************************************************/

		EXTERN CPU_ExceptStkBase
		EXTERN p_TCB_Cur
		EXTERN p_TCBHighRdy
        ;IMPORT  OSPrioCur
        ;IMPORT  OSPrioHighRdy
        ;IMPORT  OSTCBCur
        ;IMPORT  OSTCBHighRdy
      
           
        EXPORT  OSStartHighRdy               
        EXPORT  OSCtxSw
        EXPORT  OSIntCtxSw
		EXPORT  OS_CPU_SR_Save                                      ; Functions declared in this file
    	EXPORT  OS_CPU_SR_Restore       
        EXPORT  PendSV_Handler
        	
     
NVIC_INT_CTRL   	EQU     0xE000ED04  ; 中断控制寄存器
NVIC_SYSPRI14    	EQU     0xE000ED22  ; 系统优先级寄存器(2)
NVIC_PENDSV_PRI 	EQU     0xFF  ; PendSV中断和系统节拍中断
                                        ; (都为最低,0xff).
NVIC_PENDSVSET  	EQU     0x10000000  ; 触发软件中断的值.


		PRESERVE8 
		
		AREA    |.text|, CODE, READONLY
        THUMB 
    
           

;********************************************************************************************************
;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
;
; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
;              into the CPU's status register.
;
; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;
;
; Note(s)    : 1) These functions are used in general like this:
;
;                 void Task (void *p_arg)
;                 {
;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
;                     OS_CPU_SR  cpu_sr;
;                 #endif
;
;                          :
;                          :
;                     OS_ENTER_CRITICAL();             /* cpu_sr = OS_CPU_SaveSR();                */
;                          :
;                          :
;                     OS_EXIT_CRITICAL();              /* OS_CPU_RestoreSR(cpu_sr);                */
;                          :
;                          :
;                 }
;********************************************************************************************************

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为参数
    BX      LR				;返回


;/**************************************************************************************
;* 函数名称: OSStartHighRdy
;*
;* 功能描述: 使用调度器运行第一个任务
;* 
;* 参    数: None
;*
;* 返 回 值: None
;**************************************************************************************/  

OSStartHighRdy
        LDR     R4, =NVIC_SYSPRI14      ; 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, =CPU_ExceptStkBase         ; 中断嵌套时有用
        LDR     R5, [R4]
        MSR     MSP, R5

                                       ;切换到最高优先级的任务
        LDR     R4, =NVIC_INT_CTRL     ;rigger the PendSV exception (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        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

;/**************************************************************************************
;* 函数名称: OSIntCtxSw
;*
;* 功能描述: 中断级任务切换
;*
;* 参    数: None
;*
;* 返 回 值: None
;***************************************************************************************/

OSIntCtxSw
		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

;/**************************************************************************************
;* 函数名称: OSPendSV
;*
;* 功能描述: OSPendSV is used to cause a context switch.
;*
;* 参    数: None
;*
;* 返 回 值: None
;***************************************************************************************/

PendSV_Handler
    CPSID   I                                                   ; Prevent interruption during context switch
    MRS     R0, PSP                                             ; PSP is process stack pointer 如果在用PSP堆栈,则可以忽略保存寄存器,参考CM3权威中的双堆栈-白菜注
    CBZ     R0, PendSV_Handler_Nosave		                    ; Skip register save the first time

    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
    STM     R0, {R4-R11}

    LDR     R1, =p_TCB_Cur                                      ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                                            ; R0 is SP of process being switched out

                                                                ; At this point, entire context of process has been saved
PendSV_Handler_Nosave


    LDR     R0, =p_TCB_Cur                                      ; OSPrioCur = OSPrioHighRdy;
    LDR     R1, =p_TCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]

    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20
    MSR     PSP, R0                                             ; Load PSP with new process SP
    ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
    CPSIE   I
    BX      LR                                                  ; Exception return will restore remaining context

 end  

 

#include "timer.h"
#include "led.h"
#include "OS_Need.h"
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK战舰STM32开发板
//定时器 驱动代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/3
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved									  
//////////////////////////////////////////////////////////////////////////////////   	 

//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器


	TIM_Cmd(TIM3, ENABLE);  //使能TIMx					 
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
	char i=0;
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
		for(i=0;i<TCB_Task_NUM;i++)
		{
			if(TCB_Task[i].Dly > 0)
			{
				TCB_Task[i].Dly--;
				if(TCB_Task[i].Dly == 0)
				{
					OSSetPrioRly(i);
				}
			}
		}
	}
}
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
 #include "timer.h"
 
uint32_t OSRdyTbl;//此系统有32个优先级,同时只能有32个任务,每个任务和优先级对应
uint32_t OSPrioHighRdy;
uint32_t OSPrioCur;
struct os_tcb{ //任务控制块结构体
	uint32_t *StkPtr;
	uint32_t Dly;
	uint32_t Prio;//没有用到
};
typedef struct os_tcb TCB;

TCB *p_TCB_Cur;
TCB *p_TCBHighRdy;

#define OS_EXCEPT_STK_SIZE (1024*10)
#define TASK_1_STK_SIZE      1024
#define TASK_2_STK_SIZE      1024
#define OS_IdleTask_STK_SIZE 1024
uint32_t TASK_1_STK[TASK_1_STK_SIZE];
uint32_t TASK_2_STK[TASK_2_STK_SIZE];
uint32_t OS_IdleTask_Stk[OS_IdleTask_STK_SIZE];

TCB TCB_Task1,TCB_Task2;
#define TCB_Task_NUM 32
TCB TCB_Task[TCB_Task_NUM];//最对创建TCB_Task_NUM个任务
uint32_t TCB_Task_NUM_Counts=0;//记录现在有几个任务

uint32_t cpu_sr;
#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}
uint32_t   OS_CPU_SR_Save(void);
void       OS_CPU_SR_Restore(uint32_t	cpu_sr);

void       OSCtxSw(void);
void       OSIntCtxSw(void);
void       OSStartHighRdy(void);

void       OSPendSV(void);
void OSTimeDly(uint32_t ticks);
void OSSched(void);
void OS_TASK_Init(void);
void task_1(void);
void task_2(void);
void OS_IdleTask(void);



void OSSetPrioRly(uint16_t prio)
{
	OSRdyTbl |= 0x01<<prio;
}

void OSDelPrioRly(uint16_t prio)
{
	OSRdyTbl &= ~(0x01<<prio);
}
 
void OSGetHighRdy(void)
{//此函数在优先级表OSRdyTbl中选出最高的优先级
	uint32_t OSNextTaskPrio;
	for(OSNextTaskPrio = 0;(OSNextTaskPrio<32) && !(OSRdyTbl&(0x01<<OSNextTaskPrio));OSNextTaskPrio++)
		;
	OSPrioHighRdy = OSNextTaskPrio;
}


//以下是任务控制块

//以下是堆栈
uint32_t CPU_ExceptStk[OS_EXCEPT_STK_SIZE];
uint32_t *CPU_ExceptStkBase;

//建立一个任务
void Task_Create (void (*task)(void ), uint32_t *p_stk ,uint16_t prio)
{
    uint32_t *stk;
    stk       = p_stk;                            /* Load stack pointer                                 */
                                                 /* Registers stacked as if auto-saved on exception    */
    *(stk)    = (uint32_t)0x01000000L;             /* xPSR                                               */
    *(--stk)  = (uint32_t)task;                    /* Entry Point                                        */
    *(--stk)  = (uint32_t)0xFFFFFFFEL;             /* R14 (LR) (init value will cause fault if ever used)*/
    *(--stk)  = (uint32_t)0x12121212L;             /* R12                                                */
    *(--stk)  = (uint32_t)0x03030303L;             /* R3                                                 */
    *(--stk)  = (uint32_t)0x02020202L;             /* R2                                                 */
    *(--stk)  = (uint32_t)0x01010101L;             /* R1                                                 */
    *(--stk)  = (uint32_t)0x01010101L;                   /* R0 : argument                                      */

                                                 /* Remaining registers saved on process stack         */
    *(--stk)  = (uint32_t)0x11111111L;             /* R11                                                */
    *(--stk)  = (uint32_t)0x10101010L;             /* R10                                                */
    *(--stk)  = (uint32_t)0x09090909L;             /* R9                                                 */
    *(--stk)  = (uint32_t)0x08080808L;             /* R8                                                 */
    *(--stk)  = (uint32_t)0x07070707L;             /* R7                                                 */
    *(--stk)  = (uint32_t)0x06060606L;             /* R6                                                 */
    *(--stk)  = (uint32_t)0x05050505L;             /* R5                                                 */
    *(--stk)  = (uint32_t)0x04040404L;             /* R4                                                 */
		
    TCB_Task[prio].StkPtr = (stk);
		OSSetPrioRly(prio);
		//TCB_Task[TCB_Task_NUM_Counts].Prio =  prio;
		//TCB_Task_NUM_Counts++;//任务数量计数器加1 , TCB_Task_NUM_Counts 必须不能大于TCB_Task_NUM
}




int main(void)
{	
	delay_init();	    //延时函数初始化	 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级	
	LED_Init();		  	//初始化与LED连接的硬件接口
	uart_init(9600);
	TIM3_Int_Init(49,7199);//10Khz的计数频率,计数到50为5ms  
	
	printf("this is the begin of the task ...\ntask is running ...\n");
	CPU_ExceptStkBase = CPU_ExceptStk + OS_EXCEPT_STK_SIZE - 1;
	OS_ENTER_CRITICAL();
	Task_Create(   task_1 , &TASK_1_STK[TASK_1_STK_SIZE-1] ,7);
	Task_Create(   task_2 , &TASK_2_STK[TASK_2_STK_SIZE-1] ,6);
	OS_EXIT_CRITICAL();
	//p_TCBHighRdy = &TCB_Task1;
	//OSStartHighRdy();
	OS_TASK_Init();
	while(1);
}
/*
void Task_Switch(void)
{
	if(p_TCB_Cur == &TCB_Task1)
		p_TCBHighRdy = &TCB_Task2;
	else
		p_TCBHighRdy = &TCB_Task1;
	OSCtxSw();
}*/

void OSTimeDly(uint32_t ticks)
{
	if(ticks > 0)
	{
		OS_ENTER_CRITICAL();
		OSDelPrioRly(OSPrioCur);
		TCB_Task[OSPrioCur].Dly = ticks;
		OS_EXIT_CRITICAL();
		OSSched();
	}
}
void OS_TASK_Init(void)
{
	OS_ENTER_CRITICAL();
	Task_Create(OS_IdleTask , &OS_IdleTask_Stk[OS_IdleTask_STK_SIZE-1],TCB_Task_NUM-1);//将空闲任务设置为最低优先级
	OS_EXIT_CRITICAL();
	OSGetHighRdy();
	OSPrioCur = OSPrioHighRdy;
	p_TCBHighRdy = &TCB_Task[OSPrioHighRdy];
	OSStartHighRdy();
}
void OSSched(void)
{
	OSGetHighRdy();
	if(OSPrioHighRdy != OSPrioCur)
	{
		p_TCBHighRdy = &TCB_Task[OSPrioHighRdy];
		OSPrioCur = OSPrioHighRdy;
		OSCtxSw();
	}
}
void task_1(void){
	while(1)
	{
		printf("task 1\n");
		//Task_Switch();
		OSTimeDly(20);
	}
}
void task_2(void){
	while(1)
	{
		printf("task 2\n");
		//Task_Switch();
		OSTimeDly(20);
	}
}

void OS_IdleTask(void)
{

	while(1){
	
		OSSched();
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章