Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
19 years ago

UART interrupt

I'm in the process of converting an old NIOS II project over to eCos. The interrupts do not work when I use the eCos API. Here is the relevant code.

#include <cyg/hal/system.h># include <cyg/kernel/kapi.h>
unsigned char abycin;
volatile unsigned int byrxptr = 0;
unsigned int bywrptr = 0;
cyg_uint32 uart_debug_isr(cyg_vector_t vector, cyg_addrword_t data)
{
    volatile int clr_int;
  
  // Block this interrupt from occurring until this ISR completes.
  cyg_interrupt_mask(vector);
  // Tell the processor that we have received the interrupt.
  cyg_interrupt_acknowledge(vector);
  if (!(IORD_ALTERA_AVALON_UART_STATUS(UART_DEBUG_BASE) & 0x02))    
 {
    abycin = IORD_ALTERA_AVALON_UART_RXDATA(UART_DEBUG_BASE);
    if(byrxptr < (RXBUF_SIZE_DEBUG - 2)) byrxptr++;
    else byrxptr = 0;
  }
  else clr_int = IORD_ALTERA_AVALON_UART_RXDATA(UART_DEBUG_BASE); // read UDR if framing error just to clear interrupt
  // Allow this interrupt to occur again.
  //cyg_interrupt_unmask (vector);
  // Tell the kernel that chained interrupt processing is done. 
  //return CYG_ISR_HANDLED;
  return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
}
void uart_debug_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
  //printf("DSR\n");
  //out_str("DSR\n");
  cyg_interrupt_unmask(vector);
}
void out_str(char *s)
{
  unsigned char *c;
  
  for(c = s;; c++)
  {
  if(*c == 0)
    break;
  out_char((unsigned char)*c);
  } 
}
void out_char(unsigned char c)
{
  while(!(IORD_ALTERA_AVALON_UART_STATUS(UART_DEBUG_BASE) & 0x40));
  IOWR_ALTERA_AVALON_UART_TXDATA(UART_DEBUG_BASE, c);
}
void cyg_user_start(void)
{
  int divisor = 0;
  int old = 0;
  cyg_handle_t uart_debug_handle, timer_handle;
  cyg_interrupt uart_debug_intr, timer_intr;
  cyg_interrupt_create(UART_DEBUG_IRQ, 99, 0, &uart_debug_isr, &uart_debug_dsr, &uart_debug_handle, &uart_debug_intr);
  cyg_interrupt_attach(uart_debug_handle);
  cyg_interrupt_disable();
  /* Other initialization tasks performed here */
  cyg_interrupt_enable();
  cyg_interrupt_unmask(UART_DEBUG_IRQ);
  while(1)
  {
     while (bywrptr != byrxptr) // Check to see if any data has been received by the Uart
     {
        printf("bywrptr != byrxptr\n");
        ProcessRxBuf(); // Process new data received from Uart
      }
      //while (rtdwrptr != rtdrxptr)
        //MDP();
  }
}

Is there something special that needs to be done in the nios2configtool to get interrupts to work?

3 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    originally posted by lee@Jan 2 2007, 11:54 AM

    i&#39;m in the process of converting an old nios ii project over to ecos. the interrupts do not work when i use the ecos api. here is the relevant code.

    #include <cyg/hal/system.h># include <cyg/kernel/kapi.h>
    unsigned char abycin;
    volatile unsigned int byrxptr = 0;
    unsigned int bywrptr = 0;
    cyg_uint32 uart_debug_isr(cyg_vector_t vector, cyg_addrword_t data)
    {
        volatile int clr_int;
      
      // block this interrupt from occurring until this isr completes.
      cyg_interrupt_mask(vector);
      // tell the processor that we have received the interrupt.
      cyg_interrupt_acknowledge(vector);
      if (!(iord_altera_avalon_uart_status(uart_debug_base) & 0x02))    
     {
        abycin = iord_altera_avalon_uart_rxdata(uart_debug_base);
        if(byrxptr < (rxbuf_size_debug - 2)) byrxptr++;
        else byrxptr = 0;
      }
      else clr_int = iord_altera_avalon_uart_rxdata(uart_debug_base); // read udr if framing error just to clear interrupt
      // allow this interrupt to occur again.
      //cyg_interrupt_unmask (vector);
      // tell the kernel that chained interrupt processing is done. 
      //return cyg_isr_handled;
      return cyg_isr_handled | cyg_isr_call_dsr;
    }
    void uart_debug_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
    {
      //printf("dsr\n");
      //out_str("dsr\n");
      cyg_interrupt_unmask(vector);
    }
    void out_str(char *s)
    {
      unsigned char *c;
      
      for(c = s;; c++)
      {
      if(*c == 0)
        break;
      out_char((unsigned char)*c);
      } 
    }
    void out_char(unsigned char c)
    {
      while(!(iord_altera_avalon_uart_status(uart_debug_base) & 0x40));
      iowr_altera_avalon_uart_txdata(uart_debug_base, c);
    }
    void cyg_user_start(void)
    {
      int divisor = 0;
      int old = 0;
      cyg_handle_t uart_debug_handle, timer_handle;
      cyg_interrupt uart_debug_intr, timer_intr;
      cyg_interrupt_create(uart_debug_irq, 99, 0, &uart_debug_isr, &uart_debug_dsr, &uart_debug_handle, &uart_debug_intr);
      cyg_interrupt_attach(uart_debug_handle);
      cyg_interrupt_disable();
      /* other initialization tasks performed here */
      cyg_interrupt_enable();
      cyg_interrupt_unmask(uart_debug_irq);
      while(1)
      {
         while (bywrptr != byrxptr) // check to see if any data has been received by the uart
         {
            printf("bywrptr != byrxptr\n");
            processrxbuf(); // process new data received from uart
          }
          //while (rtdwrptr != rtdrxptr)
            //mdp();
      }
    }

    is there something special that needs to be done in the nios2configtool to get interrupts to work?

    <div align='right'><{post_snapback}> (index.php?act=findpost&pid=20322)</div>

    --- Quote End ---

    You&#39;re probably suffering from the fact that the eCos port already contains a driver for the UART and two drivers talking to one piece of hardware is never good
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hey thanks, I&#39;ve got it working now using the cyg_io functions.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Has anyone gotten multiple UARTs to work in a single system?

    My default debug/diagnostics UART works fine when mapped to "/dev/haldiag", but I have two other UARTs in the system which aren&#39;t working using the cyg_io functions.

    In the nios2configtool I have TTY mode channel# 0 mapped to "/dev/uart_rtd" and TTY mode channel# 1 mapped to "/dev/uart_radio". When I do the lookup for "/dev/tty0" I receive no error, but then the processor resets somewhere inside the cyg_io_read() function.

    Am I missing something?

    void cyg_user_start(void)
    {
      cyg_io_handle_t uart_rtd_handle;
      Cyg_ErrNo error;
      char readbuf;
      cyg_uint32 readbuf_size = 1;
      
      cyg_io_init();
      error = cyg_io_lookup("/dev/tty0", &uart_rtd_handle);
      out_str("Error 1 = ");
      out_hex(error);
      while(!error)
      {
         error = cyg_io_read(uart_rtd_handle, (void *)&readbuf, &readbuf_size);
         out_hex(readbuf);
         out_char(&#39; &#39;);
      }
    }