mini2440 sd卡加载过程详解

2020-05-26来源: eefocus关键字:mini2440  sd卡  加载过程

最近在研究wifi模组, 是sdio接口的, 而手头刚好有一块mini2440,了解了一下sdio加载的过程, 发现和sd卡加载的过程是类似的。 


这里用mini2440的内核源码, 来剖析一下sd卡的加载过程:


首先, mini2440内核加载的时候, 就会指定一部分设备初始化列表:


//---------------------------- arch/arm/mach-s3c2440/mach-mini2440.c ----------------------------//

/* devices we initialise */

static struct platform_device *mini2440_devices[] __initdata = {

    &s3c_device_usb,

    &s3c_device_rtc,

    &s3c_device_lcd,

    &s3c_device_wdt,

    &s3c_device_i2c0,

    &s3c_device_iis,

    &mini2440_device_eth,

    &s3c24xx_uda134x,

    &s3c_device_nand,

    &s3c_device_sdi,                                        // sd设备

    &s3c_device_usbgadget,

};

/* MMC/SD  */

static struct s3c24xx_mci_pdata mini2440_mmc_cfg = {

    .gpio_detect   = S3C2410_GPG(8),                        // 插入检测引脚

    .gpio_wprotect = S3C2410_GPH(8),                        // 写保护引脚

    .set_power     = NULL,

    .ocr_avail     = MMC_VDD_32_33|MMC_VDD_33_34,           // 有效电压范围是3.2~3.3V, 3.3~3.4V

};

 

static void __init mini2440_machine_init(void)

{

    s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;                   

    platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));   

}

来看看s3c_device_sdi的定义:

//---------------------------- arch/arm/plat-s3c24xx/devs.c ----------------------------//

/* SDI */

static struct resource s3c_sdi_resource[] = {

    [0] = {

        .start = S3C24XX_PA_SDI,

        .end   = S3C24XX_PA_SDI + S3C24XX_SZ_SDI - 1,

        .flags = IORESOURCE_MEM,

    },

    [1] = {

        .start = IRQ_SDI,

        .end   = IRQ_SDI,

        .flags = IORESOURCE_IRQ,

    }

 

};

 

struct platform_device s3c_device_sdi = {

    .name   = "s3c2410-sdi",

    .id   = -1,

    .num_resources   = ARRAY_SIZE(s3c_sdi_resource),

    .resource   = s3c_sdi_resource,

};

有些人会奇怪, 我们这里不是在讲解2440吗, 为什么这里是s3c2410-sdi, 别急, 往下看:

//---------------------------- arch/arm/mach-s3c2440/mach-mini2440.c ----------------------------//

static void __init mini2440_machine_init(void)

{

    s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;                   

    platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));   

}

 

//---------------------------- arch/arm/plat-s3c24xx/s3c244x.c ----------------------------//

void __init s3c244x_map_io(void)

{

    iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));

 

    /* rename any peripherals used differing from the s3c2410 */

 

    s3c_device_sdi.name  = "s3c2440-sdi";                           // 重命名为s3c2440-sdi

    s3c_device_i2c0.name  = "s3c2440-i2c";

    s3c_device_nand.name = "s3c2440-nand";

    s3c_device_usbgadget.name = "s3c2440-usbgadget";

}

理解了吧?  

接下来讲sd驱动的加载:


//---------------------------- drivers/mmc/host/s3cmci.c ----------------------------//

static struct platform_device_id s3cmci_driver_ids[] = {

    {

        .name = "s3c2410-sdi",

        .driver_data = 0,

    }, {

        .name = "s3c2412-sdi",

        .driver_data = 1,

    }, {

        .name = "s3c2440-sdi",

        .driver_data = 1,                            // 下面会用到!!!

    },

    { }

};

 

static struct platform_driver s3cmci_driver = {

   .driver = {

       .name = "s3c-sdi",

       .owner = THIS_MODULE,

       .pm = s3cmci_pm_ops,

   },

   .id_table = s3cmci_driver_ids,

   .probe = s3cmci_probe,

   .remove = __devexit_p(s3cmci_remove),

   .shutdown = s3cmci_shutdown,

};

 

static int __init s3cmci_init(void)

{

   return platform_driver_register(&s3cmci_driver);

}

 

module_init(s3cmci_init); 

驱动和设备匹配上的话,就会调用驱动的probe函数:

static int __devinit s3cmci_probe(struct platform_device *pdev)

{

struct s3cmci_host *host;

struct mmc_host *mmc;

 

    is2440 = platform_get_device_id(pdev)->driver_data;                 // 是否是2440, 这里就用到上面提到的driver_data,

 

    mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);       // 分配mmc_host结构体

 

    for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) {               // SDCLK SDCMD DATA0~DATA3

        ret = gpio_request(i, dev_name(&pdev->dev));                    // 申请gpio资源

        if (ret) {

            dev_err(&pdev->dev, "failed to get gpio %dn", i);

 

            for (i--; i >= S3C2410_GPE(5); i--)

                gpio_free(i);

 

            goto probe_free_host;

        }

    }

 

host = mmc_priv(mmc);                                               // 获取private域

host->mmc = mmc;

host->pdev = pdev;

host->is2440 = is2440;

 

host->pdata = pdev->dev.platform_data;                              // 即上面提到的mini2440_mmc_cfg

if (!host->pdata) {

pdev->dev.platform_data = &s3cmci_def_pdata;

host->pdata = &s3cmci_def_pdata;

}

 

if (is2440) {

host->sdiimsk = S3C2440_SDIIMSK;

host->sdidata = S3C2440_SDIDATA;

host->clk_div = 1;

} else {

host->sdiimsk = S3C2410_SDIIMSK;

host->sdidata = S3C2410_SDIDATA;

host->clk_div = 2;

}

 

    // 申请内存

host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);         // 这里会读取IORESOURCE_MEM域

 

host->mem = request_mem_region(host->mem->start,

       resource_size(host->mem), pdev->name);

 

host->base = ioremap(host->mem->start, resource_size(host->mem));

 

 

host->irq = platform_get_irq(pdev, 0);                              // 这里会读取IORESOURCE_IRQ域, 返回start地址

if (host->irq == 0) {

dev_err(&pdev->dev, "failed to get interrupt resouce.n");

ret = -EINVAL;

goto probe_iounmap;

}

 

    // 申请中断,该中断为读写SD卡数据时所产生的中断

if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {

dev_err(&pdev->dev, "failed to request mci interrupt.n");

ret = -ENOENT;

goto probe_iounmap;

}

 

    // 禁止上面所申请的中断

    disable_irq(host->irq);                                             

    host->irq_state = false;

 

if (!host->pdata->no_detect) {                                      // 如果SD控制器具有检测SD卡插拔状态的功能

        ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect");  // 申请插入检测io

 

        host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);

        if (host->irq_cd >= 0) {

            if (request_irq(host->irq_cd, s3cmci_irq_cd,                // 注册插入检测中断处理函数, 申请中断,当有SD卡插入或拔出时,则进入该中断

                        IRQF_TRIGGER_RISING |

                        IRQF_TRIGGER_FALLING,

                        DRIVER_NAME, host)) {

                dev_err(&pdev->dev,

                        "can't get card detect irq.n");

ret = -

[1] [2] [3]
关键字:mini2440  sd卡  加载过程 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic498310.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:mini2440开发板之使用nfs无法启动的问题(Virtualbox桥接网络)
下一篇:mini2440+jlink+mkd 裸机按键中断调试心得体会

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

mini2440裸机试炼之——Uart与pc端实现文件、字符传输
:rULCON0|=0x03;              //设置UART0数据发送8个数据位赵老师的一段话(关于中断的,作为笔记):最后还要强调几点关于非FIFO模式下UART中断的一些注意事项:1.对于s3c2440来说,接收数据是被动的,发送数据是主动的,因此一般来说,接收数据用中断方式,发送数据用查询方式较好;2. 在中断方式下,当接收到数据时,尽管可能该数据无用,但也一定要读取它,否则下次再接收数据时,不会再引起中断,因为接收数据缓存器被上次接收到的数据所霸占,只要没有读取它,它就永远在那里;3. 由于UART中断涉及到SUBSRCPND寄存器,因此在
发表于 2020-07-04
<font color='red'>mini2440</font>裸机试炼之——Uart与pc端实现文件、字符传输
mini2440裸机试炼之IIS——音乐播放器
; Port_Init();    MMU_Init(); //地址映射初始化    Beep(2000, 100);       music_player();}music_player.c/*********************************** 实现功能     music播放器  ***********************************/ #include "2440lib.h"#include "2440
发表于 2020-07-04
<font color='red'>mini2440</font>裸机试炼之IIS——音乐播放器
mini2440裸机试炼之——IIC控制EEPROM数据传输
,AT24C02A会再返回一个从设备地址信息或从设备内存地址信息作为应答,所以一定要把该字节读取后抛弃,因为它不是我们所要读取的信息;4、按照AT24C02A的时序,在发送从设备地址字节时,它的最低位是0表示写,1表示读。但对于s3c2440来说,不用人为设置这一位,即是0是1都无所谓,因为这一位是由s3c2440根据是主设备发送模式还是主设备接收模式来自动设置。(所以都默认使用0xa0);EEPROM介绍AT24CXX系列是带有iic总线接口的EEPROM,其中主要包括AT24C01/02/08/16等,其容量(bits x页)分别为128 x 8/256x 8/1024 x 8/2048 x 8/;对于AT24C02A的三位地址线都是
发表于 2020-07-04
<font color='red'>mini2440</font>裸机试炼之——IIC控制EEPROM数据传输
mini2440裸机试炼之——看门狗中断和复位操作
结果:AXD调试执行到看门狗计数器rWTCNT为零时,进入复位,CPU停止工作,也就不产生中断。复位关闭axd后,u-boot串口初始化提示(没能及时在第一次蜂鸣器响按下按键停止autoboot):复位关闭axd后,u-boot串口初始化提示(及时在第一次蜂鸣器响按下按键停止autoboot):这里就是复位到用uboot初始化开发板的时候,可是不明确为什么必需要在第一次蜂鸣器就按下按键才干进到uboot附:硬件环境:J-link v8、mini2440、J-link转接板、串口转USB线软件环境:windows7(32位)、开发板uboot(NandFlash)、J-link驱动(J-Link ARM V4.10i)、SecureCRT
发表于 2020-07-04
<font color='red'>mini2440</font>裸机试炼之——看门狗中断和复位操作
arm-linux-gcc 裸机程序开发(一)
以前开发arm裸机程序都是在ADS1.2开发环境下编译和调试的。刚开始时初学嵌入式好多东西不懂,选择这个开发环境的理由,一是资料多的,mini2440开发板上提供了很多例程可以参考,网上几乎所有arm裸机程序都是基于ADS1.2开发的。二是开发环境友善,虽然后来感觉ADS1.2有点难用,但毕竟是IDE的环境,对初学者来说总比命令行的方式更加直观与方便。随着学习的深入,感觉它就像傻瓜相机一样,虽然好用但屏蔽了很多内容,影响了我们深入理解代码编译以及链接的细节。而且ADS对于程序的开发没有GNU工具链灵活。这段时间因为需要,又要编写一些arm裸机程序。自己已经用Linux习惯了,不想再切回windows下工作了。所以,最近对linux
发表于 2020-07-04
mini2440开发板建立Keil MDK/Jlink开发调试环境
新建Keil工程,device选择三星的s3c2440。询问”是否将启动代码拷贝到工程目录”,选择是。在工程配置的Target标签页中做如下配置:确定后编写主函数并编译工程。假如没有错误,打开工程目录下的”工程名.sct”文件,就会发现ROM1的0×30000000就是程序的入口地址,对应启动代码中的”RESET”。安装Jlink驱动后,在Keil的debug标签中选择”J-link/J-Trace”作为调试工具。在Initialization File文本框中选择调试的初始化文件。打开初始化文件,将文件最后的”LOAD .XXX.axf”,中的XXX替换为自己工程目录下的axf文件名。在Utilities标签页中,选择J
发表于 2020-07-02
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved