niedziela, 2 lipca 2017

[2] STM32F429I - Discovery - SDRAM ISSI IS42S16400, CubeMx

Ten post chciałbym poświęcić na opisanie sposobu generacji oraz wykonania projektu, w oparciu o biblioteki hala oraz środowisko CubeMx w celu przygotowania projektu obsługującego pamieć SDRAM ISSI IS42S16400.

Cube Mx:


Poniżej przedstawię sposób wykonania projektu dla pamięci SDRAM w programie CubeMx.



Podłączenie pamięci na płytce SDRAM jest następujące:


  • FMC SDCKE1 - PB5;
  • FMC SDNE1 - PB6;
  • FMC SDNWE - PC0;
  • FMC D2 - PD0;
  • FMC D3 - PD1;
  • FMC D13 - PD8;
  • FMC D14 - PD9;
  • FMC D15 - PD10;
  • FMC D0 - PD14;
  • FMC D1 - PD15;
  • FMC NBL0 - PE0;
  • FMC NBL1 - PE1;
  • FMC D4 - PE7;
  • FMC D5 - PE8;
  • FMC D6 - PE9;
  • FMC D7 - PE10;
  • FMC D8 - PE11;
  • FMC D9 - PE12;
  • FMC D10 - PE13;
  • FMC D11 - PE14;
  • FMC D12 - PE15;
  • FMC A0 - PF0;
  • FMC A1 - PF1;
  • FMC A2 - PF2;
  • FMC A3 - PF3;
  • FMC A4 - PF4;
  • FMC A5 - PF5;
  • FMC SDNRAS - PF11;
  • FMC A6 - PF12;
  • FMC A7 - PF13;
  • FMC A8 - PF14;
  • FMC A9 - PF15;
  • FMC A10 - PG0;
  • FMC A11 - PG1;
  • FMC BA0 - PG4;
  • FMC BA1 - PG5;
  • FMC SDCLK - PG8;
  • FMC SDNCAS - PG15;


Konfiguracja FMC w pinout wygląda następująco:


Konfiguracja zegara wygląda następująco:


Ustawienie FMC w głównej konfiguracji prezentuje się następująco:


Programowanie:


Funkcja uruchamiająca zegary, wygląda następująco:

  1. static void SystemClock_Config(void)
  2. {
  3.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  4.   RCC_OscInitTypeDef RCC_OscInitStruct;
  5.   /* Enable Power Control clock */
  6.   __HAL_RCC_PWR_CLK_ENABLE();
  7.   /* The voltage scaling allows optimizing the power consumption when the device is
  8.      clocked below the maximum system frequency, to update the voltage scaling value
  9.      regarding system frequency refer to product datasheet.  */
  10.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  11.   /* Enable HSE Oscillator and activate PLL with HSE as source */
  12.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  13.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  14.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  15.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  16.   RCC_OscInitStruct.PLL.PLLM = 8;
  17.   RCC_OscInitStruct.PLL.PLLN = 360;
  18.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  19.   RCC_OscInitStruct.PLL.PLLQ = 7;
  20.   HAL_RCC_OscConfig(&RCC_OscInitStruct);
  21.   /* Activate the Over-Drive mode */
  22.   HAL_PWREx_EnableOverDrive();
  23.   /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
  24.      clocks dividers */
  25.   RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  26.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  27.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  28.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;  
  29.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;  
  30.   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
  31. }

Procedura inicjalizacyjna przygotowana w programie Cube Mx wygląda następująco:

  1. uint8_t SDRAM_Init(void)
  2. {
  3.     static uint8_t initialized = 0;
  4.    
  5.     /* SDRAM handler declaration */
  6.     SDRAM_HandleTypeDef hsdram;
  7.     FMC_SDRAM_TimingTypeDef SDRAM_Timing;
  8.     FMC_SDRAM_CommandTypeDef command;
  9.     /* If it is already initialized */
  10.     if (initialized) { return 1; }
  11.    
  12.     /* Set instance */
  13.     hsdram.Instance = FMC_SDRAM_DEVICE;
  14.    
  15.     /* Init pins of FMC controler */
  16.     SDRAM_InitPins();
  17.    
  18.     /* Enable FMC clock */
  19.     __HAL_RCC_FMC_CLK_ENABLE();
  20.    
  21.     /* Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) */
  22.     /* TMRD: 2 Clock cycles */
  23.     SDRAM_Timing.LoadToActiveDelay    = 2;          /* 1 clock cycle = 1 / 90MHz = 11.1ns */
  24.     SDRAM_Timing.ExitSelfRefreshDelay = 7;          /* TXSR: min=70ns (6x11.10ns) */
  25.     SDRAM_Timing.SelfRefreshTime      = 4;          /* TRAS: min=42ns (4x11.10ns) max=120k (ns) */
  26.     SDRAM_Timing.RowCycleDelay        = 7;          /* TRC:  min=70 (6x11.10ns) */
  27.     SDRAM_Timing.WriteRecoveryTime    = 2;          /* TWR:  2 Cycles */  
  28.     SDRAM_Timing.RPDelay              = 2;          /* TRP:  20ns => 2x11.10ns */
  29.     SDRAM_Timing.RCDDelay             = 2;          /* TRCD: 20ns => 2x11.10ns */
  30.    
  31.    
  32.     /* FMC SDRAM control configuration */
  33.     hsdram.Init.SDBank             = FMC_SDRAM_BANK2;
  34.     hsdram.Init.ColumnBitsNumber   = FMC_SDRAM_COLUMN_BITS_NUM_8;
  35.     hsdram.Init.RowBitsNumber      = FMC_SDRAM_ROW_BITS_NUM_12;
  36.     hsdram.Init.MemoryDataWidth    = FMC_SDRAM_MEM_BUS_WIDTH_16;
  37.     hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
  38.     hsdram.Init.CASLatency         = FMC_SDRAM_CAS_LATENCY_3;
  39.     hsdram.Init.WriteProtection    = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
  40.     hsdram.Init.SDClockPeriod      = FMC_SDRAM_CLOCK_PERIOD_2;
  41.     hsdram.Init.ReadBurst          = FMC_SDRAM_RBURST_DISABLE;
  42.     hsdram.Init.ReadPipeDelay      = FMC_SDRAM_RPIPE_DELAY_1;
  43.    
  44.   /* Initialize the SDRAM controller */
  45.   if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
  46.   {
  47.     /* Initialization Error */
  48.   }
  49.     /* SDRAM Init sequence */
  50.    
  51.     /* Configure a clock configuration enable command */
  52.     command.CommandMode             = FMC_SDRAM_CMD_CLK_ENABLE;
  53.     command.CommandTarget           = SDRAM_COMMAND_TARGET_BANK;
  54.     command.AutoRefreshNumber       = 1;
  55.     command.ModeRegisterDefinition  = 0;
  56.    
  57.     /* Send command */
  58.     HAL_SDRAM_SendCommand(&hsdram, &command, SDRAM_TIMEOUT);
  59.    
  60.     /* Little delay */
  61.     HAL_Delay(130);
  62.    
  63.     /* Configure a PALL (precharge all) command */
  64.     command.CommandMode             = FMC_SDRAM_CMD_PALL;
  65.     command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK2;
  66.     command.AutoRefreshNumber       = 1;
  67.     command.ModeRegisterDefinition  = 0;
  68.    
  69.     /* Send the command */
  70.     HAL_SDRAM_SendCommand(&hsdram, &command, SDRAM_TIMEOUT);
  71.     /* Configure a Auto-Refresh command */
  72.     command.CommandMode             = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
  73.     command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK2;
  74.     command.AutoRefreshNumber       = 4;
  75.     command.ModeRegisterDefinition  = 0;
  76.    
  77.     /* Send the command */
  78.     HAL_SDRAM_SendCommand(&hsdram, &command, SDRAM_TIMEOUT);
  79.    
  80.     /* Configure a load Mode register command */
  81.     command.CommandMode             = FMC_SDRAM_CMD_LOAD_MODE;
  82.     command.CommandTarget           = SDRAM_COMMAND_TARGET_BANK;
  83.     command.AutoRefreshNumber       = 1;
  84.     command.ModeRegisterDefinition  = (uint32_t)SDRAM_REG_VALUE;
  85.    
  86.     /* Wait until the SDRAM controller is ready */
  87.     HAL_SDRAM_SendCommand(&hsdram, &command, SDRAM_TIMEOUT);
  88.     /* Set the refresh rate counter */
  89.     HAL_SDRAM_ProgramRefreshRate(&hsdram, SDRAM_REFRESH_COUNT);
  90.     HAL_Delay(100);
  91.    
  92.     /* Check if there is nor Error in initialization */
  93.     SDRAM_Write_8_Bit(0x20, 0xA5);
  94.    
  95.     /* Read and check */
  96.     if (SDRAM_Read_8_Bit(0x20) == 0xA5) {
  97.         initialized = 1;
  98.         return 1;
  99.     }
  100.    
  101.     /* Not initialized ERROR */
  102.     initialized = 0;
  103.    
  104.     /* ERROR */
  105.     return 0;
  106. }

W przypadku wykorzystywania funkcji wygenerowanej przez program, która wygląda następująco:

  1. /* FMC initialization function */
  2. static void MX_FMC_Init(void)
  3. {
  4.   FMC_SDRAM_TimingTypeDef SdramTiming;
  5.   /** Perform the SDRAM1 memory initialization sequence
  6.   */
  7.   hsdram1.Instance = FMC_SDRAM_DEVICE;
  8.   /* hsdram1.Init */
  9.   hsdram1.Init.SDBank = FMC_SDRAM_BANK2;
  10.   hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
  11.   hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
  12.   hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
  13.   hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_2;
  14.   hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
  15.   hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
  16.   hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
  17.   hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
  18.   hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
  19.   /* SdramTiming */
  20.   SdramTiming.LoadToActiveDelay = 2;
  21.   SdramTiming.ExitSelfRefreshDelay = 7;
  22.   SdramTiming.SelfRefreshTime = 4;
  23.   SdramTiming.RowCycleDelay = 7;
  24.   SdramTiming.WriteRecoveryTime = 3;
  25.   SdramTiming.RPDelay = 2;
  26.   SdramTiming.RCDDelay = 2;
  27.   if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
  28.   {
  29.     _Error_Handler(__FILE__, __LINE__);
  30.   }
  31. }

To aby uruchomić poprawnie SDRAM należy jeszcze przesłać odpowiednie komendy do układu, wywołuje się funkcjami umieszczonymi w bibliotece:

  1. //=================================================================================
  2. uint8_t SDRAM_Set_Operation(void)
  3. {
  4.     FMC_SDRAM_CommandTypeDef command;
  5.        
  6.     /* Configure a clock configuration enable command */
  7.     command.CommandMode             = FMC_SDRAM_CMD_CLK_ENABLE;
  8.     command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK2;
  9.     command.AutoRefreshNumber       = 1;
  10.     command.ModeRegisterDefinition  = 0;
  11.    
  12.     /* Send command */
  13.     HAL_SDRAM_SendCommand(&hsdram1, &command, SDRAM_TIMEOUT);
  14.    
  15.     /* Little delay */
  16.     HAL_Delay(130);
  17.    
  18.     /* Configure a PALL (precharge all) command */
  19.     command.CommandMode             = FMC_SDRAM_CMD_PALL;
  20.     command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK2;
  21.     command.AutoRefreshNumber       = 1;
  22.     command.ModeRegisterDefinition  = 0;
  23.    
  24.     /* Send the command */
  25.     HAL_SDRAM_SendCommand(&hsdram1, &command, SDRAM_TIMEOUT);
  26.     /* Configure a Auto-Refresh command */
  27.     command.CommandMode             = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
  28.     command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK2;
  29.     command.AutoRefreshNumber       = 4;
  30.     command.ModeRegisterDefinition  = 0;
  31.    
  32.     /* Send the command */
  33.     HAL_SDRAM_SendCommand(&hsdram1, &command, SDRAM_TIMEOUT);
  34.    
  35.     /* Configure a load Mode register command */
  36.     command.CommandMode             = FMC_SDRAM_CMD_LOAD_MODE;
  37.     command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK2;
  38.     command.AutoRefreshNumber       = 1;
  39.     command.ModeRegisterDefinition  = (uint32_t)SDRAM_REG_VALUE;
  40.    
  41.     /* Wait until the SDRAM controller is ready */
  42.     HAL_SDRAM_SendCommand(&hsdram1, &command, SDRAM_TIMEOUT);
  43.     /* Set the refresh rate counter */
  44.     HAL_SDRAM_ProgramRefreshRate(&hsdram1, SDRAM_REFRESH_COUNT);
  45.   HAL_Delay(100);
  46.    
  47.     if(Check_If_SDRAM_Works_OK() == 1)
  48.     {
  49.         return 1;
  50.     }
  51.    
  52.     /* ERROR */
  53.     return 0;
  54. }
  55. //=================================================================================
  56. static uint8_t Check_If_SDRAM_Works_OK(void)
  57. {
  58.     static uint8_t check = 0;
  59.    
  60.     SDRAM_Write_8_Bit(0x20, 0xA5);
  61.    
  62.     if (SDRAM_Read_8_Bit(0x20) == 0xA5) {
  63.         check = 1;
  64.         return check;
  65.     }
  66.    
  67.     /* Not initialized ERROR */
  68.     check = 0;
  69.    
  70.     return check;
  71. }

Włączenie podłączonych wyprowadzeń wykonuje się za pomocą następującej instrukcji:

  1. /* Private functions */
  2. static void SDRAM_InitPins(void)
  3. {
  4.   GPIO_InitTypeDef GPIO_InitStruct;
  5.    
  6.   /* Enable clocks */
  7.   __HAL_RCC_GPIOB_CLK_ENABLE();
  8.   __HAL_RCC_GPIOC_CLK_ENABLE();
  9.   __HAL_RCC_GPIOD_CLK_ENABLE();
  10.   __HAL_RCC_GPIOE_CLK_ENABLE();
  11.   __HAL_RCC_GPIOF_CLK_ENABLE();
  12.   __HAL_RCC_GPIOG_CLK_ENABLE();
  13.    
  14.   /* GPIO B */
  15.   GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_6;
  16.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  17.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  18.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  19.   GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  20.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  21.    
  22.   /* GPIO C */
  23.   GPIO_InitStruct.Pin = GPIO_PIN_0;
  24.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  25.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  26.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  27.   GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  28.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  29.   /* GPIO D */ 
  30.   GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 |
  31.                         GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15;
  32.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  33.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  34.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  35.   GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  36.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  37.    
  38.   /* GPIO E */
  39.   GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 |
  40.                         GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 |
  41.                         GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 |
  42.                         GPIO_PIN_14 | GPIO_PIN_15;
  43.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  44.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  45.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;    
  46.   GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  47.   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
  48.    
  49.   /* GPIO F */
  50.   GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 |
  51.                         GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 |
  52.                         GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
  53.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  54.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  55.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  56.   GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  57.   HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
  58.    
  59.   /* GPIO G */
  60.   GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 |
  61.                         GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15;
  62.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  63.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  64.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;    
  65.   GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  66.   HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
  67. }

Włączenie pinów odbywa się albo poprzez CubeMx gdzie wybiera się odpowiednie wyprowadzenia wraz z wszystkimi ustawieniami. W przypadku korzystania z funkcji z biblioteki, procedura inicjalizująca odwołuje się do funkcji statycznej, która ustawia wyprowadzenia dla pamięci.

Teraz funkcje pozwalające na wpisywanie podanych danych do programu. Funkcje zapisu i odczytu danych 8 bitowych:

  1. //=================================================================================
  2. /*
  3.  * @brief   Write 8 bit data value into SDRAM
  4.  * @param   addressOffset from start value                     
  5.  *          dataToSave data that will be save in SDRAM
  6.  * @ret     none
  7.  */
  8. inline void SDRAM_Write_8_Bit(uint32_t addressOffset, uint8_t dataToSave){
  9.     (*(__IO uint8_t *) (SDRAM_START_ADR + (addressOffset)) = (dataToSave));
  10. }
  11. //=================================================================================
  12. /*
  13.  * @brief   read 8 bit data value from SDRAM
  14.  * @param   addressOffset from start value                     
  15.  * @ret     value that has been read from Sdram
  16.  */
  17. inline uint8_t SDRAM_Read_8_Bit(uint32_t addressOffset){
  18.     return (*(__IO uint8_t *) (SDRAM_START_ADR + (addressOffset)));
  19. }

Funkcje zapisu i odczytu danych 16 bitowych:

  1. //=================================================================================
  2. /*
  3.  * @brief   Write 16 bit data value into SDRAM
  4.  * @param   addressOffset from start value                     
  5.  *                  dataToSave data that will be save in SDRAM
  6.  * @ret         none
  7.  */
  8. inline void SDRAM_Write_16_Bit(uint32_t addressOffset, uint16_t dataToSave) {
  9.     (*(__IO uint16_t *) (SDRAM_START_ADR + (addressOffset)) = (dataToSave));
  10. }
  11. //=================================================================================
  12. /*
  13.  * @brief   Read 16 bit data value into SDRAM
  14.  * @param   addressOffset from start value                     
  15.  * @ret         none
  16.  */
  17. inline uint16_t SDRAM_Read_16_Bit(uint32_t address){
  18.     return (*(__IO uint16_t *) (SDRAM_START_ADR + (address)));
  19. }

Funkcje zapisu i odczytu danych 32 bitowych:

  1. //=================================================================================
  2. /*
  3.  * @brief   Write 32 bit data value into SDRAM
  4.  * @param   addressOffset from start value                     
  5.  *                  dataToSave data that will be save in SDRAM
  6.  * @ret         none
  7.  */
  8. inline void SDRAM_Write_32_Bit(uint32_t addressOffset, uint32_t dataToSave){
  9.     (*(__IO uint32_t *) (SDRAM_START_ADR + (addressOffset)) = (dataToSave));
  10. }
  11. //=================================================================================
  12. /*
  13.  * @brief   Reads 32 bit data value into SDRAM
  14.  * @param   addressOffset from start value                     
  15.  *                  dataToSave data that will be save in SDRAM
  16.  * @ret         none
  17.  */
  18. inline uint32_t SDRAM_Read_32_Bit(uint32_t address){
  19.     return (*(__IO uint32_t *) (SDRAM_START_ADR + (address)));
  20. }

Funkcje zapisu i odczytu danych float:

  1. //=================================================================================
  2. /*
  3.  * @brief   Write float bit data value into SDRAM
  4.  * @param   addressOffset from start value                     
  5.  *                  dataToSave data that will be save in SDRAM
  6.  * @ret         none
  7.  */
  8. inline void SDRAM_Write_Float(uint32_t addressOffset, uint32_t dataToSave){
  9.     (*(__IO float *) (SDRAM_START_ADR + (addressOffset)) = (dataToSave));
  10. }
  11. //=================================================================================
  12. /*
  13.  * @brief   Reads float bit data value into SDRAM
  14.  * @param   addressOffset from start value                     
  15.  *                  dataToSave data that will be save in SDRAM
  16.  * @ret         none
  17.  */
  18. inline float SDRAM_Read_Float(uint32_t addressOffset){
  19.     return (*(__IO float *) (SDRAM_START_ADR + (addressOffset)));
  20. }

Pętla główna programu wygląda następująco:

  1. /* Private function prototypes -----------------------------------------------*/
  2. void SystemClock_Config(void);
  3. static void MX_GPIO_Init(void);
  4. static void MX_FMC_Init(void);
  5. static void MX_USART1_UART_Init(void);
  6. /* USER CODE BEGIN PFP */
  7. /* Private function prototypes -----------------------------------------------*/
  8. /* USER CODE END PFP */
  9. /* USER CODE BEGIN 0 */
  10. uint32_t WriteBuffer[32];
  11. uint32_t ReadBuffer[32];
  12. /* USER CODE END 0 */
  13. int main(void)
  14. {
  15.   /* USER CODE BEGIN 1 */
  16.   uint8_t i = 0;
  17.   /* USER CODE END 1 */
  18.   /* MCU Configuration----------------------------------------------------------*/
  19.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  20.   HAL_Init();
  21.   /* USER CODE BEGIN Init */
  22.   /* USER CODE END Init */
  23.   /* Configure the system clock */
  24.   SystemClock_Config();
  25.   /* USER CODE BEGIN SysInit */
  26.   /* USER CODE END SysInit */
  27.   /* Initialize all configured peripherals */
  28.   MX_GPIO_Init();
  29.   MX_FMC_Init();
  30.     SDRAM_Set_Operation();
  31.   MX_USART1_UART_Init();
  32.        
  33.   /* USER CODE BEGIN 2 */
  34.     /* When using functions from library */
  35.     //SDRAM_Init();
  36.    
  37.     /* Fill write data */
  38.     for (= 0; i < 255; i++) {
  39.         WriteBuffer[i] = 0xA5;
  40.        
  41.         /* Write to SDRAM */
  42.         SDRAM_Write_32_Bit(16 * i, WriteBuffer[i]);
  43.     }
  44.     /* Read data from SDRAM */
  45.     for (= 0; i < 255; i++) {
  46.         ReadBuffer[i] = SDRAM_Read_32_Bit(16 * i);
  47.     }
  48.         /* Memory compare */
  49.     if (memcmp((uint8_t *)ReadBuffer, (uint8_t *)WriteBuffer, sizeof(ReadBuffer)) == 0) {
  50.         /* SDRAM is OK */
  51.         HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET);
  52.     } else {
  53.         /* SDRAM failed */
  54.         HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_SET);
  55.     }
  56.    
  57.   /* USER CODE END 2 */
  58.   /* Infinite loop */
  59.   /* USER CODE BEGIN WHILE */
  60.   while (1)
  61.   {
  62.   /* USER CODE END WHILE */
  63.   /* USER CODE BEGIN 3 */
  64.   }
  65.   /* USER CODE END 3 */
  66. }

Pliki z projektem można znaleźć na dysku Google pod tym linkiem.