下载 FreeRTOS
 

出色的 RTOS & 嵌入式软件

内核
最新资讯
简化任何设备的身份验证云连接。
利用 CoAP 设计节能型云连接 IoT 解决方案。
11.0.0 版 FreeRTOS 内核简介:
FreeRTOS 路线图和代码贡献流程。
使用 FreeRTOS 实现 OPC-UA over TSN。

ST STM32H745 双核 AMP 演示
使用消息缓冲区进行核心间的通信
[RTOS 移植]


来自 ST 的 STM32H745I Discovery 板
STM32H745I Discovery 板


本页记载了简单的非对称多处理 (AMP) 核心间 通信演示, 该演示使用 FreeRTOS 消息缓冲区实现。 随附一篇另外的文章 详细描述一些内部实施细节。

演示已预配置为在 STM32H745I 上运行 Discovery 板上运行并使用 IAR 编译器和 Embedded Workbench IDE 进行构建。 STM32H7xx 有一个 ARM Cortex-M4 核心和一个 ARM Cortex-M7 核心。 两个核心运行同一 ARMv7-M FreeRTOS 移植。

Embedded Workbench 提供了高效且功能丰富的开发环境; 它随附一个具有充分线程感知能力的 FreeRTOS 内核插件, 允许同时调试两个 MCU 核心。


重要提示!使用FreeRTOS ARMv7-M (Cortex-M4 和 M7)移植的注意事项

使用此 RTOS 移植之前,请阅读以下所有要点。

  1. 源代码组织
  2. 演示应用程序功能
  3. 构建并运行 RTOS 演示应用程序
  4. 调试演示应用程序 - STLink
  5. 调试演示应用程序 - I-jet
  6. RTOS 配置和使用详情
另请参见常见问题:我的应用程序未运行,哪里出错了?

源代码组织

FreeRTOS zip 文件下载内容中包含所有 FreeRTOS 移植的源代码及 所有演示应用程序。 这意味着它包含的文件数量远多于 使用 FreeRTOS STM32H745I 双核 AMP 演示所需的文件。 请参阅 源代码组织页面,了解 了解 zip 文件的目录结构体信息。此演示的 IAR Embedded Workbench 工作区 位于 FreeRTOS/Demo/CORTEX_M7_M4_AMP_STM32H745I_Discovery_IAR 目录下。 工作区中的项目包含两个配置,一个用于 Cortex-M4 核心,另一个用于 Cortex-M7 核心。



STM32H745 双核演示应用程序

功能

消息缓冲区用于传递递增数字的 ASCII 表示(因此 “0” , 后面是 “1” ,再后面是 “2” 等等),即从单一'发送' RTOS 任务(或‘线程’) (在 Arm Cortex-M7 核心上运行)传递到两个“接收” RTOS 任务 (在 Arm Cortex-M4 核心上运行)。 字符串长度随位数个数的增加而变化。 数据信息缓冲区有两个, 每个缓冲区都对应一个接收任务。 为区分两个接收任务, 将一个任务的编号指定为 0 ,另一个任务的编号指定为 1。

AMP 多核配置中两个核心上的 rtos
硬件拓扑。 点击放大。


Cortex-M7 任务位于向每个 Cortex-M4 任务发送 ascii 字符串的循环中。 如果一个 接收任务在序列中接收到下一个预期值, 它会将其任务编号打印到 uART。 如果接收任务接收到其他任何东西,或者 其数据接收超时,那它会命中一个assert(), 在停止 Cortex-M4 上的所有后续处理之前向 UART 打印错误消息 。 以下伪代码片段分别演示了发送 任务和接收任务的结构体。

SendingTask()
{
    for ever
    {
        Generate the next string in the sequence

        /* The message buffers become full so a block time is used.
        on each send. */
        Send the generated string to the first message buffer
        Send the generated string to the second message buffer
    }
}
				
简化过的伪代码,显示发送任务结构体

ReceivingTask()
{
    for ever
    {
        Read next message from the message buffer

        /* Failed asserts print an error and stop execution. */
        configASSERT( Received message is next expected in sequence );
        Write task number (0 or 1) to the UART
    }
}
				
简化过的伪代码,显示接收任务结构体


当执行正确时, 分配到任务编号 0 的接收任务会在 UART 写入一串 “0”,每次接收 任务接收序列中的下一个预期消息时就会时写入一个 0。 同样的, 分配到任务编号 1 的接收任务 也会在 UART 写入一串 “1”。 演示 会尽可能快地运行,将字符输出到 UART 所需的时间是一大 限制因素。 由于 发送任务在 Cortex-M7 核心上运行, 且其运行速度是 Cortex-M4 核心速度的两倍,再加上发送任务不 受 UART 速度的限制,因此控制消息缓冲区(请参阅下文实现部分)会变满。


执行演示时的 UART 输出


实施细节

此演示附带的另一篇文章 提供了详细的解释。


构建并运行 RTOS 演示应用程序

重要提示: 如果目录结构体与 在官方 FreeRTOS zip 文件版本中使用的目录结构体不同,则不会构建项目。

构建和运行演示应用程序:

  1. 确保包含在 IAR Embedded Studio for ARM 安装文件中的零件数据库 包含 STM32H745。 在编写时, 您有必要手动下载 适用于 STM32H7 的 STM32Cube 程序包 以获取 IAR 安装文件的更新补丁。如果 您使用的是最新的 IAR 工具,则没有必要这么做。

  2. 演示通过 STM32H745I Discovery 板上的 USB 连接器 CN14 (标记为 STLink)输出 UART 数据。 使用 USB 数据线将 STM32H745I Discovery 板上的端口 CN14 连接至 主机(用于查看 UART 输出的计算机)并给 Discovery 板充电, 以使 USB(虚拟)COM 端口在主机上枚举 。 由 JP8 跳线组设置的电源选项有好几个。

  3. 使用主机上的 Teraterm 等哑串行终端, 连接到连接 Discovery 板时被枚举的那个 COM 端口, 并将端口设置为 115200 波特、8 数据位、1 停止位,没有奇偶校验位 。 查找 COM 端口号的一个简单方法 就是查看 STM32H745I Discovery 板充电和未充电时,哑终端分别提供了哪些端口号选项。

  4. 打开 FreeRTOS/Demo/CORTEX_M7_M4_AMP_STM32H745I_Discovery_IAR/Project.ew ——在 IAR Embedded Workspace IDE 中(或在 Embedded Workbench 中直接双击此文件打开它)。

  5. 使用工作区窗口顶部的下拉菜单选择 cortex-M4 核心的配置。


  6. 从 "Project" 菜单中选择 "Make" 以构建项目(或只需按下 F7 即可)。

  7. 右键单击工作区窗口中的项目,打开项目选项对话框,从弹出菜单中选择 "Options" 。


  8. 从选项对话框中的 "Debugger" 类别中选择调试接口 。 我使用内置的 STM32Link 和外部 I -Jet 进行测试。


  9. 仍然在选项对话框中的 “Debugger” 类别中,选择 您的调试接口的特定类别,确保选项被 设置为“重置下连接”并使用 SWD (而非 JTAG) 接口。

  10. 最后在 “Debugger” 类别中,为准备调试 嵌入式工作台(见下文),选择 “Plugins” 选项卡并确保 已选择能充分进行线程感知的 FreeRTOS 内核插件。如果 您已单独安装 WITTENSTEIN StateViewer 插件,请将它们也选上。


  11. 从 "Project" 菜单中选择 "Download->Download Active Project" 以对 Cortex-M4 核心进行编程。

  12. 重复上述步骤,但此次是针对 Cortex-M7 核心(因此, 先在工作区窗口顶部的下拉菜单选择 cortex-M7 核心的配置)。

  13. 按 STM32H745 Discovery 板上的重置按钮并查看 哑终端中的输出。 如果一切顺利,您将看到 一串 1 和 0 正在终端窗口中快速向上滚动。


要使用内置的 STLink 调试接口调试演示应用程序:

  1. 按照上文说明构建并运行应用程序, 确保选择 STLink 作为调试接口且 STM32H745 Discovery 板上的 STLink USB 连接器 CN14 已连接至主机。

    ST 提供应用程序笔记,描述如何配置项目选项中的 STLink 调试设置以启用双核调试。 在 编写时,项目选项只允许一次调试一个核心 。 如果您使用 EWARM V8.40.1 或更高的版本, 且按照下图配置调试选项, 那进行双核调试是有可能的:


    在 Cortex-M4 项目中进行双核调试所需的 STLink 设置



    在 Cortex-M7 项目中进行双核调试所需的 STLink 设置

  2. 选择 Cortex-M7 项目作为活动项目, 从 "Project" 菜单选择 "Download and Debug"。 由 Cortex-M4 核心打印到 UART 的消息应显示 Cortex-M4 核心也被重置了。 调试器应在 Cortex -M7 核心上的应用程序开始运行时中断,您可以像往常那样在该位置单步调试代码、设置断点以及 检查变量等。

  3. 请注意,如果应用程序被设置为正在运行,则 Cortex-M7 核心 会在调试器中停止,同时 Cortex-M4 核心继续保持运行, 然后 Cortex-M4 核心上的接收任务将识别出 来自 Cortex-M7 核心的消息已停止到达,且将命中 assert()。 为防止这种情况发生, 请将 prvM4CoreTasks() 中的 xShortBlockTime 变量值设置为 portMAX_DELAY, 这样它就不会超时了。 prvM4CoreTasks() 在 Cortex-M4 中的 main.c 文件中实现。

  4. 从 "FreeRTOS" 菜单中选择 "Task List" 以打开能够充分进行线程感知的 FreeRTOS 插件窗口。


要使用 I-jet(两个核心一起)调试演示应用程序,则需:

  1. 按照上文说明构建并运行应用程序, 确保选择 I-jet 作为调试接口。

  2. 选择 Cortex-M7 项目作为活动项目,再次打开 项目选项。

  3. 在项目选项 “Debugger” 类别中选择 “Multicore” 选项卡, 然后按下文所示配置选项卡(点击放大)- 将 FreeRTOS/Demo/CORTEX_M7_M4_AMP_STM32H745I_Discovery_IAR/Project.eww 当作从属工作区使用,以及将 FreeRTOSIAR/Demo/CORTEX_M7_M4_AMP_STM32H745I_Discovery_/Project.ewp 当作从属项目使用 (与 Cortex-M7 核心使用的工作区和项目相同 - 只是配置不同)。


  4. 关闭项目选项对话框后, 从 "Project" 菜单选择 "Download and Debug"。 Embedded Workbench 的[主]实例 将进行编程,然后启动 适用于 Cortex-M7 核心的调试会话。Embedded Workbench 的第二个[从属]实例 将自动打开,并对 Cortex-M4 核心进行同样的操作。 Embedded Workbench 的主实例和从属实例是同步的, 因此,您现在可以单独启动、停止和调试每个核心,也可以同时启动、停止 并调试两个核心。 请参阅 IAR 多核调试章节 (在 IAR 网站上)以了解更多信息。

  5. 请注意,如果应用程序被设置为正在运行,则 Cortex-M7 核心 会在调试器中停止,同时 Cortex-M4 核心继续保持运行, 然后 Cortex-M4 核心上的接收任务将识别出 来自 Cortex-M7 核心的消息已停止到达,且将命中 assert()。 为防止这种情况发生, 请将 prvM4CoreTasks() 中的 xShortBlockTime 变量值设置为 portMAX_DELAY, 这样它就不会超时了。 prvM4CoreTasks() 在 Cortex-M4 中的 main.c 文件中实现。

  6. 从 "FreeRTOS" 菜单中选择 "Task List" 以打开能够充分进行线程感知的 FreeRTOS 插件窗口。


配置和用法详情

RTOS 移植特定配置

专用于 Cortex-M4 构建的配置项目包含在 FreeRTOS/Demo/CORTEX_M7_M4_AMP_STM32H745I_Discovery_IAR/cm4/INCLUDE/FreeRTOSConfig.h 中, 专用于 Cortex-M7 构建的配置项目包含在 FreeRTOS/Demo/CORTEX_M7_M4_AMP_STM32H745I_Discovery_IAR/CM7/INCLUDE/FreeRTOSConfig.h 中。 您可以编辑此文件中定义的常量,使其适合您的应用程序。 特别是:

  • configTICK_RATE_HZ

    此常量设置了 RTOS tick 中断的频率。 提供的数值 1000 Hz 可用于 测试 RTOS 内核功能,但此频率比大多数应用程序所需的频率都要高。 降低频率会提高效率。

  • configKERNEL_INTERRUPT_PRIORITY and configMAX_SYSCALL_INTERRUPT_PRIORITY

    请 参阅 RTOS 内核配置文档,获取这些配置常量的完整信息。

  • configLIBRARY_LOWEST_INTERRUPT_PRIORITY 和 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY

    鉴于 configKERNEL_INTERRUPT_PRIORITY 和 configMAX_SYSCALL_INTERRUPT_PRIORITY 是完整的八位未移位值,且被定义为作为原始数据直接在 ARM CORTEX-M NVIC 寄存器中使用, 因此,configLIBRARY_LOWEST_INTERRUPT_PRIORITY 和 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 是等效物,它们被定义为仅使用 STM32H7 NVIC 中实现的 4 个优先级位 。 提供这些值是因为 CMSIS 库函数 NVIC_SetPriority() 需要未偏移的 4 位格式。

请注意!: 请参阅有关如何在 ARM Cortex-M 设备上设置中断优先级的说明页面我们还建议确保将所有优先级位指定为 抢占式优先级位,不要将任何优先级位指定为次优先级位, 正如在演示项目中通过函数调用进行这样的设置

HAL_NVIC_SetPriorityGrouping( NVIC_PRIORITYGROUP_4 );

每个移植都将 "BaseType_t" 定义为 数据类型。 此移植将 BaseType_t 定义为长类型。


中断服务例程

与许多 FreeRTOS 移植不同的是,引发上下文切换的中断服务例程 无特殊要求,可根据编译器文档进行编写。 宏 portYIELD_FROM_ISR() 可用于在 中断服务例程内请求上下文切换。

请注意,portYIELD_FROM_ISR() 将使中断处于启用状态。

下列源代码片段仅作为示例提供。 中断 使用直达任务通知 以与任务(未显示)同步,并调用 portYIELD_FROM_ISR 以确保中断直接返回至任务。

void Dummy_IRQHandler(void)
{
long lHigherPriorityTaskWoken = pdFALSE;

    /* Clear the interrupt if necessary. */
    Dummy_ClearITPendingBit();

    /* This interrupt does nothing more than demonstrate how to synchronise a
    task with an interrupt.  A task notification is used for this purpose.  Note
    lHigherPriorityTaskWoken is initialised to zero. */
    vTaskNotifyGiveFromISR()( xTaskToNotify, &lHigherPriorityTaskWoken );

    /* If the task with handle xTaskToNotify was blocked waiting for the notification
    then sending the notification will have removed the task from the Blocked
    state.  If the task left the Blocked state, and if the priority of the task
    is higher than the current Running state task (the task that this interrupt
    interrupted), then lHigherPriorityTaskWoken will have been set to pdTRUE
    internally within vTaskNotifyGiveFromISR().  Passing pdTRUE into the
    portYIELD_FROM_ISR() macro will result in a context switch being pended to
    ensure this interrupt returns directly to the unblocked, higher priority,
    task.  Passing pdFALSE into portYIELD_FROM_ISR() has no effect. */
    portYIELD_FROM_ISR( lHigherPriorityTaskWoken );
}

只有以 "FromISR" 结尾的 FreeRTOS API 函数可以从 中断服务例程中调用 - 而且中断的优先级须 小于或等于 configMAX_SYSCALL_interrupt_PRIORITY 配置常量(或 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY)设置的优先级。


FreeRTOS 使用的资源

FreeRTOS 需要独占 SysTick 和 PendSV 中断。 其也使用 SVC 编号 #0。


抢占式内核和协作式 RTOS 内核之间的切换

FreeRTOSConfig.h 中的定义 configUSE_PREEMPTION 设置为 1 即可使用抢占式内核, 可使用协作式内核。 选择协作式 RTOS 调度器时,完整的演示应用程序可能 无法正确执行。


编译器选项

与所有的端口一样,使用正确的编译器选项至关重要。 若要确保这一点, 最佳方法是基于提供的演示应用程序文件构建您的应用程序。


内存分配

Source/Portable/MemMang/heap_4.c 包含在 ARM Cortex-M7 和 ARM Cortex-M4 配置中, 以提供 RTOS 内核所需的内存分配。 请参阅 API 文档的内存管理部分, 以获取完整信息。


其他事项

请注意,vPortEndScheduler() 尚未实现。






Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.