{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"オリジナルの作成:2015/02/15"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Arduino SDカードライブラリ\n",
"SDカードシールドを作ってから、LBEDにはまだSDカードライブラリがないことに気づきました。\n",
"\n",
"通常なら、LBEDは完全を目指す物では無いのでまぁいいや的になるのですが、 lbeDuinoではシールドを作成したガジェットを外に持ち運ぶことが想定されます。\n",
"\n",
"このような状況で記録手段がないことは大きな問題と考え、思い腰を持ち上げてArduinoのSDライブラリの 移植に取り掛かりました。\n",
"\n",
"この記事のみどころ?は、どうやって移植したかでは無く、どうやって動くようにしたかです。\n",
"\n",
"### Arduino SDカードのマシン依存部\n",
"移植の元にしたのは、Arduinoアプリケーション配下の(MacOSX版で説明します)Contents/Resources/Java/libraries/SDです。\n",
"\n",
"このソースはとても良くできていて、SDカードのSPIの処理に関連する部分は、utility/Sd2Card.cpp, SdCard.hに凝縮されています。\n",
"\n",
"lbedへの移植は、Sd2Cardクラスのメンバ変数にSPIクラスの_spi変数とDigitalOutクラスのchipSelect_を追加し、初期化とspiSend, spiRec関数をlbedのSPI用に書き替えるだけです。 *1\n",
"\n",
"Sd2Card.hの変更点\n",
"\n",
"```C++\n",
"//#include \"Sd2PinMap.h\"\n",
"#include \"SdInfo.h\"\n",
"#include \"lbed.h\" // LBEDのヘッダをインクルード\n",
"\n",
"\n",
"// コンストラクタの変更\n",
" Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0),\n",
" spi_(MOSI, MISO, SCKL), chipSelect_(D4){}\n",
"\n",
"\n",
"// spiSend, spiRecの変更\n",
" void spiSend(uint8_t b) { spi_.write((int)b); };\n",
" uint8_t spiRec(void) { return spi_.write((int)0xFF); };\n",
"\n",
"// private:宣言の追加\n",
" SPI spi_;\n",
" DigitalOut chipSelect_;\n",
"```\n",
"\n",
"ここでは、SDカードシールドに合わせchipSelectをD4に固定としています。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 失敗談\n",
"最初は、SPIのSCKLのピンをD10に割り当てており、SDカードの初期化に失敗していました。\n",
"\n",
"ここでもLabToolのプロトコルアナライザーが役に立ちました。\n",
"\n",
"\n",
"\n",
"LabToolとlbeDuinoとの接続は、以下の通りです。\n",
"\n",
" | LabToolピン\t | ケーブルの色\t | 機能\t | lbeDuino | \n",
" |---|---|---|---|\n",
" | DIO_3\t | Orange\t | SPI-SSEL\t | D4 | \n",
" | DIO_4\t | Yellow\t | SPI-MOSI\t | D11 | \n",
" | DIO_5\t | Green\t | SPI-MISO\t | D12 | \n",
" | DIO_6\t | Blue\t | SPI_SCK\t | D13 | \n",
"\n",
"### 初期化は規定どおり\n",
"SDカードの処理手順は、ChaNさんの \n",
"[MMC/SDCの使いかた](http://elm-chan.org/docs/mmc/mmc.html)\n",
"を参考にさせて頂きました。\n",
"\n",
"初期化のchipSelectがHightでSCKLを74クロック以上入れるとある部分では、80回のクロックを入れた後初期化コマンドを送っています。\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## MBRの読込失敗\n",
"初期化でSDカードの情報のタイプはきちんと読み込んでいるのですが、SDカードのMBRを読み込んだ後にエラーとなってしまいます。\n",
"\n",
"ここでもLabToolが役立ちました。以下の画面では、0x0が続いて読み込まれており、デバッガでもその値が正しく読み取れました。\n",
"\n",
"\n",
"\n",
"このような状態ではSPIの読込が原因では無いことが明らかです。\n",
"\n",
"そこで、FAT関連の構造体をよく見てみると原因が隠れていました。\n",
"\n",
"FatStructs.hを見てみると、fat32BootSectorの構造体が以下の様に定義されています。\n",
"\n",
"```C++\n",
"struct fat32BootSector {\n",
" /** X86 jmp to boot program */\n",
" uint8_t jmpToBootCode[3];\n",
" /** informational only - don't depend on it */\n",
" char oemName[8];\n",
" /** BIOS Parameter Block */\n",
" bpb_t bpb;\n",
" /** for int0x13 use value 0X80 for hard drive */\n",
" uint8_t driveNumber;\n",
" /** used by Windows NT - should be zero for FAT */\n",
" uint8_t reserved1;\n",
" /** 0X29 if next three fields are valid */\n",
" uint8_t bootSignature;\n",
" /** usually generated by combining date and time */\n",
" uint32_t volumeSerialNumber;\n",
" /** should match volume label in root dir */\n",
" char volumeLabel[11];\n",
" /** informational only - don't depend on it */\n",
" char fileSystemType[8];\n",
" /** X86 boot code */\n",
" uint8_t bootCode[420];\n",
" /** must be 0X55 */\n",
" uint8_t bootSectorSig0;\n",
" /** must be 0XAA */\n",
" uint8_t bootSectorSig1;\n",
"}__attribute__ ((packed));\n",
"```\n",
"\n",
"volumeSerialNumberの後に、char型でvolumeLabel[11], fileSystemType[8]と定義されています。 32bitマイコンのLPC1114では、構造体のアライメントが32bit単位となるので、volumeLabelとfileSystemTypeは連続した領域に割り当てられません。そこで、FatStructs.h内の構造体の終わりに\n",
"```\n",
"__attribute__ ((packed))\n",
"```\n",
"を付けてやりました。 これで何とかSDライブラリが動くようになりました。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 動作確認\n",
"Arduino勉強会/0G-lbeDuinoシールドを作るの結果を再度掲載します。\n",
"\n",
""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.13"
}
},
"nbformat": 4,
"nbformat_minor": 0
}