This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Adding Baud Rate Characteristic to UART example

Hello All,

I am implementing a simple UART bridge over BLE and want to add a Characteristic to update the baud rate being used. I thought I added code to support a new characteristic everywhere it needs to go, but when I scan for characteristics with the nRF connect app or another BLE scanner, it does not show up in the list.  The plan is to look for the newly defined BLE_NUS_EVT_BAUD event in the nus_data_handler and update the baud rate accordingly. Is there anything I am missing here when it comes to adding a characteristic?

I added the following lines of code to the UART example:

in ble_nus.h


struct ble_nus_s
{
uint8_t uuid_type; /**< UUID type for Nordic UART Service Base UUID. */
uint16_t service_handle; /**< Handle of Nordic UART Service (as provided by the SoftDevice). */
ble_gatts_char_handles_t tx_handles; /**< Handles related to the TX characteristic (as provided by the SoftDevice). */
ble_gatts_char_handles_t baud_handles;
ble_gatts_char_handles_t rx_handles; /**< Handles related to the RX characteristic (as provided by the SoftDevice). */
blcm_link_ctx_storage_t * const p_link_ctx_storage; /**< Pointer to link context storage with handles of all current connections and its context. */
ble_nus_data_handler_t data_handler; /**< Event handler to be called for handling received data. */
};

in ble_nus.c

#define BLE_UUID_NUS_BAUD_CHARACTERISTIC 0x0004 /**< The UUID of the BAUD Characteristic. */
#define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */
#define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */

#define BLE_NUS_MAX_BAUD_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the BAUD Characteristic (in bytes). */
#define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */
#define BLE_NUS_MAX_TX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */

in on_write in ble_nus.c

else if ((p_evt_write->handle == p_nus->baud_handles.value_handle) &&
(p_nus->data_handler != NULL))
{
evt.type = BLE_NUS_EVT_BAUD;
evt.params.rx_data.p_data = p_evt_write->data;
evt.params.rx_data.length = p_evt_write->len;

p_nus->data_handler(&evt);
}

in ble_nus_init in ble_nus.c

// Add the BAUD Characteristic.
memset(&add_char_params, 0, sizeof(add_char_params));
add_char_params.uuid = BLE_UUID_NUS_BAUD_CHARACTERISTIC;
add_char_params.uuid_type = p_nus->uuid_type;
add_char_params.max_len = BLE_NUS_MAX_RX_CHAR_LEN;
add_char_params.init_len = sizeof(uint8_t);
add_char_params.is_var_len = true;
add_char_params.char_props.write = 1;
add_char_params.char_props.read = 1;

add_char_params.read_access = SEC_OPEN;
add_char_params.write_access = SEC_OPEN;

err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->baud_handles);
if (err_code != NRF_SUCCESS)
{
return err_code;
}

Parents
  • I see that there is no clean easy way to change the baudrate of the uart on the fly.

    So I am just showing you an option to use the registers directly (instead of using NRFX API) to come to an easy and short solution. Please do not take the below code as official suggested solution, but just as an implication to see how it can be done quickly as below

    /**@brief Callback handling Nordic UART Service (NUS) client events.
     *
     * @details This function is called to notify the application of NUS client events.
     *
     * @param[in]   p_ble_nus_c   NUS client handle. This identifies the NUS client.
     * @param[in]   p_ble_nus_evt Pointer to the NUS client event.
     */
    
    /**@snippet [Handling events from the ble_nus_c module] */
    static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt)
    {
        ret_code_t err_code;
    
        switch (p_ble_nus_evt->evt_type)
        {
            case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
                NRF_LOG_INFO("Discovery complete.");
                err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles);
                APP_ERROR_CHECK(err_code);
    
                err_code = ble_nus_c_tx_notif_enable(p_ble_nus_c);
                APP_ERROR_CHECK(err_code);
                NRF_LOG_INFO("Connected to device with Nordic UART Service.");
                break;
    
            case BLE_NUS_C_EVT_NUS_TX_EVT:
                ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);
                break;
    
            case BLE_NUS_EVT_BAUD:
                // make sure that there are no ongoing transactions
                // APP_UART_DRIVER_INSTANCE is 0
                NRF_UARTE0->BAUDRATE = (uint16_t)*p_ble_nus_evt->p_data; //uint32_t if the len is different, depends on what you sent on the peer side
    #if 0
                // APP_UART_DRIVER_INSTANCE is 1
                NRF_UARTE1->BAUDRATE = (uint16_t)*p_ble_nus_evt->p_data; //uint32_t if the len is different, depends on what you sent on the peer side
    #endif
                break;
    
            case BLE_NUS_C_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected.");
                scan_start();
                break;
        }
    }

  • Thank you. 

    A couple other questions for my application. How can I set the value of the characteristic to be read from the peer side on initialization? I would want the end user to be able to read what baud rate is set in the BLE device and then allow them to change it if needed.

    Secondly, is there any memory available in this chip to be able to save settings such as device name and baud rate over a power cycle, and set them accordingly on the next power up?

  • aaron.mcneil said:
    A couple other questions for my application. How can I set the value of the characteristic to be read from the peer side on initialization? I would want the end user to be able to read what baud rate is set in the BLE device and then allow them to change it if needed.

     NRF_UARTE->BAUDRATE is a read-write register. So after the uart is initialized and all services discovered, you can send a notification to the peer with a magic prefix(command) combined with a baudrate value. There are many ways to do it and you need to consider this properly to see which way first best to your application architecture.

     

    aaron.mcneil said:
    Secondly, is there any memory available in this chip to be able to save settings such as device name and baud rate over a power cycle, and set them accordingly on the next power up?

     Save to flash (non-volatile memory) which will keep the data even after power cycles. FDS library can help you with that.

Reply
  • aaron.mcneil said:
    A couple other questions for my application. How can I set the value of the characteristic to be read from the peer side on initialization? I would want the end user to be able to read what baud rate is set in the BLE device and then allow them to change it if needed.

     NRF_UARTE->BAUDRATE is a read-write register. So after the uart is initialized and all services discovered, you can send a notification to the peer with a magic prefix(command) combined with a baudrate value. There are many ways to do it and you need to consider this properly to see which way first best to your application architecture.

     

    aaron.mcneil said:
    Secondly, is there any memory available in this chip to be able to save settings such as device name and baud rate over a power cycle, and set them accordingly on the next power up?

     Save to flash (non-volatile memory) which will keep the data even after power cycles. FDS library can help you with that.

Children
Related