250 lines
7.0 KiB
C
250 lines
7.0 KiB
C
/**
|
||
**************************************************************************
|
||
* @file flash.c
|
||
* @brief flash program
|
||
**************************************************************************
|
||
* Copyright notice & Disclaimer
|
||
*
|
||
* The software Board Support Package (BSP) that is made available to
|
||
* download from Artery official website is the copyrighted work of Artery.
|
||
* Artery authorizes customers to use, copy, and distribute the BSP
|
||
* software and its related documentation for the purpose of design and
|
||
* development in conjunction with Artery microcontrollers. Use of the
|
||
* software is governed by this copyright notice and the following disclaimer.
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
|
||
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
|
||
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
|
||
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
|
||
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
|
||
*
|
||
**************************************************************************
|
||
*/
|
||
|
||
#include "bsp_flash.h"
|
||
#include "string.h"
|
||
|
||
/** @addtogroup AT32A423_periph_examples
|
||
* @{
|
||
*/
|
||
|
||
#if defined (AT32A423xC)
|
||
#define SECTOR_SIZE 2048 /* this parameter depends on the specific model of the chip */
|
||
#else
|
||
#define SECTOR_SIZE 1024 /* this parameter depends on the specific model of the chip */
|
||
#endif
|
||
|
||
#define FLASH_HEAD 0XA55AA55A
|
||
#define FLASH_TAIL 0X5AA55AA5
|
||
|
||
uint16_t flash_buf[SECTOR_SIZE / 2];
|
||
|
||
/**
|
||
* @brief read data using halfword mode
|
||
* @param read_addr: the address of reading
|
||
* @param p_buffer: the buffer of reading data
|
||
* @param num_read: the number of reading data
|
||
* @retval 0 = success, 1 = fail
|
||
*/
|
||
uint8_t flash_read(uint32_t read_addr, void *p_buffer, uint32_t num_read)
|
||
{
|
||
uint16_t *buf = (uint16_t *)p_buffer;
|
||
uint32_t i;
|
||
|
||
for(i = 0; i < num_read; i++)
|
||
{
|
||
buf[i] = *(uint16_t*)(read_addr);
|
||
read_addr += 2;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief write data using halfword mode without checking
|
||
* @param write_addr: the address of writing
|
||
* @param p_buffer: the buffer of writing data
|
||
* @param num_write: the number of writing data
|
||
* @retval 0 = success, 1 = fail
|
||
*/
|
||
uint8_t flash_write_nocheck(uint32_t write_addr, const void *p_buffer, uint32_t num_write)
|
||
{
|
||
uint16_t *buf = (uint16_t *)p_buffer;
|
||
uint32_t i;
|
||
flash_status_type status = FLASH_OPERATE_DONE;
|
||
|
||
for(i = 0; i < num_write; i++)
|
||
{
|
||
status = flash_halfword_program(write_addr, buf[i]);
|
||
if(status != FLASH_OPERATE_DONE)
|
||
return 1;
|
||
write_addr += 2;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief write data using halfword mode with checking
|
||
* @param write_addr: the address of writing
|
||
* @param p_buffer: the buffer of writing data
|
||
* @param num_write: the number of writing data
|
||
* @retval 0 = success, 1 = fail
|
||
*/
|
||
uint8_t flash_write(uint32_t write_addr, const void *p_buffer, uint32_t num_write)
|
||
{
|
||
uint16_t *buf = (uint16_t *)p_buffer;
|
||
uint32_t offset_addr;
|
||
uint32_t sector_position;
|
||
uint32_t sector_offset;
|
||
uint32_t sector_remain;
|
||
uint32_t i;
|
||
flash_status_type status = FLASH_OPERATE_DONE;
|
||
|
||
flash_unlock();
|
||
offset_addr = write_addr - FLASH_BASE;
|
||
sector_position = offset_addr / SECTOR_SIZE;
|
||
sector_offset = (offset_addr % SECTOR_SIZE) / 2;
|
||
sector_remain = (SECTOR_SIZE / 2) - sector_offset;
|
||
|
||
if(num_write <= sector_remain)
|
||
sector_remain = num_write;
|
||
|
||
while(1)
|
||
{
|
||
flash_read(sector_position * SECTOR_SIZE + FLASH_BASE, flash_buf, SECTOR_SIZE / 2);
|
||
for(i = 0; i < sector_remain; i++)
|
||
{
|
||
if(flash_buf[sector_offset + i] != 0xFFFF)
|
||
break;
|
||
}
|
||
if(i < sector_remain)
|
||
{
|
||
status = flash_operation_wait_for(ERASE_TIMEOUT);
|
||
|
||
if((status == FLASH_PROGRAM_ERROR) || (status == FLASH_EPP_ERROR))
|
||
flash_flag_clear(FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);
|
||
else if(status == FLASH_OPERATE_TIMEOUT)
|
||
{
|
||
flash_lock();
|
||
return 1;
|
||
}
|
||
status = flash_sector_erase(sector_position * SECTOR_SIZE + FLASH_BASE);
|
||
if(status != FLASH_OPERATE_DONE)
|
||
{
|
||
flash_lock();
|
||
return 1;
|
||
}
|
||
for(i = 0; i < sector_remain; i++)
|
||
{
|
||
flash_buf[i + sector_offset] = buf[i];
|
||
}
|
||
if(flash_write_nocheck(sector_position * SECTOR_SIZE + FLASH_BASE, flash_buf, SECTOR_SIZE / 2) != 0)
|
||
{
|
||
flash_lock();
|
||
return 1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(flash_write_nocheck(write_addr, buf, sector_remain) != 0)
|
||
{
|
||
flash_lock();
|
||
return 1;
|
||
}
|
||
}
|
||
if(num_write == sector_remain)
|
||
break;
|
||
else
|
||
{
|
||
sector_position++;
|
||
sector_offset = 0;
|
||
buf += sector_remain;
|
||
write_addr += (sector_remain * 2);
|
||
num_write -= sector_remain;
|
||
if(num_write > (SECTOR_SIZE / 2))
|
||
sector_remain = SECTOR_SIZE / 2;
|
||
else
|
||
sector_remain = num_write;
|
||
}
|
||
}
|
||
flash_lock();
|
||
return 0;
|
||
}
|
||
|
||
int load_config_params(flash_para_struct *params)
|
||
{
|
||
uint32_t *head = (uint32_t*)FMC_WRITE_START_ADDR;
|
||
uint32_t *tail = (uint32_t*)(FMC_WRITE_START_ADDR + sizeof(flash_para_struct) - 4);
|
||
|
||
if(*head == FLASH_HEAD && *tail == FLASH_TAIL)
|
||
{
|
||
memcpy((uint32_t *)params, head, sizeof(flash_para_struct));
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
int save_config_params(flash_para_struct *params)
|
||
{
|
||
params->flash_head = FLASH_HEAD;
|
||
params->flash_tail = FLASH_TAIL;
|
||
flash_write(FMC_WRITE_START_ADDR, params, sizeof(flash_para_struct)/sizeof(uint16_t));
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
* @param sector_addr <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ַ
|
||
* @param len <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>δʹ<CEB4>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ֽӿڼ<D3BF><DABC>ݣ<EFBFBD>
|
||
* @return 0 = success, 1 = fail
|
||
*/
|
||
uint8_t flash_erase(uint32_t sector_addr, uint32_t len)
|
||
{
|
||
flash_status_type status;
|
||
|
||
flash_unlock();
|
||
status = flash_operation_wait_for(ERASE_TIMEOUT);
|
||
if(status == FLASH_OPERATE_TIMEOUT)
|
||
{
|
||
flash_lock();
|
||
return 1;
|
||
}
|
||
|
||
if((status == FLASH_PROGRAM_ERROR) || (status == FLASH_EPP_ERROR))
|
||
{
|
||
flash_flag_clear(FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);
|
||
}
|
||
|
||
status = flash_sector_erase(sector_addr);
|
||
flash_lock();
|
||
|
||
return (status == FLASH_OPERATE_DONE) ? 0 : 1;
|
||
}
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
uint8_t bsp_flash_is_erased(uint32_t addr, uint32_t size)
|
||
{
|
||
const uint8_t *flash_ptr = (const uint8_t *)addr;
|
||
uint32_t i;
|
||
|
||
for (i = 0U; i < size; i++)
|
||
{
|
||
if (flash_ptr[i] != 0xFF)
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|