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

Bluetooth bare metal implementation without binary blob

Hello,

I have a question regarding the nRF5340 microcontroller or similar.
Usually, when programming UART, I2C or SPI bare metal, one is using interrupts, register and buffers in RAM.
Even more complex transmission channels such as ETH with the TCPIP protocol or USB can be programmed bare metal,
for example data pages are allocated in the memory and their pointers are written to the corresponding registers in the µC.
Next step is then to implement the protocol.
But is it also possible to program the bluetooth module of a Nordic Semiconductor microcontroller bare metal?
Without binary blobs, just by using registers, interrupts and internal RAM?
I understand that the next layer (protocol) can be complex. However, I would really like to recreate the Bluetooth stack with interrupts and registers. Many thanks.
  • Why can't you use nordic's BLE controller 'blob'? 

    Do you insight into the inner workings of the stack, if so, why?

    Is it size limitations? 


  • Because until now I wrote SENT, SPI, UART, I2C, USB and ETH bare metal. I would like to keep it that way, if possible, to have full control of size and speed of a firmware, even by inserting ASM code.
    I don't understand why the vendor locks the hardware interface that way (not NordSemi, it looks promising, but until now I found all other vendors have only binary blobs, especially for WiFi). Is it due to hardware errors that are fixed within Blops?

  • Waldi1 said:
    Is it due to hardware errors that are fixed within Blops?

    That is often the case, but there's also the fact that silicon vendors have implemented proprietary [read secret] features that would be exposed by an open source stack. 
    A BLE stack also has to be tested and qualified. Each release of our SoftDevice has gone through extensive integration, regression, and conformance testing, to the point that you'd need a prohibitive amount of resources to even come close to the code quality. It's also already optimized for speed and size, again, to the point where it really makes no sense to re-do it. 

    You can ofc use the Zephyr BLE controller, that way you have full control, but at the cost of code quality. 

    With the nRF53 you have the option of running the BLE controller and host on the network core. If you can accept a binary blob in the BLE controller on the network core, you have the whole application core to yourself. You don't need to run zephyr on it, you'd only need to implement the application side of the IPC — Interprocessor communication

  • For those of us that prefer bare metal, Nordic has provided the "nrfx" modules. These headers and source files help a lot to get code up and running with minimal bloat. I wish the same concept can be applied when writing a Bluetooth application. In the case of a Bluetooth application you want to start with one of the Nordic examples and pair it  down to the essentials. Unfortunately, this is extremely difficult since the examples are really tied to almost every part of the SDK. The file dependencies get out of hand quickly and then you spend days just to get the basic example running in your code base.

    In my view the SDK and its examples are good to get you started with nice looking demos but when you really try to do production code ... well good luck.

  • This where IOsonata library comes into play.  It encapsulate the difficulties of the SDK to provide a simple way to write Bluetooth firmware.  Here is an example of how much code you need to write to advertise an incremental number every second.  The whole firmware code you need to write is 4 function calls and a configuration data.  More details on this blog page

    /**-------------------------------------------------------------------------
    @example	BleAdvertiser.cpp
    
    @brief	BLE non-connectable advertiser
    
    This demo show how to advertise an incremental counter in the manufacturer
    specific data.  The counter increments every second.
    
    @author	Hoang Nguyen Hoan
    @date	Dec. 19, 2017
    
    @license
    
    MIT License
    
    Copyright (c) 2017, I-SYST inc., all rights reserved
    
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:
    
    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
    
    ----------------------------------------------------------------------------*/
    #include <string.h>
    
    #include "app_util.h"
    
    #include "istddef.h"
    #include "ble_app.h"
    #include "iopinctrl.h"
    
    #define DEVICE_NAME                     "Advertiser"
    
    #define APP_ADV_INTERVAL                MSEC_TO_UNITS(100, UNIT_0_625_MS)
    #define APP_ADV_TIMEOUT_IN_SECONDS      MSEC_TO_UNITS(1000, UNIT_10_MS)
    
    uint32_t g_AdvCnt = 0;
    
    const BLEAPP_CFG s_BleAppCfg = {
    	{ // Clock config nrf_clock_lf_cfg_t
    #ifdef IMM_NRF51822
    		NRF_CLOCK_LF_SRC_RC,	// Source RC
    		1, 1, 0
    #else
    		NRF_CLOCK_LF_SRC_XTAL,	// Source 32KHz XTAL
    		//NRF_CLOCK_LF_SRC_RC,
    #ifdef NRF51
    		0, 0, NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM
    #else
    		0, 0, NRF_CLOCK_LF_ACCURACY_20_PPM
    #endif
    #endif
    	},
    	0,						// Number of central link
    	1,						// Number of peripheral link
    	BLEAPP_MODE_NOCONNECT,	// Connectionless beacon type
    	DEVICE_NAME,			// Device name
    	ISYST_BLUETOOTH_ID,		// PnP Bluetooth/USB vendor id
    	1,                      // PnP Product ID
    	0,						// Pnp prod version
    	false,					// Enable device information service (DIS)
    	NULL,					// Pointer device info descriptor
    	(uint8_t*)&g_AdvCnt,   	// Manufacture specific data to advertise
    	sizeof(g_AdvCnt),      	// Length of manufacture specific data
    	NULL,
    	0,
    	BLEAPP_SECTYPE_NONE,    // Secure connection type
    	BLEAPP_SECEXCHG_NONE,   // Security key exchange
    	NULL,      				// Service uuids to advertise
    	0, 						// Total number of uuids
    	APP_ADV_INTERVAL,       	// Advertising interval in msec
    	APP_ADV_TIMEOUT_IN_SECONDS,	// Advertising timeout in sec
    	0,							// Slow advertising interval, if > 0, fallback to
    								// slow interval on adv timeout and advertise until connected
    	0,		// Min. connection interval
    	0,		// Max. connection interval
    	-1,		// Led port nuber
    	-1,		// Led pin number
    	0,
    	0,		// Tx power
    	NULL	// RTOS Softdevice handler
    };
    
    void BlePeriphEvtUserHandler(ble_evt_t * p_ble_evt)
    {
    }
    
    void BleAppAdvTimeoutHandler()
    {
    	g_AdvCnt++;
    
    	BleAppAdvManDataSet((uint8_t*)&g_AdvCnt, sizeof(g_AdvCnt), NULL, 0);
    	BleAppAdvStart(BLEAPP_ADVMODE_FAST);
    }
    
    int main()
    {
        BleAppInit((const BLEAPP_CFG *)&s_BleAppCfg, true);
    
        BleAppRun();
    
    	return 0;
    }
    

Related