Hi,
I modified the USB BLE example (nRF5_SDK_17.0.2_d674dde/examples/peripheral/usbd_ble_uart) to sends bytes using a timer timeout as "fixed bytes transactions" or "waits for a special characters" are not feasible.
I used app_usbd_cdc_acm_read_any to receive partial bytes and the buffer pointer increments in usb event handler (if the event triggers before timeout) as below:
case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
{
ret_code_t ret;
//NRF_LOG_INFO("Bytes waiting: %d", app_usbd_cdc_acm_bytes_stored(p_cdc_acm));
nrfx_timer_pause(&m_usb_cdc_timer);
nrfx_timer_clear(&m_usb_cdc_timer);
do
{
/*Get amount of data transferred*/
size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
rx_buffer += size;
//NRF_LOG_INFO("RX: size: %lu char: %c", size, *rx_buffer);
/* Fetch data until internal buffer is empty */
ret = app_usbd_cdc_acm_read_any(&m_app_cdc_acm,
rx_buffer,
READ_SIZE);
} while (ret == NRF_SUCCESS);
nrfx_timer_resume(&m_usb_cdc_timer);
break;
}
And in the timeout event, I have to reset the buffer pointer to the initial position for the next transaction. This is not possible as there was a null pointer check inside the function, i.e. if a buffer assigned already, the function is not allowed to change it. I removed that option, and it works fine in my tests. However, I would like to know if there any other consequences, modified code is below:
ret_code_t app_usbd_cdc_acm_read_any(app_usbd_cdc_acm_t const * p_cdc_acm,
void * p_buf,
size_t length)
{
ASSERT(p_buf != NULL);
ret_code_t ret;
app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
if (0U == (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR))
{
/*Port is not opened*/
return NRF_ERROR_INVALID_STATE;
}
#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
CRITICAL_REGION_ENTER();
#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
if (p_cdc_acm_ctx->bytes_left > 0)
{
size_t to_copy = MIN(length, p_cdc_acm_ctx->bytes_left);
memcpy(p_buf, p_cdc_acm_ctx->p_copy_pos, to_copy);
p_cdc_acm_ctx->bytes_left -= to_copy;
p_cdc_acm_ctx->p_copy_pos += to_copy;
p_cdc_acm_ctx->last_read = to_copy;
ret = NRF_SUCCESS;
}
else
{
// if (p_cdc_acm_ctx->rx_transfer[0].p_buf == NULL)
// {
p_cdc_acm_ctx->rx_transfer[0].p_buf = p_buf;
p_cdc_acm_ctx->rx_transfer[0].read_left = length;
nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(app_usbd_cdc_acm_class_inst_get(p_cdc_acm));
nrf_drv_usbd_handler_desc_t const handler_desc = {
.handler.consumer = cdc_acm_single_shoot_consumer,
.p_context = p_cdc_acm_ctx
};
ret = app_usbd_ep_handled_transfer(ep, &handler_desc);
if (ret == NRF_SUCCESS)
{
ret = NRF_ERROR_IO_PENDING;
}
// }
else
{
ret = NRF_ERROR_BUSY;
}
}
#if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
CRITICAL_REGION_EXIT();
#endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
return ret;
}
The line "if (p_cdc_acm_ctx->rx_transfer[0].p_buf == NULL)" has been removed.