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;
        }
    }

  • I tried this code but my p_ble_nus_evt does have not a member named p_data. I can use (uint32_t)*p_evt->params.rx_data.p_data, but this doesnt seem to be getting the entire int 32 I set. I can see I'm getting a 2 digit hex value, and it is the proper last 2 digits of what im trying to set there but not the whole number. For example, when i set baud to 9600 this value is 0x80, while it should be 0x2580.

    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
    
        if (p_evt->type == BLE_NUS_EVT_RX_DATA)
        {
            uint32_t err_code;
    
            NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
            NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    
            for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
            {
                do
                {
                    err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
                    if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
                    {
                        NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
                        APP_ERROR_CHECK(err_code);
                    }
                } while (err_code == NRF_ERROR_BUSY);
            }
    //        if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r')
    //        {
    //            while (app_uart_put('\n') == NRF_ERROR_BUSY);
    //        }
        }else if(p_evt->type == BLE_NUS_EVT_BAUD)
        {   
            uint32_t baud_rate;
            baud_rate = (uint32_t)*p_evt->params.rx_data.p_data;
            
            if(baud_rate == 9600){
             NRF_UARTE0->BAUDRATE = NRF_UART_BAUDRATE_9600;
            }else if(baud_rate == 57600){
              NRF_UARTE0->BAUDRATE = NRF_UART_BAUDRATE_57600;
            }else if(baud_rate == 38400){
              NRF_UARTE0->BAUDRATE = NRF_UART_BAUDRATE_38400;
            }else if(baud_rate == 115200){
              NRF_UARTE0->BAUDRATE = NRF_UART_BAUDRATE_115200;
            }
            
            NRF_LOG_DEBUG("BAUD Rate Char Written to");
        }
    
    }

  • I figured out this issue. p_data is only a uint8_t. Have to combine all 4 bytes to get the baud rate.

Reply Children
Related