移植和使用ucOSII

目录

1、首先打开STM32CubeMx,选择New Project,选择芯片型号

2、其次,选择RCC时钟配置

3、第三,选择对应的debug接口

 4、配置主频时钟

 5、不生成PendSV_IRQn代码

 6、配置LED灯的IO用于测试

 7、配置代码生成选项,点击生成

 8、先修改keil设置,验证HAL_Delay

8.1 使用微库,不使用浮点单元(target选项)

8.2 选择编译输出文件的目录,并去掉索引编译

8.3 选择最低代码优化等级

8.4 选择烧录工具

 9、注释掉Error_Handler中的初始代码

 10、在main函数while(1)中添加测试代码

 11、移植ucOSII代码

11.1 拷贝ucOSII源码

11.2 添加到工程中,并添加头文件路径包含

11.3 移植和运行

12、结束


本篇文章记录和讲述一下,如何创建一个新的keil工程,并将ucOSII移植进去。

我的板子MCU是STM32F429ZGT6,有3个LED灯,支持USB/BT通讯。

1、首先打开STM32CubeMx,选择New Project,选择芯片型号

2、其次,选择RCC时钟配置

 根据自己的MCU外围电路选择时钟,如下图,一般都是直接勾选这两个选项。

3、第三,选择对应的debug接口

 4、配置主频时钟

比如F4芯片,如果有类似USB/SDIO等需要单独提供时钟,而不是来自APB1、APB2上的,建议先使能接口,再选择时钟。

比如我这里,先勾选上 1、USB接口和 2、USB虚拟串口设备(从机),时钟配置选项那里就会提示警告。

然后再去配置时钟。

 

 5、不生成PendSV_IRQn代码

把下图中的勾选取消掉。

否则移植ucOSII代码时,会提示重复定义。因为在ucOSII的汇编代码中,已经定义了其处理函数。

 6、配置LED灯的IO用于测试

如下图,点击IO选择output功能,然后在GPIO设置中定义一个标签名。

 7、配置代码生成选项,点击生成

注意点1:路径中不要有中文名,否则最后生成会提示失败;其次最好是自己创建工程目录,不要用Cubemx去新建文件夹。

注意点2:尽量勾选“Copy Only the libraryies into the project files”,否则Drivers目录下会有一大堆冗余文件,用git存储时就比较浪费空间了。

 8、先修改keil设置,验证HAL_Delay

8.1 使用微库,不使用浮点单元(target选项)

8.2 选择编译输出文件的目录,并去掉索引编译

HAL库代码虽然简单易用,但是代码量剧增,编译起来速度会相当慢。

8.3 选择最低代码优化等级

8.4 选择烧录工具

如下,以Jlink为例,先选择Jlink,再选择SWD port,

右侧如果出现ID code表示识别成功。

最后记得,在Download选项中勾选reset,否则你烧录程序之后,需要手动进行硬件复位

 

 9、注释掉Error_Handler中的初始代码

如下,将这段代码注释掉,可以自行添加代码打印或其它操作代码。

Error_Handler函数,是用在HAL库的初始化失败时调用,但是有些初始化失败是没有影响的,不能直接死掉。

 10、在main函数while(1)中添加测试代码

测试LED灯闪烁及HAL库延时函数。

编译,然后烧录,可以看到板子开始循环闪烁。

 11、移植ucOSII代码

11.1 拷贝ucOSII源码

STM32F4平台的源码,是非常少的。

不像F7、H7系列,还有BSP、CPU等多个文件夹。

具体结构如下图。

源码文件:

Core目录下文件:

 Port目录下文件:

11.2 添加到工程中,并添加头文件路径包含

1)添加内核文件

不需要的模块可以不添加,比如事件标志组和内存管理的文件,我就没添加,但前提是ucOSII的配置文件没有使能这两个模块。

2)添加cpu.c和cpu.asm文件

 3)包含路径

至此,先编译一下,没有警告和错误,证明移植成功了。

11.3 移植和运行

对于,ucOSii再做两个加工。

一是SysTickHandler,二是OSStart。顾名思义,分别是systick中断调用服务和系统启动函数。

1)SysTickHandler和OSStart

void  OS_CPU_SysTickHandler (void)
{
    OSIntEnter();                        /* Tell uC/OS-II that we are starting an ISR          */

    OSTimeTick();                        /* Call uC/OS-II's OSTimeTick()                       */

    OSIntExit();                         /* Tell uC/OS-II that we are leaving the ISR          */
}
#define START_UP_TASK_PRIO 8

#define START_UP_TASK_SIZE 512

OS_STK START_UP_TASK[START_UP_TASK_SIZE];

__weak void StartUpTask(void *pdata) { pdata = pdata; OSStatInit();  for(;;) { OSTimeDly(1); } }

void  OS_CPU_Start(void)
{
	OSInit();
	OSTaskCreate(StartUpTask,(void *)0,(OS_STK *)&START_UP_TASK[START_UP_TASK_SIZE-1],START_UP_TASK_PRIO);
	OSStart();
}

2)头文件封装

实现 includes.h 文件,并在main.h文件中进行调用。

这样在涉及底层HAL库驱动和RTOS的API时,只需要调用这一个文件。

/*
************************************************************************************************
文 件: INCLUDES.C ucos主要的包含文件
************************************************************************************************
*/

#ifndef __INCLUDES_H__
#define __INCLUDES_H__

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <stdint.h>

#include "ucos_ii.h"
#include "os_cpu.h"
#include "os_cfg.h"

#endif

其中,系统启动函数,内部定义了1个弱函数,内部循环delay。

 我们可以在外部直接定义这个任务函数。

参考流程如下:

1. main文件包含includes.h 文件

#include "includes.h"

 2. SysTick_Handler中调用OS_CPU_SysTickHandler

void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */
  OS_CPU_SysTickHandler();
  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

3. main函数中调用OS_CPU_Start

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */

  OS_CPU_Start();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  HAL_GPIO_TogglePin(LED_YELLOW_GPIO_Port, LED_YELLOW_Pin);
	  HAL_Delay(200);
  }
  /* USER CODE END 3 */

4. 定义起始任务

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

void StartUpTask(void *pdata)
{
	
	pdata = pdata;
	
	OSStatInit();
	
	for(;;)
	{
		HAL_GPIO_TogglePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin);
		OSTimeDly(200);
	}
}

/* USER CODE END 0 */

5. 烧录执行,观察结果

可以看到,黄灯不亮了,蓝灯开始闪烁。

说明,main函数中启动OS之后,在启动代码之后的代码便不再执行,

只会执行任务或中断中的代码。

12、结束

猜你喜欢

转载自blog.csdn.net/weixin_38743772/article/details/126445512
今日推荐