Platform: iMX8MQ EVK
Linux kernel: 4.14.78
Yocto: imx-linux-sumo 4.14.98-1.0.0 GA
I tried running the GPT capture sample in SDK 2.5.1 on the M4. I have an external signal connected to GPT1_CAPTURE1 via TP 803. This works just fine till Linux starts to boot. At some point during bootup, the GPT sample stops working. I have disabled sound card support entirely and notice that GPT1 is disabled in the device tree (<yocto_build_dir>/tmp/work-shared/imx8mqevk/kernel-source/arch/arm64/boot/dts/freescale/fsl-imx8mq.dtsi). Table 2-3 in the Linux reference manual states that iMX8M uses the System Counter Timer instead of GPT. Given what I know, I do not understand if there is a resource conflict between Linux and M4, or in general, why this sample would stop working when Linux starts to come up.
Also, it looks like for this platform, GPT1 is the only timer with a pin out for capture channels so I can't use any other timers on the M4. Any help would be greatly appreciated!
Have you solved the problem? How can you solve it? I have encountered similar problems. Can you help me solve this problem? Thank you.
The question is in the link below.
For these types of problems, often the easiest approach to debug the issue is to look at the actual relevant SoC registers to attempt to determine what happened. So why would the GPT IP module stop working during Linux boot?
While not an exhaustive list, a couple of possibilities immediately jump off the page:
1. The iomux was reconfigured for a different purpose
2. The clocks going to the GPT IP changed (or the clock gate was disabled)
3. The GPT itself was reconfigured.
The first step is to head to the SoC reference manual to determine what other IP is multiplexed to the I/O in question:
Taking a look at the i.MX8MQ device tree found in /arch/arm64/boot/dts/freescale/fsl-imx8mq-evk.dts, we see an sai5 entry, and it is enabled. This indicates that when Linux configures the device tree, our GPT1_CAPTURE1 will be reconfigured to the SAI5 IP. Thus we need to disable this device tree node. Note that there is already a pre-made device tree for the RPMSG demo, targetted for M4 operation. So let's modify that instead, and configure U-boot to alway load that:
At the bottom, let's add an entry:
status = "disabled";
After recompiling, and copying the file to our non-volatile storage, we now have the updated M-4 DTB in our FAT partition. We can then set it to be loaded by Linux by changing the fdt_file u-boot environment variable.
u-boot> editenv fdt_file
u-boot> fatload mmc 1:1 0x7e0000 gpt_capture.bin
u-boot> bootaux 0x7e0000
Huh, still exhibits the same behavior. NOTE: this does NOT mean we were wrong, it just means there is another issue in addition to this one.
So, on to step 2: let's find out if there is something going wrong with the clocks/GPT configuration. U-boot and the validation images for linux have tools to peek/poke physical addresses. Let's do a before and after comparison to determine what is going wrong.
So what registers are we interested in? Well, taking a look back in the SoC Reference Manual, we can look at the clock tree to determine where the problem could be:
So there is a mux that could have changed, pre and post dividers, as well as a clock gate (CCRG16):
Now, we need to find what manages the GPT1_CLK_ROOT:
So clock slice 107 controls the clock root, need to find that register:
and et cetera.
We would also like to look at the GPT configuration, just in case that changed:
Going back into u-boot, let's peek and poke those registers!:
u-boot=> fatload mmc 1:1 0x7e0000 gpt_timer.bin
17316 bytes read in 25 ms (675.8 KiB/s)
u-boot=> bootaux 0x7e0000
## Starting auxiliary core at 0x007E0000 ...
u-boot=> md 0x30384100 1 # Clock gate CCGR 16
30384100: 00000032 2...
u-boot=> md 0x30360030 1 # CCM_ANALOG_SYS_PLL1_CFG0
30360030: 82aaaa08 ....
u-boot=> md 3038b580 1 # Clock source 107
3038b580: 12000003 ....
u-boot=> md 302d0000 1 # GPT1 configuration
302d0000: 0000006b k...
u-boot=> md 302d0004 1
302d0004: 00000002 ....
u-boot=> md 302d0008 1
302d0008: 00000000 ....
u-boot=> md 302d000c 1
302d000c: 00000001 ....
u-boot=> md 302d0010 1
302d0010: 01fca055 U...
u-boot=> md 302d0014 1
302d0014: ffffffff ....
u-boot=> md 302d0018 1
302d0018: ffffffff ....
u-boot=> md 302d0024 1
Ok, that's great. We see the configuration of both the basic clocks and the GPT1. Next, let's boot Linux and see what changes (note that you will need to build the validation image OR add unit_tests to your build):
root@imx8mqevk:~# cd /unit_tests/
root@imx8mqevk:/unit_tests# ./memtool 0x30384100 1
Reading 0x1 count starting at address 0x30384100
root@imx8mqevk:/unit_tests# ./memtool 0x30360030 1
Reading 0x1 count starting at address 0x30360030
root@imx8mqevk:/unit_tests# ./memtool 0x3038b580 1
Reading 0x1 count starting at address 0x3038B580
OK, whoa! Something changed, what is this bit? Back to the Reference Manual:
Ouch, Linux turned off our clock!! What the heck, man?!
So, then the question becomes, where is Linux going squirrelly?
NXP adds a separate folder for i.MX in the Linux clocks driver - /drivers/clk/imx/clk-imx8mq.c holds the init function for the clocks. A quick perusal shows that line 563 seems suspect:
There is also a clk.h and clk.c that holds many of the definitions, and can be investigated. Chasing this down a bit, we see that when clk_register_gate2() is called by imx_clk_gate4(), this bit field is disabled.
So the easiest approach is just to comment out that line, as we want the M-4 to control that clock.
Recompile, not only the Linux, but also the full image. Recopy gpt_capture.bin back to the non-volatile storage after flashing the new image. Proceed to test (note that I do not have a breakout board handy right now, so I'm testing with gpt_timer.bin) -- YES! VICTORY!
So, is this a bug in the NXP SDK? No, as NXP we want to provide GPT functionality to Linux, it just happens in your application that is not the desired behavior.
I realize that I've been a little long-winded, but the purpose of this is to demonstrate HOW these types of issues are troubleshoot. Hopefully, this will be helpful in future efforts.
Further note, we could have done this and produced some really nasty bugs. Note that there is a gpt1 node in our device tree -- that's one reason to use the M-4 DTB, as it is already disabled in that device tree. It's usually best to start with the device tree, then when that is exhausted, start peeking/poking registers. For the vast majority of these types of issues, JTAG debugging is not required. When using JTAG, make sure you HALT the processors before you start to read/write the registers.
one can use linux/arch/arm64/boot/dts/freescale/fsl-imx8mq-evk-m4.dts
and procedure for running rpmsg m4 examples described in sect.2.8.5 Running i.MX RPMsg Test Programs
attached Linux Manual.
There are other approaches for running m4 appilcations from linux:
AN5317 Loading Code on Cortex-M4 from Linux for the i.MX 6SoloX and i.MX7Dual/7Solo Application Processors
Yes, GPT1 is the only timer with a external pin out for capture.
Note: If this post answers your question, please click the Correct Answer button. Thank you!
Thanks so much for your response Igor. I will look into the documents you pointed me to but wanted to give a quick update, I did set status to enabled for GPT1 in the fsl-imx8mq-evk-m4.dts file but that didn't help either. Also, I ran the GPT sample while I was in the uboot environment and it ran just fine. It was when I continued on to boot the Linux kernel when the sample seemed to stop working. Thought I should make that clear.
I have run both RPMSG demo apps and those work fine. It seemed to me that GPT1 was not being used by Linux in any way but since the M4 sample seems to freeze, perhaps it actually is being used in some way? Can't seem to figure this out.
I also tried to set a hardware watchpoint in kgdb for the GPT1 control register to try to narrow down what kernel component might be using it but that didn't work. It looks like some eFuses need changing? Is there updated documentation for iMX8? I see some for some flavors of 6 and 7.