drv_gpio.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-06-16 guohp1128 first version
  9. */
  10. #include "drv_gpio.h"
  11. #ifdef RT_USING_PIN
  12. static const struct pin_index pins[] =
  13. {
  14. __NRF5X_PIN(0 , 0, 0 ),
  15. __NRF5X_PIN(1 , 0, 1 ),
  16. __NRF5X_PIN(2 , 0, 2 ),
  17. __NRF5X_PIN(3 , 0, 3 ),
  18. __NRF5X_PIN(4 , 0, 4 ),
  19. __NRF5X_PIN(5 , 0, 5 ),
  20. __NRF5X_PIN(6 , 0, 6 ),
  21. __NRF5X_PIN(7 , 0, 7 ),
  22. __NRF5X_PIN(8 , 0, 8 ),
  23. __NRF5X_PIN(9 , 0, 9 ),
  24. __NRF5X_PIN(10, 0, 10),
  25. __NRF5X_PIN(11, 0, 11),
  26. __NRF5X_PIN(12, 0, 12),
  27. __NRF5X_PIN(13, 0, 13),
  28. __NRF5X_PIN(14, 0, 14),
  29. __NRF5X_PIN(15, 0, 15),
  30. __NRF5X_PIN(16, 0, 16),
  31. __NRF5X_PIN(17, 0, 17),
  32. __NRF5X_PIN(18, 0, 18),
  33. __NRF5X_PIN(19, 0, 19),
  34. __NRF5X_PIN(20, 0, 20),
  35. __NRF5X_PIN(21, 0, 21),
  36. __NRF5X_PIN(22, 0, 22),
  37. __NRF5X_PIN(23, 0, 23),
  38. __NRF5X_PIN(24, 0, 24),
  39. __NRF5X_PIN(25, 0, 25),
  40. __NRF5X_PIN(26, 0, 26),
  41. __NRF5X_PIN(27, 0, 27),
  42. __NRF5X_PIN(28, 0, 28),
  43. __NRF5X_PIN(29, 0, 29),
  44. __NRF5X_PIN(30, 0, 30),
  45. __NRF5X_PIN(31, 0, 31),
  46. __NRF5X_PIN(32, 1, 0 ),
  47. __NRF5X_PIN(33, 1, 1 ),
  48. __NRF5X_PIN(34, 1, 2 ),
  49. __NRF5X_PIN(35, 1, 3 ),
  50. __NRF5X_PIN(36, 1, 4 ),
  51. __NRF5X_PIN(37, 1, 5 ),
  52. __NRF5X_PIN(38, 1, 6 ),
  53. __NRF5X_PIN(39, 1, 7 ),
  54. __NRF5X_PIN(40, 1, 8 ),
  55. __NRF5X_PIN(41, 1, 9 ),
  56. __NRF5X_PIN(42, 1, 10),
  57. __NRF5X_PIN(43, 1, 11),
  58. __NRF5X_PIN(44, 1, 12),
  59. __NRF5X_PIN(45, 1, 13),
  60. __NRF5X_PIN(46, 1, 14),
  61. __NRF5X_PIN(47, 1, 15),
  62. };
  63. /* EVENTS_IN[n](n=0..7) and EVENTS_PORT */
  64. static struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
  65. {
  66. {-1, 0, RT_NULL, RT_NULL},
  67. {-1, 0, RT_NULL, RT_NULL},
  68. {-1, 0, RT_NULL, RT_NULL},
  69. {-1, 0, RT_NULL, RT_NULL},
  70. {-1, 0, RT_NULL, RT_NULL},
  71. {-1, 0, RT_NULL, RT_NULL},
  72. {-1, 0, RT_NULL, RT_NULL},
  73. {-1, 0, RT_NULL, RT_NULL},
  74. {-1, 0, RT_NULL, RT_NULL},
  75. };
  76. #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
  77. /*pin: the number of pins*/
  78. static const struct pin_index *get_pin(uint8_t pin)
  79. {
  80. const struct pin_index *index;
  81. if (pin < ITEM_NUM(pins))
  82. {
  83. index = &pins[pin];
  84. if (index->index == -1)
  85. index = RT_NULL;
  86. }
  87. else
  88. {
  89. index = RT_NULL;
  90. }
  91. return index;
  92. };
  93. static void nrf5x_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
  94. {
  95. const struct pin_index *index;
  96. index = get_pin(pin);
  97. if (index == RT_NULL)
  98. {
  99. return;
  100. }
  101. nrf_gpio_pin_write(pin, value);
  102. }
  103. static int nrf5x_pin_read(rt_device_t dev, rt_base_t pin)
  104. {
  105. int value;
  106. const struct pin_index *index;
  107. value = PIN_LOW;
  108. index = get_pin(pin);
  109. if (index == RT_NULL)
  110. {
  111. return value;
  112. }
  113. value = nrf_gpio_pin_read(pin);
  114. return value;
  115. }
  116. static void nrf5x_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
  117. {
  118. const struct pin_index *index;
  119. index = get_pin(pin);
  120. if (index == RT_NULL)
  121. {
  122. return;
  123. }
  124. if (mode == PIN_MODE_OUTPUT)
  125. {
  126. /* output setting */
  127. nrf_gpio_cfg_output(pin);
  128. }
  129. else if (mode == PIN_MODE_INPUT)
  130. {
  131. /* input setting: not pull. */
  132. nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL);
  133. }
  134. else if (mode == PIN_MODE_INPUT_PULLUP)
  135. {
  136. /* input setting: pull up. */
  137. nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_PULLUP);
  138. }
  139. else if (mode == PIN_MODE_INPUT_PULLDOWN)
  140. {
  141. /* input setting: pull down. */
  142. nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_PULLDOWN);
  143. }
  144. else if (mode == PIN_MODE_OUTPUT_OD)
  145. {
  146. /* output setting: od. */
  147. nrf_gpio_cfg(
  148. pin,
  149. NRF_GPIO_PIN_DIR_OUTPUT,
  150. NRF_GPIO_PIN_INPUT_DISCONNECT,
  151. NRF_GPIO_PIN_NOPULL,
  152. NRF_GPIO_PIN_S0D1,
  153. NRF_GPIO_PIN_NOSENSE);
  154. }
  155. }
  156. static void pin_irq_hdr(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
  157. {
  158. int i;
  159. int irq_quantity;
  160. irq_quantity = ITEM_NUM(pin_irq_hdr_tab);
  161. for(i = 0; i < irq_quantity; i++)
  162. {
  163. if(pin_irq_hdr_tab[i].pin == pin)
  164. {
  165. pin_irq_hdr_tab[i].hdr(pin_irq_hdr_tab[i].args);
  166. }
  167. }
  168. }
  169. /* args = true : hi_accuracy(IN_EVENT)
  170. * args = false: lo_accuracy(PORT_EVENT)
  171. */
  172. static rt_err_t nrf5x_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
  173. rt_uint32_t mode, void (*hdr)(void *args), void *args)
  174. {
  175. const struct pin_index *index;
  176. rt_int32_t irqindex = -1;
  177. rt_base_t level;
  178. nrfx_err_t err_code;
  179. int i;
  180. int irq_quantity;
  181. index = get_pin(pin);
  182. if (index == RT_NULL)
  183. {
  184. return RT_ENOSYS;
  185. }
  186. irq_quantity = ITEM_NUM(pin_irq_hdr_tab);
  187. for(i = 0; i < irq_quantity; i++)
  188. {
  189. if(pin_irq_hdr_tab[i].pin != -1)
  190. {
  191. irqindex = -1;
  192. continue;
  193. }
  194. else
  195. {
  196. irqindex = i;
  197. break;
  198. }
  199. }
  200. if(irqindex == -1)
  201. {
  202. return RT_ENOMEM;
  203. }
  204. level = rt_hw_interrupt_disable();
  205. pin_irq_hdr_tab[irqindex].pin = pin;
  206. pin_irq_hdr_tab[irqindex].hdr = hdr;
  207. pin_irq_hdr_tab[irqindex].mode = mode;
  208. pin_irq_hdr_tab[irqindex].args = args;
  209. if(mode == PIN_IRQ_MODE_RISING)
  210. {
  211. nrfx_gpiote_in_config_t inConfig = NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(args);
  212. inConfig.pull = NRF_GPIO_PIN_PULLDOWN;
  213. err_code = nrfx_gpiote_in_init(pin, &inConfig, pin_irq_hdr);
  214. }
  215. else if(mode == PIN_IRQ_MODE_FALLING)
  216. {
  217. nrfx_gpiote_in_config_t inConfig = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(args);
  218. inConfig.pull = NRF_GPIO_PIN_PULLUP;
  219. err_code = nrfx_gpiote_in_init(pin, &inConfig, pin_irq_hdr);
  220. }
  221. else if(mode == PIN_IRQ_MODE_RISING_FALLING)
  222. {
  223. nrfx_gpiote_in_config_t inConfig = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(args);
  224. inConfig.pull = NRF_GPIO_PIN_PULLUP;
  225. err_code = nrfx_gpiote_in_init(pin, &inConfig, pin_irq_hdr);
  226. }
  227. rt_hw_interrupt_enable(level);
  228. switch(err_code)
  229. {
  230. case NRFX_ERROR_BUSY:
  231. return RT_EBUSY;
  232. case NRFX_SUCCESS:
  233. return RT_EOK;
  234. case NRFX_ERROR_NO_MEM:
  235. return RT_ENOMEM;
  236. default:
  237. return RT_ERROR;
  238. }
  239. }
  240. static rt_err_t nrf5x_pin_dettach_irq(struct rt_device *device, rt_int32_t pin)
  241. {
  242. const struct pin_index *index;
  243. rt_base_t level;
  244. int i;
  245. int irq_quantity;
  246. index = get_pin(pin);
  247. if (index == RT_NULL)
  248. {
  249. return RT_ENOSYS;
  250. }
  251. irq_quantity = ITEM_NUM(pin_irq_hdr_tab);
  252. for(i = 0; i < irq_quantity; i++)
  253. {
  254. if(pin_irq_hdr_tab[i].pin == pin)
  255. {
  256. level = rt_hw_interrupt_disable();
  257. pin_irq_hdr_tab[i].pin = -1;
  258. pin_irq_hdr_tab[i].hdr = RT_NULL;
  259. pin_irq_hdr_tab[i].mode = 0;
  260. pin_irq_hdr_tab[i].args = RT_NULL;
  261. nrfx_gpiote_in_uninit(pin);
  262. rt_hw_interrupt_enable(level);
  263. break;
  264. }
  265. }
  266. if(i >= irq_quantity)
  267. {
  268. return RT_ENOSYS;
  269. }
  270. return RT_EOK;
  271. }
  272. static rt_err_t nrf5x_pin_irq_enable(struct rt_device *device, rt_base_t pin,
  273. rt_uint32_t enabled)
  274. {
  275. const struct pin_index *index;
  276. rt_base_t level;
  277. int i;
  278. int irq_quantity;
  279. index = get_pin(pin);
  280. if (index == RT_NULL)
  281. {
  282. return RT_ENOSYS;
  283. }
  284. irq_quantity = ITEM_NUM(pin_irq_hdr_tab);
  285. for(i = 0; i < irq_quantity; i++)
  286. {
  287. if(pin_irq_hdr_tab[i].pin == pin)
  288. {
  289. level = rt_hw_interrupt_disable();
  290. if(enabled == PIN_IRQ_ENABLE)
  291. {
  292. nrfx_gpiote_in_event_enable(pin,enabled);
  293. }
  294. else if(enabled == PIN_IRQ_DISABLE)
  295. {
  296. nrfx_gpiote_in_event_disable(pin);
  297. }
  298. rt_hw_interrupt_enable(level);
  299. break;
  300. }
  301. }
  302. if(i >= irq_quantity)
  303. {
  304. return RT_ENOSYS;
  305. }
  306. return RT_EOK;
  307. }
  308. const static struct rt_pin_ops _nrf5x_pin_ops =
  309. {
  310. nrf5x_pin_mode,
  311. nrf5x_pin_write,
  312. nrf5x_pin_read,
  313. nrf5x_pin_attach_irq,
  314. nrf5x_pin_dettach_irq,
  315. nrf5x_pin_irq_enable,
  316. };
  317. int rt_hw_pin_init(void)
  318. {
  319. nrfx_err_t err_code;
  320. err_code = (nrfx_err_t)rt_device_pin_register("pin", &_nrf5x_pin_ops, RT_NULL);
  321. err_code = nrfx_gpiote_init(NRFX_GPIOTE_CONFIG_IRQ_PRIORITY);
  322. switch(err_code)
  323. {
  324. case NRFX_ERROR_INVALID_STATE:
  325. return RT_EINVAL;
  326. case NRFX_SUCCESS:
  327. return RT_EOK;
  328. default:
  329. return RT_ERROR;;
  330. }
  331. }
  332. #endif /* RT_USING_PIN */