Note:
This is a project for building BLE firmware that can be flashed to the Wireless MCUs available on some SolidRun products. The firmware is based on Apache mynewt OS with the Apache NimBLE Application providing BLE functionality and HCI protocol support.
Supported Products:
- i.MX8MQ SoM
- u-blox Nina-B1
- SolidSense N6
- u-blox Nina-B1
- u-blox Nina-B3
- Fujitsu FWM7BLZ22
- SolidSense N8
- u-blox Nina-B1
- Fujitsu FWM7BLZ22
sudo apt-get install gcc-arm-none-eabi
Either:
-
Install natively according to mynewt documentation. Note: Download links and version numbers in mynewt documentation are outdated. Please instead follow the steps below:
-
Download "newt" tool v1.11:
wget https://archive.apache.org/dist/mynewt/apache-mynewt-1.11.0/apache-mynewt-newt-bin-linux-1.11.0.tgz tar --strip-components=1 -xvf apache-mynewt-newt-bin-linux-1.11.0.tgz apache-mynewt-newt-bin-linux-1.11.0/newt ./newt version sudo install -v -m755 -o root -g root newt /usr/local/bin/ rm newt
-
Download a native compiler targeting your host PC
-
On Debian / Ubuntu the native distro-compilers can be used:
sudo apt-get update && sudo apt-get install build-essential
-
On openSUSE/SLE the native distro-compilers can be used:
sudo zypper install -t pattern devel_C_C++
-
-
Download a Cross-Compiler targeting ARM MCUs:
wget https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz tar -xvf arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz export PATH="$PWD/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin:$PATH"
Note: The cross-compiler path should be exported each time a new terminal is opened for development purposes.
-
-
Install with docker as a shortcut
sudo apt install docker.io sudo usermod -a -G docker <username> # log out and back in alias newt='docker run -e NEWT_HOST=$(uname) $ti --rm --device=/dev/bus/usb --privileged -v $(pwd):/workspace -w /workspace quay.io/josua-sr/newt:latest /newt'
git clone https://github.com/SolidRun/mynewt-sr-blehci
cd mynewt-sr-blehci
newt upgrade
First, choose a target:
imx8mqsom-nina-b1
- i.MX8MQ SoM
ssn6-nina-b111
- SolidSense N6
- SolidSense N8
ssn6-nina-b301
- SolidSense N6
ssn6-fwm7blz22
- SolidSense N6
- SolidSense N8
Use substitute in the instructions below "imx8mq-nina-b1" with the correct target name.
Then compile bootloader & application:
newt build imx8mqsom-nina-b1_boot
newt build imx8mqsom-nina-b1_blehci
Finally create an application image (adding header with version number). Note that the version number here is a user choice and has no functional impact.
newt create-image imx8mqsom-nina-b1_blehci 0.0.1
OpenOCD is a debugger and programmer that will be used for installing firmware to the MCU - using the SWD protocol.
To compile & install openocd from source-code:
-
install compilers and library dependencies
sudo apt-get install build-essential git autoconf libtool make pkg-config libusb-1.0-0 libusb-1.0-0-dev libgpiod-dev
-
download openocd source-code
git clone https://git.code.sf.net/p/openocd/code openocd cd openocd git reset --hard v0.12.0
-
compile
./configure --prefix=/usr --sysconfdir=/etc --enable-imx_gpio --enable-linuxgpiod --disable-sysfsgpio --disable-stlink --disable-ti-icdi --disable-ulink --disable-usb-blaster-2 --disable-vsllink --disable-xds110 --disable-osbdm --disable-opendous --disable-aice --disable-usbprog --disable-rlink --disable-armjtagew --disable-cmsis-dap --disable-kitprog --disable-usb-blaster --disable-presto --disable-openjtag --disable-jlink --disable-buspirate --disable-esp-usb-jtag --disable-cmsis-dap-v2 --disable-ft232r --disable-ftdi make -j2
-
install
sudo make install
-
Substitute MCU-specific flash locations for loader & application in steps 6 & 7:
- Nina-B1:
- boot:
0x0000
- application:
0x8000
- boot:
- Nina-B3:
- boot:
0x0000
- application:
0xc000
- boot:
- FWM7BLZ22:
- boot:
0x0000
- application:
0x8000
- boot:
- Nina-B1:
-
Generate platform-specific openocd configuration
-
i.MX8MQ SoM
source [find interface/imx-native.cfg] transport select swd set WORKAREASIZE 0 source [find target/nrf52.cfg] imx_gpio_swd_nums 8 66
-
SolidSense N6: Sink 1
source [find interface/imx-native.cfg] transport select swd set WORKAREASIZE 0 source [find target/nrf52.cfg] imx_gpio_swd_nums 82 81
-
SolidSense N6: Sink 2
source [find interface/imx-native.cfg] transport select swd set WORKAREASIZE 0 source [find target/nrf52.cfg] imx_gpio_swd_nums 59 125
-
SolidSense N8:
source [find interface/imx-native.cfg] transport select swd set WORKAREASIZE 0 source [find target/nrf52.cfg] imx_gpio_peripheral_base 0x30200000 imx_gpio_speed_coeffs 50000 50 imx_gpio_swd_nums 14 15
-
-
Launch OpenOCD (server process)
sudo openocd --file ./openocd.cfg
-
Connect to OpenOCD console using telnet (in separate console)
telnet 127.0.0.1 4444 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Open On-Chip Debugger >
-
Check MCU status
> targets TargetName Type Endian TapName State -- ------------------ ---------- ------ ------------------ ------------ 0* nrf52.cpu cortex_m little nrf52.cpu running
If the table shows State as "running" - then the MCU must be stopped by running the halt command:
> halt
[nrf52.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x00012c68 psp: 0x20000288
-
Erase flash
> nrf5 mass_erase RF52833-xxAA(build code: A0) 512kB Flash, 128kB RAM Mass erase completed.
-
program loader
> program /home/debian/boot.elf.bin 0x0000 ... ** Programming Finished **
Note: Specify correct offset for target MCU (0x0000)!
-
program application
> program /home/debian/nimble.img 0x8000 ... ** Programming Finished **
Note: Specify correct offset for target MCU (0x0000)!
-
restart MCU
> reset
Firmware expects a permanent MAC address stored in UICR registers.
MAC can be programmed with OpenOCD using the instructions above but stopping before step 5. Then:
-
read existing UICR registers (on openocd console)
flash read_bank 1 /home/debian/mac
-
write mac address as binary data to the UICR register dumpfile (on linux console)
# 75:c1:1d:09:1c:07 printf '\x07\x1c\x09\x1d\xc1\x75' | dd of=/home/debian/mac bs=1 seek=128 count=6 conv=notrunc
-
write mac address to UICR registers (on openocd console)
> flash erase_sector 1 0 last > flash write_bank 1 /home/debian/mac
The device should now be ready to be initialized under Linux.
sudo btattach -B /dev/ttymxc3 -S 1000000 -N
# Note: btattach is available with bluez on debian
The hci interface should now be available.
hciconfig
hci0: Type: Primary Bus: UART
BD Address: BB:EC:E6:0D:DC:04 ACL MTU: 255:12 SCO MTU: 0:0
UP RUNNING
RX bytes:231 acl:0 sco:0 events:16 errors:0
TX bytes:112 acl:0 sco:0 commands:16 errors:0