text: /**
    ******************************************************************************
    * @file    FMC/FMC_SDRAM_MemRemap/Src/main.c
    * @author  MCD Application Team
    * @brief   This sample code shows how to use the SDRAM device mounted on the
    *          Evaluation board as a data memory.
    ******************************************************************************
    * @attention
    *
    * Copyright (c) 2016 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 STM32F7xx_HAL_Examples
    * @{
    */
  
  /** @addtogroup FMC_SDRAM_MemRemap
    * @{
    */
  
  /* Private typedef -----------------------------------------------------------*/
  /* Private define ------------------------------------------------------------*/
  /* Private macro -------------------------------------------------------------*/
  /* Private variables ---------------------------------------------------------*/
  /* Data array */
  uint32_t aTable[1024];
  
  /* Counter index */
  uint32_t uwIndex;
  
  __IO uint32_t uwTabAddr;
  __IO uint32_t MSPValue = 0;
  
  /* Private function prototypes -----------------------------------------------*/
  static void MPU_Config(void);
  static void SystemClock_Config(void);
  static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLength, uint16_t uwOffset);
  static void CPU_CACHE_Enable(void);
  
  /* Private functions ---------------------------------------------------------*/
  
  /**
    * @brief  Main program
    * @param  None
    * @retval None
    */
  int main(void)
  {
    /* Configure the MPU attributes */
    MPU_Config();
  
    /* Enable the CPU Cache */
    CPU_CACHE_Enable();
  	
    /* STM32F7xx HAL library initialization:
         - Configure the Flash ART accelerator on ITCM interface
         - Systick timer is configured by default as source of time base, but user 
           can eventually implement his proper time base source (a general purpose 
           timer for example or other time source), keeping in mind that Time base 
           duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and 
           handled in milliseconds basis.
         - Set NVIC Group Priority to 4
         - Low Level Initialization
       */
    HAL_Init();
    
    /* Configure LED1, LED2 and LED3 */
    BSP_LED_Init(LED1);
    BSP_LED_Init(LED2);
    BSP_LED_Init(LED3);
  
    /* Configure the system clock to 200 MHz */
    /* This function will be executed from SDRAM */
    SystemClock_Config();
  
    /*##-1- Fill the buffer in the SDRAM device ##########################################*/
    Fill_Buffer(aTable, 1024, 0);
  
    /*##-2- Read address of the buffer and stack pointer address ########################*/
    uwTabAddr = (uint32_t)aTable; /* should be above 0x60000000 */
    
    /* Get main stack pointer value */
    MSPValue = __get_MSP(); /* should be above 0x60000000 */
  
    /*##-3- Activate LEDs pending on read values ########################################*/
    if ((uwTabAddr >= SDRAM_ADDRESS) && (MSPValue >= SDRAM_ADDRESS))
    {
      BSP_LED_On(LED1);
    }
    else
    {/* Toggle LED3 in an infinite loop */
      while (1)
      {
        BSP_LED_Toggle(LED3);
        /* Insert delay 100 ms */
        HAL_Delay(100);
      }
    }
  
    /* Infinite loop */
    while (1)
    {
    }
  }
  
  /**
    * @brief  System Clock Configuration
    *         The system Clock is configured as follow : 
    *            System Clock source            = PLL (HSE)
    *            SYSCLK(Hz)                     = 200000000
    *            HCLK(Hz)                       = 200000000
    *            AHB Prescaler                  = 1
    *            APB1 Prescaler                 = 4
    *            APB2 Prescaler                 = 2
    *            HSE Frequency(Hz)              = 25000000
    *            PLL_M                          = 25
    *            PLL_N                          = 400
    *            PLL_P                          = 2
    *            PLL_Q                          = 8
    *            VDD(V)                         = 3.3
    *            Main regulator output voltage  = Scale1 mode
    *            Flash Latency(WS)              = 6
    * @param  None
    * @note   This function will be executed from SDRAM   
    * @retval None
    */
  #if defined ( __ICCARM__ )	
  #pragma location = ".sdram"
  #elif defined ( __CC_ARM   )
  __attribute__((section("sdram")))
  #elif defined (__GNUC__)
  __attribute__((section(".sdram")))
  #endif
  static void SystemClock_Config(void)
  {
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_OscInitTypeDef RCC_OscInitStruct;
    HAL_StatusTypeDef ret = HAL_OK;
  
    /* 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 = 25;
    RCC_OscInitStruct.PLL.PLLN = 400;  
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 8;
    RCC_OscInitStruct.PLL.PLLR = 7;
    
    ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
    if(ret != HAL_OK)
    {
      while(1) { ; }
    }
    
    /* Activate the OverDrive to reach the 200 MHz Frequency */  
    ret = HAL_PWREx_EnableOverDrive();
    if(ret != HAL_OK)
    {
      while(1) { ; }
    }
    
    /* 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; 
    
    ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6);
    if(ret != HAL_OK)
    {
      while(1) { ; }
    }
    
    /* Switch On LED2 */
    BSP_LED_On(LED2);
  }
  
  /**
    * @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 uwBufferLength, uint16_t uwOffset)
  {
    uint16_t tmpIndex = 0;
  
    /* Put in global buffer different values */
    for (tmpIndex = 0; tmpIndex < uwBufferLength; tmpIndex++ )
    {
      pBuffer[tmpIndex] = tmpIndex + uwOffset;
    }
  }
  
  /**
    * @brief  CPU L1-Cache enable.
    * @param  None
    * @retval None
    */
  static void CPU_CACHE_Enable(void)
  {
    /* Enable I-Cache */
    SCB_EnableICache();
  
    /* Enable D-Cache */
    SCB_EnableDCache();
  }
  
  
  /**
    * @brief  Configure the MPU attributes
    * @param  None
    * @retval None
    */
  static void MPU_Config(void)
  {
    MPU_Region_InitTypeDef MPU_InitStruct;
  
    /* Disable the MPU */
    HAL_MPU_Disable();
  
    /* Configure the MPU as Strongly ordered for not defined regions */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = 0x00;
    MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
    MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER0;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable = 0x87;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
  
    /* Configure the MPU attributes as WT for SDRAM */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = SDRAM_ADDRESS;
    MPU_InitStruct.Size = MPU_REGION_SIZE_32MB;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER1;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
  
    /* Configure the MPU attributes FMC control registers */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = 0xA0000000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_8KB;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER2;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable = 0x0;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
    
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
  
    /* Enable the MPU */
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
  }
  
  #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
  
  /**
    * @}
    */
  
  /**
    * @}
    */
  
  