STM32 FMC - netx 90 DPM interface

Q

How to connect the parallel memory interface - FMC - of a STM32 Microcontroller to the paralell DPM (Dual Port Memory) of netX 90?

A

Notes

  • Usage of SDRAM on netX 90 is not possible when a parallel DPM connection to an external host is used.
    Some Hilscher LFWs (Loadable Firmware) require external SDRAM and can not be used when a parallel DPM connection to an external host is used.
    These are IoT LFWs (e.g. PROFINET + OPC UA) and future LFWs with security functionality.
    Use case C cannot be used since it requires external SDRAM

  • STM32 FMC always use word addresssing, netX 90 DPM requires byte addressing.
    Therfore the address signals must be shifted in hardware → FMC_A0:DPM_A1, FMC_A1:DPM_A2, etc.
    DPM_A0 must be connected to byte enable FMC_NBL0

    (warning) Although netX DPM allows address shifting by configuration (dpm_if_cfg Bit 15 addr_sh  =0 byte address, 1=word address)
    it is not usable. In this mode (dpm_if_cfg Bit 15 = 1), no byte enable can be used and only whole words must be written.
    This does not meet the requirements of the Hilscher DPM access.
  • STM32 FMC extended mode must be enabled
    configure Mode A -> FMC_NOE (netX_90_RD) toggles back to inactive during address change
    netX DPM RD signal requires to be inactive -> tRDI (Read inter access idle time ) min 12.5nsec

    (warning) Mode 1 does not work, since FMC_NOE (netX_90_RD) does not become inactive during address change, 


STMCubeMX project

  • 16bit none-mux: ETH-MC-FMC.ioc
  • only the FMC related part of the *.ioc file is relevant
FMC config
/* FMC initialization function */
void initFMC(void)
{
  FMC_NORSRAM_TimingTypeDef Timing = {0};
  FMC_NORSRAM_TimingTypeDef ExtTiming = {0};

  /** Perform the SRAM1 memory initialization sequence
  */
  hsram1.Instance = FMC_NORSRAM_DEVICE;
  hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
  /* hsram1.Init */
  hsram1.Init.NSBank = FMC_NORSRAM_BANK1;
  hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
  hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
  hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
  //hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;
  hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
  hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
  hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
  hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
  hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
  hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_ENABLE;
  hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
  hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
  hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
  hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
  hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
  /* Timing */
  Timing.AddressSetupTime = 15;
  Timing.AddressHoldTime = 15;
  Timing.DataSetupTime = 255;
  Timing.BusTurnAroundDuration = 15;
  Timing.CLKDivision = 16;
  Timing.DataLatency = 17;
  Timing.AccessMode = FMC_ACCESS_MODE_A;
  /* ExtTiming */
  ExtTiming.AddressSetupTime = 15;
  ExtTiming.AddressHoldTime = 15;
  ExtTiming.DataSetupTime = 255;
  ExtTiming.BusTurnAroundDuration = 15;
  ExtTiming.CLKDivision = 16;
  ExtTiming.DataLatency = 17;
  ExtTiming.AccessMode = FMC_ACCESS_MODE_A;

  if (HAL_SRAM_Init(&hsram1, &Timing, &ExtTiming) != HAL_OK){
    Error_Handler( );
  }

}
GPIO configuration
  /* Peripheral clock enable */
  __HAL_RCC_FMC_CLK_ENABLE();
  
  /** FMC GPIO Configuration  
  PF0   ------> FMC_A0
  PF1   ------> FMC_A1
  PF2   ------> FMC_A2
  PF3   ------> FMC_A3
  PF4   ------> FMC_A4
  PF5   ------> FMC_A5
  PF12   ------> FMC_A6
  PF13   ------> FMC_A7
  PF14   ------> FMC_A8
  PF15   ------> FMC_A9
  PG0   ------> FMC_A10
  PG1   ------> FMC_A11
  PE7   ------> FMC_D4
  PE8   ------> FMC_D5
  PE9   ------> FMC_D6
  PE10   ------> FMC_D7
  PE11   ------> FMC_D8
  PE12   ------> FMC_D9
  PE13   ------> FMC_D10
  PE14   ------> FMC_D11
  PE15   ------> FMC_D12
  PD8   ------> FMC_D13
  PD9   ------> FMC_D14
  PD10   ------> FMC_D15
  PD14   ------> FMC_D0
  PD15   ------> FMC_D1
  PG2   ------> FMC_A12
  PG3   ------> FMC_A13
  PG4   ------> FMC_A14
  PC7   ------> FMC_NE1
  PD0   ------> FMC_D2
  PD1   ------> FMC_D3
  PD4   ------> FMC_NOE
  PD5   ------> FMC_NWE
  */
  /* GPIO_InitStruct */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13 
                          |GPIO_PIN_14|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;

  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);


Hilscher HW config

16bit none-mux

Hardware Connection

16bit none-mux

STM32F767ZI pinSTM32 FMC signalnetx 90 pin
PE0FMC_NBL0DPM_A0
PF0FMC_A0DPM_A1
PF1FMC_A1DPM_A2
PF2FMC_A2DPM_A3
PF3FMC_A3DPM_A4
PF4FMC_A4DPM_A5
PF5FMC_A5DPM_A6
PF12FMC_A6DPM_A7
PF13FMC_A7DPM_A8
PF14FMC_A8DPM_A9
PF15FMC_A9DPM_A10
PG0FMC_A10DPM_A11
PG1FMC_A11DPM_A12
PG2FMC_A12DPM_A13
PG3FMC_A13DPM_A14



PD14FMC_D0DPM_D0
PD15FMC_D1DPM_D1
PD0FMC_D2DPM_D2
PD1FMC_D3DPM_D3
PE7FMC_D4DPM_D4
PE8FMC_D5DPM_D5
PE9FMC_D6DPM_D6
PE10FMC_D7DPM_D7
PE11FMC_D8DPM_D8
PE12FMC_D9DPM_D9
PE13FMC_D10DPM_D10
PE14FMC_D11DPM_D11
PE15FMC_D12DPM_D12
PD8FMC_D13DPM_D13
PD9FMC_D14DPM_D14
PD10FMC_D15DPM_D15



PC7FMC_NE1DPM_CS
PD4FMC_NOEDPM_RDn
PD5FMC_NWEDPM_WRn
PE1FMC_NBL1DPM_BHEN
PC6FMC_NWAITDPM_RDY
any external IRQ capable port

DPM_DIRQ


8bit none-mux

STM32F767ZI pinSTM32 FMC signalnetx 90 pin
PF0FMC_A0DPM_A0
PF1FMC_A1DPM_A1
PF2FMC_A2DPM_A2
PF3FMC_A3DPM_A3
PF4FMC_A4DPM_A4
PF5FMC_A5DPM_A5
PF12FMC_A6DPM_A6
PF13FMC_A7DPM_A7
PF14FMC_A8DPM_A8
PF15FMC_A9DPM_A9
PG0FMC_A10DPM_A10
PG1FMC_A11DPM_A11
PG2FMC_A12DPM_A12
PG3FMC_A13DPM_A13
PG4FMC_A14DPM_A14



PD14FMC_D0DPM_D0
PD15FMC_D1DPM_D1
PD0FMC_D2DPM_D2
PD1FMC_D3DPM_D3
PE7FMC_D4DPM_D4
PE8FMC_D5DPM_D5
PE9FMC_D6DPM_D6
PE10FMC_D7DPM_D7



PC7FMC_NE1DPM_CS
PD4FMC_NOEDPM_RDn
PD5FMC_NWEDPM_WRn
PC6FMC_NWAITDPM_RDY
any external IRQ capable port

DPM_DIRQ