Merge pull request #934 from microbuilder/usbboot

[WIP] nRF52840 USB Bootloader
This commit is contained in:
Limor "Ladyada" Fried 2018-06-15 09:35:30 -07:00 committed by GitHub
commit 9fc0ec6af8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 11123 additions and 32 deletions

2
.gitignore vendored
View File

@ -7,7 +7,7 @@
*.bin
*.map
*.hex
!ports/nrf/**/bootloader/*.hex
!ports/nrf/**/bootloader/**/*.hex
*.dis
*.exe

@ -1 +1 @@
Subproject commit d48561b07386132b849d0125b0ff6a532d833d8b
Subproject commit 9e7dfb28a5c6f3d7a19340971b32e0c2b4128ecf

View File

@ -291,9 +291,22 @@ FLASHER ?=
ifeq ($(FLASHER),)
# Adafruit use bootloader that requires writing to its settting ( app valid = 0x0001, crc = 0x0000 )
ifneq (,$(filter $(BOARD),feather52 feather52840))
flash: $(BUILD)/$(OUTPUT_FILENAME).hex
nrfjprog --program $< --sectorerase -f $(MCU_VARIANT)
nrfjprog --erasepage $(BOOT_SETTING_ADDR) -f $(MCU_VARIANT)
nrfjprog --memwr $(BOOT_SETTING_ADDR) --val 0x00000001 -f $(MCU_VARIANT)
nrfjprog --reset -f $(MCU_VARIANT)
else
flash: $(BUILD)/$(OUTPUT_FILENAME).hex
nrfjprog --program $< --sectorerase -f $(MCU_VARIANT)
nrfjprog --reset -f $(MCU_VARIANT)
endif
sd: $(BUILD)/$(OUTPUT_FILENAME).hex
nrfjprog --eraseall -f $(MCU_VARIANT)

View File

@ -28,6 +28,20 @@ This is a port of CircuitPython to the Nordic Semiconductor nRF52 series of chip
* nRF52840
* [PCA10056](http://www.nordicsemi.com/eng/Products/nRF52840-Preview-DK)
## Board Specific Instructions
For board-specific instructions on building and flashing CircuitPython, see
the following links:
> **NOTE**: These board specific readmes may be more up to date than the
generic board-neutral documentation further down.
* Adafruit [Feather nRF52](boards/feather52/README.md): 512KB Flash, 64KB SRAM
* Adafruit [Feather nRF52840](boards/feather52840/README.md): 1MB Flash, 256KB SRAM
* Nordic PCA10056 see [Feather nRF52840](boards/feather52840/README.md)
For all other board targets, see the generic notes below.
## Compile and Flash
Prerequisite steps for building the nrf port:

View File

@ -6,6 +6,7 @@ SOFTDEV_VERSION ?= 2.0.1
LD_FILE = boards/feather52/custom_nrf52832_dfu_app_$(SOFTDEV_VERSION).ld
BOOTLOADER_PKG = boards/feather52/bootloader/feather52_bootloader_$(SOFTDEV_VERSION)_s132_single.zip
BOOT_SETTING_ADDR = 0x7F000
NRF_DEFINES += -DNRF52832_XXAA
ifeq ($(OS),Windows_NT)
@ -31,12 +32,12 @@ __check_defined = \
.PHONY: dfu-gen dfu-flash boot-flash
dfu-gen:
$(NRFUTIL) dfu genpkg --dev-type 0x0052 --application $(BUILD)/$(OUTPUT_FILENAME).hex $(BUILD)/dfu-package.zip
$(NRFUTIL) dfu genpkg --sd-req 0xFFFE --dev-type 0x0052 --application $(BUILD)/$(OUTPUT_FILENAME).hex $(BUILD)/dfu-package.zip
dfu-flash:
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyUSB0)
$(NRFUTIL) dfu serial --package $(BUILD)/dfu-package.zip -p $(SERIAL) -b 115200
$(NRFUTIL) dfu serial --package $(BUILD)/dfu-package.zip -p $(SERIAL) -b 115200 --singlebank
boot-flash:
dfu-bootloader:
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyUSB0)
$(NRFUTIL) dfu serial --package $(BOOTLOADER_PKG) -p $(SERIAL) -b 115200

View File

@ -74,7 +74,7 @@ nrfjprog version: 9.7.2
JLinkARM.dll version: 6.20f
```
### Flash the Bootloader with `nrfjprog`
### Option 1 (nRF52832 or nRF52840): Flash the HW UART Bootloader with `nrfjprog`
> This operation only needs to be done once, and only on boards that don't
already have the serial bootloader installed.
@ -105,6 +105,37 @@ Run.
From this point onward, you can now use a simple serial port for firmware
updates.
### Option 2 (nRF52840): Flash the USB CDC Bootloader with 'nrfjprog'
> This operation only needs to be done once, and only on boards that don't
already have the serial bootloader installed.
Once `nrfjprog` is installed and available in `PATH` you can flash your
board with the serial bootloader via the following command:
```
make SD=s140 BOARD=feather52840 boot-usb-flash
```
This should give you the following (or very similar) output, and you will see
a DFU blinky pattern on one of the board LEDs:
```
$ make SD=s140 BOARD=feather52840 boot-usb-flash
Use make V=1, make V=2 or set BUILD_VERBOSE similarly in your environment to increase build verbosity.
nrfjprog --program boards/feather52840/bootloader/usb/feather52840_bootloader_6.0.0_s140_single.hex -f nrf52 --chiperase --reset
Parsing hex file.
Erasing user available code and UICR flash areas.
Applying system reset.
Checking that the area to write is not protected.
Programing device.
Applying system reset.
Run.
```
From this point onward, you can now use a simple serial port for firmware
updates.
### IMPORTANT: Disable Mass Storage on PCA10056 J-Link
The J-Link firmware on the PCA10056 implement USB Mass Storage, but this
@ -174,11 +205,11 @@ BUTTON1 still pressed as you come out of reset).
This will give you a **fast blinky DFU pattern** to indicate you are in DFU
mode.
At this point, you can build and flash a CircuitPython binary via the following
At this point, you can **build and flash** a CircuitPython binary via the following
command:
```
$ make V=1 SD=s140 SERIAL=/dev/tty.usbmodem1411 BOARD=feather52840 dfu-gen dfu-flash
$ make V=1 SD=s140 SERIAL=/dev/tty.usbmodem1411 BOARD=feather52840 all dfu-gen dfu-flash
```
This should give you the following results:

View File

@ -9,12 +9,11 @@
0x000FE000..0x000FEFFF ( 4KB) Master Boot Record Params
0x000F4000..0x000FDFFF ( 40KB) Serial + OTA Bootloader
0x000F3000..0x000F3FFF ( 4KB ) Private Config Data (Bonding, Keys, etc.)
0x000F2000..0x000F2FFF ( 4KB ) User NVM data
0x000B2000..0x000F1FFF (256KB) User Filesystem
0x000ED000..0x000F3FFF (28KB ) Private Config Data (Bonding, Keys, etc.)
0x000AD000..0x000ECFFF (256KB) User Filesystem
0x00025000..0x000B1FFF (564KB) Application Code (including ISR vector)
0x00001000..0x00024FFF (144KB) SoftDevice
0x00026000..0x000ACFFF (540KB) Application Code (including ISR vector)
0x00001000..0x00025FFF (148KB) SoftDevice
0x00000000..0x00000FFF (4KB) Master Boot Record
*/
@ -23,9 +22,9 @@ MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x100000
FLASH_ISR (rx) : ORIGIN = 0x00025000, LENGTH = 0x001000
FLASH_TEXT (rx) : ORIGIN = 0x00026000, LENGTH = 0x08C000
FLASH_FATFS (r) : ORIGIN = 0x000B2000, LENGTH = 0x040000
FLASH_ISR (rx) : ORIGIN = 0x00026000, LENGTH = 0x001000
FLASH_TEXT (rx) : ORIGIN = 0x00027000, LENGTH = 0x086000
FLASH_FATFS (r) : ORIGIN = 0x000AD000, LENGTH = 0x040000
/* 0x2000000 - RAM:ORIGIN is reserved for Softdevice */
RAM (xrw) : ORIGIN = 0x20004000, LENGTH = 0x20040000 - 0x20004000
@ -42,6 +41,6 @@ _estack = ORIGIN(RAM) + LENGTH(RAM);
/* RAM extents for the garbage collector */
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_end = 0x20007000; /* tunable */
_heap_end = 0x20020000; /* tunable */
INCLUDE "boards/common.ld"

View File

@ -28,7 +28,7 @@
#define MICROPY_HW_BOARD_NAME "Feather52840"
#define MICROPY_HW_MCU_NAME "NRF52840"
#define MICROPY_PY_SYS_PLATFORM "nrf52840-PDK"
#define MICROPY_PY_SYS_PLATFORM "nrf52840"
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)

View File

@ -4,8 +4,10 @@ MCU_SUB_VARIANT = nrf52840
SOFTDEV_VERSION ?= 6.0.0-6.alpha
LD_FILE = boards/feather52840/bluefruit_nrf52840_s140_6.0.0.ld
BOOTLOADER_FILENAME = boards/feather52840/bootloader/feather52840_bootloader_6.0.0_s140_single
BOOT_UART_FILE = boards/feather52840/bootloader/uart/feather52840_bootloader_6.0.0_s140_single
BOOT_USB_FILE = boards/feather52840/bootloader/usb/feather52840_bootloader_6.0.0_s140_single
BOOT_SETTING_ADDR = 0xFF000
NRF_DEFINES += -DNRF52840_XXAA
ifeq ($(OS),Windows_NT)
@ -17,8 +19,8 @@ endif
CFLAGS += -DADAFRUIT_FEATHER52840
ifeq ($(SD), )
INC += -Idrivers/bluetooth/s140_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/s140_$(MCU_SUB_VARIANT)_$(SOFTDEV_VERSION)_API/include
INC += -Idrivers/bluetooth/s140_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/s140_$(MCU_SUB_VARIANT)_$(SOFTDEV_VERSION)_API/include/$(MCU_VARIANT)
INC += -Idrivers/bluetooth/s140_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/s140_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include
INC += -Idrivers/bluetooth/s140_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/s140_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include/$(MCU_VARIANT)
endif
check_defined = \
@ -28,14 +30,18 @@ __check_defined = \
$(if $(value $1),, \
$(error Undefined make flag: $1$(if $2, ($2))))
.PHONY: dfu-gen dfu-flash boot-flash
.PHONY: dfu-gen dfu-flash boot-flash boot-usb-flash
dfu-gen:
$(NRFUTIL) dfu genpkg --sd-req 0xFFFE --dev-type 0x0052 --application $(BUILD)/$(OUTPUT_FILENAME).hex $(BUILD)/dfu-package.zip
dfu-flash:
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyUSB0)
$(NRFUTIL) --verbose dfu serial --package $(BUILD)/dfu-package.zip -p $(SERIAL) -b 115200
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0)
$(NRFUTIL) --verbose dfu serial --package $(BUILD)/dfu-package.zip -p $(SERIAL) -b 115200 --singlebank
boot-flash:
nrfjprog --program $(BOOTLOADER_FILENAME).hex -f nrf52 --chiperase --reset
dfu-bootloader:
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0)
$(NRFUTIL) --verbose dfu serial --package $(BOOT_USB_FILE).zip -p $(SERIAL) -b 115200
bootloader:
nrfjprog --program $(BOOT_USB_FILE).hex -f nrf52 --chiperase --reset

View File

@ -8,7 +8,11 @@ else ifeq ($(SOFTDEV_VERSION), 5.0.0)
CFLAGS += -DBLE_API_VERSION=4
endif
else ifeq ($(SD), s140)
SOFTDEV_VERSION_LONG = $(SD)_$(MCU_SUB_VARIANT)_$(SOFTDEV_VERSION)
ifeq ($(SOFTDEV_VERSION), 6.0.0-6.alpha)
SOFTDEV_VERSION_LONG = $(SD)_$(MCU_SUB_VARIANT)_$(SOFTDEV_VERSION)
else
SOFTDEV_VERSION_LONG = $(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)
endif
CFLAGS += -DBLUETOOTH_SD=140
CFLAGS += -DBLE_API_VERSION=4

View File

@ -53,6 +53,24 @@ function download_s140_nrf52_6_0_0_6_alpha
cd -
}
function download_s140_nrf52_6_0_0
{
echo ""
echo "####################################"
echo "### Downloading s140_nrf52_6.0.0 ###"
echo "####################################"
echo ""
mkdir -p "${1}/s140_nrf52_6.0.0"
cd "${1}/s140_nrf52_6.0.0"
wget https://www.nordicsemi.com/eng/nordic/download_resource/60624/19/10544096/116072
mv 116072 temp.zip
unzip -u temp.zip
rm temp.zip
cd -
}
SCRIPT_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ $# -eq 0 ]; then
@ -60,6 +78,7 @@ if [ $# -eq 0 ]; then
download_s132_nrf52_2_0_1 "${SCRIPT_DIR}"
download_s132_nrf52_5_0_0 "${SCRIPT_DIR}"
download_s140_nrf52_6_0_0_6_alpha "${SCRIPT_DIR}"
download_s140_nrf52_6_0_0 "${SCRIPT_DIR}"
else
case $1 in
"s132_nrf52_2_0_1" )
@ -68,6 +87,8 @@ else
download_s132_nrf52_5_0_0 "${SCRIPT_DIR}" ;;
"s140_nrf52_6_0_0_6_alpha" )
download_s140_nrf52_6_0_0_6_alpha "${SCRIPT_DIR}" ;;
"s140_nrf52_6_0_0" )
download_s140_nrf52_6_0_0 "${SCRIPT_DIR}" ;;
esac
fi

View File

@ -114,7 +114,7 @@ int hal_uart_available(NRF_UART_Type * p_instance)
void hal_uart_init(NRF_UART_Type * p_instance, hal_uart_init_t const * p_uart_init) {
hal_gpio_cfg_pin(p_uart_init->tx_pin->port, p_uart_init->tx_pin->pin, HAL_GPIO_MODE_OUTPUT, HAL_GPIO_PULL_DISABLED);
hal_gpio_cfg_pin(p_uart_init->tx_pin->port, p_uart_init->rx_pin->pin, HAL_GPIO_MODE_INPUT, HAL_GPIO_PULL_DISABLED);
hal_gpio_cfg_pin(p_uart_init->rx_pin->port, p_uart_init->rx_pin->pin, HAL_GPIO_MODE_INPUT, HAL_GPIO_PULL_DISABLED);
hal_gpio_pin_clear(p_uart_init->tx_pin->port, p_uart_init->tx_pin->pin);
@ -156,6 +156,10 @@ void hal_uart_init(NRF_UART_Type * p_instance, hal_uart_init_t const * p_uart_in
NVIC_EnableIRQ(p_uart_init->irq_num);
}
bool hal_uart_inited(NRF_UART_Type * p_instance)
{
return !(p_instance->PSELTXD & (1 << 31)) && !(p_instance->PSELRXD & (1 << 31));
}
void UARTE0_UART0_IRQHandler(void)
{

View File

@ -117,6 +117,7 @@ typedef struct
typedef void (*uart_complete_cb)(void);
void hal_uart_init(NRF_UART_Type * p_instance, hal_uart_init_t const * p_uart_init);
bool hal_uart_inited(NRF_UART_Type * p_instance);
hal_uart_error_t hal_uart_char_write(NRF_UART_Type * p_instance, uint8_t ch);

View File

@ -331,6 +331,6 @@ extern const struct _mp_obj_module_t ble_module;
#include <alloca.h>
#define MICROPY_PIN_DEFS_PORT_H "pin_defs_nrf5.h"
//#define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt"
#define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt"
#endif

View File

@ -65,9 +65,23 @@ bool mp_hal_stdin_any(void) {
}
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
while(len--) {
hal_uart_char_write(UART_INSTANCE, *str++);
}
// #ifdef MICROPY_HW_LED_TX
// gpio_toggle_pin_level(MICROPY_HW_LED_TX);
// #endif
//
// #ifdef CIRCUITPY_BOOT_OUTPUT_FILE
// if (boot_output_file != NULL) {
// UINT bytes_written = 0;
// f_write(boot_output_file, str, len, &bytes_written);
// }
// #endif
if ( hal_uart_inited(UART_INSTANCE) ) {
while(len--) {
hal_uart_char_write(UART_INSTANCE, *str++);
}
}
}
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) {

View File

@ -49,8 +49,13 @@ void serial_init(void) {
.id = 0,
.rx_pin = &MICROPY_HW_UART1_RX,
.tx_pin = &MICROPY_HW_UART1_TX,
#if MICROPY_HW_UART1_HWFC
.rts_pin = &MICROPY_HW_UART1_RTS,
.cts_pin = &MICROPY_HW_UART1_CTS,
#else
.rts_pin = NULL,
.cts_pin = NULL,
#endif
.flow_control = MICROPY_HW_UART1_HWFC ? true : false,
.use_parity = false,
.baud_rate = HAL_UART_BAUD_115K2,