10 KiB
My development board
-
512KB flash
-
64KB RAM
-
Using the Generic board variant from arduino-nRF5. This is kinda similar to the Adafruit feather nrf52832 board definition, but seems to use sandeepmistry:openocd instead of nrfutil and uses a different linker as well.
Articles
- Great article about using Rust and Apache Mynewt, but also covers J-Link, ST-Link, openocd, unlocking the nrf52. Link on medium
nrf command line utilities
- nrfjprog Used for programming hex files using the J-Link programmer.
- nrfutil Used for DFU - device firmware update - via the USB port. No J-Link. This is what Adafruit uses for uploading code via USB. This is "higher level" and requires a pre-existing bootloader in the nrf52 chip that understands DFU. The Adafruit_nRF52_Bootloader is such a bootloader, which we can burn using nrfjprog + J-Link once. Adafruit has its own version,
adafruit-nrfutil.
SWD vs. Bootloader vs. DFU
- How
nrfutilis used in the platformio nordicnrf52 package: link - Seems like we can use DFU if we install a DFU-enabled bootloader like the Adafruit_nRF52_Bootloader
- Using the adafruit nrf52 bootloader with the E73-TBB link
Burning the Adafruit bootloader
$ brew cask install nordic-nrf-command-line-tools-> Didn't work. I had to manually install the pkgs from nordicpip install intelhexPATH=$PATH:/Users/rbaron/.platformio/packages/framework-arduinoadafruitnrf52/tools/adafruit-nrfutil/macos make BOARD=feather_nrf52840_express all
Burning our custom bootloader
The error I was making was using a non-softdevice bootloader. The following works:
# Compile
$ PATH=$PATH:/Users/rbaron/.platformio/packages/framework-arduinoadafruitnrf52/tools/adafruit-nrfutil/macos make BOARD=e73_tbb all
# Flash (make sure you use the _s132_ hex file)
$ JAVA_HOME=/Users/rbaron/homebrew/Cellar/openjdk/15.0.1 nrfjprog --program _build/build-e73_tbb/e73_tbb_bootloader-0.4.0-2-g4ba802d_s132_6.1.1.hex --sectoranduicrerase -f nrf52 --reset
Now we can drop the JLink and use the USB serial for uploading/monitoring.
Uploading with nrfutil
$ ~/.platformio/packages/framework-arduinoadafruitnrf52/tools/adafruit-nrfutil/macos/adafruit-nrfutil dfu genpkg --dev-type 0x0052 --sd-req 0x00B7 --application .pio/build/e73-tbb/firmware.hex dfu-pkg.zip
Zip created at dfu-pkg.zip
$ ~/.platformio/packages/framework-arduinoadafruitnrf52/tools/adafruit-nrfutil/macos/adafruit-nrfutil dfu serial --package dfu-pkg.zip -p /dev/cu.usbserial-14330 -b 115200
Upgrading target on /dev/cu.usbserial-14330 with DFU package /Users/rbaron/dev/parasite/code/parasite/dfu-pkg.zip. Flow control is disabled, Dual bank, Touch disabled
########################################
########################################
########################################
########################################
########################################
#######################
Activating new firmware
Device programmed.
Linking
In platformio-core/tools/pioplatform.py:
if "build.ldscript" in board_config:
env.Replace(LDSCRIPT_PATH=board_config.get("build.ldscript"))
In platformio-core/platformio.py:
# append into the beginning a main LD script
if env.get("LDSCRIPT_PATH") and not any("-Wl,-T" in f for f in env["LINKFLAGS"]):
env.Prepend(LINKFLAGS=["-T", env.subst("$LDSCRIPT_PATH")])
The -T flag expects a path to a linker script, as per ld docs.
Frameworks, such as the nordicnrf52, contain boards definitions that specify the ldscript.
- For the adafruit_feather_nrf52832 board, we have:
"arduino":{
"ldscript": "nrf52832_s132_v6.ld"
},
Which is defined here.
- For the nrf52_dk, we have:
"arduino":{
"ldscript": "nrf52_xxaa.ld"
},
Which is the most common linker script, and is part of the nordic official SDK, it seems, available here. For reference, check out the linker for the Adafruit nRF52 Bootloader. Here you can see the memory map of the nRF52 Feather.
Same platform, different framework
Both the Feather nRF52832 and the Generic boards above point to the same platform, the nordicnrf52. Inside this platorm, there's a switch for selecting which framework to use, based on the board name, here:
if self.board_config(board).get("build.bsp.name",
"nrf5") == "adafruit":
self.frameworks["arduino"][
"package"] = "framework-arduinoadafruitnrf52"
What does each line in the linker mean?
Memory layout
The SoftDevice S132 spec specifies the layout as the soft device begins at addr 0x0 and the application code comes after it, at the address APP_CODE_BASE.
PWM
- HardwarePWM.cpp by Adafruit is a good reference. Servo.c uses it.
- nrf52832 pwm spec
- nrf5 SDK PWM reference HAL => Hardware Abstraction Layer?
Analog to digital converter (ADC)
- In nrf52-land, the ADC is called SSADC
- Example in the sdk: in
examples/peripheral/saadc/main.c - Docs from Adafruit. It uses Arduino's
analogRead.
Resoultion
The default resolution is 10 bits (1024 values),
Reference value
The default reference is an internally supplied 3.6V. It seems like we woulld only be able to read values up to 3.6V. This might be enough if we're using a CR2032 coin cell, but might not if we use a LiPo (4.2V fully charged).
Question: what happens if Vcc < 3.6?
There is a possibility of using Vcc as a reference. Then I imagine 0 -> 0V; 1024 -> Vcc. This might be exactly what we want: In a PWM positive pulse, our RC_parasitic will rise to 0.63Vcc in R*C_para time. If we use Vcc as a reference for the ADC, I think we "cancel out" the Vcc factor.
So in Arduino land, using AR_VDD4 does all we need: use nrf's SAADC_CH_CONFIG_REFSEL_VDD1_4 (Vcc/4 ref) and a gain of 4 (SAADC_CH_CONFIG_GAIN_Gain1_4). While connected via USB, with:
analogReference(AR_VDD4);
int sens_val = analogRead(kSensAnalogPin);
I'm getting ~680 when in the air; ~65 while holding the sensor. The default resolution is 10 bits, so 1024 -> 3.3V. On the scope, I'm reading the sensor output value to be 2.16V. This matches the value I'm reading: 1024/3.3 * 2.15 = 667. Nice.
Battery
- CR2032 datasheet
- 235 mAh (from 3.0V to 2.0V)
- Typical discharge current: 0.19 mA -> 1200 hours
Battery monitoring
- Good post on how to measure lipo batteries: link
BLE
- BLE examples for platformio with nordicnrf52 platform: link
- BLEPeripheral seems to be a popular library choice
- nrf5 BLE examples are way more complicated than I need for now