Free劲客TOS–疑难杂症

花了三个夜晚,把这些章节看完,收益匪浅。

  1. 最实用的应有是与中断相关的荒谬,优先排查中断优先级设置。
  2. 堆栈溢出检查,只怕用到,一般先把仓库设置的丰盛大,只要没有溢出就是好事,溢出了,通晓了栈溢出钩子函数排错很有益于。
  3. printf()连带的题材应该尽大概不会并发,究竟如果需求打字与印刷调节和测试音讯的事态下才使用,而且嵌入式系统一般都是用串口重定向的。
    讲真,嵌入式中printf()当真挺烦的,严重影响属性,小编的开支案例中发觉,串口打字与印刷会影响板子的
    power save品质,那是实地度量到的。

此章节涉嫌新手最常遇见的3种难点:

  1. 错误的中断优先级设置
  2. 栈溢出
  3. 不正好的应用printf()

使用configASSERT()可见明显地增强生产效用,它亦可捕获、识别七种类型的谬误。强烈建议在开发依旧调节和测试中开启宏configASSERT()

停顿优先级

注意:那是第超级必要技术补助的标题,在大部的移植版本中通过定义configASSERT()就能够即时捕获这几个张冠李戴。

倘诺Free索罗德TOS移植版本补助中断嵌套,并且中断服务程序使用了FreeQashqaiTOS
API,那么必须把暂停优先级设置为configMAX_SYSCALL_INTERRUPT_PRIORITY抑或低一些。没有如此设置将会造成临界区失效,反过来就会导致间歇性的错误。

当FreeLX570TOS运转在偏下处理器上要求尤其注意:

  • 暂停优先级应用恐怕的参天优先级,这正是APRADOM Cortex
    处理器上的情况,还有部分任何的。在那几个电脑上,调用FreeWranglerTOS API
    的中止的先行级不能够留置未初阶化。
  • 事先级数值越高意味着逻辑上优先级越低,那只怕与直觉相反,因而可能导致混淆。同样那或然在好几A路虎极光M
    Cortex处理器上,恐怕还有任何的。
  • 譬如,在某些处理器上三个暂停的先期级为5,正在运行,不过能够被八个先行级为4的间歇打断。由此,借使configMAX_SYSCALL_INTERRUPT_PRIORITY设置为5,那么其余其余的运用Free奥迪Q5TOS
    API的间歇的事先级必须安装为5竟是更高。在那种景观下优先级为5或许6的是实用的,然而优先级为3的中止是无效的。
  • 差别的库实现梦想中断优先级用分歧的主意钦点。别的尤其是本着A奇骏M
    Cortex处理器相关的库,它们的间歇优先级在写入硬件寄存器从前是经过位移的。有个别库大概本人进行运动操作,然则其他的库期待中断优先级在传给库函数在此以前早已开展了移动操作。
  • 同样架构上的两样的达成,完成的是搁浅优先级的比特位不一样。例就好像样的Cortex-M拍卖器某1个厂商恐怕达成了二个优先级比特位,然则另三个厂商达成了5个先行级比特位。
  • 概念3个停顿优先级的比特位被分成两个部分,一部分概念抢占的级别,另外的比特位定义子优先级。确定保证全部的比特位都是点名抢占的优先级,而子优先级不选用。

在少数移植版本中configMAX_SYSCALL_INTERRUPT_PRIORITY有3个别称configMAX_API_CALL_INTERRUPT_PRIORITY

栈溢出

栈溢出是第③个常常寻求技术帮忙的标题。Free福特ExplorerTOS提供了几个特色来援助捕获和调节和测试和栈相关的难点。

API函数uxTaskGetStackHighWaterMark()

每一个职务都在保卫安全和谐的栈,栈的总大小在创制职务的时候就钦赐了。函数uxTaskGetStackHighWaterMark()就算用来查询分配给那么些职务的栈接近栈溢出的档次。重回值称为栈的高水位线

UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );

任务选用栈的多少,随着任务的运行和间断的拍卖时而扩大时而减弱。uxTaskGetStackHighWaterMark()回来自职分先河运转以来剩余可用的栈空间的纤维值。它回到的是栈未使用的半空中占最大值的比率。高水位越接近于0,那么这些职务的栈就越快要溢出。

运作时栈检查

Free帕杰罗TOS提供了两种在运维时检查栈的机制。都是由文件FreeRTOSConfig.h中的configCHECK_FOR_STACK_OVERFLOW来在编写翻译时举办支配的。三种方法都会扩张上下文切换的年华。

栈溢出钩子函数(又称为栈溢出回调函数)是三个由基础检查到栈溢出时调用的函数。要使用栈溢出钩子函数要满意以下原则:

  1. 在文件FreeRTOSConfig.h中把configCHECK_FOR_STACK_OVERFLOW设置为1或者2
  2. 落实以下钩子函数,使用完全平等的函数名字和原型:

    void vApplicationStackOverflowHook( TaskHandle_t pxTask, signed char pcTaskName);

栈溢出钩子函数会让捕获和调剂栈错误越来越的简易,但是产生栈溢出荒唐时是未曾主意苏醒的。此函数把发生栈溢出的任务的句柄和名字传递进入。

栈溢出钩子函数会在三个一曝十寒的上下文中开展调用。

一点微控制器在检查和测试到3个荒唐的内部存款和储蓄器访问时会发生三个谬误格外,那么些错误格外的触发会使得内核根本就从未有过机会调用栈溢出钩子函数。

运转时栈检查–方法1

当进行如下设置是会选取情势1.

#define configCHECK_FOR_STACK_OVERFLOW 1

每当1个任务被切换出去时它的整套的施行上下文都会被封存到它和谐的栈中。很有恐怕那正是栈使用率高达最大值的时候。当使用方法1是,当义务的上下文被封存之后基本回去检查栈指针是不是在栈可用空间内。假设发现栈指针已经不止了可用的界定那么就会调用栈溢出钩子函数。

主意1执行进度快,可是在产生前后文切换时有恐怕会错过栈溢出。

运营时栈检查–方法2

拓展如下设置后才会采用格局2.

#define configCHECK_FOR_STACK_OVERFLOW 2

除开艺术第11中学的行为,方法2还会实施此外的检讨。

始建义务时它的栈会被一个已知的范本填充。任务2反省栈空间的末梢二十五个字节,验证这几个已知的样本是不是业已被遮住。假设那18个字节的值与预期值不等同那么就会调用栈溢出钩子函数。

方法2不如方法1快,当时相对来讲如故快,终究只是测试十多个字节。很有大概方法2会捕获到具备的栈溢出,可是有或许(大约不容许)有个别栈溢出依旧漏掉了。

不稳当地采纳printf()sprintf()

不安妥地只用printf()是一种常见的错误源,并且没有察觉到那种错误,平日选择开发者会扩张越来越多的printf()来帮衬调节和测试,结果便是加深了难题。

多多接力编译器香港中华厂商联合会提供一种适合在小型嵌入式系统中运用的printf()的贯彻。固然在那种景观下,printf()的贯彻大概并不是线程安全的,差不多能够肯定不切合在暂停服务程序中运用,并且取决于输出被重定向到哪儿,会占用相当短的一段实施时间。。

倘若小型嵌入式系统的printf()的贯彻不可用,并且动用了通用的printf()的完毕,那么就须要特别注意了:

  • 唯有增添了1个对printf()或者sprintf()的调用就会强烈的扩展应用执行文书的体量;
  • 即使利用了heap_3以外的仓库储存空间方案,printf()sprintf()调用了malloc(),这些是低效的。
  • printf()sprintf()唯恐会申请2个几倍于平时意况的栈空间。

Printf-stdarg.c

洋洋的FreeOdysseyTOS示例工程了运用了一个printf-stdarg.c的公文,它提供了贰个十分小的、栈使用率十二分迅猛的能够代表标准库函数版本的sprintf()福寿康宁。在多数状态下,使得职责每一次调用sprintf()抑或相关的函数却分配更少的栈空间。

printf-stdarg.c提供了一种机制把printf()输出重定向,二个字节二个字节的输出,就算慢,不过却相当大地减小了栈空间的挤占。

注意:并不是兼备的Free大切诺基TOS下载副本中文件printf-stdarg.c都完结了snprintf()函数。没有落实snprintf()的副本直接忽略缓冲区大小参数,它们是一向照射到sprintf()函数。

printf-stdarg.c是开源的,不过是第壹方拥有的,因而它的授权和FreeKoleosTOS是分离的。它的授权条款在文件的首部。

其余的大规模错误

症状:添加八个粗略职分到例程中却促成了例程挂掉

创办职分急需从堆中分配内部存款和储蓄器。许多示范工程的栈空间仅仅能够容纳例程职分,由此在开创了例程任务后,没有丰盛的堆空间留给其余越多的职务,队列,事件组,信号量。

空闲职务,又或然是FreePAJEROTOS的医生和医护人员进度,在调用vTaskStartScheduler()时是全自动创设的。只有当堆空间不足以创立那些职责时vTaskStartScheduler()才会重临。在调用vTaskStartScheduler()从此添加四个for(;;);会让这些难题更易于排错。

要想添加越来越多的天职,要么扩张堆空间,要么减弱已经存在的事例职务。

症状:中断中动用API导致应用挂掉

在暂停服务程序中毫无选取API,除非API名字是以FromISR()最终。特别地,在暂停中并非创立四个临界区,除非选取中断安全的宏。

在支撑中断嵌套的FreeEscortTOS移植版本中,借使中断优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY就绝不在其间使用
API 函数。

症状:有时应用程序在刹车服务函数中挂掉

率先要反省立中学断是还是不是发生了栈溢出。有的移植版本中只检查职分的栈溢出,并从未检查中断是不是栈溢出。

暂停的概念和选取方法随着移植版本和编写翻译器的分歧而分裂。因而,其次要反省语法,宏定义,调用规则在暂停服务程序中的使用是还是不是与移植文书档案中的完全一致,是不是与例程中的完全一致。

万一选择运营在数值越低的事先级表示逻辑上越高的事先级的微处理器上,那么必要确认保证分配给中断的预先级要考虑到那种情形,因为它看起来是违背直觉的。

假使应用运转在把暂停优先级私下认可设置为最大大概的先期级的电脑上,必要保障每个中断的优先级没有留置为私下认可值。

症状:调度器尝试运维第二个职务时挂掉

管教设置了FreePAJEROTOS的中止句柄。参考FreeOdysseyTOS移植文书档案,还有示例程序。

有个别处理器必须在调度器运行以前处于特权方式。最简易的兑现形式是在C语言main()前边的启航代码中就把电脑内置特权形式。

症状: 中断被丰裕地取缔了,又可能临界区未曾科学地嵌套

一经在调度器运维在此以前就调用了FreeWranglerTOS
API函数那么中断就会被有意地取缔,直到第①个职责运营现在才会重新使能。那样做是为了维护连串不挂掉,原因在于初步化进度中间断尝试调用FreeRAV4TOS
API函数,不过调度器还未曾运营,它也许处于二个不雷同的情景。

除向外调拨运输用taskENTER_CRITICAL()taskEXIT_CRITICAL()函数之外不要使用其余其余的法子来更改微处理器的刹车使能位和先行级标志。那八个宏会总计中断嵌套深度确定保障当刹车嵌套深度为0时中断又使能。要求知悉有个别库函数恐怕在里边使能和禁止中断。

症状:远在调度器运转从前使用就挂掉了

有也许发生上下文切换的间歇是禁止在调度器运营此前就起来实践的。同样的平整适用于尝试发送可能吸收Free大切诺基TOS对象(例如队列和信号量)的别样中断服务程序。上下文切换必须在调度器运转今后才能产生。

重重API函数必须在调度器运维现在才能调用。最好是在调用vTaskStartScheduler()从此将API的选拔范围在开立诸如职分,队列和信号量上,而不是采纳那一个指标。

症状: 在调度器挂起时又可能是临界区在那之中调用API函数会导致应用程序挂掉

调用函数vTaskSuspendAll()会挂起调度器,调用函数xTaskResumeAll()会恢复生机调度器。

调用函数taskENTER_CRITICAL()会跻身临界区,调用函数taskEXIT_CRITICAL()会脱离临界区。

在调度器挂起时要么临界区内永远不要调用API函数。

声明

欢迎转发,请注脚出处和笔者,同时保留申明。
作者:LinTeX9527
出处:http://www.cnblogs.com/LinTeX9527/p/8031565.html
本博客的小说如无特殊表明,均为原创,转发请证明出处。如未经小编同意必须保留此段评释,且在文章页面明显地方给出最初的小说连接,不然保留追究法律权利的任务。