819 lines
25 KiB
C
819 lines
25 KiB
C
/**
|
|
******************************************************************************
|
|
* @file WiFi/Esp8266_IAP_Client/Src/main.c
|
|
* @author MCD Application Team
|
|
* @brief This sample code shows how to use the ESP8266 WiFi module to download
|
|
* a fw from a http server, write it into the flash then jump to run it.
|
|
******************************************************************************
|
|
* @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 <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "main.h"
|
|
#include "esp8266.h"
|
|
#ifdef USE_LCD
|
|
#include "lcd_log.h"
|
|
#endif /* USE_LCD */
|
|
#include "flash_if.h"
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
/* Private define ------------------------------------------------------------*/
|
|
#define HTML_SUCCESS_STRING "200 OK"
|
|
#define VSYNC 1
|
|
#define VBP 1
|
|
#define VFP 1
|
|
#define VACT 480
|
|
#define HSYNC 1
|
|
#define HBP 1
|
|
#define HFP 1
|
|
#define HACT 800
|
|
|
|
#define LAYER0_ADDRESS (LCD_FB_START_ADDRESS)
|
|
/* Private macro -------------------------------------------------------------*/
|
|
/* Private variables ---------------------------------------------------------*/
|
|
typedef void (*pFunction)(void);
|
|
pFunction Jump_To_Application;
|
|
uint32_t JumpAddress;
|
|
static uint8_t HtmlData[DATA_MAX_SIZE];
|
|
static uint8_t HtmlRequest[256];
|
|
static uint32_t FlashWriteAddress;
|
|
uint8_t IpAddress[15];
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
extern LTDC_HandleTypeDef hltdc_discovery;
|
|
extern DSI_HandleTypeDef hdsi_discovery;
|
|
DSI_CmdCfgTypeDef CmdCfg;
|
|
DSI_LPCmdTypeDef LPCmd;
|
|
DSI_PLLInitTypeDef dsiPllInit;
|
|
static RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
static void MPU_Config(void);
|
|
static void SystemClock_Config(void);
|
|
static void ErrorHandler(void);
|
|
static void StartWiFiIAP(void);
|
|
static void CPU_CACHE_Enable(void);
|
|
|
|
|
|
#ifdef USE_LCD
|
|
static void LCDConfig(void);
|
|
static void LTDC_Init(void);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Private functions ---------------------------------------------------------*/
|
|
|
|
/**
|
|
* @brief Main program
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
|
|
int main(void)
|
|
{
|
|
uint32_t Trial = 0;
|
|
ESP8266_StatusTypeDef Status;
|
|
|
|
/* 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
|
|
- 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();
|
|
|
|
/* Initialize the SDRAM */
|
|
BSP_SDRAM_Init();
|
|
|
|
/* Configure leds */
|
|
BSP_LED_Init(LED1);
|
|
BSP_LED_Init(LED2);
|
|
|
|
/* Configure Key Button */
|
|
BSP_PB_Init(BUTTON_USER, BUTTON_MODE_GPIO);
|
|
|
|
/* Test if Key Tamper -button on STM32F769I-Discovery Board is not pressed */
|
|
if (BSP_PB_GetState(BUTTON_USER) == 0x00)
|
|
{ /* Key Tamper -button not pressed: jump to user application */
|
|
|
|
/* Check if valid stack address (RAM address) then jump to user application */
|
|
if (((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
|
|
{
|
|
/* Jump to user application */
|
|
JumpAddress = *(__IO uint32_t*) (USER_FLASH_FIRST_PAGE_ADDRESS + 4);
|
|
Jump_To_Application = (pFunction) JumpAddress;
|
|
|
|
/* Initialize user application's Stack Pointer */
|
|
__set_MSP(*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS);
|
|
Jump_To_Application();
|
|
}
|
|
}
|
|
|
|
#ifdef USE_LCD
|
|
/* Configure LCD */
|
|
LCDConfig();
|
|
BSP_LCD_LayerDefaultInit(0, LAYER0_ADDRESS);
|
|
BSP_LCD_SelectLayer(0);
|
|
|
|
/* Initialize the log unit */
|
|
LCD_LOG_Init();
|
|
/* Send Display On DCS Command to display */
|
|
HAL_DSI_ShortWrite(&(hdsi_discovery),
|
|
0,
|
|
DSI_DCS_SHORT_PKT_WRITE_P1,
|
|
OTM8009A_CMD_DISPON,
|
|
0x00);
|
|
|
|
BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
|
|
BSP_LCD_FillRect(0, 0, 800, 112);
|
|
|
|
/* Write the demo header log */
|
|
LCD_LOG_SetHeader((uint8_t *)"WiFi IAP Demo");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
HAL_Delay(1000);
|
|
#endif /* USE_LCD */
|
|
|
|
#ifdef USE_LCD
|
|
LCD_UsrLog("Initializing Wifi module...\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Initialize the WiFi module ESP8266 */
|
|
Status = ESP8266_Init();
|
|
|
|
/* Check if initialization passed */
|
|
if (Status != ESP8266_OK)
|
|
{
|
|
#ifdef USE_LCD
|
|
LCD_ErrLog("Initializing Wifi module Failed!\n\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
ErrorHandler();
|
|
}
|
|
#ifdef USE_LCD
|
|
else
|
|
{
|
|
LCD_UsrLog("O.K!\n\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
}
|
|
|
|
/* Join Access Point defined by user */
|
|
LCD_UsrLog("Joining Access Point ' "WIFI_SSID " ' ...\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
while(ESP8266_JoinAccessPoint((uint8_t *)WIFI_SSID, (uint8_t *)WIFI_PASSWORD) != ESP8266_OK)
|
|
{
|
|
#if USE_LCD
|
|
LCD_UsrLog("Retrying ( %d )to Join Access Point "WIFI_SSID"\n\n", (int)++Trial);
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
if (Trial == MAX_NUM_TRIAL)
|
|
break;
|
|
}
|
|
|
|
/* Check if maximum number of trials has been reached */
|
|
if (Trial == MAX_NUM_TRIAL)
|
|
{
|
|
#if USE_LCD
|
|
LCD_ErrLog("Joining Access Point ' "WIFI_SSID" ' Failed!\n\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
ErrorHandler();
|
|
}
|
|
else
|
|
{
|
|
/* Reset the IP address field to 0 */
|
|
memset(IpAddress, '\0', 15);
|
|
|
|
/* Access point joined: start getting IP address */
|
|
ESP8266_GetIPAddress(ESP8266_STATION_MODE, IpAddress);
|
|
#ifdef USE_LCD
|
|
LCD_UsrLog("OK!\nGot IP Address: %s\n\n", (char *)IpAddress);
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
HAL_Delay(1000);
|
|
}
|
|
/* IP Address acquired: Start the IAP over WiFi (retrieve the binary file
|
|
for server and download it to Flash memory) */
|
|
StartWiFiIAP();
|
|
}
|
|
|
|
static void StartWiFiIAP(void)
|
|
{
|
|
uint8_t *FwData;
|
|
uint32_t FwSize;
|
|
uint32_t DataSize = 0;
|
|
uint32_t Trial = 0;
|
|
|
|
ESP8266_ConnectionInfoTypeDef ConnectionInfo;
|
|
ESP8266_StatusTypeDef Result = ESP8266_OK;
|
|
|
|
/* Initialize the HTML request field to 0 */
|
|
memset(HtmlRequest, '\0', 128);
|
|
|
|
/*
|
|
Send an HTML GET request to download the "FW_FILE", the request is as follows
|
|
====================================
|
|
GET /<fw_file> HTTP/1.1
|
|
Host: <http_server>
|
|
User-Agent: <esp8266_for_example>
|
|
Accept: * / * <= no space here
|
|
Connection: keep-alive
|
|
====================================
|
|
the request MUST end with a "\r\n\r\n" otherwise it won't be processed correctly.
|
|
*/
|
|
sprintf((char *)HtmlRequest, "GET /"FW_FILE" HTTP/1.1%c%cHost: "HOST_ADDRESS"%c%cUser-Agent: esp8266/stm32%c%cAccept: */*%c%cConnection: keep-alive%c%c%c%c",
|
|
'\r','\n','\r','\n','\r','\n','\r','\n','\r','\n','\r','\n');
|
|
|
|
#ifdef USE_LCD
|
|
LCD_UsrLog("Connecting to %s:%d ...\n", HOST_ADDRESS, HOST_PORT);
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Initialize Connection info structure */
|
|
Trial = 0;
|
|
memset(&ConnectionInfo, '\0', sizeof (ESP8266_ConnectionInfoTypeDef));
|
|
|
|
ConnectionInfo.connectionType = ESP8266_TCP_CONNECTION;
|
|
ConnectionInfo.ipAddress = (uint8_t *)HOST_ADDRESS;
|
|
ConnectionInfo.isServer = ESP8266_FALSE;
|
|
ConnectionInfo.port = HOST_PORT;
|
|
|
|
/* Wait for communication establishment */
|
|
while (ESP8266_EstablishConnection(&ConnectionInfo) != ESP8266_OK)
|
|
{
|
|
#ifdef USE_LCD
|
|
LCD_UsrLog("Retrying( %d ) to connect to %s:%d \n", (int)++Trial, HOST_ADDRESS, HOST_PORT);
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
HAL_Delay(1000);
|
|
|
|
#endif /* USE_LCD */
|
|
|
|
if (Trial == MAX_NUM_TRIAL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Check if trials number exceeded maximum limit */
|
|
if (Trial == MAX_NUM_TRIAL)
|
|
{
|
|
#ifdef USE_LCD
|
|
LCD_ErrLog("Connecting to %s:%d Failed!\n", HOST_ADDRESS, HOST_PORT);
|
|
LCD_ErrLog("Quitting Access Point...\n\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Leave the access point */
|
|
ESP8266_QuitAccessPoint();
|
|
|
|
/* Deinitialize the WiFi module */
|
|
ESP8266_DeInit();
|
|
|
|
/* Call the error Handler */
|
|
ErrorHandler();
|
|
}
|
|
|
|
#ifdef USE_LCD
|
|
else
|
|
{
|
|
LCD_UsrLog("O.K!\n\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
HAL_Delay(1000);
|
|
}
|
|
#endif /* USE_LCD */
|
|
|
|
/* Reset the HTML data field to 0 */
|
|
memset(HtmlData, '\0', ARRAY_SIZE(HtmlData));
|
|
|
|
#ifdef USE_LCD
|
|
LCD_UsrLog("Downloading the firmware ' "FW_FILE" '...\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
|
|
Result = ESP8266_SendData(HtmlRequest, strlen((char *)HtmlRequest));
|
|
|
|
/* In case of error, quit the Access point */
|
|
if (Result != ESP8266_OK)
|
|
{
|
|
#ifdef USE_LCD
|
|
LCD_ErrLog("Downloading the firmware ' "FW_FILE" ' Failed!\n");
|
|
LCD_ErrLog("Quitting Access Point...\n\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Deinitialize the WiFi module */
|
|
ESP8266_DeInit();
|
|
|
|
/* Call the error Handler */
|
|
ErrorHandler();
|
|
}
|
|
|
|
/* Check whether the data was correctly received.
|
|
This is can be done by checking the GET request response.
|
|
in case of success the string '200 OK' is received.
|
|
see (https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) */
|
|
Result = ESP8266_ReceiveData(HtmlData, DATA_MAX_SIZE, &DataSize);
|
|
|
|
/* If data reception failed */
|
|
if (Result != ESP8266_OK)
|
|
{
|
|
#ifdef USE_LCD
|
|
LCD_ErrLog("Downloading the firmware ' "FW_FILE" ' Failed!\n");
|
|
LCD_ErrLog("Quitting Access Point...\n\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Leave the access point */
|
|
ESP8266_QuitAccessPoint();
|
|
|
|
/* Deinitialize the WiFi module */
|
|
ESP8266_DeInit();
|
|
|
|
/* Call the error Handler */
|
|
ErrorHandler();
|
|
}
|
|
|
|
/* If data reception passed */
|
|
if(strstr((char *)HtmlData, HTML_SUCCESS_STRING) == NULL)
|
|
{
|
|
#ifdef USE_LCD
|
|
LCD_ErrLog("Downloading the firmware ' "FW_FILE" ' Failed!\n");
|
|
LCD_ErrLog("Quitting Access Point...\n\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Leave the access point */
|
|
ESP8266_QuitAccessPoint();
|
|
|
|
/* Deinitialize the WiFi module */
|
|
ESP8266_DeInit();
|
|
|
|
/* Call the error Handler */
|
|
ErrorHandler();
|
|
}
|
|
|
|
/* The actual fw data is located after the HTML HEADER
|
|
the end of header is marked with the string "\r\n\r\n" */
|
|
FwData = (uint8_t *)(strstr((char *)HtmlData, "\r\n\r\n"));
|
|
|
|
/* Check if data is null */
|
|
if (FwData != NULL)
|
|
{
|
|
/* Increment data pointer by 4 to get the data load */
|
|
FwData += 4;
|
|
|
|
/* Stop WiFi module to avoid errors when erasing flash */
|
|
ESP8266_DeInit();
|
|
|
|
/* The actual fw data size can be retrieved from the html header
|
|
by looking at the "Content-Length" field.
|
|
but let's do it in a faster way: FwSize = DataSize - (FwData - HtmlData) */
|
|
FwSize = DataSize - (FwData - HtmlData);
|
|
|
|
#ifdef USE_LCD
|
|
LCD_UsrLog("Downloaded firmware ' %s ', size = %ld Bytes\n\n", FW_FILE, FwSize);
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
HAL_Delay(1000);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Now the firmware can be written into Flash memory */
|
|
#ifdef USE_LCD
|
|
LCD_UsrLog("State: Programming...\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Initialize the Flash memory module for write operations */
|
|
FLASH_If_Init();
|
|
|
|
/* Erase 2 sectors, 128KB each (the downloaded firmware size doesn't exceed 192KB) */
|
|
FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
|
|
FLASH_If_Erase(USER_FLASH_SECOND_PAGE_ADDRESS);
|
|
|
|
/* Set the write address */
|
|
FlashWriteAddress = USER_FLASH_FIRST_PAGE_ADDRESS;
|
|
|
|
/* Start writing the binary file into the Flash memory */
|
|
if (FLASH_If_Write(&FlashWriteAddress, (uint32_t*)FwData, FwSize) != 0)
|
|
{
|
|
#ifdef USE_LCD
|
|
LCD_ErrLog("Programming Failed !\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
/* Leave the access point */
|
|
ESP8266_QuitAccessPoint();
|
|
|
|
/* Deinitialize the WiFi module */
|
|
ESP8266_DeInit();
|
|
|
|
/* Call the error Handler */
|
|
ErrorHandler();
|
|
}
|
|
else
|
|
{
|
|
#ifdef USE_LCD
|
|
LCD_UsrLog("Programming Done !\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef USE_LCD
|
|
LCD_ErrLog("The firmware ' "FW_FILE" ' is empty\n");
|
|
LCD_ErrLog("Quitting Access Point...\n\n");
|
|
/*Refresh the LCD display*/
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
#endif /* USE_LCD */
|
|
|
|
/* Leave the access point */
|
|
ESP8266_QuitAccessPoint();
|
|
|
|
/* Deinitialize the WiFi module */
|
|
ESP8266_DeInit();
|
|
|
|
/* Call the error Handler */
|
|
ErrorHandler();
|
|
}
|
|
|
|
/* Stop WiFi module */
|
|
ESP8266_DeInit();
|
|
|
|
/* Set LED2 On */
|
|
BSP_LED_On(LED2);
|
|
|
|
while(ESP8266_TRUE)
|
|
{
|
|
HAL_Delay(300);
|
|
BSP_LED_Toggle(LED2);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief This function is executed in case of error occurrence.
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
static void ErrorHandler(void)
|
|
{
|
|
/* Stop WiFi Module */
|
|
ESP8266_DeInit();
|
|
|
|
/* Keep blinking LED1 */
|
|
while(1)
|
|
{
|
|
HAL_Delay(100);
|
|
BSP_LED_Toggle(LED1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @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
|
|
* PLL_R = 7
|
|
* 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;
|
|
HAL_StatusTypeDef Result = HAL_OK;
|
|
|
|
/* 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 = 25;
|
|
RCC_OscInitStruct.PLL.PLLN = 400;
|
|
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
|
RCC_OscInitStruct.PLL.PLLQ = 9;
|
|
RCC_OscInitStruct.PLL.PLLR = 7;
|
|
|
|
|
|
Result = HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
|
if(Result != HAL_OK)
|
|
{
|
|
while(1) { ; }
|
|
}
|
|
|
|
/* Activate the OverDrive to reach the 200 MHz Frequency */
|
|
Result = HAL_PWREx_EnableOverDrive();
|
|
if(Result != 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;
|
|
|
|
Result = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
|
|
if(Result != HAL_OK)
|
|
{
|
|
while(1) { ; }
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @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 = 0xC0000000;
|
|
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_LCD
|
|
/**
|
|
* @brief This function initializes the LCD Configuration.
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
static void LCDConfig(void)
|
|
{
|
|
DSI_PHY_TimerTypeDef PhyTimings;
|
|
|
|
/* Toggle Hardware Reset of the DSI LCD using
|
|
* its XRES signal (active low) */
|
|
BSP_LCD_Reset();
|
|
|
|
/* Call first MSP Initialize only in case of first initialization
|
|
* This will set IP blocks LTDC, DSI and DMA2D
|
|
* - out of reset
|
|
* - clocked
|
|
* - NVIC IRQ related to IP blocks enabled
|
|
*/
|
|
BSP_LCD_MspInit();
|
|
|
|
/* LCD clock configuration */
|
|
/* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
|
|
/* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 417 Mhz */
|
|
/* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 417 MHz / 5 = 83.4 MHz */
|
|
/* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_2 = 83.4 / 2 = 41.7 MHz */
|
|
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
|
|
PeriphClkInitStruct.PLLSAI.PLLSAIN = 417;
|
|
PeriphClkInitStruct.PLLSAI.PLLSAIR = 5;
|
|
PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2;
|
|
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
|
|
|
/* Base address of DSI Host/Wrapper registers to be set before calling De-Init */
|
|
hdsi_discovery.Instance = DSI;
|
|
|
|
HAL_DSI_DeInit(&(hdsi_discovery));
|
|
|
|
dsiPllInit.PLLNDIV = 100;
|
|
dsiPllInit.PLLIDF = DSI_PLL_IN_DIV5;
|
|
dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1;
|
|
|
|
hdsi_discovery.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
|
|
hdsi_discovery.Init.TXEscapeCkdiv = 0x4;
|
|
HAL_DSI_Init(&(hdsi_discovery), &(dsiPllInit));
|
|
|
|
/* Configure the DSI for Command mode */
|
|
CmdCfg.VirtualChannelID = 0;
|
|
CmdCfg.HSPolarity = DSI_HSYNC_ACTIVE_HIGH;
|
|
CmdCfg.VSPolarity = DSI_VSYNC_ACTIVE_HIGH;
|
|
CmdCfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
|
|
CmdCfg.ColorCoding = DSI_RGB888;
|
|
CmdCfg.CommandSize = HACT;
|
|
CmdCfg.TearingEffectSource = DSI_TE_DSILINK;
|
|
CmdCfg.TearingEffectPolarity = DSI_TE_RISING_EDGE;
|
|
CmdCfg.VSyncPol = DSI_VSYNC_FALLING;
|
|
CmdCfg.AutomaticRefresh = DSI_AR_DISABLE;
|
|
CmdCfg.TEAcknowledgeRequest = DSI_TE_ACKNOWLEDGE_ENABLE;
|
|
HAL_DSI_ConfigAdaptedCommandMode(&hdsi_discovery, &CmdCfg);
|
|
|
|
LPCmd.LPGenShortWriteNoP = DSI_LP_GSW0P_ENABLE;
|
|
LPCmd.LPGenShortWriteOneP = DSI_LP_GSW1P_ENABLE;
|
|
LPCmd.LPGenShortWriteTwoP = DSI_LP_GSW2P_ENABLE;
|
|
LPCmd.LPGenShortReadNoP = DSI_LP_GSR0P_ENABLE;
|
|
LPCmd.LPGenShortReadOneP = DSI_LP_GSR1P_ENABLE;
|
|
LPCmd.LPGenShortReadTwoP = DSI_LP_GSR2P_ENABLE;
|
|
LPCmd.LPGenLongWrite = DSI_LP_GLW_ENABLE;
|
|
LPCmd.LPDcsShortWriteNoP = DSI_LP_DSW0P_ENABLE;
|
|
LPCmd.LPDcsShortWriteOneP = DSI_LP_DSW1P_ENABLE;
|
|
LPCmd.LPDcsShortReadNoP = DSI_LP_DSR0P_ENABLE;
|
|
LPCmd.LPDcsLongWrite = DSI_LP_DLW_ENABLE;
|
|
HAL_DSI_ConfigCommand(&hdsi_discovery, &LPCmd);
|
|
|
|
/* Initialize LTDC */
|
|
LTDC_Init();
|
|
|
|
/* Start DSI */
|
|
HAL_DSI_Start(&(hdsi_discovery));
|
|
|
|
/* Configure DSI PHY HS2LP and LP2HS timings */
|
|
PhyTimings.ClockLaneHS2LPTime = 35;
|
|
PhyTimings.ClockLaneLP2HSTime = 35;
|
|
PhyTimings.DataLaneHS2LPTime = 35;
|
|
PhyTimings.DataLaneLP2HSTime = 35;
|
|
PhyTimings.DataLaneMaxReadTime = 0;
|
|
PhyTimings.StopWaitTime = 10;
|
|
HAL_DSI_ConfigPhyTimer(&hdsi_discovery, &PhyTimings);
|
|
|
|
/* Initialize the OTM8009A LCD Display IC Driver (KoD LCD IC Driver)
|
|
* depending on configuration set in 'hdsivideo_handle'.
|
|
*/
|
|
OTM8009A_Init(OTM8009A_COLMOD_RGB888, LCD_ORIENTATION_LANDSCAPE);
|
|
|
|
LPCmd.LPGenShortWriteNoP = DSI_LP_GSW0P_DISABLE;
|
|
LPCmd.LPGenShortWriteOneP = DSI_LP_GSW1P_DISABLE;
|
|
LPCmd.LPGenShortWriteTwoP = DSI_LP_GSW2P_DISABLE;
|
|
LPCmd.LPGenShortReadNoP = DSI_LP_GSR0P_DISABLE;
|
|
LPCmd.LPGenShortReadOneP = DSI_LP_GSR1P_DISABLE;
|
|
LPCmd.LPGenShortReadTwoP = DSI_LP_GSR2P_DISABLE;
|
|
LPCmd.LPGenLongWrite = DSI_LP_GLW_DISABLE;
|
|
LPCmd.LPDcsShortWriteNoP = DSI_LP_DSW0P_DISABLE;
|
|
LPCmd.LPDcsShortWriteOneP = DSI_LP_DSW1P_DISABLE;
|
|
LPCmd.LPDcsShortReadNoP = DSI_LP_DSR0P_DISABLE;
|
|
LPCmd.LPDcsLongWrite = DSI_LP_DLW_DISABLE;
|
|
HAL_DSI_ConfigCommand(&hdsi_discovery, &LPCmd);
|
|
|
|
HAL_DSI_ConfigFlowControl(&hdsi_discovery, DSI_FLOW_CONTROL_BTA);
|
|
|
|
/* Send Display Off DCS Command to display */
|
|
HAL_DSI_ShortWrite(&(hdsi_discovery),
|
|
0,
|
|
DSI_DCS_SHORT_PKT_WRITE_P1,
|
|
OTM8009A_CMD_DISPOFF,
|
|
0x00);
|
|
|
|
/* Refresh the display */
|
|
HAL_DSI_Refresh(&hdsi_discovery);
|
|
}
|
|
|
|
/**
|
|
* @brief
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
static void LTDC_Init(void)
|
|
{
|
|
/* DeInit */
|
|
HAL_LTDC_DeInit(&hltdc_discovery);
|
|
|
|
/* LTDC Config */
|
|
/* Timing and polarity */
|
|
hltdc_discovery.Init.HorizontalSync = HSYNC;
|
|
hltdc_discovery.Init.VerticalSync = VSYNC;
|
|
hltdc_discovery.Init.AccumulatedHBP = HSYNC+HBP;
|
|
hltdc_discovery.Init.AccumulatedVBP = VSYNC+VBP;
|
|
hltdc_discovery.Init.AccumulatedActiveH = VSYNC+VBP+VACT;
|
|
hltdc_discovery.Init.AccumulatedActiveW = HSYNC+HBP+HACT;
|
|
hltdc_discovery.Init.TotalHeigh = VSYNC+VBP+VACT+VFP;
|
|
hltdc_discovery.Init.TotalWidth = HSYNC+HBP+HACT+HFP;
|
|
|
|
/* background value */
|
|
hltdc_discovery.Init.Backcolor.Blue = 0;
|
|
hltdc_discovery.Init.Backcolor.Green = 0;
|
|
hltdc_discovery.Init.Backcolor.Red = 0;
|
|
|
|
/* Polarity */
|
|
hltdc_discovery.Init.HSPolarity = LTDC_HSPOLARITY_AL;
|
|
hltdc_discovery.Init.VSPolarity = LTDC_VSPOLARITY_AL;
|
|
hltdc_discovery.Init.DEPolarity = LTDC_DEPOLARITY_AL;
|
|
hltdc_discovery.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
|
|
hltdc_discovery.Instance = LTDC;
|
|
|
|
HAL_LTDC_Init(&hltdc_discovery);
|
|
}
|
|
|
|
#endif /* USE_LCD */
|
|
|