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: IPC example understanding & Applying in SYS/BIOS

Part Number: TMS320F28388D

Tools

- CCS 10.1.1

- C2000Ware 3.03.00

- Complier V20.2.1.LTS

- Xdc tool 3.61.02.27

- BIOS 6.83.00.18


Thanks to previous E2E post , (  https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/976857 ) I updated Hwi manager .

Now, I'm studying IPC with TRM & several examples (  ex : driverlib \ f2838x \ examples \ c28x_cm \ ipc ) .

Could you check what I understand , please?


Basically, IPC operates with 3 steps ( send data from CPU1 to CM ) 

1.  Local Core ( CPU1 ) set IPC FLAGs High , one for sending interrupt signal and one for sending command , then Remote Core ( CM ) enable IPC interrupt.

2.  CPU1 send data which is divieded into 3 parts : command , start address , data length

3.  CM receives command , and starts reading data in shared memory during IPC_ISR0

let's see example code  

<CPU1>

IPC_clearFlagLtoR(IPC_CPU1_L_CM_R, IPC_FLAG_ALL);
IPC_sync(IPC_CPU1_L_CM_R, IPC_FLAG31);  // step 1
for(i=0; i<10; i++)
    {
        readData[i] = i;
    }
IPC_sendCommand(IPC_CPU1_L_CM_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,
                    IPC_CMD_READ_MEM, (uint32_t)readData, 10); // step 2
IPC_waitForAck(IPC_CPU1_L_CM_R, IPC_FLAG0);
if(IPC_getResponse(IPC_CPU1_L_CM_R) == TEST_PASS)
    {
        pass = 1;
    }
    else
    {
        pass = 0;
    }


<CM>
main.c IPC_clearFlagLtoR(IPC_CM_L_CPU1_R, IPC_FLAG_ALL); IPC_registerInterrupt(IPC_CM_L_CPU1_R, IPC_INT0, IPC_ISR0); // step 1 IPC_sync(IPC_CM_L_CPU1_R, IPC_FLAG31); void IPC_ISR0() { IPC_readCommand(IPC_CM_L_CPU1_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE, &command, &addr, &data); if(command == IPC_CMD_READ_MEM) { status = true; for(i=0; i<data; i++) { if(*((uint32_t *)addr + i) != i) status = false; } } // step 3 if(status) { IPC_sendResponse(IPC_CM_L_CPU1_R, TEST_PASS); } else { IPC_sendResponse(IPC_CM_L_CPU1_R, TEST_FAIL); } IPC_ackFlagRtoL(IPC_CM_L_CPU1_R, IPC_FLAG0); }

As a result, CM can get data ( 10 bits array : [ 0~ 9 ] ) from CPU1.

Q1 ) where can i check this data in CM? can i see it in expressions session?

Q2 ) I think this process with IPC interrupt doesn't run infinitly like other LED blink examples, Do I understand right?

Q3 ) If I construct this process with SYS/BIOS, I think It's not just adding IPC_ISR0() on .cfg file. How can I write inital setting before BIOS_start()?

I'm sorry I asked you the basics.

Regards, 

Donghee Kim.


  • Q1) The example doesn't put the data in a buffer, but just reads it from the address instead, so there's nothing to add to the Expressions window. You can get the value of addr from the Expressions window and then navigate to that address in the Memory Browser to see the data. You could also change the code to declare a buffer and then add code to the "Read and compare data" loop to transfer the data from addr into your new buffer.

    Q2) Right, this example only sends one command to the CM, so the interrupt only occurs once.

    Q3) I'm not sure what initial settings you're referring to--I think you already have all the Device_init() and Device_bootCM() code you need. You can do like the example does and clear the flags and perform a sync if that makes sense for your application. There are no special SYS/BIOS configurations for IPC--just creating Hwis for your IPC interrupts like you would for any peripheral.

    Whitney

  • Thank you for replying , Whitney.

    Can I ask more about buffer setting on Q1)?

    Q1-1) I debuged example project and checked every single line by step over process, after all processes were done, I noticed address changes on IpcCPUxtoCPUyREgs : IPCRECV - COM , ADDR , DATA . I think value of these register doens't mean real data , just information about data state.( I guess data is in shared MSGRAM ) 

    How can I find exat data address on main.c file?

    Q1-2)

    there are structs "IPC_PutBuffer_t" & "IPC_GetBuffer_t" on Ipc.h . So I trying to use these struct to declare new buffer

    How can I create new buffer to watch data transportation using those structs?

    I guess I have to declare buffer using  IPC_PutBuffer_t struct, on CPU2 & IPC_GetBuffer_t on CPU2

    ex) <CPU2>

     typedef struct
    {
        uint32_t command;
        uint32_t address;
        uint32_t dataw1;
        uint32_t dataw2;
    }IPC_Message_t;
    
     IPC_Message_t TxMsg
    
     TxMsg.command = IPC_CMD_RESP;
     TxMsg.address = 0; 
     TxMsg.dataw1  = status ? TEST_PASS : TEST_FAIL;
     TxMsg.dataw2  = RxMsg.dataw2;
    
    typedef struct
    {
        IPC_Message_t Buffer[IPC_NUM_OF_INTERRUPTS][IPC_BUFFER_SIZE];
        uint16_t      GetWriteIndex[IPC_NUM_OF_INTERRUPTS];
        uint16_t      PutReadIndex[IPC_NUM_OF_INTERRUPTS];
    }IPC_GetBuffer_t;
    

    How can I declare IPC_GetBuffer_t struct component? and is it enough to watch data on expression window?

    Regards,

    Donghee Kim

     

  • Q1-1) That's right. Note that the CPU1 program declares the array readData[10] and places it in the CPU-to-CM RAM. It then passes its address as the addr parameter of IPC_sendCommand(). This address doesn't actually go into the register as-is though--it's adjusted to an offset to deal with the fact that the message RAMs are mapped to different addresses on CM and CPU1.

    When CM reads the command with the IPC_readCommand() function, the function will use the value in the ADDR register to calculate the equivalent address on the CM and return it to the application in the addr parameter. Put a breakpoint in the ISR after the IPC_readCommand() call and you'll be able to read the value of addr in the Expressions window.

    Also note that the data parameter is being used to hold the length of the data--not the data itself.

    Q1-2) In my previous message I was suggesting you could create an array on the CM side and copy the data from the message RAM into it. So declare something like uint32_t rcvData[20]; and then in the ISR as it's looping through the data to check its correctness, add a line rcvData[i] = *((uint32_t *)addr + i);. You would then be able to put rcvData in the Expressions window.

    Those IPC_Put/GetBuffer_t structs are used by the message queue feature. It's not used in this example--look at ipc_ex2_msgqueue example instead.

    Whitney

  • Sorry for late reply.

    Anyway, It helped me a lot

    Thanks!

    Donghee Kim