Diff
checker
텍스트
텍스트
이미지
문서
Excel
폴더
Legal
Enterprise
데스크톱
요금제
로그인
데스크톱 앱 다운로드
텍스트 비교
두 텍스트 파일의 차이점을 찾아보세요
도구
기록
실시간 편집
변경 없는 행 숨기기
줄바꿈 비활성화
레이아웃
나란히 보기
합쳐 보기
비교 단위
스마트
단어
글자
구문 강조
언어 선택
제외
텍스트 변환
첫 변경으로
수정
Diffchecker Desktop
가장 안전하게 Diffchecker를 사용하는 방법. 데스크톱 앱을 사용하면 비교 데이터가 외부로 전송되지 않습니다!
데스크톱 앱 받기
Untitled diff
생성일
11년 전
비교 결과 만료 없음
초기화
내보내기
공유
설명
12 삭제
행
총
삭제
글자
총
삭제
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
523 행
복사
103 추가
행
총
추가
글자
총
추가
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
613 행
복사
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
*
*
* The information contained herein is property of Nordic Semiconductor ASA.
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
*
* Licensees are granted free, non-transferable use of the information. NO
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
* the file.
*
*
*/
*/
#include "nrf_drv_gpiote.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_common.h"
#include "nrf_drv_common.h"
#include "nrf_drv_config.h"
#include "nrf_drv_config.h"
#include "app_util_platform.h"
#include "app_util_platform.h"
#include "nrf_assert.h"
#include "nrf_assert.h"
#define FORBIDDEN_HANDLER_ADDRESS ((nrf_drv_gpiote_evt_handler_t)UINT32_MAX)
#define FORBIDDEN_HANDLER_ADDRESS ((nrf_drv_gpiote_evt_handler_t)UINT32_MAX)
#define PIN_NOT_USED (-1)
#define PIN_NOT_USED (-1)
#define PIN_USED (-2)
#define PIN_USED (-2)
#define NO_CHANNELS (-1)
#define NO_CHANNELS (-1)
#define SENSE_FIELD_POS (6)
#define SENSE_FIELD_POS (6)
#define SENSE_FIELD_MASK (0xC0)
#define SENSE_FIELD_MASK (0xC0)
//lint -save -e661
//lint -save -e661
typedef struct
typedef struct
{
{
nrf_drv_state_t state;
nrf_drv_state_t state;
nrf_drv_gpiote_evt_handler_t handlers[NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
nrf_drv_gpiote_evt_handler_t handlers[NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
int8_t pin_assignments[NUMBER_OF_PINS];
int8_t pin_assignments[NUMBER_OF_PINS];
int8_t handlers_to_pins[GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
int8_t handlers_to_pins[GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
} control_block_t;
} control_block_t;
static control_block_t m_cb;
static control_block_t m_cb;
복사
복사됨
복사
복사됨
typedef void (*app_gpiote_event_handler_t)(uint32_t event_pins_low_to_high,
uint32_t event_pins_high_to_low);
/**@brief GPIOTE user type. */
typedef struct
{
uint32_t pins_mask; /**< Mask defining which pins user wants to monitor. */
uint32_t pins_low_to_high_mask; /**< Mask defining which pins will generate events to this user when toggling low->high. */
uint32_t pins_high_to_low_mask; /**< Mask defining which pins will generate events to this user when toggling high->low. */
uint32_t sense_high_pins; /**< Mask defining which pins are configured to generate GPIOTE interrupt on transition to high level. */
app_gpiote_event_handler_t event_handler; /**< Pointer to function to be executed when an event occurs. */
} gpiote_user_t;
extern uint32_t m_enabled_users_mask; /**< Mask for tracking which users are enabled. */
extern uint8_t m_user_array_size; /**< Size of user array. */
extern uint8_t m_user_count; /**< Number of registered users. */
extern gpiote_user_t * mp_users; /**< Array of GPIOTE users. */
__STATIC_INLINE bool pin_in_use(uint32_t pin)
__STATIC_INLINE bool pin_in_use(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] != PIN_NOT_USED) ? true : false;
return (m_cb.pin_assignments[pin] != PIN_NOT_USED) ? true : false;
}
}
__STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin)
__STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] == PIN_USED) ? true : false;
return (m_cb.pin_assignments[pin] == PIN_USED) ? true : false;
}
}
__STATIC_INLINE bool pin_in_use_by_te(uint32_t pin)
__STATIC_INLINE bool pin_in_use_by_te(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < NUMBER_OF_GPIO_TE) ? true : false;
return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < NUMBER_OF_GPIO_TE) ? true : false;
}
}
__STATIC_INLINE bool pin_in_use_by_port(uint32_t pin)
__STATIC_INLINE bool pin_in_use_by_port(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] >= NUMBER_OF_GPIO_TE) ? true : false;
return (m_cb.pin_assignments[pin] >= NUMBER_OF_GPIO_TE) ? true : false;
}
}
__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
{
{
return (m_cb.pin_assignments[pin] >= 0) ? true : false;
return (m_cb.pin_assignments[pin] >= 0) ? true : false;
}
}
__STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin,
__STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin,
uint32_t channel_id,
uint32_t channel_id,
nrf_drv_gpiote_evt_handler_t handler,
nrf_drv_gpiote_evt_handler_t handler,
bool is_channel)
bool is_channel)
{
{
m_cb.pin_assignments[pin] = channel_id;
m_cb.pin_assignments[pin] = channel_id;
m_cb.handlers[channel_id] = handler;
m_cb.handlers[channel_id] = handler;
if (!is_channel)
if (!is_channel)
{
{
m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)pin;
m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)pin;
}
}
}
}
__STATIC_INLINE void pin_in_use_set(uint32_t pin)
__STATIC_INLINE void pin_in_use_set(uint32_t pin)
{
{
m_cb.pin_assignments[pin] = PIN_USED;
m_cb.pin_assignments[pin] = PIN_USED;
}
}
__STATIC_INLINE void pin_in_use_clear(uint32_t pin)
__STATIC_INLINE void pin_in_use_clear(uint32_t pin)
{
{
m_cb.pin_assignments[pin] = PIN_NOT_USED;
m_cb.pin_assignments[pin] = PIN_NOT_USED;
}
}
__STATIC_INLINE int8_t channel_port_get(uint32_t pin)
__STATIC_INLINE int8_t channel_port_get(uint32_t pin)
{
{
return m_cb.pin_assignments[pin];
return m_cb.pin_assignments[pin];
}
}
__STATIC_INLINE uint8_t pin_from_port_get(uint32_t port_channel)
__STATIC_INLINE uint8_t pin_from_port_get(uint32_t port_channel)
{
{
return m_cb.handlers_to_pins[port_channel];
return m_cb.handlers_to_pins[port_channel];
}
}
__STATIC_INLINE nrf_drv_gpiote_evt_handler_t channel_handler_get(uint32_t channel)
__STATIC_INLINE nrf_drv_gpiote_evt_handler_t channel_handler_get(uint32_t channel)
{
{
return m_cb.handlers[channel];
return m_cb.handlers[channel];
}
}
복사
복사됨
복사
복사됨
void sense_level_toggle(gpiote_user_t * p_user, uint32_t pins);
void sense_level_disable(uint32_t pins);
static int8_t channel_port_alloc(uint32_t pin,nrf_drv_gpiote_evt_handler_t handler, bool channel)
static int8_t channel_port_alloc(uint32_t pin,nrf_drv_gpiote_evt_handler_t handler, bool channel)
{
{
int8_t channel_id = NO_CHANNELS;
int8_t channel_id = NO_CHANNELS;
uint32_t i;
uint32_t i;
uint32_t start_idx = channel ? 0 : NUMBER_OF_GPIO_TE;
uint32_t start_idx = channel ? 0 : NUMBER_OF_GPIO_TE;
uint32_t end_idx = channel ? NUMBER_OF_GPIO_TE : (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);
uint32_t end_idx = channel ? NUMBER_OF_GPIO_TE : (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);
//critical section
//critical section
for (i = start_idx; i < end_idx; i++)
for (i = start_idx; i < end_idx; i++)
{
{
if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
{
{
pin_in_use_by_te_set(pin, i, handler, channel);
pin_in_use_by_te_set(pin, i, handler, channel);
channel_id = i;
channel_id = i;
break;
break;
}
}
}
}
//critical section
//critical section
return channel_id;
return channel_id;
}
}
static void channel_free(uint8_t channel_id)
static void channel_free(uint8_t channel_id)
{
{
m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;
m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;
if (channel_id >= NUMBER_OF_GPIO_TE)
if (channel_id >= NUMBER_OF_GPIO_TE)
{
{
m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)-1;
m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)-1;
}
}
}
}
ret_code_t nrf_drv_gpiote_init(void)
ret_code_t nrf_drv_gpiote_init(void)
{
{
if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
{
{
return NRF_ERROR_INVALID_STATE;
return NRF_ERROR_INVALID_STATE;
}
}
uint8_t i;
uint8_t i;
for (i = 0; i < NUMBER_OF_PINS; i++)
for (i = 0; i < NUMBER_OF_PINS; i++)
{
{
pin_in_use_clear(i);
pin_in_use_clear(i);
}
}
for (i = 0; i < (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
for (i = 0; i < (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
{
{
channel_free(i);
channel_free(i);
}
}
nrf_drv_common_irq_enable(GPIOTE_IRQn, GPIOTE_CONFIG_IRQ_PRIORITY);
nrf_drv_common_irq_enable(GPIOTE_IRQn, GPIOTE_CONFIG_IRQ_PRIORITY);
nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
m_cb.state = NRF_DRV_STATE_INITIALIZED;
m_cb.state = NRF_DRV_STATE_INITIALIZED;
return NRF_SUCCESS;
return NRF_SUCCESS;
}
}
bool nrf_drv_gpiote_is_init(void)
bool nrf_drv_gpiote_is_init(void)
{
{
return (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) ? true : false;
return (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) ? true : false;
}
}
void nrf_drv_gpiote_uninit(void)
void nrf_drv_gpiote_uninit(void)
{
{
ASSERT(m_cb.state!=NRF_DRV_STATE_UNINITIALIZED);
ASSERT(m_cb.state!=NRF_DRV_STATE_UNINITIALIZED);
uint32_t i;
uint32_t i;
for (i = 0; i < NUMBER_OF_PINS; i++)
for (i = 0; i < NUMBER_OF_PINS; i++)
{
{
if (pin_in_use_as_non_task_out(i))
if (pin_in_use_as_non_task_out(i))
{
{
nrf_drv_gpiote_out_uninit(i);
nrf_drv_gpiote_out_uninit(i);
}
}
else if( pin_in_use_by_gpiote(i))
else if( pin_in_use_by_gpiote(i))
{
{
/* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on
/* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on
* so it can be called on all pins used by GPIOTE.
* so it can be called on all pins used by GPIOTE.
*/
*/
nrf_drv_gpiote_in_uninit(i);
nrf_drv_gpiote_in_uninit(i);
}
}
}
}
m_cb.state = NRF_DRV_STATE_UNINITIALIZED;
m_cb.state = NRF_DRV_STATE_UNINITIALIZED;
}
}
ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin, nrf_drv_gpiote_out_config_t * p_config)
ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin, nrf_drv_gpiote_out_config_t * p_config)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(m_cb.state == NRF_DRV_STATE_INITIALIZED);
ASSERT(m_cb.state == NRF_DRV_STATE_INITIALIZED);
ASSERT(p_config);
ASSERT(p_config);
ret_code_t result = NRF_SUCCESS;
ret_code_t result = NRF_SUCCESS;
if (pin_in_use(pin))
if (pin_in_use(pin))
{
{
result = NRF_ERROR_INVALID_STATE;
result = NRF_ERROR_INVALID_STATE;
}
}
else
else
{
{
if (p_config->task_pin)
if (p_config->task_pin)
{
{
int8_t channel = channel_port_alloc(pin, NULL, true);
int8_t channel = channel_port_alloc(pin, NULL, true);
if (channel != NO_CHANNELS)
if (channel != NO_CHANNELS)
{
{
nrf_gpiote_task_configure(channel, pin, p_config->action, p_config->init_state);
nrf_gpiote_task_configure(channel, pin, p_config->action, p_config->init_state);
}
}
else
else
{
{
result = NRF_ERROR_NO_MEM;
result = NRF_ERROR_NO_MEM;
}
}
}
}
else
else
{
{
pin_in_use_set(pin);
pin_in_use_set(pin);
}
}
if (result == NRF_SUCCESS)
if (result == NRF_SUCCESS)
{
{
nrf_gpio_cfg_output(pin);
nrf_gpio_cfg_output(pin);
if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
{
{
nrf_gpio_pin_set(pin);
nrf_gpio_pin_set(pin);
}
}
else
else
{
{
nrf_gpio_pin_clear(pin);
nrf_gpio_pin_clear(pin);
}
}
}
}
}
}
return result;
return result;
}
}
void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
if (pin_in_use_by_te(pin))
if (pin_in_use_by_te(pin))
{
{
channel_free((uint8_t)m_cb.pin_assignments[pin]);
channel_free((uint8_t)m_cb.pin_assignments[pin]);
}
}
pin_in_use_clear(pin);
pin_in_use_clear(pin);
nrf_gpio_cfg_default(pin);
nrf_gpio_cfg_default(pin);
}
}
void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(!pin_in_use_by_te(pin))
ASSERT(!pin_in_use_by_te(pin))
nrf_gpio_pin_set(pin);
nrf_gpio_pin_set(pin);
}
}
void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(!pin_in_use_by_te(pin))
ASSERT(!pin_in_use_by_te(pin))
nrf_gpio_pin_clear(pin);
nrf_gpio_pin_clear(pin);
}
}
void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(!pin_in_use_by_te(pin))
ASSERT(!pin_in_use_by_te(pin))
nrf_gpio_pin_toggle(pin);
nrf_gpio_pin_toggle(pin);
}
}
void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin))
ASSERT(pin_in_use_by_te(pin))
nrf_gpiote_task_enable(m_cb.pin_assignments[pin]);
nrf_gpiote_task_enable(m_cb.pin_assignments[pin]);
}
}
void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin))
ASSERT(pin_in_use_by_te(pin))
nrf_gpiote_task_disable(m_cb.pin_assignments[pin]);
nrf_gpiote_task_disable(m_cb.pin_assignments[pin]);
}
}
uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin)
uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_te(pin));
ASSERT(pin_in_use_by_te(pin));
nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin)));
nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin)));
return nrf_gpiote_task_addr_get(task);
return nrf_gpiote_task_addr_get(task);
}
}
void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state)
void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin));
ASSERT(pin_in_use_by_te(pin));
nrf_gpiote_outinit_t init_val = state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
nrf_gpiote_outinit_t init_val = state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
nrf_gpiote_task_force(m_cb.pin_assignments[pin], init_val);
nrf_gpiote_task_force(m_cb.pin_assignments[pin], init_val);
}
}
void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin));
ASSERT(pin_in_use_by_te(pin));
nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin)));
nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin)));
nrf_gpiote_task_set(task);
nrf_gpiote_task_set(task);
}
}
ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin,
ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin,
nrf_drv_gpiote_in_config_t * p_config,
nrf_drv_gpiote_in_config_t * p_config,
nrf_drv_gpiote_evt_handler_t evt_handler)
nrf_drv_gpiote_evt_handler_t evt_handler)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ret_code_t result = NRF_SUCCESS;
ret_code_t result = NRF_SUCCESS;
/* Only one GPIOTE channel can be assigned to one physical pin. */
/* Only one GPIOTE channel can be assigned to one physical pin. */
if (pin_in_use_by_gpiote(pin))
if (pin_in_use_by_gpiote(pin))
{
{
result = NRF_ERROR_INVALID_STATE;
result = NRF_ERROR_INVALID_STATE;
}
}
else
else
{
{
int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
if (channel != NO_CHANNELS)
if (channel != NO_CHANNELS)
{
{
if (p_config->is_watcher)
if (p_config->is_watcher)
{
{
nrf_gpio_cfg_watcher(pin);
nrf_gpio_cfg_watcher(pin);
}
}
else
else
{
{
nrf_gpio_cfg_input(pin,p_config->pull);
nrf_gpio_cfg_input(pin,p_config->pull);
}
}
if (p_config->hi_accuracy)
if (p_config->hi_accuracy)
{
{
nrf_gpiote_event_configure(channel, pin,p_config->sense);
nrf_gpiote_event_configure(channel, pin,p_config->sense);
}
}
else
else
{
{
m_cb.handlers_to_pins[channel-NUMBER_OF_GPIO_TE] |= (p_config->sense)<< SENSE_FIELD_POS;
m_cb.handlers_to_pins[channel-NUMBER_OF_GPIO_TE] |= (p_config->sense)<< SENSE_FIELD_POS;
}
}
}
}
else
else
{
{
result = NRF_ERROR_NO_MEM;
result = NRF_ERROR_NO_MEM;
}
}
}
}
return result;
return result;
}
}
void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable)
void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_gpiote(pin));
ASSERT(pin_in_use_by_gpiote(pin));
if (pin_in_use_by_port(pin))
if (pin_in_use_by_port(pin))
{
{
uint8_t pin_and_sense = pin_from_port_get(channel_port_get(pin)-NUMBER_OF_GPIO_TE);
uint8_t pin_and_sense = pin_from_port_get(channel_port_get(pin)-NUMBER_OF_GPIO_TE);
nrf_gpiote_polarity_t polarity = (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS);
nrf_gpiote_polarity_t polarity = (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS);
nrf_gpio_pin_sense_t sense;
nrf_gpio_pin_sense_t sense;
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
{
{
/* read current pin state and set for next sense to oposit */
/* read current pin state and set for next sense to oposit */
sense = (nrf_gpio_pins_read() & (1 << pin)) ?
sense = (nrf_gpio_pins_read() & (1 << pin)) ?
NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
}
}
else
else
{
{
sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
}
}
nrf_gpio_cfg_sense_set(pin,sense);
nrf_gpio_cfg_sense_set(pin,sense);
}
}
else if(pin_in_use_by_te(pin))
else if(pin_in_use_by_te(pin))
{
{
int32_t channel = (int32_t)channel_port_get(pin);
int32_t channel = (int32_t)channel_port_get(pin);
nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+4*channel);
nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+4*channel);
nrf_gpiote_event_enable(channel);
nrf_gpiote_event_enable(channel);
nrf_gpiote_event_clear(event);
nrf_gpiote_event_clear(event);
if (int_enable)
if (int_enable)
{
{
nrf_gpiote_int_enable(1 << channel);
nrf_gpiote_int_enable(1 << channel);
}
}
}
}
}
}
void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_gpiote(pin));
ASSERT(pin_in_use_by_gpiote(pin));
if (pin_in_use_by_port(pin))
if (pin_in_use_by_port(pin))
{
{
nrf_gpio_input_disconnect(pin);
nrf_gpio_input_disconnect(pin);
}
}
else if(pin_in_use_by_te(pin))
else if(pin_in_use_by_te(pin))
{
{
int32_t channel = (int32_t)channel_port_get(pin);
int32_t channel = (int32_t)channel_port_get(pin);
nrf_gpiote_event_disable(channel);
nrf_gpiote_event_disable(channel);
nrf_gpiote_int_disable(1 << channel);
nrf_gpiote_int_disable(1 << channel);
}
}
}
}
void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin)
void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_gpiote(pin));
ASSERT(pin_in_use_by_gpiote(pin));
nrf_drv_gpiote_in_event_disable(pin);
nrf_drv_gpiote_in_event_disable(pin);
if(pin_in_use_by_te(pin))
if(pin_in_use_by_te(pin))
{
{
nrf_gpiote_te_default(channel_port_get(pin));
nrf_gpiote_te_default(channel_port_get(pin));
}
}
nrf_gpio_cfg_default(pin);
nrf_gpio_cfg_default(pin);
channel_free((uint8_t)channel_port_get(pin));
channel_free((uint8_t)channel_port_get(pin));
pin_in_use_clear(pin);
pin_in_use_clear(pin);
}
}
bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin)
bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
return nrf_gpio_pin_read(pin) ? true : false;
return nrf_gpio_pin_read(pin) ? true : false;
}
}
uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin)
uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin)
{
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_te(pin));
ASSERT(pin_in_use_by_te(pin));
nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+(4*channel_port_get(pin)));
nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+(4*channel_port_get(pin)));
return nrf_gpiote_event_addr_get(event);
return nrf_gpiote_event_addr_get(event);
}
}
void GPIOTE_IRQHandler(void)
void GPIOTE_IRQHandler(void)
{
{
uint32_t status = 0;
uint32_t status = 0;
uint32_t input = 0;
uint32_t input = 0;
복사
복사됨
복사
복사됨
uint32_t i;
uint32_t pins_changed = 1;
uint32_t pins_sense_enabled = 0;
uint32_t pins_sense_disabled = 0;
uint32_t pins_state = NRF_GPIO->IN;
/* collect PORT status event, if event is set read pins state. Processing is postponed to the
* end of interrupt. */
if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))
{
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
input = nrf_gpio_pins_read();
}
while (pins_changed)
{
// Check all users.
for (i = 0; i < m_user_count; i++)
{
gpiote_user_t * p_user = &mp_users[i];
// Check if user is enabled.
if (((1 << i) & m_enabled_users_mask) != 0)
{
uint32_t transition_pins;
uint32_t event_low_to_high = 0;
uint32_t event_high_to_low = 0;
pins_sense_enabled |= (p_user->pins_mask & ~pins_sense_disabled);
// Find set of pins on which there has been a transition.
transition_pins = (pins_state ^ ~p_user->sense_high_pins) & (p_user->pins_mask & ~pins_sense_disabled);
sense_level_disable(transition_pins);
pins_sense_disabled |= transition_pins;
pins_sense_enabled &= ~pins_sense_disabled;
// Call user event handler if an event has occurred.
event_high_to_low |= (~pins_state & p_user->pins_high_to_low_mask) & transition_pins;
event_low_to_high |= (pins_state & p_user->pins_low_to_high_mask) & transition_pins;
if ((event_low_to_high | event_high_to_low) != 0)
{
p_user->event_handler(event_low_to_high, event_high_to_low);
}
}
}
// Second read after setting sense.
// Check if any pins with sense enabled have changed while serving this interrupt.
pins_changed = (NRF_GPIO->IN ^ pins_state) & pins_sense_enabled;
pins_state ^= pins_changed;
}
// Now re-enabling sense on all pins that have sense disabled.
// Note: a new interrupt might fire immediatly.
for (i = 0; i < m_user_count; i++)
{
gpiote_user_t * p_user = &mp_users[i];
복사
복사됨
복사
복사됨
// Check if user is enabled.
if (((1 << i) & m_enabled_users_mask) != 0)
{
if (pins_sense_disabled & p_user->pins_mask)
{
sense_level_toggle(p_user, pins_sense_disabled & p_user->pins_mask);
}
}
}
/* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
/* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
복사
복사됨
복사
복사됨
uint32_t i;
nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0;
nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0;
uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
{
{
복사
복사됨
복사
복사됨
if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(
1 << i
))
if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(
mask
))
{
{
nrf_gpiote_event_clear(event);
nrf_gpiote_event_clear(event);
status |= mask;
status |= mask;
}
}
mask <<= 1;
mask <<= 1;
복사
복사됨
복사
복사됨
event = (nrf_gpiote_events_t)((uint32_t)event +
4
);
/* Incrementing to next event, utilizing the fact that events are grouped together
* in ascending order. */
event = (nrf_gpiote_events_t)((uint32_t)event +
sizeof(uint32_t)
);
}
}
/* collect PORT status event, if event is set read pins state. Processing is postponed to the
/* collect PORT status event, if event is set read pins state. Processing is postponed to the
* end of interrupt. */
* end of interrupt. */
if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))
if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))
{
{
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
input = nrf_gpio_pins_read();
input = nrf_gpio_pins_read();
}
}
/* Process pin events. */
/* Process pin events. */
if (status & NRF_GPIOTE_INT_IN_MASK)
if (status & NRF_GPIOTE_INT_IN_MASK)
{
{
복사
복사됨
복사
복사됨
mask =
1
;
mask =
(uint32_t)NRF_GPIOTE_INT_IN0_MASK
;
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
{
{
if (mask & status)
if (mask & status)
{
{
nrf_drv_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i);
nrf_drv_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i);
nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i);
nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i);
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(i);
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(i);
handler(pin,polarity);
handler(pin,polarity);
}
}
mask <<= 1;
mask <<= 1;
}
}
}
}
if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
{
{
/* Process port event. */
/* Process port event. */
for (i = 0; i < GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
for (i = 0; i < GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
{
{
복사
복사됨
복사
복사됨
uint8_t pin_and_sense = pin_from_port_get(i);
if (m_cb.
port
_handlers_
pin
s[i] != PIN_NOT_USED
)
nrf_drv_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK);
nrf_gpiote_polarity_t polarity =
(nrf_gpiote_polarity_t)((pin_and_sense & SENSE_FIELD_MASK) >> SENSE_FIELD_POS);
mask = 1 << pin;
if (pin_in_use_by_
port
(
pin
)
)
{
{
복사
복사됨
복사
복사됨
uint8_t pin_and_sense = m_cb.port_handlers_pins[i];
nrf_drv_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK);
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin));
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin));
if (handler)
if (handler)
{
{
복사
복사됨
복사
복사됨
nrf_gpiote_polarity_t polarity =
(nrf_gpiote_polarity_t)((pin_and_sense & SENSE_FIELD_MASK) >> SENSE_FIELD_POS);
mask = 1 << pin;
nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
if (((mask & input) && (sense==NRF_GPIO_PIN_SENSE_HIGH)) ||
if (((mask & input) && (sense==NRF_GPIO_PIN_SENSE_HIGH)) ||
(!(mask & input) && (sense==NRF_GPIO_PIN_SENSE_LOW)) )
(!(mask & input) && (sense==NRF_GPIO_PIN_SENSE_LOW)) )
{
{
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
{
{
nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ?
nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ?
NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
nrf_gpio_cfg_sense_set(pin, next_sense);
nrf_gpio_cfg_sense_set(pin, next_sense);
}
}
handler(pin, polarity);
handler(pin, polarity);
}
}
}
}
}
}
}
}
}
}
}
}
//lint -restore
//lint -restore
저장된 비교 결과
원본
파일 열기
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. * * The information contained herein is property of Nordic Semiconductor ASA. * Terms and conditions of usage are described in detail in NORDIC * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. * * Licensees are granted free, non-transferable use of the information. NO * WARRANTY of ANY KIND is provided. This heading must NOT be removed from * the file. * */ #include "nrf_drv_gpiote.h" #include "nrf_drv_common.h" #include "nrf_drv_config.h" #include "app_util_platform.h" #include "nrf_assert.h" #define FORBIDDEN_HANDLER_ADDRESS ((nrf_drv_gpiote_evt_handler_t)UINT32_MAX) #define PIN_NOT_USED (-1) #define PIN_USED (-2) #define NO_CHANNELS (-1) #define SENSE_FIELD_POS (6) #define SENSE_FIELD_MASK (0xC0) //lint -save -e661 typedef struct { nrf_drv_state_t state; nrf_drv_gpiote_evt_handler_t handlers[NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS]; int8_t pin_assignments[NUMBER_OF_PINS]; int8_t handlers_to_pins[GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS]; } control_block_t; static control_block_t m_cb; __STATIC_INLINE bool pin_in_use(uint32_t pin) { return (m_cb.pin_assignments[pin] != PIN_NOT_USED) ? true : false; } __STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin) { return (m_cb.pin_assignments[pin] == PIN_USED) ? true : false; } __STATIC_INLINE bool pin_in_use_by_te(uint32_t pin) { return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < NUMBER_OF_GPIO_TE) ? true : false; } __STATIC_INLINE bool pin_in_use_by_port(uint32_t pin) { return (m_cb.pin_assignments[pin] >= NUMBER_OF_GPIO_TE) ? true : false; } __STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin) { return (m_cb.pin_assignments[pin] >= 0) ? true : false; } __STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin, uint32_t channel_id, nrf_drv_gpiote_evt_handler_t handler, bool is_channel) { m_cb.pin_assignments[pin] = channel_id; m_cb.handlers[channel_id] = handler; if (!is_channel) { m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)pin; } } __STATIC_INLINE void pin_in_use_set(uint32_t pin) { m_cb.pin_assignments[pin] = PIN_USED; } __STATIC_INLINE void pin_in_use_clear(uint32_t pin) { m_cb.pin_assignments[pin] = PIN_NOT_USED; } __STATIC_INLINE int8_t channel_port_get(uint32_t pin) { return m_cb.pin_assignments[pin]; } __STATIC_INLINE uint8_t pin_from_port_get(uint32_t port_channel) { return m_cb.handlers_to_pins[port_channel]; } __STATIC_INLINE nrf_drv_gpiote_evt_handler_t channel_handler_get(uint32_t channel) { return m_cb.handlers[channel]; } static int8_t channel_port_alloc(uint32_t pin,nrf_drv_gpiote_evt_handler_t handler, bool channel) { int8_t channel_id = NO_CHANNELS; uint32_t i; uint32_t start_idx = channel ? 0 : NUMBER_OF_GPIO_TE; uint32_t end_idx = channel ? NUMBER_OF_GPIO_TE : (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); //critical section for (i = start_idx; i < end_idx; i++) { if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS) { pin_in_use_by_te_set(pin, i, handler, channel); channel_id = i; break; } } //critical section return channel_id; } static void channel_free(uint8_t channel_id) { m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS; if (channel_id >= NUMBER_OF_GPIO_TE) { m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)-1; } } ret_code_t nrf_drv_gpiote_init(void) { if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) { return NRF_ERROR_INVALID_STATE; } uint8_t i; for (i = 0; i < NUMBER_OF_PINS; i++) { pin_in_use_clear(i); } for (i = 0; i < (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++) { channel_free(i); } nrf_drv_common_irq_enable(GPIOTE_IRQn, GPIOTE_CONFIG_IRQ_PRIORITY); nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk); m_cb.state = NRF_DRV_STATE_INITIALIZED; return NRF_SUCCESS; } bool nrf_drv_gpiote_is_init(void) { return (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) ? true : false; } void nrf_drv_gpiote_uninit(void) { ASSERT(m_cb.state!=NRF_DRV_STATE_UNINITIALIZED); uint32_t i; for (i = 0; i < NUMBER_OF_PINS; i++) { if (pin_in_use_as_non_task_out(i)) { nrf_drv_gpiote_out_uninit(i); } else if( pin_in_use_by_gpiote(i)) { /* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on * so it can be called on all pins used by GPIOTE. */ nrf_drv_gpiote_in_uninit(i); } } m_cb.state = NRF_DRV_STATE_UNINITIALIZED; } ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin, nrf_drv_gpiote_out_config_t * p_config) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(m_cb.state == NRF_DRV_STATE_INITIALIZED); ASSERT(p_config); ret_code_t result = NRF_SUCCESS; if (pin_in_use(pin)) { result = NRF_ERROR_INVALID_STATE; } else { if (p_config->task_pin) { int8_t channel = channel_port_alloc(pin, NULL, true); if (channel != NO_CHANNELS) { nrf_gpiote_task_configure(channel, pin, p_config->action, p_config->init_state); } else { result = NRF_ERROR_NO_MEM; } } else { pin_in_use_set(pin); } if (result == NRF_SUCCESS) { nrf_gpio_cfg_output(pin); if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH) { nrf_gpio_pin_set(pin); } else { nrf_gpio_pin_clear(pin); } } } return result; } void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); if (pin_in_use_by_te(pin)) { channel_free((uint8_t)m_cb.pin_assignments[pin]); } pin_in_use_clear(pin); nrf_gpio_cfg_default(pin); } void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(!pin_in_use_by_te(pin)) nrf_gpio_pin_set(pin); } void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(!pin_in_use_by_te(pin)) nrf_gpio_pin_clear(pin); } void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(!pin_in_use_by_te(pin)) nrf_gpio_pin_toggle(pin); } void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(pin_in_use_by_te(pin)) nrf_gpiote_task_enable(m_cb.pin_assignments[pin]); } void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(pin_in_use_by_te(pin)) nrf_gpiote_task_disable(m_cb.pin_assignments[pin]); } uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_te(pin)); nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin))); return nrf_gpiote_task_addr_get(task); } void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(pin_in_use_by_te(pin)); nrf_gpiote_outinit_t init_val = state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW; nrf_gpiote_task_force(m_cb.pin_assignments[pin], init_val); } void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(pin_in_use_by_te(pin)); nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin))); nrf_gpiote_task_set(task); } ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin, nrf_drv_gpiote_in_config_t * p_config, nrf_drv_gpiote_evt_handler_t evt_handler) { ASSERT(pin < NUMBER_OF_PINS); ret_code_t result = NRF_SUCCESS; /* Only one GPIOTE channel can be assigned to one physical pin. */ if (pin_in_use_by_gpiote(pin)) { result = NRF_ERROR_INVALID_STATE; } else { int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy); if (channel != NO_CHANNELS) { if (p_config->is_watcher) { nrf_gpio_cfg_watcher(pin); } else { nrf_gpio_cfg_input(pin,p_config->pull); } if (p_config->hi_accuracy) { nrf_gpiote_event_configure(channel, pin,p_config->sense); } else { m_cb.handlers_to_pins[channel-NUMBER_OF_GPIO_TE] |= (p_config->sense)<< SENSE_FIELD_POS; } } else { result = NRF_ERROR_NO_MEM; } } return result; } void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_gpiote(pin)); if (pin_in_use_by_port(pin)) { uint8_t pin_and_sense = pin_from_port_get(channel_port_get(pin)-NUMBER_OF_GPIO_TE); nrf_gpiote_polarity_t polarity = (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS); nrf_gpio_pin_sense_t sense; if (polarity == NRF_GPIOTE_POLARITY_TOGGLE) { /* read current pin state and set for next sense to oposit */ sense = (nrf_gpio_pins_read() & (1 << pin)) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH; } else { sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ? NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW; } nrf_gpio_cfg_sense_set(pin,sense); } else if(pin_in_use_by_te(pin)) { int32_t channel = (int32_t)channel_port_get(pin); nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+4*channel); nrf_gpiote_event_enable(channel); nrf_gpiote_event_clear(event); if (int_enable) { nrf_gpiote_int_enable(1 << channel); } } } void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_gpiote(pin)); if (pin_in_use_by_port(pin)) { nrf_gpio_input_disconnect(pin); } else if(pin_in_use_by_te(pin)) { int32_t channel = (int32_t)channel_port_get(pin); nrf_gpiote_event_disable(channel); nrf_gpiote_int_disable(1 << channel); } } void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_gpiote(pin)); nrf_drv_gpiote_in_event_disable(pin); if(pin_in_use_by_te(pin)) { nrf_gpiote_te_default(channel_port_get(pin)); } nrf_gpio_cfg_default(pin); channel_free((uint8_t)channel_port_get(pin)); pin_in_use_clear(pin); } bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); return nrf_gpio_pin_read(pin) ? true : false; } uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_te(pin)); nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+(4*channel_port_get(pin))); return nrf_gpiote_event_addr_get(event); } void GPIOTE_IRQHandler(void) { uint32_t status = 0; uint32_t input = 0; /* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/ uint32_t i; nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0; uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK; for (i = 0; i < NUMBER_OF_GPIO_TE; i++) { if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(1 << i)) { nrf_gpiote_event_clear(event); status |= mask; } mask <<= 1; event = (nrf_gpiote_events_t)((uint32_t)event + 4); } /* collect PORT status event, if event is set read pins state. Processing is postponed to the * end of interrupt. */ if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT)) { nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK; input = nrf_gpio_pins_read(); } /* Process pin events. */ if (status & NRF_GPIOTE_INT_IN_MASK) { mask = 1; for (i = 0; i < NUMBER_OF_GPIO_TE; i++) { if (mask & status) { nrf_drv_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i); nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i); nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(i); handler(pin,polarity); } mask <<= 1; } } if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK) { /* Process port event. */ for (i = 0; i < GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++) { uint8_t pin_and_sense = pin_from_port_get(i); nrf_drv_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK); nrf_gpiote_polarity_t polarity = (nrf_gpiote_polarity_t)((pin_and_sense & SENSE_FIELD_MASK) >> SENSE_FIELD_POS); mask = 1 << pin; if (pin_in_use_by_port(pin)) { nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin)); if (handler) { nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin); if (((mask & input) && (sense==NRF_GPIO_PIN_SENSE_HIGH)) || (!(mask & input) && (sense==NRF_GPIO_PIN_SENSE_LOW)) ) { if (polarity == NRF_GPIOTE_POLARITY_TOGGLE) { nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH; nrf_gpio_cfg_sense_set(pin, next_sense); } handler(pin, polarity); } } } } } } //lint -restore
수정본
파일 열기
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. * * The information contained herein is property of Nordic Semiconductor ASA. * Terms and conditions of usage are described in detail in NORDIC * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. * * Licensees are granted free, non-transferable use of the information. NO * WARRANTY of ANY KIND is provided. This heading must NOT be removed from * the file. * */ #include "nrf_drv_gpiote.h" #include "nrf_drv_common.h" #include "nrf_drv_config.h" #include "app_util_platform.h" #include "nrf_assert.h" #define FORBIDDEN_HANDLER_ADDRESS ((nrf_drv_gpiote_evt_handler_t)UINT32_MAX) #define PIN_NOT_USED (-1) #define PIN_USED (-2) #define NO_CHANNELS (-1) #define SENSE_FIELD_POS (6) #define SENSE_FIELD_MASK (0xC0) //lint -save -e661 typedef struct { nrf_drv_state_t state; nrf_drv_gpiote_evt_handler_t handlers[NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS]; int8_t pin_assignments[NUMBER_OF_PINS]; int8_t handlers_to_pins[GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS]; } control_block_t; static control_block_t m_cb; typedef void (*app_gpiote_event_handler_t)(uint32_t event_pins_low_to_high, uint32_t event_pins_high_to_low); /**@brief GPIOTE user type. */ typedef struct { uint32_t pins_mask; /**< Mask defining which pins user wants to monitor. */ uint32_t pins_low_to_high_mask; /**< Mask defining which pins will generate events to this user when toggling low->high. */ uint32_t pins_high_to_low_mask; /**< Mask defining which pins will generate events to this user when toggling high->low. */ uint32_t sense_high_pins; /**< Mask defining which pins are configured to generate GPIOTE interrupt on transition to high level. */ app_gpiote_event_handler_t event_handler; /**< Pointer to function to be executed when an event occurs. */ } gpiote_user_t; extern uint32_t m_enabled_users_mask; /**< Mask for tracking which users are enabled. */ extern uint8_t m_user_array_size; /**< Size of user array. */ extern uint8_t m_user_count; /**< Number of registered users. */ extern gpiote_user_t * mp_users; /**< Array of GPIOTE users. */ __STATIC_INLINE bool pin_in_use(uint32_t pin) { return (m_cb.pin_assignments[pin] != PIN_NOT_USED) ? true : false; } __STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin) { return (m_cb.pin_assignments[pin] == PIN_USED) ? true : false; } __STATIC_INLINE bool pin_in_use_by_te(uint32_t pin) { return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < NUMBER_OF_GPIO_TE) ? true : false; } __STATIC_INLINE bool pin_in_use_by_port(uint32_t pin) { return (m_cb.pin_assignments[pin] >= NUMBER_OF_GPIO_TE) ? true : false; } __STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin) { return (m_cb.pin_assignments[pin] >= 0) ? true : false; } __STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin, uint32_t channel_id, nrf_drv_gpiote_evt_handler_t handler, bool is_channel) { m_cb.pin_assignments[pin] = channel_id; m_cb.handlers[channel_id] = handler; if (!is_channel) { m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)pin; } } __STATIC_INLINE void pin_in_use_set(uint32_t pin) { m_cb.pin_assignments[pin] = PIN_USED; } __STATIC_INLINE void pin_in_use_clear(uint32_t pin) { m_cb.pin_assignments[pin] = PIN_NOT_USED; } __STATIC_INLINE int8_t channel_port_get(uint32_t pin) { return m_cb.pin_assignments[pin]; } __STATIC_INLINE uint8_t pin_from_port_get(uint32_t port_channel) { return m_cb.handlers_to_pins[port_channel]; } __STATIC_INLINE nrf_drv_gpiote_evt_handler_t channel_handler_get(uint32_t channel) { return m_cb.handlers[channel]; } void sense_level_toggle(gpiote_user_t * p_user, uint32_t pins); void sense_level_disable(uint32_t pins); static int8_t channel_port_alloc(uint32_t pin,nrf_drv_gpiote_evt_handler_t handler, bool channel) { int8_t channel_id = NO_CHANNELS; uint32_t i; uint32_t start_idx = channel ? 0 : NUMBER_OF_GPIO_TE; uint32_t end_idx = channel ? NUMBER_OF_GPIO_TE : (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); //critical section for (i = start_idx; i < end_idx; i++) { if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS) { pin_in_use_by_te_set(pin, i, handler, channel); channel_id = i; break; } } //critical section return channel_id; } static void channel_free(uint8_t channel_id) { m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS; if (channel_id >= NUMBER_OF_GPIO_TE) { m_cb.handlers_to_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)-1; } } ret_code_t nrf_drv_gpiote_init(void) { if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) { return NRF_ERROR_INVALID_STATE; } uint8_t i; for (i = 0; i < NUMBER_OF_PINS; i++) { pin_in_use_clear(i); } for (i = 0; i < (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++) { channel_free(i); } nrf_drv_common_irq_enable(GPIOTE_IRQn, GPIOTE_CONFIG_IRQ_PRIORITY); nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk); m_cb.state = NRF_DRV_STATE_INITIALIZED; return NRF_SUCCESS; } bool nrf_drv_gpiote_is_init(void) { return (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) ? true : false; } void nrf_drv_gpiote_uninit(void) { ASSERT(m_cb.state!=NRF_DRV_STATE_UNINITIALIZED); uint32_t i; for (i = 0; i < NUMBER_OF_PINS; i++) { if (pin_in_use_as_non_task_out(i)) { nrf_drv_gpiote_out_uninit(i); } else if( pin_in_use_by_gpiote(i)) { /* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on * so it can be called on all pins used by GPIOTE. */ nrf_drv_gpiote_in_uninit(i); } } m_cb.state = NRF_DRV_STATE_UNINITIALIZED; } ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin, nrf_drv_gpiote_out_config_t * p_config) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(m_cb.state == NRF_DRV_STATE_INITIALIZED); ASSERT(p_config); ret_code_t result = NRF_SUCCESS; if (pin_in_use(pin)) { result = NRF_ERROR_INVALID_STATE; } else { if (p_config->task_pin) { int8_t channel = channel_port_alloc(pin, NULL, true); if (channel != NO_CHANNELS) { nrf_gpiote_task_configure(channel, pin, p_config->action, p_config->init_state); } else { result = NRF_ERROR_NO_MEM; } } else { pin_in_use_set(pin); } if (result == NRF_SUCCESS) { nrf_gpio_cfg_output(pin); if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH) { nrf_gpio_pin_set(pin); } else { nrf_gpio_pin_clear(pin); } } } return result; } void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); if (pin_in_use_by_te(pin)) { channel_free((uint8_t)m_cb.pin_assignments[pin]); } pin_in_use_clear(pin); nrf_gpio_cfg_default(pin); } void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(!pin_in_use_by_te(pin)) nrf_gpio_pin_set(pin); } void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(!pin_in_use_by_te(pin)) nrf_gpio_pin_clear(pin); } void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(!pin_in_use_by_te(pin)) nrf_gpio_pin_toggle(pin); } void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(pin_in_use_by_te(pin)) nrf_gpiote_task_enable(m_cb.pin_assignments[pin]); } void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(pin_in_use_by_te(pin)) nrf_gpiote_task_disable(m_cb.pin_assignments[pin]); } uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_te(pin)); nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin))); return nrf_gpiote_task_addr_get(task); } void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(pin_in_use_by_te(pin)); nrf_gpiote_outinit_t init_val = state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW; nrf_gpiote_task_force(m_cb.pin_assignments[pin], init_val); } void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use(pin)); ASSERT(pin_in_use_by_te(pin)); nrf_gpiote_tasks_t task = (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(4*channel_port_get(pin))); nrf_gpiote_task_set(task); } ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin, nrf_drv_gpiote_in_config_t * p_config, nrf_drv_gpiote_evt_handler_t evt_handler) { ASSERT(pin < NUMBER_OF_PINS); ret_code_t result = NRF_SUCCESS; /* Only one GPIOTE channel can be assigned to one physical pin. */ if (pin_in_use_by_gpiote(pin)) { result = NRF_ERROR_INVALID_STATE; } else { int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy); if (channel != NO_CHANNELS) { if (p_config->is_watcher) { nrf_gpio_cfg_watcher(pin); } else { nrf_gpio_cfg_input(pin,p_config->pull); } if (p_config->hi_accuracy) { nrf_gpiote_event_configure(channel, pin,p_config->sense); } else { m_cb.handlers_to_pins[channel-NUMBER_OF_GPIO_TE] |= (p_config->sense)<< SENSE_FIELD_POS; } } else { result = NRF_ERROR_NO_MEM; } } return result; } void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_gpiote(pin)); if (pin_in_use_by_port(pin)) { uint8_t pin_and_sense = pin_from_port_get(channel_port_get(pin)-NUMBER_OF_GPIO_TE); nrf_gpiote_polarity_t polarity = (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS); nrf_gpio_pin_sense_t sense; if (polarity == NRF_GPIOTE_POLARITY_TOGGLE) { /* read current pin state and set for next sense to oposit */ sense = (nrf_gpio_pins_read() & (1 << pin)) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH; } else { sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ? NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW; } nrf_gpio_cfg_sense_set(pin,sense); } else if(pin_in_use_by_te(pin)) { int32_t channel = (int32_t)channel_port_get(pin); nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+4*channel); nrf_gpiote_event_enable(channel); nrf_gpiote_event_clear(event); if (int_enable) { nrf_gpiote_int_enable(1 << channel); } } } void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_gpiote(pin)); if (pin_in_use_by_port(pin)) { nrf_gpio_input_disconnect(pin); } else if(pin_in_use_by_te(pin)) { int32_t channel = (int32_t)channel_port_get(pin); nrf_gpiote_event_disable(channel); nrf_gpiote_int_disable(1 << channel); } } void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_gpiote(pin)); nrf_drv_gpiote_in_event_disable(pin); if(pin_in_use_by_te(pin)) { nrf_gpiote_te_default(channel_port_get(pin)); } nrf_gpio_cfg_default(pin); channel_free((uint8_t)channel_port_get(pin)); pin_in_use_clear(pin); } bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); return nrf_gpio_pin_read(pin) ? true : false; } uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin) { ASSERT(pin < NUMBER_OF_PINS); ASSERT(pin_in_use_by_te(pin)); nrf_gpiote_events_t event = (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+(4*channel_port_get(pin))); return nrf_gpiote_event_addr_get(event); } void GPIOTE_IRQHandler(void) { uint32_t status = 0; uint32_t input = 0; uint32_t i; uint32_t pins_changed = 1; uint32_t pins_sense_enabled = 0; uint32_t pins_sense_disabled = 0; uint32_t pins_state = NRF_GPIO->IN; /* collect PORT status event, if event is set read pins state. Processing is postponed to the * end of interrupt. */ if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT)) { nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK; input = nrf_gpio_pins_read(); } while (pins_changed) { // Check all users. for (i = 0; i < m_user_count; i++) { gpiote_user_t * p_user = &mp_users[i]; // Check if user is enabled. if (((1 << i) & m_enabled_users_mask) != 0) { uint32_t transition_pins; uint32_t event_low_to_high = 0; uint32_t event_high_to_low = 0; pins_sense_enabled |= (p_user->pins_mask & ~pins_sense_disabled); // Find set of pins on which there has been a transition. transition_pins = (pins_state ^ ~p_user->sense_high_pins) & (p_user->pins_mask & ~pins_sense_disabled); sense_level_disable(transition_pins); pins_sense_disabled |= transition_pins; pins_sense_enabled &= ~pins_sense_disabled; // Call user event handler if an event has occurred. event_high_to_low |= (~pins_state & p_user->pins_high_to_low_mask) & transition_pins; event_low_to_high |= (pins_state & p_user->pins_low_to_high_mask) & transition_pins; if ((event_low_to_high | event_high_to_low) != 0) { p_user->event_handler(event_low_to_high, event_high_to_low); } } } // Second read after setting sense. // Check if any pins with sense enabled have changed while serving this interrupt. pins_changed = (NRF_GPIO->IN ^ pins_state) & pins_sense_enabled; pins_state ^= pins_changed; } // Now re-enabling sense on all pins that have sense disabled. // Note: a new interrupt might fire immediatly. for (i = 0; i < m_user_count; i++) { gpiote_user_t * p_user = &mp_users[i]; // Check if user is enabled. if (((1 << i) & m_enabled_users_mask) != 0) { if (pins_sense_disabled & p_user->pins_mask) { sense_level_toggle(p_user, pins_sense_disabled & p_user->pins_mask); } } } /* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/ nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0; uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK; for (i = 0; i < NUMBER_OF_GPIO_TE; i++) { if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(mask)) { nrf_gpiote_event_clear(event); status |= mask; } mask <<= 1; /* Incrementing to next event, utilizing the fact that events are grouped together * in ascending order. */ event = (nrf_gpiote_events_t)((uint32_t)event + sizeof(uint32_t)); } /* collect PORT status event, if event is set read pins state. Processing is postponed to the * end of interrupt. */ if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT)) { nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK; input = nrf_gpio_pins_read(); } /* Process pin events. */ if (status & NRF_GPIOTE_INT_IN_MASK) { mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK; for (i = 0; i < NUMBER_OF_GPIO_TE; i++) { if (mask & status) { nrf_drv_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i); nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i); nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(i); handler(pin,polarity); } mask <<= 1; } } if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK) { /* Process port event. */ for (i = 0; i < GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++) { if (m_cb.port_handlers_pins[i] != PIN_NOT_USED) { uint8_t pin_and_sense = m_cb.port_handlers_pins[i]; nrf_drv_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK); nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin)); if (handler) { nrf_gpiote_polarity_t polarity = (nrf_gpiote_polarity_t)((pin_and_sense & SENSE_FIELD_MASK) >> SENSE_FIELD_POS); mask = 1 << pin; nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin); if (((mask & input) && (sense==NRF_GPIO_PIN_SENSE_HIGH)) || (!(mask & input) && (sense==NRF_GPIO_PIN_SENSE_LOW)) ) { if (polarity == NRF_GPIOTE_POLARITY_TOGGLE) { nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH; nrf_gpio_cfg_sense_set(pin, next_sense); } handler(pin, polarity); } } } } } } //lint -restore
비교하기