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.

Linux/TDA2EVM5777: Problem using DSP in custom build environment

Part Number: TDA2EVM5777
Other Parts Discussed in Thread: TDA2

Tool/software: Linux

Hello *!

I've got the following problem bringing up the DSP of the TDA2 in a command line custom build environment (OUTSIDE CCS): 

Environment descrition

custom resource table (rproc)

...
/*
Linux - Carve out -> device tree: 
reg = <0x0 0xA100_0000 0x0   0x200_0000>;
*/
#define DSP_SHMEM            0xa1004000
#define DSP_SHMEM_SIZE        0x1000000
/* OC_MEMORY */
#define IPC_MEM_VIRT        0x40300000
#define IPC_MEM_PHYS        0x40300000
#define IPC_MEM_VIRT_SIZE   0x80000
...
struct my_resource_table {
    struct resource_table base;

    unsigned int offset[RSC_NUM_ENTRIES];  /* Should match 'num' in actual definition */

    /* rpmsg vdev entry */
    struct fw_rsc_vdev rpmsg_vdev;
    struct fw_rsc_vdev_vring rpmsg_vring0;
    struct fw_rsc_vdev_vring rpmsg_vring1;

    /* text carveout entry */
    struct fw_rsc_carveout text_cout;

    /* devmem entry */
    struct fw_rsc_devmem devmem0;
};

//extern char ti_trace_SysMin_Module_State_0_outbuf__A;

#pragma DATA_SECTION(ti_ipc_remoteproc_ResourceTable, ".resource_table")
#pragma DATA_ALIGN  (ti_ipc_remoteproc_ResourceTable, 4096)
#pragma RETAIN (ti_ipc_remoteproc_ResourceTable)

struct my_resource_table ti_ipc_remoteproc_ResourceTable = {
    1,      /* we're the first version that implements this */
    RSC_NUM_ENTRIES,     /* number of entries in the table */
    0, 0,   /* reserved, must be zero */
    /* offsets to entries */
    {
        offsetof(struct my_resource_table, rpmsg_vdev),
        offsetof(struct my_resource_table, text_cout),
        offsetof(struct my_resource_table, devmem0),
   },
    /* rpmsg vdev entry */
    {
        TYPE_VDEV, VIRTIO_ID_RPMSG, 0,
        RPMSG_DSP_C0_FEATURES, 0, 0, 0, 2, { 0, 0 },
        /* no config data */
    },
    /* the two vrings */
    { DSP_MEM_RPMSG_VRING0, 4096, DSP_RPMSG_VQ0_SIZE, 1, 0 },
    { DSP_MEM_RPMSG_VRING1, 4096, DSP_RPMSG_VQ1_SIZE, 2, 0 },

    {
        TYPE_CARVEOUT,
        DSP_SHMEM, 0,
        DSP_SHMEM_SIZE, 0, 0, "DSP_SHMEM",
    },

    {
        TYPE_DEVMEM,
        IPC_MEM_VIRT, IPC_MEM_PHYS,
        IPC_MEM_VIRT_SIZE, 0, 0, "IPC_MEM_VIRT",
    },
};

linker cmd file

MEMORY
{
    IRAM_MEM:  o = 0x00800000 l = 0x00008000   /* 32kB internal SRAM */
    OCMC_RAM1: o = 0x40300000 l = 0x00080000   /* 512kB L3 OCMC SRAM1 */
    SHMEM:     o = 0xa1004000 l = 0xF00000
}

SECTIONS
{
    .text          >  SHMEM
    .stack         >  SHMEM
    .bss           >  SHMEM
    .cio           >  SHMEM
    .const         >  SHMEM
    .data          >  SHMEM
    .switch        >  SHMEM
    .sysmem        >  SHMEM
    .far           >  SHMEM
    .args          >  SHMEM
    .ppinfo        >  SHMEM
    .ppdata        >  SHMEM

    /* COFF sections */
    .pinit         >  SHMEM
    .cinit         >  SHMEM

    /* EABI sections */
    .binit         >  SHMEM
    .init_array    >  SHMEM
    .neardata      >  SHMEM
    .fardata       >  SHMEM
    .rodata        >  SHMEM
    .c6xabi.exidx  >  SHMEM
    .c6xabi.extab  >  SHMEM
    .resource_table > SHMEM {
                main.obj(.resource_table)
     }
}

call of cl6x in Makefile

...
TOP=${PWD}
TOOLCHAIN=$(TOP)/linux_toolchain/C6000_7.4.2
TICL=$(TOOLCHAIN)/bin/cl6x
INCLUDE=$(TOOLCHAIN)/lib
TARGET_NAME=dra7-dsp1-fw.xe66

CL6X_OPTIONS= --abi=eabi --run_linker --ram_model --unused_section_elimination=on --map_file=link.map --stack_size=0x1000   linker.cmd
LDFLAGS= -w -q -u _c_int00 -c -m linker.map
BUILD_FLAGS=-mv6600  -g --diag_warning=225 --diag_wrap=off --display_error_number --preproc_with_compile --preproc_dependency="depend.d" --c99
LINK= -l $(INCLUDE)/libc.a

all: build_objects link_together

build_objects: 
        $(TICL) --abi=eabi -c main.c $(BUILD_FLAGS)

link_together:
        $(TICL) $(CL6X_OPTIONS) -o $(TARGET_NAME) -i $(INCLUDE) $(LINK) -u _c_int00
...

Result in Error:

[  835.520532] remoteproc remoteproc2: rsc: type 3
[  835.520544] remoteproc remoteproc2: rsc: type 0
[  835.520553] remoteproc remoteproc2: rsc: type 1
[  835.520561] remoteproc remoteproc2: rsc: type 3
[  835.520571] remoteproc remoteproc2: vdev rsc: id 7, dfeatures 1, cfg len 0, 2 vrings
[  835.520582] remoteproc remoteproc2: vdev rsc: vring0: da a0000000, qsz 256, align 4096
[  835.520591] remoteproc remoteproc2: vdev rsc: vring1: da a0004000, qsz 256, align 4096
[  835.521595] remoteproc remoteproc2: vring0: va e1000000 dma 0xa1000000 size 3000 idr 0
[  835.521646] remoteproc remoteproc2: vring1: va e1004000 dma 0xa1004000 size 3000 idr 1
[  835.521667] remoteproc remoteproc2: powering up 40800000.dsp
[  835.521679] remoteproc remoteproc2: Booting fw image dra7-dsp1-fw.xe66, size 28540
[  835.528810] omap_hwmod: mmu0_dsp1: _wait_target_disable failed
[  835.528854] omap-iommu 40d01000.mmu: 40d01000.mmu: version 3.0
[  835.528946] omap-iommu 40d02000.mmu: 40d02000.mmu: version 3.0
[  835.528966] remoteproc remoteproc2: rsc: type 3
[  835.528975] remoteproc remoteproc2: rsc: type 0
[  835.528984] remoteproc remoteproc2: carveout rsc: da a1004000, pa 0, len 1000000, flags 0
[  835.535316] remoteproc remoteproc2: carveout va e1100000, dma 0xa1100000, len 0x1000000
[  835.662825] remoteproc remoteproc2: carveout mapped 0xa1004000 to 0xa1100000
[  835.662836] remoteproc remoteproc2: rsc: type 1
[  835.663096] remoteproc remoteproc2: mapped devmem pa 0x40300000, da 0x40300000, len 0x80000
[  835.663115] remoteproc remoteproc2: rsc: type 3
[  835.663123] remoteproc remoteproc2: rsc: type 0
[  835.663131] remoteproc remoteproc2: rsc: type 1
[  835.663640] omap-iommu 40d01000.mmu: iommu fault: da 0xb3175f30 flags 0x0
[  835.663651] remoteproc remoteproc2: crash detected in 40800000.dsp: type mmufault
[  835.663663] omap-iommu 40d01000.mmu: 40d01000.mmu: errs:0x00000002 da:0xb3175f30 pgd:0xee5f2cc
4 *pgd:px00000000
[  835.663699] remoteproc remoteproc2: remote processor 40800000.dsp is now up
[  835.664010] virtio_rpmsg_bus virtio0: rpmsg host is online
[  835.664950] remoteproc remoteproc2: registered virtio0 (type 7)
[  835.664962] remoteproc remoteproc2: rsc: type 0
[  835.664971] remoteproc remoteproc2: rsc: type 1
[  835.664995] remoteproc remoteproc2: enter rproc_crash_handler_work
[  835.665004] remoteproc remoteproc2: handling crash #1 in 40800000.dsp
[  835.665012] remoteproc remoteproc2: recovering 40800000.dsp
[  835.806178] omap_hwmod: mmu1_dsp1: _wait_target_disable failed
[  835.813328] omap_hwmod: mmu0_dsp1: _wait_target_disable failed
[  835.813366] remoteproc remoteproc2: stopped remote processor 40800000.dsp

Something is going wrong in my mappings, but what.... and: Why?

TNX - Marco.

  • Hi Marco,

    which version is the SDK you use?

    Thanks,
    Yordan
  • I do not use a sdk to build this. It is a custom build-environment based on cl6x 7.4.2,
    because we are not able to use XDC, RTOS-fragments, etc... we have to fulfill a couple of security checks, the requirements do not fit the way the TI SDK work... (Esp. the affinity to CCS is not useful in our case).

    I also got a Vision_SDK_2_12_02_00, which I try to use as a guideline....
    I took a look into the "IPC"-stuff... which provides something like a "run from linux"-code example.

    But it make usage of XDC, SYS/BIOS and I run against the same problems I almost had during the "STRIP DOWN" of the IPU stuff.

    Criticism: It seams for me, that TI don't take much care for customers who are not able to use CCS and SDKs. It's a hard fight to get informations to bring up the processors outside the "common" way... (I have to leave as mentioned above).

    So... again (same conversation like IPU-Thread...) -> Please help me bring up the DSP outside the SDK and CCS.

    (FYI: Until now the development on the IPU-Cores "really bare metal" works fine! It took a long time to extract everything needed, but now we are able to build very small, high efficient code and use rproc to fire up the cores. NICE! AND NOW... I have to do the same with the DSP...).

    CU Marco

  • About the main.c and how to implement the resource table: 

    Our Main.c is very easy....

    /**
     * main.c
     */
    
    #include "custom_rsc_table_dsp.h"
    
    void  main(void)
    {
            while (1) {
                    // DO NOTHING.
            }
    }
    

    We go on doing something useful, if the code run on the target without errors and MMU-Violations. 
    -> The rproc-mechanism seems to work... the resource_table have been used, the mapping have been done... but during start of the code, it crashes... 

    section allocations

    maybe its helpful: 

         33 SECTION ALLOCATION MAP
         34 
         35  output                                  attributes/
         36 section   page    origin      length       input sections
         37 --------  ----  ----------  ----------   ----------------
         38 .cinit     0    a1004000    00000000     UNINITIALIZED
         39 
         40 .init_array 
         41 *          0    a1004000    00000000     UNINITIALIZED
         42 
         43 .stack     0    a1004000    00001000     UNINITIALIZED
         44                   a1004000    00000008     rts6600_elf.lib : boot.obj (.stack)
         45                   a1004008    00000ff8     --HOLE--
         46 
         47 .text      0    a1005000    000005a0     
         48                   a1005000    00000100     rts6600_elf.lib : autoinit.obj (.text:_auto_init_elf)
         49                   a1005100    00000100                     : cpy_tbl.obj (.text:copy_in)
         50                   a1005200    000000c0                     : exit.obj (.text:exit)
         51                   a10052c0    000000c0                     : tls.obj (.text:tls:init:__TI_tls_init)
         52                   a1005380    000000a0                     : memcpy64.obj (.text:memcpy)
         53                   a1005420    00000080                     : boot.obj (.text:_c_int00)
         54                   a10054a0    00000060                     : cpp_init.obj (.text:__TI_cpp_init)
         55                   a1005500    00000040                     : args_main.obj (.text:_args_main)
         56                   a1005540    00000040     main.obj (.text)
         57                   a1005580    00000020     rts6600_elf.lib : exit.obj (.text:abort)
         58 
         59 .fardata   0    a10055a0    0000000c     
         60                   a10055a0    0000000c     rts6600_elf.lib : exit.obj (.fardata)
         61 
         62 .resource_table 
         63 *          0    a1006000    000000d0     
         64                   a1006000    000000d0     main.obj (.resource_table:retain)
         65 
    

    (UNINIT, because of RAM-MODEL).

    BTW: What about the startup code?

    A colleague told me, I do not have to take care about it, it would be "inserted" by the compiler and jumps to "main" itself. Really?!
    (I don't think so, this explains why the code craches during trying to start it...) 

    So outside the SDK: Is there an example of a simple start-up code (TDA2-C6xx-DSP)? I can not find out where it is. (I bring up a simple "hello worls" project in CCS and now wondering in the "makefile" directory, where all the well-known-elements are, I've learned they are elementary... ?) 

  • Hi Marco,

    I have forwarded your questions to an expert.

    Regards,
    Yordan
  • Hi Marco,

    You would need to have a vector table in your DSP code which can then point to the _c_int00 code. The compiler inserts the _c_int00 to main code but the vector table is something you need to populate.
    The location of the vector table is determined by what is programmed in the CTRL_CORE_CONTROL_DSP1_RST_VECT or CTRL_CORE_CONTROL_DSP2_RST_VECT register. The configuration is as below:
    /* DSPSS Boot Address */
    WR_MEM_32(CTRL_CORE_CONTROL_DSPx_RST_VECT, (DSPxSSBOOTADDRVALUE >> 10));

    So you would need to check from the A15 what value you are setting for this register.

    You can refer to the starterware_XX_XX_XX_XX\system_config\c66x\intvecs.asm as to how to create a DSP vector table. You should have atleast the reset handler implemented.

    It looks from the log, that the A15 lifts the DSP reset and the DSP does not find the vector table and hence the code execution flies off to some random locations and that creates the faults.

    Please try adding the vector table and let me know if this works for you.

    Thanks and Regards,
    Piyali
  • Hello Piyali

    I'm back again, slightly confused on this MMU error:

    omap-iommu 40d01000.mmu: iommu fault: da 0xb3175f30 flags 0x0

    (Information: It is always this address: 0xb3175f30 ... which don't belong to my code...)

    If I load the shipped binary into the DSP, everything works fine. With my own binary, this error will happen.

    I examined the working ELF and found that the vector table have to be placed to address: 0xA1A3_6000...

    I've still got some trouble accessing 0x4A00_255C while linux running.

    Some values: 0xFFFF_FFFD and 0x0000_0000 have been displayed...

    During my examinations I recognized that there is a lot of code inserted by the C6XL:

    __TI_enable_exit_profile_

    __TI_CINIT_Base

    ...

    So. what is going on?

    I think, I got everything I need to bring up the DSP with my small build environment and I've got so much informations, that I am not able to see how.

    So lets see what I have, again:

    I've got a custom table results in the following RPROC behavior:

    [   74.732441] remoteproc remoteproc2: vdev rsc: id 7, dfeatures 1, cfg len 0, 2 vrings
    [   74.732448] remoteproc remoteproc2: vdev rsc: vring0: da a0000000, qsz 256, align 4096
    [   74.732455] remoteproc remoteproc2: vdev rsc: vring1: da a0004000, qsz 256, align 4096
    [   74.733084] remoteproc remoteproc2: vring0: va e1000000 dma 0xa1000000 size 3000 idr 0
    [   74.733115] remoteproc remoteproc2: vring1: va e1004000 dma 0xa1004000 size 3000 idr 1
    [   74.733128] remoteproc remoteproc2: powering up 40800000.dsp
    [   74.733136] remoteproc remoteproc2: Booting fw image dra7-dsp1-fw.xe66, size 31025
    [   74.739723] omap_hwmod: mmu0_dsp1: _wait_target_disable failed
    [   74.739758] omap-iommu 40d01000.mmu: 40d01000.mmu: version 3.0
    [   74.739807] omap-iommu 40d02000.mmu: 40d02000.mmu: version 3.0
    [   74.739819] remoteproc remoteproc2: rsc: type 3
    [   74.739825] remoteproc remoteproc2: rsc: type 0
    [   74.739831] remoteproc remoteproc2: carveout rsc: da a1200000, pa 0, len 1000000, flags 0
    [   74.744068] remoteproc remoteproc2: carveout va e1100000, dma 0xa1100000, len 0x1000000
    [   74.744498] remoteproc remoteproc2: carveout mapped 0xa1200000 to 0xa1100000
    [   74.744503] remoteproc remoteproc2: rsc: type 0
    [   74.744510] remoteproc remoteproc2: carveout rsc: da a1000000, pa 0, len 200000, flags 0
    [   74.745133] remoteproc remoteproc2: carveout va e2100000, dma 0xa2100000, len 0x200000
    [   74.745193] remoteproc remoteproc2: carveout mapped 0xa1000000 to 0xa2100000
    [   74.745199] remoteproc remoteproc2: rsc: type 1
    [   74.745233] remoteproc remoteproc2: mapped devmem pa 0x40300000, da 0x40300000, len 0x10000
    

    And, of course, there is "my" bug: 

    omap-iommu 40d01000.mmu: iommu fault: da 0xb3175f30 flags 0x0
    

    My linker file now looks like: 

    -stack  0x001000                            /* Software Stack Size */
    -heap   0x001000                            /* Heap Area Size */
    
    --retain="*(.vects)"
    
    #define RST_VEC 0xa1a36000
    
    MEMORY
    {
        IRAM_MEM:  o = 0x00800000 l = 0x00008000   /* 32kB internal SRAM */
        OCMC_RAM1: o = 0x40300000 l = 0x00080000   /* 512kB L3 OCMC SRAM1 */
        DATA_MEM:  o = 0xa1200000 l = 0x1800000    /* data, text, COFF and co... space for ALL other stuff */
        CODE_MEM:  o = 0xa1000000 l = 0x200000     /* data, text, COFF and co... space for ALL other stuff */
    }
    
    SECTIONS
    {
        /* BOOTING DSP */
    
        .vects         >  RST_VEC
    
        /* COMMON SECTIONS */
        .text          >  CODE_MEM
        .const         >  CODE_MEM
        .cinit         >  CODE_MEM
    
        .stack         >  DATA_MEM
        .data          >  DATA_MEM
        .cio           >  DATA_MEM
        .far           >  DATA_MEM
        .fardata       >  DATA_MEM
        .stack         >  DATA_MEM
        .switch        >  DATA_MEM
        .sysmen        >  DATA_MEM
        .resource_table > CODE_MEM {
                    main.obj(.resource_table)
         }
    }
    

    ... and I use the assembler code from the location you posted above to generate something like a "startup code". 

    My main program may contain the error, because I have to improve something like a placeholder for the vector table... and I'm not shure, if this do it the right way: 

    /**
     * main.c
     */
    
    #include "custom_rsc_table_dsp.h"
    
    #pragma DATA_SECTION(__ISR_Table, ".vects")
    Uint32  __ISR_Table[16] = {
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000
    };
    
    
    void counter (void){
            unsigned int ui_loop = 0xffff;
    
            while (ui_loop--);
    }
    
    void  main(void)
    {
            while (1) {
                    counter();
            }
    }
    ~     

    My current Makefile:

    TOP=${PWD}
    TOOLCHAIN=$(TOP)/linux_toolchain/C6000_7.4.2
    TICL=$(TOOLCHAIN)/bin/cl6x
    INCLUDE=$(TOOLCHAIN)/lib
    TARGET_NAME=dra7-dsp1-fw.xe66
    
    LIST_OF_OBJ=intvecs.obj main.obj
    
    CL6X_LINKER= --abi=eabi --run_linker $(LIST_OF_OBJ) --ram_model --map_file=link.map --stack_size=0x1000   linker.cmd
    BUILD_FLAGS=-mv6600  -g --diag_warning=225 --diag_wrap=off --display_error_number --preproc_with_compile --preproc_dependency="depend.d"
    LINK= -l $(INCLUDE)/libc.a
    
    
    all: build_objects link_together
    
    build_objects: 
            $(TICL) --abi=eabi -c main.c $(BUILD_FLAGS)
            $(TICL) --abi=eabi -mv6600 --abi=eabi -g intvecs.asm
    
    link_together:
            $(TICL) $(CL6X_LINKER) -o $(TARGET_NAME) -I $(INCLUDE) $(LINK)
    
    version:
            $(TICL) -version
    
    clean: 
            rm -rf *.obj
            rm -rf *.d
            rm -rf *.map
            rm -rf *.out
            rm -rf $(TARGET_NAME)
    

    May be you (or somebody else...) is able to take a short look at my "stuff" and recognize something which MUST result in a crash?

    Hmmm.... first: Thanks to everybody who helped me until now.

    (BTW: If I do not start linux and enable the DSP, push in the ELF over JTAG instad of REPROC, the code runs... but I don't now if the GEL-scripts of the CCS do the whole job and of course using CCS is not my goal to reach.)

  • Marco,

    When GEL files are used, the MMU is not setup and all addresses accessed by the DSP are treated as physical addresses.

    When you load the binary through Linux, the kernel sets up the L2 MMU for the DSP based on the resource table. Any attempts to access regions outside those specified in the resource table will result in an MMU fault. At the minimum, the register region containing the timers should be specified in the resource table.

    git.ti.com/.../rsc_table_vayu_dsp.h

    I would suggest adding the DEVMEM regions corresponding to L3/L4 peripherals into the resource table and verify that the DSP binary works. After that, the resource table can be pruned as necessary.

    regards,
    Venkat
  • Hi Venkat,

    That explains why the binary can be loaded into the DSP and will run over JTAG on CCS.

    On the otherhand, what I did:
    I use the CARVEOUT of the Linux for code/data storage and generated two CARVEOUT segments on which I split the sections from the linker.cmd file of the cl6x.

    WHY should I add the peripherals into the table... Only some of them I will use, later... In the code I can see (?!) there is no need to do so...

    My intention, why I "got though the hell of simplifying" is quite easy: We have to guarantee, that we have EVERY CODE running on DSP (security relevant!) under our OWN CONTROL.
    When the CL6X adds code, from which I do not know what it will do... which I can not configure... WOW: This might be a show-stopper.

    So MAYBE there is any manual which explains WHAT exactly I have to do bringing up the DSP on the TDA2 "FROM SCRATCH" on my own, outside the SDK with not more than the CL6X and code I have under my control?
  • Marco,

    Is the entry point in the DSP code aligned to 1KB boundary? This is a requirement to take DSP out of reset.

    Are you saying that you are seeing the exception if you just have an infinite while loop in the code?

    regards,
    Venkat
  • Venkat,

    Indeed this is not really clear to me: I used the basics out of "IPC"-Baremetal directory of the SDK... so I'm not really shure... hmmm.

    Would you please introduce me from an expert point of view, how to define the entry point?
    (It is programmable using a special register on A15,... done by remoteproc?)

    Other question:
    Yes, I think the "main"-code have not been reached, it crashes before... may be it is the "jump" to it, or unalignment bug... or it may be any kind of access to none-mapped periphery (I do not touch any kind of periphery... if so, there must be some code used, which is not under my control... cl6x-stuff?).

    NOW -> I try to examine the code, because you gave a lot of tips! THANK YOU!
    (Especially: What is the target of the illegal address-call...)

    AGAIN: Please show me hot to set the entry point correct and how to handle "CTRL_CORE_CONTROL_DSP2_RST_VECT" of the A15, or is it done by remoteproc automatically? Then: How to tell the cl6x to set the "entry point" definition in the ELF-File during linking...

    I've got a leak of information on that.... THANK YOU for your help.
  • Marco,

    >> Please show me hot to set the entry point correct and how to handle "CTRL_CORE_CONTROL_DSP2_RST_VECT" of the A15, or is it done by remoteproc automatically?

    The entry point is read from the ELF binary by remoteproc. You can look at the output of "readelf -a <dsp-binary.xe66>" to find the entry point. Below is a sample output. You can see the entry point aligned to 1024 bytes.

    Entry point address: 0x95023800
    ...
    Section Headers:
    [19] .vecs PROGBITS 95023800 024800 000200 00 AX 0 0 1024

    If the address is not aligned, you can use the "ALIGN" directive in the linker command file to align the section containing the reset vector.

    You can find the linker documentation here.

    www.ti.com/lit/pdf/spru186

    >> Would you please introduce me from an expert point of view, how to define the entry point?

    Please look into the usage of "--entry_point" option in SPRU186. If you are using C code, this is defined at "_c_int00" by default.

    regards,
    Venkat