300 likes | 452 Views
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. Hart 7.3 digit cos(x):.
E N D
Microcontrollers, Advanced Advanced Challenges With Real-Time Systems January 30, 2012Jack Ganssle
Design for Speed Keep ISRs Short! Avoid loops Remove all unneeded code Understand the cost of a LOC
Hart 7.3 digit cos(x): a=.9999999523 - .4999990534 * b**2 + .04166358 * b**4 - .001385370 * b**6 + .000023233 * b**8 Computer Approximations, by John Hart
A Commercial Product Micro Digital’s GoFast: www.smxrtos.com For NIOS-II processor at 24 MHz, times in microseconds: double precision single precision GoFast GCC GoFast GCC cos 16.0 120.9 4.0 38.4 acos 32.2 201.5 9.6 59.6 pow 43.5 542.0 10.6 163.6 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) { count=data*2; data=count; } int count;
Shared Variable Perils Using statics or globals non-atomically makes the code non-reentrant. void function(int *data) { count=data*2; data=count; } static int 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: inc [bx] lock
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 can’t 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 Hardware timer register High 16 bits Low 16 bits ++timer_hi Overflow of timer register ISR
Async Hardware/Software int timer_hi; interrupt timer() { ++timer_hi; } long timer_read(void) { unsigned int low, high; low =inword(hardware_register); high=timer_hi; return (((ulong)high<<16) + (ulong)low); } Bad code! See next slide….
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 32 bit counter Register Bits 16-31 To CPU Bits 0-15 Data hold clock 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)
Power Spectrum Tr = signal’s 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
Common Impedance Problems • ALE • 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 won’t 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