AnsweredAssumed Answered

STM32F415ZG FSMC example

Question asked by kamba.hugues on Apr 25, 2014
Hi all,

I would like to interface a NOR Flash using the FSMC. However I cannot find a tutorial how to compute ADDSET and DATAST.
I  found application note AN2784 but it is for STM32F10xxx. Also looking at the values and formulas provided in the NOR Flash example, it seems some calculation mistakes have been made, so it is unreliable.
The NOR Flash I will be interfacing is the SPANSION S29GL128S. Any help will be greatly appreciated.
If I use the formulas provided in AN2784, my results are as follows:
  // Configure then enable NOR Flash
  // tHCLK = 6 ns, tWC =  60 ns, tWP = 25 ns,
  // Formula 1: DATAST = tWP / HCLK = 25 / 6 ~= 4
  // Formula 2: ( (ADDSET + 1) + (DATAST + 1) ) × tHCLK = max (tWC)
  // so (ADDSET + 1) = 60 / 6 - ( 5 + 1 ) -> ADDSET = 4
However, using those values read wrong values (0s everywhere). When I use ADDSET = 0 and DATAST = 17 I get good readings. The reason I used 17 for DATAST is because the S29GL128S tACC is 100 ns and my tHCLK is 6, so 17 x 6 is 102..

Please help.

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    | PE2  <-> FSMC_A23   | PF2  <-> FSMC_A2 | PG2 <-> FSMC_A12  |
 | PD5  <-> FSMC_NWE    | PE3  <-> FSMC_A19   | PF3  <-> FSMC_A3 | PG3 <-> FSMC_A13  |
 | PD6  <-> FSMC_NWAIT  | PE4  <-> FSMC_A20   | PF4  <-> FSMC_A4 | PG4 <-> FSMC_A14  |
 | PD7  <-> FSMC_NE1    | PE5  <-> FSMC_A21   | PF5  <-> FSMC_A5 | PG5 <-> FSMC_A15  |
 | PD8  <-> FSMC_D13    | PE6  <-> FSMC_A22   | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2  |
 | PD9  <-> FSMC_D14    | PE7  <-> FSMC_D4    | PF13 <-> FSMC_A7 | PG10 <-> FSMC_NE3 |
 | PD10 <-> FSMC_D15    | PE8  <-> FSMC_D5    | PF14 <-> FSMC_A8 | PG12 <-> FSMC_NE4 |
 | PD11 <-> FSMC_A16    | PE9  <-> FSMC_D6    | PF15 <-> FSMC_A9 | PG13 <-> FSMC_A24 |
 | PD12 <-> FSMC_A17    | PE10 <-> FSMC_D7    |------------------+ PG14 <-> FSMC_A25 |
 | PD13 <-> FSMC_A18    | PE11 <-> FSMC_D8    |                  +-------------------+
 | PD14 <-> FSMC_D0     | PE12 <-> FSMC_D9    |
 | PD15 <-> FSMC_D1     | PE13 <-> FSMC_D10   |
 |                      | PE14 <-> FSMC_D11   |
 |                      | PE15 <-> FSMC_D12   |
 +---------------------+----------------------+--------------------+--------------------+
*/
 
  uint32_t DATAST;
  uint32_t ADDSET;
   
  // Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock
  RCC->AHB1ENR   = (RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN | RCC_AHB1ENR_GPIOGEN);
   
  // Connect PDx pins to FSMC Alternate function
  GPIOD->AFR[0]  = 0xcccc00cc;
  GPIOD->AFR[1]  = 0xcccccccc; 
  GPIOD->MODER   = 0xaaaaaa0a;                // Configure PDx pins in Alternate function mode 
  GPIOD->OSPEEDR = 0xaaaaaa0a;                // Configure PDx pins speed to 50 MHz  
  GPIOD->OTYPER  = 0x00000000;                // Configure PDx pins Output type to push-pull 
  GPIOD->PUPDR   = 0x00000000;                // No pull-up, pull-down for PDx pins
 
  // Connect PEx pins to FSMC Alternate function
  GPIOE->AFR[0]  = 0xcccccccc;
  GPIOE->AFR[1]  = 0xcccccccc; 
  GPIOE->MODER   = 0xaaaaaaaa;                  // Configure PEx pins in Alternate function mode   
  GPIOE->OSPEEDR = 0xaaaaaaaa;                  // Configure PEx pins speed to 50 MHz 
  GPIOE->OTYPER  = 0x00000000;                  // Configure PEx pins Output type to push-pull  
  GPIOE->PUPDR   = 0x00000000;                  // No pull-up, pull-down for PEx pins
 
  // Connect PFx pins to FSMC Alternate function
  GPIOF->AFR[0]  = 0x00cccccc;
  GPIOF->AFR[1]  = 0xcccc0000; 
  GPIOF->MODER   = 0xaa000aaa;                  // Configure PFx pins in Alternate function mode 
  GPIOF->OSPEEDR = 0xaa000aaa;                  // Configure PFx pins speed to 50 MHz  
  GPIOF->OTYPER  = 0x00000000;                  // Configure PFx pins Output type to push-pull  
  GPIOF->PUPDR   = 0x00000000;                  // No pull-up, pull-down for PFx pins
 
  // Connect PGx pins to FSMC Alternate function
  GPIOG->AFR[0]  = 0x00cccccc;
  GPIOG->AFR[1]  = 0x0ccc0cc0;
   
  GPIOG->MODER   = 0x2a280aaa;                  // Configure PGx pins in Alternate function mode  
  GPIOG->OSPEEDR = 0x2a280aaa;                  // Configure PGx pins speed to 50 MHz 
  GPIOG->OTYPER  = 0x00000000;                  // Configure PGx pins Output type to push-pull 
  GPIOG->PUPDR   = 0x00000000;                  // No pull-up, pull-down for PGx pins
   
//-- FSMC Configuration ------------------------------------------------------*/
  // Enable the FSMC interface clock
  RCC->AHB3ENR |= RCC_AHB3ENR_FSMCEN;
 
  //NE1 = CS0 = SRAM
  //NE2 = CS1 = FLASH
  //NE3 = CS2 = Not used
  //NE4 = CS3 = Ethernet
  //Note: HCLK cycle = 1/168MHz = 6 ns, use it to adjust memory transaction times
   
  // Configure then enable SRAM (Mode 1)
  // tHCLK = 6 ns, tWC = 10 ns, tPWE1 = 7 ns, tAA = 10 ns, tsu(Data_NE) = 10 ns, tv(A_NE) = 4.5 ns
  // Formula 1: DATAST = tPWE1 / tHCLK = 7 / 6 = 1
  // Formula 2: ( (ADDSET + 1) + (DATAST + 1) ) × tHCLK = max (tWC)
  // so (ADDSET + 1) = 10 / 6 - ( 1 + 1 ) -> ADDSET = 0
  // Verify with Formula 3 below
  // DATAST >= (tAA + tsu(Data_NE) + tv(A_NE))/tHCLK – ADDSET – 4   
  // ADDSET and DATAST should be set to 0 and 1 respectively according to the formula, however, it causes some reading inaccuracy at times.
  FSMC_Bank1->BCR1 = (FSMC_BCR1_WREN|FSMC_BCR1_RESERVED|FSMC_BCR1_MWID_0);
  ADDSET = 2;
  DATAST = 2;
  FSMC_Bank1->BTR1 = ADDSET | (DATAST<<8);
  FSMC_Bank1->BCR1 |= FSMC_BCR1_MBKEN;
   
  // Configure then enable NOR Flash
  // tHCLK = 6 ns, tWC =  60 ns, tWP = 25 ns, tAVQV = 100 ns, tsu(Data_NE) =  10 ns, tv(A_NE) = 4.5 ns
  // Formula 1: DATAST = tWP / HCLK = 25 / 6 ~= 4
  // Formula 2: ( (ADDSET + 1) + (DATAST + 1) ) × tHCLK = max (tWC)
  // so (ADDSET + 1) = 60 / 6 - ( 5 + 1 ) -> ADDSET = 4
  // Mode 2  
  FSMC_Bank1->BCR2 =  FSMC_BCR2_WREN|
                      /*FSMC_BCR2_WAITCFG|*/
                      FSMC_BCR2_RESERVED|
                      FSMC_BCR2_FACCEN|
                      FSMC_BCR2_MWID_0|
                      FSMC_BCR2_MTYP_1;     
  ADDSET = 4;
  DATAST = 4;          
  FSMC_Bank1->BTR2 = (ADDSET | (DATAST<<8)) ;
  FSMC_Bank1->BCR2 |= FSMC_BCR2_MBKEN;
     
  // Configure then enable Ethernet (Mode 1)
  FSMC_Bank1->BCR4 = (FSMC_BCR4_WREN|FSMC_BCR4_RESERVED|FSMC_BCR4_MWID_0);
  ADDSET = 0;
  DATAST = 8;             //48 ns, Ethernet max access time: 45 ns
  FSMC_Bank1->BTR4 = ADDSET | (DATAST<<8);
  FSMC_Bank1->BCR4 |= FSMC_BCR4_MBKEN; 
   
}

Outcomes