i.MX7 M4 application stops when Linux boots

Hi all,

I am having trouble to run both the M4 and Linux at the same time.
When I halt U-boot on startup I can manually start the M4 application which is, in view of the current problem, just a simple FreeRTOS application that prints “hello world” on UARTB and then echos all received characters. No other peripherals are configured/initialized/used.

As long as I got the U-boot prompt, everything works fine. But when I then give the boot command and the Linux kernel starts (“Starting kernel …” is displayed), the M4 application stops responding to input on UARTB.
I also added run m4boot to the U-Boot bootcmd variable so that the M4 code starts automatically after reset. In this case, the M4 application starts, echoes characters and then stops after a few seconds when Linux boots.

Linux works fine after the boot (I’m using TorizonCore Upstream 5.7.0+build.17 by the way. I upgraded last week from 5.6.0 build 13 on which I have the same problem).

I did of course some research before seeking help. One of the possible issues is Linux cutting off the M4 clock and I added setenv defargs clk_ignore_unused to the U-Boot environment without any difference in the behavior.

Could there be something wrong (or missing) in the device tree ?

Does anyone has a suggestion of what to do next ?

Any help is greatly appreciated,
Jeroen

EDIT: I am using a custom carrier board, so the device tree has been modified and some peripherals like GPIO bank 2, UART2, ECSPI3, I2C4, GPT1 and GPT4 are reserved for the M4. But as said, the current “hello world” executable that I am using here does not use anything other than UART2

Hi @ompie !

Did you follow our documentation about this topic?

Best regards,

Hi @ henrique.tx
Yes I did follow that documentation. And as I mentioned, the M4 executable runs correctly, but only until Linux boots.

I did some more investigation. I also have an Aster carrier board (with its own Colibri i.MX7D 1GB module on it) and I created an image (based on TorizonCore Upstream 5.7.0+build.17 just like on my custom carrier board) using the default device tree files with only one modification: disabling UART2 in imx7d-colibri-emmc-aster.dts.

I see the same behavior with my minimal ‘hello world’ program:

  • On the U-Boot prompt I can start the M4 program with either run m4boot or via the debugger. In both cases the program runs (printing “hello world” every second).
    When starting the kernel (Uboot “boot” command), the M4 program stops and the kernel hangs as well
  • With the hanging kernel, I can reset the M4 and restart the M4 program via the debugger. The M4 then runs correctly again(Kernel still hangs of course)
  • When I start the Kernel without M4 program, Linux starts up as expected
    (and UART2 is not visible when doing ls /dev/ttym*. I only have ttymxc0 and ttymxc2)
    In this state, I am not able to reset and start the M4 via the debugger.

The latter observation makes me think that the M4 clock is not running (I do have defargs=clk_ignore_unused set in U-boot, I just checked). Although I’m not sure whether that explains why the kernel startup hangs as well…

On the M4 side:

  • board.c is the default one that comes under FreeRTOS\examples\imx7_colibri_m4
  • hardware_init.c is also the same as can be found under \FreeRTOS\examples\imx7_colibri_m4\demo_apps\hello_world
  • in the only FreeRTOS task that is created, I’m only doing a PRINTF() + vTaskDelay() in a while-loop.

So no fancy access to any hardware…

If it helps, I can upload any files you want to check.

Thanks in advance for your help,
Jeroen

Hi @ompie !

Even after applying the device tree overlay colibri-imx7_disable-uart-b_overlay.dtbo, as explained in the documentation, do you still face the problem?

According to the documentation:

By default, our Linux device tree uses UART_B too, which leads to an external abort when the Linux kernel tries to access UART_B. It is recommended to alter the device tree and disable UART_B using the status property, which can be done by applying device tree overlays.
Edit /boot/overlays.txt and append ‘colibri-imx7_disable-uart-b_overlay.dtbo’ to the end of the ‘fdt_overlays’ line.

Best regards,

hi @ henrique.tx,

The method you are referring to (using a .dtbo file) is for Yocto builds if I’m correct. I am using TorizonCore (version 5.7.0 build 17 as I already wrote) and in that case , the method is described here.
As I already mentioned, I modified the top-level device tree file for Aster by adding:

&uart2 {
        status = "disabled";   
};

and used that to generate the Linux image using Torizoncore-builder. This seems to work since doing ls -l /dev/ttym* on the Linux prompt gives:

crw------- 1 torizon tty     207, 16 Dec  7 16:07 /dev/ttymxc0
crw-rw---- 1 root    dialout 207, 18 Dec  7 16:01 /dev/ttymxc2

So no /dev/ttymxc1 which is the device corresponding to UART_B.

Best regards,
Jeroen

Hi @ompie !

Actually, device tree overlays are support in both Yocto builds and TorizonCore (you can use the command dto from TorizonCore Builder to apply device tree overlays)

Can you please confirm that you are using the GitHub - toradex/FreeRTOS-Colibri-iMX7: FreeRTOS for Colibri iMX7 for your M4-firmware development?

Best regards,

Hi @ompie,

Did you look for your problem in existing threads?

Hi @henrique.tx

No, that’s not the one I’m currently using. I initially used that one but gcc had some problems with the syntax of the linker scripts. On advice of one of your collegues I changed to https://git.toradex.com/cgit/freertos-toradex.git.

So I’m really confused now. What is the “official one” ?
I can give the other one a try but that will not be before tomorrow.

Jeroen

Hi @ompie !

Besides the fact that from https://git.toradex.com/cgit/freertos-toradex.git/refs/, we can see that this repository has not received new updates for a longer time than GitHub - toradex/FreeRTOS-Colibri-iMX7: FreeRTOS for Colibri iMX7, the documentation recommends the later.

Therefore, GitHub - toradex/FreeRTOS-Colibri-iMX7: FreeRTOS for Colibri iMX7 is the recommended one, along with the whole documentation in Toradex Developer website.


As a side note:

Sorry, but I didn’t see people from Toradex recommending the repository you pointed out.

Please see that all Toradex users have:

  • .tx in the end of their username, and
  • the little Toradex badge below the photo, and
  • is a moderator (the shield badge to the right of the username)

Although @Edward is a great contributor to Toradex Comunity (as you can see from previous interactions with him), he doesn’t work at Toradex :slight_smile:

Best regards,

1 Like

Hi,

Did I recommend any specific git repo? I just recommended to use search before posting new questions. Issue sounds as a clock issue. Possible solution and ways to investigate it are mentioned in a link in my previous message. M4 clock issue is Linux specific, no matter which FreeRTOS repo.

Hi @henrique.tx,

Oops, you’re right. I’ll take care not to “accuse” Toradex again :slight_smile:
And indeed, @Edward is a great help and he just suggested to have a look at the other repo.

So let’s forget about that and focus on the actual problem. I’ll try to test the other repository this afternoon, and follow up on @Edward’s suggestions

Jeroen

I believe I didn’t. Where did I suggest it?

Edit: And changing repo most likely won’t help with M4 app stop issue. According to your description it must be clock issue. Determine what else M4 clock is shared with, make sure M4 clock is enabled in clk_summary. If it’s disabled after Linux boots, then the best would be to use remoteproc to launch M4 FW, since it allows to make clock “used” by Linux, which in turn won’t allow something like eCSPI driver to turn that “unused” shared clock off. Or, like @mst31 did, patch kernel to make M4 clock always used. You may as well try to reconfigure M4 parent clock to something, which is not affected by eCSPI or other drivers…

Hi @Edward

It was here.

Concerning your message yesterday:

I agree with you but I’ll try the other repository anyway.
Concerning the link in your previous message, I did already have a look at it when I searched the Toradex support pages.
At one point, @ mst31 wrote "had to edit file linux-toradex/drivers/clk/imx/clk-imx7d.c"
As I understand correctly, this is a solution if you’re compiling your own Kernel with Yocto. But I am currently using Torizon with TorizonCore Builder, only to modify the device tree.

I also tried some other settings from the link above:

  • setenv fdt_fixup 'fdt addr ${fdt_addr_r} && fdt rm serial1 && fdt rm spi2'
    => no change, “Hello World” still stops when the Kernel boots
  • setenv fdt_high 0xffffffff
    => I’m not even sure what this does but there was no change in behavior

Jeroen

Hi @henrique.tx,

I changed to the recommended GIT repository but this did not solve my problem.

I’m almost certain that is has to do with the M4 clock source. If I start the M4 application in the debugger (while on the U-Boot prompt) and then start Linux, the application stops running and the debugger (Segger J-Link) complains about not being able to read the registers:

ERROR: Cannot read register 15 (R15) while CPU is running
Reading all registers
ERROR: Cannot read register 0 (R0) while CPU is running
ERROR: Cannot read register 1 (R1) while CPU is running
...
ERROR: Cannot read register 64 (FPS31) while CPU is running
WARNING: Failed to read memory @ address 0xDEADBEEE
WARNING: Failed to read memory @ address 0xDEADBEEE

The question now is how to proceed…
If you want, I can send you a .elf that simply prints out something on UART_B every second without using any other hardware.

Thanks,
Jeroen

Is Torizon so unfriendly to developers so you can’t even
cat /sys/kernel/debug/clk/clk_summary
?
enable_count’s of all arm_m4_root_clk parents has to be >=1.

Edward

Hi @Edward

I can do that :slight_smile:

The result is 437 lines of info. When searching for arm_m4_root_clk, there is only one line:

                                          enable  prepare  protect                                duty
   clock                                  count    count    count        rate   accuracy phase  cycle
---------------------------------------------------------------------------------------------

       arm_m4_src                          0        0        0         240000000       0     0  50000
          arm_m4_cg                        0        0        0         240000000       0     0  50000
              arm_m4_div                   0        0        0         240000000       0     0  50000
                 arm_m4_root_clk           0        0        0         240000000       0     0  50000

(I slightly reformatted the output for readability)
And as you can see, the enable count is 0. And there are not other lines containing “m4” in the output (except “pwm4”)

So we can indeed conclude that the clock to the M4 is shut down.

The BIG question is now how to enable the M4 root clock, or to avoid that it is disabled when the Kernel boots up?
Does anybody know how to do this in Torizon, using Torizoncore builder ? @henrique.tx ?

Thanks @Edward for pointing this out !

Jeroen

Hi @ompie,

I see there are a lot of messages going on and different problems appearing. Thanks, @Edward for all the support, as always!

Let me take a step back and try the TorizonCore 5.7 with M4 myself and check what might be the issue. One quick question, have you also tried the BSP 6 to check if the same problem occurs? (no need to try if you haven’t tried yet, I just want to know if you have this information).

I’ll get back to you when I test here on my side. Thanks for your patience so far.

Best Regards,
Hiago.

Hi @hfranco.tx

No, I did not try BSP 6.
I can send you my executable but I think the fact that the enable count of the arm_m4_root_clk is 0 tells enough.
Thanks for testing !

Jeroen

@ompie,

arm_m4_root_clk, since you launch M4 from U-Boot, will stay zero. Linux doesn’t know in this case about M4 and thus isn’t enabling clocks for it. You need to look further one parent clock level. Default M4 clock source is pll_sys_main_240m. And since it is as well default parent for eCSPI’s, eCSPI driver will disable it when not used. Interesting, above mentioned clk-imx7d.patch is already applied in downstream kernel
here. Upstream kernel used in Torizon seems not including it.

You may try removing all eCSPI instances in U-Boot’s fdt_fixup. It may help. At least it should when clk_ignore_unused is engaged.

You may try as well chanding M4 clock source to SYS_PLL_PFD2 from M4 FW. pll_sys_pfd2_270m_clk in Linux is used at least for ipg_root_clk, so clearly won’t be disabled.

Edward

Hi @Edward,

Thanks again for your answers!

I’m not sure whether I understand everything.
I do understand that the parent clock, pll_sys_main_240m is used by eCSPI and may be switched off by Linux if no eCSPI is used. But in my case, I do use ecspi1 on the Linux side. It is enabled in the device tree and I have 5 different devices with their Chip Selects defined. And they do work in My application under Linux.

Basically, you’re saying that the Torizon kernel does not include a patch that was applied to the downstream kernel. So the solution would be to include this in Torizon as well…

Concerning your two suggestions:

I do not have a varaible fdt_fixup defined in U-Boot:

Colibri iMX7 # printenv fdt_fixup
fdt_fixup=;

So I’m afraid I cant remove eCSPI instances from it

Is that done in the BOARD_ClockInit() function defined in board.c ?
What I have now is :

    /* We need system PLL Div2 to run M4 core */
    CCM_ControlGate( CCM, ccmPllGateSys,        ccmClockNeededRun);
    CCM_ControlGate( CCM, ccmPllGateSysDiv2,    ccmClockNeededRun);

I did change these two lines to:


    CCM_ControlGate( CCM, ccmPllGatePfd2,        ccmClockNeededRun);
    CCM_ControlGate( CCM, ccmPllGatePfd2Div2,    ccmClockNeededRun);

But this did not change anything. The M4 still starts but is stopped as soon as the Kernel boots