MMC on P2020 QorIQ

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 
1,501件の閲覧回数
notshure
Contributor IV

Hello everybody,
I am looking for reference C codes (reading and writing from memory) to use MMC with the p2020.

0 件の賞賛
返信
1 解決策
1,428件の閲覧回数
yipingwang
NXP TechSupport
NXP TechSupport

Please refer to the following SendCommand function provided in NetCommSw.

static e_EsdhcCmdStatus SendCommand(t_Esdhc* p_Esdhc, uint32_t command, uint32_t argument, bool transferCmd)
{
uint32_t xfertypeReg = 0, tmp, prsstat;
e_EsdhcCmdStatus cmdStatus;
uint32_t timeout;

xfertypeReg |= ((command << XFERTYPE_CMDINX_SHIFT) & XFERTYPE_CMDINX_MASK);

timeout = p_Esdhc->timeout + XX_CurrentTime();
do
{
prsstat = GET_UINT32(p_Esdhc->p_MemMap->prsstat) & PRSSTAT_CIHB_MASK;
} while((XX_CurrentTime() < timeout) && (prsstat));

if (prsstat)
return e_ESDHC_CANNOT_ISSUE_CMD;

/* Check if card can issue command using DAT lines */
if ((glbCmdArgArray[command].dataPresent) && (command != e_ESDHC_CMD_STOP_TRANS) && (command != e_ESDHC_CMD_IO_RW_DIRECT))
{
if ((GET_UINT32(p_Esdhc->p_MemMap->prsstat) & PRSSTAT_CDIHB_MASK))
return e_ESDHC_CANNOT_ISSUE_CMD;

while ((GET_UINT32(p_Esdhc->p_MemMap->prsstat) & PRSSTAT_DLSL31_MASK) != PRSSTAT_DLSL31_MASK){}
}

/* Switch command*/
if (e_ESDHC_CMD_SWITCH == command)
{
glbCmdArgArray[command] = (e_SDHC_MMC_CARD == p_Esdhc->cardDetails.cardType) ?
SwitchCmdArgs[ESDHC_MMC_INDEX] : SwitchCmdArgs[ESDHC_SD_INDEX];
}

xfertypeReg |= (glbCmdArgArray[command].dataPresent << XFERTYPE_DPSEL_SHIFT);
xfertypeReg |= (glbCmdArgArray[command].read << XFERTYPE_DTDSEL_SHIFT);

if (transferCmd)
{
if (e_SDHC_TRANS_MODE_INTERNAL_DMA == p_Esdhc->transferParam.dmaMode)
xfertypeReg |= XFERTYPE_DMAEN_MASK; /* enable internal DMA */

if (1 < p_Esdhc->transferParam.blkNum)
{
xfertypeReg |= XFERTYPE_MSBSEL_MASK;
xfertypeReg |= XFERTYPE_BCEN_MASK;
xfertypeReg |= XFERTYPE_AC12EN_MASK;
}
}

switch (glbCmdArgArray[command].cmdType) {
case e_ESDHC_NORMAL_CMD:
case e_ESDHC_SUSPEND_CMD:
case e_ESDHC_RESUME_CMD:
case e_ESDHC_ABORT_CMD:
xfertypeReg |= (glbCmdArgArray[command].cmdType << XFERTYPE_CMDTYPE_SHIFT);
break;
default:
return e_ESDHC_CMD_INVALID_PARAMS;
break;
}

switch (glbCmdArgArray[command].respType) {
case e_ESDHC_NO_RESP:
xfertypeReg |= (glbCmdArgArray[command].respType << XFERTYPE_RSPTYPE_SHIFT);
break;
case e_ESDHC_R2_RESP:
xfertypeReg |= (glbCmdArgArray[command].respType << XFERTYPE_RSPTYPE_SHIFT);
xfertypeReg |= XFERTYPE_CCCEN_MASK;
break;
case e_ESDHC_R3_RESP:
xfertypeReg |= (e_ESDHC_R1_RESP << XFERTYPE_RSPTYPE_SHIFT);
break;
case e_ESDHC_R1_RESP:
case e_ESDHC_R1b_RESP:
xfertypeReg |= (glbCmdArgArray[command].respType << XFERTYPE_RSPTYPE_SHIFT);
xfertypeReg |= XFERTYPE_CCCEN_MASK;
xfertypeReg |= XFERTYPE_CICEN_MASK;
break;
default:
return e_ESDHC_CMD_INVALID_PARAMS;
break;
}

WRITE_UINT32(p_Esdhc->p_MemMap->cmdarg, argument);
tmp = GET_UINT32(p_Esdhc->p_MemMap->cmdarg);

/* Send the command to the card*/
WRITE_UINT32(p_Esdhc->p_MemMap->xfertyp, xfertypeReg);

cmdStatus = WaitCmdDone(p_Esdhc);

return cmdStatus;
}

元の投稿で解決策を見る

0 件の賞賛
返信
5 返答(返信)
1,472件の閲覧回数
yipingwang
NXP TechSupport
NXP TechSupport

Please refer to drivers/mmc/card/mmc_test.c in Linux Kernel.

0 件の賞賛
返信
1,458件の閲覧回数
notshure
Contributor IV

i tried to view drivers / mmc / card / mmc_test.c, but it's too generic.
I'm trying to follow the flows found in the p2020 datasheet

for example this one which implements the function to send a command:

send_command(cmd_index, cmd_arg, other requirements)
{
WORD wCmd; // 32-bit integer to make up the data to write into the XFERTYP register, it is
// recommended to implement in a bit-field manner
wCmd = (<cmd_index> & 0x3f) << 24; // set the first 8 bits as '00'+<cmd_index>
set CMDTYP, DPSEL, CICEN, CCCEN, RSTTYP, and DTDSEL according to the command index;
// XFERTYP register bits
if (internal DMA is used) wCmd |= 0x1;
if (multi-block transfer) {
set XFERTYP[MSBSEL] bit;
if (finite block number) {
set XFERTYP[BCEN] bit;
if (auto12 command is to use) set XFERTYP[AC12EN] bit;
}
}
write_reg(CMDARG, <cmd_arg>); // configure the command argument
write_reg(XFERTYP, wCmd); // set XFERTYP register as wCmd value to issue the command
}
wait_for_response(cmd_index)
{
while (IRQSTAT[CC] is not set); // wait until command complete bit is set
read IRQSTAT register and check if any error bits about command are set;
if (any error bits are set) report error;
write 1 to clear IRQSTAT[CC] and all command error bits;
}

0 件の賞賛
返信
1,451件の閲覧回数
yipingwang
NXP TechSupport
NXP TechSupport

Please refer to the following driver source code in Linux Kernel.

drivers/mmc/host/sdhci.c

drivers/mmc/host/sdhci-pltfm.c

drivers/mmc/host/sdhci-of-esdhc.c

0 件の賞賛
返信
1,445件の閲覧回数
notshure
Contributor IV

Following the example of pseudocode on the datasheet of p2020 I have implemented the function that allows me to send commands.

void send_command(int cmd_index)
{
int count;
unsigned int wCmd;
unsigned int temp0,temp1;

// cmd_index
wCmd = (cmd_index & 0x3F) << 24;

// -No response
// -Data present
// -Enable. The eSDHC checks the index field in the response to see if it has the same value as the command index. If it is not, it is reported as a command index error.
// -Enable. The eSDHC checks the CRC field in the response if it contains the CRC field. If an error is detected, it is reported as a command CRC error.
// -No response
// -Write (host to card)
(*MMC_REG.XFERTYP)= CMDTYP | DPSEL | CICEN | CCCEN | RSPTYP | DTDSEL;

// Command Argument
(*MMC_REG.CMDARG) = 0x00000000;

// set XFERTYP register as wCmd value to issue the command
(*MMC_REG.XFERTYP)= wCmd;

// wait_for_response
while(1)
{
temp0=(*MMC_REG.IRQSTAT) & 0x00000001;
temp1 = (*MMC_REG.CMDRSP0);
printf("%x\n",temp1);
printf("%x\n",(*MMC_REG.CMDRSP1));
printf("%x\n",(*MMC_REG.CMDRSP2));
printf("%x\n",(*MMC_REG.CMDRSP2));
if ( temp0 == 0x00000001) break;
}
// write 1 to clear IRQSTAT[CC] and all command error bits;
(*MMC_REG.IRQSTAT) = 0x00000001;

}

 

set CMDTYP, DPSEL, CICEN, CCCEN, RSTTYP, and DTDSEL according to the command index;
XFERTYP register bits

i can't understand these two steps.
How does a status register be able to send the command

write_reg(XFERTYP, wCmd); // set XFERTYP register as wCmd value to issue the command

for now the send command function has been implemented only to send the Zero command, just to verify correct operation

0 件の賞賛
返信
1,429件の閲覧回数
yipingwang
NXP TechSupport
NXP TechSupport

Please refer to the following SendCommand function provided in NetCommSw.

static e_EsdhcCmdStatus SendCommand(t_Esdhc* p_Esdhc, uint32_t command, uint32_t argument, bool transferCmd)
{
uint32_t xfertypeReg = 0, tmp, prsstat;
e_EsdhcCmdStatus cmdStatus;
uint32_t timeout;

xfertypeReg |= ((command << XFERTYPE_CMDINX_SHIFT) & XFERTYPE_CMDINX_MASK);

timeout = p_Esdhc->timeout + XX_CurrentTime();
do
{
prsstat = GET_UINT32(p_Esdhc->p_MemMap->prsstat) & PRSSTAT_CIHB_MASK;
} while((XX_CurrentTime() < timeout) && (prsstat));

if (prsstat)
return e_ESDHC_CANNOT_ISSUE_CMD;

/* Check if card can issue command using DAT lines */
if ((glbCmdArgArray[command].dataPresent) && (command != e_ESDHC_CMD_STOP_TRANS) && (command != e_ESDHC_CMD_IO_RW_DIRECT))
{
if ((GET_UINT32(p_Esdhc->p_MemMap->prsstat) & PRSSTAT_CDIHB_MASK))
return e_ESDHC_CANNOT_ISSUE_CMD;

while ((GET_UINT32(p_Esdhc->p_MemMap->prsstat) & PRSSTAT_DLSL31_MASK) != PRSSTAT_DLSL31_MASK){}
}

/* Switch command*/
if (e_ESDHC_CMD_SWITCH == command)
{
glbCmdArgArray[command] = (e_SDHC_MMC_CARD == p_Esdhc->cardDetails.cardType) ?
SwitchCmdArgs[ESDHC_MMC_INDEX] : SwitchCmdArgs[ESDHC_SD_INDEX];
}

xfertypeReg |= (glbCmdArgArray[command].dataPresent << XFERTYPE_DPSEL_SHIFT);
xfertypeReg |= (glbCmdArgArray[command].read << XFERTYPE_DTDSEL_SHIFT);

if (transferCmd)
{
if (e_SDHC_TRANS_MODE_INTERNAL_DMA == p_Esdhc->transferParam.dmaMode)
xfertypeReg |= XFERTYPE_DMAEN_MASK; /* enable internal DMA */

if (1 < p_Esdhc->transferParam.blkNum)
{
xfertypeReg |= XFERTYPE_MSBSEL_MASK;
xfertypeReg |= XFERTYPE_BCEN_MASK;
xfertypeReg |= XFERTYPE_AC12EN_MASK;
}
}

switch (glbCmdArgArray[command].cmdType) {
case e_ESDHC_NORMAL_CMD:
case e_ESDHC_SUSPEND_CMD:
case e_ESDHC_RESUME_CMD:
case e_ESDHC_ABORT_CMD:
xfertypeReg |= (glbCmdArgArray[command].cmdType << XFERTYPE_CMDTYPE_SHIFT);
break;
default:
return e_ESDHC_CMD_INVALID_PARAMS;
break;
}

switch (glbCmdArgArray[command].respType) {
case e_ESDHC_NO_RESP:
xfertypeReg |= (glbCmdArgArray[command].respType << XFERTYPE_RSPTYPE_SHIFT);
break;
case e_ESDHC_R2_RESP:
xfertypeReg |= (glbCmdArgArray[command].respType << XFERTYPE_RSPTYPE_SHIFT);
xfertypeReg |= XFERTYPE_CCCEN_MASK;
break;
case e_ESDHC_R3_RESP:
xfertypeReg |= (e_ESDHC_R1_RESP << XFERTYPE_RSPTYPE_SHIFT);
break;
case e_ESDHC_R1_RESP:
case e_ESDHC_R1b_RESP:
xfertypeReg |= (glbCmdArgArray[command].respType << XFERTYPE_RSPTYPE_SHIFT);
xfertypeReg |= XFERTYPE_CCCEN_MASK;
xfertypeReg |= XFERTYPE_CICEN_MASK;
break;
default:
return e_ESDHC_CMD_INVALID_PARAMS;
break;
}

WRITE_UINT32(p_Esdhc->p_MemMap->cmdarg, argument);
tmp = GET_UINT32(p_Esdhc->p_MemMap->cmdarg);

/* Send the command to the card*/
WRITE_UINT32(p_Esdhc->p_MemMap->xfertyp, xfertypeReg);

cmdStatus = WaitCmdDone(p_Esdhc);

return cmdStatus;
}

0 件の賞賛
返信