Skip to content

Commit a3f61a0

Browse files
authored
Merge pull request #2591 from ssievert42/xiaoble
Add board: Seeed XIAO BLE
2 parents 672e959 + 18b47c0 commit a3f61a0

File tree

13 files changed

+845
-10
lines changed

13 files changed

+845
-10
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
strategy:
4040
# devices to build for
4141
matrix:
42-
board: [LINUX, ESP32, ESP8266_BOARD, ESP8266_4MB, MICROBIT1, MICROBIT2, ESP32C3_IDF4]
42+
board: [LINUX, ESP32, ESP8266_BOARD, ESP8266_4MB, MICROBIT1, MICROBIT2, ESP32C3_IDF4, XIAOBLE]
4343
# try and build for all devices even if one fails
4444
fail-fast: false
4545
steps:
@@ -62,6 +62,7 @@ jobs:
6262
name: ${{ matrix.board }}
6363
path: |
6464
bin/*.bin
65+
bin/*.uf2
6566
bin/*.hex
6667
bin/*.tgz
6768
bin/*.zip

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
Bangle.js: Ensure fake LED1/LED2 remember state
1010
Ensure E.setComparator is added to the build for nRF52
1111
Bangle.js2: Update test to use accelerometer to test vibration motor
12+
Build: Allow creating UF2 images
13+
XiaoBLE: Add board: Seeed XIAO BLE
14+
nRF5x: Allow entering UF2 bootloader mode by calling E.rebootToDFU() (on boards that have such a bootloader)
1215

1316
2v25 : ESP32C3: Get analogRead working correctly
1417
Graphics: Adjust image alignment when rotating images to avoid cropping (fix #2535)

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,8 @@ clean:
891891
$(Q)rm -f $(PROJ_NAME).bin
892892
$(Q)rm -f $(PROJ_NAME).srec
893893
$(Q)rm -f $(PROJ_NAME).lst
894+
$(Q)rm -f $(PROJ_NAME).app_hex
895+
$(Q)rm -f $(PROJ_NAME).uf2
894896
$(Q)rm -f $(BINDIR)/espruino_embedded.h
895897
$(Q)rm -f $(BINDIR)/espruino_embedded.c
896898
$(Q)rm -f $(BINDIR)/jstypes.h

README_BuildProcess.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ This is a partial list of definitions that can be added in a `BOARD.py` file's `
148148
* `ESPR_LCD_MANUAL_BACKLIGHT` - STM32/FSMC: Don't turn the backlight on and leave code to do this manually
149149
* `ESPR_DISABLE_KICKWATCHDOG_PIN=BTN1_PININDEX` - If this pin is 1, skip kickWatchdog calls (which would eventually force a reboot if WDT enabled)
150150
* `ESPR_TERMNINAL_NO_SCROLL` - disable scrolling in the onscreen terminal (once we get to the end, we just clear the screen and start at the top)
151+
* `ESPR_HAS_BOOTLOADER_UF2` - nRF5x: Allow entering UF2 bootloader mode by calling E.rebootToDFU()
151152

152153

153154
There are some specifically that are useful for cutting a few bytes out of the build:

boards/XIAOBLE.py

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#!/bin/false
2+
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
3+
#
4+
# Copyright (C) 2013 Gordon Williams <[email protected]>
5+
#
6+
# This Source Code Form is subject to the terms of the Mozilla Public
7+
# License, v. 2.0. If a copy of the MPL was not distributed with this
8+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
#
10+
# ----------------------------------------------------------------------------------------
11+
# This file contains information for a specific board - the available pins, and where LEDs,
12+
# Buttons, and other in-built peripherals are. It is used to build documentation as well
13+
# as various source and header files for Espruino.
14+
# ----------------------------------------------------------------------------------------
15+
16+
# To build and flash run:
17+
"""
18+
source ./scripts/provision.sh XIAOBLE
19+
make clean && BOARD=XIAOBLE RELEASE=1 make
20+
"""
21+
# Then connect the board to your computer and press the reset button twice.
22+
# You should now see a USB storage device called "XIAO-SENSE" (no matter which version you have).
23+
# Copy the "espruino_*_xiaoble.uf2" file from the "bin" folder to that drive.
24+
# The board should automatically disconnect after copying is finished, and reboot into Espruino,
25+
# which turns on the red led for a short time after starting up.
26+
27+
# If you accidentally put some stuff in .boot0 that prevents you from interacting with Espruino:
28+
# Pull pin D1 to 3.3 V / high (important: make sure you use 3.3 V; higher voltages may cause damage) and reset the board,
29+
# by either pressing the reset button or cutting the power and powering it up again.
30+
# This behaviour is archived by configuring pin D1 as BTN1.
31+
32+
import pinutils
33+
info = {
34+
"name": "Seeed Xiao BLE",
35+
"link": ["https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html"],
36+
"default_console": "EV_USBSERIAL",
37+
"variables": 14000, # How many variables are allocated for Espruino to use. RAM will be overflowed if this number is too high and code won't compile.
38+
"binary_name": "espruino_%v_xiaoble.uf2",
39+
"build": {
40+
"optimizeflags": "-Os",
41+
"libraries": [
42+
"BLUETOOTH",
43+
# "GRAPHICS",
44+
"CRYPTO","SHA256","SHA512",
45+
"AES_CCM",
46+
# "NFC",
47+
# "TENSORFLOW",
48+
"NEOPIXEL",
49+
"JIT",
50+
],
51+
"makefile": [
52+
"DEFINES += -DESPR_LSE_ENABLE", # Ensure low speed external osc enabled
53+
"DEFINES += -DCONFIG_GPIO_AS_PINRESET", # Allow the reset pin to work
54+
"DEFINES += -DNRF_USB=1 -DUSB",
55+
"DEFINES += -DNEOPIXEL_SCK_PIN=33 -DNEOPIXEL_LRCK_PIN=34", # nRF52840 needs LRCK pin defined for neopixel
56+
"DEFINES += -DBLUETOOTH_NAME_PREFIX='\"XIAOBLE\"'",
57+
"DEFINES += -DSPIFLASH_READ2X", # Read SPI flash at 2x speed using MISO and MOSI for IO
58+
"DEFINES += -DESPR_UNICODE_SUPPORT=1",
59+
"DEFINES += -DNRF_SDH_BLE_GATT_MAX_MTU_SIZE=131", # 23+x*27 rule as per https://devzone.nordicsemi.com/f/nordic-q-a/44825/ios-mtu-size-why-only-185-bytes
60+
# 'DEFINES += -DPIN_NAMES_DIRECT=1', # Package skips out some pins, so we can't assume each port starts from 0
61+
"LDFLAGS += -Xlinker --defsym=LD_APP_RAM_BASE=0x2ec0", # set RAM base to match MTU
62+
'DEFINES += -DESPR_BLE_PRIVATE_ADDRESS_SUPPORT',
63+
'DEFINES += -DESPR_HAS_BOOTLOADER_UF2',
64+
'NRF_SDK15=1',
65+
],
66+
},
67+
}
68+
69+
chip = {
70+
"part": "NRF52840",
71+
"family": "NRF52",
72+
"package": "AQFN73",
73+
"ram": 256,
74+
"flash": 1024,
75+
"speed": 64,
76+
"usart": 1,
77+
"spi": 1,
78+
"i2c": 2,
79+
"adc": 1,
80+
"dac": 0,
81+
"saved_code": {
82+
"address": 0x60000000, # put this in external spiflash (see below)
83+
"page_size": 4096,
84+
"pages": 512, # Entire 2 MB of external flash
85+
"flash_available": 1024 - ((38 + 7 + 12 + 1) * 4) - 780,
86+
# Softdevice 140 uses 38 pages of flash, user data 7, bootloader 12, plus 1 page of padding (because I'm paranoid and really don't want to overwrite the bootloader).
87+
# Each page is 4 KB.
88+
},
89+
}
90+
91+
devices = {
92+
"LED1": {"pin": "D11"},
93+
"LED2": {"pin": "D13"},
94+
"LED3": {"pin": "D12"},
95+
"BTN1": {"pin": "D1", "pinstate" : "IN_PULLDOWN"},
96+
"BAT": {
97+
"pin_charging": "D23",
98+
"pin_voltage": "D32",
99+
},
100+
"NFC": {"pin_a": "D30", "pin_b": "D31"},
101+
# accelerometer is only present on the "sense" variant (Seeed XIAO BLE nRF52840 Sense)
102+
#"ACCEL" : {
103+
# # device is actually a LSM6DS3TR-C, not sure if this would even work
104+
# "device" : "LSM6DSL", "addr" : 0x6b,
105+
# "pin_sda" : "D17",
106+
# "pin_scl" : "D16"
107+
#},
108+
"SPIFLASH": {
109+
"pin_cs": "D25",
110+
"pin_sck": "D24",
111+
"pin_mosi": "D26",
112+
"pin_miso": "D27",
113+
"pin_wp": "D28",
114+
"pin_rst": "D29",
115+
"size": 4096 * 512, # 2 MB
116+
"memmap_base": 0x60000000, # map into the address space (in software)
117+
},
118+
}
119+
120+
# left-right, or top-bottom order
121+
board = {}
122+
123+
# schematic at https://files.seeedstudio.com/wiki/XIAO-BLE/Seeed-Studio-XIAO-nRF52840-Sense-v1.1.pdf
124+
# pinout sheet https://files.seeedstudio.com/wiki/XIAO-BLE/XIAO-nRF52840-pinout_sheet.xlsx
125+
# see also https://github.com/Seeed-Studio/Adafruit_nRF52_Arduino/blob/master/variants/Seeed_XIAO_nRF52840/variant.h
126+
# and https://github.com/Seeed-Studio/Adafruit_nRF52_Arduino/blob/master/variants/Seeed_XIAO_nRF52840/variant.cpp
127+
def get_pins():
128+
pins = [
129+
{ "name": "PD0", "sortingname": "D00", "port": "D", "num": "2", "functions": { "ADC1_IN0": 0 } },
130+
{ "name": "PD1", "sortingname": "D01", "port": "D", "num": "3", "functions": { "ADC1_IN1": 0 } },
131+
{ "name": "PD2", "sortingname": "D02", "port": "D", "num": "28", "functions": { "ADC1_IN4": 0 } },
132+
{ "name": "PD3", "sortingname": "D03", "port": "D", "num": "29", "functions": { "ADC1_IN5": 0 } },
133+
{ "name": "PD4", "sortingname": "D04", "port": "D", "num": "4", "functions": { "ADC1_IN2": 0 } },
134+
{ "name": "PD5", "sortingname": "D05", "port": "D", "num": "5", "functions": { "ADC1_IN3": 0 } },
135+
{ "name": "PD6", "sortingname": "D06", "port": "D", "num": "43", "functions": {} },
136+
{ "name": "PD7", "sortingname": "D07", "port": "D", "num": "44", "functions": {} },
137+
{ "name": "PD8", "sortingname": "D08", "port": "D", "num": "45", "functions": {} },
138+
{ "name": "PD9", "sortingname": "D09", "port": "D", "num": "46", "functions": {} },
139+
{ "name": "PD10", "sortingname": "D10", "port": "D", "num": "47", "functions": {} },
140+
{ "name": "PD11", "sortingname": "D11", "port": "D", "num": "26", "functions": { "NEGATED": 0, "LED_RED": 0 } },
141+
{ "name": "PD12", "sortingname": "D12", "port": "D", "num": "6", "functions": { "NEGATED": 0, "LED_BLUE": 0 } },
142+
{ "name": "PD13", "sortingname": "D13", "port": "D", "num": "30", "functions": { "ADC1_IN6": 0, "NEGATED": 0, "LED_GREEN": 0 } },
143+
{ "name": "PD14", "sortingname": "D14", "port": "D", "num": "14", "functions": { "NEGATED": 0, "VBAT_ENABLE": 0 } },
144+
{ "name": "PD15", "sortingname": "D15", "port": "D", "num": "40", "functions": { "6D_PWR": 0 } },
145+
{ "name": "PD16", "sortingname": "D16", "port": "D", "num": "27", "functions": { "6D_I2C_SCL": 0 } },
146+
{ "name": "PD17", "sortingname": "D17", "port": "D", "num": "7", "functions": { "6D_I2C_SDA": 0 } },
147+
{ "name": "PD18", "sortingname": "D18", "port": "D", "num": "11", "functions": { "6D_INT1": 0 } },
148+
{ "name": "PD19", "sortingname": "D19", "port": "D", "num": "42", "functions": { "MIC_PWR": 0 } },
149+
{ "name": "PD20", "sortingname": "D20", "port": "D", "num": "32", "functions": { "PDM_CLK": 0 } },
150+
{ "name": "PD21", "sortingname": "D21", "port": "D", "num": "16", "functions": { "PDM_DATA": 0 } },
151+
{ "name": "PD22", "sortingname": "D22", "port": "D", "num": "13", "functions": { "HICHG": 0 } },
152+
{ "name": "PD23", "sortingname": "D23", "port": "D", "num": "17", "functions": { "NEGATED": 0, "CHG": 0 } },
153+
{ "name": "PD24", "sortingname": "D24", "port": "D", "num": "21", "functions": { "QSPI_SCK": 0 } },
154+
{ "name": "PD25", "sortingname": "D25", "port": "D", "num": "25", "functions": { "QSPI_CSN": 0 } },
155+
{ "name": "PD26", "sortingname": "D26", "port": "D", "num": "20", "functions": { "QSPI_DI": 0 } },
156+
{ "name": "PD27", "sortingname": "D27", "port": "D", "num": "24", "functions": { "QSPI_DO": 0 } },
157+
{ "name": "PD28", "sortingname": "D28", "port": "D", "num": "22", "functions": { "QSPI_WP": 0 } },
158+
{ "name": "PD29", "sortingname": "D29", "port": "D", "num": "23", "functions": { "QSPI_HOLD": 0 } },
159+
{ "name": "PD30", "sortingname": "D30", "port": "D", "num": "9", "functions": { "NFC1": 0 } },
160+
{ "name": "PD31", "sortingname": "D31", "port": "D", "num": "10", "functions": { "NFC2": 0 } },
161+
{ "name": "PD32", "sortingname": "D32", "port": "D", "num": "31", "functions": { "ADC1_IN7": 0, "VBAT": 0 } },
162+
]
163+
# D23 CHG
164+
# get charge state via digitalRead(D23)
165+
# HIGH: charging, LOW: not charging
166+
# D22 HICHG / PIN_CHARGING_CURRENT
167+
# battery charging current see https://wiki.seeedstudio.com/XIAO_BLE/#battery-charging-current
168+
# HIGH: 100mA, LOW: 50mA
169+
# D14 VBAT_ENABLE
170+
# enable battery voltage reading by digitalWrite(D14, true)
171+
# D32 VBAT
172+
# battery voltage; remember to enable voltage reading if you want to use this
173+
174+
# everything is non-5v tolerant
175+
for pin in pins:
176+
pin["functions"]["3.3"] = 0
177+
return pins

make/common/NRF5X.make

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,9 @@ $(PROJ_NAME).hex: $(PROJ_NAME).app_hex
527527
python scripts/hexmerge.py $(SOFTDEVICE) $(PROJ_NAME).app_hex -o $(PROJ_NAME).hex
528528
endif # USE_BOOTLOADER
529529

530+
$(PROJ_NAME).uf2: $(PROJ_NAME).hex
531+
@echo Creating UF2
532+
python3 scripts/uf2/uf2conv.py $(PROJ_NAME).hex -c -f $(CHIP) -o $(PROJ_NAME).uf2
530533

531534
$(PROJ_NAME).zip: $(PROJ_NAME).app_hex
532535
ifdef NRF5X_SDK_11 # SDK11 requires non-secure DFU that the adafruit tools support
@@ -561,11 +564,10 @@ partflash: all
561564

562565
ifdef DFU_UPDATE_BUILD_WITH_HEX
563566
proj: $(PROJ_NAME).hex $(PROJ_NAME).zip
564-
else
565-
ifdef DFU_UPDATE_BUILD
567+
else ifdef DFU_UPDATE_BUILD
566568
proj: $(PROJ_NAME).zip
569+
else ifdef CREATE_UF2
570+
proj: $(PROJ_NAME).uf2
567571
else
568572
proj: $(PROJ_NAME).hex
569573
endif
570-
endif
571-

scripts/get_makefile_decls.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
binaryName = binaryName[:binaryName.find('.bin')]
5454
if binaryName.find('.hex')>=0:
5555
binaryName = binaryName[:binaryName.find('.hex')]
56+
if binaryName.find('.uf2')>=0:
57+
binaryName = binaryName[:binaryName.find('.uf2')]
58+
print("CREATE_UF2=1")
5659
print("PROJ_NAME=$(BINDIR)/"+binaryName)
5760

5861
if board.chip["family"]!="LINUX":

scripts/uf2/LICENSE.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Microsoft UF2
2+
3+
The MIT License (MIT)
4+
5+
Copyright (c) Microsoft Corporation
6+
7+
All rights reserved.
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in all
17+
copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
SOFTWARE.

0 commit comments

Comments
 (0)