查看: 13656|回复: 31

[其他] 每天解决一个问题15:KL26Z开发板移植Freertos详细步骤

[复制链接]

该用户从未签到

61

主题

965

帖子

0

金牌会员

Rank: 6Rank: 6

积分
2394
最后登录
1970-1-1
发表于 2015-9-17 08:26:45 | 显示全部楼层 |阅读模式
   昨天在KL26Z上移植了Freertos实时操作系统。整理了一下,把移植的过程及注意的地方共享一下。有需要的可以参考。

FreeRtos移植:版本 FreeRTOS V8.2.2   目前最新版本
1,源文件准备,可以到freertos官网上下载。
1)与FreeRTOS内核有关的文件数量仅为3个,分别是list.c queue.c tasks.c croutine.c timers.c该文件位于FreeRTOS\Source
2)与内存分配有关的文件共有4个,分别是heap_1.c,heap_2.c,heap_3.c,heap_4.c,heap_5.c最新版有5个文件只需选择其中的1个,STM32选择heap_2.c。新塘选择heap_2.c。KL26Zheap_2.c。我们也选择该文件位于Source\portable\MemMang。
3) 与移植相关的代码包括port.c,portmacro.h。这些代码不但和编译器有关还和平台(MCU)有关。FreeRTOS先以编译器为大类,然后再以平台(MCU)为小类。在这里选择Keil编译器,平台为ARM_CM4F。该文件位于Source\portable\RVDS\ARM_CM4F。
4)除了上述内容之外,还包括FreeRTOS内核相关的头文件。该文件FreeRTOS\Source\include。
2,在工程中加入Freertos文件。
加入的文件有list.c queue.c tasks.c  timers.c  heap_2.c,port.c
3,在工程中加入Freertos文件的头文件路径
4,编译,提示错误,没有FreeRTOSConfig.h文件
   编写该文件对内核的配置,需要FreeRTOSConfig.h中的相关宏定义
5需要在启动代码中修改这些中断向量的名称,并声明这些中断向量为外部函数。这也是初次使用FreeRTOS容易范的错误。我这里就在FreeRTOSConfig.h中定义:
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
编译出现错误:
.\obj\USBD_VCOM.axf: Error: L6218E: Undefined symbol vApplicationIdleHook (referred from tasks.o).
.\obj\USBD_VCOM.axf: Error: L6218E: Undefined symbol vApplicationTickHook (referred from tasks.o).
.\obj\USBD_VCOM.axf: Error: L6218E: Undefined symbol vApplicationMallocFailedHook (referred from heap_2.o).
原因是没有定义这三个函数。
main文件中定义这三个函数:
void vApplicationIdleHook(void)
{
  
}
void vApplicationTickHook(void)
{
#if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 0 )
    {
        // In this case the tick hook is used as part of the queue set test.
    }
#endif // mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
}
void vApplicationMallocFailedHook(void)
{
    taskDISABLE_INTERRUPTS();
    for(;;);
}
再编译,还出现一个错误:
.\obj\USBD_VCOM.axf: Error: L6218E: Undefined symbol taskDISABLE_INTERRUPTS (referred from main.o).
是因为main文件中没有添加内核头文件:
// Kernel includes.
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
这时编译通过.
6,到这里移植就完成了,是不是很简单?可以开始实现任务代码了,我在这里实现一个简单的任务,实现USB收发数据。
xTaskCreate(USBD_Task,  "USBD", configMINIMAL_STACK_SIZE, NULL, mainKEY_TASK_PRIORITY, NULL);
/* Start the scheduler. */
        vTaskStartScheduler();
    while(1)
    {
      
}
注意,这时候运行起来,好像切换是有问题的,是因为我定义了
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); },导致启动内核的时候有问题。解决办法:一是不要定义configASSERT,关于configASSERT后面会说到。二是在port.c中的BaseType_t xPortStartScheduler( void )的函数中去掉
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
#if( configASSERT_DEFINED == 1 )
{
        volatile uint32_t ulOriginalPriority;
        volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile uint8_t ucMaxPriorityValue;
ulOriginalPriority = *pucFirstUserPriorityRegister;
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
configASSERT( ucMaxPriorityValue == ( configKERNEL_INTERRUPT_PRIORITY & ucMaxPriorityValue ) );
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
        ulMaxPRIGROUPValue--;
        ucMaxPriorityValue <<= ( uint8_t ) 0x01;
}
#endif
这个运行就一切正常了。
7,有人应该注意到了,我们还有一个文件需要配置些什么东西。这个文件是FreeRTOSConfig.h(这个文件自己编写),FreeRTOS 是高度可配置的。所有的可配置项都在FreeRTOSConfig.h 文件中。每一个Demo 程序中都包含了一个配置好的FreeRTOSConfig.h 文件,可以以Demo程序中的FreeRTOSConfig.h 文件作为模板,在其基础上加以修改。
关注portmacro.h
1)在portmacro.h
portmacro.h 主要包括两部分内容,第一部分定义了一系列内核代码中用到的数据类型。FreeRTOS uC/OS-II 一样,并不直接使用charint 等这些原生类型,而是将其重新定义为一系列以port开头的新类型。在uC/OS-II的移植代码中,通常采用 typedef 来定义新的类型,而FreeRTOS的作者似乎更喜欢用宏定义,相应代码:
#define portCHAR                char
#define portFLOAT                float
#define portDOUBLE                double
#define portLONG                long
#define portSHORT                short
#define portSTACK_TYPE        uint32_t
#define portBASE_TYPE        long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
        typedef uint16_t TickType_t;
        #define portMAX_DELAY ( TickType_t ) 0xffff
#else
        typedef uint32_t TickType_t;
        #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
        /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
        not need to be guarded with a critical section. */
        #define portTICK_TYPE_IS_ATOMIC 1
#endif
然后是一些硬件相关的定义。包括数据对其方式,堆栈增长方向,Tick Rate,还有任务切换的宏
#define portSTACK_GROWTH                        ( -1 )
#define portTICK_PERIOD_MS                        ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT                        8
/* Constants used with memory barrier intrinsics. */
#define portSY_FULL_READ_WRITE                ( 15 )
portSTACK_GROWTH 定义为1 表示堆栈是正向生长的,-1为逆向生长的。一般来说堆栈都是倒生的。
多说一句在 uC/OS-II 中,对应的宏是OS_STK_GROWTH1 表示逆向生长,0表示正向生长。
portTICK_RATE_MS 只在应用代码中可能会用到,表示的是Tick 间间隔多少 ms
portYIELD() 实现的是任务切换,相当于 uC/OS-II中的 OS_TASK_SW()
#define portYIELD()                                                                                                                       
{                                                                                                                                                       
        portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;                                                       
        __dsb( portSY_FULL_READ_WRITE );                                                                                       
        __isb( portSY_FULL_READ_WRITE );                                                                                       
}
然后是有关临界区的处理代码:
#define portDISABLE_INTERRUPTS()                                vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS()                                        vPortSetBASEPRI( 0 )
2FreeRTOSConfig.h配置说明
//是否配置成抢先式多任务内核,是1的时候,优先级高的任务优先执行。 为0任务就没有优//先级之说,用时间片轮流执行
#define configUSE_PREEMPTION            1
// IDLE任务的HOOK函数,用于OS功能扩展,需要你自己编相应函数, 名字是void //vApplicationIdleHook( void )
#define configUSE_IDLE_HOOK             1
// SYSTEM TICK的HOOK函数,用于OS功能扩展,需要你自己编相应函数, 名字是 void //vApplicationTickHook( void )
#define configUSE_TICK_HOOK             1
#define configCPU_CLOCK_HZ   ( SystemCoreClock ) // 系统CPU频率,单位是Hz
// 系统SYSTEM TICK每秒钟的发生次数, 数值越大系统反应越快,但是CPU用在任务切换//的开销就越多
#define configTICK_RATE_HZ  ( ( portTickType ) 1000 )
//系统任务优先级数。10 说明任务有10级优先度。这个数目越大耗费RAM越多
#define configMAX_PRIORITIES        ( ( unsigned portBASE_TYPE ) 10 )
// 系统最小堆栈尺寸,注意128不是128字节,而是128个入栈。比如ARM32位,128个入//栈就是512字节
#define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 100 )
// 系统可用内存。一般设成除了操作系统和你的程序所用RAM外的最大RAM。 比如20KRAM
//你用了2K,系统用了3K,剩下15就是最大HEAP 尺寸。你可以先设小然后看编译结果往大//里加
#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 8 * 1024 ) )
// 任务的PC名字最大长度,因为函数名编译完了就不见了,所以追踪时不知道哪个名字。10  
//表示10个char
#define configMAX_TASK_NAME_LEN         ( 10 )
// 是否设定成追踪,由PCTraceCon.exe记录,也可以转到系统显示屏上
#define configUSE_TRACE_FACILITY        1
// 就是SYSTEM TICK的长度,1616位,如果是16位以下CPU, 一般选1;如果是32
//位系统,一般选0
#define configUSE_16_BIT_TICKS          0
// 简单理解一下就是和IDLE TASK同样优先级的任务执行情况。建议设成1,对系统影响不大
#define configIDLE_SHOULD_YIELD         1
//是否用MUTEXES。 MUTEXES是任务间通讯的一种方式,特别是用于任务共享资源的应//用,比如打印机,任务A用的时候就排斥别的任务应用,用完了别的任务才可以应用。
#define configUSE_MUTEXES               1
//用于DEBUG,登记SEMAPHORESQ和QUEUE的最大个数, 需要在任务用应用函数//vQueueAddToRegistry()和vQueueUnregisterQueue()
#define configQUEUE_REGISTRY_SIZE       8
//此项用于DEBUG, 来看是否有栈溢出,需要你自己编相应检查函数void //vApplicationStackOverflowHook( xTaskHandle *pxTask, signed //portCHAR *pcTaskName )
#define configCHECK_FOR_STACK_OVERFLOW  0
#define configUSE_RECURSIVE_MUTEXES     1// 确定是否用递归式的MUTEXES
#define configUSE_MALLOC_FAILED_HOOK    1
#define configUSE_APPLICATION_TASK_TAG  0
#define configUSE_COUNTING_SEMAPHORES   1
#define configGENERATE_RUN_TIME_STATS   0
#define configUSE_QUEUE_SETS            1
// Co-routine definitions.
//是用用协程。协程公用堆栈,节省RAM,但是没有任务优先级高,也无法和任务通讯 设置//为1则包含co-routines 功能,如果包含了co-routines功能,则编译时需包含croutine.c 文件
#define configUSE_CO_ROUTINES       0
//co-routines 可以使用的优先级的数量
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
//Software timer definitions.
#define configUSE_TIMERS                1//设置为1则包含软件定时器功能
#define configTIMER_TASK_PRIORITY       ( 2 )//设置软件定时器任务的优先级
//设置软件定时器任务中用到的命令队列的长度
#define configTIMER_QUEUE_LENGTH        10
//设置软件定时器任务需要的任务堆栈大小。
#define        configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE * 2 )
// Set the following definitions to 1 to include the API function, or zero
//to exclude the API function.
#define INCLUDE_vTaskPrioritySet        1// 设定可以改变任务优先度
#define INCLUDE_uxTaskPriorityGet       1// 设定可以查询任务优先度
#define INCLUDE_vTaskDelete             1// 设定可以删除任务
// 据说是可以回收删除任务后的资源(RAM等)
#define INCLUDE_vTaskCleanUpResources   1
#define INCLUDE_vTaskSuspend            1 //设置可以把任务挂起
// 设置任务延迟的绝对时间,比如现在430,延迟到500。时间都是绝对时间
#define INCLUDE_vTaskDelayUntil         1
// 设置任务延时,比如延迟30分钟,相对的时间,现在什么时间,不需要知道
#define INCLUDE_vTaskDelay    1
#define INCLUDE_xTaskGetSchedulerState 1 //设置取得当前任务分配器的状态
#define INCLUDE_xTaskGetCurrentTaskHandle 1 //设置当前任务是由哪个任务开的
//是否使能这一函数,函数的目的是返回任务执行后任务堆栈的最小未用数量,同样是为防止//堆栈溢出
#define INCLUDE_uxTaskGetStackHighWaterMark 0

// 系统内核的中断优先级,中断优先级越低,越不会影响其他中断。一般设成最低
#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
// 系统SVC中断优先级,这两项都在在M3和PIC32上应用
#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
configASSERT
configASSERT()的作用类似C语言标准库中的宏assert()configASSERT() 可以帮助调试,但是定义了configASSERT()后会增加程序代码,也会使程序变慢。
Demo_FreeRtos.rar (1.07 MB, 下载次数: 38)
回复

使用道具 举报

  • TA的每日心情
    擦汗
    2016-12-4 23:20
  • 签到天数: 3 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    9

    主题

    573

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1785
    最后登录
    2017-3-3
    发表于 2015-9-17 09:06:15 | 显示全部楼层
    先收藏,
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2019-10-17 08:07
  • 签到天数: 273 天

    连续签到: 1 天

    [LV.8]以坛为家I

    74

    主题

    2338

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    7508
    最后登录
    2021-8-30
    发表于 2015-9-17 09:08:44 | 显示全部楼层
    坚决支持楼主
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2017-5-3 11:19
  • 签到天数: 10 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    50

    主题

    1万

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    14090
    最后登录
    2024-4-19
    发表于 2015-9-17 09:28:00 | 显示全部楼层
    坚决支持楼主 blank.png blank1.png blank2.png blank3.png blank4.png blank5.png blank6.png blank7.png blank8.png blank9.png
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2016-11-24 10:19
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    50

    主题

    1028

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2870
    最后登录
    1970-1-1
    发表于 2015-9-17 09:48:17 | 显示全部楼层
    好详细     
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    61

    主题

    965

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2394
    最后登录
    1970-1-1
     楼主| 发表于 2015-9-17 11:33:12 | 显示全部楼层

    谢谢      
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    61

    主题

    965

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2394
    最后登录
    1970-1-1
     楼主| 发表于 2015-9-17 11:34:02 | 显示全部楼层

    希望对大家有用
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    61

    主题

    965

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2394
    最后登录
    1970-1-1
     楼主| 发表于 2015-9-17 11:34:25 | 显示全部楼层

    有用就好            
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    61

    主题

    965

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2394
    最后登录
    1970-1-1
     楼主| 发表于 2015-9-17 11:35:39 | 显示全部楼层

    边移植编写的,碰到的问题及解决方法记录下来,让有需要的人少走弯路
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-2-9 14:16
  • 签到天数: 17 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    25

    主题

    1785

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2250
    最后登录
    2024-6-11
    发表于 2015-9-17 14:13:54 | 显示全部楼层
    楼主不错,板子刚收到,系统都移植好了
    freescaleic.org.png
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-21 20:56 , Processed in 0.113294 second(s), 31 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表