Merge pull request #49 from adafruit/upstream-merge-2019-04

Merge from microsoft/uf2-samdx1; fuse repair
This commit is contained in:
Dan Halbert 2019-04-14 22:07:15 -04:00 committed by GitHub
commit b9e9e70e98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1283 additions and 36 deletions

View file

@ -42,7 +42,7 @@ endif
LDFLAGS= $(COMMON_FLAGS) \
-Wall -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common \
-Wl,--warn-section-align -Wl,--warn-unresolved-symbols \
-Wl,--warn-section-align \
-save-temps -nostartfiles \
--specs=nano.specs --specs=nosys.specs
BUILD_PATH=build/$(BOARD)
@ -64,6 +64,8 @@ COMMON_SRC = \
src/init_$(CHIP_FAMILY).c \
src/startup_$(CHIP_FAMILY).c \
src/usart_sam_ba.c \
src/screen.c \
src/images.c \
src/utils.c
SOURCES = $(COMMON_SRC) \
@ -100,6 +102,27 @@ burn: all
run: burn wait logs
# This currently only works on macOS with a BMP debugger attached.
# It's meant to flash the bootloader in a loop.
BMP = $(shell ls -1 /dev/cu.usbmodem* | head -1)
BMP_ARGS = --nx -ex "set mem inaccessible-by-default off" -ex "set confirm off" -ex "target extended-remote $(BMP)" -ex "mon swdp_scan" -ex "attach 1"
GDB = arm-none-eabi-gdb
bmp-flash: $(BUILD_PATH)/$(NAME).bin
@test "X$(BMP)" != "X"
$(GDB) $(BMP_ARGS) -ex "load" -ex "quit" $(BUILD_PATH)/$(NAME).elf | tee build/flash.log
@grep -q "Transfer rate" build/flash.log
bmp-flashone:
while : ; do $(MAKE) bmp-flash && exit 0 ; sleep 1 ; done
afplay /System/Library/PrivateFrameworks/ScreenReader.framework/Versions/A/Resources/Sounds/Error.aiff
bmp-loop:
while : ; do $(MAKE) bmp-flashone ; sleep 5 ; done
bmp-gdb: $(BUILD_PATH)/$(NAME).bin
$(GDB) $(BMP_ARGS) $(BUILD_PATH)/$(NAME).elf
wait:
sleep 5

View file

@ -117,7 +117,7 @@ to temporarily turn off the protection. In gdb the command is:
* `make` and an Unix environment
* `node`.js in path (optional)
* `arm-none-eabi-gcc` in the path (the one coming with Yotta will do just fine)
* `arm-none-eabi-gcc` in the path (the one coming with Yotta will do just fine). You can get the latest version from ARM: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
* `openocd` - you can use the one coming with Arduino (after your install the M0 board support)
Atmel Studio is not supported.

2
boards/CC03/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -0,0 +1,16 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define VENDOR_NAME "XinaBox Limited"
#define PRODUCT_NAME "CC03"
#define VOLUME_LABEL "CC03"
#define INDEX_URL "https://xinabox.cc/products/cc03"
#define BOARD_ID "SAMD21G18A-CC03-v0"
//#define USB_VID 0x2341
//#define USB_PID 0x024D
#define LED_PIN PIN_PA07
#endif

2
boards/CS11/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -0,0 +1,16 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define VENDOR_NAME "XinaBox Limited"
#define PRODUCT_NAME "CS11"
#define VOLUME_LABEL "CS11"
#define INDEX_URL "https://xinabox.cc/products/cc11"
#define BOARD_ID "SAMD21G18A-CS11-v0"
//#define USB_VID 0x2341
//#define USB_PID 0x024D
#define LED_PIN PIN_PA08
#endif

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd51
CHIP_VARIANT = SAMD51J19A

View file

@ -0,0 +1,110 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define VENDOR_NAME "Adafruit Industries"
#define PRODUCT_NAME "Arcade D51"
#define VOLUME_LABEL "ARCADE-D5"
#define INDEX_URL "http://adafru.it/"
#define BOARD_ID "SAMD51J19A-Arcade-D51"
#define USB_VID 0x239A
#define USB_PID 0x002B
#define LED_PIN PIN_PA23
#define BOARD_NEOPIXEL_PIN PIN_PA15
#define BOARD_NEOPIXEL_COUNT 5
#define BOARD_SCREEN 1
#define BOOT_USART_MODULE SERCOM3
#define BOOT_USART_MASK APBAMASK
#define BOOT_USART_BUS_CLOCK_INDEX MCLK_APBBMASK_SERCOM3
#define BOOT_USART_PAD_SETTINGS UART_RX_PAD1_TX_PAD0
#define BOOT_USART_PAD3 PINMUX_UNUSED
#define BOOT_USART_PAD2 PINMUX_UNUSED
#define BOOT_USART_PAD1 PINMUX_PA22C_SERCOM3_PAD0
#define BOOT_USART_PAD0 PINMUX_PA23C_SERCOM3_PAD1
#define BOOT_GCLK_ID_CORE SERCOM3_GCLK_ID_CORE
#define BOOT_GCLK_ID_SLOW SERCOM3_GCLK_ID_SLOW
#define HAS_CONFIG_DATA 1
// This configuration data should be edited at https://microsoft.github.io/uf2/patcher/
// Just drop this file there.
// Alternatively, it can be also binary edited there after the bootloader is compiled.
#ifdef DEFINE_CONFIG_DATA
const uint32_t config_data[] = {
/* CF2 START */
513675505, 539130489, // magic
60, 100, // used entries, total entries
1, 0x2e, // PIN_ACCELEROMETER_INT = PB14
2, 0xd, // PIN_ACCELEROMETER_SCL = PIN_SCL
3, 0xc, // PIN_ACCELEROMETER_SDA = PIN_SDA
4, 0x3ef, // PIN_BTN_A = P_1007
5, 0x3ee, // PIN_BTN_B = P_1006
13, 0x17, // PIN_LED = PIN_D13
18, 0x36, // PIN_MISO = PB22
19, 0x37, // PIN_MOSI = PB23
20, 0xf, // PIN_NEOPIXEL = PA15
21, 0x11, // PIN_RX = PA17
23, 0x11, // PIN_SCK = PA17
24, 0xd, // PIN_SCL = PA13
25, 0xc, // PIN_SDA = PA12
28, 0x10, // PIN_TX = PA16
32, 0x2d, // PIN_DISPLAY_SCK = PB13
34, 0x2c, // PIN_DISPLAY_MOSI = PB12
35, 0x27, // PIN_DISPLAY_CS = PB07
36, 0x25, // PIN_DISPLAY_DC = PB05
37, 0xa0, // DISPLAY_WIDTH = 160
38, 0x80, // DISPLAY_HEIGHT = 128
39, 0x80, // DISPLAY_CFG0 = 0x80
40, 0x12c2d, // DISPLAY_CFG1 = 0x12c2d
41, 0x18, // DISPLAY_CFG2 = 0x18
43, 0x1, // PIN_DISPLAY_RST = PA01
44, 0x0, // PIN_DISPLAY_BL = PA00
47, 0x3e8, // PIN_BTN_LEFT = P_1000
48, 0x3eb, // PIN_BTN_RIGHT = P_1003
49, 0x3e9, // PIN_BTN_UP = P_1001
50, 0x3ea, // PIN_BTN_DOWN = P_1002
51, 0x3ec, // PIN_BTN_MENU = P_1004
59, 0x200, // SPEAKER_VOLUME = 512
60, 0x10, // PIN_JACK_TX = PIN_D5
65, 0x2, // PIN_JACK_SND = PIN_A0
69, 0x3ed, // PIN_BTN_SOFT_RESET = P_1005
70, 0x32, // ACCELEROMETER_TYPE = LIS3DH
71, 0x20, // PIN_BTNMX_LATCH = PB00
72, 0x3f, // PIN_BTNMX_CLOCK = PB31
73, 0x3e, // PIN_BTNMX_DATA = PB30
100, 0x2, // PIN_A0 = PA02
101, 0x5, // PIN_A1 = PA05
102, 0x28, // PIN_A2 = PB08
103, 0x29, // PIN_A3 = PB09
104, 0x4, // PIN_A4 = PA04
105, 0x6, // PIN_A5 = PA06
152, 0x23, // PIN_D2 = PB03
153, 0x22, // PIN_D3 = PB02
154, 0xe, // PIN_D4 = PA14
155, 0x10, // PIN_D5 = PA16
156, 0x12, // PIN_D6 = PA18
159, 0x13, // PIN_D9 = PA19
160, 0x14, // PIN_D10 = PA20
161, 0x15, // PIN_D11 = PA21
162, 0x16, // PIN_D12 = PA22
163, 0x17, // PIN_D13 = PA23
200, 0x5, // NUM_NEOPIXELS = 5
204, 0x80000, // FLASH_BYTES = 0x80000
205, 0x30000, // RAM_BYTES = 0x30000
208, 0x18591ab9, // BOOTLOADER_BOARD_ID = 0x18591ab9
209, 0x55114460, // UF2_FAMILY = ATSAMD51
210, 0x20, // PINS_PORT_SIZE = PA_32
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* CF2 END */
};
#endif
#endif

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd51
CHIP_VARIANT = SAMD51J19A

View file

@ -0,0 +1,106 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define VENDOR_NAME "Adafruit Industries"
#define PRODUCT_NAME "Feather Arcade D51"
#define VOLUME_LABEL "ARCADE-D5"
#define INDEX_URL "https://arcade.makecode.com/"
#define BOARD_ID "SAMD51J19A-Feather-Arcade-D51"
#define USB_VID 0x239A
#define USB_PID 0x0022
#define LED_PIN PIN_PA23
#define BOARD_NEOPIXEL_PIN PIN_PB03
#define BOARD_NEOPIXEL_COUNT 1
#define BOOT_USART_MODULE SERCOM0
#define BOOT_USART_MASK APBAMASK
#define BOOT_USART_BUS_CLOCK_INDEX MCLK_APBAMASK_SERCOM0
#define BOOT_USART_PAD_SETTINGS UART_RX_PAD3_TX_PAD0
#define BOOT_USART_PAD3 PINMUX_PA07D_SERCOM0_PAD3
#define BOOT_USART_PAD2 PINMUX_UNUSED
#define BOOT_USART_PAD1 PINMUX_UNUSED
#define BOOT_USART_PAD0 PINMUX_PA04D_SERCOM0_PAD0
#define BOOT_GCLK_ID_CORE SERCOM0_GCLK_ID_CORE
#define BOOT_GCLK_ID_SLOW SERCOM0_GCLK_ID_SLOW
#define HAS_CONFIG_DATA 1
#define BOARD_SCREEN 1
// This configuration data should be edited at https://microsoft.github.io/uf2/patcher/
// Just drop this file there.
// Alternatively, it can be also binary edited there after the bootloader is compiled.
#ifdef DEFINE_CONFIG_DATA
const uint32_t config_data[] = {
/* CF2 START */
513675505, 539130489, // magic
53, 100, // used entries, total entries
4, 0xd, // PIN_BTN_A = PIN_SCL
5, 0x12, // PIN_BTN_B = PIN_D6
13, 0x17, // PIN_LED = PIN_D13
18, 0x36, // PIN_MISO = PB22
19, 0x37, // PIN_MOSI = PB23
20, 0x23, // PIN_NEOPIXEL = PB03
21, 0x31, // PIN_RX = PB17
23, 0x11, // PIN_SCK = PA17
24, 0xd, // PIN_SCL = PA13
25, 0xc, // PIN_SDA = PA12
26, 0xe, // PIN_SPEAKER_AMP = PIN_D4
28, 0x30, // PIN_TX = PB16
32, 0x11, // PIN_DISPLAY_SCK = PIN_SCK
33, 0x36, // PIN_DISPLAY_MISO = PIN_MISO
34, 0x37, // PIN_DISPLAY_MOSI = PIN_MOSI
35, 0x28, // PIN_DISPLAY_CS = PIN_A2
36, 0x29, // PIN_DISPLAY_DC = PIN_A3
37, 0xa0, // DISPLAY_WIDTH = 160
38, 0x80, // DISPLAY_HEIGHT = 128
39, 0x90, // DISPLAY_CFG0 = 0x90
40, 0xe14ff, // DISPLAY_CFG1 = 0xe14ff
41, 0x18, // DISPLAY_CFG2 = 0x18
43, 0x4, // PIN_DISPLAY_RST = PIN_A4
44, 0x6, // PIN_DISPLAY_BL = PIN_A5
47, 0x15, // PIN_BTN_LEFT = PIN_D11
48, 0x13, // PIN_BTN_RIGHT = PIN_D9
49, 0x14, // PIN_BTN_UP = PIN_D10
50, 0x16, // PIN_BTN_DOWN = PIN_D12
51, 0xc, // PIN_BTN_MENU = PIN_SDA
59, 0x200, // SPEAKER_VOLUME = 512
60, 0x30, // PIN_JACK_TX = PIN_D1
100, 0x2, // PIN_A0 = PA02
101, 0x5, // PIN_A1 = PA05
102, 0x28, // PIN_A2 = PB08
103, 0x29, // PIN_A3 = PB09
104, 0x4, // PIN_A4 = PA04
105, 0x6, // PIN_A5 = PA06
150, 0x31, // PIN_D0 = PB17
151, 0x30, // PIN_D1 = PB16
154, 0xe, // PIN_D4 = PA14
155, 0x10, // PIN_D5 = PA16
156, 0x12, // PIN_D6 = PA18
159, 0x13, // PIN_D9 = PA19
160, 0x14, // PIN_D10 = PA20
161, 0x15, // PIN_D11 = PA21
162, 0x16, // PIN_D12 = PA22
163, 0x17, // PIN_D13 = PA23
200, 0x1, // NUM_NEOPIXELS = 1
204, 0x80000, // FLASH_BYTES = 0x80000
205, 0x30000, // RAM_BYTES = 0x30000
208, 0x2b9e3d05, // BOOTLOADER_BOARD_ID = 0x2b9e3d05
209, 0x55114460, // UF2_FAMILY = ATSAMD51
210, 0x20, // PINS_PORT_SIZE = PA_32
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* CF2 END */
};
#endif
#endif

View file

@ -0,0 +1,7 @@
PIN_BTN_A = PIN_D10
PIN_BTN_B = PIN_D11
PIN_BTN_LEFT = PIN_SDA
PIN_BTN_UP = PIN_D7
PIN_BTN_RIGHT = PIN_SCL
PIN_BTN_DOWN = PIN_D9
PIN_BTN_MENU = PIN_D12

View file

@ -0,0 +1,2 @@
DISPLAY_CFG0 = 0x01000080
DISPLAY_CFG1 = 0x00000603

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd51
CHIP_VARIANT = SAMD51G19A

View file

@ -0,0 +1,108 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define VENDOR_NAME "Adafruit Industries"
#define PRODUCT_NAME "Itsy Arcade D51"
#define VOLUME_LABEL "ARCADE-D5"
#define INDEX_URL "https://arcade.makecode.com/"
#define BOARD_ID "SAMD51G19A-Itsy-Arcade-D51"
#define USB_VID 0x239A
#define USB_PID 0x002B
#define LED_PIN PIN_PA22
#define BOARD_RGBLED_CLOCK_PIN PIN_PB02
#define BOARD_RGBLED_DATA_PIN PIN_PB03
#define BOOT_USART_MODULE SERCOM3
#define BOOT_USART_MASK APBAMASK
#define BOOT_USART_BUS_CLOCK_INDEX MCLK_APBBMASK_SERCOM3
#define BOOT_USART_PAD_SETTINGS UART_RX_PAD1_TX_PAD0
#define BOOT_USART_PAD3 PINMUX_UNUSED
#define BOOT_USART_PAD2 PINMUX_UNUSED
#define BOOT_USART_PAD1 PINMUX_PA22C_SERCOM3_PAD0
#define BOOT_USART_PAD0 PINMUX_PA23C_SERCOM3_PAD1
#define BOOT_GCLK_ID_CORE SERCOM3_GCLK_ID_CORE
#define BOOT_GCLK_ID_SLOW SERCOM3_GCLK_ID_SLOW
#define HAS_CONFIG_DATA 1
#define BOARD_SCREEN 1
// This configuration data should be edited at https://microsoft.github.io/uf2/patcher/
// Just drop this file there.
// Alternatively, it can be also binary edited there after the bootloader is compiled.
#ifdef DEFINE_CONFIG_DATA
const uint32_t config_data[] = {
/* CF2 START */
513675505, 539130489, // magic
60, 100, // used entries, total entries
4, 0xd, // PIN_BTN_A = PIN_SCL
5, 0x12, // PIN_BTN_B = PIN_D7
7, 0x22, // PIN_DOTSTAR_CLOCK = PB02
8, 0x23, // PIN_DOTSTAR_DATA = PB03
9, 0x2b, // PIN_FLASH_CS = PB11
10, 0x9, // PIN_FLASH_MISO = PA09
11, 0x8, // PIN_FLASH_MOSI = PA08
12, 0x2a, // PIN_FLASH_SCK = PB10
13, 0x16, // PIN_LED = PIN_D13
18, 0x37, // PIN_MISO = PB23
19, 0x0, // PIN_MOSI = PA00
21, 0x10, // PIN_RX = PA16
23, 0x1, // PIN_SCK = PA01
24, 0xd, // PIN_SCL = PA13
25, 0xc, // PIN_SDA = PA12
26, 0x7, // PIN_SPEAKER_AMP = PIN_D2
28, 0x11, // PIN_TX = PA17
32, 0x1, // PIN_DISPLAY_SCK = PIN_SCK
33, 0x37, // PIN_DISPLAY_MISO = PIN_MISO
34, 0x0, // PIN_DISPLAY_MOSI = PIN_MOSI
35, 0x28, // PIN_DISPLAY_CS = PIN_A2
36, 0x29, // PIN_DISPLAY_DC = PIN_A3
37, 0xa0, // DISPLAY_WIDTH = 160
38, 0x80, // DISPLAY_HEIGHT = 128
39, 0x90, // DISPLAY_CFG0 = 0x90
40, 0xe14ff, // DISPLAY_CFG1 = 0xe14ff
41, 0x18, // DISPLAY_CFG2 = 0x18
43, 0x4, // PIN_DISPLAY_RST = PIN_A4
44, 0x6, // PIN_DISPLAY_BL = PIN_A5
47, 0x15, // PIN_BTN_LEFT = PIN_D11
48, 0x13, // PIN_BTN_RIGHT = PIN_D9
49, 0x14, // PIN_BTN_UP = PIN_D10
50, 0x17, // PIN_BTN_DOWN = PIN_D12
51, 0xc, // PIN_BTN_MENU = PIN_SDA
59, 0x200, // SPEAKER_VOLUME = 512
60, 0x11, // PIN_JACK_TX = PIN_D1
100, 0x2, // PIN_A0 = PA02
101, 0x5, // PIN_A1 = PA05
102, 0x28, // PIN_A2 = PB08
103, 0x29, // PIN_A3 = PB09
104, 0x4, // PIN_A4 = PA04
105, 0x6, // PIN_A5 = PA06
150, 0x10, // PIN_D0 = PA16
151, 0x11, // PIN_D1 = PA17
152, 0x7, // PIN_D2 = PA07
153, 0x36, // PIN_D3 = PB22
154, 0xe, // PIN_D4 = PA14
155, 0xf, // PIN_D5 = PA15
157, 0x12, // PIN_D7 = PA18
159, 0x13, // PIN_D9 = PA19
160, 0x14, // PIN_D10 = PA20
161, 0x15, // PIN_D11 = PA21
162, 0x17, // PIN_D12 = PA23
163, 0x16, // PIN_D13 = PA22
201, 0x1, // NUM_DOTSTARS = 1
204, 0x80000, // FLASH_BYTES = 0x80000
205, 0x30000, // RAM_BYTES = 0x30000
208, 0x7a236324, // BOOTLOADER_BOARD_ID = 0x7a236324
209, 0x55114460, // UF2_FAMILY = ATSAMD51
210, 0x20, // PINS_PORT_SIZE = PA_32
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* CF2 END */
};
#endif
#endif

2
boards/mkr1300/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -0,0 +1,15 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define VENDOR_NAME "Arduino LLC"
#define PRODUCT_NAME "Arduino MKR1300"
#define VOLUME_LABEL "MKR1300"
#define BOARD_ID "SAMD21G18A-MKR1300-v0"
#define USB_VID 0x2341
#define USB_PID 0x8053
#define LED_PIN PIN_PA20
#endif

149
inc/configkeys.h Normal file
View file

@ -0,0 +1,149 @@
#ifndef __CONFIGKEYS_H
#define __CONFIGKEYS_H 1
#define CFG_MAGIC0 0x1e9e10f1
#define CFG_MAGIC1 0x20227a79
#define CFG_PIN_ACCELEROMETER_INT 1
#define CFG_PIN_ACCELEROMETER_SCL 2
#define CFG_PIN_ACCELEROMETER_SDA 3
#define CFG_PIN_BTN_A 4
#define CFG_PIN_BTN_B 5
#define CFG_PIN_BTN_SLIDE 6
#define CFG_PIN_DOTSTAR_CLOCK 7
#define CFG_PIN_DOTSTAR_DATA 8
#define CFG_PIN_FLASH_CS 9
#define CFG_PIN_FLASH_MISO 10
#define CFG_PIN_FLASH_MOSI 11
#define CFG_PIN_FLASH_SCK 12
#define CFG_PIN_LED 13
#define CFG_PIN_LIGHT 14
#define CFG_PIN_MICROPHONE 15
#define CFG_PIN_MIC_CLOCK 16
#define CFG_PIN_MIC_DATA 17
#define CFG_PIN_MISO 18
#define CFG_PIN_MOSI 19
#define CFG_PIN_NEOPIXEL 20
#define CFG_PIN_RX 21
#define CFG_PIN_RXLED 22
#define CFG_PIN_SCK 23
#define CFG_PIN_SCL 24
#define CFG_PIN_SDA 25
#define CFG_PIN_SPEAKER_AMP 26
#define CFG_PIN_TEMPERATURE 27
#define CFG_PIN_TX 28
#define CFG_PIN_TXLED 29
#define CFG_PIN_IR_OUT 30
#define CFG_PIN_IR_IN 31
#define CFG_PIN_DISPLAY_SCK 32
#define CFG_PIN_DISPLAY_MISO 33
#define CFG_PIN_DISPLAY_MOSI 34
#define CFG_PIN_DISPLAY_CS 35
#define CFG_PIN_DISPLAY_DC 36
#define CFG_DISPLAY_WIDTH 37
#define CFG_DISPLAY_HEIGHT 38
#define CFG_DISPLAY_CFG0 39
#define CFG_DISPLAY_CFG1 40
#define CFG_DISPLAY_CFG2 41
#define CFG_DISPLAY_CFG3 42
#define CFG_PIN_DISPLAY_RST 43
#define CFG_PIN_DISPLAY_BL 44
#define CFG_PIN_SERVO_1 45
#define CFG_PIN_SERVO_2 46
#define CFG_PIN_BTN_LEFT 47
#define CFG_PIN_BTN_RIGHT 48
#define CFG_PIN_BTN_UP 49
#define CFG_PIN_BTN_DOWN 50
#define CFG_PIN_BTN_MENU 51
#define CFG_PIN_LED_R 52
#define CFG_PIN_LED_G 53
#define CFG_PIN_LED_B 54
#define CFG_PIN_LED1 55
#define CFG_PIN_LED2 56
#define CFG_PIN_LED3 57
#define CFG_PIN_LED4 58
#define CFG_SPEAKER_VOLUME 59
#define CFG_PIN_JACK_TX 60
#define CFG_PIN_JACK_SENSE 61
#define CFG_PIN_JACK_HPEN 62
#define CFG_PIN_JACK_BZEN 63
#define CFG_PIN_JACK_PWREN 64
#define CFG_PIN_JACK_SND 65
#define CFG_PIN_JACK_BUSLED 66
#define CFG_PIN_JACK_COMMLED 67
#define CFG_PIN_BTNMX_LATCH 66
#define CFG_PIN_BTNMX_CLOCK 67
#define CFG_PIN_BTNMX_DATA 68
#define CFG_PIN_BTN_SOFT_RESET 69
#define CFG_ACCELEROMETER_TYPE 70
#define CFG_PIN_A0 100
#define CFG_PIN_A1 101
#define CFG_PIN_A2 102
#define CFG_PIN_A3 103
#define CFG_PIN_A4 104
#define CFG_PIN_A5 105
#define CFG_PIN_A6 106
#define CFG_PIN_A7 107
#define CFG_PIN_A8 108
#define CFG_PIN_A9 109
#define CFG_PIN_A10 110
#define CFG_PIN_A11 111
#define CFG_PIN_A12 112
#define CFG_PIN_A13 113
#define CFG_PIN_A14 114
#define CFG_PIN_A15 115
#define CFG_PIN_D0 150
#define CFG_PIN_D1 151
#define CFG_PIN_D2 152
#define CFG_PIN_D3 153
#define CFG_PIN_D4 154
#define CFG_PIN_D5 155
#define CFG_PIN_D6 156
#define CFG_PIN_D7 157
#define CFG_PIN_D8 158
#define CFG_PIN_D9 159
#define CFG_PIN_D10 160
#define CFG_PIN_D11 161
#define CFG_PIN_D12 162
#define CFG_PIN_D13 163
#define CFG_PIN_D14 164
#define CFG_PIN_D15 165
#define CFG_NUM_NEOPIXELS 200
#define CFG_NUM_DOTSTARS 201
#define CFG_DEFAULT_BUTTON_MODE 202
#define CFG_SWD_ENABLED 203
#define CFG_FLASH_BYTES 204
#define CFG_RAM_BYTES 205
#define CFG_SYSTEM_HEAP_BYTES 206
#define CFG_LOW_MEM_SIMULATION_KB 207
#define CFG_BOOTLOADER_BOARD_ID 208
#define CFG_UF2_FAMILY 209
#define CFG_PINS_PORT_SIZE 210
#define ACCELEROMETER_TYPE_LIS3DH 0x32
#define ACCELEROMETER_TYPE_MMA8453 0x38
#define ACCELEROMETER_TYPE_FXOS8700 0x3c
#define ACCELEROMETER_TYPE_MMA8653 0x3a
#define ACCELEROMETER_TYPE_MSA300 0x4c
#define UF2_FAMILY_ATSAMD21 0x68ed2b88
#define UF2_FAMILY_ATSAMD51 0x55114460
#define UF2_FAMILY_NRF52840 0x1b57745f
#define UF2_FAMILY_STM32F103 0x5ee21072
#define UF2_FAMILY_STM32F401 0x57755a57
#define UF2_FAMILY_ATMEGA32 0x16573617
#define UF2_FAMILY_CYPRESS_FX2 0x5a18069b
#define PINS_PORT_SIZE_PA_16 0x10
#define PINS_PORT_SIZE_PA_32 0x20
#define PINS_PORT_SIZE_P0_16 0x1010
#define PINS_PORT_SIZE_P0_32 0x1020
#define DEFAULT_BUTTON_MODE_ACTIVE_HIGH_PULL_DOWN 0x11
#define DEFAULT_BUTTON_MODE_ACTIVE_HIGH_PULL_UP 0x21
#define DEFAULT_BUTTON_MODE_ACTIVE_HIGH_PULL_NONE 0x31
#define DEFAULT_BUTTON_MODE_ACTIVE_LOW_PULL_DOWN 0x10
#define DEFAULT_BUTTON_MODE_ACTIVE_LOW_PULL_UP 0x20
#define DEFAULT_BUTTON_MODE_ACTIVE_LOW_PULL_NONE 0x30
#endif // __CONFIGKEYS_H

View file

@ -1,6 +1,7 @@
#ifndef UF2_H
#define UF2_H 1
#include <stdint.h>
#include "board_config.h"
#include "sam.h"
@ -14,10 +15,14 @@
#include <stdio.h>
#include <string.h>
#include "configkeys.h"
#undef DISABLE
#undef ENABLE
// always go for crystalless - smaller and more compatiable
// always go for crystalless - smaller and more compatible
#ifndef CRYSTALLESS
#define CRYSTALLESS 1
#endif
@ -55,6 +60,12 @@
// Doesn't yet disable code, just enumeration
#define USE_MSC 1
#ifdef BOARD_SCREEN
#define USE_SCREEN 1
#else
#define USE_SCREEN 0
#endif
// If enabled, bootloader will start on power-on and every reset. A second reset
// will start the app. This only happens if the app says it wants that (see SINGLE_RESET() below).
// If disabled here or by the app, the bootloader will only start with double-click of the reset
@ -125,7 +136,13 @@
// End of config
#define USE_MONITOR (USE_CDC || USE_UART)
#ifdef SAMD51
// 51 also runs at 48MHz in bootloader mode, but it's still faster
#define TIMER_STEP 2000
#else
#define TIMER_STEP 1500
#endif
#ifdef BOARD_NEOPIXEL_PIN
#define COLOR_START 0x040000
@ -233,8 +250,13 @@ void padded_memcpy(char *dst, const char *src, int len);
#define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef
#if USE_SINGLE_RESET
#ifdef SAMD21
#define SINGLE_RESET() (*((uint32_t *)0x20B4) == 0x87eeb07c)
#endif
#ifdef SAMD51
#define SINGLE_RESET() (*((uint32_t *)0x4268) == 0x87eeb07c)
#endif
#endif
void resetIntoApp(void);
void resetIntoBootloader(void);
@ -249,9 +271,16 @@ void led_signal(void);
void led_init(void);
void RGBLED_set_color(uint32_t color);
// Not all targets have a LED
#if defined(LED_PIN)
#define LED_MSC_OFF() PINOP(LED_PIN, OUTCLR)
#define LED_MSC_ON() PINOP(LED_PIN, OUTSET)
#define LED_MSC_TGL() PINOP(LED_PIN, OUTTGL)
#else
#define LED_MSC_OFF()
#define LED_MSC_ON()
#define LED_MSC_TGL()
#endif
extern uint32_t timerHigh, resetHorizon;
void timerTick(void);
@ -271,4 +300,12 @@ STATIC_ASSERT(FLASH_NUM_ROWS * 4 == FLASH_NB_OF_PAGES);
extern const char infoUf2File[];
#if USE_SCREEN
void draw_screen(void);
void draw_hf2(void);
void draw_drag(void);
void screen_init(void);
void screen_early_init(void);
#endif
#endif

View file

@ -9,9 +9,11 @@
// if you increase that, you will also need to update the linker script file
#ifdef SAMD21
#define APP_START_ADDRESS 0x00002000
#define UF2_FAMILY 0x68ed2b88
#endif
#ifdef SAMD51
#define APP_START_ADDRESS 0x00004000
#define UF2_FAMILY 0x55114460
#endif
#define UF2_MAGIC_START0 0x0A324655UL // "UF2\n"
@ -20,6 +22,10 @@
// If set, the block is "comment" and should not be flashed to the device
#define UF2_FLAG_NOFLASH 0x00000001
#define UF2_FLAG_FAMILYID_PRESENT 0x00002000
#define UF2_IS_MY_FAMILY(bl) \
(((bl)->flags & UF2_FLAG_FAMILYID_PRESENT) == 0 || (bl)->familyID == UF2_FAMILY)
typedef struct {
// 32 byte header
@ -30,7 +36,7 @@ typedef struct {
uint32_t payloadSize;
uint32_t blockNo;
uint32_t numBlocks;
uint32_t reserved;
uint32_t familyID;
// raw data;
uint8_t data[476];
@ -54,7 +60,7 @@ typedef void (*UF2_HID_Handover_Handler)(int ep);
// this is required to be exactly 16 bytes long by the linker script
typedef struct {
void *reserved0;
const uint32_t *config_data;
UF2_HID_Handover_Handler handoverHID;
UF2_MSC_Handover_Handler handoverMSC;
const char *info_uf2;

View file

@ -10,6 +10,7 @@ struct HF2_BININFO_Result {
uint32_t flash_page_size;
uint32_t flash_num_pages;
uint32_t max_message_size;
uint32_t uf2_family;
};
#define HF2_CMD_INFO 0x0002

View file

@ -354,7 +354,7 @@ static char msOS20Descriptor[] = {
//
'{', 0, '9', 0, '2', 0, 'C', 0, 'E', 0, '6', 0, '4', 0, '6', 0, '2', 0, '-', 0, '9', 0, 'C', 0,
'7', 0, '7', 0, '-', 0, '4', 0, '6', 0, 'F', 0, 'E', 0, '-', 0, '9', 0, '3', 0, '3', 0, 'B', 0,
'-', 0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'A', 0, 'A', 0, '3', 0, 'B', 0,
'-', 0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'B', 0, 'B', 0, '3', 0, 'B', 0,
'9', 0, '}', 0, 0, 0, 0, 0};
STATIC_ASSERT(sizeof(msOS20Descriptor) == WINUSB_SIZE);

View file

@ -72,6 +72,8 @@ const char indexFile[] = //
"</html>\n";
#endif
// WARNING -- code presumes only one NULL .content for .UF2 file
// and requires it be the last element of the array
static const struct TextFile info[] = {
{.name = "INFO_UF2TXT", .content = infoUf2File},
#if USE_INDEX_HTM
@ -79,11 +81,12 @@ static const struct TextFile info[] = {
#endif
{.name = "CURRENT UF2"},
};
#define NUM_INFO (sizeof(info) / sizeof(info[0]))
#define NUM_FILES (sizeof(info) / sizeof(info[0]))
#define NUM_DIRENTRIES (NUM_FILES + 1) // Code adds volume label as first root directory entry
#define UF2_SIZE (FLASH_SIZE * 2)
#define UF2_SECTORS (UF2_SIZE / 512)
#define UF2_FIRST_SECTOR (NUM_INFO + 1)
#define UF2_FIRST_SECTOR (NUM_FILES + 1) // WARNING -- code presumes each non-UF2 file content fits in single sector
#define UF2_LAST_SECTOR (UF2_FIRST_SECTOR + UF2_SECTORS - 1)
#endif
@ -96,6 +99,12 @@ static const struct TextFile info[] = {
#define START_ROOTDIR (START_FAT1 + SECTORS_PER_FAT)
#define START_CLUSTERS (START_ROOTDIR + ROOT_DIR_SECTORS)
// all directory entries must fit in a single sector
// because otherwise current code overflows buffer
#define DIRENTRIES_PER_SECTOR (512/sizeof(DirEntry))
STATIC_ASSERT(NUM_DIRENTRIES < DIRENTRIES_PER_SECTOR * ROOT_DIR_SECTORS);
static const FAT_BootBlock BootBlock = {
.JumpInstruction = {0xeb, 0x3c, 0x90},
.OEMInfo = "UF2 UF2 ",
@ -103,12 +112,13 @@ static const FAT_BootBlock BootBlock = {
.SectorsPerCluster = 1,
.ReservedSectors = RESERVED_SECTORS,
.FATCopies = 2,
.RootDirectoryEntries = (ROOT_DIR_SECTORS * 512 / 32),
.RootDirectoryEntries = (ROOT_DIR_SECTORS * DIRENTRIES_PER_SECTOR),
.TotalSectors16 = NUM_FAT_BLOCKS - 2,
.MediaDescriptor = 0xF8,
.SectorsPerFAT = SECTORS_PER_FAT,
.SectorsPerTrack = 1,
.Heads = 1,
.PhysicalDriveNum = 0x80, // to match MediaDescriptor of 0xF8
.ExtendedBootSig = 0x29,
.VolumeSerialNumber = 0x00420042,
.VolumeLabel = VOLUME_LABEL,
@ -129,24 +139,27 @@ void read_block(uint32_t block_no, uint8_t *data) {
memset(data, 0, 512);
uint32_t sectionIdx = block_no;
if (block_no == 0) {
if (block_no == 0) { // Requested boot block
memcpy(data, &BootBlock, sizeof(BootBlock));
data[510] = 0x55;
data[511] = 0xaa;
// logval("data[0]", data[0]);
} else if (block_no < START_ROOTDIR) {
} else if (block_no < START_ROOTDIR) { // Requested FAT table sector
sectionIdx -= START_FAT0;
// logval("sidx", sectionIdx);
if (sectionIdx >= SECTORS_PER_FAT)
sectionIdx -= SECTORS_PER_FAT;
sectionIdx -= SECTORS_PER_FAT; // second FAT is same as the first...
#if USE_FAT
if (sectionIdx == 0) {
data[0] = 0xf0;
for (int i = 1; i < NUM_INFO * 2 + 4; ++i) {
// WARNING -- code presumes only one NULL .content for .UF2 file
// and all non-NULL .content fit in one sector
// and requires it be the last element of the array
for (int i = 1; i < NUM_FILES * 2 + 4; ++i) {
data[i] = 0xff;
}
}
for (int i = 0; i < 256; ++i) {
for (int i = 0; i < 256; ++i) { // Generate the FAT chain for the firmware "file"
uint32_t v = sectionIdx * 256 + i;
if (UF2_FIRST_SECTOR <= v && v <= UF2_LAST_SECTOR)
((uint16_t *)(void *)data)[i] = v == UF2_LAST_SECTOR ? 0xffff : v + 1;
@ -157,26 +170,29 @@ void read_block(uint32_t block_no, uint8_t *data) {
#endif
}
#if USE_FAT
else if (block_no < START_CLUSTERS) {
else if (block_no < START_CLUSTERS) { // Requested sector of the root directory
sectionIdx -= START_ROOTDIR;
if (sectionIdx == 0) {
DirEntry *d = (void *)data;
padded_memcpy(d->name, BootBlock.VolumeLabel, 11);
d->attrs = 0x28;
for (int i = 0; i < NUM_INFO; ++i) {
for (int i = 0; i < NUM_FILES; ++i) {
d++;
const struct TextFile *inf = &info[i];
d->size = inf->content ? strlen(inf->content) : UF2_SIZE;
d->startCluster = i + 2;
padded_memcpy(d->name, inf->name, 11);
d->createDate = 0x4d99;
d->updateDate = 0x4d99;
}
}
} else {
} else { // Requested sector from file space
sectionIdx -= START_CLUSTERS;
if (sectionIdx < NUM_INFO - 1) {
// WARNING -- code presumes all but last file take exactly one sector
if (sectionIdx < NUM_FILES - 1) {
memcpy(data, info[sectionIdx].content, strlen(info[sectionIdx].content));
} else {
sectionIdx -= NUM_INFO - 1;
sectionIdx -= NUM_FILES - 1;
uint32_t addr = sectionIdx * 256;
if (addr < FLASH_SIZE) {
UF2_Block *bl = (void *)data;
@ -187,6 +203,8 @@ void read_block(uint32_t block_no, uint8_t *data) {
bl->numBlocks = FLASH_SIZE / 256;
bl->targetAddr = addr;
bl->payloadSize = 256;
bl->flags |= UF2_FLAG_FAMILYID_PRESENT;
bl->familyID = UF2_FAMILY;
memcpy(bl->data, (void *)addr, bl->payloadSize);
}
}
@ -196,7 +214,7 @@ void read_block(uint32_t block_no, uint8_t *data) {
void write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state) {
UF2_Block *bl = (void *)data;
if (!is_uf2_block(bl)) {
if (!is_uf2_block(bl) || !UF2_IS_MY_FAMILY(bl)) {
return;
}

View file

@ -138,6 +138,7 @@ void process_core(HID_InBuffer *pkt) {
resp->bininfo.flash_page_size = FLASH_ROW_SIZE;
resp->bininfo.flash_num_pages = FLASH_SIZE / FLASH_ROW_SIZE;
resp->bininfo.max_message_size = sizeof(pkt->buf);
resp->bininfo.uf2_family = UF2_FAMILY;
send_hf2_response(pkt, sizeof(resp->bininfo));
return;

118
src/images.c Normal file
View file

@ -0,0 +1,118 @@
#include <stdint.h>
// all https://makecode.com/_VrfEKzV4xfvq
// https://makecode.com/_7VxXm3JMPXfM - file
// https://makecode.com/_LuEUCsPEKUbs - download
const uint8_t fileLogo[] = {
32, 32, 71, 140, 201, 151, 1, 2, 146, 1, 2, 146, 63, 2, 151, 9, 153, 9, 153, 9, 146, 1, 9, 146, 3, 9, 146, 7, 9, 137, 205, 72, 140, 206, 36, 139, 207, 18, 138, 206, 36, 139, 205, 72, 149, 7, 9, 146, 3, 9, 146, 1, 9, 153, 9, 153, 9, 153, 9, 148, 63, 2, 146, 1, 2, 146, 1, 2, 146, 201, 191, 191, 191, 174
};
// https://makecode.com/_9b0RcK5yRa12
const uint8_t pendriveLogo[] = {
32, 32, 59, 137, 215, 137, 1, 143, 1, 8, 146, 203, 149, 3, 8, 146, 3, 8, 146, 115, 8, 146, 115, 8, 146, 3, 8, 146, 3, 8, 146, 115, 8, 146, 115, 8, 146, 3, 8, 146, 3, 8, 146, 203, 149, 1, 8, 146, 1, 8, 146, 1, 120, 211, 191, 191, 191, 191, 191, 191, 191, 135
};
// https://makecode.com/_TTqbj705L4mr
const uint8_t arrowLogo[] = {
32, 32, 54, 137, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 146, 211, 142, 209, 144, 207, 146, 205, 148, 203, 150, 201, 152, 199, 154, 31, 154, 7, 154, 1, 191, 191, 191, 175
};
const uint8_t font8[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00,
0x28, 0xfe, 0x28, 0xfe, 0x28, 0x00,
0x4c, 0x92, 0xff, 0x92, 0x64, 0x00,
0x02, 0x65, 0x12, 0x48, 0xa6, 0x40,
0x6c, 0x92, 0x92, 0x6c, 0xa0, 0x00,
0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0x82, 0x00, 0x00,
0x00, 0x00, 0x82, 0x7c, 0x00, 0x00,
0x54, 0x38, 0x10, 0x38, 0x54, 0x00,
0x10, 0x10, 0x7c, 0x10, 0x10, 0x00,
0x00, 0x00, 0x90, 0x70, 0x00, 0x00,
0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
0x00, 0x00, 0x60, 0x60, 0x00, 0x00,
0x00, 0x60, 0x10, 0x08, 0x06, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x3c, 0x00,
0x00, 0x44, 0x7e, 0x40, 0x00, 0x00,
0x00, 0x44, 0x62, 0x52, 0x4c, 0x00,
0x00, 0x42, 0x4a, 0x4e, 0x32, 0x00,
0x30, 0x28, 0x24, 0x7e, 0x20, 0x00,
0x00, 0x4e, 0x4a, 0x4a, 0x32, 0x00,
0x00, 0x3c, 0x4a, 0x4a, 0x30, 0x00,
0x00, 0x02, 0x62, 0x12, 0x0e, 0x00,
0x00, 0x34, 0x4a, 0x4a, 0x34, 0x00,
0x00, 0x0c, 0x52, 0x52, 0x3c, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0x00, 0x00,
0x00, 0x00, 0x96, 0x76, 0x00, 0x00,
0x10, 0x28, 0x28, 0x44, 0x44, 0x00,
0x28, 0x28, 0x28, 0x28, 0x28, 0x00,
0x44, 0x44, 0x28, 0x28, 0x10, 0x00,
0x00, 0x02, 0x59, 0x09, 0x06, 0x00,
0x3c, 0x42, 0x5a, 0x56, 0x08, 0x00,
0x78, 0x14, 0x12, 0x14, 0x78, 0x00,
0x7e, 0x4a, 0x4a, 0x4a, 0x34, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x24, 0x00,
0x00, 0x7e, 0x42, 0x42, 0x3c, 0x00,
0x00, 0x7e, 0x4a, 0x4a, 0x42, 0x00,
0x00, 0x7e, 0x0a, 0x0a, 0x02, 0x00,
0x00, 0x3c, 0x42, 0x52, 0x34, 0x00,
0x00, 0x7e, 0x08, 0x08, 0x7e, 0x00,
0x00, 0x42, 0x7e, 0x42, 0x00, 0x00,
0x20, 0x40, 0x42, 0x3e, 0x02, 0x00,
0x00, 0x7e, 0x08, 0x14, 0x62, 0x00,
0x00, 0x7e, 0x40, 0x40, 0x40, 0x00,
0x7e, 0x04, 0x18, 0x04, 0x7e, 0x00,
0x00, 0x7e, 0x04, 0x08, 0x7e, 0x00,
0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00,
0x00, 0x7e, 0x12, 0x12, 0x0c, 0x00,
0x00, 0x3c, 0x52, 0x62, 0xbc, 0x00,
0x00, 0x7e, 0x12, 0x12, 0x6c, 0x00,
0x00, 0x24, 0x4a, 0x52, 0x24, 0x00,
0x02, 0x02, 0x7e, 0x02, 0x02, 0x00,
0x00, 0x3e, 0x40, 0x40, 0x3e, 0x00,
0x00, 0x1e, 0x70, 0x70, 0x1e, 0x00,
0x7e, 0x20, 0x18, 0x20, 0x7e, 0x00,
0x42, 0x24, 0x18, 0x24, 0x42, 0x00,
0x06, 0x08, 0x70, 0x08, 0x06, 0x00,
0x00, 0x62, 0x52, 0x4a, 0x46, 0x00,
0x00, 0x7e, 0x42, 0x42, 0x00, 0x00,
0x00, 0x06, 0x08, 0x10, 0x60, 0x00,
0x00, 0x42, 0x42, 0x7e, 0x00, 0x00,
0x08, 0x04, 0x02, 0x04, 0x08, 0x00,
0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
0x00, 0x30, 0x48, 0x48, 0x78, 0x00,
0x00, 0x7e, 0x48, 0x48, 0x30, 0x00,
0x00, 0x30, 0x48, 0x48, 0x48, 0x00,
0x00, 0x30, 0x48, 0x48, 0x7e, 0x00,
0x00, 0x30, 0x68, 0x58, 0x50, 0x00,
0x00, 0x10, 0x7c, 0x12, 0x04, 0x00,
0x00, 0x18, 0xa4, 0xa4, 0x78, 0x00,
0x00, 0x7e, 0x08, 0x08, 0x70, 0x00,
0x00, 0x48, 0x7a, 0x40, 0x00, 0x00,
0x00, 0x40, 0x84, 0x7d, 0x00, 0x00,
0x00, 0x7e, 0x10, 0x28, 0x40, 0x00,
0x00, 0x42, 0x7e, 0x40, 0x00, 0x00,
0x78, 0x08, 0x30, 0x08, 0x70, 0x00,
0x00, 0x78, 0x08, 0x08, 0x70, 0x00,
0x00, 0x30, 0x48, 0x48, 0x30, 0x00,
0x00, 0xfc, 0x24, 0x24, 0x18, 0x00,
0x00, 0x18, 0x24, 0x24, 0xfc, 0x00,
0x00, 0x78, 0x10, 0x08, 0x10, 0x00,
0x00, 0x50, 0x58, 0x68, 0x28, 0x00,
0x00, 0x08, 0x3e, 0x48, 0x20, 0x00,
0x00, 0x38, 0x40, 0x40, 0x78, 0x00,
0x00, 0x18, 0x60, 0x60, 0x18, 0x00,
0x38, 0x40, 0x30, 0x40, 0x38, 0x00,
0x00, 0x48, 0x30, 0x30, 0x48, 0x00,
0x00, 0x5c, 0xa0, 0xa0, 0x7c, 0x00,
0x00, 0x48, 0x68, 0x58, 0x48, 0x00,
0x00, 0x08, 0x36, 0x41, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x41, 0x36, 0x08, 0x00, 0x00,
0x00, 0x08, 0x04, 0x08, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

View file

@ -72,7 +72,7 @@
* to use the interrupt vectors of the application @0x2000.<- not required as
* application code is taking care of this
*
*/
*/
#include "uf2.h"
@ -109,13 +109,12 @@ static void check_start_application(void) {
#if USE_SINGLE_RESET
if (SINGLE_RESET()) {
if (RESET_CONTROLLER->RCAUSE.bit.POR ||
*DBL_TAP_PTR != DBL_TAP_MAGIC_QUICK_BOOT) {
if (RESET_CONTROLLER->RCAUSE.bit.POR || *DBL_TAP_PTR != DBL_TAP_MAGIC_QUICK_BOOT) {
// the second tap on reset will go into app
*DBL_TAP_PTR = DBL_TAP_MAGIC_QUICK_BOOT;
// this will be cleared after succesful USB enumeration
// this is around 1.5s
resetHorizon = timerHigh + 300;
resetHorizon = timerHigh + 50;
return;
}
}
@ -162,7 +161,7 @@ int main(void) {
while (1) {
}
#if (USB_VID == 0x239a) && (USB_PID == 0x0013) // Adafruit Metro M0
#if (USB_VID == 0x239a) && (USB_PID == 0x0013) // Adafruit Metro M0
// Delay a bit so SWD programmer can have time to attach.
delay(15);
#endif
@ -209,6 +208,11 @@ int main(void) {
#endif
RGBLED_set_color(COLOR_USB);
led_tick_step = 1;
#if USE_SCREEN
screen_init();
draw_drag();
#endif
}
main_b_cdc_enable = true;
@ -240,5 +244,12 @@ int main(void) {
process_msc();
}
#endif
if (!main_b_cdc_enable) {
// get more predictable timings before the USB is enumerated
for (int i = 1; i < 256; ++i) {
asm("nop");
}
}
}
}

View file

@ -42,6 +42,8 @@
*/
#define DEFINE_CONFIG_DATA 1
#include "uf2.h"
#include "lib/usb_msc/sbc_protocol.h"
@ -864,6 +866,9 @@ static void handover(UF2_HandoverArgs *args) {
#endif
__attribute__((section(".binfo"))) __attribute__((__used__)) const UF2_BInfo binfo = {
#ifdef HAS_CONFIG_DATA
.config_data = config_data,
#endif
#if USE_MSC_HANDOVER
.handoverMSC = handover,
#endif

455
src/screen.c Normal file
View file

@ -0,0 +1,455 @@
#include "uf2.h"
#if USE_SCREEN
#include <string.h>
#define DISPLAY_WIDTH 160
#define DISPLAY_HEIGHT 128
#define ST7735_NOP 0x00
#define ST7735_SWRESET 0x01
#define ST7735_RDDID 0x04
#define ST7735_RDDST 0x09
#define ST7735_SLPIN 0x10
#define ST7735_SLPOUT 0x11
#define ST7735_PTLON 0x12
#define ST7735_NORON 0x13
#define ST7735_INVOFF 0x20
#define ST7735_INVON 0x21
#define ST7735_DISPOFF 0x28
#define ST7735_DISPON 0x29
#define ST7735_CASET 0x2A
#define ST7735_RASET 0x2B
#define ST7735_RAMWR 0x2C
#define ST7735_RAMRD 0x2E
#define ST7735_PTLAR 0x30
#define ST7735_COLMOD 0x3A
#define ST7735_MADCTL 0x36
#define ST7735_FRMCTR1 0xB1
#define ST7735_FRMCTR2 0xB2
#define ST7735_FRMCTR3 0xB3
#define ST7735_INVCTR 0xB4
#define ST7735_DISSET5 0xB6
#define ST7735_PWCTR1 0xC0
#define ST7735_PWCTR2 0xC1
#define ST7735_PWCTR3 0xC2
#define ST7735_PWCTR4 0xC3
#define ST7735_PWCTR5 0xC4
#define ST7735_VMCTR1 0xC5
#define ST7735_RDID1 0xDA
#define ST7735_RDID2 0xDB
#define ST7735_RDID3 0xDC
#define ST7735_RDID4 0xDD
#define ST7735_PWCTR6 0xFC
#define ST7735_GMCTRP1 0xE0
#define ST7735_GMCTRN1 0xE1
uint32_t lookupCfg(uint32_t key, uint32_t defl);
#define CFG(v) lookupCfg(CFG_##v, 0x42)
uint32_t lookupCfg(uint32_t key, uint32_t defl) {
const uint32_t *ptr = UF2_BINFO->config_data;
if (!ptr || (((uint32_t)ptr) & 3) || *ptr != CFG_MAGIC0) {
// no config data!
} else {
ptr += 4;
while (*ptr) {
if (*ptr == key)
return ptr[1];
ptr += 2;
}
}
if (defl == 0x42)
while (1)
;
return defl;
}
void pin_set(int pincfg, int v) {
int pin = lookupCfg(pincfg, -1);
if (pin < 0)
return;
if (v) {
PINOP(pin, OUTSET);
} else {
PINOP(pin, OUTCLR);
}
}
void setup_output_pin(int pincfg) {
int pin = lookupCfg(pincfg, -1);
if (pin < 0)
return;
PINOP(pin, DIRSET);
PINOP(pin, OUTCLR);
}
#define PINPORT(pin) PORT->Group[(pin) / 32]
#define pinmask(pin) (1 << (pin & 0x1f))
void transfer(uint8_t *ptr, uint32_t len) {
int mosi = CFG(PIN_DISPLAY_MOSI);
int sck = CFG(PIN_DISPLAY_SCK);
volatile uint32_t *mosi_set = &PINPORT(mosi).OUTSET.reg;
volatile uint32_t *mosi_clr = &PINPORT(mosi).OUTCLR.reg;
volatile uint32_t *sck_tgl = &PINPORT(sck).OUTTGL.reg;
uint32_t mosi_mask = pinmask(mosi);
uint32_t sck_mask = pinmask(sck);
PINOP(sck, OUTCLR);
uint8_t mask = 0, b;
for (;;) {
if (!mask) {
if (!len--)
break;
mask = 0x80;
b = *ptr++;
}
if (b & mask)
*mosi_set = mosi_mask;
else
*mosi_clr = mosi_mask;
*sck_tgl = sck_mask;
mask >>= 1;
*sck_tgl = sck_mask;
}
}
#define DELAY 0x80
// clang-format off
static const uint8_t initCmds[] = {
ST7735_SWRESET, DELAY, // 1: Software reset, 0 args, w/delay
120, // 150 ms delay
ST7735_SLPOUT , DELAY, // 2: Out of sleep mode, 0 args, w/delay
120, // 500 ms delay
ST7735_INVOFF , 0 , // 13: Don't invert display, no args, no delay
ST7735_COLMOD , 1 , // 15: set color mode, 1 arg, no delay:
0x05, // 16-bit color
ST7735_GMCTRP1, 16 , // 1: Magical unicorn dust, 16 args, no delay:
0x02, 0x1c, 0x07, 0x12,
0x37, 0x32, 0x29, 0x2d,
0x29, 0x25, 0x2B, 0x39,
0x00, 0x01, 0x03, 0x10,
ST7735_NORON , DELAY, // 3: Normal display on, no args, w/delay
10, // 10 ms delay
ST7735_DISPON , DELAY, // 4: Main screen turn on, no args w/delay
10,
0, 0 // END
};
// clang-format on
static uint8_t cmdBuf[20];
#define SET_DC(v) pin_set(CFG_PIN_DISPLAY_DC, v)
#define SET_CS(v) pin_set(CFG_PIN_DISPLAY_CS, v)
static void scr_delay(unsigned msec) {
int k = msec * 15000;
while (k--)
asm("nop");
}
static void sendCmd(uint8_t *buf, int len) {
// make sure cmd isn't on stack
if (buf != cmdBuf)
memcpy(cmdBuf, buf, len);
buf = cmdBuf;
SET_DC(0);
SET_CS(0);
transfer(buf, 1);
SET_DC(1);
len--;
buf++;
if (len > 0)
transfer(buf, len);
SET_CS(1);
}
static void sendCmdSeq(const uint8_t *buf) {
while (*buf) {
cmdBuf[0] = *buf++;
int v = *buf++;
int len = v & ~DELAY;
// note that we have to copy to RAM
memcpy(cmdBuf + 1, buf, len);
sendCmd(cmdBuf, len + 1);
buf += len;
if (v & DELAY) {
scr_delay(*buf++);
}
}
}
static uint32_t palXOR;
static void setAddrWindow(int x, int y, int w, int h) {
uint8_t cmd0[] = {ST7735_RASET, 0, (uint8_t)x, 0, (uint8_t)(x + w - 1)};
uint8_t cmd1[] = {ST7735_CASET, 0, (uint8_t)y, 0, (uint8_t)(y + h - 1)};
sendCmd(cmd1, sizeof(cmd1));
sendCmd(cmd0, sizeof(cmd0));
}
static void configure(uint8_t madctl, uint32_t frmctr1) {
uint8_t cmd0[] = {ST7735_MADCTL, madctl};
uint8_t cmd1[] = {ST7735_FRMCTR1, (uint8_t)(frmctr1 >> 16), (uint8_t)(frmctr1 >> 8),
(uint8_t)frmctr1};
sendCmd(cmd0, sizeof(cmd0));
sendCmd(cmd1, cmd1[3] == 0xff ? 3 : 4);
}
#define COL0(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
#define COL(c) COL0((c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff)
const uint16_t palette[] = {
COL(0x000000), // 0
COL(0xffffff), // 1
COL(0xff2121), // 2
COL(0xff93c4), // 3
COL(0xff8135), // 4
COL(0xfff609), // 5
COL(0x249ca3), // 6
COL(0x78dc52), // 7
COL(0x003fad), // 8
COL(0x87f2ff), // 9
COL(0x8e2ec4), // 10
COL(0xa4839f), // 11
COL(0x5c406c), // 12
COL(0xe5cdc4), // 13
COL(0x91463d), // 14
COL(0x000000), // 15
};
uint8_t fb[168 * 128];
extern const uint8_t font8[];
extern const uint8_t fileLogo[];
extern const uint8_t pendriveLogo[];
extern const uint8_t arrowLogo[];
static void printch(int x, int y, int col, const uint8_t *fnt) {
for (int i = 0; i < 6; ++i) {
uint8_t *p = fb + (x + i) * DISPLAY_HEIGHT + y;
uint8_t mask = 0x01;
for (int j = 0; j < 8; ++j) {
if (*fnt & mask)
*p = col;
p++;
mask <<= 1;
}
fnt++;
}
}
static void printch4(int x, int y, int col, const uint8_t *fnt) {
for (int i = 0; i < 6 * 4; ++i) {
uint8_t *p = fb + (x + i) * DISPLAY_HEIGHT + y;
uint8_t mask = 0x01;
for (int j = 0; j < 8; ++j) {
for (int k = 0; k < 4; ++k) {
if (*fnt & mask)
*p = col;
p++;
}
mask <<= 1;
}
if ((i & 3) == 3)
fnt++;
}
}
void printicon(int x, int y, int col, const uint8_t *icon) {
int w = *icon++;
int h = *icon++;
int sz = *icon++;
uint8_t mask = 0x80;
int runlen = 0;
int runbit = 0;
uint8_t lastb = 0x00;
for (int i = 0; i < w; ++i) {
uint8_t *p = fb + (x + i) * DISPLAY_HEIGHT + y;
for (int j = 0; j < h; ++j) {
int c = 0;
if (mask != 0x80) {
if (lastb & mask)
c = 1;
mask <<= 1;
} else if (runlen) {
if (runbit)
c = 1;
runlen--;
} else {
if (sz-- <= 0)
panic(10);
lastb = *icon++;
if (lastb & 0x80) {
runlen = lastb & 63;
runbit = lastb & 0x40;
} else {
mask = 0x01;
}
--j;
continue; // restart
}
if (c)
*p = col;
p++;
}
}
}
void print(int x, int y, int col, const char *text) {
int x0 = x;
while (*text) {
char c = *text++;
if (c == '\r')
continue;
if (c == '\n') {
x = x0;
y += 10;
continue;
}
/*
if (x + 8 > DISPLAY_WIDTH) {
x = x0;
y += 10;
}
*/
if (c < ' ')
c = '?';
if (c >= 0x7f)
c = '?';
c -= ' ';
printch(x, y, col, &font8[c * 6]);
x += 6;
}
}
void print4(int x, int y, int col, const char *text) {
while (*text) {
char c = *text++;
c -= ' ';
printch4(x, y, col, &font8[c * 6]);
x += 6 * 4;
}
}
void draw_screen() {
if (lookupCfg(CFG_PIN_DISPLAY_SCK, 1000) == 1000)
return;
cmdBuf[0] = ST7735_RAMWR;
sendCmd(cmdBuf, 1);
SET_DC(1);
SET_CS(0);
uint8_t *p = fb;
for (int i = 0; i < DISPLAY_WIDTH; ++i) {
uint8_t cc[DISPLAY_HEIGHT * 2];
uint32_t dst = 0;
for (int j = 0; j < DISPLAY_HEIGHT; ++j) {
uint16_t color = palette[*p++ & 0xf];
cc[dst++] = color >> 8;
cc[dst++] = color & 0xff;
}
transfer(cc, sizeof(cc));
}
SET_CS(1);
}
void drawBar(int y, int h, int c) {
for (int x = 0; x < DISPLAY_WIDTH; ++x) {
memset(fb + x * DISPLAY_HEIGHT + y, c, h);
}
}
void draw_hf2() {
print4(20, 22, 5, "<-->");
print(40, 110, 7, "flashing...");
draw_screen();
}
void draw_drag() {
drawBar(0, 52, 7);
drawBar(52, 55, 8);
drawBar(107, 14, 4);
print4(108, 5, 1, "D5");
print(112, 40, 6, UF2_VERSION_BASE);
print(23, 110, 1, "arcade.makecode.com");
#define DRAG 70
#define DRAGX 10
printicon(DRAGX + 20, DRAG + 5, 1, fileLogo);
printicon(DRAGX + 66, DRAG, 1, arrowLogo);
printicon(DRAGX + 108, DRAG, 1, pendriveLogo);
print(10, DRAG - 12, 1, "arcade.uf2");
print(98, DRAG - 12, 1, "ARCADE-D5");
draw_screen();
}
void screen_early_init() {
setup_output_pin(CFG_PIN_DISPLAY_BL);
}
void screen_init() {
if (lookupCfg(CFG_PIN_DISPLAY_SCK, 1000) == 1000)
return;
setup_output_pin(CFG_PIN_DISPLAY_SCK);
setup_output_pin(CFG_PIN_DISPLAY_MOSI);
setup_output_pin(CFG_PIN_DISPLAY_BL);
setup_output_pin(CFG_PIN_DISPLAY_DC);
setup_output_pin(CFG_PIN_DISPLAY_RST);
setup_output_pin(CFG_PIN_DISPLAY_CS);
SET_CS(1);
SET_DC(1);
pin_set(CFG_PIN_DISPLAY_BL, 1);
pin_set(CFG_PIN_DISPLAY_RST, 0);
scr_delay(20);
pin_set(CFG_PIN_DISPLAY_RST, 1);
scr_delay(20);
sendCmdSeq(initCmds);
uint32_t cfg0 = CFG(DISPLAY_CFG0);
//uint32_t cfg2 = CFG(DISPLAY_CFG2);
uint32_t frmctr1 = CFG(DISPLAY_CFG1);
palXOR = (cfg0 & 0x1000000) ? 0xffffff : 0x000000;
uint32_t madctl = cfg0 & 0xff;
uint32_t offX = (cfg0 >> 8) & 0xff;
uint32_t offY = (cfg0 >> 16) & 0xff;
//uint32_t freq = (cfg2 & 0xff);
// DMESG("configure screen: FRMCTR1=%p MADCTL=%p SPI at %dMHz", frmctr1, madctl, freq);
configure(madctl, frmctr1);
setAddrWindow(offX, offY, CFG(DISPLAY_WIDTH), CFG(DISPLAY_HEIGHT));
memset(fb, 0, sizeof(fb));
}
#endif

View file

@ -47,15 +47,37 @@ void setBootProt(int v) {
fuses[0] = *((uint32_t *)NVM_FUSE_ADDR);
fuses[1] = *(((uint32_t *)NVM_FUSE_ADDR) + 1);
bool repair_fuses = false;
// Check for damaged fuses. If the NVM user page was accidentally erased, there
// will be 1's in wrong places. This would enable the watchdog timer and cause other
// problems. So check for all ones outside of the SAMD21/51 BOOTPROT fields, or all ones
// in fuses[1]. If it appears the fuses page was erased, replace fuses with reasonable values.
if ((fuses[0] & 0x03fffff0) == 0x03fffff0 || fuses[1] == 0xffffffff) {
repair_fuses = true;
// These canonical fuse values taken from working Adafruit SAMD21 and SAMD51 boards.
#ifdef SAMD21
fuses[0] = 0xD8E0C7FA;
fuses[1] = 0xFFFFFC5D;
#endif
#ifdef SAMD51
fuses[0] = 0xF69A9239;
fuses[1] = 0xAEECFF80;
#endif
}
uint32_t bootprot = (fuses[0] & NVMCTRL_FUSES_BOOTPROT_Msk) >> NVMCTRL_FUSES_BOOTPROT_Pos;
logval("repair_fuses", repair_fuses);
logval("fuse0", fuses[0]);
logval("fuse1", fuses[1]);
logval("bootprot", bootprot);
logval("needed", v);
if (bootprot == v)
// Don't write if nothing will be changed.
if (bootprot == v && !repair_fuses) {
return;
}
fuses[0] = (fuses[0] & ~NVMCTRL_FUSES_BOOTPROT_Msk) | (v << NVMCTRL_FUSES_BOOTPROT_Pos);
@ -102,14 +124,15 @@ int main(void) {
logmsg("Before main loop");
#ifdef SAMD21
setBootProt(7); // 0k
// Disable BOOTPROT while updating bootloader.
setBootProt(7); // 0k - See "Table 22-2 Boot Loader Size" in datasheet.
#endif
#ifdef SAMD51
// We only need to set the BOOTPROT once on the SAMD51. For updates, we can
// temporarily turn the protection off instead.
if (NVMCTRL->STATUS.bit.BOOTPROT != 13) {
setBootProt(13); // 16k
}
// setBootProt() will only write BOOTPROT if it is not already correct.
// setBootProt() will also fix the fuse values if they appear to be all ones.
setBootProt(13); // 16k. See "Table 25-10 Boot Loader Size" in datasheet.
exec_cmd(NVMCTRL_CTRLB_CMD_SBPDIS);
NVMCTRL->CTRLA.bit.CACHEDIS0 = true;
NVMCTRL->CTRLA.bit.CACHEDIS1 = true;
@ -155,6 +178,7 @@ int main(void) {
LED_MSC_OFF();
#ifdef SAMD21
// Re-enable BOOTPROT
setBootProt(2); // 8k
#endif
// For the SAMD51, the boot protection will automatically be re-enabled on

View file

@ -5,14 +5,14 @@ static uint32_t timerLow;
uint32_t timerHigh, resetHorizon;
void delay(uint32_t ms) {
// SAMD21 starts up at 1mhz by default.
#ifdef SAMD21
// SAMD21 starts up at 1mhz by default.
#ifdef SAMD21
ms <<= 8;
#endif
// SAMD51 starts up at 48mhz by default.
#ifdef SAMD51
#endif
// SAMD51 starts up at 48mhz by default.
#ifdef SAMD51
ms <<= 12;
#endif
#endif
for (int i = 1; i < ms; ++i) {
asm("nop");
}
@ -141,7 +141,9 @@ void led_signal() {
}
void led_init() {
#if defined(LED_PIN)
PINOP(LED_PIN, DIRSET);
#endif
LED_MSC_ON();
#if defined(BOARD_RGBLED_CLOCK_PIN)
@ -152,6 +154,11 @@ void led_init() {
// This won't work for neopixel, because we're running at 1MHz or thereabouts...
RGBLED_set_color(COLOR_LEAVE);
#endif
#if USE_SCREEN
// turn display backlight
screen_early_init();
#endif
}
#if defined(BOARD_RGBLED_CLOCK_PIN)