Hello All,
I have 2 evaluation boards nrf53840 EVB "PCA10056".
I would like to run on them the "ble_app_uart" in "nRF5_SDK_15.3.0_59ac345" as following:
- A custom board send via uart a buffer for example of 30 characters to the peripheral on the pin P0.26 every 5 ms.
- The Board "peripheral" send this packet via bluetooth to the "central board" (where I uploaded the "ble_app_uart_c" code)
- The "central board" print via uart the packet received.
Let's say that I have previous tried to remove all the possible bottle necks of the app, for instance commenting out the part where the bytes received from the central board are sent back again:
// if (ECHOBACK_BLE_UART_DATA)
// {
// // Send data back to the peripheral.
// do
// {
// ret_val = ble_nus_c_string_send(&m_ble_nus_c, p_data, data_len);
// if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
// {
// NRF_LOG_ERROR("Failed sending NUS message. Error 0x%x. ", ret_val);
// APP_ERROR_CHECK(ret_val);
// }
// }while (ret_val == NRF_ERROR_BUSY);
// }
At the beginning I tried to sent a packet of 30 characters every 5 ms. What happened was that as soon as I started sending data to the UART of the peripheral, a disconnection occurred.
The program goes in the "__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)" routine.
The lineup of the latest functions is as follows:

- Unknown function at 0x00015FD6
- void nrfx_uart_0_irq_handler()
- void uarte_evt_handler(.....)
- void uarte_event_handler(.....)
- void uarte_event_handle(.....)
- void app_error_handler_bare(...)
- void app_error_fault_handler(...)
2)
static void uarte_irq_handler(NRF_UARTE_Type * p_uarte,
uarte_control_block_t * p_cb)
{
if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ERROR))
{
nrfx_uarte_event_t event;
nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ERROR);
event.type = NRFX_UARTE_EVT_ERROR;
event.data.error.error_mask = nrf_uarte_errorsrc_get_and_clear(p_uarte);
event.data.error.rxtx.bytes = nrf_uarte_rx_amount_get(p_uarte);
event.data.error.rxtx.p_data = p_cb->p_rx_buffer;
// Abort transfer.
p_cb->rx_buffer_length = 0;
p_cb->rx_secondary_buffer_length = 0;
p_cb->handler(&event, p_cb->p_context);
}
3)
#if defined(NRF_DRV_UART_WITH_UARTE)
static void uarte_evt_handler(nrfx_uarte_event_t const * p_event,
void * p_context)
{
uint32_t inst_idx = (uint32_t)p_context;
nrf_drv_uart_event_t event =
{
.type = (nrf_drv_uart_evt_type_t)p_event->type,
.data =
{
.error =
{
.rxtx =
{
.p_data = p_event->data.error.rxtx.p_data,
.bytes = p_event->data.error.rxtx.bytes,
},
.error_mask = p_event->data.error.error_mask,
}
}
};
m_handlers[inst_idx](&event, m_contexts[inst_idx]);
}
#endif // defined(NRF_DRV_UART_WITH_UARTE)
4)
static void uart_event_handler(nrf_drv_uart_event_t * p_event, void* p_context)
{
app_uart_evt_t app_uart_event;
uint32_t err_code;
switch (p_event->type)
{
case NRF_DRV_UART_EVT_RX_DONE:
// Write received byte to FIFO.
err_code = app_fifo_put(&m_rx_fifo, p_event->data.rxtx.p_data[0]);
if (err_code != NRF_SUCCESS)
{
app_uart_event.evt_type = APP_UART_FIFO_ERROR;
app_uart_event.data.error_code = err_code;
m_event_handler(&app_uart_event);
}
// Notify that there are data available.
else if (FIFO_LENGTH(m_rx_fifo) != 0)
{
app_uart_event.evt_type = APP_UART_DATA_READY;
m_event_handler(&app_uart_event);
}
// Start new RX if size in buffer.
if (FIFO_LENGTH(m_rx_fifo) <= m_rx_fifo.buf_size_mask)
{
(void)nrf_drv_uart_rx(&app_uart_inst, rx_buffer, 1);
}
else
{
// Overflow in RX FIFO.
m_rx_ovf = true;
}
break;
case NRF_DRV_UART_EVT_ERROR:
app_uart_event.evt_type = APP_UART_COMMUNICATION_ERROR;
app_uart_event.data.error_communication = p_event->data.error.error_mask;
(void)nrf_drv_uart_rx(&app_uart_inst, rx_buffer, 1);
m_event_handler(&app_uart_event);
break;
case NRF_DRV_UART_EVT_TX_DONE:
// Get next byte from FIFO.
if (app_fifo_get(&m_tx_fifo, tx_buffer) == NRF_SUCCESS)
{
(void)nrf_drv_uart_tx(&app_uart_inst, tx_buffer, 1);
}
else
{
// Last byte from FIFO transmitted, notify the application.
app_uart_event.evt_type = APP_UART_TX_EMPTY;
m_event_handler(&app_uart_event);
}
break;
5)
/**@snippet [Handling the data received over UART] */
void uart_event_handle(app_uart_evt_t * p_event)
{
static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
static uint8_t index = 0;
uint32_t err_code;
switch (p_event->evt_type)
{
case APP_UART_DATA_READY:
UNUSED_VARIABLE(app_uart_get(&data_array[index]));
index++;
if ((data_array[index - 1] == '\n') ||
(data_array[index - 1] == '\r') ||
(index >= m_ble_nus_max_data_len))
{
if (index > 1)
{
NRF_LOG_DEBUG("Ready to send data over BLE NUS");
NRF_LOG_HEXDUMP_DEBUG(data_array, index);
do
{
uint16_t length = (uint16_t)index;
err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
if ((err_code != NRF_ERROR_INVALID_STATE) &&
(err_code != NRF_ERROR_RESOURCES) &&
(err_code != NRF_ERROR_NOT_FOUND))
{
APP_ERROR_CHECK(err_code);
}
} while (err_code == NRF_ERROR_RESOURCES);
}
index = 0;
}
break;
case APP_UART_COMMUNICATION_ERROR:
APP_ERROR_HANDLER(p_event->data.error_communication);
break;
case APP_UART_FIFO_ERROR:
APP_ERROR_HANDLER(p_event->data.error_code);
break;
default:
break;
}
}
In 5) The program passes from
case APP_UART_FIFO_ERROR:
APP_ERROR_HANDLER(p_event->data.error_code);
break;
6)
void app_error_handler_bare(ret_code_t error_code)
{
error_info_t error_info =
{
.line_num = 0,
.p_file_name = NULL,
.err_code = error_code,
};
app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
UNUSED_VARIABLE(error_info);
}
7)
__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
{
__disable_irq();
NRF_LOG_FINAL_FLUSH();
#ifndef DEBUG
NRF_LOG_ERROR("Fatal error");
#else
switch (id)
{
#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT
case NRF_FAULT_ID_SD_ASSERT:
NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED");
break;
case NRF_FAULT_ID_APP_MEMACC:
NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS");
break;
#endif
case NRF_FAULT_ID_SDK_ASSERT:
{
assert_info_t * p_info = (assert_info_t *)info;
NRF_LOG_ERROR("ASSERTION FAILED at %s:%u",
p_info->p_file_name,
p_info->line_num);
break;
}
case NRF_FAULT_ID_SDK_ERROR:
{
error_info_t * p_info = (error_info_t *)info;
NRF_LOG_ERROR("ERROR %u [%s] at %s:%u\r\nPC at: 0x%08x",
p_info->err_code,
nrf_strerror_get(p_info->err_code),
p_info->p_file_name,
p_info->line_num,
pc);
NRF_LOG_ERROR("End of error report");
break;
}
default:
NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc);
break;
}
#endif
NRF_BREAKPOINT_COND;
// On assert, the system can only recover with a reset.
#ifndef DEBUG
NRF_LOG_WARNING("System reset");
NVIC_SystemReset();
#else
app_error_save_and_stop(id, pc, info);
#endif // DEBUG
}
/*lint -restore */
The info in debug terminal are:
<info> app: Debug logging for UART over RTT started.
<info> app: Connected
<info> app: Data len is set to 0xF4(244)
<info> app: Disconnected
<error> app: Fatal error
Then I tried to put this part of code:
ble_gap_phys_t const phys =
{
.rx_phys = BLE_GAP_PHY_2MBPS,
.tx_phys = BLE_GAP_PHY_2MBPS,
};
err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
APP_ERROR_CHECK(err_code);
at the end of the BLE_GAP_EVT_CONNECTED event In order to request a phy change.
Once that was done I had no more trouble sending 30 characters every 5 ms.
But then I tried to increase both the number of characters and speed (60 every 4 ms, for example).
What happens is that:
if the 2 devices are connected and then I start the data stream on the peripheral UART I can see data received on the "central unit". However, if these disconnect for any reason (for example moving the 2 boards away), and the external board continues to send data on the UART, the peripheral board goes in the error routine described above.
The only way to restart is to block the flow of data, wait for them to reconnect and then restart the flow.
Anyone who can help me?
Thanks in advance
