72677


Arduinoで開発しています。  
100Hz(10ms)でセンサデータ取得しRAMにため込み、10秒ごとに100KB程度のデータをmicroSDにwriteしています。  
microSDの処理時間がクロック周波数156
MHzの時、20ms～40msでセンサの周期10msより長いため、microSDにwriteすると、センサ取得時間を逃してしまいます。

質問1.microSDへのwriteを高速化する方法はありませんか。  
質問2.microSDへのWriteをノンブロッキング処理に変更する方法はありませんか。  
質問3.内蔵FLASHの容量は8MBで間違いありませんか。


CC BY-SA 4.0
2020-12-10T14:01:18.647
72574
2020-12-15T14:13:25.453
43103
question
spresense
microSDへのwrite処理をバックグラウンドにできませんか


直接質問に答えるには情報が不足しているので一般論

1 : microSD 自体の速度は十分か (class いくつ?)  
2 : とにかく RAM にため込み、測定の終了段階で microSD に書くのではだめか？  
3 : Arduino は確か 5V 電源なので microSD 3.3V に直結はできなかったはず、電圧変換回路は？

microSD 側が遅いのであればノンブロッキングにしたところで破綻するのは見えているっス。  
電圧変換回路の IC の仕様次第では速度を上げることはハード的に不可能

ってことでオイラなら 2. を採用するっス（測定時間に制限が発生するが制約事項とする）


CC BY-SA 4.0
2020-12-14T07:07:13.240
72641
2020-12-14T07:07:13.240
8589
72574
answer


> 質問1.microSDへのwriteを高速化する方法はありませんか。  
>  質問2.microSDへのWriteをノンブロッキング処理に変更する方法はありませんか。

microSDへの書き込みを高速化する方法については知らないのですが、  
Arduinoのloop処理だけでは実現できないと思うので、  
どうすれば良いかちょっと方法を考えてみました。

  1. マルチタスクで処理する
  2. マルチコアを使う

(1) マルチタスク化

SPRESENSEのArduino環境は中にOSが搭載されているのでマルチタスクで動かすことができます。  
task_create()関数でSD書き込み専用のタスクを作成します。  
作成するタスクはsetup/loopよりも優先度を低くしておきます。  
setup/loopが優先度100で動作しているので、優先度はそれよりも低い90で作成しておきます。

センサデータ用のRAMはA面/B面のダブルバッファを用意しておいて、  
A面->B面->A面->... と順番にバッファリングするようにします。  
A面のバッファが溜まった状態で、SD書き込み専用タスクへA面データの書き込み処理を依頼します。  
A面をSDカードへ書き込みしている間は、センサーデータをB面に溜め続けます。

以下のようなイメージで並行動作させます。

[code]

    センサデータ A面→B面→A面->...
    SDへ書き込み     A面→B面->...
    
[/code]

ざっくりとした実装イメージは以下の通りです。

[code]

    SDClass SD;
    File file;
    sem_t sem; // タスク間通信用セマフォ
    
    static int save_task(int argc, FAR char *argv[])
    {
      while (1) {
        sem_wait(&sem);
        file.write(buf, size); // 溜まったバッファをファイルに書き込み
        file.flush();
      }
    }
    
    void setup()
    {
      while (!SD.begin());
      file = SD.open("sensor.log", FILE_WRITE);
      sem_init(&sem, 0, 0);
      task_create("save_task", 90, 2048, save_task, NULL);
    }
    
    void loop()
    {
      センサデータ取得A面/B面へ保存
      
      if (バッファが溜まったら) {
        sem_post(&sem); // 書き込みタスクを起こす
      }
      usleep(1);
    }
    
[/code]

(2) マルチコアを使う

SPRESENSEのマルチコア環境を使用して、  
<https://developer.sony.com/develop/spresense/docs/arduino_tutorials_ja.html#_tutorial_multicore>  
センサデータの取得をSubCoreで実行し、SDカードへの書き込みをMainCoreで実行します。

こちらもダブルバッファにしておいて、  
SubCoreはセンサデータをA面/B面に順番に溜めておいてバッファが一杯になったら  
MainCoreにバッファのポインタを渡すだけ、  
MainCoreはポインタを受け取ったらそれをSDカードへ書き込むだけ、  
こちらの方が簡単に実現できそうな気がします。

> 質問3.内蔵FLASHの容量は8MBで間違いありませんか。

内蔵FLASHはトータル8MBで、半分の4MBがファームウェア(プログラム)保存領域、  
もう半分の4MBがアプリケーションから自由に触れるストレージ領域になっているようです。


CC BY-SA 4.0
2020-12-15T14:13:25.453
72677
2020-12-15T14:13:25.453
31378
72574
answer