Hello,
There seems to be a bug with scanning for many Bluetooth advertisements while simultaneously sending data over uart in Nrf sdk v17.
I have tried to work around this issue by using the nrfx_uart/uarte library, and slowing the scanning rate. Both of these changes did not fix the issue, just made it take longer to show up. Also originally I was using nrf sdk v16, upgrading to v17 made the issue better but still shows up.
At the bottom of this post is a reproducible project that shows this bug.
If the code is programmed and the python script is pointing to the com port of the device, you will see that thereis a wild inconsistency with the data recieved.

If lines 166 and 167 are commented out (the nrf_ble_scan_start) and start the script again, the script will show that every 100 bytes received are in the same pattern

Note: this only seems to happen when there are a lot of advertisers around.
Can you please help find a solution to this problem?
Thanks
#include "nrfx_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_scan.h"
#include <nrfx.h>
#include "nrf_uarte.h"
#include "nrf_gpio.h"
#define APP_BLE_CONN_CFG_TAG 1
struct uart_config_t {
uint32_t pseltxd; ///< TXD pin number.
uint32_t pselrxd; ///< RXD pin number.
uint32_t pselcts; ///< CTS pin number.
uint32_t pselrts; ///< RTS pin number.
void * p_context; ///< Context passed to interrupt handler.
nrf_uarte_hwfc_t hwfc; ///< Flow control configuration.
nrf_uarte_parity_t parity; ///< Parity configuration.
nrf_uarte_baudrate_t baudrate; ///< Baudrate.
uint8_t interrupt_priority; ///< Interrupt priority.
} ;
static nrf_ble_scan_t m_scan;
NRF_UARTE_Type * p_uart = NRF_UARTE0;
static void send_uart_payload();
static void ble_evt(ble_evt_t const * p_evt, void * p_context);
NRF_SDH_BLE_OBSERVER(m_ble_observer, 1, ble_evt, 0);
#define UART_PAYLOAD_SIZE 100
static uint8_t pl[UART_PAYLOAD_SIZE] = { 0 };
static void ble_evt(ble_evt_t const * p_evt, void * p_context) {
if (p_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT) {
ble_gap_evt_adv_report_t const * p_adv_report = &p_evt->evt.gap_evt.params.adv_report;
NRFX_LOG_INFO("ADV");
}
send_uart_payload();
nrf_ble_scan_on_ble_evt(p_evt, &m_scan);
}
static void init_softdevice() {
ret_code_t err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
}
static void init_bluetooth() {
uint32_t ram_start = 0;
ret_code_t err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
}
static void send_uart_payload() {
nrf_uarte_tx_buffer_set(p_uart, pl, UART_PAYLOAD_SIZE);
nrf_uarte_task_trigger(p_uart, NRF_UARTE_TASK_STARTTX);
}
void nrfx_uarte_0_irq_handler(void) {
if (nrf_uarte_int_enable_check(p_uart, NRF_UARTE_INT_ERROR_MASK) && nrf_uarte_event_check(p_uart, NRF_UARTE_EVENT_ERROR)) {
nrf_uarte_event_clear(p_uart, NRF_UARTE_EVENT_ERROR);
nrf_uarte_int_disable(p_uart, NRF_UARTE_INT_RXDRDY_MASK | NRF_UARTE_INT_ERROR_MASK);
NRFX_LOG_ERROR("uart error!");
}
if (nrf_uarte_event_check(p_uart, NRF_UARTE_EVENT_ENDTX)) {
nrf_uarte_event_clear(p_uart, NRF_UARTE_EVENT_ENDTX);
nrf_uarte_event_clear(p_uart, NRF_UARTE_EVENT_TXSTOPPED);
send_uart_payload();
}
}
static void init_scanner() {
nrf_ble_scan_init_t init_scan = {
.connect_if_match = false,
.conn_cfg_tag = APP_BLE_CONN_CFG_TAG
};
ret_code_t err_code = nrf_ble_scan_init(&m_scan, &init_scan, 0);
APP_ERROR_CHECK(err_code);
m_scan.scan_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS);
m_scan.scan_params.window = MSEC_TO_UNITS(100, UNIT_0_625_MS);
m_scan.scan_params.timeout = MSEC_TO_UNITS(0, UNIT_10_MS);
}
static void apply_uart_config(const struct uart_config_t* p_config) {
if (p_config->pseltxd != NRF_UARTE_PSEL_DISCONNECTED) {
nrf_gpio_pin_set(p_config->pseltxd);
nrf_gpio_cfg_output(p_config->pseltxd);
}
if (p_config->pselrxd != NRF_UARTE_PSEL_DISCONNECTED) {
nrf_gpio_cfg_input(p_config->pselrxd, NRF_GPIO_PIN_NOPULL);
}
nrf_uarte_baudrate_set(p_uart, p_config->baudrate);
nrf_uarte_configure(p_uart, p_config->parity, p_config->hwfc);
nrf_uarte_txrx_pins_set(p_uart, p_config->pseltxd, p_config->pselrxd);
if (p_config->hwfc == NRF_UARTE_HWFC_ENABLED) {
if (p_config->pselcts != NRF_UARTE_PSEL_DISCONNECTED) {
nrf_gpio_cfg_input(p_config->pselcts, NRF_GPIO_PIN_NOPULL);
}
if (p_config->pselrts != NRF_UARTE_PSEL_DISCONNECTED) {
nrf_gpio_pin_set(p_config->pselrts);
nrf_gpio_cfg_output(p_config->pselrts);
}
nrf_uarte_hwfc_pins_set(p_uart, p_config->pselrts, p_config->pselcts);
}
}
static void init_uart() {
struct uart_config_t config = {
.pseltxd = 6,
.pselrxd = 5,
.pselcts = NRF_UARTE_PSEL_DISCONNECTED,
.pselrts = NRF_UARTE_PSEL_DISCONNECTED,
.p_context = NULL,
.hwfc = NRF_UARTE_HWFC_DISABLED,
.parity = NRF_UARTE_PARITY_EXCLUDED,
.baudrate = NRF_UARTE_BAUDRATE_9600,
.interrupt_priority = NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY,
};
apply_uart_config(&config);
nrf_uarte_event_clear(p_uart, NRF_UARTE_EVENT_TXDRDY);
nrf_uarte_event_clear(p_uart, NRF_UARTE_EVENT_RXTO);
nrf_uarte_int_enable(p_uart,
NRF_UARTE_INT_TXDRDY_MASK | NRF_UARTE_INT_RXTO_MASK | NRF_UARTE_INT_ERROR_MASK);
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_uart),
config.interrupt_priority);
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_uart));
nrf_uarte_enable(p_uart);
}
int main() {
ret_code_t err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
err_code = nrf_pwr_mgmt_init();
APP_ERROR_CHECK(err_code);
NRFX_LOG_INFO("Test started.");
memset(pl, 0xAB, UART_PAYLOAD_SIZE);
for (uint16_t i = 0; i < UART_PAYLOAD_SIZE; i++) {
if (i % 2 == 0) {
pl[i] = 0xAB;
} else {
pl[i] = 0xCD;
}
}
init_softdevice();
init_bluetooth();
init_scanner();
init_uart();
send_uart_payload();
err_code = nrf_ble_scan_start(&m_scan);
APP_ERROR_CHECK(err_code);
for (;;) {
if (!NRF_LOG_PROCESS()) {
nrf_pwr_mgmt_run();
}
}
return 0;
}
import serial
def main():
with serial.Serial('COM17', baudrate=9600) as s:
while True:
p = []
while len(p) < 100:
p += s.read(100 - len(p))
print(''.join(map('{:X}'.format, p)))
if __name__ == "__main__":
main()