creep 发表于 2017-4-6 22:58:28

【NUCLEO-L496ZG评测】+ UCOSIII简单移植

本帖最后由 creep 于 2017-5-6 17:28 编辑

STM32中文官网(www.stmcu.com.cn)

         在上一个开箱测试帖子我们进行了简单的串口输出和点灯测试,这次就把这个测试移植到UCOSIII实现。在ST的HAL开发包了cubemx有很多freeRTOS的例子,作为一款免费的RTOS,freeRTOS越来越多被众多开发者使用和讨论,如果要学习freeRTOS,只要去研究ST提供的例子就基本应该可以入门。和freeRTOS相比我更喜欢UCOSIII的代码风格和结构,虽然收费但是目前UCOSIII依旧是开源可以下载到最新的源码。如果选择一个RTOS入门,UCOSIII从教程到代码本身都是一个很好的选择。下面是ST的HAL开发包中提供的freeRTOS的例程。



1、UCOSIII的下载和移植

在UCOSIII的官方网站上注册后可以下载到移植好的很多ST的开发板的例子,从IAR到MDK都可以找到可以参考的例程。如果嫌麻烦不想注册去下载也可以参考国内很多开源的例程中的源码,大致的源码结构如下,具体的移植步骤可以参考原子*野火*安富莱等开源的移植步骤。


■首先是定义一些任务的堆栈、控制块、任务函数这些变量,为了看起来整洁,我把这些任务需要的定义都放在了一个单独的C文件中,然后再main函数中包含这个C文件:

然后在main文件中包含

■在main函数中主要是初始化OS,创建一个开始任务,然后启动任务
int main(void)
{
OS_ERR err;
CPU_SR_ALLOC();
HAL_Init();
SystemClock_Config();
delay_init(80);

LPUART1_Init();
LED_Init();
OSInit(&err);
OS_CRITICAL_ENTER();
      OSTaskCreate((OS_TCB         * )&StartTaskTCB,               
                                 (CPU_CHAR      * )"start task",               
               (OS_TASK_PTR )start_task,                        
               (void                * )0,                                       
               (OS_PRIO          )START_TASK_PRIO,   
               (CPU_STK   * )&START_TASK_STK,      
               (CPU_STK_SIZE)START_STK_SIZE/10,      
               (CPU_STK_SIZE)START_STK_SIZE,               
               (OS_MSG_QTY)0,                                       
               (OS_TICK          )0,                                       
               (void         * )0,                                       
               (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
               (OS_ERR         * )&err);                              
      OS_CRITICAL_EXIT();      
      OSStart(&err);   
while(1);
}■ 然后在开始任务中 创建1个LED闪烁任务,2个串口输出任务
void start_task(void *p_arg)
{
      OS_ERR err;
      CPU_SR_ALLOC();
      p_arg = p_arg;

      CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);                        
#endif
      
#ifdef CPU_CFG_INT_DIS_MEAS_EN               
    CPU_IntDisMeasMaxCurReset();      
#endif
      
#if      OS_CFG_SCHED_ROUND_ROBIN_EN
      
      OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif      
      
      OS_CRITICAL_ENTER();      
      
      OSTaskCreate((OS_TCB         * )&Task1_TaskTCB,               
                                 (CPU_CHAR      * )"Task1 task",               
               (OS_TASK_PTR )task1_task,                        
               (void                * )0,                                       
               (OS_PRIO          )TASK1_TASK_PRIO,   
               (CPU_STK   * )&TASK1_TASK_STK,      
               (CPU_STK_SIZE)TASK1_STK_SIZE/10,      
               (CPU_STK_SIZE)TASK1_STK_SIZE,               
               (OS_MSG_QTY)0,                                       
               (OS_TICK          )0,                                       
               (void         * )0,                                       
               (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
               (OS_ERR         * )&err);                              
                                 
      
      OSTaskCreate((OS_TCB         * )&Task2_TaskTCB,               
                                 (CPU_CHAR      * )"task2 task",               
               (OS_TASK_PTR )task2_task,                        
               (void                * )0,                                       
               (OS_PRIO          )TASK2_TASK_PRIO,            
               (CPU_STK   * )&TASK2_TASK_STK,      
               (CPU_STK_SIZE)TASK2_STK_SIZE/10,      
               (CPU_STK_SIZE)TASK2_STK_SIZE,               
               (OS_MSG_QTY)0,                                       
               (OS_TICK          )0,                                       
               (void         * )0,                              
               (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
               (OS_ERR         * )&err);                        
      
      OSTaskCreate((OS_TCB         * )&Task3_TaskTCB,               
                                 (CPU_CHAR      * )"task3 task",               
               (OS_TASK_PTR )task3_task,                        
               (void                * )0,                                       
               (OS_PRIO          )TASK3_TASK_PRIO,            
               (CPU_STK   * )&TASK3_TASK_STK,      
               (CPU_STK_SIZE)TASK3_STK_SIZE/10,      
               (CPU_STK_SIZE)TASK3_STK_SIZE,               
               (OS_MSG_QTY)0,                                       
               (OS_TICK          )0,                                       
               (void         * )0,                              
               (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
               (OS_ERR         * )&err);                        
               
      OS_CRITICAL_EXIT();      
      OSTaskDel((OS_TCB*)0,&err);      
}■ LED任务就是周期的闪烁,串口不停的打印信息
//LED task1
void task1_task(void *p_arg)
{
static   uint8_t sta = ON;
      OS_ERR err;
      while(1)
      {
    LED1(sta);
    LED2(sta);
    LED3(sta);
                sta = !sta;

                OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //ÑÓʱ1s
               
      }
}

// UART task2
void task2_task(void *p_arg)
{
      OS_ERR err;
      CPU_SR_ALLOC();
      while(1)
      {
    OS_CRITICAL_ENTER();
    printf("Please do not respond,the message from Task2!!\r\n");
          OS_CRITICAL_EXIT();
                OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //ÑÓʱ1s
      }
}

//UART task3
void task3_task(void *p_arg)
{
      OS_ERR err;
      CPU_SR_ALLOC();
      while(1)
      {
    OS_CRITICAL_ENTER();
    printf("Please do not respond,the message from Task3!!\r\n");
          OS_CRITICAL_EXIT();
                OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //ÑÓʱ1s
      }
}
2、测试结果

LED闪烁效果

与此同时串口输出几乎会“同时”输出信息如下:





STM32L496使用的是M4内核,如果之前做过同样的移植那么移植到Nucleo-L496就会比较方便,如果没有移植过也可以参考很多的教程和文档。

测试代码:


参考文档:



相关阅读:
【NUCLEO-L496ZG评测】+ UCOSIII:软件定时器和信号量

【NUCLEO-L496ZG评测】+ UCOSIII:事件标志组


【NUCLEO-L496ZG评测】+ UCOSIII:内存管理和消息队列

【NUCLEO-L496ZG评测】+ UCOSIII:软件定时器和信号量


哈佛祖安智 发表于 2017-4-7 09:06:14

帮顶

jackten 发表于 2017-4-7 09:08:00

厉害厉害                           

斜阳__ 发表于 2017-4-7 09:33:27

橙子又出精品

wofei1314 发表于 2017-4-7 09:38:48

好贴,顶起~

any012 发表于 2017-4-7 16:33:26

最近在学freertos,请问,官方的freertos例程在哪个目录下?

creep 发表于 2017-4-7 17:07:50

any012 发表于 2017-4-7 16:33
最近在学freertos,请问,官方的freertos例程在哪个目录下?

http://ww1.sinaimg.cn/large/62842993gy1fee87wx1ygj20k40angm9.jpg

any012 发表于 2017-4-8 10:50:16

creep 发表于 2017-4-7 17:07


F1系列的,就一个...

creep 发表于 2017-4-8 11:13:01

any012 发表于 2017-4-8 10:50
F1系列的,就一个...

其实这个和哪个系列关系不大,只要移植好一个工程模板,freeRTOS的其他功能的移植可以参考其他系列其他开发板里面的例子,都是一样的。

any012 发表于 2017-4-8 11:25:34

谢谢,我正在下载L4的固件库看看。
页: [1] 2
查看完整版本: 【NUCLEO-L496ZG评测】+ UCOSIII简单移植