Funpack2-2 TC275板卡多核编程
本次funpack活动给我们带来的是来自Infineon的AURIX TC275 lite评估板。他是一款家庭微控制器产品,具备丰富的外设,方便我们的开发和配置
标签
嵌入式系统
MPU
数字逻辑
caoyi
更新2022-10-11
586

1 板卡介绍

本次funpack活动给我们带来的是来自Infineon的AURIX TC275 lite评估板。他是一款家庭微控制器产品,具备丰富的外设,方便我们的开发和配置,包括:

  • Arduino 连接器
  • Arduino ICSP 连接器
  • 稳压器 5V 至 3.3V
  • 可选 0 欧姆电阻器(1210 英制中的 R39_opt/R40_opt)
  • Arduino 连接器(数字)
  • 用于 AURIX™ TM的 20 MHz 晶振和用于 OCDS 的 12 MHz 晶振
  • 用于 WIFI/BLE 的 Mikrobus 连接器
  • 英飞凌 CAN 收发器 TLE9251VSJ 和 CAN 连接器
  • 针连接器 X2
  • 电源指示灯 (D5)
  • LED D1/D2 用于 ADBUS7/4 和 LED3 用于 ESR0 信号(低电平有效)
  • Arduino 针连接器(电源和模拟输入)
  • 电位器 (10 kOhm) 和可焊接的 0 Ohm 电阻器(0805 英制中的 R33)
  • 微型 USB(推荐 USB3.0)
  • 10 针 DAP 连接器
  • 复位按钮
  • 2 x Shield2GO 连接器,用于 Infineon Maker Shields
  • EEPROM 1Kbit

2 任务介绍

本次我选择的是任务一:使用TC275的三个核心,轮流休眠待机,分别控制板卡上的LED灯,如core0检测按键按下,唤醒core1翻转LED1,一秒后,唤醒core2翻转LED2,系统休眠

需实现的功能如下:

  • 只有core0启动,并控制LED1以0.1s的频率闪烁
  • 监听到按键按下后,core0休眠,core1启动翻转LED1
  • 一秒后,core1休眠,core2启动翻转LED2
  • 唤醒core2翻转LED2,系统休眠

3 任务分析

  • 使用GPIO口的输入模式,监测按键的输入,读取用户输入
  • 使用GPIO口的输出模式,控制GPIO口输出低电平时,LED被点亮
  • 使用IfxCpu_setCoreMode方法,设置指定的CPU核心为休眠、运行模式
  • 使用寄存器配置设置整个系统进入睡眠模式

4 代码思路

代码主要参考了TC257休眠的样例,进行修改。在SCU_Power_Down_Idle.c中定义GPIO, CPU休眠,CPU睡眠,定时器等方法。最后在Cpu0_Main.c,Cpu1_Main.c,Cpu2_Main.c中进行调用,进行编排即可。

5 代码实现

这里是SCU_Power_Down_Idle.c,设置了主要的功能,包括设置各个CPU进入休眠模式的方法,设置各个CPU运行的方法,设置系统进入睡眠模式的方法,GPIO初始化的方法以及设置读取和设置GPIO的方法。

#define ISR_PRIORITY_2      2
/* Defines CPU that triggers the interrupt */
#define ISR_PROVIDER_CPU0   0
/* Defines CPU that triggers the interrupt */
#define ISR_PROVIDER_CPU2   2
/* Rate 0.5 Hz */
#define RATE_0_5_HZ         0.25
/* Rate 1 Hz */
#define RATE_1_HZ           0.5
/* LED */
#define LED1                &MODULE_P00,5
#define LED2                &MODULE_P00,6
#define BUTTON  &MODULE_P00,7   /* Port pin for the button  */

#define ALLOW_SLEEP_MODE    0x0                 /* Allow sleep mode for GTM                                         */
#define BLOCK_SLEEP_MODE    0x1                 /* Block sleep mode for STM                                         */
#define PMSWCR1_CPUSEL      0x1                 /* Set the CPU0 as CPU master                                       */
#define PMCSR0_REQSLP       0x2                 /* Request sleep mode                                               */
/*********************************************************************************************************************/
/*----------------------------------------------Function Implementations---------------------------------------------*/
/*********************************************************************************************************************/
/* Maps the Interrupt Service Routine with the CPU and Priority */
IFX_INTERRUPT(systemTimerIsrCmp0, ISR_PROVIDER_CPU2, ISR_PRIORITY_2);

/* Interrupt Service Routine to switch the CPU0 between idle and run mode */
void systemTimerIsrCmp0(void)
{

    IfxCpu_setCoreMode(&MODULE_CPU2, IfxCpu_CoreMode_idle);         /* Set CPU2 in IDLE mode                    */
    // static boolean setIdle = TRUE;                                      /* Alternating between Idle and non-Idle    */

    // IfxCpu_enableInterrupts();                                          /* Enabling interrupts as ISR disables it   */
    // IfxStm_Timer_acknowledgeTimerIrq(&g_myTimer);                       /* IR acknowledge and set new compare value */

    // if(setIdle == TRUE)
    // {
    //     IfxCpu_setCoreMode(&MODULE_CPU2, IfxCpu_CoreMode_idle);         /* Set CPU2 in IDLE mode                    */
    //     setIdle = FALSE;
    // }
    // else
    // {
    //     setIdle = FALSE;
    // }

}

/* Defines the routine to initialize and start the system timer */
void configSystemTimer(void)
{
    IfxStm_Timer_Config timerConfig;

    IfxStm_Timer_initConfig(&timerConfig, &MODULE_STM0);                /* Setup timerConfig with default values    */

    timerConfig.base.frequency = RATE_0_5_HZ;                             /* Interrupt rate 0.5 Hz or every 2s        */
    timerConfig.base.isrPriority = ISR_PRIORITY_2;                      /* Interrupt priority                       */
    timerConfig.base.isrProvider = (IfxSrc_Tos)ISR_PROVIDER_CPU2;       /* CPU0 to trigger the interrupt            */
    timerConfig.comparator = IfxStm_Comparator_0;                       /* Comparator 0 register is used            */

    IfxStm_Timer_init(&g_myTimer, &timerConfig);                        /* Use timerConfig to initialize the STM    */

    IfxStm_Timer_run(&g_myTimer);                                       /* Run STM and set Compare Value            */
}

/* Initialize the LED port pin */
void configLED(void)
{
    /* Set Port Pin 00.5 to output mode and turn off the LED (LED is low-level active) */
    IfxPort_setPinModeOutput(LED1, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
    IfxPort_setPinHigh(LED1);
}

/* Toggle the LED port pin state */
void toggleLED(void)
{
    IfxPort_togglePin(LED1);                                             /* Toggle Port Pin 00.5                     */
}


void configLED2(void)
{
    /* Set Port Pin 00.5 to output mode and turn off the LED (LED is low-level active) */
    IfxPort_setPinModeOutput(LED2, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
    IfxPort_setPinHigh(LED2);
    IfxPort_setPinMode(BUTTON, IfxPort_Mode_inputPullUp);
}

/* Toggle the LED port pin state */
void toggleLED2(void)
{
    IfxPort_togglePin(LED2);                                             /* Toggle Port Pin 00.5                     */
}
#define WAIT_TIME   50
static boolean setIdle = TRUE;                                      /* Alternating between Idle and non-Idle    */

int if_key_is_pushed(void)
{
    /* With the routine getPinState() the value of a particular pin can be retrieved. This
     * function can be used to retrieve any port state by just specifying the port number
     * as illustrated.
     */
    if(IfxPort_getPinState(BUTTON) == 0)
    {
        /* With the routine setPinState() the state of the port can be set to drive either
         * LOW or HIGH. This function can be used to retrieve any port state by just
         * specifying the port number as illustrated.
         */

        waitTime(IfxStm_getTicksFromMilliseconds(BSP_DEFAULT_TIMER, WAIT_TIME));
        if (IfxPort_getPinState(BUTTON) == 0){

            IfxCpu_enableInterrupts();                                          /* Enabling interrupts as ISR disables it   */
//            IfxStm_Timer_acknowledgeTimerIrq(&g_myTimer);                       /* IR acknowledge and set new compare value */

//            if(setIdle == TRUE)
//            {
//                IfxCpu_setCoreMode(&MODULE_CPU0, IfxCpu_CoreMode_idle);         /* Set CPU0 in IDLE mode                    */
//                setIdle = FALSE;
//            }
//            else
//            {
//                IfxCpu_setCoreMode(&MODULE_CPU0, IfxCpu_CoreMode_run);         /* Set CPU0 in IDLE mode                    */
//                setIdle = TRUE;
//            }
            while (1) {
                if (IfxPort_getPinState(BUTTON) != 0) {
                    return 1;
                }
            }
        }
    }
    return 0;

}

设置CPU休眠,睡眠相关代码

void set_c1_c2_idle(void)
{
    /*
     * 设置cpu1, cpu2为idle.
     */

    IfxCpu_enableInterrupts();
    IfxCpu_setCoreMode(&MODULE_CPU1, IfxCpu_CoreMode_idle);
    IfxCpu_setCoreMode(&MODULE_CPU2, IfxCpu_CoreMode_idle);
}

void set_c0_idle(void)
{
    /*
     * 设置cpu0为idle.
     */
    IfxCpu_enableInterrupts();
    IfxCpu_setCoreMode(&MODULE_CPU0, IfxCpu_CoreMode_idle);
}


void set_c0_run(void)
{
    /*
     * 设置cpu0为run.
     */
    IfxCpu_enableInterrupts();
    IfxCpu_setCoreMode(&MODULE_CPU0, IfxCpu_CoreMode_run);
}

void set_c1_idle(void)
{
    /*
     * 设置cpu1为idle.
     */
    IfxCpu_enableInterrupts();
    IfxCpu_setCoreMode(&MODULE_CPU1, IfxCpu_CoreMode_idle);
}

void set_c1_run(void)
{
    /*
     * 设置cpu1为run.
     */
    IfxCpu_enableInterrupts();
    IfxCpu_setCoreMode(&MODULE_CPU1, IfxCpu_CoreMode_run);
    set_c0_idle();
}

void set_c2_idle(void)
{
    /*
     * 设置cpu2为idle.
     */
    IfxCpu_enableInterrupts();
    IfxCpu_setCoreMode(&MODULE_CPU2, IfxCpu_CoreMode_idle);
}


void set_c2_run(void)
{
    /*
     * 设置cpu1为run.
     */
//    set_c0_idle();
    IfxCpu_enableInterrupts();
    IfxCpu_setCoreMode(&MODULE_CPU2, IfxCpu_CoreMode_run);
    set_c1_idle();
}

#define ISR_PRIORITY_STM    20    
IFX_INTERRUPT(stmIsr, 0, ISR_PRIORITY_STM);



IfxGtm_Tom_Timer g_gtmTimer;                    /* TOM driver handle                                                */
IfxStm_Timer g_stmTimer;                        /* STM driver handle                                                */
float32 g_stmPeriod = 0.1;                      /* Period in seconds at which power modes toggle                    */
uint8 g_sleep = 0;                              /* Variable used to monitor the current set mode (sleep/run mode)   */
#define ISR_PRIORITY_TOM    10                  /* TOM Interrupt priority                                           */
#define TOM_FREQ            25.0f               /* TOM frequency                                                    */
#define LED                 &MODULE_P00, 5      /* LED which is toggled in Interrupt Service Routine (ISR)          */


void set_sleep(void) {
    if(g_sleep == 0)
    {
        /* Next interrupt --> run mode */
        g_sleep = 1;

        /* Clear safety EndInit protection */
        IfxScuWdt_clearSafetyEndinitInline(IfxScuWdt_getSafetyWatchdogPasswordInline());
        /* Clear EndInit protection */
        IfxScuWdt_clearCpuEndinit(IfxScuWdt_getCpuWatchdogPassword());

        GTM_CLC.B.EDIS = ALLOW_SLEEP_MODE;          /* Allow GTM to go into sleep mode                              */

        STM0_CLC.B.EDIS = BLOCK_SLEEP_MODE;         /* Prohibit STM to go into sleep mode                           */

        SCU_PMSWCR1.B.CPUSEL = PMSWCR1_CPUSEL;      /* Set the CPU0 as CPU master to trigger a power down mode      */

        SCU_PMCSR0.B.REQSLP = PMCSR0_REQSLP;        /* Request System Sleep Mode CPU0                               */

        /* Set safety EndInit protection */
        IfxScuWdt_setSafetyEndinitInline(IfxScuWdt_getSafetyWatchdogPasswordInline());
        /* Set EndInit protection */
        IfxScuWdt_setCpuEndinit(IfxScuWdt_getCpuWatchdogPassword());
    }
    else
    {
        /* Next interrupt --> sleep mode */
        g_sleep = 1;
    }
}
void initStm(void)
{
    IfxStm_Timer_Config timerConfig;                                /* Timer configuration structure                */

    IfxStm_Timer_initConfig(&timerConfig, &MODULE_STM0);            /* Initialize it with default values            */

    timerConfig.base.frequency = 1 / g_stmPeriod;                   /* Interrupt rate every STM_PERIOD seconds      */
    timerConfig.base.isrPriority = ISR_PRIORITY_STM;                /* Interrupt priority                           */
    timerConfig.base.isrProvider = IfxSrc_Tos_cpu2;                 /* CPU0 to trigger the interrupt                */
    timerConfig.comparator = IfxStm_Comparator_0;                   /* Comparator 0 register is used                */

    IfxStm_Timer_init(&g_stmTimer, &timerConfig);                   /* Use timerConfig to initialize the STM        */

    IfxStm_Timer_run(&g_stmTimer);                                  /* Run the STM and set the compare Value        */
}

void initTom(void)
{
    IfxGtm_enable(&MODULE_GTM);                                     /* Enable the GTM                               */

    IfxGtm_Tom_Timer_Config timerConfig;                            /* Timer configuration structure                */
    IfxGtm_Tom_Timer_initConfig(&timerConfig, &MODULE_GTM);         /* Initialize the timer configuration           */

    timerConfig.base.frequency = TOM_FREQ;                          /* Set the timer frequency                      */
    timerConfig.base.isrPriority = ISR_PRIORITY_TOM;                /* Set the interrupt priority                   */
    timerConfig.base.isrProvider = IfxSrc_Tos_cpu0;                 /* Set the interrupt provider                   */
    timerConfig.tom = IfxGtm_Tom_1;                                 /* Define the used timer                        */
    timerConfig.timerChannel = IfxGtm_Tom_Ch_0;                     /* Define the used channel                      */
    timerConfig.clock = IfxGtm_Tom_Ch_ClkSrc_cmuFxclk3;             /* Define the used CMU clock                    */

    IfxGtm_Cmu_enableClocks(&MODULE_GTM, IFXGTM_CMU_CLKEN_FXCLK);   /* Enable the CMU clock                         */
    IfxGtm_Tom_Timer_init(&g_gtmTimer, &timerConfig);               /* Initialize the TOM                           */

    IfxPort_setPinModeOutput(LED, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general); /* Set port pin mode     */

    IfxGtm_Tom_Timer_run(&g_gtmTimer); /* Start the TOM */
}

6 运行状态

下面是运行时的状态

上电时:

FhI746CiNWLpPNc7TtaW-bbkt_8A

第一次按下按键:

Fj6XMtfuPsIG5iP65ChLZh6tMQL7

按键按下一秒后休眠:

FvLQsZx_paHUi_F8226Exo90imqr

7 心得体会

这是我第一次通过英飞凌的评估套件进行开发,不同于以往的通过Keil进行开发。英飞凌强大的生态大大得简化了开发步骤,让我省去了板卡适配环节。同时英飞凌提供了完善的开发样例,让我们了更加清楚地了解到各个外设如何调用。

十分感谢硬禾,能够提供机会让我们接触到如此优秀的板卡,也希望Funpack能继续办下去,让广大爱好者既能学到东西,又能接触到优秀的硬件。

附件下载
TC275多核编程.zip
团队介绍
caiyi
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号