IO端口映射和IO内存映射(详解S3C24XX_GPIO驱动)
(2)inb和outb:
在Linux设备驱动中,宜使用Linux内核提供的函数来访问定位于I/O空间的端口,这些函数包括:
·读写字节端口(8位宽)
unsigned inb(unsigned port);
void outb(unsigned char byte, unsigned port);
·读写字端口(16位宽)
unsigned inw(unsigned port);
void outw(unsigned short word, unsigned port);
·读写长字端口(32位宽)
unsigned inl(unsigned port);
void outl(unsigned longword, unsigned port);
·读写一串字节
void insb(unsigned port, void *addr, unsigned long count);
void outsb(unsigned port, void *addr, unsigned long count);
· insb()从端口port开始读count个字节端口,并将读取结果写入addr指向的内存;outsb()将addr指向的内存的count个字节连续地写入port开始的端口。
·读写一串字
void insw(unsigned port, void *addr, unsigned long count);
void outsw(unsigned port, void *addr, unsigned long count);
·读写一串长字
void insl(unsigned port, void *addr, unsigned long count);
void outsl(unsigned port, void *addr, unsigned long count);
上述各函数中I/O端口号port的类型高度依赖于具体的硬件平台,因此,只是写出了unsigned。
以上知识点摘自:http://www.embeddedlinux.org.cn/html/yingjianqudong/201304/20-2556.html
这儿我不献丑了,因为上面的已经写的很好了。
(四)Linux下的IO端口和IO内存
由于我本人对IMX257的IO内存分配不太了解,曾经询问过很多周立功公司那些所谓的技术人员,每个人回答的答案都是,"你好,我们提供的资料就只是官网上的光盘资料了哦",每次碰到这种话,我真的很无语,我只能说,好吧,只能说是我智商太低了,那些资料太高深了。
好了,废话也不多说了,这次,我就针对S3C24XX的gpio驱动程序来讲解io端口的分配。
1. 定义一些寄存器(数据寄存器,配置寄存器)
上图中,gpio_va就是我们GPIO的基址,是用来确定GPFCON配置寄存器和GPFDAT数据寄存器的指针地址的
,其初始化我们在init函数中会讲解。
2.在init函数中确定gpio基址
前面我们寄存器的正常作用的前提就是gpio_va这个基址,所以我们在init函数中分配IO端口
如图所示,将gpio的地址0x56这个io端口分配为gpio_va,这样也就确定了,前面的配置寄存器和数据寄存器。
3.在open函数中配置GPIO
和单片机程序一样,使用GPIO都要先配置GPIO,原理一样:
给GPIO引脚赋初值,以后对GPIO引脚的操作,直接用这个寄存器赋值就可以了
4.在exit函数中释放IO端口
使用完GPIO引脚后,要将我们申请的IO端口释放掉。
总结一下,很简单,申请,配置,释放
申请IO端口à配置GPIO端口为输出(入)à给数据寄存器赋值(读取)à释放IO端口
附上驱动程序:
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 12 #define DEVICE_NAME "leds" 13 /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */14 #define LED_MAJOR 231 /* 主设备号 */15 16 static struct class *leds_class;17 static struct class_device *leds_class_devs[4];18 19 /* bit0<=>D10, 0:亮, 1:灭 20 * bit1<=>D11, 0:亮, 1:灭 21 * bit2<=>D12, 0:亮, 1:灭 22 */ 23 static char leds_status = 0x0; 24 static DECLARE_MUTEX(leds_lock); // 定义赋值25 26 //static int minor;27 static unsigned long gpio_va; //gpio基址28 #define GPIO_OFT(x) ((x) - 0x56)29 //GPIO 配置寄存器30 #define GPFCON (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56050)))31 //GPIO 数据寄存器32 #define GPFDAT (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56054)))33 /* 应用程序对设备文件/dev/leds执行open(...)时,34 * 就会调用s3c24xx_leds_open函数35 */36 static int s3c24xx_leds_open(struct inode *inode, struct file *file)37 {38 int minor = MINOR(inode->i_rdev); //MINOR(inode->i_cdev);39 switch(minor)40 {41 case 0: /* /dev/leds */42 {43 // 配置3引脚为输出44 //s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);45 GPFCON &= ~(0x3<(4*2));46 GPFCON = (1<(4*2));47 48 //s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);49 GPFCON &= ~(0x3<(5*2));50 GPFCON = (1<(5*2));51 52 //s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);53 GPFCON &= ~(0x3<(6*2));54 GPFCON = (1<(6*2));55 56 // 都输出057 //s3c2410_gpio_setpin(S3C2410_GPF4, 0);58 GPFDAT &= ~(1<4);59 60 //s3c2410_gpio_setpin(S3C2410_GPF5, 0);61 GPFDAT &= ~(1<5);62 //s3c2410_gpio_setpin(S3C2410_GPF6, 0);63 GPFDAT &= ~(1<6);64 65 down(&leds_lock);66 leds_status = 0x0;67 up(&leds_lock);68 69 break;70 }71 72 case 1: /* /dev/led1 */73 {74 s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);75 s3c2410_gpio_setpin(S3C2410_GPF4, 0);76 77 down(&leds_lock);78 leds_status &= ~(1<0);79 up(&leds_lock);80 81 break;82 }83 84 case 2: /* /dev/led2 */85 {86 s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);87 s3c2410_gpio_setpin(S3C2410_GPF5, 0);88 leds_status &= ~(1<1);89 break;90 }91 92 case 3: /* /dev/led3 */93 {94 s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);95 s3c2410_gpio_setpin(S3C2410_GPF6, 0);96 97 down(&leds_lock);98 leds_status &= ~(1<2);99 up(&leds_lock);100 101 break;102 }103 } 104 return 0;105 }106 static int s3c24xx_leds_read(struct file *filp, char __user *buff, 107 size_t count, loff_t *offp)108 {109 int minor = MINOR(filp->f_dentry->d_inode->i_rdev);110 char val;112 switch (minor)113 {114 case 0: /* /dev/leds */115 {116 copy_to_user(buff, (const void *)&leds_status, 1);117 break;118 }119 case 1: /* /dev/led1 */120 {121 down(&leds_lock);122 val = leds_status & 0x1;123 up(&leds_lock);124 copy_to_user(buff, (const void *)&val, 1);125 break;126 }127 case 2: /* /dev/led2 */128 {129 down(&leds_lock);130 val = (leds_status>>1) & 0x1;131 up(&leds_lock);132 copy_to_user(buff, (const void *)&val, 1);133 break;134 }135 case 3: /* /dev/led3 */136 {137 down(&leds_lock);138 val = (leds_status>>2) & 0x1;139 up(&leds_lock);140 copy_to_user(buff, (const void *)&val, 1);141 break;142 }143 }144 return 1;145 }146 static ssize_t s3c24xx_leds_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)147 {148 //int minor = MINOR(inode->i_rdev); //MINOR(inode->i_cdev);149 int minor = MINOR(file->f_dentry->d_inode->i_rdev);150 char val;151 copy_from_user(&val, buf, 1);152 switch (minor)153 {154 case 0: /* /dev/leds */155 { 156 s3c2410_gpio_setpin(S3C2410_GPF4, (val & 0x1));157 s3c2410_gpio_setpin(S3C2410_GPF5, (val & 0x1));158 s3c2410_gpio_setpin(S3C2410_GPF6, (val & 0x1));159 down(&leds_lock);160 leds_status = val;161 up(&leds_lock);162 break;163 }164 case 1: /* /dev/led1 */165 {166 s3c2410_gpio_setpin(S3C2410_GPF4, val);167 if (val == 0)168 {169 down(&leds_lock);170 leds_status &= ~(1<0);171 up(&leds_lock);172 }173 else174 {175 down(&leds_lock);176 leds_status = (1<0); 177 up(&leds_lock);178 }179 break;180 }181 case 2: /* /dev/led2 */182 {183 s3c2410_gpio_setpin(S3C2410_GPF5, val);184 if (val == 0)185 {186 down(&leds_lock);187 leds_status &= ~(1<1);188 up(&leds_lock);189 }190 else191 {192 down(&leds_lock);193 leds_status = (1<1); 194 up(&leds_lock);195 }196 break;197 }198 case 3: /* /dev/led3 */199 {200 s3c2410_gpio_setpin(S3C2410_GPF6, val);201 if (val == 0)202 {203 down(&leds_lock);204 leds_status &= ~(1<2);205 up(&leds_lock);206 }207 else208 {209 down(&leds_lock);210 leds_status = (1<2); 211 up(&leds_lock);212 }213 break;214 }215 }216 return 1;217 }218 /* 这个结构是字符设备驱动程序的核心219 * 当应用程序操作设备文件时所调用的open、read、write等函数,220 * 最终会调用这个结构中指定的对应函数221 */static struct file_operations s3c24xx_leds_fops = {223 .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */224 .open = s3c24xx_leds_open, 225 .read = s3c24xx_leds_read, 226 .write = s3c24xx_leds_write, 227 };228 229 /*230 * 执行insmod命令时就会调用这个函数 231 */232 static int __init s3c24xx_leds_init(void)233 {234 int ret;235 int minor = 0;236 237 gpio_va = ioremap(0x56, 0x100);238 if (!gpio_va) {239 return -EIO;240 }241 /* 注册字符设备242 * 参数为主设备号、设备名字、file_operations结构;243 * 这样,主设备号就和具体的file_operations结构联系起来了,244 * 操作主设备为LED_MAJOR的设备文件时,就会调用s3c24xx_leds_fops中的相关成员函数245 * LED_MAJOR可以设为0,表示由内核自动分配主设备号246 */247 ret =
IO端口映射IO内存映射S3C24XXGPIO驱 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)