Linux下如何加载一个字符驱动(GPIO)

来源:互联网 发布:软件开发与设计培训 编辑:程序博客网 时间:2024/06/07 00:17

加载一个IO口的字符驱动,并验证之:

1、在“内核/drivers/char”路径下增加gpio_ctrl.c文件,该文件主要作用是申请设备号、注册设备节点等,并在该路径下的makefile中编写编译选项,将gpio_ctrl.c嵌入内核;

2、调用“内核/quich.sh”文件重新编译内核,生成的新内核文件位于“内核/arch/

</pre>arm/boot<span style="font-family:宋体;">”中,文件名见</span><span style="font-family:Calibri;">quich.sh</span><span style="font-family:宋体;">中的定义,此处为</span><span style="font-family:Calibri;">zImage;</span></p><p>3、将内核文件拷贝到<span style="font-family:Calibri;">tftp</span><span style="font-family:宋体;">根目录下,即“</span><span style="font-family:Calibri;">/tftproot</span><span style="font-family:宋体;">”,以供</span><span style="font-family:Calibri;">uboot</span><span style="font-family:宋体;">下载;</span></p><p> </p><p>验证:</p><p>1、编写<span style="font-family:Calibri;">gpio_test.c</span><span style="font-family:宋体;">文件,并编写相应</span><span style="font-family:Calibri;">makefile</span><span style="font-family:宋体;">,生成可执行文件</span><span style="font-family:Calibri;">gpio0421</span><span style="font-family:宋体;">;</span></p><p>2、将<span style="font-family:Calibri;">gpio0421</span><span style="font-family:宋体;">拷贝到文件系统目录下,</span></p><p>即“<span style="font-family:Calibri;">\mnt\sda4\Imx6q_my\05_filesystem\distro-fsl-image\home\root</span><span style="font-family:宋体;">”;</span></p><p> </p><p>上述完成后,将板子重上电,<span style="font-family:Calibri;">uboot</span><span style="font-family:宋体;">自动加载。完成后,</span></p><p>1、在串口工具中“<span style="font-family:Calibri;">ls /dev</span><span style="font-family:宋体;">”查看,应有</span><span style="font-family:Calibri;">gpio_ctrl</span><span style="font-family:宋体;">的设备节点;</span></p><p>cd<span style="font-family:宋体;">到</span><span style="font-family:Calibri;">/home/root</span><span style="font-family:宋体;">目录,直接执行</span><span style="font-family:Calibri;">gpio0421</span><span style="font-family:宋体;">,观察其打印信息即可;</span></p><p><span style="font-family:宋体;"></span></p><p><span style="font-family:宋体;"></span></p><p><span style="font-family:宋体;"></span></p><p><span style="font-family:宋体;"></span></p><p><span style="font-family:宋体;"></span></p><p><span style="font-family:宋体;"></span></p><p><span style="font-family:宋体;"></span></p><p><span style="font-family:宋体;">gpio_test.c:</span></p><p><span style="font-family:宋体;"></span><pre name="code" class="cpp">#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#define GPIO_CTRL_CMD_L 0x00#define GPIO_CTRL_CMD_H 0x01#define PSTN_MODE_RST 0 // 要操作的GPIOint main(int argc, char *argv[]){int fd;    int index;    if (argc < 2) {        printf("Usage: \n %s < H|L >\n", argv[0]);        return -1;    }        fd = open("/dev/gpio_ctrl", O_RDWR);    if (fd < 0) {        printf("open gpio_ctrl failed.\n");        return -1;    }    index = PSTN_MODE_RST;    if ((!strcmp(argv[1], "H")) || (!strcmp(argv[1], "h")))    {ioctl(fd, GPIO_CTRL_CMD_H, &index);printf("Ctrl High\n");}    else if ((!strcmp(argv[1], "L")) || (!strcmp(argv[1], "l")))    {ioctl(fd, GPIO_CTRL_CMD_L, &index);printf("Ctrl Low\n");}printf("close the /dev/gpio_ctrl\n");    close(fd);return 0;}

makefile:

TARGET=gpio0421CC=arm-linux-gnueabihf-gcc -c -g -I./#LINK=gccLINK=arm-linux-gnueabihf-gccC_SOURCE=$(wildcard *.c)C_OBJS=$(C_SOURCE:%.c=%.o)$(TARGET): $(C_OBJS)@echo Linking $@ from $^..$(LINK) -o $@ $^$(C_OBJS): %.o: %.c @echo $(C_OBJS)@echo Compiling $@ from $<..$(CC) -o $@ $<PHONY:cleanclean:rm -rf $(C_OBJS) $(TARGET)


gpio_ctrl.c

#include <linux/init.h>#include <linux/module.h>#include <linux/cdev.h> //cdev#include <linux/fs.h> //file_operations#include <linux/uaccess.h> //copy_* #include <linux/types.h>#include <linux/ioctl.h>#include <linux/delay.h>#include <linux/i2c.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/bcd.h>#include <linux/ctype.h>#include <linux/kernel.h>#include <linux/device.h>#include <linux/workqueue.h>#include <asm/gpio.h>#include <linux/gpio.h>//#include <arch/arm/mach-imx/hardware.h>MODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("yangyufeng");MODULE_DESCRIPTION("A simple char driver: GPIO CTROL");MODULE_VERSION("1.0");#define IMX_GPIO_NR(bank, nr)  (((bank) - 1) * 32 + (nr))#define PSTN_MODE_RST  IMX_GPIO_NR(2, 5)#define debug_print(x...) printk(x)#define GPIO_CTRL_CMD_L 0x00#define GPIO_CTRL_CMD_H 0x01int i;struct gpio_info {    int gpio;    char *name;};static struct gpio_info gpio_name[] = {    {    .gpio = PSTN_MODE_RST,    .name = "pstn module GPIO2_05"    },};dev_t gpio_ctrl_devno;struct cdev *gpio_ctrl_cdev;static struct class *gpio_ctrl_class = NULL;static int     gpio_ctrl_open(struct inode *inode, struct file *filp);static int     gpio_ctrl_release(struct inode *inode, struct file *filp);static ssize_t gpio_ctrl_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);static ssize_t  gpio_ctrl_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);static int gpio_ctrl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);struct file_operations gpio_ctrl_fops = {    .owner   = THIS_MODULE,    .read    = gpio_ctrl_read,    .write   = gpio_ctrl_write,    .open    = gpio_ctrl_open,    .release = gpio_ctrl_release,    .unlocked_ioctl = gpio_ctrl_ioctl,};static int isl12026_i2c_eeprom_init(void){int ret = 0;ret = alloc_chrdev_region(&gpio_ctrl_devno, 0, 1, "gpio_control");if(ret<0)printk(KERN_ALERT"Error: Can not register device number\n");elseprintk(KERN_ALERT"Major:%d  Minor:%d\n",MAJOR(gpio_ctrl_devno),MINOR(gpio_ctrl_devno));gpio_ctrl_cdev   = cdev_alloc(); // 分配字符设备对象gpio_ctrl_cdev->ops   = &gpio_ctrl_fops;gpio_ctrl_cdev->owner = THIS_MODULE;ret = cdev_add(gpio_ctrl_cdev, gpio_ctrl_devno, 1); //注册字符设备if(ret) {printk(KERN_ALERT"Error %d adding chdrv",ret);}// 自动生成设备节点gpio_ctrl_class = class_create(THIS_MODULE, "gpio_ctrl"); //创建一个子类device_create(gpio_ctrl_class, NULL, gpio_ctrl_devno, NULL, "gpio_ctrl");// ---------------操作GPIO--------------------//申请GPIO资源for (i = 0; i < ARRAY_SIZE(gpio_name); i++) {        gpio_request(gpio_name[i].gpio, gpio_name[i].name);    }        // ---------------操作GPIO--------------------return 0;}static void isl12026_i2c_eeprom_cleanup(void){// ---------------操作GPIO--------------------for (i = 0; i < ARRAY_SIZE(gpio_name); i++) {        gpio_free(gpio_name[i].gpio);     }    // ---------------操作GPIO--------------------device_destroy(gpio_ctrl_class, gpio_ctrl_devno); //delete device node under /dev    class_destroy(gpio_ctrl_class); //delete class createdunregister_chrdev_region(gpio_ctrl_devno, 1);}static int gpio_ctrl_open(struct inode* inode, struct file* file){printk("gpio open\n");return 0;}static int gpio_ctrl_release(struct inode* inode, struct file* file){printk("gpio release\n");return 0;}static ssize_t gpio_ctrl_read(struct file* file, char* buf, size_t count, loff_t* f_pos){printk("gpio read\n");return 0;}static ssize_t gpio_ctrl_write(struct file* file, const char* buf, size_t count, loff_t* f_pos){printk("gpio write\n");return 0;}static int gpio_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg){int index = 0;int no_use = 0;no_use = copy_from_user(&index, (int *)arg, sizeof(index));switch (cmd) {case GPIO_CTRL_CMD_L:printk("gpio ctrl LOW\n");gpio_direction_output(gpio_name[index].gpio, 0);break;case GPIO_CTRL_CMD_H:printk("gpio ctrl HIGH\n");gpio_direction_output(gpio_name[index].gpio, 1);default:return -1;}return 0;}module_init(isl12026_i2c_eeprom_init);module_exit(isl12026_i2c_eeprom_cleanup);/**************************************************************************//* End of file                                                            *//**************************************************************************/

makefile

## Makefile for the kernel character device drivers.#obj-y+= mem.o random.oobj-$(CONFIG_TTY_PRINTK)+= ttyprintk.oobj-y+= misc.oobj-$(CONFIG_ATARI_DSP56K)+= dsp56k.oobj-$(CONFIG_VIRTIO_CONSOLE)+= virtio_console.oobj-$(CONFIG_RAW_DRIVER)+= raw.oobj-$(CONFIG_SGI_SNSC)+= snsc.o snsc_event.oobj-$(CONFIG_MSM_SMD_PKT)+= msm_smd_pkt.oobj-$(CONFIG_MSPEC)+= mspec.oobj-$(CONFIG_MMTIMER)+= mmtimer.oobj-$(CONFIG_UV_MMTIMER)+= uv_mmtimer.oobj-$(CONFIG_IBM_BSR)+= bsr.oobj-$(CONFIG_SGI_MBCS)+= mbcs.oobj-$(CONFIG_BFIN_OTP)+= bfin-otp.oobj-$(CONFIG_FSL_OTP)+= fsl_otp.oobj-$(CONFIG_THERMAL_PRINTER) += jx_2r_01.oobj-$(CONFIG_THERMAL_PRINTER) += jx_2r_01_dev.oobj-$(CONFIG_THERMAL_PRINTER) += gpio_ctrl.oobj-$(CONFIG_PRINTER)+= lp.oobj-$(CONFIG_APM_EMULATION)+= apm-emulation.oobj-$(CONFIG_DTLK)+= dtlk.oobj-$(CONFIG_APPLICOM)+= applicom.oobj-$(CONFIG_SONYPI)+= sonypi.oobj-$(CONFIG_RTC)+= rtc.oobj-$(CONFIG_HPET)+= hpet.oobj-$(CONFIG_GEN_RTC)+= genrtc.oobj-$(CONFIG_EFI_RTC)+= efirtc.oobj-$(CONFIG_DS1302)+= ds1302.oobj-$(CONFIG_XILINX_HWICAP)+= xilinx_hwicap/ifeq ($(CONFIG_GENERIC_NVRAM),y)  obj-$(CONFIG_NVRAM)+= generic_nvram.oelse  obj-$(CONFIG_NVRAM)+= nvram.oendifobj-$(CONFIG_TOSHIBA)+= toshiba.oobj-$(CONFIG_I8K)+= i8k.oobj-$(CONFIG_DS1620)+= ds1620.oobj-$(CONFIG_HW_RANDOM)+= hw_random/obj-$(CONFIG_PPDEV)+= ppdev.oobj-$(CONFIG_NWBUTTON)+= nwbutton.oobj-$(CONFIG_NWFLASH)+= nwflash.oobj-$(CONFIG_SCx200_GPIO)+= scx200_gpio.oobj-$(CONFIG_PC8736x_GPIO)+= pc8736x_gpio.oobj-$(CONFIG_NSC_GPIO)+= nsc_gpio.oobj-$(CONFIG_GPIO_TB0219)+= tb0219.oobj-$(CONFIG_TELCLOCK)+= tlclk.oobj-$(CONFIG_MWAVE)+= mwave/obj-y+= agp/obj-$(CONFIG_PCMCIA)+= pcmcia/obj-$(CONFIG_HANGCHECK_TIMER)+= hangcheck-timer.oobj-$(CONFIG_TCG_TPM)+= tpm/obj-$(CONFIG_PS3_FLASH)+= ps3flash.oobj-$(CONFIG_JS_RTC)+= js-rtc.ojs-rtc-y = rtc.oobj-$(CONFIG_TILE_SROM)+= tile-srom.oobj-$(CONFIG_HAVE_IMX_AMP)      += imx_amp/


0 1
原创粉丝点击