Quality RTOS & Embedded Software

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




Loading

*stupid* How to declare ISR?

Posted by sven-de on April 15, 2011
Hi, my setup is an ICSwift board with AT91SAM7X256 running the GCC/Eclipse-Demo. I managed to set up simple tasks on my own to blink the LEDs and to send out a simple countdown via CAN which I monitor with a CAN PC-card. Except for the uIP all of the demo tasks are disabled.

Now I'm trying to set up an Interrupt to react on incoming CAN-messages, but whenever I sent a message (ie. trigger the interrupt) this totally resets the controller. This is visible by the LEDs, the CAN-Countdown restarts and even the network-connection is lost for an instant.

I'm fairy certain this is because I don't declare my ISR as such, but failed the whole morning to find out how to do this. So please, tell me the obviuous: how to declare an ISR?

Am I missing something else, like clearing the Interrupt after being done?
void CAN_IR_Handler(void)
{
volatile unsigned int status;
status = AT91C_BASE_CAN->CAN_SR & AT91C_BASE_CAN->CAN_IMR;

if(status & AT91C_CAN_WAKEUP) {
AT91C_BASE_CAN->CAN_IDR = AT91C_CAN_WAKEUP;
flagCAN = 1;
}

if(status & AT91C_CAN_MB0) {
AT91C_BASE_CAN->CAN_MB0.CAN_MB_MCR = AT91C_CAN_MTCR;
}
}

RE: *stupid* How to declare ISR?

Posted by sven-de on April 15, 2011
After repeated reading of the demo documentation I tried this declaration
void CAN_IR_Handler(void) __attribute__((interrupt("IRQ")));

But got the Error, that "ISR cannot be coded in thumb mode"

I figure it could also be, that the IR-vector points to the wrong location, so here's the code for setting that up:
AT91F_AIC_ConfigureIt( AT91C_ID_CAN, 1, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, CAN_IR_Handler);
AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_CAN;

RE: *stupid* How to declare ISR?

Posted by Dave on April 15, 2011
On an ARM7 you have to use ARM mode for interrupts, or at least the interrupt entry point. Different versions of GCC have different bugs when it comes to trying to use the __attribute__((interrupt)), so it is best avoided. Instead, write your own interrupt entry code. There are lots of examples on the FreeRTOS web site, and in the download source code. For example look at the Interrupt Service Routines section on this page http://www.freertos.org/portat91fr40008.html

Even then it suggests using an attribute((naked)) function for the entry point, but that too has issues with some GCC versions. I would say, write the wrapper in ARM assembly code, and write the handler that is called by the wrapper in C code. I'm sure there are examples of that in the download too.

RE: *stupid* How to declare ISR?

Posted by sven-de on April 18, 2011
Hi Dave, thanks for your quick reply. I've been following your advice without success, the CAN-Interrupt still resets the whole controller. What bugs me most is that the code in SAM7_EMAC.c and EMAC_ISR.c looks just like mine but is working (incoming traffic doesn't reset everything).

One strange thing I observed: The order of Handler/Wrapper-definition makes a difference. When defining the handler first an the wrapper second (as below) I get the mentioned reset. But when switching the order to wrapper first, handler second (as in EMAC_ISR.c) I get a total freeze. Also removing flagCAN = 1; in the Handler causes a freeze. This behaviour contradicts everything I believed to know about programming.

Speaking of strange: When using portSAVE_CONTEXT() and portRESTORE_CONTEXT() as in EMAC_ISR.c the compiler complains with a couple of these: "Error: selected processor does not support `stmdb SP!,{R0}'". Meanwhile EMAC_ISR.c compiles just fine.

This is my current code:
void CAN_IR_Wrapper(void) __attribute__ ((naked));
void CAN_IR_Handler(void) __attribute__ ((noinline));

void CAN_IR_Wrapper(void)
{
//portSAVE_CONTEXT();

__asm volatile ("bl CAN_IR_Handler");

//portRESTORE_CONTEXT();
}

void CAN_IR_Handler(void)
{
volatile unsigned int status;
status = AT91C_BASE_CAN->CAN_SR & AT91C_BASE_CAN->CAN_IMR;

if(status & AT91C_CAN_WAKEUP) {
AT91C_BASE_CAN->CAN_IDR = AT91C_CAN_WAKEUP;
flagCAN = 1;
}

if(status & AT91C_CAN_MB0) {
AT91C_BASE_CAN->CAN_MB0.CAN_MB_MCR = AT91C_CAN_MTCR;
}
/* Clear the interrupt. */
AT91C_BASE_AIC->AIC_EOICR = 1;
}

// within main() before starting the scheduler or any tasks:
portENTER_CRITICAL();
// CAN Interrupt aktivieren
AT91C_BASE_CAN->CAN_IER = AT91C_CAN_MB0;

AT91F_AIC_ConfigureIt( AT91C_ID_CAN, 6, 0, ( void (*)( void ) ) CAN_IR_Wrapper);
AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_CAN;
portEXIT_CRITICAL();

RE: *stupid* How to declare ISR?

Posted by sven-de on April 18, 2011
PROBLEM SOLVED

The ARM vs. THUMB mode aspect never really fired in my brain so I hat the ISR in my main.c. By coincidence I had a look into the makefile and only then realised my mistake. The ISR need to be in a dedicated file listed among those destined for compilation in ARM mode.

Jesus, am I glad. Free hugs for everyone!


[ 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