stm32 fsmc synchronous mode
http://www.silica.com/designers-community/forum/view/topic/fsmc_in_synchrnous_mode.html
with FSMC_CLK = 2 HCLK cycles, throughput for write is about 32MBytes/s.
# STM32F2 runs at 120 MHz
# FSMC CLK = 60 MHz
#
NET "FSMC_CLK" TNM_NET = FSMC_CLK;
TIMESPEC TS_FSMC_CLK = PERIOD "FSMC_CLK" 60 MHz HIGH 50%;
# PlanAhead Generated physical constraints
NET "FSMC_A[0]" LOC = J13;
NET "FSMC_A[1]" LOC = H13;
NET "FSMC_A[2]" LOC = H15;
NET "FSMC_A[3]" LOC = H14;
NET "FSMC_A[4]" LOC = G13;
NET "FSMC_A[5]" LOC = G14;
#NET "FSMC_A[6]" LOC = C17;
#NET "FSMC_A[7]" LOC = E16;
#NET "FSMC_A[8]" LOC = E18;
#NET "FSMC_A[9]" LOC = D17;
#NET "FSMC_A[10]" LOC = G16;
#NET "FSMC_A[11]" LOC = F14;
#NET "FSMC_A[12]" LOC = T18;
#NET "FSMC_A[13]" LOC = U18;
#NET "FSMC_A[14]" LOC = H12;
#NET "FSMC_A[15]" LOC = K16;
#NET "FSMC_A[16]" LOC = L17;
#NET "FSMC_A[17]" LOC = K18;
#NET "FSMC_A[18]" LOC = P18;
#NET "FSMC_A[19]" LOC = T17;
#NET "FSMC_A[20]" LOC = U17;
#NET "FSMC_A[21]" LOC = L13;
#NET "FSMC_A[22]" LOC = M13;
#NET "FSMC_A[23]" LOC = P16;
#NET "FSMC_A[24]" LOC = M16;
#NET "FSMC_A[25]" LOC = M18;
NET "FSMC_D[0]" LOC = N17;
NET "FSMC_D[1]" LOC = P17;
NET "FSMC_D[2]" LOC = L15;
NET "FSMC_D[3]" LOC = K13;
NET "FSMC_D[4]" LOC = F18;
NET "FSMC_D[5]" LOC = F17;
NET "FSMC_D[6]" LOC = F16;
NET "FSMC_D[7]" LOC = G18;
NET "FSMC_D[8]" LOC = F15;
NET "FSMC_D[9]" LOC = H18;
NET "FSMC_D[10]" LOC = H17;
NET "FSMC_D[11]" LOC = J16;
NET "FSMC_D[12]" LOC = J18;
NET "FSMC_D[13]" LOC = L18;
NET "FSMC_D[14]" LOC = K17;
NET "FSMC_D[15]" LOC = N18;
NET "FSMC_CLK" LOC = K15;
NET "FSMC_NBL[0]" LOC = N16 | PULLUP;
NET "FSMC_NBL[1]" LOC = P15 | PULLUP;
#NET "FSMC_NE[1]" LOC = L16 | PULLUP;
NET "FSMC_NE[2]" LOC = L12 | PULLUP;
#NET "FSMC_NE[3]" LOC = N15 | PULLUP;
#NET "FSMC_NE[4]" LOC = N14 | PULLUP;
NET "FSMC_NL" LOC = L14 | PULLUP;
NET "FSMC_NOE" LOC = H16 | PULLUP;
NET "FSMC_NWAIT" LOC = M14;
NET "FSMC_NWE" LOC = K12 | PULLUP;
# PlanAhead Generated IO constraints
NET "FSMC_A[*]" IOSTANDARD = LVCMOS33;
NET "FSMC_CLK" IOSTANDARD = LVCMOS33;
NET "FSMC_D[*]" IOSTANDARD = LVCMOS33 | SLEW = FAST;
NET "FSMC_NBL[0]" IOSTANDARD = LVCMOS33;
NET "FSMC_NBL[1]" IOSTANDARD = LVCMOS33;
NET "FSMC_NE[*]" IOSTANDARD = LVCMOS33;
NET "FSMC_NL" IOSTANDARD = LVCMOS33;
NET "FSMC_NOE" IOSTANDARD = LVCMOS33;
NET "FSMC_NWAIT" IOSTANDARD = LVCMOS33;
NET "FSMC_NWE" IOSTANDARD = LVCMOS33;
library IEEE; use IEEE.std_logic_1164.all; --use IEEE.numeric_std.all; use IEEE.std_logic_unsigned.all; use ieee.std_logic_arith.all; entity fsmc is port ( -- clk_25mhz : in STD_LOGIC; FSMC_A : in STD_LOGIC_VECTOR(5 downto 0); --25 FSMC_D : inout STD_LOGIC_VECTOR(15 downto 0); FSMC_NBL : in STD_LOGIC_VECTOR(1 downto 0); FSMC_NE : in STD_LOGIC_VECTOR(2 downto 2); -- 4 downto 1 FSMC_NL : in STD_LOGIC; FSMC_NOE : in STD_LOGIC; FSMC_NWAIT : out STD_LOGIC; FSMC_NWE : in STD_LOGIC; FSMC_CLK : in STD_LOGIC; ); end fsmc; architecture Behavioral of fsmc is constant memsize : integer := 6; -- 2^6 = 64 bytes signal NE : std_logic; signal ADDR : std_logic_vector ( memsize-1 downto 0); signal rdADDR : std_logic_vector ( memsize-1 downto 0); signal phase : integer range 0 to 32 := 0; signal FSMC_dout : std_logic_vector(15 downto 0); type memory_type is array (0 to ((2**memsize) - 1)) of std_logic_vector(7 downto 0); signal mbuf_hi : memory_type; signal mbuf_lo : memory_type; attribute ram_style : string; attribute ram_style of mbuf_hi : signal is "block"; attribute ram_style of mbuf_lo : signal is "block"; begin FSMC_NWAIT <= '1'; -- Wait states not used NE <= FSMC_NE(2); -- bank 2 chipselect LED <= "11"; --(not green) & (not red); FSMC_D <= FSMC_dout when FSMC_NOE = '0' else (others => 'Z'); process (FSMC_CLK) begin if (FSMC_CLK'event and FSMC_CLK = '1') then if (NE = '0') then if (FSMC_NL = '0') then -- access starts with NL (NADVL) low phase <= 0; else phase <= phase + 1; -- increment clock phase end if; if (FSMC_NL = '0') then -- access starts with NL (NADVL) low ADDR <= FSMC_A((memsize-1) downto 0); end if; if ((FSMC_NL = '1') and (FSMC_NWE = '0') and (phase > 1)) then if FSMC_NBL(1) = '0' then mbuf_hi(conv_integer(ADDR((memsize-1) downto 0))) <= FSMC_D(15 downto 8); end if; if FSMC_NBL(0) = '0' then mbuf_lo(conv_integer(ADDR((memsize-1) downto 0))) <= FSMC_D(7 downto 0); end if; ADDR <= ADDR + 1; end if; end if; end if; -- rising edge, WRITE if (FSMC_CLK'event and FSMC_CLK = '0') then if (phase = 0) then rdADDR <= ADDR; elsif (NE = '0') then FSMC_dout(15 downto 8) <= mbuf_hi(conv_integer(rdADDR((memsize-1) downto 0))); FSMC_dout(7 downto 0) <= mbuf_lo(conv_integer(rdADDR((memsize-1) downto 0))); if (FSMC_NOE = '0') then rdADDR <= rdADDR + 1; end if; end if; end if; -- falling edge, READ end process; end Behavioral;
void SystemInit_ExtMemCtl(void) { /*-- GPIOs Configuration -----------------------------------------------------*/ /* +-------------------+--------------------+------------------+------------------+ + SRAM pins assignment + +-------------------+--------------------+------------------+------------------+ | PD0 <-> FSMC_D2 | PE0 <-> FSMC_NBL0 | PF0 <-> FSMC_A0 | PG0 <-> FSMC_A10 | | PD1 <-> FSMC_D3 | PE1 <-> FSMC_NBL1 | PF1 <-> FSMC_A1 | PG1 <-> FSMC_A11 | | PD4 <-> FSMC_NOE | PE7 <-> FSMC_D4 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 | | PD5 <-> FSMC_NWE | PE8 <-> FSMC_D5 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 | | PD8 <-> FSMC_D13 | PE9 <-> FSMC_D6 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 | | PD9 <-> FSMC_D14 | PE10 <-> FSMC_D7 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 | | PD10 <-> FSMC_D15 | PE11 <-> FSMC_D8 | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 | | PD11 <-> FSMC_A16 | PE12 <-> FSMC_D9 | PF13 <-> FSMC_A7 |------------------+ | PD12 <-> FSMC_A17 | PE13 <-> FSMC_D10 | PF14 <-> FSMC_A8 | | PD14 <-> FSMC_D0 | PE14 <-> FSMC_D11 | PF15 <-> FSMC_A9 | | PD15 <-> FSMC_D1 | PE15 <-> FSMC_D12 |------------------+ +-------------------+--------------------+ PD3 <-> FSMC_CLK PD6 <-> FSMC_NWAIT PB7 <-> FSMC_NL (NADVL) */ /* Enable GPIOB, GPIOD, GPIOE, GPIOF and GPIOG interface clock */ RCC->AHB1ENR = 0x0000007a; // /78 /* Connect PBx pins to FSMC Alternate function */ GPIOB->AFR[0] = 0xc0000000; GPIOB->AFR[1] = 0x00000000; /* Configure PBx pins in Alternate function mode */ GPIOB->MODER = 0x00008000; /* Configure PBx pins speed to 100 MHz */ GPIOB->OSPEEDR = 0x0000c000; /* Configure PBX pins Output type to push-pull */ GPIOB->OTYPER = 0x00000000; /* No pull-up, pull-down for PBx pins */ GPIOB->PUPDR = 0x00000000; /* Connect PDx pins to FSMC Alternate function */ GPIOD->AFR[0] = 0x0cccc0cc; // 0x00cc00cc GPIOD->AFR[1] = 0xcc0ccccc; /* Configure PDx pins in Alternate function mode */ GPIOD->MODER = 0xa2aa2a8a; // 0xa2aa0a0a /* Configure PDx pins speed to 100 MHz */ GPIOD->OSPEEDR = 0xf3ff3fcf; // 0xf3fff0f0f /* Configure PDx pins Output type to push-pull */ GPIOD->OTYPER = 0x00000000; /* No pull-up, pull-down for PDx pins */ // PD6 NWAIT pullup GPIOD->PUPDR = 0x00001000; /* Connect PEx pins to FSMC Alternate function */ GPIOE->AFR[0] = 0xc00000cc; GPIOE->AFR[1] = 0xcccccccc; /* Configure PEx pins in Alternate function mode */ GPIOE->MODER = 0xaaaa800a; /* Configure PEx pins speed to 100 MHz */ GPIOE->OSPEEDR = 0xffffc00f; /* Configure PEx pins Output type to push-pull */ GPIOE->OTYPER = 0x00000000; /* No pull-up, pull-down for PEx pins */ GPIOE->PUPDR = 0x00000000; /* Connect PFx pins to FSMC Alternate function */ GPIOF->AFR[0] = 0x00cccccc; GPIOF->AFR[1] = 0xcccc0000; /* Configure PFx pins in Alternate function mode */ GPIOF->MODER = 0xaa000aaa; /* Configure PFx pins speed to 100 MHz */ GPIOF->OSPEEDR = 0xff000fff; /* Configure PFx pins Output type to push-pull */ GPIOF->OTYPER = 0x00000000; /* No pull-up, pull-down for PFx pins */ GPIOF->PUPDR = 0x00000000; /* Connect PGx pins to FSMC Alternate function */ GPIOG->AFR[0] = 0x00cccccc; GPIOG->AFR[1] = 0x000000c0; /* Configure PGx pins in Alternate function mode */ GPIOG->MODER = 0x00080aaa; /* Configure PGx pins speed to 100 MHz */ GPIOG->OSPEEDR = 0x000c0fff; /* Configure PGx pins Output type to push-pull */ GPIOG->OTYPER = 0x00000000; /* No pull-up, pull-down for PGx pins */ GPIOG->PUPDR = 0x00000000; /*-- FSMC Configuration ------------------------------------------------------*/ /* Enable the FSMC interface clock */ RCC->AHB3ENR = 0x00000001; /* Configure and enable Bank1_SRAM2 */ FSMC_Bank1->BTCR[2] = 0x00081115; // 0x00001015 // CBURSTRW = 1 // ACYCWAIT = 0 // EXTMOD = 0 // WAITEN = 0 // WREN = 1 // WAITCFG = 0 // WRAPMOD = 0 // WAITPOL = 0 // BURSTEN = 1 // FACCEN = 0 // MWID = 01 (16 bits) // MTYP = 01 (PSRAM) // MUXEN = 0 (Non-multiplexed) // MBKEN = 1 FSMC_Bank1->BTCR[3] = 0x00110400; // 0x00010400 // ACCMOD = 00 (Access mode A) // DATLAT = 0 (2 CLK cycles) // CLKDIV = 1 (2 HCLK periods) // BUSTURN = 1 (1 HCLK added) // DATAST = 4 (data phase 4 HCLK cycles) // ADDHLD = 0 (Reserved) // ADDSET = 0 (0 HCLK cycles) FSMC_Bank1E->BWTR[2] = 0x0fffffff; // BTCR 0 = BCR1 // BTCR 1 = BTR1 // BTCR 2 = BCR2 // BTCR 3 = BTR2 // BTCR 4 = BCR3 // BTCR 5 = BTR3 // BTCR 6 = BCR4 // BTCR 7 = BTR4 /* Bank1_SRAM2 is configured as follow: p.FSMC_AddressSetupTime = 0; p.FSMC_AddressHoldTime = 0; p.FSMC_DataSetupTime = 4; p.FSMC_BusTurnAroundDuration = 1; p.FSMC_CLKDivision = 0; p.FSMC_DataLatency = 0; p.FSMC_AccessMode = FSMC_AccessMode_A; FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2; FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM; FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p; */ }
Attached file contains function SystemInit_ExtMemCtl which i did modify.
Uncomment this line:
#define DATA_IN_ExtSRAM
I added following pins
PD3 <-> FSMC_CLK
PD6 <-> FSMC_NWAIT
PB7 <-> FSMC_NL (NADVL)
And then enabled CBURSTRW, BURSTEN, set CLKDIV=1