init_timer(&timer1);
timer1.function = test_time;
timer1.data = ;
timer1.expires = jiffies + msecs_to_jiffies();
add_timer(&timer1);
sd_test(mmc);
printk("count = %d \n",count);

sd_test()函数写在probe函数中,但要等待sd初始化完毕才行,需要在上电时就插入SD卡,而不要等待系统起来之后。另外,如果mmc_rescan函数使用的工作队列实现的,那么它与probe就属于两个线程,会造成在执行sd_test时,sd卡还没初始化好,所以测试时不要用工作队列,直接调用就可以了。

void test_time(void)
{
count++;
mod_timer(&timer1,jiffies+msecs_to_jiffies(1));
}

计数方式,没1/HZ时间计数一次,HZ跟系统相关,我的是250HZ,精确度是0.004S,msecs_to_jiffies(x),x是指tick数,间断时间由tick数*精确度。系统的计数器是超时计数,使用mod_timer函数重启计数,并赋值新的值。

void sd_test(struct mmc_host *mmc)
{
struct sepmmc_host *host = mmc_priv(mmc);
reset_hardware(host);
disable_any_int(host);
clear_any_pending_int(host); sepmmc_start_command(host);
init_completion(&host->cmd_complete_request);
enable_command_done_int(host);
wait_for_completion(&host->cmd_complete_request);
printk("command transfer over\n"); init_completion(&host->data_complete_request);
enable_data_transfer_over_int(host);
wait_for_completion(&host->data_complete_request);
printk("data transfer over\n");
// dma_free_coherent(NULL, 0x2000, p ,bus_addr);
// if (!mrq->data->error && mrq->stop) {
// init_completion(&host->cmd_complete_request);
// enable_command_done_int(host);
// wait_for_completion(&host->cmd_complete_request);
// } host->mrq = NULL;
if(host->cmd)
kfree(host->cmd);
host->cmd = NULL;
host->data = NULL; // mmc_request_done(mmc, mrq);
printk("------sd_test out------\n");
}
void sepmmc_start_command(struct sepmmc_host *host)
{
struct mmc_command *cmd;
unsigned int cmd_reg=0;
dma_test(host->mmc);
cmd = (struct mmc_command *)kmalloc(sizeof(struct mmc_command),GFP_KERNEL);
printk("sepmmc_start_command into\n");
cmd->opcode = 18;
cmd->arg = 0;
cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
cmd_reg |= cmd->opcode;
if(cmd->flags & MMC_RSP_PRESENT)
cmd_reg |= SDIO_CMD_RESP_EXPE(1);
if(cmd->flags & MMC_RSP_136)
cmd_reg |= SDIO_CMD_LONG_RESP(1);
if(cmd->flags & MMC_RSP_CRC)
cmd_reg |= SDIO_CMD_CHK_RESP_CRC(1); cmd_reg |= SDIO_CMD_HAVE_DAT_TRAN(1);
cmd_reg |= SDIO_CMD_WAIT_DAT(1);
cmd_reg |= SDIO_CMD_START;
host->cmd = cmd;
writel(0,SDIO1_CMDARG_V);
// writel(cmd_reg,SDIO1_CMD_V);
writel(0x80002352,SDIO1_CMD_V);
printk("sepmmc_start_command over\n");
}
void dma_test(struct mmc_host *mmc)
{
struct sepmmc_host *host = mmc_priv(mmc);
//struct sepmmc_dma_descriptor *descriptor_test[1];
struct mmc_data *data;
//dma_addr_t DESCRIPTOR_BASE_TEST[1];
dma_addr_t bus_addr;
int i = 0;
char *p ;
printk("------sd_test into------\n"); writel(512,SDIO1_BLKSIZ_V); //block size 512
writel(0x800000,SDIO1_BYTCNT_V);//8M
data = (struct mmc_data*)kmalloc(sizeof(struct mmc_data),GFP_KERNEL);
data->blksz = 512;
data->blocks = 0x4000;
data->flags = MMC_DATA_READ;
data->stop = NULL;
host->data = data; for(i = 0;i < 1024;i++)
{
descriptor_test[i]=dma_alloc_coherent(NULL, sizeof(struct sepmmc_dma_descriptor),&DESCRIPTOR_BASE_TEST[i], GFP_KERNEL);
if(!descriptor_test[i])
printk("descriptor malloc err\n");
}
// p=dma_alloc_coherent(NULL,0x2000,&bus_addr,GFP_KERNEL);
// if(!p)
// printk("p malloc err\n");
// descriptor_test[0]->des0 = 0x8000003c;
// descriptor_test[0]->des1 = 0x2000;
// descriptor_test[0]->des2 = bus_addr;
// descriptor_test[0]->des3 = 0; for(i=0;i<1024;i++)
{
if(i == 0)
descriptor_test[i]->des0 = 0x80000018;
else if(i == 1023)
descriptor_test[i]->des0 = 0x80000034;
else
descriptor_test[i]->des0 = 0x80000010;
} p=dma_alloc_coherent(NULL,0x2000,&bus_addr,GFP_KERNEL);
if(!p)
printk("p malloc err\n"); for(i = 0;i<1024;i++)
{
descriptor_test[i]->des1 = 0x2000;
descriptor_test[i]->des2 = bus_addr;
} for(i = 0;i<1024;i++)
{
if(i < 1023)
descriptor_test[i]->des3 = DESCRIPTOR_BASE_TEST[i+1];
else
descriptor_test[i]->des3 = 0;
} writel(DESCRIPTOR_BASE_TEST[0],SDIO1_DBADDR_V);
writel(0x82,SDIO1_BMOD_V);
printk("dma init over\n");
}

这边配置要注意,自己创建cmd 和 data函数,比如不需要stop命令,就使用data->stop = NULL;这些在中断处理函数中要用,主要的错误就出现在中断处理函数中。

我使用的是内部DMA,与一般的外部DMA不一样,代码差距较大。

SD卡 驱动层测速的更多相关文章

  1. sd 卡驱动--基于高通平台

    点击打开链接 内容来自以下博客: http://blog.csdn.net/qianjin0703/article/details/5918041 Linux设备驱动子系统第二弹 - SD卡 (有介绍 ...

  2. SD卡驱动分析(一)

    Android下的SD卡驱动与标准LINUX下的SD卡驱动好像没有太大的区别,这里就以高通的ANDROID 2.3以代表,来简要分析一下LINUX下SD卡驱动的写法.由于小弟的技术有限,分析的有错的地 ...

  3. SD卡驱动分析(二)

    三.下面分析一下高通的android2.3的代码中SD卡驱动的流程. 在kernel中,SD卡是作为平台设备加入到内核中去的,在/kernel/arch/arm/mach-msm/devices-ms ...

  4. tiny4412 --Uboot移植(6) SD卡驱动,启动内核

    开发环境:win10 64位 + VMware12 + Ubuntu14.04 32位 工具链:linaro提供的gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-g ...

  5. 使用FreeRTOS在SD卡驱动使用非系统延时导致上电重启不工作的情况

    一.问题描述在一个使用FreeRTOS的工程中,只做了SD卡的驱动,由于RTOS使用了Systick,故非系统延时函数使用的是 DWT中的时钟周期(CYCCNT)计数功能,但是在SD卡驱动中使用了这个 ...

  6. NUC972当检测到sd卡时,在sd卡驱动中操作gpio开启sd卡的电源,解决sd卡因低电压有时识别不正常的问题

    1.根据硬件原理图,找到对应控制sd卡电源的gpio引脚,并在sd卡驱动文件中定义操作改该引脚的宏 2.在sd卡检测函数中,使用glib增加开sd卡电源的操作,如此当sd卡每次被检测到时,驱动中就会自 ...

  7. Linux SD卡驱动开发(四) —— SD 控制器之真正的硬件操作

    前面对SD卡控制器有了一个主要的介绍.事实上SD控制器层更过的意义是为core层提供一种操作SD卡硬件的一种方法.当然不同的控制器对硬件控制的方法不尽同样,可是他们终于都能像core层提交一个统一的封 ...

  8. 基于tiny4412的Linux内核移植 -- SD卡驱动移植(五)

    作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...

  9. SD卡驱动学习

    https://blog.csdn.net/zqixiao_09/article/category/6163492 sd 协议解析: https://blog.csdn.net/g_salamande ...

随机推荐

  1. RequireJS 上手使用

    首先 点击此处 得到requirejs. 捣鼓了俩小时终于运行成功了,原因是因为require(['我是空格underscore',...],function(){...})的时候 变量多个空格(坑爹 ...

  2. Android(java)学习笔记200:JNI之NDK的概念

    1.交叉编译 (1)概念 在一个平台(硬件)和os(软件)环境下,编译出另一种平台和os下可以运行的二进制代码. e.g:     电脑端                               ...

  3. jsonP 现在360浏览器竟然阻止本机 jquery load一些html js什么的

    别的浏览器正常可以jquery.load本机文件,但是360浏览器不行了,缺德啊!! jsonP代码 index3.html <!DOCTYPE HTML PUBLIC "-//W3C ...

  4. JAVA学习笔记16——控制线程

    Java的线程支持提供了一些便捷的工具方法,通过这些便捷的工具方法可以很好地控制线程执行.   join线程 Thread提供了让一个线程等待另一个线程完成的方法——join().当在某个线程执行流中 ...

  5. [笔记] APIO 2018 Day1

    计算折纸 computaional origami 全息算法(???) margulis napkin problem 素数里有任意长的等差数列 xor gate Σxi or gate(exact ...

  6. MySQL 快速入门教程

    转:MySQL快速 入门教程 目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数据 ...

  7. ResNet,DenseNet

    目录 ResNet BOOM Why call Residual? 发展史 Basic Block Res Block ResNet-18 DenseNet ResNet 确保20层能训练好的前提下, ...

  8. Spider-Scrapy css选择器提取数据

    首先我们来说说css选择器:其实在上面的概述:和scrapy相关的函数就这么三个而已:response.css("css表达式").extract().extract_first( ...

  9. Jbox 弹出窗口 子页面操作完成后关闭 父页面刷新

    父页面js //父页面js <script> var isFreshFlag = '1'; //添加会议活动 function addMeetingAct(){ var attendVip ...

  10. Oracle 实现查询不区分大小写(设置数据库)

    转http://blog.csdn.net/shl7765856/article/details/7622756 查询数据的时候. SQL Server 默认 不区分大小写. 如果要区分,就要额外的设 ...