Hello,
As I have already connected two peripherals at the same time, the central can automatically receive and display the data only for the first connection.
While I tried to receive the data from both two connections and displayed the data by UART.
I think it is mainly relevant to the ble_data_received function that writes the "tx" to the FIFO of "fifo_inc_ble_data" then read it when UART interrupts.
However, I actually don't know how to add anther tx linking with the second connection to write the second data to FIFO,
or should I give anther FIFO which gets the second data to the UART?
Hence, can you please tell me where should I modify or some configurations were missing?
#include <errno.h> #include <zephyr.h> #include <sys/byteorder.h> #include <sys/printk.h> #include <sys/util.h> #include <string.h> #include <usb/usb_device.h> #include <drivers/uart.h> #include <bluetooth/bluetooth.h> #include <bluetooth/hci.h> #include <bluetooth/conn.h> #include <bluetooth/uuid.h> #include <bluetooth/gatt.h> #include <bluetooth/services/nus.h> #include <bluetooth/services/nus_client.h> #include <bluetooth/gatt_dm.h> #include <bluetooth/scan.h> #include <settings/settings.h> #include <logging/log.h> #include <device.h> #include <devicetree.h> #include <drivers/gpio.h> #define LED0_NODE DT_ALIAS(led0) #if DT_NODE_HAS_STATUS(LED0_NODE, okay) #define LED0 DT_GPIO_LABEL(LED0_NODE, gpios) #define PIN DT_GPIO_PIN(LED0_NODE, gpios) #define FLAGS DT_GPIO_FLAGS(LED0_NODE, gpios) #else /* A build error here means your board isn't set up to blink an LED. */ #error "Unsupported board: led0 devicetree alias is not defined" #define LED0 "" #define PIN 0 #define FLAGS 0 #endif #define LED1_NODE DT_ALIAS(led1) #if DT_NODE_HAS_STATUS(LED1_NODE, okay) #define LED1 DT_GPIO_LABEL(LED1_NODE, gpios) #define PIN1 DT_GPIO_PIN(LED1_NODE, gpios) #define FLAGS1 DT_GPIO_FLAGS(LED1_NODE, gpios) #else /* A build error here means your board isn't set up to blink an LED. */ #error "Unsupported board: led0 devicetree alias is not defined" #define LED0 "" #define PIN 0 #define FLAGS 0 #endif #define LOG_MODULE_NAME central_uart LOG_MODULE_REGISTER(LOG_MODULE_NAME); /* UART payload buffer element size. */ #define UART_BUF_SIZE 100 #define KEY_PASSKEY_ACCEPT DK_BTN1_MSK #define KEY_PASSKEY_REJECT DK_BTN2_MSK #define NUS_WRITE_TIMEOUT K_MSEC(150) #define UART_WAIT_FOR_BUF_DELAY K_MSEC(50) #define UART_RX_TIMEOUT 50 int counter; int con_num = 0; #define DEVICE_NAME "FF_22" char device_name[5]="FF_22"; char *name = device_name; static const struct device *uart; static struct k_work_delayable uart_work; K_SEM_DEFINE(nus_write_sem, 0, 1); struct uart_data_t { void *fifo_reserved; uint8_t data[UART_BUF_SIZE]; uint16_t len; }; static K_FIFO_DEFINE(fifo_inc_ble_data); static K_FIFO_DEFINE(fifo_out_ble_data); static struct bt_conn *default_conn; static struct bt_nus_client nus_client; const struct device *dev; bool led_is_on = true; bool led1_is_on = true; int ret; static void ble_data_sent(uint8_t err, const uint8_t *const data, uint16_t len) { LOG_INF("BLE data sent!"); struct uart_data_t *buf; /* Retrieve buffer context. */ buf = CONTAINER_OF(data, struct uart_data_t, data); k_free(buf); // k_sem_give(&nus_write_sem); if (err) { LOG_WRN("ATT error code: 0x%02X", err); } } static uint8_t ble_data_received(const uint8_t *const data, uint16_t len) { LOG_INF("BLE data arrived! length %d",len); struct uart_data_t *tx = k_malloc(sizeof(*tx)); if(!tx){ LOG_INF("malloc failed!"); } else{ tx->len = len; memcpy(tx->data,data,len); k_fifo_put(&fifo_inc_ble_data, tx); } uart_irq_tx_enable(uart); //display the received data counter++; if(counter == 50) { if (con_num == 1) { gpio_pin_set(dev, PIN1, false); //off LED2 gpio_pin_set(dev, PIN, (int)led_is_on); led_is_on = !led_is_on; } else if(con_num == 2) { gpio_pin_set(dev, PIN, false); //off LED1 gpio_pin_set(dev, PIN1, (int)led1_is_on); led1_is_on = !led1_is_on; } counter = 0; } return BT_GATT_ITER_CONTINUE; } static void uart_isr( void *dev) { uart_irq_update(dev); if(uart_irq_rx_ready(dev)) { LOG_INF("Data to read on RX"); struct uart_data_t *rx = k_malloc(sizeof(*rx)); if(!rx){ LOG_INF("malloc failed!"); } else{ uint8_t len = uart_fifo_read(dev,rx->data,UART_BUF_SIZE); rx->len = len; k_fifo_put(&fifo_out_ble_data, rx); } } if(uart_irq_tx_ready(dev)) { LOG_INF("SPACE IN UART FIFO FOR MORE"); if(!k_fifo_is_empty(&fifo_inc_ble_data)) { struct uart_data_t *tx = k_fifo_get(&fifo_inc_ble_data, K_NO_WAIT); LOG_INF("tx from queue is: %d",tx); uart_fifo_fill(dev, tx->data, tx->len); k_free(tx); } // else{ // LOG_INF("NO TX"); // } } if(uart_irq_tx_complete) { LOG_INF("TX done."); } } static int uart_init(void) { LOG_INF("Enabling UART"); int err; uart = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME); if (!uart) { LOG_ERR("UART binding failed"); return -ENXIO; } if (usb_enable(NULL)) { return -1; } if (strlen(CONFIG_UART_CONSOLE_ON_DEV_NAME) != strlen("CDC_ACM_0") || strncmp(CONFIG_UART_CONSOLE_ON_DEV_NAME, "CDC_ACM_0", strlen(CONFIG_UART_CONSOLE_ON_DEV_NAME))) { printk("Error: Console device name is not USB ACM\n"); return -1; } uart_irq_callback_set(uart,uart_isr); uart_irq_callback_user_data_set(uart,uart_isr,uart); uart_irq_rx_enable(uart); return 0; } static void discovery_complete(struct bt_gatt_dm *dm, void *context) { struct bt_nus_client *nus = context; LOG_INF("Service discovery completed"); bt_gatt_dm_data_print(dm); bt_nus_handles_assign(dm, nus); bt_nus_subscribe_receive(nus); bt_gatt_dm_data_release(dm); } static void discovery_service_not_found(struct bt_conn *conn, void *context) { LOG_INF("Service not found"); } static void discovery_error(struct bt_conn *conn, int err, void *context) { LOG_WRN("Error while discovering GATT database: (%d)", err); } struct bt_gatt_dm_cb discovery_cb = { .completed = discovery_complete, .service_not_found = discovery_service_not_found, .error_found = discovery_error, }; static void gatt_discover(struct bt_conn *conn) { int err; if (conn != default_conn) { return; } err = bt_gatt_dm_start(conn, BT_UUID_NUS_SERVICE, &discovery_cb, &nus_client); if (err) { LOG_ERR("could not start the discovery procedure, error " "code: %d", err); } } static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params) { if (!err) { LOG_INF("MTU exchange done: %d",bt_att_get_mtu(conn)); } else { LOG_WRN("MTU exchange failed (err %" PRIu8 ")", err); } } static void connected(struct bt_conn *conn, uint8_t conn_err) { char addr[BT_ADDR_LE_STR_LEN]; int err; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); if (conn_err) { LOG_INF("Failed to connect to %s (%d)", log_strdup(addr), conn_err); if (default_conn == conn) { bt_conn_unref(default_conn); default_conn = NULL; err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); if (err) { LOG_ERR("Scanning failed to start (err %d)", err); } } return; } LOG_INF("Connected: %s", log_strdup(addr)); static struct bt_gatt_exchange_params exchange_params; exchange_params.func = exchange_func; err = bt_gatt_exchange_mtu(conn, &exchange_params); if (err) { LOG_WRN("MTU exchange failed (err %d)", err); } err = bt_conn_set_security(conn, BT_SECURITY_L2); if (err) { LOG_WRN("Failed to set security: %d", err); gatt_discover(conn); } err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); if (err) { LOG_ERR("Scanning failed to start (err %d)", err); return; } LOG_INF("Scanning again"); } static void disconnected(struct bt_conn *conn, uint8_t reason) { char addr[BT_ADDR_LE_STR_LEN]; int err; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_INF("Disconnected: %s (reason %u)", log_strdup(addr), reason); con_num--; if (con_num == 0) gpio_pin_set(dev, PIN, false); //off LED1 if (default_conn != conn) { return; } bt_conn_unref(default_conn); default_conn = NULL; err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); if (err) { LOG_ERR("Scanning failed to start (err %d)", err); } } static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); if (!err) { LOG_INF("Security changed: %s level %u", log_strdup(addr), level); } else { LOG_WRN("Security failed: %s level %u err %d", log_strdup(addr), level, err); } gatt_discover(conn); } static struct bt_conn_cb conn_callbacks = { .connected = connected, .disconnected = disconnected, .security_changed = security_changed }; static void scan_filter_match(struct bt_scan_device_info *device_info, struct bt_scan_filter_match *filter_match, bool connectable) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr)); LOG_INF("Filters matched. Address: %s connectable: %d", log_strdup(addr), connectable); con_num++; LOG_INF("Connection number: %d",con_num); //record the peripheral connection number } static void scan_connecting_error(struct bt_scan_device_info *device_info) { LOG_WRN("Connecting failed"); } static void scan_connecting(struct bt_scan_device_info *device_info, struct bt_conn *conn) { default_conn = bt_conn_ref(conn); } static int nus_client_init(void) { int err; struct bt_nus_client_init_param init = { .cb = { .received = ble_data_received, .sent = ble_data_sent, } }; err = bt_nus_client_init(&nus_client, &init); if (err) { LOG_ERR("NUS Client initialization failed (err %d)", err); return err; } LOG_INF("NUS Client module initialized"); return err; } BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL, scan_connecting_error, scan_connecting); static int scan_init(void) { int err; struct bt_scan_init_param scan_init = { .connect_if_match = 1, }; bt_scan_init(&scan_init); bt_scan_cb_register(&scan_cb); err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_NAME, DEVICE_NAME); if (err) { LOG_ERR("Scanning filters cannot be set (err %d)", err); return err; } err = bt_scan_filter_enable(BT_SCAN_NAME_FILTER, false); if (err) { LOG_ERR("Filters cannot be turned on (err %d)", err); return err; } LOG_INF("Scan module initialized"); return err; } static void auth_cancel(struct bt_conn *conn) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_INF("Pairing cancelled: %s", log_strdup(addr)); } static void pairing_confirm(struct bt_conn *conn) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); bt_conn_auth_pairing_confirm(conn); LOG_INF("Pairing confirmed: %s", log_strdup(addr)); } static void pairing_complete(struct bt_conn *conn, bool bonded) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_INF("Pairing completed: %s, bonded: %d", log_strdup(addr), bonded); } static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_WRN("Pairing failed conn: %s, reason %d", log_strdup(addr), reason); } static struct bt_conn_auth_cb conn_auth_callbacks = { .cancel = auth_cancel, .pairing_confirm = pairing_confirm, .pairing_complete = pairing_complete, .pairing_failed = pairing_failed }; void main(void) { int err; dev = device_get_binding(LED0); if (dev == NULL) { return; } ret = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_INACTIVE | FLAGS); if (ret < 0) { return; } dev = device_get_binding(LED1); if (dev == NULL) { return; } ret = gpio_pin_configure(dev, PIN1, GPIO_OUTPUT_INACTIVE | FLAGS1); if (ret < 0) { return; } err = bt_conn_auth_cb_register(&conn_auth_callbacks); if (err) { LOG_ERR("Failed to register authorization callbacks."); return; } err = bt_enable(NULL); if (err) { LOG_ERR("Bluetooth init failed (err %d)", err); return; } LOG_INF("Bluetooth initialized"); if (IS_ENABLED(CONFIG_SETTINGS)) { settings_load(); } bt_conn_cb_register(&conn_callbacks); int (*module_init[])(void) = { uart_init, scan_init, nus_client_init}; for (size_t i = 0; i < ARRAY_SIZE(module_init); i++) { err = (*module_init[i])(); if (err) { return; } } LOG_INF("Initialized done."); printk("Starting Bluetooth Dongle\n"); err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); if (err) { LOG_ERR("Scanning failed to start (err %d)", err); return; } LOG_INF("Scanning successfully started"); for (;;) { } }
Thank you in advance for any suggestions here!
Best Regards
Ethan