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++
12603 Discussions

interfacing to custom logic with an interrupt

Altera_Forum
Honored Contributor II
1,280 Views

I have made an interface to custom logic using an avalon slave port with the following signals, 

 

clk, irq, readdata, address, read, chipselect 

 

the idea is that custom logic can set the irq line high, wait for the nios-ii to read the data, then set it low again.  

 

However in practice, the sotfware creates the interrupt OK, goes into the ISR, but never calls the DSR, and if I try to read from the port in the ISR, it seems to read the data, but never sends a read or chipselect signal, 

 

below is some code excerpts 

 

creating the interrupt in cyg_user_start... 

   cyg_handle_t intrpt_handle;  cyg_interrupt intr_mem;    diag_printf("Initialising the interrupt\n");    cyg_interrupt_create( INTERRUPT_INTERFACE_0_IRQ,        0,        0,        &isr_interrupt_interface,        &dsr_interrupt_interface,        &intrpt_handle,        &intr_mem); cyg_interrupt_attach( intrpt_handle); cyg_interrupt_unmask(INTERRUPT_INTERFACE_0_IRQ); 

the isr and dsr... 

 

cyg_uint32 isr_interrupt_interface(cyg_vector_t vector, cyg_addrword_t data) {     volatile unsigned short *isr_reg_addr = (unsigned short *)INTERRUPT_INTERFACE_0_BASE;       // Block this interrupt from occurring until     // the DSR completes.     cyg_interrupt_mask( vector );     // Tell the processor that we have received     // the interrupt.     cyg_interrupt_acknowledge( vector );     isr_data = *isr_reg_addr;     bldy_isr++;   return  CYG_ISR_CALL_DSR; } void dsr_interrupt_interface(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t z_isr_data) {    volatile unsigned short *isr_reg_addr = (unsigned short *)INTERRUPT_INTERFACE_0_BASE;    //bldy_isr++;    isr_data++;// = *isr_reg_addr;    cyg_interrupt_unmask( vector ); } 

 

bldy_isr and isr_data are two global variables that I can use to check what is happening 

 

Can someone give me a few clues as to what to do find out why the DSR is not called, and also I cannot find any documentation as to how long the irq must be asserted for. The avalon interface specification says... 

 

<div class='quotetop'>QUOTE </div> 

--- Quote Start ---  

9.1.1. Slave Interrupt Signal: irq  

... The peripheral logic must assert irq continuously until a master port explicitly resets the interrupt request.[/b] 

--- Quote End ---  

 

How does a master port reset the irq?
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
350 Views

Hi manns, 

 

> I cannot find any documentation as to how long the irq must be asserted for. 

 

See the "Nios II Processor Reference Handbook", the sub-section entitled, "Integral Interrupt Controller". 

 

IRQ signals are level-sensitive. So, they must be asserted until explicitly negated (in most cases 

by the CPU data master as a result of a software action). The bottom line is your logic must 

maintain the level at least long enough for the interrupt to be recognized (CPU transfers 

execution to the exception address) and the exception handler identifies the specific IRQ that 

caused the exception. 

 

> The avalon interface specification says... 

> Slave Interrupt Signal: irq 

> ... The peripheral logic must assert irq continuously until a master port explicitly resets the interrupt 

> request. 

> How does a master port reset the irq? 

 

In most cases your software will read a register, clear/set a bit, whatever. This is up to you ... 

some mechanism your custom logic provides. 

 

Regards, 

--Scott
0 Kudos
Altera_Forum
Honored Contributor II
350 Views

thanks Scott, 

 

I&#39;m pretty sure that the logic is not the problem now. It resets the irq when it detects a read and chipselect going high.  

 

I&#39;ve tested this by reading the register outside of the ISR (when the irq is high), and sure enough everything goes fine.  

 

So... 

 

Why when I&#39;m in the ISR and read from this register, doesn&#39;t the read get asserted? 

 

and... 

 

Why doesn&#39;t the DSR ever get called?
0 Kudos
Altera_Forum
Honored Contributor II
350 Views

I don&#39;t know if you&#39;ve got to the bottom of this, but it looks to me like the offending line of code is: 

 

isr_data = *isr_reg_addr; 

 

This is accessing your peripheral through the data cache (assuming you have one). It therefore may or may not cause a real access, which may cause you to fail to clear the interrupt. To avoid this problem you should use one of the access macros defined in hal_io.h, e.g.: HAL_READ_UINT32.
0 Kudos
Altera_Forum
Honored Contributor II
350 Views

I wasn&#39;t using a data cache, but have changed to using the access macros to avoid possible problems later down the track. Thanks for the tip. 

 

I&#39;ve managed to sort out the issue since and are able to clear the interrupt. It was (embarrassingly) a combination of logic functions and how I was viewing the problem. 

 

However the DSR is still not being called. We are running from ROM only, and need to get debugging capability up and running to go further with this one...
0 Kudos
Altera_Forum
Honored Contributor II
350 Views

In my system, my ISR returns CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; yours is omitting CYG_ISR_HANDLED. Not sure how much of a problem this is; I know that, at least, it will go poll every ISR if you don&#39;t have it. Maybe it&#39;s ignoring CYG_ISR_CALL_DSR since CYG_ISR_HANDLED isn&#39;t there? 

 

Also, I have to concur that it&#39;s good to access peripherals via only IORD/IOWR macros; it&#39;s one less thing to worry about.
0 Kudos
Reply