Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

Interrupts and AT91

Posted by Stephen Eaton on October 8, 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;

}

RE: Interrupts and AT91

Posted by Nobody/Anonymous on October 8, 2006
> 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.

I would suggest writing a simple program that does not use FreeRTOS to get the PIOB interrupt working as you want first, then add the known working code to your FreeRTOS project. Something very simple, like toggle an LED from the interrupt and have main just setup the interrupt, then sit in a for(;;); loop not doing anything (assuming your PIOB interrupt occur slowly enough to see the LED toggle).


> 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???

You have to clear the AIC as:
AT91C_BASE_AIC->AIC_EOICR = 0;

Other than that, you may have to clear the BIOB interrupt also, I don't know the details of how the port interrupts work. You don't need to enable interrupts as such.

Maybe you ISR is being continuously entered. Run the code in the debugger, set a break point in the ISR, then step trough the code. Do you immediately go back into the ISR when the ISR function ends? If so then the interrupt is still being asserted.


>
> 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.

The stack size is set in the startup file - the asm file that calls main. You will probably find a definition in there for the stack size of each processor mode.


>
> 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.


Do not call ENTER_EXIT critical from the ISR - this is a definite no no. Also don't call a function to toggle an LED that uses enter/exit critical.

The enter/exit switching isr macros need only be used if the isr causes a context switch, and should only be used if the ISR is declared as naked.

I don't know what the debug() function does - but I suspect it will be something that you don't want to happen from within an ISR!


Hope this provides some pointers.

RE: Interrupts and AT91

Posted by Nobody/Anonymous on October 9, 2006
Thanks for that.

I'm already clearing the AIC at the end of my ISR, and by reading the PIOB Interrupt Register it should be clearing it (as I interpret the datasheet anyway)

I only had the entry/exit ISR macros in to test as a "naked" ISR to see if it made any difference.

I will remove everything else and test tonight without FreeRTOS when I get home as you suggest. this was the next thing I was going to do.

Thanks,

Stephen...


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS