Colibri-imx7 freezes using memtool to access certain registers

I’m trying to validate the EIM interface on a Colibri-iMX7 and Colibri Evaluation Board. I’ve found three tools to read and write to configuration registers of peripherals. They are all having trouble reading certain registers.
I’m running angstrom linux built with the Yocto project. I followed this guide. http://developer.toradex.com/knowledge-base/board-support-package/openembedded-(core)

First, I found and used a program called devreg.

I had to hack away a little to get it working.

Then, I tried memtool by adding IMAGE_INSTALL_append = " imx-test" in my local.conf.

Both could read and write many registers. I toggled a gpio (captured the output on a scope) to make sure they were working. However, when I tried to write to registers that configure the EIM, I couldn’t write. I started looking at the CCM and RDC. Trying to read certain registers in the RDC caused the board to freeze. SSH became unresponsive, the display stopped, the serial port is froze. I could read RDC_MRSA0 just fine, but trying to read RDC_MRSA16, for example, caused everything to stop working. Other registers in the RDC have also caused it to lock up and the only fix I’ve found is a reboot.

Next I loaded up the DS-5 debugger and Eclipse with the Blinky-M4 example. I connected to the M4 core and went to look at the registers. I halted the core and opened up the RDC section. It read some but then said “Unavailable” for others and started the core again. See attached image. When I tried to re-halt I got the following error:

interrupt

ERROR(TAD9-NAL64):

! Unable to stop device Cortex-M4

! Target in wrong state/mode.

I looked up the error and disabled CPU_IDLE in my .config and rebuilt but my problem persists. https://community.arm.com/tools/b/blog/posts/error-tad9-nal52-why-is-ds-5-unable-to-control-my-target-when-debugging-the-linux-kernel-via-jtag

Any ideas or advice would be much appreciated, thank you.

There are various reasons why access to a register might be blocked or even leading to a freeze. E.g. it could be a MMU/MPU which prevents access (but this usually resulting in a Segmentation Fault in user space. Depending on JTAG reads might go through CPU/MMU too). Bus faults are often caused by invalid address or when access is otherwise prohibited (e.g. read only register, or wrong read/write width). System freezes are usually caused by missing/disabled clocks. There are also cases where the CPU mode seems to deny access, e.g. I think the CCM register can only be written in privileged mode (typically in kernel).

When reading RDC_MRSA16 from U-Boot it seems to work:

Colibri iMX7 # md.l 0x303D0900 1
303d0900: 00000000

Since the register is dealing with WEIM my guess is that clocks get disabled by Linux. To prevent Linux from disabling unused clocks you can add the clk_ignore_unused kernel parameter, but this seems not to
help in this case… It might be that this registers are also only allowed to be accessed in privileged mode.

Note that our image provides the devmem2 utility which allows to read/write single registers.

In general, the direct userspace register access is not really recommended since it bring all this problems with it… A proper Linux kernel driver makes sure that all resources are properly set up (clocks, memory mapping)…

Thanks for the response. I’ll try to address your comments and elaborate on my goals and problems a little more.

I am aware that a proper driver is the right place to do all this. My current goal is just to verify the EIM and show it’s limitations. We want to use it to interface with an FPGA. Long term we will be writing a driver and probably modifying the .dts. Short term, just want to see the EIM work and fiddle with its settings. Are these tools (memtool, devmem2) sufficient for my short term goal?

I’m beginning to question if they are because of the difficulties I mentioned above and more that I will detail below. I have gotten seg. faults and bus faults but they always recover, i.e. my system doesn’t stop. I got seg. faults trying to do this initially with a plain user space program and I’ve gotten bus faults with memtool and the devreg.cpp when trying to do a read32 from a 16 bit register and things like that. As far as the freeze being caused by missing/disabled clocks, why can I read/write from some registers in a module but not others? I’ve replicated the issues in my original post with the provided devmem2 utility. I’ve also looked for the root clock and gate that power the Resource Domain Controller (RDC). The gate is set to “b11 Clocks needed all the time” but it doesn’t look like the root is enabled. From table 5-12 RDC module Root Clock is IPG_CLK_ROOT. The enable bit in CCM_TARGET_ROOT33 is not set. Weirdly I can’t set it by writing a 1 to it in the CCM_TARGET_ROOT33_SET register. Also weirdly, that is the root clock for GPIO1 but I was able to toggle a GPIO1 pin.

This is brings me to the other problems I’ve come accross, I can’t write to certain registers or all of certain registers when I think I should be able to. For example with the one above, I can change the POST_PODF field but not the ENABLE field. I’ve also had similar problems with other CCM register and EIM configuration registers. Why do you think this is? I’ve verified registers in the RDC and the CCM_ACCESS_CTRL_ROOT registers and everything looks like the domain the A7 cores are in has read/write access to those registers.

I’m new to such low level configurations on such a complicated processor. Thank you for your time and advice. I really appreciate it.

Trying to read registers in u boot this morning the board froze and required a restart after executing the command md.l 0x303d0980 1

I guess it really depends on what kind of verification you plan to do, it might work with such utilities.

I see that the enable bit is not set, but the IPG_CLK_ROOT is most certainly enabled, since almost every IP is running from that clock (and the fact that you can access RDC otherwise). Also the Linux source code does not have a gate defines in the Linux clock source, so I guess this is just not well documented.

I guess the RDC is just somewhat special because it manages access to other peripheries. Some operations seem to need not only the clock for RDC enabled, but also the clock for the target peripheral…

Memory region at 0x980-0x9FC is PCIe, likely needs some other clock…