This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28379D: Dual Core Startup delay issue

Part Number: TMS320F28379D


Hello there!

I have an issue with F28379D MCU. The problem is about CPU1 and CPU2 communication. I am sending you programs for both cores (see below).

Program is very simple (in the code, there are comments in Czech language, you can ignore them), CPU1 asks CPU2 for data, CPU2 place them into message ram and CPU1 print them via UART. It works properly if there is delay in form of for loop on line 40, but If I delete it, then UART output sends a random data garbage with random length.

I do not know, why the delay is so crucial. I added conditions asking for boot state of CPU2, cleared FLAGS 32 and 0, but no change. Only change is the delay (the delay time is randomly set by me, probably it can be shorter).

The easies way for you to see the problem is to load it to F28379D launchpad and see the difference when the delay for loop on line 40 is there or is commented out. You should see the behavior when you connect COM terminal to the device.

Please, could you give me an advice, why it behaves like that and how to resolve it, so I will not use random delay in the code?

Thank you very much for help.

Vojtech Skrivanek

MainCPU1.c :

// Included Files
#include "F2837xD_Ipc_drivers.h"
#include "pin_map.h"
#include "sci.h"
#include "gpio.h"

void Cpu2Start()
{
    // cekej, dokud neni CPU2 spusteno (referencni manual kap. 4.10.11.3)
    while ((IpcRegs.IPCBOOTSTS & C2_BOOTROM_BOOTSTS_SYSTEM_READY) != C2_BOOTROM_BOOTSTS_SYSTEM_READY);

    // cekej, dokud nejsou CPU2 IPC priznaky 0 a 31 dostupne
    while ((IpcRegs.IPCFLG.bit.IPC0 == 1U) && (IpcRegs.IPCFLG.bit.IPC31 == 1U));

    // nastaveni startovaciho rezimu CPU2 (referencni manual kap. 4.10.8.2)
    IpcRegs.IPCBOOTMODE = C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH;

    // prikaz na provedeni noveho startu programu CPU2 (referencni manual kap. 4.10.8.2)
    IpcRegs.IPCSENDCOM  = BROM_IPC_EXECUTE_BOOTMODE_CMD;

    // nastaveni priznaku, aby CPU2 provedlo prikaz (referencni manual kap. 4.10.8.1 a
    // TMS320F2838x Real-Time Microcontrollers With Connectivity Manager kap. 5.5.2 a 5.7.2
    IpcRegs.IPCSET.all = 0x80000001U;
}

// Main
void main(void)
{
    Cpu2Start();

    // povoli hodinovy signal pro SCIA
    EALLOW;
    CpuSysRegs.PCLKCR7.bit.SCI_A = 1U;
    EDIS;

    // nastavi GPIO 42/43 jako TX a RX pro UART
    GPIO_setPinConfig(GPIO_42_SCITXDA);
    GPIO_setPinConfig(GPIO_43_SCIRXDA);

    for(int x = 0U; x < 20000U; x++);

    // vstupni frekvence je f_intosc2 (10 MHz) / LSPCLK (4) = 2,5 MHz
    SCI_setConfig(SCIA_BASE, 2500000U, 9600U, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE));

    uint8_t* messageRamIn = (uint8_t*)0x03F800U;

    // posli preruseni 0 pro CPU2
    IpcRegs.IPCSET.bit.IPC0 = 1U;

    // cekej na potvrzeni od CPU2
    while(IpcRegs.IPCFLG.bit.IPC0 == 1U);

    // odesli data o dane delce z RAM
    SCI_writeCharArray(SCIA_BASE, &messageRamIn[IpcRegs.IPCRECVADDR], IpcRegs.IPCREMOTEREPLY);

    // Loop Forever
    for(;;)
    {}
}

MainCPU2.c :

// Included Files
#include "F2837xD_Ipc_drivers.h"
#include "hw_ints.h"
#include "interrupt.h"
#include "stdio.h"
#include "string.h"

// ukazatel na zacatek message RAM
uint8_t* messageRamOut = (uint8_t*)0x03F800U;

// data
const char data[] = "Data prenesena z CPU2 do CPU1 pomoci Message RAM";

__interrupt void IPC_ISR0()
{
    uint8_t datovyPosun = 15U;

    memcpy(&messageRamOut[datovyPosun], data, strlen(data));

    IpcRegs.IPCSENDADDR = datovyPosun;

    IpcRegs.IPCLOCALREPLY = strlen(data);

    // vynuluj priznak preruseni
    IpcRegs.IPCACK.bit.IPC0 = 1U;

    // vymaze priznak preruseni skupiny 1
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}

// Main
void main(void)
{
    // globalne vypne preruseni jadra
    DINT;

    // Incializuje radic preruseni
    Interrupt_initModule();

    // povoli linku 1 preruseni jadra
    Interrupt_enableInCPU(INTERRUPT_CPU_INT1);

    // povoli preruseni IPC_0
    Interrupt_enable(INT_IPC_0);

    // zaregistruje funkci do vektoru preruseni pro IPC_0
    Interrupt_register(INT_IPC_0, IPC_ISR0);

    // globalne povoli preruseni jadra
    EINT;

    // Loop Forever
    for(;;)
    {
    }
}

  • Hi,

    It would be good to do some kind of handshaking between the cores indicating the init completion.

    For example, after the EINT instruction in CPU2, you can send an IPC Flag to CPU2 indicating it is read to receive IPC interrupts. On the CPU1 side, you can have the wait for this flag somewhere before it sends the data to CPU2. Without this, there is chance that CPU1 completes its own init too soon and sends the data to CPU2, and CPU2 has not completed configuring its interrupts. That could be the reason why the delay has helped.

    Regards,

    Veena