app_gpiote_fast_detect.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include "app_gpiote.h"
  13. #include <stdlib.h>
  14. #include "app_util_platform.h"
  15. #include "nrf_gpio.h"
  16. #include "sdk_common.h"
  17. #define NRF51_GPIOTE_CHANNEL 4
  18. #define NRF51_PINS 31
  19. #ifdef NRF51
  20. #define SWI_IRQHandler SWI1_IRQHandler
  21. #define SWI_IRQn SWI1_IRQn
  22. #elif defined NRF52
  23. #define SWI_IRQHandler SWI1_EGU1_IRQHAndler
  24. #define SWI_IRQn SWI1_EGU1_IRQn
  25. #endif
  26. /**@brief GPIOTE user type. */
  27. typedef struct
  28. {
  29. uint32_t pins_mask; /**< Mask defining which pins user wants to monitor. */
  30. uint32_t pins_low_to_high_mask; /**< Mask defining which pins will generate events to this user when toggling low->high. */
  31. uint32_t pins_high_to_low_mask; /**< Mask defining which pins will generate events to this user when toggling high->low. */
  32. uint32_t sense_high_pins; /**< Mask defining which pins are configured to generate GPIOTE interrupt on transition to high level. */
  33. app_gpiote_event_handler_t event_handler; /**< Pointer to function to be executed when an event occurs. */
  34. } gpiote_user_t;
  35. STATIC_ASSERT(sizeof (gpiote_user_t) <= GPIOTE_USER_NODE_SIZE);
  36. STATIC_ASSERT(sizeof (gpiote_user_t) % 4 == 0);
  37. static uint32_t m_enabled_users_mask; /**< Mask for tracking which users are enabled. */
  38. static uint8_t m_user_array_size; /**< Size of user array. */
  39. static uint8_t m_user_count; /**< Number of registered users. */
  40. static gpiote_user_t * mp_users = NULL; /**< Array of GPIOTE users. */
  41. #define MODULE_INITIALIZED (mp_users != NULL)
  42. #include "sdk_macros.h"
  43. static app_gpiote_input_event_handler_t m_app_gpiote_input_event_handlers[4] = {0};
  44. static app_gpiote_input_event_handler_t m_app_gpiote_end_irq_event_handler = NULL;
  45. /**@brief Function for toggling sense level for specified pins.
  46. *
  47. * @param[in] p_user Pointer to user structure.
  48. * @param[in] pins Bitmask specifying for which pins the sense level is to be toggled.
  49. */
  50. static void sense_level_toggle(gpiote_user_t * p_user, uint32_t pins)
  51. {
  52. uint32_t pin_no;
  53. for (pin_no = 0; pin_no < NO_OF_PINS; pin_no++)
  54. {
  55. uint32_t pin_mask = (1 << pin_no);
  56. if ((pins & pin_mask) != 0)
  57. {
  58. uint32_t sense;
  59. //Invert sensing.
  60. if ((p_user->sense_high_pins & pin_mask) == 0)
  61. {
  62. sense = GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos;
  63. p_user->sense_high_pins |= pin_mask;
  64. }
  65. else
  66. {
  67. sense = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos;
  68. p_user->sense_high_pins &= ~pin_mask;
  69. }
  70. NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk;
  71. NRF_GPIO->PIN_CNF[pin_no] |= sense;
  72. }
  73. }
  74. }
  75. /**@brief Function for handling the GPIOTE interrupt.
  76. */
  77. void GPIOTE_IRQHandler(void)
  78. {
  79. bool gpiote_in_evt = false;
  80. bool gpiote_port_evt = false;
  81. if ((NRF_GPIOTE->EVENTS_IN[0] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN0_Msk))
  82. {
  83. NRF_GPIOTE->EVENTS_IN[0] = 0;
  84. gpiote_in_evt = true;
  85. if (m_app_gpiote_input_event_handlers[0])
  86. {
  87. m_app_gpiote_input_event_handlers[0]();
  88. }
  89. }
  90. if ((NRF_GPIOTE->EVENTS_IN[1] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN1_Msk))
  91. {
  92. NRF_GPIOTE->EVENTS_IN[1] = 0;
  93. gpiote_in_evt = true;
  94. if (m_app_gpiote_input_event_handlers[1])
  95. {
  96. m_app_gpiote_input_event_handlers[1]();
  97. }
  98. }
  99. if ((NRF_GPIOTE->EVENTS_IN[2] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN2_Msk))
  100. {
  101. NRF_GPIOTE->EVENTS_IN[2] = 0;
  102. gpiote_in_evt = true;
  103. if (m_app_gpiote_input_event_handlers[2])
  104. {
  105. m_app_gpiote_input_event_handlers[2]();
  106. }
  107. }
  108. if ((NRF_GPIOTE->EVENTS_IN[3] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN3_Msk))
  109. {
  110. NRF_GPIOTE->EVENTS_IN[3] = 0;
  111. gpiote_in_evt = true;
  112. if (m_app_gpiote_input_event_handlers[3])
  113. {
  114. m_app_gpiote_input_event_handlers[3]();
  115. }
  116. }
  117. if ((NRF_GPIOTE->EVENTS_PORT == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_PORT_Msk))
  118. {
  119. //Clear event.
  120. NRF_GPIOTE->EVENTS_PORT = 0;
  121. gpiote_port_evt = true;
  122. }
  123. if (m_app_gpiote_end_irq_event_handler && gpiote_in_evt)
  124. {
  125. m_app_gpiote_end_irq_event_handler();
  126. }
  127. if (gpiote_port_evt)
  128. {
  129. NVIC_SetPendingIRQ(SWI_IRQn);
  130. }
  131. }
  132. /**@brief Function for handling the SWI1 interrupt.
  133. */
  134. void SWI_IRQHandler(void)
  135. {
  136. uint8_t i;
  137. uint32_t pins_changed;
  138. uint32_t pins_state = NRF_GPIO->IN;
  139. //Check all users.
  140. for (i = 0; i < m_user_count; i++)
  141. {
  142. gpiote_user_t * p_user = &mp_users[i];
  143. //Check if user is enabled.
  144. if (((1 << i) & m_enabled_users_mask) != 0)
  145. {
  146. uint32_t transition_pins;
  147. uint32_t event_low_to_high;
  148. uint32_t event_high_to_low;
  149. //Find set of pins on which there has been a transition.
  150. transition_pins = (pins_state ^ ~p_user->sense_high_pins) & p_user->pins_mask;
  151. //Toggle SENSE level for all pins that have changed state.
  152. sense_level_toggle(p_user, transition_pins);
  153. //Second read after setting sense.
  154. //Check if any pins have changed while serving this interrupt.
  155. pins_changed = NRF_GPIO->IN ^ pins_state;
  156. if (pins_changed)
  157. {
  158. //Transition pins detected in late stage.
  159. uint32_t late_transition_pins;
  160. pins_state |= pins_changed;
  161. //Find set of pins on which there has been a transition.
  162. late_transition_pins = (pins_state ^ ~p_user->sense_high_pins) & p_user->pins_mask;
  163. //Toggle SENSE level for all pins that have changed state in last phase.
  164. sense_level_toggle(p_user, late_transition_pins);
  165. //Update pins that has changed state since the interrupt occurred.
  166. transition_pins |= late_transition_pins;
  167. }
  168. //Call user event handler if an event has occurred.
  169. event_high_to_low = (~pins_state & p_user->pins_high_to_low_mask) & transition_pins;
  170. event_low_to_high = (pins_state & p_user->pins_low_to_high_mask) & transition_pins;
  171. if ((event_low_to_high | event_high_to_low) != 0)
  172. {
  173. p_user->event_handler(event_low_to_high, event_high_to_low);
  174. }
  175. }
  176. }
  177. }
  178. /**@brief Function for enabling interrupt SWI1.
  179. */
  180. static void app_gpiote_swi1_enable_irq(void)
  181. {
  182. NVIC_ClearPendingIRQ(SWI_IRQn);
  183. NVIC_SetPriority(SWI_IRQn, APP_IRQ_PRIORITY_LOW);
  184. NVIC_EnableIRQ(SWI_IRQn);
  185. }
  186. /**@brief Function for disabling interrupt SWI1.
  187. */
  188. static void app_gpiote_swi1_disable_irq(void)
  189. {
  190. NVIC_DisableIRQ(SWI_IRQn);
  191. }
  192. /**@brief Function for sense disabling for all pins for specified user.
  193. *
  194. * @param[in] user_id User id.
  195. */
  196. static void pins_sense_disable(app_gpiote_user_id_t user_id)
  197. {
  198. uint32_t pin_no;
  199. for (pin_no = 0; pin_no < 32; pin_no++)
  200. {
  201. if ((mp_users[user_id].pins_mask & (1 << pin_no)) != 0)
  202. {
  203. NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk;
  204. NRF_GPIO->PIN_CNF[pin_no] |= GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos;
  205. }
  206. }
  207. }
  208. uint32_t app_gpiote_init(uint8_t max_users, void * p_buffer)
  209. {
  210. if (p_buffer == NULL)
  211. {
  212. return NRF_ERROR_INVALID_PARAM;
  213. }
  214. //Check that buffer is correctly aligned.
  215. if (!is_word_aligned(p_buffer))
  216. {
  217. return NRF_ERROR_INVALID_PARAM;
  218. }
  219. //Initialize file globals.
  220. mp_users = (gpiote_user_t *)p_buffer;
  221. m_user_array_size = max_users;
  222. m_user_count = 0;
  223. m_enabled_users_mask = 0;
  224. memset(mp_users, 0, m_user_array_size * sizeof (gpiote_user_t));
  225. (void)app_gpiote_enable_interrupts();
  226. return NRF_SUCCESS;
  227. }
  228. uint32_t app_gpiote_user_register(app_gpiote_user_id_t * p_user_id,
  229. uint32_t pins_low_to_high_mask,
  230. uint32_t pins_high_to_low_mask,
  231. app_gpiote_event_handler_t event_handler)
  232. {
  233. //Check state and parameters.
  234. VERIFY_MODULE_INITIALIZED();
  235. if (event_handler == NULL)
  236. {
  237. return NRF_ERROR_INVALID_PARAM;
  238. }
  239. if (m_user_count >= m_user_array_size)
  240. {
  241. return NRF_ERROR_NO_MEM;
  242. }
  243. //Allocate new user.
  244. mp_users[m_user_count].pins_mask = pins_low_to_high_mask | pins_high_to_low_mask;
  245. mp_users[m_user_count].pins_low_to_high_mask = pins_low_to_high_mask;
  246. mp_users[m_user_count].pins_high_to_low_mask = pins_high_to_low_mask;
  247. mp_users[m_user_count].event_handler = event_handler;
  248. *p_user_id = m_user_count++;
  249. //Make sure SENSE is disabled for all pins.
  250. pins_sense_disable(*p_user_id);
  251. return NRF_SUCCESS;
  252. }
  253. uint32_t app_gpiote_enable_interrupts(void)
  254. {
  255. NVIC_ClearPendingIRQ(GPIOTE_IRQn);
  256. NVIC_SetPriority(GPIOTE_IRQn, APP_IRQ_PRIORITY_HIGH);
  257. NVIC_EnableIRQ(GPIOTE_IRQn);
  258. //Enable interrupt SWI1.
  259. app_gpiote_swi1_enable_irq();
  260. return NRF_SUCCESS;
  261. }
  262. uint32_t app_gpiote_disable_interrupts(void)
  263. {
  264. NVIC_DisableIRQ(GPIOTE_IRQn);
  265. //Disable interrupt SWI1.
  266. app_gpiote_swi1_disable_irq();
  267. return NRF_SUCCESS;
  268. }
  269. uint32_t app_gpiote_input_event_handler_register(const uint8_t channel,
  270. const uint32_t pin,
  271. const uint32_t polarity,
  272. app_gpiote_input_event_handler_t event_handler)
  273. {
  274. if (channel < NRF51_GPIOTE_CHANNEL && pin < NRF51_PINS)
  275. {
  276. NRF_GPIOTE->CONFIG[channel] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) |
  277. (pin << GPIOTE_CONFIG_PSEL_Pos) |
  278. (polarity << GPIOTE_CONFIG_POLARITY_Pos);
  279. switch (channel)
  280. {
  281. case 0:
  282. NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN0_Enabled << GPIOTE_INTENSET_IN0_Pos);
  283. break;
  284. case 1:
  285. NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN1_Enabled << GPIOTE_INTENSET_IN1_Pos);
  286. break;
  287. case 2:
  288. NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN2_Enabled << GPIOTE_INTENSET_IN2_Pos);
  289. break;
  290. case 3:
  291. NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN3_Enabled << GPIOTE_INTENSET_IN3_Pos);
  292. break;
  293. default:
  294. break;
  295. }
  296. m_app_gpiote_input_event_handlers[channel] = event_handler;
  297. return NRF_SUCCESS;
  298. }
  299. return NRF_ERROR_INVALID_PARAM;
  300. }
  301. uint32_t app_gpiote_input_event_handler_unregister(const uint8_t channel)
  302. {
  303. if (channel < NRF51_GPIOTE_CHANNEL)
  304. {
  305. const uint32_t pin_not_connected = 31UL;
  306. NRF_GPIOTE->CONFIG[channel] = (GPIOTE_CONFIG_MODE_Disabled << GPIOTE_CONFIG_MODE_Pos) |
  307. (pin_not_connected << GPIOTE_CONFIG_PSEL_Pos) |
  308. (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);
  309. switch (channel)
  310. {
  311. case 0:
  312. NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN0_Disabled << GPIOTE_INTENSET_IN0_Pos);
  313. break;
  314. case 1:
  315. NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN1_Disabled << GPIOTE_INTENSET_IN1_Pos);
  316. break;
  317. case 2:
  318. NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN2_Disabled << GPIOTE_INTENSET_IN2_Pos);
  319. break;
  320. case 3:
  321. NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN3_Disabled << GPIOTE_INTENSET_IN3_Pos);
  322. break;
  323. default:
  324. break;
  325. }
  326. m_app_gpiote_input_event_handlers[channel] = NULL;
  327. return NRF_SUCCESS;
  328. }
  329. return NRF_ERROR_INVALID_PARAM;
  330. }
  331. uint32_t app_gpiote_end_irq_event_handler_register(app_gpiote_input_event_handler_t event_handler)
  332. {
  333. m_app_gpiote_end_irq_event_handler = event_handler;
  334. return NRF_SUCCESS;
  335. }
  336. uint32_t app_gpiote_end_irq_event_handler_unregister(void)
  337. {
  338. m_app_gpiote_end_irq_event_handler = NULL;
  339. return NRF_SUCCESS;
  340. }
  341. uint32_t app_gpiote_user_enable(app_gpiote_user_id_t user_id)
  342. {
  343. uint32_t pin_no;
  344. uint32_t pins_state;
  345. //Check state and parameters.
  346. VERIFY_MODULE_INITIALIZED();
  347. if (user_id >= m_user_count)
  348. {
  349. return NRF_ERROR_INVALID_PARAM;
  350. }
  351. //Clear any pending event.
  352. NRF_GPIOTE->EVENTS_PORT = 0;
  353. pins_state = NRF_GPIO->IN;
  354. //Enable user.
  355. if (m_enabled_users_mask == 0)
  356. {
  357. NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;
  358. }
  359. m_enabled_users_mask |= (1 << user_id);
  360. //Enable sensing for all pins for specified user.
  361. mp_users[user_id].sense_high_pins = 0;
  362. for (pin_no = 0; pin_no < 32; pin_no++)
  363. {
  364. uint32_t pin_mask = (1 << pin_no);
  365. if ((mp_users[user_id].pins_mask & pin_mask) != 0)
  366. {
  367. uint32_t sense;
  368. if ((pins_state & pin_mask) != 0)
  369. {
  370. sense = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos;
  371. }
  372. else
  373. {
  374. sense = GPIO_PIN_CNF_SENSE_High <<
  375. GPIO_PIN_CNF_SENSE_Pos;
  376. mp_users[user_id].sense_high_pins |= pin_mask;
  377. }
  378. NRF_GPIO->PIN_CNF[pin_no] &= ~GPIO_PIN_CNF_SENSE_Msk;
  379. NRF_GPIO->PIN_CNF[pin_no] |= sense;
  380. }
  381. }
  382. return NRF_SUCCESS;
  383. }
  384. uint32_t app_gpiote_user_disable(app_gpiote_user_id_t user_id)
  385. {
  386. //Check state and parameters.
  387. VERIFY_MODULE_INITIALIZED();
  388. if (user_id >= m_user_count)
  389. {
  390. return NRF_ERROR_INVALID_PARAM;
  391. }
  392. //Disable sensing for all pins for specified user.
  393. pins_sense_disable(user_id);
  394. //Disable user.
  395. m_enabled_users_mask &= ~(1UL << user_id);
  396. if (m_enabled_users_mask == 0)
  397. {
  398. NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_PORT_Msk;
  399. }
  400. return NRF_SUCCESS;
  401. }
  402. uint32_t app_gpiote_pins_state_get(app_gpiote_user_id_t user_id, uint32_t * p_pins)
  403. {
  404. gpiote_user_t * p_user;
  405. //Check state and parameters.
  406. VERIFY_MODULE_INITIALIZED();
  407. if (user_id >= m_user_count)
  408. {
  409. return NRF_ERROR_INVALID_PARAM;
  410. }
  411. //Get pins.
  412. p_user = &mp_users[user_id];
  413. *p_pins = NRF_GPIO->IN & p_user->pins_mask;
  414. return NRF_SUCCESS;
  415. }