182.694 Microcontroller VU Kyrill Winkler SS 2014 Featuring Today: Structured C Programming 136 Weekly Training Objective ◮ Already done 3.1.1 C demo program 3.1.3 Floating point operations 3.3.2 Interrupts 3.4.3 Generating periodic signals ◮ This week 3.3.1 Interrupt & callback demo 3.4.1 Input capture 3.6.1 UART receiver 3.6.2 UART sender 3.9.1 Keypad ◮ Next week 3.4.4 PWM signals and glitches 3.6.4 TWI (I 2 C) 3.8.2 Button debouncing 3.8.4 LCD 137 Follow-up from last time: My dear compiler int o = y + (z ^ 255); What does (z ^ 255) do? 138
Follow-up from last time: My dear compiler int o = y + (z ^ 255); What does (z ^ 255) do? It depends. 138 Follow-up from last time: My dear compiler int o = y + (z ^ 255); What does (z ^ 255) do? It depends. What data-type does z have? Lets assume it is int , then it has . . . bits! 138 Follow-up from last time: My dear compiler int o = y + (z ^ 255); What does (z ^ 255) do? It depends. What data-type does z have? Lets assume it is int , then it has 16 bits! 138
Follow-up from last time: My dear compiler int o = y + (z ^ 255); What does (z ^ 255) do? It depends. What data-type does z have? Lets assume it is int , then it has 16 bits! So the snipplet negates the lower 8 bits of z . 138 Follow-up from last time: My dear compiler int o = y + (z ^ 255); What does (z ^ 255) do? It depends. What data-type does z have? Lets assume it is int , then it has 16 bits! So the snipplet negates the lower 8 bits of z . The size of int is varies across toolchains/architectures! Therefore be explicit and use uint8 t or uint16 t etc.! 138 While on the topic of variable declarations. . . bool timeout = f a l s e ; ISR (MY TIMER INTERRUPT , ISR NOBLOCK) { timeout = t r u e ; } i n t main ( void ) { ( timeout == t r u e ) { i f t u r n o n l e d s ( ) ; } } 139
While on the topic of variable declarations. . . bool timeout = f a l s e ; ISR (MY TIMER INTERRUPT , ISR NOBLOCK) { timeout = t r u e ; } i n t main ( void ) { i f ( timeout == t r u e ) { t u r n o n l e d s ( ) ; } } On some versions of the toolchain the if-statement will be interpreted as always false! 139 The volatile keyword bool v o l a t i l e timeout = f a l s e ; ISR (MY TIMER INTERRUPT , ISR NOBLOCK) { timeout = t r u e ; } i n t main ( void ) { i f ( timeout == t r u e ) { t u r n o n l e d s ( ) ; } } volatile prevents the compiler from optimizing timeout , in particular it won’t assume that timeout is never changed. 140 The const keyword ◮ const is used to declare variables that are written to only once (more on that later) 141
The const keyword ◮ const is used to declare variables that are written to only once (more on that later) ◮ C allows using pointers as output parameters 141 The const keyword ◮ const is used to declare variables that are written to only once (more on that later) ◮ C allows using pointers as output parameters ◮ You should declare whether this is your intention or not: myfunc(uint8 t *str) myfunc(const uint8 t *str) . 141 Side effects ◮ Avoid side effects! Never use printf("%i", i++) etc. 142
Side effects ◮ Avoid side effects! Never use printf("%i", i++) etc. ◮ Be aware of short-circuit evaluation: if (a != 0 && myfunc(b) != 0) 142 Side effects ◮ Avoid side effects! Never use printf("%i", i++) etc. ◮ Be aware of short-circuit evaluation: if (a != 0 && myfunc(b) != 0) ◮ Depending on value of a , myfunc(b) may or may not be called! 142 Structured C Programming 2 important pradigms: ◮ background (BG) tasks vs. interrupt service routines (ISRs) ◮ callback functions 143
Structured C Programming 2 important pradigms: ◮ background (BG) tasks vs. interrupt service routines (ISRs) ◮ callback functions Helpful extensions (“ -std=c99 ”) ◮ <util/atomic.h> ◮ <stdbool.h> ◮ useful macros for interrupts, eeprom, sleepmode, crc, baudrate , watchdog, . . . ◮ detailed documentation: avr-libc manual 143 Backgrounding Basic structure of a C-program: i n t main ( void ) { i n i t ( ) ; // c a l l s i n i t i a l i z t i o n s of used modules ( ; ; ) { for background ( ) ; // c a l l s background t a s k s s l e e p ( ) ; } } Every interrupt executes the background code once. 144 Backgrounding Basic structure of a background task: void background ( void ) { i f ( mystate == i n i t ) { b g t a s k p l a y I n t r o M u s i c ( ) ; bgtask showIntroAnimation ( ) ; } e l s e i f ( mystate == goal ) { . . . } } 145
Backgrounding Basic structure of a background task: void background ( void ) { ( mystate == i n i t ) { i f b g t a s k p l a y I n t r o M u s i c ( ) ; bgtask showIntroAnimation ( ) ; } ( mystate == goal ) { e l s e i f . . . } } Beware of monopolizing background tasks! Animation will be played after bgtask playIntroMusic returned. 145 Backgrounding Implementing a basic scheduler: void background ( void ) { while ( t h e r e i s s o m e t h i n g t o d o ( ) ) { i f ( mystate==i n i t ) { i f ( ! done music ) done music=b g t a s k p l a y I n t r o M u s i c ( ) ; i f ( ! done anim ) done anim=bgtask showIntroAnimation ( ) ; } e l s e i f ( mystate==goal ) { . . . } } } 146 Callback functions 147
Callback functions 1 void ( ∗ myCallbackFunction )( u i n t 8 t ) ; // g l o b a l f u n c t i o n p o i n t e r v a r i a b l e 2 3 ISR (MY TIMER INTERRUPT , ISR NOBLOCK) { 4 / ∗ execute the c a l l b a c k f u n c t i o n ∗ / 5 myCallbackFunction ( 1 ) ; 6 } 7 void s e t c a l l b a c k ( void ( ∗ c a l l b a c k )( u i n t 8 t )) { 8 myCallbackFunction = c a l l b a c k ; 9 } 10 void myfunc ( u i n t 8 t i ) { 11 . . . 12 } 13 14 i n t main ( void ) { 15 s e t c a l l b a c k ( myfunc ) ; // r e g i s t e r myfunc as c a l l b a c k f u n c t i o n 16 } 147 ATMega1280’s memories ◮ 128 KB program memory (flash) ◮ Biggest memory in ATMega1280 ◮ Great for storing constants ◮ 8 KB internal RAM ◮ RAM size is quite restricted ◮ Beware of stack overflow ◮ 4 KB EEPROM ◮ Useful for storing values that rarely change ◮ Limited number of read/write cycles 148 Using ATMega1280’s memories in C ◮ Memory sections available: ◮ .text : program memory, flash ◮ .data : RAM and flash ◮ .bss : RAM ◮ .eeprom ◮ The .data memory section contains constants and variable initializations; it occupies both RAM and flash space. ◮ RAM is volatile and therfore not programmable (before run-time). ◮ Therefore: put constant values into flash alone! ◮ No need to occupy twice the required memory! ◮ How? See Section 5 of the avr-libc manual. 149
The .initN sections (section 4.6 avr-libc) .init0 Weakly bound to init(). If user defines init(), it will be jumped into immediately after a reset. .init1 Unused. User definable. .init2 In C programs, weakly bound to initialize the stack, and to clear zero reg (r1). .init3 Unused. User definable. .init4 For devices with > 64 KB of ROM, .init4 defines the code which takes care of copying the contents of .data from the flash to SRAM. For all other devices, this code as well as the code to zero out the .bss section is loaded from libgcc.a. .init5 Unused. User definable. .init6 Unused for C programs, but used for constructors in C++ programs. .init7 Unused. User definable. .init8 Unused. User definable. .init9 Jumps into main(). 150 Using .initN sections Applying attributes to functions void m y i n i t p o r t b ( void ) a t t r i b u t e (( naked , used , s e c t i o n ( ” . i n i t 3 ” ) ) ) ; void m y i n i t p o r t b ( void ) { PORTB = 0 x f f ; DDRB = 0 x f f ; } 151 Benchmarking memory usage ◮ After compilation, the static memory usage of your program can be analyzed via avr-size . ◮ Analyzing the dynamic memory usage can be done by (1) Code analysis (requires bounding recursion depth and heap usage). (2) Run-time analysis directly on the µc or via simulation (needs a software that monitors memory access). 152
Dynamic memory benchmark example void memstatInit ( void ) a t t r i b u t e (( naked , used , s e c t i o n ( ” . i n i t 3 ” ) ) ) ; extern u i n t 8 t end ; // end of bss // never c a l l t h i s f u n c t i o n ! void memstatInit () { r e g i s t e r u i n t 1 6 t i ; f o r ( i =( u i n t 1 6 t )& end ; i < RAMEND; i ++) { ∗ ( u i n t 8 t ∗ ) i = ( u i n t 8 t ) i ; } } 153 Dynamic memory benchmark example 1 mem stat t ∗ memstatGetStat ( void ) { 2 s t a t i c mem stat t s t a t ; 3 u i n t 1 6 t i ; 4 u i n t 8 t u n i n i t ; 5 6 s t a t . maxStackSize = 0 x f f f f ; 7 s t a t . maxHeapSize = 0 x f f f f ; 8 // s e a r c h end of stack , s t a r t at SP and go down 9 . . . 10 // s e a r c h end of heap , s t a r t at bss end and go up 11 u n i n i t = 0; 12 f o r ( i =( u i n t 1 6 t )& end ; i < RAMEND; i ++) { 13 i f ( ∗ ( u i n t 8 t ∗ ) i == ( u i n t 8 t ) i ) { 14 u n i n i t ++; 15 ( u n i n i t == 10) { i f 16 s t a t . maxHeapSize = i − ( u i n t 1 6 t )& end − 9; 17 break ; 18 } 19 } e l s e { u n i n i t = 0; } 20 } 21 return &s t a t ; 22 } 154 Linker scripts ◮ (in the lab) located at /usr/avr/lib/ldscripts/ ◮ Mapping of virtual memory adresses for the ELF-file ◮ Very powerful! 155
Recommend
More recommend