社区导航

 

搜索
查看: 1591|回复: 14

[求助] 需要实现spiflash的山区读写操作,如何快速补足数组而不丢失数据?

[复制链接]

304

TA的帖子

5

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

发表于 2017-7-20 09:48 | 显示全部楼层 |阅读模式


硬件:
     MCU: stm32f103,
     FLASH: w25q128
开发平台:
     keil5.20

需要在一块板子上实现spi_flash以扇区大小为单位的读写操作,接口函数如下:
  1. /*
  2. *********************************************************************************************************
  3. *        函 数 名: sf_WriteSector
  4. *        功能说明: 向指定扇区写入整个扇区的数据
  5. *        形    参:  _pBuf:数据源缓冲区
  6. *                                                _uSectorNumber:扇区编号(以w25q128为例,编号取值范围为0~4095)
  7. *        返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void sf_WriteSector(uint8_t * _pBuf, uint16_t _uSectorNumber)
  11. {
  12.         uint16_t len;
  13.         uint16_t i;
  14.         len = sizeof(_pBuf)/sizeof(uint8_t);
  15.         if(4096 > len)
  16.         {
  17.                     //当写入数据缓冲区大小小于扇区大小时进行补足操作
  18.         }
  19.         sf_WriteBuffer(_pBuf, _uSectorNumber*4096+0, 4096);//写入数据缓冲区,扇区编号,扇区大小
  20. }

  21. /*
  22. *********************************************************************************************************
  23. *        函 数 名: sf_ReadSector
  24. *        功能说明: 读取指定扇区的全部数据
  25. *        形    参:  _pBuf:读取数据缓冲区
  26. *                                                _uSectorNumber:扇区编号(以w25q128为例,编号取值范围为0~4095)
  27. *        返 回 值: 无
  28. *********************************************************************************************************
  29. */
  30. void sf_ReadSector(uint8_t * _pBuf, uint16_t _uSectorNumber)
  31. {
  32.         sf_ReadBuffer(_pBuf, _uSectorNumber*4096+0, 4096);
  33. }
复制代码


需要考虑写入时,若写入数据缓冲区数据不足4K(一个扇区的大小),那么就需要对其进行补足操作,
使用code blocks验证malloc、sizeof、memcpy的用法,测试代码如下所示:
malloc: 不知道什么原因,不管是len=(int*)malloc(3*sizeof(int))
len=(int*)malloc(6*sizeof(int)),malloc所分配的内存大小长度‘len一直为1~~
不过使用malloc进行内存分配,则数组中的原始数据将被覆盖,,
sizeof:主要是为了测试如何得到传入数据的长度,可以通过sizeof(array)/sizeof(TYPE)得到数组长度
memcpy: 可采用它实现数组补足功能
不过还是未找到扩充数组长度且保留数组元数据的方法,请问各位大神遇到这种情况怎么解决呢?
  1. #include"stdio.h"
  2. #include"stdlib.h"
  3. #include"string.h"

  4. int main()
  5. {
  6.     int i;
  7.     int len;
  8.     int* array;
  9.     int* arrayCopy;
  10.     int data = 3;

  11.     /*测试数组内存分配及赋值*/
  12.     array = (int*)malloc(3*sizeof(int));
  13.     if(!array)
  14.     {
  15.         printf("创建数组失败!\n");
  16.         exit(1);
  17.     }

  18.     memcpy(array,&data,3*sizeof(int));
  19.     len = sizeof(array)/sizeof(int);

  20.     for(i=0; i<len-1; i++)
  21.     {
  22.         printf("%d ",array[i]);
  23.     }
  24.     printf("%d & first array len is %d\n",array[i], len);

  25.     /*测试数组扩展*/
  26.     array = (int*)malloc(6*sizeof(int));
  27.     if(!array)
  28.     {
  29.         printf("创建数组失败!\n");
  30.         exit(1);
  31.     }
  32.     len = sizeof(array)/sizeof(int);
  33.     for(i=0; i<len-1; i++)
  34.     {
  35.         printf("%d ",array[i]);
  36.     }
  37.     printf("%d & second array len is %d\n",array[i], len);
  38. }
复制代码

运行结果:

test.jpg



此帖出自编程基础论坛

回复

使用道具 举报

1775

TA的帖子

0

TA的资源

五彩晶圆(初级)

Rank: 7Rank: 7Rank: 7

发表于 2017-7-20 10:41 | 显示全部楼层
在写入函数中进行补足就可以了啊,你的写入函数传递的参数有要写入的数据缓冲区指针和要写入的数据个数,那么在写入函数里面进行判断,如果传递进来的数据个数等于一个扇区的大小,就不用补足直接写入,要是小于一个扇区的大小,则将要写入的数据写入之后,再将剩余的空间使用预设的补足数据写入不就可以啦

点评

多谢指点!思路是有的,想请教下有没有可以偷懒的方法,例如合理调用标准库中相应的库函数来实现数组补足功能,那样就可以直接调用库函数解决了  详情 回复 发表于 2017-7-21 11:19

回复

使用道具 举报

304

TA的帖子

5

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

 楼主| 发表于 2017-7-21 11:19 | 显示全部楼层
bobde163 发表于 2017-7-20 10:41
在写入函数中进行补足就可以了啊,你的写入函数传递的参数有要写入的数据缓冲区指针和要写入的数据个数,那 ...

多谢指点!思路是有的,想请教下有没有可以偷懒的方法,例如合理调用标准库中相应的库函数来实现数组补足功能,那样就可以直接调用库函数解决了

点评

有些标准库函数调用了反倒会增加单片机的负担,具体看情况而定,使用简单易懂的方式去实现就好  详情 回复 发表于 2017-7-21 13:58

回复

使用道具 举报

1775

TA的帖子

0

TA的资源

五彩晶圆(初级)

Rank: 7Rank: 7Rank: 7

发表于 2017-7-21 13:58 | 显示全部楼层
Tobey 发表于 2017-7-21 11:19
多谢指点!思路是有的,想请教下有没有可以偷懒的方法,例如合理调用标准库中相应的库函数来实现数组补足 ...

有些标准库函数调用了反倒会增加单片机的负担,具体看情况而定,使用简单易懂的方式去实现就好

点评

好的 谢谢  详情 回复 发表于 2017-7-21 15:01

回复

使用道具 举报

304

TA的帖子

5

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

 楼主| 发表于 2017-7-21 15:01 | 显示全部楼层
bobde163 发表于 2017-7-21 13:58
有些标准库函数调用了反倒会增加单片机的负担,具体看情况而定,使用简单易懂的方式去实现就好

好的 谢谢

回复

使用道具 举报

7903

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2017-8-9 11:36 | 显示全部楼层
那啥,楼主,你那样求 缓冲长度 是不对的......

有代码为证(从你那偷的........)

  1. //=========================================
  2. uint8_t temp[1024];

  3. void sf_WriteSector(uint8_t * _pBuf)
  4. {
  5.     uint16_t len;
  6.     uint16_t i;
  7.     len = sizeof(_pBuf)/sizeof(uint8_t);
  8.     printf("i...i can get the right size??? %d\n",len);
  9. }

  10. //=========================================

  11. int main()
  12. {
  13.     //monthly();
  14.     //printf("============================================\n");
  15.     //weekly();
  16.     sf_WriteSector(temp);
  17.     return 0;
  18. }
复制代码


有图有真相
QQ图片20170809113507.png

点评

我是在codeblock上写的测试代码,,不过记得一开始用变量测试过的,得到的结果是正确的,上面这是不是没赋初始值所以得到的是错误的?今天去游泳了,明天我再试试  详情 回复 发表于 2017-8-9 18:39

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

7903

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2017-8-9 11:49 | 显示全部楼层
看了帖子,我梳理一下
你的问题应该是:

你是想一次写4K一个页的大小?
——其实为什么呢?
不需要的,虽然一次擦除是页擦除,但是每次写的时候,你可以直接在 4对齐的任意地址开始写的。

如果说遇到 每次写都要擦除,因为你要覆盖原内容,我是这么做的。

比方说,在1个4K页里,假如我要改写最开始那1K的内容,那我就直接搞一个4K的局部数组——如果你的栈不够大,那就用全局数组好了。
然后直接把4K全部读出来,然后只修改前1K,或其他任何你要修改的地方,然后别的原封不动,再写回去就好了。

不需要对那些没用的内容做什么多一步的补齐。

点评

嗯 其实源程序就是按照您说的方式进行写入操作的,不过一个页面感觉还是太大了,所以我现在仅在扇区首地址写入数据时进行擦除操作,并且按照页为基本单位写入数据,也就是每次最少可以仅对256个字节进行操作  详情 回复 发表于 2017-8-9 18:40

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

7903

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2017-8-9 11:50 | 显示全部楼层
至于malloc问题,我的建议是,你先检查一下你的 单片机的 s文件,heap空间留了多少。
其实我看到你的问题我觉得很奇怪,假如分配成功,返回结果非NULL,按道理就不该出现这个奇怪的问题。

点评

多谢提醒,这部分代码我没在单片机上测试,仅在PC上跑了跑,单片机上的程序后来直接开了个定长的数组进行写入操作,,测试程序也被搁置了,明天我再试试  详情 回复 发表于 2017-8-9 18:43

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

304

TA的帖子

5

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

 楼主| 发表于 2017-8-9 18:39 | 显示全部楼层
辛昕 发表于 2017-8-9 11:36
那啥,楼主,你那样求 缓冲长度 是不对的......

有代码为证(从你那偷的........)

[mw_shl_code=c,t ...

我是在codeblock上写的测试代码,,不过记得一开始用变量测试过的,得到的结果是正确的,上面这是不是没赋初始值所以得到的是错误的?今天去游泳了,明天我再试试

点评

应该是用变量凑巧对了。 不管有没赋值,这没关系。 因为数组传递的时候,是作为地址,地址就和指针一样,只是一个 4字节的数据,任何时候都是。 除非这机器类型是8位或者64位,那就是2个字节或者8个字节,但永远  详情 回复 发表于 2017-8-10 10:06

回复

使用道具 举报

304

TA的帖子

5

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

 楼主| 发表于 2017-8-9 18:40 | 显示全部楼层
辛昕 发表于 2017-8-9 11:49
看了帖子,我梳理一下
你的问题应该是:

你是想一次写4K一个页的大小?
——其实为什么呢?
不需要的 ...

嗯 其实源程序就是按照您说的方式进行写入操作的,不过一个页面感觉还是太大了,所以我现在仅在扇区首地址写入数据时进行擦除操作,并且按照页为基本单位写入数据,也就是每次最少可以仅对256个字节进行操作

点评

嗯,256当然很好。 这也是flash比之eprom不好的地方,但是,有利有弊了。 其实对于现在的大多数单片机,用4K到8K的RAM也还好了,没多大事。  详情 回复 发表于 2017-8-10 10:09

回复

使用道具 举报

304

TA的帖子

5

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

 楼主| 发表于 2017-8-9 18:43 | 显示全部楼层
辛昕 发表于 2017-8-9 11:50
至于malloc问题,我的建议是,你先检查一下你的 单片机的 s文件,heap空间留了多少。
其实我看到你的问题 ...

多谢提醒,这部分代码我没在单片机上测试,仅在PC上跑了跑,单片机上的程序后来直接开了个定长的数组进行写入操作,,测试程序也被搁置了,明天我再试试

回复

使用道具 举报

7903

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2017-8-10 10:06 | 显示全部楼层
Tobey 发表于 2017-8-9 18:39
我是在codeblock上写的测试代码,,不过记得一开始用变量测试过的,得到的结果是正确的,上面这是 ...

应该是用变量凑巧对了。
不管有没赋值,这没关系。
因为数组传递的时候,是作为地址,地址就和指针一样,只是一个 4字节的数据,任何时候都是。
除非这机器类型是8位或者64位,那就是2个字节或者8个字节,但永远都不再是那个数组。

点评

确实,,把之前的测试程序重新运行了几次,,都是错的  详情 回复 发表于 2017-8-11 17:02

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

7903

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2017-8-10 10:09 | 显示全部楼层
Tobey 发表于 2017-8-9 18:40
嗯 其实源程序就是按照您说的方式进行写入操作的,不过一个页面感觉还是太大了,所以我现在仅在扇区首地 ...

嗯,256当然很好。
这也是flash比之eprom不好的地方,但是,有利有弊了。
其实对于现在的大多数单片机,用4K到8K的RAM也还好了,没多大事。

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

47

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2017-8-11 10:29 | 显示全部楼层
我是来学习的
我是好宝宝,我要努力奋斗

回复

使用道具 举报

304

TA的帖子

5

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

 楼主| 发表于 2017-8-11 17:02 | 显示全部楼层
辛昕 发表于 2017-8-10 10:06
应该是用变量凑巧对了。
不管有没赋值,这没关系。
因为数组传递的时候,是作为地址,地址就和指针一样 ...

确实,,把之前的测试程序重新运行了几次,,都是错的

回复

使用道具 举报

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

关闭

站长推荐上一条 1/4 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-4-2 21:21 , Processed in 0.416992 second(s), 21 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表