2、雹轿梁VxWorks不帆猛仅是一种嵌入式实时 *** 作系统,源运又是可以运行的最小基本程序。其内部有BSP(BoardSupportPackage,板级支持包),便于进行驱动程序的编写。此外,VxWorks具有强实时性、微内核设计、可裁剪性、可移植性和可靠性等特点,能较好地满足嵌入式开发的需求。缺点就是昂贵的价格让开发者望而却步。
FreeRTOS 的移植主要需要改写如下三个文件。
1. portmacro.h
2. port.c
3. 物哪 port.asm
如果采用的C编译器允许在C 代码中插入汇编,并且支持用C语言写中断处理函数。则port.asm 文件的内容是可以合并到port.c 中的。
下面以将 FreeRTOS 移植到FreeScale 68HCS12 内核的单片机为例,开发环境采用:CodeWarriorDevelopment Studio V5.9.0
之所以采用FreeScale 68HCS12 作为示例 CPU,是因为我以前写过一篇将uC/OS-II移植到FreeScale 68HCS12 核单片机的笔记。采用同样的CPU,同样的开发环境,可以方便我们比较两种不同实时 *** 作系统的移植代码的异同。另外,FreeScale 68HCS12 相对ARM、MIPS 等构架要简单的多。移植代码量相对来说也要小一些,因此也更容易入门。
portmacro.h
portmacro.h 主要包括两部分内容,第一部分定义了一系列内核代码中用到的数据类型。FreeRTOS 与 uC/OS-II 一样,并不直接使用char、int 等这些原生类型,而是将其重新定义为一系列以port开头的新类型。在uC/OS-II的移植代码中,通常采用 typedef 来定义新的类型,而FreeRTOS的作者似乎更喜欢用宏定义。下面是相应的代码片段。
portTickType 既可以定义为16位的无符号整数,也可以定义为32位的无符号整数。具体用那种定义,要看 FreeRTOSConfig.h 文件中如何设置configUSE_16_BIT_TICKS。
然后是一些硬件相关的定义。包括数据对其方式,堆栈增长方向,Tick Rate,还有任务切换的宏。
portBYTE_ALIGNMENT 在uC/OS-II 是不需要的,FreeRTOS的代码中在分配任务堆栈空间时用到这个宏定义。
portSTACK_GROWTH 定义为1 表示堆栈是正向生长的,-1为逆向生长的。一般来说堆栈都是倒生的,68HCS12 也不例外,因此这里定义为 (-1)。
多说一句在 uC/OS-II 中,对应的宏是OS_STK_GROWTH, 1 表示逆向生长,0表示正向生长。
portTICK_RATE_MS 只在应用代码中可能会用到,表示的是Tick 间间隔多少 ms。
portYIELD() 实现的是任务切换,相当于 uC/OS-II中的 OS_TASK_SW()。
portNOP() 顾名思义就是对空 *** 作定义了个宏。具体在FreeRTOS 代码中哪里用到了这个宏没注意过,但是想必是有地方用到了。
然罩谨码后是有关临界区的处理代码:
这部分的代码挺长的,不过其实是对 Small Memery Model 和Banked Memery Model 分别提供了如下两个宏定义:
portRESTORE_CONTEXT()
portSAVE_CONTEXT()
使用哪一套宏定义是通过BANKED_MODEL 这个宏是否被定义来确定的。其实,CodeWarrior Development Studio V5.9.0 中提供的官方代码中给出了一种更正规的判断方法:
FreeRTOS中保存和恢复任务上下文环境的代码与uC/OS-II中的大同小异,唯一有点区别的晌皮就是要保存uxCriticalNesting 的值。原因上面已经介绍过了。
之所以要搞这两个宏,是为了利用某些C编译器的扩展功能对任务函数进行更好的优化。CodeWarrior 并不提供相关的功能,所以在这里任务就是普通的函数。
* 1. 学习FreeRTOS的任务栈溢出检测方法一(模拟栈溢出)。
* 2. FreeRTOS的任务栈溢出检测方法一说明:
* a. FreeRTOSConfig.h文件中配置宏定义:
* #define configCHECK_FOR_STACK_OVERFLOW 1
* b. 在任务切换时检测任务栈指针是否过界了,如果过界了,在任务切换的时候会触发栈溢出钩子函数。
* void vApplicationStackOverflowHook( TaskHandle_t xTask,
* signed char *pcTaskName )
* 用户可以在钩子函数里面做一些处理。本实验是在钩子函数中打印出现栈溢出的任务。
* c. 这种方法不能保证所有的栈溢出都能检测到。比如任务在执行的过程中发送过栈溢出。任务切换前
* 栈指针又恢复到了正常水平,这种情况在任务切换的时候是检测不到的。又比如任务栈溢出后,把
* 这部分栈区的数据修改了,这部分栈区的数据不重要或者暂时没有用到还好,如果是重要数据被修
* 改将直接导致系统进入硬件异常。这种情况下,栈溢出检测功能也是检测不到的。
* d. 本实验就是简单的在任务vTaskUserIF中申请过大的栈空间,模拟出一种栈溢出的情况,溢出后触
* 发钩子函数,因为我们将溢出部分的数据修改了,进而造成进入硬件异常。
#define configCHECK_FOR_STACK_OVERFLOW 1
/*
*********************************************************************************************************
* 函 数 名: StackOverflowTest
* 功能说明: 任务栈溢出测试
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void StackOverflowTest(void)
{
int16_t i
uint8_t buf[2048]
(void)buf/* 防止警告 */
/*
1. 为了能够模拟任务栈溢出,并触发任务栈溢出函数,这里强烈建议使用数组的时候逆着赋值。
因为对于M3和M4内核的MCU,堆栈生长方向是向下生长的满栈。即高地址是buf[2047], 低地址
是buf[0]。如果任务栈溢出了,也是从高地址buf[2047]到buf[0]的某个地址开始溢出。
因此,如果用户直接修改的是buf[0]开始的数据且这些溢出部分的数据比较重要,会直接导致
进入到硬件异常。
2. 栈溢出检测是在任务切换的时候执行的,我们这里加个延迟函数,防止修改了重要的数据导致直接
进入硬件异常。
3. 任务vTaskTaskUserIF的栈空间大小是2048字节,在此任务的入口已经申请了栈空间大小
------uint8_t ucKeyCode
------uint8_t pcWriteBuffer[500]
这里再申请如下这么大的栈空间
-------int16_t i
-------uint8_t buf[2048]
必定溢出。
*/
for(i = 2047i >= 0i--)
{
buf[i] = 0x55
vTaskDelay(1)
}
}
/*
*********************************************************************************************************
* 函 数 名: vApplicationStackOverflowHook
* 功能说明: 栈溢出的钩子函数
* 形 参: xTask 任务句柄
* pcTaskName 任务名
* 返 回 值: 无
*********************************************************************************************************
*/
void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
{
printf("任务:%s 发现栈溢出\r\n", pcTaskName)
}
实验目的:
* 1. 学习FreeRTOS的任务栈溢出检测方法二(模拟栈溢出)。
* 2. FreeRTOS的任务栈溢出检测方法二说明:
* a. FreeRTOSConfig.h文件中配置宏定义:
* #define configCHECK_FOR_STACK_OVERFLOW 2
* b. 在任务切换时检测任务栈指针是否过界了,如果过界了,在任务切换的时候会触发栈溢出钩子函数。
* void vApplicationStackOverflowHook( TaskHandle_t xTask,
* signed char *pcTaskName )
* 用户可以在钩子函数里面做一些处理。本实验是在钩子函数中打印出现栈溢出的任务。
* c. 任务创建的时候将任务栈所有数据初始化为0xa5,任务切换时进行任务栈检测的时候检测末尾
* 的16个字节是否都是0xa5,通过这种方式来检测任务栈是否溢出了。相比方法一,这种方法的速度
* 稍慢些,但是这样就有效的避免了方法一里面的部分情况。不过依然不能保证所有的栈溢出都能检测
* 到,比如任务栈末尾的16个字节没有用到,即没有被修改,但是任务栈已经溢出了,这种情况是检
* 测不到的。另外任务栈溢出后,任务栈末尾的16个字节没有修改,但是溢出部分的栈区的数据修改
* 了,这部分栈区的数据不重要或者暂时没有用到还好,如果是重要数据被修改将直接导致系统进入硬
* 件异常。这种情况下,栈溢出检测功能也是检测不到的。
* d. 本实验就是简单的在任务vTaskUserIF中申请过大的栈空间,模拟出一种栈溢出的情况,溢出后触
* 发钩子函数,因为我们将溢出部分的数据修改了,进而造成进入硬件异常。
#define configCHECK_FOR_STACK_OVERFLOW 2
函数内容和上面一样:
static void StackOverflowTest(void)
void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)