090701

|



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に積みたいので ちょっとおざなりのまま先に。ハード的な問題も実験したいし。間にあうのか 微妙....。最悪ノイズをサンプリングテストまででも。
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;
}