Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
12748 Discussions

Nested interrupts and uart question with HAL

Altera_Forum
Honored Contributor II
1,304 Views

Hi, 

 

The setup is the following :  

- a stratix II GX hosts a Nios IIe 

- one timer running continuously at a period of 1s, priority level 6, the handler for this interrupt has some functions calls to usleep and performs polling, this handler is made interruptible via the use of the alt_irq_interruptible and alt_irq_noninterruptible pair of functions 

- one hw interrupt generates an interrupt every 500 us with a prioity level 2 a uart running at 115 kbauds using the small driver implementation (no interrupt) 

- the main function of the C program is waiting forever for characters to come in via the uart and when a command is received it processes it and gets back to expecting a new command forever 

 

With this setup it seems that the uart does not work well. When I pause the program after noticing it does not respond the program is almost always located in the usleep function called from the low priority interrupt handler. Is there anything in the setup described that is bad design ? What am i missing ? All ideas are welcome ! 

 

Best regards, 

 

JF
0 Kudos
2 Replies
Altera_Forum
Honored Contributor II
457 Views

If you pause the program manually, chances are it's going to stop in a sleep handler. Why not set a breakpoint in your UART ISR? I *think* you might then be able to see the timer ISR in the call stack. 

 

Failing that, you could try the following bit banging technique. I don't use the alt_irq_interruptible and alt_irq_noninterruptible functions. 

 

What the following does is set the IRQ mask to choose what IRQs you don't want to the serviced (note this includes the current IRQ number to avoid another instance of it running). It then remembers the "global IRQ enable" state, and forces it on. 

 

The "finish" routine merely resets the state noted in the "start" routine. 

 

Please let me know if I've got anything wrong! 

 

# ifndef _IRQ_DEBUG_H_# define _IRQ_DEBUG_H_ // ---------------------------------------------------------------------------- extern volatile alt_u32 alt_irq_active; // ---------------------------------------------------------------------------- // 26/09/05 - Call this within an ISR to allow other handlers to run static ALT_INLINE alt_irq_context ALT_ALWAYS_INLINE IRQ_ALLOW_ESSENTIAL_START (alt_u32 id, alt_u32* pActive) { alt_irq_context Ctrl0; alt_u32 irq_mask; // irq_mask = ~(0x0FFFFFFFF << id); //mask out self and all others of lower priority irq_mask = (~(1 << id)) & 0x000FFFFFF; //mask out self and IRQs 32-29, 28-25 *pActive = alt_irq_active; alt_irq_active &= irq_mask; NIOS2_WRITE_IENABLE (alt_irq_active); /* equivalent to: alt_irq_disable (id); //avoid re-entry alt_irq_disable (IRQ1); //disable those that can wait alt_irq_disable (IRQ2); ...etc */ NIOS2_READ_STATUS (Ctrl0); Ctrl0 |= NIOS2_STATUS_PIE_MSK; NIOS2_WRITE_STATUS (Ctrl0); return (Ctrl0); } // ---------------------------------------------------------------------------- static ALT_INLINE void ALT_ALWAYS_INLINE IRQ_ALLOW_ESSENTIAL_FINISH (alt_irq_context Ctrl0, alt_u32 id, alt_u32 Active) { Ctrl0 &= ~NIOS2_STATUS_PIE_MSK; NIOS2_WRITE_STATUS (Ctrl0); /* * equivalent to..... alt_irq_enable (IRQ1); .... alt_irq_enable (id); */ alt_irq_active = Active; NIOS2_WRITE_IENABLE (Active); } // ---------------------------------------------------------------------------- # endif //_IRQ_DEBUG_H_ in ISR: 

// class DeviceDriver..... // public: // static void Handle_Device_IRQ (void* context, alt_u32 id) void DeviceDriver::Handle_Device_IRQ (void* context, alt_u32 id) { alt_irq_context Ctrl0; alt_u32 Active; //do something uninterruptible //Allow other high priority IRQs to be serviced Ctrl0 = IRQ_ALLOW_ESSENTIAL_START (id, &Active); //do something interruptible IRQ_ALLOW_ESSENTIAL_FINISH (Ctrl0, id, Active); }
0 Kudos
Altera_Forum
Honored Contributor II
457 Views

Hi, 

 

Thank you for the information. Actually, I increased the size of the stack and heap because I had many function calls made (up to 16 as far as I could notice) and when I checked when stuck some global variables value they were not at all coherent so I believe they were crushed by some overflow ! 

I have a question regarding the usleep function though. In our first implementation we used the usleep function from within the interrupt handler of the timer. It is written in the HAL reference document that usleep is not available from within an ISR. While reading the usleep actual code am I not sure why this is the case ! Could some one provide some information about usleep ? 

 

Best regards, 

 

JF Hasson
0 Kudos
Reply