twl_wrapsdk/build/libraries/devices/sdmc/ARM7/sdif.c
Shirait 4fe5688d29 add SD driver and FATFS library (tentative)
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/twl_wrapsdk/trunk@96 4ee2a332-4b2b-5046-8439-1ba90f034370
2007-05-30 10:22:28 +00:00

1189 lines
46 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Project: CTR SD Card driver
File: sd_card.c
2006, Research and Development Department, Nintendo.
*/
#include <twl.h>
#include "sdmc_config.h"
#include "sdif_reg.h" /* IP 対応レジスタ定義 */
#include "sdmc.h"
#include "sdif_ip.h" /* IP 対応フラグ定義 */
#if (SD_DEBUG_PRINT_ON == 1)
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define PRINTDEBUG osTPrintf
#else
#include <ctr/vlink.h>
#define PRINTDEBUG vlink_dos_printf
#endif
#else
#define PRINTDEBUG( ...) ((void)0)
#endif
#define ADD_CHECK 1
/***********************************************************************
グローバル
***********************************************************************/
u16 SD_CID[8]; /* CID保存用 (Card IDentification register) : ID*/
u16 SD_CSD[8]; /* CSD保存用 (Card Specific Data register) : spec*/
u16 SD_OCR[2]; /* OCR保存用 (Operation Condition Register) : voltage and status*/
u16 SD_SCR[4]; /* SCR保存用 (Sd card Configulation Register) : bus-width, card-ver, etc*/
u16 SD_RCA; /* RCA保存用 (Relative Card Address register) : address*/
s16 SDCARD_MMCFlag; /* MMCカードフラグ */
s16 SDCARD_SDHCFlag; /* SDHCカードフラグ(ここではPhysicalLayer2.0の意) */
u16 SD_port_number; /* 現在のポート番号 */
/***********************************************************************
外部参照変数
***********************************************************************/
extern volatile u16 SDCARD_ErrStatus; /* エラーステータス */
extern volatile u32 SDCARD_Status; /* カードステータス */
//extern volatile s16 SDCARD_OutFlag; /* カード排出発生判定フラグ */
//extern void (*func_SDCARD_Out)(void); /* カード排出イベント用コールバック保存用 */
void SD_DisableInfo( void);
/*---------------------------------------------------------------------------*
Name: SD_Init
Description: reset and initialize SD card interface
SDカードIPのリセットと初期設定
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void SD_Init(void)
{
SD_AndFPGA( SOFT_RST,(~(SOFT_RST_SDIF_RST))); /* SD I/F モジュールをリセット */
SD_OrFPGA( SOFT_RST,((SOFT_RST_SDIF_RST))); /* SD I/F モジュールをリセット復帰 */
SD_AndFPGA( SD_STOP,(~SD_STOP_STP)); /* データ転送終了クリア */
}
/*---------------------------------------------------------------------------*
Name: SD_EnableInfo
Description: enable SD card insert and remove interrupts.
SDカードの挿入/抜取 割り込みを許可する
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void SD_EnableInfo( void)
{
if(SD_port_number == SDCARD_PORT0)
{
SD_AndFPGA(SD_INFO1,(~(SD_INFO1_INSERT | SD_INFO1_REMOVE))); /* SD_INFO1レジスタの card inserted removedをクリア */
SD_AndFPGA(SD_INFO1_MASK,(~(SD_INFO1_MASK_INSERT | SD_INFO1_MASK_REMOVE))); /* 挿/抜 割り込み許可 */
}
else if(SD_port_number == SDCARD_PORT1)
{ /* ポート1はCD端子が繋がっていないので実質無効 */
SD_AndFPGA(EXT_CD,(~(EXT_CD_PORT1_INSERT | EXT_CD_PORT1_REMOVE))); /* EXT_CD レジスタの card inserted removedをクリア */
SD_AndFPGA(EXT_CD_MASK,(~(EXT_CD_MASK_PORT1INSERT | EXT_CD_MASK_PORT1REMOVE))); /* 挿抜 割り込み許可 */
}
}
/*---------------------------------------------------------------------------*
Name: SD_DisableInfo
Description: disable SD card insert and remove interrupts.
SDカードの挿入/抜取 割り込みを禁止する
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void SD_DisableInfo( void)
{
if(SD_port_number == SDCARD_PORT0)
{
SD_AndFPGA(SD_INFO1,(~(SD_INFO1_INSERT | SD_INFO1_REMOVE))); /* SD_INFO1レジスタの card inserted removedをクリア */
SD_OrFPGA(SD_INFO1_MASK,(SD_INFO1_MASK_INSERT | SD_INFO1_MASK_REMOVE)); /* 挿/抜 割り込み禁止 */
}
else if(SD_port_number == SDCARD_PORT1)
{ /* ポート1はCD端子が繋がっていないので実質無効 */
SD_AndFPGA(EXT_CD,(~(EXT_CD_PORT1_INSERT | EXT_CD_PORT1_REMOVE))); /* EXT_CD レジスタの card inserted removedをクリア */
SD_OrFPGA(EXT_CD_MASK,(EXT_CD_MASK_PORT1INSERT | EXT_CD_MASK_PORT1REMOVE)); /* 挿抜 割り込み禁止 */
}
}
/*---------------------------------------------------------------------------*
Name: SD_Command
Description: send command that the card will response only.
コマンドを送出する(レスポンスが返ってくるだけのコマンド用)
Arguments: ucCommand : command number
Returns: 0 : success
>0 : error
*---------------------------------------------------------------------------*/
u16 SD_Command(u16 ucCommand)
{
SD_AndFPGA(SD_INFO2,(~SD_INFO2_ERR_ALLCLR)); /* SD Card I/F の 全エラーをクリア */
SD_AndFPGA(SD_INFO1,(~SD_INFO1_RES_END)); /* SD_INFO1レジスタの Response end クリア */
SD_AndFPGA(SD_INFO2_MASK,(~SD_INFO2_MASK_ALLERRMASK)); /* SD Card I/F の 全エラー割込み許可 */
SD_SetFPGA(SD_CMD,(ucCommand)); /* コマンド発行 */
while(!SD_CheckFPGAReg(SD_INFO1,SD_INFO1_RES_END)){ /* Response end 待ち */
if(SDCARD_ErrStatus & SDMC_ERR_FPGA_TIMEOUT){ /* タイムアウトチェック */
break;
}
}
SD_OrFPGA(SD_INFO2_MASK,(SD_INFO2_MASK_ALLERRMASK)); /* SD Card I/F の全エラー割込み禁止 */
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_AppCommand
Description: send apprication command.
アプリケーションコマンド(CMD55)を送出する
Arguments: None
Returns: 0 : success
>0 : error
*---------------------------------------------------------------------------*/
u16 SD_AppCommand(void)
{
PRINTDEBUG( " CMD55 (APP_CMD)\n");
/* argumentをセット */
SD_SetFPGA(SD_ARG0,(0x0000)); /* Argument(15:0) = stuff bits */
SD_SetFPGA(SD_ARG1,(SD_RCA)); /* Argument(31:16) = RCA */
SD_Command(SD_CMD_CMD | APP_CMD); /* CMD55発行、レスポンス(R1)待ち */
#if ADD_CHECK
/*SD_CheckStatusを行うと、直前にCMD8を発行していた場合、SDHC以外はCardStatusの
IllegalCommandエラーフラグが立ってしまうので、ここで引っかかることになる
このフラグがクリアされるのは1コマンドぶん遅れるため
SD Physical Layer 仕様書の Card Status参照*/
// SD_CheckStatus(FALSE); /* コマンドレスポンス(R1) の Card Status チェック */
#endif
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_AppOpCond
Description: get operating condition register data of SD card.
SDカードのACMD41を発行してOCRを取得する
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_AppOpCond(void)
{
SD_ClrErr((u16)(~SDMC_ERR_FPGA_TIMEOUT)); /* タイムアウト以外のエラーをクリア */
while(!SDCARD_ErrStatus){ /* エラーが発生しない間は繰り返し */
/* Argument(31:0) = OCR without busy (0x00100000 = 3.2-3.3V) */
/*ホスト側で電圧を選択できる場合などは、初回にSD_ARG1を0にすることにより
カードが対応している電圧を問い合わせることができる。CTRは電圧3.3V決め打ち
なので問い合わせせず、いきなり3.3V対応をカードに要求する。対応できない
カードは Inactive Mode に移行する。*/
SD_SetFPGA(SD_ARG0,(0x0000));
if( SDCARD_SDHCFlag) {
SD_SetFPGA(SD_ARG1,(0x4010));
}else{
SD_SetFPGA(SD_ARG1,(0x0010));
}
PRINTDEBUG( " ACMD41 (SD_SEND_OP_COND)\n");
SD_Command(SD_CMD_ACMD | SD_APP_OP_COND); /* ACMD41発行、レスポンス(R3)待ち */
if(!SDCARD_ErrStatus){ /* エラーステータスの確認(エラー無し?)*/
SD_GetFPGA(SD_OCR[0],SD_RSP0); /* レスポンス(R3)からOCR取得 */
SD_GetFPGA(SD_OCR[1],SD_RSP1); /* レスポンス(R3)からOCR取得 */
if(SD_RSP1 & RSP_R3_OCR31){ /* OCR(レジスタ)の31bit目チェック(busy?) */
break;
}
}
SD_AppCommand(); /* 決定済みのRCAを設定しCMD55発行 */
}
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SendOpCond
Description: send CMD1 without busy for MMC
MMC の CMD1を発行するSDのACMD41に位置するコマンド
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SendOpCond(void)
{
PRINTDEBUG( " CMD1 (SEND_OP_COND)\n");
SD_ClrErr((u16)(~SDMC_ERR_FPGA_TIMEOUT)); /* タイムアウトエラーをクリア */
while(!SDCARD_ErrStatus){ /* エラーが発生しない間は繰り返し */
SD_SetFPGA(SD_ARG0,(0x0000)); /* Argument(15:0) for MMC (None for SD) */
SD_SetFPGA(SD_ARG1,(0x0010)); /* Argument(31:16) for MMC (None for SD) */
SD_Command(SD_CMD_CMD | SEND_OP_COND); /* CMD1発行、レスポンス(R1)待ち */
if(!SDCARD_ErrStatus){ /* エラーステータスの確認(エラー無し?) */
SD_GetFPGA(SD_OCR[0],SD_RSP0);
SD_GetFPGA(SD_OCR[1],SD_RSP1);
if(SD_RSP1 & RSP_R3_OCR31){ /* OCR(レジスタ)の31bit目チェック(busy?) */
break;
}
}
}
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SendIfCond
Description: send CMD8
CMD8を発行するPhysical Layer 2.00で追加されたコマンド)
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SendIfCond(void)
{
PRINTDEBUG( " CMD8 (SEND_IF_COND)\n");
SD_ClrErr((u16)(~SDMC_ERR_FPGA_TIMEOUT)); /* タイムアウトエラーをクリア */
/* (31:12) Reserved bits, (11:8) supply voltage(VHS), (7:0) check pattern */
SD_SetFPGA(SD_ARG0,(0x01AA)); /* Argument */
SD_SetFPGA(SD_ARG1,(0x0000)); /* Argument */
SD_Command(SD_CMD_CMD | SEND_IF_COND_EXT); /* CMD8発行、レスポンス(R7)待ち */
if(!SDCARD_ErrStatus){ /* エラーステータスの確認(エラー無し?) */
SDCARD_SDHCFlag = TRUE; /* SDHC */
// SD_GetFPGA(SD_R7[0],SD_RSP0);
// SD_GetFPGA(SD_R7[1],SD_RSP1);
}else{
SDCARD_SDHCFlag = FALSE;
}
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SendRelativeAddr
Description: send relative addr
CMD3を発行し、SDカードの場合はレスポンスのRCAを取得する
RCAは他のコマンド発行時にArgumentとして必要
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SendRelativeAddr(void)
{
PRINTDEBUG( " CMD3 (SEND_RELATIVE_ADDR)\n");
if(SDCARD_MMCFlag){ /* MMCカードフラグ ON */
SD_SetFPGA(SD_ARG0,(0x0000)); /* Argument(15:0) */
SD_SetFPGA(SD_ARG1,(0x0001)); /* Argument(31:16) = 0x0001 (松下drvはなぜか0x0100にしていた) */
} /* SDカードのときはArgument(31:0) = stuff bits */
SD_Command(SD_CMD_CMD | SEND_RELATIVE_ADDR); /* CMD3発行、レスポンス(R6)待ち */
if(!SDCARD_ErrStatus){ /* エラーステータスの確認(エラー無し?) */
if(SDCARD_MMCFlag){ /* MMCカードフラグ ON */
SD_RCA = 0x0001; /* RCA <- 1 (松下drvはなぜか0x0100にしていた) */
}else{
SD_GetFPGA(SD_RCA,SD_RSP1); /* レスポンスレジスタからRCAを取得 */
}
}
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SelectCard
Description: toggle card between the stand-by and transfer states.
CMD7を発行してスタンバイモードと転送モードを切り替える
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SelectCard(void)
{
PRINTDEBUG( " CMD7 (SELECT#/DESELECT_CARD)\n");
SD_SetFPGA(SD_ARG0,(0x0000)); /* Argument(15:0) = stuff bits*/
SD_SetFPGA(SD_ARG1,(SD_RCA)); /* Argument(31:16) = RCA */
SD_Command(SD_CMD_CMD | SELECT_CARD); /* CMD7発行、レスポンス(R1b)待ち */
#if ADD_CHECK
SD_CheckStatus(FALSE); /* コマンドレスポンス(R1) の Card Status チェック */
#endif
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SetBlockLength
Description: set of block length.
SDカードのブロックレングスを設定する。
注意multiple read のときに SD_SIZEレジスタに512以外の値を
設定すると正しく動作しない(IP reg spec資料より)。
Arguments: ulBlockLength : bytes of a block ( must be multiplier of 2)
(memo : the default block length is as specified in the CSD.)
1ブロックの長さ2の乗数を指定すること
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SetBlockLength(u32 ulBlockLength)
{
u16 usValue;
PRINTDEBUG( " CMD16 (SET_BLOCKLEN)\n");
/*------- IPの transfer length を設定 -------*/
if(ulBlockLength == 512){
SD_SetFPGA(SD_SIZE,(SD_SIZE_DATA_LENGTH_512B)); /* SDカードデータ転送サイズ 512Bytes 設定 */
}else{
usValue = (u16)ulBlockLength; /* 16bitに変換 */
SD_SetFPGA(SD_SIZE,(usValue)); /* IPにSDカードデータ転送サイズを設定 */
}/*------------------------------------------*/
/*------- カードの設定 -------*/
/* argument(31:0) = block length */
SD_SetFPGA(SD_ARG0,(((LELONG *)&ulBlockLength)->dt2word.low));
SD_SetFPGA(SD_ARG1,(((LELONG *)&ulBlockLength)->dt2word.high));
SD_Command(SD_CMD_CMD | SET_BLOCKLEN); /* CMD16発行、レスポンス(R1)待ち */
#if ADD_CHECK
SD_CheckStatus(FALSE); /* コマンドレスポンス(R1) の Card Status チェック */
#endif
/*----------------------------*/
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SendCID
Description: get card identification data (128bits).
SDカードのCID値を取得する
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SendCID(void)
{
PRINTDEBUG( " CMD2 (ALL_SEND_CID)\n");
/* Argument(31:0) = stuff bits */
SD_Command(SD_CMD_CMD | ALL_SEND_CID); /* CMD2発行、レスポンス(R2)待ち */
if(!SDCARD_ErrStatus){ /* エラーステータスの確認(エラー無し?) */
SD_GetFPGA(SD_CID[0],SD_RSP0);
SD_GetFPGA(SD_CID[1],SD_RSP1);
SD_GetFPGA(SD_CID[2],SD_RSP2);
SD_GetFPGA(SD_CID[3],SD_RSP3);
SD_GetFPGA(SD_CID[4],SD_RSP4);
SD_GetFPGA(SD_CID[5],SD_RSP5);
SD_GetFPGA(SD_CID[6],SD_RSP6);
SD_GetFPGA(SD_CID[7],SD_RSP7);
}
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SendCSD
Description: get card specific data
SDカードのCSD値を取得する
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SendCSD(void)
{
PRINTDEBUG( " CMD9 (SEND_CSD)\n");
SD_SetFPGA(SD_ARG0,(0x0000)); /* Argument(15:0) = stuff bits */
SD_SetFPGA(SD_ARG1,(SD_RCA)); /* Argument(31:16) = RCA */
SD_Command(SD_CMD_CMD | SEND_CSD); /* CMD9発行、レスポンス(R2)待ち */
if(!SDCARD_ErrStatus){ /* エラーステータスの確認(エラー無し?) */
SD_GetFPGA(SD_CSD[0],SD_RSP0);
SD_GetFPGA(SD_CSD[1],SD_RSP1);
SD_GetFPGA(SD_CSD[2],SD_RSP2);
SD_GetFPGA(SD_CSD[3],SD_RSP3);
SD_GetFPGA(SD_CSD[4],SD_RSP4);
SD_GetFPGA(SD_CSD[5],SD_RSP5);
SD_GetFPGA(SD_CSD[6],SD_RSP6);
SD_GetFPGA(SD_CSD[7],SD_RSP7);
}
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SendStatus
Description: send status read command (compatible to the MMC protocol).
マルチメディアカード互換方式でのstatus取得コマンド発行
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SendStatus(void)
{
PRINTDEBUG( " CMD13 (Send STATUS)\n");
SD_SetFPGA(SD_ARG0,(0x0000)); /* Argument(15:0) = stuff bits */
SD_SetFPGA(SD_ARG1,(SD_RCA)); /* Argument(31:16) = RCA */
/* カード排出の重複を防ぐため */
SD_AndFPGA(SD_INFO2,(~SD_INFO2_ERR_ALLCLR)); /* SD Card I/F の 全てのエラーをクリア */
SD_AndFPGA(SD_INFO1,(~SD_INFO1_RES_END)); /* SD_INFO1レジスタの Response end クリア */
SD_AndFPGA(SD_INFO2_MASK,(~SD_INFO2_MASK_ALLERRMASK)); /* SD Card I/F の 全エラー割込み許可 */
SD_SetFPGA(SD_CMD,(SD_CMD_CMD | SD_SEND_STATUS)); /* CMD13発行 */
while(!SD_CheckFPGAReg(SD_INFO1,SD_INFO1_RES_END)){ /* Response end (R1)待ち */
if(SDCARD_ErrStatus & SDMC_ERR_FPGA_TIMEOUT){
break;
}
}
SD_OrFPGA(SD_INFO2_MASK,(SD_INFO2_MASK_ALLERRMASK)); /* SD Card I/F の 全エラー割込み禁止 */
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SendSCR
Description: get condition data.
SDカード内のSCRレジスタ値取得コマンド発行。この後カードは
DATライン経由で1ブロック(8Bytesに設定しておくこと)送信してくる。
MultiBlock R/W と異なり、DATライン経由で転送されてくるSDカードの
レジスタは、MSBから先に送られてくることに注意。
(Physical Layer Specification 2.00 p12-13参照)
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SendSCR(void)
{
PRINTDEBUG( " ACMD51 (Send SCR)\n");
/* Argument(31:0) = stuff bits */
#if ADD_CHECK
SD_TransReadyFPGA(); /* 関連レジスタ初期化 */
SD_AndFPGA(SD_INFO2_MASK,(~SD_INFO2_MASK_BRE)); /* SDカードからのデータ読出し要求割込み許可*/
SD_TransCommand((SD_CMD_ACMD | SEND_SCR)); /* SCR取得コマンド発行、レスポンス(R1)待ち */
#endif
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SDStatus
Description: send status read command (for SD card only).
SDカード専用方式でのstatus取得コマンド発行。この後カードは
DATライン経由で1ブロック(64Bytesに設定しておくこと)送信してくる。
MultiBlock R/W と異なり、DATライン経由で転送されてくるSDカードの
レジスタは、MSBから先に送られてくることに注意。
(Physical Layer Specification 2.00 p12-13参照)
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SDStatus(void)
{
PRINTDEBUG( " ACMD13 (SD_SD STATUS)\n");
/* Argument(31:0) = stuff bits */
SD_TransReadyFPGA(); /* 関連レジスタ初期化 */
SD_AndFPGA(SD_INFO2_MASK,(~SD_INFO2_MASK_BRE)); /* SDカードからのデータ読出し要求割込み許可*/
SD_TransCommand((SD_CMD_ACMD | SD_STATUS)); /* ACMD13 Send the SD_CARD status コマンド発行、レスポンス(R1)待ち */
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_MultiReadBlock
Description: send multiple block read command.
マルチブロックリードコマンド発行。この後カードは
DATライン経由でデータを送信してくる。
Arguments: ulOffset : offset address to read(BYTE).
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_MultiReadBlock(u32 ulOffset)
{
PRINTDEBUG( " CMD18 (READ_MULTIPLE_BLOCK)\n");
SD_TransReadyFPGA(); /* INFOレジスタ初期化 */
if( !SDCARD_UseFifoFlag) { /* FIFOを使わないとき */
SD_AndFPGA(SD_INFO2_MASK,(~SD_INFO2_MASK_BRE)); /* SDカードからのデータ読出し要求割込み許可*/
}
/* 読み込み開始アドレス(オフセット)設定 */
SD_SetFPGA(SD_ARG0,(((LELONG *)&ulOffset)->dt2word.low));
SD_SetFPGA(SD_ARG1,(((LELONG *)&ulOffset)->dt2word.high));
SD_TransCommand((READ_MULTIPLE_BLOCK)); /* CMD18(マルチセクタリードコマンド)発行、レスポンス(R1)待ち */
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_ClockDivSet
Description: set clock speed into the SD card.
(notice : clock into IP is 33.51MHz.)
(memo : default clock is 262KHz.)
SDカードへのクロック速度を設定する。CTRからIMCLK端子でIPに供給
される基本クロックは33.51MHz。
起動直後のデフォルトでは128分周(262KHz)が設定されている。
Arguments: CSD responce include "TRAN_SPEED".
予めCSDをSDカードから読み出しておいた、TRAN_SPEEDが入っている
部分のCSD(CSD[5])。SDカード側で対応可能な周波数を参照するため。
Returns: 0 : success
> 0 : error
*---------------------------------------------------------------------------*/
u16 SD_ClockDivSet(u16 usTranSpeed)
{
u16 usTranTime;
//CTRでは、IMCLKに入力されるクロックは 33.51Mhz
//SD_CLK_CTRL の default値は 0x0020( 128分周 = 262kHz)
/*------*/
usTranTime = (u16)((usTranSpeed >> 11) & 0x000F); /* CSD[103:96] の time value(=4bit) 取得 */
usTranSpeed &= CSD_TRANSFER_RATE; /* CSD[103:96] の transfer rate unit を取得 */
usTranSpeed = (u16)(usTranSpeed >> 8); /* transfer rate unit を下位8ビットに設定する */
/*------*/
switch( usTranSpeed) {
/*--- 100kbit/s(one dat line) = 100KHz, の倍数のとき ---*/
case CSD_TRAN_SPEED_100K:
if(usTranTime > 0x000C){ /* time value が 5.5 より大きい? */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_64)); /* 523KHz */
}
else{
if(usTranTime > 0x0006){ /* time value が 2.5 より大きい? */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_128)); /* 262KHz */
}else{
if( usTranTime == 1) { /* time value が 1.0 ? */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_512)); /* 65KHz */
}else{ /* time value が 1.22.5 のとき */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_256)); /* 131KHz */
}
}
}
break;
/*--- 1Mbit/s(one dat line) = 1MHz, の倍数のとき ---*/
case CSD_TRAN_SPEED_1M:
if(usTranTime == 0x0001){ /* time value が 1.0 ? */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_64)); /* 523KHz */
}
else{
if(usTranTime <= 0x0005){ /* time value が 2.0 以下? */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_32)); /* 1.05MHz */
}
else{
if(usTranTime <= 0x0009){ /* time value が 4.0 以下? */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_16)); /* 2.095MHz */
}else{ /* time value が 4.5 以上のとき */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_8)); /* 4.18MHz */
}
}
}
break;
/*--- 10Mbit/s(one dat line) = 10MHz, の倍数のとき ---*/
case CSD_TRAN_SPEED_10M:
if(usTranTime > 0x0004){ /* time value が 1.5 より大きい? */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_2)); /* 16.76MHz */
}else{ /* time value が 1.5 以下のとき */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_4)); /* 8.38MHz */
}
break;
/*--- 100Mbit/s(one dat line) = 100MHz, の倍数のとき ---*/
case CSD_TRAN_SPEED_100M: /* time value がどんな値であっても */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_2)); /* 16.76MHz */
break;
default:
if( usTranSpeed != 7) { /* reserved値(=7)以外か? */
SD_SetFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_2)); /* 16.76MHz */
} /* (松下drvでは、4以上なら288KHzにしている) */
break; /* transfer rate unit が 7 のときは何もしない */
}
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_EnableClock
Description: enable clock
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void SD_EnableClock( void)
{
SD_OrFPGA(SD_CLK_CTRL,(SD_CLK_CTRL_SDCLKEN));
}
/*---------------------------------------------------------------------------*
Name: SD_DisableClock
Description: disable clock (for power save).
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void SD_DisableClock( void)
{
SD_AndFPGA(SD_CLK_CTRL,(~SD_CLK_CTRL_SDCLKEN));
}
/*---------------------------------------------------------------------------*
Name: SD_SelectBitWidth
Description: set bus width for SD Card ( Not for MMC Card).
(The allowed data bus widths are given in SCR register.)
SDカードのDATラインバス幅を1bitまたは4bitに設定する。
SDカードが4bitに対応していないか、MMCカードの場合はバス幅を4bitに
設定することはできない。SDカードの許容するバス幅は、予め取得済みの
SCRレジスタによって参照している。
Arguments: b4bit : TRUE = 4bit, FALSE = 1bit
Returns: 0 : success
> 0 : error
*---------------------------------------------------------------------------*/
u16 SD_SelectBitWidth(s16 b4bit)
{
/*--- カードの仕様(SCR)を参照 ---*/
#if ADD_CHECK
if( b4bit){ /* SCRレジスタがリード済であること! */
if( !(SD_SCR[0] & SCR_DAT_BUS_WIDTH_4BIT)) { /* カードが4bit幅に対応していないか? */
b4bit = FALSE; /* 対応していない場合は1bit幅を指定しておく */
}
}/*------------------------------*/
#endif
/*--- 4bit(TRUE) 指定のとき ---*/
if(b4bit){
if(!SDCARD_MMCFlag){ /* MMCカードフラグ OFF(ONなら何もしない) */
if(SD_AppCommand()){ /* RCA設定後 CMD55発行 */
return SDCARD_ErrStatus; /* CMD55が正常終了しなかったらエラー終了 */
}
SD_SetFPGA(SD_ARG0,(0x0002)); /* Argument(1:0) = (10) to 4bit,(00) to 1bit */
SD_SetFPGA(SD_ARG1,(0x0000)); /* Argument(31:2) = stuff bits */
PRINTDEBUG( " ACMD6 (SET_BUS_WIDTH:4bit)\n");
SD_Command(SD_CMD_ACMD | SET_BUS_WIDTH); /* ACMD6ビット幅選択コマンド発行、レスポンス(R1)待ち */
#if ADD_CHECK
SD_CheckStatus(FALSE); /* コマンドレスポンス(R1)の Card Status チェック */
#endif
if(!SDCARD_ErrStatus){ /* エラーなし? */
SD_AndFPGA(SD_OPTION,(~SD_OPTION_WIDTH_1BIT)); /* IPにビット幅の設定(4bit幅) */
}
}
}/*--- 1bit(FALSE) 指定のとき ---*/
else{
if(!SDCARD_MMCFlag){ /* MMCカードフラグ OFF(ONなら何もしない) */
if(SD_AppCommand()){ /* RCA設定後 CMD55発行処理 */
return SDCARD_ErrStatus; /* CMD55が正常終了しなかったらエラー終了 */
}
SD_SetFPGA(SD_ARG0,(0x0000)); /* Argument(1:0) = bus width : 1bit */
SD_SetFPGA(SD_ARG1,(0x0000)); /* Argument(31:2) = stuff bits */
PRINTDEBUG( " ACMD6 (SET_BUS_WIDTH:1bit)\n");
SD_Command(SD_CMD_ACMD | SET_BUS_WIDTH); /* ACMD6ビット幅選択コマンド発行、レスポンス(R1)待ち */
#if ADD_CHECK
SD_CheckStatus(FALSE); /* コマンドレスポンス(R1)の Card Status チェック */
#endif
}
if(!SDCARD_ErrStatus){ /* エラーステータスの確認(エラー無し?) */
SD_OrFPGA(SD_OPTION,(SD_OPTION_WIDTH_1BIT)); /* IPにビット幅の設定(1bit幅) */
}
}/*------------------------------*/
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: MMCP_WriteBusWidth
Description: set bus width for SD Card ( Not for MMC Card).
(The allowed data bus widths are given in SCR register.)
MMCplusカードのDATラインバス幅を1bitまたは4bitに設定する。
SDまたはMMCカードの場合はバス幅を4bitに設定することはできない。
Arguments: b4bit : TRUE = 4bit, FALSE = 1bit
Returns: 0 : success
> 0 : error
*---------------------------------------------------------------------------*/
u16 MMCP_WriteBusWidth(s16 b4bit)
{
if( !SDCARD_MMCFlag) {
return 1;
}
/* 書き込み開始オフセット設定 */
if( b4bit) {
SD_SetFPGA(SD_ARG0,(0x0100)); /* Argument(15:8)=(0x1) to 4bit,(0x0) to 1bit */
}else{
SD_SetFPGA(SD_ARG0,(0x0000)); /* Argument(15:8)=(0x1) to 4bit,(0x0) to 1bit */
}
SD_SetFPGA(SD_ARG1,(0x03B7)); /* Argument(25:24)=(0x3)Write, (23:16)=(183)Index */
/* CMD6ビット幅選択コマンド発行、レスポンス(R1)待ち */
SD_Command(SD_CMD_CMD | EXT_CSD_ACCESS);
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: MMCP_BusTest
Description: バスのテストを行う。
この後カードにDATライン経由でデータを送信する必要がある。
Arguments: readflag : リード時TRUE, ライト時FALSE
Returns: 0 : success
> 0 : error
*---------------------------------------------------------------------------*/
u16 MMCP_BusTest( BOOL readflag)
{
/**/
SD_TransReadyFPGA(); /* INFOレジスタ初期化 */
SD_AndFPGA(SD_INFO2_MASK,(~SD_INFO2_MASK_BWE)); /* SDカードからのデータ書込み要求割込み許可 */
/**/
SD_SetFPGA( SD_ARG0, 0);
SD_SetFPGA( SD_ARG1, 0);
if( readflag) {
SD_TransCommand( 14);
}else{
SD_TransCommand( 19);
}
return( SDCARD_ErrStatus);
}
/*---------------------------------------------------------------------------*
Name: SD_FPGA_irq
Description: handler of data transfer request interrupt from card,
check and clear interrupt register of IP.
カードからの転送要求BREまたはBWE割り込み発生時に
どちらかを調べて返し、INFO2の当該割り込み要求フラグをクリアする。
Arguments: None
Returns: TRUE : BRE割り込み発生
FALSE : BWE割り込み発生
*---------------------------------------------------------------------------*/
s16 SD_FPGA_irq(void)
{
/*--- FIFOを使うとき ---*/
if( SDCARD_UseFifoFlag) {
if( SD_CheckFPGAReg( *SDIF_CNT_L, (u16)SDIF_CNT_FFIE)) { /* FULL割り込み許可のとき */
return TRUE;
}else{
if(!SD_CheckFPGAReg(SD_INFO2_MASK,SD_INFO2_MASK_BWE)){ /* SDカードからのデータ書込み要求あり */
SD_AndFPGA(SD_INFO2,(~SD_INFO2_BWE)); /* SD用バッファ制御 Write Enable リセット*/
}
return FALSE;
}
}else{ /*--- FIFOを使わないとき ---*/
if(!SD_CheckFPGAReg(SD_INFO2_MASK,SD_INFO2_MASK_BRE)){ /* SDカードからのデータ読出し要求あり */
SD_AndFPGA(SD_INFO2,(~SD_INFO2_BRE)); /* SD用バッファ制御 Read Enable リセット*/
return TRUE;
}
if(!SD_CheckFPGAReg(SD_INFO2_MASK,SD_INFO2_MASK_BWE)){ /* SDカードからのデータ書込み要求あり */
SD_AndFPGA(SD_INFO2,(~SD_INFO2_BWE)); /* SD用バッファ制御 Write Enable リセット*/
return FALSE;
}
}
return FALSE;
}
/*---------------------------------------------------------------------------*
Name: SD_StopTransmission
Description: manual send CMD12 to terminate translate.
手動でCMD12を発行し、転送終了をFPGAに通知する
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void SD_StopTransmission(void)
{
SD_OrFPGA(SD_STOP,(SD_STOP_STP)); /* データ転送終了設定 */
}
/*---------------------------------------------------------------------------*
Name: SD_TransEndFPGA
Description: clear the transfer interrupt.
カード転送終了時に転送関連の割り込みを禁止に戻しておく
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void SD_TransEndFPGA(void)
{
SD_OrFPGA(SD_INFO2_MASK,(SD_INFO2_MASK_ALLERRMASK)); /* SD Card I/F の 全エラー割込み禁止 */
SD_OrFPGA(SD_INFO1_MASK,(SD_INFO1_MASK_ALL_END)); /* R/W アクセス終了割込み禁止 */
if(!SD_CheckFPGAReg(SD_INFO2_MASK,SD_INFO2_MASK_BRE)){ /* SDカードからのデータ読込み要求割込み許可か? */
SD_OrFPGA(SD_INFO2_MASK,(SD_INFO2_MASK_BRE)); /* SDカードからのデータ読込み要求割込み禁止 */
}
if(!SD_CheckFPGAReg(SD_INFO2_MASK,SD_INFO2_MASK_BWE)){ /* SDカードからのデータ書込み要求割込み許可か? */
SD_OrFPGA(SD_INFO2_MASK,(SD_INFO2_MASK_BWE)); /* SDカードからのデータ書込み要求割込み禁止 */
}
}
/*---------------------------------------------------------------------------*
Name: SD_CheckStatus
Description: check the card status in the R1.
R1レスポンスのカードステータスをチェックする
Arguments: bRead : 読み込み処理時 = TRUE
Returns: 0 : success
>0 : error
*---------------------------------------------------------------------------*/
u16 SD_CheckStatus(BOOL bRead)
{
/* コマンドレスポンス(R1)の[39:8] から Card status を取得 */
SD_GetFPGA((((LELONG *)&SDCARD_Status)->dt2word.low),SD_RSP0);
SD_GetFPGA((((LELONG *)&SDCARD_Status)->dt2word.high),SD_RSP1);
/*--- 松下サンプルドライバでやっている処理 ---*/
if(bRead){ /* リード時か? */
if(!(SDCARD_ErrStatus & SDMC_ERR_TIMEOUT)){ /* タイムアウト発生していないか? */
SDCARD_Status &= ~SDCARD_STATUS_OUT_OF_RANGE; /* OUT_OF_RANGEフラグを落とす */
}
}/*-------------------------------------------*/
PRINTDEBUG( " SD_CheckStatus ======== 0x%x\n", SDCARD_Status);
if(SDCARD_Status & RSP_R1_STATUS_ERR){ /* コマンドレスポンス(R1)のカードステータスがエラーか確認 */
SD_SetErr(SDMC_ERR_R1_STATUS); /* コマンドレスポンス(R1)のカードステータス エラー */
}
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_SwapByte
Description: swap bytes in a 16bit data.
16bitデータの上位と下位を入れ換える
Arguments: data : 16bit data
Returns: swapped data
*---------------------------------------------------------------------------*/
u16 SD_SwapByte(u16 *data)
{
u16 usDATA;
usDATA = *data;
usDATA = (u16)(((usDATA & 0x00FF) << 8) | ((usDATA & 0xFF00) >> 8));
return usDATA;
}
/*---------------------------------------------------------------------------*
Name: SD_EnableSeccnt
Description: enable SD_SECCNT register.
SD_SECCNT を有効化して値をセットする。
Arguments: ulSDCARD_SectorCount : セクタカウント値1セクタ=512byte
Returns: None
*---------------------------------------------------------------------------*/
void SD_EnableSeccnt( u32 ulSDCARD_SectorCount)
{
u16 usSector;
usSector = (u16)ulSDCARD_SectorCount;
SD_OrFPGA(SD_STOP,SD_STOP_SEC_ENABLE); /* SD_SECCNTレジスタを有効にする */
SD_SetFPGA(SD_SECCNT,usSector); /* SD_SECCNTレジスタに転送セクタカウントを設定 */
}
/*---------------------------------------------------------------------------*
Name: SD_DisableSeccnt現在は未使用関数
Description: disable SD_SECCNT register.
SD_SECCNT を無効化する。
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void SD_DisableSeccnt( void)
{
u16 i;
/*--- 松下ドライバでやっていること ---*/
for ( i=0; i<50000; i++) /* カウント値50000では足りないことあり */
{ /* SD_INFO1レジスタの R/W access all end 待ち */
if(SD_CheckFPGAReg(SD_INFO1,SD_INFO1_ALL_END)) {
break;
}
}/*-----------------------------------*/
SD_AndFPGA(SD_STOP,(~SD_STOP_SEC_ENABLE)); /* SD_SECCNTレジスタを無効にする */
}
/*---------------------------------------------------------------------------*
Name: SD_SetErr
Description: set error flag
指定のエラーフラグをセットする
Arguments: Error : error flag to set
Returns: None
*---------------------------------------------------------------------------*/
void SD_SetErr(u16 Error)
{
OSIntrMode irq_core_flag;
#if (TARGET_OS_CTR == 1)
irq_core_flag = osDisableInterrupts(); /* 割込み禁止 */
SDCARD_ErrStatus |= Error; /* エラーステータスを設定 */
osRestoreInterrupts( irq_core_flag); /* 割り込み設定を元に戻す */
#else
irq_core_flag = OS_DisableInterrupts();
SDCARD_ErrStatus |= Error; /* エラーステータスを設定 */
OS_RestoreInterrupts( irq_core_flag);
#endif
}
/*---------------------------------------------------------------------------*
Name: SD_ClrErr
Description: clear error flag
指定のエラーフラグをクリアする
Arguments: Error : error flag to clear
Returns: None
*---------------------------------------------------------------------------*/
void SD_ClrErr(u16 Error)
{
OSIntrMode irq_core_flag;
#if (TARGET_OS_CTR == 1)
irq_core_flag = osDisableInterrupts(); /* 割込み禁止 */
SDCARD_ErrStatus &= ~(Error); /* エラーステータスをクリア */
osRestoreInterrupts( irq_core_flag); /* 割り込み設定を元に戻す */
#else
irq_core_flag = OS_DisableInterrupts(); /* 割込み禁止 */
SDCARD_ErrStatus &= ~(Error); /* エラーステータスをクリア */
OS_RestoreInterrupts( irq_core_flag); /* 割り込み設定を元に戻す */
#endif
}
/*---------------------------------------------------------------------------*
Name: SD_TransReadyFPGA
Description: setup for the command that the card will response and request data transfer.
DATラインでのデータ転送が発生するコマンド発行前の転送準備
BRE, BWE割り込みの許可は別途行うこと
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void SD_TransReadyFPGA(void)
{
/* 関連レジスタ初期化 */
SD_AndFPGA(SD_INFO2,(~SD_INFO2_ERR_ALLCLR)); /* SD Card I/F の 全てのエラーをクリア */
SD_AndFPGA(SD_INFO1,(~(SD_INFO1_RES_END | SD_INFO1_ALL_END))); /* SD_INFO1レジスタの Response end と access all end クリア */
SD_AndFPGA(SD_INFO2,(~SD_INFO2_BRE)); /* SD用バッファ制御 Read Enable クリア*/
SD_AndFPGA(SD_INFO2,(~SD_INFO2_BWE)); /* SD用バッファ制御 Write Enable クリア*/
SD_AndFPGA(SD_STOP,(~SD_STOP_STP)); /* データ転送終了クリア */
/* 割り込み関連許可 */
SD_AndFPGA(SD_INFO2_MASK,(~SD_INFO2_MASK_ALLERRMASK)); /* SD Card I/F の 全エラー割込み許可 */
SD_AndFPGA(SD_INFO1_MASK,(~SD_INFO1_MASK_ALL_END)); /* R/W access all end 割込み許可(Responseはポーリングで見るため許可しない) */
}
/*---------------------------------------------------------------------------*
Name: SD_TransCommand
Description: send command that the card will response and request data transfer.
コマンドを送出するDATラインでのデータ転送が発生するコマンド用
Arguments: ucCommand : command number
Returns: 0 : success
>0 : error
*---------------------------------------------------------------------------*/
u16 SD_TransCommand(u16 ucCommand)
{
SD_SetFPGA(SD_CMD,(ucCommand)); /* コマンド発行 */
while(!SD_CheckFPGAReg(SD_INFO1,SD_INFO1_RES_END)){ /* Response end 待ち */
if(SDCARD_ErrStatus & SDMC_ERR_FPGA_TIMEOUT){
break;
}
}
SD_CheckStatus(FALSE); /* R1レスポンスのcard statusチェック*/
if(SDCARD_ErrStatus & SDMC_ERR_R1_STATUS){
SD_StopTransmission(); /* カード転送終了をFPGAに通知 */
}
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_CheckFPGAReg
Description: check register bits.
レジスタの状態をチェックする
Arguments: reg : 16bit register data
value : mask data
Returns: TRUE : some of mask data bits are 1 on the register.
FALSE : no mask data bits is 1 on the register.
*---------------------------------------------------------------------------*/
BOOL SD_CheckFPGAReg(u16 reg,u16 value)
{
if( reg & value) {
return TRUE;
}else{
return FALSE;
}
}
/*---------------------------------------------------------------------------*
Name: SD_SendNumWRSectors
Description: send "number of well written blocks" command (for SD card only).
SDカード専用方式でのライト済みセクタ数取得コマンド発行。この後カードは
DATライン経由で1ブロック(4Bytesに設定しておくこと)送信してくる。
MultiBlock R/W と異なり、DATライン経由で転送されてくるSDカードの
レジスタは、MSBから先に送られてくることに注意。
(Physical Layer Specification 2.00 p12-13参照)
Arguments: None
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_SendNumWRSectors(void)
{
PRINTDEBUG( " ACMD22 (SEND_NUM_WR_SECTORS)\n");
/* Argument(31:0) = stuff bits */
SD_TransReadyFPGA(); /* 関連レジスタ初期化 */
SD_AndFPGA(SD_INFO2_MASK,(~SD_INFO2_MASK_BRE)); /* SDカードからのデータ読込み要求割込み許可 */
SD_TransCommand((SD_CMD_ACMD | SEND_NUM_WR_SECTORS)); /* ACMD22書きこみ完了セクタ数取得コマンド発行、レスポンス(R1)待ち */
return SDCARD_ErrStatus;
}
/*---------------------------------------------------------------------------*
Name: SD_MultiWriteBlock
Description: send multiple block write command.
マルチブロックライトコマンド発行。この後カードに
DATライン経由でデータを送信する必要がある。
Arguments: ulOffset : offset address to write(BYTE).
Returns: 0 : success
> 0 : error code
*---------------------------------------------------------------------------*/
u16 SD_MultiWriteBlock(u32 ulOffset)
{
PRINTDEBUG( " CMD25 (WRITE_MULTIPLE_BLOCK)\n");
SD_TransReadyFPGA(); /* INFOレジスタ初期化 */
// if( !SDCARD_UseFifoFlag) { /* FIFOを使わないとき */
SD_AndFPGA(SD_INFO2_MASK,(~SD_INFO2_MASK_BWE)); /* SDカードからのデータ書込み要求割込み許可 */
// }
/* 書き込み開始オフセット設定 */
SD_SetFPGA(SD_ARG0,(((LELONG *)&ulOffset)->dt2word.low));
SD_SetFPGA(SD_ARG1,(((LELONG *)&ulOffset)->dt2word.high));
SD_TransCommand(WRITE_MULTIPLE_BLOCK); /* CMD25マルチセクタライトコマンド発行 */
return SDCARD_ErrStatus;
}