赞
踩
内嵌的闪存存储器可以用于在线编程(ICP)或在程序中编程(IAP)烧写。
在线编程 (In-Circuit Programming - ICP) 方式用于更新闪存存储器的全部内容, 它通过 JTAG、 SWD协议或系统加载程序(Bootloader)下载用户应用程序到微控制器中。
ICP 是一种快速有效的编程方法,消除了封装和管座的困扰。
与 ICP 方式对应,在程序中编程(In-Application Programming - IAP)可以使用微控制器支持的任一种通信接口(如 I/O 端口、USB、CAN、UART、I2C、SPI 等)下载程序或数据到存储器中。
IAP 允许用户在程序运行时重新烧写闪存存储器中的内容.
然而,IAP 要求至少有一部分程序已经使用 ICP烧到闪存存储器中。
闪存接口是在 AHB 协议上实现了对指令和数据的访问,它通过对存储器的预取缓存,加快了存储器的访问;
闪存接口还实现了在所有工作电压下对闪存编程和擦除所需的逻辑电路,这里还包括访问和写入保护以及选择字节的控制。
uint8_t bsp_flash_erase_page(uint32_t page_addr, uint32_t page_num);
uint8_t bsp_flash_read_byte(uint32_t addr);
bool bsp_flash_read_nbyte(uint32_t addr, uint8_t *data, uint32_t len);
uint16_t bsp_flash_read_halfword(uint32_t addr);
uint32_t bsp_flash_read_word(uint32_t addr);
bool bsp_flash_write_byte(uint32_t addr, uint8_t data);
bool bsp_flash_write_nbyte(uint32_t addr, uint8_t *data, uint32_t len);
bool bsp_flash_write_nbyte_s(uint32_t addr, uint8_t *data, uint32_t len);
bool bsp_flash_write_word(uint32_t addr, uint32_t data);
bool bsp_flash_is_busy(void);
bool bsp_flash_carry(uint32_t t_addr, uint32_t s_addr, uint32_t size);
/********************************************************************************
* @file bsp_flash.c
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-09-30
* @brief flash读写操作
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "RTE_Components.h"
#include CMSIS_device_header
#include "bsp_flash.h"
#include "sys_api.h"
/* Private Includes ----------------------------------------------------------*/
#include "business_gpio.h"
#include "business_function.h"
/* Private Define ------------------------------------------------------------*/
#define BSP_FLASH_PAGE_SIZE BS_FLASH_PAGE_SIZE
/* Private Variables ---------------------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
/**
* @brief Flash erase page
* @param page_addr: flash addr example
* @param page_num: Number of pages to erase
* @retval status
*/
uint8_t bsp_flash_erase_page(uint32_t page_addr, uint32_t page_num)
{
uint32_t i;
// 一页 512 字节
if (page_addr % BSP_FLASH_PAGE_SIZE != 0)
{
page_addr -= (page_addr % BSP_FLASH_PAGE_SIZE);
}
if (page_addr < 1)
{
page_addr = 1;
}
FLASH_Unlock();
for (i = 0; i < page_num; i++)
{
FLASH_ErasePage(page_addr + i * BSP_FLASH_PAGE_SIZE);
}
FLASH_Lock();
return 0;
}
/**
* @brief flash 读字节
* @param addr: flash地址
* @retval 字节内容
*/
uint8_t bsp_flash_read_byte(uint32_t addr)
{
return (uint8_t)*(uint32_t *)(addr);
}
/**
* @brief flash 读多字节
* @param addr: flash地址
* @param *data: 缓存buff地址
* @param len: 读取长度
* @retval 0--失败 1--成功
*/
bool bsp_flash_read_nbyte(uint32_t addr, uint8_t *data, uint32_t len)
{
uint32_t i;
if (len == 0)
{
return false;
}
for (i = 0; i < len; i++)
{
*(data + i) = bsp_flash_read_byte(addr + i);
}
return true;
}
/**
* @brief flash 读半字
* @param addr: flash地址
* @retval 半字内容
*/
uint16_t bsp_flash_read_halfword(uint32_t addr)
{
return (uint16_t)*(uint32_t *)(addr);
}
/**
* @brief flash 读字
* @param addr: flash地址
* @retval 字内容
*/
uint32_t bsp_flash_read_word(uint32_t addr)
{
return (uint32_t)*(uint32_t *)(addr);
}
/**
* @brief flash 写字节
* @param addr: flash地址
* @param data: 字节
* @retval 0--失败 1--成功
*/
bool bsp_flash_write_byte(uint32_t addr, uint8_t data)
{
FLASH_Unlock();
if (FLASH_ProgramByte(addr, data))
{
FLASH_Lock();
return false;
}
FLASH_Lock();
return true;
}
/**
* @brief flash 写字
* @param addr: flash地址
* @param data: 字
* @retval 0--失败 1--成功
*/
bool bsp_flash_write_word(uint32_t addr, uint32_t data)
{
FLASH_Unlock();
if (FLASH_ProgramWord(addr, data))
{
FLASH_Lock();
return false;
}
FLASH_Lock();
return true;
}
/**
* @brief flash 写多字节
* @param addr: flash地址
* @param *data: 数据缓冲区
* @param len: 数据长度
* @retval 0--失败 1--成功
*/
bool bsp_flash_write_nbyte(uint32_t addr, uint8_t *data, uint32_t len)
{
uint32_t i;
if (len == 0)
{
return false;
}
FLASH_Unlock();
for (i = 0; i < len; i++)
{
FLASH_ProgramByte((addr + i), *(data + i));
}
FLASH_Lock();
return true;
}
/**
* @brief 得到flash每页字节大小
* @note
* @retval
*/
uint16_t bsp_flash_get_page_size(void)
{
return BSP_FLASH_PAGE_SIZE;
}
/**
* @brief flash 写多字节(带关闭中断函数)
* @param addr: flash地址
* @param *data: 数据缓冲区
* @param len: 数据长度
* @retval 0--失败 1--成功
*/
bool bsp_flash_write_nbyte_s(uint32_t addr, uint8_t *data, uint32_t len)
{
bool ret;
sys_disable_irq();
ret = bsp_flash_write_nbyte(addr, data, len);
sys_enable_irq();
return ret;
}
bool bsp_flash_is_busy(void)
{
if (FLASH->STS == 1)
{
return true;
}
else
{
return false;
}
}
/**
* @brief flash搬运 (addr2 搬运到 addr1 ,并擦除addr1)
* @param t_addr: 目标地址(addr1)
* @param s_addr: 欲搬地址(addr2)
* @param size: 字节大小
* @retval 0--失败 1--成功
*/
bool bsp_flash_carry(uint32_t t_addr, uint32_t s_addr, uint32_t size)
{
bool ret = true;
uint32_t word_len;
uint32_t page_len;
uint32_t i;
word_len = (size / sizeof(uint32_t));
page_len = (size % BSP_FLASH_PAGE_SIZE) == 0 ?
(size / BSP_FLASH_PAGE_SIZE) : (size / BSP_FLASH_PAGE_SIZE) + 1;
for (i = 0; i < page_len; i++)
{
bsp_flash_erase_page(t_addr + i * BSP_FLASH_PAGE_SIZE, 1);
}
while(bsp_flash_is_busy());
for (i = 0; i < word_len; i++)
{
ret = bsp_flash_write_word(t_addr + i * sizeof(uint32_t),
bsp_flash_read_word(s_addr + i * sizeof(uint32_t)));
if (ret == false)
{
break;
}
}
if (ret == true)
{
for (i = 0; i < page_len; i++)
{
bsp_flash_erase_page(s_addr + i * BSP_FLASH_PAGE_SIZE, 1);
}
}
return ret;
}
/********************************************************************************
* @file bsp_flash.h
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-04-03
* @brief flash操作
********************************************************************************/
#ifndef __BSP_FLASH_H
#define __BSP_FLASH_H
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
/* Public struct ------------------------------------------------------------*/
typedef struct
{
uint32_t usercfg0;
uint32_t usercfg1;
uint32_t usercfg2;
uint32_t boot_state; // 0--run app 1--in dfu 2--move ota in app
uint32_t boot_run_tick; // 掉电次数
uint32_t boot_carry_size; // 需要复制的字节数量
uint32_t app_crc; // app 运行前先crc校验,防止app损坏
uint32_t chip_lock; // 任意值--锁住swo XXXX--特殊码解锁swo
} option_bytes_t;
typedef struct
{
uint8_t boot_state; // 0--run app 1--in dfu 2--move ota in app
uint16_t boot_run_tick; // 掉电次数
uint32_t boot_carry_size; // 需要复制的字节数量
uint16_t app_crc; // app 运行前先crc校验,防止app损坏
uint16_t chip_lock; // 任意值--锁住swo XXXX--特殊码解锁swo
} boot_info_t;
/* Public Function Prototypes ------------------------------------------------*/
uint8_t bsp_flash_erase_page(uint32_t page_addr, uint32_t page_num);
uint8_t bsp_flash_read_byte(uint32_t addr);
bool bsp_flash_read_nbyte(uint32_t addr, uint8_t *data, uint32_t len);
uint16_t bsp_flash_read_halfword(uint32_t addr);
uint32_t bsp_flash_read_word(uint32_t addr);
bool bsp_flash_write_byte(uint32_t addr, uint8_t data);
bool bsp_flash_write_nbyte(uint32_t addr, uint8_t *data, uint32_t len);
bool bsp_flash_write_nbyte_s(uint32_t addr, uint8_t *data, uint32_t len);
bool bsp_flash_write_word(uint32_t addr, uint32_t data);
bool bsp_flash_is_busy(void);
bool bsp_flash_carry(uint32_t t_addr, uint32_t s_addr, uint32_t size);
#endif
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。