Skip to content

Commit

Permalink
Redo RP2040 flash settings
Browse files Browse the repository at this point in the history
This switches stage2 to C and uses Jinja to change the C code based
on flash settings from https://github.com/adafruit/nvm.toml. It
produces the fastest settings for the given set of external flashes.
Flash size is no longer hard coded so switching flashes with similar
capabilities but different sizes should *just work*.

This PR also places "ITCM" code in RAM to save the XIP cache for
code execution. Further optimization is possible. A blink code.py
still requires a number of flash fetches every blink.

Fixes adafruit#4041
  • Loading branch information
tannewt committed Mar 18, 2021
1 parent 2589515 commit 5d2b60c
Show file tree
Hide file tree
Showing 31 changed files with 411 additions and 65 deletions.
6 changes: 5 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,8 @@
url = https://github.com/adafruit/Adafruit_CircuitPython_LC709203F
[submodule "ports/raspberrypi/sdk"]
path = ports/raspberrypi/sdk
url = https://github.com/raspberrypi/pico-sdk.git
url = https://github.com/adafruit/pico-sdk.git
[submodule "data/nvm.toml"]
path = data/nvm.toml
url = https://github.com/adafruit/nvm.toml.git
branch = main
1 change: 1 addition & 0 deletions data/nvm.toml
Submodule nvm.toml added at da5054
16 changes: 11 additions & 5 deletions ports/raspberrypi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ INC += -I. \
-I$(BUILD)

# Pico specific configuration
CFLAGS += -DPICO_ON_DEVICE=1 -DPICO_NO_BINARY_INFO=0 -DPICO_TIME_DEFAULT_ALARM_POOL_DISABLED=1 -DPICO_DIVIDER_CALL_IDIV0=0 -DPICO_DIVIDER_CALL_LDIV0=0 -DPICO_DIVIDER_HARDWARE=1 -DPICO_DOUBLE_ROM=1 -DPICO_FLOAT_ROM=1 -DPICO_MULTICORE=1 -DPICO_BITS_IN_RAM=0 -DPICO_DIVIDER_IN_RAM=0 -DPICO_DOUBLE_PROPAGATE_NANS=0 -DPICO_DOUBLE_IN_RAM=0 -DPICO_MEM_IN_RAM=0 -DPICO_FLOAT_IN_RAM=0 -DPICO_FLOAT_PROPAGATE_NANS=1 -DPICO_NO_FLASH=0 -DPICO_COPY_TO_RAM=0 -DPICO_DISABLE_SHARED_IRQ_HANDLERS=0 -DPICO_NO_BI_BOOTSEL_VIA_DOUBLE_RESET=0
CFLAGS += -DRASPBERRYPI -DPICO_ON_DEVICE=1 -DPICO_NO_BINARY_INFO=0 -DPICO_TIME_DEFAULT_ALARM_POOL_DISABLED=1 -DPICO_DIVIDER_CALL_IDIV0=0 -DPICO_DIVIDER_CALL_LDIV0=0 -DPICO_DIVIDER_HARDWARE=1 -DPICO_DOUBLE_ROM=1 -DPICO_FLOAT_ROM=1 -DPICO_MULTICORE=1 -DPICO_BITS_IN_RAM=0 -DPICO_DIVIDER_IN_RAM=0 -DPICO_DOUBLE_PROPAGATE_NANS=0 -DPICO_DOUBLE_IN_RAM=0 -DPICO_MEM_IN_RAM=0 -DPICO_FLOAT_IN_RAM=0 -DPICO_FLOAT_PROPAGATE_NANS=1 -DPICO_NO_FLASH=0 -DPICO_COPY_TO_RAM=0 -DPICO_DISABLE_SHARED_IRQ_HANDLERS=0 -DPICO_NO_BI_BOOTSEL_VIA_DOUBLE_RESET=0
OPTIMIZATION_FLAGS ?= -O3
# TinyUSB defines
CFLAGS += -DTUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX=1 -DCFG_TUSB_MCU=OPT_MCU_RP2040 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
Expand Down Expand Up @@ -169,7 +169,7 @@ SRC_SDK := \
src/rp2_common/hardware_irq/irq.c \
src/rp2_common/hardware_pio/pio.c \
src/rp2_common/hardware_pll/pll.c \
src/rp2_common/hardware_rtc/rtc.c \
src/rp2_common/hardware_rtc/rtc.c \
src/rp2_common/hardware_spi/spi.c \
src/rp2_common/hardware_sync/sync.c \
src/rp2_common/hardware_timer/timer.c \
Expand Down Expand Up @@ -270,9 +270,15 @@ $(BUILD)/boot2.bin: $(BUILD)/boot2.elf
$(STEPECHO) "OBJCOPY $<"
$(Q)$(OBJCOPY) -O binary $< $@

$(BUILD)/boot2.elf: $(BOOT2_S_UPPER) | $(BUILD)/

$(BUILD)/stage2.c: stage2.c.jinja gen_stage2.py | $(BUILD)/
$(STEPECHO) "GEN $<"
$(Q)$(PYTHON3) gen_stage2.py $< $@ $(EXTERNAL_FLASH_DEVICES)

$(BUILD)/boot2.elf: $(BUILD)/stage2.c
$(STEPECHO) "BOOT $<"
$(Q)$(CC) $(CFLAGS) $(BOOT2_S_CFLAGS) -Isdk/src/rp2_common/boot_stage2/asminclude --specs=nosys.specs -nostartfiles -Wl,-T,sdk/src/rp2_common/boot_stage2/boot_stage2.ld -o $@ $<
$(Q)$(CC) $(CFLAGS) $(BOOT2_S_CFLAGS) -Os -ggdb3 -I. -fPIC --specs=nosys.specs -nostartfiles -Wl,-T,boot_stage2.ld -Wl,-Map=$@.map -o $@ $<
$(Q)$(SIZE) $@

SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)

Expand All @@ -285,7 +291,7 @@ $(BUILD)/firmware.elf: $(OBJ) link.ld

$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(STEPECHO) "Create $@"
$(Q)$(OBJCOPY) -O binary $^ $@
$(Q)$(OBJCOPY) -O binary -R .dtcm_bss $^ $@

$(BUILD)/firmware.uf2: $(BUILD)/firmware.bin
$(STEPECHO) "Create $@"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,3 @@

#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
#define DEFAULT_UART_BUS_TX (&pin_GPIO0)

// Flash chip is GD25Q64 connected over QSPI
#define TOTAL_FLASH_SIZE (8 * 1024 * 1024)
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ USB_MANUFACTURER = "Adafruit"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2

INTERNAL_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICES = "GD25Q64C"
2 changes: 0 additions & 2 deletions ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
#define DEFAULT_UART_BUS_TX (&pin_GPIO0)

#define TOTAL_FLASH_SIZE (2 * 1024 * 1024)

// These pins are unconnected
#define IGNORE_PIN_GPIO2 1
#define IGNORE_PIN_GPIO22 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ USB_MANUFACTURER = "Pimoroni"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2

INTERNAL_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICES = "W25Q16JV_IQ"

CIRCUITPY__EVE = 1
2 changes: 0 additions & 2 deletions ports/raspberrypi/boards/pimoroni_picosystem/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
#define DEFAULT_UART_BUS_TX (&pin_GPIO0)

#define TOTAL_FLASH_SIZE (16 * 1024 * 1024)

// These pins are unconnected
#define IGNORE_PIN_GPIO3 1
#define IGNORE_PIN_GPIO10 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ USB_MANUFACTURER = "Pimoroni"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2

INTERNAL_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICES = "W25Q128JV_IQ"

CIRCUITPY__EVE = 1
2 changes: 0 additions & 2 deletions ports/raspberrypi/boards/pimoroni_tiny2040/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

#define MICROPY_HW_USER_SW (&pin_GPIO23)

#define TOTAL_FLASH_SIZE (8 * 1024 * 1024)

// These pins are unconnected
#define IGNORE_PIN_GPIO8 1
#define IGNORE_PIN_GPIO9 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ USB_MANUFACTURER = "Pimoroni"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2

INTERNAL_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ"

CIRCUITPY__EVE = 1
3 changes: 0 additions & 3 deletions ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,3 @@

// #define DEFAULT_UART_BUS_RX (&pin_PA11)
// #define DEFAULT_UART_BUS_TX (&pin_PA10)

// Flash chip is GD25Q64 connected over QSPI
#define TOTAL_FLASH_SIZE (8 * 1024 * 1024)
2 changes: 1 addition & 1 deletion ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ USB_MANUFACTURER = "Adafruit"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2

INTERNAL_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICES = "W25Q32JV_IQ"
16 changes: 0 additions & 16 deletions ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,2 @@
// LEDs
// #define MICROPY_HW_LED_STATUS (&pin_PA17)

#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico"
#define MICROPY_HW_MCU_NAME "rp2040"

// #define DEFAULT_I2C_BUS_SCL (&pin_PA23)
// #define DEFAULT_I2C_BUS_SDA (&pin_PA22)

// #define DEFAULT_SPI_BUS_SCK (&pin_PB11)
// #define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
// #define DEFAULT_SPI_BUS_MISO (&pin_PA12)

// #define DEFAULT_UART_BUS_RX (&pin_PA11)
// #define DEFAULT_UART_BUS_TX (&pin_PA10)

// Flash chip is W25Q16JVUXIQ connected over QSPI
#define TOTAL_FLASH_SIZE (2 * 1024 * 1024)
4 changes: 1 addition & 3 deletions ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ USB_MANUFACTURER = "Raspberry Pi"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2

INTERNAL_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICES = "W25Q16JV_IQ"

CIRCUITPY__EVE = 1

BOOT2_S_UPPER = sdk/src/rp2_common/boot_stage2/boot2_w25q080.S
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,3 @@

#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
#define DEFAULT_UART_BUS_TX (&pin_GPIO0)

// Flash chip is GD25Q128 connected over QSPI
#define TOTAL_FLASH_SIZE (16 * 1024 * 1024)
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ USB_MANUFACTURER = "SparkFun"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2

INTERNAL_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICES = "W25Q128JV_IM"
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,3 @@

#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
#define DEFAULT_UART_BUS_TX (&pin_GPIO0)

// Flash chip is GD25Q128 connected over QSPI
#define TOTAL_FLASH_SIZE (16 * 1024 * 1024)
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ USB_MANUFACTURER = "SparkFun"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2

INTERNAL_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICES = "W25Q128JV_IM"
13 changes: 13 additions & 0 deletions ports/raspberrypi/boot_stage2.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
MEMORY {
/* We are loaded to the top 256 bytes of SRAM, which is above the bootrom
stack. Note 4 bytes occupied by checksum. */
SRAM(rx) : ORIGIN = 0x20041f00, LENGTH = 252
}

SECTIONS {
. = ORIGIN(SRAM);
.text : {
*(.entry.*)
*(.text.*)
} >SRAM
}
82 changes: 82 additions & 0 deletions ports/raspberrypi/gen_stage2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import sys
import cascadetoml
import pathlib
import typer
from jinja2 import Template


def main(input_template: pathlib.Path, output_path: pathlib.Path, skus: str = typer.Argument("")):
if ", " in skus:
skus = skus.split(", ")
else:
skus = [skus]
skus = ['sku="{}"'.format(f) for f in skus]
flashes = cascadetoml.filter_toml(pathlib.Path("../../data/nvm.toml"), skus)

if len(skus) == 0:
print("Set EXTERNAL_FLASH_DEVICES in mpconfigboard.mk with all possible flash skus")
raise typer.Exit(code=1)

def all_have(nvms, key):
for nvm in nvms:
if not nvm.get(key, False):
return False
return True

def all_match(nvms, key, default=None):
shared_value = nvms[0].get(key, default)
for nvm in nvms:
this_value = nvm.get(key, default)
if this_value != shared_value:
print(
"{}.{} = {} does not match {}".format(
nvm["sku"], key, this_value, shared_value
)
)
return None
return shared_value

quad_enable_status_byte = all_match(flashes["nvm"], "quad_enable_status_byte", 0)
quad_enable_bit_mask = all_match(flashes["nvm"], "quad_enable_bit_mask")
continuous_status_write = all_have(flashes["nvm"], "01_continuous_status_write")
split_status_write = all_have(flashes["nvm"], "write_status_register_split")
e7_quad_word_read = all_have(flashes["nvm"], "e7_quad_word_read")

quad_ok = quad_enable_status_byte is not None and quad_enable_bit_mask is not None

max_clock_speed_mhz = min((x.get("max_clock_speed_mhz", 1000) for x in flashes["nvm"]))

# Check that we have a consistent way to set quad enable.
if continuous_status_write is None and split_status_write is None:
print("quad not ok", continuous_status_write, split_status_write)
quad_ok = False

clock_divider = 4

read_command = 0x03
wait_cycles = 0
if quad_ok:
if e7_quad_word_read:
read_command = 0xE7
wait_cycles = 2
else:
read_command = 0xEB
wait_cycles = 4

flash_settings = {
"quad_ok": quad_ok,
"quad_enable_status_byte": quad_enable_status_byte,
"quad_enable_bit_mask": quad_enable_bit_mask,
"split_status_write": split_status_write,
"clock_divider": clock_divider,
"read_command": read_command,
"wait_cycles": wait_cycles,
}

template = Template(input_template.read_text())

output_path.write_text(template.render(flash_settings))


if __name__ == "__main__":
typer.run(main)
34 changes: 34 additions & 0 deletions ports/raspberrypi/link.ld
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,40 @@ SECTIONS
__data_end__ = .;
} > RAM AT> FLASH_FIRMWARE

.itcm :
{
. = ALIGN(4);
*(.itcm.*)

. = ALIGN(4);
} > RAM AT> FLASH_FIRMWARE
_ld_itcm_destination = ADDR(.itcm);
_ld_itcm_flash_copy = LOADADDR(.itcm);
_ld_itcm_size = SIZEOF(.itcm);

.dtcm_data :
{
. = ALIGN(4);

*(.dtcm_data.*)

. = ALIGN(4);
} > RAM AT> FLASH_FIRMWARE
_ld_dtcm_data_destination = ADDR(.dtcm_data);
_ld_dtcm_data_flash_copy = LOADADDR(.dtcm_data);
_ld_dtcm_data_size = SIZEOF(.dtcm_data);

.dtcm_bss :
{
. = ALIGN(4);

*(.dtcm_bss.*)

. = ALIGN(4);
} > RAM AT> RAM
_ld_dtcm_bss_start = ADDR(.dtcm_bss);
_ld_dtcm_bss_size = SIZEOF(.dtcm_bss);

.uninitialized_data (COPY): {
. = ALIGN(4);
*(.uninitialized_data*)
Expand Down
2 changes: 2 additions & 0 deletions ports/raspberrypi/mpconfigport.mk
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,5 @@ USB_SERIAL_NUMBER_LENGTH = 16

# Number of USB endpoint pairs.
USB_NUM_EP = 8

INTERNAL_FLASH_FILESYSTEM = 1
2 changes: 1 addition & 1 deletion ports/raspberrypi/sdk
Loading

0 comments on commit 5d2b60c

Please sign in to comment.