adafruit / Adafruit_nRF52_Arduino

Adafruit code for the Nordic nRF52 BLE SoC on Arduino
Other
625 stars 498 forks source link

nrf52840 dongle (PCA10059) support #200

Closed jpconstantineau closed 4 years ago

jpconstantineau commented 5 years ago

I started with getting the variant file ported over to the Nordic NRF52840 dongle (PCA10059)

I was able to flash the PCA10059 bootloader that's in the dev branch (thanks for that). I was able to use the UF2 files and upload them to the Dongle.

Issues found:

image

hathach commented 5 years ago

current code assume nrf52840 always come with an external flash (true for feather 52840 and DK). You need to remap that to internal flash. It is complicated, maybe you can disable the USB MSC class in the tusb_config.h and move on with others first. When I got more time, I could do that remap part later.

jpconstantineau commented 5 years ago

@hathach Is the USB MSC comment for the usb_init issue or the P0.12/P1.09 issue? I assume it's for the USB issue; with would make sense for all the windows trouble I had. I can leave the usb_init out for now and focus on getting the GPIOs tested and working...

jpconstantineau commented 5 years ago

Update: I tested all the GPIOs and pulled out my oscilloscope to validate that everything checks out. The LEDs on P0.12 and P1.09 work "fine" There is a signal going to them, as measured at the resistances. However, because VDD is at 1.8V, it probably does not have enough voltage to drive the LEDs to be visible. I would have to add an external power source/regulator to test this out.

After converting the NFC pins to GPIOs, only Pin P1.00 cannot be toggled using digitalToggle(32). All other GPIOs accessible on the dongle can be toggled. All I can measure at P1.00 is a constant digital high (1.8V). Pressing reset momentarily toggles it to 0V.

hathach commented 5 years ago

@jpconstantineau usb_init() will init the whole usb stack, you still need it for Serial/CDC and uploading (without jlink). You could simply turn usb msc off (leaving cdc on) by change this config https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/usb/tusb_config.h#L88

For the voltage issue, you may find this useful, I think Dan did an amazing job to address this.

https://github.com/adafruit/circuitpython/issues/1174

jpconstantineau commented 5 years ago

@hathach That did it! Thanks! Dropped the suggested code from https://devzone.nordicsemi.com/f/nordic-q-a/28562/nrf52840-regulator-configuration into a form similar to the code to switch from nfc to gpio and that worked. I am wondering where would be the best place to drop that code in. Would variantInit be a good choice? I suspect the bootloader would make more sense...

P1.00 still stays at logic high even if I toggle the pin every 100ms

hathach commented 5 years ago

Glad that works for you. You can put it into variant init for now ( with comment if possible ). I will double check and move it later to bootloader if needed. Or you can also fork our bootloader repo https://github.com/adafruit/Adafruit_nRF52_Bootloader and submit your PR as well. Either way, when I got more time to work/verify with the dongle, I will try my best to move it into correct place.

jpconstantineau commented 5 years ago

According to the Pin assignments in the specs, P1.00 Maps to General purpose I/O, Trace buffer TRACEDATA[0] and Serial wire output (SWO) with recommended usage of QSPI. I suspect that P1.00 being "locked" might have to do with this. Do you know if QSPI in the nrf52840 feather express is tied to that line?

oddstr13 commented 5 years ago

What is the current status of this branch?

oddstr13 commented 5 years ago

I am having trouble getting the BLE UART example working on the dongle. The dongle is resetting on Bluefruit.begin();

Minimal example

#include <bluefruit.h>

void setup()
{
  // Logic analyzer debug output (1.13)
  pinMode(45, OUTPUT);
  digitalWrite(45, LOW);

  Serial.begin(115200);
  while ( !Serial ) delay(10);   // for nrf52840 with native usb

  Serial.println("Bluefruit52 BLEUART Example");
  Serial.println("---------------------------\n");

  Bluefruit.begin();

  Serial.println("Bluefruit initialized.");
}

void loop() {
  delay(1000);
}

My setup

Debuging

Serial output of the example code, including my debug prints

Bluefruit52 BLEUART Example
---------------------------

$0001
$0002
$0003
$0004
$0005
[CFG   ] SoftDevice's RAM requires: 0x20002530
$0006
$0007
$0008
$0009
$0010
$0011
$0012
$0013
$0014
$0015
LittleFS::begin$1
_iflash_read: 0xED000, 128
_iflash_read: 0xED080, 128
lfs error:494: Corrupted dir pair at 0 1
lfs error:2222: Invalid superblock at 0 1
LittleFS::begin$2: -52
[IFLASH] Format internal file system
LittleFS::format$1
_iflash_read: 0xED000, 128
_iflash_read: 0xED100, 128
_iflash_erase
_iflash_prog
_iflash_sync$1

fal_erase from flash_nrf5x.c, with debug output

bool fal_erase (uint32_t addr)
{
  digitalWrite(45, HIGH);
  delayMicroseconds(1000);
  digitalWrite(45, LOW);
  // Init semaphore for first call
  if ( _sem == NULL )
  {
    _sem = xSemaphoreCreateCounting(10, 0);
    VERIFY(_sem);
  }

  // retry if busy
  uint32_t err;
  while ( NRF_ERROR_BUSY == (err = sd_flash_page_erase(addr / FLASH_NRF52_PAGE_SIZE)) )
  {
    digitalToggle(45);
    delay(1);
  }
  digitalWrite(45, HIGH);
  delayMicroseconds(100);
  digitalWrite(45, LOW);
  VERIFY_STATUS(err, false);
  digitalWrite(45, HIGH);
  delayMicroseconds(100);
  digitalWrite(45, LOW);

  // wait for async event if SD is enabled
  uint8_t sd_en = 0;
  (void) sd_softdevice_is_enabled(&sd_en);
  digitalWrite(45, HIGH);
  delayMicroseconds(100); // The reset seems to happen about halfway thru this delay
  digitalWrite(45, LOW);

  if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);

  digitalWrite(45, HIGH);
  delayMicroseconds(1000);
  digitalWrite(45, LOW);
  return true;
}

Logic analyzer

5x fal_read followed by a partial fal_erase 5x `fal_read` followed by a partial `fal_erase` Zoomed in on the fal_erase Zoomed in on the `fal_erase`

As this is (consistently) happening in the middle of a delay (something parallel to the current code is causing the reset), I'm at a loss of how to continue debugging the issue.

Could it be due to me using the default bootloader?

@jpconstantineau could you verify wether the minimal example provided above results in a reset (and loss of the Serial link), or if it is likely to be something wrong on my end?

hathach commented 5 years ago

hi, just want to say, we remove the pca10056 bootloader binary since we are doing release and this board port is not done yet. The bootloader binary for that board can be found here

https://github.com/adafruit/Adafruit_nRF52_Bootloader/releases

hathach commented 5 years ago

@jpconstantineau Could you be able to resolve all the issues with pca100569. This board is not commonly used official by Adafruit engineer, therefore we have limited support, should issue with this board arise. It would be great if you can help us along the line.

jpconstantineau commented 5 years ago

@hathach I have been busy completing some of the work I had committed to last year. Once my nrf52832 firmware is in a good spot, I'll move back on to the 840.

Has the bootloader been updated for it?

hathach commented 5 years ago

@jpconstantineau no problem, I can actually help testing the dongle for the PR, though, you need to help us in the long-term, should issue arises specifically with this board since it is not our "official" board, and other tech may not have this in his/her hand. If yes, please response to Limor in your PR.

TasosR83 commented 5 years ago

I started with getting the variant file ported over to the Nordic NRF52840 dongle (PCA10059)

I was able to flash the PCA10059 bootloader that's in the dev branch (thanks for that). I was able to use the UF2 files and upload them to the Dongle.

Issues found:

* [ ]  When Bootloader is in "DFU" Mode, serial port name is shown as  "nrf52840 feather express" in Arduino IDE (but not in device manager)" See picture below

* [x]  LEDs on P0.12 or P1.09 cannot be turned on/off. LEDs on P0.06 and P0.08 work as expected.

* [ ]  When usb_init(); is called in initVariant, it enables the USB storage.  Unfortunately, my Windows 10 PC does not like it at all. It stalls regularly and even audio settings are impacted (loose audio, sends to monitor instead, finds audio again). Not activating usb_init in initVariant avoids all these computer issues.  It looks like there is something not behaving right when it's activated.

* [x]  Test GPIOs

* [ ]  P1.00 GPIO cannot be toggled

image

Dear @jpconstantineau , You have written that: " I started with getting the variant file ported over to the Nordic NRF52840 dongle (PCA10059) I was able to flash the PCA10059 bootloader that's in the dev branch (thanks for that). I was able to use the UF2 files and upload them to the Dongle. "

Can you please help me on how to flash the bootloader and how upload UF2 files to the dongle ? The 'nrf connect programmer' doesnt allow me to change the bootloader (unsecure bootloader warning) and nrfjprog doesnt allow me to pass the bootloader's .hex file too...

hathach commented 5 years ago

You will need a jlink or another dk board.

TasosR83 commented 5 years ago

You will need a jlink or another dk board.

I have a DK board, do you have any link to read the exact procedure ?

ladyada commented 5 years ago

@TasosR83 we have some docs here https://learn.adafruit.com/circuitpython-on-the-nrf52 but overall do not provide support for using nordic DK boards (we don't sell or use them!)

ericlangel commented 5 years ago

my 840 Dongle doesn't appear as COM Port after flashing Adafruits Bootloader Hex files

i tried different files...but the is not recognized as a COM Port....

ericlangel commented 5 years ago

i think there was a Problem with the DapLink Programmer i took a JLink Programmer and everythink was fine

RoganDawes commented 5 years ago

For what it is worth, I was able to flash the UF2 bootloader onto my PCA10059 using a Black Magic Probe, with the following sequence:

Use Black Magic Probe, and SWDP mode, 4 wires only plugged into a breadboard.

Use the breadboard holes and male DuPont connectors to hold the dongle in place, and male dupont wires to press against the relevant headers. Vcc, Ground and SWCLK on one side of the board, TMS to SWDIO on the other side of the board. In this way, you can avoid soldering onto the board, as this is only required for a very short time. You may need to apply pressure to make sure you get good connections while performing the following GDB commands.

Then, in gdb:

$ arm-none-eabi-gdb
(gdb) target extended-remote /dev/ttyACM0
(gdb) mon tpwr enable
(gdb) mon swdp
Target voltage: 3.3V
Available Targets:
No. Att Driver
 1      Nordic nRF52
 2      Nordic nRF52 Access Port

(gdb) att 1
Attaching to Remote target
0xfffffffe in ?? ()
0xfffffffe in ?? ()
(gdb) mon erase_mass
erase..
(gdb) detach
Detaching from program: , Remote target
(gdb) att 2
Attaching to Remote target
warning: while parsing target description: no element found
warning: Could not load XML target description; ignoring
PC not available
PC register is not available
PC not available
(gdb) mon erase_mass
(gdb) detach

(gdb) att 1
Attaching to Remote target
0xfffffffe in ?? ()
(gdb) load pca10059_bootloader-0.2.9_s140_6.1.1.hex 

Then unplug from BMP, plug in to USB, should see the bootloader in dmesg, creating an NRF52BOOT Mass Storage Class volume, which can be used to load UF2-formatted files.

P.S. It would be awesome if someone could create a firmware flashable via NRFConnect Desktop that contained a copy of the UF2 bootloader, and simply overwrote the Nordic bootloader, then rebooted after verifying that it was successfully written.

hathach commented 5 years ago

P.S. It would be awesome if someone could create a firmware flashable via NRFConnect Desktop that contained a copy of the UF2 bootloader, and simply overwrote the Nordic bootloader, then rebooted after verifying that it was successfully written.

I remember reading nordic bootloader is secured, you could upload application with open mode. But to upgrade bootloader it need to be signed. It also use ACL to prevent writing to bootloader in application mode as well. jlink is much easier.

RoganDawes commented 5 years ago

Interesting! I would have expected the application running on the processor to have full control over the flash, at least in terms of writing to it. I was unaware that it may be possible to prevent the application from writing to certain zones in this manner! I agree, a JLink would certainly avoid any of those problems. But not all users have access to a JLink/SWD device.

hathach commented 4 years ago

closed due to lack of active development

dmpolukhin commented 3 years ago

@hathach it looks like this task abandoned but support for PCA10059 still missing in master. Does it make sense to make pull request that adds PCA10059 board or there is no interest in supporting this board because it requires initial flashing with external debugger? It looks like PCA10059 is fully functional just need 3V mode to be useful i.e. LED flashing, etc.

hathach commented 3 years ago

There is no interest to support pca10059, we are currently only focusing on support boards that our team have access to.

dmpolukhin commented 3 years ago

It is sad but I see your point. The only reason I started making pca10059 board is that there is no Adafruit BLE boards that performs comparable to pca10059 in low power. With Feather Sense that does nothing the lowest power consumption that I able to achieve is about 500uA. At the same time with Dongle that reads sensor and advertises I can go down to about 30uA. I wish I had Adafruit board with LiPo connector and potentially charger and comparable low power performance.

I would be happy to upstream both but... :( My fork that makes pca10059 working is here https://github.com/dmpolukhin/Adafruit_nRF52_Arduino Platformio board support is here https://github.com/dmpolukhin/platform-nordicnrf52 Use like this:

platform = https://github.com/dmpolukhin/platform-nordicnrf52.git
board = nordic_nrf52840_dongle
platform_packages = framework-arduinoadafruitnrf52@https://github.com/dmpolukhin/Adafruit_nRF52_Arduino.git
ladyada commented 3 years ago

we understand, it is just too difficult for us to become the support manager for a board we dont own, didn't design. it will disappoint people who have support questions and we don't want to do that. please continue to use your fork :)

mame82 commented 2 years ago

Leaving this Twitter thread here, which gives some guidance on issues which I had to overcome, in order to work with pca10059:

https://threadreaderapp.com/thread/1552233889867120641.html

mame82 commented 2 years ago

Here are required code changes, to allow compilation for pca10059 (Community_nRF52_Arduino) with armeabi toolchain on KALI-Linux (debian):

diff --git a/cores/nRF5/HardwarePWM.h b/cores/nRF5/HardwarePWM.h
index 47ec16c..f3ecbb3 100644
--- a/cores/nRF5/HardwarePWM.h
+++ b/cores/nRF5/HardwarePWM.h
@@ -51,7 +51,7 @@ class HardwarePWM
   private:
     enum { MAX_CHANNELS = 4 }; // Max channel per group
     NRF_PWM_Type * const _pwm;
-    std::atomic_uint32_t _owner_token;
+    std::atomic<uint32_t> _owner_token;

     uint16_t _seq0[MAX_CHANNELS];

diff --git a/cores/nRF5/itoa.c b/cores/nRF5/itoa.c
index 608145e..49aca53 100644
--- a/cores/nRF5/itoa.c
+++ b/cores/nRF5/itoa.c
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2014 Arduino LLC.  All right reserved.
+  Copyright (c) 2016 Arduino.  All right reserved.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -8,7 +8,7 @@

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
   See the GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
@@ -20,8 +20,56 @@
 #include <string.h>

 #ifdef __cplusplus
-extern "C" {
-#endif
+extern "C"{
+#endif // __cplusplus
+
+#if 0
+/* reverse:  reverse string s in place */
+static void reverse( char s[] )
+{
+  int i, j ;
+  char c ;
+
+  for ( i = 0, j = strlen(s)-1 ; i < j ; i++, j-- )
+  {
+    c = s[i] ;
+    s[i] = s[j] ;
+    s[j] = c ;
+  }
+}
+
+/* itoa:  convert n to characters in s */
+extern void itoa( int n, char s[] )
+{
+  int i, sign ;
+
+  if ( (sign = n) < 0 )  /* record sign */
+  {
+    n = -n;          /* make n positive */
+  }
+
+  i = 0;
+  do
+  {       /* generate digits in reverse order */
+    s[i++] = n % 10 + '0';   /* get next digit */
+  } while ((n /= 10) > 0) ;     /* delete it */
+
+  if (sign < 0 )
+  {
+    s[i++] = '-';
+  }
+
+  s[i] = '\0';
+
+  reverse( s ) ;
+}
+
+#else
+
+extern char* itoa( int value, char *string, int radix )
+{
+  return ltoa( value, string, radix ) ;
+}

 extern char* ltoa( long value, char *string, int radix )
 {
@@ -73,6 +121,11 @@ extern char* ltoa( long value, char *string, int radix )
   return string;
 }

+extern char* utoa( unsigned long value, char *string, int radix )
+{
+  return ultoa( value, string, radix ) ;
+}
+
 extern char* ultoa( unsigned long value, char *string, int radix )
 {
   char tmp[33];
@@ -90,7 +143,7 @@ extern char* ultoa( unsigned long value, char *string, int radix )
   {
     return 0;
   }
-
+ 
   while (v || tp == tmp)
   {
     i = v % radix;
@@ -103,14 +156,15 @@ extern char* ultoa( unsigned long value, char *string, int radix )

   sp = string;

-
+ 
   while (tp > tmp)
     *sp++ = *--tp;
   *sp = 0;

   return string;
 }
+#endif /* 0 */

 #ifdef __cplusplus
 } // extern "C"
-#endif
+#endif // __cplusplus
diff --git a/cores/nRF5/itoa.h b/cores/nRF5/itoa.h
index ba0010a..a0cb31d 100644
--- a/cores/nRF5/itoa.h
+++ b/cores/nRF5/itoa.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2016 Arduino.  All right reserved.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -8,7 +8,7 @@

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
   See the GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
@@ -16,15 +16,27 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

-#pragma once
+#ifndef _ITOA_
+#define _ITOA_

 #ifdef __cplusplus
 extern "C"{
-#endif
+#endif // __cplusplus

+#if 0
+
+extern void itoa( int n, char s[] ) ;
+
+#else
+
+extern char* itoa( int value, char *string, int radix ) ;
 extern char* ltoa( long value, char *string, int radix ) ;
+extern char* utoa( unsigned long value, char *string, int radix ) ;
 extern char* ultoa( unsigned long value, char *string, int radix ) ;
+#endif /* 0 */

 #ifdef __cplusplus
 } // extern "C"
-#endif
+#endif // __cplusplus
+
+#endif // _ITOA_
ladyada commented 2 years ago

thanks, feel free to submit a PR for the core changes (we still cant support the board definition but at least this will make it easier!)

jpconstantineau commented 2 years ago

Thanks @ladyada for the comment.

@mame82 I am planning to deprecate my "community" BSP and move over to a new tracking Community repo here: https://github.com/nRF52-Arduino/nRF52_Arduino

You can give a try to the new repo and see if the same changes that you identified applies.

If I remember well, I think many of the boards the original community BSP has are already there but with the advantage that any changes to the original Adafruit BSP will make its way to the new community much more easily - akin to micropython and circuitpython.

ladyada commented 2 years ago

yay thanks @jpconstantineau :)