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.

AM5728: DSP memory mapping

Part Number: AM5728

HI,

I am trying to understand the memory architecture of AM5728, in my project I am able to use DSP1, DSP2 and ARM cores without issue, I have the following doubts.

1. Below is the portion of map file of DSP1.

******************************************************************************
               TMS320C6x Linker Unix v8.2.2                    
******************************************************************************
>> Linked Wed May 22 19:10:58 2019

OUTPUT FILE NAME:   <dra7-dsp1-fw.xe66>
ENTRY POINT SYMBOL: "ti_sysbios_family_c64p_Hwi0"  address: 9503f400


MEMORY CONFIGURATION

         name            origin    length      used     unused   attr    fill
----------------------  --------  ---------  --------  --------  ----  --------
  L2SRAM                00800000   00040000  0000ea60  000315a0  RW X
  OCMC_RAM1             40300000   00080000  00000000  00080000  RW X
  OCMC_RAM2             40400000   00100000  00000000  00100000  RW X
  OCMC_RAM3             40500000   00100000  00000000  00100000  RW X
  EXT_CODE              95000000   00100000  0003f420  000c0be0  RW X
  EXT_DATA              95100000   00100000  000a4444  0005bbbc  RW  
  EXT_HEAP              95200000   00300000  00000000  00300000  RW  
  TRACE_BUF             9f000000   00060000  00008004  00057ffc  RW  
  EXC_DATA              9f060000   00010000  00000000  00010000  RW  
  PM_DATA               9f070000   00020000  00000000  00020000  RW X

Below ia the portion of map file for DSP2

******************************************************************************
               TMS320C6x Linker Unix v8.2.2                    
******************************************************************************
>> Linked Wed May 22 22:08:44 2019

OUTPUT FILE NAME:   <dra7-dsp2-fw.xe66>
ENTRY POINT SYMBOL: "ti_sysbios_family_c64p_Hwi0"  address: 95043000


MEMORY CONFIGURATION

         name            origin    length      used     unused   attr    fill
----------------------  --------  ---------  --------  --------  ----  --------
  L2SRAM                00800000   00040000  0002a76c  00015894  RW X
  OCMC_RAM1             40300000   00080000  00000000  00080000  RW X
  OCMC_RAM2             40400000   00100000  00000000  00100000  RW X
  OCMC_RAM3             40500000   00100000  00000000  00100000  RW X
  EXT_CODE              95000000   00100000  00042f60  000bd0a0  RW X
  EXT_DATA              95100000   00900000  00305a1c  005fa5e4  RW  
  EXT_HEAP              95a00000   00400000  00000000  00400000  RW  
  TRACE_BUF             9f000000   00060000  00008004  00057ffc  RW  
  EXC_DATA              9f060000   00010000  00000000  00010000  RW  
  PM_DATA               9f070000   00020000  00000000  00020000  RW X

If we observe the different sections such as "EXT_CODE","EXT_DATA" and other sections from above tables, DSP1 and DSP2 is using the same origin address. I observe both the cores are running independently without issue. How is actually the memory being manged? 

From device tree we allocate different CMA base address for DSP1 and DSP2, from map file we see that both cores are using same address for different sections. In resource table of DSP1 we are using below macro 

#define PHYS_MEM_IPC_VRING      0x99000000

and in resource table of DSP2 we are using below macro

#define PHYS_MEM_IPC_VRING      0x9F000000

Can someone please explain how exacly the memory is being organzed and utilized by different cores?

2. I need to understand what the below API is acually doing

status = Resource_physToVirt(cmem_address, (UInt32 *)&cmem_ptr);

Is this API converting Physical address to virtual address? In Resource table am I supposed to use the virtual address anywhere? 

From following section of resource table "PHYS_CMEM_IOBUFS" is the physical address and "DSP_CMEM_IOBUFS" is the corresponding virtual address. 

#define DSP_CMEM_IOBUFS 0x85000000
#define PHYS_CMEM_IOBUFS 0xA0000000

{
TYPE_DEVMEM,
DSP_CMEM_IOBUFS, PHYS_CMEM_IOBUFS,
DSP_CMEM_IOBUFS_SIZE, 0, 0, "DSP_CMEM_IOBUFS",
},

Can someone provide clearity on this?

Thanks,

Janardan

  • Hello Janardan,

    1. The addresses in the DSP map file are the virtual addresses, i.e. the addresses seen by the DSP subsystem. The physical location where the DSP code/data actually resides is defined by the CMA carveout in the Linux device tree. The resource table is used to bridge the physical and virtual addresses.

    This entry in the resource table

    {
            TYPE_CARVEOUT,
            DSP_MEM_DATA, 0,
            DSP_MEM_DATA_SIZE, 0, 0, "DSP_MEM_DATA",
    },

    tells remoteproc to allocate memory from its CMA area and map the allocated physical address to the virtual address specified in the carveout (the 1st field after TYPE_CARVEOUT), in the DSP's MMU.

    As mentioned earlier, the actual location where the DSP code/data will reside is defined by this entry in the Linux dts:

     dsp1_cma_pool: dsp1_cma@99000000 {
                    compatible = "shared-dma-pool";
                    reg = <0x0 0x99000000 0x0 0x4000000>;
                    reusable;
                    status = "okay";
            };
    
            dsp2_cma_pool: dsp2_cma@9f000000 {
                    compatible = "shared-dma-pool";
                    reg = <0x0 0x9f000000 0x0 0x800000>;
                    reusable;
                    status = "okay";
            };
    };

    The address of "PHYS_MEM_IPC_VRING" needs to match the address defined here.  

    2. That API translates the physical address to a virtual address so that it can be used by the DSP. It does this by looking up the mapping defined in the resource table. The snippet below is an example of the ARM sending the physical address of a buffer to the DSP, followed by the DSP receiving the physical address, translating it to a virtual address, and accessing the buffer. 

    /* allocate message */
    msg = (App_Msg *)MessageQ_alloc(Module.heapId, Module.msgSize);
    if (msg == NULL) {
    status = -1;
    goto leave;
    }
    /* set the return address in the message header */
    MessageQ_setReplyQueue(Module.hostQue, (MessageQ_Msg)msg);
    /* fill in message payload */
    msg->cmd = App_CMD_NOP;
    msg->physAddr = cmem_buf_desc.physAddr;
    /* send message */
    MessageQ_put(Module.slaveQue, (MessageQ_Msg)msg);
    /* wait for inbound message */
    status = MessageQ_get(Module.slaveQue, (MessageQ_Msg *)&msg,
    MessageQ_FOREVER);
    if (status < 0) {
    goto leave;
    }
    Log_print1(Diags_INFO, "Server_exec: physAddr=0x%x", msg->physAddr);
    ret = Resource_physToVirt(msg->physAddr, &va);
    if(ret == Resource_S_SUCCESS) {
    for (i=0; i<4; i++)
    Log_print1(Diags_INFO, "Server_exec: *VA=0x%x", *((UInt32 *)va + i));
    }

    Most of this is described in the Linux IPC on AM57xx document found here: http://software-dl.ti.com/processor-sdk-linux/esd/docs/latest/linux/Foundational_Components_IPC.html#ipc-for-am57xx

    I hope this clears things up. If you have any questions please let me know.

    Regards,
    Sahin

  • Hi sachin,

    Thanks for the explainatin , I am quite clear now.

    Regards,

    Janardan

  • Hi Janardan,

    No problem! If you don't have any more questions, please mark this thread as Resolved. Thanks!

    Regards,
    Sahin