当前位置: 首页 > news >正文

【ARM驱动】【FreeROTS移植到ARM驱动平台介绍】

1. 问题背景

HME的H7/P2等系列是SOC产品,系列芯片的架构是相同的,ARM是都Correx-M3,FPGA在资源、接口上有所差异。FPGA工程师按照正常的开发即可,ARM工程师拿到HME的驱动文件就可以进行裸片开发。但是,有些客户需要移植FreeRTOS,因此对FreeRTOS移植到HEM ARM驱动做以介绍。

2. 概念介绍

裸机:裸机又称为前后台系统,前台系统指中断服务函数,后台系统指大循环,即应用程序。

裸机缺点:

a. 实时性差,应用程序轮流执行;

b. 空等待,CPU不执行其他代码;

c. 结构臃肿,实现功能都放在无限循环。

RTOS特点:RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时性。

a. 分而治之,实现功能划分为多个任务;

b. 延时函数,任务调动;

c. 抢占式,高优先级任务抢占低优先级任务;

d. 任务堆栈,每个任务都有自己的栈空间;

注意1:中断可以打断任意任务

注意2:任务可以同等优先级

关于FreeRTOS的细节,可以通过官网或者B站上各位大神的讲解学习。

3. 移植步骤

针对HME的驱动平台移植,可以做步骤:.

(1)获取FreeRTOS源码;

(2) FreeRTOS移植以及系统配置

(1)获取FreeRTOS源码

FreeRTOS官网:https://www.freertos.org/

如下图所示:

点击1或者3“红框”可以下载最新默认的版本,如图所示当前时间最新版本是FreeRTOS 202406. 04 LTS;

点击2 “红框”有关于版本下载信息的说明;

要想获取之前的版本需要通过GitHub获取。

下图是官网下载的V202406.01版本

代码移植过程中,主要关心“红框”的源码。

以下红框是移植过程中必须的文件以及文件夹。

portable文件夹

FreeRTOS操作系统归根结底是软件层面实现的,那FreeRTOS是如何跟硬件联系在一起的呢?

portable文件夹里面的内容就是连接桥梁。

在Coretex-M3上开发,需要关注Keil、MemMang、RVDS。

(2) FreeRTOS移植

移植步骤:

1. 添加FreeRTOS源码

将FreeRTOS源码添加至基础工程、头文件路径等;

源码添加:

因为该系列芯片采用Coretex-M3,堆栈使用heap_4.c,以及RVDS\ARM_CM3下的port.c文件。

头文件路径添加:

2. FreeRTOSConfig.h

添加FreeRTOSConfig.h配置文件,并修改。

适配configCPU_CLOCK_HZ为HME的系统宏;

适配configSUPPORT_DYNAMIC_ALLOCATION为1,动态方式创建任务;

这移植配置未使能静态方式创建任务编译宏。

示例代码如下:


#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include <hme_conf.h>
#include <stdio.h>//断言
#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)/***************************************************************************************************************/
/*                                        FreeRTOS基础配置配置选项                                              */
/***************************************************************************************************************/
#define configUSE_PREEMPTION                    1                       //1使用抢占式内核,0使用协程
#define configUSE_TIME_SLICING                  1                       //1使能时间片调度(默认式使能的)
#define configUSE_PORT_OPTIMISED_TASK_SELECTION	1                       //1启用特殊方法来选择下一个要运行的任务//一般是硬件计算前导零指令,如果所使用的//MCU没有这些硬件指令的话此宏应该设置为0!
#define configUSE_TICKLESS_IDLE                 0                       //1启用低功耗tickless模式
#define configUSE_QUEUE_SETS                    1                       //为1时启用队列
//#define configCPU_CLOCK_HZ                        (SystemCoreClock)       //CPU频率
#define configCPU_CLOCK_HZ                      (HME_SYS_CLK)           //CPU频率
#define configTICK_RATE_HZ                      (1000)                  //时钟节拍频率,这里设置为1000,周期就是1ms
#define configMAX_PRIORITIES                    (32)                    //可使用的最大优先级
#define configMINIMAL_STACK_SIZE                ((unsigned short)130)   //空闲任务使用的堆栈大小
#define configMAX_TASK_NAME_LEN                 (16)                    //任务名字字符串长度#define configUSE_16_BIT_TICKS                  0                       //系统节拍计数器变量数据类型,//1表示为16位无符号整形,0表示为32位无符号整形
#define configIDLE_SHOULD_YIELD                 1                       //为1时空闲任务放弃CPU使用权给其他同优先级的用户任务
#define configUSE_TASK_NOTIFICATIONS            1                       //为1时开启任务通知功能,默认开启
#define configUSE_MUTEXES                       1                       //为1时使用互斥信号量
#define configQUEUE_REGISTRY_SIZE               8                       //不为0时表示启用队列记录,具体的值是可以//记录的队列和信号量最大数目。
#define configCHECK_FOR_STACK_OVERFLOW          0                       //大于0时启用堆栈溢出检测功能,如果使用此功能//用户必须提供一个栈溢出钩子函数,如果使用的话//此值可以为1或者2,因为有两种栈溢出检测方法。
#define configUSE_RECURSIVE_MUTEXES             1                       //为1时使用递归互斥信号量
#define configUSE_MALLOC_FAILED_HOOK            0                       //1使用内存申请失败钩子函数
#define configUSE_APPLICATION_TASK_TAG          0                       
#define configUSE_COUNTING_SEMAPHORES           1                       //为1时使用计数信号量/***************************************************************************************************************/
/*                                FreeRTOS与内存申请有关配置选项                                                */
/***************************************************************************************************************/
#define configSUPPORT_DYNAMIC_ALLOCATION        1                       //支持动态内存申请
#define configTOTAL_HEAP_SIZE                   ((size_t)(20*1024))     //系统所有总的堆大小/***************************************************************************************************************/
/*                                FreeRTOS与钩子函数有关的配置选项                                              */
/***************************************************************************************************************/
#define configUSE_IDLE_HOOK                     0                       //1,使用空闲钩子;0,不使用
#define configUSE_TICK_HOOK                     0                       //1,使用时间片钩子;0,不使用/***************************************************************************************************************/
/*                                FreeRTOS与运行时间和任务状态收集有关的配置选项                                 */
/***************************************************************************************************************/
#define configGENERATE_RUN_TIME_STATS           0                       //为1时启用运行时间统计功能
#define configUSE_TRACE_FACILITY                1                       //为1启用可视化跟踪调试
#define configUSE_STATS_FORMATTING_FUNCTIONS    1                       //与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数//prvWriteNameToBuffer(),vTaskList(),//vTaskGetRunTimeStats()/***************************************************************************************************************/
/*                                FreeRTOS与协程有关的配置选项                                                  */
/***************************************************************************************************************/
#define configUSE_CO_ROUTINES                   0                       //为1时启用协程,启用协程以后必须添加文件croutine.c
#define configMAX_CO_ROUTINE_PRIORITIES         ( 2 )                   //协程的有效优先级数目/***************************************************************************************************************/
/*                                FreeRTOS与软件定时器有关的配置选项                                            */
/***************************************************************************************************************/
#define configUSE_TIMERS                        1                               //为1时启用软件定时器
#define configTIMER_TASK_PRIORITY               (configMAX_PRIORITIES-1)        //软件定时器优先级
#define configTIMER_QUEUE_LENGTH                5                               //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH            (configMINIMAL_STACK_SIZE*2)    //软件定时器任务堆栈大小/***************************************************************************************************************/
/*                                FreeRTOS可选函数配置选项                                                      */
/***************************************************************************************************************/
#define INCLUDE_xTaskGetSchedulerState          1
#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
#define INCLUDE_eTaskGetState                   1
#define INCLUDE_xTimerPendFunctionCall          1/***************************************************************************************************************/
/*                                FreeRTOS与中断有关的配置选项                                                  */
/***************************************************************************************************************/
#ifdef __NVIC_PRIO_BITS#define configPRIO_BITS         __NVIC_PRIO_BITS
#else#define configPRIO_BITS         4
#endif#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         15                      //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5                       //系统可管理的最高中断优先级
#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )/***************************************************************************************************************/
/*                                FreeRTOS与中断服务函数有关的配置选项                                          */
/***************************************************************************************************************/
#define xPortPendSVHandler  PendSV_Handler
#define vPortSVCHandler     SVC_Handler#endif /* FREERTOS_CONFIG_H */

3. 修改中断相关文件

hem_it.c,修改代码如下。

#include "FreeRTOS.h"
#include "task.h"void SysTick_Handler(void)
{if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行{xPortSysTickHandler();}
}

4. 添加应用程序

freertos_demo.c内容:

/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"#include "freertos_demo.h"/******************************************************************************************************/
/*FreeRTOS配置*//* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 *//* TASK0 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK0_PRIO      2                   /* 任务优先级 */
#define TASK0_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task0Task_Handler;  /* 任务句柄 */
void task0(void *pvParameters);             /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO      3                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 *//* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO      4                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 *//******************************************************************************************************//*** @brief       FreeRTOS例程入口函数* @param       无* @retval      无*/
void freertos_demo(void)
{    xTaskCreate((TaskFunction_t )start_task,            /* 任务函数 */(const char*    )"start_task",          /* 任务名称 */(uint16_t       )START_STK_SIZE,        /* 任务堆栈大小 */(void*          )NULL,                  /* 传入给任务函数的参数 */(UBaseType_t    )START_TASK_PRIO,       /* 任务优先级 */(TaskHandle_t*  )&StartTask_Handler);   /* 任务句柄 */vTaskStartScheduler();
}/*** @brief       start_task* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           /* 进入临界区 *//* 创建任务0 */xTaskCreate((TaskFunction_t )task0,(const char*    )"task0",(uint16_t       )TASK0_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK0_PRIO,(TaskHandle_t*  )&Task0Task_Handler);/* 创建任务1 */xTaskCreate((TaskFunction_t )task1,(const char*    )"task1",(uint16_t       )TASK1_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK1_PRIO,(TaskHandle_t*  )&Task1Task_Handler);/* 创建任务2 */xTaskCreate((TaskFunction_t )task2,(const char*    )"task2",(uint16_t       )TASK2_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK2_PRIO,(TaskHandle_t*  )&Task2Task_Handler);vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区 */
}/*** @brief       task0* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task0(void *pvParameters)
{    while(1){printf("Welcome to use HME H7 series FPGA chips! task0\r\n");HME_GPIO_Toggle(DEMO_GPIO, GPIO_PIN0);vTaskDelay(1000);                                               /* 延时1000ticks */}
}/*** @brief       task1* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task1(void *pvParameters)
{while(1){printf("Welcome to use HME H7 series FPGA chips! task1\r\n");HME_GPIO_Toggle(DEMO_GPIO, GPIO_PIN1);vTaskDelay(800);                           /* 延时800ticks */}
}/*** @brief       task2* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task2(void *pvParameters)
{while(1){printf("Welcome to use HME H7 series FPGA chips! task2\r\n");vTaskDelay(600);                           /* 延时600ticks */}
}

测试说明:通过task0、task1、task2三个任务分别实现打印的功能,同时task0、task1中有灯翻转,且task0频率小于task1的频率。

main.c内容:

#include <stdio.h>
#include <string.h>
#include "hme_includes.h"
#include "hme_retarget.h"
#include "freertos_demo.h"
#include "flash_operation.h"uint32_t HAL_Phase0(void)
{/*Initialize necessary debugging functions*/HME_UART_InitTypeDef init;HME_UART_StructInit(&init);HME_UART_Init(DEMO_UART, &init);/*Enable Interrupt Vector */NVIC_EnableIRQ(DEMO_UART_IRQn);/*Enable Reception Function*/HME_UART_ITConfig(DEMO_UART, UART_Int_Received_Data_Available, true);HME_GPIO_InitTypeDef GPIO_Init;HME_GPIO_DeInit(DEMO_GPIO);GPIO_Init.Mode = PIN_MODE_OUTPUT;GPIO_Init.Pins = GPIO_PIN0 | GPIO_PIN1;HME_GPIO_Init(DEMO_GPIO, &GPIO_Init);return RET_OK;
}int main(void)
{uint32_t ret = RET_OK;ret = HAL_Phase0();if (ret != RET_OK) {printf("Phase0 has failed!\r\n");return ret;}printf("Welcome to use HME H7 series FPGA chips!\r\n");;ret = SpiFlash_InitAddrSpace(DEMO_SPI, FLASH_ADDR_OFFSET);if (ret != RET_OK) {printf("SpiFlash_InitAddrSpace has failed!\r\n");return ret;}SpiFlash_WriteData(DEMO_SPI, FLASH_ADDR_OFFSET);freertos_demo();while (1) {};
}

4. 问题记录

4.1 RAM空间不够

编译提示如下:

.\Objects\HME_MCU.axf: Error: L6406E: No space in execution regions with .ANY selector matching xxx.o(.bss).

由于移植FreeRTOS的代码,因此需要扩展RAM。

解决方法,如下图:

4.2 任务卡死现象

通过debug发现是vTaskDelay卡死,目前发现有两种原因导致。

1. 未适配hem_it.c中的SysTick_Handler,或者适配有问题;

解决方法:按照以上的介绍适配。

2. 任务的堆栈空间不足。

解决方法:扩展堆栈的空间

关于如何估算任务占用的堆栈空间,待......

http://www.dtcms.com/a/532031.html

相关文章:

  • BELLE中的表1
  • go-ethereum core之交易索引txIndexer
  • 描述对于营销型网站建设很重要飘红效果更佳信阳做网站 汉狮网络
  • 油猴脚本学习1——元数据头部
  • mysql 如何让事件执行
  • PantherX2 debain/armbian Jellyfin10.10.7升级10.11启动后无法监听端口8096的解决办法
  • 网站建设利弊中山币做网站公司
  • Kaleidoscope for mac 文件对比工具
  • LeetCode 1901.寻找峰值2
  • 沈阳建设网站费用北京网站优化软件
  • 【Android】【底层原理】深入解析SELinux模块
  • 阮一峰《TypeScript 教程》学习笔记——注释指令
  • 最好的开发网站建设价格app免费制作平台下载
  • 供应链进销存源码uniapp全开源ERP多仓库管理系统pc+app手机端
  • 生物化学Learning Track(15)酶活性的调节
  • 站酷设计网站官网入口下载国外手机设计网站
  • Rust 泛型与特性
  • GPT-1 技术报告
  • 中英双语 网站 模板wordpress返佣
  • 机器学习库的决策树绘制
  • k8s的calico出现ipset报错解决方法
  • SimpleDateFormat
  • 网站后期的维护和更新池州网站建设推广
  • 低空经济的实时神经系统:空地一体化音视频架构的技术演进
  • 更换MacbookAir固态硬盘,并用U盘安装MacOS操作系统
  • 创建一个简单的SpringBoot
  • 硅基计划2.0 学习总结 玖 图书管理系统 2.0复盘版(文字末尾源码可复制)
  • 河北省建设信息网站十种营销方法
  • qt调用摄像头进行yolo的实时检测
  • 网站备案通过什么可以备案wordpress熊掌号插件