- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
thanks Scott,
I'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'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'm in the ISR and read from this register, doesn't the read get asserted? and... Why doesn't the DSR ever get called?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't know if you'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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I wasn'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'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...- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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't have it. Maybe it's ignoring CYG_ISR_CALL_DSR since CYG_ISR_HANDLED isn't there?
Also, I have to concur that it's good to access peripherals via only IORD/IOWR macros; it's one less thing to worry about.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page