STM32上面运行UCOSII的步骤
1、 移植 UCOSII
- 要想 UCOSII 在 STM32 正常运行,当然首先是需要移植 UCOSII。
- ALIENTEK 提供的 SYSTEM 文件夹里面的系统函数直接支持 UCOSII,只需要在 sys.h 文件里面将: SYSTEM_SUPPORT_UCOS 宏定义改为 1,即可通过 delay_init 函数初始化 UCOSII 的系统时钟节拍,为 UCOSII 提供时钟节拍。
2、 编写任务函数并设置其堆栈大小和优先级等参数。
- 编写任务函数,以便 UCOSII 调用;
- 设置函数堆栈大小,这个需要根据函数的需求来设置;
- 堆栈字节对齐的问题,如果任务运行出现莫名其妙的错误(比如用到 sprintf 出错),请考虑是不是字节对齐的问题。
- 设置任务优先级, 这个需要大家根据任务的重要性和实时性设置,记住高优先级的任务有优先使用 CPU 的权利。
3、 初始化 UCOSII,并在 UCOSII 中创建任务
- 调用 OSInit,初始化 UCOSII,通过调用 OSTaskCreate 函数创建我们的任务。
4、 启动 UCOSII
- 调用 OSStart,启动 UCOSII。
通过以上 4 个步骤, UCOSII 就开始在 STM32 上面运行了,这里还需要注意我们必须对os_cfg.h 进行部分配置,以满足我们自己的需要。
软件设计
1、 在工程源码下面加入 UCOSII 文件夹,存放 UCOSII源码(我们已经将 UCOSII源码分为三个文件夹:CORE、PORT和 CONFIG)。
打开工程,新建 UCOSII-CORE、 UCOSII-PORT 和 UCOSII-CONFIG 三个分组,分别添加UCOSII 三个文件夹下的源码,并将这三个文件夹加入头文件包含路径:

- UCOSII-CORE 分组下面是 UCOSII 的核心源码,我们不需要做任何变动。
- UCOSII-PORT 分组下面是我们移植 UCOSII 要修改的 3 个代码,这个在移植的时候完成。
- UCOSII-CONFIG 分组下面是 UCOSII 的配置部分,主要由用户根据自己的需要对 UCOSII 进行裁剪或其他设置。
1、 软件介绍
- os_cfg.h 里面定义 OS_TICKS_PER_SEC 的值为 200,也就是设置 UCOSII 的时钟节拍为 5ms,同时设置 OS_MAX_TASKS 为 10,也就是最多 10 个任务(包括空闲任务和统计任务在内)。
- sys.h 里面设置 SYSTEM_SUPPORT_UCOS 为 1,以支持 UCOSII,通过这个设置,我们不仅可以实现利用 delay_init 来初始化 SYSTICK,产生 UCOSII 的系统时钟节拍,还可以让 delay_us 和 delay_ms 函数在 UCOSII 下能够正常使用。
- UCOSII 的时钟节拍由 SYSTICK 的中断服务函数提供,该部分代码如下:
//systick 中断服务函数,使用 ucos 时用到 void SysTick_Handler(void) { OSIntEnter(); //进入中断 OSTimeTick(); //调用 ucos 的时钟服务程序 OSIntExit(); //触发任务切换软中断 }
① OSIntEnter 是进入中断服务函数,用来记录中断嵌套层数(OSIntNesting增加 1);
② OSTimeTick 是系统时钟节拍服务函数,在每个时钟节拍了解每个任务的延时状态,使已经到达延时时限的非挂起任务进入就绪状态;
③ OSIntExit 是退出中断服务函数,该函数可能触发一次任务切换(当 OSIntNesting==0&&调度器未上锁&&就绪表最高优先级任务 != 被中断的任务优先级时),否则继续返回原来的任务执行代码(如果 OSIntNesting 不为 0,则减 1)。
· 任何中断服务函数,我们都应该加上 OSIntEnter 和 OSIntExit 函数,UCOSII 是一个可剥夺型的内核,中断服务子程序运行之后,系统会根据情况进行一次任务调度去运行优先级别最高的就绪任务,而并不一定接着运行被中断的任务!
例程中main 函数只创建了 start_task 一个任务,然后在 start_task 再创建另外两个任务,在创建之后将自身(start_task)挂起。单独创建 start_task,是为了提供一个单一任务,实现应用程序开始运行之前的准备工作(比如:外设初始化、创建信号量、创建邮箱、 创建消息队列、创建信号量集、 创建任务、初始化统计任务等等)。
在应用程序中经常有一些代码段必须不受任何干扰地连续运行,这样的代码段叫做临界段(或临界区)。为了使临界段在运行时不受中断所打断,在临界段代码前必须用关中断指令使 CPU 屏蔽中断请求,而在临界段代码后必须用开中断指令解除屏蔽使得 CPU 可以响应中断请求。UCOSII 提供 OS_ENTER_CRITICAL 和 OS_EXIT_CRITICAL 两个宏来实现,这两个宏需要我们在移植 UCOSII 的时候实现,我们采用方法 3(即 OS_CRITICAL_METHOD 为3)来实现这两个宏。 因为临界段代码不能被中断打断,将严重影响系统的实时性,所以临界段代码越短越好!
在 start_task 任务中,我们在创建 led0_task 和 led1_task 的时候,不希望中断打断,故使用了临界区。
一个任务里面一般是必须有延时函数的,以释放 CPU 使用权,否则可能导致低优先级的任务因高优先级的任务不释放 CPU 使用权而一直无法得到 CPU 使用权,从而无法运行。

浙公网安备 33010602011771号