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"