嵌入式实时操作系统(RTOS)

2023-05-16

一、项目准备工作

1、创建一个标准库项目

这里不用很麻烦,项目能跑就行,后面要以这个项目为基础移植。

2、下载ucOSⅢ源码

ucosⅢ源码:百度网盘链接:提取码:1234(STM32-F107对应版本)
也可以去官网下载:链接,这里就不介绍官网下载的方法了,可以自行搜索。

完成下载后的文件结构是这样的:
在这里插入图片描述

3、创建相应的文件夹

在我们第一步建立的标准库项目中的USER文件夹下新建如下几个文件夹:
在这里插入图片描述

二、开始移植

1.复制文件

转移APP文件夹文件

把我们下载好的源码中对应地址下的这几个文件复制到我们准备好的APP文件夹下:
在这里插入图片描述
在这里插入图片描述

转移BSP文件夹文件

把我们下载好的源码中对应地址下的这几个文件复制到我们准备好的BSP文件夹下:
在这里插入图片描述
在这里插入图片描述

转移uc-CPU文件夹

将该项目转移至自己所创建的项目User目录下:
在这里插入图片描述

工程中添加文件分组

1、在keil项目中创建如下图五个文件夹以对应USER文件夹里的文件:

在这里插入图片描述

2、向“APP”分组添加“User/APP”文件夹下的所有文件:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
添加效果如下图所示:
在这里插入图片描述

3、向“ BSP”分组添加“ \User\BSP”文件夹下的所有文件:

在这里插入图片描述

4.向“ μC/CPU”分组添加“User\uC-CPU”文件夹下的所有文件和 “ \User\uC-CPU\ARM-Cortex-M3\RealView”文件夹下的所有文件:

在这里插入图片描述

5.向“μC/LIB”分组添加“User\uC-LIB”文件夹下的所有文件和 “User\uC-LIB\Ports\ARM-Cortex-M3\1RealView”文件夹下的所有文件:

在这里插入图片描述

6.向“ μC/OS-III Source”分组添加 “ \User\uCOS-III\Source”文件夹下的所有文件:

在这里插入图片描述

7.向“μC/OS-III Port”分组添加 “User\uCOS-III\Ports\ARM-Cortex-M3\Generic\RealView”文件夹下的所有文件:

在这里插入图片描述

2、添加头文件路径到工程

源码已经添加到开发环境的组文件夹下面,编译的时候需要为这些源文件指定头文件的路径,不然编译会报错,此时我们先将头文件添加到我们的 工程中:

在这里插入图片描述

3、具体的工程文件修改

添加完头文件路径后,我们可以编译一下整个工程,但肯定会有错误的, μC/OS-III 的移植尚未完毕,接下来需要对工程文件进行修改。 首先修改工程的启动文件“ startup_stm32f10x_hd.s”。 其中将PendSV_Handler 和 SysTick_Handler 分别改为OS_CPU_PendSVHandler 和OS_CPU_SysTickHandler,共两处,因为μC/OS官方已经给我们处理好对应的中断函数,就无需我们自己处理与系统相关的中断了, 同时我们还需要将stm32f10x_it.c文件中的PendSV_Handler和SysTick_Handler函数注释掉(不注释也不会有问题):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、修改源码中的bsp.c与bsp.h文件

首先要知道,BSP (Board Support Package)是板级支持包,不同型号的板子对应的bsp文件是不一样的,但是里面的具体内容我们一般不去管,只有一个 BSP_Init()的初始化函数可以在里面实现一些例如电灯或者串口发送等的程序用来测试或者函数调用。这里给出bsp.c修改后的代码

bsp.c


#define  BSP_MODULE
#include <bsp.h>



CPU_INT32U  BSP_CPU_ClkFreq_MHz;



#define  DWT_CR      *(CPU_REG32 *)0xE0001000
#define  DWT_CYCCNT  *(CPU_REG32 *)0xE0001004
#define  DEM_CR      *(CPU_REG32 *)0xE000EDFC
#define  DBGMCU_CR   *(CPU_REG32 *)0xE0042004




#define  DBGMCU_CR_TRACE_IOEN_MASK       0x10
#define  DBGMCU_CR_TRACE_MODE_ASYNC      0x00
#define  DBGMCU_CR_TRACE_MODE_SYNC_01    0x40
#define  DBGMCU_CR_TRACE_MODE_SYNC_02    0x80
#define  DBGMCU_CR_TRACE_MODE_SYNC_04    0xC0
#define  DBGMCU_CR_TRACE_MODE_MASK       0xC0

#define  DEM_CR_TRCENA                   (1 << 24)

#define  DWT_CR_CYCCNTENA                (1 <<  0)




void  BSP_Init (void)
{
	//NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4);
	
	//LED_Init (); 
	
}



CPU_INT32U  BSP_CPU_ClkFreq (void)
{
    RCC_ClocksTypeDef  rcc_clocks;


    RCC_GetClocksFreq(&rcc_clocks);

    return ((CPU_INT32U)rcc_clocks.HCLK_Frequency);
}




#if ((APP_CFG_PROBE_OS_PLUGIN_EN == DEF_ENABLED) && \
     (OS_PROBE_HOOKS_EN          == 1))
void  OSProbe_TmrInit (void)
{
}
#endif




#if ((APP_CFG_PROBE_OS_PLUGIN_EN == DEF_ENABLED) && \
     (OS_PROBE_HOOKS_EN          == 1))
CPU_INT32U  OSProbe_TmrRd (void)
{
    return ((CPU_INT32U)DWT_CYCCNT);
}
#endif




#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void  CPU_TS_TmrInit (void)
{
    CPU_INT32U  cpu_clk_freq_hz;


    DEM_CR         |= (CPU_INT32U)DEM_CR_TRCENA;                /* Enable Cortex-M3's DWT CYCCNT reg.                   */
    DWT_CYCCNT      = (CPU_INT32U)0u;
    DWT_CR         |= (CPU_INT32U)DWT_CR_CYCCNTENA;

    cpu_clk_freq_hz = BSP_CPU_ClkFreq();
    CPU_TS_TmrFreqSet(cpu_clk_freq_hz);
}
#endif



#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR  CPU_TS_TmrRd (void)
{
    return ((CPU_TS_TMR)DWT_CYCCNT);
}
#endif
bsp.h
#ifndef  BSP_PRESENT
#define  BSP_PRESENT




#ifdef   BSP_MODULE
#define  BSP_EXT
#else
#define  BSP_EXT  extern
#endif




#include  <stdarg.h>
#include  <stdio.h>

#include  <cpu.h>
#include  <cpu_core.h>

#include  <lib_ascii.h>
#include  <lib_def.h>
#include  <lib_mem.h>
#include  <lib_str.h>

#include "stm32f10x.h"         

#include  <app_cfg.h>

void         BSP_Init                    (void);

CPU_INT32U   BSP_CPU_ClkFreq             (void);



#endif                                                          /* End of module include.                               */

5、修改os_cfg.h(在APP目录下)

#ifndef OS_CFG_H
#define OS_CFG_H


/* --- 其他配置 --- */
#define OS_CFG_APP_HOOKS_EN             1u/* 是否使用钩子函数     */
#define OS_CFG_ARG_CHK_EN               1u/* 是否使用参数检查     */
#define OS_CFG_CALLED_FROM_ISR_CHK_EN   1u/* 是否使用中断调用检查 */
#define OS_CFG_DBG_EN                   1u/* 是否使用debug        */
#define OS_CFG_ISR_POST_DEFERRED_EN     1u/* 是否使用中断延迟post操作*/
#define OS_CFG_OBJ_TYPE_CHK_EN          1u/* 是否使用对象类型检查   */
#define OS_CFG_TS_EN                    1u/*是否使用时间戳     */

#define OS_CFG_PEND_MULTI_EN            1u/*是否使用支持多个任务pend操作*/

#define OS_CFG_PRIO_MAX                32u/*定义任务的最大优先级 */

#define OS_CFG_SCHED_LOCK_TIME_MEAS_EN  1u/*是否使用支持测量调度器锁定时间 */
#define OS_CFG_SCHED_ROUND_ROBIN_EN     1u/* 是否支持循环调度         */
#define OS_CFG_STK_SIZE_MIN            64u/* 最小的任务栈大小        */


/* ---------- 事件标志位---------- */
#define OS_CFG_FLAG_EN                  1u/*是否使用事件标志位    */
#define OS_CFG_FLAG_DEL_EN                  1u/*是否包含OSFlagDel()的代码 */
#define OS_CFG_FLAG_MODE_CLR_EN         1u/*是否包含清除事件标志位的代码*/
#define OS_CFG_FLAG_PEND_ABORT_EN       1u/*是否包含OSFlagPendAbort()的代码*/


/* --------- 内存管理 --- */
#define OS_CFG_MEM_EN                   1u/* 是否使用内存管理         */


/* -------- 互斥量 ----- */
#define OS_CFG_MUTEX_EN                 1u/*是否使用互斥量 */
#define OS_CFG_MUTEX_DEL_EN             1u/*是否包含OSMutexDel()的代码*/
#define OS_CFG_MUTEX_PEND_ABORT_EN      1u/*是否包含OSMutexPendAbort()的代码*/


/* ------- 消息队列--------------- */
#define OS_CFG_Q_EN                     1u/* 是否使用消息队列       */
#define OS_CFG_Q_DEL_EN                 1u/* 是否包含OSQDel()的代码 */
#define OS_CFG_Q_FLUSH_EN               1u/* 是否包含OSQFlush()的代码 */
#define OS_CFG_Q_PEND_ABORT_EN          1u/* 是否包含OSQPendAbort()的代码*/


/* -------------- 信号量 --------- */
#define OS_CFG_SEM_EN                   1u/*是否使用信号量  */
#define OS_CFG_SEM_DEL_EN               1u/*是否包含OSSemDel()的代码*/
#define OS_CFG_SEM_PEND_ABORT_EN        1u/*是否包含OSSemPendAbort()的代码*/
#define OS_CFG_SEM_SET_EN               1u/*是否包含OSSemSet()的代码  */


/* ----------- 任务管理 -------------- */
#define OS_CFG_STAT_TASK_EN             1u/* 是否使用任务统计功能 */
#define OS_CFG_STAT_TASK_STK_CHK_EN     1u/* 从统计任务中检查任务栈 */

#define OS_CFG_TASK_CHANGE_PRIO_EN      1u/* 是否包含OSTaskChangePrio()的代码*/
#define OS_CFG_TASK_DEL_EN              1u/* 是否包含OSTaskDel()的代码*/
#define OS_CFG_TASK_Q_EN                1u/*是否包含OSTaskQXXXX()的代码*/
#define OS_CFG_TASK_Q_PEND_ABORT_EN     1u/* 是否包含OSTaskQPendAbort()的代码 */
#define OS_CFG_TASK_PROFILE_EN          1u/* 是否在OS_TCB中包含变量以进行性能分析 */
#define OS_CFG_TASK_REG_TBL_SIZE     1u/*任务特定寄存器的数量  */
#define OS_CFG_TASK_SEM_PEND_ABORT_EN   1u/* 是否包含OSTaskSemPendAbort()的代码 */
#define OS_CFG_TASK_SUSPEND_EN       1u/*是否包含OSTaskSuspend()和
                        OSTaskResume()的代码*/

/* ------- 时间管理 ------- */
#define OS_CFG_TIME_DLY_HMSM_EN      1u/*是否包含OSTimeDlyHMSM()的代码*/
#define OS_CFG_TIME_DLY_RESUME_EN   1u/*是否包含OSTimeDlyResume()的代码*/


/* ---------- 定时器管理 ------- */
#define OS_CFG_TMR_EN                   1u/* 是否使用定时器        */
#define OS_CFG_TMR_DEL_EN               1u/* 是否支持OSTmrDel()  */

#endif

6、修改cpu_cfg.h(在APP目录下)


#ifndef  CPU_CFG_MODULE_PRESENT
#define  CPU_CFG_MODULE_PRESENT




                                                                /* Configure CPU host name feature (see Note #1) :      */
#define  CPU_CFG_NAME_EN                        DEF_ENABLED
                                                                /*   DEF_DISABLED  CPU host name DISABLED               */
                                                                /*   DEF_ENABLED   CPU host name ENABLED                */

                                                                /* Configure CPU host name ASCII string size ...        */
#define  CPU_CFG_NAME_SIZE                                16u   /* ... (see Note #2).                                   

                                                                /* Configure CPU timestamp features (see Note #1) :     */
#define  CPU_CFG_TS_32_EN                       DEF_ENABLED          // Modified by fire (原是 DEF_DISABLED)
#define  CPU_CFG_TS_64_EN                       DEF_DISABLED
                                                                /*   DEF_DISABLED  CPU timestamps DISABLED              */
                                                                /*   DEF_ENABLED   CPU timestamps ENABLED               */

                                                                /* Configure CPU timestamp timer word size ...          */
                                                                /* ... (see Note #2) :                                  */
#define  CPU_CFG_TS_TMR_SIZE                    CPU_WORD_SIZE_32



#if 1          // Modified by fire (原是 0)                    /* Configure CPU interrupts disabled time ...           */
#define  CPU_CFG_INT_DIS_MEAS_EN                                /* ... measurements feature (see Note #1a).             */
#endif

                                                                /* Configure number of interrupts disabled overhead ... */
#define  CPU_CFG_INT_DIS_MEAS_OVRHD_NBR                    1u   /* ... time measurements (see Note #1b).                */



#if 1                                                           /* Configure CPU count leading zeros bits ...           */
#define  CPU_CFG_LEAD_ZEROS_ASM_PRESENT                         /* ... assembly-version (see Note #1).                  */
#endif


/*$PAGE*/


#endif                                                          /* End of CPU cfg module include.                       */



7、修改os_cfg_app.h(在APP目录下)

#ifndef OS_CFG_APP_H
#define OS_CFG_APP_H


/* --------------------- MISCELLANEOUS ------------------ */
#define  OS_CFG_MSG_POOL_SIZE            100u/* 支持的最大消息数量 */
#define  OS_CFG_ISR_STK_SIZE             128u/*ISR栈的大小 */
#define  OS_CFG_TASK_STK_LIMIT_PCT_EMPTY  10u/*检查栈的剩余大小(百分百形式,
                        此处是10%)*/


/* ---------------------- 空闲任务 --------------------- */
#define  OS_CFG_IDLE_TASK_STK_SIZE       128u/* 空闲任务栈大小    */


/* ------------------ 中断处理任务------------------ */
#define  OS_CFG_INT_Q_SIZE                10u/*中断处理任务队列大小  */
#define  OS_CFG_INT_Q_TASK_STK_SIZE      128u/* 中断处理任务的栈大小*/


/* ------------------- 统计任务------------------- */
#define  OS_CFG_STAT_TASK_PRIO            11u/* 统计任务的优先级  */
#define  OS_CFG_STAT_TASK_RATE_HZ         10u/* 统计任务的指向频率(10HZ)*/
#define  OS_CFG_STAT_TASK_STK_SIZE       128u/*统计任务的栈大小*/


/* ------------------------ 时钟节拍任务 ----------------------- */
#define  OS_CFG_TICK_RATE_HZ       1000u/*系统的时钟节拍(一般为10 到 1000 Hz) */
#define  OS_CFG_TICK_TASK_PRIO            1u/*时钟节拍任务的优先级    */
#define  OS_CFG_TICK_TASK_STK_SIZE       128u/* 时钟节拍任务的栈大小*/
#define  OS_CFG_TICK_WHEEL_SIZE           17u/* 时钟节拍任务的列表大小 */


/* ----------------------- 定时器任务 ----------------------- */
#define  OS_CFG_TMR_TASK_PRIO          11u/*定时器任务的优先级  */
#define  OS_CFG_TMR_TASK_RATE_HZ        10u/* 定时器频率(10 Hz是典型值) */
#define  OS_CFG_TMR_TASK_STK_SIZE      128u/* 定时器任务的栈大小    */
#define  OS_CFG_TMR_WHEEL_SIZE          17u/*定时器任务的列表大小  */

#endif

7、修改app.c(在APP目录下)

#include <includes.h>  
int main(void)
{
    /*暂时没有在main里面创建任务应用任务 */
}

三、任务实现

1、添加初始化文件

由于我们的任务是用三个任务实行不同频率的点灯和串口发送,所以我们需要添加两个文件来分别初始化LED和USART串口,最好在bsp文件目录下加,作为板载文件
在这里插入图片描述

LED.c
#include "stm32f10x.h"                  // Device header

void LED1_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);
}

void LED1_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}

void LED1_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_1);
}

void LED1_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_1);
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);
	}
}

void LED2_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}

void LED2_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_2);
}

void LED2_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_2);
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_2);
	}
}


LED.h
#ifndef __LED_H
#define __LED_H

void LED_Init(void);
void LED1_ON(void);
void LED1_OFF(void);
void LED1_Turn(void);
void LED2_ON(void);
void LED2_OFF(void);
void LED2_Turn(void);

#endif


Serial.c
#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>

void Serial_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1, &USART_InitStructure);
	
	USART_Cmd(USART1, ENABLE);
}

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}

void Serial_SendString(char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);
	}
}

uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y --)
	{
		Result *= X;
	}
	return Result;
}

void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
}

int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);
	return ch;
}

void Serial_Printf(char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	Serial_SendString(String);
}


Serial.h
#ifndef __SERIAL_H
#define __SERIAL_H

#include <stdio.h>

//void Serial_Init(void);
//void Serial_SendByte(uint8_t Byte);
//void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
//void Serial_SendNumber(uint32_t Number, uint8_t Length);
//void Serial_Printf(char *format, ...);

#endif


在bsp.h里把LED.h和Serial.h的头文件都加进去
#include "LED.h"
#include "Serial.h"

2、任务模块介绍

1、定义任务栈

下面展示一些 内联代码片

// A code block
var foo = 'bar';
// An highlighted block
var foo = 'bar';

2、定义任务控制块

定义一个栈, 目前我们使用的是静态内存,所以任务栈是一个独立的全局变量。任务的栈占用的是MCU内部的RAM,当任务越多的时候, 需要使用的栈空间就越大,即需要使用的RAM空间就越多。

static OS_TCB AppTaskStartTCB;

3、定义任务主体函数

任务实际上就是一个无限循环且不带返回值的C函数。这里,我们创建一个这样的任务作为例子, 让开发板上面的LED灯以500ms的频率闪烁,

static voidLED_Task (void* parameter)
{
    while (1)                                  
    {
        LED1_ON;
        OSTimeDly (500,OS_OPT_TIME_DLY,&err);/* 延时500个tick */

        LED1_OFF;
        OSTimeDly (500,OS_OPT_TIME_DLY,&err);/* 延时500个tick */

    }
}

4、创建任务

一个任务的三要素是任务主体函数,任务栈,任务控制块,那么怎么样把这三个要素联合在一起?μC/OS里面有一个叫任务创建函数OSTaskCreate(), 它就是干这个活的。它将任务主体函数,任务栈和任务控制块这三者联系在一起,让任务在创建之后可以随时被系统启动与调度。

OSTaskCreate((OS_TCB     *)&AppTaskStartTCB,                       
            (CPU_CHAR   *)"App Task Start",               
            (OS_TASK_PTR ) AppTaskStart,                  
            (void       *) 0,                                    
            (OS_PRIO     ) APP_TASK_START_PRIO,          
            (CPU_STK    *)&AppTaskStartStk[0],                 
            (CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10,   
            (CPU_STK_SIZE) APP_TASK_START_STK_SIZE,        
            (OS_MSG_QTY  ) 5u,                            
            (OS_TICK     ) 0u,                          
            (void       *) 0,                                 
            (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), 
            (OS_ERR     *)&err);                                   

5、启动任务

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

3、任务具体实现

1、 创建多任务只需要按照创建单任务的套路依葫芦画瓢即可,接下来我们创建四个任务,分别是起始任务(用来开启其他任务)、 LED1 任务、 LED2 任务和USART3任务。 任务1让一个LED灯闪烁,任务2让另外一个LED闪烁,两个LED闪烁的频率不一样,任务3让串口发送字符串。三个任务的优先级不一样。

2、主函数运行时创建起始任务, 起始任务运行时进行创建两个LED 灯的任务一个串口发送任务和删除自身,之后就运行三个任务。两个 LED 灯的任务优先级不一样, LED1任务为 LED1 每隔 1秒切换一次亮灭状态, LED2 任务为 LED2 每隔 3 秒切换一次亮灭状态, USART3 任务以2s周期通过串口发送“hello uc/OS! 欢迎来到RTOS多任务环境!”

1、首先在“ app_cfg.h”里,增加定义三个任务的优先级和栈空间大小

在这里插入图片描述

2、修改app.c



#include <includes.h>



//任务控制块
static  OS_TCB   AppTaskStartTCB;
static  OS_TCB   AppTaskLed1TCB;
static  OS_TCB   AppTaskLed2TCB;
static  OS_TCB   AppTaskUSART3TCB;



//定义任务栈
static  CPU_STK  AppTaskStartStk[APP_TASK_START_STK_SIZE];
static  CPU_STK  AppTaskLed1Stk [ APP_TASK_LED1_STK_SIZE ];
static  CPU_STK  AppTaskLed2Stk [ APP_TASK_LED2_STK_SIZE ];
static  CPU_STK  AppTaskUSART3Stk [ APP_TASK_USART3_STK_SIZE ];


static  void  AppTaskStart  (void *p_arg);
static  void  AppTaskLed1  ( void * p_arg );
static  void  AppTaskLed2  ( void * p_arg );
static  void  AppTaskUSART3  ( void * p_arg );


int  main (void)
{
    OS_ERR  err;


    OSInit(&err);                                               /* Init uC/OS-III.                                      */

    OSTaskCreate((OS_TCB     *)&AppTaskStartTCB,                /* Create the start task                                */
                 (CPU_CHAR   *)"App Task Start",
                 (OS_TASK_PTR ) AppTaskStart,
                 (void       *) 0,
                 (OS_PRIO     ) APP_TASK_START_PRIO,
                 (CPU_STK    *)&AppTaskStartStk[0],
                 (CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10,
                 (CPU_STK_SIZE) APP_TASK_START_STK_SIZE,
                 (OS_MSG_QTY  ) 5u,
                 (OS_TICK     ) 0u,
                 (void       *) 0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 (OS_ERR     *)&err);

    OSStart(&err);                                              /* Start multitasking (i.e. give control to uC/OS-III). */
		
		
}




//定义任务函数

static  void  AppTaskStart (void *p_arg)
{
    CPU_INT32U  cpu_clk_freq;
    CPU_INT32U  cnts;
    OS_ERR      err;

  LED1_Init();
   (void)p_arg;

    //BSP_Init();                                                 /* Initialize BSP functions                             */
    CPU_Init();

    cpu_clk_freq = BSP_CPU_ClkFreq();                           /* Determine SysTick reference freq.                    */
    cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz;        /* Determine nbr SysTick increments                     */
    OS_CPU_SysTickInit(cnts);                                   /* Init uC/OS periodic time src (SysTick).              */

    Mem_Init();                                                 /* Initialize Memory Management Module                  */

#if OS_CFG_STAT_TASK_EN > 0u
    OSStatTaskCPUUsageInit(&err);                               /* Compute CPU capacity with no task running            */
#endif

    CPU_IntDisMeasMaxCurReset();
	
	//任务1
	 OSTaskCreate((OS_TCB     *)&AppTaskLed1TCB,                /* Create the start task                                */
                 (CPU_CHAR   *)"App Task Led1",
                 (OS_TASK_PTR ) AppTaskLed1,
                 (void       *) 0,
                 (OS_PRIO     ) APP_TASK_LED1_PRIO,
                 (CPU_STK    *)&AppTaskLed1Stk[0],
                 (CPU_STK_SIZE) APP_TASK_LED1_STK_SIZE / 10,
                 (CPU_STK_SIZE) APP_TASK_LED1_STK_SIZE,
                 (OS_MSG_QTY  ) 5u,
                 (OS_TICK     ) 0u,
                 (void       *) 0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 (OS_ERR     *)&err);
	
	
	//任务2
	OSTaskCreate((OS_TCB     *)&AppTaskLed2TCB,                /* Create the start task                                */
                 (CPU_CHAR   *)"App Task Led2",
                 (OS_TASK_PTR ) AppTaskLed2,
                 (void       *) 0,
                 (OS_PRIO     ) APP_TASK_LED2_PRIO,
                 (CPU_STK    *)&AppTaskLed2Stk[0],
                 (CPU_STK_SIZE) APP_TASK_LED2_STK_SIZE / 10,
                 (CPU_STK_SIZE) APP_TASK_LED2_STK_SIZE,
                 (OS_MSG_QTY  ) 5u,
                 (OS_TICK     ) 0u,
                 (void       *) 0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 (OS_ERR     *)&err);
	
	//任务3
				 //任务2
	OSTaskCreate((OS_TCB     *)&AppTaskUSART3TCB,                /* Create the start task                                */
                 (CPU_CHAR   *)"App Task USART3",
                 (OS_TASK_PTR ) AppTaskUSART3,
                 (void       *) 0,
                 (OS_PRIO     ) APP_TASK_USART3_PRIO,
                 (CPU_STK    *)&AppTaskUSART3Stk[0],
                 (CPU_STK_SIZE) APP_TASK_USART3_STK_SIZE / 10,
                 (CPU_STK_SIZE) APP_TASK_USART3_STK_SIZE,
                 (OS_MSG_QTY  ) 5u,
                 (OS_TICK     ) 0u,
                 (void       *) 0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 (OS_ERR     *)&err);
	
				 //创建三个任务成功,删除起始任务
	OSTaskDel ( & AppTaskStartTCB, & err );	
		
}


//任务1具体实现
static  void  AppTaskLed1 ( void * p_arg )
{
    OS_ERR      err;

    (void)p_arg;

    while (DEF_TRUE) {                                          /* Task body, always written as an infinite loop.       */
			LED1_ON();
			OSTimeDly ( 3, OS_OPT_TIME_DLY, & err );
		    LED1_OFF();
		    OSTimeDly ( 3000, OS_OPT_TIME_DLY, & err );
    }
}

//任务2具体实现
static  void  AppTaskLed2 ( void * p_arg )
{
    OS_ERR      err;


    (void)p_arg;
	
	 //LED1_Init();

    while (DEF_TRUE) {                                          /* Task body, always written as an infinite loop.       */
			LED2_ON();
			OSTimeDly ( 1, OS_OPT_TIME_DLY, & err );
		    LED2_OFF();
		    OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err );
    }


}

//任务3具体实现
static  void  AppTaskUSART3 ( void * p_arg )
{
    OS_ERR      err;
    (void)p_arg;
	
	 Serial_Init();

    while (DEF_TRUE) {                                          /* Task body, always written as an infinite loop.       */
			Serial_SendString("hello uc/OS! 欢迎来到RTOS多任务环境!\r\n");
		OSTimeDly ( 2000, OS_OPT_TIME_DLY, & err );
    }
}

四、实验结果

1

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式实时操作系统(RTOS) 的相关文章

  • 阿里云云平台,物联网可视化web界面简单教程

    目前市面上的云平台 xff0c 多以华为 xff0c 阿里 xff0c 中国移动为主 但是了解一个 xff0c 便可满足需求了 1 首先 xff0c 我们要创建一个属于自己的账号 xff0c 然后尽可能的领取各种限免套餐 2 打开产品这一栏
  • LCD屏幕 ~ 字模提取工具和图片转码工具

    目录 字模提取 工具资源下载 xff1a 图片转码 工具资源下载 xff1a 字模提取 工具资源下载 xff1a 链接 xff1a https pan baidu com s 1BF8lJLmM V vWrl2F6Cd7Q pwd 61 m
  • (练习篇)萤火虫esp32与小爱音响---实现笔记本电脑唤醒

    目录 初步工作 xff1a 进入正题 xff1a 初步工作 xff1a xff08 已使用过ESP32的同志们 xff0c 可以忽略这一步 xff09 首先下载arduinoIDE Software Arduino 我安装的是1 8 18直
  • Python:列表有趣挑战--斗地主扑克牌发牌

    目录 游戏描述 xff1a 题目分析与关键点 xff1a 代码参考 xff1a 游戏描述 xff1a 本题限定用以下方法打乱序列中的元素 random shuffle 几个人用一副扑克牌玩游戏 xff0c 游戏过程通常有洗牌 发牌 理牌等动
  • Python: 常用指令归纳(持续更新中)

    目录 复合赋值运算符 位运算符的运算规则 常用的转义符 常用字符串格式转换控制符 字符串处理函数 序列类型的常用操作符 复合赋值运算符 复合赋值运算符 运 算 符功 能 描 述 示 例 x 61 5 xff0c y 61 3 43 61 加
  • 无线远距离WiFi模块图传技术,无人机智能安防预警应用

    随着社会经济的快速发展 xff0c 交通工具日渐增多 xff0c 人员 车辆流动性大 xff0c 警车 警员在执法过程中对移动目标 突发场合的信息收集与现场预警 xff0c 当场发现嫌疑目标并进行抓捕已成为公安警务工作的紧迫需求 从警务执法
  • yolov5输出检测框的中心位置,框的长宽,框的位置,以及输出对应标签格式的输出

    yolov5输出检测框的中心位置 xff0c 框的长宽 xff0c 框的位置 xff0c 以及输出对应标签格式的输出 模型读取每个图片 xff0c 并将上述的信息依此输出到同名的txt文件中保存 xff0c 具体需要哪些坐标可以自己选 更改
  • 无人机远距离WiFi图传应用,CV5200无线WiFi模组,远程实时通信传输方案

    无线图传在实际应用中越来越受到追捧 xff0c 无线图传免布线 移动方便 安装简单 xff0c 大大节约了材料和人工成本 无线图传能够在远距离范围内实时视频无线传输 xff0c 满足了不同距离需要的需求 xff0c 也覆盖了不同规模的企业
  • antd表单赋值,回显表格数据

    使用 antd 做表格回显数据时 xff0c 会看到文档有写 xff1a 所以我们可以 1 定义hooks const form 61 Form useForm 2 在触发事件中使用 xff0c 以打开模态框赋值为例 const showM
  • jetson nano jacksdk4.6中cuda,cudnn,tensorrt的版本查看

    JetPack 4 6上已经预装了CUDA cuDNN and TensorRT VPI 1 1 可以直接从官网下载 xff08 jetson sdk xff09 使用拷贝到SD卡 JetPack 4 6 is the latest pro
  • 无人船毕设进展

    智能无人测量船设计进展 xff08 硬件系统 xff09 目录前言课题目的研究现状控制系统 xff08 Pixhawk xff09 动力系统供电系统通讯系统传感器系统pixhawk2 4 8接口分析控制系统详细分析技术路线参考文献 目录 前
  • OpenMV:20追踪其他物体的云台

    文章目录 追踪人脸的云台追踪AprilTags的云台追踪圆形的云台 和追踪小车的原理是一样的 首先获得目标物体的x y坐标 xff0c 然后通过目标物体的xy坐标来控制我们云台的两个舵机的pid运动 无论追踪什么物体 xff0c 都是通过物
  • 如何在Linux终端使用录屏工具Asciinema?

    安装asciinema apt get install asciinema 开始记录视频 asciinema rec first cast 以倍速重播 asciinema play s 2 first cast 分享或上传至网络 ascii
  • 初探进程和线程

    初探进程和线程 之前学习过RTOS xff0c 对线程有一些认识和理解 xff0c 但接触到Linux后还遇到了进程这个概念 xff0c 虽然两者之间名字很相像 xff0c 但其实是完全不同的两个概念 进程包含一个内存地址和执行的线程 xf
  • CENTOS7设置静态IP

    Centos7网卡配置配置永久ip xff1a 1 网卡目录 xff1a etc sysconfig network scripts ifcfg ens33 2 网卡重启命令 xff1a sudo ip addr flush dev ens
  • lsof命令

    一 lsof命令 lsof命令用于查看你进程开打的文件 xff0c 打开文件的进程 xff0c 进程打开的端口 TCP UDP 找回 恢复删除的文件 是十分方便的系统监视工具 xff0c 因为lsof命令需要访问核心内存和各种文件 xff0
  • 官网TimescaleDB 配置

    官网 xff1a https www zabbix com documentation current zh manual appendix install timescaledb TimescaleDB 配置 概述 Zabbix支持Tim
  • centos7-UBTUN配置单网卡多IP(子接口)

    文件位置 proc sys net ipv4 conf nbsp nbsp 查看适配器 网卡 名称 网卡目录 nbsp etc sysconfig network scripts 一 centos7 即Linux下配置网卡ip别名何谓ip别
  • centos7 and unbtun设置多网卡多IP + 单网卡多子接口(子ip)

    一 centos7 多网卡多IP 目录 proc sys net ipv4 conf nbsp nbsp nbsp nbsp nbsp nbsp nbsp 查看网卡 小注 vmare添加一块新的网络适配器之后查看新添加的网卡名称 基础环境配
  • centos7配置网卡bonding+(多网卡多IP单网卡单IP)

    目录 xff1a proc sys net ipv4 conf 查看网卡 watch n 1 cat proc net bonding bond0 监控 bond0 状态 xff0c 小注 xff1a vmare添加一块新的网络适配器之后查

随机推荐