Sunday, October 31, 2010

Erratum ENGcm09395 and OpenOCD

Apparently, the Erratum ENGcm09395 for iMX515 made the OpenOCD problems clear. It states the location of ROM Table is misreported. But still, I wanted to implement the ROM Table location autodetection as Oyvind Harboe hinted me to.

Therefore I added a function for handling quirks as this and did some code shuffling in OpenOCD. The patches for this are already in the OpenOCD mailing list. I'm still a bit uncertain about them, but I hope after one or two iterations, they will land in mainline OpenOCD.

Saturday, October 30, 2010

Studies, U-Boot, OpenOCD and CortexA8

The lack of additions on this blog recently wasn't caused by me disappearing out of the blue. It was caused by me preparing for my degree's exams, then fighting with U-Boot and recently working on a new hardware. Read on.

Studies
In case you're only interested in technical stuff, you can skip this part, which is mostly about gaining my bachelor's degree at the Faculty of Mathematics and Physics Charles University and the OpenBSD thesis.

Due to rather personal than other circumstances, I ended up finishing my first academic degree at the end of the summer rather than at the beginning of it. Well, whatever.

That means, the OpenBSD hacking days are past me since I finished my bachelor's thesis. I believe I wrote about this in some of the previous blogs, but now it's officially past me and sealed away. In the end, the thesis was graded A by both the opponent (Mgr. Martin Decky) and the supervisor (RNDr. Leo Galambos, Ph.D.) so the final grade from the thesis was A as well.

Note, the grading system in our country is different than in most other countries. Here, it's numeric, but "1" is equal to A, "2" to B, "3" to C and "4" to Failed. I'll hereby stick with the system using letters to make it less confusing.

Then I had to prepare for the exams, which were really thorough so the preparation certainly couldn't be underestimated. That took me about a month where I didn't hack on stuff much, I was just reviewing patches and from time to time I sent some minor fixes. At the exam, I finished with a total grade of B.

Apparently, on the diploma, there is only one grade, not two (one from thesis and one from examination), so the examination committee has to ultimately decide this grade. My final grade was A, which is what will be on my bachelor's diploma, which I'll receive later next month.

U-Boot
Once the exam was past me, I got back to maintaining U-Boot PXA. Apparently, there were a lot of changes going on inside the U-Boot.

Firstly, Wolfgang Denk pushed me to rework pxa-regs.h so the standard accessors can be used to access PXA CPU registers instead of the preprocessor goo that was there before. This was a patch over 6000 lines big as it affected a lot of code in U-Boot, not only pxa-regs.h. Obviously, platform code as well as drivers were affected and had to be patched to use {read[blw],write[bwl]}() accessors. Catching all the damaged code wasn't really easy in some cases, but I think I caught them all.

With that out of the way, I checked pxa-lcd driver and fixed various, mostly coding-style related problems and added a few new LCD definitions. Then, I fixed PXA250 UART problem, where the UART was omitted in U-Boot from the initialization routine on PXA25x and PXA26x.

Also, the Palm LifeDrive, Palm Tungsten|C and Balloon3 support went in, Voipac PXA270 got various bugs fixed and there were also fixes for the memory init code by Mikhail Kshevetskiy. I also got an USB3.0 flash disk, but apparently, it didn't work with USB on PXA in U-Boot, so I submitted a patch for this.

Then though, Heiko Schocher introduced a change in U-Boot, which allows it to relocate in RAM. More into detail, this change allows U-Boot to always sit at the end of RAM, which is useful on systems where there are various models with different size of RAM detected at runtime. This change broke the PXA port of U-Boot altogether.

This was a good enough motivation to completely rework the PXA init code. I rewrote half of the start.S assembler bootstrap from scratch, because the code there was really old, messy and and with the relocation patches in, no longer suitable for the purpose. The start.S can no longer use RAM until certain point, but it needs to use stack. Sure, for stack, SRAM can be used on PXA27x, but there are PXA CPUs older than that which have no SRAM. This set me in front of a challenge -- where should I point stack pointer register is there's no RAM.

The solution is somehow easy, but needs you to understand how the caches on ARMv5/XScale core work. What was the trick? It was easy, the caches allow the user to lock entries in them. That is, they allow the user to write into the cached area, while convince the CPU not to actually write the data into that area, but only keep them in cache. But for using caches, MMU has to be enabled. So the big picture is, I manually generated an 1:1 VA:PA mapping MMU table within the U-Boot binary and at the bootstrap, I point the CPU at this table and enable MMU. Within this table, at the place which indexes RAM start +1MB*, I made a special entry that configures the area as cachable. Then I used the information from the XScale core documentation to lock 4 kb of data to create a tiny, 4 kb in-cache RAM. So writing to that area of RAM behaves as if the RAM was where and was working, even though there's no backing store. The rest was just a matter of pointing a stack pointer there, end of the fairy tale.

This wasn't the only thing about relocation patches though. Because there was no need to init the RAM in assembler code anymore, I could push the RAM init into the C routines which were executed much later. I did this and in current state, most of the hardware initialization takes place much later. This has one very big advantage in the long-term. As the hardware is not initialized in C code, it'll now be easily possible to walk a Flattened Device Tree and do the hardware initialization according to that. So imagine having single U-Boot binary work many CPUs and only supplying a FDT for each board. That's the long-term plan now.

There were other changes related to this relocation stuff, which in the end generated about 30 patches in total. One more thing is interesting though. Because there are boards which have multiple variants and it's not possible to detect which variant is which on the fly, there started to appear a Makefile pollution in U-Boot, which Wolfgang Denk didn't like. We discussed this and came to a conclusion about a solution. I implemented first version, then he improved it and committed it. So now, all of the U-Boot board variant setup should happen in boards.cfg finally and there's no longer need to touch Makefile.

OpenOCD and CortexA8
About a month ago, I received an Genesi USA EfikaMX Smarttop from their developer sponsorship program called Power Developer. My task was to support this device with OpenOCD so common people can JTAG it with those cheap FT2232-based JTAG dongles.

The system contains an Freescale iMX515 CPU, for which apparently there were some previous unsuccessful attempts to make it work. I based my efforts on these, but did a further investigation of the matter. "Sadly", all the support for Cortex A8 was already in place, which spoiled my fun ;-)

And in the end, it turned out the solution of the problem was very simple. The people trying to get iMX515 working with OpenOCD forget, that the Cortex A8 support there was OMAP3-centric. The DAP address was hardcoded for OMAP3, which has it at 0x54011000 address, but for iMX515, the DAP address is at 0x60008000. Adjusting this in the source code made the CPU mostly work.

The problem with this though is, that this stuff should be auto-detectable. So far, I was digging in the CortexA8 stuff for about two days so I have still a lot to learn about this. But I was hinted by Oyvind Harboe and Zack Welch to use the "dap info 1" command and look around that. The command reads the MEM-AP's BASE register to figure out the location of ROM Table. And by parsing the ROM table, it's possible to figure out the location of DAP, which is exactly the address I mentioned in previous paragraph that needs to be autodetected.

The problem is, this command for some reason misdetects the location of ROM Table and returns the ROM Table is empty. By manually adjusting the source code and pointing the command to a proper location of ROM Table, the parsing algoright catches up and correctly dumps the contents. You can keep an eye on further development of this matter for example here (or the OpenOCD mailing list obviously).

There, you can also find preliminary patches with which the iMX515 works, but the autodetection of ROM Table base is still missing. So, if you want to use iMX515 with OpenOCD, you can, but those three patches won't probably make it into mainline OpenOCD until the autodetection problem is solved.