page 1
play

Page 1 Compiler Requirements Want To Tell the Compiler Be - PDF document

Something Cool Lab Lab 1 due next Tues Seemed to go pretty well on Tues? RFID is an exciting Questions? and growing technology This reader from Parallax is $40 and has a serial interface Quiz Results Last Time


  1. Something Cool Lab � Lab 1 due next Tues Seemed to go pretty well on Tues? � RFID is an exciting � � Questions? and growing technology � This reader from Parallax is $40 and has a serial interface Quiz Results Last Time Low-level parts of the toolchain for � Problem 1: About 50% of class got it totally � embedded systems right � Linkers Problem 2: � � Programmers � Most everyone got the first 4 parts correct � Booting an embedded CPU � Remaining 3 parts were about 60% � Debuggers Problem 3: 40% � JTAG � Any weak link in the toolchain will hinder � � Problem 4: 50% development Problem 5: 90% was close, about 20% was � totally correct Today: Intro to Embedded C Embedded Compilers We are not learning C Today: � � � General capabilities � We are leaning “advanced embedded C” � Specific issues part 1 � Issues that frequently come up when developing embedded software � Seldom care about these when writing general- � First: Almost all compilers for embedded purpose apps systems are cross-compilers � Compiler runs on an architecture other than its target � Does this matter at all? Page 1

  2. Compiler Requirements Want To Tell the Compiler… � Be correct � There are only 32 KB of RAM � Embedded compilers are notoriously buggy � Program must fit, but there’s no point reducing � Relatively few copies sold RAM consumption further � Diverse hardware impedes thorough testing There are only 256 KB of ROM � Produce small, fast code � � Again: Program must fit but there’s no point � Speed and size are conflicting goals reducing ROM consumption further � Oops! Interrupt handler 7 is time critical � � Take advantage of platform-specific features � So make it very fast, even if this bloats code Produce code that’s easy to debug � Threads 8-13 are background threads � � Conflicts with optimization � Performance is unimportant so focus on � Whole-program optimization particularly reducing code size problematic What We Get To Tell It Nice Example A few compiler flags: � I have a 1982 book on 6502 assembly � � -O2, -Os, Etc. programming: � May or may not do what you want � strcmp(): compare two strings � Typically no flags for controlling RAM usage � Registers used: all Therefore… � � Execution time: 93 + 19 * length of shorter string � Meeting resource constraints is 100% your problem � Code size: 52 bytes � Shouldn’t assume compiler did the right thing � Data size: � Shouldn’t assume code you reuse does the right � 4 bytes on page 0 thing � 4 bytes to hold the string pointers � Including the C library Try to find this information for current C � � Figure out which resources matter and focus on libraries! dealing with them � Changing or upgrading compiler mid-project is usually very bad Why use C? Why not use C? Hard to write portable code � � “Mid-level” language � For example “int” does not have a fixed size � Some high-level features Hard to write correct code � � Good low-level control � Very hard to tell when your code does something � Static types bad � Type system is easily subverted � E.g. out-of-bounds array reference C is popular and well-understood � This is Microsoft’s major problem… � � Plenty of good developers exist � Language standard is weak in some areas � Plenty of good compilers exist � Means there is plenty of diversity in implementations � Plenty of good books and web pages exist Linking model is unsafe � � In many cases there’s no obviously superior language Preprocessor is poorly designed � Page 2

  3. CPP – the C Preprocessor Some Interesting Macros #define PLUS_ONE(x) x+1 � CPP runs as a separate pass before the int a = PLUS_ONE(y)*3 compiler Basic usage: � #define TIMES_TWO(x) (x*2) � #define FOO 32 int a = TIMES_TWO(1+1) � int y = FOO; Compiler sees: � � int y = 32; #define MAX(x,y) ((x)>(y)?(x):(y)) CPP operates by lexical substitution � void f () { int m = MAX(a++,b); } Important: The compiler never sees FOO � � So of course the debugger, linker, etc. do not #define INT_POINTER int * know about it either INT_POINTER x, y; Macro Problems Root of the problem: Old conventional wisdom: � � � C preprocessor is highly error-prone � Careful use of CPP is good � Avoid it except to do very simple things � Fully parenthesize macro definitions � New conventional wisdom: � Make macro usage conventions clear � Most uses of CPP can be avoided � Trust the optimizer Entertaining macros: � #define DISABLE_INTS asm volatile (“cli”); { #define ENABLE_INTS asm volatile (“sei”); } � Is this good or bad macro usage? Macro Avoidance More Macro Avoidance Constants Conditional compilation � � � Instead of � Instead of � #define X 10 � #if FOO … #endif � Use � Use � const int X = 10; � if (FOO) { … } � Instead of � #ifdef X86 … #endif Functions � � Put x86 code into a separate file � Instead of � #define INC_X x++ � However: Design of C makes it impossible � Use to avoid macros entirely � inline void INC_X(void) { x++ } � C++ much better in this respect Page 3

  4. Bit Manipulation CPP in Action without Macros � Sometimes you need to look at the CPP output Something like this is good: � � That is, see what the C compiler really sees � There’s always a way to do this void set_bit (int *a, int bit) { � In CodeWarrior, do this using the IDE *a |= (1<<bit); � For gcc: “gcc –E foo.c” } void clear_bit (int *a, int bit) { *a &= ~(1<<bit); } Intrinsics Integer Division Intrinsics On ARM7 � “Intrinsic” functions are built in to the � sdiv: compiler str lr, [sp, #-4]! � As opposed to living in a library somewhere bl __divsi3 Why do compilers support intrinsics? � int sdiv (int x, int y) ldr pc, [sp], #4 � Efficiency – can perform interesting optimizations { � Ease of use return x/y; � Compiler can add function calls where they On AVR � } do not exist in your code sdiv: � Compiler can eliminate “library calls” in your rcall __divmodhi4 code mov r25,r23 Need to be careful when compiler inserts � function calls for you! mov r24,r22 ret Copy Intrinsic More Copy � On ARM7 struct foo { int x, y[3]; double z; struct_copy2: }; str lr, [sp, #-4]! ColdFire code: void struct_copy2 (struct foo *a, mov lr, r1 struct foo *b) struct_copy2: mov ip, r0 link a6,#0 { ldmia lr!, {r0, r1, r2, r3} moveq #6,d1 *a = *b; move.w (a1),(a0) } stmia ip!, {r0, r1, r2, r3} move.w 2(a1),2(a0) ldmia lr, {r0, r1} addq.l #4,a1 addq.l #4,a0 stmia ip, {r0, r1} subq.l #1,d1 ldr pc, [sp], #4 bne.s *-14 unlk a6 rts Page 4

  5. Copy on x86-64 String Length int len_hello1 (void) � From Intel CC (but copying a larger struct): { return strlen ("hello"); } struct_copy: pushq %rsi � ColdFire code: movl $4000, %edx call _intel_fast_memcpy len_hello1: popq %rcx 0x00000000 link a6,#0 ret 0x00000004 lea _@71,a0 0x0000000A jsr _strlen 0x00000010 unlk a6 0x00000012 rts Another String Length So What? ARM7 Compiler can add function calls where you � � didn’t have one Compiler can take out function calls that � len_hello1: you put in mov r0, #5 bx lr How will you understand the resource � usage of the resulting code? � What resources are we even talking about? ARM / GCC Interrupt 30-Second Interrupt Review Interrupts are a kind of asynchronous void __attribute__ ((interrupt("IRQ"))) � exception tc0_cmp (void); � When some external condition becomes { true, CPU jumps to the interrupt vector timeval++; When an interrupt returns, previously � VICVectAddr = 0; executing code resumes as if nothing happened } � Unless the interrupt handler is buggy � Also, the state of memory and/or devices has � All embedded compilers provide similar probably changed extensions With appropriate compiler support � C language has no support for interrupts � interrupts look just like regular functions � Don’t be fooled – there are major differences between interrupts and functions Page 5

Recommend


More recommend