Вы находитесь на странице: 1из 30

Microcontrollers, Advanced

Advanced Challenges With Real-Time Systems January 30, 2012 Jack Ganssle

Design for Speed


Keep ISRs Short! Avoid loops Remove all unneeded code Understand the cost of a LOC

8051 usec/M Hz int = int + int int * int / int for long = long + long long * long / long for 36 90 120 462 1344 132 624 540 546 1128 4878 642

186 usec/MHz 12 8 8 20 40 44 64 32 32 1068 3420 44

8051 Min usec/MHz acos asin atan cos sin exp sqrt tan 3690 4950 12300 4944 5406 2844 13800 7878

8051 Max usec/MHz 52632 53550 26214 23748 23616 35046 15990 35820

186 Min usec/MHz 5232 5232 48096 69644 38696 6832 58644 120428

186 Max usec/MHz 5238 5238 102388 82092 79444 189240 59396 179028

8051 Min usec/MHz cos Hart cos 7.3 digits Hart cos 5.2 digits Hart cos 3.2 digits 4944 6660 5586 4548

8051 Max usec/MHz 23748 6744 5670 4632

186 Min usec/MHz 69644 4160 3180 2204

186 Max usec/MHz 82092 4216 3236 2260

Hart 7.3 digit cos(x):


a=.9999999523 - .4999990534 * b**2 + .04166358 - .001385370 * b**4 * b**6 + .000023233 * b**8

Computer Approximations, by John Hart

A Commercial Product
Micro Digitals GoFast: www.smxrtos.com
For NIOS-II processor at 24 MHz, times in microseconds: double precision single precision GoFast GCC GoFast GCC 16.0 120.9 4.0 38.4 32.2 201.5 9.6 59.6 43.5 542.0 10.6 163.6

cos acos pow

Note GoFast is fully reentrant.

Reentrancy Problems
A function is reentrant if: If it uses all shared variables in an atomic way, If it does not call non-reentrant functions If it does not use the hardware in a non-atomic way

Shared Variable Perils


Using statics or globals non-atomically makes the code non-reentrant. void function(int *data) { int count; count=data*2; data=count; }

Shared Variable Perils


Using statics or globals non-atomically makes the code non-reentrant. void function(int *data) { static int count; count=data*2; data=count; }

Shared Variable Perils


Atomic operations may not be atomic. int data; void function() { ++data; }

Shared Variable Perils


mov cx,[bx] add cx,1 mov [bx],cx Atomic alternative: lock inc [bx]

The Danger of DI
long i; void do_something(void) { disable_interrupts(); i+=0x1234; enable_interrupts(); }

NO!
long i; void do_something(void) { int key; key=disable_interrupts(); i+=0x1234; restore_interrupts(key); }

Better

Using a Handshake Flag


while (in_use); //wait till resource free in_use=TRUE; //set resource busy Do non-reentrant stuff in_use=FALSE; //set resource available Bad Code! An interrupt between the first two statements may cause two sections of code to think they both have exclusive access to the shared resource.

TSET Substitute
loop:mov al,0 ; 0 means in use lock xchg al,variable cmp al,0 je loop ; loop if in use

If al=0, we swapped 0 with zero; nothing changed but the code loops since someone else is using the resource. If al=1, we put a 0 into the in use variable, marking the resource as busy. We fall out of the loop, now having control of the resource.

On some ARM processors, use LDREX/STREX

Calling non-reentrant Routines


Calling a non-reentrant function makes the caller non-reentrant. Be wary of runtime packages, and purchased code.

Non-atomic Hardware Accesses


If you cant manage a hardware resource atomically, then the code is non-reentrant. /* swap peripheral modes*/ peripheral_reg_1=0xaa; peripheral_reg_2=0x55; peripheral_reg_2=0x22;

Async Hardware/Software
Variable timer_hi High 16 bits ++timer_hi ISR Hardware timer register Low 16 bits Overflow of timer register

Async Hardware/Software
int timer_hi; interrupt timer() { ++timer_hi; } Bad code! See next slide.

long timer_read(void) { unsigned int low, high; low =inword(hardware_register); high=timer_hi; return (((ulong)high<<16) + (ulong)low); }

Async Hardware/Software
long timer_read(void) { unsigned int low, high; (hardware_register=ffff, timer_hi=0000) low =inword(hardware_register); (overflow; low=ffff, timer_hi=0001) high=timer_hi; return (((ulong)high<<16) + (ulong)low); (returns 0001ffff) } Bad code! As you can see, an interrupt may corrupt the result.

long timer_read(void) { unsigned int low, high; push_interrupt_state; disable_interrupts; low=inword(hardware_register); high=timer_hi; if(timer_overflow) {++high; low=inword(hardware_register);} pop_interrupt_state; return (((ulong)high)<<16 + (ulong)low); }

Input Capture Register


Bits 16-31 32 bit counter Register To CPU Bits 0-15

clock

Data hold Metastable design! Will surely fail

Speed Kills

Required reading: High Speed Digital Design (a Handbook of Black Magic) by Howard Johnson and Martin Graham (1993 PTR Prentice Hall, NJ)

Speed is a function of the edges, not clock rate.

Power Spectrum
Tr = signals rise time F = All frequencies higher than F are 40 dBV down in amplitude

If Tr = 20 nsec, F= 25 MHz If Tr = 1 nsec, F= 500 MHz

Bouncing in a 10 Inch wire


TP2 - after 10 of wire TP1 - driving signal

Now Terminated
TP4 TP3

The Tek TPP1000 Probe

ALE

Common Impedance Problems

Edge sensitive interrupts (e.g., NMI) All signals going off-board Clock - particular problem as it goes all over the typical board. Few CPUs accept TTL clock signals; many wont tolerate anything less than a perfect clock.

Resources
An Embedded Software Primer by David E. Simon 1999, Addison Wesley Longman ISBN 0-201-61569-X MicroC/OS-II by Jean J. LaBrosse 1999, Miller Freeman ISBN 0-87930-543-6
http://embedded.com/design/205203908 - Great multicore article MicroC/OS-III by Jean J. LaBrosse - MicroC/OS-III

http://www.ecoscentric.com - ecos

Questions?

Вам также может понравиться