OMAP3 - How to deal with different hardware configurations for different boards?
Jeffrey Lee (213) 6048 posts |
If you’re reading this thread then you’re probably aware that there are a number of different OMAP3 boards available. Some of these boards already run RISC OS, some of them will definitely run it in the future, and some of them stand a good chance of running RISC OS even though we don’t have any specific plans to port the OS to that hardware. The main problem RISC OS faces with supporting all these different OMAP3 boards is that each one has a different hardware (and software) configuration. But at the moment there’s no way for the HAL to identify what board type RISC OS is running on, and therefore there’s no way for the HAL to know how to correctly initialise the hardware (e.g. turning on the power to the USB host transceiver or to the DVI framer), or which hardware should be used for what (e.g. which IIC line should be used for EDID data, or which location in NAND should be used for storing NVRAM/CMOS settings). This is obviously a bit of a problem. I can think of there being four basic solutions:
Out of the options I think option 4 is the best. Although I don’t think we should rely too much on u-boot doing things for us (it’s nice to know that our hardware drivers are capable of initialising everything properly themselves), we should at least allow u-boot to be used to tell us what the basic hardware configuration of the board is. Which serial ports should be used, which I2C lines are connected to what, where the CMOS/NVRAM settings should be stored, what timings to use for an attached LCD panel, etc. Basically the same kind of stuff that u-boot passes to the Linux kernel. Any thoughts? If we decide to go ahead with this, I should be able to fairly quickly knock up some code to allow the HAL to parse the parameter string and react accordingly. Then with the autobuilt ROM images we can bundle a set of u-boot scripts and a readme file instructing the user to user to use the correct boot script for his board type (although there’s also an API to allow the child OS to call u-boot as if it were a BIOS - it would be worth investigating that to see if RISC OS can simply ask u-boot what the board type is) |
Peter Naulls (143) 147 posts |
u-boot has a lot of merit – it’s almost certainly used on the boards already to boot Linux (there are other bootloaders out there like redboot, but u-boot is really the most comprehensive), and certainly if I had a board I’d likely want to boot Linux as well as RISC OS. However, do you have an idea of categorization here? Of grouping of similar hardware that might conceivably boot the same kernel? Here’s a starting point: |
Jeffrey Lee (213) 6048 posts |
I think the general consensus is that there will be one ROM image for each SoC/SoC family. This strikes a good balance between ROM image size/complexity and the number of ROM images that must be maintained. In the future if we end up with too many ROM images to maintain we can always begin merging them together a bit (e.g. it would be fairly easy to build a ROM image containing multiple HALs, and then have u-boot or something similar indicate to the OS which HAL should be used) Just to be clear – I’m talking about using u-boot to pass a parameter string to the HAL. I’m not suggesting that we use u-boot as a “HAL replacement” (Although if u-boot is flexible enough to be used in such a manner then it’s certainly something worth considering for any future RISC OS ports) |
André Timmermans (100) 655 posts |
No criticism really since all the porting efforts are currently concentrated around Soc chips but I view the current trend of of putting everything in the HAL as less flexible than drivers on a sub-system basis, a bit like RISC OS 6 has done with its display drivers for VIDC, ViewFinder and VPod. |
Ben Avison (25) 445 posts |
For what it’s worth, when we did a variety of STBs with different board layouts but based on various members of the same SoC family, we handled them using different ROM images (built using the same HAL source code but different Components files specifying different options to be passed on the command line when building the HAL). But then, in that case it wasn’t the end-user’s responsibility to ensure the ROM image for the correct hardware was programmed into the flash, so maybe the situation isn’t really equivalent. Historically, of course, Acorn tried to detect board variants (e.g. Risc PC vs A7000) at run time. But then they had the advantage that they designed all the boards and could ensure that they were easily distinguishable by software.
Sounds a bit ugly to me. Plus the initial entry point is in the HAL rather than the OS, so this would amount to specifying alternate execution addresses to U-boot. In which case you could save on duplicating most of the HAL code and have that HAL start like this: Entry1 MOV r0, #Board_Beagle ; address &FC000000 B CommonEntry Entry2 MOV r0, #Board_Pandora ; address &FC000008 B CommonEntry Entry3 MOV r0, #Board_Touchbook ; address &FC000010 B CommonEntry ... CommonEntry STR r0, BoardType ... which is basically your option 3. Another option is for the HAL and OS images to be distributed (and maybe flashed) separately. This was one of the original design goals of separating the HAL into a separate binary lump which is not directly linked against the OS at all. There could be a single OS image for OMAP boards (or any other boards – Freescale ones perhaps – that have the same CPU and an equivalent set of peripherals) that contains the OS sides of each driver, and a set of HAL images, one for each board. As the port progress, the frequency of changes to the HAL should decrease, until eventually when the port is mature, its users would only need to reflash the OS image anyway.
The difference is that Viewfinder and Vpod are modular, user-installable or removable pieces of hardware. The RISC OS 5 approach is to put the hardware-specific parts of drivers for hardware on the motherboard in the HAL. Code that understands standardised register sets or messaging protocols remains in the OS, to avoid code duplication and allow different platforms to inherit each other’s bugfixes – only the mechanics of how the registers are written or the messages are sent is devolved to the HAL. Likewise, any code that interacts with other modules remains in the OS. There are a few cases where different HALs share code – perhaps otherwise unrelated boards might use the same audio DAC, for example, but this is exception rather than the rule, and can usually be achieved by simply copying a single source file. The most significant example I can think of is the way that the HAL code for allocating PCI bus addresses for Tungsten was re-used for Castle’s ARM9 STBs that also featured an external PCI bus. Where expansion cards are used (so for drivers for devices not on the motherboard), the RISC OS 5 model still uses RISC OS modules to provide the drivers. This is reflected in the APIs developed – for example, OS_Hardware devices can be created from a HAL->OS call or using a SWI (which can only be called from a module), but can only be removed using a SWI (so can only be removed from a module). Most notably, the graphics system offers most operations to holders of GraphicsV (which have to be modules – in the Iyonix, the NVidia module drives the standard graphics card, but others could have been developed) before passing them on to the HAL so that the motherboard graphics system is used in the absence of an expansion card. There was an aborted plan at one stage to offer a SATA card for the Iyonix – in which case ADFS would have handled the motherboard PATA controller via the HAL interface and the SATA card whose driver would have lived in a module – but the knowledge of the ATA command set would remain within ADFS. I hope this illustrates the concepts. |
Jeffrey Lee (213) 6048 posts |
Yeah, that’s one option I didn’t think of. It would certainly work, so again it’s just a question of whether we want the flexibility offered by option 4, where users can specify their own configuration options. Where to store CMOS RAM settings and what LCD timing parameters to use are the only two options I can really think of that users would be interested in changing, but even then it’s probably only a handful of people who would want to change those settings anyway (Not that that means we should ignore their requests!) |
Jeffrey Lee (213) 6048 posts |
In the end I’ve decided to go with option 3 (multiple entry points). There’s also the the possibility of adding option 4 (parsing an argument string) later on. Basically for each board config there’ll be a structure defining all of its characteristics. A branch table at the start of the HAL will be used to select which board config to use, based around the address that the HAL is entered at. The corresponding board config structure will then be copied into the 64K SRAM (which RISC OS currently doesn’t touch), keeping it safe during the initialisation code. Later on when RISC OS calls HAL_Init the structure will then be copied into the HAL workspace, where it’s quicker/easier for the HAL to access. For distributing the ROM it would just be a case of supplying multiple u-boot boot scripts, one per board type. This would also allow us to do other little tweaks to the boot scripts, e.g. to avoid using a load address that overwrites any board-specific splash screen that u-boot displays. For supporting option 4 it would just be a case of adding another entry point, say 256 bytes into the image (to avoid getting overwritten by jump table growth), which would then parse the argument string u-boot supplies and create the corresponding config structure inside SRAM. This code could also support using an existing config as a prototype, so it becomes easier to do minor changes like selecting a different storage location for CMOS/NVRAM settings. |
Jeffrey Lee (213) 6048 posts |
Some more thoughts on this. After spending some time today and yesterday looking at the u-boot and mkimage source code, it looks like packaging ROM images as u-boot uImages is a fairly sensible idea:
Also it looks like it would be fairly trivial to add uImage support to romlinker itself – for an uncompressed image all that would be needed would be a custom header with a couple of checksums. This is perhaps better than the alternative (a seperate post-process to run mkimage on a ROM image), because it means we can just overwrite the start of the ROM with the uImage header, so we can still fit a 4MB ROM inside the “standard” 4MB NAND partition. So with that in mind, does anyone at ROOL know if RISC OS relies on any of the magic values that romlinker pokes into the ROM image? Specifically, the “image size” at offset &60, and the values that are inserted at the end of the image (POST zero word, ROM signature, checksum pair). As far as I can tell they aren’t actually needed (or at least not for the OMAP ROM), so it would be good to be able to get rid of them if we added uImage support to romlinker (especially since it would be almost impossible to find uImage and romlinker checksum values that don’t contradict each other). For vanity’s sake we could also submit a patch to add RISC OS to the list of OS’s that u-boot recognises; it might not do much to help us with this generation of devices (unless we force everyone to upgrade to the latest u-boot), but for future devices it would mean that u-boot lists the file as being a RISC OS ROM image instead of a Linux kernel. Really this is something I should have thought of doing last year when I first started! (Although there’s no guarantee that any device would have shipped with RISC OS support enabled – u-boot configuration headers allow you to turn OS support on and off on a per-OS basis) |