東芝から発売されているFlashAirを用いた開発を行う人々向けのまとめwikiです。※本wikiは東芝及びフィックスターズ、キオクシアとは何の関係もありません。お問合わせは管理者へお願いします。

転載: https://sites.google.com/site/gpsnmeajp/electricme...

FlashAirの共有メモリをマイコンから扱う

共有メモリをマイコンから扱うコードは、ページ下部にあります。
Arduino用のコードですが、移植しやすいように心がけたつもりなので、他のマイコンでも使えると思います。
これをArduinoのライブラリとしてまとめたのはこちらのページに有ります。

公式のサンプルと異なり、SPI通信用のライブラリ以外に依存していません。

共有メモリとは

そもそも、共有メモリとは何なのか、説明しておきます。
一応、FlashAir-Developersにも解説があるのですが、念のため。

共有メモリは、FlashAirのiSDIO空間にある512Byteの領域で、アドレスで言うと01000h-01FFFhの先頭512Byte、
規格上はReserved for Vendorとされている場所に割り当てられた領域です。
iSDIOのコマンドCMD48, CMD49で読み出し、書き込みができます。

共有メモリというからには、どこかと共有しているわけです。
1つは、外部のマイコンですが、他は何でしょう?

W-02では、HTTPサーバーと共有していました。
command.cgiのリファレンスページに、記載があります。
これにより、マイコンと、ブラウザ上のjavascriptで、Ajaxを用いた通信が出来ました。

W-03では、さらにLuaスクリプトが動くようになり、スクリプト上にて、fa.sharedmemory関数によってアクセスできるようになりました。
これによって、HTTPサーバーとLuaスクリプト間の連携や、Luaスクリプト同士の処理の引き継ぎ、
Luaスクリプトと外部マイコンの通信など、様々な用途に使えるようになりました。

マイコンからも、HTTPサーバーからも、Luaスクリプトからも、1Byte単位で扱うことが出来ます。



Luaスクリプトから外部マイコンと通信する手段はいくつかあります。
1. fa.pioを使った、ソフトパラレル通信。ソフトSPI、ソフトI2C等、ピン操作による通信
 →Luaインタプリタの速度もあり、低速。また通信中は他の処理ができない。
2. fa.spiを使ったSPI通信
 →1Byte辺りの速度は高速だが、親がFlashAir側であり、また通信中は他の処理ができない。
3. ファイルの受け渡し
 →通信はSDカードコントローラがやるので、両者好きなタイミングでやりとりできる。かなり大規模なデータのやり取りも可能。しかし、あまり頻繁だとフラッシュの寿命が縮む。
4. iSDIOの共有メモリを用いた通信
 →マイコン側が親であり、通信はSDカードコントローラがやるので2.5ms程度で512Byteの送信ができる。メモリ上なのでフラッシュの心配もない。


また、共有メモリのメリットはもう一つあり、それはメモリの少ないマイコンでも扱えるということです。
通常のSDカード同様のFATファイルシステムに書き込むためには、最低でもFATを扱うために512Byte、さらにファイルの領域分のメモリが必要となりますが、
共有メモリは、単なるバイト列ですので、SDカードにアクセスするための引数の計算に使う8〜10Byte程度があれば書き込み・読み出しができます。

また、iSDIOのアクセスは512Byte単位ですが、アクセス時には長さの指定ができ、そのため、必要なバイト数の操作を終えたら、あとは読み飛ばし・書き飛ばしをすれば済みます。
ただ、その読み飛ばし・書き飛ばしにも相応の時間がかかるため、512Byte一気に扱えない場合は、アクセス回数分の時間がかかります。
(1回に付き概ね2.5ms@4MHzです。SPIのクロックにもよります。)

特に、1Byte単位でアクセスした場合は、ひどく時間的に無駄となります。
なので、SharedMemWriteSimple, SharedMemReadSimpleというのはかなり無駄な処理なのですが、
それでも1Byte単位で扱いたい場合というのがありそうな気がしたので、用意しておきました。

※command.cgiは、共有メモリのバイナリは読み出せても、バイナリを書き込むことは出来なかった気がします。(URIの制限で)
 ので、512Byteをビット単位でフル活用は出来ないと思うので、ご注意ください。Luaスクリプトの方は問題なかった気がします。

コードの説明

やっていることは、本当にただのSDコマンドの発行です。
SharedMemInitでは、74クロックの起動クロック、CMD0の発行(リセット)、CMD8(問い合わせ&設定)、ACMD41(SDHCの初期化)をしています。
CMD8が必要だったり、ACMD41にSDHC/XC用のビットを立てる必要があったりと、色々ハマりポイントが有って苦労しましたが。
今回のコードは、FlashAir専用(といっても共有メモリを実装しているのはFlashAirしかない)なので、種々の判定や場合分けは無視してハードコーディングしています。

SharedMemWriteはCMD49, SharedMemReadはCMD48の発行をしています。
本来は、ReadExt, WriteExtなどと分けて実装するようなのですが、無視して、共有メモリ専用にしています。
それによって、大分シンプルに作ることが出来ました。

というのも、私がこれを使いたいのはArduinoではなく、いわゆるRAMが少なすぎてSDカードの扱えないPIC16Fシリーズや12Fシリーズなどで
使うことを考えていたので、汎用性を上げるより、ROMを節約したかったのです。

コード

繰り返しになりますが、このコードは、Arduino用のライブラリとして別ページにて配布しています。
参考のために、ページ上にも掲載しています。
/*
BSD 3-Clause License

Copyright (c) 2016, GPS_NMEA
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/


#include <SPI.h>

int cs = 4;
uint8_t spi_trans(uint8_t x)
{
	return SPI.transfer(x);
}

void cs_release()
{
	//release
	digitalWrite(cs,HIGH);
	spi_trans(0xFF);
}

int8_t sd_cmd(uint8_t cmd,uint32_t arg)
{
	uint8_t val;

	spi_trans(0xFF);//END of MODE

	digitalWrite(cs,LOW);
	spi_trans(0x40 | cmd);
	spi_trans(arg>>24);
	spi_trans(arg>>16);
	spi_trans(arg>>8);
	spi_trans(arg);
	
	if(cmd == 0x00)
		spi_trans(0x95);
	else if(cmd == 0x08)
		spi_trans(0x87);
	else
		spi_trans(0x01); //CRC+STOP

	do{
		val = spi_trans(0xFF);//R1 Rcv
	}while(val == 0xFF);
	
	return val;
}

int8_t SharedMemInit(int _cs)
{
	cs = _cs;
	uint8_t val;
	
	SPI.begin();
	pinMode(cs, OUTPUT);//CS output
	SPI.setClockDivider(SPI_CLOCK_DIV4);
	SPI.setDataMode(SPI_MODE0);
	SPI.setBitOrder(MSBFIRST);
	
	//power-on clock
	digitalWrite(cs,LOW);
	for(int8_t i=0;i<10;i++)
		spi_trans(0xFF);

	cs_release();
	if(sd_cmd(0,0x00000000) != 1){
		return -1;
	}

	cs_release();
	if(sd_cmd(8,0x000001AA) != 1){
		return -2;
	}
	//R7 Responce
	spi_trans(0xFF); //0
	spi_trans(0xFF); //0
	spi_trans(0xFF); //0
	if(spi_trans(0xFF) != 0xAA) //AA
	{
		return -3;
	}
	
	//--ACMD41--
	do{
		cs_release();
		val = sd_cmd(55,0x00000000);
		val = sd_cmd(41,0x40000000); //HCS=1
	}while(val != 0);
	
	cs_release();
	return 0;
}
int8_t SharedMemWrite(uint16_t adr, uint16_t len, uint8_t buf[])
{
	if(adr + len > 512)
		return -1;
	if(len == 0)
		return -1;
		
	uint32_t sd_adr = 0x1000 + adr;
	uint32_t arg = 0x90000000 | ((sd_adr & 0x1FFFF) << 9) | ((len - 1) & 0x1FF);
	
	if(sd_cmd(49,arg) != 0)
	{
		return -2;
	}
	
	spi_trans(0xFE); //BLOCK START
	
	for (int16_t i = 0; i < 512; i++) {
		if(i < len){
			spi_trans(buf[i]);
		}else{
			spi_trans(0xFF);
		}
	}

	//CRC
	spi_trans(0xFF);
	spi_trans(0xFF);
	
	//Ans
	if((spi_trans(0xFF) & 0x1F) != 0x05) //DATA ACCEPTED
	{
		return -3;
	}
	
	//Wait for Busy
	while(spi_trans(0xFF) == 0x00);

	cs_release();
	return 0;
}

int8_t SharedMemRead(uint16_t adr, uint16_t len, uint8_t buf[])
{
	if(adr + len > 512)
		return -1;
	if(len == 0)
		return -1;
		
	uint32_t sd_adr = 0x1000 + adr;
	uint32_t arg = 0x90000000 | ((sd_adr & 0x1FFFF) << 9) | ((len - 1) & 0x1FF);

	if(sd_cmd(48,arg) != 0)
	{
		return -2;
	}

	while((spi_trans(0xFF)) != 0xFE);
 
	for (int16_t i = 0; i < 514; i++) {
		if(i < len){
			buf[i] = spi_trans(0xFF);
		}else{
			spi_trans(0xFF);
		}
	}
	cs_release();
	return 0;
}

int8_t SharedMemWriteSimple(uint16_t adr, uint8_t data)
{
	uint8_t buf[1] = {data}; 
	return SharedMemWrite(adr,1,buf);
}
int16_t SharedMemReadSimple(uint16_t adr)
{
	uint8_t buf[1] = {0};
	int16_t stat = SharedMemRead(adr,1,buf);
	if(stat < 0)
		return stat;
	
	return buf[0];
}
void setup()
{
	delay(1000);
	Serial.begin(9600);

	if(SharedMemInit(4)){
		Serial.println("Init err");
		return;
	}else{
		Serial.println("Init OK");
	}

	Serial.print("Read 1Byte[0x000]:");
	Serial.write(SharedMemReadSimple(0x000));
	Serial.println();

	Serial.print("Read 1Byte[0x001]:");
	Serial.write(SharedMemReadSimple(0x001));
	Serial.println();
	
	uint8_t buf[512];

	long time3 = micros();
	if(SharedMemRead(0,512,buf)){
		Serial.println("\nread err");
		return;
	}
	long time4 = micros() - time3;
	Serial.print("\nTime:");
	Serial.print(time4);
	Serial.println("[us]");
	Serial.println("Data Red.");
	Serial.print(">");
	for(int i=0;i<512;i++)
		Serial.write(buf[i]);
	


	uint8_t buf2[512] = {'T','E','S','T'};

	long time = micros();
	if(SharedMemWrite(0,512,buf2)){
		Serial.println("\nwrite err");
		return;
	}
	long time2 = micros() - time;
	Serial.print("\nTime:");
	Serial.print(time2);
	Serial.println("[us]");
	Serial.println("Data Wrote.");
	Serial.print(">");
	
	for(int i=0;i<512;i++)
		Serial.write(buf2[i]);

	Serial.println();
	Serial.print("Write 1Byte[0x005] Status:");
	Serial.print(SharedMemWriteSimple(0x005,'A'));
	Serial.println();

	Serial.print("Read 1Byte[0x006] Status:");
	Serial.print(SharedMemWriteSimple(0x006,'B'));
	Serial.println();
	


	Serial.print("\nDone!\n");
}

void loop(void) {
}

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

スマートフォンの方は画面下部よりPC版に切り替えることをおすすめします

アクセス解析中

忍者アナライズ

GoogleAnalytics

編集にはIDが必要です