User Tools

Site Tools


arduino:s340_softdevice_adafruit_nrf52840_feather_express

This is an old revision of the document!


S340 SoftDevice & Adafruit nRF52840 Express Feather

This lazy-guide is a short summary about how I made my Adafruit Feather nRF52840 Express work with ANT+.

The Feather is an Arduino compatible board using the nRF52840 SoC from Nordic Semiconductor (NordicSemi).

Introduction

ANT (Adaptive Network Topology) is a wireless communication network standard intended for sensor networks. Originally developed by DynaStream, it currently belongs to Garmin. It operates in the ISM spectrum and most of its specs available publicly. Certain IPR-s remains controlled by Garmin, but for non-commerical use it can be used without a license fee.

ANT+ is a interoperability standard on top of the ANT transport standard in order to create an “ultra low-power wireless” ecosystem for fitness and medical applications. Notably, Garmin runners' and bikers' watches and bike-computers uses this standard to communicate with various measurement sensors.

The nRF52840 SoC is part of the nRF52 series of chips from NordicSemi. It is multi-protocol capable and a number of Arduino compatible boards sports this chipset. The most notable ones:

For legal (and probably other reasons) neither of these boards come with the ANT+ protocol stack pre-installed, albeit they are fully capable of running that stack. This guide is a summary of how I made my Adafruit nRF52840 Feather ANT+ capable while I kept its original functionality, i.e., being Arduino compatible and supporting Adafruit's Bluefruit Bluetooth library.

The adaptation removes the Bluetooth only S140 SoftDevice from the firmware and replaces it with the S340 combined SoftDevice running BLE5 and ANT+ concurrently.

Note: The CircuitPython capability will be lost, since the stock CircuitPython interpreter for this Feather is provided as a binary UF2 firmware update is bound to the S140 Bluetooth-only softdevice.

BEWARE: trying to install the CircuitPython UF2 package to a S340-adapted Feather will brick your Feather and you will need to use a SWD programmer device to make your Feather usable again!

Credits

A number of internet resources helped me. The biggest help came as form of a personal mail from rtgree01, whom I got acquainted with by Curtis Malainey. It was him, who first managed the S340 SoftDevice to work with his Feather and he kindly shared his steps with me. This guide is based primarily on his work.

Prerequisites

Must to have

Most likely you will need to have

  • An SWD programmer (Segger J-link), just in case if you need to “unbrick” your feather after a mistake.

Note: the nRF52840-DK from NordicSemi contains an On-Board Segger programmer (Segger-OB), which is free to use for Nordic chipsets. The Segger OB on the NordicSemi DevKit also has an SWD connector for external boards, so it can be used with the Feather, as well. Otherwise the Segger EDU can be a not-so-expensive alternative

Good to have

Adapting the bootloader

Note: this tutorial is based on the v.6.1.1 versions of the NordicSemi softdevices and the 0.3.0 version of the Adafruit bootloader

A. Warm-up: Rebuild the Adafruit bootloader

1. Clone the Adafruit bootloader from https://github.com/adafruit/Adafruit_nRF52_Bootloader. It contains two submodules, hence you need to clone it recursively. I used to the GitHub Desktop, which does recursive cloning automagically

git clone https://github.com/adafruit/Adafruit_nRF52_Bootloader
cd Adafruit_nRF52_Bootloader
git submodule update --init --recursive

Follow its readme: https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/master/README.md

  1. install the ARM-GCC toolchain, plus the GNU make, as needed. See above
  2. install nRF5x command line tools, as needed. See above
  3. install adafruit-nrfutil, a modified version of Nordic nrfutil, which required to perform DFU. Install python3 if it is not installed already and run this command to install adafruit-nrfutil from PyPi:
$ pip3 install --user adafruit-nrfutil

2. Make sure that you can succesfully build and flash it into your board.

Follow the instructions at https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/master/README.md. Change the serial to your actual serial device. For me, under Windows10 it was COM5. Under Linux it could be, for example, /dev/ttyACM0

$ make BOARD=feather_nrf52840_express all combinehex
$ make BOARD=feather_nrf52840_express SERIAL=COM5 dfu-flash

If you run into any trouble, then DO NOT PROCEED further down within this lazy-guide until you can successfully rebuild the original bootloader and flash it into your device!! (If you can't build and flash the original version, then it makes no sense to try to hack it.)

B. Get the ANT SoftDevice

Download S340 SoftDevice from thisisant.com. Unpack it somewhere. You will need to rename and copy it later.

C. Modify the Adafruit bootloader

1. Adapt the Makefile

Insert the following after setting flags according to MCU_SUB_VARIANTS after line #106:

ifdef USE_S340 
#if S340 then adjust SD_NAME and MCU
  SD_NAME = s340
  MCU_FLAGS = -DNRF52840_XXAA -DS340
endif

The graphical diff looks like this (left is orginal, right is modified) Makefile diff

2. Insert the S340 SoftDevice headers and binary into the source tree

Go to …\lib\softdevice\. Create a dir called s340_nrf52_6.1.1:

...\lib\softdevice $ mkdir s340_nrf52_6.1.1

This directory needs to store the v6.1.1 version of the BLE+ANT combinded S340 softdevice headers + the .hex binary. The way you can get that is described here: https://www.nordicsemi.com/Software-and-tools/Software/S340-ANT

IMPORTANT:

  1. you should rename the .hex file to: s340_nrf52_6.1.1_softdevice.hex
  2. You should put the S340 library headers under: s340_nrf52_6.1.1_API

That is, your resulted library tree should look exactly like this:

s340_nrf52_6.1.1/
├── s340_nrf52_6.1.1_API
│   └── include
│       ├── ant_error.h
│       ├── ant_interface.h
│       ├── ant_parameters.h
│       ├── ble.h
│       ├── ble_err.h
│       ├── ble_gap.h
│       ├── ble_gatt.h
│       ├── ble_gattc.h
│       ├── ble_gatts.h
│       ├── ble_hci.h
│       ├── ble_l2cap.h
│       ├── ble_ranges.h
│       ├── ble_types.h
│       ├── nrf52
│       │   └── nrf_mbr.h
│       ├── nrf_error.h
│       ├── nrf_error_sdm.h
│       ├── nrf_error_soc.h
│       ├── nrf_nvic.h
│       ├── nrf_sd_def.h
│       ├── nrf_sdm.h
│       ├── nrf_soc.h
│       └── nrf_svc.h
└── s340_nrf52_6.1.1_softdevice.hex

3. Modify nrf_sdm.h

  • Go to …/lib/softdevice/s340_nrf52_6.1.1/s340_nrf52_6.1.1_API/include/
  • Modify 'nrf_sdm.h' at line #191: uncomment the ANT_LICENSE_KEY in case your use of the softdevice conforms to the Garmin licensing conditions for ANT evaluation license!. If not, then you must obtain a commercial license.

The graphical diff looks like this (left is orginal, right is modified)

4. Create a new board definition called ''feather_nrf52840_express_s340''

  • Go to … /src/boards/.
  • Copy the 'feather_nrf52840_express' dir to 'feather_nrf52840_express_s340'
  • Go into the 'feather_nrf52840_express_s340' subdir, which was just freshly created by copying 'feather_nrf52840_express' over.
Modify src/boards/feather_nrf52840_express_s340/board.h
  • Change the #include guards from “_FEATHER_NRF52840_H” to something else, say _FEATHER_NRF52840_S340_H
  • Change the “BLEDIS_MODEL” to something else, say “Feather nRF52840 Express S340”
  • Change the “UF2_PRODUCT_NAME” to something else, say ““Adafruit Feather nRF52840 Express S340”

The graphical diff looks like this (left is orginal, right is modified)

Modify src/boards/feather_nrf52840_express_s340/board.mk
  1. Add “USE_S340 = true” to the end of the file as a new line

The graphical diff looks like this (left is orginal, right is modified)

5. Modify the linker script of the UF2 bootloader

Go to …/src/usb/uf2. Modify the “USER_FLASH_START” definition inside uf2cfg.h:

  • In case of the original S140 the flash area shall start at 0x26000
  • In case of the S340 the flash area shall start at 0x31000

That is, the “USER_FLASH_START” shall be defined as follows:

#ifdef S340
#define USER_FLASH_START   0x31000
#else // #ifdef S340
#define USER_FLASH_START   0x26000
#endif // #ifdef S340

The graphical diff looks like this (left is orginal, right is modified)

6. Create a new GCC linker script for the freshly defined board

  1. Go to …/src/linker directory.
  2. Copy the S140 linker script as S340 linker, as follows
src/linker $ cp nrf52840_s140_v6.ld nrf52840_s340_v6.ld 

7. Adapt the main.c program

  1. Go to …/src/
  2. Adapt …/src/main.c to supply the ANT_LICENSE_KEY for the softdevice enable in case of S340, otherwise call the function without the key, as follows:
#ifndef ANT_LICENSE_KEY
APP_ERROR_CHECK( sd_softdevice_enable(&clock_cfg, app_error_fault_handler) );
#else
APP_ERROR_CHECK( sd_softdevice_enable(&clock_cfg, app_error_fault_handler, ANT_LICENSE_KEY) );
#endif

The graphical diff looks like this (left is orginal, right is modified)

D. Build and flash the modified Adafruit bootloader

Go to the root of the bootloader directory tree. Build and flash as follows.

NOTE: adapt the GNU_INSTALL_ROOT and SERIAL definitions according to your local setup!

make GNU_INSTALL_ROOT="C:/Program Files (x86)/GNU Tools Arm Embedded/9 2019-q4-major/bin/"  BOARD=feather_nrf52840_express_s340 all combinehex
make GNU_INSTALL_ROOT="C:/Program Files (x86)/GNU Tools Arm Embedded/9 2019-q4-major/bin/"  BOARD=feather_nrf52840_express_s340 SERIAL=COM5 dfu-flash

Enjoy :)

If you got confused you can check my forked repo at: https://github.com/orrmany/Adafruit_nRF52_Bootloader/tree/s340-for-nrf52840-Feather

E. Appendix: a transcript of my build

C:\Users\egbozie\Google Drive\Arduino\libraries\Adafruit_nRF52_Bootloader>make BOARD=feather_nrf52840_express all combinehex
CC main.c
CC boards.c
CC flash_nrf5x.c
CC dfu_ble_svc.c
CC dfu_init.c
CC nrfx_power.c
CC nrfx_nvmc.c
CC system_nrf52840.c
CC bootloader.c
CC bootloader_settings.c
CC bootloader_util.c
CC dfu_transport_serial.c
CC dfu_transport_ble.c
CC dfu_single_bank.c
CC pstorage_raw.c
CC ble_dfu.c
CC ble_dis.c
CC app_timer.c
CC app_scheduler.c
CC app_error.c
CC app_util_platform.c
CC crc16.c
CC hci_mem_pool.c
CC hci_slip.c
CC hci_transport.c
CC nrf_assert.c
CC usb_desc.c
CC usb.c
CC msc_uf2.c
CC ghostfat.c
CC dcd_nrf5x.c
CC tusb_fifo.c
CC usbd.c
CC usbd_control.c
CC cdc_device.c
CC msc_device.c
CC tusb.c
AS gcc_startup_nrf52840.S
LD feather_nrf52840_express_bootloader-0.2.13-21-g454b281-dirty-nosd.out
''
   text    data     bss     dec     hex filename
  30376     212   22426   53014    cf16 _build-feather_nrf52840_express/feather_nrf52840_express_bootloader-0.2.13-21-g454b281-dirty-nosd.out
''
CR feather_nrf52840_express_bootloader-0.2.13-21-g454b281-dirty-nosd.hex
CR feather_nrf52840_express_bootloader-0.2.13-21-g454b281-dirty_s340_6.1.1.hex
 
C:\Users\egbozie\Google Drive\Arduino\libraries\Adafruit_nRF52_Bootloader>make BOARD=feather_nrf52840_express SERIAL=COM5 dfu-flash
LD feather_nrf52840_express_bootloader-0.2.13-21-g454b281-dirty-nosd.out
CR feather_nrf52840_express_bootloader-0.2.13-21-g454b281-dirty-nosd.hex
Zip created at _build-feather_nrf52840_express/feather_nrf52840_express_bootloader-0.2.13-21-g454b281-dirty_s340_6.1.1.zip
adafruit-nrfutil --verbose dfu serial --package _build-feather_nrf52840_express/feather_nrf52840_express_bootloader-0.2.13-21-g454b281-dirty_s340_6.1.1.zip -p COM5 -b 115200 --singlebank --touch 1200
Upgrading target on COM5 with DFU package C:\Users\egbozie\Google Drive\Arduino\libraries\Adafruit_nRF52_Bootloader\_build-feather_nrf52840_express\feather_nrf52840_express_bootloader-0.2.13-21-g454b281-dirty_s340_6.1.1.zip. Flow control is disabled, Single bank, Touch 1200
Touched serial port COM5
Opened serial port COM5
Starting DFU upgrade of type 3, SoftDevice size: 190272, bootloader size: 30580, application size: 0
Sending DFU start packet
Sending DFU init packet
Sending firmware file
########################################
########################################
########################################
########################################
########################################
########################################
########################################
########################################
########################################
########################################
################################
Activating new firmware
 
DFU upgrade took 24.582117557525635s
Device programmed.
 
C:\Users\egbozie\Google Drive\Arduino\libraries\Adafruit_nRF52_Bootloader>
arduino/s340_softdevice_adafruit_nrf52840_feather_express.1588596115.txt.gz · Last modified: 2020/05/04 14:41 by orrmany