Last Time Today � Coding and translation of interrupt handlers � Advanced C � There will be an “advanced interrupts “ lecture later Coding inline assembly � � Compiler intrinsics Also Today 30-Second Interrupt Review Interrupts are a kind of asynchronous � exception Lab 1 due � When some external condition becomes Lab 2 on the web � � true, CPU jumps to the interrupt vector � When an interrupt returns, previously executing code resumes as if nothing happened � Unless the interrupt handler is buggy � Also, the state of memory and/or devices has probably changed � With appropriate compiler support interrupts look just like regular functions � Don’t be fooled – there are major differences between interrupts and functions Example CF Interrupt Assembly for CF Interrupt rtc_handler: � You write: strldsr #0x2700 __declspec(interrupt) link a6,#0 void rtc_handler(void) lea -16(a7),a7 { movem.l d0-d1/a0,4(a7) MCF_GPIO_PORTTC ^= 0xf; movea.l #1074790415,a0 moveq #0,d1 } move.b (a0),d1 After CPP: � moveq #15,d0 __declspec(interrupt) eor.l d0,d1 void rtc_handler(void) move.b d1,(a0) { movem.l 4(a7),d0-d1/a0 unlk a6 (*(vuint8 *)(0x4010000F)) ^= 0xf; addq.l #4,a7 } rte Page 1
ARM / GCC Interrupt Inline Assembly void __attribute__ ((interrupt("IRQ"))) � Two reasons to add assembly into a C tc0_cmp (void); program: { Need to say something that can’t be said in C 1. timeval++; Need higher performance than the C compiler 2. provides VICVectAddr = 0; � In both cases } � Write most of a function in C and then throw in a few instructions of assembly where needed All embedded compilers provide similar � Let the compiler do the grunt work of � respecting the calling convention extensions � When writing asm to increase performance: � C language has no support for interrupts � Be absolutely sure you identified the culprit � First try to write faster C CodeWarrior Inline Asm Inline Assembly Example square: long square (short a) { link a6,#0 long result=0; subq.l #8,a7 asm { move.w d0,-8(a6) move.w a,d0 // fetch function argument ‘a’ mulu.w d0,d0 // multiply clr.l -6(a6) move.l d0,result // store in local ‘result’ move.w -8(a6),d0 } mulu.w d0,d0 return result; move.l d0,-6(a6) } move.l -6(a6),d0 Compiler generates glue code integrating the assembler unlk a6 � and C code rts � What if it can’t? GCC Inline Assembly Intrinsics “Intrinsic” functions are built in to the � Format: � compiler � As opposed to living in a library somewhere asm volatile (code : outputs : inputs : clobbers ); Why do compilers support intrinsics? � Code – instructions � � Outputs – maps results of instructions into C � Efficiency – can perform interesting variables optimizations � Inputs – maps C variables to inputs of instructions � Ease of use � Clobbers – tells the compiler to forget the contents � Compiler can add function calls where they of registers that were invalidated by the assembly do not exist in your code code � Compiler can eliminate “library calls” in your code This syntax is much more difficult to use than � Need to be careful when compiler inserts � CodeWarrior’s! function calls for you – performance of resulting code may be bad Page 2
Intrinsic Example 1 More Example 1 int smul (int x, int y) � ARM7 { return x*y; smul: } mul r0, r1, r0 � ColdFire code: bx lr smul: � AVR link a6,#0 muls.l d1,d0 smul: unlk a6 rcall __mulhi3 rts ret Intrinsic Example 2 More Example 2 int sdiv (int x, int y) On ARM7 � { sdiv: return x/y; str lr, [sp, #-4]! } bl __divsi3 ldr pc, [sp], #4 � ColdFire code: � On AVR sdiv: sdiv: rcall __divmodhi4 link a6,#0 mov r25,r23 divs.l d1,d0 mov r24,r22 unlk a6 ret rts Example 3 More Example 3 struct foo { int x, y[3]; double z; }; void struct_copy2 (struct foo *a, On ARM7 � struct foo *b) { *a=*b; } � ColdFire code: struct_copy2: str lr, [sp, #-4]! struct_copy2: mov lr, r1 0x00000000 link a6,#0 0x00000004 moveq #6,d1 mov ip, r0 0x00000006 move.w (a1),(a0) ldmia lr!, {r0, r1, r2, r3} 0x00000008 move.w 2(a1),2(a0) 0x0000000E addq.l #4,a1 stmia ip!, {r0, r1, r2, r3} 0x00000010 addq.l #4,a0 ldmia lr, {r0, r1} 0x00000012 subq.l #1,d1 0x00000014 bne.s *-14 stmia ip, {r0, r1} 0x00000016 unlk a6 ldr pc, [sp], #4 0x00000018 rts Page 3
Example 4 More Example 4 int len_hello1 (void) { � ARM7 return strlen ("hello"); } len_hello1: mov r0, #5 � ColdFire code: bx lr len_hello1: 0x00000000 link a6,#0 0x00000004 lea _@71,a0 0x0000000A jsr _strlen 0x00000010 unlk a6 0x00000012 rts Summary You need to understand what actually � happens on the processor � Interrupts are fundamental to what embedded systems do � We’ll be seeing more about them soon � Inline assembly gives you fine-grain control � Intrinsics hide things from you � Function calls can appear, disappear relative to what you expect from the code � For example all floating point is emulated in software on our ColdFire processors � Need to look at compiler output to see what happened Page 4
Recommend
More recommend