GPIO_API

本文详细介绍了GPIO请求、配置及中断处理的相关API函数,包括gpio_request、gpio_free、gpio_direction_input等,以及如何通过这些函数实现GPIO的输入输出配置、中断触发等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include // 标准 GPIO_API

   intgpio_request(unsigned gpio, const char *label);

   获得并占有 GPIO port 的使用权,由参数 gpio 指定具体 port,非空的lables指针有助于诊断。主要是告诉内核这地址被占用了。当其它地方调用同一地址的gpio_request就会报告错误,该地址已被申请。在/proc/mem应该会有地址占用表描述。

这种用法的保护作用前提是大家都遵守先申请再访问,有一个地方没遵守这个规则,这功能就失效了。好比进程互斥,必需大家在访问临界资源的时候都得先获取锁一样,其中一个没遵守约定,代码就废了。

例1:void gpio_free(unsignedgpio);//释放 GPIO port 的使用权,由gpio 指定具体 port。

例2:gpio_free(RK29_PIN0_PA0);//释放GPIO0_A0

int gpio_direction_input(unsignedgpio);//返回0

例3:gpio_direction_input (RK29_PIN0_PA0);//把GPIO0_A0设置为输入

int gpio_direction_output(unsigned gpio, intvalue);//返回0

       例4:gpio_direction_output(RK29_PIN0_PA0,GPIO_LOW);//把GPIO0_A0设置为输出口,且其电平拉低。   int gpio_get_value(unsignedgpio);//返回value

       例5:ret = gpio_get_value (RK29_PIN0_PA0);//读取GPIO0_A0的电平,并赋值给变量ret。

void gpio_set_value(unsigned gpio, intvalue);

例6:gpio_set_value (RK29_PIN0_PA0, GPIO_HIGH);//设置RK29_PIN0_PA0电平为高。

       int gpio_pull_updown(unsigned gpio,unsigned value);

       value = 0, normal

       value = 1, pull up

       value = 2, pull down

       例7:gpio_pull_updown(RK29_PIN0_PA0,1)上拉

      int gpio_cansleep(unsigned gpio);

支持这种gpio的平台为了通过在这个函数中返回非零来区分其它类型的gpio(需要一个已经被 gpio_request申请的gpio号)为了访问这些端口,定义了另一组函数接口:

      int gpio_get_value_cansleep(unsigned gpio);

      voidgpio_set_value_cansleep(unsigned gpio, int value);

       只能在允许睡眠的上下文中访问这些端口,比如线程化的中断中,

      static inline int gpio_is_valid(intnumber)//判断GPIO是否有效,有效返回0

      int gpio_export(unsigned gpio, booldirection_may_change);//返回0成功

       voidgpio_unexport();  //返回0成功

       intgpio_export_link(struct device *dev, const char *name, unsignedgpio) 

//创建到导出GPIO的 sysfs link ,第一个参数是在哪个dev下创建,第二个是参数名字,第三个是gpio编号 

 

中断部分的API:

  static inline intgpio_to_irq(unsigned gpio)

    例8:gpioToIrq = gpio_to_irq (RK29_PIN0_PA0);//把GPIO0_A0的PIN值转换为相应的IRQ值,并赋值给变量gpioToIrq。

  gpio_to_irq()返回的中断编号可以传给request_irq()和free_irq()。

  irq_to_gpio()返回的gpio编号通常用来调用gpio_get_value(),比如在沿触发的中断中获取引脚的状态。有些平台不支持这种映射,应该避免调用映射函数

   staticinline int __must_check request_irq(unsigned int irq, irq_handler_thandler, unsigned long flags, const char *name, void*dev);

范例:irq是要申请的硬件中断号;handler是向系统登记的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev参数将被传递; flags是中断处理的属性,若设置SA_INTERRUPT,标明中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置SA_SHIRQ,则多个设备共享中断,*dev在中断共享时会用到,一般设置为这个设备的device结构本身或者NULL。 当flags发生时,触发中断。

      例9:static irqreturn_t PA0IntHandler(int irq, void*dev_id)

{

      printk(KERN_INFO "PA0IntHandler:irq=%d",irq);

   return IRQ_HANDLED;

}

void main(void)

{

// 把GPIO0_A0的PIN值转换为相应的IRQ值,并赋值给变量gpioToIrq。

unsigned long req_flags =IRQF_TRIGGER_RISING;

int gpioToIrq = gpio_to_irq(RK29_PIN0_PA0);

If(gpioToIrq != -1){

//注册PA0IntHandler中断处理函数,中断号是RK29_PIN0_PA0,设置为上升沿触发

   request_irq(gpioToIrq, PA0IntHandler,req_flags, "PA0_test",NULL);

   }

}

     void free_irq(unsigned int irq, void*dev_id)//释放中断

irq: 释放的中断号  dev_id: 释放的dev_id

例10: free_irq(gpio_to_irq(RK29_PIN0_PA0),NULL);//释放GPIO0_A0中断。

    int set_irq_type(unsigned int irq, unsigned inttype)

irq: 指定的中断号type  : 设置的中断类型

例11:set_irq_type(gpio_to_irq(RK2818_PIN_PA0),IRQF_TRIGGER_LOW);//设置GPIO0_A0中断为低电平触发

     void disable_irq_nosync(unsigned intirq)

强行关闭指定中断,不会等待当前中断处理程序执行完毕。,立即返回

例12:disable_irq_nosync(gpio_to_irq(RK29_PIN0_PA0));//关闭GPIO0_A0中断。

     void disable_irq(unsigned intirq)

将关闭硬件中断并等待(可能有的)中断处理完成才返回。

例13:disable_irq(gpio_to_irq(RK29_PIN0_PA0));//关闭GPIO0_A0中断。

     void enable_irq(unsigned intirq)

使能一个指定的中断

例14: enable_irq(gpio_to_irq(RK29_PIN0_PA0));//使能GPIO0_A0中断。

注意:使能IRQ和不使能IRQ应该配对使用。

   若调用enable_irq之前,并未关闭指定中断(如调用disable_irq_nosync 关闭指定中断),

   则调用enable_irq会报警告(WARNING: at kernel/irq/manage.c:274enable_irq+0x48/0x68();Unbalanced enable for IRQ 58),此为正常现象。

    int enable_irq_wake(unsigned intirq)//返回0成功

    int disable_irq_wake(unsigned int irq)//返回0成功

  要enable和disable的次数相同

例15:static inline intenable_irq_wake(unsigned int irq)

{returnset_irq_wake(irq, 1);

}

static inline intdisable_irq_wake(unsigned int irq)

{

return set_irq_wake(irq,0);

}

  voidrk29_gpio_suspend(void)// 让GPIO进入省电睡眠模式

调用此函数,是否会让GPIO进入省电睡眠模式,与enable_irq_wake和disable_irq_wake函数相关,

例16:如果先调用了enable_irq_wake(gpio_to_irq(RK29_PIN0_PA0)),则即使调用了

  voidrk29_gpio_resume(void)//唤醒GPIO

#ifdef __cplusplus extern "C" { #endif /** * @defgroup gpio_apis GPIO API * @ingroup driver_apis * @{ */ /** * @brief GPIO Examples * * If GPIO PIN number > 32, the binding device name is CONFIG_GPIO_A_NAME. * If GPIO PIN number > 32 and < 64, the binding device name is CONFIG_GPIO_B_NAME. * If GPIO PIN number >64 and < GPIO_MAX_PIN_NUM, the binding device name is CONFIG_GPIO_C_NAME. * * @code * * #include <drivers/gpio.h> * * // 1. GPIO output function example * uint8_t gpio_out_pin = 6, gpio_out_level = 1; * const char *gpio_dev_name = CONFIG_GPIO_A_NAME; * int ret; * * // If gpio_flags_t masks with GPIO_PULL_UP/GPIO_PULL_DOWN, the GPIO pin state will be pulled up/down. * // If gpio_flags_t masks with GPIO_INT_DEBOUNCE, the GPIO pin will enable schmitt function. * // If gpio_flags_t masks with GPIO_OUTPUT | (GPIO_OUTPUT_INIT_HIGH/GPIO_OUTPUT_INIT_LOW), the GPIO pin will output * // high/low state at initialization. * gpio_flags_t = GPIO_OUTPUT; * * const struct device *gpio_dev = device_get_binding(gpio_dev_name); * if (!gpio_dev) { * printk("failed to bind device %s\n", gpio_dev_name); * return -ENODEV; * } * * ret = gpio_pin_configure(gpio_dev, gpio_out_pin, GPIO_OUTPUT); * if (ret) { * printk("failed to configure gpio:%d output\n", gpio_out_pin); * return ret; * } * * // If gpio_out_level = 1 GPIO will output high level, and when gpio_out_level = 0 will output low level. * gpio_pin_set(gpio_dev, gpio_out_pin, gpio_out_level); * * // 2. GPIO input function example * uint8_t gpio_in_pin = 6; * const char *gpio_dev_name = CONFIG_GPIO_A_NAME; * gpio_pin_t gpio_in_level; * * const struct device *gpio_dev = device_get_binding(gpio_dev_name); * if (!gpio_dev) { * printk("failed to bind device %s\n", gpio_dev_name); * return -ENODEV; * } * * ret = gpio_pin_configure(gpio_dev, gpio_in_pin, GPIO_INPUT); * if (ret) { * printk("failed to configure gpio:%d input\n", gpio_in_pin); * return ret; * } * * // Get GPIO input voltage level. * gpio_pin_get(gpio_dev, gpio_in_pin, &gpio_in_level); * * // 3. GPIO interrupt function example * uint8_t gpio_irq_pin = 6; * const char *gpio_dev_name = CONFIG_GPIO_A_NAME; * struct gpio_callback gpio_irq_cb; * * static void gpio_irq_callback(const struct device *port, * struct gpio_callback *cb, * uint32_t pins) { * printk("GPIO IRQ callback\n"); * } * * const struct device *gpio_dev = device_get_binding(gpio_dev_name); * if (!gpio_dev) { * printk("failed to bind device %s\n", gpio_dev_name); * return -ENODEV; * } * * gpio_pin_configure(gpio_dev, gpio_irq_pin, * GPIO_INPUT | GPIO_INT_EDGE_TO_INACTIVE | GPIO_ACTIVE_HIGH); * * gpio_init_callback(&gpio_irq_cb, gpio_irq_callback, BIT(gpio_irq_pin)); * * gpio_add_callback(gpio_dev, &gpio_irq_cb); * * @endcode */ /** * @} end defgroup gpio_apis */ /** * @brief GPIO Driver APIs * @defgroup gpio_interface GPIO Driver APIs * @ingroup io_interfaces * @{ */ /** * @name GPIO input/output configuration flags * @{ */ /** Enables pin as input. */ #define GPIO_INPUT (1U << 8) /** Enables pin as output, no change to the output state. */ #define GPIO_OUTPUT (1U << 9) /** Disables pin for both input and output. */ #define GPIO_DISCONNECTED 0 /** @cond INTERNAL_HIDDEN */ /* Initializes output to a low state. */ #define GPIO_OUTPUT_INIT_LOW (1U << 10) /* Initializes output to a high state. */ #define GPIO_OUTPUT_INIT_HIGH (1U << 11) /* Initializes output based on logic level */ #define GPIO_OUTPUT_INIT_LOGICAL (1U << 12) /** @endcond */ /** Configures GPIO pin as output and initializes it to a low state. */ #define GPIO_OUTPUT_LOW (GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW) /** Configures GPIO pin as output and initializes it to a high state. */ #define GPIO_OUTPUT_HIGH (GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH) /** Configures GPIO pin as output and initializes it to a logic 0. */ #define GPIO_OUTPUT_INACTIVE (GPIO_OUTPUT | \ GPIO_OUTPUT_INIT_LOW | \ GPIO_OUTPUT_INIT_LOGICAL) /** Configures GPIO pin as output and initializes it to a logic 1. */ #define GPIO_OUTPUT_ACTIVE (GPIO_OUTPUT | \ GPIO_OUTPUT_INIT_HIGH | \ GPIO_OUTPUT_INIT_LOGICAL) /** GPIO pin is active (has logical value '1') in low state. */ #define GPIO_ACTIVE_LOW (1 << 0) /** GPIO pin is active (has logical value '1') in high state. */ #define GPIO_ACTIVE_HIGH (0 << 0) /* Configures GPIO output in single-ended mode (open drain or open source). */ #define GPIO_SINGLE_ENDED (1 << 1) /* Configures GPIO output in push-pull mode */ #define GPIO_PUSH_PULL (0 << 1) /* Indicates single ended open drain mode (wired AND). */ #define GPIO_LINE_OPEN_DRAIN (1 << 2) /* Indicates single ended open source mode (wired OR). */ #define GPIO_LINE_OPEN_SOURCE (0 << 2) /** @endcond */ /** Configures GPIO output in open drain mode (wired AND). * * @note 'Open Drain' mode also known as 'Open Collector' is an output * configuration which behaves like a switch that is either connected to ground * or disconnected. */ #define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN) /** Configures GPIO output in open source mode (wired OR). * * @note 'Open Source' is a term used by software engineers to describe output * mode opposite to 'Open Drain'. It behaves like a switch that is either * connected to power supply or disconnected. There exist no corresponding * hardware schematic and the term is generally unknown to hardware engineers. */ #define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE) /** Enables GPIO pin pull-up. */ #define GPIO_PULL_UP (1 << 4) /** Enable GPIO pin pull-down. */ #define GPIO_PULL_DOWN (1 << 5) /** @} */ /** * @name GPIO interrupt configuration flags * The `GPIO_INT_*` flags are used to specify how input GPIO pins will trigger * interrupts. The interrupts can be sensitive to pin physical or logical level. * Interrupts sensitive to pin logical level take into account GPIO_ACTIVE_LOW * flag. If a pin was configured as Active Low, physical level low will be * considered as logical level 1 (an active state), physical level high will * be considered as logical level 0 (an inactive state). * @{ */ /** Disables GPIO pin interrupt. */ #define GPIO_INT_DISABLE (1U << 13) /** @cond INTERNAL_HIDDEN */ /* Enables GPIO pin interrupt. */ #define GPIO_INT_ENABLE (1U << 14) /* GPIO interrupt is sensitive to logical levels. * * This is a component flag that should be combined with other * `GPIO_INT_*` flags to produce a meaningful configuration. */ #define GPIO_INT_LEVELS_LOGICAL (1U << 15) /* GPIO interrupt is edge sensitive. * * Note: by default interrupts are level sensitive. * * This is a component flag that should be combined with other * `GPIO_INT_*` flags to produce a meaningful configuration. */ #define GPIO_INT_EDGE (1U << 16) /* Trigger detection when input state is (or transitions to) physical low or * logical 0 level. * * This is a component flag that should be combined with other * `GPIO_INT_*` flags to produce a meaningful configuration. */ #define GPIO_INT_LOW_0 (1U << 17) /* Trigger detection on input state is (or transitions to) physical high or * logical 1 level. * * This is a component flag that should be combined with other * `GPIO_INT_*` flags to produce a meaningful configuration. */ #define GPIO_INT_HIGH_1 (1U << 18) /** @endcond */ /** Configures GPIO interrupt to be triggered on pin rising edge and enables it. */ #define GPIO_INT_EDGE_RISING (GPIO_INT_ENABLE | \ GPIO_INT_EDGE | \ GPIO_INT_HIGH_1) /** Configures GPIO interrupt to be triggered on pin falling edge and enables * it. */ #define GPIO_INT_EDGE_FALLING (GPIO_INT_ENABLE | \ GPIO_INT_EDGE | \ GPIO_INT_LOW_0) /** Configures GPIO interrupt to be triggered on pin rising or falling edge and * enables it. */ #define GPIO_INT_EDGE_BOTH (GPIO_INT_ENABLE | \ GPIO_INT_EDGE | \ GPIO_INT_LOW_0 | \ GPIO_INT_HIGH_1) /** Configures GPIO interrupt to be triggered on pin physical level low and * enables it. */ #define GPIO_INT_LEVEL_LOW (GPIO_INT_ENABLE | \ GPIO_INT_LOW_0) /** Configures GPIO interrupt to be triggered on pin physical level high and * enables it. */ #define GPIO_INT_LEVEL_HIGH (GPIO_INT_ENABLE | \ GPIO_INT_HIGH_1) /** Configures GPIO interrupt to be triggered on pin state change to logical * level 0 and enables it. */ #define GPIO_INT_EDGE_TO_INACTIVE (GPIO_INT_ENABLE | \ GPIO_INT_LEVELS_LOGICAL | \ GPIO_INT_EDGE | \ GPIO_INT_LOW_0) /** Configures GPIO interrupt to be triggered on pin state change to logical * level 1 and enables it. */ #define GPIO_INT_EDGE_TO_ACTIVE (GPIO_INT_ENABLE | \ GPIO_INT_LEVELS_LOGICAL | \ GPIO_INT_EDGE | \ GPIO_INT_HIGH_1) /** Configures GPIO interrupt to be triggered on pin logical level 0 and enables * it. */ #define GPIO_INT_LEVEL_INACTIVE (GPIO_INT_ENABLE | \ GPIO_INT_LEVELS_LOGICAL | \ GPIO_INT_LOW_0) /** Configures GPIO interrupt to be triggered on pin logical level 1 and enables * it. */ #define GPIO_INT_LEVEL_ACTIVE (GPIO_INT_ENABLE | \ GPIO_INT_LEVELS_LOGICAL | \ GPIO_INT_HIGH_1) /** @} */ /** Enable GPIO pin debounce. * * @note Drivers that do not support a debounce feature should ignore * this flag rather than rejecting the configuration with -ENOTSUP. */ #define GPIO_INT_DEBOUNCE (1U << 19) /** * @name GPIO drive strength flags * The `GPIO_DS_*` flags are used with `gpio_pin_configure` to specify the drive * strength configuration of a GPIO pin. * * The drive strength of individual pins can be configured * independently for when the pin output is low and high. * * The `GPIO_DS_*_LOW` enumerations define the drive strength of a pin * when output is low. * The `GPIO_DS_*_HIGH` enumerations define the drive strength of a pin * when output is high. * * The interface supports two different drive strengths: * `DFLT` - The lowest drive strength supported by the HW * `ALT` - The highest drive strength supported by the HW * * On hardware that supports only one standard drive strength, both * `DFLT` and `ALT` have the same behavior. * @{ */ /** @cond INTERNAL_HIDDEN */ #define GPIO_DS_LOW_POS 20 #define GPIO_DS_LOW_MASK (0x3U << GPIO_DS_LOW_POS) /** @endcond */ /** Default drive strength standard when GPIO pin output is low. */ #define GPIO_DS_DFLT_LOW (0x0U << GPIO_DS_LOW_POS) /** Alternative drive strength when GPIO pin output is low. * For hardware that does not support configurable drive strength * use the default drive strength. */ #define GPIO_DS_ALT_LOW (0x1U << GPIO_DS_LOW_POS) /** @cond INTERNAL_HIDDEN */ #define GPIO_DS_HIGH_POS 22 #define GPIO_DS_HIGH_MASK (0x3U << GPIO_DS_HIGH_POS) /** @endcond */ /** Default drive strength when GPIO pin output is high. */ #define GPIO_DS_DFLT_HIGH (0x0U << GPIO_DS_HIGH_POS) /** Alternative drive strength when GPIO pin output is high. * For hardware that does not support configurable drive strengths * use the default drive strength. */ #define GPIO_DS_ALT_HIGH (0x1U << GPIO_DS_HIGH_POS) /** @} */ /** @cond INTERNAL_HIDDEN */ #define GPIO_DIR_MASK (GPIO_INPUT | GPIO_OUTPUT) /** @endcond */
最新发布
06-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值