HALifying/32bitting the Portable module
Pages: 1 2
Jeffrey Lee (213) 6048 posts |
What’s ROOL’s preference for how I should manage the source code for the HAL/32bit version of the Portable module? Stick it under a new HAL branch in CVS, or just overwrite what’s already there? For the moment I’m just aiming for a Portable_Idle implementation that uses the WFI instruction, so not much (if any) of the original code will make it into the first version of the 32bit version. |
Steve Revill (20) 1361 posts |
I suspect as it’s not even 32-bit, you may as well develop the trunk version. If we ever need to create a version for older architectures but that’s also 32-bit, then we’ll either do it with conditional assembly of your version or branch off. |
Ben Avison (25) 445 posts |
What you can’t see from the public repository is that various (unreleased) variants of the Portable module in directories alongside it. A bit like Sound0 has been handled recently. IIRC, the one in the public CVS repository is the one for the Stork (the unreleased Risc PC portable). As such it’ll have all the functions for battery management, LCD control etc. However, I think its only purpose in current builds is to provide its header file. There’s also PortableA4 – the version for the A4 (the Archimedes portable), which is fully featured. I believe all the other variants only implement SWI Portable_Idle – separate modules in each case because traditionally the way you suspend the CPU is different in each implementation, so it’s nice to see ARM standardising it with the WFI instruction. I remember discussing the lack of HALization with someone once, and the answer was it’s just laziness – since it’s only a matter of changing a single poke, nobody could be bothered to go to all the trouble of defining a HAL API for it. I’d suggest putting PortableHAL alongside, if only because the initial implementation will be so cut-down. The original Portable module serves as an illustration of how the battery/LCD SWIs are meant to operate, which may be useful if they are implemented in HAL machines in future. Note to self: we should probably add Portable75 (the variant for the 7500FE, the only IOMD machine with a CPU suspend function) to the list of things to release. |
Jeffrey Lee (213) 6048 posts |
OK, I’ll add the new version as PortableHAL. Having the other versions released into CVS would certainly be useful. The Stork version of the module in CVS has a couple of SWIs that are commented out, and a couple more that have been disabled via conditional assembly – it would be good to know if they were ever used, and if so, how. Likewise for the other modules – I don’t want to go adding a new SWI ontop of an existing one. |
Theo Markettos (89) 919 posts |
Just to complete Ben’s little list for other uses of the Portable module: The A9 has a Portable module for something, though I’m not entirely sure what. It might be something to do with Portable_Idle again, I don’t know. VRPC has a Portable module that talks to Windows to read things like battery state etc. Uses exactly the same calls as the A4. RPCEmu gained a Portable module this afternoon. Only for Portable_Idle support for the moment. |
Jeffrey Lee (213) 6048 posts |
I’ve now got a rough plan on how to extend the HAL version of the Portable module to deal with all the power management things that are needed by the OMAP port (CPU speed control, battery charging/monitoring, suspend-to-RAM, etc.). I’ve also put together a rather large feature matrix showing which features are implemented by which variant of the Portable module. With any luck I’ll have both of the above up on the wiki in the next day or two. |
Jeffrey Lee (213) 6048 posts |
Right, here’s my plan for how I’m going to extend PortableHAL to deal with the OMAP power management stuff. CPU speed controlThe existing Portable_Speed SWI only provides two speed choices, “slow” and “fast”. This isn’t as flexible or as informative as I want it to be, so I’m proposing the following:
Note that there’s no ‘set CPU speed’ call; this is to avoid confusion/conflicts with Portable_Speed. If software wants to set the CPU speed to a specific value (or even disable Portable_Speed entirely) it can simply set appropriate ‘slow’ and ‘fast’ speeds instead. HAL interfaceThe module will most likely defer to a HAL device for all activities – setting the clock speed, reporting current/min/max values, etc. But I haven’t yet read up on the full details of what’s required in writing a SmartReflex driver, so this plan may need to change a bit. Also I know that people like to overclock their OMAPs, due to them being rather overclock-friendly. To cater for this I’m thinking of adding a call to the HAL device which will allow people to overwrite the table that the HAL uses to determine the frequency/voltage values. This will allow people to overclock their OMAPs at will, without polluting the Portable’s SWI interface with something very CPU-specific. Obviously people will have to be careful with what they’re doing, but it shouldn’t be any more dangerous than what they’re doing now if they’re using modified versions of my ‘opp.bas’ program. Battery managementThe existing BMU API is poorly documented (no mention of what units any of the measurements are in!) and inappropriate for some machines (the interface only supports one battery, but the Touch Book has 2 and the Smart Book has 3). So with this in mind, I’m proposing the following:
HAL interfaceEach battery will be a seperate HAL device, and the module will defer to those devices for all status updates, etc. However this won’t work too well with BMU variables 21 & 22, so it might be that some extra magic is needed for that. I might just make it so that the module asks the primary battery and assumes that the device knows how to take into account the effect of the other batteries in the system. The “lid open” flag in BMU variable 10 obviously isn’t anything to do with the battery, but it should be easy enough for the Portable module to report on it via a suitable HAL device. Suspend to RAM (aka Portable_Stop)The Stork version of the Portable module supports this, with keyboard wakeup, and seemingly unimplemented/nonfunctional RTC wakeup. My plan is to support both, using the existing Stork APIs:
HAL interface
General hardware monitoringI think it would be nice if the Portable module was able to report things like the CPU temperature, system power consumption, etc. This would be done via a new SWI (Portable_Status2? Portable_Monitor? Portable_Sensor?) which would provide a list of the detected sensors and allow their description, data type, and value to be reported. Internally each sensor would be a seperate HAL device. Other
For anyone wondering when this new stuff will appear, I’m going to be implementing it all in steps, in roughly the following order:
And finally, here’s the big scary feature matrix that I mentioned earlier. I’ve also updated the existing pages to cover the full feature set, but haven’t yet added any pages for stuff that the wiki didn’t previously cover (e.g. all the Stork SWIs) |
Jeffrey Lee (213) 6048 posts |
Looks like I may have spoken too soon about my plans for the CPU speed interface. Existing code seems to use Portable_Speed to slow the CPU clock in the same situations in which Portable_Idle is used. Using them both together like that may give less power savings than if just Portable_Idle was used by itself, so it looks like I’ll have to do some experiments to find out whether that’s the case or not as far as RISC OS is concerned. Also since reducing the clock speed reduces the effectiveness of stuff like Portable_Idle, TI recommends that the clock speed should always be kept at the maximum speed supported by the chosen OPP (i.e. core voltage). So instead of giving people the freedom to chose exact MHz values it may make more sense to only allow them to choose values that match the limits of each OPP - if it makes sense to give them CPU speed controls at all. |
Trevor Johnson (329) 1645 posts |
Jeffrey, this is a dream (or a potential nightmare, although I hope not).
Would variable 6 also be appropriate (particularly if Portable_WriteBMUVariable will be extended)? And regarding battery charging, did you see these threads on the forums for the Smart Book and Pandora? The features are probably too much for anyone to consider implementing in the initial stages… but if you think they’re valid, perhaps some pertinent points could be included as comments in the code for possible additional functionality. |
Jeffrey Lee (213) 6048 posts |
If we can find what measurement unit that it’s meant to be in, then yes.
I haven’t seen those threads, no. They certainly aren’t on my list of things to do for this initial implementation, but I’ll make a note of them so that they don’t get forgotten. |
Trevor Johnson (329) 1645 posts |
I guess your search already turned up this non definition. Is there a way to find out what nturton was thinking? (How often does this occur – implementing features already partially documented? I guess it wouldn’t really do to go chasing former developers/staff for every little bit of info they didn’t fully document or hadn’t even finally decided upon at the time!) [Edit: I’ve got an A4 - would that help? Perhaps not, as I’m pretty sure the battery holds no chrage whatsoever. But maybe it’d help with the other BMU variables in the future, e.g. 7, 8 and 9.] |
Jeffrey Lee (213) 6048 posts |
Tim Dobson and Christopher Partington, actually. nturton is just the one who imported the file into CVS.
Very rarely, I’d say. Usually you can work out what something does just be looking at the source code, but in this case all the Portable module does is read/write values over an IIC interface. The BatMgr source code, or specs for the battery manager IC, or the microcode that runs on it, would be the most useful. But since the units that the old variables used were never documented, it’s not like there’ll be any software that will attempt to use those variables (except perhaps BatMgr, which we currently don’t have the source to). So there’s no real harm in inventing a new API/set of variables which is better documented. |
Jeffrey Lee (213) 6048 posts |
And as proof of that, here’s what I’ve been able to determine from the A4/Stork BatMgr sources that Ben added to CVS earlier on today:
Overall I don’t think this has much impact for my plans for improving the BMU interface. The battery life estimation code is something that should really be handled by the Portable module instead of BatMgr. Plus the Touch Book uses 6000mAh & 12000mAh batteries; there’s no way we’d be able to represent those values within the limits of the original A4 BMU variables. |
Trevor Johnson (329) 1645 posts |
(A little) OT:
Christopher Partington is still around, FWIW. And I see that Cambridge Systems Design (referred to in the sources) was formed with Jem Davies. This’ll presumably be the same Jem Davies of ARM, who I rather cheekily begged for assistance from a couple of months ago, receiving the following reply: Sorry but I can’t really see ARM committing resource to this – we are still a small resouce-limited company and there are too many OSes out there running on ARM for us to support them all. Some employees do contribute in their spare time and I believe are aware of RISC OS. Good luck! |
Theo Markettos (89) 919 posts |
APIs look generally sensible. Can I make a couple of suggestions, feel free to ignore if they complicate things: Arrange the Podule_Speed2 API so the inputs are also meaningful for Podule_Speed. In other words, so that a fallback to _Speed works if _Speed2 isn’t present. For example, so that this works:SWI XPodule_Speed2 SWIVS XPodule_Speed Have you thought about an API for dynamic voltage scaling? It’s used quite a lot, but I don’t know how much that’s exposed to the user. However it’s not inconceivable that the CPU may be able to turn up or down the core voltage under software control, possibly independently of the clock frequency. I’ve certainly used that on my own test chips. If you’re completely redoing BMU variables, perhaps measure energy in joules rather than mAh if you can? It’s not implausible for a machine to be fitted with batteries of different voltages dependent on the number of cells that can be fitted in the physical space… a 1500mAh battery at 3.7V has rather less energy than a 1500mAh battery at 10.8V. You could, I suppose, provide fake old-style BMU variables to keep old software happy (CryptRandom is one module that reads the BMU data as a source of entropy). I’ve also confused Portable_Idle and Portable_Speed before, so if you’re motivated I recommend fixing the OS to use one or the other. I’m not aware that much third-party software uses either. |
Jeffrey Lee (213) 6048 posts |
That could be a bit tricky, since Portable_Speed2 is designed to complement Portable_Speed, not act as a full-blown replacement.
The OMAP does use voltage scaling. At the moment my code uses a lookup table to work out what core voltage is needed for each band of CPU frequencies. I don’t think it’s a good idea to have a voltage scaling API that’s readily accessible via the Portable SWIs – too much risk of people doing silly things. But you will be able to set custom voltage levels by finding the underlying HAL device and calling the ‘override’ function to specify a new lookup table (This is primarily there for people who want to overclock their machines). Hopefully the fact that this API is hidden away, and requires you to format the data in a way that’s compatible with the specific HAL device, will keep away anyone who doesn’t know enough about what they’re doing.
I can certainly try!
I think the OS should still be capable of using both at once. But for systems where both calls are present, the Portable module should be made to provide a hint as to which usage pattern will save the most energy. |
Jeffrey Lee (213) 6048 posts |
After spending a few days messing round with my TouchBook, I’ve discovered that, for the simple case of leaving the machine idle, allowing Portable_Speed to switch the CPU between min & max speed as it sees fit doesn’t hurt battery life. Obviously you could get better battery life by just leaving the CPU at its lowest possible speed, but in terms of answering the question as to whether Portable_Speed and Portable_Idle can sensibly co-exist, the answer is “yes”. So today I’ve checked into CVS some changes to the Portable module & HAL to implement Portable_Speed and Portable_Speed2. The Portable_Speed implementation is 100% compatible with the original A4 version, but the Portable_Speed2 implementation differs somewhat from my initial plans. Instead of allowing you to set the speed to any integral MHz value between the reported min & max values, it only allows you to set the speed to one of a set number of presets. These presets are dictated by the HAL device and correspond to the different “OPPs” listed in the OMAP data sheets. Apart from providing compatability with systems that won’t allow full control over the CPU clock, the decision to do this was also based around the advice that TI give in the OMAP TRM. By default the Portable module will use the maximum supported speed as its ‘fast’ setting and the minimum supported speed as its ‘slow’ setting. So for OMAP3’s this will be 600MHz (or 720MHz) for ‘fast’ and 125MHz for ‘slow’. For DM37x’s (i.e. BB-xM) it’ll be 800MHz for ‘fast’ and 300MHz for ‘slow’. See the docs for the Portable_Speed2 SWI if you’re interested in changing these defaults for whatever reason. Also it looks like I don’t have any 720MHz OMAPs handy to test the code that detects whether it’s a 600MHz or 720MHz device. So can someone with a 720MHz OMAP (e.g. BB C4) please check that the following two lines of BASIC output ‘720’? SYS "Portable_Speed2",1 TO ,,A PRINT A And finally, should anyone feel like overclocking their OMAP, you’ll be pleased to hear that I’ve added an ‘override’ entry point to the HAL device to allow you to specify a new table of supported values. The table format is device-specific, so see HAL.OMAP3.hdr.CPUClk and HAL.OMAP3.s.CPUClk for details of the required table format. To safely upload a new set of tables, it’s probably best to force the CPU to low speed by doing |
Jeffrey Lee (213) 6048 posts |
(Portable_Stop…)
Having just written the wiki page for Portable_Stop while using the Stork sources as a reference, I’ve spotted that the Stork module seems to handle a lot of the hardware power up/power down itself. So maybe the freeze/unfreeze service calls are only provided to allow software to react to the suspension? (e.g. filesystems will probably want to flush all pending writes). So if the service calls are targeted at software rather than hardware, we’ll probably want a new pair of service calls to instruct the hardware drivers to power up/power down their devices. The final bit which deals with the core chipset & PSU can be left to a HAL device, as planned. |
Ben Avison (25) 445 posts |
I think I imagined that the kernel would be able to control sleepiness of HAL devices directly, but I think you’re quite right that driver modules should be given prior warning, to enable a clean shutdown. Given that the HAL device API was designed with multiple levels of “sleepiness”, I’d say you’d want to include the sleepiness level in the parameters to the service call, so that the modules know what level to request of the HAL device. And if there is such a parameter, I think it only really needs one service call, rather than two. |
Jeffrey Lee (213) 6048 posts |
I’ve got a working implementation of a new BMU interface, and an almost working new version of BatMgr. So now I’m starting to think about nailing down some of the specifics of the new interface, and how it maps to the old interface. I’m currently thinking of going with the following approach:
At the moment I’ve only been concerning myself with the main battery (or batteries), so some further tweaks may be necessary once I start looking at RTC/NVRAM batteries (in particular setting charge voltage & current for BB/PB/etc.) Also there’s no Portable_CommandBMU yet, and I haven’t hooked up the BMU event yet (I’ll probably leave that till after the first release). |
Theo Markettos (89) 919 posts |
On the subject of Portable, would this be a sensible place for more general system monitoring info, like CPU temperature, power supply voltages, fan speed, etc? At the moment Portable is squarely about battery and CPU management. It would be good to read things like CPU temp without having to resort to platform-specific hacks. |
Steve Pampling (1551) 8172 posts |
I’d be more inclined to recommend that it doesn’t feature in the Portable module at all and that the System Environmental aspects feature in their own module. Much more innustry-stannard behaviour. |
Theo Markettos (89) 919 posts |
Yes… it might be more sensible to have a System Environmental API, for which different people can write modules for different platforms. For example, BeagleBoard folks can poke the registers of the monitoring chips, while Raspberry Pi people can talk to the GPU. Is this a HAL thing, or a higher-level module thing (most of this stuff isn’t vital for boot)? |
Jeffrey Lee (213) 6048 posts |
I was initially thinking that hardware monitoring would go in the Portable module. After all, there’s some crossover with what the Portable module already does – most of the BMU variables are for hardware monitoring, and there’ll be some crossover between controlling CPU speed and monitoring its temperature/voltage. But I guess there’s no reason why it can’t go into its own module, especially as “Portable” could become a misnomer if it’s used for too much stuff not related to portables.
Generally speaking the way things should work for any kind of hardware driver is that the HAL or the OS creates a HAL device, and then a suitable module detects that device, implements any extra functionality required, and exposes a consistent API to the rest of the OS & user apps. Although it’s usually the HAL that creates all the HAL devices, there’s no reason why a ROM module or softloaded module can’t create a HAL device which the “frontend” module can then pick up on. The only thing that isn’t clearcut is exactly where the division of labour is between the HAL device and the frontend module – in particular whether the frontend module is a generic one which can cope with any HAL device of that type (DMAManager, Portable, SDIODriver, etc.) or whether it’s tied to specific HAL devices (OMAPVideo, VCHIQ, etc.). With generic frontend modules all of the hardware-specific stuff would be done in the HAL device, whereas with modules targeting specific devices the HAL device usually implements minimal functionality – sometimes none at all, and all the module does is look for the device as a confirmation that it’s running on suitable hardware. For hardware monitoring you’d probably want a generic module with all the hardware-specific bits implemented in the HAL device. On Pi the hardware monitoring would be dependent on the mailbox property interface, so (assuming BCMSupport gets implemented) it would make sense for the HAL device to be created by a module sometime after BCMSupport in the ROM chain – or perhaps by BCMSupport itself. |
Jeffrey Lee (213) 6048 posts |
I’ve been trying to work out a way of mapping my new BMU variables to the old BMU variables. While doing this I’ve discovered a couple of things:
Taking the above into account, I’m proposing the following mapping of BMU variables:
Any thoughts on this arrangement? My main thought is that I’m not sure if there’s much point supporting the A4 NominalCapacity & UsableCapacity, since there’s no UsedCapacity or ChargeEstimate to use to measure how much charge is remaining (plus I’m still not 100% sure what all the different values represent). So maybe those two should be ignored and added as new variables instead? |
Pages: 1 2