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