加载一个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 // 要操作的GPIO
int 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=gpio0421
CC=arm-linux-gnueabihf-gcc -c -g -I./
#LINK=gcc
LINK=arm-linux-gnueabihf-gcc
C_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:clean
clean:
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 0x01
int 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");
else
printk(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 created
unregister_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.o
obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o
obj-y += misc.o
obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
obj-$(CONFIG_MSM_SMD_PKT) += msm_smd_pkt.o
obj-$(CONFIG_MSPEC) += mspec.o
obj-$(CONFIG_MMTIMER) += mmtimer.o
obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o
obj-$(CONFIG_IBM_BSR) += bsr.o
obj-$(CONFIG_SGI_MBCS) += mbcs.o
obj-$(CONFIG_BFIN_OTP) += bfin-otp.o
obj-$(CONFIG_FSL_OTP) += fsl_otp.o
obj-$(CONFIG_THERMAL_PRINTER) += jx_2r_01.o
obj-$(CONFIG_THERMAL_PRINTER) += jx_2r_01_dev.o
obj-$(CONFIG_THERMAL_PRINTER) += gpio_ctrl.o
obj-$(CONFIG_PRINTER) += lp.o
obj-$(CONFIG_APM_EMULATION) += apm-emulation.o
obj-$(CONFIG_DTLK) += dtlk.o
obj-$(CONFIG_APPLICOM) += applicom.o
obj-$(CONFIG_SONYPI) += sonypi.o
obj-$(CONFIG_RTC) += rtc.o
obj-$(CONFIG_HPET) += hpet.o
obj-$(CONFIG_GEN_RTC) += genrtc.o
obj-$(CONFIG_EFI_RTC) += efirtc.o
obj-$(CONFIG_DS1302) += ds1302.o
obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/
ifeq ($(CONFIG_GENERIC_NVRAM),y)
obj-$(CONFIG_NVRAM) += generic_nvram.o
else
obj-$(CONFIG_NVRAM) += nvram.o
endif
obj-$(CONFIG_TOSHIBA) += toshiba.o
obj-$(CONFIG_I8K) += i8k.o
obj-$(CONFIG_DS1620) += ds1620.o
obj-$(CONFIG_HW_RANDOM) += hw_random/
obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o
obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
obj-$(CONFIG_GPIO_TB0219) += tb0219.o
obj-$(CONFIG_TELCLOCK) += tlclk.o
obj-$(CONFIG_MWAVE) += mwave/
obj-y += agp/
obj-$(CONFIG_PCMCIA) += pcmcia/
obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
obj-$(CONFIG_TCG_TPM) += tpm/
obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_JS_RTC) += js-rtc.o
js-rtc-y = rtc.o
obj-$(CONFIG_TILE_SROM) += tile-srom.o
obj-$(CONFIG_HAVE_IMX_AMP) += imx_amp/