查看: 18549|回复: 6

[其他] 关于SDIO中的CMD53命令读取数据

[复制链接]

该用户从未签到

4

主题

22

帖子

0

注册会员

Rank: 2

积分
180
最后登录
2019-12-27
发表于 2016-11-8 17:12:55 | 显示全部楼层 |阅读模式
本帖最后由 andyxu 于 2016-11-9 21:32 编辑

芯片型号:MK60DN512ZVLQ10

我想利用CMD53先实现单块字节流的读取,但是不知道数据在哪儿读?
我调用自己写的函数:
_io_rw_extended(0, 0, 0, 1, &data[0], 1, 6);

函数定义如下(函数有点啰嗦,因为在调试阶段)int _io_rw_extended(int write, unsigned fn,
                unsigned addr, int incr_addr, uint8_t *buf, unsigned blocks, unsigned blksz)
{
        SDHC_Cmd_t cmd;
        uint32_t *pBuffer = (uint32_t*)buf;
        
        printf("1. SDHC_PRSSTAT = %x IRQSTAT = %x\r\n", SDHC->PRSSTAT, SDHC->IRQSTAT);                                          打印结果:1. SDHC_PRSSTAT = ff8800f8 IRQSTAT = 80
        cmd.cmd           = ESDHC_CMD53;   /* xfertype */
        cmd.arg           = write ? 0x80000000 : 0x00000000;
        cmd.arg          |= fn << 28;
        cmd.arg          |= incr_addr ? 0x04000000 : 0x00000000;         /* OP code */
        cmd.arg          |= addr << 9;
        /* Block mode && Byte/Block count */
        if (blocks == 1 && blksz < 256)
                cmd.arg |= blksz;        /* multi-byte mode */
        else
                cmd.arg |= 0x08000000 | blocks;                /* multi-block mode */
        cmd.blkSize   = blksz;
        cmd.blkCount  = blocks;
        
        uint32_t xfertyp;
        uint32_t blkattr;
        xfertyp = cmd.cmd;

        /* resume cmd must set DPSEL */
        if (ESDHC_XFERTYP_CMDTYP_RESUME == ((xfertyp & SDHC_XFERTYP_CMDTYP_MASK) >> SDHC_XFERTYP_CMDTYP_SHIFT))
        {
                xfertyp |= SDHC_XFERTYP_DPSEL_MASK;
        }

        if ((0 != cmd.blkCount) && (0 != cmd.blkSize))
        {
                xfertyp |= SDHC_XFERTYP_DPSEL_MASK;
                /* multi-block transfer */
                if (cmd.blkCount != 1)
                {
                        //多块传输
                        xfertyp |= SDHC_XFERTYP_MSBSEL_MASK;
                }
               
                /* if 0xffffffff, then infinite transfer */
                if ((uint32_t)-1 == cmd.blkCount)
                {
                        //大量传输
                        blkattr = SDHC_BLKATTR_BLKSIZE(cmd.blkSize) | SDHC_BLKATTR_BLKCNT(0xFFFF);
                }
                else
                {
                        blkattr = SDHC_BLKATTR_BLKSIZE(cmd.blkSize) | SDHC_BLKATTR_BLKCNT(cmd.blkCount);
                        xfertyp |= SDHC_XFERTYP_BCEN_MASK; /* enable the Block Count register */
                }
        }
        else
        {
                        blkattr = 0;
        }
        /* Read or Write */
        if(write)
                xfertyp &= ~SDHC_XFERTYP_DTDSEL_MASK;
        else
                xfertyp |= SDHC_XFERTYP_DTDSEL_MASK;

        /* 卡移除状态清除,每次传输完成都会有该中断标记 */
        SDHC->IRQSTAT |= SDHC_IRQSTAT_CRM_MASK;
        
        /* set water level ,0x10 by default*/
//        SDHC->WML = SDHC_WML_RDWML(1);
        SDHC->IRQSTATEN |= SDHC_IRQSTATEN_BRRSEN_MASK;
        SDHC->IRQSIGEN |= SDHC_IRQSIGEN_BRRIEN_MASK;
        /* 等待CMD\DAT线空闲 */
        SDHC_WaitCommandLineIdle();

    printf("2. SDHC_PRSSTAT = %x IRQSTAT = %x xfertyp = %x\r\n", SDHC->PRSSTAT, SDHC->IRQSTAT, xfertyp);                           打印结果:2. SDHC_PRSSTAT = ff8800f8 IRQSTAT = 0 xfertyp = 353a0012
        printf("2. CMDARG = %x\r\n", cmd.arg);
                          打印结果:2. CMDARG = 4000006
    /* issue cmd */
    SDHC->CMDARG = cmd.arg;
    SDHC->BLKATTR = blkattr;
        SDHC->DSADDR = 0;
    SDHC->XFERTYP = xfertyp;

    /* 判断命令是否传输完成 SDHC_IRQSTAT_CC_MASK标志位 CMD Complete */
    if(SD_StatusWait (SDHC_IRQSTAT_CIE_MASK | SDHC_IRQSTAT_CEBE_MASK | SDHC_IRQSTAT_CCE_MASK | SDHC_IRQSTAT_CC_MASK) != SDHC_IRQSTAT_CC_MASK)
    {
        SDHC->IRQSTAT |= SDHC_IRQSTAT_CTOE_MASK | SDHC_IRQSTAT_CIE_MASK | SDHC_IRQSTAT_CEBE_MASK | SDHC_IRQSTAT_CCE_MASK | SDHC_IRQSTAT_CC_MASK;
        return ESDHC_ERROR_cmd_FAILED;
    }
    printf("3. SDHC_PRSSTAT = %x IRQSTAT = %x\r\n", SDHC->PRSSTAT, SDHC->IRQSTAT); /* Command complete */
                    打印结果:3. SDHC_PRSSTAT = ff88020e IRQSTAT = 81
         
    /* get respond data */
    if ((xfertyp & SDHC_XFERTYP_RSPTYP_MASK) != SDHC_XFERTYP_RSPTYP(ESDHC_XFERTYP_RSPTYP_NO))
    {
        cmd.resp[0] = SDHC->CMDRSP[0];
        if ((xfertyp & SDHC_XFERTYP_RSPTYP_MASK) == SDHC_XFERTYP_RSPTYP(ESDHC_XFERTYP_RSPTYP_136))
                {
                        cmd.resp[1] = SDHC->CMDRSP[1];
                        cmd.resp[2] = SDHC->CMDRSP[2];
                        cmd.resp[3] = SDHC->CMDRSP[3];
                }
    }
        printf("4. SDHC_PRSSTAT = %x IRQSTAT = %x resp[0] = 0x%x\r\n", SDHC->PRSSTAT, SDHC->IRQSTAT, cmd.resp[0]);
                       打印结果:4. SDHC_PRSSTAT = ff88020e IRQSTAT = 81 resp[0] = 0x1000,从SDHC_PRSSTAT 的结果来看,Read Transfer Active是激活了,0e也是表示各个clock也是active的,感觉就差一步读数据了。
        /* receive data */
        uint32_t i, j;
    for(i = 0; i < blocks; i++)
    {
        for (j = (blksz + 3) >> 2;j != 0;j--)
        {
            *pBuffer++ = SDHC->DATPORT;
        }
    }
        
        return 0;
}
下面是打印的结果:
2.png
下面这个是协议上的多块读写的说明。
1.png





我知道答案 目前已有6人回答
回复

使用道具 举报

该用户从未签到

717

主题

6376

帖子

0

超级版主

Rank: 8Rank: 8

积分
25292
最后登录
2025-8-25
发表于 2016-11-9 15:51:47 | 显示全部楼层
SDHC的代码在KSDK 2.0都是有的,但是有一点需要指出来,
我们的例程给出的CMD17 才是 Read Single Block功能的
  1. /*! @brief SD/MMC card common commands */
  2. typedef enum _sdmmc_command
  3. {
  4.     kSDMMC_GoIdleState = 0U,         /*!< Go Idle State */
  5.     kSDMMC_AllSendCid = 2U,          /*!< All Send CID */
  6.     kSDMMC_SetDsr = 4U,              /*!< Set DSR */
  7.     kSDMMC_SelectCard = 7U,          /*!< Select Card */
  8.     kSDMMC_SendCsd = 9U,             /*!< Send CSD */
  9.     kSDMMC_SendCid = 10U,            /*!< Send CID */
  10.     kSDMMC_StopTransmission = 12U,   /*!< Stop Transmission */
  11.     kSDMMC_SendStatus = 13U,         /*!< Send Status */
  12.     kSDMMC_GoInactiveState = 15U,    /*!< Go Inactive State */
  13.     kSDMMC_SetBlockLength = 16U,     /*!< Set Block Length */
  14.     kSDMMC_ReadSingleBlock = 17U,    /*!< Read Single Block */
  15.     kSDMMC_ReadMultipleBlock = 18U,  /*!< Read Multiple Block */
  16.     kSDMMC_SendTuningBlock = 19U,    /*!< Send Tuning Block */
  17.     kSDMMC_SetBlockCount = 23U,      /*!< Set Block Count */
  18.     kSDMMC_WriteSingleBlock = 24U,   /*!< Write Single Block */
  19.     kSDMMC_WriteMultipleBlock = 25U, /*!< Write Multiple Block */
  20.     kSDMMC_ProgramCsd = 27U,         /*!< Program CSD */
  21.     kSDMMC_SetWriteProtect = 28U,    /*!< Set Write Protect */
  22.     kSDMMC_ClearWriteProtect = 29U,  /*!< Clear Write Protect */
  23.     kSDMMC_SendWriteProtect = 30U,   /*!< Send Write Protect */
  24.     kSDMMC_Erase = 38U,              /*!< Erase */
  25.     kSDMMC_LockUnlock = 42U,         /*!< Lock Unlock */
  26.     kSDMMC_ApplicationCommand = 55U, /*!< Send Application Command */
  27.     kSDMMC_GeneralCommand = 56U,     /*!< General Purpose Command */
  28.     kSDMMC_ReadOcr = 58U,            /*!< Read OCR */
  29. } sdmmc_command_t;
复制代码
回复 支持 反对

使用道具 举报

  • TA的每日心情
    开心
    2018-6-6 08:45
  • 签到天数: 328 天

    连续签到: 1 天

    [LV.8]以坛为家I

    10

    主题

    1047

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    2006
    最后登录
    2019-5-1
    发表于 2016-11-9 16:11:39 | 显示全部楼层
    帮顶,帮顶
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    该用户从未签到

    4

    主题

    22

    帖子

    0

    注册会员

    Rank: 2

    积分
    180
    最后登录
    2019-12-27
     楼主| 发表于 2016-11-9 21:07:55 | 显示全部楼层
    小恩GG 发表于 2016-11-9 15:51
    SDHC的代码在KSDK 2.0都是有的,但是有一点需要指出来,
    我们的例程给出的CMD17 才是 Read Single Block功 ...

    1.png
    CMD17应该是对于Memory存取的,而并非是对于sdio的接口卡。还没有研究CMD17,不知道对于解决问题有没有参考价值。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    717

    主题

    6376

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    25292
    最后登录
    2025-8-25
    发表于 2016-11-10 09:36:05 | 显示全部楼层
    andyxu 发表于 2016-11-9 21:07
    CMD17应该是对于Memory存取的,而并非是对于sdio的接口卡。还没有研究CMD17,不知道对于解决问题有没有 ...

    CMD53指令是用于通过一个单命令访问一个多I/O寄存器。允许写或读大量I/O寄存器,不管是什么卡,读数据不就是读取卡的memory上的数据,不知自己是否解释清楚了
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    4

    主题

    22

    帖子

    0

    注册会员

    Rank: 2

    积分
    180
    最后登录
    2019-12-27
     楼主| 发表于 2016-11-18 21:22:13 | 显示全部楼层
    本帖最后由 andyxu 于 2016-11-18 22:53 编辑
    小恩GG 发表于 2016-11-10 09:36
    CMD53指令是用于通过一个单命令访问一个多I/O寄存器。允许写或读大量I/O寄存器,不管是什么卡,读数据不就 ...

    我研究了你们NXP的SDK2.0的代码,并且原封不动地用SDK2.0代码实现了SD Memory卡的块读写,但是当我用到CMD53命令上的时候,始终是发送了命令过去之后,host这边始终收不到Transfer complete的中断,最终一段时间之后IRQSTAT = 100000(指的是超时中断到来)而结束了传输操作。
    1.png 2.png
    MK60DN512ZVLQ10的手册上提及了读取操作的流程,跟SDK2.0代码中的例程是一致的。
    下面是参照SDK2.0中发送命令编写的CMD53的函数,已实现CMD5、CMD3、CMD52等:
    status_t host_sdio_cmd53_rw(sd_card_t *card, int write, unsigned fn,
                    unsigned addr, int incr_addr, uint32_t *buf, unsigned blocks, unsigned blksz)
    {
            assert(card);

        sdhc_transfer_t content = {0};
        sdhc_command_t command = {0};
            sdhc_data_t data = {0};
            
        command.index = kSDMMC_IoRwExtended;
        command.argument         = write ? 0x80000000 : 0x00000000;
            command.argument   |= fn << 28;
            command.argument   |= incr_addr ? 0x04000000 : 0x00000000;         /* OP code */
            command.argument   |= addr << 9;
            if(blocks == 1U)
                    command.argument   |= blksz;
            else
                    command.argument   |= 0x08000000 | blocks;
        command.responseType = kSDHC_ResponseTypeR5;

            data.blockSize = blksz;
        data.blockCount = blocks;
            data.rxData = buf;
            
        content.command = &command;
        content.data = &data;
        if (kStatus_Success != card->host.transfer(card->host.base, &content))
        {
            LIB_TRACE("cmd53 error\r\n");
                    return kStatus_SDMMC_TransferFailed;
        }
            LIB_TRACE("CMD53 resp0 = %x\r\n", command.response[0U]);

            return kStatus_Success;
    }


    CMD53这个命令困扰了我20来天了,希望小恩GG帮我指导下。谢谢。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2022-11-9 15:32
  • 签到天数: 188 天

    连续签到: 1 天

    [LV.7]常住居民III

    3

    主题

    288

    帖子

    4

    高级会员

    Rank: 4

    积分
    820
    最后登录
    2023-8-23
    发表于 2016-11-25 09:46:38 | 显示全部楼层
    我最近也在搞SD卡,一起努力
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-8-26 03:24 , Processed in 0.094816 second(s), 28 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表