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.

TMS320F28388D: About SCI communications in 28388D CPU2

Part Number: TMS320F28388D
Other Parts Discussed in Thread: C2000WARE, SYSCONFIG

Hello engineer, I am recently working on the 28388D inter-core communication, and the function I am implementing is to send a set of data from CPU1 to CPU2 via IPC, and then CPU2 will use SCIB to send this set of data out, but at present there is a problem when the data is sent via SCIB, and it cannot be sent successfully, now I am posting the code in CPU1 and CPU2, I hope you can I would like to post the code in CPU1 and CPU2 and hope that you can help me find the problem.

Code in CPU1

//
// Included Files
//
#include "driverlib.h"
#include "device.h"

//
// Defines
//
#define IPC_CMD_READ_MEM   0x1001
#define IPC_CMD_RESP       0x2001

#define TEST_PASS          0x5555
#define TEST_FAIL          0xAAAA


#pragma DATA_SECTION(readData, "MSGRAM_CPU1_TO_CPU2")
char sdData[10]={1,2,3,4,5,6,7,8,9,'\n'};
uint32_t readData[10]={0};
uint32_t pass;

//
// Main
//
void main(void)
{
    int i;

    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Boot CPU2 core
    //
#ifdef _FLASH
    Device_bootCPU2(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
#else
    Device_bootCPU2(BOOTMODE_BOOT_TO_M0RAM);
#endif

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();
    //
    //set SCIB TX
    //
    GPIO_setPinConfig(DEVICE_GPIO_CFG_SCITXDB);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCITXDB, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(DEVICE_GPIO_PIN_SCITXDB, GPIO_PIN_TYPE_STD | GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCITXDB, GPIO_QUAL_ASYNC);

    GPIO_setMasterCore(DEVICE_GPIO_PIN_SCITXDB, GPIO_CORE_CPU2);
    GPIO_setMasterCore(DEVICE_GPIO_CFG_SCITXDB, GPIO_CORE_CPU2);
    //
    // Clear any IPC flags if set already
    //
    IPC_clearFlagLtoR(IPC_CPU1_L_CPU2_R, IPC_FLAG_ALL);

    //
    // Synchronize both the cores.
    //
    IPC_sync(IPC_CPU1_L_CPU2_R, IPC_FLAG31);

    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;

    //
    // Fill in the data to be sent
    //
    for(i=0; i<10; i++)
    {
        readData[i] = sdData[i];
    }

    //
    // Send a message without message queue
    // Length of the data to be read is passed as data.
    //
    IPC_sendCommand(IPC_CPU1_L_CPU2_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,
                    IPC_CMD_READ_MEM, (uint32_t)readData, 10);

    //
    // Wait for acknowledgment
    //
    IPC_waitForAck(IPC_CPU1_L_CPU2_R, IPC_FLAG0);

    //
    // Read response
    //
    if(IPC_getResponse(IPC_CPU1_L_CPU2_R) == TEST_PASS)
    {
        pass = 1;
    }
    else
    {
        pass = 0;
    }

    //
    // End of example. Loop forever
    //
    while(1);
}


//
// End of File
//

Code in CPU2

//
// Included Files
//
#include "driverlib.h"
#include "device.h"

//
// Defines
//
#define IPC_CMD_READ_MEM   0x1001
#define IPC_CMD_RESP       0x2001

#define TEST_PASS          0x5555
#define TEST_FAIL          0xAAAA
//
//Define variables
//
uint32_t recbuf[10]={0};
char recbuf1[10]={0};
//
// Function prototypes
//
__interrupt void IPC_ISR0();

//
// Main
//
void main(void)
{
    int t=0;
    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    //
    // Clear any IPC flags if set already
    //
    IPC_clearFlagLtoR(IPC_CPU2_L_CPU1_R, IPC_FLAG_ALL);

    //
    // Enable IPC interrupts
    //
    IPC_registerInterrupt(IPC_CPU2_L_CPU1_R, IPC_INT0, IPC_ISR0);

    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;

    //
    // Synchronize both the cores.
    //
    IPC_sync(IPC_CPU2_L_CPU1_R, IPC_FLAG31);
    //
    //Set SCIB
    //
    SCI_setConfig(SCIB_BASE, DEVICE_LSPCLK_FREQ, 256000, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE));
    SCI_resetChannels(SCIB_BASE);
    SCI_enableModule(SCIB_BASE);
    SCI_performSoftwareReset(SCIB_BASE);
    //
    // Loop forever. Wait for IPC interrupt
    //

    while(1)
    {
        for(t=0;t<10;t++)
        {
            recbuf1[t]=recbuf[t];
        }
        for(t=0;t<10;t++)
        {
            if(recbuf1[t] == 0)
            {
                continue;
            }
            SCI_writeCharBlockingNonFIFO(SCIB_BASE, recbuf1[t]);
              if(recbuf1[t] == '\n')
            {
                  recbuf1[t] = 0;
                break;
            }
              recbuf1[t] = 0;
        }
    }
}

//
// IPC ISR for Flag 0.
// C28x core sends data without message queue using Flag 0
//
__interrupt void IPC_ISR0()
{
    int i;
    uint32_t command, addr, data;
    bool status = false;

    //
    // Read the command
    //
    IPC_readCommand(IPC_CPU2_L_CPU1_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,
                    &command, &addr, &data);

    if(command == IPC_CMD_READ_MEM)
    {
        status = true;

        //
        // Read and compare data
        //
        for(i=0; i<data; i++)
        {
            recbuf[i]=*((uint32_t *)addr + i);
            //if(*((uint32_t *)addr + i) != i)
                //status = false;
        }
    }

    //
    // Send response to C28x core
    //
    if(status)
    {
        IPC_sendResponse(IPC_CPU2_L_CPU1_R, TEST_PASS);
    }
    else
    {
        IPC_sendResponse(IPC_CPU2_L_CPU1_R, TEST_FAIL);
    }

    //
    // Acknowledge the flag
    //
    IPC_ackFlagRtoL(IPC_CPU2_L_CPU1_R, IPC_FLAG0);

    //
    // Acknowledge the PIE interrupt.
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}
//
// End of File
//

I have defined the following pins in the device

#define DEVICE_GPIO_PIN_SCIRXDB 11U // GPIO number for SCIB RX
#define DEVICE_GPIO_PIN_SCITXDB 10U // GPIO number for SCIB TX
#define DEVICE_GPIO_CFG_SCIRXDB GPIO_11_SCIB_RX // "pinConfig" for SCIB RX
#define DEVICE_GPIO_CFG_SCITXDB GPIO_10_SCIB_TX // "pinConfig" for SCIB TX

Thank you very much!

Looking forward to your reply!

  • Hi,

    I dont see the handing over of SCI module to the CPU2 being done anywhere in your CPU1 code. You'll have to handover the ownership of required module to CPU2 to ensure correct operation - 

    SysCtl_selectCPUForPeripheral(SYSCTL_CPUSEL5_SCI, 2, SYSCTL_CPUSEL_CPU2);

    Also, we do have a reference example available with C2000Ware with a similar use-case. Request you to check that out for a faster development.

    Location: C2000Ware_4_03_00_00\driverlib\f2838x\examples\c28x_dual\sci

    Thanks,

    Aditya

  • Thank you very much for your reply.
    My code does have the corresponding GPIOs sent to the CPU2 core for control as follows

    GPIO_setMasterCore(DEVICE_GPIO_PIN_SCITXDB, GPIO_CORE_CPU2);
    GPIO_setMasterCore(DEVICE_GPIO_CFG_SCITXDB, GPIO_CORE_CPU2);

    But it doesn't work, so I'd like to ask what the reason is for the lack of success

    I am also debugging the example you mentioned and after importing it, three projects appear, cci_ex1_sysconfig_cpu1, cci_ex1_sysconfig_cpu2 and cci_ex1_sysconfig_multi. What is the role of sci_ex1_sysconfig_multi and do I need to burn this project when burning the program?
    Thank you very much!

  • Hi,

    The GPIO config that you have done is specific just to the GPIO pin outs. The module SCI itself needs to be transferred to the CPU2 core. For that you'll have to use the function mentioned in the previous reply.

    I am also debugging the example you mentioned and after importing it, three projects appear, cci_ex1_sysconfig_cpu1, cci_ex1_sysconfig_cpu2 and cci_ex1_sysconfig_multi. What is the role of sci_ex1_sysconfig_multi and do I need to burn this project when burning the program?

    The multi example is basically a common example which utilizes the ex1 and ex2 as the underlying examples. If you build the sci_ex1_sysconfig_multi example, it fundamentally builds the ex1 and ex2 itself. sci_ex1_sysconfig_multi is dependent on cci_ex1_sysconfig_cpu1 and cci_ex1_sysconfig_cpu2 .

  • Thank you very much for your reply, I added SysCtl_selectCPUForPeripheral(SYSCTL_CPUSEL5_SCI, 2, SYSCTL_CPUSEL_CPU2); statement to my code to enable the communication function of SCIB of CPU2

  • I believe that resolves your issue. Can you please confirm?

    Aditya