I am working with the TC397 (A2G_TC397_5V_TRB) board and attempting to run FreeRTOS across all six cores simultaneously. While I have successfully run FreeRTOS on each core individually, I’ve encountered challenges in executing it concurrently on all six cores. Are there any known approaches or sample projects that demonstrate multi-core FreeRTOS execution on the TC397?
Are you running separate instance of FreeRTOS on each core? i.e. You are building and flashing a separate binary for each core? If yes, would you please describe the problem you are facing?
Thank you for your response.
We recently came across the AMP (Asymmetric Multi-Processing) approach, which allows running FreeRTOS independently on all cores. However, we currently do not have a complete understanding of how it works in practice. Specifically, we are unsure about the process of building and flashing separate binaries for each core in the TC397 using Aurix Development Studio.
Could you kindly guide us on how to implement this setup? Any help or reference material would be greatly appreciated.
The implementation largely depends on your specific hardware. Generally, the process involves partitioning both flash and RAM among the cores, creating separate linker scripts for each core to ensure they utilize their dedicated memory regions, and compiling distinct binaries for each core using their respective linker scripts. For detailed instructions specific to the Aurix Development Studio, I’d recommend reaching out to Infineon.
Thank you for your response.
Okay we will contact infineon .
We were able to run normal task on all the cores (CPU0 to CPU5) at same time . But not able to run FreeRTOS task on all the cores at same time ? Is there any way or any reference. Can you help us with AMP approach or any other approaches with FreeRTOS?
Our requirement is to run the FreeRTOS tasks from all the cores at same time.
Can you elaborate how you ran tasks on different cores? What did you do for that?
We ran normal tasks on all six cores (CPU0–CPU5) by enabling each core using iLLD functions and writing core-specific logic in each CpuX_Main.c file. Tasks were defined in common .c and .h files and called from each core’s main function after core startup.
- The Blink_led.C file
#include "IfxPort.h"
#include "Bsp.h"
#include "Blink_Led.h"
#define LED_D302n &MODULE_P33, 4
#define LED_D303n &MODULE_P33, 5
#define LED_D304n &MODULE_P33, 6
#define LED_D305n &MODULE_P33, 7
#define LED_D306n &MODULE_P20, 11
#define LED_D307n &MODULE_P20, 12
#define DELAY_302n 500
#define DELAY_303n 300
#define DELAY_304n 700
#define DELAY_305n 1000
#define DELAY_306n 1500
#define DELAY_307n 2000
void delay_ms(uint32 ms)
{
volatile uint32 i, j;
for (i = 0; i < ms; i++)
{
for (j = 0; j < 5000; j++) // Adjust this loop count to your MCU speed
{
__nop();
}
}
}
void initLED(void)
{
IfxPort_setPinModeOutput(LED_D302n, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D303n, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D304n, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D305n, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D306n, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D307n, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinHigh(LED_D302n);
IfxPort_setPinHigh(LED_D303n);
IfxPort_setPinHigh(LED_D304n);
IfxPort_setPinHigh(LED_D305n);
IfxPort_setPinHigh(LED_D306n);
IfxPort_setPinHigh(LED_D307n);
}
void blinkLED302n(void)
{
while (1)
{
IfxPort_togglePin(LED_D302n);
delay_ms(DELAY_302n);
}
}
void blinkLED303n(void)
{
while (1)
{
IfxPort_togglePin(LED_D303n);
delay_ms(DELAY_303n);
}
}
void blinkLED304n(void)
{
while (1)
{
IfxPort_togglePin(LED_D304n);
delay_ms(DELAY_304n);
}
}
void blinkLED305n(void)
{
while (1)
{
IfxPort_togglePin(LED_D305n);
delay_ms(DELAY_305n);
}
}
- The Blink_Led.h file:
#ifndef BLINK_LED_H
#define BLINK_LED_H
// Init
void initLED(void);
void initLEDs(void);
// Non-RTOS direct blink functions
void blinkLED302n(void);
void blinkLED303n(void);
void blinkLED304n(void);
void blinkLED305n(void);
void blinkLED306n(void);
void blinkLED307n(void);
#endif // BLINK_LED_H
- The CPUX_Main.c files:
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "Blink_Led.h"
IFX_ALIGN(4) IfxCpu_syncEvent g_cpuSyncEvent = 0;
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);
initLED(); /* Initialize the LED port pin */
blinkLED302n();
while(1)
{
}
}
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "Blink_Led.h"
extern IfxCpu_syncEvent g_cpuSyncEvent;
void core1_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG1 IS DISABLED HERE!!
* Enable the watchdog and service it periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
blinkLED303n();
while(1)
{
}
}
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "Blink_Led.h"
extern IfxCpu_syncEvent g_cpuSyncEvent;
void core2_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG2 IS DISABLED HERE!!
* Enable the watchdog and service it periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
blinkLED304n();
while(1)
{
}
}
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "Blink_Led.h"
extern IfxCpu_syncEvent g_cpuSyncEvent;
void core3_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG3 IS DISABLED HERE!!
* Enable the watchdog and service it periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
blinkLED305n();
while(1)
{
}
You are not running FreeRTOS tasks on each core. You are calling a function on each core which continuously keeps blinking an LED. I see the following in the document AP32381 - AURIX™ TC3xx startup and initialisation
:
The hardware only starts the CPU0 core by default, while the other cores remain in HALT state until they are explicitly activated by software by clearing the BHALT bit in the SYSCON register.
You need to ask Infineon if it is possible to have a separate binary for each core and how to do that. You’ll then need to adjust the CPU0 startup code to start up all others cores to execute their respective binaries before proceeding to CPU0 main. This way you should be able to run a separate FreeRTOS instance on each core.
Not that I am aware of.
Thanks for your response.
The above was normal tasks that I have mentioned before.
We also attempted to run FreeRTOS tasks on all cores but were unsuccessful in getting them to work.
The term “task” is what was confusing here. Thank you for sharing code which helped clarify that.
I’d suggest to get FreeRTOS working on CPU0 first.
We confirmed that FreeRTOS tasks execute correctly on CPU0 and CPU1 when run individually; however, simultaneous execution on both cores is not yet functioning
How did you confirm that? Can you share code snippets?
We observed the LEDs blinking
- Blink_Led.c file
/*********************************************************************************************************************/
#include "IfxPort.h"
#include "Bsp.h"
#include "Blink_Led.h"
#include "FreeRTOS.h"
#include "task.h"
/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define LED_D302 &MODULE_P33, 4
#define LED_D303 &MODULE_P33, 5
#define LED_D304 &MODULE_P33, 6
#define LED_D305 &MODULE_P33, 7
#define LED_D306 &MODULE_P20, 11
#define LED_D307 &MODULE_P20, 12
#define DELAY_302 500
#define DELAY_303 700
#define DELAY_304 900
#define DELAY_305 1000
#define DELAY_306 1200
#define DELAY_307 1500
/*********************************************************************************************************************/
/*-------------------------------------------------LED Initialization------------------------------------------------*/
/*********************************************************************************************************************/
void initLEDs(void)
{
IfxPort_setPinModeOutput(LED_D302, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D303, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D304, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D305, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D306, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinModeOutput(LED_D307, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
IfxPort_setPinHigh(LED_D302); // Turn off (low-active)
IfxPort_setPinHigh(LED_D303);
IfxPort_setPinHigh(LED_D304);
IfxPort_setPinHigh(LED_D305);
IfxPort_setPinHigh(LED_D306);
IfxPort_setPinHigh(LED_D307);
}
/*********************************************************************************************************************/
/*---------------------------------------------FreeRTOS LED Tasks----------------------------------------------------*/
/*********************************************************************************************************************/
void blinkLED302(void *pvParameters)
{
(void)pvParameters;
while (1)
{
IfxPort_togglePin(LED_D302);
vTaskDelay(pdMS_TO_TICKS(DELAY_302));
}
}
void blinkLED303(void *pvParameters)
{
(void)pvParameters;
while (1)
{
IfxPort_togglePin(LED_D303);
vTaskDelay(pdMS_TO_TICKS(DELAY_303));
}
}
void blinkLED304(void *pvParameters)
{
(void)pvParameters;
while (1)
{
IfxPort_togglePin(LED_D304);
vTaskDelay(pdMS_TO_TICKS(DELAY_304));
}
}
- The Blink_Led.h
#ifndef BLINK_LED_H
#define BLINK_LED_H
// Init
void initLED(void);
void initLEDs(void);
void blinkLED302(void *pvParameters);
void blinkLED303(void *pvParameters);
void blinkLED304(void *pvParameters);
void blinkLED305(void *pvParameters);
void blinkLED306(void *pvParameters);
void blinkLED307(void *pvParameters);
#endif // BLINK_LED_H
- The Cpu0_Main.c file:
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "FreeRTOS.h"
#include "task.h"
#include "Blink_Led.h"
void core0_main(void)
{
IfxCpu_enableInterrupts();
// vCoreInit(1);
/* !!WATCHDOG1 IS DISABLED HERE!!
* Enable the watchdog and service it periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
initLEDs(); // optional
/* Create FreeRTOS tasks for each LED*/
xTaskCreate(blinkLED302, "LED302", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(blinkLED303, "LED303", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(blinkLED304, "LED304", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(blinkLED305, "LED305", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(blinkLED306, "LED306", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(blinkLED307, "LED307", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
/* Start the scheduler */
vTaskStartScheduler();
/* Infinite loop in case scheduler exits (which it shouldn't)*/
while (1)
{
// Idle loop
}
}
/* Stack overflow hook (required for FreeRTOS)*/
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
{
while (1)
{
__nop(); // Stay here for debugging
}
}
This is great. The next step is to find out how to use separate binaries for each core so that you can have a separate FreeRTOS instance running on each core. As I have suggested before, reach out to Infineon to find out that.
Hello Sabariya,
Have you thought about SMP (Symmetric MultiProcessing) instead of AMP? If the end goal is to run FreeRTOS tasks across all the cores at same time, SMP can also get you there. There are some community and partners supported ports/demos that can be used for reference:
- FreeRTOS-Kernel-Partner-Supported-Ports/TI/CORTEX_A53_64-BIT_TI_AM64_SMP at main · FreeRTOS/FreeRTOS-Kernel-Partner-Supported-Ports · GitHub
- FreeRTOS-Partner-Supported-Demos/CORTEX_A53_64-BIT_TI_AM64_SMP at main · FreeRTOS/FreeRTOS-Partner-Supported-Demos · GitHub
- FreeRTOS-Kernel-Community-Supported-Ports/GCC/CORTEX_A53_64-bit_UltraScale_MPSoC at main · FreeRTOS/FreeRTOS-Kernel-Community-Supported-Ports · GitHub