Hello all, I’m currently setting up my AT91SAM7S256 (Olimex EvalBoard, Yagarto Toolchain) and try to implement interrupts in RAM-code, however I don’t succeed. I have checked all available sample code (from various forums, from Martin Thomas, etc.) and – at least to me – the code looks OK, but still no satisfying result.. My project is based on Jim Lynch’s tutorial, I use (without modification) blinker.c, crt.s, isrsupport.c, lowlevelinit.c, script.ocd, makefile, demo_at91sam7_blink_ram.cmd, and all h- and a-files. Main.c looks like this: // ******************************************************* #include "AT91SAM7S256.h" #include "board.h" #include "math.h" #include "stdlib.h" #include "string.h" // External References extern void LowLevelInit(void); //extern unsigned enableIRQ(void); //xxx //extern unsigned enableFIQ(void); //xxx AT91PS_PIO p_PIO; AT91PS_PMC p_PMC; AT91PS_AIC p_AIC; unsigned int FiqCount = 0; // global uninitialized variable //interrupt handler: switch off LED1 void interrupt_handler_button (void) { p_PIO->PIO_SODR = LED1; //switch off LED1 } int main (void) { unsigned int test; unsigned long k; p_PIO = AT91C_BASE_PIOA; p_PMC = AT91C_BASE_PMC; p_AIC = AT91C_BASE_AIC; LowLevelInit(); p_PMC->PMC_PCER = (1 << AT91C_ID_PIOA); // p_PMC->PMC_PCER = (1<<AT91C_ID_IRQ0); //yyy // p_PMC->PMC_PCER = (1<<AT91C_ID_IRQ1); //yyy test=p_PMC->PMC_PCSR; p_PIO->PIO_PER = LED_MASK; //activate I/O for LEDs p_PIO->PIO_OER = LED_MASK; //configure LEDs as ouput p_PIO->PIO_CODR = LED1 | LED2; //define initial status of output pins p_PIO->PIO_SODR = LED3; //define initial status of output pins p_PIO->PIO_PER = SW_MASK; //activate I/O for buttons p_PIO->PIO_ODR = SW_MASK; //configure buttons #1, #2 as input p_PIO->PIO_IFER = SW_MASK; //activate glitch filtering p_PIO->PIO_MDDR = SW_MASK; //deactivate multi drive control p_PIO->PIO_PPUER = SW_MASK; //activate pull-ups for buttons p_AIC->AIC_IDCR = 0x1<<AT91C_ID_PIOA; //firstly, deactivate interrupt p_AIC->AIC_SVR[AT91C_ID_PIOA] = (unsigned int) interrupt_handler_button; //specify interrupt handler function p_AIC->AIC_SMR[AT91C_ID_PIOA] = (AT91C_AIC_SRCTYPE_POSITIVE_EDGE|AT91C_AIC_PRIOR_HIGHEST); //interrupt typ+priority p_AIC->AIC_ICCR = 0x1<<AT91C_ID_PIOA; //read (and clear) interrupts p_PIO->PIO_IER = SW_MASK; //activate input change interrupt of buttons p_AIC->AIC_IECR = AT91C_ID_PIOA; //enable interrupts //enable interrupts // enableIRQ(); //xxx // enableFIQ(); //xxx while (1) { //blink LED1 if ((p_PIO->PIO_ODSR & LED2) == LED2) p_PIO->PIO_CODR = LED2; // LED1 (DS1) on else p_PIO->PIO_SODR = LED2; // LED1 (DS1) off for (k = 1000000; k != 0; k-- ); // wait 1 second } } My most urgent question is, why does the interrupt not work? I would expect that the function interrupt_handler_button is entered when I press one of the push-buttons, but nothing happens! Other open questions are: - when I un-comment the code lines marked with yyy, I would expect to read in the variable “test” the result of having activated AT91C_ID_IRQ0 and AT91C_ID_IRQ1. But that’s not the case, PMC_PCSR’s bit 30 and 31 can never be set to 1. Why? - Do I need Jim’s code lines marked with xxx (enableIRQ and enableFIQ) or can I drop them if I write my own interrupt handlers (e.g. functions like interrupt_handler_button)? I have a feeling that I should always use at least enableIRQ to be able to use nested interrupt handlers, but I’d like to confirm this assumption. Thanks a lot for any answer, christian
Hello Christian, do you have any solution (sample code for ext int) yet? I still have problems with ext int too as you can read at Beitrag "Externer Interrupt auf AT91SAM7X-EK mit Eclipse"
Chris Breitenbach wrote: > Hello all, > > I’m currently setting up my AT91SAM7S256 (Olimex EvalBoard, Yagarto > Toolchain) and try to implement interrupts in RAM-code, however I don’t > succeed. I have checked all available sample code (from various forums, > from Martin Thomas, etc.) and – at least to me – the code looks OK, but > still no satisfying result.. > > My project is based on Jim Lynch’s tutorial, I use (without > modification) blinker.c, crt.s, isrsupport.c, lowlevelinit.c, > script.ocd, makefile, demo_at91sam7_blink_ram.cmd, and all h- and > a-files. > Main.c looks like this: > > // ******************************************************* > #include "AT91SAM7S256.h" > #include "board.h" > #include "math.h" > #include "stdlib.h" > #include "string.h" > > // External References > extern void LowLevelInit(void); > //extern unsigned enableIRQ(void); //xxx > //extern unsigned enableFIQ(void); //xxx > AT91PS_PIO p_PIO; > AT91PS_PMC p_PMC; > AT91PS_AIC p_AIC; > > unsigned int FiqCount = 0; // global uninitialized variable > > //interrupt handler: switch off LED1 > void interrupt_handler_button (void) > { > p_PIO->PIO_SODR = LED1; //switch off LED1 > } > > int main (void) { > > unsigned int test; > unsigned long k; > > p_PIO = AT91C_BASE_PIOA; > p_PMC = AT91C_BASE_PMC; > p_AIC = AT91C_BASE_AIC; > > LowLevelInit(); > > p_PMC->PMC_PCER = (1 << AT91C_ID_PIOA); > // p_PMC->PMC_PCER = (1<<AT91C_ID_IRQ0); //yyy > // p_PMC->PMC_PCER = (1<<AT91C_ID_IRQ1); //yyy > test=p_PMC->PMC_PCSR; > > p_PIO->PIO_PER = LED_MASK; //activate I/O for LEDs > p_PIO->PIO_OER = LED_MASK; //configure LEDs as ouput > p_PIO->PIO_CODR = LED1 | LED2; //define initial status of output pins > p_PIO->PIO_SODR = LED3; //define initial status of output pins > p_PIO->PIO_PER = SW_MASK; //activate I/O for buttons > p_PIO->PIO_ODR = SW_MASK; //configure buttons #1, #2 as input > p_PIO->PIO_IFER = SW_MASK; //activate glitch filtering > p_PIO->PIO_MDDR = SW_MASK; //deactivate multi drive control > p_PIO->PIO_PPUER = SW_MASK; //activate pull-ups for buttons > > p_AIC->AIC_IDCR = 0x1<<AT91C_ID_PIOA; //firstly, deactivate interrupt > p_AIC->AIC_SVR[AT91C_ID_PIOA] = (unsigned int) > interrupt_handler_button; //specify interrupt handler function > p_AIC->AIC_SMR[AT91C_ID_PIOA] = > (AT91C_AIC_SRCTYPE_POSITIVE_EDGE|AT91C_AIC_PRIOR_HIGHEST); //interrupt > typ+priority > p_AIC->AIC_ICCR = 0x1<<AT91C_ID_PIOA; //read (and clear) interrupts > p_PIO->PIO_IER = SW_MASK; //activate input change interrupt of buttons > p_AIC->AIC_IECR = AT91C_ID_PIOA; //enable interrupts > > //enable interrupts > // enableIRQ(); //xxx > // enableFIQ(); //xxx > > while (1) { > //blink LED1 > if ((p_PIO->PIO_ODSR & LED2) == LED2) > p_PIO->PIO_CODR = LED2; // LED1 (DS1) on > else > p_PIO->PIO_SODR = LED2; // LED1 (DS1) off > > for (k = 1000000; k != 0; k-- ); // wait 1 second > > } > } > > > My most urgent question is, why does the interrupt not work? I would > expect that the function interrupt_handler_button is entered when I > press one of the push-buttons, but nothing happens! > > Other open questions are: > - when I un-comment the code lines marked with yyy, I would expect to > read in the variable “test” the result of having activated AT91C_ID_IRQ0 > and AT91C_ID_IRQ1. But that’s not the case, PMC_PCSR’s bit 30 and 31 can > never be set to 1. Why? > - Do I need Jim’s code lines marked with xxx (enableIRQ and enableFIQ) > or can I drop them if I write my own interrupt handlers (e.g. functions > like interrupt_handler_button)? I have a feeling that I should always > use at least enableIRQ to be able to use nested interrupt handlers, but > I’d like to confirm this assumption. > > Thanks a lot for any answer, > > christian Hi Christian, The type of interrupt that you want is definitely an IRQ interrupt, so you probably want call the enableIRQ in your program. The reason that your interrupts are not working might have something to do with your startup code. It is not shown here, so I am just guessing, but.... I would first check in what processor mode your code runs. The startup code initializes the various stacks and specifies whether or not the IRQ's and FIQ's are enabled for all processor modes. Suppose that the startup code switches to USR mode and disables the IRQ's (Sets the I-bit), then it is not so easy to enable it in your C-program. Since the ARM processor does not allow you do clear the IRQ flag while in USR mode, the enableIRQ function does not work. Switching to another mode while in USR mode is not easy either. So, either you have to change your startup code and keep running in SYS mode, or you have to write a SWI handler and write some SWI code that does enable the interrupts. When the swi instruction is executed, the processor mode switches to SVC mode, and then you can clear the IRQ flag for USR mode. But then again, I am just guessing since I do not know what your startup code does. Kees.
This is probably old, but.... Just in case anyone wants to know the solution to the problem p_AIC->AIC_IECR = AT91C_ID_PIOA; //enable interrupts Should be p_AIC->AIC_IECR = 1 << AT91C_ID_PIOA; //enable interrupts (very easy to miss)
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.