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.

AM62A7: C75x DSP crashes before reaching main(), unless I single-step the MMU initialization

Part Number: AM62A7
Other Parts Discussed in Thread: SYSCONFIG

Moin from Hamburg,
I am trying to get the "hello_world" example from the MCU+ SDK (MCU+ SDK for AM62A – RTOS, No-RTOS - Version: 09.00.00.19) to work on the C75x DSP but am having not much success.

From what I can tell after spending a day in the debugger, it seems that the DSP either crashes or receives an interrupt it can't handle during the transition from secure mode to non-secure mode.

What I have tried:

1. Flashing the binary from CCS, following the instructions in "CCS Launch, Load and Run" from the Documentation (Wait for Linux to boot, connect to DSP, reset, load program)
--> This does NOT work. The core shows "running" in the debugger forever, and when I click "pause", the program counter is spinning on address 0x99A00000 (C7X_VECTOR_BASE from the linker file)

2. Replacing the firmware that is booted by Linux with the example
--> This does NOT work. The DSP seems to crash

3. Changing the entry point from _c_int00_secure to _c_int00
--> This allows me to load the program in CCS (after booting the DSP with /lib/firmware/vision_apps_eaik/vx_app_rtos_linux_c7x_1.out, resetting it and flashing the example).
--> However, the behavior when attempting to load this as firmware is the same as (2). The DSP crashes.

4. Loading the example (compiled with debug symbols) and disabling the Auto-Run in CCS.
--> This allows me to load the binary and dumps me at the entry point (_c_int00_secure on line 51 of $(MCU_PLUS_SDK_PATH)/source/kernel/nortos/dpl/c75/boot_c75.c). After many attempts and a lot of single-stepping, I narrowed my problem down to the call to MmuP_enable() in line 475 of $(MCU_PLUS_SDK_PATH)/source/kernel/nortos/dpl/c75/MmuP_c75.c  I can set a breakpoint there and successfully reach it. However, when I then hit "resume", the behavior described in (1) occurs (PC spinning at 0x99A00000).

However, now it gets interesting. When I single step into and through the function, I can successfully complete it. In fact, I can do this repeatedly (the function is called in a loop) and by doing this, I can complete the entire MMU initialization and afterwards the program successfully switches to the main() function and executes the example without issue.

Do you have any ideas why I am only able to complete the MMU initialization by single-stepping through it?

Any help would be appreciated.

Thanks,
Moritz

  • Hello Moritz,

    Thank you for reaching out to Texas Instruments E2E support forum.

    I have taken you inputs and working on it. Please allow some time to revert back.

    Regards,

    Tushar

  • Hello Tushar,
    thanks for looking into this.

    Some more notes from my side: I just switched from using SD-Boot to OPSI-NAND-Boot and flashed the NULL Bootloader, as described in the documentation. In this configuration, I was then able to successfully load and run the example via the debugger in CCS.

    This is now making me doubt if the issue is somewhere in my Linux installation, so I am probably going to re-install that and try again tomorrow, as my end-goal is to have the DSP communicate with an application running under Linux. But having it working with the NULL Botloader is already a good step forward.

    I am going to post an update here after I have completed the re-installation.

    Best regards,
    Moritz

  • Hello Moritz,

    Thank you for the above notes.

    Some more notes from my side: I just switched from using SD-Boot to OPSI-NAND-Boot and flashed the NULL Bootloader, as described in the documentation. In this configuration, I was then able to successfully load and run the example via the debugger in CCS.

    We have also tried to run the example on C7x core when the board is initialized with NULL bootloader.

    The example is working fine when SOC is initialized through NULL Bootloader.

    I will also try to flash the example when the board is initialized by Linux and will update the results.

    Best Regards,

    Tushar

  • Hi Moritz,

    I have tried to load the example when SOC is initialized using Linux.

    Flashing the binary from CCS, following the instructions in "CCS Launch, Load and Run" from the Documentation (Wait for Linux to boot, connect to DSP, reset, load program)
    --> This does NOT work. The core shows "running" in the debugger forever, and when I click "pause", the program counter is spinning on address 0x99A00000 (C7X_VECTOR_BASE from the linker file)

    We are also seeing the same behavior as observed by you.

    Changing the entry point from _c_int00_secure to _c_int00
    --> This allows me to load the program in CCS (after booting the DSP with /lib/firmware/vision_apps_eaik/vx_app_rtos_linux_c7x_1.out, resetting it and flashing the example).

    But in the linker.cmd file when the entry point of program is changed from _c_int00_secure to _c_int00 the example is working fine. We are able to load the program and also run it.

    Please see the below logs.

    Regards,

    Tushar

  • Hi Tushar,
    some more notes from my side:

    I looked through the documentation to try to understand how the MMU works and what it does. Anyway, at some point I ended up at this page ($(MCU_PLUS_SDK_PATH)/docs/api_guide_am62ax/KERNEL_DPL_MMU_ARMV8_PAGE.html) which has the following example configuration:

    MmuP_MapAttrs mapAttrs;
    
    /* recommend to disable Cache and MMU before setting up MMU regions */
    CacheP_disable(CacheP_TYPE_ALL);
    MmuP_disable();
    
    /* make 4G region as privileged executable, outer shareable */
    MmuP_MapAttrs_init(&mapAttrs);
    mapAttrs.accessPerm = MMUP_ACCESS_PERM_PRIV_RW_USER_NONE;
    mapAttrs.privExecute = 1;
    mapAttrs.userExecute = 0;
    mapAttrs.shareable = MMUP_SHARABLE_OUTER,
    mapAttrs.attrIndx = MMUP_ATTRINDX_MAIR0;
    mapAttrs.global = 1;
    MmuP_map(0x0u, 0x0u, 0x80000000u, &mapAttrs);
    
    /* make memory region as outer and inner writeback cacheable */
    MmuP_MapAttrs_init(&mapAttrs);
    mapAttrs.accessPerm = MMUP_ACCESS_PERM_PRIV_RW_USER_NONE;
    mapAttrs.privExecute = 1;
    mapAttrs.userExecute = 0;
    mapAttrs.shareable = MMUP_SHARABLE_OUTER,
    mapAttrs.attrIndx = MMUP_ATTRINDX_MAIR7;
    mapAttrs.global = 1;
    MmuP_map(0x80000000u, 0x80000000u, 0x80000000u, &mapAttrs);
    
    /* enable Cache and MPU after setting up MPU regions */
    MmuP_enable();
    CacheP_enable(CacheP_TYPE_ALL);

    I then replaced the content of the MmuP_setConfig() function (Line 297 of $(MCU_PLUS_SDK_PATH)/source/kernel/nortos/dpl/c75/MmuP_c75.c) with the above code and this allowed me to run the application through the debugger WITH the _c_int00_secure entrypoint.

    I then experimented with the memory ranges and ended up at the following minimal values:

    MmuP_MapAttrs mapAttrs;
    
    /* recommend to disable Cache and MMU before setting up MMU regions */
    CacheP_disable(CacheP_TYPE_ALL);
    MmuP_disable();
    
    /* mark magic region as privileged executable, outer shareable */
    MmuP_MapAttrs_init(&mapAttrs);
    mapAttrs.accessPerm = MMUP_ACCESS_PERM_PRIV_RW_USER_NONE;
    mapAttrs.privExecute = 1;
    mapAttrs.userExecute = 0;
    mapAttrs.shareable = MMUP_SHARABLE_OUTER,
    mapAttrs.attrIndx = MMUP_ATTRINDX_MAIR0;
    mapAttrs.global = 1;
    MmuP_map(0x7C280000u, 0x7C280000u, 0x00020000u, &mapAttrs); // This magic region needs to be mapped first, and then
                                                                // the other regions can be mapped.
    
    /* mark C7X main memory region as outer and inner writeback cacheable */
    MmuP_MapAttrs_init(&mapAttrs);
    mapAttrs.accessPerm = MMUP_ACCESS_PERM_PRIV_RW_USER_NONE;
    mapAttrs.privExecute = 1;
    mapAttrs.userExecute = 0;
    mapAttrs.shareable = MMUP_SHARABLE_OUTER,
    mapAttrs.attrIndx = MMUP_ATTRINDX_MAIR7;
    mapAttrs.global = 1;
    MmuP_map(0x99800000u, 0x99800000u, 0x02000000u, &mapAttrs); // C7x DDR Space  
    
    /* enable Cache and MPU after setting up MPU regions */
    MmuP_enable();
    CacheP_enable(CacheP_TYPE_ALL);

    Effectively, I first have to map the region from 0x7C280000 to 0x7C29FFFF as MAIR0, which according to https://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/bios/sysbios/6_76_01_12/exports/bios_6_76_01_12/docs/cdoc/ti/sysbios/family/arm/v8a/Mmu.html#.M.A.I.R0 seems to represent "memory with non-gathering, non-reordering and no early write acknowledegement property".

    After this, I can map other regions as well, but if I don't map this one first, then the program hangs.

    Mapping only that one region is not enough though, I then also need to map the region from 0x99800000 to 0x9B7FFFFF (which is the C7X_ALLOCATED_START until the end of C7X_DDR_SPACE from the linker file) as MAIR7, which seems to represent "normal outer and inner write-back cachable non-transient memory".

    However, even though this now works in the debugger, I still cannot use it as /lib/firmware/am62a-c71_0-fw. If I attempt to boot the system with this, the DSP crashes (see 2. from my original post).

    Also, if I adjust the gMmuRegionConfig (Line 58 of $(MCU_PLUS_SDK_PATH)/examples/hello_world/am62ax-sk/c75ss0-0_freertos/ti-c7000/generated/ti_dpl_config.c) from the example to first contain my magic region from above, it still hangs on the corresponding MmuP_map(...).

    All of this is still quite a mystery to me, but I am hoping maybe some of that information is useful to you. My end goal is to communicate between the DSP and an application running in Linux, thus the NULL Bootloader and the flashing through the debugger are not really an option for me. I kind of need to have this working as /lib/firmware/am62a-c71_0-fw

    Best Regards,
    Moritz

  • Hello Moritz,

    Thank you for the above note.

    All of this is still quite a mystery to me, but I am hoping maybe some of that information is useful to you. My end goal is to communicate between the DSP and an application running in Linux, thus the NULL Bootloader and the flashing through the debugger are not really an option for me. I kind of need to have this working as /lib/firmware/am62a-c71_0-fw

    We understood your use case. I am currently looking at the information provided by you. Please allow me some time to revert back.

    Best Regards,

    Tushar 

  • Hi Tushar,
    sorry, I misunderstood your previous reply. Thank you for looking into this.

    Best Regards,
    Moritz

  • Hello Moritz,

    Apologies for the delayed response.

    My end goal is to communicate between the DSP and an application running in Linux, thus the NULL Bootloader and the flashing through the debugger are not really an option for me. I kind of need to have this working as /lib/firmware/am62a-c71_0-fw

    I had modified some files in the hello world example provided in MCU+SDK and now it is working fine with firmware (i.e. /lib/firmware/am62a-c71_0-fw) loaded by Linux.

    Please modify the entry point from _c_init00_secure to _c_init00 in linker.cmd file as suggested in earlier replies.

    Please enable IPC in your application to load it via remote cores. Please refer Enabling IPC 

    Also add the MPU region settings for the IPC in example.syscfg file using SysConfig tool.

    To load application using remote cores please refer Booting remote cores.

    I am also attaching the modified hello_world example below.

    Please find the attached zip file.

    hello_world_c7x.zip

    Please let me know if the above solution works.

    Best Regards,

    Tushar

  • Hi Tushar,
    awesome - I just tried the precompiled binary from your .zip and I can load it via remoteproc.

    As my development laptop is running Linux and am not using CCS for development currently, I copied the modified linker file and the updated output from syscfg into my version of the hello world example project and was subsequently able to compile it myself into a binary that also works under Linux :) :)

    Thanks a lot for finding and fixing the issue!

    Best regards,
    Moritz

  • Hi Moritz,

    awesome - I just tried the precompiled binary from your .zip and I can load it via remoteproc.

    Thank you for your confirmation. Glad to see that it worked.

    Thanks a lot for finding and fixing the issue!

    Happy to help Slight smile .

    Best Regards,

    Tushar