关于 FreeRTOS和 newlib库共存问题

Posted 夏沫の浅雨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于 FreeRTOS和 newlib库共存问题相关的知识,希望对你有一定的参考价值。

写在前面:

本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。



一、版本

以下说明仅对于:

1、FreeRTOS v9.0.0(https://github.com/FreeRTOS/FreeRTOS/tree/V9.0.0)

2、GNU Arm Embedded Toolchain 10-2020-q4-major(https://launchpad.net/gcc-arm-embedded/10.0/10-2020-q4-major)内置的 newlib库


二、FreeRTOS 对 newlib 的支持

当我们使用 FreeRTOS的同时,需要值得注意的是,必须要使我们的执行任务处于线程安全之中,否者将会容易出现数据访问异常;而对 newlib库来讲,其本身是默认不带线程安全保护的(因其内部大多数调用了 malloc()等内存分配函数),虽是这样,但 FreeRTOS仍为其上下文管理提供支持,因此当我们在 FreeRTOSconfig.h 中添加:
#define configUSE_NEWLIB_REENTRANT 1 // newlib sprintf、strtok 等的线程安全需要...,那么,在使用此选项时 FreeRTOS将执行以下操作(在task.c 中):

  • 对于每个任务,在任务控制块 (TCB) 中分配并初始化一个 newlib重入结构。
  • 每次任务切换,设置 _impure_ptr 指向新激活任务的可重入结构。
  • 在任务销毁时,清理重入结构(帮助 newlib 释放任何相关内存)。

当然,newlib支持是已经包含在 FreeRTOS的普遍需求中了,但 FreeRTOS维护者本身并未使用。FreeRTOS是不负责由此产生的 newlib操作的,因此用户必须熟悉 newlib,并且必须提供必要存根的系统级实现,即这部分还需要您的供应商提供内置 newlib中内存管理线程安全的支持,否者,就自己设计实现了一个系统级的内存管理线程安全(主要是 malloc()等函数的可重入等问题)


三、当在 FreeRTOS中直接使用 newlib库的 printf/sprintf/snprintf/vsprintf/vsnprintf时出现的问题

前面说了 newlib库本身是默认不带线程安全保护,因此使得一些调用了 malloc()函数的 API函数线程不安全了,这样的结果往往就会导致出现 Hardfault异常,因此也写了 ARM Cortex-M3/M4/M7 Hardfault异常分析 这篇笔记。嘛,摊牌了,是来填坑的。

至于这种情况,网上出现很多这样的问题(本次碰到了,为了避免忘记,所以也记录一下吧):

FreeRTOS社区:

HardFault from printf - freertos 9.0.0 / stm32f0 / gcc-arm-eabi 7.2.0

How to make printf/sprintf/strtod thread safe

How to catch code that caused the hard fault

I/O Hardfault

ST社区:

HardFault Debug in STM32CubeIDE

BUG: CubeMX FreeRTOS projects corrupt memory

注意:在 CubeMX中生成的,对 newlib库可重入函数 _sbrk()的实现,需要干掉它(至少在我对它进行编译的时候,出现 Hardfault异常的可能性更大)

stackoverflow社区:

problem with sprint/printf with freeRTOS on stm32f7


附:newlib可重入问题及外部接口定义

Reentrancy

Definitions for OS interface


四、调用 printf/sprintf/snprintf/vsprintf/vsnprintf的线程安全处理

在使用 printf/sprintf/snprintf/vsprintf/vsnprintf等 newlib库中的 I/O输入输出 API函数时,由于其调用了 malloc()函数等问题,导致整个任务线程处于非安全状态,然而对于一些任意内部使用 malloc 系列或依赖于特定于线程的可重入上下文的库,您往往无能为力,因为您并没用这么大的精力去主动对 malloc()等函数进行加锁保护。那么不如考虑一下大佬提供的如下操作:

https://nadler.com/embedded/newlibAndFreeRTOS.html

https://nadler.com/embedded/NXP_newlibAndFreeRTOS.html

https://github.com/DRNadler/FreeRTOS_helpers

以上是关于关于 FreeRTOS和 newlib库共存问题的主要内容,如果未能解决你的问题,请参考以下文章

关于 FreeRTOS和 newlib库共存问题

在 stm32f7 上使用 freeRTOS 的 sprint/printf 问题

如何使用QEMU运行Newlib应用程序?

用于嵌入式系统的小型 libc [关闭]

freeRtos学习笔记 移植和CPU利用率统计

如何重建 GNU Arm Embedded Toolchain 的 newlib 和 newlib-nano