Dear People,
I am interested to use the Nested Interrupt in Software in a simple way shown in Examples, but in current RealView Tools it is not possible to access the Registers SP, LR, PSR via Inline Assembly with Assembler Macros. Macros for GCC and legacy Keil Tools:
// Macros for Interrupt Nesting #define IENABLE __asm { MRS LR, SPSR } __asm { STMFD SP!, {LR} } __asm { MSR CPSR_c, #0x1F } __asm { STMFD SP!, {LR} }
#define IDISABLE __asm { LDMFD SP!, {LR} } __asm { MSR CPSR_c, #0x92 } __asm { LDMFD SP!, {LR} } __asm { MSR SPSR_cxsf, LR }
Instead of the Macros, Mr. Dietmar Wengler developed the following Assembler Functions for Embedded Assembler:
nested_irq_enable: STMFD SP!, {R0} MOV R0, LR MRS LR, SPSR STMFD SP!, {LR} MSR CPSR_c, #0x1F STMFD SP!, {LR} BX R0
nested_irq_disable: MOV R0, LR LDMFD SP!, {LR} MSR CPSR_c, #0x92 LDMFD SP!, {LR} MSR SPSR_cxsf, LR MOV LR, R0 LDMFD SP!, {R0} BX LR
could you tell me how can i the call the nested_irq_enable and the nested_irq_disable in the c-Code. I use the Realview Compiler.
Thanks.
you can put them in a separate function:
void __asm disable(foo) { STMFD SP!, {R0} MOV R0, LR MRS LR, SPSR STMFD SP!, {LR} MSR CPSR_c, #0x1F STMFD SP!, {LR} BX R0
which you can call from C code (maybe it is not a bad idea to make this a SWI function).
Hello Micheal,
i get even so the error: #7: unrecognized token
Thanks
So use a token that is recognised, then!!
Replace the "foo" above with "void". Sorry...
I get 2x unrecognized token. the unrecognized tokens in that case are in place: STMFD SP!, {R0} and MOV R0, LR
Hello Michael, i made the function as SWI function:
void __swi(0) __asm nestedIrqEnable(void);
void __SWI_0 (void){
STMFD SP!, {R0}
MOV R0, LR
MRS LR, SPSR
STMFD SP!, {LR}
MSR CPSR_c, #0x1F
BX R0
} ===================================================== But i get the errors: Intrp.c(21): error: #20: identifier "STMFD" is undefined Intrp.c(21): error: #65: expected a ";" Intrp.c(25): error: #10: "#" not expected here Intrp.c(28): warning: #12-D: parsing restarts here after previous syntax error
try this syntax:
void __asm __swi(0) disable_interrupts(void) ; void __asm __SWI_0 (void)
could you tell me Michael what the advantage of SWI in that case
A SWI function blocks all IRQ sources as long as it is executed (and a little bit more), but not against FIQ source(s). You don't have to do it, if you guarantee that 1. The context of the processor is always restored correctly after an IRQ. 2. your code does not tamper with R13. 3. your code does not have an explicit/implicit dependency of IRQ sources. 4. there are probably additional reasons...
Hello Michael,
the 1. variant with separate function worked wonderful.
======================================================= 1. Variant:
void __asm nestedIrqEnable(void){
BX R0 }
void __asm nestedIrqDisable(void){
LDMFD SP!, {LR}
MSR CPSR_c, #0x92
MSR SPSR_cxsf, LR
MOV LR, R0
LDMFD SP!, {R0}
BX LR }
the 2. Variant with SWI-function: 2. Variant: by this variant the variable intrp_count in the eint1_srv() interrupt subroutine is not inceremented.
====================================================
void __asm __swi(0) nestedIrqEnable(void);
void __asm __SWI_0(void) { //Nested Interrupts Entry: STMFD SP!, {R0}
void __asm __swi(1) nestedIrqDisable(void); void __asm __SWI_1 (void) {//Nested Interrupts Exit: MOV R0, LR
/* Create a long time delay */
void delay (void) {
int i;
for (i = 0; i < 0x50000; i++) {
;
}
void eint1_srv (void) __irq {
EXTINT = 2; // Clear EINT1 interrupt flag
nestedIrqEnable(); // allow nested interrupts
delay (); // wait a long time
++intrp_count; // increment interrupt count
nestedIrqDisable(); // disable interrupt nesting
VICVectAddr = 0; // Acknowledge Interrupt
} ======================================================
I tested previously the SWI-Mode in the same Project with the folowing code in conjunction with the below SWI.s file: int __swi(0) swi_sum(int x, int y); int __SWI_0 (int x, int y){
return (x+y);
int __swi(1) swi_mul (int x, int y); int __SWI_1 (int x, int y){
return (x*y);
} =================== SWI.S: T_Bit EQU 0x20
PRESERVE8 ;8-Byte aligned Stack
AREA SWI_Area, CODE, READONLY
ARM
EXPORT SWI_Handler
SWI_Handler
STMFD SP!, {R12, LR} ; Store R12, LR
MRS R12, SPSR ; Get SPSR
STMFD SP!, {R8, R12} ; Store R8, SPSR
TST R12, #T_Bit ; Check Thumb Bit LDRNEH R12, [LR,#-2] ; Thumb: Load Halfword
BICNE R12, R12, #0xFF00
; Extract SWI Number LDREQ R12, [LR,#-4] ; ARM: Load Word BICEQ R12, R12, #0xFF000000
; Extract SWI Number
LDR R8, SWI_Count
CMP R12, R8
BHS SWI_Dead ; Overflow ADR R8, SWI_Table
LDR R12, [R8,R12,LSL #2] ; Load SWI Function Address MOV LR, PC ; Return Address
BX R12 ; Call SWI Function
LDMFD SP!, {R8, R12} ; Load R8, SPSR
MSR SPSR_cxsf, R12 ; Set SPSR
LDMFD SP!, {R12, PC}^ ; Restore R12 and Return
SWI_Dead B SWI_Dead ; None Existing SWI
SWI_Cnt EQU (SWI_End-SWI_Table)/4
SWI_Count DCD SWI_Cnt
IMPORT __SWI_0
IMPORT __SWI_1
SWI_Table DCD __SWI_0 ; SWI 0 Function Entry DCD __SWI_1 ; SWI 1 Function Entry
; ... SWI_End
END ==================================================== The code for the swi_sum and swi_mul functioned.
Thank you for your Help.
I cannot read this. please re-post using the proper tags.
Hello Michael here is the reposted question,
1. Variant:
void __asm nestedIrqEnable(void){ STMFD SP!, {R0} MOV R0, LR MRS LR, SPSR STMFD SP!, {LR} MSR CPSR_c, #0x1F STMFD SP!, {LR} BX R0 } void __asm nestedIrqDisable(void){ MOV R0, LR LDMFD SP!, {LR} MSR CPSR_c, #0x92 LDMFD SP!, {LR} MSR SPSR_cxsf, LR MOV LR, R0 LDMFD SP!, {R0} BX LR }
By the 2. Variant with SWI-function the variable intrp_count in the eint1_srv() interrupt subroutine is not inceremented.
2. Variant:
void __asm __swi(0) nestedIrqEnable(void); void __asm __SWI_0(void) { //Nested Interrupts Entry: STMFD SP!, {R0} MOV R0, LR MRS LR, SPSR STMFD SP!, {LR} MSR CPSR_c, #0x1F STMFD SP!, {LR} BX R0 } void __asm __swi(1) nestedIrqDisable(void); void __asm __SWI_1 (void) {//Nested Interrupts Exit: MOV R0, LR LDMFD SP!, {LR} MSR CPSR_c, #0x92 LDMFD SP!, {LR} MSR SPSR_cxsf, LR MOV LR, R0 LDMFD SP!, {R0} BX LR } /* Create a long time delay */ void delay (void) { int i; for (i = 0; i < 0x50000; i++) { ; } } void eint1_srv (void) __irq { EXTINT = 2; // Clear EINT1 interrupt flag nestedIrqEnable(); // allow nested interrupts delay (); // wait a long time ++intrp_count; // increment interrupt count nestedIrqDisable(); // disable interrupt nesting VICVectAddr = 0; // Acknowledge Interrupt }
I tested previously the SWI-Mode in the same Project with the folowing code in conjunction with the below SWI.s file
nt __swi(0) swi_sum(int x, int y); int __SWI_0 (int x, int y){ return (x+y); } int __swi(1) swi_mul (int x, int y); int __SWI_1 (int x, int y){ return (x*y); }
SWI.S-File:
T_Bit EQU 0x20 PRESERVE8 ;8-Byte aligned Stack AREA SWI_Area, CODE, READONLY ARM EXPORT SWI_Handler SWI_Handler STMFD SP!, {R12, LR} ; Store R12, LR MRS R12, SPSR ; Get SPSR STMFD SP!, {R8, R12} ; Store R8, SPSR TST R12, #T_Bit ; Check Thumb Bit LDRNEH R12, [LR,#-2] ; Thumb: Load Halfword BICNE R12, R12, #0xFF00 ; Extract SWI Number LDREQ R12, [LR,#-4] ; ARM: Load Word BICEQ R12, R12, #0xFF000000 ; Extract SWI Number LDR R8, SWI_Count CMP R12, R8 BHS SWI_Dead ; Overflow ADR R8, SWI_Table LDR R12, [R8,R12,LSL #2] ; Load SWI Function Address MOV LR, PC ; Return Address BX R12 ; Call SWI Function LDMFD SP!, {R8, R12} ; Load R8, SPSR MSR SPSR_cxsf, R12 ; Set SPSR LDMFD SP!, {R12, PC}^ ; Restore R12 and Return SWI_Dead B SWI_Dead ; None Existing SWI SWI_Cnt EQU (SWI_End-SWI_Table)/4 SWI_Count DCD SWI_Cnt IMPORT __SWI_0 IMPORT __SWI_1 SWI_Table DCD __SWI_0 ; SWI 0 Function Entry DCD __SWI_1 ; SWI 1 Function Entry ; ... SWI_End END
The code for the swi_sum and swi_mul functioned.
Thank you for your Help