当前位置: 首页 > news >正文

stm32Flash操作

//G0B0 flash大小 0x08000000-0x0807FFFF 512K(0400 1K)//2k 1页
//初始化标记数据地址 放最前面 脱机烧写器可擦除掉
#define     CONST_INITMARKDATA_ADDRESS      (0x0807D000UL) //2k 1页
//射频数据地址
#define     CONST_FREQDATA_ADDRESS          (0x0807F000UL)  //2k 1页
//本振数据地址
#define     CONST_BWLODATA_ADDRESS          (0x0807F800UL)//用户数据标记
#define     CONST_USERDATA_ACTIVECOOKIE     (0xFEDCCDEF) 

========================================================================
__align(8) static uint8_t flashWriteBuf[2048];

  1. __align(8): 用于指定存储在内存中的变量的对齐方式为 8 字节。对齐的目的是为了优化内存访问,确保变量在内存中的地址是某个值的倍数(这里是 8 字节)。这通常对于某些硬件和特定的数据结构是必要的。
  2. static: 用于指示该变量的存储持续时间为整个程序的执行期间。在这里,flashWriteBuf 是一个静态变量,它在程序的整个执行期间都存在,并且其生命周期延伸到整个程序的运行时间。

这行代码定义了一个静态的、对齐为 8 字节的、包含 2048 个无符号8位整数的数组 flashWriteBuf

=========================================================================

为什么要使用 __align(8),以及对齐方式在内存中的表现是什么样的?

在C语言中,对齐方式是指变量在内存中的存储起始位置相对于地址的偏移量。
对齐的主要目的是优化内存访问速度,特别是对于一些体系结构或硬件,它们可能要求某些数据类型的变量从特定地址开始。

  1. 访问速度: 在某些架构中,对齐的数据访问速度更快。例如,某些处理器可能要求访问 4 字节整数从4字节对齐的地址开始,否则可能会引发性能损失或错误。

  2. 缓存行: 许多处理器以缓存行为单位加载数据到缓存中。如果变量的首地址是缓存行对齐的,那么对该变量的访问可能会更加高效。

  3. 硬件限制: 某些硬件要求特定数据类型从特定对齐方式的地址开始。如果不满足这些要求,可能会导致硬件异常或性能下降。

在具体的应用场景中,选择对齐方式通常是为了优化性能或者满足硬件的要求。然而,过度的对齐可能会导致内存空间的浪费。在实际开发中,对齐的选择需要根据具体的硬件和性能需求进行权衡。

=========================================================================
1. 实现逻辑:

uint8_t* coreFlashAcquireWriteBuffer(void)
{return flashWriteBuf;
}

该函数返回一个 uint8_t 类型的指针。函数体内只有一条语句,即返回名为 flashWriteBuf 的静态数组的首地址。

主要目的是获取可用于写入的缓冲区。由于返回的是指向 uint8_t 的指针,可以将这个指针用于写入字节数据。

2. 主要目的和适用场景:
这段代码的主要目的是提供一个接口,允许外部模块或函数获取一个可用于写入的缓冲区。

这种模式常见于需要进行数据写入或者数据缓冲的情境,例如将数据写入到 Flash 存储器中。

适用场景可能包括需要向 Flash 存储器写入数据的任务。通过调用 coreFlashAcquireWriteBuffer 函数,程序可以获取一个缓冲区,然后将待写入的数据写入该缓冲区。
这种设计允许程序灵活地控制数据的写入,同时提供了一种有效的机制来管理数据的写入操作。

====================================================================
1. 实现逻辑:

static uint32_t getPage(uint32_t addr)
{uint32_t page = 0;/* Bank 1 */page = (addr - FLASH_BASE) / FLASH_PAGE_SIZE;return page;
}

​ 这段代码定义了一个静态函数 getPage,接受一个 uint32_t 类型的地址参数,计算并返回与该地址相关的页面号(page number)。在这个实现中,页面号被计算为地址相对于基地址 FLASH_BASE 的偏移量除以页面大小 FLASH_PAGE_SIZE

2. 主要目的和适用场景:

​ 主要目的是根据给定的地址计算出相应的页面号。

​ 在嵌入式系统中,Flash存储器通常分为多个页面,每个页面存储一定量的数据。

​ 获取地址对应的页面号可以用于确定数据在Flash中的位置。

​ 适用场景可能包括在程序中管理Flash存储器的情况,比如需要存储和检索数据到Flash中的特定页面。通过调用 getPage 函数,程序可以获得给定地址所在的页面号,然后使用这个页面号进行相应的操作,例如擦除或写入数据。

总体而言,这个函数是一个用于获取地址对应页面号的工具函数,可以用于在嵌入式系统中管理Flash存储器中的数据。

========================================================================
1. 实现逻辑:

int32_t coreFlashWrite(void* dstAddr, const void* srcAddr, const uint32_t size)
{//...(变量定义和初始化)//初始化FLASH_EraseInitTypeDefFLASH_EraseInitTypeDef eraseInitStruct = {0x00};int32_t ret = ERR_FLASHOP_OK;  // 返回值//判断入参正确if (!srcAddr || !dstAddr || 0 == size){return ERR_FLASHOP_PARAM_INVAL;}if (0 != ((uint32_t)srcAddr & 0x00000007)){return ERR_FLASHOP_SRCADDR_UNALIGN;}if (0 != ((uint32_t)dstAddr & 0x00000007)){return ERR_FLASHOP_DSTADDR_UNALIGN;}//获取要擦除的第一页firstPage = getPage((uint32_t)dstAddr);//获取要从第一页擦除的页数nbOfPages = size / FLASH_PAGE_SIZE + (size % FLASH_PAGE_SIZE ? 1 : 0);eraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;eraseInitStruct.Page        = firstPage;  // 擦除起始页eraseInitStruct.NbPages     = nbOfPages;  // 擦除页数HAL_FLASH_Unlock();  // Flash解锁__disable_irq();  // 擦除前需要关闭中断if (HAL_FLASHEx_Erase(&eraseInitStruct, &pageError) != HAL_OK){__enable_irq();ret = -ERR_FLASHOP_FAIL_ERASE;goto exit;}__enable_irq();//开始写入FlashflashAddress = (uint32_t)dstAddr;nWriteAll = size;while (nHasWrite < nWriteAll){// 以64位为单位写入数据srcDW = *(uint64_t*)((uint32_t)srcAddr + nHasWrite);if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flashAddress, srcDW) == HAL_OK){flashAddress += 8;nHasWrite += 8;}else{ret = ERR_FLASHOP_FAIL_PROG;goto exit;}}exit:HAL_FLASH_Lock();  // Flash加锁return ret;
}

2. 主要目的和适用场景:

​ 这段代码的主要目的是实现Flash存储器的写入操作。该函数接受目标地址 dstAddr、源地址 srcAddr 和写入大小 size 作为参数,首先擦除目标地址所在的Flash页面,然后将数据从源地址写入到目标地址。

​ 适用场景可能涉及到需要在嵌入式系统中进行Flash存储器的写入操作,例如在固件更新或配置保存等场景。

3. 使用的关键字和修饰符:

  • static: 该函数没有使用 static 关键字,因此在其他文件中可以访问。
  • uint32_t, void, const: 这些是数据类型,用于声明参数和变量的类型。
  • FLASH_EraseInitTypeDef: 这是一个结构体类型,用于配置Flash擦除的初始化参数。
  • HAL_FLASH_Unlock(), HAL_FLASH_Lock(): 这些是由HAL(Hardware Abstraction Layer)提供的函数,用于解锁和锁定Flash。

总体而言,这是一个用于在嵌入式系统中进行Flash存储器写入的函数,包括擦除和写入两个步骤。============================================================================
1. 实现逻辑:

bool initMarkDataIsActive(void)
{const volatile initMarkDataFlash_t* rawPtr = (const volatile initMarkDataFlash_t*)CONST_INITMARKDATA_ADDRESS;return (rawPtr->active == CONST_USERDATA_ACTIVECOOKIE);
}

这段代码定义了一个函数 initMarkDataIsActive,该函数返回一个布尔值。函数内部首先声明了一个指向 initMarkDataFlash_t 结构体类型的 volatile 常量指针 rawPtr,然后将其初始化为指向一个特定地址 CONST_INITMARKDATA_ADDRESS

函数最后通过比较 rawPtr->activeCONST_USERDATA_ACTIVECOOKIE 的值来确定初始化标记数据是否处于激活状态。

2. 主要目的和适用场景:

​ 主要目的是检查初始化标记数据是否处于激活状态。在嵌入式系统中,可能会有一些标记数据用于指示系统的初始化状态,这个函数就是用于检查这些标记数据是否处于激活状态。

​ 适用场景可能包括在系统启动时检查某些初始化数据,以确保系统处于已初始化的状态。

3. 使用的关键字和修饰符:

  • const, volatile: 这些关键字用于修饰指针 rawPtr,指明该指针指向的数据是常量且易变的,这通常用于防止编译器进行一些优化,确保每次访问都会从内存中读取最新的值。

总体而言,这个函数用于检查初始化标记数据是否处于激活状态,返回一个布尔值表示检查结果。

=========================================================================
1. 实现逻辑:

void initMarkDataReadFlash(void)
{const volatile initMarkDataFlash_t *rawPtr = (const volatile initMarkDataFlash_t*)CONST_INITMARKDATA_ADDRESS;if (initMarkDataIsActive()){memcpy(&initMarkDataFlash, (void*)rawPtr, sizeof(initMarkDataFlash_t));}
}

函数内部首先声明了一个指向 initMarkDataFlash_t 结构体类型的 volatile 常量指针 rawPtr,然后将其初始化为指向一个特定地址 CONST_INITMARKDATA_ADDRESS

接着,通过调用 initMarkDataIsActive 函数检查初始化标记数据是否处于激活状态。如果激活,那么通过 memcpy 函数将 Flash 中的数据复制到一个全局变量 initMarkDataFlash 中。

2. 主要目的和适用场景:

​ 主要目的是在系统启动时从 Flash 中读取初始化标记数据。在嵌入式系统中,初始化标记数据可能包含一些配置信息或者系统状态,该函数的目的是将这些数据读取到内存中,以便系统可以使用这些数据进行初始化。

​ 适用场景可能包括在系统启动时加载先前保存的配置或状态信息,以确保系统处于正确的状态。

总体而言,这个函数用于从 Flash 中读取初始化标记数据,如果数据处于激活状态,则将其复制到全局变量中。

=======================================================================
1. 实现逻辑:

int32_t initMarkDataSyncFlash(void)
{int32_t ret = 0;//用户数据写入ret = coreFlashWrite((void*)CONST_INITMARKDATA_ADDRESS, (void*)&initMarkDataFlash, sizeof(initMarkDataFlash_t));return ret;
}

函数内部首先声明了一个整数变量 ret,用于存储函数执行的结果。

接着,通过调用 coreFlashWrite 函数将全局变量 initMarkDataFlash 中的数据写入到 Flash 中的指定地址 CONST_INITMARKDATA_ADDRESS

最后,函数返回执行的结果。

2. 主要目的和适用场景:

​ 主要目的是将全局变量 initMarkDataFlash 中的数据同步到 Flash 中的指定地址。在嵌入式系统中,这可能用于将配置或状态信息保存到 Flash 中,以便在系统重新启动时恢复状态。

​ 适用场景可能包括在系统运行时修改了一些配置或状态信息,希望将这些更改保存到持久性存储中。

总体而言,这个函数用于将全局变量中的数据写入到 Flash 中的指定地址,返回一个表示执行结果的整数值。

相关文章:

stm32Flash操作

//G0B0 flash大小 0x08000000-0x0807FFFF 512K(0400 1K)//2k 1页 //初始化标记数据地址 放最前面 脱机烧写器可擦除掉 #define CONST_INITMARKDATA_ADDRESS (0x0807D000UL) //2k 1页 //射频数据地址 #define CONST_FREQDATA_ADDRESS (0x0807F000UL) //2…...

云原生系列1

1、虚拟机集群环境准备 VirtualBox类似vmware的虚拟化软件&#xff0c;去官网https://www.virtualbox.org/下载最新版本免费的&#xff0c;VirtualBox中鼠标右ctrl加home跳出鼠标到wins中。 VirtualBox安装步骤 https://blog.csdn.net/rfc2544/article/details/131338906 cent…...

设计原则 | 里式替换原则

一、里式替换原则&#xff08;Liskov Substitution Principle &#xff09; 1、原理 子类型必须能替换掉它们的基类型&#xff0c;在使用继承时&#xff0c;遵循里式替换原则&#xff0c;在子类中尽量不要重写父类中的方法。里式替换原则告诉我们&#xff0c;继承实际上让两个…...

第7节:Vue3 动态绑定多个属性

可以使用v-bind指令将多个属性动态绑定到元素上。以下是一个简单的实例&#xff1a; <template><view class"container"><text v-bind"dynamicProps">{{ message }}</text><button click"toggleActive">切换激活…...

【文件上传系列】No.1 大文件分片、进度图展示(原生前端 + Node 后端 Koa)

分片&#xff08;500MB&#xff09;进度效果展示 效果展示&#xff0c;一个分片是 500MB 的 分片&#xff08;10MB&#xff09;进度效果展示 大文件分片上传效果展示 前端 思路 前端的思路&#xff1a;将大文件切分成多个小文件&#xff0c;然后并发给后端。 页面构建 先在页…...

性能测试 —— Jmeter分布式测试的注意事项和常见问题

Jmeter是一款开源的性能测试工具&#xff0c;使用Jmeter进行分布式测试时&#xff0c;也需要注意一些细节和问题&#xff0c;否则可能会影响测试结果的准确性和可靠性。 Jmeter分布式测试时需要特别注意的几个方面 1. 参数化文件的位置和内容 如果使用csv文件进行参数化&#x…...

“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI 指数的生态质量评价及拓展应用

近年来&#xff0c;国内外学者在生态系统的敏感性、适应能力和潜在影响等方面开展了大量的生态脆弱性研究&#xff0c;他们普遍将生态脆弱性概念与农牧交错带、喀斯特地区、黄土高原区、流域、城市等相结合&#xff0c;评价不同类型研究区的生态脆弱特征&#xff0c;其研究内容…...

总结|哪些平台有大模型知识库的Web API服务

截止2023/12/6 笔者个人的调研&#xff0c;有三家有大模型知识库的web api服务&#xff1a; 平台类型文档数量文档上传并解析的结构api情况返回页码文心一言插件版多文档有问答api&#xff0c;文档上传是通过网页进行上传有&#xff0c;而且是具体的chunk id&#xff0c;需要设…...

TOMCAT9安装

1、官网下载 2、解压到任意盘符&#xff0c;注意路径不要有中文 3、环境变量 path 下 配置 %CATALINA_HOME%\bin 4、找到tomcat9/bin&#xff0c; 点击 start.bat启动 tomcat...

QT中时间时区处理总结

最近项目中要做跨国设备时间校正功能&#xff0c;用到了时区时间&#xff0c;在此做一下记录。 目录 1.常见时区名 2.测试代码 3.运行效果 1.常见时区名 "Pacific/Midway": "中途岛 (UTC-11:00)", …...

OpenAtom OpenHarmony三方库创建发布及安全隐私检测

OpenAtom OpenHarmony 三方库&#xff08;以下简称“三方库”或“包”&#xff09;&#xff0c;是经过验证可在 OpenHarmony 系统上可重复使用的软件组件&#xff0c;可帮助开发者快速开发 OpenHarmony 应用。三方库根据其开发语言分为 2 种&#xff0c;一种是使用 JavaScript …...

【1】一文读懂PyQt简介和环境搭建

目录 1. PyQt简介 1.1. Qt 1.2. PyQt 1.3. 关于PyQt和PySide 2. 通过pip安装PyQt5 3. 无法运行处理 4. VSCode配置PYQT插件 PyQt官网:Riverbank Computing | Introduction 1. PyQt简介 PyQt是一套Python的GUI开发框架,即图形用户界面开发框架。 Python中经常使用的GU…...

windows install git

refer: https://developers.weixin.qq.com/miniprogram/dev/devtools/wechatvcs.html https://blog.csdn.net/weixin_40228200/article/details/128451324 在使用小程序的时候&#xff0c;需要初始化项目&#xff0c;需要注册Git账号 1.在本地确认cmd没有安装Git,进入Git官网…...

【华为数据之道学习笔记】3-7 报告数据治理

报告数据是指对数据进行处理加工后&#xff0c;用作业务决策依据的数据。它用于支持报告和报表的生成。 用于报告和报表的数据可以分为如下几种。 用于报表项数据生成的事实表、指标数据、维度。 用于报表项统计和计算的统计函数、趋势函数及报告规则。 用于报表和报告展示的…...

SpringDataRedis 操作 Redis,并指定数据序列化器

文章目录 1. SpringDataRedis 概述2. 快速入门2.1 导入pom坐标2.2 配置文件2.3 测试代码2.4 数据序列化器2.5 StringRedisTemplate2.6 总结 1. SpringDataRedis 概述 SpringData 是Spring 中数据操作的模块&#xff0c;包含对各种数据库的集成&#xff0c;其中对Redis的集成模…...

useradd 在Linux原生应用开发过程中的简单应用

useradd命令是用于在Linux系统中创建新用户的命令。它可以创建一个新用户&#xff0c;并设置该用户的属性、家目录、默认shell等。useradd命令实际上是一个包装了一系列系统调用的高级命令。 在Linux系统中&#xff0c;用户信息存储在/etc/passwd文件中。当执行useradd命令时&…...

Linux 删除文件名乱码的文件

现象&#xff1a; 处理&#xff1a; 1.>ls -li 获取文件对应的ID号 2.把删除指定文件&#xff08;ID号 &#xff09;执行&#xff1a; find ./ -inum 268648910 -exec rm {} \;...

【测试人生】数据同步和迁移的变更注意事项

数据同步或者迁移操作也算是线上数据变更的一种类型。由于涉及的数据量非常大&#xff0c;一旦发生故障&#xff0c;会直接影响线上业务&#xff0c;并且较难止损。从变更风险管控的角度考虑&#xff0c;数据同步或迁移操作也需要走合理的发布窗口&#xff0c;并且在操作前也需…...

快手视频如何去掉水印?三个简单好用视频去水印方法

快手视频如何去掉水印&#xff1f;尽管新兴的短视频平台如春笋般涌现&#xff0c;吸引了众多观众在业余时间浏览和分享视频&#xff0c;快手作为当下主流短视频之一&#xff0c;许多自媒体创作者也常常会下载一些热门的视频素材进行二次编辑。然而&#xff0c;他们都可能会面临…...

【Linux】stat命令使用

stat命令 stat命令用于显示文件的状态信息。stat命令的输出信息比ls命令的输出信息要更详细。 著者 由Michael Meskes撰写。 stat命令 -Linux手册页 语法 stat [文件或目录] 命令选项及作用 执行令 &#xff1a; stat --help 执行命令结果 参数 -L、 --dereference 跟…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源&#xff0c;提供了很全面的思路&#xff0c;减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接&#xff1a;https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架&#xff1a; 代码框架结构&#xff1a;readme有…...