4896|19

1071

帖子

7

TA的资源

纯净的硅(中级)

楼主
 

聊聊数据存储 [复制链接]

  本帖最后由 dj狂人 于 2014-12-18 17:18 编辑

                                                                                 聊聊数据存储
之前学51的时候,对数据存储没什么概念,主要是做过的东西对这方面没这个需求自己也没往这方面考虑过。而对于STM32来说,当程序写大特别是跑OS之后数据存储就变成了不得不考虑的事情,那么我们现在就来聊聊数据存储。
假如我们在程序中定义了这么五个变量:
int Frequency = 8;
int Speed = 5;
int Power = 60;
int Voltage = 12;
int Temperature = 25;
这五个变量在程序运行的时候是可以通过按键或者其它方式人为的改变它们的值的,现在要求在人为改变它们之后对它们进行保存,那么这个时候我们该怎么去编写程序呢。
    如果是51单片机的的话,在单片机不支持IAP技术的条件下,我们一般会考虑外扩,但是在STM32上,我们可以把这五个变量保存到Flash ROM里面,在有数据变动的时候再进行重新擦写就可以了,但保存到FlashROM中会有一定的限制,那就是它不允许我们进行字节擦除,如果我们想要对其中的某个数据进行修改的话只能先把里面的数据都取出来,修改好之后把Flash ROM整页擦除再把数据写进去。这是因为Flash ROM在没有写入任何数据之前里面都是‘1’,我们写入数据只需要把相应的‘1’写成‘0’就可以了,但是它是不允许也不能把‘0’再写成‘1’的,这就是为什么Flash ROM不支持字节擦写的原因。
    那么好,确定用Flash ROM来存储数据之后,我们下面开始数据改以什么样的形式进行存储。对于上面五个变量可不可以直接这样存放进去呢
这样是可以的,但我们要考虑到虽然我们知道里面哪个地址存的是什么变量的数据,但单片机是不知道它现在取的是什么数据的,这样就要求我们为每个变量都赋一个标志,比如用0x00代表Frequency变量,0x01代表Speed变量...以此类推,那么单片机取出数据的时候先找到标志,如先找到0x00,那么它就知道这次取的是Frequency变量的数据了,如果找到0x01,它就知道这次取出的是Speed变量的数据了。
解决好这个问题之后,我们再来看看有数据变动需要修改的情况。
    如上图,现在我们的五个变量和相应的标志已经存放到FlashROM里面去了,假如程序在运行的时候,使用者通过按键修改了Speed变量的值,修改成了
Speed = 2;那么我们要更新保存在Flash ROM里的Speed的值的时候,需要在RAM里面定义一个数组,把Flash ROM里面这五个变量的值和标志取出来放到数组里面,然后通过标志找到Speed变量的数据,对它的数据进行更新,也就是把‘5’擦写成‘2’,之后对Flash ROM进行整页擦除,最后把数组里面的数据再重新写进去就完成了数据的更新。
上面介绍的方法是初学者比较常用的方法,这种方法简单,容易理解。但是有点致命的缺陷,我们都知道Flash 是有寿命的,虽然现在普遍上的Flash 可达10万次擦写,但如果在运行的时候使用者经常通过按键修改变量,频繁的对Flash进行整页擦除,会导致Flash的使用寿命大大减少。那么要解决这个问题就需要我们合理科学的使用Flash。那么对Flash又该怎么进行合理科学的使用呢。
在我们STM32的中小容量型号芯片中,一般一页有1K的内存空间,而上面我们存储五个变量加五个标志之后还剩下一大片的空间没用到,不得不说这是种浪费,如果把剩下的空间利用起来,那么有数据变动的时候我们可以先不对原数据进行更改,而是采用追加的方式保存到后面去:
这样的话我们只要在这页空间快存满或者合理的时候对这些数据进行整理,把无效旧的数据清理掉再重新写入Flash就可以了。
这样合理的使用Flash之后,我们再来看看怎么对无效数据进行清理。
如上图,当我们的一页空间里快存满或者我们想要进行清理的时候,我们可以在RAM里面先定义一个数组,把Flash中的数据取出来放到数组里面,在这个取出来的过程中,我们进行初步处理,就是判断哪些是无效数据。后面追加的数据肯定是要留下,而前面一点的数据则是要清理的,那么要清理的数据我们把它们的标志位置零,接着对Flash进行整页擦除,然后把数组里面标志不为零的数据再写入Flash里面。这样就完成了数据的清理。
    上面这种清理无效数据的方法算是比较常用的,但也有缺陷,因为我们的Flash采用追加的方式之后,里面的数据还是比较多的,这就要求我们在RAM里面定义一个相当大的数组,如果我们的程序把RAM已经使用的很大,那么剩下的空间不足够我们定义这么大的数组,就会造成数据溢出或者是把其他数据给覆盖掉,这是很致命的。那我们又该怎样解决这个问题呢。方法很简单,只要我们在要往Flash里追加数据的时候先通过标志寻到旧的数据,然后把它的标志清零再追加新数据,这样我们在整理数据的时候只需要定义一个很小的数组把Flash中标志不为零的数据取出来,对Flash进行整页擦除之后再把数据写进去就可以了。那这种方法又是否完美了?肯定不是。
    我们刚那种方法最大的缺陷就是寻找无效数据的时候太花时间,如果每改动一个数据都要遍历一页Flash一次或几次的话,在某些场合往往是无法忍受的,就像RTOS拒绝delay一样。如果不用这种方法又该怎样做才能更好的满足实时的需求又很好的避免在RAM中定义一个大数组的尴尬呢。相信也有很多程序编写者在思考这个问题,他们也肯定会有自己的处理方法。我在msOS里面就看到了一种比较新颖的处理方式。那么他是怎么处理的呢?
    在msOS这个系统中,他充分利用了变量在RAM中原有的存储空间。我们都知道程序中的指令都是存储在程序存储空间也就是Flash里面,变量是存放在数据存储空间(RAM)里面的,那么我们整理数据的时候定义的数组只用来存放标志(注意,这个标志直接就是变量在RAM中的地址),数据放回它在RAM中原有的数据存储空间去(虽然这样做会把初始化时的初始值覆盖掉,这个有好处也有坏处,看情况而定)。这样我们定义的数组就只是之前的一半就够了。
    好,数据存储就聊到这。以上都是个人在学习msOS时接触到的东西,如果有说的不对的或者不透彻的还请各位指正

最新回复

可惜我没机会在学校学习,学点不容易啊,哎……   详情 回复 发表于 2014-12-12 15:11

赞赏

2

查看全部赞赏

点赞 关注(1)
 

回复
举报

5979

帖子

8

TA的资源

版主

沙发
 
你的文章越来越耐看了!

点评

为这句话,多写几篇  详情 回复 发表于 2014-12-11 15:37
 
个人签名生活就是油盐酱醋再加一点糖,快活就是一天到晚乐呵呵的忙
===================================
做一个简单的人,踏实而务实,不沉溺幻想,不庸人自扰
 
 

回复

1071

帖子

7

TA的资源

纯净的硅(中级)

板凳
 
本帖最后由 dj狂人 于 2014-12-11 15:39 编辑
chenzhufly 发表于 2014-12-11 15:19
你的文章越来越耐看了!


为这句话,以后多写几篇
 
 
 

回复

6423

帖子

17

TA的资源

版主

4
 
这是因为Flash ROM在没有写入任何数据之前里面都是‘1’,我们写入数据只需要把相应的‘1’写成‘0’就可以了,但是它是不允许也不能把‘0’再写成‘1’的,这就是为什么Flash ROM不支持字节擦写的原因。
这个应该是先擦后写原因吧,并不是不支持字节擦写的原因

点评

恩恩 这里我想说得是 不能改变原有数据,比如如果某个地方有个数据’5‘,那么就不能在往这里写入数据了,就算写入也可能已经不是想要的结果  详情 回复 发表于 2014-12-11 21:53
 
个人签名training
 
 

回复

6423

帖子

17

TA的资源

版主

5
 
首先感谢撸主的总结分享,画了这么多图,撸主辛苦了。我在这里再帮撸主撸两下。
根据存储介质的不同,存储调度等等都有所不同,以楼主所说的片内flash也就是norflash来说了。
对于变量设置标志位来区分是哪个变量,如果五个变量是共生的就没有这个问答题了,可以直接按照便宜来区分是哪个变量。如果每次只修改其中的部分变量就要像楼主所说的那样做了。

另外一个致命的问题是没有进行掉电保护!既然要将数据记录在flash上就是想在断电的时候记录这些信息。在进行数据更新擦除时楼主的方法是将有效数据搬移到ram,然后将原数据擦除,可想而知这个时候断电,flash上的数据已经被擦除,ram中的数据因为断电也丢失了,对于数据是不可恢复的。

点评

”根据存储介质的不同,存储调度等等都有所不同,以楼主所说的片内flash也就是norflash来说了。 对于变量设置标志位来区分是哪个变量,如果五个变量是共生的就没有这个问答题了,可以直接按照便宜来区分是哪个  详情 回复 发表于 2014-12-11 22:00
 
个人签名training
 
 

回复

6423

帖子

17

TA的资源

版主

6
 
另外一个问题是楼主提到检索有效数据这个问题要遍历读,那楼主是否想到某个word地址已经被写过了呢?不是也要进行读才能判断出来。flash不能进行覆盖写,写两次的地址就不知道是个什么值了。对于检索是否写过总结一句就是都是没有映射惹的祸,而对于小容量的norflash确实没有必要进行地址映射,因为那将引入复杂的逻辑并占用一部分存储空间。
 
个人签名training
 
 

回复

6423

帖子

17

TA的资源

版主

7
 
对于擦除过的norflash是全1,在这个时候写入全1也是会出现问题的,解决的办法就是在进行全1写入的时候不进行写操作
 
个人签名training
 
 

回复

6423

帖子

17

TA的资源

版主

8
 
另外对于楼主担心擦除前有效数据放到ram,ram空间不够用的情况,可以考虑进行两个块的交替写入,即不在本块进行更新,异地更新才是固态存储的王道,将有效数据按word读出并立即写入另一个空白块,岂不是只用一个word的ram就够了,如果在此方法上加以简单的改进即可解决数据的掉电保护问题。等有效数据搬移完进行原块的擦除。只需要在块首进行标记即可找到数据

点评

恩恩 学习了  详情 回复 发表于 2014-12-11 22:04
 
个人签名training
 
 

回复

6423

帖子

17

TA的资源

版主

9
 
关于存储有一把的血泪史啊

点评

看来遇到前辈了 哈哈  详情 回复 发表于 2014-12-11 21:49
 
个人签名training
 
 

回复

6423

帖子

17

TA的资源

版主

10
 
对与存储我感觉有两点比较重要,一点是逻辑映射和调度算法(nandflash的复杂度已经不是一个级别了),二是掉电数据保护问题(这个感觉一直是很难处理的一个地方)
 
个人签名training
 
 

回复

1071

帖子

7

TA的资源

纯净的硅(中级)

11
 
白丁 发表于 2014-12-11 21:41
关于存储有一把的血泪史啊


看来遇到前辈了    哈哈

点评

前辈实在是算不上,相互学习吧  详情 回复 发表于 2014-12-11 21:52
 
 
 

回复

6423

帖子

17

TA的资源

版主

12
 
以上说的块是nandflash的最小擦除单位,norflash的擦除单位是sector,norflash中也有块的概念,这里比较习惯说块了,希望不要对别人引起误导
 
个人签名training
 
 

回复

6423

帖子

17

TA的资源

版主

13
 
dj狂人 发表于 2014-12-11 21:49
看来遇到前辈了    哈哈
前辈实在是算不上,相互学习吧
 
个人签名training
 
 

回复

1071

帖子

7

TA的资源

纯净的硅(中级)

14
 
白丁 发表于 2014-12-11 21:00
这是因为Flash ROM在没有写入任何数据之前里面都是‘1’,我们写入数据只需要把相应的‘1’写成‘0’就可以了,但是它是不允许也不能把‘0’再写成‘1’的,这就是为什么Flash ROM不支持字节擦写的原因。
这个应该是先擦后写原因吧,并不是不支持字节擦写的原因



恩恩     这里我想说得是 不能改变原有数据,比如如果某个地方有个数据’5‘,那么就不能在往这里写入数据了,就算写入也可能已经不是想要的结果
 
 
 

回复

1071

帖子

7

TA的资源

纯净的硅(中级)

15
 
白丁 发表于 2014-12-11 21:25
首先感谢撸主的总结分享,画了这么多图,撸主辛苦了。我在这里再帮撸主撸两下。
根据存储介质的不同,存储调度等等都有所不同,以楼主所说的片内flash也就是norflash来说了。
对于变量设置标志位来区分是哪个变量,如果五个变量是共生的就没有这个问答题了,可以直接按照便宜来区分是哪个变量。如果每次只修改其中的部分变量就要像楼主所说的那样做了。

另外一个致命的问题是没有进行掉电保护!既然要将数据记录在flash上就是想在断电的时候记录这些信息。在进行数据更新擦除时楼主的方法是将有效数据搬移到ram,然后将原数据擦除,可想而知这个时候断电,flash上的数据已经被擦除,ram中的数据因为断电也丢失了,对于数据是不可恢复的。


”根据存储介质的不同,存储调度等等都有所不同,以楼主所说的片内flash也就是norflash来说了。
对于变量设置标志位来区分是哪个变量,如果五个变量是共生的就没有这个问答题了,可以直接按照便宜来区分是哪个变量。如果每次只修改其中的部分变量就要像楼主所说的那样做了。“

这个我之前也考虑过这个问题,然后老师是这样说的,这个的从通用的角度出发。毕竟要保存的变量的存储区域有很大几率是分散的

另外一个致命的问题是没有进行掉电保护!既然要将数据记录在flash上就是想在断电的时候记录这些信息。在进行数据更新擦除时楼主的方法是将有效数据搬移到ram,然后将原数据擦除,可想而知这个时候断电,flash上的数据已经被擦除,ram中的数据因为断电也丢失了,对于数据是不可恢复的。


这个的话问题不大,因为当数据有改动的时候马上就追加到Flash里了,而清理无效数据可以放在开机的时候进行。不过要是突然掉电确实是个问题

点评

你还是学生吧,对于产品的稳定性没有做过多的考虑,当一个东西用的人多了,什么情况都会出现,对于存储类是非常有必要进行断电测试的  详情 回复 发表于 2014-12-11 22:08
 
 
 

回复

1071

帖子

7

TA的资源

纯净的硅(中级)

16
 
白丁 发表于 2014-12-11 21:39
另外对于楼主担心擦除前有效数据放到ram,ram空间不够用的情况,可以考虑进行两个块的交替写入,即不在本块进行更新,异地更新才是固态存储的王道,将有效数据按word读出并立即写入另一个空白块,岂不是只用一个word的ram就够了,如果在此方法上加以简单的改进即可解决数据的掉电保护问题。等有效数据搬移完进行原块的擦除。只需要在块首进行标记即可找到数据



恩恩  学习了
 
 
 

回复

6423

帖子

17

TA的资源

版主

17
 
dj狂人 发表于 2014-12-11 22:00
”根据存储介质的不同,存储调度等等都有所不同,以楼主所说的片内flash也就是norflash来说了。
对于变量设置标志位来区分是哪个变量,如果五个变量是共生的就没有这个问答题了,可以直接按照便宜来区分是哪个变量。如果每次只修改其中的部分变量就要像楼主所说的那样做了。“

这个我之前也考虑过这个问题,然后老师是这样说的,这个的从通用的角度出发。毕竟要保存的变量的存储区域有很大几率是分散的

”另外一个致命的问题是没有进行掉电保护!既然要将数据记录在flash上就是想在断电的时候记录这些信息。在进行数据更新擦除时楼主的方法是将有效数据搬移到ram,然后将原数据擦除,可想而知这个时候断电,flash上的数据已经被擦除,ram中的数据因为断电也丢失了,对于数据是不可恢复的。“


这个的话问题不大,因为当数据有改动的时候马上就追加到Flash里了,而清理无效数据可以放在开机的时候进行。不过要是突然掉电确实是个问题
你还是学生吧,对于产品的稳定性没有做过多的考虑,当一个东西用的人多了,什么情况都会出现,对于存储类是非常有必要进行断电测试的

点评

恩恩 还在读书。确实,我的思维还停留在单纯的应用层面,往往没有考虑到用户和实际情况等方面,考虑问题不周全  详情 回复 发表于 2014-12-11 22:13
 
个人签名training
 
 

回复

1071

帖子

7

TA的资源

纯净的硅(中级)

18
 
白丁 发表于 2014-12-11 22:08
你还是学生吧,对于产品的稳定性没有做过多的考虑,当一个东西用的人多了,什么情况都会出现,对于存储类是非常有必要进行断电测试的



恩恩   还在读书。确实,我的思维还停留在单纯的应用层面,往往没有考虑到用户和实际情况等方面,考虑问题不周全
 
 
 

回复

1298

帖子

0

TA的资源

纯净的硅(高级)

19
 
可惜我没机会在学校学习,学点不容易啊,哎……

点评

在哪都可以学习,相比外面能接触到更到贴近真实生活的东西  详情 回复 发表于 2014-12-12 16:27
 
 
 

回复

1071

帖子

7

TA的资源

纯净的硅(中级)

20
 
gh131413 发表于 2014-12-12 15:11
可惜我没机会在学校学习,学点不容易啊,哎……



在哪都可以学习,相比外面能接触到更到贴近真实生活的东西
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表