MOD54415 IRQ
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
MOD54415 IRQ
Hey all,
Probably a simple software question, but I couldn't quite discern the answer from the runtime library - keep in mind I'm not that good with software - yet...
Anyways, I have to ask this because my board isn't assembled yet so I can't test it.
I've enabled IRQ1 and IRQ2 on my system, and have the ISR routines set up as such:
SetPinIrq( 43, -1, &LockoutISR);
SetPinIrq( 45, -1, &OBSModeISR);
void OBSModeISR(void)
{
// ISR subroutine for manual observation mode
}
void LockoutISR(void)
{
// ISR subroutine for manual Lockout - only hard reset brings it out
while(1);
}
My question is, can I create a while loop in the ISR that polls the IRQ pin to see if the state has changed? or is that not valid in an ISR? For instance, if using IRQ2:
while (!J2[43])
{
//do stuff
}
//rest of IRQ ISR stuff here...
My IRQ pins are connected to a toggle switch via schmitt trigger for manual control of my machine. Basically I want the ISR to loop until the switch state changes...
Sorry if it sounds like a simple question, just had to ask before I turn this thing on this week. Thanks!!
Probably a simple software question, but I couldn't quite discern the answer from the runtime library - keep in mind I'm not that good with software - yet...
Anyways, I have to ask this because my board isn't assembled yet so I can't test it.
I've enabled IRQ1 and IRQ2 on my system, and have the ISR routines set up as such:
SetPinIrq( 43, -1, &LockoutISR);
SetPinIrq( 45, -1, &OBSModeISR);
void OBSModeISR(void)
{
// ISR subroutine for manual observation mode
}
void LockoutISR(void)
{
// ISR subroutine for manual Lockout - only hard reset brings it out
while(1);
}
My question is, can I create a while loop in the ISR that polls the IRQ pin to see if the state has changed? or is that not valid in an ISR? For instance, if using IRQ2:
while (!J2[43])
{
//do stuff
}
//rest of IRQ ISR stuff here...
My IRQ pins are connected to a toggle switch via schmitt trigger for manual control of my machine. Basically I want the ISR to loop until the switch state changes...
Sorry if it sounds like a simple question, just had to ask before I turn this thing on this week. Thanks!!
-
- Posts: 513
- Joined: Sat Apr 26, 2008 7:14 am
Re: MOD54415 IRQ
Not a good idea to tie up an IRQ in a while loop, particularly one that waits for user input that nay never arrive. Much better to post a semaphore to a task that can pending on user input when and if it shows up, or that can pend for a finite time before handling an error.If you go this route, your ISR should probably reconfigure the pin funtion from IRQ to GPIO so a task can polll the input. when the task completes (if successful) the last step would be to reconfigure the pin as an IRQ.
Alternatively, how about having two ISRs, one for rising edge, one for falling edge. Each time an ISR runs, it installs the opposite-sense ISR vector and also reconfigures the IRQ itself to trigger on the opposite edge. Normally I'd avoid something like this, but you might get way with it without a debounce timer due to the schmidt trigger...
Alternatively, how about having two ISRs, one for rising edge, one for falling edge. Each time an ISR runs, it installs the opposite-sense ISR vector and also reconfigures the IRQ itself to trigger on the opposite edge. Normally I'd avoid something like this, but you might get way with it without a debounce timer due to the schmidt trigger...
Re: MOD54415 IRQ
I wouldn't recommend that. Not only will you be halting whatever control you want paused, you'll be starving everything else (I/O, watchdog, etc.). I.E., can you guarantee that the pin will be deasserted within some very small timeframe (few uSeconds)?
If that's the behavior you want, I'd probably suggest that you get the initial change via a edge trigger going one way, set the Edgeport to trigger going the other way and exiting the IRQ. The second time the IRQ fires, you'll be in the state you want, and can then execute whatever control you need. If you want to stall some control for the duration, put a pause boolean and semaphore in the control loop, and set the flag on the way into the assert IRQ, and clear it and post on the way into the deassert semaphore. (Or use a queue if you're concerned with command collisions).
-Dan
[Edit: It appears that Ridgeglider posted basically the same thing as I typed this... Good to know we've got consensus out there ]
If that's the behavior you want, I'd probably suggest that you get the initial change via a edge trigger going one way, set the Edgeport to trigger going the other way and exiting the IRQ. The second time the IRQ fires, you'll be in the state you want, and can then execute whatever control you need. If you want to stall some control for the duration, put a pause boolean and semaphore in the control loop, and set the flag on the way into the assert IRQ, and clear it and post on the way into the deassert semaphore. (Or use a queue if you're concerned with command collisions).
-Dan
[Edit: It appears that Ridgeglider posted basically the same thing as I typed this... Good to know we've got consensus out there ]
Dan Ciliske
Project Engineer
Netburner, Inc
Project Engineer
Netburner, Inc
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
Re: MOD54415 IRQ
Dan and Ridgeglider -
I can give you this much information about what this is:
I have a toggle switch on both IRQ1 and IRQ2 that interrupts whatever the system is doing and runs the ISR. When IRQ2 is toggled, I want the system to loop indefinitely so that the the only way to break that loop is a hard reset. This is a safety feature for my project. When IRQ 1 toggles, it will enter an "Observation Mode" so to speak where it only monitors the system and sends UDP data to the computer. But as for IRQ1, when the switch changes, I want it to return to the task it was called from. But, while that IRQ pin is low, it needs to loop through a task.
My other option is to make both of these IRQs trigger an endless loop that needs a hard reset to break from. Again, safety feature. I guess I could use the ISR to set a flag in the system and have that flag trigger a mode upon return. That's simple enough. I did not realize that the IO pins were deasserted during the routine. Does that include all ethernet traffic as well?
Anyways, thanks for the input guys!!
I can give you this much information about what this is:
I have a toggle switch on both IRQ1 and IRQ2 that interrupts whatever the system is doing and runs the ISR. When IRQ2 is toggled, I want the system to loop indefinitely so that the the only way to break that loop is a hard reset. This is a safety feature for my project. When IRQ 1 toggles, it will enter an "Observation Mode" so to speak where it only monitors the system and sends UDP data to the computer. But as for IRQ1, when the switch changes, I want it to return to the task it was called from. But, while that IRQ pin is low, it needs to loop through a task.
My other option is to make both of these IRQs trigger an endless loop that needs a hard reset to break from. Again, safety feature. I guess I could use the ISR to set a flag in the system and have that flag trigger a mode upon return. That's simple enough. I did not realize that the IO pins were deasserted during the routine. Does that include all ethernet traffic as well?
Anyways, thanks for the input guys!!
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
Re: MOD54415 IRQ
Ridgeglider-
No need for debounce timer for the switch. I've got a 100ns one-shot in place to take care of that.
No need for debounce timer for the switch. I've got a 100ns one-shot in place to take care of that.
Re: MOD54415 IRQ
I think before I put a killer loop in an IRQ I would consider if a call to exit(1), might not be a kinder choice. I'm not sure, but I suspect you might not even be able to re-flash without physically resetting, with the killer loop approach. I do know for a fact (because I just tried it on a 5272) that if you exit() you can still re-flash over Ethernet without a reset.
-
- Posts: 513
- Joined: Sat Apr 26, 2008 7:14 am
Re: MOD54415 IRQ
Let's take it one by one.
IRQ2 has two modes: let's say that when the input goes low, things run normally. When the input goes hi, things loop forever until RESET is pressed (brutal!). I'd setup two ISRs:
The first ISR triggers when the IRQ2 input falls to start normal operation. This would also be the ISR and input edge sensitivity you'd setup immediately following a reset at power up. In these 2 situations you need to reconfigure the IRQ so that the next time IRQ1 fires (eg when the input rises) the reset lockout mode occurs. Do this by installing an alternate ISR vector that will run when the input goes hi. Additionally, change the EPORT trigger so that next time, the IRQ will fire on the rising edge. Otherwise, the ISR that runs on the falling edge doesn't do much else.
The second ISR triggers when the input rises. When the input rises, you no longer want the switch to have any effect, either immediately, or if switched low. To do this, the ISR should disable all other IRQs and kill any running hardware (eg timers, PWMs, etc), then post a semaphore to a simple task that has the highest possible priority in and no blocks, ie no OSTimeDlys or other blocking calls. Because that task will have the highest prio, it will run, and because it never blocks no other tasks will run so the system will be quite literally be locked out. The only way out will be a reset, although in my opinion, this scenario is quite draconian. At a minimum, I'd provide some LED signal or iprintf() message (followed by a brief delay) indicating that things are totally dead. Sounds like you might want a different failsafe???
Not sure we fully understand your IRQ1 needs... However, if, by 'loop through a task' you mean executing a linear series of functions in a task while the input is low, versus running a single function when the IRQ1 input is high, why not have the interrupt just point the core of the task you mentioned to two different tables of function pointers, one with the normal flow, one with the observation function(s)? Not sure this is really applicable, but it might be a start? To do this, once again you'd have two sets of ISRs and IRQ level settings for IRQ1 that flip flop between what ISR triggers on rising or falling edges.
IRQ2 has two modes: let's say that when the input goes low, things run normally. When the input goes hi, things loop forever until RESET is pressed (brutal!). I'd setup two ISRs:
The first ISR triggers when the IRQ2 input falls to start normal operation. This would also be the ISR and input edge sensitivity you'd setup immediately following a reset at power up. In these 2 situations you need to reconfigure the IRQ so that the next time IRQ1 fires (eg when the input rises) the reset lockout mode occurs. Do this by installing an alternate ISR vector that will run when the input goes hi. Additionally, change the EPORT trigger so that next time, the IRQ will fire on the rising edge. Otherwise, the ISR that runs on the falling edge doesn't do much else.
The second ISR triggers when the input rises. When the input rises, you no longer want the switch to have any effect, either immediately, or if switched low. To do this, the ISR should disable all other IRQs and kill any running hardware (eg timers, PWMs, etc), then post a semaphore to a simple task that has the highest possible priority in and no blocks, ie no OSTimeDlys or other blocking calls. Because that task will have the highest prio, it will run, and because it never blocks no other tasks will run so the system will be quite literally be locked out. The only way out will be a reset, although in my opinion, this scenario is quite draconian. At a minimum, I'd provide some LED signal or iprintf() message (followed by a brief delay) indicating that things are totally dead. Sounds like you might want a different failsafe???
Not sure we fully understand your IRQ1 needs... However, if, by 'loop through a task' you mean executing a linear series of functions in a task while the input is low, versus running a single function when the IRQ1 input is high, why not have the interrupt just point the core of the task you mentioned to two different tables of function pointers, one with the normal flow, one with the observation function(s)? Not sure this is really applicable, but it might be a start? To do this, once again you'd have two sets of ISRs and IRQ level settings for IRQ1 that flip flop between what ISR triggers on rising or falling edges.
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
Re: MOD54415 IRQ
Ridgeglider - Just a quick note before my meeting -
This is routine is part of a power system. There's an external D-SUB that a manual control box plugs into. The spec I was given was that once plugged in, the manual box has complete control. There's a switch that is allowed to place the unit in either complete lockout (off - no power) or an observation mode. The lockout mode via switch kills the power to the netburner unit, but a software lockout is required just in case the power relay fails. It was determined that when the controller was plugged in, a hard reset would be necessary to remove it from the software lockout mode. As for the observation mode, It's required that when in that mode, the only operations allowed were to poll the GPIO data, and the ADC, and transmit their states to the computer via UDP. I'll be back after my meeting, or first thing in the morning. Thanks for your time with this one!
Tony
This is routine is part of a power system. There's an external D-SUB that a manual control box plugs into. The spec I was given was that once plugged in, the manual box has complete control. There's a switch that is allowed to place the unit in either complete lockout (off - no power) or an observation mode. The lockout mode via switch kills the power to the netburner unit, but a software lockout is required just in case the power relay fails. It was determined that when the controller was plugged in, a hard reset would be necessary to remove it from the software lockout mode. As for the observation mode, It's required that when in that mode, the only operations allowed were to poll the GPIO data, and the ADC, and transmit their states to the computer via UDP. I'll be back after my meeting, or first thing in the morning. Thanks for your time with this one!
Tony
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
Re: MOD54415 IRQ
Tod,
I'm not following your exit() suggestion. My understanding is that the OSIntEnter() and OSIntExit() functions are invoked by the OS, and only a pointer to the ISR was necessary. I did not find any reference to the exit() function. Could you elaborate?
I'm not following your exit() suggestion. My understanding is that the OSIntEnter() and OSIntExit() functions are invoked by the OS, and only a pointer to the ISR was necessary. I did not find any reference to the exit() function. Could you elaborate?
-
- Posts: 192
- Joined: Mon Dec 17, 2012 6:24 am
Re: MOD54415 IRQ
So in an attempt to solve this I've utilized a bool function for each ISR. I check that it's been set when entering the ISR, if not, it is set, and the ISR sets the IRQ to trigger on the opposite signal edge as Dan suggested, and resets back to it's original state when returning back to to the main tasks. This seems to make more sense as these hardware driven signals will be gone when the manual controller is unplugged. Here's some code:
void OBSModeISR(void)
{
if (!OBSERVE_FLAG)
{
//put everything here to make sure that system enters obs mode - no subroutines from ISR
J1[31] = 1; // drive enable pin high to allow remote manual access.
J1[13] = 0; // drive inhibit pin low to allow system to operate
J2[19] = 1;
J2[20] = 1;
J2[44] = 1; // pulls DAC reset low to reset
for (int o = 0; o < 25000; o++); // 0.1 second delay
J2[44] = 0; // pulls DAC reset high to end reset cycle
enabled = false;
error = false;
inhibited = false;
lockout = false;
ready = false;
observe = true; // set for observation mode
SetPinIrq( 45, 1, &OBSModeISR); // rising edge takes out of observe mode
}
if (OBSERVE_FLAG)
{
// put everything here to make sure we enter idle mode coming out of observation mode
observe = false;
idle = true;
OBSERVE_FLAG = false;
SetPinIrq( 45, -1, &OBSModeISR); // reset for trigger on falling edge
}
}
One last question I have about this process, and maybe this is my lack of complete knowledge of C and C++, When I exit the ISR, no matter what, I do not want the OS to return to it's last thread. I would like it to actually jump straight to the while(1) loop in UserMain(). How do I accomplish this? I'm assuming that I will have to clear the transmit buffers for SPI, I2C, and UDP just in case it was in the middle of those threads...
void OBSModeISR(void)
{
if (!OBSERVE_FLAG)
{
//put everything here to make sure that system enters obs mode - no subroutines from ISR
J1[31] = 1; // drive enable pin high to allow remote manual access.
J1[13] = 0; // drive inhibit pin low to allow system to operate
J2[19] = 1;
J2[20] = 1;
J2[44] = 1; // pulls DAC reset low to reset
for (int o = 0; o < 25000; o++); // 0.1 second delay
J2[44] = 0; // pulls DAC reset high to end reset cycle
enabled = false;
error = false;
inhibited = false;
lockout = false;
ready = false;
observe = true; // set for observation mode
SetPinIrq( 45, 1, &OBSModeISR); // rising edge takes out of observe mode
}
if (OBSERVE_FLAG)
{
// put everything here to make sure we enter idle mode coming out of observation mode
observe = false;
idle = true;
OBSERVE_FLAG = false;
SetPinIrq( 45, -1, &OBSModeISR); // reset for trigger on falling edge
}
}
One last question I have about this process, and maybe this is my lack of complete knowledge of C and C++, When I exit the ISR, no matter what, I do not want the OS to return to it's last thread. I would like it to actually jump straight to the while(1) loop in UserMain(). How do I accomplish this? I'm assuming that I will have to clear the transmit buffers for SPI, I2C, and UDP just in case it was in the middle of those threads...