• 关于MMC子系统添加CMD56获取金士顿数据写入量方案


    本篇主要介绍在SDM450 Android9平台MMC子系统添加接口来获取金士顿EMMC数据写入量方案。

    1、金士顿数据写入量获取流程
    在这里插入图片描述
    2、数据写入量结果计算方式
    在这里插入图片描述
    从金士顿提供的文档来看,整体流程如下:

    1、首先发生CMD16设置blocklen为512字节

    2、CMD16发送成功后,发送CMD56用于获取数据写入量

    3、CMD56获取到的数据信息:

      bit15~bit12:written data unit size
    
      bit19~bit16:written data sector size
    
    • 1
    • 2
    • 3

    SDM450 Android10平台添加接口代码如下:

    1、kernel/msm-4.9/drivers/mmc/core/mmc_ops.c文件添加获取写入量接口

    #define HEX_STR_STEP             (3)
    #define HEX_STR_SPLIT_DSPACE     (' ')
    #define HEX_STR_SPLIT_SEMICOLON  (':')
    #define HEX_STR_SPLIT_COMMA      (',')
    
    static int starce_hex2str(uint8_t *byte, int byte_len, uint8_t *str, long str_len,uint8_t split_c)
    {
        int i = 0;
        char *pos = (char*)str;
        long tmp_len = 0;
        tmp_len = HEX_STR_STEP*byte_len + 1;
    
        if(str_len < tmp_len){
            pr_err("ERROR: len error %ld,%ld\n",str_len,tmp_len);
            return -1;
        }
    
        for(i = 0; i < byte_len -1; i += 1){
            pos += sprintf(pos, "%02X%c", byte[i],split_c);
        }
    
        pos += sprintf(pos, "%02X", byte[byte_len - 1]);
    
        if(str_len != ((uint8_t *)pos - str + HEX_STR_STEP)){
            pr_err("ERROR: starce_hex2str str_len =%ld, sp len =%ld\n",str_len,((uint8_t *)pos - str + HEX_STR_STEP));
            return -1;
        }
        return 0;
    }
    
    uint8_t * trace_byte_to_str(uint8_t* trace_byte_data,int len)
    {
        int trace_str_len = len*3+2;
        uint8_t *trace_str_data = NULL;
        int ret = 0;
    
        if(NULL == trace_byte_data){
            pr_err("tarce data is NULL\n");
            goto error;
        }
    
        pr_err("malloc trace_str_len=%d\n",trace_str_len);
    
        trace_str_data = (uint8_t *)kmalloc(trace_str_len,GFP_KERNEL);
    
        if(NULL != trace_str_data){
            memset(trace_str_data,0,trace_str_len);
            ret = starce_hex2str(trace_byte_data,len,trace_str_data,trace_str_len,HEX_STR_SPLIT_DSPACE);
            if(0 != ret){
                pr_err("error starce_hex2str fail %d\n",ret);
                goto error;
            }
        }else{
            pr_err("tarce str malloc trace_str_len=%d fail\n",trace_str_len);
            goto error;
        }
        return trace_str_data;
    error:
        return NULL;
    }
    
    int mmc_get_wr_data(struct mmc_card *card, struct mmc_host *host, u32 *unit, u32 *sector)
    {
        struct mmc_request mrq;
        struct mmc_command cmd;
        struct mmc_data data;
        struct scatterlist sg;
        char *data_buf;
        char* buf = NULL;
        int err = 0;
    
        err = mmc_set_blocklen(card, 512);
        pr_err("%s:%d: send CMD16 err = %d\n", __func__, __LINE__, err);
    
        memset(&mrq, 0, sizeof(struct mmc_request));
        memset(&cmd, 0, sizeof(struct mmc_command));
        memset(&data, 0, sizeof(struct mmc_data));
    
        data_buf = kmalloc(512, GFP_KERNEL);
        if (data_buf == NULL)
            return -ENOMEM;
    
        mrq.cmd = &cmd;
        mrq.data = &data;
    
        cmd.opcode = MMC_GEN_CMD;
        cmd.arg = 0x8D;
        cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
        data.blksz = 512;
        data.blocks = 1;
        data.flags = MMC_DATA_READ;
        data.sg = &sg;
        data.sg_len = 1;
    
        sg_init_one(&sg, data_buf, 512);
        mmc_wait_for_req(host, &mrq);
        pr_err("%s:%d: send CMD56 err = %d\n", __func__, __LINE__, cmd.error);
        if (cmd.error) {
            err = cmd.error;
        }
        else {
            buf = (char*)trace_byte_to_str(data_buf,512);
            if(NULL != buf){
                pr_err("data=%s\n",buf);
            }
            pr_err("%02x %02x %02x %02x\n",data_buf[15],data_buf[14],data_buf[13],data_buf[12]);
            pr_err("%02x %02x %02x %02x\n",data_buf[19],data_buf[18],data_buf[17],data_buf[16]);
            *unit = data_buf[15];
            *unit = *unit << 8 | data_buf[14];
            *unit = *unit << 8 | data_buf[13];
            *unit = *unit << 8 | data_buf[12];
            *sector = data_buf[19];
            *sector = *sector << 8 | data_buf[18];
            *sector = *sector << 8 | data_buf[17];
            *sector = *sector << 8 | data_buf[16];
        }
        kfree(data_buf);
    
        return err;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120

    2、 kernel/msm-4.9 / drivers/mmc/core/mmc_ops.h

    int mmc_get_wr_data(struct mmc_card *card, struct mmc_host *host, u32 *unit, u32 *sector);
    
    • 1

    3、 kernel/msm-4.9 / include/linux/mmc/card.h

    struct mmc_card {
    
        ......
    
        u32 unit;
        u32 sector;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4、 kernel/msm-4.9 / drivers/mmc/core/mmc.c

    static ssize_t mmc_wr_data_show(struct device *dev,
                    struct device_attribute *attr,
                    char *buf)
    {
        struct mmc_card *card = mmc_dev_to_card(dev);
    
        return sprintf(buf, "unit=0x%x\nsector=0x%x\n", card->unit, card->sector);
    }
    
    static DEVICE_ATTR(data_size, S_IRUGO, mmc_wr_data_show, NULL);
    
    static struct attribute *mmc_std_attrs[] = {
    
        ......
    
        &dev_attr_data_size.attr,
    
    }
    
    static int mmc_init_card(struct mmc_host *host, u32 ocr,
        struct mmc_card *oldcard)
    {
    
        ......
    
        u32 unit = 0;
        u32 sector = 0;
    
     
    
        err = mmc_get_wr_data(card, host, &unit, &sector);
        if (err == 0) {
            card->unit = unit;
            card->sector = sector;
        }
        pr_err("%s:%d:unit = 0x%x, sector = 0x%x\n", __func__, __LINE__, unit, sector);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    最终在/sys/bus/mmc/devices/mmc0:0001下生成data_size节点,用于查看数据写入量:如下
    在这里插入图片描述
    数据写入量计算结果:

    数据写入量 = (unit*128 + sector)512/1024/1024/1024 = (90313128 + 913) * 512/1024/1024/1024 = 5.5GB

  • 相关阅读:
    回归预测 | MATLAB实现BO-GRU贝叶斯优化门控循环单元多输入单输出回归预测
    记录VSCode C++网络编程 编译失败出现 undefined reference to _imp_socket等等
    重学Spring总结
    量化初探: 对称量化以及非对称量化
    地下城规划3d全景vr虚拟现实制作提高沟通效率
    YOLOv8改进实战 | 更换主干网络Backbone(五)之2023最新轻量化主干网络VanillaNet,深度学习中极简主义的力量
    Revit翻模技巧丨怎么一次性翻转所有墙体?
    计算机毕业设计Java校园疫情防控管理系统(源码+系统+mysql数据库+Lw文档)
    二叉树链式结构-c语言实现
    常见的近似算法
  • 原文地址:https://blog.csdn.net/hanmengaidudu/article/details/126461031