更新硬件SDK

This commit is contained in:
kerwincui
2023-03-04 03:44:56 +08:00
parent dcdf6e1b7c
commit e39d3d2f03
1900 changed files with 663153 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
/*
* File : fal.c
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2018-05-17 armink the first version
*/
#include <fal.h>
static uint8_t init_ok = 0;
/**
* FAL (Flash Abstraction Layer) initialization.
* It will initialize all flash device and all flash partition.
*
* @return >= 0: partitions total number
*/
int fal_init(void)
{
extern int fal_flash_init(void);
extern int fal_partition_init(void);
int result;
/* initialize all flash device on FAL flash table */
result = fal_flash_init();
if (result < 0) {
goto __exit;
}
/* initialize all flash partition on FAL partition table */
result = fal_partition_init();
__exit:
if ((result > 0) && (!init_ok))
{
init_ok = 1;
log_i("Flash Abstraction Layer (V%s) initialize success.", FAL_SW_VERSION);
}
else if(result <= 0)
{
init_ok = 0;
log_e("Flash Abstraction Layer (V%s) initialize failed.", FAL_SW_VERSION);
}
return result;
}
/**
* Check if the FAL is initialized successfully
*
* @return 0: not init or init failed; 1: init success
*/
int fal_init_check(void)
{
return init_ok;
}

View File

@@ -0,0 +1,136 @@
#include "common_api.h"
#include "FreeRTOS.h"
#include "task.h"
#include "lfs_port.h"
#include "rng.h"
#include "lfs_util.h"
#include "flash_rt.h"
#include "mem_map.h"
#include DEBUG_LOG_HEADER_FILE
#include "osasys.h"
#include "plat_config.h"
#include "fal.h"
#define BLOCK_SIZE (4096)
#define TOTOL_SIZE (64*1024)
#define MEM_MODE 0
#if MEM_MODE
static uint8_t vbuff[TOTOL_SIZE];
static int (onchip_flash_init)(void) {
memset(vbuff, 0, TOTOL_SIZE);
return 0;
}
static int (onchip_flash_read)(long offset, uint8_t *buf, size_t size) {
if (size == 0)
return 0;
memcpy(buf, vbuff + offset, size);
return size;
}
static int (onchip_flash_write)(long offset, const uint8_t *buf, size_t size) {
if (size == 0)
return 0;
memcpy(vbuff + offset, buf, size);
return size;
}
static int (onchip_flash_erase)(long offset, size_t size) {
memset(vbuff + offset, 0, size);
return 0;
}
#else // MEM_MODE == 0
// static void mem_diff(const char* tag) {
// int ret = 0;
// uint8_t *tmp = malloc(BLOCK_SIZE);
// for (size_t offset = 0; offset < TOTOL_SIZE; offset+=BLOCK_SIZE)
// {
// ret = BSP_QSPI_Read_Safe((uint8_t *)tmp, (FLASH_FDB_REGION_START + offset), BLOCK_SIZE);
// if (ret != 0) {
// DBG("%s BSP_QSPI_Read_Safe ret %d %04X", tag, ret, offset);
// break;
// }
// if (memcmp(tmp, vbuff + offset, BLOCK_SIZE)) {
// DBG("%s Data NOT Match %04X", tag, offset);
// break;
// }
// }
// free(tmp);
// }
// extern uint8_t* QSPI_FLASH_ReadUUID(void);
static int (onchip_flash_init)(void) {
return 0;
}
static int (onchip_flash_read)(long offset, uint8_t *buf, size_t size) {
int ret = 0;
if (size == 0)
return 0;
ret = BSP_QSPI_Read_Safe((uint8_t *)buf, (FLASH_FDB_REGION_START + offset), size);
return ret == 0 ? size : -1; // 特别注意, 成功的时候, 要读取到的大小!!!
}
static int (onchip_flash_write)(long offset, const uint8_t *buf, size_t size) {
int ret = 0;
if (size == 0)
return 0;
// 注意, BSP_QSPI_Write_Safe 的buf不能是flash上的常量数据
// 写入flash时XIP会关闭, 导致buf值肯定读不到
// 下面的各种判断, 就是把常量数据拷贝到ram, 然后写入
uint8_t tmp_small[128];
uint8_t *tmp = NULL;
uint32_t addr = (uint32_t)buf;
if (size <= 128) {
// 对于较小的数据, 直接在栈内存里拷贝即可,不必判断
memcpy(tmp_small, buf, size);
ret = BSP_QSPI_Write_Safe((uint8_t *)tmp_small, (FLASH_FDB_REGION_START + offset), size);
}
else if (addr >= 0x00400000 && addr <= 0x00500000) {
// 数据已经处于ram, 可以直接写入
ret = BSP_QSPI_Write_Safe((uint8_t *)buf, (FLASH_FDB_REGION_START + offset), size);
}
else {
// 超过128字节的常量数据, 应该是不存在的吧, 下面的逻辑主要是防御代码.
tmp = malloc(size);
if (tmp == NULL) {
DBG("out of memory when malloc flash write buff");
return -1;
}
memcpy(tmp, buf, size);
ret = BSP_QSPI_Write_Safe((uint8_t *)tmp, (FLASH_FDB_REGION_START + offset), size);
free(tmp);
}
return ret == 0 ? size : -1; // 特别注意, 成功的时候, 要写入的大小!!!
}
static int (onchip_flash_erase)(long offset, size_t size) {
int ret = 0;
ret = BSP_QSPI_Erase_Safe((FLASH_FDB_REGION_START + offset), size);
return ret == 0 ? 0 : -1;
}
#endif // end of MEM_MODE
const struct fal_flash_dev onchip_flash = {
.name = "onchip_flash",
.len = TOTOL_SIZE,
.blk_size = BLOCK_SIZE,
.addr = 0,
.write_gran = 32,
.ops = {
.init = onchip_flash_init,
.read = onchip_flash_read,
.write = onchip_flash_write,
.erase = onchip_flash_erase
}
};

View File

@@ -0,0 +1,99 @@
/*
* File : fal_flash.c
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2018-05-17 armink the first version
*/
#include <fal.h>
#include <string.h>
/* flash device table, must defined by user */
#if !defined(FAL_FLASH_DEV_TABLE)
#error "You must defined flash device table (FAL_FLASH_DEV_TABLE) on 'fal_cfg.h'"
#endif
static const struct fal_flash_dev * const device_table[] = FAL_FLASH_DEV_TABLE;
static const size_t device_table_len = sizeof(device_table) / sizeof(device_table[0]);
static uint8_t init_ok = 0;
/**
* Initialize all flash device on FAL flash table
*
* @return result
*/
int fal_flash_init(void)
{
size_t i;
#if FAL_DEBUG
const struct fal_flash_dev *dev;
#endif
if (init_ok)
{
return 0;
}
for (i = 0; i < device_table_len; i++)
{
assert(device_table[i]->ops.read);
assert(device_table[i]->ops.write);
assert(device_table[i]->ops.erase);
/* init flash device on flash table */
if (device_table[i]->ops.init)
{
device_table[i]->ops.init();
}
#if FAL_DEBUG
dev = device_table[i];
log_d("Flash device | %*.*s | addr: 0x%08lx | len: 0x%08x | blk_size: 0x%08x |initialized finish.",
FAL_DEV_NAME_MAX, FAL_DEV_NAME_MAX, dev->name, dev->addr, dev->len,
dev->blk_size);
#endif
}
init_ok = 1;
return 0;
}
/**
* find flash device by name
*
* @param name flash device name
*
* @return != NULL: flash device
* NULL: not found
*/
const struct fal_flash_dev *fal_flash_device_find(const char *name)
{
assert(init_ok);
assert(name);
size_t i;
for (i = 0; i < device_table_len; i++)
{
if (!strncmp(name, device_table[i]->name, FAL_DEV_NAME_MAX)) {
return device_table[i];
}
}
return NULL;
}

View File

@@ -0,0 +1,497 @@
/*
* File : fal_partition.c
* This file is part of FAL (Flash Abstraction Layer) package
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2018-05-17 armink the first version
*/
#include <fal.h>
#include <string.h>
#include <stdlib.h>
/* partition magic word */
#define FAL_PART_MAGIC_WORD 0x45503130
#define FAL_PART_MAGIC_WORD_H 0x4550L
#define FAL_PART_MAGIC_WORD_L 0x3130L
#define FAL_PART_MAGIC_WROD 0x45503130
/**
* FAL partition table config has defined on 'fal_cfg.h'.
* When this option is disable, it will auto find the partition table on a specified location in flash partition.
*/
#ifdef FAL_PART_HAS_TABLE_CFG
/* check partition table definition */
#if !defined(FAL_PART_TABLE)
#error "You must defined FAL_PART_TABLE on 'fal_cfg.h'"
#endif
#ifdef __CC_ARM /* ARM Compiler */
#define SECTION(x) __attribute__((section(x)))
#define USED __attribute__((used))
#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */
#define SECTION(x) @ x
#define USED __root
#elif defined (__GNUC__) /* GNU GCC Compiler */
#define SECTION(x) __attribute__((section(x)))
#define USED __attribute__((used))
#else
#error not supported tool chain
#endif /* __CC_ARM */
//USED static const struct fal_partition partition_table_def[] SECTION("FalPartTable") = FAL_PART_TABLE;
static const struct fal_partition partition_table_def[] = FAL_PART_TABLE;
static const struct fal_partition *partition_table = NULL;
#else /* FAL_PART_HAS_TABLE_CFG */
#if !defined(FAL_PART_TABLE_FLASH_DEV_NAME)
#error "You must defined FAL_PART_TABLE_FLASH_DEV_NAME on 'fal_cfg.h'"
#endif
/* check partition table end offset address definition */
#if !defined(FAL_PART_TABLE_END_OFFSET)
#error "You must defined FAL_PART_TABLE_END_OFFSET on 'fal_cfg.h'"
#endif
static struct fal_partition *partition_table = NULL;
#endif /* FAL_PART_HAS_TABLE_CFG */
static uint8_t init_ok = 0;
static size_t partition_table_len = 0;
/**
* print the partition table
*/
void fal_show_part_table(void)
{
char *item1 = "name", *item2 = "flash_dev";
size_t i, part_name_max = strlen(item1), flash_dev_name_max = strlen(item2);
const struct fal_partition *part;
if (partition_table_len)
{
for (i = 0; i < partition_table_len; i++)
{
part = &partition_table[i];
if (strlen(part->name) > part_name_max)
{
part_name_max = strlen(part->name);
}
if (strlen(part->flash_name) > flash_dev_name_max)
{
flash_dev_name_max = strlen(part->flash_name);
}
}
}
log_i("==================== FAL partition table ====================");
log_i("| %-*.*s | %-*.*s | offset | length |", part_name_max, FAL_DEV_NAME_MAX, item1, flash_dev_name_max,
FAL_DEV_NAME_MAX, item2);
log_i("-------------------------------------------------------------");
for (i = 0; i < partition_table_len; i++)
{
#ifdef FAL_PART_HAS_TABLE_CFG
part = &partition_table[i];
#else
part = &partition_table[partition_table_len - i - 1];
#endif
log_i("| %-*.*s | %-*.*s | 0x%08lx | 0x%08x |", part_name_max, FAL_DEV_NAME_MAX, part->name, flash_dev_name_max,
FAL_DEV_NAME_MAX, part->flash_name, part->offset, part->len);
}
log_i("=============================================================");
}
/**
* Initialize all flash partition on FAL partition table
*
* @return partitions total number
*/
int fal_partition_init(void)
{
size_t i;
const struct fal_flash_dev *flash_dev = NULL;
if (init_ok)
{
return partition_table_len;
}
#ifdef FAL_PART_HAS_TABLE_CFG
partition_table = &partition_table_def[0];
partition_table_len = sizeof(partition_table_def) / sizeof(partition_table_def[0]);
#else
/* load partition table from the end address FAL_PART_TABLE_END_OFFSET, error return 0 */
long part_table_offset = FAL_PART_TABLE_END_OFFSET;
size_t table_num = 0, table_item_size = 0;
uint8_t part_table_find_ok = 0;
uint32_t read_magic_word;
fal_partition_t new_part = NULL;
flash_dev = fal_flash_device_find(FAL_PART_TABLE_FLASH_DEV_NAME);
if (flash_dev == NULL)
{
log_e("Initialize failed! Flash device (%s) NOT found.", FAL_PART_TABLE_FLASH_DEV_NAME);
goto _exit;
}
/* check partition table offset address */
if (part_table_offset < 0 || part_table_offset >= (long) flash_dev->len)
{
log_e("Setting partition table end offset address(%ld) out of flash bound(<%d).", part_table_offset, flash_dev->len);
goto _exit;
}
table_item_size = sizeof(struct fal_partition);
new_part = (fal_partition_t)FAL_MALLOC(table_item_size);
if (new_part == NULL)
{
log_e("Initialize failed! No memory for table buffer.");
goto _exit;
}
/* find partition table location */
{
uint8_t read_buf[64];
part_table_offset -= sizeof(read_buf);
while (part_table_offset >= 0)
{
if (flash_dev->ops.read(part_table_offset, read_buf, sizeof(read_buf)) > 0)
{
/* find magic word in read buf */
for (i = 0; i < sizeof(read_buf) - sizeof(read_magic_word) + 1; i++)
{
read_magic_word = read_buf[0 + i] + (read_buf[1 + i] << 8) + (read_buf[2 + i] << 16) + (read_buf[3 + i] << 24);
if (read_magic_word == ((FAL_PART_MAGIC_WORD_H << 16) + FAL_PART_MAGIC_WORD_L))
{
part_table_find_ok = 1;
part_table_offset += i;
log_d("Find the partition table on '%s' offset @0x%08lx.", FAL_PART_TABLE_FLASH_DEV_NAME,
part_table_offset);
break;
}
}
}
else
{
/* read failed */
break;
}
if (part_table_find_ok)
{
break;
}
else
{
/* calculate next read buf position */
if (part_table_offset >= (long)sizeof(read_buf))
{
part_table_offset -= sizeof(read_buf);
part_table_offset += (sizeof(read_magic_word) - 1);
}
else if (part_table_offset != 0)
{
part_table_offset = 0;
}
else
{
/* find failed */
break;
}
}
}
}
/* load partition table */
while (part_table_find_ok)
{
memset(new_part, 0x00, table_num);
if (flash_dev->ops.read(part_table_offset - table_item_size * (table_num), (uint8_t *) new_part,
table_item_size) < 0)
{
log_e("Initialize failed! Flash device (%s) read error!", flash_dev->name);
table_num = 0;
break;
}
if (new_part->magic_word != ((FAL_PART_MAGIC_WORD_H << 16) + FAL_PART_MAGIC_WORD_L))
{
break;
}
partition_table = (fal_partition_t) FAL_REALLOC(partition_table, table_item_size * (table_num + 1));
if (partition_table == NULL)
{
log_e("Initialize failed! No memory for partition table");
table_num = 0;
break;
}
memcpy(partition_table + table_num, new_part, table_item_size);
table_num++;
};
if (table_num == 0)
{
log_e("Partition table NOT found on flash: %s (len: %d) from offset: 0x%08x.", FAL_PART_TABLE_FLASH_DEV_NAME,
FAL_DEV_NAME_MAX, FAL_PART_TABLE_END_OFFSET);
goto _exit;
}
else
{
partition_table_len = table_num;
}
#endif /* FAL_PART_HAS_TABLE_CFG */
/* check the partition table device exists */
for (i = 0; i < partition_table_len; i++)
{
flash_dev = fal_flash_device_find(partition_table[i].flash_name);
if (flash_dev == NULL)
{
log_d("Warning: Do NOT found the flash device(%s).", partition_table[i].flash_name);
continue;
}
if (partition_table[i].offset >= (long)flash_dev->len)
{
log_e("Initialize failed! Partition(%s) offset address(%ld) out of flash bound(<%d).",
partition_table[i].name, partition_table[i].offset, flash_dev->len);
partition_table_len = 0;
goto _exit;
}
}
init_ok = 1;
_exit:
#if FAL_DEBUG
fal_show_part_table();
#endif
#ifndef FAL_PART_HAS_TABLE_CFG
if (new_part)
{
FAL_FREE(new_part);
}
#endif /* !FAL_PART_HAS_TABLE_CFG */
return partition_table_len;
}
/**
* find the partition by name
*
* @param name partition name
*
* @return != NULL: partition
* NULL: not found
*/
const struct fal_partition *fal_partition_find(const char *name)
{
assert(init_ok);
size_t i;
for (i = 0; i < partition_table_len; i++)
{
if (!strcmp(name, partition_table[i].name))
{
return &partition_table[i];
}
}
return NULL;
}
/**
* get the partition table
*
* @param len return the partition table length
*
* @return partition table
*/
const struct fal_partition *fal_get_partition_table(size_t *len)
{
assert(init_ok);
assert(len);
*len = partition_table_len;
return partition_table;
}
/**
* set partition table temporarily
* This setting will modify the partition table temporarily, the setting will be lost after restart.
*
* @param table partition table
* @param len partition table length
*/
void fal_set_partition_table_temp(struct fal_partition *table, size_t len)
{
assert(init_ok);
assert(table);
partition_table_len = len;
partition_table = table;
}
/**
* read data from partition
*
* @param part partition
* @param addr relative address for partition
* @param buf read buffer
* @param size read size
*
* @return >= 0: successful read data size
* -1: error
*/
int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size)
{
int ret = 0;
const struct fal_flash_dev *flash_dev = NULL;
assert(part);
assert(buf);
if (addr + size > part->len)
{
log_e("Partition read error! Partition address out of bound.");
return -1;
}
flash_dev = fal_flash_device_find(part->flash_name);
if (flash_dev == NULL)
{
log_e("Partition read error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name);
return -1;
}
ret = flash_dev->ops.read(part->offset + addr, buf, size);
if (ret < 0)
{
log_e("Partition read error! Flash device(%s) read error!", part->flash_name);
}
return ret;
}
/**
* write data to partition
*
* @param part partition
* @param addr relative address for partition
* @param buf write buffer
* @param size write size
*
* @return >= 0: successful write data size
* -1: error
*/
int fal_partition_write(const struct fal_partition *part, uint32_t addr, const uint8_t *buf, size_t size)
{
int ret = 0;
const struct fal_flash_dev *flash_dev = NULL;
assert(part);
assert(buf);
if (size == 0)
return 0;
if (addr + size > part->len)
{
log_e("Partition write error! Partition address out of bound. %08X %04X", addr, size);
return -1;
}
flash_dev = fal_flash_device_find(part->flash_name);
if (flash_dev == NULL)
{
log_e("Partition write error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name);
return -1;
}
ret = flash_dev->ops.write(part->offset + addr, buf, size);
if (ret < 0)
{
log_e("Partition write error! Flash device(%s) write error! %08X %04X ret %d", part->flash_name, addr, size, ret);
}
return ret;
}
/**
* erase partition data
*
* @param part partition
* @param addr relative address for partition
* @param size erase size
*
* @return >= 0: successful erased data size
* -1: error
*/
int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t size)
{
int ret = 0;
const struct fal_flash_dev *flash_dev = NULL;
assert(part);
if (addr + size > part->len)
{
log_e("Partition erase error! Partition address out of bound.");
return -1;
}
flash_dev = fal_flash_device_find(part->flash_name);
if (flash_dev == NULL)
{
log_e("Partition erase error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name);
return -1;
}
ret = flash_dev->ops.erase(part->offset + addr, size);
if (ret < 0)
{
log_e("Partition erase error! Flash device(%s) erase error!", part->flash_name);
}
return ret;
}
/**
* erase partition all data
*
* @param part partition
*
* @return >= 0: successful erased data size
* -1: error
*/
int fal_partition_erase_all(const struct fal_partition *part)
{
return fal_partition_erase(part, 0, part->len);
}