• AIR32F103(五) FreeRTOSv202112核心库的集成和示例代码


    目录

    关于

    先贴一下已经集成好的项目地址, 如果对如何集成不感兴趣, 想直接使用的, 可以跳过这部分, 直接看使用部分

    AIR32F103CBT6的存储是128K Flash + 32K RAM, CCT6是256K Flash + 64K RAM, 大容量加上206MHz的工作频率, 跑FreeRTOS是非常合适的. 关于FreeRTOS的介绍和集成, 网络上已经有不少文章, 可以直接百度搜索查看, 这里主要介绍一下项目中的FreeRTOS集成步骤和代码说明.

    集成步骤

    添加 FreeRTOS 核心库文件

    参考之前的文章 STM32F10x SPL 集成 FreeRTOS, 因为 AIR32F103 和 STM32 基本上是兼容的, 低位的中断定义一样, 直接套用就可以.

    https://www.freertos.org/下载 FreeRTOS 202112.00 , 解开后到 FreeRTOS/Source 目录下, 复制以下的文件到项目目录下

    • FreeRTOS/Source/include 整个目录, 这些是头文件
    • FreeRTOS/Source 下的所有C文件
    • FreeRTOS/Source/portable/GCC/ARM_CM3 目录, 这是针对 STM32F103 的适配文件
    • FreeRTOS/Source/portable/MemMang 目录, 里面包含一些现成的内存管理实现

    只需要保留这些文件

    FreeRTOS
    ├── include
    │   ├── atomic.h
    │   ├── croutine.h
    │   ├── deprecated_definitions.h
    │   ├── event_groups.h
    │   ├── FreeRTOS.h
    │   ├── list.h
    │   ├── message_buffer.h
    │   ├── mpu_prototypes.h
    │   ├── mpu_wrappers.h
    │   ├── portable.h
    │   ├── projdefs.h
    │   ├── queue.h
    │   ├── semphr.h
    │   ├── stack_macros.h
    │   ├── StackMacros.h
    │   ├── stdint.readme
    │   ├── stream_buffer.h
    │   ├── task.h
    │   └── timers.h
    ├── portable
    │   ├── GCC
    │   │   └── ARM_CM3
    │   │       ├── port.c
    │   │       └── portmacro.h
    │   └── MemMang
    │       ├── heap_1.c
    │       ├── heap_2.c
    │       ├── heap_3.c
    │       ├── heap_4.c
    │       └── heap_5.c
    ├── croutine.c
    ├── event_groups.c
    ├── list.c
    ├── queue.c
    ├── stream_buffer.c
    ├── tasks.c
    └── timers.c
    

    然后准备 FreeRTOSConfig.h

    编辑 FreeRTOSConfig.h

    下面是一个完整的例子, 说明写到了注释里, 可以删掉

    #ifndef FREERTOS_CONFIG_H
    #define FREERTOS_CONFIG_H
    
    // [重要]开启抢占模式, 大部分组件会默认FreeRTOS是开启抢占模式的, 否则不能保障其实时性
    #define configUSE_PREEMPTION		1
    /* 不使用 idle task hook. RTOS的调度器在启动时会自动创建一个idle task, 这样保证在没有任务执行时也会运行一个任务, 这个任务会运行在最低的优先级. An idle task hook is a function that is called during each cycle of the idle task. 如果自定义了 idle task 方法, 就将其设为1.
    */
    #define configUSE_IDLE_HOOK			0
    // 不使用 tick hook. 和 idle task hook 一样, 就是tick中断时可以定义一个callback方法.
    #define configUSE_TICK_HOOK			0
    // [重要]定义主频, 别定义错, 会导致延时和定时器计算有偏差, 如果设置了216MHz或者256MHz, 这里需要修改
    #define configCPU_CLOCK_HZ			( ( unsigned long ) 72000000 )	
    // [重要]定义Tick的频率(每秒多少个tick), 和主频和SysTick的定义要结合看, 一般用1000(1毫秒), 或者100(10毫秒)
    #define configTICK_RATE_HZ			( ( TickType_t ) 1000 )
    // [重要]task中可以用的优先级个数
    #define configMAX_PRIORITIES		( 5 )
    // [重要]任务的最小堆栈尺寸, 如果stack是32位, 就是4byte, 128就是128*4=512 byte
    #define configMINIMAL_STACK_SIZE	( ( unsigned short ) 128 )
    // [重要]堆的尺寸, 根据自己的MCU RAM容量调整
    #define configTOTAL_HEAP_SIZE		( ( size_t ) ( 17 * 1024 ) )
    // 任务名长度限制
    #define configMAX_TASK_NAME_LEN		( 16 )
    // 用于需要包含额外的变量和函数结构用于协助跟踪和可视化, 不使用就设为0
    #define configUSE_TRACE_FACILITY	0
    // Tick使用16位计数值, 针对8位和16位的核使用的. 对M0 M3这种32位的不需要
    #define configUSE_16_BIT_TICKS		0
    // 开启低功耗的空闲模式, 0则永远打开tick中断. 这个配置要和 configUSE_TICKLESS_IDLE 结合看
    #define configIDLE_SHOULD_YIELD		1
    // 用于设置是否允许低优先级任务使用taskENTER_CRITICAL(), 设为0可以提高安全性, 不定义会报warning
    #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 0
    
    // 协程基本用不上, 按默认即可
    /* Co-routine definitions. */
    #define configUSE_CO_ROUTINES 		0
    #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
    
    /* Set the following definitions to 1 to include the API function, or zero
    to exclude the API function. */
    
    // 这些是属于功能裁剪的部分, 如果你使用了某些功能, 就要加上, 没用到的可以设为0或者不定义
    #define INCLUDE_vTaskPrioritySet		1
    #define INCLUDE_uxTaskPriorityGet		1
    #define INCLUDE_vTaskDelete				1
    #define INCLUDE_vTaskCleanUpResources	0
    #define INCLUDE_vTaskSuspend			1
    #define INCLUDE_vTaskDelayUntil			1
    #define INCLUDE_vTaskDelay				1
    
    /* 
    对于Cortex-M3核最低的中断优先级
    This is the raw value as per the Cortex-M3 NVIC.  Values can be 255
    (lowest) to 0 (1?) (highest). */
    #define configKERNEL_INTERRUPT_PRIORITY 		255
    /* 
    在新的移植中, configMAX_SYSCALL_INTERRUPT_PRIORITY改名为configMAX_API_CALL_INTERRUPT_PRIORITY, 这两个是等价的. 这个值代表了最高的, 可以安全调用 FreeRTOS API 的中断优先级. 如果一个中断的优先级比这个高, 那么 FreeRTOS 是无法屏蔽这个中断的, 哪怕在 critical section 内部, 也会被这个中断打断.
    !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
    See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
    #define configMAX_SYSCALL_INTERRUPT_PRIORITY 	191 /* equivalent to 0xb0, or priority 11. */
    
    /* 
    将 FreeRTOS 中的关键中断处理函数设置为宏, 避免修改startup文件
    Use MACRO to replace the handlers without changing startup file */
    #define vPortSVCHandler     SVC_Handler
    #define xPortPendSVHandler  PendSV_Handler
    #define xPortSysTickHandler SysTick_Handler
    

    在项目中使用 FreeRTOS

    开启 FreeRTOS 支持

    在项目中启用 FreeRTOS 支持, 只需要编辑 Makefile, 将 USE_FREERTOS ?= n 配置修改为 USE_FREERTOS ?= y

    # Build with FreeRTOS, y:yes, n:no
    USE_FREERTOS	?= y
    

    默认使用的内存管理方式是heap_4.c, 如果希望换成其它的内存管理方式, 可以修改这一行

    CFILES		+= Libraries/FreeRTOS/portable/MemMang/heap_4.c
    

    执行示例代码

    项目中已经针对AIR32F103准备了一些FreeRTOS的代码示例, 根据FreeRTOS的功能, 分别提供了以下示例的集合

    ├── Mem
    │   └── Malloc_And_Free             # 内存申请和释放
    ├── Queue
    │   ├── Queue_And_Notification      # 队列和定时器中断触发的通知
    │   ├── Queue_And_Notification_DMA  # 和上面一样, 但是换成了DMA中断
    │   └── Queue_Send_And_Receive      # 队列的接收和发送
    ├── Semaphore
    │   ├── Binary_Semaphore            # 单值信号量
    │   ├── Counting_Semaphore          # 计数信号量
    │   └── Mutex                       # 锁
    ├── Tasks
    │   ├── Blink                       # 多任务闪灯
    │   ├── Blink_Controlled_By_UART    # 用一个任务读取UART控制另一个任务的闪灯频率
    │   ├── DelayUntil                  # 带提前量的延迟
    │   └── Task_Notification           # 任务间的等待和通知
    └── Timers
        └── TimerCallback               # 软件定时器
    

    修改 Makefile 启用 FreeRTOS 支持后, 可以将示例代码复制到 User 目录下编译烧录.

    针对合宙AIR32F103CBT6开发板的闪灯示例代码位于 Examples/FreeRTOS/Tasks/Blink 目录, 这个示例会创建三个任务, 按不同的周期控制板载的三个LED的亮灭. 编译和烧录的步骤参考 AIR32F103(三) Linux环境基于标准外设库的项目模板

    更多阅读

  • 相关阅读:
    jichu
    scanf
    数位dp
    hdu 5667
    华东交通大学2018年ACM“双基”程序设计竞赛 K
    华东交通大学2018年ACM“双基”程序设计竞赛 D
    map
    次小生成树
    set
    c++11之为什么C++11引入了std::ref?
  • 原文地址:https://www.cnblogs.com/milton/p/16881082.html
Copyright © 2020-2023  润新知