We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Line 36 is the last line of the asm block below:
asm ( "@ MOV R0, %0\n" "@ MOV R1, %1\n" "@ MOV R2, %2\n" "swi 3\n" : : "r" (irq), "r" (isr), "r" (pri) );
I think the code was written for GCC not ARM C. How should this be written correctly using Keil compiler please
Thanks, David
Are you using Arm Compiler 5 (armcc) or Arm Compiler 6 (armclang)? The inline assembly formats are quite different, armclang generally supports the gcc format.For armcc, see:https://developer.arm.com/documentation/dui0472/m/Using-the-Inline-and-Embedded-Assemblers-of-the-ARM-Compiler
For armclang, see:https://developer.arm.com/documentation/100748/0620/Using-Assembly-and-Intrinsics-in-C-or-C---Code/Writing-inline-assembly-code
Regards, Ronan
This is for an LPC2388 so I must (I think) be using armcc. I wasn't aware of that distinction as I am new to coding for ARM and the Keil tooling.
I can (at a later date) read the manuals in some detail, but right now if you could let me know how to "fix that" I'd be grateful.
I looked at the referenced docs and am no further forward. Please will someone provide me with the correct syntax or a link to a page that will show me.
Hello David,
It is difficult to answer this without the full context - inline assembler code depends on the C code around it.
The following builds for me with armcc:
int foo(){ int r0, r1, r2; __asm{ MOV r0, 0 MOV r1, 1 MOV r2, 2 SWI 3 } return (r0+r1+r2); }
Yes I understand:
/* Register an ISR */ void RegisterIrq ( int irq, void(*isr)(void), int pri ) { asm ( "@ MOV R0, %0\n" "@ MOV R1, %1\n" "@ MOV R2, %2\n" "swi 3\n" : : "r" (irq), "r" (isr), "r" (pri) ); }
I don't believe it's adding r0-R2 they get passed into the SWI invocation:
EXPORT SWI_Handler PRESERVE8 SWI_Handler MRS IP, SPSR TST IP, #B_Thumb ; Check caller's state, ARM or Thumb LDRNEH IP, [LR, #-2] ; Get swi instruction code (in Thumb state) LDREQ IP, [LR, #-4] ; Get swi instruction code (in ARM state) AND IP, #0xFF ; Get swi comment field (lower 8 bit) CMP IP, #7 ; Check range LDRLO PC, [PC, IP, LSL #2] ; Jump to each service function when code is valid MOVS PC, LR ; Otherwise return DCD irq_disable ; 0 Disable IRQ DCD irq_enable ; 1 Enable IRQ DCD clear_vect ; 2 Clear ISRs DCD reg_irq ; 3 Register vector address for IRQ DCD sel_fiq ; 4 Select FIQ interrupt DCD load_fiq ; 5 Load FIQ shadow regs from memory DCD store_fiq ; 6 Store FIQ shadow regs to memory ; ; Omitted ; reg_irq ; Register an IRQ CMP R0, #32 ; Range check MOVCSS PC, LR LDR IP, =(LPC_BASE_VIC+VIC_VectAddr0) STR R1, [IP, R0, LSL #2] ; Set VICVectVectAddr<n> LDR IP, =(LPC_BASE_VIC+VIC_VectPriority0) STR R2, [IP, R0, LSL #2] ; Set VICVectPriority<n> MOV R1, #1 MOV R1, R1, LSL R0 LDR IP, =LPC_BASE_VIC LDR R2, [IP, #VIC_IntSelect] ; Clear corresponding bit in the VICIntSelect BIC R2, R1 STR R2, [IP, #VIC_IntSelect] STR R1, [IP, #VIC_IntEnable] ; Enable corresponding interrupt MOVS PC, LR ; ; omitted ;
/* Register an ISR */ void RegisterIrq ( int irq, void(*isr)(void), int pri ) __asm{ SWI 3 } }
This is what was generated:
31: { 32: // asm ( 33: // "@ MOV R0, %0\n" 34: // "@ MOV R1, %1\n" 35: // "@ MOV R2, %2\n" 36: // "swi 3\n" : : "r" (irq), "r" (isr), "r" (pri) 37: // ); 38: __asm{ 0x00002CD4 E92D4070 STMDB R13!,{R4-R6,R14} 0x00002CD8 E1A04000 MOV R4,R0 0x00002CDC E1A05001 MOV R5,R1 0x00002CE0 E1A06002 MOV R6,R2 39: SWI 3 40: } 0x00002CE4 EF000003 SWI 0x00000003 41: } 0x00002CE8 E8BD4070 LDMIA R13!,{R4-R6,R14} 0x00002CEC E12FFF1E BX R14
I deleted interrupt.c and changed interrupt.h to read:
__swi(0) void IrqDisable (void); /* Disable all IRQ */ __swi(1) void IrqEnable (void); /* Enable all IRQ */ __swi(2) void ClearVector (void); /* Unregister all ISRs */ __swi(3) void RegisterIrq (int irq, void(*isr)(void), int pri); /* Register an ISR as IRQ */ __swi(4) void SelectFiq (int irq); /* Switch an interrtupt source as FIQ */ __swi(5) void LoadFiqRegs (long *regs); /* Load shadow regs R8-R12 from memory */ __swi(6) void StoreFiqRegs (long *regs); /* Store shadow regs R8-R12 to memory */
That seems to have a) resolved any issues with asm format and b) simplified the code!!
I added those values so that they would not be optimized away. Inline assembler behaves quite different to the 'real' assembler.