diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-3B6544CD-FA6E-5AB2-AA63-61186F52167D.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-3B6544CD-FA6E-5AB2-AA63-61186F52167D.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,231 @@ + + + + + +Controllable +Power ResourcesThis topic explains how power resources were controlled in older +releases of Symbian platform. For later releases see the Power Resource Manager +documentation. +

This documentation is retained for reference for those working with hardware +or software that is based on older versions of Symbian platform version (in +particular old release 9.5). For later releases see the Porting +the Power Resource Manager documentation.

+

Controllable power resources are defined as being any device resource, +such as voltages on power-lines or clocks, which can be independently enabled, +disabled or modified under software control.

+

The following hardware block diagram is an example of the way power resources +might be arranged:

+ +Example power resource arrangement + + +

There is no default support or default implementation for controllable +power resources in the generic layers of Symbian platform. They must be managed +by the base port.

+

We suggest that the management of controllable power resources (the resource +manager) be implemented in the Variant DLL or the ASSP DLL. This allows the +resource manager to be up and running by the time peripheral drivers, which +might also be kernel extensions, are loaded. See the ASSP/Variant Architecture and the ASSP/Variant +Tutorials.

+

A suggested implementation has the instance of the Asic derived +class owning a pointer to the resource manager object. The interface class +for the ASSP or Variant could then have an exported or an inline member function +to return a pointer to this resource manager object. Peripheral drivers are +expected to link against either the ASSP DLL, or the Variant DLL, or both.

+

For example, for a device that has a Variant and an ASSP:

+class MyVariant : public MyASSP + { +public: + Init1(); + Init3(); + // Other mandatory Asic-derived member functions + ... +public: + ResourceManager* myResMgrPtr; + ... + }; + +

where class MyASSP is derived from class Asic.

+GLREF_D MyVariant TheVariant; +class TMyVariant + { +public: + inline static ResourceManager* ResourceManager() + {return(TheVariant.myResMgrPtr);} + // other exported methods + ... + }; + +

where TMyvariant is the Variant interface class, and ResourceManager is +the resource manager class.

+

The resource manager can be declared as a global object at the Variant +(or ASSP) scope and can therefore be created when this component is first +loaded. In this case, the Asic::Init3() function would +initialise the ResourceManager object, and set up myResMgrPtr. +Alternatively, if the Variant (or ASSP) were to need the resource manager +up and running, then you would initialise ResourceManager in Asic::Init1().

+

In this implementation, the Variant would export a header file(s) publishing +a list of controllable power resources.

+
Shared controllable +power resources

Some controllable power resources can be shared +between groups of peripherals and therefore may require usage tracking.

We +recommend that shared power resources be represented by a class derived from MPowerInput. +This class offers the Use() and Release() interface +that encapsulates resource counting behaviour. This mechanism should turn +the resource on when the count becomes non-zero, and turn the resource off +when the count becomes zero.

We suggest that your MPowerInput derived +class defines and implements a GetCount() function that returns +the usage count on the shared resource.

+
A suggested +implementation of a resource manager

While we have implied that +a resource manager is a single class, which we have called ResourceManager, +the resource manager is a notional concept for controlling power resources. Symbian +neither mandates a format for a ResourceManager class, nor even its existence. +In practice, it may be more useful to embed resource manager functions and +data in the Variant interface class (or the ASSP interface class, if appropriate).

However, +for the purpose of explaining what a resource manager can do, it is easier +to assume that this behaviour is handled by a resource manager class. This +is the outline definition of such a class.

class ResourceManager + { +public: + void InitResources(); // called by your Asic::Init3()/Asic::Init1() + void Modify(TUint aSetMask, TUint aClrMask); // only 32 simple Resources can be managed + TBool GetResourceState(TUint aResBitMask); // only 1 bit set on this mask, returns On/Off +public: + (MPowerInput-derived) iSharedResource1; // 1 per shared resource + (MPowerInput-derived) iSharedResource2; + ... + }; +

The InitResources() function would +do at least two things:

    +
  • enable an appropriate +set of simple resources at boot time

  • +
  • initialise the shared +power resource tracking objects, i.e. the instances of your MPowerInput derived +class(es).

  • +

The function would be called by the Variant or ASSP implementation +of Asic::Init3() or Asic:Init1().

The Modify() function +is an example of how to deal with power resources that are either on or off. +The function would take bit masks, where a bit represents a separate controllable +power resource. The first bit mask would represent the set of power resources +to be turned on, while the second would represent the set of power resources +to be turned off. This assumes that the function could behave synchronously. +Drivers for peripherals that use a set of these controllable power resources, +would call Modify() to turn the relevant controllable power +resources on or off.

As an example, the most common method of switching +clock resources on or off is by setting and clearing bits in a hardware register. +A base port could choose to implement common code for setting bits in registers.

A +shared power resource is further represented by a MPowerInput derived +class. The implementations of MPowerInput::Use() and MPowerInput::Release() would +call Modify() to turn on the shared resource when the usage +count becomes non zero, or turn it off when the usage count reaches zero. +Peripheral drivers would have access to shared resources, and also to the +member functions of the ResourceManager class, through the +ASSP or Variant Interface class function that returns a pointer to it.

The +resource manager, or its functions and members, could be offered as part of +a power controller interface class, the TPowerController class +suggested when we discussed the implementation of the Power +Controller's EnableWakeupEvents() function. +The class would provide an exported function that would give access to the +resource manager. The resource manager class would be made part of the power +controller kernel extension. Peripheral drivers needing access to shared power +resources would then link to the power controller DLL. If the Variant or ASSP +were also to need access to the resource manager, then the resource manager +would have to be initialised much earlier in the kernel start-up sequence. +In this case, we would suggest that the standard power controller kernel extension +entry point defined by DECLARE_STANDARD_EXTENSION() be +replaced with a custom entry point that might look like this:

GLDEF_C TInt KernelModuleEntry(TInt aReason) + { + if(aReason==KModuleEntryReasonVariantInit0) + { + ResourceManager* c = new ResourceManager (); // create Resource Manager + return c ? KErrNone : KErrNoMemory; + } + else if(aReason==KModuleEntryReasonExtensionInit0) + { + (create DPowerController and Battery Monitor and Power HAL handler) + } + return KErrNone; // gets here from calling with KModuleEntryReasonExtensionInit1 + } +

The Variant or ASSP would also need to link to the +power controller DLL.

The following base port software architecture +could be applied to the power supply arrangement as illustrated in the hardware +block diagram above (see the beginning of this section at Controllable +Power Resources):

+Base port software architecture + +
+
Multi-level, +composite and asynchronous power resources

Some power resources +may have more than one operational level. For example, it is possible that +an input clock to a peripheral can be operated at a nominal value corresponding +to the fully active state, and may be lowered to another level corresponding +to the power saving state.

The same could apply to the input voltages +that the peripheral can operate on. The control model suggested above for +simple resources may not be appropriate. A suggested alternative would have +these multi-Level resources implementing an interface that offers a public +enumeration to cover all possible usage levels at which the resource can be +used, and APIs such as:

class MultiLevelResource + { + enum TResourceLevel + { + EOperationalLevel1, + EOperationalLevel2, + . . . + ELowPowerLevel1, + ELowPowerLevel2, + . . . + }; + void UseToLevel(); + void ReleaseToLevel(); + TResourceLevel GetCurrentLevel(); + . . . + };

More importantly, it is possible that resources may +have to be operated in combination with other resources. For example, some +peripherals may have more than one input clock, and on transition between +power states, these clocks may have to be changed simultaneously.

If +the resources to be actuated simultaneously are simple resources, then the +model above with a Modify() call that takes a bit mask and +allows more than one resource to be changed at a time may be appropriate. +If the resources to be actuated are shared or multi-level, or have to be represented +individually, then another interface will have to be defined to allow modifying +more than one of them simultaneously.

Modifying some resources may +not be an instantaneous operation. For example, it may take a non-negligible +amount of time to stabilise an input clock that has just been modified.

The +nature of EKA2 strongly discourages actively waiting (or “spinning”) inside +drivers; instead it is suggested that the multithreading capabilities of EKA2 +kernel side code and the synchronisation mechanisms available be used to solve +the problem of having the driver code having to wait for a resource to stabilise +before proceeding with its use.

As an example, let us assume that +the multi-level resource mentioned above has a non-negligible delay associated +with any level changes:

    +
  • If the length of time +to wait for a power resource to stabilise is known, and is the order of a +few milliseconds or less, or the driver executes on its unique kernel thread +(not used by any other kernel-side code), then the best solution would be +to sleep the driver thread, by calling NKern::Sleep(aTime) for +the specified length of time after issuing a call to UseToLevel() (or ReleaseToLevel()).

  • +
  • When the length of time +to wait for a power resource to stabilise increases, then sleeping the driver +thread may become a problem if the driver executes in a DFC queue used by +other drivers, which is often the case. This is because blocking that thread +means that no other drivers can run. Here, the best solution is for the driver +to create another thread and DFC queue, by calling Kern::DfcQInit(), +and whenever it needs to change the resource, queue a DFC on that queue, which +will issue the calls to UseToLevel() (or ReleaseToLevel()) +and then sleep the thread.

  • +
  • If the length of time +to change a power resource cannot be known in advance, but the hardware provides +an indication of completion of the change, for example, in the form of an +interrupt, then the solution may involve the driver code waiting on a Fast +Mutex, which is signalled by the completion event (in code belonging to the MultiLevelResource derived +object).

  • +
+
\ No newline at end of file