Hi,
I am programming with nrf52833,ncs v2.9.0,generating peripheral_uart to peripheral_hid_keyboard sdk.
And now with working serial times,err happend and log is Not able to allocate UART receive buffer.
LOG is
E: No connection for handle 0 E: No connection for handle 0 W: Not able to allocate UART receive buffer, UART_RX_BUF_REQUEST W: Not able to allocate UART receive buffer, UART_RX_DISABLED W: Not able to allocate UART receive buffer, uart_work_handler
My code is
static const struct device *uart = DEVICE_DT_GET(DT_CHOSEN(nordic_nus_uart));
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
ARG_UNUSED(dev);
static size_t aborted_len;
uart_data_t *buf;
static uint8_t *aborted_buf;
static bool disable_req;
switch (evt->type) {
case UART_TX_DONE:
LOG_INF("UART_TX_DONE");
if ((evt->data.tx.len == 0) ||
(!evt->data.tx.buf)) {
return;
}
if (aborted_buf) {
buf = CONTAINER_OF(aborted_buf, uart_data_t, data[0]);
aborted_buf = NULL;
aborted_len = 0;
} else {
buf = CONTAINER_OF(evt->data.tx.buf, uart_data_t, data[0]);
}
k_free(buf);
buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
if (!buf) {
return;
}
if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
LOG_WRN("Failed to send data over UART, UART_TX_DONE");
}
break;
case UART_RX_RDY:
LOG_INF("UART_RX_RDY");
buf = CONTAINER_OF(evt->data.rx.buf, uart_data_t, data[0]);
// 防止缓冲区溢出
if (buf->len + evt->data.rx.len <= sizeof(buf->data)) {
buf->len += evt->data.rx.len;
} else {
LOG_WRN("UART RX buffer overflow detected");
buf->len = sizeof(buf->data); // 截断处理
}
//buf->len += evt->data.rx.len;
if (disable_req) {
return;
}
if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
(evt->data.rx.buf[buf->len - 1] == '\r')) {
disable_req = true;
uart_rx_disable(uart);
}
break;
case UART_RX_DISABLED:
LOG_INF("UART_RX_DISABLED");
disable_req = false;
buf = k_malloc(sizeof(*buf));
if (buf) {
buf->len = 0;
uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_WAIT_FOR_RX);
} else {
LOG_WRN("Not able to allocate UART receive buffer, UART_RX_DISABLED");
k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
return;
}
break;
case UART_RX_BUF_REQUEST:
LOG_INF("UART_RX_BUF_REQUEST");
buf = k_malloc(sizeof(*buf));
if (buf) {
buf->len = 0;
uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
} else {
LOG_WRN("Not able to allocate UART receive buffer, UART_RX_BUF_REQUEST");
}
break;
case UART_RX_BUF_RELEASED:
LOG_INF("UART_RX_BUF_RELEASED");
buf = CONTAINER_OF(evt->data.rx_buf.buf, uart_data_t, data[0]);
if (buf->len > 0) {
k_fifo_put(&fifo_uart_rx_data, buf);
//LOG_INF("k_fifo_put buf addr:%p", buf);
} else {
k_free(buf);
}
break;
case UART_TX_ABORTED:
LOG_INF("UART_TX_ABORTED");
if (!aborted_buf) {
aborted_buf = (uint8_t *)evt->data.tx.buf;
}
aborted_len += evt->data.tx.len;
buf = CONTAINER_OF((void *)aborted_buf, uart_data_t, data);
if(!buf) {
LOG_ERR("Invalid buffer in UART_TX_ABORTED");
return;
}
uart_tx(uart, &buf->data[aborted_len],
buf->len - aborted_len, SYS_FOREVER_MS);
break;
default:
break;
}
}
static void uart_work_handler(struct k_work *item)
{
uart_data_t *buf;
buf = k_malloc(sizeof(*buf));
//LOG_INF("uart_work_handler buf addr:%p", buf);
if (buf) {
buf->len = 0;
} else {
LOG_WRN("Not able to allocate UART receive buffer, uart_work_handler");
k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
return;
}
uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_WAIT_FOR_RX);
}
static bool uart_test_async_api(const struct device *dev)
{
const struct uart_driver_api *api =
(const struct uart_driver_api *)dev->api;
return (api->callback_set != NULL);
}
static int uart_init(void)
{
int err;
int pos;
uart_data_t *rx;
uart_data_t *tx;
if (!device_is_ready(uart)) {
return -ENODEV;
}
rx = k_malloc(sizeof(*rx));
if (rx) {
rx->len = 0;
} else {
return -ENOMEM;
}
k_work_init_delayable(&uart_work, uart_work_handler);
if (IS_ENABLED(CONFIG_BT_NUS_UART_ASYNC_ADAPTER) && !uart_test_async_api(uart)) {
/* Implement API adapter */
uart_async_adapter_init(async_adapter, uart);
uart = async_adapter;
}
err = uart_callback_set(uart, uart_cb, NULL);
if (err) {
k_free(rx);
LOG_ERR("Cannot initialize UART callback");
return err;
}
if (IS_ENABLED(CONFIG_UART_LINE_CTRL)) {
while (true) {
uint32_t dtr = 0;
uart_line_ctrl_get(uart, UART_LINE_CTRL_DTR, &dtr);
if (dtr) {
break;
}
/* Give CPU resources to low priority threads. */
k_sleep(K_MSEC(100));
}
err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DCD, 1);
if (err) {
LOG_WRN("Failed to set DCD, ret code %d", err);
}
err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DSR, 1);
if (err) {
LOG_WRN("Failed to set DSR, ret code %d", err);
}
}
tx = k_malloc(sizeof(*tx));
if (tx) {
pos = snprintf(tx->data, sizeof(tx->data),
"Starting ...\r\n");
if ((pos < 0) || (pos >= sizeof(tx->data))) {
k_free(rx);
k_free(tx);
LOG_ERR("snprintf returned %d", pos);
return -ENOMEM;
}
tx->len = pos;
} else {
k_free(rx);
return -ENOMEM;
}
err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
if (err) {
k_free(rx);
k_free(tx);
LOG_ERR("Cannot display welcome message (err: %d)", err);
return err;
}
err = uart_rx_enable(uart, rx->data, sizeof(rx->data), UART_WAIT_FOR_RX);
if (err) {
LOG_ERR("Cannot enable uart reception (err: %d)", err);
/* Free the rx buffer only because the tx buffer will be handled in the callback */
k_free(rx);
}
return err;
}
Best regard
Martin