续前一篇文章
2、nrfx_gpiote_in_init
程序代码如下:
nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,nrfx_gpiote_in_config_t const * p_config,nrfx_gpiote_evt_handler_t evt_handler)
{NRFX_ASSERT(nrf_gpio_pin_present_check(pin));nrfx_err_t err_code = NRFX_SUCCESS;/* Only one GPIOTE channel can be assigned to one physical pin. */if (pin_in_use_by_gpiote(pin)){err_code = NRFX_ERROR_INVALID_STATE;}else{int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);if (channel != NO_CHANNELS){if (!p_config->skip_gpio_setup){if (p_config->is_watcher){nrf_gpio_cfg_watcher(pin);}else{nrf_gpio_cfg_input(pin, p_config->pull);}pin_configured_set(pin);}if (p_config->hi_accuracy){nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense);}else{m_cb.port_handlers_pins[channel - GPIOTE_CH_NUM] |= (p_config->sense) <<POLARITY_FIELD_POS;}}else{err_code = NRFX_ERROR_NO_MEM;}}NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));return err_code;
}
下面将详细解释 nrfx_gpiote_in_init 函数,
(1) nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,
nrfx_gpiote_in_config_t const * p_config,
nrfx_gpiote_evt_handler_t evt_handler);
• pin:要初始化的 GPIO 引脚编号,根据查询有如下信息:
typedef uint32_t nrfx_gpiote_pin_t;
nrfx_gpiote_pin_t 其实就是uint32_t的意思,是为了便于理解,才这样取了一个别名。
• p_config:指向 nrfx_gpiote_in_config_t 结构体的指针,该结构体包含了引脚的配置信息。
结构体定义如下 :
typedef struct
{nrf_gpiote_polarity_t sense; /**< Transition that triggers the interrupt. */nrf_gpio_pin_pull_t pull; /**< Pulling mode. */bool is_watcher : 1; /**< True when the input pin is tracking an output pin. */bool hi_accuracy : 1; /**< True when high accuracy (IN_EVENT) is used. */bool skip_gpio_setup : 1; /**< Do not change GPIO configuration */
} nrfx_gpiote_in_config_t;
其中nrf_gpiote_polarity_t类型是一个枚举类型,其定义如下:
typedef enum
{NRF_GPIOTE_POLARITY_LOTOHI = GPIOTE_CONFIG_POLARITY_LoToHi, ///< Low to high.NRF_GPIOTE_POLARITY_HITOLO = GPIOTE_CONFIG_POLARITY_HiToLo, ///< High to low.NRF_GPIOTE_POLARITY_TOGGLE = GPIOTE_CONFIG_POLARITY_Toggle ///< Toggle.
} nrf_gpiote_polarity_t;
其中nrf_gpio_pin_pull_t类型是一个枚举类型,其定义如下:
typedef enum
{NRF_GPIO_PIN_NOPULL = GPIO_PIN_CNF_PULL_Disabled, ///< Pin pull-up resistor disabled.NRF_GPIO_PIN_PULLDOWN = GPIO_PIN_CNF_PULL_Pulldown, ///< Pin pull-down resistor enabled.NRF_GPIO_PIN_PULLUP = GPIO_PIN_CNF_PULL_Pullup, ///< Pin pull-up resistor enabled.
} nrf_gpio_pin_pull_t;
• evt_handler:事件处理函数指针,当引脚状态发生变化时会调用此函数,该函数将单独作为一篇文章学习。
(2)NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
nrfx_err_t err_code = NRFX_SUCCESS;
• NRFX_ASSERT(nrf_gpio_pin_present_check(pin));:使用断言来确保指定的引脚 pin 是存在的。如果引脚不存在,程序会触发断言错误。
• nrfx_err_t err_code = NRFX_SUCCESS;
初始化错误码 err_code 为 NRFX_SUCCESS,表示初始状态下操作是成功的。
(3) /* Only one GPIOTE channel can be assigned to one physical pin. */
if (pin_in_use_by_gpiote(pin))
{
err_code = NRFX_ERROR_INVALID_STATE;
}
• 注释表明一个物理引脚只能分配一个 GPIOTE 通道。
• if (pin_in_use_by_gpiote(pin)):检查指定的引脚是否已经被 GPIOTE 使用。如果已经被使用,将错误码 err_code 设置为 NRFX_ERROR_INVALID_STATE。其中pin_in_use_by_gpiote函数定义如下 :
__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
{return (m_cb.pin_assignments[pin] >= 0);
}
(4) else
{
int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
if (channel != NO_CHANNELS)
{
• int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
尝试为指定的引脚分配一个 GPIOTE 通道。channel_port_alloc 函数会根据引脚编号、事件处理函数和高精度配置标志来分配通道,并返回分配的通道编号。
• if (channel != NO_CHANNELS):检查通道分配是否成功。如果成功,进入后续的配置步骤。
(5) if (!p_config->skip_gpio_setup)
{
if (p_config->is_watcher)
{
nrf_gpio_cfg_watcher(pin);
}
else
{
nrf_gpio_cfg_input(pin, p_config->pull);
}
pin_configured_set(pin);
}
• if (!p_config->skip_gpio_setup):检查是否跳过 GPIO 引脚的设置。如果不跳过,继续进行引脚配置。
if (p_config->is_watcher):如果 is_watcher 标志为真,调用 nrf_gpio_cfg_watcher(pin) 函数将引脚配置为观察者模式。 ◦ else:否则,调用 nrf_gpio_cfg_input(pin, p_config->pull) 函数将引脚配置为输入模式,并设置上拉或下拉电阻。
• pin_configured_set(pin);:标记该引脚已经被配置。
(6) if (p_config->hi_accuracy)
{
nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense);
}
else
{
m_cb.port_handlers_pins[channel - GPIOTE_CH_NUM] |= (p_config->sense) <<
POLARITY_FIELD_POS;
}
}
• if (p_config->hi_accuracy):检查是否启用高精度模式。 ◦ 如果启用,调用 nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense) 函数配置 GPIOTE 事件,指定通道、引脚和触发条件。 ◦ 如果未启用,将触发条件 p_config->sense 左移 POLARITY_FIELD_POS 位,并与 m_cb.port_handlers_pins[channel - GPIOTE_CH_NUM] 进行按位或操作,更新端口处理引脚的状态。
(7) else
{
err_code = NRFX_ERROR_NO_MEM;
}
}
• 如果通道分配失败(channel == NO_CHANNELS),将错误码 err_code 设置为 NRFX_ERROR_NO_MEM,表示没有可用的通道资源。
(8)NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
return err_code;
• NRFX_LOG_INFO:记录日志信息,包含函数名和错误码的字符串表示。
• return err_code;:返回错误码,告知调用者初始化操作的结果。
总结 nrfx_gpiote_in_init 函数的主要功能是为指定的 GPIO 引脚分配一个 GPIOTE 通道,并根据配置信息对引脚进行初始化。如果引脚已经被使用或没有可用的通道资源,会返回相应的错误码。