HC32L021C8UB 移植 FreeRTOS

目录文件裁剪

源文件

FreeRTOS项目必须至少包含以下源文件([compiler] 和 [architecture] 分别是用于创建移植的编译器和移植运行的架构):

  • FreeRTOS/Source/tasks.c
  • FreeRTOS/Source/queue.c
  • FreeRTOS/Source/list.c
  • FreeRTOS/Source/portable/[compiler]/[architecture]/port.c
  • FreeRTOS/Source/portable/MemMang/heap_x.c 其中 "x" 可以是 1、2、3、4 或 5。

如果包含 port.c 文件的目录也包含程序集语言文件,那么也必须使用程序集语言文件。

可选源文件
  • 如果需要软件定时器功能,请在项目中添加 FreeRTOS/Source/timers.c。
  • 如果需要事件组功能,请在项目中添加 FreeRTOS/Source/event_groups.c。
  • 如果需要流缓冲区或消息缓冲区功能,请在项目中添加 FreeRTOS/Source/stream_buffer.c。
  • 如果需要协程功能,请在项目中添加 FreeRTOS/Source/croutine.c(请注意,协程已弃用, 不推荐用于新设计)。
头文件

以下目录必须位于编译器的 include 路径中(必须告知编译器在这些目录中搜索 头文件):

  • FreeRTOS/Source/include
  • FreeRTOS/Source/portable/[compiler]/[architecture]。
  • 无论哪个目录包含要使用的 FreeRTOSConfig.h 文件,请参阅下文"配置文件"段落。

根据移植的不同,也可能需要将相同的目录放在汇编器的 include 路径中。

配置文件

每个项目还需要一个名为 FreeRTOSConfig.h 的文件。 FreeRTOSConfig.h 它为正在构建的应用程序量身定制 RTOS 内核。因此,它是取决于 应用程序的,而不是 RTOS,并且应位于应用程序目录中, 而不是 RTOS 内核源代码目录中。

如果您的项目包含 heap_1、heap_2、heap_4 或 heap_5,则 FreeRTOSConfig.h 的 configTOTAL_HEAP_SIZE 定义将决定 FreeRTOS 堆的大小。如果 configTOTAL_HEAP_SIZE 设置得太高,则您的应用程序将无法建立连接。

FreeRTOSConfig.h 中的 configMINIMAL_STACK_SIZE 定义 设定了闲置任务使用的堆栈大小。如果 configMINIMAL_STACK_SIZE 设置得太低, 则空闲任务将造成栈溢出。建议您找到 使用相同微控制架构的 FreeRTOS 官方演示, 复制其中的 configMINIMAL_STACK_SIZE 设置。FreeRTOS 演示 项目存储在 FreeRTOS/Demo 目录的子目录中。 请注意,一些演示项目的时间距离现在比较久,因此不包含所有可用的 配置选项。

开始裁剪移植
  1. 把FreeRTOS配置模板FreeRTOS-Kernel\examples\template_configuration\FreeRTOSConfig.h拷贝到FreeRTOS-Kernel\include下。

  2. 保留选中的文件和文件夹其他的都没用删掉。

  3. 使用FreeRTOS-Kernel\portable\GCC\ARM_CM0替换FreeRTOS-Kernel\portable\RVDS\ARM_CM0 然后保留选中的文件夹其他删掉。

  4. FreeRTOS-Kernel\portable目录下保留刚才替换的文件夹其他删掉。
    '

工程添加

工程是直接使用HC模板,直接在模板上添加。

  • heap_1------ 最简单,不允许释放内存。
  • heap_2------ 允许释放内存,但不会合并相邻的空闲块。
  • heap_3------ 简单包装了标准 malloc() 和 free(),以保证线程安全。
  • heap_4------ 合并相邻的空闲块以避免碎片化。包含绝对地址放置选项。
  • heap_5------ 如同 heap_4,能够跨越多个不相邻内存区域的堆。

注意:

  • heap_1 不太有用,因为 FreeRTOS 添加了静态分配支持。
  • heap_2 现在被视为旧版,因为较新的 heap_4 实现是首选。

详细请点击查看FreeRTOS 堆内存管理

FreeRTOSConfig.h

复制代码
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/* *************************************************************************
 *                          1. 系统基础配置
 * ************************************************************************/
/* 芯片内核时钟频率 - HC32L021 主频配置为 48MHz */
#define configCPU_CLOCK_HZ              ( ( unsigned long ) 48000000 )
/* 系统时钟节拍频率 (1000Hz = 1ms中断一次),是RTOS的时间基准 */
#define configTICK_RATE_HZ              1000 
/* 最大任务优先级数,数字越大优先级越高 (Cortex-M0+推荐5~8级) */
#define configMAX_PRIORITIES            5
/* 空闲任务最小堆栈大小 (单位:字,1字=4字节),M0+小资源芯片精简配置 */
#define configMINIMAL_STACK_SIZE        64 
/* 任务名称最大字符串长度,精简内核可减小内存占用 */
#define configMAX_TASK_NAME_LEN         8
/* 系统节拍计数器位数,32位适合长时间运行,无溢出风险 */
#define configTICK_TYPE_WIDTH_IN_BITS   TICK_TYPE_WIDTH_32_BITS
/* 空闲任务是否主动让出CPU:1=开启,提高其他同优先级任务响应速度 */
#define configIDLE_SHOULD_YIELD         1

/* *************************************************************************
 *                          2. 调度器配置
 * ************************************************************************/
/* 1=抢占式调度(高优先级任务打断低优先级),0=协作式调度,FreeRTOS默认开启 */
#define configUSE_PREEMPTION            1
/* 时间片调度:0=关闭,同优先级任务不会轮流执行,适合小资源MCU */
#define configUSE_TIME_SLICING          0
/* 优化任务选择算法:Cortex-M0+不支持硬件优化,必须关闭 */
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
/* 低功耗tickless模式:0=关闭,适合普通应用;低功耗项目可开启 */
#define configUSE_TICKLESS_IDLE         0

/* *************************************************************************
 *                          3. 内存管理配置
 * ************************************************************************/
/* 静态内存分配:0=关闭,不使用静态创建任务/队列,简化开发 */
#define configSUPPORT_STATIC_ALLOCATION   0
/* 动态内存分配:1=开启,使用FreeRTOS内存堆创建任务/队列,推荐新手使用 */
#define configSUPPORT_DYNAMIC_ALLOCATION  1
/* 动态内存堆总大小 (单位:字节),HC32L021小RAM,精简配置1.5KB */
#define configTOTAL_HEAP_SIZE             1536
/* 用户自定义内存堆:0=关闭,使用FreeRTOS自带内存管理 */
#define configAPPLICATION_ALLOCATED_HEAP  0

/* *************************************************************************
 *                          4. 中断优先级配置 (Cortex-M0+核心)
 * ************************************************************************/
/* 内核中断优先级 (PendSV/SysTick),设为最低优先级0,不影响业务中断 */
#define configKERNEL_INTERRUPT_PRIORITY          0
/* 系统调用最高中断优先级,Cortex-M0+仅支持4级优先级,0=最低 */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     0
/* API调用最高中断优先级,同上述配置,保持一致避免异常 */
#define configMAX_API_CALL_INTERRUPT_PRIORITY    0

/* *************************************************************************
 *                          5. 钩子函数(回调函数)配置
 * ************************************************************************/
/* 空闲任务钩子:0=关闭,空闲时执行自定义函数,用于低功耗 */
#define configUSE_IDLE_HOOK                   0
/* 时钟节拍钩子:1=开启,每1ms执行一次自定义函数 */
#define configUSE_TICK_HOOK                   1
/* 内存分配失败钩子:1=开启,内存不足时触发,方便调试 */
#define configUSE_MALLOC_FAILED_HOOK          1
/* 堆栈溢出检测:1=开启,任务堆栈溢出时触发,调试必备 */
#define configCHECK_FOR_STACK_OVERFLOW        1

/* *************************************************************************
 *                          6. 内核可选功能裁剪
 * ************************************************************************/
/* 软件定时器:0=关闭,小资源MCU无需使用 */
#define configUSE_TIMERS                0
/* 事件组:0=关闭,精简内核 */
#define configUSE_EVENT_GROUPS          0
/* 流缓冲区:0=关闭,串口/大量数据传输才使用 */
#define configUSE_STREAM_BUFFERS        0
/* 协程:0=关闭,FreeRTOS废弃功能 */
#define configUSE_CO_ROUTINES           0

/* *************************************************************************
 *                          7. 硬件外设适配 (HC32L021专用)
 * ************************************************************************/
/* MPU内存保护单元:0=关闭,HC32L021无MPU硬件,必须关闭! */
#define configENABLE_MPU                 0
/* MPU包装函数:0=关闭,无MPU无需使用 */
#define configUSE_MPU_WRAPPERS_V1        0
/* FPU浮点单元:0=关闭,Cortex-M0+无硬件浮点 */
#define configENABLE_FPU                 0
/* TrustZone安全扩展:0=关闭,普通MCU无此功能 */
#define configENABLE_TRUSTZONE           0
/* 仅安全模式运行:0=关闭,无TrustZone无需配置 */
#define configRUN_FREERTOS_SECURE_ONLY   0
/* MVE向量扩展:0=关闭,芯片不支持 */
#define configENABLE_MVE                 0
/* 中断处理安装检查:0=关闭,适配GCC端口,解决链接报错 */
#define configCHECK_HANDLER_INSTALLATION 0

/* *************************************************************************
 *                          8. 任务通信/同步功能
 * ************************************************************************/
/* 任务通知:1=开启,轻量级任务同步,替代信号量/队列 */
#define configUSE_TASK_NOTIFICATIONS       1
/* 互斥锁:1=开启,解决多任务资源竞争 */
#define configUSE_MUTEXES                  1
/* 递归互斥锁:0=关闭,精简内核 */
#define configUSE_RECURSIVE_MUTEXES        0
/* 计数信号量:1=开启,用于资源计数、同步 */
#define configUSE_COUNTING_SEMAPHORES      1
/* 队列集:0=关闭,精简内核 */
#define configUSE_QUEUE_SETS               0

/* *************************************************************************
 *                          9. 断言函数(调试专用)
 * ************************************************************************/
/* 断言宏:参数不成立时,关闭中断并死循环,快速定位程序BUG */
#define configASSERT( x )         \
    if( ( x ) == 0 )              \
    {                             \
        taskDISABLE_INTERRUPTS(); \
        for( ; ; )                \
        ;                         \
    }

/* *************************************************************************
 *                          10. 可选API函数使能
 * ************************************************************************/
#define INCLUDE_vTaskPrioritySet               1  /* 启用 设置任务优先级 API */
#define INCLUDE_uxTaskPriorityGet              1  /* 启用 获取任务优先级 API */
#define INCLUDE_vTaskDelete                    1  /* 启用 删除任务 API */
#define INCLUDE_vTaskSuspend                   1  /* 启用 挂起任务 API */
#define INCLUDE_xResumeFromISR                 1  /* 启用 中断中恢复任务 API */
#define INCLUDE_vTaskDelayUntil                1  /* 启用 绝对延时 API */
#define INCLUDE_vTaskDelay                     1  /* 启用 相对延时 API */
#define INCLUDE_xTaskGetSchedulerState         0  /* 关闭 获取调度器状态 API */
#define INCLUDE_xTaskGetCurrentTaskHandle      0  /* 关闭 获取当前任务句柄 API */

#endif /* FREERTOS_CONFIG_H */

R_ARM_THM_JUMP11 编译报错

这里报错的意思是汇编里的跳转指令,能跳的最大距离只有 ±1KB,但要跳的目标函数(vPortSVCHandler_C)在 0xA24 这个位置,超出了芯片允许的跳转范围,硬件做不到,直接报错!

HC32L021 = Cortex-M0+ 内核只支持最简指令集(Thumb-1),普通跳转指令 b 只能跳 ±1024 字节(±1KB)还不支持长跳转指令 b.w。

解决方法是把函数地址放到寄存器里,再用 bx 跳转,想跳多远就跳多远。

c 复制代码
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
    {
        __asm volatile
        (
            " .syntax unified                \n"
            " .extern vPortSVCHandler_C      \n"
            "                                \n"
            " movs r0, #4                    \n"
            " mov r1, lr                     \n"
            " tst r0, r1                     \n"
            " beq stacking_used_msp          \n"
            "                                \n"
            " stacking_used_psp:             \n"
            "    mrs r0, psp                 \n"
            "    ldr r3, =vPortSVCHandler_C  \n"
            "    bx r3                       \n"
            "                                \n"
            " stacking_used_msp:             \n"
            "    mrs r0, msp                 \n"
            "    ldr r3, =vPortSVCHandler_C  \n"
            "    bx r3                       \n"
            "                                \n"
            " .align 4                       \n"
        );
    }

测试下

c 复制代码
void hello_Task(void *pvParameters)
{
    for(;;)
    {
		printf("hello task\r\n");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void led_Task(void *pvParameters)
{
    for(;;)
    {
		printf("led task\r\n");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

int32_t main(void)
{
	SysClockConfig();
    
    STK_LedConfig();
	GpioConfig();
	SpiConfig();
	SPI_Enable(SPI);
	UartGpioConfig();
    LpuartConfig();

    xTaskCreate(hello_Task,  "hello_Task",  configMINIMAL_STACK_SIZE, NULL, 1, NULL);
	xTaskCreate(led_Task,  "hello_Task",  configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    vTaskStartScheduler();

    while (1)
    {
        DDL_Delay1ms(500);
    }
}


优雅!

相关推荐
振南的单片机世界4 小时前
开漏输出:只能拉低,不能拉高,高电平靠“外部”帮忙
stm32·单片机·嵌入式硬件
黑白园7 小时前
STM32 通过I2C 读写EEPR0M AT24C02
stm32·单片机·嵌入式硬件
YJlio7 小时前
《Windows Internals》10.5.1 ETW 概述:看懂 Windows 的“事件高速公路”
java·windows·笔记·stm32·嵌入式硬件·学习·eclipse
YJlio8 小时前
Windows Internals 10.5.3:ETW 架构详解,从事件产生到性能分析的完整链路
windows·笔记·python·stm32·嵌入式硬件·学习·架构
SkyXZ~8 小时前
Mac上使用VScode优雅开发STM32
vscode·stm32·macos
bubiyoushang88817 小时前
STM32F103C8T6+DM9051以太网功能实现方案
stm32·单片机·嵌入式硬件
IT_阿水18 小时前
基于STM32河流水质检测
stm32·单片机·嵌入式硬件
黑白园18 小时前
STM32定时器中断
stm32·单片机·嵌入式硬件
振南的单片机世界20 小时前
时钟开关:不用的外设,把它的时钟关掉,省电!
stm32·单片机·嵌入式硬件