基于Infineon Tc397系列移植RTThread操作系统

目录

一、要修改的文件

二、cpuport.c文件修改

 三、cpuport.h文件修改

四、Ifx_Cfg_Trap.h文件修改:

五、验证

六、总结


一、要修改的文件

二、cpuport.c文件修改

/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *rt_interrupt_from_thread
 * SPDX-License-Identifier: GPL-2.0 License
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021/02/01     BalanceTWK   The unify TriCore porting code.
 */

#include <rthw.h>
#include <rtthread.h>
#include "cpuport.h"
#include "IfxCpu_Trap.h"
#include <Cpu/Std/Ifx_Types.h>
#include "Cpu/Std/IfxCpu_Intrinsics.h"
#include "Tricore/Compilers/Compilers.h"
#include "Cpu/Irq/IfxCpu_Irq.h"
#include "IfxInt_reg.h"
#include "IfxCpu_reg.h"

static IfxStm_Timer tricore_timers[2];
static volatile Ifx_STM *const STMs[2] = {&MODULE_STM0, &MODULE_STM1};
static volatile Ifx_SRC_SRCR *const GPSR[2] = {&SRC_GPSR_GPSR0_SR0, &SRC_GPSR_GPSR1_SR0};

static volatile rt_ubase_t rt_interrupt_from_thread = RT_NULL;
static volatile rt_ubase_t rt_interrupt_to_thread = RT_NULL;
static volatile rt_ubase_t rt_thread_switch_interrupt_flag = RT_NULL;

typedef struct UpperCtxInfo{
    unsigned long  _PCXI;
    unsigned long  _PSW;
    unsigned long*  _A10;
    unsigned long*  _A11;
    unsigned long  _D8;
    unsigned long  _D9;
    unsigned long  _D10;
    unsigned long  _D11;
    unsigned long*  _A12;
    unsigned long*  _A13;
    unsigned long*  _A14;
    unsigned long*  _A15;
    unsigned long  _D12;
    unsigned long  _D13;
    unsigned long  _D14;
    unsigned long  _D15;
}UpperCtx_T,*UpperCtx_Ptr;

rt_base_t rt_hw_interrupt_disable(void)
{
    rt_base_t level;
    level = IfxCpu_disableInterrupts();
    return level;
}

void rt_hw_interrupt_enable(rt_base_t level)
{
    restoreInterrupts((boolean)level);
}

void rt_hw_systick_init( void )
{
  IfxStm_Timer_Config timer_config;
  IfxStm_Timer_initConfig(&timer_config, STMs[TRICORE_CPU_ID]);

  timer_config.base.frequency = RT_TICK_PER_SECOND;
  timer_config.base.isrPriority = 2;
  IfxStm_Timer_init(&tricore_timers[TRICORE_CPU_ID], &timer_config);
  IfxStm_Timer_run(&tricore_timers[TRICORE_CPU_ID]);
}

/* inline */ void trigger_scheduling(void)
{
    UpperCtx_Ptr ptUpperCtx = NULL;
    uint8 idx = 0x00;

    __dsync();
    /* 获取当前线程的 CSA上层上下文地址 */
    ptUpperCtx = LINKWORD_TO_ADDRESS( __mfcr( CPU_PCXI ) );

    __isync();
    /* 如果from线程不为空 */
    if(rt_interrupt_from_thread)
    {
        __dsync();

        /* 将当前线程的Linkwork保存到From线程 */
        *( (unsigned long *)rt_interrupt_from_thread ) = ptUpperCtx->_PCXI;
        GPSR[TRICORE_CPU_ID]->B.SETR = 0;

    }
    /* 将to线程的linkword赋给当前线程的LinkWord*/
    ptUpperCtx->_PCXI = *( (unsigned long *)rt_interrupt_to_thread );
    /* 如果中断触发Flag置位,则复位 */
    if(rt_thread_switch_interrupt_flag)
    {
        rt_thread_switch_interrupt_flag = 0;
    }

    __isync();
}

__attribute__((noinline)) static void tricore_systick_handler( void )
{
    /* enter interrupt */
    rt_interrupt_enter();

    IfxStm_Timer_acknowledgeTimerIrq(&tricore_timers[TRICORE_CPU_ID]);

    rt_tick_increase();
    /* leave interrupt */
    rt_interrupt_leave();
}


IFX_INTERRUPT(KERNEL_INTERRUPT, 0, 2)
{
    tricore_systick_handler();
}

IFX_INTERRUPT(KERNEL_YIELD, 0, 1)
{
    trigger_scheduling();
}

/**
 * This function will initial STM32 board.
 */
#ifdef RT_USING_HEAP
extern unsigned int __HEAP[];
extern unsigned int __HEAP_END[];
#endif
void rt_hw_board_init()
{
    IfxStm_setSuspendMode(STMs[TRICORE_CPU_ID], IfxStm_SuspendMode_hard);
#ifdef RT_USING_HEAP
    /* initialize heap */
    rt_system_heap_init(__HEAP, __HEAP_END);
#endif

    /* Set-up the timer interrupt. */
    rt_hw_systick_init();
    /* USART driver initialization is open by default */
#ifdef RT_USING_SERIAL
    // rt_hw_usart_init();
#endif

    /* Set the shell console output device */
#ifdef RT_USING_CONSOLE
    // rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif

    /* Board underlying hardware initialization */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

    IfxSrc_init(GPSR[TRICORE_CPU_ID], (IfxSrc_Tos)TRICORE_CPU_ID, 1);
    IfxSrc_enable(GPSR[TRICORE_CPU_ID]);
}

void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to)
{
    rt_base_t level;

    level = rt_hw_interrupt_disable();
    /* 将from和to线程保存到对应的全局变量中,以便于后续线程切换 */
    rt_interrupt_from_thread = (*( (unsigned long *)from ));
    rt_interrupt_to_thread = (*((unsigned long *)to));
    rt_hw_interrupt_enable(level);

    /* 主动触发异常,进入Trap0,进行线程切换 */
    __syscall( 0 );
}

void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
{
    if(rt_thread_switch_interrupt_flag == 0)
    {
        /* 将from和to线程保存到对应的全局变量中,以便于后续线程切换 */
        rt_interrupt_from_thread = (*( (unsigned long *)from ));
        rt_interrupt_to_thread = (*((unsigned long *)to));
        /* 置位中断切换线程Flag */
        rt_thread_switch_interrupt_flag = 1;
        __dsync();
        /* SETR置位,触发中断,在中断函数中请求线程切换 */
        GPSR[TRICORE_CPU_ID]->B.SETR = 1;
        __isync();
    }
}

void rt_hw_context_switch_to(rt_ubase_t to)
{
    rt_base_t level;

    level = rt_hw_interrupt_disable();
    /* 启动第一个线程 */
    rt_interrupt_to_thread = (*((unsigned long *)to));

    /* 主动触发异常,进入Trap0,进行线程切换 */
    __syscall( 0 );
    rt_hw_interrupt_enable(level);
}

/**
 * This function will initialize thread stack
 *
 * @param tentry the entry of thread
 * @param parameter the parameter of entry
 * @param stack_addr the beginning stack address
 * @param texit the function will be called when thread exit
 *
 * @return stack address
 */
rt_uint8_t *rt_hw_stack_init(void       *tentry,
                             void       *parameter,
                             rt_uint8_t *stack_addr,
                             void       *texit)
{
    unsigned long *lower_csa = NULL;
    unsigned long *upper_csa = NULL;

    UpperCtx_Ptr upperCtxPtr = NULL;

    rt_hw_interrupt_disable();
    {
        __dsync();
        /* 使用两个空闲CSA存储线程上层上下文和下层上下文 */
        upper_csa = LINKWORD_TO_ADDRESS(__mfcr(CPU_FCX));

        if( NULL != upper_csa )
        {
            /* 查找上层上下文链接的下一个CSA地址 */
            lower_csa = LINKWORD_TO_ADDRESS( upper_csa[ 0 ] );
        }

        /* 如果成功分配两个CSA,则移动FCX */
        if( ( NULL != lower_csa ) && ( NULL != upper_csa ))
        {
            /* 将已经使用的两个CSA,从FCX列表中移除 */
            __disable();
            __dsync();
            __mtcr( CPU_FCX, lower_csa[ 0 ] );

            __isync();
            __enable();
        }
        else
        {
            __svlcx();
        }
    }
    rt_hw_interrupt_enable((rt_base_t)RT_NULL);

    /* 保存线程退出函数入口 */
    upper_csa[ 3 ] = ( unsigned long )texit;
    /* 保存栈指针,对应A[10]寄存器 */
    upper_csa[ 2 ] = ( unsigned long )stack_addr;
    /* 保存当前线程PSW寄存器的初始状态 */
    upper_csa[ 1 ] = TRICORE_SYSTEM_PROGRAM_STATUS_WORD;

    /* 保存函数入参,对应全局寄存器A[4] */
    lower_csa[ 8 ] = ( unsigned long ) parameter;
    /* 保存 PC 指针,A[11]*/
    lower_csa[ 1 ] = ( unsigned long ) tentry;
    /* PCXI指向上层上下文 */
    lower_csa[ 0 ] = ( TRICORE_INITIAL_PCXI_UPPER_CONTEXT_WORD | ( unsigned long ) ADDRESS_TO_LINKWORD( upper_csa ) );
    /* 将下层上下文的地址保存到栈顶 */
    *((unsigned long * )stack_addr) = (unsigned long) ADDRESS_TO_LINKWORD( lower_csa );
    __dsync();

    return ((unsigned long)stack_addr);
}



 三、cpuport.h文件修改

/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: GPL-2.0 License
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021/02/01     BalanceTWK   The unify TriCore porting code.
 */

#ifndef CPUPORT_H__
#define CPUPORT_H__

#include <rtconfig.h>
#include "IfxCpu.h"
#include "IfxCpu_reg.h"
#include "Bsp.h"
#include "Stm/Timer/IfxStm_Timer.h"
#include "Cpu0_Main.h"
#include "Cpu/Std/IfxCpu_Intrinsics.h"

#define LINKWORD_TO_ADDRESS( LinkWord )             ( ( unsigned long * )( ( ( ( LinkWord ) & 0x000F0000 ) << 12 ) | ( ( ( LinkWord ) & 0x0000FFFF ) << 6 ) ) )
#define ADDRESS_TO_LINKWORD( Address )              ( ( unsigned long )( ( ( ( (unsigned long)( Address ) ) & 0xF0000000 ) >> 12 ) | ( ( ( unsigned long )( Address ) & 0x003FFFC0 ) >> 6 ) ) )

#define TRICORE_NUM_WORDS_IN_CSA                    ( 16 )
#define TRICORE_SYSTEM_PROGRAM_STATUS_WORD          ( 0x000008FFUL ) /* Supervisor Mode, MPU Register Set 0 and Call Depth Counting disabled. */
#define TRICORE_INITIAL_PCXI_UPPER_CONTEXT_WORD     ( 0x00300000UL ) // ATEN, default value as read from the CPU after init
#define TRICORE_INITIAL_SYSCON                      ( 0x00000000UL ) /* MPU Disable. */
#define TRICORE_RESTORE_PSW_MASK                    ( ~( 0x000000FFUL ) )
#define TRICORE_CPU_ID                              (__mfcr(CPU_CORE_ID) & 0x0f)


/* inline */ void trigger_scheduling(void);
void get_clk(void);
#endif

四、Ifx_Cfg_Trap.h文件修改:

#ifndef USER_IFX_CFG_TRAP_H_
#define USER_IFX_CFG_TRAP_H_

#include "Ifx_Types.h"
#include "IfxCpu_Intrinsics.h"
#include "cpuport.h"

IFX_INLINE void tricore_trap_yield_for_task(IfxCpu_Trap trapInfo)
{
  switch(trapInfo.tId)
  {
    case 0:
        trigger_scheduling();
      break;

    default:
      /* Unimplemented trap called. */
      /* TODO*/
      break;
  }
}

#define IFX_CFG_CPU_TRAP_SYSCALL_CPU0_HOOK(trapInfo)  tricore_trap_yield_for_task(trapInfo)

#endif /* USER_IFX_CFG_TRAP_H_ */

五、验证

六、总结

移植成功代码路径如下:

https://download.csdn.net/download/u013464897/87966366

参考博客:

基于Hightec+TC375TP的RT-Thread移植详解
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以参考Infineon官网的文档:https://www.infineon.com/cms/en/product/microcontroller/32-bit-mcus/xmc-family/xmc4700/documentation/infineon-xmc4700-can-communication-application-note/ ### 回答2: 基于C语言的Infineon TC377的CAN通信代码的参考资料可以通过以下几种渠道获取: 1. Infineon官方文档和资料:访问Infineon官方网站,搜索TC377相关的开发文档、用户手册或参考资料。这些文档通常提供TC377芯片的功能介绍、硬件配置和软件开发指南,其中包含对CAN通信的详细说明和示例代码。 2. CAN通信协议标准:CAN通信协议是一种广泛应用于工业自动化、汽车电子等领域的通信协议。可以参考CAN通信协议标准(如ISO 11898)或相关的CAN网络教程,了解CAN通信协议的基本原理、帧格式和通信机制。 3. 开源软件库或项目:在开源社区(如GitHub)中搜索基于C语言实现的CAN通信库或项目,可以找到一些开源代码作为参考。这些库通常提供了封装CAN通信所需的底层驱动和高层应用接口,方便开发者进行CAN通信的程序设计。 4. 在线论坛和社区:参与相关领域的在线论坛和社区,向其他开发者请教或咨询TC377的CAN通信代码问题。常见的技术论坛和社区包括Stack Overflow、CSDN、知乎等,这些平台上有大量开发者分享和讨论关于CAN通信的经验和代码。 通过以上渠道,可以获取到不同层次的参考资料,包括官方文档、标准协议、开源项目和其他开发者的分享。根据具体需求和开发情况,结合这些资料进行学习和参考,能够更好地理解和应用C语言下基于TC377芯片的CAN通信代码。 ### 回答3: 要获取关于基于C语言的Infineon TC377的CAN通信代码的参考资料,您可以尝试以下几种途径: 1. Infineon官方网站:访问Infineon官方网站,通常它们提供了各种产品的技术文档、应用指南和代码示例。在官方网站中,您可以搜索TC377的相关技术资料,包括CAN通信的示例代码。 2. Infineon社区论坛:进入Infineon的社区论坛,与其他开发者和工程师交流,并寻求他们的建议和经验。在论坛中,您可以提问关于TC377和CAN通信的问题,并请教是否有可用的代码示例。 3. GitHub或其他代码托管平台:在开源的代码托管平台上,如GitHub,搜索使用TC377进行CAN通信的C语言项目。这样您就可以找到其他开发者分享的代码示例或工程。 4. 学术论文或科技期刊:搜索与TC377和CAN通信相关的学术论文或科技期刊。有些研究人员或工程师可能会在他们的论文中分享他们的代码实现,这将为您提供很好的参考资料。 5. 在线教程或博客:搜索关于使用TC377进行CAN通信的在线教程或博客文章。一些技术写手或工程师会分享他们的经验,并提供代码示例和详细说明。 无论通过哪种方式获取代码参考资料,请始终确认其与TC377兼容,并符合您的需求和系统要求进行适当的修改和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值