333 lines
9.1 KiB
C
333 lines
9.1 KiB
C
/* -----------------------------------------------------------------------------
|
||
* Copyright (c) 2016 ARM Ltd.
|
||
*
|
||
* This software is provided 'as-is', without any express or implied warranty.
|
||
* In no event will the authors be held liable for any damages arising from
|
||
* the use of this software. Permission is granted to anyone to use this
|
||
* software for any purpose, including commercial applications, and to alter
|
||
* it and redistribute it freely, subject to the following restrictions:
|
||
*
|
||
* 1. The origin of this software must not be misrepresented; you must not
|
||
* claim that you wrote the original software. If you use this software in
|
||
* a product, an acknowledgment in the product documentation would be
|
||
* appreciated but is not required.
|
||
*
|
||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||
* misrepresented as being the original software.
|
||
*
|
||
* 3. This notice may not be removed or altered from any source distribution.
|
||
*
|
||
*
|
||
* $Date: 10. October 2018
|
||
* $Revision: V1.0.0
|
||
*
|
||
* Project: Flash Device Description for
|
||
* STM32H743 W25Q256 SPIFI Flash
|
||
* --------------------------------------------------------------------------- */
|
||
|
||
#include "FlashOS.H" // FlashOS Structures
|
||
#include "stm32h7xx.h"
|
||
#include "bsp_qspi_flash.h"
|
||
#include "bsp_led.h"
|
||
|
||
typedef uint32_t u32;
|
||
typedef uint16_t u16;
|
||
typedef uint8_t u8;
|
||
|
||
typedef volatile uint32_t vu32;
|
||
typedef volatile uint16_t vu16;
|
||
typedef volatile uint8_t vu8;
|
||
|
||
#define PAGE_SIZE 512
|
||
|
||
/*
|
||
* Initialize Flash Programming Functions
|
||
* Parameter: adr: Device Base Address
|
||
* clk: Clock Frequency (Hz)
|
||
* fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
|
||
* Return Value: 0 - OK, 1 - Failed
|
||
*/
|
||
|
||
static void SystemClock_Config(void);
|
||
uint8_t aux_buf[PAGE_SIZE];
|
||
uint32_t base_adr;
|
||
|
||
uint32_t Address = 0, SECTORError = 0, Index = 0;
|
||
__IO uint64_t data64 = 0;
|
||
|
||
unsigned int Bootloader_size(void);
|
||
|
||
extern const unsigned char BootloaderImage[];
|
||
|
||
uint32_t ISBootloadrOK(void)
|
||
{
|
||
__IO uint32_t MemoryProgramStatus = 0;
|
||
/* <20><><EFBFBD><EFBFBD>BootLoader<65>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||
MemoryProgramStatus = 0: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
MemoryProgramStatus != 0: <20><><EFBFBD><EFBFBD>ȱʧ */
|
||
Address = 0x08000000;
|
||
MemoryProgramStatus = 0x0;
|
||
|
||
while (Address < 0x08000000+Bootloader_size())
|
||
{
|
||
|
||
data64 = *(uint64_t*)Address;
|
||
__DSB();
|
||
if(data64 != ((uint64_t*)BootloaderImage)[Index])
|
||
{
|
||
MemoryProgramStatus++;
|
||
}
|
||
Address +=8;
|
||
Index++;
|
||
}
|
||
return MemoryProgramStatus;
|
||
}
|
||
|
||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>keil<69><6C><EFBFBD>غ<EFBFBD><D8BA><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD>һ<EFBFBD>δ˺<CEB4><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>ô˺<C3B4><CBBA><EFBFBD>֮ǰkeil<69>Ḵλ<E1B8B4><CEBB>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD><EFBFBD>൱<EFBFBD>ڵ<EFBFBD>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ҫ<EFBFBD><D2AA>ʼ<EFBFBD><CABC>һ<EFBFBD><D2BB>
|
||
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
|
||
|
||
if(fnc==1)
|
||
{/* WORKAROUND for BL: Disable interrupts to avoid SPI/DMA interrupts enabled by BL */
|
||
__disable_irq();
|
||
|
||
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD><EFBFBD>븴<EFBFBD>ӵ<EFBFBD>оƬ<D0BE><C6AC><EFBFBD><EFBFBD> */
|
||
/* ʹ<><CAB9>ָ<EFBFBD><EFBFBD><EEBBBA> */
|
||
// SCB_EnableICache();
|
||
/* ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD> */
|
||
// SCB_EnableDCache();
|
||
|
||
/* Init value with the default clock after reset. Needed by HAL drivers */
|
||
SystemInit();
|
||
|
||
HAL_Init();
|
||
|
||
SystemClock_Config();
|
||
|
||
LED_GPIO_Config();
|
||
/* <20><><EFBFBD><EFBFBD>BootLoader<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
||
if (ISBootloadrOK() != 0)
|
||
{
|
||
static FLASH_EraseInitTypeDef EraseInitStruct;
|
||
|
||
/* <20><><EFBFBD><EFBFBD>Flash<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƼĴ<C6BC><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
||
HAL_FLASH_Unlock();
|
||
|
||
/* <20><><EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD>ṹ<EFBFBD><E1B9B9>*/
|
||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
||
EraseInitStruct.Banks = FLASH_BANK_1;
|
||
EraseInitStruct.Sector = FLASH_SECTOR_0;
|
||
EraseInitStruct.NbSectors = 1;
|
||
|
||
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
|
||
{
|
||
return (1);
|
||
}
|
||
|
||
/* <20><><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>û<EFBFBD>Flash<73><68><EFBFBD><EFBFBD> */
|
||
|
||
Address = 0x08000000;
|
||
Index =0;
|
||
while (Address < 0x08000000+Bootloader_size())
|
||
{
|
||
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, Address, ((uint32_t)BootloaderImage)+Index) == HAL_OK)
|
||
{
|
||
Address = Address + 32;
|
||
Index = Index + 32;
|
||
}
|
||
else
|
||
{
|
||
return (1);
|
||
}
|
||
}
|
||
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƼĴ<C6BC><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD>鱣<EFBFBD><E9B1A3><EFBFBD><EFBFBD><EFBFBD>治<EFBFBD>ܿ<EFBFBD><DCBF>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>***/
|
||
HAL_FLASH_Lock();
|
||
}
|
||
|
||
/*<2A><>ʼ<EFBFBD><CABC>Flash*/
|
||
QSPI_FLASH_Init();
|
||
}
|
||
base_adr = adr;
|
||
return (0);
|
||
}
|
||
|
||
|
||
/*
|
||
* De-Initialize Flash Programming Functions
|
||
* Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
|
||
* Return Value: 0 - OK, 1 - Failed
|
||
*/
|
||
|
||
int UnInit (unsigned long fnc) {
|
||
|
||
return (0);
|
||
}
|
||
|
||
|
||
/*
|
||
* Erase complete Flash Memory
|
||
* Return Value: 0 - OK, 1 - Failed
|
||
*/
|
||
|
||
int EraseChip (void) {
|
||
uint8_t res = QSPI_ERROR;
|
||
res = BSP_QSPI_Erase_Chip();
|
||
if(res != QSPI_OK)
|
||
return (1);/* Finished with Errors */
|
||
else
|
||
return (0);/* Finished without Errors */
|
||
}
|
||
|
||
|
||
/*
|
||
* Erase Sector in Flash Memory
|
||
* Parameter: adr: Sector Address
|
||
* Return Value: 0 - OK, 1 - Failed
|
||
*/
|
||
|
||
int EraseSector (unsigned long adr) {
|
||
uint8_t res = QSPI_ERROR;
|
||
res = BSP_QSPI_Erase_Block(adr-base_adr);
|
||
if(res != QSPI_OK)
|
||
{
|
||
return (1);
|
||
} /* Finished with Errors */
|
||
else
|
||
return (0); /* Finished without Errors */
|
||
}
|
||
|
||
|
||
/*
|
||
* Blank Check Checks if Memory is Blank
|
||
* Parameter: adr: Block Start Address
|
||
* sz: Block Size (in bytes)
|
||
* pat: Block Pattern
|
||
* Return Value: 0 - OK, 1 - Failed
|
||
*/
|
||
|
||
int BlankCheck (unsigned long adr, unsigned long sz, unsigned char pat) {
|
||
return (1); /* Always Force Erase */
|
||
}
|
||
|
||
|
||
/*
|
||
* Program Page in Flash Memory
|
||
* Parameter: adr: Page Start Address
|
||
* sz: Page Size
|
||
* buf: Page Data
|
||
* Return Value: 0 - OK, 1 - Failed
|
||
*/
|
||
|
||
int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {
|
||
|
||
uint8_t res = QSPI_ERROR;
|
||
res = BSP_QSPI_Write(buf,adr-base_adr,sz);
|
||
if(res != QSPI_OK)
|
||
return (1); /* Finished with Errors */
|
||
else
|
||
return (0); /* Finished without Errors */
|
||
}
|
||
|
||
|
||
/*
|
||
* Verify Flash Contents
|
||
* Parameter: adr: Start Address
|
||
* sz: Size (in bytes)
|
||
* buf: Data
|
||
* Return Value: (adr+sz) - OK, Failed Address
|
||
*/
|
||
|
||
/*
|
||
Verify function is obsolete because all other function leave
|
||
the SPIFI in memory mode so a memory compare could be used.
|
||
*/
|
||
unsigned long Verify (unsigned long adr, unsigned long sz, unsigned char *buf) {
|
||
|
||
int numWR;// ʵ<>ʶ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
int oriAddr=adr,oriSize=sz;// <20><>¼ԭ<C2BC><D4AD>ַ<EFBFBD>ʹ<EFBFBD>С
|
||
uint8_t res = QSPI_ERROR;
|
||
|
||
while(sz!=0)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>sz<73><7A><EFBFBD><EFBFBD>PAGE_SIZE<5A><45><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>ȡ<EFBFBD><C8A1>һ<EFBFBD>ζ<EFBFBD>PAGE_SIZE<5A><45><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ϊsz-=numWR<57><52>
|
||
if(sz>PAGE_SIZE)
|
||
{
|
||
numWR=PAGE_SIZE;
|
||
sz-=numWR;
|
||
}
|
||
else
|
||
{
|
||
numWR=sz;// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>PAGE_SIZE<5A><45>ֱ<EFBFBD>Ӷ<EFBFBD>ȡnumWR<57><52><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>szΪ0<CEAA><30>
|
||
sz=0;
|
||
}
|
||
|
||
res = BSP_QSPI_FastRead(aux_buf,adr-base_adr,numWR);
|
||
if(res == QSPI_OK)
|
||
{
|
||
for (int i = 0; i< numWR; i++)
|
||
{
|
||
if (aux_buf[i] != buf[i])
|
||
return (adr+i); // Verification Failed (return address)
|
||
}
|
||
adr+=numWR;// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>ĵ<EFBFBD>ַ
|
||
}
|
||
else
|
||
{
|
||
return (0x0badc0de);// failed
|
||
}
|
||
}
|
||
|
||
return (oriAddr+oriSize); // Done successfully
|
||
}
|
||
|
||
static void SystemClock_Config(void)
|
||
{
|
||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||
|
||
/** Supply configuration update enable
|
||
*/
|
||
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
|
||
/** Configure the main internal regulator output voltage
|
||
*/
|
||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
|
||
|
||
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
|
||
/** Initializes the RCC Oscillators according to the specified parameters
|
||
* in the RCC_OscInitTypeDef structure.
|
||
*/
|
||
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 = 5;
|
||
RCC_OscInitStruct.PLL.PLLN = 192;
|
||
RCC_OscInitStruct.PLL.PLLP = 2;
|
||
RCC_OscInitStruct.PLL.PLLQ = 2;
|
||
RCC_OscInitStruct.PLL.PLLR = 2;
|
||
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
|
||
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
|
||
RCC_OscInitStruct.PLL.PLLFRACN = 0;
|
||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||
{
|
||
while(1);
|
||
}
|
||
/** Initializes the CPU, AHB and APB buses clocks
|
||
*/
|
||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|
||
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
|
||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
|
||
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
|
||
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
|
||
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
|
||
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
|
||
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
|
||
|
||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
|
||
{
|
||
while(1);
|
||
}
|
||
}
|