Skip to content
Permalink
Browse files

stm32/boards/STM32F769DISC: Use external QSPI flash to store some code.

This demonstrates how to use external QSPI flash in XIP (execute in place)
mode.  The default configuration has all extmod/ code placed into external
QSPI flash, but other code can easily be put there by modifying the custom
f769_qspi.ld script.
  • Loading branch information...
dpgeorge committed Mar 4, 2019
1 parent c8bbf2c commit 84479569de7db32ddc9bfb48c0e3a31b605a8638
@@ -0,0 +1,20 @@
#include "drivers/memory/spiflash.h"
#include "qspi.h"

// This configuration is needed for mboot to be able to write to the external QSPI flash

const mp_spiflash_config_t spiflash_config = {
.bus_kind = MP_SPIFLASH_BUS_QSPI,
.bus.u_qspi.data = NULL,
.bus.u_qspi.proto = &qspi_proto,
.cache = NULL,
};

mp_spiflash_t spiflash_instance;

// This init function is needed to memory map the QSPI flash early in the boot process

void board_early_init(void) {
qspi_init();
qspi_memory_map();
}
@@ -0,0 +1,108 @@
/*
Custom linker script for STM32F769DISC board with external memory-mapped QSPI flash

Memory layout:

FLASH_QSPI .text_qspi

FLASH_APP .isr_vector
FLASH_APP .text
FLASH_APP .data

RAM .data
RAM .bss
RAM .heap
RAM .stack
*/

MEMORY
{
FLASH_APP (rx) : ORIGIN = 0x08020000, LENGTH = 2016K /* sectors 1-11 3x32K 1*128K 7*256K */
FLASH_QSPI (rx) : ORIGIN = 0x90000000, LENGTH = 64M /* external QSPI flash in XIP mode */
DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* Used for storage cache */
RAM (xrw) : ORIGIN = 0x20020000, LENGTH = 384K /* SRAM1 = 368K, SRAM2 = 16K */
}

/* Produce a link error if there is not this amount of RAM for these sections */
_minimum_stack_size = 2K;
_minimum_heap_size = 16K;

/* Define tho top end of the stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);

/* RAM extents for the garbage collector */
_ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = _ebss; /* heap starts just after statically allocated memory */
_heap_end = 0x20078000; /* tunable */

ENTRY(Reset_Handler)

SECTIONS
{
/* Define the code that goes in QSPI flash */
.text_qspi :
{
. = ALIGN(4);
*extmod/*(.text* .rodata*)
. = ALIGN(4);
} >FLASH_QSPI

/* The startup code goes first into main flash */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH_APP

/* The program code and other data goes into flash */
.text :
{
. = ALIGN(4);
*(.text*)
*(.rodata*)
. = ALIGN(4);
_etext = .;
} >FLASH_APP

/* Used by the startup to initialize data */
_sidata = LOADADDR(.data);

/* The initialized data section */
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data*)
. = ALIGN(4);
_edata = .;
} >RAM AT> FLASH_APP

/* The uninitialized (zeroed) data section */
.bss :
{
. = ALIGN(4);
_sbss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >RAM

/* Define the start of the heap, and make sure we have a minimum size */
.heap :
{
. = ALIGN(4);
. = . + _minimum_heap_size;
. = ALIGN(4);
} >RAM

/* Just checks there is enough RAM for the stack */
.stack :
{
. = ALIGN(4);
. = . + _minimum_stack_size;
. = ALIGN(4);
} >RAM
}
@@ -14,6 +14,9 @@
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_USB (1)

#define MICROPY_BOARD_EARLY_INIT board_early_init
void board_early_init(void);

// HSE is 25MHz
// VCOClock = HSE * PLLN / PLLM = 25 MHz * 432 / 25 = 432 MHz
// SYSCLK = VCOClock / PLLP = 432 MHz / 2 = 216 MHz
@@ -25,6 +28,15 @@

#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_7 // 210-216 MHz needs 7 wait states

// 512MBit external QSPI flash, to be memory mapped
#define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (29)
#define MICROPY_HW_QSPIFLASH_CS (pin_B6)
#define MICROPY_HW_QSPIFLASH_SCK (pin_B2)
#define MICROPY_HW_QSPIFLASH_IO0 (pin_C9)
#define MICROPY_HW_QSPIFLASH_IO1 (pin_C10)
#define MICROPY_HW_QSPIFLASH_IO2 (pin_E2)
#define MICROPY_HW_QSPIFLASH_IO3 (pin_D13)

// UART config
#define MICROPY_HW_UART1_TX (pin_A9)
#define MICROPY_HW_UART1_RX (pin_A10)
@@ -177,3 +189,16 @@
#define MICROPY_HW_FMC_D30 (pyb_pin_FMC_D30)
#define MICROPY_HW_FMC_D31 (pyb_pin_FMC_D31)
#endif

/******************************************************************************/
// Bootloader configuration

// Give Mboot access to the external QSPI flash
extern const struct _mp_spiflash_config_t spiflash_config;
extern struct _mp_spiflash_t spiflash_instance;
#define MBOOT_SPIFLASH_ADDR (0x90000000)
#define MBOOT_SPIFLASH_BYTE_SIZE (512 * 128 * 1024)
#define MBOOT_SPIFLASH_LAYOUT "/0x90000000/512*128Kg"
#define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (128 / 4) // 128k page, 4k erase block
#define MBOOT_SPIFLASH_CONFIG (&spiflash_config)
#define MBOOT_SPIFLASH_SPIFLASH (&spiflash_instance)
@@ -1,18 +1,38 @@
# By default this board is configured to use mboot which must be deployed first
USE_MBOOT ?= 1

# By default this board puts some code into external QSPI flash set in XIP mode
# USE_MBOOT must be enabled; see f769_qspi.ld for code that goes in QSPI flash
USE_QSPI ?= 1

# MCU settings
MCU_SERIES = f7
CMSIS_MCU = STM32F769xx
MICROPY_FLOAT_IMPL = double
AF_FILE = boards/stm32f767_af.csv

ifeq ($(USE_MBOOT),1)
# When using Mboot all the text goes together after the filesystem
ifeq ($(USE_QSPI),1)

# When using Mboot and QSPI the text is split between internal and external flash
LD_FILES = boards/STM32F769DISC/f769_qspi.ld
TEXT0_ADDR = 0x08020000
TEXT1_ADDR = 0x90000000
TEXT0_SECTIONS = .isr_vector .text .data
TEXT1_SECTIONS = .text_qspi

else

# When using Mboot but not QSPI all the text goes together after the filesystem
LD_FILES = boards/stm32f769.ld boards/common_blifs.ld
TEXT0_ADDR = 0x08020000

endif
else

# When not using Mboot the ISR text goes first, then the rest after the filesystem
LD_FILES = boards/stm32f769.ld boards/common_ifs.ld
TEXT0_ADDR = 0x08000000
TEXT1_ADDR = 0x08020000

endif
@@ -69,6 +69,12 @@ UART5_TX,PC12
UART5_RX,PD2
CAN2_TX,PB13
CAN2_RX,PB12
QSPI_CS,PB6
QSPI_CLK,PB2
QSPI_D0,PC9
QSPI_D1,PC10
QSPI_D2,PE2
QSPI_D3,PD13
ETH_REF_CLK,PA1
ETH_MDIO,PA2
ETH_CRS_DV,PA7

0 comments on commit 8447956

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.