[Tinyos-devel] Re: TEP 101 - the proposal for ADC interfaces

Yuval Peduel yuvalpeduel at digitalsun.com
Fri Feb 25 00:13:49 PST 2005


Vlado Handziski wrote:

>First of all, thanks for your comments. This kind of feedback from the
>community is exactly what we need to further improve the HW
>abstraction proposals for TinyOS-2.x
>
>I don't have much to add to Jan's reply on the technical side, instead
>I just wanted to clarify what seems to be a misunderstanding about the
>relation among  ADC TEP102, TinyOS-2.0, TinyOS-1.x implementation for
>the MSP430 and the TinyOS-1.x implementation for Atmel.
>
>1. The current (TinyOS-1.x) implementation of the ADC stack for the
>Atmel does not follow the HAA, and its HPLADC interface does not
>follow the recommendations from TEP2.
>  
>
I am glad that you and so many others see this. I was most upset when 
the first response claimed that the 1.1.x Atmel implementation did 
follow the HAA model closely.

>As you have pointed out, there are several issues with the way the
>abstractions were done in TinyOS-1.x and it was because of this that
>we embarked on defining the new HAA. The HAA is going to be fully
>applied to all abstractions and on all platforms starting from
>TinyOS-2.0!
>  
>

That makes perfect sense, and, as I've already noted, I support the 
notion of the HAA hierarchy.

>Having said that, most of the ideas behind the HAA were developed
>during the porting of TinyOS-1.x to the MSP430 platform.  Because of
>this, the current TinyOS-1.x ADC stack for the MSP430 closely follows
>the HAA and its interfaces can be used as an example how the HAA can
>be applied to a sizable HW module like the ADC.
>  
>
That's good to hear.

However, now that we've taken care of my first order issues, it is time 
to go to the next level.

One of our concerns, like that of many other users of TinyOS, is 
minimizing power usage to maximize battery life. In addition to careful 
use of the radio, the most power hungry component, our primary approach 
to power management is to put the processor to sleep. At the same time, 
we want to put as many of the peripherals as possible in their minimum 
power state as well. On the Atmega 128, this includes clearing the ADC 
enable bit.

So now comes the really hard question (to which I don't have a good 
answer): at what level should this be done and with what kind of 
interface? In particular:

1. Do we really want the power control routine to know the details of 
the ADC hardware implementation, completely ignoring the ADC driver 
hierarchy, as the HPLPowerManagementM.nc code currently does? The idea 
that the ADC registers are touched in multiple pieces of code scares me 
and creates what can only be a maintenance nightmare.

2. Do we go through the HPL layer, again knowing about the hardware but 
being a little more polite about accessing it, yet still ignoring the 
state information in the HAL driver?

3. Do we go through the HAL layer, making it possible to keep its state 
consistent but not that of the HIL driver?

4. Or do we insist that there be a busy/idle and sleep/awake methods for 
the ADC HIL layer?

5. And then, do we take whatever solution seems best and apply it across 
the board to every device?

My first reaction is that it needs to be done at the HIL layer just to 
make sure that the state at all levels is properly maintained across the 
sleep/wake cycle. However, this creates a number of problems, especially 
when generalized to other devices:

1. At the HIL layer, the driver may use multiple underlying devices and 
resources; not just the ADC. If some of these are also shared resources 
that have to be put to sleep, then there is the question of proper 
ordering. We can't put to sleep a component that the HIL driver uses 
until after the HIL driver no longer needs it. Similarly, on wake-up, we 
have to wake the lower-level components first.

2. In some cases, the system is willing to abort the current operation 
and the hardware supports a simple reset of the device. But in other 
cases, either because the system is not willing to abort an ongoing 
operation or because getting the hardware to a safe state for sleeping 
requires significant time, one might feel the need for a split sleep 
request. This would significantly complicate things if the extra 
generality afforded by it were not needed.

(In our current application, we have, in addition to the ADC sensors, a 
capacitance sensor and a light sensor. Both take milliseconds to 
complete a sample. As it happens, we are willing to abort the ongoing 
operation so we've been able to finesse these problems, but just 
thinking about them made it clear that they are not easy to deal with. 
Which is, of course, why the current 1.1.x goes about it so crudely.)

Note that in some cases, people use the stop/start methods of StdControl 
for putting components to sleep and waking them up. For some components 
(those that people care about most), the code has been carefully crafted 
to support this usage. But if it is part of the spec for start and stop, 
then I haven't seen it, and judging from the implementations I've seen, 
most of the implementors of components don't see this as a requirement.

(Most components do not count the number of start() calls they get, but 
stop with the first call to stop() rather than when the number of stop() 
calls equals the number of start() calls. That means that the ordering 
requirements, when two components use a common lower-level component, 
are violated.)

As I noted, I know of no easy answer to this issue, but as sleeping is 
so central to real-world TinyOS applications, I think it should be 
addressed. The TEP 101 ADC spec might not be the best place to do it in 
its entirety, but as it clearly affects device interfaces, the TEP 101 
spec should clearly address the issue, even if only to say that it isn't 
going to deal with it for now but leave it as an open question.

>2. As a consequence of the above, TEP102 provides much more detail
>about the HAA aligned interfaces on the MSP430 platform then on the
>Atmel one.
>
>For the latest state of the ADC stack in TinyOS-2.0 on the Atmel,
>please consult the code in the tinyos-2_0_devel-BRANCH branch in
>/tinyos-2.x/tos/chips/ATmega128 on CVS. You will see that the new
>HPLADC is more aligned with the HAA than the current implementation.
>Among else, it exports the "enable" command that you've asked for.
>
>I hope that the developers from Xbow (responsible for the TinyOS-2.0
>ADC stack on Atmel) can provide you with more info.
>
>Vlado
>
>On Mon, 14 Feb 2005 13:41:12 -0800, Yuval Peduel
><yuvalpeduel at digitalsun.com> wrote:
>  
>
>>Jan Hauer wrote:
>>
>>    
>>
>>>>1. As someone who does not know anything about the external ADCs or the
>>>>MSP 430, I am very concerned that any Hardware Independent Layer spec be
>>>>written in such a way that I as an ignorant user can safely write
>>>>platform-independent code and that I as a developer on a new platform
>>>>can write a compatible implementation.
>>>>2. As someone who has spent a good bit of time using the Atmel Atmega
>>>>128 and its ADC unit, I'm very concerned about the fundamental approach
>>>>this proposal is taking as it seems to be extending the TinyOS 1.1.x
>>>>interface and implementation rather than looking forward to the HAA model.
>>>>Let's start with the HIL. This is supposed to be a hardware independent
>>>>interface, yet understanding it seems to require detailed understanding
>>>>of the MSP 430. Looking at this spec, I haven't the foggiest notion of
>>>>how I would go about writing an application. Under what circumstances
>>>>would I use reserve(), reserveContinuous(), and unreserve()? Under what
>>>>circumstances would I use ADCMultiple as opposed to ADCSingle? What
>>>>error conditions might I encounter and what error returns correspond?
>>>>
>>>>
>>>>        
>>>>
>>>I think some things need to be cleared up.
>>>An application, if it wires to the HIL interface, should not have to
>>>deal with platform dependent issues (MSP430, external ADCs...) because
>>>HIL is the platform independent level.
>>>
>>>      
>>>
>>Exactly. That means that its users shouldn't need to know anything about
>>the hardware they are running on. They should be able to understand the
>>HIL interface spec on its own.
>>
>>    
>>
>>>This implies, however, that the
>>>HIL interface is defined in such a way that it can be implemented on
>>>ALL platforms - the HIL is a common denominator, it should take into
>>>account, for example, that some external ADCs are connected to the MCU
>>>on a bus and need extra setup time (arbitration issues, etc.). This
>>>must be reflected in the HIL interface if it is to be platform
>>>independent. Therefor we chose to add a reserve(),
>>>reserveContinuous(), and unreserve() command to it, see e.g.
>>>tinyos-1.x/tos/platform/msp430/ADCSingle.nc for detailed information
>>>(the HIL interfaces will be moved to tinyos-1.x/tos/interfaces):
>>>
>>> /**
>>>   * Reserves the ADC for one single conversion.  If this call
>>>   * succeeds the next call to <code>getData</code> will also succeed
>>>   * and the corresponding conversion will then be started with a
>>>   * minimum latency.
>>>   *
>>>   * @return ADC_SUCCESS if reservation was successful,
>>>   * to accept the request, error code otherwise (see ADCHIL.h).
>>>   */
>>> async command adcresult_t reserve();
>>>
>>>
>>>If on the mica (on the MSP430 as well) a reserve() is less meaningful
>>>then an application programmer does not need to use it (you don't need
>>>to use the commands, but only implement eventhandlers and there is
>>>only one event, dataReady). If you look closely at the interfaces you
>>>will see that they extend the old interfaces (ADC, ADCControl), i.e.
>>>they offer you more functionality - whether you use it or not is up to
>>>you.
>>>
>>>
>>>      
>>>
>>You seem to have missed the point. I am in no position to judge whether
>>the reserve-related methods do or do not belong in the HIL (if only
>>because I don't know enough about them). That was not the issue I
>>raised. I noted only that if they were in the HIL, then they had to be
>>well documented enough for:
>>
>>1. An application programmer to know when and how to use them.
>>
>>2. A platform developer to know how to implement them.
>>
>>My point was that the documentation I saw was completely inadequate for
>>either function. For example, on the application level, your description
>>says:
>>
>>    
>>
>>>   * Reserves the ADC for one single conversion.  If this call
>>>   * succeeds the next call to <code>getData</code> will also succeed
>>>   * and the corresponding conversion will then be started with a
>>>   * minimum latency.
>>>
>>>      
>>>
>>This raises the following questions that I couldn't find an answer to:
>>
>>1. Is there any reason for not calling reserve() before every call to
>>getData? After all, we all want minimum latency. And if they should be
>>called before every call to getData, why not merge them in with getData?
>>
>>2. Under what circumstances can a call to getData otherwise fail? (How
>>can I write application code not knowing what a failure means?)
>>
>>(Note that once I understand the reserve() family, I may come to some
>>conclusions about whether they belong in the HIL. :-)
>>
>>    
>>
>>>Another important fact to know about the HAA is that you can always
>>>write platform dependent code that wires to the HAL. I.e. if you know
>>>your code only runs on the Atmega 128 you simply use ADCControl and
>>>the slighty changed ADC interface (Atmega128ADC).
>>>
>>>The ADC hardware stack does very well align with the HAA (in fact the
>>>ADC actually inspired the whole concept of hardware abstraction), you
>>>can very well see the separation into three layers, where HAL provides
>>>platform dependent and HIL provides platform independent interfaces.
>>>
>>>
>>>      
>>>
>>Are you seriously claiming that the HPLADC interface provides access to
>>all the registers as an HPL interface in the HAA should? How do I, with
>>the current HPLADC interface keep ADC Enable on all the the time so my
>>samples take only 13 cycles rather than 25? How do I abort a sample and
>>yet leave the ADC in a good state with the current HPLADC interface?
>>
>>We've had to modify the HPLADC interface in order to use the hardware as
>>Atmel suggests. In the HAA model, one should not have to modify the HPL
>>level to take full advantage of the hardware. In fact, my understanding
>>is that in the HAA model only the developer of the HAL implementation
>>should even see the HPL. Applications should all be using either the HIL
>>or the HAL.
>>
>>    
>>
>>>>Note also that as a developer of a compatible implementation, I would
>>>>have to understand all of these issues thoroughly. I could not just play
>>>>safe by using ADCSingle and ignore the "reserve" issues. This means that
>>>>any HIL interface must be extremely well documented.
>>>>
>>>>
>>>>        
>>>>
>>>As a developer of HPL, HAL and HIL components, of course you must
>>>fully understand these issues - as an application programmer not. Yes,
>>>the HIL must be very well documented.
>>>
>>>
>>>      
>>>
>>So what are you objecting to? With respect to the HIL, all I noted was
>>that the documentation was inadequate; that I, for one, do not
>>understand it. Do you believe that it is already adequate?
>>
>>    
>>
>>>>On to the Atmel Atmega 128, its ADC, your interfaces, and the current
>>>>1.1.x implementations.
>>>>
>>>>
>>>>        
>>>>
>>>[actually I don't know the details of the atmel implementation]
>>>
>>>
>>>      
>>>
>>Then how can you argue for keeping the new interfaces and code backward
>>compatible? The current interfaces are essentially undocumented so one
>>has to code to the implementation. Change the implementation and, even
>>if the interface signature hasn't changed, the application code may
>>break (as ours did when we moved to 1.1.x, forcing us to replace the
>>1.1.x implementation).
>>
>>    
>>
>>>>Therefore, it introduced two problems:
>>>>1. There was no way of knowing whether a "successful" request was, in
>>>>fact, currently being executed. This made it impossible to know whether
>>>>the results were actually timely (an important issue in such
>>>>applications as using the ADC to control radio transmission in the
>>>>context of squelch).
>>>>
>>>>
>>>>        
>>>>
>>>And this is exactly where the reserve() comes into play :)
>>>
>>>
>>>      
>>>
>>1. O.K. And where was this documented?
>>
>>2. As I noted, the original version didn't need reserve(). So the
>>implementation got messed up and we're going to save it by making it
>>more complex? I hope there are better reasons for introducing the
>>reserve() family.
>>
>>    
>>
>>>>2. When switching from a single-ended to a differential channel, the
>>>>Atmel spec suggests waiting 125usec or throwing away a sample or two.
>>>>With the original interface, if we wanted to read a differential
>>>>channel, we could start a read at the task level and then at the
>>>>dataReady signal throw that result away and start another, secure in the
>>>>knowledge that no other code could get in to start a sample on a
>>>>different channel. With the new implementation, another channel may have
>>>>been requested before the dataReady, so even with the second request at
>>>>the dataReady level, there was no guarantee that the two samples on the
>>>>differential channel would be adjacent and hence result in a usable value.
>>>>
>>>>
>>>>        
>>>>
>>>This could theoretically also be solved with the reserve(), but then
>>>it probably needed to be split-phase. Come to think of it, it makes
>>>sense to have reserve() split-phase anyway - but then we'd need to
>>>have another event on HIL level (I can just hope that users have at
>>>least a "foggy notion" about what it will mean, because they'll have to
>>>implement the eventhandler).
>>>
>>>
>>>      
>>>
>>It sounds like you really haven't thought through what the Atmel ADC
>>implementation should look like to support the operations that
>>applications really need. As I noted, ADCs are rather tricky and
>>idiosyncratic beasts.
>>
>>    
>>
>>>>Another concern with the current implementation is the handling of ADC
>>>>Enable. The 1.1.x HPLADCC code keeps ADC Enable off by default. It turns
>>>>it on at each getData, and then turns it off again at each dataReady.
>>>>The result is that each ADC sample takes about twice as many cycles as
>>>>it should, again an issue in such applications as CC1000 radio squelch
>>>>control.
>>>>
>>>>
>>>>        
>>>>
>>>For HIL this must be accepted, on the HAL one could add another
>>>command (you can add one yourself).
>>>
>>>
>>>      
>>>
>>What? This is fundamental to the existing HPLADCC implementation. Adding
>>another command doesn't help; HPLADCC has to be rewritten.
>>
>>And if you are saying that I have to add another command to either the
>>HAL or the HPL, doesn't that indicate that they are inadequate as
>>interfaces?
>>
>>    
>>
>>>>Then there is the issue of "binding".
>>>>
>>>>
>>>>        
>>>>
>>>Yes, something we are quite proud of.
>>>
>>>
>>>
>>>      
>>>
>>>>Different hardware platforms use
>>>>different voltage references. Some, like the mica, use external
>>>>references; others use one of the two internal references. When one
>>>>switches between one reference and another, a settling period is
>>>>required (as when switching from a single ended to a differential
>>>>input), though one might also argue that this generally makes no sense.
>>>>More to the point, when the current code loads the hardware, it uses the
>>>>value in the "binding" to specify the voltage reference.
>>>>
>>>>
>>>>        
>>>>
>>>When you bind to some settings the HIL/HAL implementation must make
>>>sure these settings are valid on a getData() call, i.e. it could delay
>>>the call on HIL (an app wiring to HIL does not know about timing
>>>issues).
>>>
>>>
>>>      
>>>
>>You haven't provided documentation on just what the HIL and HAL
>>interfaces require for binding so I can't comment on this.
>>
>>    
>>
>>>>And when an
>>>>application specifies the binding, it must, therefore, also specify the
>>>>voltage reference.
>>>>
>>>>
>>>>        
>>>>
>>>Wrong.
>>>
>>>      
>>>
>>Are you saying that this is not true of the current Atmel implementation
>>or not true of your plans for the HAA? I was describing the current
>>interfaces and implementations. It is true for those.
>>
>>If you don't want it to be true for the HAL interface, then you had
>>better change the current interface instead of claiming that it is adequate.
>>
>>    
>>
>>>I think there is a general misunderstanding about the HIL.
>>>Don't mix up HIL interface (platform independent) and HIL
>>>implementation (platform dependent). The application will only use the
>>>ADCSingle and ADCMultiple interfaces, therefore it does NOT know about
>>>ADC settings (ref.voltage, sample-hold-time, channel, etc). The
>>>settings are very chip (ADC) specific, it would be very hard (and
>>>inefficient) to allow an application to access them in a platform
>>>independent way. Instead, a wrapper (the HIL component) is provided
>>>for each sensor you actually want to sample. The wrapper will hide the
>>>binding and translation to HAL from the application. The application
>>>wires to the wrapper, e.g. TemperatureC, and only deals with the data.
>>>
>>>This is in fact very close to the ideas of the Sensor interface
>>>(tinyos-1.x/doc/specs/sensors.pdf), maybe the two will merge in future
>>>into one interface.
>>>
>>>
>>>
>>>      
>>>
>>>>While this may be suitable at the HPL interface
>>>>level, it clearly is not at the ADCControl level.
>>>>You note that the HPL interface should give access to the registers. The
>>>>current HPLADC interface does not. For example, there is no way to reset
>>>>the ADC in the middle of a conversion (important when going to sleep, as
>>>>well as a safety net in case of errors); there is no interface to check
>>>>if it is busy; etc. Similarly, there is no way to get around the ADC
>>>>Enable problem other than by writing a replacement for HPLADCC.
>>>>
>>>>
>>>>        
>>>>
>>>The HAA for the ADC for mica has not been committed. And even if, why
>>>don't you just add the commands you need to the HPL then ?
>>>
>>>
>>>      
>>>
>>Because, as TEP-2 says:
>>
>>    
>>
>>>For optimal integration with the rest of the architecture, each /HPL/
>>>component SHOULD have:
>>>
>>>    * commands for initialization, starting, and stopping of the
>>>      hardware module that are necessary for effective power
>>>      management policy
>>>    * "get" and "set" commands for the register(s) that control the
>>>      operation of the hardware
>>>    * separate commands with descriptive names for the most frequently
>>>      used flag-setting/testing operations
>>>    * commands for enabling and disabling of the interrupts generated
>>>      by the hardware module
>>>    * service routines for the interrupts that are generated by the
>>>      hardware module
>>>
>>>      
>>>
>>The current HPLADC interface doesn't come close to meeting this. If it
>>did, then this wouldn't be an issue. (Though I might have to write my
>>own HAL implementation.)
>>
>>    
>>
>>>>In summary, none of the existing Atmel Atmega 128 ADC interfaces are
>>>>well defined, and none of them are really suited as either an HPL or as
>>>>an HAL interface. And even if the interfaces were adequately defined,
>>>>their implementations would have to be changed enough so that much
>>>>existing code would have to be rethought, if not rewritten.
>>>>
>>>>
>>>>        
>>>>
>>>The code you currently have was not written with the HAA in mind, the
>>>HAA is fairly new, but there will be new implementations to adapt it to
>>>HAA. I agree that code is sometimes insufficiently documented, at
>>>least HIL interfaces must and will be well documented though.
>>>
>>>
>>>      
>>>
>>But all the current application code was written with the current
>>implementation in mind. If you change the implementation, all that will
>>have to be rethought and perhaps rewritten. So why bother making saving
>>it a concern?
>>
>>    
>>
>>>>Thus from what I can see, the idea that you want "To maintain
>>>>compatibility with the existing code" makes no sense at all if you are
>>>>serious about "aligning the ADC abstraction with the three-layer
>>>>Hardware Abstraction Architecture (HAA)".
>>>>
>>>>
>>>>        
>>>>
>>><>Why ? On mica ADCC becomes HAL, HPLADCM becomes HPL (with
>>>modifications), on the msp430 it's even simpler.
>>>      
>>>
>>>I think the HAA is a good idea and I'm glad to see it as your goal. ADCs
>>>are idiosyncratic enough that it is going to be very difficult, if not
>>>impossible, to actually integrate every possible, or even every
>>>reasonable ADC hardware and usage mode into such a model.
>>>
>>>
>>>      
>>>
>>>I hope you understand now why we took the HIL/wrapper approach...
>>>
>>>
>>>
>>>      
>>>
>>>>But surely we
>>>>can do much better if we do not tie ourselves to legacy code, and,
>>>>instead, start with what we have learned about how ADC code should be
>>>>written? If that requires throwing out the existing implementations, or
>>>>at least letting them continue running only on TinyOS 1.x rather than
>>>>2.x too, so be it
>>>>
>>>>
>>>>        
>>>>
>>><>It does not.
>>>Jan.
>>>
>>>
>>>
>>>
>>>      
>>>
>>_______________________________________________
>>Tinyos-devel mailing list
>>Tinyos-devel at Millennium.Berkeley.EDU
>>http://mail.Millennium.Berkeley.EDU/mailman/listinfo/tinyos-devel
>>
>>
>>    
>>
>
>  
>



More information about the Tinyos-devel mailing list