基于STM32的简易RT0S分析-任务切换实例分析

手上没有使用Cortex-M3内核的芯片,只有一个STM32F407VG的Discovery开发版,这款芯片使用的是Cortex-M4F的内核,这个内核是基于ARMV7E-M架构的与Cortex-M3十分类似,只是多了一个FPU(浮点运算单元)以及浮点运算需要的相关寄存器。也因为这个FPU导致进入中断的时候保存的寄存器有些差别,不过这些堆栈都是硬件自动保存的,对编写任务切换代码没有影响,在文章的最后来简单分析下浮点寄存器如何入栈。这篇文章的思路参考了《一步步写STM32 OS【三】PendSV与堆栈操作

一、IAR工程代码

使用IAR和MDK建立的工程在系统初始化堆栈时是不一样的,MDK在启动文件的开头就初始化了堆栈的大小,而IAR工程堆栈的大小定义是在icf文件中,具体怎样在IAR工程中修改堆栈初始化信息可以参考这篇文章《STM32编程:是时候深入理解栈了》,作者写的很清晰了。从icf文件中得知MSP堆栈的大小为0x2000,下面来看具体的代码文件,os_port.asm文件是汇编代码,用于实现任务的具体切换,这次我们不再为MSP单独指定堆栈,而是使用系统上电初始化时建立的堆栈。工程里一共包含两个文件main.c和os_port.asm。

main.c源代码如下,代码里屏蔽了RTOS建立主堆栈的代码,如果像Ucos一样在中断中使用RTOS自己设置的主堆栈,可以打开这段代码。

#include "stm32f4xx.h"

/******************变量类型定义*******************************/
typedef unsigned int   uint32;

typedef struct TaskTCB
{
    uint32 *StackPtr;
}sTaskTCB,*pTaskTCB;
 
typedef void( *pFun )( void );

/********************定义任务控制块************************************/
sTaskTCB StartTaskTCB;
sTaskTCB SecondTaskTCB;

pTaskTCB  OSTCBCurPtr;
pTaskTCB  OSTCBHighRdyPtr;
/***********************定义进程堆栈**********************************/
#define START_STACK_SIZE   48
#define SECOND_STACK_SIZE  48
uint32 StartTaskStack[START_STACK_SIZE];
uint32 SecondTaskStack[SECOND_STACK_SIZE];

/**********************定义主堆栈*****************************************/
//#define  OS_CPU_STACK_SIZE   128               未使用
//uint32 OS_CPU_ExceptStk[OS_CPU_STACK_SIZE];    未使用
//uint32 *g_OS_CPU_ExceptStkBase;                未使用

/*************************全局变量****************************************/
static int StartTaskFlag ,SecondTaskFlag,EndFlag;

/*************************函数定义*****************************************/
extern void OSCtxSw(void);
extern void OSStartHighRdy(void);

void TaskSwitch(void)
{
    if(OSTCBCurPtr == &StartTaskTCB)
        OSTCBHighRdyPtr=&SecondTaskTCB;
    else
        OSTCBHighRdyPtr=&StartTaskTCB;
    
    OSCtxSw();
}

void StartTask(void)
{
    StartTaskFlag = 1;
    TaskSwitch();
}

void SecondTask(void)
{
    SecondTaskFlag = 1;
    StartTaskFlag = 0;
    TaskSwitch();
}

void EndTask(void)
{
    EndFlag = 1;
    SecondTaskFlag = 0;
    while(1)
    {
        ;
    }
}

//任务创建函数
void Task_Create(sTaskTCB *pTcb,pFun task,uint32 *stk,uint32 stacksize)
{
    uint32  *pStack;/*grows from high memory to low*/
    pStack      = &stk[stacksize];/*Top of stack*/
    pStack      = (uint32 *)((uint32)(pStack) & 0xFFFFFFF8u);//AAPCS(ARM application procedure all standard) Align the stack to 8bytes

	/*Registers stacked as if auto-saved on exception*/
    *(--pStack) = (uint32)0x01000000uL;                   //xPSR bit24 thumb state bit
    *(--pStack) = (uint32)task;                           // Entry Point(PC)
    *(--pStack) = (uint32)EndTask;                        // R14 (LR)
    *(--pStack) = (uint32)0x12121212uL;                   // R12
    *(--pStack) = (uint32)0x03030303uL;                   // R3
    *(--pStack) = (uint32)0x02020202uL;                   // R2
    *(--pStack) = (uint32)0x01010101uL;                 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值