原创
友善之臂中的mini2440 GPIO相关函数操作
在mini2440的驱动中,如果要对GPIO进行相关功能的配置和数据的写入获取,需要直接对相应的寄存器进行操作,其中使用的函数有:
mini2440中端口号的形成可以使用下边的宏:
S3C2410_GPn(m),获得n组io的第m个端口
例如:
S3C2410_GPB(5);使用宏可以很方便的进行操作。
在S3C2440中的GPIO通常有第二功能,在配置IO口功能的时候需要使用如下的宏定义:
# define S3C2410_GPIO_LEAVE ( 0xFFFFFFFF) # define S3C2410_GPIO_INPUT ( 0xFFFFFFF0) /* not available on A */ # define S3C2410_GPIO_OUTPUT ( 0xFFFFFFF1) # define S3C2410_GPIO_IRQ ( 0xFFFFFFF2) /* not available for all */ # define S3C2410_GPIO_SFN2 ( 0xFFFFFFF2) /* bank A => addr/cs/nand */ # define S3C2410_GPIO_SFN3 ( 0xFFFFFFF3) /* not available on A */
上述宏要注意数据内容,S3C2410_GPIO功能配置在各个IO是不一样的,有些IO口使用一位寄存器来配置,而有些寄存器使用2位寄存器来设置,但使用上述宏定义之后,就可以很方便的配置IO,而不用计较到底是2位还是1位寄存器。
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; } }
s3c2410_gpio_setpin(端口号,数据) 对相应的端口置位
void s3c2410_gpio_setpin( unsigned int pin, unsigned int to) { void __iomem * base = S3C24XX_GPIO_BASE( pin) ; unsigned long offs = S3C2410_GPIO_OFFSET( pin) ; unsigned long flags; unsigned long dat; local_irq_save( flags) ; dat = __raw_readl( base + 0x04) ; dat & = ~ ( 1 < < offs) ; dat | = to < < offs; __raw_writel( dat, base + 0x04) ; local_irq_restore( flags) ; }
s3c2410_gpio_setpin(端口号) 会的相应端口的数据,通过函数返回值的形式获得。
unsigned int s3c2410_gpio_getpin( unsigned int pin) { void __iomem * base = S3C24XX_GPIO_BASE( pin) ; unsigned long offs = S3C2410_GPIO_OFFSET( pin) ; return __raw_readl( base + 0x04) & ( 1< < offs) ; }
例如:
# include < linux/ miscdevice. h> # include < linux/ delay. h> # include < asm / irq. h> # include < mach/ regs- gpio. h> # include < mach/ hardware. h> # include < linux/ kernel. h> # include < linux/ module. h> # include < linux/ init. h> # include < linux/ mm. h> # include < linux/ fs. h> # include < linux/ types. h> # include < linux/ delay. h> # include < linux/ moduleparam. h> # include < linux/ slab. h> # include < linux/ errno . h> # include < linux/ ioctl. h> # include < linux/ cdev. h> # include < linux/ string . h> # include < linux/ list . h> # include < linux/ pci. h> # include < linux/ gpio. h> # include < asm / uaccess. h> # include < asm / atomic. h> # include < asm / unistd. h> # define DEVICE_NAME "leds"
// 要使用的IO口static unsigned long led_table [ ] = { S3C2410_GPB( 5) , S3C2410_GPB( 6) , S3C2410_GPB( 7) , S3C2410_GPB( 8) , } ;
// 相应IO口功能的配置 static unsigned int led_cfg_table [ ] = { S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, } ; static int sbc2440_leds_ioctl( struct inode * inode, struct file * file , unsigned int cmd, unsigned long arg ) { switch ( cmd) { case 0: case 1: if ( arg > 4) { return - EINVAL; }
// IO口赋值 s3c2410_gpio_setpin( led_table[ arg ] , ! cmd) ; return 0; default : return - EINVAL; } } static struct file_operations dev_fops = { . owner = THIS_MODULE, . ioctl = sbc2440_leds_ioctl, } ; static struct miscdevice misc = { . minor = MISC_DYNAMIC_MINOR, . name = DEVICE_NAME, . fops = & dev_fops, } ; static int __init dev_init( void ) { int ret; int i; for ( i = 0; i < 4; i+ + ) {
//设置IO口功能 s3c2410_gpio_cfgpin( led_table[ i] , led_cfg_table[ i] ) ; // 对应IO口赋值为0
s3c2410_gpio_setpin( led_table[ i] , 0) ; } ret = misc_register( & misc) ; printk ( DEVICE_NAME"\tinitialized\n" ) ; return ret; } static void __exit dev_exit( void ) { misc_deregister( & misc) ; } module_init( dev_init) ; module_exit( dev_exit) ; MODULE_LICENSE( "GPL" ) ; MODULE_AUTHOR( "FriendlyARM Inc." ) ;
文章评论(0条评论)
登录后参与讨论