page 1
play

Page 1 ARM / GCC Interrupt Inline Assembly void __attribute__ - PDF document

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


  1. 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

  2. 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

  3. 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

  4. 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

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend