字符设备驱动4: ioremap


#define GPIO_OFT(x) ((x) - 0x56000000)
#define GPFCON (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000050)))

static int s3c24xx_leds_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev); //MINOR(inode->i_cdev); switch(minor)
{
case : /* /dev/leds */
{
// 配置3引脚为输出
GPFCON &= ~(0x3<<(*));
//oo00:这里GPFCON是虚拟地址,在驱动模块开始(见下面s3c24xx_leds_init)的时候,这个虚拟地址已经通过宏定义 #define GPFCON (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000050)))被映射到物理地址
            GPFCON |= (<<(*));
    .......
} static struct file_operations s3c24xx_leds_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = s3c24xx_leds_open,
.read = s3c24xx_leds_read,
.write = s3c24xx_leds_write,
}; static int __init s3c24xx_leds_init(void)//模块入口
{
gpio_va = ioremap(0x56000000, 0x100000); // 物理地址0x56000000, 映射区分配的大小0x100000字节 printk(DEVICE_NAME "gpio_va = %x\n",gpio_va);//oo00 debug
    register_chrdev(LED_MAJOR, DEVICE_NAME, &s3c24xx_leds_fops);
...
leds_class = class_create(THIS_MODULE, "leds");
...
for (minor = ; minor < ; minor++)
{
leds_class_devs[minor] = class_device_create(leds_class, NULL, MKDEV(LED_MAJOR, minor), NULL, "led%d", minor); ..
} }

gpio_va = ioremap(0x56000000, 0x100000);//变为虚拟地址

#define GPIO_OFT(x) ((x) - 0x56000000)
#define GPFCON (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000050)))

GPFCON |= (1<<(4*2));//在ioremap成功的前提下,对虚拟地址的操作作用于对应的物理地址

————————————————————————————————————

test:

insmod myleds_ou.ko
ledsgpio_va = c5400000

—————————————————————————————————————————————————————————————————————

ioremap (unsigned long offset, unsigned long size);

参考: S3C2440开发板LED驱动——ioremap 映射  http://www.linuxidc.com/Linux/2012-12/76084.htm

上一篇:Flask入门之Bootstrap介绍使用和Flask-Nav快速导航栏


下一篇:5.机器学习——DBSCAN聚类算法