打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

LiSun

打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  1. 本芯片包含 1 颗 64K / 32K Byte 容量的嵌入式 Flash 存储器,包括一个 128 / 64 sector 的 Main Array区域,一个 8 sector 的 NVR 区域。每个 sector 的容量为 512 Byte。Flash 的 Main Array 区域是给用户使用的, 可以存放用户开发的程序和数据。 NVR 区域中, 一个 sector 用于存放系统配置, 一个 sector用于存放选项字节,其余的 6 个 sector 用于存放系统的 ISP 程序。本模块支持对 Flash 存储器的擦除、编程以及读取操作。此外,本模块支持对 Flash 存储器擦写的保护,以及控制寄存器的写保护。
    在这里插入图片描述
    Main Array 区域用于存放用户的代码。
    NVR 区域的 sector 0~5 这 6 个 sector 用于存放厂家提供的系统 ISP(在系统可编程)代码,用户可以通过 ISP 代码下载开发的应用程序,用户程序不能对 ISP 代码进行读取或者擦除操作。NVR 区域的Sector 6 是选项字节区域, 用于用户实现部分系统功能的配置。 NVR 区域的 Sector 7 是系统配置区,用于存放系统配置值。

本控制器支持对 Flash 的 byte(8bits)、 half-word(16bits)、 word(32bits)三种位宽读写操作。 注意, byte操作的地址必须按 byte 对齐,half-word 操作的目标地址必须按 half-word 对齐(地址最低位为 0),word 操作的目标地址必须按 word 对齐(地址最低两位为 0)。如果读写操作的地址没有按照位宽规定对齐,该操作无效,并且系统会进入 hard fault 出错中断。

/********************************************************************************
* @file    bsp_flash.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2021-04-15
* @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  FLASH_PAGE_SIZE
/* Private Variables ---------------------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
/**
  * @brief  Flash erase page
  * @param  page_addr: flash addr example,0xFE00(63.5K)
  * @param  page_num: Number of pages to erase
  * @retval status
  */
uint8_t bsp_flash_erase_page(uint32_t page_addr, uint32_t page_num)
{
    FLASH_EraseInitTypeDef flash_erase_init_t;
    uint32_t error_page; //记录错误的写入位置

    // 一页 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_erase_init_t.TypeErase   = FLASH_TYPEERASE_PAGES;
    flash_erase_init_t.PageAddress = page_addr;
    flash_erase_init_t.NbPages     = page_num;

    return HAL_FLASH_Erase(&flash_erase_init_t, &error_page);
}

/**
 * @brief  flash 读字节
 * @note   NULL
 * @param  addr: flash地址
 * @retval 字节内容
 */
uint8_t bsp_flash_read_byte(uint32_t addr)
{
    return (uint8_t)*(uint32_t *)(addr);
}

/**
 * @brief  flash 读多字节
 * @note   NULL
 * @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 读半字
 * @note   NULL
 * @param  addr: flash地址
 * @retval 半字内容
 */
uint16_t bsp_flash_read_halfword(uint32_t addr)
{
    return (uint16_t)*(uint32_t *)(addr);
}

/**
 * @brief  flash 读字
 * @note   NULL
 * @param  addr: flash地址
 * @retval 字内容
 */
uint32_t bsp_flash_read_word(uint32_t addr)
{
    return (uint32_t)*(uint32_t *)(addr);
}

/**
 * @brief  flash 写字节
 * @note   NULL
 * @param  addr: flash地址
 * @param  data: 字节
 * @retval 0--失败 1--成功
 */
bool bsp_flash_write_byte(uint32_t addr, uint8_t data)
{
    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, addr, data))
    {
        return false;
    }
    return true;
}

/**
 * @brief  flash 写字
 * @note   NULL
 * @param  addr: flash地址
 * @param  data: 字
 * @retval 0--失败 1--成功
 */
bool bsp_flash_write_word(uint32_t addr, uint32_t data)
{
    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr, data))
    {
        return false;
    }
    return true;
}

/**
 * @brief  flash 写多字节
 * @note   NULL
 * @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;
    }

    for (i = 0; i < len; i++)
    {
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, (addr + i), *(data + i));
    }

    return true;
}

/**
 * @brief  得到flash每页字节大小
 * @note   
 * @retval 
 */
uint16_t bsp_flash_get_page_size(void)
{
    return BSP_FLASH_PAGE_SIZE;
}

/**
 * @brief  flash 写多字节(带关闭中断函数)
 * @note   NULL
 * @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;
}

/**
 * @brief  flash搬运 (addr2 搬运到 addr1 ,并擦除addr1)
 * @note   NULL
 * @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);
    }

    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
{
    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
} 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);

uint16_t bsp_flash_get_page_size(void);

bool bsp_flash_carry(uint32_t t_addr, uint32_t s_addr, uint32_t size);

#endif

posted on 2022-08-13 11:00  xuejianqiang  阅读(102)  评论(0编辑  收藏  举报
打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033