本帖最后由 ESSEMI华东FAE 于 2020-4-8 15:16 编辑
FreeRTOS目录结构
FreeRTOS包含Demo例程和内核源码两部分。
Demo 文件夹里面包含了FreeRTOS官方为各个单片机移植好的工程代码,Source文件夹里面包含的是FreeRTOS内核的源代码,我们移植FreeRTOS的时候就需要这部分源代码。
Source\include是通用的头文件。Source\portable是与编译器和内存管理相关的源文件和头文件。其中,RVDS文件夹是Keil开发环境对应的编译器支持文件,MemMang文件夹是跟内存管理相关的源文件。
使用Keil开发环境需要复制的文件有:
Source\下所有.c文件
Source\include文件夹
Source\portable\RVDS\ ARM_CMx文件夹
Source\portable\MemMang下heap_4.c
移植使用的RTOS版本是9.0.0 。首先示范如何移植FreeRTOS到HR8P506上。
HR8P506上移植步骤
FreeRTOS内核是高度可定制的,使用配置文件FreeRTOSConfig.h进行定制。每个FreeRTOS应用都必须包含这个头文件,用户根据实际应用来裁剪定制FreeRTOS内核。这个配置文件是针对用户程序的,而非内核,因此配置文件一般放在应用程序目录下,不要放在RTOS内核源码目录下。
这里使用的是\Demo\CORTEX_M0_STM32F0518_IAR里面的FreeRTOSConfig.h文件。
1、在AN074_Examples_HR8P506目录下面建一个空文件夹FreeRTOS。
把FreeRTOS V9.0.0源码中Source\下所有.c文件、Source\include文件夹、Source\portable文件夹复制到这个文件夹里。
portable文件夹中实际只用到\RVDS\ ARM_CM0文件夹和\MemMang下heap_4.c。
然后,创建分组FreeRTOS,并添加相应文件。
app分组添加文件FreeRTOSConfig.h。
编译工程
FreeRTOS的源码已经添加到开发环境的组文件夹下面,编译的时候需要为这些源文件指定头文件的路径,不然编译会报错。FreeRTOS的源码里面只有FreeRTOS\include和FreeRTOS\port\RVDS\ARM_CM0这两个文件夹下面有头文件,只需要将这两个头文件的路径在开发环境里面指定即可。同时我们还将FreeRTOSConfig.h这个头文件拷贝到了工程根目录下的APP文件夹下,所以APP的路径也要加到开发环境里面。
2、添加头文件路径
编译后
3、修改FreeRTOSConfig.h
configCHECK_FOR_STACK_OVERFLOW改成0
configUSE_TICK_HOOK改成0
configUSE_TIMERS改成0
configUSE_MALLOC_FAILED_HOOK改成0
添加
#define vPortSVCHandler SVC_IRQHandler
#define xPortPendSVHandler PendSV_IRQHandler
#define xPortSysTickHandler SysTick_IRQHandler
编译后报错
4、修改irqhandler.c
屏蔽irqhandler.c里
void SVC_IRQHandler(void){}
void PendSV_IRQHandler(void){}
void SysTick_IRQHandler(void){TimingDelay_Decrement();}
编译后报错
5、修改FreeRTOSConfig.h
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 11000 ) )
改成
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 4000 ) )
按照xTaskCreate()函数中代码
pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );
将总的栈大小configTOTAL_HEAP_SIZE设置成4000
编译通过
6、栈大小设置注意事项
如果栈大小设置太小会出现调度器无法调度的问题。
在一开始把configTOTAL_HEAP_SIZE设置成1000时,
执行 xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, (const char* )"AppTaskCreate“, (uint16_t )512, (void* )NULL, (UBaseType_t )1, (TaskHandle_t* )&AppTaskCreate_Handle);
后xReturn不等于pdPASS,vTaskStartScheduler();就不会执行,调度器就无法工作。
追踪到xTaskCreate内,发现问题出在这里:
pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );
最后会返回内存不足的错误
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
这个地方给任务分配TCB控制块和栈的内存空间,产生了失败。
栈宽度StackType_t是4个字节,可以把单个任务的栈空间从512改成256,256*4*3=3072,把configTOTAL_HEAP_SIZE修改成4000,这样就可以成功运行3个任务了。
见task.h中的注释
|