<libmaple/fsmc.h>

Flexible Static Memory Controller (FSMC) support. The FSMC peripheral is only available on some targets. Including this header on a target without an FSMC will cause a compilation error. Check your target’s documentation to determine if it’s available. You can also use STM32_HAVE_FSMC from <libmaple/stm32.h> to determine whether your target has an FSMC at build time.

All functionality documented here is portable.

Usage Note

FSMC support is fairly limited at this time. Current Leaflabs boards only use the FSMC to interface with external SRAM chips, so that’s what there’s the most support for (patches welcome!). Even for use with SRAM, you will still need to program some registers directly.

To use the FSMC with an SRAM chip, first call fsmc_sram_init_gpios() to configure its data, address, and control lines. Then, turn on the FSMC clock (by calling rcc_clk_enable(RCC_FSMC)). You can then configure the relevant fsmc_nor_psram_reg_map BCR register yourself for the SRAM chip you are using.

You can additionally use fsmc_nor_psram_set_datast() and fsmc_nor_psram_set_datast() to control read/write timing.

Devices

None at this time.

Functions

void fsmc_sram_init_gpios(void)

Configure FSMC GPIOs for use with SRAM.

static void fsmc_nor_psram_set_datast(fsmc_nor_psram_reg_map *regs, uint8 datast)

Set the DATAST bits in the given NOR/PSRAM register map’s chip-select timing register (FSMC_BTR).

Parameters
  • regs -

    NOR Flash/PSRAM register map whose chip-select timing register to set.

  • datast -

    Value to use for DATAST bits.

static void fsmc_nor_psram_set_addset(fsmc_nor_psram_reg_map *regs, uint8 addset)

Set the ADDHLD bits in the given NOR/PSRAM register map’s chip select timing register (FSMC_BTRx).

Parameters
  • regs -

    NOR Flash/PSRAM register map whose chip-select timing register to set.

  • addset -

    Value to use for ADDSET bits.

Register Maps

The general purpose register map type is fsmc_reg_map; its base pointer is FSMC_BASE. The fsmc_nor_psram_reg_map type is for use configuring the registers for an individual NOR/PSRAM region (FSMC_BCRx, FSMC_BTRx, and FSMC_BWTRx); the relevant base pointers are FSMC_NOR_PSRAM_REGION1 through FSMC_NOR_PSRAM_REGION4.

FSMC_BASE

FSMC register map base pointer.

FSMC_NOR_PSRAM1_BASE

FSMC NOR/PSRAM base pointer 1.

FSMC_NOR_PSRAM2_BASE

FSMC NOR/PSRAM base pointer 2.

FSMC_NOR_PSRAM3_BASE

FSMC NOR/PSRAM base pointer 3.

FSMC_NOR_PSRAM4_BASE

FSMC NOR/PSRAM base pointer 4.

struct fsmc_reg_map

FSMC register map type.

struct fsmc_nor_psram_reg_map

FSMC NOR/PSRAM register map type.

Memory Bank Boundary Addresses

Reading and writing data on an external memory chip using FSMC is done by reading and writing from addresses in special memory-mapped sections of the address space called memory banks.

This is convenient, since it implies that the usual load and store instructions used for I/O with the internal SRAM are also used to perform bus transactions with the external memory chip. (Which means you can use memcpy() etc. on external memory.)

Pointers to the memory banks’ base addresses are given by the following macros.

FSMC_BANK1

Void pointer to base address of FSMC memory bank 1 (NOR/PSRAM).

This bank is split into 4 regions. Each region supports interfacing with 1 NOR Flash, SRAM, or PSRAM chip. The base addresses of these regions are FSMC_NOR_PSRAM_REGIONx, for x = 1, 2, 3, 4.

FSMC_BANK2

Void pointer to base address of FSMC memory bank 2 (NAND Flash).

FSMC_BANK3

Void pointer to base address of FSMC memory bank 3 (NAND Flash).

FSMC_BANK4

Void pointer to base address of FSMC memory bank 4 (PC card devices).

FSMC_NOR_PSRAM_REGION1

Void pointer to base address of FSMC memory bank 1, region 1 (NOR/PSRAM).

FSMC_NOR_PSRAM_REGION2

Void pointer to base address of FSMC memory bank 1, region 2 (NOR/PSRAM).

FSMC_NOR_PSRAM_REGION3

Void pointer to base address of FSMC memory bank 1, region 3 (NOR/PSRAM).

FSMC_NOR_PSRAM_REGION4

Void pointer to base address of FSMC memory bank 1, region 4 (NOR/PSRAM).

Register Bit Definitions

These are given as source code.

/* NOR/PSRAM chip-select control registers */

#define FSMC_BCR_CBURSTRW_BIT           19
#define FSMC_BCR_ASYNCWAIT_BIT          15
#define FSMC_BCR_EXTMOD_BIT             14
#define FSMC_BCR_WAITEN_BIT             13
#define FSMC_BCR_WREN_BIT               12
#define FSMC_BCR_WAITCFG_BIT            11
#define FSMC_BCR_WRAPMOD_BIT            10
#define FSMC_BCR_WAITPOL_BIT            9
#define FSMC_BCR_BURSTEN_BIT            8
#define FSMC_BCR_FACCEN_BIT             6
#define FSMC_BCR_MUXEN_BIT              1
#define FSMC_BCR_MBKEN_BIT              0

#define FSMC_BCR_CBURSTRW               (1U << FSMC_BCR_CBURSTRW_BIT)
#define FSMC_BCR_ASYNCWAIT              (1U << FSMC_BCR_ASYNCWAIT_BIT)
#define FSMC_BCR_EXTMOD                 (1U << FSMC_BCR_EXTMOD_BIT)
#define FSMC_BCR_WAITEN                 (1U << FSMC_BCR_WAITEN_BIT)
#define FSMC_BCR_WREN                   (1U << FSMC_BCR_WREN_BIT)
#define FSMC_BCR_WAITCFG                (1U << FSMC_BCR_WAITCFG_BIT)
#define FSMC_BCR_WRAPMOD                (1U << FSMC_BCR_WRAPMOD_BIT)
#define FSMC_BCR_WAITPOL                (1U << FSMC_BCR_WAITPOL_BIT)
#define FSMC_BCR_BURSTEN                (1U << FSMC_BCR_BURSTEN_BIT)
#define FSMC_BCR_FACCEN                 (1U << FSMC_BCR_FACCEN_BIT)
#define FSMC_BCR_MWID                   (0x3 << 4)
#define FSMC_BCR_MWID_8BITS             (0x0 << 4)
#define FSMC_BCR_MWID_16BITS            (0x1 << 4)
#define FSMC_BCR_MTYP                   (0x3 << 2)
#define FSMC_BCR_MTYP_SRAM              (0x0 << 2)
#define FSMC_BCR_MTYP_PSRAM             (0x1 << 2)
#define FSMC_BCR_MTYP_NOR_FLASH         (0x2 << 2)
#define FSMC_BCR_MUXEN                  (1U << FSMC_BCR_MUXEN_BIT)
#define FSMC_BCR_MBKEN                  (1U << FSMC_BCR_MBKEN_BIT)

/* SRAM/NOR-Flash chip-select timing registers */

#define FSMC_BTR_ACCMOD                 (0x3 << 28)
#define FSMC_BTR_ACCMOD_A               (0x0 << 28)
#define FSMC_BTR_ACCMOD_B               (0x1 << 28)
#define FSMC_BTR_ACCMOD_C               (0x2 << 28)
#define FSMC_BTR_ACCMOD_D               (0x3 << 28)
#define FSMC_BTR_DATLAT                 (0xF << 24)
#define FSMC_BTR_CLKDIV                 (0xF << 20)
#define FSMC_BTR_BUSTURN                (0xF << 16)
#define FSMC_BTR_DATAST                 (0xFF << 8)
#define FSMC_BTR_ADDHLD                 (0xF << 4)
#define FSMC_BTR_ADDSET                 0xF

/* SRAM/NOR-Flash write timing registers */

#define FSMC_BWTR_ACCMOD                 (0x3 << 28)
#define FSMC_BWTR_ACCMOD_A               (0x0 << 28)
#define FSMC_BWTR_ACCMOD_B               (0x1 << 28)
#define FSMC_BWTR_ACCMOD_C               (0x2 << 28)
#define FSMC_BWTR_ACCMOD_D               (0x3 << 28)
#define FSMC_BWTR_DATLAT                 (0xF << 24)
#define FSMC_BWTR_CLKDIV                 (0xF << 20)
#define FSMC_BWTR_DATAST                 (0xFF << 8)
#define FSMC_BWTR_ADDHLD                 (0xF << 4)
#define FSMC_BWTR_ADDSET                 0xF

/* NAND Flash/PC Card controller registers */

#define FSMC_PCR_ECCEN_BIT               6
#define FSMC_PCR_PTYP_BIT                3
#define FSMC_PCR_PBKEN_BIT               2
#define FSMC_PCR_PWAITEN_BIT             1

#define FSMC_PCR_ECCPS                   (0x7 << 17)
#define FSMC_PCR_ECCPS_256B              (0x0 << 17)
#define FSMC_PCR_ECCPS_512B              (0x1 << 17)
#define FSMC_PCR_ECCPS_1024B             (0x2 << 17)
#define FSMC_PCR_ECCPS_2048B             (0x3 << 17)
#define FSMC_PCR_ECCPS_4096B             (0x4 << 17)
#define FSMC_PCR_ECCPS_8192B             (0x5 << 17)
#define FSMC_PCR_TAR                     (0xF << 13)
#define FSMC_PCR_TCLR                    (0xF << 9)
#define FSMC_PCR_ECCEN                   (1U << FSMC_PCR_ECCEN_BIT)
#define FSMC_PCR_PWID                    (0x3 << 4)
#define FSMC_PCR_PWID_8BITS              (0x0 << 4)
#define FSMC_PCR_PWID_16BITS             (0x1 << 4)
#define FSMC_PCR_PTYP                    (1U << FSMC_PCR_PTYP_BIT)
#define FSMC_PCR_PTYP_PC_CF_PCMCIA       (0x0 << FSMC_PCR_PTYP_BIT)
#define FSMC_PCR_PTYP_NAND               (0x1 << FSMC_PCR_PTYP_BIT)
#define FSMC_PCR_PBKEN                   (1U << FSMC_PCR_PBKEN_BIT)
#define FSMC_PCR_PWAITEN                 (1U << FSMC_PCR_PWAITEN_BIT)

/* FIFO status and interrupt registers */

#define FSMC_SR_FEMPT_BIT                6
#define FSMC_SR_IFEN_BIT                 5
#define FSMC_SR_ILEN_BIT                 4
#define FSMC_SR_IREN_BIT                 3
#define FSMC_SR_IFS_BIT                  2
#define FSMC_SR_ILS_BIT                  1
#define FSMC_SR_IRS_BIT                  0

#define FSMC_SR_FEMPT                    (1U << FSMC_SR_FEMPT_BIT)
#define FSMC_SR_IFEN                     (1U << FSMC_SR_IFEN_BIT)
#define FSMC_SR_ILEN                     (1U << FSMC_SR_ILEN_BIT)
#define FSMC_SR_IREN                     (1U << FSMC_SR_IREN_BIT)
#define FSMC_SR_IFS                      (1U << FSMC_SR_IFS_BIT)
#define FSMC_SR_ILS                      (1U << FSMC_SR_ILS_BIT)
#define FSMC_SR_IRS                      (1U << FSMC_SR_IRS_BIT)

/* Common memory space timing registers */

#define FSMC_PMEM_MEMHIZ                 (0xFF << 24)
#define FSMC_PMEM_MEMHOLD                (0xFF << 16)
#define FSMC_PMEM_MEMWAIT                (0xFF << 8)
#define FSMC_PMEM_MEMSET                 0xFF

/* Attribute memory space timing registers */

#define FSMC_PATT_ATTHIZ                 (0xFF << 24)
#define FSMC_PATT_ATTHOLD                (0xFF << 16)
#define FSMC_PATT_ATTWAIT                (0xFF << 8)
#define FSMC_PATT_ATTSET                 0xFF

/* I/O space timing register 4 */

#define FSMC_PIO_IOHIZ                  (0xFF << 24)
#define FSMC_PIO_IOHOLD                 (0xFF << 16)
#define FSMC_PIO_IOWAIT                 (0xFF << 8)
#define FSMC_PIO_IOSET                  0xF