2007-09-18 10:53 PM
Problem on Interrupt (VIC0 and VIC1)
2011-05-17 12:33 AM
My program have three routine of response to the interrupt:
1 routine) it is the routine of response to the interrupt TIMER0; programmed like PWM (VIC0). 2 routine) it is the routine of response to the interrupt TIMER3; programmed like cycle interrupt to 1mS (VIC0). 3 routine) it is the routine of response to the interrupt VIC1.10; programmed like interrupt on external entry. (P3.6 -- line 6 from WIU -- VIC1). If I enable the interrupt of the first and of the second routine, all functions regularly. If I enable the third also then, in casual way, it is had that the cpu jumps the address 0 (RESET). It seem the problem in the document: - STR91xF Errata sheet. - STR91xF Rev B and D limitations and correction - 12280.pdf pag.6.like ''Silicon limitations --> VIC interrupt controller wrong vector fetch'' but I have the D revisone already (on the micro appears number 631). There is it a mode for resolve this problem? Best Regards2011-05-17 12:33 AM
Example software that from the problem.
You read the line ''ReportToST.doc'' contained in STError.zip. Where do I be making a mistake? Best Regards2011-05-17 12:33 AM
Do you resolve this problem ?
I've also a reset problem If I use Timer and Uart interrupts. Best regards2011-05-17 12:33 AM
Hi,
the solution is to assign the both DVAR registers to a dummy IRQ hanlers. In case of not using the library IRQ handler (so jumping directly to the ISRs), the VARs should be also written to 0 at the end of the dummy ISRs. Jiri2011-05-17 12:33 AM
Hi Jiri,
that is not clear for me. 1.) I use the STLIB sources in my projects, which includes f.e. the file IRQ.s and all the other STLIB assembly files. 2.) I use also the 91x_it.c file which includes all interupthandlers. 3.) I use the Keil startup file Str91x.s which includes following .... ;// Setup Library Exception Handlers LEH_SETUP EQU 1 .... Vectors LDR PC, Reset_Addr LDR PC, Undef_Addr LDR PC, SWI_Addr LDR PC, PAbt_Addr LDR PC, DAbt_Addr NOP ; Reserved Vector LDR PC, IRQ_Addr ; LDR PC, [PC, #-0x0FF0] LDR PC, FIQ_Addr IF LEH_SETUP <> 0 EXTERN UndefHandler EXTERN SWIHandler EXTERN PAbtHandler EXTERN DAbtHandler EXTERN IRQHandler EXTERN FIQHandler ENDIF Reset_Addr DCD Reset_Handler Undef_Addr DCD UndefHandler SWI_Addr DCD SWIHandler PAbt_Addr DCD PAbtHandler DAbt_Addr DCD DAbtHandler DCD 0 ; Reserved Address IRQ_Addr DCD IRQHandler FIQ_Addr DCD FIQHandler .... Please give an example for using the dummy interrupthandler for my application. Thank you and best regards B.2011-05-17 12:33 AM
Hello,
I use the Timer0 and the UART2 without any of the original STM libraries. The addresses of the ISR are directly programmed into the belonging registers, i.e. VIC1_VA2R = (dword)UART_vIsr; and VIC0_VA5R = (dword)TMR_vIsr; In case of enabling both interrupts with high interrupt cycles (timer0 every 100µs, UART2 Rx with 115200 baud), the system runs only a few seconds until the UART2-ISR will be stopped. Searching the problem, I generated three test signals (toggling external pins) in the Timer0-ISR, the UART2-ISR and the main(). After a few seconds of running the programm, the UART2 toggling stopps. With other words it looks like a UART2 interrupt disable. But the interrupt was definitely NOT disabled by the software. Setting a breakpoint into the so called spuriuos interrupt routine the system halted at this point. As a second step I made two ''spuriuos ISR'', one for VIC0 and one for VIC1, but only the VIC0 spurious ISR will be started. I programmed a dummy write to the belonging register (VIC0_VAR = 0;) and it seams, that the problem would have been fixed. Note: For testing purpose I counted the spurious interrupt events and I found more than 200 spurious ISR during a transfer of more than 500,000 bytes into UART2??? But then I tried to activate the I2C0. The I2C0 channel is located at VIC1. Guess what happens if I enable the I2C0 ISR? Yeah, you are right, the UART2 - ISR will never be reached!!!! That's awful. What in the hell is wrong with the VIC0 and/or VIC1 hardware logic? What does a spurious interrupt do? And why is there no documentation about that behavior available? Questions about question and no answer. Best regards, Jens P.S. Sorry about my harsh comments, but I spent lots of hours to look at a problem other micros don't have.2011-05-17 12:33 AM
Hi,
Spent a week on this issue and I think I have a workable workaround that does work. Tried all the idea's mentioned here but alas they don't work, so here's mine which has been working for more than 24 hours errors and all. We all seem to have the same issue which is that occasionally the VIC0_VAR reports an address of 0x00000000 for what is an interrupt from VIC1 which is documented in the ST documents: - STR91xF Errata sheet. - STR91xF Rev B and D limitations and correction - 12280.pdf pag.6.like ''Silicon limitations --> VIC interrupt controller wrong vector fetch'' I'm running an interrupt off the watchdog timer at a rate of 10mS and hammering characters out via UART0 also under interrupt. All the usual stuff interrupt enables, vector priority is set up as per the manual. I'm using the Raisonance tool set with the GNU compiler. This is my solution. Set a common interrupt handler which is called for all interrupts, i.e set the address at 0x0000018 to ''ldr pc,=KerCpuIrqHandler'' These are my vectors: ldr pc,=ResetHandler ldr pc,=UndefinedHandler ldr pc,=SWIHandler ldr pc,=PrefetchAbortHandler ldr pc,=DataAbortHandler nop ldr pc,=KerCpuIrqHandler ldr pc,=KerCpuFiqHandler Set the VICx_VAiR register to the address of the function to handle the interrupt i.e. VIC0_VA0R to the watchdog function and VIC1_VA0R to the UART0 function Code up the common interrupt handler as shown below: typedef void (*TdVoidFuncPtrVoid)(void); unsigned int irqcounter; void KerCpuIrqHandler(void) { TdVoidFuncPtrVoid ptr0; ptr0 = (TdVoidFuncPtrVoid)VIC0->VAR; if(ptr0) (*ptr0)(); else { ptr0 = (TdVoidFuncPtrVoid)VIC1->VAR; irqcounter++; if(ptr0) (*ptr0)(); } VIC0->VAR = 0; VIC1->VAR = 0; } When the function is called via the jump from the IRQ vector it reads the VIC0_VAR register, if a non zero address is passed back then call the function at that address to service the appropriate interrupt, this would be the VIC0 or VIC1 interrupt (the way it should work). If the returned address is zero then read the value from VIC1_VAR and run the function given by the address passed back as this is the VIC1 interrupt that needs to be serviced and is always returned. I make tha assumption that as an interrupt is being serviced and the returned address from VIC0 is zero and I have interrupts enabled on VIC1 then this interrupt must be from from VIC1. The variable ''irqcounter'' is incremented every time the VIC0_VAR zero address value is returned which with my code is about 5 failures per hour but the interrupt is served correctly. My conclusion is that silicon wise something is going wrong with the daisy chaining of the 2 VIC controllers but the controllers are individually working OK. Hope this solution helps, feedback would be much appreciated Mark2011-05-17 12:33 AM
Hello,
my solution now, together with the STRLIB is using the following: .... void DummyFuncVic0 () { ++Vic0Cnt; } void DummyFuncVic1 () { ++Vic1Cnt; } ... VIC0->DVAR = &DummyFuncVic0; VIC1->DVAR = &DummyFuncVic1; .... Vic0Cnt was incremented multiple times, in 2 hours 100 times or more. Vic1Cnt was never incremented. I use Timer3-, Uart0- and SPI0 interrupts. Best regards B.[ This message was edited by: Barricade on 22-01-2007 19:16 ]2011-05-17 12:33 AM
Hi,
As I wrote, I thought I have fixed the problem. Using two independend spurious ISR with updating the hardware logic at VIC0 and VIC1 looks like the solution I need. But, adding the I2C0 to VIC1 (UART2 was still in use) shows the well known effect (ISR were lost). Looking about the forum entries, I think some of the describted problems looks like basing on the same reason. There must be an error in the VICs! Please have a look on my code fragments and say what is wrong with it: static unsigned spuriousInterruptCount0 = 0; void defaultISR0( void ) __attribute ((interrupt(''IRQ''))); void defaultISR0( void ){ spuriousInterruptCount0++; VIC0_VAR = 0; } static unsigned spuriousInterruptCount1 = 0; void defaultISR1( void ) __attribute ((interrupt(''IRQ''))); void defaultISR1( void ){ spuriousInterruptCount1++; VIC1_VAR = 0; } .... VIC0_DVAR = (unsigned int)defaultISR0; VIC1_DVAR = (unsigned int)defaultISR1; VIC0_VA5R = (unsigned int)TMR_vIsr; VIC1_VA2R = (unsigned int)UART_vIsr; VIC1_VA2R = (unsigned int)I2C_vIsr; As you see I'm not a friend of complex interrupt handlers, like the STM library. I'm also wouldn't agree with some of describted solutions. I fear that the problem in the hardware interrupt handler was only covered not fixed! Best regards, Jens