Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

FreeRTOS handling hardware interrupts


  • Please log in to reply
10 replies to this topic

#1 Bobi

Bobi

    Member

  • Members
  • PipPip
  • 10 posts

Posted 09 November 2011 - 02:32 PM

Hello,

I want to run a FreeRTOS program on my Netduino plus board. I'm working on the ARM7 uIP demo for IAR (uIP_Demo_IAR_ARM7) that's provided with the FreeRTOS source code. I know that this may be an easy question but I have lost too much time trying to do it on my own. I want to be able to handle PIO button interrupts.
The netduino has an onaboard button (PA29) and I want to initialise and handle the interrupts so that when you press the button the onboard LED (PB23) will turn ON.
I want to achieve this using the provided FreeRTOS at91sam7x256 port. I already have it working with the demos which come from the Atmel site but they use a very different port which fails to work together with the FreeRTOS. I want to use the FreeRTOS port because the main goal of the application will be far different from turning LEDs on and off.

Here is my code:
First in board.h I have defined that LED1 is (1 << 23) and SW1 is (1 << 29).
I have the following interrupt handler, which will turn the onboard LED ON:

void Handler(void)
{
        if( AT91F_PIO_GetInput( AT91C_BASE_PIOA ) & LED1 )
        {
                AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED1 );
        }
        else
        {
                AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED1 );					
        }  
}

And in the prvSetupHardware function I have added the following:
        AT91F_PIO_CfgInput( AT91C_BASE_PIOA, SW1 );
        AT91F_PIO_CfgPullup( AT91C_BASE_PIOA, SW1 );
        AT91F_PIO_CfgInputFilter( AT91C_BASE_PIOA, SW1 );
        
        AT91F_AIC_ConfigureIt(AT91C_BASE_PIOA, AT91C_ID_PIOA, 0x07, 0x0, Handler);
        AT91F_AIC_EnableIt(AT91C_BASE_PIOA, AT91C_ID_PIOA);

And here I am confused about am I initializing the interrupt properly? As long as the button belongs to PA29 I know that I have to use the AT91C_BASE_PIOA when I make the call to AT91F_AIC_ConfigureIt. And here I am not sure about the irq_id parameter. Should it be 29 (as I am using PA29) or should it be AT91C_ID_PIOA? And if its AT91C_ID_PIOA where should I specify that I want to handle intterupts coming from PA29?

Thanks :)

#2 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 09 November 2011 - 03:04 PM

And if its AT91C_ID_PIOA where should I specify that I want to handle intterupts coming from PA29?

All I/O lines of the same port share one interrupt. In your trivial case, you could just simply check the appropriate bit of PIO_ISR register in the interrupt handler.

#3 Bobi

Bobi

    Member

  • Members
  • PipPip
  • 10 posts

Posted 09 November 2011 - 03:33 PM

All I/O lines of the same port share one interrupt. In your trivial case, you could just simply check the appropriate bit of PIO_ISR register in the interrupt handler.


Hi,

Ok great and do you think that the interrupt initialization is OK then, because when I press the button nothing happens?
Is there any way to debug your code when it's running on the netduino if you don't have a jtag?

#4 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 09 November 2011 - 04:34 PM

Ok great and do you think that the interrupt initialization is OK then, because when I press the button nothing happens?

In the above code, there is missing call to enable clock on PIOA (i.e. AT91F_PMC_EnablePeriphClock) and AT91F_PIO_InterruptEnable() for the button. Also, you should use constants instead of hardcoded values in AT91F_AIC_ConfigureIt(), like PIO_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE.

Is there any way to debug your code when it's running on the netduino if you don't have a jtag?

Nope - without JTAG, you can use pin toggling and diagnostic output via serial line (COMx). But if you mean that Netduino does not have JTAG connector and you have JTAG debugger, then it should be possible to solder thin wires directly to microcontroller leads to access JTAG lines...

#5 Bobi

Bobi

    Member

  • Members
  • PipPip
  • 10 posts

Posted 09 November 2011 - 04:59 PM

In the above code, there is missing call to enable clock on PIOA (i.e. AT91F_PMC_EnablePeriphClock) and AT91F_PIO_InterruptEnable() for the button. Also, you should use constants instead of hardcoded values in AT91F_AIC_ConfigureIt(), like PIO_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE.

Hi,

Thanks for the fast reply! It looks perfectly fine to me now but it still doesn't work. What am I misssing?

#define PIO_INTERRUPT_LEVEL 0x7
#define AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE ((unsigned int) 0x1 <<  5)

void Handler(void)
{
        AT91F_PIO_ClearOutput( AT91C_BASE_PIOB, LED1 ); // turn LED OFF				
}

static void prvSetupHardware( void )
{
	AT91F_PIO_CfgOutput( AT91C_BASE_PIOB, LED1 );        
        AT91F_PIO_SetOutput( AT91C_BASE_PIOB, LED1 );	// turn LED ON              
	
	AT91F_PMC_EnablePeriphClock( AT91C_BASE_PMC, 1 << AT91C_ID_PIOA );
	AT91F_PMC_EnablePeriphClock( AT91C_BASE_PMC, 1 << AT91C_ID_PIOB ) ;
	                        
        AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA, 1 << AT91C_ID_PIOA);
        
        AT91F_PIO_CfgInput( AT91C_BASE_PIOA, SW1 );
        AT91F_PIO_CfgPullup( AT91C_BASE_PIOA, SW1 );
        AT91F_PIO_CfgInputFilter( AT91C_BASE_PIOA, SW1 );
        
        AT91F_AIC_ConfigureIt(AT91C_BASE_PIOA, 
                              AT91C_ID_PIOA, 
                              PIO_INTERRUPT_LEVEL, 
                              AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE, 
                              Handler);
        AT91F_AIC_EnableIt(AT91C_BASE_PIOA, AT91C_ID_PIOA);        
}

I'm not aboslutely sure about the PIO_INTERRUPT_LEVEL value. In the documentation they say that its between 0(lowest) and 7(highest). Otherwise this is what you mean, right?

#6 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 09 November 2011 - 05:12 PM

Thanks for the fast reply! It looks perfectly fine to me now but it still doesn't work. What am I misssing?

static void prvSetupHardware( void )
{
  ...
  // The second parameter should be button pin               		
  AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA, SW1);
  ...        
}
Also, don't forget to read PIO_ISR in Handler().

#7 Bobi

Bobi

    Member

  • Members
  • PipPip
  • 10 posts

Posted 09 November 2011 - 06:54 PM

static void prvSetupHardware( void )
{
  ...
  // The second parameter should be button pin               		
  AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA, SW1);
  ...        
}
Also, don't forget to read PIO_ISR in Handler().


OK, I did this and now when I deploy the bin file on the Netduino and connect it in my Computer I see an instant flash and the LED stays ON and when you press the button nothing happens. There must be something else... ?

How is the right way to read the PIO_ISR register? Should I simply say:
   if(PIO_ISR  == 29){
      // ...
   }


#8 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 09 November 2011 - 07:57 PM

OK, I did this and now when I deploy the bin file on the Netduino and connect it in my Computer I see an instant flash and the LED stays ON and when you press the button nothing happens. There must be something else... ?

Well, it's kind of impossible to troubleshoot interrupt issues remotely ;-) I am not very familiar with FreeRTOS itself, but according to the information I've found on the Internet, it requires some special coding for ISR routines, like declaring __attribute__((interrupt("IRQ"))) (?) and portENTER_CRITICAL()/portEXIT_CRITICAL() macros (?) - so I would suggest you looking at the FreeRTOS documentation and samples.

How is the right way to read the PIO_ISR register? Should I simply say: if(PIO_ISR == 29){

No, the register contains bit mask, so you'd need to use 1 << 29; usually the code looks like

...
isr = AT91C_BASE_PIOA->PIO_ISR;
if(isr & SW1)
{
  // Button
}
...
AT91C_BASE_AIC->AIC_EOICR = 0; // Clear AIC to complete ISR processing


#9 Bobi

Bobi

    Member

  • Members
  • PipPip
  • 10 posts

Posted 10 November 2011 - 02:27 PM

Well, it's kind of impossible to troubleshoot interrupt issues remotely ;-) I am not very familiar with FreeRTOS itself, but according to the information I've found on the Internet, it requires some special coding for ISR routines, like declaring __attribute__((interrupt("IRQ"))) (?) and portENTER_CRITICAL()/portEXIT_CRITICAL() macros (?) - so I would suggest you looking at the FreeRTOS documentation and samples.


No, the register contains bit mask, so you'd need to use 1 << 29; usually the code looks like

...
isr = AT91C_BASE_PIOA->PIO_ISR;
if(isr & SW1)
{
  // Button
}
...
AT91C_BASE_AIC->AIC_EOICR = 0; // Clear AIC to complete ISR processing


Hi, thanks for your replies!
I already have a working demo of the same functionality which was included in the Getting Started Tutorial I got from Atmel. It works perfectly fine and the code looks like executing exactly the same steps except that they are using a different port. FreeRTOS have implemented their own port and one solution I can think of is to get FreeRTOS running with the Atmel port for sam7x512.

#10 Bobi

Bobi

    Member

  • Members
  • PipPip
  • 10 posts

Posted 14 November 2011 - 10:16 AM

Hi, I found the problem!!! It works great now.
There are a few things which need to be done:
  • In the documentation of the AT91F_AIC_ConfigureIt function the first parameter is described as "pointer to the AIC registers" and therefore when you configure your interrupt you should pass AT91C_BASE_AIC but not AT91C_BASE_PIOA. I'm not absolutely sure why is that but it just works only if I pass the AT91C_BASE_AIC register. You do the same for the AT91F_AIC_EnableIt call. The activation level that works for me is AT91C_AIC_SRCTYPE_EXT_LOW_LEVEL - (AIC) External Sources Code Label Low-level Sensitive.
  • If you are using IAR you have to do a few more steps. You need to decide whether your interrupt service routine should cause a context switch. Look here for an example.

In my case - I needed a context switch, so I had to create a DriverISR.s79 assembler file where I execute
portSAVE_CONTEXT
call the ISR routine
portRESTORE_CONTEXT

And this is all FreeRTOS specific (this is also described in the demo from the link above).

Best Regards,
Bobi

#11 flado

flado

    New Member

  • Members
  • Pip
  • 1 posts

Posted 25 July 2012 - 11:48 AM

hi there im using freertos as well and have difficulties setting an external interrupt i tried to combine my code with yours but still i cannot have an interrupt from button could you be more specific about how u did that to make the code works i appreciate ur help..thx:)




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.