drivers/apbuart: add TX FIFO interrupt support
Use TX FIFO level interrupt if available in hardware. It matches the Zephyr UART API and avoids "bootstrapping" which is needed when using the TX edge interrupt ("TI"). TX FIFO has room for up to 32 characters and will typically reduce the number of interrupts. Details: APBUART can be synthesized with or without support for TX/RX FIFO. Edge interrupts which fire when TX holding register changes and RX data available are always available, independent of the FIFO configuration. If FIFO is made available at synthesis time, two additional interrupts become available: TX FIFO half-empty and RX FIFO half-full. These are level interrupts. Signed-off-by: Martin Åberg <martin.aberg@gaisler.com>
This commit is contained in:
parent
697baf1c47
commit
40ab00ac3d
1 changed files with 32 additions and 3 deletions
|
@ -312,6 +312,17 @@ static int apbuart_fifo_fill(const struct device *dev, const uint8_t *tx_data,
|
|||
volatile struct apbuart_regs *regs = (void *) DEV_CFG(dev)->regs;
|
||||
int i;
|
||||
|
||||
if (DEV_DATA(dev)->usefifo) {
|
||||
/* Transmitter FIFO full flag is available. */
|
||||
for (
|
||||
i = 0;
|
||||
(i < size) && !(regs->status & APBUART_STATUS_TF);
|
||||
i++
|
||||
) {
|
||||
regs->data = tx_data[i];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
for (i = 0; (i < size) && (regs->status & APBUART_STATUS_TE); i++) {
|
||||
regs->data = tx_data[i];
|
||||
}
|
||||
|
@ -337,6 +348,12 @@ static void apbuart_irq_tx_enable(const struct device *dev)
|
|||
volatile struct apbuart_regs *regs = (void *) DEV_CFG(dev)->regs;
|
||||
unsigned int key;
|
||||
|
||||
if (DEV_DATA(dev)->usefifo) {
|
||||
/* Enable the FIFO level interrupt */
|
||||
regs->ctrl |= APBUART_CTRL_TF;
|
||||
return;
|
||||
}
|
||||
|
||||
regs->ctrl |= APBUART_CTRL_TI;
|
||||
/*
|
||||
* The "TI" interrupt is an edge interrupt. It fires each time the TX
|
||||
|
@ -358,13 +375,16 @@ static void apbuart_irq_tx_disable(const struct device *dev)
|
|||
{
|
||||
volatile struct apbuart_regs *regs = (void *) DEV_CFG(dev)->regs;
|
||||
|
||||
regs->ctrl &= ~APBUART_CTRL_TI;
|
||||
regs->ctrl &= ~(APBUART_CTRL_TF | APBUART_CTRL_TI);
|
||||
}
|
||||
|
||||
static int apbuart_irq_tx_ready(const struct device *dev)
|
||||
{
|
||||
volatile struct apbuart_regs *regs = (void *) DEV_CFG(dev)->regs;
|
||||
|
||||
if (DEV_DATA(dev)->usefifo) {
|
||||
return !(regs->status & APBUART_STATUS_TF);
|
||||
}
|
||||
return !!(regs->status & APBUART_STATUS_TE);
|
||||
}
|
||||
|
||||
|
@ -405,9 +425,18 @@ static int apbuart_irq_is_pending(const struct device *dev)
|
|||
if ((ctrl & APBUART_CTRL_RI) && (status & APBUART_STATUS_DR)) {
|
||||
return 1;
|
||||
}
|
||||
if ((ctrl & APBUART_CTRL_TI) && (status & APBUART_STATUS_TE)) {
|
||||
return 1;
|
||||
|
||||
if (DEV_DATA(dev)->usefifo) {
|
||||
/* TH is the TX FIFO half-empty flag */
|
||||
if (status & APBUART_STATUS_TH) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if ((ctrl & APBUART_CTRL_TI) && (status & APBUART_STATUS_TE)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue