h2zero / n-able-Arduino

An arduino core for ARM based BLE devices supported by the NimBLE stack.
GNU Lesser General Public License v2.1
34 stars 12 forks source link

Building Circuit Playground Express Bluefruit w/ Platform IO #38

Open jhmaloney opened 4 months ago

jhmaloney commented 4 months ago

I'm trying to compile for a CPX Bluefruit with Platform IO. Here is my platformio.ini file entry:

[env:cplay52] platform = https://github.com/h2zero/platform-n-able.git#1.0.0 board = adafruit_cplaynrf52840 build_flags = -D CONFIG_WDT_TIMEOUT_SECONDS=0 lib_deps = h2zero/NimBLE-Arduino@^1.4.0

When I try to build I get an error:

Error. Board type requires board_bootloader to be specified

Same problem with the Adafruit Clue.

Thank you!

jhmaloney commented 4 months ago

Oh, I just found examples/BLE-client-test/platformio.ini and I see that I need to add the line:

board_bootloader = adafruit

To my entry. It now compiles but I get an error when attempting to instal firmware on the Clue:

Failed to upgrade target. Error is: No data received on serial port. Not able to proceed. Possible causes:

  • Selected Bootloader version does not match the one on Bluefruit device. Please upgrade the Bootloader or select correct version in Tools->Bootloader.
  • Baud rate must be 115200, Flow control must be off.
  • Target is not in DFU mode. Ground DFU pin and RESET and release both to enter DFU mode.

The firmware installs on the CPX Bluefruit but it fails to start (that could be my bug).

Any ideas?

jhmaloney commented 4 months ago

I updated the Adafruit bootloader on the CPX Bluefruit board to the latest (0.8.3) and now PlatformIO is able to install firmware. However, the resulting program does not run. The Neopixels turn red and the Serial port does not open.

The example program in .platformio/platforms/n-able/examples/BLE-server-test fails and, in fact, even a "hello, world!" program that simply does Serial.println() fails.

What am I doing wrong?

jhmaloney commented 4 months ago

Here is a test program that fails:

void setup() { pinMode(LED_BUILTIN, OUTPUT); }

void loop() { digitalWrite(LED_BUILTIN, HIGH); delay(250); digitalWrite(LED_BUILTIN, LOW); delay(250); }

With this platformio entry:

[env:test] platform = https://github.com/h2zero/platform-n-able.git#1.0.0 board_bootloader = adafruit board = adafruit_cplaynrf52840

h2zero commented 4 months ago

I'm not sure what the issue is. I am guessing that perhaps the bootloader is not installed and would try burning the bootloader first then test.

jhmaloney commented 4 months ago

Yes, I'm guessing this is a bootloader. The board has a bootloader but the bootloader has a SoftDevice which may be conflicting with NimBLE. Here is the info file:

UF2 Bootloader 0.8.3 lib/nrfx (v2.0.0) lib/tinyusb (0.12.0-145-g9775e7691) lib/uf2 (remotes/origin/configupdate-9-gadbb8c7) Model: Adafruit Circuit Playground nRF52840 Board-ID: nRF52840-CircuitPlayground-revD Date: Jan 29 2024 SoftDevice: S140 6.1.1

Do you know what version of the bootloader I should use and if it should include the SoftDevices?

jhmaloney commented 4 months ago

The problem may be this (from the README):

"The provided Adafruit bootloaders have no softdevice, if you currently are using the softdevice based Adafruit bootloader on your nRF52 board you will need to update it to the one provided by selecting it from the boards menu and clicking Burn Bootloader."

Unfortunately, I can't seem make the Arduino IDE burn the bootloader; it complains about not being able to find adafruit-nrfutil in $PATH. (It is in my path in a Terminal; I'm not sure where the Arduino IDE is getting it's PATH.)

I've been trying to use adafruit-nrfutil from the command line but no luck so far. How would you suggest installing a bootloader on Adafruat boards like CPX Bluefruit and Clue using the command line?

h2zero commented 4 months ago

I haven't had to do that in a very long time, I can't really remember much about it now. Definitely easier with the arduino ide. Maybe try reinstalling the board packages in there, get the adafruit one too so you have the tool.

jhmaloney commented 4 months ago

The Adafruit bootloader may have changed since you last tested n-able-arduino on Adafruit boards.

The current bootloader apparently prevents replacing itself or the built-in softdevice. I tried replacing the bootloader both by using the Arduino IDE and by calling nrfutil from the command line. I finally succeeded in replacing it using a JLink hardware programmer. However, most potential users of n-able-arduino are unlikely to own a hardware programmer.

My program (MicroBlocks) is aimed at students and teachers, and I wanted them to be able to install it just by dropping a .uf2 file on their Circuit Playground Bluefruit or Clue boards. Thus, I decided to NOT replace the Adafruit bootloader. Instead, I changed the linker script to install the application after the softdevice. My code never starts the softdevice and n-able-arduino and NimBLE run fine. The only downside of this approach is giving up about 150k of Flash memory, but Flash is plentiful on nRF52 chips. The benefit is that MicroBlocks users can switch easily between MicroBlocks, Makecode, MicroPython, and Arduino programming without messing with bootloaders.

You might consider taking the same approach for the Adafruit boards in the n-able-arduino framework. If you do, note that, in addition to changing the linker script for those boards, I had to replace cores/nRF5/nordic/linker/gcc_startup_nrf52840.S with the version from Adafruit's nrf5 Arduino framework to set the heap and stack addresses correctly. There might be a different way to solve that problem using the linker script.

The suggested change would make n-able-arduino usable on Adafruit boards without replacing the bootloader, which seems to be quite difficult these days.

jhmaloney commented 4 months ago

The suggested change would also address issues #11 and #20.

h2zero commented 4 months ago

@jhmaloney Thank you for this information, I totally agree that the bootloader for those boards should not be changed in this case and we may be able to leverage it for OTA updates in a way too. I would more than welcome a PR to address the linker script issues.

jhmaloney commented 4 months ago

I don't think I have the expertise to do a PR for this, but I'd be happy to advise.

I don't fully understand what the gcc_startup_nrf52840.S must do or how to create a version of it that works for both Adafruit boards with a softdevice (and thus install the user program after the bootloader in Flash) and boards without a softdevice.

I'm also not sure how to organize the linker scripts. We'd need different linker scripts for Adafruit boards and other nRF52840 boards, and we'd need update the entries in the board definitions for both Arduino and platformio to use the proper linker script.

To make it work in my system, I replaced the gcc_startup_nrf52840.S in cores/nRF5/nordic/linker with the one from Adafruit's "framework-arduinoadafruitnrf52" framework. I also added this line:

board_build.ldscript = $PROJECT_DIR/boards/adafruit/nrf52840_s140_v6.ld

to my platformio board environment for the Circuit Playground Bluefruit and copied Adafruit's nrf52840_s140_v6.ld and nrf52_common.ld into a "boards" subfolder of my build folder.

These steps were enough to get MicroBlocks working with BLE support on the Circuit Playground Bluefruit but I'm not compiling for any non-Adafruit nrf52840 boards, and the Adafruit version of gcc_startup_nrf52840.S might not work for those boards.

h2zero commented 4 months ago

Thanks, I have some ideas to support this. I think it would be a simple matter of selecting the linker script based on the bootloader setting.

I would need to look into adafruits bootloader further to ensure it will work without too much trouble. I'm a little concerned that you may have issues with flash storage currently. I think the bootloader uses the last block of flash to store information, if so it will conflict with the EEPROM here.

jhmaloney commented 4 months ago

The Adafruit memory maps here may help. I think both the "user data" and, of course, the "bootloader" sections are reserved. However, the nRF52840 has 1024k of Flash, so even with the soft device and a huge application, we're unlikely to bump into the user data. It is possible that the softdevice, if it were active, would part of the Flash memory as a buffer for OTA provisioning. However, since we are using NimBLE, the soft device is not active, so we needn't worry about that.