I am having a problem when disabling the UART on a CC2650, which causes strange sleep/standby behavior and BLE connections to be dropped. I have modified a version of simple_peripheral_cc2650em_app with POWER_SAVING defined, running on a SmartRF06. Software versions are BLE SDK 2.02.00.31, TI-RTOS 2.18.00.03, and XDCtools 3.32.00.06 (also tried 3.32.01.22). While I have modified the characteristics, the BLE setup and default settings are unmodified.
The UART is initialized at the very end of SimpleBLEPeripheral_init(). TX blocks and RX uses a callback function. The callback uses a variation of the receive-continuously example from UARTCC26xx.h, with RETURN_PARTIAL_ENABLE, writing to a circular buffer. (I did originally try the tl.c example code, but ultimately wanted something simpler and smaller.) It functions as expected when connected to a terminal via SmartRF06 USB. To enable sleep, I can signal the system to stop reading and disable/close the UART (which is necessary for our ultimate device).
I first noticed that after disabling the UART, if there was a client connected to SimpleBLEPeripheral, the connection would shortly drop, and reconnection would be difficult and/or short-lived. (Advertising seems unaffected.) I looked at the packets and saw that prior to disconnection, the connection interval would increase significantly, perhaps in response to the fact that SimpleBLEPeripheral was missing a lot of packets when responding to the Master/Client. When disconnection occurs, the new state is given as GAPROLE_WAITING_AFTER_TIMEOUT.
I registered a power notify function that counts the number of PowerCC26XX_ENTERING_STANDBY events, and monitor this in the debugger. With the unmodified version of SimpleBLEPeripheral (i.e. no UART), standby events occur fairly slowly and regularly, about once per second. With the UART code, of course no standby events occur while the UART is continuously reading. But as soon as I disable and close the UART, the standby counter starts increasing rapidly, much faster than the unmodified case.
I have tried various things, trying to reduce the UART code to the bare minimum, but I am at a loss to solve this problem. Hopefully someone can offer a solution or some suggestions. Any help would be greatly appreciated!
I have included the code I am using. By the way, no errors or buffer overflows are occurring, as the amount of data being transferred is tiny compared to the buffer size. The call to UART_readCancel() does cause a size=0 call to the callback function, and the reads terminate prior to closing the UART.
Hardware parameters are as is from CC2650DK_7ID.c:
/* UART hardware parameter structure, also used to assign UART pins */
const UARTCC26XX_HWAttrsV1 uartCC26XXHWAttrs[CC2650DK_7ID_UARTCOUNT] = {
{
.baseAddr = UART0_BASE,
.powerMngrId = PowerCC26XX_PERIPH_UART0,
.intNum = INT_UART0_COMB,
.intPriority = ~0,
.swiPriority = 0,
.txPin = Board_UART_TX,
.rxPin = Board_UART_RX,
.ctsPin = PIN_UNASSIGNED,
.rtsPin = PIN_UNASSIGNED
}
};
#define UART_BUF_LENGTH (512)
#define UART_BUF_MASK (UART_BUF_LENGTH-1)
static uint8_t rx_buf[UART_BUF_LENGTH];
static uint16_t rx_head;
static uint16_t rx_tail;
static UART_Handle uartHandle = NULL;
static uint8_t uartEnabled = FALSE;
static int uerror = 0;
// UART RX Callback function
static void readCallback(UART_Handle handle, void *buf, size_t size)
{
size_t nextrd=0;
// check for errors
UARTCC26XX_Object *object = handle->object;
UART_Status ustat = object->status;
if (ustat)
{
uerror = 1;
}
rx_head = UART_BUF_MASK & (rx_head + size);
// Store the event.
events |= GP_UART_RX_EVT;
// Wake up the application.
Semaphore_post(sem);
if (uartEnabled)
{
nextrd = UART_BUF_MASK & (rx_tail - rx_head - 1);
if (nextrd > (UART_BUF_LENGTH - rx_head))
{
nextrd = UART_BUF_LENGTH - rxbuf.head;
}
if (nextrd > (UART_BUF_LENGTH/2))
{
nextrd = (UART_BUF_LENGTH/2);
}
// Start another read into available space
UART_read(handle, rx_buf+rx_head, nextrd);
}
}
void uartInit(void)
{
if (!uartEnabled)
{
// Configure UART parameters.
UART_Params params;
UART_Params_init(¶ms);
params.baudRate = 115200;
params.writeDataMode = UART_DATA_BINARY;
params.readMode = UART_MODE_CALLBACK;
params.readDataMode = UART_DATA_BINARY;
params.readCallback = readCallback;
// Open / power on the UART.
uartHandle = UART_open(Board_UART, ¶ms);
uartEnabled = TRUE;
//Enable Partial Reads on all subsequent UART_read()
UART_control(uartHandle, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL);
rx_head = rx_tail = 0;
// initiate reading from port
UART_control(uartHandle, UARTCC26XX_CMD_RX_FIFO_FLUSH, NULL);
UART_read(uartHandle, rx_buf, UART_BUF_LENGTH/2);
}
}
void disableUart(void)
{
if (uartEnabled)
{
uartEnabled = FALSE;
UART_readCancel(uartHandle);
// should not be necessary, because UART_write is blocking, but try anyway
UART_writeCancel(uartHandle);
UART_close(uartHandle);
uartHandle = NULL;
}
}