linux内核中2410_gpio_cfgpin函数分析
来源:互联网 发布:itunes软件许可协议 编辑:程序博客网 时间:2024/06/05 18:00
2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT) 函数分析:作用设置相应GPIO口的工作模式,输入、输出、中断等。
一,首先宏展开:为方便描述,展开后用等号表示
#define S3C2410_GPIO_OUTPUT (0xFFFFFFF1) #define S3C2410_GPB0 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 0) #define S3C2410_GPIO_BANKB (32*1)#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
所以S3C2410_GPB0 = S3C2410_GPIONO((32*1), 0)= (32*1);
S3C2410_GPIO_OUTPUT = (0xFFFFFFF1);
最终得到:
s3c2410_gpio_cfgpin(32, 0xFFFFFFF1)
二、接下来进入s3c2410_gpio_cfgpin函数分析:
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function){ void __iomem *base = S3C24XX_GPIO_BASE(pin); unsigned long mask; unsigned long con; unsigned long flags; if (pin < S3C2410_GPIO_BANKB) { mask = 1 << S3C2410_GPIO_OFFSET(pin); } else { mask = 3 << S3C2410_GPIO_OFFSET(pin)*2; } switch (function) { case S3C2410_GPIO_LEAVE: mask = 0; function = 0; break; case S3C2410_GPIO_INPUT: case S3C2410_GPIO_OUTPUT: case S3C2410_GPIO_SFN2: case S3C2410_GPIO_SFN3: if (pin < S3C2410_GPIO_BANKB) { function -= 1; function &= 1; function <<= S3C2410_GPIO_OFFSET(pin); } else { function &= 3; function <<= S3C2410_GPIO_OFFSET(pin)*2; } } /* modify the specified register wwith IRQs off */ local_irq_save(flags); con = __raw_readl(base + 0x00); con &= ~mask; con |= function; __raw_writel(con, base + 0x00); local_irq_restore(flags);}
1、S3C24XX_GPIO_BASE(pin)宏展开:
#define S3C24XX_GPIO_BASE(x) S3C2410_GPIO_BASE(x)#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)#define S3C24XX_VA_GPIO ((S3C2410_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)#define S3C2410_PA_GPIO (0x56000000)#define S3C24XX_PA_UART S3C2410_PA_UART ——>#define S3C2410_PA_UART (0x50000000) #define S3C24XX_VA_UART S3C2410_ADDR(0x00400000) ——>#define S3C2410_ADDR(x) (0xF0000000 + (x))
将宏全部替换:
S3C2410_PA_GPIO = 0x56000000 S3C24XX_PA_UART = 0x50000000S3C24XX_VA_UART = 0xF0400000//虚拟地址S3C24XX_VA_GPIO = ((0x56000000 - 0x50000000) + 0xF0400000) = 0xF6400000S3C24XX_GPIO_BASE(32) = ((((32) & ~31) >> 1) + 0xF6400000) = 0xF6400010
所以S3C24XX_GPIO_BASE(pin)宏展开后为:
S3C24XX_GPIO_BASE(32) = ((((32) & ~31) >> 1) + 0xF6400000) = 0xF6400010
作用:获得所要配置的控制寄存器的基地址,注意这是虚拟地址
2、S3C2410_GPIO_OFFSET宏展开:
#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
3、通过分析最终得到
pin = 32;
function= 0xFFFFFFF1 = S3C2410_GPIO_OUTPUT;
base = 0xF6400010;
mask = 3;
function &= 3; ——> function = 0x01;
__raw_readl,__raw_writel分析:
__raw_readl和__raw_writel
Linux对I/O的操作都定义在asm/io.h中,相应的在arm平台下,就在asm-arm/io.h中。
#define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a))#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))
在include\linux\compiler.h中:
#ifdef __CHECKER__……extern void __chk_io_ptr(void __iomem *);#else……# define __chk_io_ptr(x) (void)0……#endif
raw_readl(a)展开是:((void)0, (volatile unsigned int _force )(a))。在定义了__CHECKER的时候先调用__chk_io_ptr检查该地址,否则__chk_io_ptr什么也不做,(volatile unsigned int _force )(a)就是返回地址为a处的值。
所以以下代码进行寄存器的设置,使GPIO口的工作模式为,输入、输出、中断等:
con = __raw_readl(base + 0x00);//从基地址对应的寄存器中取出值 con &= ~mask;//将我们要设置的相应位清零,其他位不变 con |= function;//对们要设置的相应位进行设置 __raw_writel(con, base + 0x00);//写回寄存器
mask = 3;
function = 0x01;
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT)通过这个函数名和参数起始我们也能看出他的作用:设置GPBCON寄存器,使得GPB0为OUTPUT,即输出。
GPB0对应GPBCON在0、1位,con &= ~mask即con &= ~3,j就是清除我们要设置的相应位,con |= function;对们要设置的相应位进行设置,con |= 0x01;就是把0、1位设置为01,即输出。所以与通过这个函数名和参数起始得出作用一致。
- linux内核中2410_gpio_cfgpin函数分析
- Linux内核中mktime()函数算法分析
- Linux内核中start_kernel函数的分析
- Linux内核中mktime()函数算法分析
- armv8(aarch64)linux内核中flush_dcache_all函数详细分析
- LINUX 内核中物理内存分配函数(kernel api)分析
- linux内核中打印栈回溯信息 - dump_stack()函数分析
- linux内核中打印栈回溯信息 - dump_stack()函数分析
- Linux内核0.11版本sched.c中sleep_on()函数分析
- linux内核schedule函数分析
- linux内核--wait_event_interruptible_timeout()函数分析
- Linux内核中sk_buff分析
- Linux内核中LIST_HEAD分析
- Linux内核中DMA分析
- Linux内核中GET_CURRENT()函数
- linux 内核中 mktime函数
- linux中内核延时函数
- linux内核分析之signal.c函数
- 总结:详细讲解MapReduce过程(整理补充)
- Java GC垃圾回收机制
- Tomcat在Linux上的安装与配置
- 汪国新监督员参加最高人民法院特约监督员工作座谈会
- Integer i2=100 与 Integer i3=100 的比较以及String实例的联想
- linux内核中2410_gpio_cfgpin函数分析
- 8.2学长讲解(数论入门)
- caffe中的layers
- 设计模式--如何学习设计模式
- 【自考】第一遍快速阅读C++程序设计
- 再谈快速排序
- 清华大学操作系统实验准备--挖坑
- linux中如何使用find命令查找文件
- 愉快玩耍GitHub