华大HC32F072移植FreeRTOS超详细教程

网上关于华大系列的RTOS教程比较少,特分享此移植过程

背景原因:STM32太贵了,而且CubeMx太强了,移植难度0。
做一个国产单片机的移植,后续其它单片机移植也可参考类似过程。

环境说明:

开发IDE:MDK-ARM Plus ver 5.34
MCU:
国产华大单片机 HC32F072,主频 48Mhz ,Core M0+内核 ,RAM 16KB ,ROM 128KB
RTOS:FreeRTOS V10.4.3

移植分为以下几个步骤

一、准备
二、FreeRTOS源码

三、添加工程
四、裁剪
五、使用


一、准备

首先准备一个HC32F072的最小系统,可以参考官方点灯Demo。为了发挥最大性能,将主频修改至最大48Mhz。此处不做详细教程,也可参考已修改好的branch-noOS
下载FreeRTOS源代码,官网:https://www.freertos.org/a00104.html
选择稳定版本下载:FreeRTOS LTS Release 202012.01 并解压


二、FreeRTOS源码

先在最小系统的source目录下新建一个FreeRTOS目录用来存放RTOS源码!

拷贝FreeRTOS源码解压后的路径下FreeRTOS-LTSFreeRTOSFreeRTOS-Kernel 的所有内容到本地的source/FreeRTOS目录下。

在source/FreeRTOS目录下再新建一个一个source目录,将source/FreeRTOS目录下的所有.c文件剪切到source/FreeRTOS/source目录下。

现在FreeRTOS源码被我们分成了三个目录,分别是①include目录;②portable目录;③source目录
这里 分析一下 FreeRTOS源码结构,①和③包含的是FreeRTOS核心功能源文件及头文件 .c和.h,这两部分的文件试用于各种编译器和处理器,是通用的,基本不需要修改,②为需要移植修改的目录,这与编译器和所使用的CPU有关,属于RTOS硬件接口层。

再分析一下②portable目录

keil就是我们就是我们使用的编译器,其实keil里面的内容跟RVDS里面的内容一样,所以我们只需要分析RVDS文件夹里面的内容即可。
RVDS里面包含了各种处理器相关的文件夹,与CPU内核相关。FreeRTOS是一个软件,单片机是一个硬件,FreeRTOS要想运行在一个单片机上面,它们就必须关联在一起。
MemMang文件夹下存放的是跟内存管理相关的源文件,一般情况我们都选用heap4方式。

三、添加工程

打开keil
Manage -> project Items -> Groups 添加三个工程目录,分别为FreeRTOS/src ;FreeRTOS/port ;FreeRTOS/config 点击OK。



3. 在 Project栏中 选中FreeRTOS/src,右击->Add Existing File to Group ... .添加sourceFreeRTOsource目录下的所有.c文件

4. 在 Project栏中 选中FreeRTOS/port,右击->Add Existing File to Group ... .添加sourceFreeRTOSportableRVDS*ARM_CM0* 目录下的所有.c文件。这里因为MCU是core M0内核,其它MCU选中对应内核目录

5. 在 Project栏中 选中FreeRTOS/port,右击->Add Existing File to Group ... .添加sourceFreeRTOSportableMemMang 目录下的heap_4.c文件


6. 添加头文件路径 在options -> c/c++ -> include paths -> ...
.sourceFreeRTOSinclude
.sourceFreeRTOSportableMemMang
.sourceFreeRTOSportableRVDSARM_CM0

四、裁剪

FreeRTOS的裁剪主要依靠FreeRTOSConfig.h中的宏定义去完成,需要什么功能就打开对应的宏就可以了。
现在我们需要一个FreeRTOSConfig.h文件。但在源码FreeRTOS-Kernel目录下没有提供config文件。

再去FreeRTOS官网下载常规版本的源码,在demo目录下找到对应内核目录下的demo(可能是其它MCU,不要紧)拷贝一个FreeRTOSConfig.h文件到本地sourceFreeRTOSinclude目录n内。我提供里一个带注释版本的FreeRTOSConfig.h文件,复制到本地sourceFreeRTOSinclude目录。内容如下:


#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

#define configUSE_PREEMPTION 1//抢占式调度器开关
#define configUSE_IDLE_HOOK 0//空闲任务钩子函数
#define configUSE_TICK_HOOK 0//时间片钩子函数
#define configCPU_CLOCK_HZ ( SystemCoreClock )//CPU主频
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )//RTOS节拍频率 即1秒的中断次数
#define configMAX_PRIORITIES ( 5 )//可使用的最大优先级
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 60 )//定义空闲任务使用的堆栈大小
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8*1024 ) )//RTOS内核总计可用的有效的RAM大小
#define configMAX_TASK_NAME_LEN ( 12 )//任务名最大长度
#define configUSE_TRACE_FACILITY 0//是否启动可视化跟踪调试
#define configUSE_16_BIT_TICKS 0//系统节拍计数器的变量类型 0为32位 1为16为
#define configIDLE_SHOULD_YIELD 1//空闲任务放弃CPU使用权给其他同优先级的用户任务
#define configUSE_MUTEXES 1//是否使用互斥信号量
#define configQUEUE_REGISTRY_SIZE 8//设置可以注册的信号量和消息队列个数
#define configCHECK_FOR_STACK_OVERFLOW 0//堆栈溢出检查 大于0有效
#define configUSE_RECURSIVE_MUTEXES 1//是否使用递归互斥信号量
#define configUSE_MALLOC_FAILED_HOOK 0//内存申请失败钩子函数
#define configUSE_APPLICATION_TASK_TAG 0//为任务分配标签
#define configUSE_COUNTING_SEMAPHORES 1//是否使用计数信号量
#define configGENERATE_RUN_TIME_STATS 0//是否启用运行时间统计功能

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0//启用协程,启用协程以后必须添加文件croutine.c
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )//协程的有效优先级数目

/* Software timer definitions. */
#define configUSE_TIMERS 0//是否启用软件定时器
#define configTIMER_TASK_PRIORITY ( 2 )//软件定时器优先级
#define configTIMER_QUEUE_LENGTH 5//软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH ( 80 )//软件定时器任务堆栈大小

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. *///是否启用RTOS API函数
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1

/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names - or at least those used in the unmodified vector table. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

#endif /* FREERTOS_CONFIG_H */

3. 为了方便修改 在 Project栏中 选中FreeRTOS/config,右击->Add Existing File to Group ... .添加sourceFreeRTOinclude目录下的FreeRTOSConfig.h

4.为了将应用层代码和系统层关联在一起,需要引用一下对方的头文件
在main.c中添加引用FreeRTOS头文件 #include "FreeRTOS.h" 和 #include "task.h"
在FreeRTOSConfig.h中添加头文件华大的头文件 #include "hc32f072.h"

5. RTOS心跳时钟本质是通过定时器中断是实现的,所以我们需要设置一个符合RTOS节拍的定时器中断用作RTOS的“心跳” ,并将中断处理函数交给RTOS管理。

定时器中断 其实在FreeRTOS中,这一部分已经完成了,在port.c文件中已经实现vPortSetupTimerInterrupt()函数 ,采用了滴答定时器SysTick ,中断时间是根据FreeRTOSConfig.h里configCPU_CLOCK_HZ和configTICK_RATE_HZ宏来设置的,目前是1mS,当我们启动任务调度函数vTaskStartScheduler()时就会调用,所以我们不需要修改什么


中断服务函数 这一部分FreeRTOS源码中也已经帮我们实现好了,在port.c文件中已经实现xPortSysTickHandler()函数,所以我们要注释原来的SysTick中断服务函数,在sourcecommon目录在的interrupts_hc32f072.c文件中

6. 尝试编译一下, 如果没有报错及警告说明移植工作已经完成
如果出现类以下错误:

是由于你的ARM编译器太高了,处理汇编和C代码的混合时导致无法识别__ASM关键字导致语法错误。
有两种解决办法
① 修改编译器版本为V5,在options -> Target -> ARM compiler 中选择Use default compiler version 5

② 修改类似的代码如下

这里建议还是选择方法①

五、使用

写一个闪烁点灯任务,注意是一个死循环,并通过RTOS 延时API vTaskDelay()函数延时



2. 创建一个任务句柄变量




3. 在main函数中,创建一个点灯任务,并启动任务调度




4. 编译




5. 完成!!!

HC32F072+FreeRTOS源码下载:
github

看完不要忘了点个赞哦~~~! ^-^

展开阅读全文

页面更新:2024-05-04

标签:信号量   优先级   定时器   编译器   单片机   内核   函数   源码   文件   目录   教程   详细

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top