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

Tobey   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



回复评论 (14)

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

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

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

好的 谢谢
点赞  2017-7-21 15:01
那啥,楼主,你那样求 缓冲长度 是不对的......

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

  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
强者为尊,弱者,死无葬身之地
点赞  2017-8-9 11:36
看了帖子,我梳理一下
你的问题应该是:

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

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

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

不需要对那些没用的内容做什么多一步的补齐。
强者为尊,弱者,死无葬身之地
点赞  2017-8-9 11:49
至于malloc问题,我的建议是,你先检查一下你的 单片机的 s文件,heap空间留了多少。
其实我看到你的问题我觉得很奇怪,假如分配成功,返回结果非NULL,按道理就不该出现这个奇怪的问题。
强者为尊,弱者,死无葬身之地
点赞  2017-8-9 11:50
引用: 辛昕 发表于 2017-8-9 11:36
那啥,楼主,你那样求 缓冲长度 是不对的......

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

[mw_shl_code=c,t ...

我是在codeblock上写的测试代码,,不过记得一开始用变量测试过的,得到的结果是正确的,上面这是不是没赋初始值所以得到的是错误的?今天去游泳了,明天我再试试
点赞  2017-8-9 18:39
引用: 辛昕 发表于 2017-8-9 11:49
看了帖子,我梳理一下
你的问题应该是:

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

嗯 其实源程序就是按照您说的方式进行写入操作的,不过一个页面感觉还是太大了,所以我现在仅在扇区首地址写入数据时进行擦除操作,并且按照页为基本单位写入数据,也就是每次最少可以仅对256个字节进行操作
点赞  2017-8-9 18:40
引用: 辛昕 发表于 2017-8-9 11:50
至于malloc问题,我的建议是,你先检查一下你的 单片机的 s文件,heap空间留了多少。
其实我看到你的问题 ...

多谢提醒,这部分代码我没在单片机上测试,仅在PC上跑了跑,单片机上的程序后来直接开了个定长的数组进行写入操作,,测试程序也被搁置了,明天我再试试
点赞  2017-8-9 18:43
引用: Tobey 发表于 2017-8-9 18:39
我是在codeblock上写的测试代码,,不过记得一开始用变量测试过的,得到的结果是正确的,上面这是 ...

应该是用变量凑巧对了。
不管有没赋值,这没关系。
因为数组传递的时候,是作为地址,地址就和指针一样,只是一个 4字节的数据,任何时候都是。
除非这机器类型是8位或者64位,那就是2个字节或者8个字节,但永远都不再是那个数组。
强者为尊,弱者,死无葬身之地
点赞  2017-8-10 10:06
引用: Tobey 发表于 2017-8-9 18:40
嗯 其实源程序就是按照您说的方式进行写入操作的,不过一个页面感觉还是太大了,所以我现在仅在扇区首地 ...

嗯,256当然很好。
这也是flash比之eprom不好的地方,但是,有利有弊了。
其实对于现在的大多数单片机,用4K到8K的RAM也还好了,没多大事。
强者为尊,弱者,死无葬身之地
点赞  2017-8-10 10:09
我是来学习的
我是好宝宝,我要努力奋斗
点赞  2017-8-11 10:29
引用: 辛昕 发表于 2017-8-10 10:06
应该是用变量凑巧对了。
不管有没赋值,这没关系。
因为数组传递的时候,是作为地址,地址就和指针一样 ...

确实,,把之前的测试程序重新运行了几次,,都是错的
点赞  2017-8-11 17:02
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复