Skip to content

Commit

Permalink
Adds 9bit reception support to the TI uart drivers. (#713)
Browse files Browse the repository at this point in the history
Implements a 9-bit reception mode for Tiva and CC32xx UART drivers.
The nine-bit reception works by reading two byte payloads from the fd for each incoming byte, LSB-first. The second byte contains the parity bit. The special mode is enabled with an ioctl, and only works for RX, not for TX.

===

* Adds 9bit reception capability to the CC32xxUart.

* Adds 9bit to the tiva UART as well.

* Fix comments.
  • Loading branch information
balazsracz authored Jul 8, 2023
1 parent 685d61e commit dda901d
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 9 deletions.
2 changes: 2 additions & 0 deletions include/freertos/tc_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
#define TCPAREVEN IO(TERMIOS_IOC_MAGIC, 0xF2)
#define TCPARONE IO(TERMIOS_IOC_MAGIC, 0xF3)
#define TCPARZERO IO(TERMIOS_IOC_MAGIC, 0xF4)
/// Use 9-bit reception mode
#define TCNINEBITRX IO(TERMIOS_IOC_MAGIC, 0xF5)
/// One stop bit
#define TCSTOPONE IO(TERMIOS_IOC_MAGIC, 0xF8)
/// Two stop bits
Expand Down
37 changes: 33 additions & 4 deletions src/freertos_drivers/ti/CC32xxUart.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ CC32xxUart::CC32xxUart(const char *name, unsigned long base, uint32_t interrupt,
, uartMode_(mode | UART_CONFIG_PAR_NONE)
, txPending_(false)
, hwFIFO_(hw_fifo)
, nineBit_(false)
{
static_assert(
UART_CONFIG_PAR_NONE == 0, "driverlib changed against our assumptions");
Expand Down Expand Up @@ -169,6 +170,13 @@ int CC32xxUart::ioctl(File *file, unsigned long int key, unsigned long data)
uartMode_ |= UART_CONFIG_PAR_ONE;
MAP_UARTParityModeSet(base_, UART_CONFIG_PAR_ONE);
break;
case TCNINEBITRX:
nineBit_ = data != 0;
if (!nineBit_)
{
break;
}
// fall through
case TCPARZERO:
uartMode_ &= ~UART_CONFIG_PAR_MASK;
uartMode_ |= UART_CONFIG_PAR_ZERO;
Expand Down Expand Up @@ -289,14 +297,35 @@ void CC32xxUart::interrupt_handler()
while (MAP_UARTCharsAvail(base_))
{
long data = MAP_UARTCharGetNonBlocking(base_);
if (data >= 0 && data <= 0xff)
if (nineBit_)
{
unsigned char c = data;
if (rxBuf->put(&c, 1) == 0)
if (rxBuf->space() < 2)
{
++overrunCount;
}
rxBuf->signal_condition_from_isr();
else
{
// parity error bit is moved to the ninth bit, then two bytes
// are written to the buffer.
long bit9 = (data & 0x200) >> 1;
data &= 0xff;
data |= bit9;
rxBuf->put((uint8_t *)&data, 2);
rxBuf->signal_condition_from_isr();
}
}
else if (data >= 0 && data <= 0xff)
{
if (rxBuf->space() < 1)
{
++overrunCount;
}
else
{
unsigned char c = data;
rxBuf->put(&c, 1);
rxBuf->signal_condition_from_isr();
}
}
}
/* transmit a character if we have pending tx data */
Expand Down
1 change: 1 addition & 0 deletions src/freertos_drivers/ti/CC32xxUart.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ private:
uint32_t uartMode_; /**< mode of the UART, 8 or 9 bit, 1 or 2 stop... */
uint8_t txPending_; /**< transmission currently pending */
uint8_t hwFIFO_; /**< true if hardware fifo is to be enabled, else false */
uint8_t nineBit_; /**< true if using 9-bit reception */

/** Default constructor.
*/
Expand Down
1 change: 1 addition & 0 deletions src/freertos_drivers/ti/TivaDev.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ private:
uint8_t hwFIFO_; /**< enable HW FIFO */
uint8_t uartMode_; /**< uart config (mode) flags */
uint8_t txPending_; /**< transmission currently pending */
uint8_t nineBit_; /**< true if using 9-bit reception */

/** Default constructor.
*/
Expand Down
39 changes: 34 additions & 5 deletions src/freertos_drivers/ti/TivaUart.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ TivaUart::TivaUart(const char *name, unsigned long base, uint32_t interrupt,
, hwFIFO_(hw_fifo)
, uartMode_(mode)
, txPending_(false)
, nineBit_(false)
{
static_assert(
UART_CONFIG_PAR_NONE == 0, "driverlib changed against our assumptions");
Expand Down Expand Up @@ -218,14 +219,35 @@ void TivaUart::interrupt_handler()
while (MAP_UARTCharsAvail(base_))
{
long data = MAP_UARTCharGetNonBlocking(base_);
if (data >= 0 && data <= 0xff)
if (nineBit_)
{
unsigned char c = data;
if (rxBuf->put(&c, 1) == 0)
if (rxBuf->space() < 2)
{
overrunCount++;
++overrunCount;
}
else
{
// parity error bit is moved to the ninth bit, then two bytes
// are written to the buffer.
long bit9 = (data & 0x200) >> 1;
data &= 0xff;
data |= bit9;
rxBuf->put((uint8_t *)&data, 2);
rxBuf->signal_condition_from_isr();
}
}
else if (data >= 0 && data <= 0xff)
{
if (rxBuf->space() < 1)
{
++overrunCount;
}
else
{
unsigned char c = data;
rxBuf->put(&c, 1);
rxBuf->signal_condition_from_isr();
}
rxBuf->signal_condition_from_isr();
}
}
/* transmit a character if we have pending tx data */
Expand Down Expand Up @@ -302,6 +324,13 @@ int TivaUart::ioctl(File *file, unsigned long int key, unsigned long data)
uartMode_ |= UART_CONFIG_PAR_ONE;
MAP_UARTParityModeSet(base_, UART_CONFIG_PAR_ONE);
break;
case TCNINEBITRX:
nineBit_ = data != 0;
if (!nineBit_)
{
break;
}
// fall through
case TCPARZERO:
uartMode_ &= ~UART_CONFIG_PAR_MASK;
uartMode_ |= UART_CONFIG_PAR_ZERO;
Expand Down

0 comments on commit dda901d

Please sign in to comment.