Ticket Name: Linux/TDA2EVM5777: Problem using DSP in custom build environment Query Text: 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. Responses: 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 Thank you! 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 Thanks Piyali Goswami ! I will check this.... 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 " 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