seaton wrote on Sunday, October 08, 2006:
I’m a real newb to the AT91SAM7X and on a bit of a learning curve.
I’m having some issues trying to get an ISR on one of my PIOB inputs
working. I’m using GNUARM and FreeRTOS on a small robotics project.
Under FreeRTOS I’m successfully running a simple task ( blink Led)
that as the name says just blinks a led, it gives me some indication
that things a running, and I also have my non context switching ISR
that I want to run based on a digital input PIOB, that will
eventually be my wheel encoder ISR.
It appears my ISR is being called when I put a high on the PIOB input
port, I have my ISR turning on one of my development board Leds, this
is happening the first time, then freezes the controller So I’m
wondering. Do I have to re-enable interrupts manually after I
complete my ISR???
Another thing I thought what could be causing it could be ISR Stack
Size. Anyone know where this is set? However I don’t think it is
stack size of the ISR as I have tested it by cutting the ISR back to
just about nothing, and it still froze.
Anyway my Interrupt setup code so far if anyone can see any serious
holes that they could drive a truck though that a beginner like me
might be missing.
----GPIOB_ISR.c----
/#include "Board.h"
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "appboard.h"
#include "buzzbot.h"
/*-----------------------------------------------------------*/
extern struct Encoder_ Encoder;
/*-----------------------------------------------------------*/
/* This does not cause a Context switch so is declared as IRQ */
void PIOB_ISR(void) __attribute__((interrupt("IRQ")));
/*-----------------------------------------------------------*/
/*
* wheel encoder runs each time interrupt occurs generated from PIOB
*/
void PIOB_ISR(void)
{
//portENTER_SWITCHING_ISR();
portENTER_CRITICAL() ;
// This reads and clears the IRQ Status Register on the PIO
unsigned int ulIRQ = AT91C_BASE_PIOB->PIO_ISR;
//if (ulIRQ & L_WHEEL) {
//TODO just for testing of ISR, need to determine source of interrupt
etc
// Encoder.l_Distance++;
// }
//if (ulIRQ & R_WHEEL) {
// Encoder.r_Distance++;
//}
// give some thing visual
if (AppLed_GetState(0))
AppLed_SetState(0,0);
else
AppLed_SetState(0,1);
Debug( 2, "PIOB_ISR Hit!!!!" );
/* Clear AIC to complete ISR processing */
AT91C_BASE_AIC->AIC_EOICR = 0;
portEXIT_CRITICAL()
/* Do a task switch if needed */
//portEXIT_SWITCHING_ISR( 0 );
}
---- interrupt setup code -----
/* -----------------------------------------------------------*/
/* Configures PIOB for interrupt on change of state */
int Din_PIOB_Setup(void)
{
//unsigned int oldHandler;
unsigned int mask ;
// interrupts need the clock
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB;
// Configure AIC
//AT91C_AIC_SRCTYPE_POSITIVE_EDGE,AT91C_AIC_SRCTYPE_EXT_LOW_LEVEL,
AT91C_AIC_SRCTYPE_HIGH_LEVEL,AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE
// gets old IRQ handler
//oldHandler = AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOB];
mask = 0x1 << AT91C_ID_PIOB ;
//* Disable the interrupt on the interrupt controller
AT91C_BASE_AIC->AIC_IDCR = mask ;
//* Save the interrupt handler routine pointer and the interrupt
priority
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOB] = (unsigned int) PIOB_ISR ;
//* Store the Source Mode Register
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOB] =
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 7 ; // IRQ Priority
//* Clear the interrupt on the interrupt controller
AT91C_BASE_AIC->AIC_ICCR = mask ;
//* Enable the interrupt on the interrupt controller
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_PIOB ;
//AT91F_AIC_EnableIt(AT91C_BASE_AIC, 0x1 << AT91C_ID_PIOB);
return CONTROLLER_OK;
}
/*---------------------------------------------------------------- */
/* Configures specified pin as a digital input and */
/* enables this pin as interrupt source */
int Din_PIOB_Enable(unsigned int pin)
{
// Disable output on specified PIO pin
AT91C_BASE_PIOB->PIO_ODR = 0x1<<pin;
AT91C_BASE_PIOB->PIO_PER = 0x1<<pin;
// enable interrupt on PIO Pin
AT91C_BASE_PIOB->PIO_IER = 0x1<<pin;
return CONTROLLER_OK;
}