We have a STR9 project that we're porting from IAR to Yagarto. We have interrupts on UART0, RTC, ADC (all via the standard VIC interface). The RTC is driven by a 32Khz external clock. The ADC interrupt is started off in main(), then restarts itself in the ADC IRQ. These interrupts have all been running fine in the IAR implementation. When the gcc build starts up, the RTC starts up, and ticks along merrily. Then, after a couple of seconds, we initiate the first ADC conversion, and the ADC interrupt triggers... once... After that ADC interrupt, no interrupts ever occur again in the system. The RTC, ADC, and UART interrupts all simply fail to occur any further. Main loop is running along happily. The cpsr shows IRQ interrupt is enabled (cpsr = 0x2000001F). I don't understand what could be causing the ADC interrupt to disable all interrupts (without disabling interrupts)... ?? I'm using the same ISR to handle all the VIC interrupts (via IRQ interrupt), so if I'm exiting from the RTC interrupt successfully, the ADC should be fine also. Does anyone have any insights on this odd issue? #************************************************************* My IRQ ISR code: # STR9 firmware method from ST (Ride code) .macro Savecontext $r0,$r4 STMFD sp!,{r0-r4,lr} /* Save The workspace plus the current return*/ /* address lr_ mode into the stack.*/ .endm # STR9 firmware method from ST (Ride code) .macro RestoreContext $r0,$r4 LDMFD sp!,{r0-r4,pc}^ /* Return to the instruction following...*/ /*...the exception interrupt.*/ .endm #************************************************************* My IRQ setup code (from main()) // Initialize the real time clock(RTC) for the timer that works on the external 32.8K crystal RTC_DeInit(); // RTC default configuration : Reset configuration // Configure the VIC VIC_Config(RTC_ITLine, VIC_IRQ, 8); // set up the RTC interrupt priority to 8 VIC_ITCmd(RTC_ITLine, ENABLE); // Enable the VIC // Configure the RTC to generate an interrupt 16Hz RTC_PeriodicIntConfig(RTC_Per_16Hz); RTC_ITConfig(RTC_IT_Per, ENABLE); // Enable the RTC Periodic interrupt //SCU_APBPeriphClockConfig(__ADC, ENABLE); // Enable the clock for the ADC // Configure the GPIO4 as analog input 8 pins GPIO_ANAPinConfig(GPIO_ANAChannelALL, ENABLE); // ADC setup omitted... // Enable the ADC ADC_Cmd(ENABLE); // Configure the ADC ADC_Init(&ADC_InitStructure); // VIC configuration VIC_Config(ADC_ITLine, VIC_IRQ, 15); VIC_ITCmd(ADC_ITLine, ENABLE); // ADC interrupt config ADC_ITConfig(ADC_IT_ECV, ENABLE);
Dan Miller wrote: > We have a STR9 project that we're porting from IAR to Yagarto. We have > interrupts on UART0, RTC, ADC (all via the standard VIC interface). The > RTC is driven by a 32Khz external clock. The ADC interrupt is started > off in main(), then restarts itself in the ADC IRQ. These interrupts > have all been running fine in the IAR implementation. > > When the gcc build starts up, the RTC starts up, and ticks along > merrily. Then, after a couple of seconds, we initiate the first ADC > conversion, and the ADC interrupt triggers... once... > After that ADC interrupt, no interrupts ever occur again in the system. > The RTC, ADC, and UART interrupts all simply fail to occur any further. > Main loop is running along happily. The cpsr shows IRQ interrupt is > enabled (cpsr = 0x2000001F). I don't understand what could be causing > the ADC interrupt to disable all interrupts (without disabling > interrupts)... ?? > > I'm using the same ISR to handle all the VIC interrupts (via IRQ > interrupt), so if I'm exiting from the RTC interrupt successfully, the > ADC should be fine also. > > Does anyone have any insights on this odd issue? > > #************************************************************* > My IRQ ISR code: > > # STR9 firmware method from ST (Ride code) > .macro Savecontext $r0,$r4 > STMFD sp!,{r0-r4,lr} /* Save The workspace plus the current > return*/ > /* address lr_ mode into the stack.*/ > .endm > > # STR9 firmware method from ST (Ride code) > .macro RestoreContext $r0,$r4 > > LDMFD sp!,{r0-r4,pc}^ /* Return to the instruction following...*/ > /*...the exception interrupt.*/ > .endm # oops, left out the actual interrupt handler: /*********************************************************************** ********* * Function Name : IRQHandler * Description : This function is called when IRQ exception is entered. * Input : none * Output : none ************************************************************************ ********/ IRQHandler: SUB lr,lr ,#4 SaveContext r0,r4 LDR r0, = VectorAddress LDR r0, [r0] /* Read the routine address from VIC0 Vector Address register */ BLX r0 /* Branch with link to the IRQ handler. */ RestoreContext r0,r4 > > #************************************************************* > My IRQ setup code (from main()) > > // Initialize the real time clock(RTC) for the timer that works on the > external 32.8K crystal > RTC_DeInit(); // RTC default configuration : Reset configuration > > // Configure the VIC > VIC_Config(RTC_ITLine, VIC_IRQ, 8); // set up the RTC interrupt > priority to 8 > VIC_ITCmd(RTC_ITLine, ENABLE); // Enable the VIC > > // Configure the RTC to generate an interrupt 16Hz > RTC_PeriodicIntConfig(RTC_Per_16Hz); > RTC_ITConfig(RTC_IT_Per, ENABLE); // Enable the RTC Periodic > interrupt > > //SCU_APBPeriphClockConfig(__ADC, ENABLE); // Enable the clock for > the ADC > // Configure the GPIO4 as analog input 8 pins > GPIO_ANAPinConfig(GPIO_ANAChannelALL, ENABLE); > > // ADC setup omitted... > > // Enable the ADC > ADC_Cmd(ENABLE); > > // Configure the ADC > ADC_Init(&ADC_InitStructure); > > // VIC configuration > VIC_Config(ADC_ITLine, VIC_IRQ, 15); > VIC_ITCmd(ADC_ITLine, ENABLE); > > // ADC interrupt config > ADC_ITConfig(ADC_IT_ECV, ENABLE);
What you have not posted is the code to the specific device handlers. I would suggest that sight of all the code that executes when the ADC interrupt occurs might be useful. Interrupt share a separate stack from the normal running code. Is it possible that your ADC interrupt has caused a stack overflow? How much have you allocated? It needs to be sufficient to handle worst-case interrupt nesting. Clifford
Dan Miller wrote: > Dan Miller wrote: >> We have a STR9 project that we're porting from IAR to Yagarto. We have >> interrupts on UART0, RTC, ADC (all via the standard VIC interface). The >> RTC is driven by a 32Khz external clock. The ADC interrupt is started >> off in main(), then restarts itself in the ADC IRQ. These interrupts >> have all been running fine in the IAR implementation. >> >> When the gcc build starts up, the RTC starts up, and ticks along >> merrily. Then, after a couple of seconds, we initiate the first ADC >> conversion, and the ADC interrupt triggers... once... >> After that ADC interrupt, no interrupts ever occur again in the system. >> The RTC, ADC, and UART interrupts all simply fail to occur any further. >> Main loop is running along happily. The cpsr shows IRQ interrupt is >> enabled (cpsr = 0x2000001F). I don't understand what could be causing >> the ADC interrupt to disable all interrupts (without disabling >> interrupts)... ?? >> >> I'm using the same ISR to handle all the VIC interrupts (via IRQ >> interrupt), so if I'm exiting from the RTC interrupt successfully, the >> ADC should be fine also. >> >> Does anyone have any insights on this odd issue? >> >> #************************************************************* All your interrupt code looks wrong, it has code missing to correctly restore interrupts etc. You either have a copy paste issue or have a very old and incorrect version of ride. Attached is my own code that may help. Cheers Spen
Thanks for your comments, Spen!! As it turns out, after I posted the above data, I went back and compared the IAR startup code (which our IAR project used) with the RideV7 code that I was using for reference, and I saw that I was missing alot of code. Just to figure out what was going on, I just went to the ST website this morning, and downloaded um0233.zip, which is the firmware library that ST distributes on their support website. Both the Ride and EWARM/IAR code reflect the code which I posted on friday, which is clearly incomplete. I guess the moral is, when using ST's chips, *don't* use ST's code to make them work. Anyway, the updated Savecontext, Restorecontext, and IRQ_Handler code that I'm using now agrees almost exactly with what you posted. The only difference is that ours uses: BX r0 /* Branch to the IRQ handler. */ while yours uses: MOV pc, r0 /* Branch to the IRQ handler. */ Is there any practical difference between the two?? Otherwise, interrupts now appear to be working reliably, now that I'm finally using complete IRQ code. //******************************************************* Also, regarding your question about the ADC interrupt handler, I actually put a return statement at the first instruction in ADC_IRQHandler, to make sure it didn't have too much overhead; this made no difference in the symptoms that we saw...
Dan, > Anyway, the updated Savecontext, Restorecontext, and IRQ_Handler code > that I'm using now agrees almost exactly with what you posted. The only > difference is that ours uses: > BX r0 /* Branch to the IRQ handler. */ > > while yours uses: > MOV pc, r0 /* Branch to the IRQ handler. */ > > Is there any practical difference between the two?? > a bx is a v5 instruction that is equiv to the following v4 instuctions LDR lr, =ReturnAddress /* Read the return address. */ MOV pc, r0 /* Branch to the IRQ handler. */ It also can switch between arm/thumb mode, so is a better instruction to use. Cheers Spen
Spencer Oliver wrote: > Dan, > > a bx is a v5 instruction that is equiv to the following v4 instuctions > LDR lr, =ReturnAddress /* Read the return address. */ > MOV pc, r0 /* Branch to the IRQ handler. */ > > It also can switch between arm/thumb mode, so is a better instruction to > use. > Whoa!!! Thanks for that clarification, very valuable!! Soo... The fact that we have: LDR lr, =IRQ_ReturnAddress /* ; Read the return address. */ BX r0 /* ; Branch to the IRQ handler. */ is redundant?? 8-{P
Actually i am getting my instructions mixed up - i was thinking of BLX you will still need the following with a BX LDR lr, =IRQ_ReturnAddress /* ; Read the return address. */ BX r0 /* ; Branch to the IRQ handler. */ with a blx you would just require BLX r0 /* ; Branch to the IRQ handler. */ On the original instruction MOV pc, r0 /* Branch to the IRQ handler. */ the compiler will add the switch to thumb if required, so you may save a instruction by using the bx, you will have to check the asm to verify this. I have not tested the above, so double check before using. The only limiting factor with the B* instructions is they can only handle a +-32MB jump - whereas the LDR can jump anywhere in the arm address space. Cheers Spen
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.