中国汽车工程师之家--聚集了汽车行业80%专业人士 

论坛口号:知无不言,言无不尽!QQ:542334618 

本站手机访问:直接在浏览器中输入本站域名即可 

搜索附件  
汽车工程师之家 附件中心 结构原理专业知识特区 『汽车控制器VCU/BMS/MCU/域控』 Tc397 + hightec 编译器 移植 freertosw1.jpg
左侧广告
附件中心&附件聚合2.0
For Discuz! X2.5 © hgcad.com

Tc397 + hightec 编译器 移植 freertosw1.jpg

 

Tc397 + hightec 编译器 移植 freertos:


前言:autosar os 确实很强,但是我们在学习一些汽车软件的协议栈的时候,比如学习以太网协议栈,CAN 协议栈, 诊断等 相关知识的时候,需要os, 但是也不至于把os 搞一遍,这时候我们的开发环境就需要一个简单好用的操作系统。

于是我网上找了各种资源,也没找到找到tc397 + hightec 编译器的 freertos 说明。于是 自己做一个吧。

目录





需要完整环境,可以在最下方打赏领取。谢谢,制作不易


背景

硬件编译环境

芯片:Aurix Tc39x

编译器:Hightec

移植 freertos 操作系统。

freertos git 地址

JSON                 
https://github.com/FreeRTOS/FreeRTOS-Kernel.git

Rtos 源码地址

也可以访问官网去下载,学习。

JSON                 
https://www.FreeRTOS.org                 
https://github.com/FreeRTOS

[img=552.010009765625,293.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia6rNxWeib28VMFh0GicWKgicwCibUw5muiclDu7wJ0ehTHC1IYRR3K2cKzvJZaxALBUFM5LVB1wnLHhmTQ/640?wx_fmt=png[/img]
   

本文介绍 基于 硬件 aurix tc397 编译器 hightec 的环境 去移植 freertos.  内核版本

JSON                 
FreeRTOS Kernel V10.5.1

移植freertos项目

工程 代码目录结构

JSON                 
├─asw                 
├─Configurations                 
│  └─Debug                 
├─Libraries                 
│  ├─iLLD                 
│  │  └─TC39B                 
│  │      └─Tricore                 
│  │          ├─Asclin                 
│  │          │  ├─Asc                 
│  │          │  ├─Lin                 
│  │          │  ├─Spi                 
│  │          │  └─Std                 
│  │          ├─Can                 
│  │          │  ├─Can                 
│  │          │  └─Std                 
│  │          ├─Ccu6                 
│  │          │  ├─Icu                 
│  │          │  ├─PwmBc                 
│  │          │  ├─PwmHl                 
│  │          │  ├─Std                 
│  │          │  ├─Timer                 
│  │          │  ├─TimerWithTrigger                 
│  │          │  └─TPwm                 
│  │          ├─Convctrl                 
│  │          │  └─Std                 
│  │          ├─Cpu                 
│  │          │  ├─Irq                 
│  │          │  ├─Std                 
│  │          │  └─Trap                 
│  │          ├─Dma                 
│  │          │  ├─Dma                 
│  │          │  └─Std                 
│  │          ├─Dts                 
│  │          │  ├─Dts                 
│  │          │  └─Std                 
│  │          ├─Ebu                 
│  │          │  ├─BFlashSpansion                 
│  │          │  ├─BFlashSt                 
│  │          │  ├─Dram                 
│  │          │  ├─Sram                 
│  │          │  └─Std                 
│  │          ├─Edsadc                 
│  │          │  ├─Edsadc                 
│  │          │  └─Std                 
│  │          ├─Emem                 
│  │          │  └─Std                 
│  │          ├─Eray                 
│  │          │  ├─Eray                 
│  │          │  └─Std                 
│  │          ├─Evadc                 
│  │          │  ├─Adc                 
│  │          │  └─Std                 
│  │          ├─Fce                 
│  │          │  ├─Crc                 
│  │          │  └─Std                 
│  │          ├─Flash                 
│  │          │  └─Std                 
│  │          ├─Geth                 
│  │          │  ├─Eth                 
│  │          │  └─Std                 
│  │          ├─Gpt12                 
│  │          │  ├─IncrEnc                 
│  │          │  └─Std                 
│  │          ├─Gtm                 
│  │          │  ├─Atom                 
│  │          │  │  ├─Dtm_PwmHl                 
│  │          │  │  ├─Pwm                 
│  │          │  │  ├─PwmHl                 
│  │          │  │  └─Timer                 
│  │          │  ├─Std                 
│  │          │  ├─Tim                 
│  │          │  │  ├─In                 
│  │          │  │  └─Timer                 
│  │          │  ├─Tom                 
│  │          │  │  ├─Dtm_PwmHl                 
│  │          │  │  ├─Pwm                 
│  │          │  │  ├─PwmHl                 
│  │          │  │  └─Timer                 
│  │          │  └─Trig                 
│  │          ├─Hspdm                 
│  │          │  └─Std                 
│  │          ├─Hssl                 
│  │          │  ├─Hssl                 
│  │          │  └─Std                 
│  │          ├─I2c                 
│  │          │  ├─I2c                 
│  │          │  └─Std                 
│  │          ├─Iom                 
│  │          │  ├─Driver                 
│  │          │  ├─Iom                 
│  │          │  └─Std                 
│  │          ├─Msc                 
│  │          │  ├─Msc                 
│  │          │  └─Std                 
│  │          ├─Mtu                 
│  │          │  └─Std                 
│  │          ├─Pms                 
│  │          │  └─Std                 
│  │          ├─Port                 
│  │          │  ├─Io                 
│  │          │  └─Std                 
│  │          ├─Psi5                 
│  │          │  ├─Psi5                 
│  │          │  └─Std                 
│  │          ├─Psi5s                 
│  │          │  ├─Psi5s                 
│  │          │  └─Std                 
│  │          ├─Qspi                 
│  │          │  ├─SpiMaster                 
│  │          │  ├─SpiSlave                 
│  │          │  └─Std                 
│  │          ├─Rif                 
│  │          │  ├─Rif                 
│  │          │  └─Std                 
│  │          ├─Scu                 
│  │          │  └─Std                 
│  │          ├─Sdmmc                 
│  │          │  ├─Emmc                 
│  │          │  ├─Sd                 
│  │          │  └─Std                 
│  │          ├─Sent                 
│  │          │  ├─Sent                 
│  │          │  └─Std                 
│  │          ├─Smu                 
│  │          │  ├─Smu                 
│  │          │  └─Std                 
│  │          ├─Spu                 
│  │          │  └─Std                 
│  │          ├─Src                 
│  │          │  └─Std                 
│  │          ├─Stm                 
│  │          │  ├─Std                 
│  │          │  └─Timer                 
│  │          ├─_Build                 
│  │          ├─_Impl                 
│  │          ├─_Lib                 
│  │          │  ├─DataHandling                 
│  │          │  └─InternalMux                 
│  │          └─_PinMap                 
│  ├─Infra                 
│  │  ├─Platform                 
│  │  │  └─Tricore                 
│  │  │      └─Compilers                 
│  │  ├─Sfr                 
│  │  │  └─TC39B                 
│  │  │      └─_Reg                 
│  │  └─Ssw                 
│  │      └─TC39B                 
│  │          └─Tricore                 
│  └─Service                 
│      └─CpuGeneric                 
│          ├─If                 
│          │  └─Ccu6If                 
│          ├─StdIf                 
│          ├─SysSe                 
│          │  ├─Bsp                 
│          │  ├─Comm                 
│          │  ├─General                 
│          │  ├─Math                 
│          │  └─Time                 
│          └─_Utilities                 
└─os                 
    └─FreeRTOS                 
        ├─include                 
        └─portable                 
            ├─GCC                 
            │  └─TC3                 
            ├─MemMang                 
            │  └─reserve                 
            └─Tasking                 
                └─TC3        

初始环境

通过上面的文件夹结构,大家也能发现,base 实际上是aurix 的 iLLD环境。没错,我们一开始需要一个能跑到 main 的 无操作系统环境。

初始项目环境

这个环境怎么获取呢。可以通过aurix 的IDE 新建一个项目即可。

[img=94.0,81.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia6rNxWeib28VMFh0GicWKgicwCOorI1UQ7UeE0emBib3F45tQz8Yick7OiaSvjXtoFTiaia9OfEmw3qjKibIiag/640?wx_fmt=png[/img]

确保 main 可以跑到。这个怎么验证呢。

JSON                 
    /*Call main function of Cpu0 */                 
    Ifx_Ssw_jumpToFunction(core0_main);

在main 里面写好标识,调试一下即可。默认的环境应该都是可以的。

链接文件

注意 IDE 使用的默认编译器是tasking. 如果我们想换成 hightec 的编译器,需要修改 连接文件。

这里我们使用默认的地址分配。

JSON                 
MEMORY                 
{                 
    dsram5_local (w!xp): org = 0xd0000000, len = 96K                 
    dsram5 (w!xp): org = 0x10000000, len = 96K                 
    psram5 (w!xp): org = 0x10100000, len = 64K                 
                     
    dsram4_local (w!xp): org = 0xd0000000, len = 96K                 
    dsram4 (w!xp): org = 0x30000000, len = 96K                 
    psram4 (w!xp): org = 0x30100000, len = 64K                 
                     
    dsram3_local (w!xp): org = 0xd0000000, len = 96K                 
    dsram3 (w!xp): org = 0x40000000, len = 96K                 
    psram3 (w!xp): org = 0x40100000, len = 64K                 
                     
    dsram2_local (w!xp): org = 0xd0000000, len = 96K                 
    dsram2 (w!xp): org = 0x50000000, len = 96K                 
    psram2 (w!xp): org = 0x50100000, len = 64K                 
                     
    dsram1_local (w!xp): org = 0xd0000000, len = 240K                 
    dsram1 (w!xp): org = 0x60000000, len = 240K                 
    psram1 (w!xp): org = 0x60100000, len = 64K                 
                     
    dsram0_local (w!xp): org = 0xd0000000, len = 240K                 
    dsram0 (w!xp): org = 0x70000000, len = 240K                 
    psram0 (w!xp): org = 0x70100000, len = 64K                 
                     
    psram_local (w!xp): org = 0xc0000000, len = 64K                 
                     
    pfls0 (rx!p): org = 0x80000000, len = 3M                 
    pfls0_nc (rx!p): org = 0xa0000000, len = 3M                 
                     
    pfls1 (rx!p): org = 0x80300000, len = 3M                 
    pfls1_nc (rx!p): org = 0xa0300000, len = 3M                 
                     
    pfls2 (rx!p): org = 0x80600000, len = 3M                 
    pfls2_nc (rx!p): org = 0xa0600000, len = 3M                 
                     
    pfls3 (rx!p): org = 0x80900000, len = 3M                 
    pfls3_nc (rx!p): org = 0xa0900000, len = 3M                 
                     
    pfls4 (rx!p): org = 0x80c00000, len = 3M                 
    pfls4_nc (rx!p): org = 0xa0c00000, len = 3M                 
                     
    pfls5 (rx!p): org = 0x80f00000, len = 1M                 
    pfls5_nc (rx!p): org = 0xa0f00000, len = 1M                 
                     
    dfls0 (rx!p): org = 0xaf000000, len = 1M                 
                     
    ucb (rx!p): org = 0xaf400000, len = 24K                 
                     
    cpu0_dlmu (w!xp): org = 0x90000000, len = 64K                 
    cpu0_dlmu_nc (w!xp): org = 0xb0000000, len = 64K                 
                     
    cpu1_dlmu (w!xp): org = 0x90010000, len = 64K                 
    cpu1_dlmu_nc (w!xp): org = 0xb0010000, len = 64K                 
                     
    cpu2_dlmu (w!xp): org = 0x90020000, len = 64K                 
    cpu2_dlmu_nc (w!xp): org = 0xb0020000, len = 64K                 
                     
    cpu3_dlmu (w!xp): org = 0x90030000, len = 64K                 
    cpu3_dlmu_nc (w!xp): org = 0xb0030000, len = 64K                 
                     
    lmuram (w!xp): org = 0x90040000, len = 768K                 
    lmuram_nc (w!xp): org = 0xb0040000, len = 768K                 
                     
    cpu4_dlmu (w!xp): org = 0x90100000, len = 64K                 
    cpu4_dlmu_nc (w!xp): org = 0xb0100000, len = 64K                 
                     
    cpu5_dlmu (w!xp): org = 0x90110000, len = 64K                 
    cpu5_dlmu_nc (w!xp): org = 0xb0110000, len = 64K                 
                     
    edmem (w!xp): org = 0x99000000, len = 4M                 
    edmem_nc (w!xp): org = 0xb9000000, len = 4M                 
}

起始地址函数

JSON                 
void cstart(void)                 
{                 
    Ifx_Ssw_jumpToFunction(__StartUpSoftware);                 
}

需要根据实际的编译选项来修改。

到这里初始项目环境已经完毕。

添加os源码到工程

在这个基础上我们添加了 os的源码

JSON                 
└─os                 
    └─FreeRTOS                 
        ├─include                 
        └─portable                 
            ├─GCC                 
            │  └─TC3                 
            ├─MemMang                 
            │  └─reserve                 
            └─Tasking                 
                └─TC3

移植

堆使用

Rtos  对象是动态创建的所以需要用到 C 库 malloc() 和 free() 函数。但是这里不是直接使用 标准C 接口,而是进行了 丰富,优化,约束。

当 RTOS 内核需要 RAM 时,它不调用 malloc(),而是调用 pvPortMalloc()。释放 RAM 时, RTOS 内核调用 vPortFree(),而不是 free()。

在 rtos 源码中提供了下面五种 堆内存使用方式。在我们移植的时候,只需要选择其中一种。

1heap_1 —— 最简单,不允许释放内存。

1heap_2—— 允许释放内存,但不会合并相邻的空闲块。

1heap_3 —— 简单包装了标准 malloc() 和 free(),以保证线程安全。

1heap_4 —— 合并相邻的空闲块以避免碎片化。包含绝对地址放置选项。

1heap_5 —— 如同 heap_4,能够跨越多个不相邻内存区域的堆。

为了简单。本文使用了heap_1.c  ( heap_1 不太有用,因为 FreeRTOS 添加了静态分配支持)

所以在移植过程 文件夹MemMang 文件夹下面的五个文件

JSON                 
    heap_1.c                 
    heap_2.c                 
    heap_3.c                 
    heap_4.c                 
    heap_5.c

只需要保留 heap_1.c

FreeRTOSConfig.h

这里需要根据tc397的芯片手册进行修改。

比如 300M的主频

JSON                 
#define configCPU_CLOCK_HZ                         ( ( unsigned long ) 300000000UL )

下面这些定时器,中断相关的参数

比如下面的STM 的clc 控制寄存器,寄存器地址就需要去芯片手册里找。我这里找一个

JSON                 
/** \brief 0, Clock Control Register */                 
#define STM0_CLC /*lint --e(923, 9078)*/ (*(volatile Ifx_STM_CLC*)0xF0001000u)                 
/** \brief Clock Control Register */                 
typedef struct _Ifx_STM_CLC_Bits                 
{                 
    Ifx_UReg_32Bit DISR:1;            /**< \brief [0:0] Module Disable Request Bit - DISR (rw) */                 
    Ifx_UReg_32Bit DISS:1;            /**< \brief [1:1] Module Disable Status Bit - DISS (r) */                 
    Ifx_UReg_32Bit reserved_2:1;      /**< \brief [2:2] \internal Reserved */                 
    Ifx_UReg_32Bit EDIS:1;            /**< \brief [3:3] Sleep Mode Enable Control - EDIS (rw) */                 
    Ifx_UReg_32Bit reserved_4:28;     /**< \brief [31:4] \internal Reserved */                 
} Ifx_STM_CLC_Bits;

下面给出全部的 该文件对应 tc397  配置。

JSON                 
#ifndef FREERTOS_CONFIG_H                 
#define FREERTOS_CONFIG_H                 
                 
#define configUSE_PREEMPTION                       1                 
#define configUSE_IDLE_HOOK                        0                 
                 
#define configCPU_CLOCK_HZ                         ( ( unsigned long ) 300000000UL )                 
#define configTICK_RATE_HZ                         ( ( TickType_t ) 1000UL )                 
                 
#define configMAX_PRIORITIES                       ( 10 )                 
#define configMINIMAL_STACK_SIZE                   ( ( unsigned short ) 256 )                 
#define configTOTAL_HEAP_SIZE                      ( ( size_t ) ( 48U * 1024U ) )                 
#define configMAX_TASK_NAME_LEN                    ( 16 )                 
                 
#define configENABLE_BACKWARD_COMPATIBILITY        0                 
#define configUSE_TRACE_FACILITY                   0                 
#define configUSE_16_BIT_TICKS                     0                 
#define configIDLE_SHOULD_YIELD                    0                 
#define configUSE_MALLOC_FAILED_HOOK               0                 
#define configCHECK_FOR_STACK_OVERFLOW             1                 
#define configUSE_TICK_HOOK                        0                 
#define configUSE_COUNTING_SEMAPHORES              1                 
#define configUSE_RECURSIVE_MUTEXES                1                 
#define configUSE_MUTEXES                          1                 
#define configRECORD_STACK_HIGH_ADDRESS            1                 
                 
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS    5                 
                 
/* Software timer configuration. */                 
#define configUSE_TIMERS                           ( 1 )                 
#define configTIMER_TASK_PRIORITY                  ( 9 )                 
#define configTIMER_QUEUE_LENGTH                   ( 5 )                 
#define configTIMER_TASK_STACK_DEPTH               configMINIMAL_STACK_SIZE                 
                 
/* 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                 
#define INCLUDE_vTaskCleanUpResources              1                 
#define INCLUDE_vTaskSuspend                       1                 
#define INCLUDE_vTaskDelayUntil                    1                 
#define INCLUDE_vTaskDelay                         1                 
                 
/* Interrupt above priority 31 are not effected by critical sections, but cannot call interrupt safe FreeRTOS functions. */                 
#define configMAX_API_CALL_INTERRUPT_PRIORITY      31                 
                 
/* Default definition of configASSERT(). */                 
#ifdef DEBUG                 
#ifdef __TASKING__                 
#define configASSERT( x )    if( ( x ) == 0 ) { __disable(); __debug(); }                 
#endif                 
#ifdef __clang__                 
#define configASSERT( x )    if( ( x ) == 0 ) { __builtin_tricore_disable(); __builtin_tricore_debug(); }                 
#endif                 
#else                 
#define configASSERT( x ) ((void)(x)) /* Empty macro to remove compiler warning(s) about unused variables */                 
#endif                 
                 
/* AURIX TCxxx definitions */                 
#define configCONTEXT_INTERRUPT_PRIORITY    1                  
#define configTIMER_INTERRUPT_PRIORITY      200 /* This value must not be bigger then context priority */                 
#define configCPU_NR                        0                 
#define configPROVIDE_SYSCALL_TRAP          0                 
#define configSYSCALL_CALL_DEPTH            2                 
#define configSTM                           ( ( uint32_t * ) (0xF0001000 + configCPU_NR*0x100 ) )                 
#define configSTM_SRC                       ( ( uint32_t * ) (0xF0038300 + configCPU_NR*0x8) )                 
#define configSTM_CLOCK_HZ                  ( 100000000 )                 
#define configSTM_DEBUG                     ( 1 )                 
#define configCONTEXT_SRC                   ( ( uint32_t * ) 0xF0038990 )                 
                 
#endif /* FREERTOS_CONFIG_H */                 


port.c 与 portmacro.h

这两个文件是需要开发者主要关注的文件。里面包含了大量的针对板子的移植工作。

比如根据芯片手册查到的 寄存器地址

寄存器地址

[img=552.010009765625,415.0100402832031]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia6rNxWeib28VMFh0GicWKgicwC33wuBvVbStP0WrKGl60uiaibsNqV4GEeL6dZiczmO98eyadzP76NImgxQ/640?wx_fmt=png[/img]

截图出自 TC3xx Architecture vol1 V1.2.2.pdf         

对应的移植就是

JSON                 
#define portCPU_PSW              0xFE04                 
#define portCPU_PSW_IS_OFF       ( 9 )                 
#define portCPU_PSW_CSC_MSK      ( 0x7F )                 
#define portCPU_ICR              0xFE2C                 
#define portCPU_ICR_CCPN_OFF     ( 0 )                 
#define portCPU_ICR_CCPN_MSK     ( 0x000000FFUL )                 
#define portCPU_FCX              0xFE38                 
#define portCPU_PCXI             0xFE00                 
#define portCPU_CORE_ID          0xFE1C

数据类型定义

JSON                 
/* Type definitions. */                 
#define portCHAR                 char                 
#define portSHORT                short                 
#define portLONG                 long                 
#define portFLOAT                float                 
#define portDOUBLE               double                 
#define portSTACK_TYPE           unsigned int                 
#define portBASE_TYPE            long                 
#define portPOINTER_SIZE_TYPE    uintptr_t

编译器指令

JSON                 
/* Instructions */                 
#define portNOP()               _nop()                 
#define portMEMORY_BARRIER()    _dsync()

话不多说,直接给出 portmacro.h

JSON                 
                 
#ifndef PORTMACRO_H                 
#define PORTMACRO_H                 
                 
#ifdef __cplusplus                 
    extern "C"                 
#endif                 
                 
#include "FreeRTOSConfig.h"                 
#include
         
#define portCPU_PSW              0xFE04         
#define portCPU_PSW_IS_OFF       ( 9 )         
#define portCPU_PSW_CSC_MSK      ( 0x7F )         
#define portCPU_ICR              0xFE2C         
#define portCPU_ICR_CCPN_OFF     ( 0 )         
#define portCPU_ICR_CCPN_MSK     ( 0x000000FFUL )         
#define portCPU_FCX              0xFE38         
#define portCPU_PCXI             0xFE00         
#define portCPU_CORE_ID          0xFE1C         
         
/* Register defintions */         
#define portSRC_SRCR_SRPN_OFF    0         
#define portSRC_SRCR_SRE_OFF     10         
#define portSRC_SRCR_TOS_OFF     11         
#define portSRC_SRCR_SRR_OFF     24         
#define portSRC_SRCR_SETR_OFF    26         
         
/* Type definitions. */         
#define portCHAR                 char         
#define portSHORT                short         
#define portLONG                 long         
#define portFLOAT                float         
#define portDOUBLE               double         
#define portSTACK_TYPE           unsigned int         
#define portBASE_TYPE            long         
#define portPOINTER_SIZE_TYPE    uintptr_t         
         
typedef portSTACK_TYPE       StackType_t;         
typedef long                 BaseType_t;         
typedef unsigned long        UBaseType_t;         
         
#if ( configUSE_16_BIT_TICKS == 1 )         
    typedef unsigned short   TickType_t;         
    #define portMAX_DELAY    ( TickType_t ) 0xffff         
#else         
    typedef unsigned int     TickType_t __attribute__( ( aligned( 4 ) ) );         
    #define portMAX_DELAY    ( TickType_t ) 0xffffffffUL         
#endif         
         
/* FreeRTOS parameters */         
#define portTICK_TYPE_IS_ATOMIC        1         
#define portSTACK_GROWTH               ( -1 )         
#define portTICK_PERIOD_MS             ( ( TickType_t ) 1000 / configTICK_RATE_HZ )         
#define portBYTE_ALIGNMENT             8         
#define portCRITICAL_NESTING_IN_TCB    0         
         
/* Attributes */         
#define portDONT_DISCARD               __attribute__( ( used ) )         
#define portNORETURN                   __attribute__( ( noreturn ) )         
         
/* Instructions */         
#define portNOP()               _nop()         
#define portMEMORY_BARRIER()    _dsync()         
         
/* Critical section management */         
extern void vPortEnterCritical( void );         
extern void vPortExitCritical( void );         
#define portENTER_CRITICAL()                                     vPortEnterCritical()         
#define portEXIT_CRITICAL()                                      vPortExitCritical()         
#define portENABLE_INTERRUPTS()                                  vPortSetCCPN( 0 );         
#define portDISABLE_INTERRUPTS()                                 vPortSetCCPN( configMAX_API_CALL_INTERRUPT_PRIORITY )         
#define portASSERT_IF_IN_ISR()                                   configASSERT( ( _mfcr( portCPU_PSW ) & ( 1 << portCPU_PSW_IS_OFF ) ) == 0 )         
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedMaskValue )    vPortSetICR( ulSavedMaskValue )         
#define portSET_INTERRUPT_MASK_FROM_ISR()                        xPortSetCCPN( configMAX_API_CALL_INTERRUPT_PRIORITY )         
         
#ifndef configYIELD_SYSCALL_ID         
    #define configYIELD_SYSCALL_ID    0         
#endif         
         
#define portYIELD()    _syscall( configYIELD_SYSCALL_ID )         
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken )                                                                                \         
    {                                                                                                                                 \         
        const uint32_t xTrigger = ( ( *configCONTEXT_SRC >> portSRC_SRCR_SRR_OFF ) & 0x1 ) != 1 && ( xHigherPriorityTaskWoken != 0 ); \         
        *configCONTEXT_SRC |= ( xTrigger << portSRC_SRCR_SETR_OFF );                                                                  \         
                                                                                                                                      \         
        /* Wait until write request completes to trigger IRQ */                                                                       \         
        _dsync();                                                                                                                     \         
        _isync();                                                                                                                     \         
    }         
         
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION         
    #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1         
#endif         
         
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )         
         
/* Check the configuration. */         
    #if ( configMAX_PRIORITIES > 32 )         
        #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.         
    #endif         
         
/* Store/clear the ready priorities in a bit map. */         
    #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities )      ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )         
    #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities )       ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )         
         
    #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )    uxTopPriority = ( 31UL - ( ( uint32_t ) __builtin_clz( ( uxReadyPriorities ) ) ) )         
         
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */         
         
/* Function prototypes */         
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )         
#define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )         
         
/* TCB handling */         
extern void vPortReclaimCSA( unsigned long ** pxTCB );         
#define portCLEAN_UP_TCB( pxTCB )    vPortReclaimCSA( ( unsigned long ** ) ( pxTCB ) )         
         
/* ICR & CCPN modifying functions to enable and disable interrupts.         
* Only interrupts with a priority lower than         
*/         
static void __attribute__( ( used, always_inline ) ) vPortSetCCPN( unsigned char ucCCPN )         
{         
    _disable();         
    _mtcr( portCPU_ICR, ( _mfcr( portCPU_ICR ) & ~portCPU_ICR_CCPN_MSK ) | ( ucCCPN & portCPU_ICR_CCPN_MSK ) );         
    _isync();         
    _enable();         
}         
         
static void __attribute__( ( used, always_inline ) ) vPortSetICR( portBASE_TYPE ulICR )         
{         
    _disable();         
    _mtcr( portCPU_ICR, ( unsigned int ) ulICR );         
    _isync();         
    _enable();         
}         
         
static portBASE_TYPE __attribute__( ( used, always_inline ) ) xPortSetCCPN( unsigned char ucCCPN )         
{         
    unsigned int xICR;         
         
    _disable();         
    xICR = _mfcr( portCPU_ICR );         
    _mtcr( portCPU_ICR, ( xICR & ~portCPU_ICR_CCPN_MSK ) | ( ucCCPN & portCPU_ICR_CCPN_MSK ) );         
    _isync();         
    _enable();         
    return ( portBASE_TYPE ) xICR;         
}         
         
#ifdef __cplusplus         
}         
#endif         
         
#endif /* PORTMACRO_H */         
        

话不多说,直接给出 port.c

JSON                 
                 
#include
#include
#include
           
#include "FreeRTOS.h"           
#include "task.h"           
           
/* Prgoram status word macros */           
#define portINITIAL_SYSTEM_PSW \           
    ( 0x000008FFUL ) /* Supervisor Mode, MPU Register Set 0 and Call Depth Counting disabled. */           
           
/* Context save area macros */           
#define portCSA_FCX_MASK          ( 0x000FFFFFUL )           
#define portINITIAL_LOWER_PCXI    ( 0x00300000UL ) /* Set UL to upper and PIE to 1 */           
#define portINITIAL_UPPER_PCXI    ( 0x00200000UL ) /* Set UL to lower and PIE to 1 */           
#define portNUM_WORDS_IN_CSA      ( 16 )           
           
extern volatile unsigned long * pxCurrentTCB;           
           
/* Tick and context switch config */           
#define portTICK_COUNT    ( configSTM_CLOCK_HZ / configTICK_RATE_HZ )           
           
/* Register defines */           
static volatile uint32_t *const pxStm = configSTM;           
static volatile uint32_t *const pxStmSrc = configSTM_SRC;           
static volatile uint32_t *const pxContextSrc = configCONTEXT_SRC;           
#define portSTM_TIM0                 0x10           
#define portSTM_CMP0                 0x30           
#define portSTM_COMCON               0x38           
#define portSTM_ICR                  0x3C           
#define portSTM_ISCR                 0x40           
#define portSTM_OCS                  0xE8           
           
#define portSTM_CMCON_MSTART0_OFF    8           
#define portSTM_CMCON_MSIZE0_OFF     0           
#define portSTM_ICR_CMP0EN_OFF       0           
#define portSTM_ICR_CMP0OS_OFF       2           
#define portSTM_ISCR_CMP0IRR_OFF     0           
           
static inline void vPortStartFirstTask( void );           
static inline void vPortInitContextSrc( void );           
static inline void vPortInitTickTimer( void );           
           
static inline void __attribute__( ( always_inline ) ) vPortLoadContext( unsigned char ucCallDepth );           
static inline void __attribute__( ( always_inline ) ) vPortSaveContext( unsigned char ucCallDepth );           
           
static inline uint32_t * __attribute__( ( always_inline ) ) pxPortCsaToAddress( uint32_t xCsa );           
           
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;           
           
/* FreeRTOS required functions */           
BaseType_t xPortStartScheduler( void )           
{           
    vPortInitTickTimer();           
    vPortInitContextSrc();           
    vPortStartFirstTask();           
           
    return 0;           
}           
           
void vPortEndScheduler()           
{           
    pxStmSrc[ 0 ] &= ~( 1 << portSRC_SRCR_SRE_OFF );           
    pxContextSrc[ 0 ] &= ~( 1 << portSRC_SRCR_SRE_OFF );           
}           
           
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack,           
                                    TaskFunction_t pxCode,           
                                    void * pvParameters )           
{           
    uint32_t xLowerCsa = 0, xUpperCsa = 0;           
    uint32_t * pxUpperCSA = NULL;           
    uint32_t * pxLowerCSA = NULL;           
           
    /* Have to disable interrupts here because the CSAs are going to be           
     * manipulated. */           
    _disable();           
    {           
        /* DSync to ensure that buffering is not a problem. */           
        _dsync();           
           
        /* Consume two free CSAs. */           
        xLowerCsa = _mfcr( portCPU_FCX );           
        pxLowerCSA = pxPortCsaToAddress( xLowerCsa );           
           
        if( pxLowerCSA != NULL )           
        {           
            /* The Lower Links to the Upper. */           
            xUpperCsa = pxLowerCSA[ 0 ];           
            pxUpperCSA = pxPortCsaToAddress( pxLowerCSA[ 0 ] );           
        }           
           
        /* Check that we have successfully reserved two CSAs. */           
        if( ( pxLowerCSA != NULL ) && ( pxUpperCSA != NULL ) )           
        {           
            /* Remove the two consumed CSAs from the free CSA list. */           
            _mtcr( portCPU_FCX, pxUpperCSA[ 0 ] );           
            _isync();           
        }           
        else           
        {           
            /* Simply trigger a context list depletion trap. */           
            __asm( "\tsvlcx" );           
        }           
    }           
    _enable();           
           
    /* Upper Context. */           
    memset( pxUpperCSA, 0, portNUM_WORDS_IN_CSA * sizeof( uint32_t ) );           
    pxUpperCSA[ 2 ] = ( uint32_t ) pxTopOfStack; /* A10;    Stack Return aka Stack Pointer */           
    pxUpperCSA[ 1 ] = portINITIAL_SYSTEM_PSW;    /* PSW    */           
    pxUpperCSA[ 0 ] = portINITIAL_UPPER_PCXI;           
           
    /* Lower Context. */           
    memset( pxLowerCSA, 0, portNUM_WORDS_IN_CSA * sizeof( uint32_t ) );           
    pxLowerCSA[ 8 ] = ( uint32_t ) pvParameters;          /* A4;    Address Type Parameter Register    */           
    pxLowerCSA[ 1 ] = ( uint32_t ) pxCode;                /* A11;    Return Address aka RA */           
    pxLowerCSA[ 0 ] = portINITIAL_LOWER_PCXI | xUpperCsa; /* PCXI pointing to the Upper context. */           
           
    /* Initialize the uxCriticalNesting. */           
    pxTopOfStack--;           
    *pxTopOfStack = 0;           
    /* Save the link to the CSA to the top of stack. */           
    pxTopOfStack--;           
    *pxTopOfStack = xLowerCsa;           
           
    return pxTopOfStack;           
}           
           
void __attribute__( ( interrupt_handler ) ) vPortSystemContextHandler()           
{           
    /* Disable interrupts to protect section*/           
    _disable();           
           
    /* Do a save, switch, execute */           
    vPortSaveContext( 0 );           
    vTaskSwitchContext();           
    vPortLoadContext( 0 );           
           
    _enable();           
}           
           
#define STR( x )     # x           
#define XSTR( s )    STR( s )           
__asm__ (           
    " .pushsection .intvec_tc" XSTR( configCPU_NR ) "_" XSTR( configCONTEXT_INTERRUPT_PRIORITY ) ",\"ax\",@progbits\n"           
                                                                                                 " .align 5\n"           
                                                                                                 " __intvec_entry_" XSTR( configCONTEXT_INTERRUPT_PRIORITY ) ":\n"           
                                                                                                                                                             " svlcx\n"           
                                                                                                                                                             " movh.a %a14, hi:vPortSystemContextHandler\n"           
                                                                                                                                                             " lea %a14, [%a14]lo:vPortSystemContextHandler\n"           
                                                                                                                                                             " ji %a14\n"           
                                                                                                                                                             " .org 32\n"           
                                                                                                                                                             " .popsection\n" );           
void __attribute__( ( interrupt_handler ) ) vPortSystemTickHandler()           
{           
    unsigned long ulSavedInterruptMask;           
    BaseType_t xYieldRequired;           
           
    /* Increment compare value by tick count */           
    pxStm[ portSTM_CMP0 >> 2 ] = pxStm[ portSTM_CMP0 >> 2 ] + portTICK_COUNT;           
    pxStm[ portSTM_ISCR >> 2 ] |= ( 1 << portSTM_ISCR_CMP0IRR_OFF );           
           
    /* Check for possible tick drop.           
     * If the time is beyond the compare value, the next tick will need a complete           
     * wrap around. The tick count isn't accruate any more. Increase the tick count           
     * or adapt to execute xTaskIncrementTick multiple times depending on the           
     * counts missed.   */           
    #if configCPU_STM_DEBUG != 0           
        configASSERT( ( pxStm[ portSTM_CMP0 >> 2 ] - pxStm[ portSTM_TIM0 >> 2 ] ) <= portTICK_COUNT );           
    #endif           
           
    /* Kernel API calls require Critical Sections. */           
    ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();           
    {           
        /* Increment the Tick. */           
        xYieldRequired = xTaskIncrementTick();           
    }           
    portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );           
           
    portYIELD_FROM_ISR( xYieldRequired );           
}           
           
__asm__ (           
    " .pushsection .intvec_tc" XSTR( configCPU_NR ) "_" XSTR( configTIMER_INTERRUPT_PRIORITY ) ",\"ax\",@progbits\n"           
                                                                                               " .align 5\n"           
                                                                                               " __intvec_entry_" XSTR( configTIMER_INTERRUPT_PRIORITY ) ":\n"           
                                                                                                                                                         " svlcx\n"           
                                                                                                                                                         " movh.a %a14, hi:vPortSystemTickHandler\n"           
                                                                                                                                                         " lea %a14, [%a14]lo:vPortSystemTickHandler\n"           
                                                                                                                                                         " ji %a14\n"           
                                                                                                                                                         " .org 32\n"           
                                                                                                                                                         " .popsection\n" );           
           
void __attribute__( ( noinline ) ) vPortSyscallYield( void );           
           
int vPortSyscallHandler( unsigned char id )           
{           
    switch( id )           
    {           
        case 0:           
            vPortSyscallYield();           
            break;           
           
        default:           
            break;           
    }           
           
    return 0;           
}           
           
void vPortInitTickTimer()           
{           
    pxStm[ portSTM_COMCON >> 2 ] =           
        ( 0 << portSTM_CMCON_MSTART0_OFF ) | ( 31 << portSTM_CMCON_MSIZE0_OFF );           
    pxStm[ portSTM_ICR >> 2 ] &= ~( 1 << portSTM_ICR_CMP0OS_OFF );           
    pxStmSrc[ 0 ] = ( ( configCPU_NR > 0 ?           
                        configCPU_NR + 1 : configCPU_NR ) << portSRC_SRCR_TOS_OFF ) |           
                    ( ( configTIMER_INTERRUPT_PRIORITY ) << portSRC_SRCR_SRPN_OFF );           
    pxStmSrc[ 0 ] |= ( 1 << portSRC_SRCR_SRE_OFF );           
    pxStm[ portSTM_CMP0 >> 2 ] = pxStm[ portSTM_TIM0 >> 2 ];           
    pxStm[ portSTM_ISCR >> 2 ] |= ( 1 << portSTM_ISCR_CMP0IRR_OFF );           
    pxStm[ portSTM_ICR >> 2 ] |= ( 1 << portSTM_ICR_CMP0EN_OFF );           
    pxStm[ portSTM_CMP0 >> 2 ] = pxStm[ portSTM_TIM0 >> 2 ] + portTICK_COUNT;           
    #if configTICK_STM_DEBUG != 0           
        pxStm[ portSTM_OCS >> 2 ] = 0x12000000;           
    #endif           
}           
           
void vPortInitContextSrc()           
{           
    pxContextSrc[ 0 ] =           
        ( ( configCPU_NR > 0 ?           
            configCPU_NR + 1 : configCPU_NR ) << portSRC_SRCR_TOS_OFF ) |           
        ( ( configCONTEXT_INTERRUPT_PRIORITY ) << portSRC_SRCR_SRPN_OFF );           
    pxContextSrc[ 0 ] |= ( 1 << portSRC_SRCR_SRE_OFF );           
}           
           
void vPortStartFirstTask()           
{           
    /* Disable interrupts  */           
    _disable();           
           
    vPortLoadContext( 0 );           
           
    /* Reset the call stack counting, to avoid trap on rfe */           
    unsigned long ulPsw = _mfcr( portCPU_PSW );           
           
    ulPsw &= ~( portCPU_PSW_CSC_MSK );           
    _mtcr( portCPU_PSW, ulPsw );           
    _isync();           
           
    /* Load the lower context and upper context through rfe to enable irqs */           
    __asm( "\trslcx" );           
    __asm( "\trfe" );           
    _nop();           
    _nop();           
    _nop();           
}           
           
void vPortLoadContext( unsigned char ucCallDepth )           
{           
    uint32_t ** ppxTopOfStack;           
    uint32_t uxLowerCSA;           
           
    /* Dsync is required for save CSA access */           
    _dsync();           
           
    /* Load the new CSA id from the stack and update the stack pointer */           
    ppxTopOfStack = ( uint32_t ** ) pxCurrentTCB;           
    uxLowerCSA = **ppxTopOfStack;           
    ( *ppxTopOfStack )++;           
    uxCriticalNesting = **ppxTopOfStack;           
    ( *ppxTopOfStack )++;           
           
    /* Store the lower context directly if inside the syscall or interrupt,           
     * else replace the lower context in the call stack. */           
    if( !ucCallDepth )           
    {           
        /* Update the link register */           
        _mtcr( portCPU_PCXI, uxLowerCSA );           
        _isync();           
    }           
    else           
    {           
        /* Update previous lower context */           
        uint32_t * pxCSA = pxPortCsaToAddress( _mfcr( portCPU_PCXI ) );           
        int i;           
           
        for(i = 0; i < ucCallDepth - 1; i++)           
        {           
            pxCSA = pxPortCsaToAddress( pxCSA[ 0 ] );           
        }           
           
        pxCSA[ 0 ] = uxLowerCSA;           
    }           
}           
           
void vPortSaveContext( unsigned char ucCallDepth )           
{           
    uint32_t ** ppxTopOfStack;           
    uint32_t * pxLowerCSA, * pxUpperCSA;           
    uint32_t uxLowerCSA;           
           
    /* Dsync is required for save CSA access */           
    _dsync();           
           
    /* Get the current context information. */           
    uxLowerCSA = _mfcr( portCPU_PCXI );           
           
    /* If this function is used inside a function from the syscall or interrupt,           
     * load the correct context from the call stack */           
    if( ucCallDepth )           
    {           
        uint32_t * pxCSA = pxPortCsaToAddress( uxLowerCSA );           
        int i;           
           
        for(i = 0; i < ucCallDepth - 1; i++)           
        {           
            pxCSA = pxPortCsaToAddress( pxCSA[ 0 ] );           
        }           
           
        uxLowerCSA = pxCSA[ 0 ];           
    }           
           
    pxLowerCSA = pxPortCsaToAddress( uxLowerCSA );           
    pxUpperCSA = pxPortCsaToAddress( pxLowerCSA[ 0 ] );           
           
    /* Load the stack pointer */           
    ppxTopOfStack = ( uint32_t ** ) pxCurrentTCB;           
    /* Update the stack info in the TCB */           
    *ppxTopOfStack = ( uint32_t * ) pxUpperCSA[ 2 ];           
    /* Place ucNestedContext */           
    ( *ppxTopOfStack )--;           
    **ppxTopOfStack = uxCriticalNesting;           
    /* Place the lower CSA id on the stack */           
    ( *ppxTopOfStack )--;           
    **ppxTopOfStack = uxLowerCSA;           
}           
           
void vPortSyscallYield()           
{           
    /* Do a save, switch, execute */           
    vPortSaveContext( configSYSCALL_CALL_DEPTH );           
    vTaskSwitchContext();           
    vPortLoadContext( configSYSCALL_CALL_DEPTH );           
}           
           
uint32_t * pxPortCsaToAddress( uint32_t xCsa )           
{           
    uint32_t pxCsa;           
           
    __asm ( "extr.u %0, %1, 16, 4\n"           
          "sh     %0, %0, 28\n"           
          "insert %0, %0, %1 6, 16\n" : "+d" ( pxCsa ) : "d" ( xCsa ) );           
    /*pxCsa = (_extr_u(xCsa, 16, 4) << 28); */           
    /*pxCsa = _insert(pxCsa, xCsa, 6, 16); */           
    return ( uint32_t * ) pxCsa;           
}           
           
void vPortEnterCritical( void )           
{           
    portDISABLE_INTERRUPTS();           
    uxCriticalNesting++;           
           
    /* This is not the interrupt safe version of the enter critical function so           
     * assert() if it is being called from an interrupt context.  Only API           
     * functions that end in "FromISR" can be used in an interrupt.  Only assert if           
     * the critical nesting count is 1 to protect against recursive calls if the           
     * assert function also uses a critical section. */           
    if( uxCriticalNesting == 1 )           
    {           
        portASSERT_IF_IN_ISR();           
    }           
}           
           
void vPortExitCritical( void )           
{           
    configASSERT( uxCriticalNesting );           
    uxCriticalNesting--;           
           
    if( uxCriticalNesting == 0 )           
    {           
        portENABLE_INTERRUPTS();           
    }           
}           
           
void vPortReclaimCSA( unsigned long ** pxTCB )           
{           
    uint32_t ulHeadCSA, ulFreeCSA;           
    uint32_t * pulNextCSA;           
           
    /* The lower context (PCXI value) to return to the task is stored as the           
     * current element on the stack. Mask off everything in the PCXI register           
     * other than the address. */           
    ulHeadCSA = ( **pxTCB ) & portCSA_FCX_MASK;           
           
    /* Iterate over the CSAs that were consumed as part of the task. */           
    for(pulNextCSA = pxPortCsaToAddress( ulHeadCSA );           
        ( pulNextCSA[ 0 ] & portCSA_FCX_MASK ) != 0;           
        pulNextCSA = pxPortCsaToAddress( pulNextCSA[ 0 ] ) )           
    {           
        /* Mask off everything in the PCXI value other than the address. */           
        pulNextCSA[ 0 ] &= portCSA_FCX_MASK;           
    }           
           
    _disable();           
    {           
        /* Look up the current free CSA head. */           
        _dsync();           
        ulFreeCSA = _mfcr( portCPU_FCX );           
           
        /* Join the current free onto the tail of what is being reclaimed. */           
        pulNextCSA[ 0 ] = ulFreeCSA;           
           
        /* Move the head of the reclaimed into the Free. */           
        _mtcr( portCPU_FCX, ulHeadCSA );           
        _isync();           
    }           
    _enable();           
}           
           
void __attribute__( ( noreturn ) ) vPortLoopForever( void )           
{           
    while( 1 )           
    {           
    }           
}           
         

测试代码

我们在main 函数里面创建了两个任务。

创建任务

1task_app1

1task_app2

JSON                 
void core0_main(void)                 
{                 
    IfxCpu_enableInterrupts();                 
                     
    /* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!                 
     * Enable the watchdogs and service them periodically if it is required                 
     */                 
    IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());                 
    IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());                 
                     
    /* Wait for CPU sync event */                 
    IfxCpu_emitEvent(&g_cpuSyncEvent);                 
    IfxCpu_waitEvent(&g_cpuSyncEvent, 1);                 
                     
    /* Initialize a time variable */                 
    // Ifx_TickTime ticksFor1s = IfxStm_getTicksFromMilliseconds(BSP_DEFAULT_TIMER, WAIT_TIME);                 
                 
    /* Create LED1 app task */                 
    app1_status = xTaskCreate(task_app1, "APP1", configMINIMAL_STACK_SIZE, NULL, 3, NULL);                 
                 
    /* Create LED2 app task */                 
    app2_status = xTaskCreate(task_app2, "APP2", configMINIMAL_STACK_SIZE, NULL, 5, NULL);                 
                 
    /* Start the scheduler */                 
    vTaskStartScheduler();                 
                 
    while(1)                 
    {                 
    }                 
}

任务的内容很简单,就是周期任务,里面有counter 在自增。

任务实现

JSON                 
void task_app1(void)                 
{                 
    app1_cnt++;                 
    TickType_t xLastWakeTime;                 
    xLastWakeTime = xTaskGetTickCount();                 
    while(1)                 
    {                 
        app1_cnt++;                 
        vTaskDelayUntil(&xLastWakeTime, 1000);                 
    }                 
                 
}                 
void task_app2(void)                 
{                 
    app2_cnt++;                 
    while(1)                 
    {                 
        app2_cnt++;                 
        /* Delay 250ms */                 
        vTaskDelay(pdMS_TO_TICKS(250));                 
    }                 
}

编译测试

编译生成 elf, 和 map 文件。

检查map文件

我们来读取一下map 文件中的两个任务。实际上就是两个函数。和我们预期的一样。

JSON                 
0x800394cc 0x8003950d    66 g task_app1                                         pfls0     .CPU0.text      .text.task_app1                                         output\objs\src\Cpu0_Main.o                 
0x8003950e 0x8003953f    50 g task_app2                                         pfls0     .CPU0.text      .text.task_app2   

我们也通过hightec 编译器提供的工具来读一下elf文件,看一下两个 任务的 符号

检查elf文件

JSON                 
tricore-readelf.exe .\tc397_rtos.elf -s | grep task_*                 
   369: 00000000     0 FILE    LOCAL  DEFAULT   ABS tasks.c                 
   794: 800394cc    66 FUNC    GLOBAL DEFAULT    45 task_app1                 
  5511: 8003950e    50 FUNC    GLOBAL DEFAULT    45 task_app2

测试

直接调试器看一下 任务里面的全局变量是不是预想的自增。并且有大概四倍的关系。

测试通过。

[img=552.010009765625,122.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia6rNxWeib28VMFh0GicWKgicwCnONSlPukeybwJyZG9S9U8duoibv3Potw20YZF8ibT3NJS5aunmSUsq2g/640?wx_fmt=png[/img]
Tc397 + hightec 编译器 移植 freertosw1.jpg

QQ|手机版|小黑屋|Archiver|汽车工程师之家 ( 渝ICP备18012993号-1 )

GMT+8, 18-5-2024 22:50 , Processed in 0.296821 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2013 Comsenz Inc.