4ms / stm32mp1-baremetal

Baremetal framework and example projects for the STM32MP15x Cortex-A7 based MPU
Other
153 stars 28 forks source link

Trustzone problem with bare metal program #18

Closed kamejoko80 closed 1 year ago

kamejoko80 commented 1 year ago

Hello,

Thanks for your great thing to make a bare metal program work. I've tried with my board stm32mp157a-dk1 to run the gdb debug boot loader mp1-boot image and got stuck at function SystemClocks::init_core_clocks(Board::HSE_Clock_Hz, Board::MPU_MHz); It looks like there is an issue related to the trust zone, I've also checked the register RCC_TZCR value is 0x3. Is there any way to access RCC_TZCR in none secure app?

Thanks

danngreen commented 1 year ago

Hi, I just tried loading mp1-boot from the master branch onto an stm32mp157a-dk1 and it ran OK.

But I do see an issue which might be causing it to hang in init_core_clocks: Line 34 of clocks.hh sets the HSE type to a passive crystal, but I believe on the DK1, it's an active oscillator. So that should be changed to:

OscEnableDIGBYP::set();

Does that fix it for you? For me, it runs either way (it seems HSE functions with an active oscillator regardless of the DIGBYP setting). But it could be some different revision of the board from ST causing it to not work for your board.

Also, can you use gdb to pinpoint which exact line it's stuck on? You may want to change OPTFLAG to -O0 in the Makefile to make for a better debugging experience.

As for TrustZone, during mp1-boot execution it's in secure mode, so it has access to all registers. In security_init(), after the clocks are set up, RCC->TZCR is set to 0. What is the reason you mention this register being at 3 that might cause an issue?

kamejoko80 commented 1 year ago

Hi @danngreen,

Thanks for your prompt reply.

When I executed gdb the program got stuck at Line 30 of clocks.hh.

// HSE
{
    OscEnableHSEON::clear();
    while (HSEClockReady::read())
        ;

    // Set Bypass Mode = analog oscillator
    OscEnableDIGBYP::set();
    OscEnableHSEBYP::set();

    OscEnableHSEON::set();
    while (!HSEClockReady::read())
        ;
}

I've checked in the STM32MP1 user manual description:

10.7.2 RCC TrustZone control register (RCC_TZCR)

Bit 1 MCKPROT: Protection of the generation of mcuss_ck clock (secure) Enable
Set and reset by software in order to control the security for all registers involved in the
generation of the mcuss_ck clock. This bit is only significant if TZEN = '1'.
When TZEN = '1', if MCKPROT = '1', then only secure accesses are allowed to change the
register controlling the mcuss_ck clock.
In all other cases, non secure accesses are allowed to those registers.
Refer to Section 10.4.14: RCC TrustZone function for details.
0: The registers controlling mcuss_ck clock are not protected
1: The registers controlling mcuss_ck clock are protected, if TZEN = '1' (default after reset).

Bit 0 TZEN: RCC TrustZone (secure) Enable
Set and reset by software in order to control the TrustZone mode. When this bit is set, the
control of several RCC functions shall be controlled using secure accesses. Refer to
Section 10.4.14: RCC TrustZone function for details.
0: No protection
1: TrustZone enabled (default after reset).

I've just tried to clear those bits in order to access the RCC subsystem. Perhaps after the ROM bootloader, mp1-boot can be executed in a secure mode I don't know, but it is different when executing in debug mode with gdb because I've monitored the register RCC_TZCR's value, it was only 0x3 so that means RCC register set is locked.

In order to debug with the openocd below are the steps I did:

  1. Modified the OPTFLAG = -O1, added -g flag into the AFLAGS and CFLAGS (OPTFLAG = -O0 doesn't work for me due to compile error).
  2. Start the openocd gdb server command: "./openocd.exe -f board/stm32mp15x_dk2.cfg"
  3. Start gdb command: "arm-none-eabi-gdb build/fsbl.elf"
  4. Run some extra setup commands: ( gdb ) target remote localhost:3334
    ( gdb ) monitor cortex_a smp_off ( gdb ) monitor cortex_a smp_gdb 0 ( gdb ) load

I've also tried to clear the RCC_TZCR register but it doesn't help. I'm not sure what was wrong with my environment setup but think you can find something if you have time to take a challenge with the openocd debugging.

Thanks

danngreen commented 1 year ago

Hmm, I might see the problem: The correct gdb port for the A7 cores is 3333, not 3334 (3334 is CM4 core). Since the CM4 core cannot modify the RCC TZCR register, nor does it has access by default to the HSE registers (OCRDYR), that would explain the TrustZone issue and the hanging in clocks.hh.

I just confirmed this works: Set BOOT0 OFF and BOOT2 ON, to enable "Engineering boot" mode. Power cycle the board. Then launch openocd and arm-none-eabi-gdb just like you already are doing, but run these commands in gdb:

target extended-remote localhost:3333
load
hbreak main
c

You should see it break at the start of main, and now you are able to step through code. Of course, the boot method will be detected as "Unknown" since doing this bypasses BOOTROM. If you need to debug the actual loading of the application binary, then you'll need to set the boot method to SD Card manually.

Second, I can confirm that compiling with -O0 was indeed broken, because of undefined symbols (_getpid(), _exit(), _kill()). Stubs for these are provided in shared/system/syscalls.c. I added this file to the Makefile, and it can compile with -O0 now. Thanks for finding that, I'll push the fix shortly.

kamejoko80 commented 1 year ago

Hi @danngreen

The gdb port depends on the openocd version, I've compiled it from this repo. So the right port is 3334 for my environment.

Set BOOT0 OFF and BOOT2 ON, to enable "Engineering boot" mode.

After setting it to engineering boot mode, I could run the gdb properly. BTW, it would be nice if you add vscode workspace setting something like "settings.json, tasks.json, launch.json" into your repo. It should work well on both Linux and Windows host PC.

My issue has been resolved, much appreciated for pointing out how to address my issue.

danngreen commented 1 year ago

Great! Glad it's working for you. I'll close this issue.

For vscode workspace settings: Could you open a separate issue for that and explain more details about what types of tasks would be useful? I'm not a VSCode user, so I'll open it up for help from others.