一、下载ucosii系统源文件
https://www.micrium.com/downloadcenter/download-results/?searchterm=mi-stm32f103ze&supported=true
二、创建工程
在stm32裸机工程的基础上实现ucos系统的移植。在工程目录下新建uCOSII目录,并在该目录下建立CONFIG,CORE,PORT三个文件夹,分类存放需要的系统源文件。
\Micrium\Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD中的app_cfg.h,include.h,os_cfg.h复制到CONFIG文件夹中
\Micrium\Software\uCOS-II\Source中的所有文件复制到CORE目录下
\Micrium\Software\uCOS-II\Ports\arm-cortex-m3\Generic\IAR中的所有文件复制到PORT目录下
在工程中添加对应的组,并将文件添加到工程中,将头文件目录添加到工程的包含路径中
三、需要修改的文件
os_cpu_a.asm
将PUBLIC FUNCTIONS中的PUBLIC修改为EXPORT,因为MDK编程环境不是别PUBLIC,
PUBLIC OS_CPU_SR_Save EXPORT OS_CPU_SR_Save
PUBLIC OS_CPU_SR_RestoreEXPORT OS_CPU_SR_Restore
PUBLIC OSStartHighRdyEXPORT OSStartHighRdy
PUBLIC OSCtxSw EXPORT OSCtxSw
PUBLIC OSIntCtxSw EXPORT OSIntCtxSw
PUBLIC OS_CPU_PendSVHandler EXPORT OS_CPU_PendSVHandler
将CODE GENERATION DIRECTIVES中的内容替换成环境可以识别的指令
RSEGCODE:CODE:NOROOT(2)
转换成
AREA|.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
os_dbg.c
去掉#define OS_COMPILER_OPT 的宏定义
#define OS_COMPILER_OPT // __root
includes.h
取消暂时没有使用的头文件
//#include <cpu.h>
//#include <lib_def.h>
//#include <lib_mem.h>
//#include <lib_str.h>
//#include <lib_ascii.h>
//#include <stm32f10x_lib.h>
//#include <bsp.h>
//#include <probe_com.h>
//#include <ksd.h>
//#include <ksd.h>
//#include <probe_rs232.h>
#//include <os_probe.h>
os_cfg.h
取消APP_HOOK的使能
#defineOS_APP_HOOKS_EN 0
startup_stm32f10x_hd.s
将处理器启动文件中所有的PendSV_Handler中断向量名修改为OS_CPU_PendSVHandler
stm32f10x_it.c
添加头文件,并完善SysTick_Handler()函数
#include<ucos_ii.h>
/**
*@brief This function handles SysTickHandler.
*@param None
*@retval None
*/
voidSysTick_Handler(void)
{
OSIntEnter(); //进入中断
OSTimeTick(); //调用ucos的时钟服务程序
OSIntExit(); //触发任务切换软中断
}
四、程序设计
主程序通过两个任务实现两个LED灯同时闪烁
//UCOSII-任务调度
#include "includes.h"
#define LED3(opt) ((opt) ? (GPIOB->BRR |= 1<<5):(GPIOB->BSRR |= 1<<5))
#define LED2(opt) ((opt) ? (GPIOE->BRR |= 1<<5):(GPIOE->BSRR |= 1<<5))
#define SystemFrequency 72000000
/////////////////////////UCOSII任务堆栈设置///////////////////////////////////
//START任务
//设置任务优先级
#define START_TASK_PRIO 10 //开始任务的优先级设置为最低
//设置任务堆栈大小
#define START_STK_SIZE 64
//创建任务堆栈空间
OS_STK START_TASK_STK[START_STK_SIZE];
//任务函数接口
void start_task(void *pdata);
//LED1任务
#define LED1_TASK_PRIO 7
#define LED1_STK_SIZE 64
OS_STK LED1_TASK_STK[LED1_STK_SIZE];
void led1_task(void *pdata);
//LED2任务
#define LED2_TASK_PRIO 6
#define LED2_STK_SIZE 64
OS_STK LED2_TASK_STK[LED2_STK_SIZE];
void led2_task(void *pdata);
//初始化PB5和PE5为输出口并使能这两个时钟
//LED IO初始化
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE两个端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5输出高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
}
void SysTick_init(void)
{
SysTick_Config(SystemFrequency/OS_TICKS_PER_SEC);
}
int main(void)
{
SysTick_init();
LED_Init();
OSInit();
OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO );//创建起始任务
OSStart();
}
//开始任务
void start_task(void *pdata)
{
OS_CPU_SR cpu_sr=0;
pdata = pdata;
OSStatInit(); //³õʼ»¯Í³¼ÆÈÎÎñ.ÕâÀï»áÑÓʱ1ÃëÖÓ×óÓÒ
OS_ENTER_CRITICAL(); //½øÈëÁÙ½çÇø(ÎÞ•¨±»Öжϴò¶Ï)
OSTaskCreate(led1_task,(void *)0,(OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO);
OSTaskCreate(led2_task,(void *)0,(OS_STK*)&LED2_TASK_STK[LED2_STK_SIZE-1],LED2_TASK_PRIO);
OSTaskSuspend(START_TASK_PRIO); //挂起起始任务
OS_EXIT_CRITICAL(); //退出临界区
}
//LED1任务
void led2_task(void *pdata)
{
while(1)
{
LED3(1);
OSTimeDlyHMSM(0,0,2,0);
LED3(0);
OSTimeDlyHMSM(0,0,0,500);
};
}
//LED2任务
void led1_task(void *pdata)
{
while(1)
{
LED2(1);
OSTimeDlyHMSM(0,0,1,0);
LED2(0);
OSTimeDlyHMSM(0,0,1,0);
};
}