Hi,
In my setup I have one central where several peripherals are connected. I'm using the Multi-NUS service to communicate from the central to the peripherals. Here you see a snippet of sending a broadcast to all peripherals. I'm using a single semaphore which will be freed in the on_ble_data_sent(...) callback
K_SEM_DEFINE(ble_send_semaphore, 1, 1); void ble_connector_t::on_ble_data_sent(bt_nus_client *nus, uint8_t err, const uint8_t *const data, uint16_t len) { k_sem_give(&ble_send_semaphore); } int ble_connector_t::send_broadcast(uint8_t *data, uint16_t len) { int err = 0; LOG_INF("BLE broadcast: Length:%d", len); const size_t num_nus_conns = bt_conn_ctx_count(&conns_ctx_lib); for (size_t i = 0; i < num_nus_conns; i++) { const struct bt_conn_ctx *ctx = bt_conn_ctx_get_by_id(&conns_ctx_lib, i); if (ctx) { struct bt_nus_client *nus_client = (struct bt_nus_client*) ctx->data; if (nus_client) { err = k_sem_take(&ble_send_semaphore, K_MSEC(5000)); if(err) { LOG_WRN("BLE semaphore timeout, dropping packet (err %d)", err); } else { err = bt_nus_client_send(nus_client, data, len); if (err) { LOG_WRN("Failed to send data over BLE connection (err %d)", err); k_sem_give(&ble_send_semaphore); } } } bt_conn_ctx_release(&conns_ctx_lib, (void *)ctx->data); } } return err; }
The problem with this is you kinda destroy the performance. You can't send a broadcast to all peripherals in "parallel" because the system waits for each message to be finished (semaphore). If I get rid of the semaphore I can send one broadcast to all peripherals without any problems but if I try to send two broadcast fast in a row, the second one will fail.
I'm wondering how I could improve the performance of this.
- If I get rid of the semaphore, several messages to the same peripheral will fail, cause there is still a write process ongoing (NUS_C_RX_WRITE_PENDING flag)
- If I use the semaphore I wait for each message to be finished, although I could send all in "parallel" (if they are for different peripherals).
- Should I use a semaphore array, one for each peripheral?
- Is there any other elegant way, maybe a queue for each peripheral, am I missing anything?
My Setup is: NRF52840, Zephyr, NCS 2.5.1
Thanks for your help,
Phobios