text: /**
    ******************************************************************************
    * @file    LwIP/LwIP_TCP_Echo_Client/Src/main.c 
    * @author  MCD Application Team
    * @brief   This sample code implements a TCP Echo Client application based on 
    *          Raw API of LwIP stack. This application uses STM32F7xx the 
    *          ETH HAL API to transmit and receive data. 
    *          The communication is done with a web browser of a remote PC.
    ******************************************************************************
    * @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"
  #include "lwip/opt.h"
  #include "lwip/init.h"
  #include "lwip/netif.h"
  #include "lwip/timeouts.h"
  #include "netif/etharp.h"
  #include "ethernetif.h"
  #include "app_ethernet.h"
  #include "tcp_echoclient.h"
  #ifdef USE_LCD
  #include "lcd_log.h"
  #endif
  
  /* Private typedef -----------------------------------------------------------*/
  /* Private define ------------------------------------------------------------*/
  /* Private macro -------------------------------------------------------------*/
  /* Private variables ---------------------------------------------------------*/
  struct netif gnetif;
  
  /* Private function prototypes -----------------------------------------------*/
  static void SystemClock_Config(void);
  static void BSP_Config(void);
  static void Netif_Config(void);
  static void Error_Handler(void);
  static void MPU_Config(void);
  static void CPU_CACHE_Enable(void);
  
  /* Private functions ---------------------------------------------------------*/
  
  /**
    * @brief  Main program
    * @param  None
    * @retval None
    */
  int main(void)
  {
    /* Configure the MPU attributes as Device memory for ETH DMA descriptors */
    MPU_Config();
    
    /* Enable the CPU Cache */
    CPU_CACHE_Enable();
  
    /* STM32F7xx HAL library initialization:
         - Configure the Flash ART accelerator on ITCM interface
         - 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 the system clock to 200 MHz */
    SystemClock_Config(); 
    
    /* Configure the BSP */
    BSP_Config();
      
    /* Initialize the LwIP stack */
    lwip_init();
    
    /* Configure the Network interface */
    Netif_Config();
    
    /* Notify user about the network interface config */
    User_notification(&gnetif);
    
    /* Infinite loop */
    while (1)
    {  
      /* Read a received packet from the Ethernet buffers and send it 
         to the lwIP for handling */
      ethernetif_input(&gnetif);
  
      /* Handle timeouts */
      sys_check_timeouts();
  
  #ifdef USE_DHCP
      /* handle periodic timers for DHCP */
      DHCP_Periodic_Handle(&gnetif);
  #endif 
    } 
  }
  
  /**
    * @brief  Setup the BSP.
    * @param  None
    * @retval None
    */
  static void BSP_Config(void)
  {
    /* Configure LED1, LED2, LED3 and LED4 */
    BSP_LED_Init(LED1);
    BSP_LED_Init(LED2);
    BSP_LED_Init(LED3);
    BSP_LED_Init(LED4);
  
    /* Configure Key Button */
    BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI);
    
    /* Set Systick Interrupt to the highest priority */
    HAL_NVIC_SetPriority(SysTick_IRQn, 0x0, 0x0);
    
    /* Init MFX */
    BSP_IO_Init();
    
    /* Enable MFX interrupt for ETH MII pin */
    BSP_IO_ConfigPin(MII_INT_PIN, IO_MODE_IT_FALLING_EDGE);
  
  #ifdef USE_LCD
  
    /* Initialize the LCD */
    BSP_LCD_Init();
    
    /* Initialize the LCD Layers */
    BSP_LCD_LayerDefaultInit(1, LCD_FB_START_ADDRESS);
    
    /* Set LCD Foreground Layer  */
    BSP_LCD_SelectLayer(1);
    
    BSP_LCD_SetFont(&LCD_DEFAULT_FONT);
    
    /* Initialize LCD Log module */
    LCD_LOG_Init();
    
    /* Show Header and Footer texts */
    LCD_LOG_SetHeader((uint8_t *)"TCP Echo Client Raw API");
    LCD_LOG_SetFooter((uint8_t *)"STM32756G-EVAL board");
    
    LCD_UsrLog ("  State: Ethernet Initialization ...\n");
  
  #endif
  }
  
  /**
    * @brief  Setup the network interface
    * @param  None
    * @retval None
    */
  static void Netif_Config(void)
  {
    ip_addr_t ipaddr;
    ip_addr_t netmask;
    ip_addr_t gw;
   
  #ifdef USE_DHCP
    ip_addr_set_zero_ip4(&ipaddr);
    ip_addr_set_zero_ip4(&netmask);
    ip_addr_set_zero_ip4(&gw);
  #else
    IP_ADDR4(&ipaddr,IP_ADDR0,IP_ADDR1,IP_ADDR2,IP_ADDR3);
    IP_ADDR4(&netmask,NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3);
    IP_ADDR4(&gw,GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3);
  #endif /* USE_DHCP */
    
    /* add the network interface */    
    netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_input);
    
    /* Registers the default network interface */
    netif_set_default(&gnetif);
    
    if (netif_is_link_up(&gnetif))
    {
      /* When the netif is fully configured this function must be called */
      netif_set_up(&gnetif);
    }
    else
    {
      /* When the netif link is down this function must be called */
      netif_set_down(&gnetif);
    }
    
    /* Set the link callback function, this function is called on change of link status */
    netif_set_link_callback(&gnetif, ethernetif_update_config);
  }
  
  /**
    * @brief EXTI line detection callbacks
    * @param  GPIO_Pin: Specifies the pins connected EXTI line
    * @retval None
    */
  void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  {
    
    if (GPIO_Pin == MFX_IRQOUT_PIN)
    {
      /* Get the IT status register value */
      if(BSP_IO_ITGetStatus(MII_INT_PIN))
      {
        ethernetif_set_link(&gnetif);
      }
      BSP_IO_ITClear();
    }
    else if (GPIO_Pin == GPIO_PIN_13)
    {
       /*connect to tcp server */ 
       tcp_echoclient_connect();
    }
  }
  
  /**
    * @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                          = 9
    *            VDD(V)                         = 3.3
    *            Main regulator output voltage  = Scale1 mode
    *            Flash Latency(WS)              = 7
    * @param  None
    * @retval None
    */
  static void SystemClock_Config(void)
  {
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_OscInitTypeDef RCC_OscInitStruct;
  
    /* Enable HSE Oscillator and activate PLL with HSE as source */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
    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 = 9;
    if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
      Error_Handler();
    }
  
    /* activate the OverDrive */
    if(HAL_PWREx_EnableOverDrive() != HAL_OK)
    {
      Error_Handler();
    }
    
    /* 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;  
    if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
    {
      Error_Handler();
    }
  }
  
  /**
    * @brief  This function is executed in case of error occurrence.
    * @param  None
    * @retval None
    */
  static void Error_Handler(void)
  {
    /* User may add here some code to deal with this error */
    while(1)
    {
    }
  }
  
  /**
    * @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 as Normal Non Cacheable for Ethernet Buffers in the SRAM2 */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = 0x2004C000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_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_NUMBER1;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
    /* Configure the MPU as Device for Ethernet Descriptors in the SRAM2 */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = 0x2004C000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
    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 = 0x00;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
    /* Configure the MPU attributes as WT for SRAM */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = SDRAM_DEVICE_ADDR;
    MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
    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_NUMBER3;
    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_NUMBER4;
    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);
  }
  
  /**
    * @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();
  }
  
  #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
  
  