Part Number: CC1352P
Hello,
I have struggled with a problem on the UART of CC1352P, using Simplelink SDK 2.30 and UARTCC26XX driver. (This driver's source code did not change to SDK 2.40.)
Use case: I am transferring and receiving concurrently and with high duty cycle at 9600 Baud. Transmitting several bytes at once, reading single bytes. Using callback mode for both RX and TX.
Error: After minutes to 1 hour, transmission fails.
This is what happens in error case:
- UARTCC26XX_read() is interrupted while at line
/* Enable RX */
HWREG(hwAttrs->baseAddr + UART_O_CTL) |= UART_CTL_RXE;
by UARTCC26XX_swiIntFxn() which disables the UART_CTL_TXE bit.
/* Disable TX */
HWREG(hwAttrs->baseAddr + UART_O_CTL) &= ~(UART_CTL_TXE);
- UARTCC26XX_read() continues and it erroneously restores the UART_CTL_TXE bit.
- UARTCC26XX_write() then checks for UART_CTL_TXE cleared and fails with UART_ERROR.
/* The UART TX is disabled after a successful write, if it is
* still active another write is in progress, reject. */
uint32_t writeActive = HWREG(hwAttrs->baseAddr + UART_O_CTL) & (UART_CTL_TXE);
if (!object->opened || writeActive) {
HwiP_restore(key);
DebugP_log1("UART:(%p) Could not write data, uart closed or in use.",
((UARTCC26XX_HWAttrsV2 const *)(handle->hwAttrs))->baseAddr);
return (UART_ERROR);
}
There are several of these read-modify-write instructions, using the HWREG() macro, in this driver. And only a few of them are within HwiP_disable()...HwiP_restore() blocks.
Second possible source of these errors could be the UARTIntEnable()/UARTIntDisable() functions which use the HWREG() macro as well.
I have attached a patch that fixes my problem and I hope it is of use for future revisions of the UARTCC26XX driver.
Best regards,
hkr
diff --git a/UARTCC26XX.c b/UARTCC26XX.c
@@ -437,7 +456,9 @@ static void writeTxFifoFlush(UARTCC26XX_Object *object, UARTCC26XX_HWAttrsV2 co
/*It is not possible to flush the TX FIFO with simple write to HW, doing workaround:
* 0. Disable TX interrupt
*/
+ unsigned int key = HwiP_disable();
UARTIntDisable(hwAttrs->baseAddr, UART_INT_TX);
+ HwiP_restore(key);
/* 1. Ensure TX IO will stay high when connected to GPIO */
PIN_setOutputEnable(object->hPin, hwAttrs->txPin, 1);
PIN_setOutputValue(object->hPin, hwAttrs->txPin, 1);
@@ -1113,7 +1134,9 @@ int_fast32_t UARTCC26XX_write(UART_Handle handle, const void *buffer,
threadSafeStdbyDisSet(&uartTxPowerConstraint);
/* Enable TX */
+ key = HwiP_disable();
HWREG(hwAttrs->baseAddr + UART_O_CTL) |= UART_CTL_TXE;
+ HwiP_restore(key);
uint32_t writtenLast = size;
/* Fill up TX FIFO */
@@ -1151,7 +1174,9 @@ int_fast32_t UARTCC26XX_write(UART_Handle handle, const void *buffer,
} else {
/* Enable TX interrupts */
+ key = HwiP_disable();
UARTIntEnable(hwAttrs->baseAddr, UART_INT_TX);
+ HwiP_restore(key);
/* If writeMode is blocking, block and get the status. */
if (object->writeMode == UART_MODE_BLOCKING) {
@@ -1263,12 +1288,16 @@ void UARTCC26XX_writeCancel(UART_Handle handle)
writeTxFifoFlush(object, hwAttrs);
}
+ key = HwiP_disable();
+
/* Disable TX interrupt */
UARTIntDisable(hwAttrs->baseAddr, UART_INT_TX);
/* Disable UART TX */
HWREG(hwAttrs->baseAddr + UART_O_CTL) &= ~(UART_CTL_TXE);
+ HwiP_restore(key);
+
/* Release constraint since transaction is done */
threadSafeStdbyDisRelease(&uartTxPowerConstraint);
@@ -1355,6 +1384,8 @@ int_fast32_t UARTCC26XX_read(UART_Handle handle, void *buffer, size_t size)
/* Set constraint for sleep to guarantee transaction */
threadSafeStdbyDisSet(&uartRxPowerConstraint);
+ key = HwiP_disable();
+
/* Enable RX */
HWREG(hwAttrs->baseAddr + UART_O_CTL) |= UART_CTL_RXE;
@@ -1362,6 +1393,8 @@ int_fast32_t UARTCC26XX_read(UART_Handle handle, void *buffer, size_t size)
UARTIntEnable(hwAttrs->baseAddr, UART_INT_RX | UART_INT_RT |
UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE);
+ HwiP_restore(key);
+
/* If readMode is blocking, block and get the status. */
if (object->readMode == UART_MODE_BLOCKING) {
/* Pend on semaphore and wait for Hwi to finish. */