你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32F429开发日志】UCOSII简单移植

[复制链接]
仙人掌 提问时间:2014-6-23 21:35 /
 一直都是用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的讲解,非常详细和经典。
 
 
 
 
 
 
收藏 评论5 发布时间:2014-6-23 21:35

举报

5个回答
wakojosin 回答时间:2014-6-25 00:14:38

RE:【STM32F429开发日志】UCOSII简单移植

谢谢楼主分享经验,不过讲的略简
stm32神舟开发板 回答时间:2014-6-25 01:01:09

RE:【STM32F429开发日志】UCOSII简单移植

可否把代码打个包贴上来呢,那样就更好了!
仙人掌 回答时间:2014-6-26 00:00:19

回复:【STM32F429开发日志】UCOSII简单移植

回复第 3 楼 于2014-06-25 01:01:09发表:
可否把代码打个包贴上来呢,那样就更好了!
http://www.openedv.com/posts/list/13912.htm这里有详细的资料,呵呵,本人的代码从上面借鉴不少,很多值得学习的地方.
 
stary666 回答时间:2015-4-8 10:43:49
学习一下。。。
stary666 回答时间:2015-4-12 16:26:46
学习一下。。。。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版