下载 FreeRTOS
 

出色的 RTOS & 嵌入式软件

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

以下为常见问题节选

在查看常见问题之前...

关于常见问题“我的应用程序没有运行,可能出了什么问题?”,请参见以下内容。 查看之前, 以下是几点有用的提示。

ARM Cortex-M MCU 用户注意事项

针对 ARM Cortex-M 微控制器的大多数支持请求 都与中断优先级分配不正确导致的问题有关。 FreeRTOS V7.5.0 及以上的版本使用 configASSERT() 调用 来捕获此常见的用户错误来源。 在开发时,请您务必对 configASSERT() 进行定义。

此外,我们提供以下两个在线资源:

  1. 一个专门解释 ARM Cortex-M 中断行为,以及它与 中断嵌套相关 FreeRTOSConfig.h 设置关系的页面。

  2. 一个描述如何调试 ARM Cortex-M 硬故障异常的页面。


关于 configASSERT() 的说明

configASSERT() 宏可用于 帮助捕获用户错误。 在开发 或调试您的 FreeRTOS 应用程序时,请务必对 configASSERT() 进行定义。


其他帮助资源

如果阅读此常见问题页面后,您的问题依然没有得到解决,请使用其他支持资源, 包括快速入门指南 (其中包含的链接指向 FreeRTOS.org 网站中能够提供帮助的页面),以及 官方支持系统


FreeRTOS常见问题:我的应用程序没有运行,可能出了什么问题?

以下为常见问题节选

虽然我不了解您的应用程序的具体情况,但以下是一些常见的解决方案:

  1. 我创建的应用程序可以编译,但不能运行
    每个官方 FreeRTOS 端口都附有一个官方演示 (至少在创建时),无需任何修改即可在其硬件开发平台上 编译和执行。 提供演示项目是为了确保新用户可以在最短时间内上手使用 FreeRTOS, 最大限度地降低学习和探索成本。 我们总是建议 从提供的预配置演示中选择一个来开始创建一个新的 FreeRTOS 项目, 然后再对其进行适配。 这样做可以确保新的 项目包括所有必要的源文件和头文件,并安装 必要的中断服务程序,为项目创建者节省精力。

    如果您创建的项目正在编译中,并且至少执行到 调度器已启动的状态, 但是 调用 vTaskStartScheduler() 后,只有一个任务在执行,甚至没有任何任务在执行, 那么这可能是因为中断向量表不正确。

    所有 FreeRTOS 端口都使用定时器中断,一些 FreeRTOS 端口使用 多个中断。 使用提供的演示项目作为示例。

    针对 ARM Cortex-M 用户的特别提示: ARM Cortex-M3、ARM Cortex-M4 和 ARM Cortex-M4F 端口要求 FreeRTOS 处理程序 安装在 SysTick、 PendSV 和 SVCCall 中断向量上。 可以 将 FreeRTOS 定义的 xPortSysTickHandler(), xPortPendSVHandler() 和 vPortSVCHandler() 函数直接填入向量表的对应位置,或者如果 中断向量表与 CMSIS 相容,可以将以下三行 添加到 FreeRTOSConfig.h,用于将 FreeRTOS 函数名称映射到 其对应的 CMSIS 名称。

    #define vPortSVCHandler SVC_Handler
    #define xPortPendSVHandler PendSV_Handler
    #define xPortSysTickHandler SysTick_Handler
    	
    以这种方式使用 #defines 的前提是, 您的开发工具提供的默认处理程序 被定义为弱符号。 如果默认处理程序没有被定义为弱符号, 则需要将其注释掉或删除。

  2. 任务堆栈
    [另请参阅 uxTaskGetStackHighWaterMark() API 函数,以及 堆栈溢出检测选项]

    目前,栈溢出是最常见的支持请求原因。 任务可用堆栈 的大小是使用 xTaskCreate() 的 usStackDepth 参数 或 xTaskCreateStatic() API 函数来设置的。

    对于造成问题的任务, 尝试增加为它分配的堆栈大小,或减少它利用的堆栈数量。 请不要编写需要大量堆栈的 中断服务程序。

    调用任何字符串格式化函数的任务可能需要很多堆栈,尤其是在使用 GCC 编译器时。 这种任务很容易产生栈溢出。

    创建任务时,任务堆栈的每个字节都被设置为 0xa5,因此比较容易发现是否产生了栈溢出。 此外,task.c 中的函数 usTaskCheckFreeStackSpace() 演示了 如何在运行时检查堆栈使用情况(不过这个函数效率较低,因此应当仅用于调试)。

  3. main() 堆栈
    FreeRTOS 调度器启动后,main() 没有上下文,因为调度器启动后,只有 RTOS 任务和中断才有上下文。 由于 main() 的上下文不再存在,在 C 标准允许的情况下,为了使可用于 FreeRTOS 应用程序的 RAM 最大化, 一些 FreeRTOS 端口重新使用分配给 main() 的堆栈作为系统堆栈或中断堆栈。 因此,如果变量或缓存 是 FreeRTOS 应用程序所需要的,或能以任何方式访问的,那么请不要将它们分配在 main() 使用的堆栈上,因为它们很可能会被覆盖。

  4. 中断未执行
    首先,请确保问题与 FreeRTOS 相关。 尝试将中断作为没有使用 FreeRTOS 的简单基本应用程序来使用。

    如果在启动调度器之前调用了一个 FreeRTOS API 函数, 那么中断将维持在禁用状态,直到第一个任务开始执行 才重新启用。 这是为了保护系统。因为在系统初始化期间、调度器启动之前、启动器处于不一致状态时, 中断试图使用 FreeRTOS API 函数 可能导致故障, 从而对系统产生影响。

    更改微控制器中断启用位或优先级标志时, 请不要使用除调用 taskENTER_CRITICAL() 和 TASKEXIT_CRITICAL() 以外的任何方法。 这些宏对它们的调用嵌套深度进行计数, 以确保只有在调用嵌套已完全展开后 才重新启用中断。 请注意,某些库函数本身可能会启用和禁用 中断。

  5. 我在演示中添加了一个简单的任务,现在演示出故障了!
    创建任务需要从内核堆获取内存。 许多演示应用程序项目 将堆的大小设置为刚好能够运行演示任务,因此,向项目添加更多任务时没有足够的空间。 空闲任务 会在您启动 RTOS 调度器时自动创建。 如果堆的大小不够用于创建空闲任务,则 vTaskStartScheduler() 将返回, 导致应用程序根本无法启动。

    要纠正这一点,需增加堆空间,或删除一些演示应用程序任务。

  6. 在中断中使用 API 函数
    除非 API 函数的名称以 "...FromISR()" 结尾,否则,请不要在中断服务程序中使用 API 函数。

    ARM Cortex-M3、ARM Cortex-M4 和 ARM Cortex-M7 用户,请注意: 这是 ARM Cortex-M 设备 95% 的支持请求的原因:

    [还提供了一个单独的页面,解释了 ARM Cortex-M 的中断优先级, 并提供了关于设置 ARM Cortex-M 中断优先级 以用于强大的 FreeRTOS 中断嵌套模型的全部信息]

    如果中断的优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY 的设置, 那么就无法从此中断中调用 API 函数。 设置中断优先级时,请注意以下几点:

    • configMAX_SYSCALL_INTRUPT_PRIORITY 在 FreeRTOSConfig.h 中定义。 在 ARM Cortex-M3 设备上,中断优先级的数值越低,其优先级越高。 请务必 为中断分配优先级,否则将默认其优先级为 0。 0 代表最高的优先级,这将超出 configMAX_SYSCALL_INTERRUPT_PRIORITY 的设置。

    • 设定优先级时请注意,不同的 ARM Cortex-M3 实现,使用的优先级位数量也不同。

    • ARM Cortex-M3 使用一个字节的 n 个最高有效位来表示一个中断优先级。此前说过,n 是由实现来定义的。 ARM 和各种 ARM Cortex-M3 被许可方 提供库函数以允许中断优先级的分配,其中一些期望在调用库函数之前,优先级已经移动到最高有效位中,而另一些则 自行完成这一操作。

    • 定义一个中断优先级的位被拆分,一部分代表抢占式优先级,另一部分代表副优先级。 为了最大程度的简化和 兼容性,请确保所有优先级位被指定为“抢占式优先级”位。
  7. 尝试启动第一个任务时,RTOS 调度器出现故障
    如果您正在使用 ARM7 目标板,那么 RTOS 调度器启动时,处理器一定是处于 Supervisor 管理模式。

  8. 中断启用标志设置不正确
    请不要使用除调用 portENTER_CRITICAL() 和 portEXIT_CRITICAL() 以外的任何方法来禁用或启用中断。 这些宏对它们的调用嵌套深度进行计数, 以确保只有在调用嵌套已完全展开后才重新启用中断。

    如果在启动调度器之前调用了一个 FreeRTOS API 函数, 那么大部分 FreeRTOS 端口将禁用中断,直到第一个任务开始执行 才重新启用。 这是为了保护系统。 因为在系统初始化期间、调度器启动之前, 中断试图使用 FreeRTOS API 函数可能导致故障, 从而对系统产生影响。

  9. RTOS 调度器还没启动,我的应用程序就出现故障了
    只有在 RTOS 调度器启动后,才能进行上下文切换。 因此,可能导致上下文切换的中断服务程序 不能在 RTOS 调度器启动前执行。 试图发送到队列或信号量或从其接收的任何中断服务程序也是如此。

    在 RTOS 调度器启动之前,许多 API 函数都无法调用。 这种做法最好仅用于创建那些 在 RTOS 调度器开始运行后立即被使用的任务、队列和信号量。

  10. 挂起 RTOS 调度器(调用 vTaskSuspendAll())给我造成了问题
    在 RTOS 调度器挂起时,不要调用 API 函数。 只有一部分函数可以使用,并非所有。 这并非设置挂起机制原本的目的。

  11. 我创建了一个新的应用程序,但是它无法编译
    请基于为您正在使用的端口所提供的演示项目文件来创建新的应用程序。 这样一来,您可以确保包含了正确的文件,并且编译器配置正确。

  12. 我卡在了启动 for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); 的那一行
    可能的原因包括:
    1. 堆栈溢出。请参阅 http://www.freertos.org/Stacks-and-stack-overflow-checking.html
    2. 不正确的中断优先级分配,尤其是在 ARM Cortex-M3 设备上,中断优先级的数值越大,代表实际中断优先级越小, 这一点可能有些反直觉。 请 前往 http://www.freertos.org/a00110.html#kernel_priority 参阅有关 configMAX_SYSCALL_INTRUPT_PRIORITY 的内容。
    3. 从关键部分中,或在 RTOS 调度器挂起时调用 API 函数。

我还能做什么?
  1. 查看下载页面上的已知问题列表
  2. 受监控的支持论坛中发帖,描述您遇到的问题。




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