送给从STM32库或者其他单片机爬过来的熊孩纸
操作GPIO还是这个顺序:
1:开时钟(linux不用管)
2:设置属性
3:设置方向
4:看是否需要设置上下拉
我这个版本是exynos5260平台的,常规IO操作方式如下
通常在配置一个GPIO口时,首先通过gpio_request函数申请GPIO口,再通过s3c_gpio_cfgpin、s3c_gpio_setpull、gpio_set_value函数配置GPIO口,在不用时通过gpio_free函数释放GPIO口。
相关源码路径:
/*
kernel/drivers/gpio/gpiolib.c
kernel/arm/alpha/include/asm/gpio.h(和gpiolib的内容直接关联,由于三星源码版本,所以路径可能有差异)
kernel/drivers/gpio/gpio-samsung.c(所有API的source都在这里)
kernel/arch/arm/mach-exynos/include/mach/gpio.h
kernel/arch/arm/plat-samsung/include/plat/gpio-cfg.h
(老版本是linux/arch/arm/plat-s3c/include/plat/gpio-cfg.h,所有要用的API都集中在这个文件,还带参数宏,有故事的同学直接戳这个文件即可)
*/
内核中已经将GPIO的相关操作做好了,我们只需要调用即可。这里只给出几种常用的操作函数的使用方法,具体实现过程可以琢磨源码(kernel/drivers/gpio/gpio-samsung.c)。
一:设置GPIO上下拉属性的函数
// kernel/drivers/gpio/gpio-samsung.c
int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
{
struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
int offset, ret;
if (!chip)
return -EINVAL;
offset = pin - chip->chip.base;
ret = samsung_gpio_do_setpull(chip, offset, pull);
return ret;
}
EXPORT_SYMBOL(s3c_gpio_setpull);
第一个传入参数表示需要设置的管脚编号,第二个传入参数表示上下拉的属性。每一个GPIO的管脚编号都可以通过宏来指定,这些宏都在kernel/arch/arm/mach-exynos/include/mach/gpio.h中定义。按照5260datasheet的寄存器介绍,GPIO可以配置成none,上拉或下拉三种状态,对应宏定义如下:
//kernel/arch/arm/plat-samsung/include/plat/gpio-cfg.h
/* Define values for the pull-{up,down} available for each gpio pin.
*
* These values control the state of the weak pull-{up,down} resistors
* available on most pins on the S3C series. Not all chips support both
* up or down settings, and it may be dependent on the chip that is being
* used to whether the particular mode is available.
*/
#define S3C_GPIO_PULL_NONE ((__force samsung_gpio_pull_t)0x00)
#define S3C_GPIO_PULL_DOWN ((__force samsung_gpio_pull_t)0x01)
#define S3C_GPIO_PULL_UP ((__force samsung_gpio_pull_t)0x03)
比如设置GPX0-1为上拉:
s3c_gpio_setpull(EXYNOS5260_GPX0(1), S3C_GPIO_PULL_UP);
二:设置GPIO功能属性的函数
// kernel/drivers/gpio/gpio-samsung.c
int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
{
struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
int offset;
int ret;
if (!chip)
return -EINVAL;
offset = pin - chip->chip.base;
ret = samsung_gpio_do_setcfg(chip, offset, config);
return ret;
}
EXPORT_SYMBOL(s3c_gpio_cfgpin);
第一个传入参数表示管脚编号,第二个传入参数表示配置信息,如下宏可以表述管脚的配置状态:
#define S3C_GPIO_SPECIAL_MARK (0xfffffff0)
#define S3C_GPIO_SPECIAL(x) (S3C_GPIO_SPECIAL_MARK | (x))
/* Defines for generic pin configurations */
#define S3C_GPIO_INPUT (S3C_GPIO_SPECIAL(0))
#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1))
#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x))
#define samsung_gpio_is_cfg_special(_cfg) \
(((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)
S3C_GPIO_SFN(0)或S3C_GPIO_INPUT表示将管脚设置为输入,S3C_GPIO_SFN(1)或S3C_GPIO_OUTPUT表示将管脚设置为输出,将管脚设置为其他复合的功能时,需参考5260芯片用户手册的寄存器参数表,结合S3C_GPIO_SFN宏使用。
以下程序表示将GPX0(1)管脚设置为输出:
s3c_gpio_cfgpin(EXYNOS5260_GPX0(1), S3C_GPIO_SFN(1));
当GPIO被设置为输出时,设置其电平状态属性的函数清单如下&