Mynewt FAQ - Bluetooth¶
- NimBLE on nRF52840
- Trigger Exactly One BLE Advertisement Immediately
- Supported Bluetooth Radio Transceivers
- NimBLE Operational Questions
blemeshForgets All Keys on Restart
- L2CAP Connection
- Bitbang, BLE Mesh, BLE Advertising
- Extended Advertising with
- Configuring Maximum Number of Connections for
- Disconnect/Crash While Writing Analog Value From Central Module
- Documentation for
- Multicast Messaging and Group Messaging
- Read the Value of a Characteristic of a Peripheral Device from a Central Device
Q: Is the nRF52840 supported by NimBLE?
A: The nRF52840 is supported, including Bluetooth 5 features.
Q: Is there a way to trigger exactly one BLE advertisement immediately? I basically want to use BLE as a means to advertise to a whole group of devices and it needs to be relatively time-precise. Hoping for about 1ms precision, but it’s okay if there’s a delay as long as it’s deterministic.
A: With extended advertising you can enable an advertising instance for exactly 1 advertising event but there will be some delay before controller starts advertising which depends on the level of precision. The NimBLE controller always schedules the 1st advertising event with a constant 5ms delay. However, if there are other things scheduled in the controller it may need to schedule it later so it’s not guaranteed to be deterministic. Periodic advertising is currently not supported.
Q: Are there any other Bluetooth radio transceivers that are supported already or anyone working on? If there is a Bluetooth radio that can be integrated using the HCI, we can use the NimBLE host? If so, I suppose we don’t need detailed specs of the Bluetooth radio?
A: You should be able to run the NimBLE host against pretty much any controller using HCI. We have a BLE controller implementation for Nordic only, but host (in theory) should work with all. More likely, it will work with 5.0 controller. For 4.x controllers it may fail on initialization since we do not check controller features - but this can be fixed as for other radio transceivers. For example, there’s NXP KW41Z which has BLE-compatible radio documented. However, NXP documentation is more or less a description of zillions of different registers so not as friendly as the one from Nordic which explains how to actually use it.
Q: Can I update firmware via BLE for multiple devices simultaneously using a single device/phone supporting Bluetooth?
A: Yes, it is possible to update several Nimble devices simultaneously from a single phone (e.g., central) as long as the central can handle all the simultaneous Bluetooth connections. You can also do it using your computer as a central with newtmgr. Just open two terminals and initiate a newtmgr image upload command in each, each to a different device. You will, however, get better overall throughput if you limit yourself to one upgrade at a time.
Q: I have the following doubts on NimBLE: The document says 32+ concurrent connections, multiple connections in simultaneous central and peripheral roles. Does that mean the “device running NimBLE” can connect to 32 different other devices like phones?
A: Yes, with one caveat: each of the 32 centrals needs to be sufficiently cooperative in choosing connection partners
(http://www.novelbits.io/ble-connection-intervals/). Your app might need to request different connection parameters from
the centrals (using
Of course, you will also need to build the Mynewt image device with a configuration suitable for 32 concurrent connections
Q: Is it expected that the blemesh example forgets all the keys on restart and needs to be provisioned again? If so, how can I implement key persistence myself? Is there any API to obtain / provide mesh keys before the mesh node is started? I found bt_mesh_provision, but the comment there seems to indicate that this is not the right way to use it.
A: Mesh implementations do not persist keys at the moment. There is a plan to add it but not sure about timeline. It
probably needs to be implemented inside mesh implementation so there’s no API, but if you’d like to hack something I suggest
taking a look at shell.c and testing.c - there are some testing functions to add/display keys. Another area to look if you
actually want to persist keys to flash is
net/nimble/host/store/config/src/ble_store_config.c. This is the code that
persists and restores security material for (non-mesh) Bluetooth.
Q: I want to do an L2CAP connection, and am trying the auth-passkey command, but am not sure about the parameters
oob. What is
psm, and what is the value of that parameter in the btshell command
do I set the parameters
psm stands for Protocol Service Multiplexer. You pass the
psm value to either
l2cap-create-server. The parameters
oob are just passing constant values as defined in the API.
Q: Is it possible to run bitbanging and BLE mesh at the same time? How about running BLE Mesh and BLE advertising at the same time?
A: It is possible to run bitbanging and BLE mesh at the same time, but the bitbanging UART takes a lot of CPU on Nordic.
We’ve run it at 9600 which would probably be okay for lower rate devices, but for reliability it is recommended to run at
4800. If this is just for the console and your UART port is tied up,
rtt is recommended. Take a look at
Segger RTT Console for more information. However, bitbanger can be handy given limited UARTs.
You can certainly continue advertisements during connections, if you are using the GATT bearer for mesh. Mesh is also tied into the ext-adv bearer in Mynewt, which also allows for interleaving, even if you’re transmitting mesh data on advertising channels.
Q: I am using
btshell for advertising with nRF52. When I use 31 bytes,
mfg_data accepts the data with extended
advertising. But when I use more bytes than that,
mfg_data doesn’t accept it. Is 251 byte payload supported in extended
advertising? How can I send more than a 251 byte payload on extended advertising?
A: You need to set the
BLE_EXT_ADV_MAX_SIZE syscfg to your required value. For example:
newt target amend <your_target> syscfg=BLE_EXT_ADV=1:BLE_EXT_ADV_MAX_SIZE=1650
The default is 31 bytes, and the max is 1650.
Keep in mind that with extended advertising, you cannot set advertising data for an instance configured as scannable
advertise-configure scannable=1). Either set scan response data using
(parameters are the same as for
advertise-set-adv-data) or configure the instance as non-scannable. For example,
advertise-configure alone will configure the instance as non-connectable and non-scannable which means you can
set advertising data. Also note that if you continue to use a scannable instance you will need to perform active
scanning in order to get scan response data.
FYI, legacy advertising instances can accept both advertising and scan response data but since they use legacy PDUs the limit is still 31 bytes.
Q: How do I set the maximum number of connections for the
I see there is a
MYNEWT_VAL_BLE_MAX_CONNECTIONS, but I don’t know how to set it.
A: You can to set it in target settings:
newt target amend <target> syscfg=BLE_MAX_CONNECTIONS=2
and then rebuild using
newt build <target>.
MYNEWT_VAL_BLE_MAX_CONNECTIONS is just a symbol that is defined in
syscfg.h which is autogenerated by
newt tool and contains all the settings set at package/app/target level.
Q: What if I need to set 2 constants? What’s the syntax?
A: You can set each setting in separate commands or separate
key=value pairs with colon:
newt target amend <target> syscfg=FOO=1:BAR=2
Q: How do you know the constant is
BLE_MAX_CONNECTIONS and not
Is there a place I can see those names?
A: This is actually one of NimBLE’s settings - you can find these settings available for different packages in the
syscfg.yml files in the repository. You can also use
newt target config show <target> to show all settings with
their current values, and then change any of these settings accordingly. Each setting will get a symbol prefixed by
MYNEWT_VAL_ in the autogenerated
syscfg.h file so you can get the actual setting name from this symbol. For more
info on System Configuration and Initialization, please visit the Compile-Time Configuration and Initialization page in the OS User Guide.
Q: I’m trying to write analog sensor data from my central module to my peripheral module. I can receive the values
from the ADC callback perfectly, but I’m not able to write them to the peripheral module. The peripheral module disconnects
right when the
ble_gattc_write_flat command is called. What could be causing the issue?
A: First, check the reason for the disconnect. The gap event callback should indicate the reason in
If the code never reaches the disconnect callback, then the code most likely crashed. If so, check whether
is called from an interrupt context. Calling into the BLE host from within an interrupt is a bad idea in general, and may cause a
crash to occur because the Bluetooth host attempts to log to the console during the write procedure. Logging to the console uses
quite a bit of stack space, so it is likely that the interrupt stack is overflowing.
Instead, you should send an event to the event queue and handle this in a task context. You’ll need to associate the characteristic
data with the event so that your event callback knows what payload to pass to the
ble_gattc_write_flat() function. If you don’t
need to perform multiple writes in rapid succession, then you can just use a single global event and single global buffer. However,
you will still need to make sure your buffer doesn’t become corrupted by a subsequent ADC interrupt while you are in mid-write.
Q: Is there documentation somewhere on correct values for
ble_gap_disc_params? I’m trying to do a passive discovery and getting
A: Unfortunately, not at the moment. Here is a brief description of the fields:
itvl: This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. (units=0.625 msec)
window: The duration of the LE scan.
LE_Scan_Windowshall be less than or equal to
filter_policy: The only useful documentation is the table in the Bluetooth spec (section 2.E.7.8.10). This field controls which types of devices to listen for.
limited: If set, only discover devices in limited discoverable mode.
passive: If set, don’t send scan requests to advertisers (i.e., don’t request additional advertising data).
filter_duplicates: If set, the controller ignores all but the first advertisement from each device.
Q: Is it possible to send a broadcast message by one of the devices present in the mesh (e.g. broadcast an event which happened)? Something like a push notification instead of continuously polling for it by a client.
A: It is possible to do so with a publish model. Group address or virtual address should help here, according to the Mesh spec. There is no real documentation on it but you can try it out on our
btmesh_shell app. There is a
shell.c file which exposes configuration client which you can use for testing (e.g. you can subscribe to virtual addresses). You can also trigger sending messages to devices. By playing with the
dst command, you probably should be able to set destination to some group. However, since we do not support the provisioner role, there is a command provision which sets fixed keys so you can create a mesh network out of a couple of nodes without the actual provisioner.
Q: I want to read the value of a characteristic of a peripheral device from a central device which runs on Mynewt OS. How can I obtain the value using the following function?
int ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle, ble_gatt_attr_fn *cb, void *cb_arg);
A: To see an example of this function being used, take a look at the
blecent sample app. The data is in
attr->om, which is an
mbuf struct. There are dedicated APIs to access data in mbufs (see
attr->om->om_data is a raw pointer to access data in mbuf so you could also use it, but keep in mind that data in mbuf can be fragmented so you may not be able to access them easily like this. Thus, it is safer to use mbuf APIs instead.
os_mbuf_copydata should be especially useful here since it can copy data from mbuf to flat buffer.