Skip to content

Commit

Permalink
Adds support for RS485 mode to the tiva UART driver. (#613)
Browse files Browse the repository at this point in the history
* Adds support for RS485 mode to the tiva UART driver.

* Update Tiva UART for EOT support for RS-485 enable line.

* One more further simplification of the Tiva UART driver.

Co-authored-by: Stuart Baker <[email protected]>
  • Loading branch information
balazsracz and bakerstu authored Mar 6, 2022
1 parent 0fac0bd commit f27dc08
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 31 deletions.
19 changes: 18 additions & 1 deletion src/freertos_drivers/ti/TivaDev.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -166,16 +166,23 @@ public:
CSTOPB = UART_CONFIG_STOP_TWO, /**< send two stop bits instead of 1 */
};

/** Function point for the tx enable assert and deassert methods */
typedef void (*TxEnableMethod)();

/** Constructor.
* @param name name of this device instance in the file system
* @param base base address of this device
* @param interrupt interrupt number of this device
* @param baud desired baud rate
* @param mode to configure the UART for
* @param hw_fifo true if hardware fifo is to be enabled, else false.
* @param tx_enable_assert callback to assert the transmit enable
* @param tx_enable_deassert callback to deassert the transmit enable
*/
TivaUart(const char *name, unsigned long base, uint32_t interrupt,
uint32_t baud = 115200, uint32_t mode = CS8, bool hw_fifo = true);
uint32_t baud = 115200, uint32_t mode = CS8, bool hw_fifo = true,
TxEnableMethod tx_enable_assert = nullptr,
TxEnableMethod tx_enable_deassert = nullptr);

/** Destructor.
*/
Expand All @@ -200,8 +207,18 @@ private:
*/
void tx_char() override;

/** Send data until there is no more space left.
*/
void send();

/** Sets the port baud rate and mode from the class variables. */
void set_mode();

/** function pointer to a method that asserts the transmit enable. */
TxEnableMethod txEnableAssert_;

/** function pointer to a method that deasserts the transmit enable. */
TxEnableMethod txEnableDeassert_;

/** Notifiable to invoke when the transmit engine has finished operation. */
Notifiable* txComplete_{nullptr};
Expand Down
90 changes: 60 additions & 30 deletions src/freertos_drivers/ti/TivaUart.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ static Atomic isr_lock;
* @param interrupt interrupt number of this device
*/
TivaUart::TivaUart(const char *name, unsigned long base, uint32_t interrupt,
uint32_t baud, uint32_t mode, bool hw_fifo)
uint32_t baud, uint32_t mode, bool hw_fifo, TxEnableMethod tx_enable_assert,
TxEnableMethod tx_enable_deassert)
: Serial(name)
, txEnableAssert_(tx_enable_assert)
, txEnableDeassert_(tx_enable_deassert)
, base_(base)
, interrupt_(interrupt)
, baud_(baud)
Expand Down Expand Up @@ -148,24 +151,54 @@ void TivaUart::disable()
MAP_UARTDisable(base_);
}

/** Try and transmit a message.
/** Send data until there is no more space left.
*/
void TivaUart::tx_char()
void TivaUart::send()
{
if (txPending_ == false)
do
{
uint8_t data = 0;

if (txBuf->get(&data, 1))
{
MAP_UARTCharPutNonBlocking(base_, data);

MAP_IntDisable(interrupt_);
txPending_ = true;
MAP_UARTIntEnable(base_, UART_INT_TX);
MAP_IntEnable(interrupt_);
txBuf->signal_condition();
}
else
{
break;
}
}
while (MAP_UARTSpaceAvail(base_));

if (txBuf->pending())
{
/* more data to send later */
MAP_UARTTxIntModeSet(base_, UART_TXINT_MODE_FIFO);
}
else
{
/* no more data left to send */
MAP_UARTTxIntModeSet(base_, UART_TXINT_MODE_EOT);
MAP_UARTIntClear(base_, UART_INT_TX);
}
}

/** Try and transmit a message.
*/
void TivaUart::tx_char()
{
if (txPending_ == false)
{
if (txEnableAssert_)
{
txEnableAssert_();
}

send();
txPending_ = true;

MAP_UARTIntEnable(base_, UART_INT_TX);
txBuf->signal_condition();
}
}

Expand Down Expand Up @@ -196,32 +229,29 @@ void TivaUart::interrupt_handler()
}
}
/* transmit a character if we have pending tx data */
if (txPending_)
if (txPending_ && (status & UART_INT_TX))
{
/** @todo (Stuart Baker) optimization opportunity by getting a read
* pointer to fill the fifo and then consume the buffer when finished.
*/
while (MAP_UARTSpaceAvail(base_))
if (txBuf->pending())
{
unsigned char data;
if (txBuf->get(&data, 1) != 0)
send();
txBuf->signal_condition_from_isr();
}
else
{
/* no more data left to send */
HASSERT(MAP_UARTTxIntModeGet(base_) == UART_TXINT_MODE_EOT);
if (txEnableDeassert_)
{
MAP_UARTCharPutNonBlocking(base_, data);
txBuf->signal_condition_from_isr();
txEnableDeassert_();
}
else
txPending_ = false;
if (txComplete_)
{
/* no more data pending */
txPending_ = false;
if (txComplete_)
{
Notifiable *t = txComplete_;
txComplete_ = nullptr;
t->notify_from_isr();
}
MAP_UARTIntDisable(base_, UART_INT_TX);
break;
Notifiable *t = txComplete_;
txComplete_ = nullptr;
t->notify_from_isr();
}
MAP_UARTIntDisable(base_, UART_INT_TX);
}
}
os_isr_exit_yield_test(woken);
Expand Down

0 comments on commit f27dc08

Please sign in to comment.