LPC2388のSD/MMCカードインターフェース続き。
そこそこコードも整理しました。このLPC2388のSD/MMCカードインターフェース はR/Wをはじめると、絶対にコントローラのタイミングでFIFOに書き込むか読み 込むかしないといけない。72MHzで動かしていてもこれはとてもきついタイミン グです。
SD/MMCカード自体はクロックをいくら止めてもいいので、FIFOが待ちになったら クロックを止めてくれればよかったのに。
Cで呑気に書いたくらいだと18KHzくらいが安牌。DMA使ってアセンブラでガチガ チに組まないと普通には使えない感じです。これはこの後のロガーの実装で問 題になるかもしれない。データの入力は落としてでも書きこむスケジューリングに しないと。
前日でCMD1がうまくいかないのは仕様だった。MMCカードではなく、SD/MMCカー ドの場合、CS#をアサートしてCMD1を発行すればSPIモードになるけれど、アサー トしていない場合は蹴られるのだ。SDカードとしてACMD41を発行してくれとい うことなのだ。
もうちょっと詰めたいのだけど、BS走行会までに、これをCR85に積みたいので ちょっとおざなりのまま先に。ハード的な問題も実験したいし。間にあうのか 微妙....。最悪ノイズをサンプリングテストまででも。
そこそこコードも整理しました。このLPC2388のSD/MMCカードインターフェース はR/Wをはじめると、絶対にコントローラのタイミングでFIFOに書き込むか読み 込むかしないといけない。72MHzで動かしていてもこれはとてもきついタイミン グです。
SD/MMCカード自体はクロックをいくら止めてもいいので、FIFOが待ちになったら クロックを止めてくれればよかったのに。
Cで呑気に書いたくらいだと18KHzくらいが安牌。DMA使ってアセンブラでガチガ チに組まないと普通には使えない感じです。これはこの後のロガーの実装で問 題になるかもしれない。データの入力は落としてでも書きこむスケジューリングに しないと。
前日でCMD1がうまくいかないのは仕様だった。MMCカードではなく、SD/MMCカー ドの場合、CS#をアサートしてCMD1を発行すればSPIモードになるけれど、アサー トしていない場合は蹴られるのだ。SDカードとしてACMD41を発行してくれとい うことなのだ。
もうちょっと詰めたいのだけど、BS走行会までに、これをCR85に積みたいので ちょっとおざなりのまま先に。ハード的な問題も実験したいし。間にあうのか 微妙....。最悪ノイズをサンプリングテストまででも。
bool
mci_mmc_init ()
{
int i;
mci_power (FALSE);
mci_power (TRUE);
mmc_debug = 0;
まずCMD0を送ってIdle状態にします。
// [CMD0] Reset
mci_cpsm_command (NULL, &cpsm_command[MMC_CMD0]);
この状態でCS#はHi-Z(本当はプルアップするべきみたい)。MMCカードならこのCMD1に
レスポンスを返すはず。
// [CMD1] MMC card response this. SD card don't response.
if (mci_cpsm_command (NULL, &cpsm_command[MMC_CMD1]))
{
card_info.type = CARD_MMC;
return FALSE; // not supported.
}
SD, SDHCカードなので反応しない。初期化をやり直すためにCMD0をもう一回発行します。
// [CMD0] Reset again for SD, SDHC card.
mci_cpsm_command (NULL, &cpsm_command[MMC_CMD0]);
SDHCカードを確認します。CMD8に反応すればSDHC
// [CMD8] Check SD card or SDHC card.
if (mci_cpsm_command (NULL, &cpsm_command[MMC_CMD8]))
{
printf ("SDHC card\n");
card_info.type = CARD_SDHC;
}
else
{
printf ("SD card\n");
card_info.type = CARD_SD;
}
ここでSD,SDHCカードを初期化。
// [CMD41] Initialize SD, SDHC card.
cpsm_command[MMC_ACMD41].arg =
card_info.type == CARD_SDHC ? 0x40ff8000: 0x00ff8000;
for (i = 0; i < 100; i++)
{
if (mci_cpsm_command (NULL, &cpsm_command[MMC_CMD55]) &&
mci_cpsm_command (NULL, &cpsm_command[MMC_ACMD41]))
break;
}
if (i == 100)
{
printf ("ACMD41 failed.\n");
return FALSE;
}
// mmc_debug = 1;
// Check OCR
card_info.block_address = FALSE;
if (card_info.type == CARD_SDHC)
{
if (response[3] & 0x40000000)
{
SDHCカードの場合、ディスクアドレスではなく、セクタ番号を指定する場合が
あるので、それをチェック。(4GBまでならディスクアドレスでした)
printf ("SDHC block addresssing.\n");
card_info.block_address = TRUE;
}
}
// [CMD2] Get CID.
if (!mci_cpsm_command (NULL, &cpsm_command[MMC_CMD2]))
return FALSE;
CMD7,9,10,13に必要なRCAを取得します。
// [CMD3] Get RCA.
if (!mci_cpsm_command (NULL, &cpsm_command[MMC_CMD3]))
return FALSE;
card_info.rca = response[0];
printf ("RCA=%x\n", card_info.rca);
// [CMD9] Get CSD
if (!mci_cpsm_command (&card_info, &cpsm_command[MMC_CMD9]))
return FALSE;
フルスピードにするとFIFOの読み込みが間にあわないので400KHz以下のまま。
// Full speed clock.
// *MCI_CLOCK |= CLOCK_BYPASS;
// [CMD10] Get CID again. (paranoia)
if (!mci_cpsm_command (&card_info, &cpsm_command[MMC_CMD10]))
return FALSE;
// [CMD7] Set RCA to r/w This command must be last.
if (!mci_cpsm_command (&card_info, &cpsm_command[MMC_CMD7]))
return FALSE;
return TRUE;
}
