This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

interrupt.c(36): error: #18: expected a ")"

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

Parents Reply Children
  • 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.

    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.

    Thanks, David

  • 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
    ;
    


    I "suspect" that this may work:

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