Merge pull request #1004 from adafruit/nrf52840_usbboot

Nrf52840 usbboot
This commit is contained in:
Scott Shawcroft 2018-07-12 11:47:27 -07:00 committed by GitHub
commit 75f48a5bc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 22917 additions and 10746 deletions

1
.gitattributes vendored
View File

@ -12,6 +12,7 @@
*.dxf binary
*.mpy binary
*.deb binary
*.zip binary
# These should also not be modified by git.
tests/basics/string_cr_conversion.py -text

2
.gitignore vendored
View File

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

4
.gitmodules vendored
View File

@ -73,3 +73,7 @@
[submodule "ports/nrf/nrfx"]
path = ports/nrf/nrfx
url = https://github.com/NordicSemiconductor/nrfx.git
[submodule "lib/tinyusb"]
path = lib/tinyusb
url = https://github.com/hathach/tinyusb.git
branch = develop

View File

@ -117,6 +117,7 @@ exclude_patterns = ["**/build*",
"ports/nrf/hal",
"ports/nrf/modules",
"ports/nrf/nrfx",
"ports/nrf/usb",
"ports/pic16bit",
"ports/qemu-arm",
"ports/stm32",

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

1
lib/tinyusb Submodule

@ -0,0 +1 @@
Subproject commit a0849fee9f4b268ccc9798c70c654a835f8e20c8

View File

@ -1,22 +1,23 @@
# Select the board to build for: if not given on the command line,
# then default to feather52832.
BOARD ?= feather52832
ifeq ($(wildcard boards/$(BOARD)/.),)
$(error Invalid BOARD specified)
# Select the board to build for.
ifeq ($(BOARD),)
$(info You must provide a BOARD parameter with 'BOARD=')
$(info Possible values are:)
$(info $(sort $(subst /.,,$(subst boards/,,$(wildcard boards/*/.)))))
$(error BOARD not defined)
else
ifeq ($(wildcard boards/$(BOARD)/.),)
$(error Invalid BOARD specified)
endif
endif
# If SoftDevice is selected, try to use that one.
# Default to SD132 (exact version can be set with SOFTDEV_VERSION)
SD ?= s132
include boards/$(BOARD)/mpconfigboard.mk
SD_LOWER = $(shell echo $(SD) | tr '[:upper:]' '[:lower:]')
# TODO: Verify that it is a valid target.
# If the build directory is not given, make it reflect the board name
# Build directory with SD
BUILD ?= $(if $(SD),build-$(BOARD)-$(SD_LOWER),build-$(BOARD))
include ../../py/mkenv.mk
include boards/$(BOARD)/mpconfigboard.mk
-include mpconfigport.mk
ifneq ($(SD), )
@ -52,6 +53,8 @@ INC += -I./nrfx/drivers/include
INC += -I../../lib/mp-readline
INC += -I./drivers/bluetooth
INC += -I./drivers
INC += -I../../lib/tinyusb/src
INC += -I./usb
NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET
@ -87,6 +90,7 @@ LIBS += -L $(dir $(LIBC_FILE_NAME)) -lc
LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc
SRC_NRFX = $(addprefix nrfx/,\
drivers/src/nrfx_power.c \
drivers/src/nrfx_spim.c \
drivers/src/nrfx_twim.c \
drivers/src/nrfx_uart.c \
@ -96,10 +100,13 @@ SRC_C += \
mphalport.c \
fatfs_port.c \
tick.c \
background.c \
internal_flash.c \
drivers/bluetooth/ble_drv.c \
drivers/bluetooth/ble_uart.c \
boards/$(BOARD)/board.c \
nrfx/mdk/system_$(MCU_SUB_VARIANT).c \
nrfx/hal/nrf_nvmc.c \
device/$(MCU_VARIANT)/startup_$(MCU_SUB_VARIANT).c \
lib/oofatfs/ff.c \
lib/oofatfs/option/ccsbcs.c \
@ -108,10 +115,25 @@ SRC_C += \
lib/utils/context_manager_helpers.c \
lib/utils/interrupt_char.c \
lib/utils/pyexec.c \
lib/utils/stdout_helpers.c \
lib/libc/string0.c \
lib/mp-readline/readline.c \
internal_flash.c \
ifeq ($(MCU_SUB_VARIANT),nrf52840)
SRC_C += \
usb/tusb_descriptors.c \
usb/usb_msc_flash.c \
lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c \
lib/tinyusb/src/portable/nordic/nrf5x/hal_nrf5x.c \
lib/tinyusb/src/common/tusb_fifo.c \
lib/tinyusb/src/device/usbd.c \
lib/tinyusb/src/device/usbd_desc.c \
lib/tinyusb/src/class/msc/msc_device.c \
lib/tinyusb/src/class/cdc/cdc_device.c \
lib/tinyusb/src/tusb.c \
endif
DRIVERS_SRC_C += $(addprefix modules/,\
ubluepy/modubluepy.c \
@ -213,9 +235,9 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
$(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os
$(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os
.phony: all flash sd binary hex
.phony: all flash sd binary hex bootloader
all: binary hex
all: binary hex uf2
OUTPUT_FILENAME = firmware
@ -231,12 +253,18 @@ hex: $(BUILD)/$(OUTPUT_FILENAME).hex
$(BUILD)/$(OUTPUT_FILENAME).hex: $(BUILD)/$(OUTPUT_FILENAME).elf
$(OBJCOPY) -O ihex $< $@
#####################
# Flash with debugger
#####################
FLASHER ?=
ifeq ($(FLASHER),)
# Also update to bootloader settting to validate application and skip checksum ( app valid = 0x0001, crc = 0x0000 )
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)
sd: $(BUILD)/$(OUTPUT_FILENAME).hex
@ -245,6 +273,9 @@ sd: $(BUILD)/$(OUTPUT_FILENAME).hex
nrfjprog --program $< --sectorerase -f $(MCU_VARIANT)
nrfjprog --reset -f $(MCU_VARIANT)
bootloader:
nrfjprog --program $(BOOT_FILE).hex -f nrf52 --chiperase --reset
else ifeq ($(FLASHER), pyocd)
flash: $(BUILD)/$(OUTPUT_FILENAME).hex
@ -257,6 +288,41 @@ sd: $(BUILD)/$(OUTPUT_FILENAME).hex
endif
#####################
# Flash with DFU
#####################
.phony: dfu-gen dfu-flash dfu-bootloader
ifeq ($(OS),Windows_NT)
NRFUTIL = ../../lib/nrfutil/binaries/win32/nrfutil.exe
else
NRFUTIL = nrfutil
endif
check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
__check_defined = \
$(if $(value $1),, \
$(error Undefined make flag: $1$(if $2, ($2))))
dfu-gen: $(BUILD)/$(OUTPUT_FILENAME).hex
$(NRFUTIL) dfu genpkg --sd-req 0xFFFE --dev-type 0x0052 --application $^ $(BUILD)/dfu-package.zip
dfu-flash: $(BUILD)/dfu-package.zip
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyUSB0)
$(NRFUTIL) --verbose dfu serial --package $^ -p $(SERIAL) -b 115200 --singlebank
dfu-bootloader:
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0)
$(NRFUTIL) --verbose dfu serial --package $(BOOT_FILE).zip -p $(SERIAL) -b 115200
uf2: $(BUILD)/$(OUTPUT_FILENAME).hex
$(ECHO) "Create $(OUTPUT_FILENAME).uf2"
$(PYTHON2) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xADA52840 -c -o "$(BUILD)/$(OUTPUT_FILENAME).uf2" $^
$(BUILD)/dfu-package.zip: dfu-gen
$(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) -Wl,--start-group $(LIBS) -Wl,--end-group

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:

34
ports/nrf/background.c Normal file
View File

@ -0,0 +1,34 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "tusb.h"
void run_background_tasks(void) {
#ifdef NRF52840_XXAA
tusb_task();
tud_cdc_flush();
#endif
}

View File

@ -7,14 +7,13 @@
---------- ---------- ------- -----------------------------------------
0x000FF000..0x000FFFFF ( 4KB) Bootloader Settings
0x000FE000..0x000FEFFF ( 4KB) Master Boot Record Params
0x000F4000..0x000FDFFF ( 40KB) Serial + OTA Bootloader
0x000F4000..0x000FDFFF ( 40KB) Bootloader (UF2 + CDC + OTA)
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

@ -1,37 +1,11 @@
MCU_SERIES = m4
MCU_VARIANT = nrf52
MCU_SUB_VARIANT = nrf52
SD ?= s132
SOFTDEV_VERSION ?= 2.0.1
LD_FILE = boards/feather52832/custom_nrf52832_dfu_app_$(SOFTDEV_VERSION).ld
BOOTLOADER_PKG = boards/feather52832/bootloader/feather52_bootloader_$(SOFTDEV_VERSION)_s132_single.zip
BOOT_FILE = boards/feather52832/bootloader/feather52_bootloader_$(SOFTDEV_VERSION)_s132_single
BOOT_SETTING_ADDR = 0x7F000
NRF_DEFINES += -DNRF52832_XXAA
ifeq ($(OS),Windows_NT)
NRFUTIL = ../../lib/nrfutil/binaries/win32/nrfutil.exe
else
NRFUTIL = nrfutil
endif
CFLAGS += -DADAFRUIT_FEATHER52
check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
__check_defined = \
$(if $(value $1),, \
$(error Undefined make flag: $1$(if $2, ($2))))
.PHONY: dfu-gen dfu-flash boot-flash
dfu-gen:
$(NRFUTIL) dfu genpkg --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
boot-flash:
@:$(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`
### 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.
@ -83,14 +83,14 @@ 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-flash
make SD=s140 BOARD=feather52840 bootloader
```
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-flash
$ make SD=s140 BOARD=feather52840 bootloader
Use make V=1, make V=2 or set BUILD_VERBOSE similarly in your environment to increase build verbosity.
nrfjprog --program boards/feather52840/bootloader/feather52840_bootloader_6.0.0_s140_single.hex -f nrf52 --chiperase --reset
Parsing hex file.
@ -150,9 +150,9 @@ $ sudo pip install -r requirements.txt
$ sudo python setup.py install
```
#### Changes to `nrfutil` in 0.5.2b
#### Changes to `nrfutil` in 0.5.2d
**IMPORTANT**: Make sure that you have version **0.5.2b**, since a small
**IMPORTANT**: Make sure that you have version **0.5.2d**, since a small
change was required to `dfu_transport_serial.py` to account for the
increased minimum flash erase time on the nRF52840 compared to the earlier
nRF52832!
@ -160,12 +160,7 @@ nRF52832!
You can also manually change the file with the following new values (lines
67-68), and reinstall the utility via `sudo python setup.py install`:
```
FLASH_PAGE_ERASE_MAX_TIME = 0.1 # Worst time to erase a page 100 ms
FLASH_PAGE_ERASE_MIN_TIME = 0.09 # Best time to erase a page 90 ms
```
### Flashing CircuitPython
### Flashing CircuitPython with USB CDC
With the serial bootloader present on your board, you first need to force your
board into DFU mode by holding down BUTTON1 and RESETTING the board (with
@ -174,28 +169,48 @@ 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:
```
$ make V=1 SD=s140 SERIAL=/dev/tty.usbmodem1411 BOARD=feather52840 dfu-gen dfu-flash
$make V=1 BOARD=feather52840 SD=s140 SERIAL=/dev/tty.usbmodem1411 dfu-gen dfu-flash
nrfutil dfu genpkg --sd-req 0xFFFE --dev-type 0x0052 --application build-feather52840-s140/firmware.hex build-feather52840-s140/dfu-package.zip
Zip created at build-feather52840-s140/dfu-package.zip
nrfutil --verbose dfu serial --package build-feather52840-s140/dfu-package.zip -p /dev/tty.usbmodem1411 -b 115200
Upgrading target on /dev/tty.usbmodem1411 with DFU package /Users/kevintownsend/Dropbox/microBuilder/Code/CircuitPython/circuitpython-mb/ports/nrf/build-feather52840-s140/dfu-package.zip. Flow control is disabled.
Starting DFU upgrade of type 4, SoftDevice size: 0, bootloader size: 0, application size: 195252
nrfutil --verbose dfu serial --package build-feather52840-s140/dfu-package.zip -p /dev/ttyACM1 -b 115200 --singlebank
Upgrading target on /dev/ttyACM1 with DFU package /home/hathach/Dropbox/adafruit/circuitpython/ada_cp/ports/nrf/build-feather52840-s140/dfu-package.zip. Flow control is disabled, Single bank mode
Starting DFU upgrade of type 4, SoftDevice size: 0, bootloader size: 0, application size: 199840
Sending DFU start packet
Sending DFU init packet
Sending firmware file
################################################################################################################################################################################################################################################################################################################################################################################################
#########################################################################################################################################################################################################################################################################################################################################################################################################
Activating new firmware
DFU upgrade took 41.6610329151s
DFU upgrade took 8.50606513023s
Device programmed.
```
### Flashing CircuitPython with MSC UF2
Make `uf2` target to generate the uf2
```
$ make V=1 SD=s140 SERIAL=/dev/tty.usbmodem1411 BOARD=feather52840 all uf2
Create firmware.uf2
../../tools/uf2/utils/uf2conv.py -c -o "build-feather52840-s140/firmware.uf2" "build-feather52840-s140/firmware.hex"
Converting to uf2, output size: 392192, start address: 0x26000
Wrote 392192 bytes to build-feather52840-s140/firmware.uf2.
```
Simply drag and drop firmware.uf2 to the MSC, the nrf52840 will blink fast and reset after done.
**Note**: you need to update `tools/uf2` for uf2conv.py to support hex file input, current circuitpython's master use older verion of uf2conv.py which only support biin file input. To update, change directory to top folder of circuitpython and run. The size of uf2 should be ~400KB, if using the old uf2conv.py the output file would be 1 MB which is not correct.
```
git submodule update --init
```

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 "Feather52840"
#define MICROPY_HW_UART_RX NRF_GPIO_PIN_MAP(0, 8)
#define MICROPY_HW_UART_TX NRF_GPIO_PIN_MAP(0, 6)

View File

@ -1,36 +1,16 @@
MCU_SERIES = m4
MCU_VARIANT = nrf52
MCU_SUB_VARIANT = nrf52840
SD ?= s140
SOFTDEV_VERSION ?= 6.0.0
LD_FILE = boards/feather52840/bluefruit_nrf52840_s140_6.0.0.ld
BOOTLOADER_FILENAME = boards/feather52840/bootloader/feather52840_bootloader_6.0.0_s140_single
BOOT_SETTING_ADDR = 0xFF000
BOOT_FILE = boards/$(BOARD)/bootloader/$(SOFTDEV_VERSION)/$(BOARD)_bootloader_$(SOFTDEV_VERSION)_s140
NRF_DEFINES += -DNRF52840_XXAA
ifeq ($(OS),Windows_NT)
NRFUTIL = ../../lib/nrfutil/binaries/win32/nrfutil.exe
ifeq ($(SD),)
LD_FILE = boards/nrf52840_1M_256k.ld
else
NRFUTIL = nrfutil
LD_FILE = boards/bluefruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_$(SOFTDEV_VERSION).ld
endif
CFLAGS += -DADAFRUIT_FEATHER52840
check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
__check_defined = \
$(if $(value $1),, \
$(error Undefined make flag: $1$(if $2, ($2))))
.PHONY: dfu-gen dfu-flash boot-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
boot-flash:
nrfjprog --program $(BOOTLOADER_FILENAME).hex -f nrf52 --chiperase --reset
NRF_DEFINES += -DNRF52840_XXAA

View File

@ -1,6 +1,7 @@
MCU_SERIES = m4
MCU_VARIANT = nrf52
MCU_SUB_VARIANT = nrf52
SD ?= s132
SOFTDEV_VERSION ?= 5.0.0
ifeq ($(SD),)

View File

@ -27,12 +27,40 @@
#include <string.h>
#include <stdbool.h>
#include "nrf.h"
#include "nrfx.h"
#include "nrfx_power.h"
#include "boards/board.h"
#include "tick.h"
#include "tusb.h"
void board_init(void) {
// Clock
NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
// Init USB
#ifdef SOFTDEVICE_PRESENT
// TODO support Softdevice config
#else
// Softdevice is not present, init power module and register tusb power event function
// for vusb detect, ready, removed
extern void tusb_hal_nrf_power_event(uint32_t event);
// Power module init
const nrfx_power_config_t pwr_cfg = { 0 };
nrfx_power_init(&pwr_cfg);
// USB Power detection
const nrfx_power_usbevt_config_t config = { .handler = (nrfx_power_usb_event_handler_t) tusb_hal_nrf_power_event };
nrfx_power_usbevt_init(&config);
nrfx_power_usbevt_enable();
#endif
tusb_init();
}
bool board_requests_safe_mode(void) {
@ -42,3 +70,23 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
//--------------------------------------------------------------------+
// tinyusb callbacks
//--------------------------------------------------------------------+
void tud_mount_cb(uint8_t rhport) {
(void) rhport;
}
void tud_umount_cb(uint8_t rhport) {
(void) rhport;
}
uint32_t tusb_hal_millis(void) {
uint64_t ms;
uint32_t us;
current_tick(&ms, &us);
return (uint32_t) ms;
}

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
#define MICROPY_HW_BOARD_NAME "PCA10056"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_PY_SYS_PLATFORM "nRF52840-PDK"
#define MICROPY_PY_SYS_PLATFORM "nRF52840-DK"
#define MICROPY_HW_UART_RX NRF_GPIO_PIN_MAP(0, 8)
#define MICROPY_HW_UART_TX NRF_GPIO_PIN_MAP(0, 6)
@ -34,3 +34,7 @@
#define PORT_HEAP_SIZE (128 * 1024)
#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
// Temp (could be removed) 0: usb cdc (default), 1 : hwuart (jlink)
#define CFG_HWUART_FOR_SERIAL 0

View File

@ -1,12 +1,17 @@
MCU_SERIES = m4
MCU_VARIANT = nrf52
MCU_SUB_VARIANT = nrf52840
SD ?= s140
SOFTDEV_VERSION ?= 6.0.0
BOOT_SETTING_ADDR = 0xFF000
BOOT_FILE = boards/$(BOARD)/bootloader/$(SOFTDEV_VERSION)/$(BOARD)_bootloader_$(SOFTDEV_VERSION)_s140
ifeq ($(SD),)
LD_FILE = boards/nrf52840_1M_256k.ld
else
LD_FILE = boards/nrf52840_1M_256k_s140_$(SOFTDEV_VERSION).ld
LD_FILE = boards/bluefruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_$(SOFTDEV_VERSION).ld
endif
NRF_DEFINES += -DNRF52840_XXAA

View File

@ -1,4 +1,4 @@
P0_00,P0_01
P0_00,P0_00
P0_01,P0_01
P0_02,P0_02
P0_03,P0_03

1 P0_00 P0_01 P0_00
2 P0_01 P0_01
3 P0_02 P0_02
4 P0_03 P0_03

View File

@ -35,8 +35,9 @@
extern volatile bool mp_msc_enabled;
void common_hal_storage_remount(const char *mount_path, bool readonly) {
if (strcmp(mount_path, "/") != 0)
if (strcmp(mount_path, "/") != 0) {
mp_raise_OSError(MP_EINVAL);
}
}
void common_hal_storage_erase_filesystem(void) {

View File

@ -29,14 +29,11 @@
#include <string.h>
#include "ble_uart.h"
#include "ringbuffer.h"
#include "py/mphal.h"
#include "lib/utils/interrupt_char.h"
#if MICROPY_PY_BLE_NUS
#if BLUETOOTH_WEBBLUETOOTH_REPL
#include "hal_time.h"
#endif // BLUETOOTH_WEBBLUETOOTH_REPL
static ubluepy_uuid_obj_t uuid_obj_service = {
.base.type = &ubluepy_uuid_type,
.type = UBLUEPY_UUID_128_BIT,

View File

@ -36,7 +36,7 @@
#include "lib/oofatfs/ff.h"
#include "supervisor/shared/rgb_led_status.h"
#include "nrf.h"
#include "nrf_nvmc.h"
#ifdef BLUETOOTH_SD
#include "nrf_sdm.h"
@ -46,17 +46,30 @@
extern uint32_t __fatfs_flash_start_addr[];
extern uint32_t __fatfs_flash_length[];
#define NO_CACHE 0xffffffff
#define FL_PAGE_SZ 4096
uint8_t _flash_cache[FL_PAGE_SZ] __attribute__((aligned(4)));
uint32_t _flash_page_addr = NO_CACHE;
/*------------------------------------------------------------------*/
/* Internal Flash API
*------------------------------------------------------------------*/
static inline uint32_t lba2addr(uint32_t block) {
return ((uint32_t)__fatfs_flash_start_addr) + block * FILESYSTEM_BLOCK_SIZE;
}
void internal_flash_init(void) {
// Activity LED for flash writes.
#ifdef MICROPY_HW_LED_MSC
#ifdef MICROPY_HW_LED_MSC
struct port_config pin_conf;
port_get_config_defaults(&pin_conf);
pin_conf.direction = PORT_PIN_DIR_OUTPUT;
port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf);
port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
#endif
// flash_init(&internal_flash_desc, NVMCTRL);
#endif
}
uint32_t internal_flash_get_block_size(void) {
@ -67,100 +80,62 @@ uint32_t internal_flash_get_block_count(void) {
return ((uint32_t) __fatfs_flash_length) / FILESYSTEM_BLOCK_SIZE ;
}
// TODO support flashing with SD enabled
void internal_flash_flush(void) {
}
if (_flash_page_addr == NO_CACHE) return;
void flash_flush(void) {
internal_flash_flush();
}
static uint32_t convert_block_to_flash_addr(uint32_t block) {
return ((uint32_t)__fatfs_flash_start_addr) + block * FILESYSTEM_BLOCK_SIZE;
}
bool internal_flash_write_block(const uint8_t *src, uint32_t block) {
uint8_t sd_en = 0;
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, true);
#endif
temp_status_color(ACTIVE_WRITE);
// non-MBR block, copy to cache
uint32_t dest = convert_block_to_flash_addr(block);
uint32_t pagenum = dest / FLASH_PAGE_SIZE;
uint32_t* flash_align = (uint32_t*) (pagenum*FLASH_PAGE_SIZE);
// Read back current page to update only 512 portion
__ALIGN(4) uint8_t buf[FLASH_PAGE_SIZE];
memcpy(buf, flash_align, FLASH_PAGE_SIZE);
memcpy(buf + (dest%FLASH_PAGE_SIZE), src, FILESYSTEM_BLOCK_SIZE);
#ifdef BLUETOOTH_SD
(void) sd_softdevice_is_enabled(&sd_en);
if (sd_en) {
if (NRF_SUCCESS != sd_flash_page_erase(pagenum)) {
return false;
// Skip if data is the same
if (memcmp(_flash_cache, (void *)_flash_page_addr, FL_PAGE_SZ) != 0) {
// _is_flashing = true;
nrf_nvmc_page_erase(_flash_page_addr);
nrf_nvmc_write_words(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t));
}
if (NRF_SUCCESS != sd_flash_write(flash_align, (uint32_t*) buf, FLASH_PAGE_SIZE / sizeof(uint32_t))) {
return false;
}
}
#endif
if (!sd_en) {
// Erase
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
NRF_NVMC->ERASEPAGE = dest;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
// Write
uint32_t *p_src = (uint32_t*) buf;
uint32_t *p_dest = flash_align;
uint32_t i = 0;
while (i < (FLASH_PAGE_SIZE / sizeof(uint32_t))) {
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
*p_dest++ = *p_src++;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
++i;
}
}
clear_temp_status();
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
#endif
return true;
_flash_page_addr = NO_CACHE;
}
mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {
uint32_t src = convert_block_to_flash_addr(block);
uint32_t src = lba2addr(block);
memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks);
return 0; // success
}
mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
for (size_t i = 0; i < num_blocks; i++) {
if (!internal_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) {
return 1; // error
mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32_t num_blocks) {
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, true);
#endif
while (num_blocks) {
uint32_t const addr = lba2addr(lba);
uint32_t const page_addr = addr & ~(FL_PAGE_SZ - 1);
uint32_t count = 8 - (lba % 8); // up to page boundary
count = MIN(num_blocks, count);
if (page_addr != _flash_page_addr) {
internal_flash_flush();
// writing previous cached data, skip current data until flashing is done
// tinyusb stack will invoke write_block() with the same parameters later on
// if ( _is_flashing ) return;
_flash_page_addr = page_addr;
memcpy(_flash_cache, (void *)page_addr, FL_PAGE_SZ);
}
memcpy(_flash_cache + (addr & (FL_PAGE_SZ - 1)), src, count * FILESYSTEM_BLOCK_SIZE);
// adjust for next run
lba += count;
src += count * FILESYSTEM_BLOCK_SIZE;
num_blocks -= count;
}
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
#endif
return 0; // success
}
@ -224,6 +199,10 @@ const mp_obj_type_t internal_flash_type = {
.locals_dict = (mp_obj_t)&internal_flash_obj_locals_dict,
};
/*------------------------------------------------------------------*/
/* Flash API
*------------------------------------------------------------------*/
void flash_init_vfs(fs_user_mount_t *vfs) {
vfs->base.type = &mp_fat_vfs_type;
vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL;
@ -241,3 +220,7 @@ void flash_init_vfs(fs_user_mount_t *vfs) {
vfs->u.ioctl[0] = (mp_obj_t)&internal_flash_obj_ioctl_obj;
vfs->u.ioctl[1] = (mp_obj_t)&internal_flash_obj;
}
void flash_flush(void) {
internal_flash_flush();
}

View File

@ -44,8 +44,6 @@ uint32_t internal_flash_get_block_size(void);
uint32_t internal_flash_get_block_count(void);
void internal_flash_irq_handler(void);
void internal_flash_flush(void);
bool internal_flash_read_block(uint8_t *dest, uint32_t block);
bool internal_flash_write_block(const uint8_t *src, uint32_t block);
// these return 0 on success, non-zero on error
mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks);

View File

@ -238,6 +238,10 @@ extern const struct _mp_obj_module_t ble_module;
// We need to provide a declaration/definition of alloca()
#include <alloca.h>
extern void run_background_tasks(void);
#define MICROPY_VM_HOOK_LOOP run_background_tasks();
#define MICROPY_VM_HOOK_RETURN run_background_tasks();
//#define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt"
#endif

View File

@ -28,10 +28,12 @@
#include <string.h>
#include "mphalport.h"
#include "py/mpstate.h"
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len);
#if (MICROPY_PY_BLE_NUS == 0)
#if !defined( NRF52840_XXAA) || ( defined(CFG_HWUART_FOR_SERIAL) && CFG_HWUART_FOR_SERIAL == 1 )
int mp_hal_stdin_rx_chr(void) {
uint8_t data = 0;
@ -57,26 +59,71 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
NRFX_ASSERT(err);
}
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) {
const char cr = '\r';
#else
while (len--) {
if (*str == '\n')
mp_hal_stdout_tx_strn(&cr, sizeof(cr));
#include "tusb.h"
mp_hal_stdout_tx_strn(str++, sizeof(char));
int mp_hal_stdin_rx_chr(void) {
for (;;) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP
#endif
// if (reload_requested) {
// return CHAR_CTRL_D;
// }
if (tud_cdc_available()) {
#ifdef MICROPY_HW_LED_RX
gpio_toggle_pin_level(MICROPY_HW_LED_RX);
#endif
return tud_cdc_read_char();
}
}
return 0;
}
bool mp_hal_stdin_any(void) {
return tud_cdc_available() > 0;
}
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
#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
tud_cdc_write(str, len);
}
#endif // USB
#endif // NUS
/*------------------------------------------------------------------*/
/* delay
*------------------------------------------------------------------*/
void mp_hal_delay_ms(mp_uint_t delay) {
uint64_t start_tick = ticks_ms;
uint64_t duration = 0;
while (duration < delay) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP
#endif
// Check to see if we've been CTRL-Ced by autoreload or the user.
if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
break;
}
duration = (ticks_ms - start_tick);
// TODO(tannewt): Go to sleep for a little while while we wait.
}
}
#endif
void mp_hal_stdout_tx_str(const char *str) {
mp_hal_stdout_tx_strn(str, strlen(str));
}
void mp_hal_delay_ms(mp_uint_t ms) {
NRFX_DELAY_US(ms * 1000);
}
void mp_hal_delay_us(mp_uint_t us) {
NRFX_DELAY_US(us);
}

View File

@ -46,7 +46,7 @@ int mp_hal_stdin_rx_chr(void);
void mp_hal_stdout_tx_str(const char *str);
bool mp_hal_stdin_any(void);
void mp_hal_delay_ms(mp_uint_t ms);
void mp_hal_delay_us(mp_uint_t us);
#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us))
#endif

View File

@ -1,6 +1,10 @@
#ifndef NRFX_CONFIG_H__
#define NRFX_CONFIG_H__
// Power
#define NRFX_POWER_ENABLED 1
#define NRFX_POWER_CONFIG_IRQ_PRIORITY 7
// SPI
#define NRFX_SPIM_ENABLED 1

View File

@ -80,6 +80,11 @@ void __assert_func(const char *file, int line, const char *func, const char *exp
*/
#define NRFX_STATIC_ASSERT(expression)
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
//------------------------------------------------------------------------------
#ifdef SOFTDEVICE_PRESENT

View File

@ -32,23 +32,23 @@
#include "internal_flash.h"
fs_user_mount_t fs_user_mount_flash;
mp_vfs_mount_t mp_vfs_mount_flash;
static mp_vfs_mount_t _mp_vfs;
static fs_user_mount_t _internal_vfs;
void filesystem_init(bool create_allowed) {
// init the vfs object
fs_user_mount_t *vfs_fat = &fs_user_mount_flash;
vfs_fat->flags = 0;
flash_init_vfs(vfs_fat);
fs_user_mount_t *int_vfs = &_internal_vfs;
int_vfs->flags = 0;
flash_init_vfs(int_vfs);
// try to mount the flash
FRESULT res = f_mount(&vfs_fat->fatfs);
FRESULT res = f_mount(&int_vfs->fatfs);
if (res == FR_NO_FILESYSTEM && create_allowed) {
// no filesystem so create a fresh one
uint8_t working_buf[_MAX_SS];
res = f_mkfs(&vfs_fat->fatfs, FM_FAT | FM_SFD, 4096, working_buf, sizeof(working_buf));
res = f_mkfs(&int_vfs->fatfs, FM_FAT | FM_SFD, 4096, working_buf, sizeof(working_buf));
// Flush the new file system to make sure its repaired immediately.
flash_flush();
if (res != FR_OK) {
@ -56,24 +56,26 @@ void filesystem_init(bool create_allowed) {
}
// set label
f_setlabel(&vfs_fat->fatfs, "CIRCUITPY");
flash_flush();
f_setlabel(&int_vfs->fatfs, "CIRCUITPY");
// create lib folder
f_mkdir(&vfs_fat->fatfs, "/lib");
f_mkdir(&int_vfs->fatfs, "/lib");
flash_flush();
} else if (res != FR_OK) {
return;
}
mp_vfs_mount_t *vfs = &mp_vfs_mount_flash;
vfs->str = "/";
vfs->len = 1;
vfs->obj = MP_OBJ_FROM_PTR(vfs_fat);
vfs->next = NULL;
MP_STATE_VM(vfs_mount_table) = vfs;
mp_vfs_mount_t *mp_vfs = &_mp_vfs;
mp_vfs->str = "/";
mp_vfs->len = 1;
mp_vfs->obj = MP_OBJ_FROM_PTR(int_vfs);
mp_vfs->next = NULL;
MP_STATE_VM(vfs_mount_table) = mp_vfs;
// The current directory is used as the boot up directory.
// It is set to the internal flash filesystem by default.
MP_STATE_PORT(vfs_cur) = vfs;
MP_STATE_PORT(vfs_cur) = mp_vfs;
}
void filesystem_flush(void) {
@ -81,6 +83,13 @@ void filesystem_flush(void) {
}
void filesystem_writable_by_python(bool writable) {
fs_user_mount_t *vfs = &_internal_vfs;
if (writable) {
vfs->flags |= FSUSER_USB_WRITABLE;
} else {
vfs->flags &= ~FSUSER_USB_WRITABLE;
}
}
bool filesystem_present(void) {

View File

@ -33,6 +33,8 @@
#include "pin.h"
#endif
#if !defined( NRF52840_XXAA) || ( defined(CFG_HWUART_FOR_SERIAL) && CFG_HWUART_FOR_SERIAL == 1 )
#define INST_NO 0
nrfx_uart_t serial_instance = NRFX_UART_INSTANCE(INST_NO);
@ -78,3 +80,30 @@ bool serial_bytes_available(void) {
void serial_write(const char *text) {
mp_hal_stdout_tx_str(text);
}
#else
#include "tusb.h"
void serial_init(void) {
// usb is already initialized in board_init()
}
bool serial_connected(void) {
return tud_cdc_connected();
}
char serial_read(void) {
return (char) tud_cdc_read_char();
}
bool serial_bytes_available(void) {
return tud_cdc_available() > 0;
}
void serial_write(const char* text) {
tud_cdc_write(text, strlen(text));
}
#endif

View File

@ -51,8 +51,7 @@ void SysTick_Handler(void) {
void tick_init() {
uint32_t ticks_per_ms = common_hal_mcu_processor_get_frequency() / 1000;
SysTick_Config(ticks_per_ms);
// NVIC_EnableIRQ(SysTick_IRQn);
SysTick_Config(ticks_per_ms); // interrupt is enabled
}
void tick_delay(uint32_t us) {

125
ports/nrf/usb/tusb_config.h Normal file
View File

@ -0,0 +1,125 @@
/**************************************************************************/
/*!
@file tusb_config.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#ifndef _TUSB_CONFIG_H_
#define _TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// COMMON CONFIGURATION
//--------------------------------------------------------------------+
#define CFG_TUSB_MCU OPT_MCU_NRF5X
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
#define CFG_TUSB_DEBUG 0
/*------------- RTOS -------------*/
#define CFG_TUSB_OS OPT_OS_NONE
//#define CFG_TUD_TASK_QUEUE_SZ 16
//#define CFG_TUD_TASK_PRIO 0
//#define CFG_TUD_TASK_STACK_SZ 150
//--------------------------------------------------------------------+
// DEVICE CONFIGURATION
//--------------------------------------------------------------------+
/*------------- Core -------------*/
#define CFG_TUD_DESC_AUTO 1
#define CFG_TUD_DESC_VID 0x239A
#define CFG_TUD_DESC_PID 0x802A
#define CFG_TUD_ENDOINT0_SIZE 64
//------------- CLASS -------------//
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 1
#define CFG_TUD_HID_KEYBOARD 0
#define CFG_TUD_HID_MOUSE 0
#define CFG_TUD_HID_GENERIC 0
/*------------------------------------------------------------------*/
/* CLASS DRIVER
*------------------------------------------------------------------*/
// FIFO size of CDC TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE 1024
#define CFG_TUD_CDC_TX_BUFSIZE 1024
/* TX is sent automatically on every Start of Frame event ~ 1ms.
* If not enabled, application must call tud_cdc_flush() periodically
* Note: Enabled this could overflow device task, if it does, define
* CFG_TUD_TASK_QUEUE_SZ with large value
*/
#define CFG_TUD_CDC_FLUSH_ON_SOF 0
// Number of supported Logical Unit Number (At least 1)
#define CFG_TUD_MSC_MAXLUN 1
// Number of Blocks
#define CFG_TUD_MSC_BLOCK_NUM (256*1024)/512
// Block size
#define CFG_TUD_MSC_BLOCK_SZ 512
// Buffer size for each read/write transfer, the more the better
#define CFG_TUD_MSC_BUFSIZE (4*1024)
// Vendor name included in Inquiry response, max 8 bytes
#define CFG_TUD_MSC_VENDOR "Adafruit"
// Product name included in Inquiry response, max 16 bytes
#define CFG_TUD_MSC_PRODUCT "CircuitPY nRF52"
// Product revision string included in Inquiry response, max 4 bytes
#define CFG_TUD_MSC_PRODUCT_REV "1.0"
//--------------------------------------------------------------------+
// USB RAM PLACEMENT
//--------------------------------------------------------------------+
#define CFG_TUSB_ATTR_USBRAM
#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4)
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_CONFIG_H_ */

View File

@ -0,0 +1,78 @@
/**************************************************************************/
/*!
@file tusb_descriptors.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include "tusb.h"
//--------------------------------------------------------------------+
// STRING DESCRIPTORS
//--------------------------------------------------------------------+
// array of pointer to string descriptors
uint16_t const * const string_desc_arr [] =
{
// 0 index is supported language = English
TUD_DESC_STRCONV(0x0409),
// Manufacturer
TUD_DESC_STRCONV('A','d','a','f','r','u','i','t',' ','I','n','d','u','s','t','r','i','e','s'),
// Product
TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','Y',' ','n','R','F','5','2'),
// Serials TODO use chip ID
TUD_DESC_STRCONV('1', '2', '3', '4', '5'),
// CDC Interface
TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','S','e','r','i','a','l'),
// MSC Interface
TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','S','t','o','r','a','g','e'),
// Custom Interface
TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','C','u','s','t','o','m')
};
// tud_desc_set is required by tinyusb stack
// since CFG_TUD_DESC_AUTO is enabled, we only need to set string_arr
tud_desc_set_t tud_desc_set =
{
.device = NULL,
.config = NULL,
.string_arr = (uint8_t const **) string_desc_arr,
.hid_report = NULL
};

View File

@ -0,0 +1,176 @@
/**************************************************************************/
/*!
@file usb_msc_flash.c
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2018, Adafruit Industries (adafruit.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#include "tusb.h"
#include "internal_flash.h"
// For updating fatfs's cache
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "lib/oofatfs/ff.h"
#include "py/mpstate.h"
/*------------------------------------------------------------------*/
/* MACRO TYPEDEF CONSTANT ENUM
*------------------------------------------------------------------*/
#define MSC_FLASH_ADDR_END 0xED000
#define MSC_FLASH_SIZE (256*1024)
#define MSC_FLASH_ADDR_START (MSC_FLASH_ADDR_END-MSC_FLASH_SIZE)
#define MSC_FLASH_BLOCK_SIZE 512
#define FL_PAGE_SZ 4096
static scsi_sense_fixed_data_t mscd_sense_data =
{
.response_code = 0x70,
.sense_key = 0, // no errors
.additional_sense_len = sizeof(scsi_sense_fixed_data_t) - 8
};
static scsi_mode_parameters_t const msc_dev_mode_para =
{
.mode_data_length = 3,
.medium_type = 0,
.device_specific_para = 0,
.block_descriptor_length = 0
};
//--------------------------------------------------------------------+
// tinyusb callbacks
//--------------------------------------------------------------------+
int32_t tud_msc_scsi_cb (uint8_t rhport, uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) {
// read10 & write10 has their own callback and MUST not be handled here
void const* ptr = NULL;
uint16_t len = 0;
// most scsi handled is input
bool in_xfer = true;
switch ( scsi_cmd[0] )
{
case SCSI_CMD_REQUEST_SENSE:
ptr = &mscd_sense_data;
len = sizeof(scsi_sense_fixed_data_t);
break;
case SCSI_CMD_MODE_SENSE_6:
ptr = &msc_dev_mode_para;
len = sizeof(msc_dev_mode_para);
break;
case SCSI_CMD_TEST_UNIT_READY:
ptr = NULL;
len = 0;
break;
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
ptr = NULL;
len = 0;
break;
default:
// negative is error -> Data stage is STALL, status = failed
return -1;
}
// return len must not larger than bufsize
TU_ASSERT(bufsize >= len);
if ( ptr && len )
{
if ( in_xfer )
{
memcpy(buffer, ptr, len);
} else
{
// SCSI output
}
}
//------------- clear sense data if it is not request sense command -------------//
if ( SCSI_CMD_REQUEST_SENSE != scsi_cmd[0] )
{
mscd_sense_data.sense_key = SCSI_SENSEKEY_NONE;
mscd_sense_data.additional_sense_code = 0;
mscd_sense_data.additional_sense_qualifier = 0;
}
return len;
}
/*------------------------------------------------------------------*/
/* Tinyusb Flash READ10 & WRITE10
*------------------------------------------------------------------*/
int32_t tud_msc_read10_cb (uint8_t rhport, uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) {
(void) rhport;
(void) lun;
(void) offset;
uint32_t const block_count = bufsize / MSC_FLASH_BLOCK_SIZE;
internal_flash_read_blocks(buffer, lba, block_count);
return block_count * MSC_FLASH_BLOCK_SIZE;
}
int32_t tud_msc_write10_cb (uint8_t rhport, uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) {
(void) rhport;
(void) lun;
(void) offset;
uint32_t const block_count = bufsize / MSC_FLASH_BLOCK_SIZE;
// bufsize <= CFG_TUD_MSC_BUFSIZE (4096)
internal_flash_write_blocks(buffer, lba, block_count);
// update fatfs's cache if address matches
fs_user_mount_t* vfs = MP_STATE_VM(vfs_mount_table)->obj;
if ( (lba <= vfs->fatfs.winsect) && (vfs->fatfs.winsect <= (lba + bufsize / MSC_FLASH_BLOCK_SIZE)) ) {
memcpy(vfs->fatfs.win, buffer + MSC_FLASH_BLOCK_SIZE * (vfs->fatfs.winsect - lba), MSC_FLASH_BLOCK_SIZE);
}
return block_count * MSC_FLASH_BLOCK_SIZE;
}
void tud_msc_write10_complete_cb (uint8_t rhport, uint8_t lun) {
(void) rhport;
(void) lun;
// flush pending cache when write10 is complete
internal_flash_flush();
}

@ -1 +1 @@
Subproject commit 449f26673855736dbc0fc3f18d72403f25f62974
Subproject commit 6c37e72342d814079bc9b760e2840dc0d766f94f