中国钓鱼网站大全,线上分销平台,国内最专业的设计网站建设,广州海珠区好玩的地方前言 前两篇已经 通过 STM32CubeMX 搭建了 NUCLEO-L476RG 的 STM32L476RG 的 裸机工程#xff0c;下载了 uC-OS2 V2.93 的源码#xff0c;并把 uC-OS2 的源文件加入 Keil MDK5 工程 本篇适配 uC-OS2 的 系统定时器#xff08;Systick#xff09;与 PendSV_Handler#xf…前言 前两篇已经 通过 STM32CubeMX 搭建了 NUCLEO-L476RG 的 STM32L476RG 的 裸机工程下载了 uC-OS2 V2.93 的源码并把 uC-OS2 的源文件加入 Keil MDK5 工程 本篇适配 uC-OS2 的 系统定时器Systick与 PendSV_Handler创建 用户任务让 uC-OS2 启动并运行起来
开发环境 win10 64位 Keil uVision5MDK V5.36 uC-OS2 V2.93 开发板NUCLEO-L476RG MCU 为 STM32L476RG STM32CubeMX 6.9.1用于生成 STM32的裸机工程
创建用户任务
这里创建一个 led 闪烁的任务在 main.c 中实现
#include main.h
#include led.h
#include app_cfg.h
#include os.hUART_HandleTypeDef huart2;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);#define TASK_LED_PRIO 5
#define TASK_LED_STACK_SIZE 128
static OS_STK task_led_stack[TASK_LED_STACK_SIZE];static void task_led_entry(void *p_arg)
{while (1){led_grn_ctrl(1);OSTimeDly(1000);led_grn_ctrl(0);OSTimeDly(1000);}
}void led_task_init(void)
{OSTaskCreate(task_led_entry,(void *)0, task_led_stack[TASK_LED_STACK_SIZE-1], TASK_LED_PRIO);
}HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{return HAL_OK;
}/*** brief The application entry point.* retval int*/
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART2_UART_Init();OSInit();led_task_init();OS_CPU_SysTickInitFreq(80000000);OSStart();return 0;
}适配 Systick 工程编译下载后发现 任务没有正常调度起来原因是没有适配 uC-OS2 首先需要开启 uC-OS2 的系统定时器也就是系统的心跳 uC-OS2 V2.93 有 Systick 的初始化函数uC-OS2\Ports\ARM-Cortex-M\ARMv7-M\os_cpu_c.cOS_CPU_SysTickInitFreq 备注 STM32的 HAL库默认在 HAL_Init 中通过 HAL_InitTick 初始化了 1ms 一次的 Systick 这里首先重新 STM32 HAL 库的 HAL_InitTick默认是个 weak 函数可以重新这里重写为空也就是不通过 STM32 HAL 库初始化 Systick
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{return HAL_OK;
}通过 OS_CPU_SysTickInitFreq(80000000); 初始化 Systick 初始化了 Systick就要处理一下 Systick 的中断函数 SysTick_Handler需要调用 uC-OS2 的 OS_CPU_SysTickHandler修改文件 stm32l476_ucosii_led\Core\Src\stm32l4xx_it.c
#include app_cfg.h
#include os_cpu.hvoid SysTick_Handler(void)
{OS_CPU_SysTickHandler();HAL_IncTick();
}以上的修改 Systick 初始化Systick 的中断可以周期性的触发 如果发现 Systick 没有按1毫秒触发一次中断如延时1秒发现时间是 10秒需要修改 uC-OS2\Cfg\Template\os_cfg.h修改 OS_TICKS_PER_SEC 改为 #define OS_TICKS_PER_SEC 1000u也就是 1毫秒触发一次Systick 中断
适配 PendSV_Handler
像 STM32 系列的芯片默认通过 PendSV_Handler 中断进行任务的切换修改文件 stm32l476_ucosii_led\Core\Src\stm32l4xx_it.c 中的 PendSV_Handler
void PendSV_Handler(void)
{OS_CPU_PendSVHandler();
}注意 stm32l476_ucosii_led\Core\Src\stm32l4xx_it.c 中 包含头文件
#include app_cfg.h
#include os_cpu.h编译烧写 编译烧写后发现开发板的 LED 正常的闪烁 uC-OS2 系统移植初步完成任务切换、系统延时等正常工作了 可以点击 Keil MDK5 的【Debug】调试按钮进入 Debug 调试模式加入【断点】单步或者连续运行观察 uC-OS2 的任务调度、切换用户例程的执行等
调试说明
如果调试发现【断点】不起作用需要调整 Keil MDK5 的编译优化等级改为 O0 试试 通过软件调试可以熟悉整个系统的初始化、启动、运行流程
小结 本篇通过适配 uC-OS2 的两个关键的适配 系统滴答定时器与 PendSV 系统异常实现 uC-OS2 的正常启动与运行 uC-OS2 移植起来相对简单后面继续研究 uC-OS2如增加串口输出、移植 Shell 等