1. uCOS移植

下载uCOS源码

uCOS官网Github仓库实验所需uCOS源码正点原子开发指南本次实验源码

HAL基本工程

stm32cubemx建立cmake工程,打开串口1,板载LED。

生成MDK工程

程序测试

重写printf函数

printf

测试

在main.c中引用,并在while函数中添加以下代码:

HAL_Delay(500);
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
printf("hello %.2f\n",3.1415926);

编译并下载

打开串口助手,led每500ms闪烁

移植uCOS

引用.c文件

在工程目录下新建文件夹uCOS

打开基础工程,新建四个分组,分别为 uCOS/BSPuCOS/CPUuCOS/LIBuCOS/OS,如下图所示:

uCOS/BSP

uC-CPU/BSP/Template/bsp_cpu.c

uC-OS3/Template/bsp_os_dt.c

uCOS/CPU

uC-CPU/ARM-Cortex-M/ARMv7-M/ARM/cpu_a.asm

uC-CPU/ARM-Cortex-M/ARMv7- M/cpu_c.c

uC-CPU/cpu_core.c

uCOS/LIB

uC-LIB/lib_ascii.c

uC-LIB/lib_math.c

uC-LIB/lib_mem.c

uC-LIB/lib_str.c

uCOS/OS

uC-OS3/Cfg/Template/os_app_hooks.c

uC-OS3/Ports/ARM-Cortex-M/ARMv7- M/ARM/os_cpu_a.asm

uC-OS3/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c

uC-OS3/Source目录下除__dbg_uCOS-III.c外的所有 C 源文件

添加.h文件

替换中断服务函数

在 µC/OS-III 的移植过程中会遇到两个重要的中断,分别为 SysTick 中断和 PendSV 中断, 这两个中断分别用于为 µC/OS-III 内核提供时基和任务切换。HAL 库会默认定义 SysTick 和 PendSV 的中断服 务函数,因此在移植 µC/OS-III 的时候,需要将 HAL 库默认定义的 SysTick 和 PendSV 中断服 务函数,替换为 µC/OS-III 提供了中断服务函数。

将启动文件中的PendSV_HandlerSysTick_Handler 修改为OS_CPU_PendSVHandlerOS_CPU_SysTickHandler。分别在第74~75行和215~210行左右。

µC/CPU 的配置文件的路径在 uC-CPU/Cfg/Template/cpu_cfg.h,打开该文件,并将配置文件中用于配置配置 CPU 中断优先级寄存 器使用位数的宏开关置 1 即可

编译,0错误0警告

测试uCOS

新建用户文件夹

在keil中引用

头文件路径

添加测试代码

#include <stdio.h>

#include "rtos.h"

/**
 * start_task任务配置
 */
#define START_TASK_PRIO 5                           /* 任务优先级 */
#define START_TSAK_STACK_SIZE 256                   /* 任务栈大小 */
CPU_STK satrt_task_stack[START_TSAK_STACK_SIZE];    /* 任务栈 */
OS_TCB  start_task_tcb;                             /* 任务控制块 */
void start_task (void *p_arg);                      /* 任务函数 */

/**
 * led_task任务配置
 */
#define LED_TASK_PRIO 6                             /* 任务优先级 */ 
#define LED_TSAK_STACK_SIZE 256                     /* 任务栈大小 */ 
CPU_STK led_task_stack[LED_TSAK_STACK_SIZE];        /* 任务栈 */ 
OS_TCB  led_task_tcb;                               /* 任务控制块 */ 
static void led_task (void *p_arg);                 /* 任务函数 */ 

/**
 * uart_task任务配置
 */
#define UART_TASK_PRIO 6                            /* 任务优先级 */ 
#define UART_TSAK_STACK_SIZE 256                    /* 任务栈大小 */ 
CPU_STK uart_task_stack[UART_TSAK_STACK_SIZE];      /* 任务栈 */
OS_TCB  uart_task_tcb;                              /* 任务控制块 */ 
static void uart_task (void *p_arg);                /* 任务函数 */ 

/**
 * @brief   uCOS入口函数
 * @retval  无
 */
void OS_StartScheduler(void)
{
    OS_ERR err;

    /* 初始化uCOS-III */
    OSInit(&err);
    /* 创建 start_task */
    OSTaskCreate((OS_TCB *)     &start_task_tcb,
                (CPU_CHAR*)     "start_task",
                (OS_TASK_PTR)   start_task,
                (void*)         0,
                (OS_PRIO)       START_TASK_PRIO,
                (CPU_STK*)      &satrt_task_stack[0],
                (CPU_STK_SIZE)  START_TSAK_STACK_SIZE/10,
                (CPU_STK_SIZE)  START_TSAK_STACK_SIZE,
                (OS_MSG_QTY)    0,
                (OS_TICK)       0,
                (void*)         0,
                (OS_OPT)        (OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                (OS_ERR*)       &err);

    /* 开启任务调度 */
    OSStart(&err);
}

void start_task (void *p_arg)
{
    OS_ERR  err;

    CPU_INT32U  cnts;
    CPU_Init();

    /* 根据配置的节拍频率配置 SysTick */
    cnts = HAL_RCC_GetSysClockFreq() / OS_CFG_TICK_RATE_HZ;
    OS_CPU_SysTickInit(cnts);

    /* 创建 led_task */
    OSTaskCreate((OS_TCB *)     &led_task_tcb,
                (CPU_CHAR*)     "led_task",
                (OS_TASK_PTR)   led_task,
                (void*)         0,
                (OS_PRIO)       LED_TASK_PRIO,
                (CPU_STK*)      &led_task_stack[0],
                (CPU_STK_SIZE)  LED_TSAK_STACK_SIZE/10,
                (CPU_STK_SIZE)  LED_TSAK_STACK_SIZE,
                (OS_MSG_QTY)    0,
                (OS_TICK)       0,
                (void*)         0,
                (OS_OPT)        (OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                (OS_ERR*)       &err);
    /* 创建 uart_task */    
    OSTaskCreate((OS_TCB *)     &uart_task_tcb,
                (CPU_CHAR*)     "uart_task",
                (OS_TASK_PTR)   uart_task,
                (void*)         0,
                (OS_PRIO)       UART_TASK_PRIO,
                (CPU_STK*)      &uart_task_stack[0],
                (CPU_STK_SIZE)  UART_TSAK_STACK_SIZE/10,
                (CPU_STK_SIZE)  UART_TSAK_STACK_SIZE,
                (OS_MSG_QTY)    0,
                (OS_TICK)       0,
                (void*)         0,
                (OS_OPT)        (OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                (OS_ERR*)       &err);
    /* 删除start_sask */
    OSTaskDel((OS_TCB *)0, &err);
}

/**
 * @brief led_task
 * @param p_arg: 传入参数(未用到)
 * @retval 无
 */
static void led_task (void *p_arg)
{
    OS_ERR err;
    while (1)
    {
        HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
        OSTimeDly(1000,OS_OPT_TIME_DLY,&err);
    }

}

/**
 * @brief uart_task
 * @param p_arg: 传入参数(未用到)
 * @retval 无
 */
static void uart_task (void *p_arg)
{
    OS_ERR err;
        uint8_t i = 0;
    while (1)
    {
        OSTimeDly(1000,OS_OPT_TIME_DLY,&err);
        if (i < 10) 
        {
            printf("hello world! %d\n",i);
        }
        else 
        {
            printf("task deleted\n");
            OSTaskDel(NULL,&err); 
        }             
        i++;
    }

}
#ifndef __RTOS_H
#define __RTOS_H

#include <cpu.h>
#include <os.h>

#include "main.h"

void OS_StartScheduler(void);

#endif

main.c中引用#include "rtos.h",在while(1)前添加OS_StartScheduler()。程序将由uCOS接管,并不会运行while函数。

实验结果

板载LED灯每秒闪烁一次,并且串口每秒发送一次,当发送10次时停止发送

results matching ""

    No results matching ""