Hi,
Mocroprocessor: AT91SAM7s128 Toolchain: RealView MDK-ARM Version: 3.20
I have the following ADC code need to be run while interrupts disabled to eliminate 60hz noise. So I put it inside SWI (all interrupts are disabled in SWI).
int __swi(1) GetRawCountsFromExternalADC2DataBuffer(unsigned short * P); int __SWI_1 (unsigned short * P) { unsigned int Index; unsigned int Sum; // Start the ADC StartPWMC(); do // Eliminate first reading { // Check if the ADC ready for the data Sum = CheckADCReady(); }while(Sum == 0); SelectSpiPort(SPI_ADC); GetDataFromSpi(); // Start get 1024 readins for(Index = 0; Index < TOTAL_SAMPLE; Index ++) { do { // Check if the ADC ready for the data Sum = CheckADCReady(); }while(Sum == 0); SelectSpiPort(SPI_ADC); *(P + Index) = (unsigned short)GetDataFromSpi(); } // Stop the ADC StopPWMC(); return(1); }
The problem is that all interrupts (Timer and UART) will be stopped after it runs for random time. I also use the spuriouse interrupt handler to fix the problem, but it is not working.
The following code is used to catch the spurious interrupts.
// STORE SPURIOUS INTERRUPT HANDLER TO AIC_SPU AT91C_BASE_AIC->AIC_SPU = (unsigned long) SpuriousInterruptHandler; static void SpuriousInterruptHandler(void) { // END OF INTERRUPT AT91C_BASE_AIC->AIC_EOICR = 0; }
If I am not using disable/enable interrupts for ADC code (data with 60hz will not right), the code runs without any problem.
Any comments are appreciated!
Here is the SWI handler I am suing. It is from Keil.
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 ;IMPORT __SWI_2 ;IMPORT __SWI_3 SWI_Table DCD __SWI_0 ; SWI 0 Function Entry DCD __SWI_1 ; SWI 1 Function Entry ;DCD __SWI_2 ; SWI 2 Function Entry ;DCD __SWI_3 ; SWI 3 Function Entry ; ... SWI_End END
Xiao
Hi all,
I have the following update:
If I stop the debuger (ULINK 2) after all the interrupts stop, I can see both I and F flags are set to 1 in SPSR. This means all the IRQ and FIQ are disabled.
I know SWI blocks all the interrupts during its operation, why interrupts are not enabled sometime afte SWI is done?
Regards, Xiao
why interrupts are not enabled sometime afte SWI is done?
How sure are you that your SWI actually is done, at that point? Did you check the stack(s) and the program counter at the point you stopped it?
I know the SWI is done because the code goes back to the main loop and waiting for new interrupts. I can step through all the code inside the main loop.
The new interrupt coming in while SWI is disabling interrupt may cause this problem. Is it possible?
By the way, I found following:
- Interrupt stops (no scan activity) - Stop the ULINK - Open "Timer Counter" under "Peripherals" menu - Press start and the code is running again
Openning of "timer counter" window seems re-enable interrupts
Do you have a __swi(0) ?
If you don't have a __swi(0), then change your swi number to 0 first.
And maybe, take a look at the below link, and try the updated SWI Handler provided by Franc Urbanc
http://www.keil.com/forum/docs/thread14826.asp
Yes, I have __swi(0). SWI0 is used to program one page of the flash memory. It works very well. I use it for firmware upgrade and storing calibration constants into flash (flash like EEPROM) without any problems.
The difference between SWI0 and SWI1 is the time spent for the operation.
SWI0 only spents couple of mini seconds to finish. And the SWI1 needs at least 16ms, sometime it can use up to 256 mini seconds if I want high resolution reading.
Another difference is SWI1 is used much much more often than SWI0.
Thanks for the link! I will try the updated SWI handler.
Quick Update:
The updated SWI handler is not working.
It is really frustrating problem.
I use the RTOS when I first started this project and RTOS stops randomly. I was told by some posts on this forum that Keil has a fix for the "RTOS stop" (related to interrupt detection).
I stopped using RTOS and have the same problem again. I think there something wrong in this compiler dealing with the interrupt. Actually RTOS does the pretty much same thing as I do. Both use SWI very offen.