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

FreeRTOS学习笔记——移植说明、任务创建

由于静态创建使用不多,先学习动态创建。
使用的开发板为WCH的CH32V307开发板,其提供的工程中存在FreeRTOS工程,已经移植好。

一、移植源码

FreeRTOS移植已经有很多教程,这里仅说明移植关键点。

  1. 从官网下载源码之后,创建的FreeRTOS文件夹中,包含以下几个文件和文件夹。其中include和.c文件,为rtos基本的功能,一般无需修改。
    在这里插入图片描述
  2. portable包含如下三个文件夹,是删掉其他文件夹留下的。
    Common和MemMang是通用的,一般不需要修改,MenMang中仅包含heap_4.c文件。
    GCC文件夹则是编译方式决定的,里面有一个RISC-V文件夹。如果是Keil开发,应该留下Keil文件夹。
    在这里插入图片描述
  3. 除了上述三个,额外的还需要移植FreeRTOSConfig.h,复制到user文件夹即可。

二、补充和修改必要函数

  1. 周期中断切换任务:对于FreeRTOS,其任务切换在周期中断中完成。在CH32工程中,代码在port.c中,如下,完成portYIELD(); // 任务切换即可。
    在这里插入图片描述
  2. 对于系统时钟,需要初始化,按照FreeRTOSConfig.h中的configTICK_RATE_HZ进行周期中断。初始化并没有在main中明示,而是在vTaskStartScheduler();中,进行初始化。如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  3. 其他包含中断相关的代码,如下,同样放在port.c的最下面。
/*-----------------------------------------------------------*/
void vPortEnterCritical(void)
{portDISABLE_INTERRUPTS();  // 禁用中断uxCriticalNesting++;  // 临界区嵌套计数增加
}/*-----------------------------------------------------------*/
void vPortExitCritical(void)
{configASSERT(uxCriticalNesting);  // 断言临界区嵌套计数大于0uxCriticalNesting--;  // 临界区嵌套计数减少if (uxCriticalNesting == 0){portENABLE_INTERRUPTS();  // 恢复中断}
}/*-----------------------------------------------------------*/
portUBASE_TYPE xPortSetInterruptMask(void)
{portUBASE_TYPE uvalue=0;__asm volatile("csrrw %0, mstatus, %1":"=r"(uvalue):"r"(0x7800));return uvalue;
}/*-----------------------------------------------------------*/
void vPortClearInterruptMask(portUBASE_TYPE uvalue)
{__asm volatile("csrw  mstatus, %0"::"r"(uvalue));
}
  1. 问题:发现中断中还包括了Software_IRQn,这是因为portYIELD()就是创建一个软件触发的中断,防止因阻塞 SysTick 定时器的中断而导致系统出错。
#define portYIELD()   NVIC_SetPendingIRQ(Software_IRQn)

三、config配置

直接参考下面的代码,按需要启用

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include "debug.h"/* don't have MTIME */
#define configMTIME_BASE_ADDRESS      ( 0 )    // MTIME寄存器的基地址,通常用于配置定时器(如果硬件平台没有此寄存器,值可设为0)
#define configMTIMECMP_BASE_ADDRESS   ( 0 )    // MTIMECMP寄存器的基地址,通常用于设置定时器的比较值(如果硬件平台没有此寄存器,值可设为0)#define configUSE_PREEMPTION            1       // 启用抢占式调度:1表示启用,0表示禁用
#define configUSE_IDLE_HOOK             0       // 是否使用空闲钩子函数:0表示不使用,1表示使用
#define configUSE_TICK_HOOK             0       // 是否使用Tick钩子函数:0表示不使用,1表示使用
#define configCPU_CLOCK_HZ              SystemCoreClock // CPU时钟频率,通常设置为系统时钟频率
#define configTICK_RATE_HZ              ( ( TickType_t ) 500 )  // 操作系统Tick中断的频率(500次/秒)
#define configMAX_PRIORITIES            ( 15 )  // 系统支持的最大优先级数(0表示最高优先级,最大为15)
#define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 256 )  // 每个任务的最小栈大小,单位为字节(通常根据任务的复杂度调整)
#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 12 * 1024 ) )    // 系统总堆内存大小,单位为字节
#define configMAX_TASK_NAME_LEN         ( 16 )  // 最大任务名长度,任务名最长可为16个字符
#define configUSE_TRACE_FACILITY        0       // 是否启用跟踪功能:0表示不启用,1表示启用
#define configUSE_16_BIT_TICKS          0       // 是否使用16位Tick计数:0表示不使用,1表示使用(通常设置为0)
#define configIDLE_SHOULD_YIELD         0       // 空闲任务是否应放弃CPU:0表示不放弃,1表示放弃(通常设置为0)
#define configUSE_MUTEXES               1       // 是否使用互斥量:0表示不使用,1表示使用
#define configQUEUE_REGISTRY_SIZE       8       // 队列注册表的大小,用于跟踪创建的队列数,默认为8
#define configCHECK_FOR_STACK_OVERFLOW  0       // 是否检查任务栈溢出:0表示不检查,1表示检查
#define configUSE_RECURSIVE_MUTEXES     1       // 是否支持递归互斥量:0表示不支持,1表示支持
#define configUSE_MALLOC_FAILED_HOOK    0       // 是否启用内存分配失败钩子函数:0表示不启用,1表示启用
#define configUSE_APPLICATION_TASK_TAG  0       // 是否为每个任务分配标签:0表示不分配,1表示分配
#define configUSE_COUNTING_SEMAPHORES   1       // 是否使用计数信号量:0表示不使用,1表示使用
#define configGENERATE_RUN_TIME_STATS   0       // 是否生成运行时间统计数据:0表示不生成,1表示生成
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0   // 是否使用优化的任务选择方式:0表示不优化,1表示优化/* Co-routine definitions. */
#define configUSE_CO_ROUTINES           0       // 是否启用协程:0表示不启用,1表示启用(协程适用于轻量级任务调度)
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )   // 最大协程优先级:设置协程的最大优先级数,通常为2或更低/* 软件定时器定义 */
#define configUSE_TIMERS                1       // 是否启用软件定时器:0表示不启用,1表示启用
#define configTIMER_TASK_PRIORITY       ( configMAX_PRIORITIES - 1 )    // 定时器任务的优先级,通常设置为最大优先级减1
#define configTIMER_QUEUE_LENGTH        4       // 定时器队列的长度,用于存储定时器任务(默认设置为4)
#define configTIMER_TASK_STACK_DEPTH    ( configMINIMAL_STACK_SIZE )    // 定时器任务的栈深度,通常设置为最小栈大小/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet            1       // 是否包含任务优先级设置函数vTaskPrioritySet:1表示包含,0表示不包含
#define INCLUDE_uxTaskPriorityGet           1       // 是否包含获取任务优先级函数uxTaskPriorityGet:1表示包含,0表示不包含
#define INCLUDE_vTaskDelete                 1       // 是否包含删除任务函数vTaskDelete:1表示包含,0表示不包含
#define INCLUDE_vTaskCleanUpResources       1       // 是否包含清理任务资源函数vTaskCleanUpResources:1表示包含,0表示不包含
#define INCLUDE_vTaskSuspend                1       // 是否包含挂起任务函数vTaskSuspend:1表示包含,0表示不包含
#define INCLUDE_vTaskDelayUntil             1       // 是否包含延迟直到某一时刻函数vTaskDelayUntil:1表示包含,0表示不包含
#define INCLUDE_vTaskDelay                  1       // 是否包含延迟任务函数vTaskDelay:1表示包含,0表示不包含
#define INCLUDE_eTaskGetState               1       // 是否包含获取任务状态函数eTaskGetState:1表示包含,0表示不包含
#define INCLUDE_xTimerPendFunctionCall      1       // 是否包含挂起定时器函数xTimerPendFunctionCall:1表示包含,0表示不包含
#define INCLUDE_xTaskAbortDelay             1       // 是否包含中止任务延迟函数xTaskAbortDelay:1表示包含,0表示不包含
#define INCLUDE_xTaskGetHandle              1       // 是否包含获取任务句柄函数xTaskGetHandle:1表示包含,0表示不包含
#define INCLUDE_xSemaphoreGetMutexHolder    1       // 是否包含获取互斥量持有者函数xSemaphoreGetMutexHolder:1表示包含,0表示不包含/* Normal assert() semantics without relying on the provision of an assert.h header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); printf("err at line %d of file \"%s\". \r\n ",__LINE__,__FILE__); while(1); }
// 断言宏:如果条件x为0,则禁用中断,并打印错误信息(包括出错的行号和文件名),然后进入死循环。
// 这种方式的断言实现不依赖于assert.h头文件,适用于FreeRTOS等嵌入式系统。/* Map to the platform printf function. */
#define configPRINT_STRING( pcString )  printf( pcString )
// 定义平台上的printf函数:将FreeRTOS中的打印函数映射到具体平台的printf函数。
// 该宏用于打印字符串(pcString),在嵌入式系统中通常会映射到系统的标准输出。#endif /* FREERTOS_CONFIG_H */

三、任务创建

  1. 任务创建因素:对于简单任务,需要的提前创建的包括 函数task1_task,优先级TASK1_TASK_PRIO,句柄Task1Task_Handler。对于TASK1_STK_SIZE,可以默认为256等基本的,不用多考虑。
xTaskCreate((TaskFunction_t )task1_task,(const char*    )"task1",(uint16_t       )TASK1_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK1_TASK_PRIO,(TaskHandle_t*  )&Task1Task_Handler);
  1. 任务的可通过挂起、恢复、删除方式对任务的运行进行操作。例如如下按键任务,操作led开关任务的挂起和恢复
void taskkey_task()
{uint8_t tres = 1;static uint8_t mode = 0;while(1){if(0 == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)){taskENTER_CRITICAL();vTaskDelay(10);if(0 == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)){if(0==mode){mode = 1;vTaskSuspend(Task1Task_Handler);printf("Task1 suspend\r\n");}else {mode = 0;vTaskResume(Task1Task_Handler);printf("Task1 resume\r\n");}}while(0==GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)){vTaskDelay(20);}taskEXIT_CRITICAL();}vTaskDelay(20);}
}

文章转载自:
http://cerulean.hdqtgc.cn
http://bubalis.hdqtgc.cn
http://cerotic.hdqtgc.cn
http://autoptic.hdqtgc.cn
http://brainfag.hdqtgc.cn
http://amuck.hdqtgc.cn
http://alcor.hdqtgc.cn
http://antiphonal.hdqtgc.cn
http://affectivity.hdqtgc.cn
http://capsulary.hdqtgc.cn
http://biocytinase.hdqtgc.cn
http://cella.hdqtgc.cn
http://assafetida.hdqtgc.cn
http://adenoacanthoma.hdqtgc.cn
http://bulbar.hdqtgc.cn
http://bfc.hdqtgc.cn
http://advertizer.hdqtgc.cn
http://avn.hdqtgc.cn
http://acapulco.hdqtgc.cn
http://brainstorm.hdqtgc.cn
http://catheter.hdqtgc.cn
http://chemist.hdqtgc.cn
http://antiallergenic.hdqtgc.cn
http://acranial.hdqtgc.cn
http://babiroussa.hdqtgc.cn
http://adz.hdqtgc.cn
http://burnt.hdqtgc.cn
http://biter.hdqtgc.cn
http://aplanatic.hdqtgc.cn
http://cathodal.hdqtgc.cn
http://www.dtcms.com/a/280679.html

相关文章:

  • 【Ubuntu22.04】repo安装方法
  • Linux715 磁盘管理:逻辑卷
  • 聊聊MySQL中的buffer pool
  • Spring Boot目录变文件夹?3步解决!
  • Unity Editor下拉框,支持搜索,多层级
  • BGP服务器和多线服务器的不同之处
  • Python初学者笔记第十三期 -- (常用内置函数)
  • 原点安全签约金网络数科,共建一体化数据安全防护体系
  • Docker 镜像(Image)常用命令总结
  • ASP .NET Core 8结合JWT轻松实现身份验证和授权
  • CMake基础:覆盖项目开发的五大配套工具
  • LLM面试题及讲解 4
  • VSCode同时支持Vue2和Vue3开发的插件指南
  • 【编程】-环形缓冲区
  • 安全参綉25暑假第一次作业
  • 超详细 anji-captcha滑块验证uniapp微信小程序前端组件
  • 备忘录设计模式
  • asyncio 与 uvloop
  • 策略设计模式分析
  • 如何将华为文件传输到电脑
  • Linux的用户和用户组与权限解析、环境变量说明与配置、sudo配置解析和使用
  • HarmonyOS从入门到精通:自定义组件开发指南(七):自定义事件与回调
  • 涨停板池,跌停板池,炸板池,次新股池,强势股池数据接口
  • 单臂路由实现VLAN互通实验
  • e签宝电子合同成为白象食品数字化转型中的关键一环
  • PostgreSQL 超详细安装与使用教程:从入门到实战
  • 深入剖析 React Server Components:原理、应用与性能优势
  • 设计模式一: 模板方法模式 (Template Method Pattern)
  • Nexus 私服管理工具
  • 李宏毅《生成式人工智能导论》 | 第11讲-第14讲:大型语言模型的可解释性、能力评估、安全性