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.

[DRA829]Question about SBL jumping to APP

Other Parts Discussed in Thread: SYSBIOS

Hi,

I recently looked at the process of SBL startup, I have the following questions:

1.I only started the MCU R5F Core0. I only saw some checksum analysis of the appimage file, but I did not find the corresponding code to copy the appimage file to the corresponding RAM area to run.

2.In the final jump part, the SBL file calls the SBL_SlaveCoreBoot function to complete the jump from SBL to appimage and run. Within the SBL_SlaveCoreBoot function, we can see some function calls as shown below. Is it transferred to appimage after calling Sciclient_procBootReleaseProcessor function in the last part?

3.I use my own bootloaer file (the startup process is SBL->sysfw->bootloader(*.appimage)->APP(HEX)), and use the same process at the end of the bootloader to jump to the APP (that is, call SBL_SlaveCoreBoot- >...->Sciclient_procBootReleaseProcessor) can not jump successfully, only use ((void(*)(void))0x0)() function can jump successfully. Is there a problem with our method of use? Please also lift my doubts.

Please reply as soon as possible,

Regards,

Xie

  • Hi Xie,

    Xie Linda said:
    I only started the MCU R5F Core0. I only saw some checksum analysis of the appimage file, but I did not find the corresponding code to copy the appimage file to the corresponding RAM area to run.

    It is done in SBL_MulticoreImageParse (after calling another Rprc related func inside there).

    Xie Linda said:
    .In the final jump part, the SBL file calls the SBL_SlaveCoreBoot function to complete the jump from SBL to appimage and run. Within the SBL_SlaveCoreBoot function, we can see some function calls as shown below. Is it transferred to appimage after calling Sciclient_procBootReleaseProcessor function in the last part?

    There’s a special case for “MCU1_CPU0_ID” (which is the core that you’re currently running on).  If you are using the RESET R5 feature (NOT using the SBL_SKIP_MCU_RESET compile flag), then the code will call “Sciclient_procBootReleaseProcessor” for CPU0, and then it will wait for things to be set up subsequently for CPU1 before resetting the pair of R5s.  After this, then the SBL_SlaveCoreBoot function gets called again, finally, for CPU1 & CPU0 handling (using core ID: “MCU1_CPU1_ID”), which then has another special case where “Sciclient_procBootRequestProcessor” is called (with proper core sequencing), and then “Sciclient_procBootWaitProcessorState” is called (to tell the SYSFW to wait for R5 WFI state before rebooting), and then a few more Sciclient power down sequencing functions are called to get ready to power down & restart the R5 cores.  Finally, the R5 enters “WFI” at the end, which signals the SYSFW to power down the MCU R5s and restart them with the new .appimage that was loaded previously.

    NOTE: the code sequence is very different if you compile the SBL with the token “SBL_SKIP_MCU_RESET”.  In that case, the SBL code doesn’t go through all the elaborate setup listed above for resetting the R5 cores.

    Xie Linda said:
    .I use my own bootloaer file (the startup process is SBL->sysfw->bootloader(*.appimage)->APP(HEX)), and use the same process at the end of the bootloader to jump to the APP (that is, call SBL_SlaveCoreBoot- >...->Sciclient_procBootReleaseProcessor) can not jump successfully, only use ((void(*)(void))0x0)() function can jump successfully. Is there a problem with our method of use? Please also lift my doubts.

    You are probably trying to use the code sequence with the “SBL_SKIP_MCU_RESET” flag enabled.  That is the only time you would use the “jump” to the app code directly like that: ((void(*)(void))0x0)().  You should try the other boot sequencing method (with the full R5 RESET involved), as I mentioned in my answer to #2, above.

    Regards,

    Karan

  • Hi Karan,

    I use the following code to implement jumping to APP, and not using the SBL_SKIP_MCU_RESET compile flag.The program does not jump to the APP normally, the log printed by the serial port is as follows,Can you help me analyze the reason for the jump failure, thank you!

    CODE:

    for (core_id = MPU1_CPU0_ID; core_id <= DSP2_C7X_ID; core_id ++)
    {
    k3xx_evmEntry.CpuEntryPoint[core_id] = (void *)0x0;
    /* Try booting all cores other than the cluster running the SBL */
    if ((k3xx_evmEntry.CpuEntryPoint[core_id] != SBL_INVALID_ENTRY_ADDR) &&
    (core_id != MCU1_CPU1_ID))
    SBL_SlaveCoreBoot(core_id, NULL, &k3xx_evmEntry);
    }

    /* Boot the core running SBL in the end */
    if ((k3xx_evmEntry.CpuEntryPoint[MCU1_CPU1_ID] != SBL_INVALID_ENTRY_ADDR) ||
    (k3xx_evmEntry.CpuEntryPoint[MCU1_CPU0_ID] < SBL_INVALID_ENTRY_ADDR))
    {
    k3xx_evmEntry.CpuEntryPoint[MCU1_CPU1_ID] = (void *)0x0;
    SBL_SlaveCoreBoot(MCU1_CPU1_ID, NULL, &k3xx_evmEntry);
    }
    /* Execute a WFI */
    asm volatile (" wfi");

    UART LOG:

    SBL Revision: 01.00.09.02 (Dec 4 2019 - 00:08:30)
    SYSFW ver: 19.8.0-v2019.08 (Terrific Llama
    CanApp_Startup Init!!!
    Bootm_GotoApplication!!!
    : CRC passed !!!
    Calling Sciclient_procBootRequestProcessor, ProcId 0x20...
    Sciclient_procBootSetProcessorCfg, ProcId 0x20, EntryPoint 0x0...
    Sciclient_pmSetModuleClkFreq, DevId 0xca @ 2000000000Hz...
    Sciclient_procBootReleaseProcessor, ProcId 0x20...
    Sciclient_pmSetModuleState Off, DevId 0xca...
    Sciclient_pmSetModuleState On, DevId 0xca...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x21...
    Sciclient_procBootSetProcessorCfg, ProcId 0x21, EntryPoint 0x0...
    Sciclient_pmSetModuleClkFreq, DevId 0xcb @ 2000000000Hz...
    Sciclient_procBootReleaseProcessor, ProcId 0x21...
    Sciclient_pmSetModuleState Off, DevId 0xcb...
    Sciclient_pmSetModuleState On, DevId 0xcb...
    Calling Sciclient_procBootRequestProcessor, ProcId 0xbad00000...
    Sciclient_procBootRequestProcessor...FAILED
    Sciclient_procBootSetProcessorCfg, ProcId 0x0, EntryPoint 0x0...
    Sciclient_procBootSetProcessorCfg...FAILED
    Sciclient_pmSetModuleClkFreq, DevId 0xbad00000 @ -1160773632Hz...
    Sciclient_procBootReleaseProcessor, ProcId 0xbad00000...
    Sciclient_procBootReleaseProcessor, ProcId 0xbad00000...FAILED
    Sciclient_pmSetModuleState Off, DevId 0xbad00000...
    Sciclient_pmSetModuleState On, DevId 0xbad00000...
    Calling Sciclient_procBootRequestProcessor, ProcId 0xbad00000...
    Sciclient_procBootRequestProcessor...FAILED
    Sciclient_procBootSetProcessorCfg, ProcId 0x0, EntryPoint 0x0...
    Sciclient_procBootSetProcessorCfg...FAILED
    Sciclient_pmSetModuleClkFreq, DevId 0xbad00000 @ -1160773632Hz...
    Sciclient_procBootReleaseProcessor, ProcId 0xbad00000...
    Sciclient_procBootReleaseProcessor, ProcId 0xbad00000...FAILED
    Sciclient_pmSetModuleState Off, DevId 0xbad00000...
    Sciclient_pmSetModuleState On, DevId 0xbad00000...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x1...
    Sciclient_procBootSetProcessorCfg, ProcId 0x1, EntryPoint 0x0...
    Sciclient_pmSetModuleClkFreq, DevId 0xfa @ 1000000000Hz...
    Sciclient_procBootReleaseProcessor, ProcId 0x1...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x6...
    Sciclient_procBootSetProcessorCfg, ProcId 0x6, EntryPoint 0x0...
    Sciclient_pmSetModuleClkFreq, DevId 0xf5 @ 1000000000Hz...
    Clearing HALT for ProcId 0x6...
    Sciclient_pmSetModuleState On, DevId 0xf5...
    Sciclient_procBootReleaseProcessor, ProcId 0x6...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x7...
    Sciclient_procBootSetProcessorCfg, ProcId 0x7, EntryPoint 0x0...
    Sciclient_procBootSetProcessorCfg...FAILED
    Sciclient_pmSetModuleClkFreq, DevId 0xf6 @ 1000000000Hz...
    Clearing HALT for ProcId 0x7...
    Sciclient_pmSetModuleState On, DevId 0xf6...
    Sciclient_procBootReleaseProcessor, ProcId 0x7...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x8...
    Sciclient_procBootSetProcessorCfg, ProcId 0x8, EntryPoint 0x0...
    Sciclient_pmSetModuleClkFreq, DevId 0xf7 @ 1000000000Hz...
    Clearing HALT for ProcId 0x8...
    Sciclient_pmSetModuleState On, DevId 0xf7...
    Sciclient_procBootReleaseProcessor, ProcId 0x8...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x9...
    Sciclient_procBootSetProcessorCfg, ProcId 0x9, EntryPoint 0x0...
    Sciclient_procBootSetProcessorCfg...FAILED
    Sciclient_pmSetModuleClkFreq, DevId 0xf8 @ 1000000000Hz...
    Clearing HALT for ProcId 0x9...
    Sciclient_pmSetModuleState On, DevId 0xf8...
    Sciclient_procBootReleaseProcessor, ProcId 0x9...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x3...
    Sciclient_procBootSetProcessorCfg, ProcId 0x3, EntryPoint 0x0...
    Sciclient_pmSetModuleClkFreq, DevId 0x8e @ 1350000000Hz...
    Sciclient_procBootReleaseProcessor, ProcId 0x3...
    Sciclient_pmSetModuleState Off, DevId 0x8e...
    Sciclient_pmSetModuleState On, DevId 0x8e...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x4...
    Sciclient_procBootSetProcessorCfg, ProcId 0x4, EntryPoint 0x0...
    Sciclient_pmSetModuleClkFreq, DevId 0x8f @ 1350000000Hz...
    Sciclient_procBootReleaseProcessor, ProcId 0x4...
    Sciclient_pmSetModuleState Off, DevId 0x8f...
    Sciclient_pmSetModuleState On, DevId 0x8f...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x30...
    Sciclient_procBootSetProcessorCfg, ProcId 0x30, EntryPoint 0x0...
    Sciclient_pmSetModuleClkFreq, DevId 0xf @ 1000000000Hz...
    Sciclient_procBootReleaseProcessor, ProcId 0x30...
    Sciclient_pmSetModuleState Off, DevId 0xf...
    Sciclient_pmSetModuleState On, DevId 0xf...
    Calling Sciclient_procBootRequestProcessor, ProcId 0xbad00000...
    Sciclient_procBootRequestProcessor...FAILED
    Sciclient_procBootSetProcessorCfg, ProcId 0x0, EntryPoint 0x0...
    Sciclient_procBootSetProcessorCfg...FAILED
    Sciclient_pmSetModuleClkFreq, DevId 0xbad00000 @ -1160773632Hz...
    Sciclient_procBootReleaseProcessor, ProcId 0xbad00000...
    Sciclient_procBootReleaseProcessor, ProcId 0xbad00000...FAILED
    Sciclient_pmSetModuleState Off, DevId 0xbad00000...
    Sciclient_pmSetModuleState On, DevId 0xbad00000...
    Calling Sciclient_procBootRequestProcessor, ProcId 0x2...
    Sciclient_procBootSetProcessorCfg, ProcId 0x2, EntryPoint 0x0...
    Sciclient_pmSetModuleClkFreq, DevId 0xfb @ 1000000000Hz...
    Sciclient_procBootRequestProcessor, ProcId 0x1...
    Sciclient_procBootWaitProcessorState, ProcId 0x1..

  • Hi,

    yajuan ma said:
    k3xx_evmEntry.CpuEntryPoint[MCU1_CPU1_ID] = (void *)0x0;

    Why are you setting the entry point explicitly here?

    Can you please summarize the changes you have from TI's SBL code?

    Regards,

    Karan

  • Hi,Karan

    I use my own bootloaer file (the startup process is SBL->sysfw->bootloader(*.appimage)->APP(HEX)),I did not add all the code in SBL, just added the code shown to you at the end of our bootloader to jump to the APP, so for convenience, I set the entry point of each core in this place.

    In addition, Xie Linda and I described the same project, and we are studying this part together.Hope to get your help, thanks.

  • Hi Yajuan Ma,

    The original code doesn't have that code of explicitly setting the entry point: 

    281     for (core_id = MPU1_CPU0_ID; core_id <= DSP2_C7X_ID; core_id ++)
    282     {
    283         /* Try booting all cores other than the cluster running the SBL */
    284         if ((k3xx_evmEntry.CpuEntryPoint[core_id] != SBL_INVALID_ENTRY_ADDR) &&
    285             (core_id != MCU1_CPU1_ID))
    286             SBL_SlaveCoreBoot(core_id, NULL, &k3xx_evmEntry);
    287     }
    288
    289     /* Boot the core running SBL in the end */
    290     if ((k3xx_evmEntry.CpuEntryPoint[MCU1_CPU1_ID] != SBL_INVALID_ENTRY_ADDR) ||
    291         (k3xx_evmEntry.CpuEntryPoint[MCU1_CPU0_ID] < SBL_INVALID_ENTRY_ADDR))
    292         SBL_SlaveCoreBoot(MCU1_CPU1_ID, NULL, &k3xx_evmEntry);
    293
    294     /* Execute a WFI */
    295     asm volatile (" wfi");
    296
    297     return 0;
    

    Let me know all your questions and I'll try to help you.

    Regards,

    Karan

  • Hi,Karan

    The purpose I want to achieve is to jump from my bootloader to the APP, so I only added the following code to my bootloader project, and set an entrypoint for each core. The reason for setting the entrypoint here is that I did not find the assignment of the variable k3xx_evmEntry in the SBL code. My colleague told me that I can set the k3xx_evmEntry.CpuEntryPoint of each core to 0. Then call the SBL_SlaveCoreBoot function to achieve the jump, but the final jump is not successful, UART LOG has been provided to you.

    Thanks.

    CODE:

    for (core_id = MPU1_CPU0_ID; core_id <= DSP2_C7X_ID; core_id ++)
    {
    k3xx_evmEntry.CpuEntryPoint[core_id] = (void *)0x0;
    /* Try booting all cores other than the cluster running the SBL */
    if ((k3xx_evmEntry.CpuEntryPoint[core_id] != SBL_INVALID_ENTRY_ADDR) &&
    (core_id != MCU1_CPU1_ID))
    SBL_SlaveCoreBoot(core_id, NULL, &k3xx_evmEntry);
    }

    /* Boot the core running SBL in the end */
    if ((k3xx_evmEntry.CpuEntryPoint[MCU1_CPU1_ID] != SBL_INVALID_ENTRY_ADDR) ||
    (k3xx_evmEntry.CpuEntryPoint[MCU1_CPU0_ID] < SBL_INVALID_ENTRY_ADDR))
    {
    k3xx_evmEntry.CpuEntryPoint[MCU1_CPU1_ID] = (void *)0x0;
    SBL_SlaveCoreBoot(MCU1_CPU1_ID, NULL, &k3xx_evmEntry);
    }
    /* Execute a WFI */
    asm volatile (" wfi");

  • Hi,

    yajuan ma said:
    The reason for setting the entrypoint here is that I did not find the assignment of the variable k3xx_evmEntry in the SBL code.

    This would happen in the SBL_RprcImageParse() when SBL parses the RPRC image and sets the entry point. The entry point needs to be the entry point of your application. You can look at the linker command file of your application to get that entry point.

    Regards,

    Karan

  • Hi Xie, Yujan,

    I'm hoping that you got the patch fix for this offline from Fan? I will also put the patch on this forum but just wanted to confirm.

    Regards,

    Karan

  • Attaching the e-mail conversation here:

    I was able to root cause the issue. The problem was with the cache setting in the MPU configuration for the MCU R5.

    1. The R5F, was looking at stale data and hence was crashing while jumping to app2. The fix is to change the cache configuration for the regions used – DDR, OCMC and ATCM (by architecture, R5 expects its reset vectors to be in ATCM – they are copied to ATCM by the bootloader).
    2. SBL / dio_app or any other Baremetal app does the MPU configuration in the __mpu_init() function and the configuration is passed as the gCslR5MpuCfg[] structure from the application. The fix is to change the cache configuration there. The patch changes the MPU configuration and makes it same as that in the SBL.

    You can reference the patch for the MPU configuration and then it should be able to load the app2.

    I have attached the boot partition of the SD card, successful logs and the patch on MCUSW (assuming you have SBL and can_app in place).

    Patch: /cfs-file/__key/communityserver-discussions-components-files/791/0001_2D00_dio_5F00_app_2D00_Load_2D00_app2_2D00_from_2D00_SD_2D00_card.patch

    Log: /cfs-file/__key/communityserver-discussions-components-files/791/dio_5F00_loading_5F00_can.log

    Pre-built boot partition: /cfs-file/__key/communityserver-discussions-components-files/791/6545.boot.zip

    ----------------

    Explanations to followup questions:

    1. What is the basis to set the size of each region
      1. The size corresponds to the total size of the region as per the SoC or size of the region relevant to the application.
      2. For example in the patch – if you see Region 1 (ATCM) starting at 0x0, the size is 32KB which is the actual size of ATCM for mcu1_0. Similarly if you look at OCM (0x41C00000) the size is 1MB which is the actual size of On Chip Ram on the TDA4.
      3. The other attributes determine the cache policy, memory type etc .. you can find more information in the R5 TRM at https://static.docs.arm.com/ddi0460/d/DDI0460D_cortex_r5_r1p2_trm.pdf in the memory protection unit (MPU) chapter7. I can help you understand in more detail if need be.
    2. What is the effect of each cachePolicy setting
      1. The cache policy change from CSL_ARM_R5_CACHE_POLICY_WB_WA to CSL_ARM_R5_MEM_ATTR_CACHED_WT_NO_WA (in the patch) would change the cache policy from Write-back, write allocate to Write through, no write allocate.
      2. I would think that even with the old cache policy we could have worked in case we added explicit cache operations in the code just before the reset on the mcu1_0.
      3. The  main reason for this change was because we were trying to mimic the SBL and SBL has these as defaults.
    3. What is the reason for creating these regions
      1. R5 (when powers up) comes up with a default MPU configuration and that is what we can override in the application. This is basically reprograming the MPU.
    4. How about MPU configuration if with non-baremetal app
      1. The MPU configuration happens as a part of the BIOS startup code. We mention this configuration as a part of the r5_mpu.xs file which gets included in the sysbios_r5f.cfg (you can look at both these files in pdk/packages/ti/build/j721e/.)
      2. In Baremetal this happens as a part of the __mpu_init() at pdk/packages/ti/csl/arch/r5/src/startup/startup.c
        1. The gCslR5MpuCfg (used to initiallise the MPU) is a weak symbol and can be overridden – this is what we do when we define the same in the application. SBL also does the same and any Baremetal app can do this.

    Just to sum it up, the MPU sits at the boundary of the R5F and controls its accesses to the memory. Any memory access initiated by the R5F goes through the MPU and the MPU needs to have a valid entry for the memory R5F is trying to access. R5F powers on with a set of default regions programmed in the MPU and this can be overrided in either the CSL startup code (for Baremetal) or in the BIOS startup code (in BIOS apps).

    Not having the correct MPU settings for a memory will result in an exception while trying to access/execute from there. And in our case when the cache policy was wrong the core would be looking at stale data after the reset.

    1. Why MPU configuration in DioApp.c is different with it in sbl_main.c? Why 128 bytes?  
      1. 128 bytes memory is used for exception vectors – SBL copies the vectors to 0x0 (see psdk_rtos_auto_j7_07_00_00_11/pdk_jacinto_07_00_00/packages/ti/boot/sbl/soc/k3/ sbl_slave_core_boot.c line 756)
      2. In the Dio_app if you look at the linker cmd file, we don’t use the ATCM for anything else and hence only 128B is configured in the MPU as it is the minimum we need. That being said, you can configure the whole ATCM (as we are doing now after the patch or in SBL) but that won’t change anything as we won’t be using more than 128B.

    Regards,

    Karan

  • Hi Karan

    Thank you for your answer. According to the method you provided, I have solved my problem. Thank you very much!