查看: 4775|回复: 10

Arduino/Genuino101教程——使用板载Flash储存

[复制链接]
  • TA的每日心情
    奋斗
    2018-8-17 09:12
  • 签到天数: 47 天

    [LV.5]常住居民I

    发表于 2016-7-26 22:24 | 显示全部楼层 |阅读模式
    在Genuino101上有一个Flash芯片,其使用SPI总线连接,提供了2MB的存储空间。2MB的flash对于一般单片机来说已经是超大的空间了。
    101  .jpg

    官方提供了一个SerialFlash库用于flash芯片的操作。名为SerialFlash
    https://github.com/01org/corelibs-arduino101/tree/master/libraries/SerialFlash


    要使用该类库,一般掌握以下几种操作即可:

    打开文件
    [C++] 纯文本查看 复制代码
    SerialFlashFile file;
    file = SerialFlash.open("filename.bin");
    if (file) {  // true if the file exists
    


    读数据
    [C++] 纯文本查看 复制代码
    char buffer[256];
    file.read(buffer, 256);


    获取文件尺寸和位置
    [C++] 纯文本查看 复制代码
    file.size();
    file.position()
    file.seek(number);
    


    写数据
    [C++] 纯文本查看 复制代码
    file.write(buffer, 256);
    


    需要注意的是,写入的数据不能超过该文件本身的大小。

    擦除
    [C++] 纯文本查看 复制代码
    file.erase();

    Only files created for erasing can be erased. The entire file is erased to all 255 (0xFF) bytes.
    擦除文件,就是将指定文件全部内容写为255 (0xFF)

    文件管理操作
    创建新文件
    [C++] 纯文本查看 复制代码
    SerialFlash.create(filename, size);
    SerialFlash.createErasable(filename, size);


    返回值为布尔型,返回True说明创建成功,返回false说明创建失败(没有足够的可用空间)
    创建后,文件大小不可更改。

    Files created for erasing automatically increase in size to the nearest number of erasable blocks, resulting in a file that may be 4K to 128K larger than requested.

    删除文件
    [C++] 纯文本查看 复制代码
    SerialFlash.remove(filename);

    删除文件后,其暂用的空间不会被回收,但删除后,可以再创建一个同名文件。

    检查文件是否存在(不会打开文件)
    [C++] 纯文本查看 复制代码
    SerialFlash.exists(filename);


    A list of files stored in the Flash can be accessed with readdir(), which returns true for each file, or false to indicate no more files.


    写文件示例
    [C++] 纯文本查看 复制代码
    #include <SerialFlash.h>
    #include <SPI.h>
    
    #define FSIZE 256
    
    const char *filename = "myfile.txt";
    const char *contents = "0123456789ABCDEF";
    
    const int FlashChipSelect = 21; // digital pin for flash chip CS pin
    
    void setup() {
      Serial.begin(9600);
    
      // wait for Arduino Serial Monitor
      while (!Serial) ;
      delay(100);
      // Init. SPI Flash chip
      if (!SerialFlash.begin(FlashChipSelect)) {
        Serial.println("Unable to access SPI Flash chip");
      }
    
      SerialFlashFile file;
    
      // Create the file if it doesn't exist
      if (!create_if_not_exists(filename)) {
        Serial.println("Not enough space to create file " + String(filename));
        return;
      }
      // Open the file and write test data
      file = SerialFlash.open(filename);
      file.write(contents, strlen(contents) + 1);
      Serial.println("String \"" + String(contents) + "\" written to file " + String(filename));
    }
    
    bool create_if_not_exists (const char *filename) {
      if (!SerialFlash.exists(filename)) {
        Serial.println("Creating file " + String(filename));
        return SerialFlash.create(filename, FSIZE);
      }
    
      Serial.println("File " + String(filename) + " already exists");
      return true;
    }
    
    void loop() {
    }


    列出所有文件信息
    列出文件使用以下两个函数,可以列出flash芯片中的文件:
    [C++] 纯文本查看 复制代码
    SerialFlash.opendir();
    SerialFlash.readdir(buffer, buflen, filelen);

    具体使用方法如下:

    [C++] 纯文本查看 复制代码
    #include <SerialFlash.h>
    #include <SPI.h>
    
    const int FlashChipSelect = 21; // digital pin for flash chip CS pin
    
    void setup() {
      Serial.begin(9600);
    
      // wait for Arduino Serial Monitor
      while (!Serial) ;
      delay(100);
      Serial.println("All Files on SPI Flash chip:");
    
      if (!SerialFlash.begin(FlashChipSelect)) {
        error("Unable to access SPI Flash chip");
      }
    
      SerialFlash.opendir();
      unsigned int count = 0;
      while (1) {
        char filename[64];
        unsigned long filesize;
    
        if (SerialFlash.readdir(filename, sizeof(filename), filesize)) {
          Serial.print("  ");
          Serial.print(filename);
          spaces(20 - strlen(filename));
          Serial.print("  ");
          Serial.print(filesize);
          Serial.print(" bytes");
          Serial.println();
        } else {
          break; // no more files
        }
      }
    }
    
    void spaces(int num) {
      for (int i=0; i < num; i++) {
        Serial.print(" ");
      }
    }
    
    void loop() {
    }
    
    void error(const char *message) {
      while (1) {
        Serial.println(message);
        delay(2500);
      }
    }


    擦除flash芯片
    [C++] 纯文本查看 复制代码
    #include <SerialFlash.h>
    #include <SPI.h>
    
    const int FlashChipSelect = 21; // digital pin for flash chip CS pin
    
    SerialFlashFile file;
    
    const unsigned long testIncrement = 4096;
    
    void setup() {
      Serial.begin(9600);
    
      // wait up to 10 seconds for Arduino Serial Monitor
      unsigned long startMillis = millis();
      while (!Serial && (millis() - startMillis < 10000)) ;
      delay(100);
    
      SerialFlash.begin(FlashChipSelect);
      unsigned char id[5];
      SerialFlash.readID(id);
      unsigned long size = SerialFlash.capacity(id);
    
      if (size > 0) {
        Serial.print("Flash Memory has ");
        Serial.print(size);
        Serial.println(" bytes.");
        Serial.println("Erasing ALL Flash Memory:");
        // Estimate the (lengthy) wait time.
        Serial.print("  estimated wait: ");
        int seconds = (float)size / eraseBytesPerSecond(id) + 0.5;
        Serial.print(seconds);
        Serial.println(" seconds.");
        Serial.println("  Yes, full chip erase is SLOW!");
        SerialFlash.eraseAll();
        unsigned long dotMillis = millis();
        unsigned char dotcount = 0;
        while (SerialFlash.ready() == false) {
          if (millis() - dotMillis > 1000) {
            dotMillis = dotMillis + 1000;
            Serial.print(".");
            dotcount = dotcount + 1;
            if (dotcount >= 60) {
              Serial.println();
              dotcount = 0;
            }
          }
        }
        if (dotcount > 0) Serial.println();
        Serial.println("Erase completed");
        unsigned long elapsed = millis() - startMillis;
        Serial.print("  actual wait: ");
        Serial.print(elapsed / 1000ul);
        Serial.println(" seconds.");
      }
    }
    
    float eraseBytesPerSecond(const unsigned char *id) {
      if (id[0] == 0x20) return 152000.0; // Micron
      if (id[0] == 0x01) return 500000.0; // Spansion
      if (id[0] == 0xEF) return 419430.0; // Winbond
      if (id[0] == 0xC2) return 279620.0; // Macronix
      return 320000.0; // guess?
    }
    
    
    void loop() {
    
    }

            解释下最后的eraseBytesPerSecond函数,注释中的Micron、Spansion、Winbond、 Macronix都是flash芯片的厂家,每个厂家芯片的擦写速度都不一样,通过读取id[0],可以判断其生产厂家,进而知晓其擦写速度。



    为了方便大家学习理解,重写了读写示例程序http://www.arduino.cn/thread-41120-1-1.html









    如果以上内容对你有帮助,你可以通过打赏支持作者

    1人打赏

    该用户从未签到

    发表于 2016-11-4 10:51 | 显示全部楼层
    楼主,请问可以读出文件里面的内容吗?

    点评

    你自己通过以上API接入的内容,可以读出  详情 回复 发表于 2016-11-4 12:22
  • TA的每日心情
    奋斗
    2018-8-17 09:12
  • 签到天数: 47 天

    [LV.5]常住居民I

     楼主| 发表于 2016-11-4 12:22 | 显示全部楼层
    TUONIAOATUONIAO 发表于 2016-11-4 10:51
    楼主,请问可以读出文件里面的内容吗?

    你自己通过以上API接入的内容,可以读出
    如果以上内容对你有帮助,你可以通过打赏支持作者

    该用户从未签到

    发表于 2017-3-30 23:18 | 显示全部楼层
    上传项目出错
    Starting download script...

    该用户从未签到

    发表于 2018-1-27 19:36 | 显示全部楼层
    请问flash完全没反应是什么回事呢?
    curienano的板子,利用帖子里面的程序。
    SerialFlash.begin(g_FlashChipSelect)这句就完全没反应

    该用户从未签到

    发表于 2018-3-13 20:32 | 显示全部楼层
    楼主,我想请教个问题。
    file.erase();//擦除文件,就是将指定文件全部内容写为255 (0xFF)
    SerialFlash.remove(filename);//删除文件,其暂用的空间不会被回收,但删除后,可以再创建一个同名文件。
    Q:删除文件后其占用的空间不会被回收。那么擦除文件可否回收它占用的空间?
    难道说,该文件创建后它所占用的空间就无法回收了吗?只能将flash芯片全都擦除才可以吗???

    该用户从未签到

    发表于 2018-3-13 20:39 | 显示全部楼层
    楼主,你是陈吕洲吗

    点评

    对  详情 回复 发表于 2018-3-13 22:41
  • TA的每日心情
    奋斗
    2018-8-17 09:12
  • 签到天数: 47 天

    [LV.5]常住居民I

     楼主| 发表于 2018-3-13 22:41 | 显示全部楼层
    ouyangxin 发表于 2018-3-13 20:39
    楼主,你是陈吕洲吗

    如果以上内容对你有帮助,你可以通过打赏支持作者

    该用户从未签到

    发表于 2018-3-15 16:48 | 显示全部楼层
    请教个问题。
    file.erase();//擦除文件,就是将指定文件全部内容写为255 (0xFF)
    SerialFlash.remove(filename);//删除文件,其暂用的空间不会被回收,但删除后,可以再创建一个同名文件。
    Q:删除文件后其占用的空间不会被回收。那么擦除文件可否回收它占用的空间?
    难道说,该文件创建后它所占用的空间就无法回收了吗?只能将flash芯片全都擦除才可以吗???

    该用户从未签到

    发表于 2018-4-16 00:30 | 显示全部楼层
    原来的SerialFlash库在GITHUB好像挂掉了,有可以用来替换的么?
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    外部中断及LCD显示
    外部中断及LCD显示
    最近才刚开始学习Arduino,有好多不会的地方。 关于外部中断和LCD的一些问题,有人可
    有没有大神解决一下烧录程序的问题
    有没有大神解决一下烧录程
    是这样的....最近买了一块arduino,想自学,先从最简单的闪灯开始实验。我安装好了驱
    自制Arduino最小系统板,集成N多种功能,赶快来围观吧》》》
    自制Arduino最小系统板,
    前文: 最近想做点遥控的小玩具,所以一直在寻找一款实用的开发板(最好是兼容a
    原创 drawbot平面关节机械臂 教程直播贴
    原创 drawbot平面关节机械
    这个项目上个月就在做了,结构和代码反反复复改了多次,加上自己又太忙,一直没来得及
    串口数据处理问题请教
    串口数据处理问题请教
    数据如右图:现在想做的是将标志位200以下的连续8个数依次接收存入数组,也就是依次存
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表