Linux开发十三_hsmmc驱动

来源:互联网 发布:知乎周刊纸质版 编辑:程序博客网 时间:2024/06/17 14:27

Linux开发十三

hsmmc驱动

象棋小子    1048272975

存储卡具有体积小巧、携带方便、使用简单等优点,在嵌入式系统当中,一般作为独立的存储介质。Linux内核已经支持s3c2416的hsmmc控制器,可以支持mmc卡、sd卡等的读写。

1. hsmmc设备

hsmmc设备包含了名字、独有的资源等等一些驱动程序的硬件或自定义信息。通过platform_add_devices(platform_device_register)函数将定义的平台设备注册到内核中,用于匹配设备驱动。

内核在drivers\mmc\host\sdhci-s3c.c中实现了s3c2416 hsmmc驱动,hsmmc设备的平台代码如下。

#ifdef CONFIG_S3C_DEV_HSMMC

static struct resources3c_hsmmc_resource[] = {

       [0]= DEFINE_RES_MEM(S3C_PA_HSMMC0, SZ_4K),

       [1]= DEFINE_RES_IRQ(IRQ_HSMMC0),

};

 

struct s3c_sdhci_platdatas3c_hsmmc0_def_platdata = {

       .max_width   = 4,

       .host_caps     = (MMC_CAP_4_BIT_DATA |

                        MMC_CAP_MMC_HIGHSPEED |MMC_CAP_SD_HIGHSPEED),

};

 

struct platform_device s3c_device_hsmmc0= {

       .name            = "s3c-sdhci",

       .id          = 0,

       .num_resources    = ARRAY_SIZE(s3c_hsmmc_resource),

       .resource       = s3c_hsmmc_resource,

       .dev        = {

              .dma_mask          = &samsung_device_dma_mask,

              .coherent_dma_mask  = DMA_BIT_MASK(32),

              .platform_data            = &s3c_hsmmc0_def_platdata,

       },

};

 

void s3c_sdhci0_set_platdata(structs3c_sdhci_platdata *pd)

{

       s3c_sdhci_set_platdata(pd,&s3c_hsmmc0_def_platdata);

}

#endif /* CONFIG_S3C_DEV_HSMMC */

 

#ifdef CONFIG_S3C_DEV_HSMMC1

static struct resources3c_hsmmc1_resource[] = {

       [0]= DEFINE_RES_MEM(S3C_PA_HSMMC1, SZ_4K),

       [1]= DEFINE_RES_IRQ(IRQ_HSMMC1),

};

 

struct s3c_sdhci_platdatas3c_hsmmc1_def_platdata = {

       .max_width   = 4,

       .host_caps     = (MMC_CAP_4_BIT_DATA |

                        MMC_CAP_MMC_HIGHSPEED |MMC_CAP_SD_HIGHSPEED),

};

 

struct platform_device s3c_device_hsmmc1= {

       .name            = "s3c-sdhci",

       .id          = 1,

       .num_resources    = ARRAY_SIZE(s3c_hsmmc1_resource),

       .resource       = s3c_hsmmc1_resource,

       .dev        = {

              .dma_mask          = &samsung_device_dma_mask,

              .coherent_dma_mask  = DMA_BIT_MASK(32),

              .platform_data            = &s3c_hsmmc1_def_platdata,

       },

};

 

void s3c_sdhci1_set_platdata(structs3c_sdhci_platdata *pd)

{

       s3c_sdhci_set_platdata(pd,&s3c_hsmmc1_def_platdata);

}

#endif /* CONFIG_S3C_DEV_HSMMC1 */

 

static struct s3c_sdhci_platdatahome2416_hsmmc0_pdata __initdata = {

       .max_width          = 4,

       .cd_type        = S3C_SDHCI_CD_NONE,

 

};

 

static struct s3c_sdhci_platdatahome2416_hsmmc1_pdata __initdata = {

       .max_width          = 4,

       .cd_type        = S3C_SDHCI_CD_GPIO,

       .ext_cd_gpio        = S3C2410_GPF(3),

       .ext_cd_gpio_invert    = 1,

};

在板级初始化函数home2416_machine_init ()中加入hsmmc平台数据s3c_sdhci0_set_platdata(&home2416_hsmmc0_pdata)和s3c_sdhci1_set_platdata(&home2416_hsmmc1_pdata)。在static struct platform_device *home2416_devices[]板级平台设备列表中加入&s3c_device_hsmmc0和&s3c_device_hsmmc1,使hcmmc0、hcmmc1设备能够注册到内核中。

修改并更正驱动文件sdhci-s3c.c。

在sdhci_s3c_probe()函数中,加入gpio检测sd卡。

#include <linux/mmc/slot-gpio.h>// add

       if(pdata->cd_type == S3C_SDHCI_CD_PERMANENT)

              host->mmc->caps= MMC_CAP_NONREMOVABLE;

   

       //add

       if(pdata->cd_type == S3C_SDHCI_CD_GPIO) {

              if(gpio_is_valid(pdata->ext_cd_gpio)) {

                     ret= mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio,

                                            0);

                     if(ret) {

                            dev_err(mmc_dev(host->mmc),

                                   "failedto allocate card detect gpio\n");

                            gotoerr_req_regs;

                     }

              }

 

       }

在sdhci_s3c_ops结构体中加入读sd卡写保护的实现.get_ro = sdhci_s3c_get_ro,本例sd卡没有硬件写保护。

// add

static unsigned intsdhci_s3c_get_ro(struct sdhci_host *host)

{

       return0; // write enable

}

 

static struct sdhci_ops sdhci_s3c_ops ={

       .get_ro               = sdhci_s3c_get_ro, // add

       .get_max_clock           = sdhci_s3c_get_max_clk,

       .set_clock             = sdhci_s3c_set_clock,

       .get_min_clock            = sdhci_s3c_get_min_clock,

       .set_bus_width            = sdhci_s3c_set_bus_width,

       .reset                    = sdhci_reset,

       .set_uhs_signaling       = sdhci_set_uhs_signaling,

};

2. 内核配置

Linux内核配置支持hsmmc设备驱动,选中Device Drivers->MMC/SD/SDIO cardsupport->SDHCI support on Samsung S3C SoC。

sd卡使用fat32文件系统,配置内核支持vfat文件系统。File systems->DOS/FAT/NT Filesystems->VFAT (Windows-95) fssupport。

3. sd卡测试

cat/proc/devices可以知道hsmmc1的主设备好为179,次设备号为0,在/dev/block目录中创建mmcblk1设备文件。

mknod /dev/mmcblk1 b 179 0

cat/proc/partitions查看sd卡分区,先对sd卡格式化成vfat文件系统。

mkfs.vfat /dev/mmcblk1

挂载mmcblk1设备。

mkdir /mnt/sd

mount /dev/mmcblk1 /mnt/sd

对sd卡读写文件。

echo This is file test. > /mnt/sd/test.txt

cat /mnt/sd/test.txt

 

4. 应用编程

应用程序可以通过设备文件访问sd卡,hsmmc应用测试代码hsmmc_test.c如下。

#include "fcntl.h"

#include "unistd.h"

#include "sys/types.h"

#include "stdio.h"

#include "stdlib.h"

#include "string.h"

 

int main(void)

{

       intret;

       intfd;

       charwrite_buf[64] = "This is file test.";

       charread_buf[64];

       fd= open("/mnt/sd/test.txt", O_RDWR|O_CREAT);

       if(fd == -1) {

              printf("Openfile failed\n");

              exit(1);

       }

 

       ret= write(fd, write_buf, strlen(write_buf));

       if(ret == -1) {

              printf("Writefile failed\n");

              close(fd);

              exit(1);

       }

       close(fd);

       printf("write:%s\n", write_buf);

 

       fd= open("/mnt/sd/test.txt", O_RDONLY);

       ret= read(fd, read_buf, strlen(write_buf));

       if(ret == -1) {

              printf("Readfile failed\n");

              close(fd);

              exit(1);         

       }

       read_buf[strlen(write_buf)]= 0;

       printf("read:%s\n", read_buf);

       close(fd);

       return0;

}

用arm-linux-gcc静态编译,使之生成arm cpu可执行的指令,并且可脱离任何库独立运行,arm-linux-gcc -static -o hsmmc_test hsmmc_test.c,生成hsmmc_test可执行文件。复制可执行文件到根文件系统,目标板启动后在目录输入./hsmmc_test即可执行。

5. 附录

https://pan.baidu.com/s/1slczwhJ

bootloader源码以及使用说明

https://pan.baidu.com/s/1eRDJtNs

Qt5.8官网源码

https://pan.baidu.com/s/1nuGmSqt

本系列例程的根文件系统

https://pan.baidu.com/s/1i5btLGT

opev3.2.0官网源码

https://pan.baidu.com/s/1pLpuHw3

yaffs官网源码 

https://pan.baidu.com/s/1bpkZynt

busybox-1.26.2官网源码

https://pan.baidu.com/s/1i4EtjfR

tslib官网源码

https://pan.baidu.com/s/1i5MGRhb

mplayer-1.3.0官网源码

https://pan.baidu.com/s/1sl0fXlr

基于S3C2416修改的linux-4.10.10源码

 

0 0
原创粉丝点击