[Tinyos-devel] TinyOS on Cortex M3?

Paul Kimelman paul at nikoosha.com
Thu Mar 13 09:32:55 PDT 2008


To do justice to a port, it should be done taking advantage of the many 
specialized capabilities of Cortex-M3. It is important to note that CM3 is very 
much an interrupt-driven processor. The interrupt controller is integrated in, 
and provides 8 levels (minimum) priorities for all ISRs, including all processor 
faults (bus fault (both I and D), invalid instruction, divide-by-0, etc). It 
takes a max 12 cycles from pre-emption to 1st instruction of actual code (the HW 
pushes the scratch registers for you, so this is entry to a normal C function) 
and is designed to have a max of 2 cycles latency, even for load/store multiple 
(but some chips like the STM32 have multiple cycle stalls on memory/peripheals, 
so the worst case single stall must be considered).
It has multiple features to avoid use of interrupt-disable (critical sections).
More importantly, it provides integrated sleep and integrated tasking models. 
The integrated sleep allows for both SLEEP and DEEPSLEEP as builtin concepts to 
the processor (DEEPSLEEP is presumed to take more cycles to awaken in exchange 
for using less power, but it is up to the system design to determine what it 
does). SLEEP/DEEPSLEEP can be activated from use of an instruction (WFI 
normally) or by return from last exception (if selected). Return from last 
exception means that if no task is ready to run, you can skip idling code and 
the HW will just sleep (with faster wakeup on next interrupt). There is a 
built-in timer (SYSTICK) which ensures the OS port works the same on all CM3 
chips. The tasking model is normally supported by PendSV. PendSV is a bit in the 
interrupt controller. It allows an ISR to set that bit so that upon return from 
all active interrupts, the task scheduler will be woken. By making the task 
scheduler (PendSV) the lowest priority interrupt, it then runs only when there 
is something to do. Note that PendSV is reentrant safe and also atomicity safe. 
So, if about to return from PendSV (nothing to do) and an interrupt comes in and 
the ISR sets PendSV again, PendSV ISR will exit and re-enter immediately (even 
faster than 12 cycles, basically jumps back to itself).
Critical sections can be avoided in three ways: BASEPRI, exclusives, bit-band. 
BASEPRI allows masking all interrupts of a specified priority and below (0 is 
highest, so BASEPRI=5 masks 5, 6, and 7). For example, if the top 4 priority 
interrupts (0-3) do not use memory objects, then the critical section on memory 
object manipulation would mask off only the next 4 priorities by writing a 4. To 
make BASEPRI even easier, a register called BASEPRI_MAX is written to - this 
only raises the priority mask and does not lower. So, you do not have to use "if 
(critsect_pri < BASEPRI) BASEPRI = critsect_pri;". Instead, you just set 
BASEPRI_MAX and it will only set if a lower number (you restore by writing the 
saved value to BASEPRI). Additionally, you can avoid use of critical sections 
using Exclusives. This is LDREX and STREX. This makes it possible to read a 
value from memory (byte, half, word, or bit), modify it, and then write it back; 
if another task or an ISR has written it between the load and store, the store 
will not happen and you will be told that via a register. So, you use a 
spin-lock model with no extra test-and-set location. Exclusives can be used for 
FIFOs (e.g. from ISR to tasks or tasks to ISRs) as non-locking and non-blocking 
models, as well as for many other shared resources. Finally the bit-band can be 
used. Bit-band maps 1MB of SRAM and 1MB of peripheral into 32MB of addressable 
bits (each). So, for each word in the SRAM, you have 32 words in the bit-band 
space; these each access 1 bit of the word (you can also access by byte or half, 
but since a 32-bit register model, access by word is convenient). The bit band 
not only allows for memory savings (when you use boolean data), but can be used 
for critical data as well. Writes to the bit-band area are atomic in HW 
(implicit RMW of word cannot be split by an ISR). So, bits can be used for 
population and claim bits as well as requests. For example, ISRs can not only 
set PendSV, but also set tasks-to-wake via bit band. Then, the PendSV handler 
can read by word (or DWORD) to see if any tasks are waiting to be woken (or have 
work to do). To find the 1st task to run, you can use the CLZ instruction; this 
is count-leading-zeros. So, it will return the MSb which is 1. If you need the 
LSb, you use RBIT and then CLZ.

Hope this helps.

Regards, Paul


John Regehr wrote:
> I'm just curious-- has anyone looked into porting TinyOS to Cortex M3 
> chips?  These represent ARM's attempt to woo developers away from 8 and 
> 16 bit MCUs.  Based on a quick look, the STM32 product line from ST has 
> power numbers roughly in the ballpark for a mote-class device.
> 
>   http://www.st.com/mcu/inchtml.php?fdir=pages&fnam=stm32
>   http://www.st.com/mcu/files/mcu/1190813173.pdf
> 
> John Regehr
> _______________________________________________
> Tinyos-devel mailing list
> Tinyos-devel at millennium.berkeley.edu
> https://www.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-devel
> 

-- 
Paul Kimelman                   Personal email
Home: 925.256.4048              Mobile: 510.882.6495



More information about the Tinyos-devel mailing list