ISR for EPORT IRQ not working in MQX on MCF52255

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

ISR for EPORT IRQ not working in MQX on MCF52255

Jump to solution
1,743 Views
ARQuattr
Contributor IV

I'm trying to set up a simple pin interrupt on IRQ7 in MQX, but I would like to avoid using the GPIO interrupt method (GPIO_IOCTL_ENABLE_IRQ).  I've added the code below based on the MQX user guide, section 3.10.8, but modified to use the IRQ pin.  As I understand it this is the EPORT vector, and I also set some of the EPORT registers for this pin.  It installs the ISR OK, but apparently it never gets called because the tick count doesn't change.  If I set the pin as GPIO I can read the signal no problem so I don't believe there is a hardware issue.  Is there a problem with this code?

Thank you

typedef struct {

      pointer OLD_ISR_DATA;

      void (_CODE_PTR_ OLD_ISR)(pointer);

      _mqx_uint TICK_COUNT;

} MY_ISR_STRUCT, _PTR_ MY_ISR_STRUCT_PTR;



void pin_isr(pointer user_isr_ptr)

{

      MY_ISR_STRUCT_PTR isr_ptr;

     isr_ptr = (MY_ISR_STRUCT_PTR)user_isr_ptr;

      isr_ptr->TICK_COUNT++;

      /* Chain to previous notifier */

      (*isr_ptr->OLD_ISR)(isr_ptr->OLD_ISR_DATA);

}


void sensor_task(uint_32 initial_data)

{

      MY_ISR_STRUCT_PTR isr_ptr;

     isr_ptr = _mem_alloc_zero(sizeof(MY_ISR_STRUCT));

     isr_ptr->TICK_COUNT = 0;

     isr_ptr->OLD_ISR_DATA = _int_get_isr_data(MCF5225_INT_EPORT0_EPF7);

     isr_ptr->OLD_ISR = _int_get_isr(MCF5225_INT_EPORT0_EPF7);

      if (_int_install_isr(MCF5225_INT_EPORT0_EPF7, pin_isr, isr_ptr) == 0)

          printf ("Failed to install ISR\n");


     MCF_GPIO_PNQPAR |= 0x4000; //set IRQ7 pin PAR to primary function (IRQ)

     MCF_EPORT_EPPAR |= 0x4000; //set IRQ7 to rising edge triggered (see RM sec 17.4.1)

     MCF_EPORT_EPDDR &= 0x7F; //set IRQ7 pin as input (this is the reset condition)

     MCF_EPORT_EPIER |= 0x80; //enable IRQ7


     while (1) {

           _time_delay_ticks(1000);

          printf("\nTick count = %d\n", isr_ptr->TICK_COUNT);

     }

}



0 Kudos
1 Solution
1,220 Views
c0170
Senior Contributor III

Hello Angelo,

I can't locate in your code snippet where ido you enable interrupts? These 2 functions should be called to set interrupt level, unmask and enable it :  _bsp_int_init and _bsp_int_enable. All you did was install your ISR routine.

Read more information in the MQX reference manual.

Regards,

MartinK

View solution in original post

0 Kudos
13 Replies
1,221 Views
c0170
Senior Contributor III

Hello Angelo,

I can't locate in your code snippet where ido you enable interrupts? These 2 functions should be called to set interrupt level, unmask and enable it :  _bsp_int_init and _bsp_int_enable. All you did was install your ISR routine.

Read more information in the MQX reference manual.

Regards,

MartinK

0 Kudos
1,220 Views
JuroV
NXP Employee
NXP Employee

Hello,

have you set your EPORT (IRQ) functionality in the GPIO registers?

jv

1,220 Views
ARQuattr
Contributor IV

I have a new strange problem with this.  It services the interrupts and the tick count keeps getting displayed, but after the first interrupt following reset, the shell stops working.  Again I'm wondering if the ISR chaining has something to do with this, or if it is related to priority levels.  The shell task is running with priority level 13, and sensor_task is at 9.

0 Kudos
1,220 Views
JuroV
NXP Employee
NXP Employee

The chaining is not important, you don't have to do it.

1,220 Views
ARQuattr
Contributor IV

I'm still having some trouble with the interrupt handler.  Firstly, it tends to stop the shell from working.  I'm thinking it might have something to do with priority levels of the tasks.

Also, sometimes when the IRQ is serviced the program halts completely.  I understand there are some things I can't do within an ISR.  Right now I'm trying to capture the time of the event, and I'm using _time_get_elapsed_ticks and _time_diff_ticks.  Is there any problem doing this?  Otherwise there doesn't seem to be any code that should cause it to stop.  Just before exiting the ISR I have this line MCF_EPORT_EPFR |= 0x80;

Any advice why I get these lock-ups?

Thanks

Angelo

0 Kudos
1,220 Views
Martin_
NXP Employee
NXP Employee

Hi Angelo,

ICRn7 is read only set to level 7. This effectively is a non-maskable interrupt to the ColdFire core and must be handled as such. It means it can interrupt MQX at any time, even during MQX critical section, thus, you should install and use kernel isr for it and must not call any MQX API function from it.


Requirements for a kernel isr:

A kernel ISR must save the registers that it needs and must service the hardware interrupt. When the kernel ISR is finished, it must restore the registers and perform a return-from-interrupt instruction.
A kernel ISR cannot call MQX functions. However, it can put data in global data, which a task can access.

By the way, if an interrupt flag register consists of w1c bits, you should clear a bit(bits) by a simple write operation:

MCF_EPORT_EPFR = 0x80;

if you want to clear only the masked bit and not other w1c bits.

0 Kudos
1,220 Views
ARQuattr
Contributor IV

Thank you Martin for your reply.  So if I was using one of the other interrupts (1,3,5) these would not require a kernel ISR?  I would like to avoid using a kernel ISR if possible.  If I do have to do this, and if I can't call MQX functions, how can I get access to the low level timers, as I would through _time_get_elapsed_ticks?

0 Kudos
1,220 Views
Martin_
NXP Employee
NXP Employee

Right, 1, 3, 5 or ok unless you have changed the BSP default macro:

#ifndef BSP_DEFAULT_MQX_HARDWARE_INTERRUPT_LEVEL_MAX

    #define BSP_DEFAULT_MQX_HARDWARE_INTERRUPT_LEVEL_MAX    (6L)

#endif


for 1, 3, 5 you can install an MQX isr and you can call non-blocking MQX functions from MQX isrs. _time_get_elapsed_ticks() should be non-blocking, I beleive.

0 Kudos
1,220 Views
ARQuattr
Contributor IV

Thanks.  I'm not able to change the priority level for IRQ7, correct?

Are there any examples of kernel ISRs available that I could look at?

0 Kudos
1,220 Views
Martin_
NXP Employee
NXP Employee

Look into any bare metal code example with interrupts for your MCF device.

If you wish to write a kernel isr in C, CW 10.x compiler should be useful in generating prologue and epilogue for a function that is declared as interrupt routine:

__declspec(interrupt) void my_isr(void)

{

  /* your code here; call no MQX API functions */

}

0 Kudos
1,220 Views
ARQuattr
Contributor IV

I see, I thought you meant to use the MQX _int_install_kernel_isr

0 Kudos
1,220 Views
ARQuattr
Contributor IV

Yes, you're right - I had set the PAR to the primary function as shown in the code above, but I then commented it out to use it as GPIO and forgot to set it back for my last test.

I also realized after fixing this that I needed to clear the flag to avoid repeated interrupts, and now it's working as expected.  The completed isr is below.  Thank you both!

Is it important in this scenario to do the ISR chaining at the end of the function?  I assume this is necessary if MQX is relying on this interrupt, but if I haven't set that elsewhere in the code is it relevant?

Angelo

void pin_isr(pointer user_isr_ptr)

{

      MY_ISR_STRUCT_PTR isr_ptr;

     isr_ptr = (MY_ISR_STRUCT_PTR)user_isr_ptr;

     isr_ptr->TICK_COUNT++;

          //clear interrupt flag

     MCF_EPORT_EPFR |= 0x80; //clear flag bit for IRQ7 (by writing 1 to it - writing 0 has no effect)


     // Chain to previous notifier

      (*isr_ptr->OLD_ISR)(isr_ptr->OLD_ISR_DATA);

}



0 Kudos
1,220 Views
ARQuattr
Contributor IV

Thank you MartinK, that makes sense.  But those calls aren't recognized, perhaps because this is MQX3.6.2.  I checked some files in 3.8 and I see that the _bsp_int_init is usually aliased to _mcfxxxx_int_init, etc. so I put together these two lines to add after the install isr, but it's still doesn't work.  I'm not sure if I'm enabling the interrupts, or just unmasking them.  Is there some sort of master interrupt enable?

Thank you

// set the interrupt level, and unmask the interrupt in interrupt controller

_mcf5225_int_init(MCF5225_INT_EPORT0_EPF7, 3, 0, TRUE);

// enable interrupt

_mcf5225_int_unmask(MCF5225_INT_EPORT0_EPF7);



0 Kudos