一直都是用MCU裸奔程序,现在在STM32F429 discovery上试了下移植UCOSII,现在把自己的心得分享一下,有不正确的地方,请指出来! 先直接把程序贴出来,说明放在后面。关于移植前的准备工作以及UCOSII的源码,大家可以网上搜索,很多资料,现只贴出主函数部分,其中用到的其他函数都是很简单就能实现的,方法很多,就不赘述了。 #include #include "delay.h" #include "key.h" #include "led.h" #include "usart.h" #include "includes.h" //UCOSII任务设置 // 起始任务 #define START_TASK_PRIO 10 //设置任务优先级 #define START_STK_SIZE 64 //设置任务堆栈大小 OS_STK START_TASK_STK[START_STK_SIZE];//任务堆栈 void START_Task(void *pdata); //任务函数 //LED任务(红灯) #define RLED_TASK_PRIO 7 #define RLED_STK_SIZE 64 OS_STK RLED_TASK_STK[RLED_STK_SIZE]; void RLED_Task(void *pdata); //主任务 #define MAIN_TASK_PRIO 5 #define MAIN_STK_SIZE 128 OS_STK MAIN_TASK_STK[MAIN_STK_SIZE]; void MAIN_Task(void *pdata); //按键任务 #define KEY_TASK_PRIO 4 #define KEY_STK_SIZE 64 OS_STK KEY_TASK_STK[KEY_STK_SIZE]; void KEY_Task(void *pdata); OS_EVENT *msg_key; //邮箱事件块指针(按键用) OS_TMR *tmr1; //软件定时器1 //软件定时器1的回调函数 void TMR1_Callback(OS_TMR *ptmr,void *p_arg) { static u16 cpuusage = 0; static u8 tcnt = 0; if(tcnt == 5) { printf("CPU使用率:%d%%\r\n",cpuusage/5);//每隔一段时间打印出CPU使用率 cpuusage = 0; tcnt = 0; } cpuusage += OSCPUUsage; tcnt++; } int main(void) { F4_Clock_Init(); //关于时钟复位,参照官方例程,基本是照抄的 Delay_Init(150); //延时初始化 MYUSART1_Init(75,115200); //串口初始化 LED_Init(); //LED端口初始化 KEY_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; msg_key = OSMboxCreate((void *)0);//创建消息邮箱 OSStatInit(); //初始化统计任务 OS_ENTER_CRITICAL();//进入临界区,系统不响应中断 //创建如下任务 OSTaskCreate(RLED_Task,(void *)0,(OS_STK *)&RLED_TASK_STK[RLED_STK_SIZE-1],RLED_TASK_PRIO); OSTaskCreate(MAIN_Task,(void *)0,(OS_STK *)&MAIN_TASK_STK[MAIN_STK_SIZE]-1,MAIN_TASK_PRIO); OSTaskCreate(KEY_Task,(void *)0,(OS_STK *)&KEY_TASK_STK[KEY_STK_SIZE-1],KEY_TASK_PRIO ); OSTaskSuspend(START_TASK_PRIO);//将起始任务挂起 OS_EXIT_CRITICAL(); //退出临界区,系统正常响应中断 } //LED任务 void RLED_Task(void *pdata) { while(1) { LED_On(REDLED); OSTimeDly(500); LED_Off(REDLED); OSTimeDly(500); } } //主任务 void MAIN_Task(void *pdata) { u32 key = 0; u8 state; u8 err; //创建软件定时器1 tmr1 = OSTmrCreate(10,5,OS_TMR_OPT_PERIODIC,(OS_TMR_CALLBACK)TMR1_Callback,0,"tmr1",&err); OSTmrStart(tmr1,&err);//启动软件定时器1 while(1) { key = (u32)OSMboxPend(msg_key,10,&err);//获取(请求)按键消息 switch(key) { case 1: LED_Toggle(GREENLED);//翻转LED状态 state = LED_State(GREENLED);//获取LED当前状态 if(state == 1) printf("邮箱消息发送成功,绿灯点亮!\r\n"); else printf(" 邮箱消息发送成功,绿灯熄灭!\r\n"); break; default: break; } OSTimeDly(10); } } //按键扫描任务 void KEY_Task(void *pdata) { u8 key; while(1) { key = KEY_Scan(0); if(key) { printf("key=%d,准备发送消息邮箱...\r\n",key); OSMboxPost(msg_key,(void *)key);//发送消息 } OSTimeDly(10); } } 说明: 1,以上代码仅包含几个基础的简单功能:1)创建任务,设置任务的优先级,堆栈和任务函数,达到多任务运行的效果。2)通过消息邮箱,达到任务间通信的目的。3)使用软件定时器,打印出CPU的使用率。 2,在官方源码中,最重要的也是需要我们经常修改的是os_cfg.h这个文件。当然其他地方也会有修改的,限于本人水平还请大家多百度。关于os_cfg.h中几个重要的参数(仅讲本代码中用到的功能)如下: OS_MAX_TASKS 允许的任务的最大数量,最新版的UCOSII最大任务支持255个。一般调试使用10个基本够了。 OS_TICKS_PER_SEC 时间节拍,这个是很重要的参数,该参数决定整个UCOSII系统的时间基准,就是一秒钟的节拍数量,如果设置为10,那么时间基准就是1000/10=100ms,依次类推,一般设置为1~100ms。在cortex-m4内核有SYSTICK定时器,一般以此定时器在硬件上产生时间节拍。关于延时函数,最终都是要调用UCOSII的自带的延时函数OSTimeDly。 OS_TMR_EN 定时器使能,取1时使能,不然会出现无法使用数据类型OS_TMR等问题 OS_TMR_CFG_TICKS_PER_SEC 定时器的节拍,意义等同于STM32的定时器设置产生中断的时间,具体要看在软件定时器的相关函数中的用法,大家可以自己多研究下。 下一句是自己添加的,设置优先级。 #define OS_TASK_TMR_PRIO 0u //设置软件定时器1的优先级为最高 3,一些基础知识普及,比较简单基础: 1)UCOSII的任何任务都是通过任务控制块来控制,任务控制块包括: 任务函数指针,任务堆栈指针,任务优先级。 任务函数指针用于找到函数入口,去执行具体的操作; 任务堆栈指针,用于该任务释放了CPU使用权时,用于保护现场,即保存该任务的相关参数到堆栈中,等待下次改任务获取了CPU使用权了,再从堆栈中加载参数,继续执行函数; 优先级是识别每个任务的唯一标示,且优先级不能有相同的。 2)每个任务就是一个死循环,在循环中至少要有一个延时语句,这样才能在该延时语句处释放该任务的CPU使用权,转而去响应中断或者执行优先级更高的任务,且延时长短视具体程序而定,一般延时10ms。 3)关于创建任务的语句,其中一个参数与具体处理器的堆栈增长方式有关,向上增长和向下增长是不同的参数。 4)中断响应时间是体现系统实时性好不好的重要参数之一。 备注:很多代码参照了正点原子的战舰STM32F103开发板的资料,有什么不明白的,大家可以多看看相关资料,还有任哲和邵贝贝的关于UCOSII的讲解,非常详细和经典。 |
【stm32F429开发日志】STM32F429上 NES 模拟器 移植 试玩
【小“福”蝶赏灯展+Nucleo-STM32F410】
读书感悟--STM32库开发实战指南——基于STM32F4(有空更新)
【STM32F429心得\疑问】+STM32学习心得(新手必看)
【我要为STM32站台】+基于STM32F4的视觉追踪系统
【我要SHOW】我的STM32F411
【我要show】+STM32F407+我爱ST
【我与STM32共成长】+脚踏STM32F1和STM32F4两条船
[线下活动] STM32F4与STM32L4系列功耗对比分析与测试
[STM32粉丝狂欢节开箱]STM32F410和L432
RE:【STM32F429开发日志】UCOSII简单移植
RE:【STM32F429开发日志】UCOSII简单移植
回复:【STM32F429开发日志】UCOSII简单移植
可否把代码打个包贴上来呢,那样就更好了!
http://www.openedv.com/posts/list/13912.htm这里有详细的资料,呵呵,本人的代码从上面借鉴不少,很多值得学习的地方.