rtthread stm32h743的使用(十二)spi设备fal驱动的使用

news2024/10/7 6:45:05

我们要在rtthread studio 开发环境中建立stm32h743xih6芯片的工程。我们使用一块stm32h743及fpga的核心板完成相关实验,核心板如图:
在这里插入图片描述
在这里插入图片描述
fal驱动的使用是建立在sfud驱动之上的,所以我们在上一节使用的工程基础上继续实验。
在这里插入图片描述1.在上一节工程的基础上,我们添加fal驱动:
在这里插入图片描述
在这里插入图片描述
2.打开工程目录,将samples文件夹下的fal cfg.h复制到inc文件夹下,如图:
在这里插入图片描述
3.在drive文件夹下添加drv_flash_h7.c文件如图:
在这里插入图片描述
代码如下:

#include <rtconfig.h>
#include <rtdef.h>
#include <board.h>

#ifdef BSP_USING_ON_CHIP_FLASH
#include "drv_config.h"
#include "drv_flash.h"


#if defined(RT_USING_FAL)
#include "fal.h"
#endif

//#define DRV_DEBUG
#define LOG_TAG                "drv.flash"
#include <drv_log.h>

/**
 * Read data from flash.
 * @note This operation's units is word.
 *
 * @param addr flash address
 * @param buf buffer to store read data
 * @param size read bytes size
 *
 * @retval The length of bytes that have been read
 */
int stm32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size)
{
    size_t i;

    if ((addr + size - 1) > FLASH_END)
    {
        LOG_E("read outrange flash size! addr is (0x%p)", (void *)(addr + size));
        return -RT_ERROR;
    }

    for (i = 0; i < size; i++, buf++, addr++)
    {
        *buf = *(rt_uint8_t *) addr;
    }

    return size;
}

/**
 * Write data to flash.
 * @note This operation's units is word.
 * @note This operation must after erase. @see flash_erase.
 *
 * @param addr flash address
 * @param buf the write data buffer
 * @param size write bytes size
 *
 * @return The length of bytes that have been written
 */
int stm32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
{
    rt_err_t result      = RT_EOK;
    rt_uint32_t end_addr = addr + size - 1, write_addr;
    rt_uint32_t write_granularity = FLASH_NB_32BITWORD_IN_FLASHWORD * 4;
    rt_uint32_t write_size = write_granularity;
    rt_uint8_t write_buffer[32] = {0};

    if ((end_addr) > FLASH_END)
    {
        LOG_E("write outrange flash size! addr is (0x%p)", (void *)(addr + size));
        return -RT_EINVAL;
    }

    if(addr % 32 != 0)
    {
        LOG_E("write addr must be 32-byte alignment");
        return -RT_EINVAL;
    }

    if (size < 1)
    {
        return -RT_EINVAL;
    }

    HAL_FLASH_Unlock();
    write_addr = (uint32_t)buf;
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR);
    while (addr < end_addr)
    {
        if(end_addr - addr + 1 < write_granularity)
        {
            write_size = end_addr - addr + 1;
            for(size_t i = 0; i < write_size; i++)
            {
                write_buffer[i] = *((uint8_t *)(write_addr + i));
            }
            write_addr = (uint32_t)((rt_uint32_t *)write_buffer);
        }
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr, write_addr) == HAL_OK)
        {
            for(rt_uint8_t i = 0; i < write_size; i++)
            {
                if (*(rt_uint8_t *)(addr + i) != *(rt_uint8_t *)(write_addr + i))
                {
                    result = -RT_ERROR;
                    goto __exit;
                }
            }
            addr += write_granularity;
            write_addr  += write_granularity;
        }
        else
        {
            result = -RT_ERROR;
            goto __exit;
        }
    }

__exit:
    HAL_FLASH_Lock();

    if (result != RT_EOK)
    {
        return result;
    }

    return size;
}

/**
 * Erase data on flash.
 * @note This operation is irreversible.
 * @note This operation's units is different which on many chips.
 *
 * @param addr flash address
 * @param size erase bytes size
 *
 * @return result
 */
int stm32_flash_erase(rt_uint32_t addr, size_t size)
{
    rt_err_t result = RT_EOK;
    rt_uint32_t SECTORError = 0;

    if ((addr + size - 1) > FLASH_END)
    {
        LOG_E("ERROR: erase outrange flash size! addr is (0x%p)\n", (void *)(addr + size));
        return -RT_EINVAL;
    }

    rt_uint32_t addr_bank1 = 0;
    rt_uint32_t size_bank1 = 0;
#ifdef FLASH_BANK_2
    rt_uint32_t addr_bank2 = 0;
    rt_uint32_t size_bank2 = 0;
#endif

    if((addr + size) < FLASH_BANK2_BASE)
    {
        addr_bank1 = addr;
        size_bank1 = size;
#ifdef FLASH_BANK_2
        size_bank2 = 0;
#endif
    }
    else if(addr >= FLASH_BANK2_BASE)
    {
        size_bank1 = 0;
#ifdef FLASH_BANK_2
        addr_bank2 = addr;
        size_bank2 = size;
#endif
    }
    else
    {
        addr_bank1 = addr;
        size_bank1 = FLASH_BANK2_BASE - addr_bank1;
#ifdef FLASH_BANK_2
        addr_bank2 = FLASH_BANK2_BASE;
        size_bank2 = addr + size - FLASH_BANK2_BASE;
#endif
    }

    /*Variable used for Erase procedure*/
    FLASH_EraseInitTypeDef EraseInitStruct;
    /* Unlock the Flash to enable the flash control register access */
    HAL_FLASH_Unlock();
    EraseInitStruct.TypeErase     = FLASH_TYPEERASE_SECTORS;
    EraseInitStruct.VoltageRange  = FLASH_VOLTAGE_RANGE_3;
    SCB_DisableDCache();

    if(size_bank1)
    {
        EraseInitStruct.Sector    = (addr_bank1 - FLASH_BANK1_BASE) / FLASH_SECTOR_SIZE;
        EraseInitStruct.NbSectors = (addr_bank1 + size_bank1 -1 - FLASH_BANK1_BASE) / FLASH_SECTOR_SIZE - EraseInitStruct.Sector + 1;
        EraseInitStruct.Banks = FLASH_BANK_1;
        if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
        {
            result = -RT_ERROR;
            goto __exit;
        }
    }

#ifdef FLASH_BANK_2
    if(size_bank2)
    {
        EraseInitStruct.Sector    = (addr_bank2 - FLASH_BANK2_BASE) / FLASH_SECTOR_SIZE;
        EraseInitStruct.NbSectors = (addr_bank2 + size_bank2 -1 - FLASH_BANK2_BASE) / FLASH_SECTOR_SIZE - EraseInitStruct.Sector + 1;
        EraseInitStruct.Banks = FLASH_BANK_2;
        if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
        {
            result = -RT_ERROR;
            goto __exit;
        }
    }
#endif

__exit:

    SCB_EnableDCache();
    HAL_FLASH_Lock();

    if (result != RT_EOK)
    {
        return result;
    }

    LOG_D("erase done: addr (0x%p), size %d", (void *)addr, size);
    return size;
}

#if defined(RT_USING_FAL)
static int fal_flash_read_128k(long offset, rt_uint8_t *buf, size_t size);
static int fal_flash_write_128k(long offset, const rt_uint8_t *buf, size_t size);
static int fal_flash_erase_128k(long offset, size_t size);
const struct fal_flash_dev stm32_onchip_flash_128k = { "onchip_flash_128k", STM32_FLASH_START_ADRESS, FLASH_SIZE_GRANULARITY_128K, (128 * 1024), {NULL, fal_flash_read_128k, fal_flash_write_128k, fal_flash_erase_128k} };

static int fal_flash_read_128k(long offset, rt_uint8_t *buf, size_t size)
{
    return stm32_flash_read(stm32_onchip_flash_128k.addr + offset, buf, size);
}
static int fal_flash_write_128k(long offset, const rt_uint8_t *buf, size_t size)
{
    return stm32_flash_write(stm32_onchip_flash_128k.addr + offset, buf, size);
}

static int fal_flash_erase_128k(long offset, size_t size)
{
    return stm32_flash_erase(stm32_onchip_flash_128k.addr + offset, size);
}

#endif
#endif /* BSP_USING_ON_CHIP_FLASH */

4.在在board.h文件打开BSP_USING_ON_CHIP_FLASH如图:
在这里插入图片描述
5.对fal_cfg.h做更改,使其和h7芯片对应,如图:
在这里插入图片描述
6.这时候编译已经没有错误了,我们下载测试下:
在这里插入图片描述
可以看到,[I/SFUD] Probe SPI flash norflash0 by SPI device spi10 success.RT-Thread Flash Abstraction Layer initialize success.说明sfud和fal都init成功,并且打印了分区表。
7.测试几个fal指令,都没有问题:
在这里插入图片描述
8.我们测试下性能,性能将会测试 Flash的擦除、写入及读取速度,同时将会测试写入及读取数据的准确性,保证整个 Flash 或整个分区的 写入与读取 数据的一致性。
指令为fal bench 4096 yes
在这里插入图片描述
其余指令可以参考:

msh />fal
Usage:
fal probe [dev_name|part_name]   - probe flash device or partition by given name
fal read addr size               - read 'size' bytes starting at 'addr'
fal write addr data1 ... dataN   - write some bytes 'data' starting at 'addr'
fal erase addr size              - erase 'size' bytes starting at 'addr'
fal bench <blk_size>             - benchmark test with per block size

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1879493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

互联网大厂核心知识总结PDF资料

我们要敢于追求卓越&#xff0c;也能承认自己平庸&#xff0c;不要低估3&#xff0c;5&#xff0c;10年沉淀的威力 hi 大家好&#xff0c;我是大师兄&#xff0c;大厂工作特点是需要多方面的知识和技能。这种学习和积累一般人需要一段的时间&#xff0c;不太可能一蹴而就&…

Swift宏的实现

上篇介绍了Swift宏的定义与生声明&#xff0c;本篇主要看看是Swift宏的具体实现。结合Swift中Codable协议&#xff0c;封装一个工具让类或者结构体自动实现Codable协议&#xff0c;并且添加一些协议中没有的功能。 关于Codable协议 Codable很好&#xff0c;但是有一些缺陷&…

Cherno 游戏引擎笔记 (45~60)

有几个部分的笔记以图片形式呈现&#xff08;如果没找到文本可以查看是否遗漏了图片笔记&#xff09; My Github REPO(GitHub - JJJJJJJustin/Nut: The game_engine which learned from Cherno) 源码笔记&#xff0c;希望帮到你 :-} ---Shader Library&#xff08;着色器库&…

x-file-storage一行代码进行文件上传,摆脱阿里云,腾讯云,华为云等不同云的学习,简单高效

问题&#xff1a; 不使用x-file-storage时如果使用某个云首先需要学习他的sdk,这样很麻烦&#xff0c;而x-file-storage集成了各种云的上传&#xff0c;只需要进行配置即可一行代码进行上传 使用 官方地址&#xff1a;X File Storage 一行代码将文件存储到本地、FTP、SFTP、…

线性表与顺序存储结构(下)

前言 接上文&#xff08;线性表与顺序存储结构&#xff08;上&#xff09;&#xff09;。 这些顺序存储结构的方法在顺序表上下卷中已经提到过&#xff0c;但是有些许不同&#xff0c;可以为理解顺序表提供更丰富的视角。&#xff08;不过最主要的区别在于顺序表上下卷中的顺…

一个合理的前端应用文件结构

在大型应用中&#xff0c;最关键且最具挑战性的方面之一就是拥有一个良好且合理的文件结构。在考虑通过微前端将代码库拆分成多个应用之前&#xff0c;可以遵循一些步骤来改善项目级别的架构&#xff0c;并在您考虑这一路径时使过渡更容易。 我们的目标是应用某种模块化方法&am…

关于图片大小问题造成的QPixmap或QImage读取图片失败的解决办法

今天碰到一个奇怪又离谱的问题 : 图片加载失败。明明路径是正确的&#xff0c;图片也实实在在存在。。。 经过比对&#xff0c;发现如下问题&#xff1a; 我就齐了怪了 这大小怎么差这么多&#xff1f;会不会是这里除了问题。秉持着怀疑的态度&#xff0c;我试着用GIMP重新导出…

java笔记(30)——反射的 API 及其 使用

文章目录 反射1. 什么是反射2. 获取class字段&#xff08;字节码文件对象&#xff09;方式1方式2方式3应用 3. 获取构造方法和权限修饰符前期准备获取所有的公共构造方法获取所有的构造方法获取无参构造方法获取一个参数的构造方法获取一个参数的构造方法获取两个参数的构造方法…

查看Linux系统中用过什么命令 history

提示&#xff1a;以下所有命令都在Ubuntu-24.04-live-server-amd64系统中运行 文章目录 前言一、基本用法&#xff1a;二、查看其他用户历史三、增加时间戳结语 前言 history 命令用于显示和操作当前用户在当前会话中执行过的命令历史记录。它是 Bash shell 的内置命令&#x…

架构设计上中的master三种架构,单节点,主从节点,多节点分析

文章目录 背景单节点优点缺点 主从节点优点缺点 多节点优点缺点 多节点&#xff0c;多backup设计优点缺点 总结 背景 在很多分布式系统里会有master,work这种结构。 master 节点负责管理资源&#xff0c;分发任务。下面着重讨论下master 数量不同带来的影响 单节点 优点 1.设…

PTA:7-194 循环结构 —— 中国古代著名算题。趣味题目:物不知其数。

作者 苑丽红 单位 长春理工大学 中国古代著名算题。原载《孙子算经》&#xff1a;“今有物不知其数&#xff0c;三三数之剩二&#xff1b;五五数之剩三&#xff1b;七七数之剩二。问物几何?”。本题要求&#xff1a;设某物数量是 N&#xff0c;且三三数剩 x&#xff0c;五五…

如何在Ubuntu20上离线安装joern(包括sbt和scala)

在Ubuntu 20上离线安装Joern&#xff0c;由于Joern通常需要通过互联网从其官方源或GitHub等地方下载&#xff0c;但在离线环境中&#xff0c;我们需要通过一些额外的步骤来准备和安装。&#xff08;本人水平有限&#xff0c;希望得到大家的指正&#xff09; 我们首先要做的就是…

Excel 快速查询工具 2023.7.1 更新

Excel 快速查询工具作者表示这个软件是因为有时候需要在 Excel 和网站之间进行切换非常的麻烦&#xff0c;这款软件可以以半透明的方框位于桌面上。 特点 软件窗口半透明并至于顶部&#xff0c;无需来回切换界面。 实时查询&#xff0c;不用点击查询或者按回车之类的&#x…

什么是Cookie?有什么用?如何清除浏览器中的Cookie?

互联网上的每一次点击和每一个选择都可能被一种名为Cookie的技术记录下来。但Cookie是什么&#xff1f;我们在网站上登录时&#xff0c;为什么经常会被问及是否接受Cookie&#xff1f;接受Cookie登录会不会影响我们的在线隐私&#xff1f; Cookie是什么&#xff1f; Cookie是一…

vue3 全局引入 onMounted, reactive, ref 的插件全局引入

webpack 的引入 npm install -D unplugin-auto-import const AutoImport require(unplugin-auto-import/webpack).default;configureWebpack: {devtool: source-map,module: {rules: [{test: /\.mjs$/,include: /node_modules/,type: javascript/auto}],}, plugins: [Aut…

LLM——10个大型语言模型(LLM)常见面试题以及答案解析

今天我们来总结以下大型语言模型面试中常问的问题 1、哪种技术有助于减轻基于提示的学习中的偏见? A.微调 Fine-tuning B.数据增强 Data augmentation C.提示校准 Prompt calibration D.梯度裁剪 Gradient clipping 答案:C 提示校准包括调整提示&#xff0c;尽量减少产生…

基于大津阈值法和二值化与联通区域标记进行图像目标计数

1 建模 A.读取图像&#xff1a; 1.使用imread函数读取图像文件。 2.如果图像是彩色的&#xff0c;通常需要先转换为灰度图像&#xff0c;因为大津阈值法通常应用于灰度图像。 B.灰度化&#xff1a; 1&#xff0e;如果图像是彩色的&#xff0c;使用rgb2gray函数将其转换为灰度…

Data-Driven Reinforcement Learning for Robotic Manipulation

意思是 不同的任务以及机器人都有单独的数据和模型 未来需要整合 一个大的数据集包含所有的 然后训练一个大模型 以后具体的任务只需要针对这个模型进行微调 challenge bootstrapping with large data 2 3 4 高清图补充

uniapp, ‍[⁠TypeError⁠]‍ “Failed to fetch dynamically imported module“ 报错解决思路

文章目录 1. 背景2. 报错3. 解决思路4. 思考参考1. 背景 最近基于uniapp开发一款设备参数调试的APP软件,在使用第三方插件的过程中,出现下面的报错。 2. 报错 [plugin:vite:import-analysis] Cannot find module ‘D:/leaning/uniapp/demo/jk-uts-udp示例/uni_modules/uts-…

安装maven与nexus

安装maven与nexus Maven官网下载地址&#xff1a;http://maven.apache.org cd /data/software/wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.8.1/binaries/apache-maven-3.8.8-bin.tar.gz# 解压 tar xf apache-maven-3.8.1-bin.tar.gz -C /opt/[rooth…