2022-03-09 10:37:11 +01:00

347 lines
11 KiB
C

/**
******************************************************************************
* @file FMC/FMC_SDRAM/Src/main.c
* @author MCD Application Team
* @brief This sample code shows how to use STM32F4xx FMC HAL API to access
* by read and write operation the SDRAM external memory device.
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/** @addtogroup STM32F4xx_HAL_Examples
* @{
*/
/** @addtogroup FMC_SDRAM_Basic
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define BUFFER_SIZE ((uint32_t)0x0100)
#define WRITE_READ_ADDR ((uint32_t)0x0800)
#define REFRESH_COUNT ((uint32_t)0x056A) /* SDRAM refresh counter (90MHz SDRAM clock) */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* SDRAM handler declaration */
SDRAM_HandleTypeDef hsdram;
FMC_SDRAM_TimingTypeDef SDRAM_Timing;
FMC_SDRAM_CommandTypeDef command;
/* Read/Write Buffers */
uint32_t aTxBuffer[BUFFER_SIZE];
uint32_t aRxBuffer[BUFFER_SIZE];
/* Status variables */
__IO uint32_t uwWriteReadStatus = 0;
/* Counter index */
uint32_t uwIndex = 0;
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void Error_Handler(void);
static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command);
static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/* STM32F4xx HAL library initialization:
- Configure the Flash prefetch, instruction and Data caches
- Configure the Systick to generate an interrupt each 1 msec
- Set NVIC Group Priority to 4
- Global MSP (MCU Support Package) initialization
*/
HAL_Init();
/* Configure LED3 and LED4 */
BSP_LED_Init(LED3);
BSP_LED_Init(LED4);
/* Configure the system clock to 180 MHz */
SystemClock_Config();
/*##-1- Configure the SDRAM device #########################################*/
/* SDRAM device configuration */
hsdram.Instance = FMC_SDRAM_DEVICE;
/* Timing configuration for 90 MHz of SDRAM clock frequency (180MHz/2) */
/* TMRD: 2 Clock cycles */
SDRAM_Timing.LoadToActiveDelay = 2;
/* TXSR: min=70ns (6x11.90ns) */
SDRAM_Timing.ExitSelfRefreshDelay = 7;
/* TRAS: min=42ns (4x11.90ns) max=120k (ns) */
SDRAM_Timing.SelfRefreshTime = 4;
/* TRC: min=63 (6x11.90ns) */
SDRAM_Timing.RowCycleDelay = 7;
/* TWR: 2 Clock cycles */
SDRAM_Timing.WriteRecoveryTime = 2;
/* TRP: 15ns => 2x11.90ns */
SDRAM_Timing.RPDelay = 2;
/* TRCD: 15ns => 2x11.90ns */
SDRAM_Timing.RCDDelay = 2;
hsdram.Init.SDBank = FMC_SDRAM_BANK2;
hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
hsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
hsdram.Init.MemoryDataWidth = SDRAM_MEMORY_WIDTH;
hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram.Init.SDClockPeriod = SDCLOCK_PERIOD;
hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
/* Initialize the SDRAM controller */
if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/* Program the SDRAM external device */
SDRAM_Initialization_Sequence(&hsdram, &command);
/*##-2- SDRAM memory read/write access #####################################*/
/* Fill the buffer to write */
Fill_Buffer(aTxBuffer, BUFFER_SIZE, 0xA244250F);
/* Write data to the SDRAM memory */
for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)
{
*(__IO uint32_t*) (SDRAM_BANK_ADDR + WRITE_READ_ADDR + 4*uwIndex) = aTxBuffer[uwIndex];
}
/* Read back data from the SDRAM memory */
for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)
{
aRxBuffer[uwIndex] = *(__IO uint32_t*) (SDRAM_BANK_ADDR + WRITE_READ_ADDR + 4*uwIndex);
}
/*##-3- Checking data integrity ############################################*/
for (uwIndex = 0; (uwIndex < BUFFER_SIZE) && (uwWriteReadStatus == 0); uwIndex++)
{
if (aRxBuffer[uwIndex] != aTxBuffer[uwIndex])
{
uwWriteReadStatus++;
}
}
if (uwWriteReadStatus)
{
/* KO */
/* Turn on LED4 */
BSP_LED_On(LED4);
}
else
{
/* OK */
/* Turn on LED3 */
BSP_LED_On(LED3);
}
/* Infinite loop */
while (1)
{
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 180000000
* HCLK(Hz) = 180000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 8000000
* PLL_M = 8
* PLL_N = 360
* PLL_P = 2
* PLL_Q = 7
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 5
* @param None
* @retval None
*/
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 360;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/* Activate the Over-Drive mode */
HAL_PWREx_EnableOverDrive();
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}
/**
* @brief This function is executed in case of error occurrence.
* @param None
* @retval None
*/
static void Error_Handler(void)
{
/* Turn LED3 on */
BSP_LED_On(LED3);
while(1)
{
}
}
/**
* @brief Perform the SDRAM exernal memory inialization sequence
* @param hsdram: SDRAM handle
* @param Command: Pointer to SDRAM command structure
* @retval None
*/
static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
{
__IO uint32_t tmpmrd =0;
/* Step 3: Configure a clock configuration enable command */
Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 4: Insert 100 ms delay */
HAL_Delay(100);
/* Step 5: Configure a PALL (precharge all) command */
Command->CommandMode = FMC_SDRAM_CMD_PALL;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 6 : Configure a Auto-Refresh command */
Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command->AutoRefreshNumber = 4;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 7: Program the external memory mode register */
tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = tmpmrd;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 8: Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter */
HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
}
/**
* @brief Fills buffer with user predefined data.
* @param pBuffer: pointer on the buffer to fill
* @param uwBufferLenght: size of the buffer to fill
* @param uwOffset: first value to fill on the buffer
* @retval None
*/
static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset)
{
uint32_t tmpIndex = 0;
/* Put in global buffer different values */
for (tmpIndex = 0; tmpIndex < uwBufferLenght; tmpIndex++ )
{
pBuffer[tmpIndex] = tmpIndex + uwOffset;
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* @}
*/
/**
* @}
*/