Couldn't wait for my Pyra, so I bought a OMAP5432 devboard


Risca

Still Fresh
Joined
Sep 25, 2011
Messages
24
I wanted to experiment with the Cortex-M4 co-processor of the Pyra to see if I could make it measure the volume wheel and issue an interrupt to the main CPU if the value changed. I think this could help reduce the power consumption of the Pyra by not forcing the main CPU to wake up every X ms. My assumption is that the power domain of the Cortex-M4 consumes much less power than the (2x) Cortex-A15 does.

I got tired of waiting for my Pyra, so I ordered a devboard instead. It wasn't the easiest to find, but DigiKey still had a couple in stock :)

It's been a while since I worked with OMAP boards. What do people recommend as for build environment? I'm mostly fluent with Buildroot, but have used Yocto occasionally. What has the best support? Path of least resistance, so to speak. Do TI have their own build systems that's better?

I think I need Code Composer Studio for the Cortex-M4. Maybe GCC is good enough? I seem to recall GCC was good enough for the i.MX8 Cortex-M4 at least.
I also see that there is some support in the kernel for loading code into the Cortex-M4 from Linux, and starting the co-processor, through the remoteproc subsystem. I'll have to dig into that a bit, or maybe let u-boot load the code during testing and worry about Linux support later?

Mostly brainstorming here. Let me know if you have any hands-on experience! :D

IMG_20220614_191456.jpg
 

Risca

Still Fresh
Joined
Sep 25, 2011
Messages
24

Risca

Still Fresh
Joined
Sep 25, 2011
Messages
24
Okay, looks like Buildroot was able to get me a booted system that turns on the HDMI output and activate the ethernet port. The most interesting part was this from the boot log:

Code:
[    3.702099] omap-rproc 44000000.ocp:dsp: assigned reserved memory node dsp-memory@95000000
[    3.710760] remoteproc remoteproc0: 44000000.ocp:dsp is available
[    3.717229] omap-rproc 55020000.ipu: assigned reserved memory node ipu-memory@95800000
[    3.725317] remoteproc remoteproc1: 55020000.ipu is available
[    3.735265] remoteproc remoteproc0: Direct firmware load for omap5-dsp-fw.xe64T failed with error -2
[    3.744688] remoteproc remoteproc0: powering up 44000000.ocp:dsp
[    3.750982] remoteproc remoteproc0: Direct firmware load for omap5-dsp-fw.xe64T failed with error -2
[    3.760198] remoteproc remoteproc0: request_firmware failed: -2
[    3.768690] remoteproc remoteproc1: Direct firmware load for omap5-ipu-fw.xem4 failed with error -2
[    3.777872] remoteproc remoteproc1: powering up 55020000.ipu
[    3.783636] remoteproc remoteproc1: Direct firmware load for omap5-ipu-fw.xem4 failed with error -2
[    3.792791] remoteproc remoteproc1: request_firmware failed: -2

The remoteproc1: 55020000.ipu, I believe is Cortex-M4. I base this on the device tree binding documentation for ti,omap-remoteproc. The kernel driver automatically tries to load firmware during boot to the Cortex-M4 using a hard-coded path.

I still has some reading and experimenting to do before I can even do "Hello world!" :D
 

Git1

Member
Joined
Dec 23, 2020
Messages
81
Awesome, hope you can make some progress there. Thanks for sharing.
 

hns

Well-Known Member
Joined
Dec 4, 2011
Messages
592
Location
Oberhaching
Welcome to the tiny list of active omap5432evm owners and developers.
You can build a working µSD with Debian through makesd: https://projects.goldelico.com/p/gta04-makesd/
e.g.: /makesd -vk latest omap5432evm
or if you want a newer rootfs you can use: makesd -vk latest -vr latest omap5432evm
This installs the latest Letux (usually a release candidate) kernel from https://git.goldelico.com/?p=letux-kernel.git;a=tags
[warning: HDMI is broken since letux-5.19-rc1 hence please do not boot with HDMI connected; I'll need some weeks to get it fixed; letux-5.18.y works]
You can also build your own kernel on the eval board of course using debian gcc.
AFAIR remoteproc is not enabled/included.
How to write code and compile and activate the remoteproc I'd suggest to ask on the linux-omap mailing list. Some TI and Nokia veterans are still reading and the omap maintainer Tony Lingren is very helpful.
If you need more documentation we (ED or myself) may have something.
Maybe this discussion also helps a littke: https://pyra-handheld.com/boards/threads/arm-m4-usage.82072/#post-1426548
 
Last edited:

aTc

Very Active Member
Joined
Apr 25, 2009
Messages
246
Here's an image of the Pyra stuff modified slightly to run on the uevm : https://packages.pyra-handheld.com/images/extra/pyra-42-uevm.img.7z
(extract the .7z, write to microsd, put microsd in uevm, resizing the second partition to fill the sd card is up to you)

Since it's meant for the pyra hardware, a few daemons and settings obviously won't work on the uevm, but it should get to the first-run wizard.

Changes are that it uses a different uboot, the display rotation is disabled, and the default output is set to hdmi.
That uboot also needs the uevm dtb renamed to omap5-omap5_uevm.dtb to work.

I haven't tested the images on the uevm ever since getting the real pyra hardware, so be prepared for things to fail.
I think the biggest issue was that the hdmi output has some issues (image breaks up/jitter all over the place) sometimes.
 

Risca

Still Fresh
Joined
Sep 25, 2011
Messages
24
I've come down with a cold the past couple of days so progress has been slow. I also got sidetracked getting OpenGLES support working. I'm currently using Buildroot to get me a working u-boot and kernel (5.12, I believe), but the SGX drivers fail to compile. I might give up on the OpenGLES support for now. I have the exact same issues with support for my old BeagleBoard, rev C4.

I think I'll stick with Buildroot for now since I'm familiar with it and it gives me a bootable board. Thanks anyway for your help! I might switch to a different build system eventually :)

I did some reading on how the volume wheel is connected, and if I've understood it correctly we're using an ADC input of the TWL6037 PMIC? This IC has been even harder to find any good documentation for, but there's always the driver code to read. The communication channel is i2c. As you mentioned in the other thread, @hns, the Cortex-M4 should be able to access it. This is good news, but also a bit of a challenge. How do we avoid the two processors talking on the i2c bus at the same time? As indicated here https://lwn.net/Articles/425638/ there is support for HW spinlocks to protect critical sections between the two processors, and that it's indeed used for the i2c driver already. Additional locks might be needed in the TWL6037 driver, but that remains to be seen.

First, I'll have to get well again, get back on track (stupid SGX drivers:mad:), and get the minimal hello world code running on the Cortex-M4. I haven't even looked at the documentation for that yet...
 

Risca

Still Fresh
Joined
Sep 25, 2011
Messages
24
Okay, got some progress on this. Well, maybe not so much progress, but I got something.

At first, I tried installing Code Composer Studio (CCS) version 6.2, since most forum posts and references I could find mentioned the 6.x version when talking about OMAP4/5. Unfortunately, it didn't install on my system. There's some kind of bug in glibc that hangs the installer on my system, and I don't feel like downgrading my glibc or use a chroot. So, instead I installed the latest CCS (11.2.0.00007), which had a checkbox for OMAP3/4/5 processors, and built a hello world program:
C:
#include <stdio.h>
int main(void)
{
    printf("Hello world!\n");
    return 0;
}
Nevermind that this processor doesn't have any output to print to, but hey, it's an experiment. This resulted in a ELF file named hello_world.out, which I uploaded to my board.

I followed some online instructions on how to load and start the program:
Code:
echo -n "/root" > /sys/module/firmware_class/parameters/path # adjust global search path for firmwares. Bad idea generally, I know, sue me :P
cd /sys/class/remoteproc/remoteproc1/
echo -n "hello_world.out" > firmware
echo start > state
This seems to align well with the official documentation: https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-remoteproc

However, that failed:
Code:
# echo start > state
[   63.981751] remoteproc remoteproc1: powering up 55020000.ipu
[   63.989227] remoteproc remoteproc1: Booting fw image hello_world.out, size 8632
[   63.996704] omap-iommu 55082000.mmu: 55082000.mmu: version 2.1
[   64.002625] remoteproc remoteproc1: IOMMU enabled
[   64.007416] remoteproc remoteproc1: rproc prepared
[   64.012279] remoteproc remoteproc1: rproc bootaddr: 0x55020801
[   64.018646] remoteproc remoteproc1: Boot failed: -22
sh: write error: Invalid argument

A lot of printk() sprinkling later and I figure out that my elf file is missing a custom elf section called .resource_table. This was of course also mentioned in the documentation: https://www.kernel.org/doc/Documentation/remoteproc.txt

Now, here is when things start to get complicated. The resource table is meant to include information on what kind of resources should be reserved for the Cortex-M4. My initial attempt to manually hack in an empty resource table got me a bit further, but I didn't realize it at the time and thought something was wrong with my empty table.
I searched online for more answers. I looks like the IPC software stack from TI includes support for populating this section. The latest version of this software is bundled with TI Processor SDK, but none of the SDKs listed offer support for any OMAP family of CPUs! :mad: IPC 3.40 was the last version offered as a standalone package, so I went with that one. I think the upstream git repo for this code is located here: https://git.ti.com/cgit/ipc/ipcdev/
The IPC 3.40 is just a zip file with very little instructions inside :confused: Well, there are instructions but they are outdated and doesn't tell me how to incorporate IPC with CCS. I eventually gave up and just yanked the rsc_table_omap5_ipu.h and rsc_types.h files from the IPC package and massaged the whole thing to build. I ripped out the trace buffer entry from the resource table, because it was referencing some symbol that I didn't bother to investigate. I made sure to update the number of elements in the resource table appropriately.
CCS was kind enough to automatically create a linker file for my project, so I added .resource_table to the list of sections there, and set the section parameters as close as I could to what the IPC code did. IPC also seem to want to load this section at address 0x3000 by default, but I never got that to work properly. I think CCS is using a Clang flavor of compiler and linker. This is how my .resource_table section in the linker script looks like right now:
Code:
SECTIONS
{
    .text          >  OCMC_RAM
    .stack         >  OCMC_RAM
    .bss           >  OCMC_RAM
...
    .resource_table > M4RAM, type = NOINIT, align = 4096 # <- Added by me
}
I also had to update my code to actually reference the resource table, or the linker would automatically strip it! I'm sure there are ways to tell the linker to ignore it, but this was faster:
C:
#include <stdio.h>

#include "rsc_table_omap5_ipu.h"

int main(void)
{
    printf("Hello world!\n");
    printf("Using table format: %d\n", ti_ipc_remoteproc_ResourceTable.base.ver);
    return 0;
}

This got me a little further. In fact, it got me to the same point I was earlier when I had hacked in an empty resource table. Namely, I got this error now:
Code:
# echo start > state
[12507.846851] remoteproc remoteproc1: powering up 55020000.ipu
[12507.852790] remoteproc remoteproc1: Booting fw image hello_world.out, size 202624
[12507.860462] omap-iommu 55082000.mmu: 55082000.mmu: version 2.1
[12507.866528] remoteproc remoteproc1: IOMMU enabled
[12507.871326] remoteproc remoteproc1: rproc prepared
[12507.876158] remoteproc remoteproc1: rproc bootaddr: 0x550227D9
[12507.882068] remoteproc remoteproc1: fw parsed
[12507.888457] remoteproc remoteproc1: resources handled
[12507.916649] remoteproc remoteproc1: carveouts allocated
[12507.921924] remoteproc remoteproc1: bad phdr da 0x55020000 mem 0x2a34 # <- THIS ERROR
[12507.928455] remoteproc remoteproc1: Failed to load program segments: -22
[12507.937156] remoteproc remoteproc1: failed to unmap 3000/0
[12507.942706] remoteproc remoteproc1: failed to unmap 3000/0
[12507.959230] remoteproc remoteproc1: Boot failed: -22
sh: write error: Invalid argument
(please note that some of these printouts are added by me for debugging)

The Linux kernel does a sanity check on the ELF headers to verify that the software is trying to execute at the correct address, as seen by the Cortex-M4. The omap_remoteproce driver says that Cortex-M4 code should execute from address 0x2000 0000, but I can't really find that information in the OMAP5432 reference manual. The only thing I can find is that this (virtual) address is the beginning of a bit-band region in the Cortex-M4 processors. I found these 2 commits which has some info on the issue, but I wonder if the assumptions are wrong for the OMAP5432:
I would love it if someone can help me decipher the TRM regarding this.

I anyway changed my linker script so that M4RAM was set to start at offset 0x20000000, recompiled, and started it...
Code:
# echo "start" > state
[ 1736.332638] remoteproc remoteproc1: powering up 55020000.ipu
[ 1736.338766] remoteproc remoteproc1: Booting fw image hello_world.out, size 202624
[ 1736.346367] omap-iommu 55082000.mmu: 55082000.mmu: version 2.1
[ 1736.352295] remoteproc remoteproc1: IOMMU enabled
[ 1736.357043] remoteproc remoteproc1: rproc prepared
[ 1736.361931] remoteproc remoteproc1: rproc bootaddr: 0x200027D9
[ 1736.367974] remoteproc remoteproc1: fw parsed
[ 1736.374108] remoteproc remoteproc1: resources handled
[ 1736.402581] remoteproc remoteproc1: carveouts allocated
[ 1736.407952] remoteproc remoteproc1: 0x20000000 (10804) vs 0x20000000 (65536)
[ 1736.415128] remoteproc remoteproc1: 0x20002A38 (5040) vs 0x20000000 (65536)
[ 1736.422280] remoteproc remoteproc1: 0x20003DE8 (416) vs 0x20000000 (65536)
[ 1736.429314] remoteproc remoteproc1: 0x20004000 (928) vs 0x20000000 (65536)
[ 1736.436241] remoteproc remoteproc1: 0x20004000 (928) vs 0x20000000 (65536)
[ 1736.443260] remoteproc remoteproc1: searched for resource table: 43ab22d0
[ 1736.450146] remoteproc remoteproc1: subdevices prepared
[ 1736.455925] remoteproc remoteproc1: remote processor started!
[ 1736.455925] omap-iommu 55082000.mmu: iommu fault: da 0x0 flags 0x0
[ 1736.461727]  remoteproc1#vdev0buffer: assigned reserved memory node ipu-memory@95800000
[ 1736.467914] remoteproc remoteproc1: crash detected in 55020000.ipu: type mmufault
[ 1736.467919] omap-iommu 55082000.mmu: 55082000.mmu: errs:0x00000002 da:0x00000000 pgd:0xdd7074d2 *pgd:px95900002
[ 1736.476067]  remoteproc1#vdev0buffer: registered virtio0 (type 7)
[ 1736.499749] remoteproc remoteproc1: remote processor subdevicess started!
[ 1736.506585] remoteproc remoteproc1: remote processor 55020000.ipu is now up
[ 1736.513622] remoteproc remoteproc1: rproc started!
[ 1736.518547] remoteproc remoteproc1: handling crash #1 in 55020000.ipu
# [ 1736.525048] remoteproc remoteproc1: recovering 55020000.ipu
[ 1736.530987] remoteproc remoteproc1: stopped remote processor 55020000.ipu
[ 1736.538691] remoteproc remoteproc1: 0x20000000 (10804) vs 0x20000000 (65536)
[ 1736.545875] remoteproc remoteproc1: 0x20002A38 (5040) vs 0x20000000 (65536)
[ 1736.552971] remoteproc remoteproc1: 0x20003DE8 (416) vs 0x20000000 (65536)
[ 1736.559976] remoteproc remoteproc1: 0x20004000 (928) vs 0x20000000 (65536)
[ 1736.566948] remoteproc remoteproc1: 0x20004000 (928) vs 0x20000000 (65536)
[ 1736.573906] remoteproc remoteproc1: searched for resource table: 43ab22d0
[ 1736.580843] remoteproc remoteproc1: subdevices prepared
[ 1736.586354] remoteproc remoteproc1: remote processor started!
[ 1736.592158]  remoteproc1#vdev0buffer: assigned reserved memory node ipu-memory@95800000
[ 1736.600532]  remoteproc1#vdev0buffer: registered virtio0 (type 7)
[ 1736.606667] remoteproc remoteproc1: remote processor subdevicess started!
[ 1736.613517] remoteproc remoteproc1: remote processor 55020000.ipu is now up

# cat state
running
Success! My code got loaded and the Cortex-M4 started, but it crashed! xD

So, that's where I'm at right now. I haven't deciphered what the errors means. Thought I'd write down today's progress unless I forget it tomorrow. Maybe I'll ask for some help on the linux-omap tomorrow :) Now, it's time to sleep

EDIT:
I also tried to use the TI-RTOS (a.k.a SYS/BIOS) component. I ran the installer, but nothing showed up in CCS so I gave up on that for now. In the long run, I believe some kind of RTOS+RpMsg is the way to go if we want some kind of structured message passing between the two processors.
I also tried various combination of my code where I removed the printf()s and/or linked+loaded the M4 code at 0x55020000. Still crashed with an iommu fault.
 
Last edited:

Risca

Still Fresh
Joined
Sep 25, 2011
Messages
24
A small update:
I don't know what I did, but SYS/BIOS started showing up in CCS and I was able to compile a "typical example" (CCS wording) project. Project configuration is very different for this kind of project and the linker script is automatically generated during build. If I tried to modify it manually, my changes would be overwritten as soon as I pressed build. I was able to copy the needed java (yes, java) code from the IPC package to my project configuration file, app.cfg, so the resource table section showed up in the linker script again, albeit with a hard-coded address this time.

Still crashes thought xD

I also was able to have the IPC package show up in CCS, but when I try to enable it in my app.cfg, I'm left with an error. Looks like my IPC package is not compatible with the xdctools package bundled with CCS. I'm using IPC 3.40 since that's the latest standalone version. Newer versions come bundled with the "Processor SDK", of which there are none for OMAP 4 or 5 :mad: I haven't tried if it's possible to use an older version of xdctools yet.
 

Risca

Still Fresh
Joined
Sep 25, 2011
Messages
24
Hmm... I can't believe this might have worked :eek:

I went through every release of xdctools until I found a version that didn't have the version check I mentioned in my previous post. I ended up with xdctools-3.32.1.22. This version didn't play nice with the SYS/BIOS version I had (6.83.0.18), but the download page for older SYS/BIOS versions actually states what version xdctools each release is compatible with. I downloaded and installed SYS/BIOS version 8.46.6.0, which is the latest version compatible with my old version of XDCtools. I created a fresh new project with both these older versions of xdctools and SYS/BIOS and my example program built fine, but it was lacking the resource table. I know that the IPC package has the ability to automatically add this kind of resource file to my binary, so I added this package to my project as well. Then I copy-pasted things from one of the examples in the IPC example until the thing built. I had to remove some stuff in the IPC package that referenced ti.bios to make some of the configuration errors go away. I hope it wasn't needed :oops:

To summarize:
  • Code Composer Studio: 11.2.0
  • XDCtools: 3.32.1.22_core
  • SYS/BIOS: 6.46.6.00
  • IPC: 3.40.1.08
Looks like the thing didn't crash! :D
Code:
# echo start > state
[  879.517112] remoteproc remoteproc1: powering up 55020000.ipu
[  879.525505] remoteproc remoteproc1: Booting fw image hello_rtos.out, size 2501152
[  879.533195] omap-iommu 55082000.mmu: 55082000.mmu: version 2.1
[  879.539207] remoteproc remoteproc1: IOMMU enabled
[  879.543937] remoteproc remoteproc1: rproc prepared
[  879.548759] remoteproc remoteproc1: rproc bootaddr: 0x00000011
[  879.554672] remoteproc remoteproc1: fw parsed
[  879.560590] remoteproc remoteproc1: resources handled
[  879.581356] remoteproc remoteproc1: carveouts allocated
[  879.586613] remoteproc remoteproc1: 0x0 (68) vs 0x20000000 (65536)
[  879.593046] remoteproc remoteproc1: 0x400 (320) vs 0x20000000 (65536)
[  879.599616] remoteproc remoteproc1: 0x3000 (980) vs 0x20000000 (65536)
[  879.606192] remoteproc remoteproc1: 0x4000 (36464) vs 0x20000000 (65536)
[  879.613037] remoteproc remoteproc1: 0x80000000 (277256) vs 0x20000000 (65536)
[  879.620399] remoteproc remoteproc1: 0x9F000000 (32768) vs 0x20000000 (65536)
[  879.627616] remoteproc remoteproc1: 0x3000 (980) vs 0x20000000 (65536)
[  879.634188] remoteproc remoteproc1: searched for resource table: b1629c3e
[  879.641136] remoteproc remoteproc1: subdevices prepared
[  879.646749] remoteproc remoteproc1: remote processor started!
[  879.652610]  remoteproc1#vdev0buffer: assigned reserved memory node ipu-memory@95800000
[  879.660911]  remoteproc1#vdev0buffer: registered virtio0 (type 7)
[  879.667075] remoteproc remoteproc1: remote processor subdevicess started!
[  879.673898] remoteproc remoteproc1: remote processor 55020000.ipu is now up
[  879.681000] remoteproc remoteproc1: rproc started!

Next step is to go through and double check all the memory mappings and maybe actually try one of the examples. Would be totally awesome if we could get some rpmsg communications going! Then we're talking!

I uploaded my project here: https://github.com/Risca/hello_rtos
 
Last edited:
Top