Hardware interruptions

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Hardware interruptions

Jump to solution
1,954 Views
SortoVaritu
Contributor III

I would like to clarify how to use hardware interruptions in MQX. For example i want to use PIT in my application.

Is it nessesary to use ISR for it?

Tags (2)
0 Kudos
1 Solution
1,027 Views
naftalir
Contributor III

There is a way to create an interrupt with GPIO ports as this example (SD Insertion/Removal Example):

 

void main_task
(
uint_32 initial_data
)
{
/* Structures holding information about specific pin */
LWGPIO_STRUCT sd_irq;
_mqx_uint result;


/*******************************************************************************

Opening the pin  for input, initialize interrupt on it and set interrupt handler.
*******************************************************************************/
/* opening pins for input */

if (!lwgpio_init(&sd_irq, BSP_SDCARD_GPIO_DETECT, LWGPIO_DIR_INPUT, LWGPIO_VALUE_NOCHANGE))
{
printf("Initializing GPIO as input failed.\n");
_task_block();
}


/* Some platforms require to setup MUX to IRQ functionality,
for the rest just set MUXto GPIO functionality */

lwgpio_set_functionality(&sd_irq, BSP_SDCARD_DETECT_MUX_GPIO);
lwgpio_set_attribute(&sd_irq, LWGPIO_ATTR_PULL_UP, LWGPIO_AVAL_ENABLE);

 

/* enable gpio functionality for given pin, react on falling edge */
if (!lwgpio_int_init(&sd_irq, LWGPIO_INT_MODE_FALLING))
{
printf("Initializing GPIO for interrupt failed.\n");
_task_block();
}

/* install gpio interrupt service routine */
_int_install_isr(lwgpio_int_get_vector(&sd_irq), int_service_routine, (void *) sd_irq);
/* set the interrupt level, and unmask the interrupt in interrupt controller*/
_bsp_int_init(lwgpio_int_get_vector(&sd_irq), 3, 0, TRUE);
/* enable interrupt on GPIO peripheral module*/
lwgpio_int_enable(&sd_irq, TRUE);

 

/*******************************************************************************

Read value from input pin Note that in previous phase, the pin was
configured as an interrupt and it have to be reconfigured to standard GPIO.
*******************************************************************************/
/* set pin functionality (MUX) to GPIO*/

while (TRUE)
{
 }

 

}

View solution in original post

0 Kudos
12 Replies
1,027 Views
OldNick
Contributor IV

Hi,

there are two possibilities for an ISR.

MQX has an ISR handler, but it is more like a "micro thread", you register your behavioural code with MQX, and can pass parameters in and out.  It is s-l-o-w.

However, if you have moved your vector table into RAM (a good idea) you can install a kernel interrupt, which is the traditional void-void.

If you want to do anything faster than about 100 Hz, I would do it that way.

 

There are examples in the MQX directory, but you still have to learn stuff.

 

So in the spirit of generosity, here you are, some sample code for a Kinetis.

#define PIT_TIMER                   (2)

#define PIT_TMR_INTVEC  (INT_PIT0 + PIT_TIMER)
//some utilities

/*******************************************************************************/
/* void  SetPit(uint_16 rate)                                           */
/* Description:-                                                               */
/* Calculate Hardware timer count on Kinetis for appropriate f (in Hz) */
/* And jam into PIT register = which resets the PIT counter */
/* In general, the Peripheral bus clock which is used to drive PIT module      */
/* runs at half the main clock speed. (i.e. around 48MHz)                      */
/*******************************************************************************/
void  SetPIT(uint_16 rate)
{
   PITTimerCounts = BSP_BUS_CLOCK/rate;
   PIT_LDVAL(PIT_TIMER) = PITTimerCounts;
}
/*******************************************************************************/
/* void  ResetPIT(void)                                           */
/* Description:-                                                               */
/* jam precalculated count into PIT register = which resets the PIT counter */
/*******************************************************************************/
void  ResetPIT(void)
{
   PIT_LDVAL(PIT_TIMER) = PITTimerCounts;
}
/*******************************************************************************/
/* void StartPIT(void)                                                     */
/* Description:-                                                               */
/* jam precalculated count into PIT register = which resets the PIT counter */
/* Turn ON PIT in Kinetis and clear state flag */
/*******************************************************************************/
void  StartPIT(void)
{
  PIT_LDVAL(PIT_TIMER) = PITTimerCounts;
  PIT_TCTRL(PIT_TIMER) |= PIT_TCTRL_TEN_MASK;//turn on timer
  PIT_Stopped = FALSE;
}
/*******************************************************************************/
/* void StopPRF(void)                                                     */
/* Description:-                                                               */
/* Turn off PIT in Kinetis and set state flag */
/*******************************************************************************/
void  StopPIT(void)
{
  PIT_TCTRL(PIT_TIMER) &= ~PIT_TCTRL_TEN_MASK;//turn off timer
  PIT_Stopped = TRUE;
}

//here is the interrupt handler

#if MQX_ROM_VECTORS
//MQX_ISR takes a parameter
void PRF_tick_isr( pointer user_isr_ptr )
#else
//kernel ISR is void void
void PIT_tick_isr( void )
#endif
{
volatile uint_32 tmp;


   tick++;//do stuff here


   PIT_TFLG(PRF_TIMER) = PIT_TFLG_TIF_MASK; //finally, write a 1 to clear the interrupt
   tmp = PIT_CVAL(PRF_TIMER);//see errata
}
/*
Kinetis e2682: PIT: Does not generate a subsequent interrupt after clearing the interrupt flag
Errata type: Errata
Description: The PIT does not generate a subsequent interrupt after clearing the interrupt flag in the ISR
upon receiving the first interrupt. Thus, the second interrupt will never be triggered.
Workaround: In order to enable the use of subsequent interrupts from the PIT, the user must access any PIT
register after clearing the interrupt flag in the ISR.
*/
//here the routine to install the interrupt

void  InstallTimerInterrupt(void)
{
    StopTimer();//for safety, make sure the timer is disabled.
#if MQX_ROM_VECTORS
    _int_install_isr(PIT_TMR_INTVEC, PIT_tick_isr, NULL);
#else
     _int_install_kernel_isr(PIT_TMR_INTVEC, PIT_tick_isr);
#endif   
    PIT_MCR = PIT_MCR_FRZ_MASK;//enable timers but stop when in debug mode

    PIT_TCTRL(PRF_TIMER) = PIT_TCTRL_TIE_MASK;//turn on interrupt, but do not enable timer

    _bsp_int_init(PRF_TMR_INTVEC,3,0,TRUE);//also need to enable the interrupt controller
    //this bit is hidden deep in the guts of the ARM cortex documentation.
}

 

NB there may be typos in the above - I take no responsibility for any errors in this code.   Offered in good faith.

If you choose to use it, the risk is yours.  If anyone wants to criticise it, at least say how it can be improved.:robotwink:

 

Hope that helps

1,027 Views
SortoVaritu
Contributor III

I have change your solution for ADC like this:

#if MQX_ROM_VECTORS

    _int_install_isr(INT_ADC1, ADC_tick_isr, NULL);

#else

     _int_install_kernel_isr(INT_ADC1, ADC_tick_isr);

#endif  

    ADC1_SC1A|=ADC_SC1_AIEN_MASK;;//turn on interrupt, but do not enable timer

    _bsp_int_init(INT_ADC1,3,0,TRUE);//also need to enable the interrupt controller

    //this bit is hidden deep in the guts of the ARM cortex documentation.   


But when ADC1_SC1A|=ADC_SC1_AIEN_MASK; performs - my application becomes fault.

Actually when i trying to change any register - result is the same.

0 Kudos
1,027 Views
c0170
Senior Contributor III

Hello Rozberg,

what did you mean your application becomes fault? Did you enable clock for ADC peripheral? That comes to my mind as first hint, without enabled clock, application always invokes hard fault.

Regards,

MartinK

0 Kudos
1,027 Views
SortoVaritu
Contributor III

Thanks a lot! I already found the answer. You are right - need to enable clock for ADC.

0 Kudos
1,027 Views
SortoVaritu
Contributor III

Where i can find all these definitions, such

PIT_TFLG_TIF_MASK

PIT_TMR_INTVEC and others?


0 Kudos
1,027 Views
MarkP_
Contributor V

Hi,

If you are using Processor Expert they are in file:

C:\Freescale\Freescale MQX 3.8\mqx\build\cw10\bsp_xx_pe\Generated_Code\IO_Map.h

where bsp_xx_pe is your board bsp directory.

Alternative location is:

C:\Freescale\Freescale MQX 3.8\mqx\source\psp\cortex\MK10F12.h

the file depends on what CPU you are using.

~Mark

0 Kudos
1,027 Views
SortoVaritu
Contributor III

Thanks a lot!!!!!!

According with ISR manual we cant use GPIO inside interrupt function. So, how to work with ports? Should i use port registers directly?

0 Kudos
1,028 Views
naftalir
Contributor III

There is a way to create an interrupt with GPIO ports as this example (SD Insertion/Removal Example):

 

void main_task
(
uint_32 initial_data
)
{
/* Structures holding information about specific pin */
LWGPIO_STRUCT sd_irq;
_mqx_uint result;


/*******************************************************************************

Opening the pin  for input, initialize interrupt on it and set interrupt handler.
*******************************************************************************/
/* opening pins for input */

if (!lwgpio_init(&sd_irq, BSP_SDCARD_GPIO_DETECT, LWGPIO_DIR_INPUT, LWGPIO_VALUE_NOCHANGE))
{
printf("Initializing GPIO as input failed.\n");
_task_block();
}


/* Some platforms require to setup MUX to IRQ functionality,
for the rest just set MUXto GPIO functionality */

lwgpio_set_functionality(&sd_irq, BSP_SDCARD_DETECT_MUX_GPIO);
lwgpio_set_attribute(&sd_irq, LWGPIO_ATTR_PULL_UP, LWGPIO_AVAL_ENABLE);

 

/* enable gpio functionality for given pin, react on falling edge */
if (!lwgpio_int_init(&sd_irq, LWGPIO_INT_MODE_FALLING))
{
printf("Initializing GPIO for interrupt failed.\n");
_task_block();
}

/* install gpio interrupt service routine */
_int_install_isr(lwgpio_int_get_vector(&sd_irq), int_service_routine, (void *) sd_irq);
/* set the interrupt level, and unmask the interrupt in interrupt controller*/
_bsp_int_init(lwgpio_int_get_vector(&sd_irq), 3, 0, TRUE);
/* enable interrupt on GPIO peripheral module*/
lwgpio_int_enable(&sd_irq, TRUE);

 

/*******************************************************************************

Read value from input pin Note that in previous phase, the pin was
configured as an interrupt and it have to be reconfigured to standard GPIO.
*******************************************************************************/
/* set pin functionality (MUX) to GPIO*/

while (TRUE)
{
 }

 

}

0 Kudos
1,026 Views
naftalir
Contributor III

If someone know how do i clear the interrupt that occur from Inserting/Removing the SD please let me know :smileyhappy: thx.

0 Kudos
1,026 Views
naftalir
Contributor III

Found :smileyhappy: + The missing part of the Interrupt Function:

 

/*ISR*-----------------------------------------------------
*
* Task Name : int_service_routine
*END*-----------------------------------------------------*/
void int_service_routine(void *pin)
{
lwgpio_int_clear_flag((LWGPIO_STRUCT_PTR) pin);
}

0 Kudos
1,026 Views
SortoVaritu
Contributor III

Thanks a lot

0 Kudos
1,026 Views
naftalir
Contributor III

you welcome :smileyhappy: