Forum Discussion

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

NiosII UART HAL

Hello all,

Has anyone messed with the NiosII UART HAL? I've had no problem using the UART in a polled mode but every attempt I've tried to use the UART with an ISR has just screwed up everything.

I've tried modifying the SOPC design to enable hardware handshaking and then added the necessary pins in the Quartus II design but I've had no luck getting anything to work. Actually the last time I tried it I really screwed something up and had to uninstall NiosII and do a re-install in order to get anything to work.

Thanks...

1 Reply

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

    the niosII uart hal does not support hardware handshake.

    Main problem is that it does not resets RTS if the circular receive buffer gets

    full.

    I modified altera_avalon_uart.c in the following way (perhaps not the best

    way but it seems to work):

    .. in altera_avalon_uart.h

    /*

    * ALT_AVALON_UART_BUF_LEN is the length of the circular buffers used to hold

    * pending transmit and receive data. This value must be a power of two.

    */

    # define ALT_AVALON_UART_BUF_LEN (64)# define ALT_AVALON_UART_RTS_LIMIT_OFF ((ALT_AVALON_UART_BUF_LEN*3)/4)# define ALT_AVALON_UART_RTS_LIMIT_ON ((ALT_AVALON_UART_BUF_LEN*2)/4)

    .. in altera_avalon_uart.c

    int alt_avalon_uart_read (alt_fd* fd, char* ptr, int len)

    {

    ..

    ..

    /*

    * Ensure that interrupts are enabled, so that the circular buffer can

    * re-fill.

    */

    context = alt_irq_disable_all ();

    dev->ctrl |= ALTERA_AVALON_UART_CONTROL_RRDY_MSK;

    // !TF calculate number of bytes in buffer

    if(dev->rx_end>=dev->rx_start) {

    numbytes=dev->rx_end-dev->rx_start;

    }

    else {

    numbytes=ALT_AVALON_UART_BUF_LEN-(dev->rx_start-dev->rx_end);

    }

    // set RTS if RTS_ON LIMIT is reached

    if(numbytes<ALT_AVALON_UART_RTS_LIMIT_ON) {

    dev->ctrl |= ALTERA_AVALON_UART_CONTROL_RTS_MSK;

    }

    // TF!

    IOWR_ALTERA_AVALON_UART_CONTROL(dev->base, dev->ctrl);

    alt_irq_enable_all (context);

    /* Return the number of bytes read */

    return count;

    }

    static void alt_avalon_uart_rxirq (alt_avalon_uart_dev* dev,

    alt_u32 status)

    {

    ..

    ..

    ..

    /*

    * If the cicular buffer was full, disable interrupts. Interrupts will be

    * re-enabled when data is removed from the buffer.

    */

    // !TF calculate number of bytes in buffer

    if(dev->rx_end>=dev->rx_start) {

    numbytes=dev->rx_end-dev->rx_start;

    }

    else {

    numbytes=ALT_AVALON_UART_BUF_LEN-(dev->rx_start-dev->rx_end);

    }

    // clear RTS if RTS_OFF_LIMIT is reached

    if(numbytes>ALT_AVALON_UART_RTS_LIMIT_OFF) {

    dev->ctrl &= ~ALTERA_AVALON_UART_CONTROL_RTS_MSK;

    }

    // TF!

    if (next == dev->rx_start)

    {

    dev->ctrl &= ~ALTERA_AVALON_UART_CONTROL_RRDY_MSK;

    // !TF

    //dev->ctrl &= ~ALTERA_AVALON_UART_CONTROL_RTS_MSK;

    // TF!

    IOWR_ALTERA_AVALON_UART_CONTROL(dev->base, dev->ctrl);

    }

    }

    //############################################################################

    int terminal_driver_set_flowcontrol(BYTE flowctrl) {

    alt_fd* fd;

    alt_avalon_uart_dev* dev; // pointer to uart device

    if(fdterm<0) return -1;

    // see alt_ioctrl.c

    fd = (fdterm < 0) ? NULL : &alt_fd_list[fdterm];

    if (fd) {

    dev=(alt_avalon_uart_dev*)fd->dev;

    if(flowctrl) {

    dev->flags|=ALT_AVALON_UART_FC;

    }

    else {

    dev->flags&=~ALT_AVALON_UART_FC;

    }

    return 0;

    }

    return -1;

    }

    I open device uart in non blocking mode:

    static int fdterm; // FILEDESCRIPTOR RETURNED BY OPEN

    ..

    fdterm = open("/dev/uart1", O_RDWR | O_NONBLOCK | O_NOCTTY);

    ..

    reading is done by

    ..

    res=read(fdterm,uart1_tempbuff,sizeof(uart1_tempbuff)-1);

    if(res>0) {

    ... we have received some bytes

    }

    CTS can be set by function "terminal_driver_set_flowcontrol"