I observed this latest SensorTag app/RTOS/BLE Stack (TI-RTOS 2.13.0.06 and BLE-Stack 2.1).
Also observed with prior versions. Using latest CCS 6.1.0.00104
Using CC2650 SensorTag with Debug DevPack
My first step was to import the existing uartecho app, and I verified that it worked perfectly
( ... after changed outlined in https://e2e.ti.com/support/wireless_connectivity/f/538/p/441616/1591077#1591077 )
Echo worked perfectly. I took the exact same code, and integrated a new task (task_UART) into the unmodified, working SensorTag application.
Compiles, and runs properly. But when my task_UART starts to execute, it has the following code:
static void uartTaskFxn(UArg a0, UArg a1)
{
char input;
UART_Handle uart;
UART_Params uartParams;
const char echoPrompt[] = "\fEchoing characters:\r\n";
/* Create a UART with data processing off. */
UART_Params_init(&uartParams);
uartParams.writeDataMode = UART_DATA_BINARY;
uartParams.readDataMode = UART_DATA_BINARY;
uartParams.readReturnMode = UART_RETURN_FULL;
uartParams.readEcho = UART_ECHO_OFF;
uartParams.baudRate = 9600;
uart = UART_open(CC2650_UART0, &uartParams);
if (uart == NULL) {
//System_abort("Error opening the UART");
}
UART_write(uart, echoPrompt, sizeof(echoPrompt));
/* Task Loop forever echoing */
while (1) {
UART_read(uart, &input, 1);
UART_write(uart, &input, 1);
// Put out a second time, so easy to verify on scope
UART_write(uart, &input, 1);
}
}
On my PC UART terminal, I see the text string "Echoing characters" come out as expected.
But in UARTCC26XX_write, it waits upon a semaphore after the TX FIFO has been emptied.
see 1st statement: if (!Semaphore_pend(Semaphore_handle(&(object->writeSem)), object->writeTimeout))
The semaphore never gets posted, and my UART_task is suspended at this point. See UARTCC26XX_write below,
int UARTCC26XX_write(UART_Handle handle, const void *buffer, size_t size)
{
unsigned int key;
UARTCC26XX_Object *object;
UARTCC26XX_HWAttrs const *hwAttrs;
/* Get the pointer to the object */
object = handle->object;
hwAttrs = handle->hwAttrs;
/* Check that there is data to write */
Assert_isTrue(size != 0, NULL);
/* Disable preemption while checking if the UART is in use. */
key = Hwi_disable();
if (object->writeSize) {
Hwi_restore(key);
Log_warning1("UART:(%p) Could not write data, uart in use.",
((UARTCC26XX_HWAttrs const *)(handle->hwAttrs))->baseAddr);
return (UART_ERROR);
}
/* Stop the txFifoEmpty clock in case it was running due to a previous write operation */
Clock_stop((Clock_Handle) &(object->txFifoEmptyClk));
/* Update the status of the UART module */
object->status = UART_OK;
/* Save the data to be written and restore interrupts. */
object->writeBuf = buffer;
object->writeCount = 0;
Hwi_restore(key);
/* Set constraints to guarantee transaction */
threadSafeStdbyDisSet();
/* Enable TX */
HWREG(UART0_BASE + UART_O_CTL) |= UART_CTL_TXE;
uint32_t writtenLast = size;
/* Fill up TX FIFO */
if (!(object->writeSize = writeData(handle, size))) {
/* No more data to transmit - Write is finished but all bytes
* may not have been shifted out. */
startTxFifoEmptyClk((UART_Handle)handle, writtenLast);
/* If writeMode is blocking, block and get the status. */
if (object->writeMode == UART_MODE_BLOCKING) {
/* Pend on semaphore and wait for Hwi to finish. */
if (!Semaphore_pend(Semaphore_handle(&(object->writeSem)), object->writeTimeout)) {
/* Reset writeSize */
object->writeSize = 0;
/* Set status to TIMED_OUT */
object->status = UART_TIMED_OUT;
/* Workaround for flushing the TX FIFO */
writeTxFifoFlush(object, hwAttrs);
/* Release constraint */
threadSafeStdbyDisRelease();
Log_print2(Diags_USER1, "UART:(%p) Write timed out, %d bytes written",
((UARTCC26XX_HWAttrs const *)(handle->hwAttrs))->baseAddr,
object->writeCount);
/* Return UART_ERROR to indicate something went wrong, object->status set to UART_TIMED_OUT*/
return UART_ERROR;
}
return (object->writeCount);
}
} else {
/* Enable TX interrupts */
UARTIntEnable(hwAttrs->baseAddr, UART_INT_TX);
/* If writeMode is blocking, block and get the status. */
if (object->writeMode == UART_MODE_BLOCKING) {
/* Pend on semaphore and wait for Hwi to finish. */
if (!Semaphore_pend(Semaphore_handle(&(object->writeSem)), object->writeTimeout)) {
/* Semaphore timed out, make the write empty and log the write. */
/* Starting a timer to enable the posting of semaphore used in writeTxFifoFlush.
* writtenLast in this case is equal to full TX FIFO. This is a conservative number as
* some of the data might have been sent.
*/
startTxFifoEmptyClk((UART_Handle)handle, writtenLast);
/* Reset writeSize */
object->writeSize = 0;
/* Set status to TIMED_OUT */
object->status = UART_TIMED_OUT;
/* Workaround for flushing the TX FIFO */
writeTxFifoFlush(object, hwAttrs);
/* Release constraint */
threadSafeStdbyDisRelease();
Log_print2(Diags_USER1, "UART:(%p) Write timed out, %d bytes written",
((UARTCC26XX_HWAttrs const *)(handle->hwAttrs))->baseAddr,
object->writeCount);
/* Return UART_ERROR to indicate something went wrong (object->status set to UART_TIMED_OUT)*/
return UART_ERROR;
}
/* Return the numbers of samples written */
return (object->writeCount);
}
}
/* This return will only be active in UART_MODE_CALLBACK mode. */
return (0);
}
On an oscilloscope, I can see characters being received by the CC2650, and as mentioned, the CC2650 has successfully transmitted the "Echoing characters" string.
Other notes.
- In project properties Build->ARM Compiler->Advanced Options->Predefined Symbols, I added TI_DRIVERS_UART_INCLUDED ... but not sure if it is needed
- In project, I had to manually add the UART drivers alongside the existing I2C/PIN/SPI/UDMA drivers.
- Note that the original uartecho app does not run with a BLE Stack. Possibly this is a difference that may be of interest
- I have some suspicion it has something to do with ROM libraries. On my app, I don't think ROM libraries are involved, because I can single-step through the UARTCC26XX.code.
- On uartecho, I can' t step through the UART code because I believe it is using some ROM libraries.
