How to set an interrupt to be direct?

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

How to set an interrupt to be direct?

Jump to solution
5,215 Views
MQXuser
Contributor III

Is there an example of how to do this?

MQXUG reads the following, but being new to MQX this is not helping me much.

 

An interrupt comes at periodic intervals that my application must respond to very quickly
— quicker than MQX allows. What can I do?
Call _int_install_kernel_isr() to replace the kernel ISR (_int_kernel_isr()). Your replacement ISR must:
• Save all registers on entry, and restore them on exit.
• It must not call any MQX functions.
• Pass information to other tasks (if required) by an application-implemented mechanism (usually
ring buffers with head and tail pointers and total size fields).

 

Any help will be appreciatted,

 

Regards

0 Kudos
1 Solution
1,383 Views
DavidS
NXP Employee
NXP Employee

Hi MQXUser,

Enclosed is an enhanced version of the Freescale MQX 3.4\mqx\examples\isr example.

In the main_task() you can choose to have a direct ISR or allow FSLMQX to handle it.  Here is that piece of code:

#if 1 //DES 0=direct ISR preempts MQX, 1=kernel isr handles the exception

_int_install_kernel_isr(MCF5225_INT_EPORT0_EPF7, new_irq7or1_isr);

#else

*(unsigned int *) 0x2000011c = (unsigned int)&new_irq7or1_isr; //DES install direct ISR vector

#endif

 

Note I haven't updated all the comments in the file.  I've tested this with the M52259EVB and the ABORT/IRQ7 switch.

Regards,

David

 

isr.c

Message Edited by t.dowe on 2009-12-02 11:09 AM

View solution in original post

0 Kudos
13 Replies
1,383 Views
wne
Contributor I

I followed this post to set  up PIT0 timer, but I got errors! Here is my code:


extern void PIT0_isr( pointer );

_int_install_kernel_isr(INT_PIT0, PIT0_isr);                               // got error: illegal implicit conversion from 'void (void *)' to 'void (*)()'

__declspec(interrupt:0) void PIT0_isr( pointer user_isr)           //  got error: declaration syntax error

{

    PIT_TFLG0 |= PIT_TFLG_TIF_MASK;

    _lwevent_set(&lwevent_cali, LWEVENT_BIT_CALI);

}


0 Kudos
1,383 Views
brianwilloughby
Contributor III

Bing Hao: Your question may be best handled in a new thread, since this one has been answered.

However, _lwevent_set() is an MQX service, but you cannot called MQX services from a kernel ISR. I believe this is your problem.

0 Kudos
1,383 Views
JaimeR
Contributor III

Thanks David,

 

Now I'm trying to add a new interrupt outside MQX into the ISR.c example. First I tried to set an Edge Triggered DMA interrupt but upon failure (I am using the same configuration I used in order to install the interrupt with MQX  handler, with configuration I mean all the registers required) , I tried adding ISR for IRQ5 but this isn't working either. Is there something I am missing? I am following every line you have in the MainTask from the example but still it is not workin. Here is the code I am using:

 

 

__declspec(interrupt:0) void dtim0_isr( pointer user_isr_ptr ){    //reg_ptr->EPORT->EPFR = MCF522XX_EPORT_EPFR_EPF7; //DES Clear IRQ7 interrupt flag bcnt++;}__declspec(interrupt:0) void test_irq5( pointer user_isr_ptr ){    //reg_ptr->EPORT->EPFR = MCF522XX_EPORT_EPFR_EPF7; //DES Clear IRQ7 interrupt flag bcnt++;}/*TASK*----------------------------------------------------------** Task Name : main_task* Comments  : *   This task installs a new ISR to replace the timer ISR.*   It then waits for some time, finally printing out the*   number of times the ISR ran.*END*-----------------------------------------------------------*/   #define Prescaler   0x00  //8bits-   #define CaptureEdge 0x2   //2 bits   #define OutputMode  0x0   //1 bit   #define IntEnable   0x1   //1 bit   #define Restart     0x1   //1 bit   #define ClkSource   0x3   //2bits   #define EnableTimer 0x0   //1bit   void main_task( uint_32 initial_data ){   MY_ISR_STRUCT_PTR  isr_ptr;   VMCF5225_STRUCT_PTR reg_ptr = (VMCF5225_STRUCT_PTR)BSP_IPSBAR;  //DES   isr_ptr = _mem_alloc_zero((_mem_size)sizeof(MY_ISR_STRUCT));   isr_ptr->TICK_COUNT   = 0;   isr_ptr->OLD_ISR_DATA =  _int_get_isr_data(BSP_TIMER_INTERRUPT_VECTOR);   isr_ptr->OLD_ISR      =  _int_get_isr(BSP_TIMER_INTERRUPT_VECTOR);   _int_install_isr(BSP_TIMER_INTERRUPT_VECTOR, new_tick_isr, isr_ptr);#ifdef BSP_M52259EVB reg_ptr->EPORT[0].EPIER |= (MCF522XX_EPORT_EPFR_EPF7); //DES #if 0 //DES 0=direct ISR preempts MQX, 1=kernel isr handles the exception    _int_install_kernel_isr(MCF5225_INT_EPORT0_EPF7, new_irq7or1_isr); #else       *(unsigned int *) 0x20000114 = (unsigned int)&test_irq5; //DES install direct ISR vector    *(unsigned int *) 0x2000011c = (unsigned int)&new_irq7or1_isr; //DES install direct ISR vector #endif      _interrupt_controller_unmask(MCF5225_INT_EPORT0_EPF7); //DES unmask IRQ7   _interrupt_controller_unmask(MCF5225_INT_EPORT0_EPF5); //DES unmask IRQ7         reg_ptr->GPIO.PTCPAR |= 0x01;   reg_ptr->GPIO.PTCPAR &= ~0x02;   //reg_ptr->DMA_TIMER[ 0 ]-> DTMR = (pointer)(&((VMCF5225_STRUCT_PTR)_PSP_GET_IPSBAR())->DMA_TIMER[ 0 ]);   reg_ptr->DMA_TIMER[ 0 ].DTMR = (Prescaler << 8 ) |              (CaptureEdge << 6) |             (OutputMode << 5)|              (IntEnable << 4) |              (Restart << 3) |              (ClkSource << 1)|             (EnableTimer);   reg_ptr->DMA_TIMER[ 0 ].DTMR &= ~0x0001; //detiene el timer   reg_ptr->DMA_TIMER[ 0 ].DTCN = 0x0000;  //valor inicial de la cuenta   reg_ptr->DMA_TIMER[ 0 ].DTRR = 0x0001;  //valor de referencia                  reg_ptr->DMA_TIMER[ 0 ].DTER = 0x03;    //borrar las banderas de eventos   reg_ptr->DMA_TIMER[ 0 ].DTMR |= 0x0001; //inicia el timer   *(unsigned int *) 0x2000014C = (unsigned int)&dtim0_isr; //DTIM0 install direct ISR vector   _interrupt_controller_unmask(MCF5225_INT_DTIM0); //DES unmask IRQ7#elif BSP_M52259DEMO   _int_install_kernel_isr(MCF5225_INT_EPORT0_EPF1, new_irq7or1_isr);   _interrupt_controller_unmask(MCF5225_INT_EPORT0_EPF1); //DES unmask IRQ1#else #error BSP_M52259EVB or BSP_M52259DEMO#endif   for(initial_data=0;initial_data<20;initial_data++)   {     _time_delay_ticks(200); //DES was 200     printf("\nTick count = %d   bcnt = %d\n", isr_ptr->TICK_COUNT, bcnt);   }   _mqx_exit(0);}

 

 

 

 

 

0 Kudos
1,383 Views
JaimeR
Contributor III

Okay, IRQ5 is working now but I can't get DTIM0 to work, what could I be missing?

 

1.-I have GPIO register for pin configuration.

 

   reg_ptr->GPIO.PTCPAR |= 0x01;
   reg_ptr->GPIO.PTCPAR &= ~0x02;

 

 

2.-DMA Timer register configuration.

 

   #define Prescaler   0x00  //8bits-
   #define CaptureEdge 0x2   //2 bits
   #define OutputMode  0x0   //1 bit
   #define IntEnable   0x1   //1 bit
   #define Restart     0x1   //1 bit
   #define ClkSource   0x3   //2bits
   #define EnableTimer 0x0   //1bit

 

   reg_ptr->DMA_TIMER[ 0 ].DTMR = (Prescaler << 8 ) |
                                     (CaptureEdge << 6) |
                                     (OutputMode << 5)|
                                     (IntEnable << 4) |
                                     (Restart << 3) |
                                     (ClkSource << 1)|
                                     (EnableTimer);
   reg_ptr->DMA_TIMER[ 0 ].DTMR &= ~0x0001; //detiene el timer
   reg_ptr->DMA_TIMER[ 0 ].DTCN = 0x0000;  //valor inicial de la cuenta
   reg_ptr->DMA_TIMER[ 0 ].DTRR = 0x0001;  //valor de referencia              
   reg_ptr->DMA_TIMER[ 0 ].DTER = 0x03;    //borrar las banderas de eventos
   reg_ptr->DMA_TIMER[ 0 ].DTMR |= 0x0001; //inicia el timer

 

3.-DTIM0 direct ISR vector installation.

 

*(unsigned int *) 0x2000014C = (unsigned int)&dtim0_isr;    //DTIM0 install direct ISR vector

 

 

 

 

0 Kudos
1,384 Views
DavidS
NXP Employee
NXP Employee

In your user_config.h header file do you have the following #define?

#define MQX_ROM_VECTORS          0  //DES was 1  1=ROM, 0=RAM vector table

Setting to 0 has the VBR in RAM so you can add your direct vector during run-time.  If you leave VBR in ROM, then add your direct vector to the vector table (in bps vector.c).

Regards,

David

0 Kudos
1,384 Views
JaimeR
Contributor III
Yes, I have it #define MQX_ROM_VECTORS          0  .
0 Kudos
1,384 Views
DavidS
NXP Employee
NXP Employee
Hi Jaime,
Enclosed is the updated file.  I got the DTIM working and figure you can give the GPT a try.  Hope that is OK.
Issues I found:
1) DTIM0 is being used/touched by RTOS so switched to using DTIM3
2) Changed the DTMR FRR bit to 0 from 1.
3) Added code to initialize the ICR22 register.
4) updated DTIM ISR to clear interrupt flag.
 
My testing was not extensive.  On the EVB I used a jumper from J1 pin 40/TIN3 to BDM pin 25/VDD for high and BDM pin 23/GND for low.
If not connected, the pin floats and interrupt is generated often.  Note that when halted and swap jumper locations this float state causes a capture interrupt to be registered.
If connected to high no interrupt until you disconnect and connect to low (I do this while HALTed).  Then only one interrupt generated.  If not HALTed then lots of interrupts because of the float state.
If connected to low no interrupt until you disconnect and connect to low (I do this while HALTed).  Then only one interrupt generated.  If not HALTed then lots of interrupts because of the float state.
 
Regards,
David
0 Kudos
1,384 Views
eGuy
Contributor IV

Hi,

 

I followed the example to direct IRQ7 to my own isr handler.

 

However, there is no problem if the port is configured as Edge triggered. ( bcnt increased 1if there is interrupt  ---- I am using s "ABORT" switch in 52259EVB ).

 

But if the port is configured as Level triggered, it will keep triggering the interrupt if ABORT button is pressed.So the isr handler is called numerous times................ Is this right?

 

 

Thanks

 

eGuy

0 Kudos
1,384 Views
DavidS
NXP Employee
NXP Employee

Hi eGUY,

Edge sensitive IRQs latch the edge and generate one interrupt to the core.  It will not generate another interrupt until it has negated and then again gone low (i.e. generates an edge).

Level sensitive IRQs will generate interrupt as long as the IRQ signal is low.

Regards,

David

0 Kudos
1,384 Views
eGuy
Contributor IV

Thanks.

 

I use edge sensitive interrupt solved the problem.

0 Kudos
1,384 Views
DavidS
NXP Employee
NXP Employee

Hi MQXUser,

Enclosed is an enhanced version of the Freescale MQX 3.4\mqx\examples\isr example.

In the main_task() you can choose to have a direct ISR or allow FSLMQX to handle it.  Here is that piece of code:

#if 1 //DES 0=direct ISR preempts MQX, 1=kernel isr handles the exception

_int_install_kernel_isr(MCF5225_INT_EPORT0_EPF7, new_irq7or1_isr);

#else

*(unsigned int *) 0x2000011c = (unsigned int)&new_irq7or1_isr; //DES install direct ISR vector

#endif

 

Note I haven't updated all the comments in the file.  I've tested this with the M52259EVB and the ABORT/IRQ7 switch.

Regards,

David

 

isr.c

Message Edited by t.dowe on 2009-12-02 11:09 AM
0 Kudos
1,384 Views
MQXuser
Contributor III

Thank you for your answer David, I have looked the example and I have a few doubts:

 

On MQXUG I read:

 

An interrupt comes at periodic intervals that my application must respond to very quickly
— quicker than MQX allows. What can I do?
Call _int_install_kernel_isr() to replace the kernel ISR (_int_kernel_isr()). Your replacement ISR must:
• Save all registers on entry, and restore them on exit.
• It must not call any MQX functions.
• Pass information to other tasks (if required) by an application-implemented mechanism (usually
ring buffers with head and tail pointers and total size fields).

 

 

In your example,#if 1  you call _int_install_kernel_isr, therefore I am asuming kernel will handle the interrupt but in the UG I read "Call _int_install_kernel_isr() to replace the kernel ISR". This is confusing, could you explain when to use _int_install_kernel_isr ?

 

Then, the UG states that in order to  handle an Interrupt outside MQX I must "Save all registers on entry, and restore them on exit". I don't see where is this done in the isr.c example, so is it missing?, is it not necesary to do this?

 

Finally, I see you are using a global variable in the example (volatile uint_32 bcnt)  to pass information from the interrupt to the main task but again, the UG suggest to use "usually ring buffers with head and tail pointers".Can I use just a global variable or should I implement a sofisticated mechanism?

 

Thanks

 

0 Kudos
1,384 Views
DavidS
NXP Employee
NXP Employee

Hi...sorry for dealyed response.

Answers below:

 

On MQXUG I read:

 

An interrupt comes at periodic intervals that my application must respond to very quickly
— quicker than MQX allows. What can I do? 
ANSWER: MQX can handle kHz's frequent interrupts but if you want you can do a direct interupt by changing the #define to a 0 rather than 1.

ex:  

#if 1 //DES 0=direct ISR preempts MQX, 1=kernel isr handles the exception

This assumes your vector table is in RAM.


Call _int_install_kernel_isr() to replace the kernel ISR (_int_kernel_isr()). Your replacement ISR must:
• Save all registers on entry, and restore them on exit.  ANSWER: The compiler handles this for you.  This note really applies to assembly coded routines.
• It must not call any MQX functions.
• Pass information to other tasks (if required) by an application-implemented mechanism (usually
ring buffers with head and tail pointers and total size fields).

 

 

In your example,#if 1  you call _int_install_kernel_isr, therefore I am asuming kernel will handle the interrupt but in the UG I read "Call _int_install_kernel_isr() to replace the kernel ISR". This is confusing, could you explain when to use _int_install_kernel_isr ?  ANSWER: Cool feature MQX gives you is that if an interrupt is being used by MQX, MQX lets you use it too.  The default example code shows this well as does the modified code.  At the beginning of the main_task() function the "old" vector information is added to a isr_ptr structure.  Once you place your new ISR handler into the MQX hands, your code wil be called and it is your new ISR codes responsibility to call "old/orginal" isr.  This basically creates a linked list of ISRs in this case two deep....your new isr and the old isr.

 

Then, the UG states that in order to  handle an Interrupt outside MQX I must "Save all registers on entry, and restore them on exit". I don't see where is this done in the isr.c example, so is it missing?, is it not necesary to do this?  ANSWER: The compiler handles this for you.  This note really applies to assembly coded routines.
 

 

Finally, I see you are using a global variable in the example (volatile uint_32 bcnt)  to pass information from the interrupt to the main task but again, the UG suggest to use "usually ring buffers with head and tail pointers".Can I use just a global variable or should I implement a sofisticated mechanism?  ANSWER: Its implementation specific so what works for you is fine.  In this case the global works but if I had other tasks accessing that global then not best solution.

 

 

 

 

Regards,

David

0 Kudos