フォト
2018年11月
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  
無料ブログはココログ

« STM32関連 「STM32HAL&SW4入門 Kindle版」を読んでみると.. | トップページ | micro:bitをArduino環境で使う(4)豊四季Tiny BASICを動かしてみる »

2017年12月25日 (月)

micro:bitをArduino環境で使う (3)内部フラッシュへのデータ書き込み

256kバイトもあるフラッシュメモリにプログラムから自由にデータを書き込みたいと思い、ライブラリを作成しまた。

2017/12/27 更新
書込みの*addr++ = *ptr++;の両アドレスが4バイト境界でないとフォルトを起こしてしまうようです。
その防止のためのエラー処理を追加しました。

ライブラリ

//
// フラッシュメモリ書き込みライブラリ
// 2017/12/25 by たま吉さん
// 参考文献
//  nRF51 Series Reference Manual Version 3.0 「6 Non-Volatile Memory Controller (NVMC)」
//

#include <Arduino.h>
#include "nrf.h"

//
// フラッシュメモリ指定ページ消去
// フラッシュメモリアドレスは、0x00000000 ~ 0x0003FFFFの範囲とする
// 1ページのサイズは1024バイトとし、アドレスは
//
// 引数
//   addr 消去対象ページ先頭アドレス
// 戻り値
//   0:正常終了
//   1:異常終了(指定アドレスが正しくない)
//
uint8_t  flashPageErase(uint32_t addr) {
  if ( addr >= 0x00040000 )
    return 1;  // フラッシュメモリ領域外
  if ( addr % 1024 )
    return 1;  // ページ先頭アドレスでない
  
  // 書込みアンロック
  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);

  // 指定ページの消去
  NRF_NVMC->ERASEPAGE = addr;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);

  // 書込みロック
  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
  return 0;
}

// フラッシュメモリ32ビットワードデータ書き込み
// 引数
//  addr: 書込みアドレス(4バイト境界アドレスであること)
//  ptr : 書込みデータ格納アドレス(4バイト境界アドレスであること)
//  len : 書込みデータ長さ
// 戻り値
//   0:正常終了
//   1:異常終了(指定アドレスが正しくない)
//
uint8_t flashWriteData(uint32_t* addr, uint32_t *ptr, uint16_t len) {

  if ( ((uint32_t)addr) >= 0x00040000 )
    return 1;  // フラッシュメモリ領域外
  if ( ((uint32_t)addr) % 1024 )
    return 1;  // ページ先頭アドレスでない
  if (((uint32_t)ptr)%4)
    return 1;  // 4バイト境界アドレスでない
    
  // 書込み有効設定
  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);

  // データ書き込みループ
  for (uint32_t i = 0; i<len; i++) {
    *addr++ = *ptr++;
    //Serial.println(i,DEC); 
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
  }

  // 書込み無効設定
  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
  return 0;
}


利用サンプルスケッチ
//
// micro:bit フラッシュメモリ書込みテスト 2017/12/25 by たま吉さん
//

uint8_t  flashPageErase(uint32_t addr);
void flashWriteData(uint32_t* addr, uint32_t *ptr, uint16_t len);

#define FLASH_PAGESIZE    1024         // ページサイズ
#define FLASH_PAGENUM     256          // 総ページ数
#define FLASH_TOPADR      0x00000000   // フレッシュメモリ先頭アドレス
#define FLASH_SAVESIZE    4096         // 保存データサイズ(ttbasicを想定)
#define FLASH_SAVEPAGENUM 4            // 
#define FLASH_SAVENUM     1
#define FLASH_SAVEPOP  ((FLASH_TOPADR+FLASH_PAGESIZE*256)-FLASH_SAVESIZE*FLASH_SAVENUM)

uint8_t buf[FLASH_SAVESIZE];
void setup() {
  uint8_t c;
  
  Serial.begin(115200);
  Serial.print("Save top adr=");
  Serial.println(FLASH_SAVEPOP,HEX);

  // テスト用ダミーデータ
  for (uint16_t i=0; i < FLASH_SAVESIZE; i++) {
    buf[i] = i%256;
  }

  Serial.print("Write(y/n)? ");
  while(!Serial.available());
  c = Serial.read();
  Serial.write(c);
  Serial.println();
  if (c == 'y') {
  
    // ページの消去
    Serial.println("ERASE PAGE");
    for (uint8_t i=0; i<FLASH_SAVEPAGENUM; i++) {
       flashPageErase(FLASH_SAVEPOP+FLASH_PAGESIZE*i);
    }
  
    // データの書込み
    Serial.println("Write Data");
    //for (uint8_t i=0; i<FLASH_SAVEPAGENUM; i++) {
      flashWriteData((uint32_t*)FLASH_SAVEPOP, (uint32_t*)buf, FLASH_SAVESIZE/4);
    //}
  }
  
  // データの確認
  Serial.println("Read Data");
  for (uint32_t i=0; i <FLASH_SAVESIZE; i++) {
    if (i%16 == 0) {
      Serial.print(FLASH_SAVEPOP+i,HEX);
      Serial.print(":");
    }
 
    c = *((uint8_t*)FLASH_SAVEPOP+i);
    if (c<0x10){
      Serial.print("0");Serial.print(c,HEX);
    } else {
      Serial.print(c,HEX);
    }
    if (i%16 == 15) 
      Serial.println();
    else
      Serial.print(" ");
   }
}

void loop() {
  // put your main code here, to run repeatedly:

}

実行結果

03

フラッシュメモリの書込みは、ページ単位(1024バイト)で行います。
データの書込みはワード単位(4バイト)で行います。

フラッシュメモリの256kバイト領域のアドレス範囲は、
   0x00000000 ~ 0x0003FFFF
です。

テストプログラムでは、ブートローダやプログラムを破壊しないよう、後半部に4kバイトを書き込んでいます。

このライブラリは、豊四季TinyBASICの移植時に利用する予定です。

« STM32関連 「STM32HAL&SW4入門 Kindle版」を読んでみると.. | トップページ | micro:bitをArduino環境で使う(4)豊四季Tiny BASICを動かしてみる »

arduino」カテゴリの記事

micro:bit」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/571408/66199512

この記事へのトラックバック一覧です: micro:bitをArduino環境で使う (3)内部フラッシュへのデータ書き込み:

« STM32関連 「STM32HAL&SW4入門 Kindle版」を読んでみると.. | トップページ | micro:bitをArduino環境で使う(4)豊四季Tiny BASICを動かしてみる »