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

Wireless Printf using BLE UART

We are developing a custom ble service and profile however having printf makes our lives that much easier so we are trying to incorporate it purely for testing purposes.

The idea is to send debug messages to an Android device via the nRF UART App. I am using pure-gcc, Linux/Eclipse, and a custom PCB without UART-USB capability.

I noticed there is a printf-gcc which works with the over wire UART on the evaluation boards. Is there an example of how to do something similar with the BLE UART?

Currently what i have working is sending and receiving text strings over UART using a modified ble_app_uart and an the Android UART App. What i cannot figure out is how to utilize all the nice features of printf with UART to print more than just strings. I see there are examples for over the wire UART and printf but not for BLE UART.

Much Thanks!

Nick

  • You can inhibit the already existing nRF redirection module retarget.c by setting "RETARGET_ENABLED 0" in the sdk_config.h file.

    If you then make a copy of retarget.c named my_retarget.c in your project source and enable that module using som other module name like "MY_RETARGET_ENABLED 1" you can redirect as you like.

    In my case I included a 'my_retarget.h' header file in the "my_retarget.c" and "main.c" with an added reference to the "ble_nus.h" library and a redirection flag and a pointer to the ble_nus_t structure to use.

    Header file "my_retarget.h":

    #include "ble_nus.h"
    extern bool use_ble_prn;       //* Enable to use printf over ble set 'use_ble_prn' true prior to a call to printf() */
    extern ble_nus_t * p_nus;      //* Pointer to a static 'ble_nus_t' structure*/
    

    In the "my_retarget.c" I added som more code to the _write() function:

    int _write(int file, const char * p_char, int len)
    {
        int i;
    
        UNUSED_PARAMETER(file);
    
    	if (!use_ble_prn)
    	{
    		//Print to hardware UART
    		for (i = 0; i < len; i++)
    		{
    			UNUSED_VARIABLE(app_uart_put(*p_char++));
    		}	
    
    	}
    	else
    	{
    		//Print to Bluetooth UART
    		if (p_nus != NULL)
    		{
    			ble_nus_string_send(p_nus, (uint8_t *) p_char, len);			
    		}
    
    		//Disable redirection after each print
    		use_ble_prn = false;
    	}
    
        return len;
    } 
    

    The pointer p_nus was initialized in the main.c on the line next after the ble_nus_t structure

    static ble_nus_t                        m_nus;                                      /**< Structure to identify the Nordic UART Service. */
    ble_nus_t *								p_nus = &m_nus;                             /**< Ponter to UART structure used by external retarget> */  
    

    More generic approach - implementing a callback function:

    A more generic aproach would be a writeCallback() function in the my_retarget.c file. In that case you avoid references to UART devices and can do whatever you like in the callback residing in your main module.

    Declared in the my_retarget.h as

    extern volatile int (*_writeCallback)(int, const char *, int);
    

    In the my_retarget.c:

    volatile int(*_writeCallback)(int, const char *, int) = NULL;
    

    ..and callback declared in main.c as:

    //Printf callback function
    volatile int printfCallback(int file, const char * p_char, int len)
    {
    	//Send printf data to ble UART
    	ble_nus_string_send(&m_nus, (uint8_t *) p_char, len);
    	return len;	
    }
    

    ..and to init the callback from main:

    void printf_redirect_init()
    {
    	_writeCallback = printfCallback;
    }
    

    The my_redirect.c may contain a _write() function like this:

    int _write(int file, const char * p_char, int len)
    {
        int i;
    
        UNUSED_PARAMETER(file);
    
    
    	if (use_ble_prn)
    	{
    		//Disable redirection after each print
    		use_ble_prn = false;	
    
    		if (_writeCallback != NULL)
    		{
    			//Invoke callback function
    			return _writeCallback(file, p_char, len);		
    		}
    	
    	}	
    	else
    	{
    		//Print to hardware UART
    		for (i = 0; i < len; i++)
    		{
    			UNUSED_VARIABLE(app_uart_put(*p_char++));
    		}	
    
    	}
    
    
        return len;
    }
    

    At least some ideas to irritate or inspire.

Related