drv_gpio.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2021-07-23 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if (defined(BSP_USING_GPIO) && defined(RT_USING_PIN))
  14. #include <rtdevice.h>
  15. #include <rthw.h>
  16. #include "drv_common.h"
  17. #include <drv_gpio.h>
  18. #include "nu_bitutil.h"
  19. #include "stdlib.h"
  20. /* Private define ---------------------------------------------------------------*/
  21. #define PORT_OFFSET 0x40
  22. #define IRQ_MAX_NUM 16 //Max support 32
  23. /* Private functions ------------------------------------------------------------*/
  24. static void nu_gpio_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode);
  25. static void nu_gpio_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value);
  26. static rt_int8_t nu_gpio_read(struct rt_device *device, rt_base_t pin);
  27. static rt_err_t nu_gpio_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint8_t mode, void (*hdr)(void *args), void *args);
  28. static rt_err_t nu_gpio_detach_irq(struct rt_device *device, rt_int32_t pin);
  29. static rt_err_t nu_gpio_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled);
  30. static rt_base_t nu_gpio_pin_get(const char *name);
  31. /* Private variables ------------------------------------------------------------*/
  32. static struct rt_pin_irq_hdr pin_irq_hdr_tab[IRQ_MAX_NUM];
  33. static struct rt_pin_ops nu_gpio_ops =
  34. {
  35. nu_gpio_mode,
  36. nu_gpio_write,
  37. nu_gpio_read,
  38. nu_gpio_attach_irq,
  39. nu_gpio_detach_irq,
  40. nu_gpio_irq_enable,
  41. nu_gpio_pin_get,
  42. };
  43. static IRQn_Type au32GPIRQ[NU_PORT_CNT] = {GPA_IRQn, GPB_IRQn, GPC_IRQn, GPD_IRQn, GPE_IRQn, GPF_IRQn, GPG_IRQn, GPH_IRQn, GPI_IRQn, GPJ_IRQn, GPK_IRQn, GPL_IRQn, GPM_IRQn, GPN_IRQn};
  44. static rt_uint32_t g_u32PinIrqMask = 0x0;
  45. /* Functions define ------------------------------------------------------------*/
  46. static rt_err_t nu_port_check(rt_int32_t pin)
  47. {
  48. if (NU_GET_PORT(pin) >= NU_PORT_CNT)
  49. return -(RT_ERROR);
  50. return RT_EOK;
  51. }
  52. static rt_int32_t nu_find_irqindex(rt_uint32_t pin_index)
  53. {
  54. rt_int32_t irqindex;
  55. rt_int32_t u32PinIrqStatus = g_u32PinIrqMask;
  56. // Find index of pin is attached in pool.
  57. while ((irqindex = nu_ctz(u32PinIrqStatus)) < IRQ_MAX_NUM) // Count Trailing Zeros ==> Find First One
  58. {
  59. if (pin_irq_hdr_tab[irqindex].pin == pin_index)
  60. return irqindex;
  61. u32PinIrqStatus &= ~(1 << irqindex);
  62. }
  63. return -(RT_ERROR);
  64. }
  65. static void pin_irq_hdr(rt_uint32_t irq_status, rt_uint32_t port_index)
  66. {
  67. rt_int32_t irqindex, i;
  68. rt_int32_t pinindex = port_index * GPIO_PIN_MAX ;
  69. while ((i = nu_ctz(irq_status)) < GPIO_PIN_MAX)// Count Trailing Zeros ==> Find First One
  70. {
  71. int pin_mask = (1 << i);
  72. irqindex = nu_find_irqindex(pinindex + i);
  73. if (irqindex != -(RT_ERROR))
  74. {
  75. if (pin_irq_hdr_tab[irqindex].hdr)
  76. {
  77. pin_irq_hdr_tab[irqindex].hdr(pin_irq_hdr_tab[irqindex].args);
  78. }
  79. }
  80. // Clear the served bit.
  81. irq_status &= ~pin_mask;
  82. }
  83. }
  84. static rt_base_t nu_gpio_pin_get(const char *name)
  85. {
  86. /* Get pin number by name,such as PA.0, PF12 */
  87. if ((name[2] == '\0') || ((name[2] == '.') && (name[3] == '\0')))
  88. return -(RT_EINVAL);
  89. long number;
  90. if ((name[2] == '.'))
  91. number = atol(&name[3]);
  92. else
  93. number = atol(&name[2]);
  94. if (number > 15)
  95. return -(RT_EINVAL);
  96. if (name[1] >= 'A' && name[1] <= 'N')
  97. return ((name[1] - 'A') * 0x10) + number;
  98. if (name[1] >= 'a' && name[1] <= 'n')
  99. return ((name[1] - 'a') * 0x10) + number;
  100. return -(RT_EINVAL);
  101. }
  102. static void nu_gpio_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
  103. {
  104. GPIO_T *PORT;
  105. if (nu_port_check(pin))
  106. return;
  107. PORT = (GPIO_T *)(GPIOA_BASE + (NU_GET_PORT(pin) * PORT_OFFSET));
  108. if (mode == PIN_MODE_INPUT_PULLUP)
  109. {
  110. GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_INPUT);
  111. GPIO_SetPullCtl(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_PUSEL_PULL_UP);
  112. }
  113. else if (mode == PIN_MODE_INPUT_PULLDOWN)
  114. {
  115. GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_INPUT);
  116. GPIO_SetPullCtl(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_PUSEL_PULL_DOWN);
  117. }
  118. else if (mode == PIN_MODE_OUTPUT)
  119. {
  120. GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_OUTPUT);
  121. }
  122. else if (mode == PIN_MODE_INPUT)
  123. {
  124. GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_INPUT);
  125. GPIO_SetPullCtl(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_PUSEL_DISABLE);
  126. }
  127. else if (mode == PIN_MODE_OUTPUT_OD)
  128. {
  129. GPIO_SetMode(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_MODE_OPEN_DRAIN);
  130. GPIO_SetPullCtl(PORT, NU_GET_PIN_MASK(NU_GET_PINS(pin)), GPIO_PUSEL_DISABLE);
  131. }
  132. }
  133. static void nu_gpio_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
  134. {
  135. if (nu_port_check(pin))
  136. return;
  137. GPIO_PIN_DATA(NU_GET_PORT(pin), NU_GET_PINS(pin)) = value;
  138. }
  139. static rt_int8_t nu_gpio_read(struct rt_device *device, rt_base_t pin)
  140. {
  141. if (nu_port_check(pin))
  142. return PIN_LOW;
  143. return GPIO_PIN_DATA(NU_GET_PORT(pin), NU_GET_PINS(pin));
  144. }
  145. static rt_err_t nu_gpio_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint8_t mode, void (*hdr)(void *args), void *args)
  146. {
  147. rt_base_t level;
  148. rt_int32_t irqindex;
  149. if (nu_port_check(pin))
  150. return -(RT_ERROR);
  151. level = rt_hw_interrupt_disable();
  152. // Find index of pin is attached in pool.
  153. if ((irqindex = nu_find_irqindex(pin)) >= 0)
  154. goto exit_nu_gpio_attach_irq;
  155. // Find available index of pin in pool.
  156. if ((irqindex = nu_cto(g_u32PinIrqMask)) < IRQ_MAX_NUM) // Count Trailing Ones ==> Find First Zero
  157. goto exit_nu_gpio_attach_irq;
  158. rt_hw_interrupt_enable(level);
  159. return -(RT_EBUSY);
  160. exit_nu_gpio_attach_irq:
  161. pin_irq_hdr_tab[irqindex].pin = pin;
  162. pin_irq_hdr_tab[irqindex].hdr = hdr;
  163. pin_irq_hdr_tab[irqindex].mode = mode;
  164. pin_irq_hdr_tab[irqindex].args = args;
  165. g_u32PinIrqMask |= (1 << irqindex);
  166. rt_hw_interrupt_enable(level);
  167. return RT_EOK;
  168. }
  169. static rt_err_t nu_gpio_detach_irq(struct rt_device *device, rt_int32_t pin)
  170. {
  171. rt_base_t level;
  172. rt_int32_t irqindex;
  173. rt_int32_t u32PinIrqStatus;
  174. if (nu_port_check(pin))
  175. return -(RT_ERROR);
  176. level = rt_hw_interrupt_disable();
  177. u32PinIrqStatus = g_u32PinIrqMask;
  178. // Find index of pin is attached in pool.
  179. while ((irqindex = nu_ctz(u32PinIrqStatus)) < IRQ_MAX_NUM)// Count Trailing Zeros ==> Find First One
  180. {
  181. if (pin_irq_hdr_tab[irqindex].pin == pin)
  182. {
  183. pin_irq_hdr_tab[irqindex].pin = PIN_IRQ_PIN_NONE;
  184. pin_irq_hdr_tab[irqindex].hdr = RT_NULL;
  185. pin_irq_hdr_tab[irqindex].mode = PIN_IRQ_MODE_RISING;
  186. pin_irq_hdr_tab[irqindex].args = RT_NULL;
  187. g_u32PinIrqMask &= ~(1 << irqindex);
  188. break;
  189. }
  190. u32PinIrqStatus &= ~(1 << irqindex);
  191. }
  192. rt_hw_interrupt_enable(level);
  193. return RT_EOK;
  194. }
  195. static void nu_gpio_isr(int vector, void *param)
  196. {
  197. rt_uint32_t int_status;
  198. GPIO_T *PORT = (GPIO_T *)param;
  199. rt_uint32_t port_idx = ((rt_uint32_t)PORT - GPIOA_BASE) / PORT_OFFSET ;
  200. int_status = PORT->INTSRC;
  201. pin_irq_hdr(int_status, port_idx);
  202. PORT->INTSRC = int_status;
  203. }
  204. static rt_err_t nu_gpio_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
  205. {
  206. GPIO_T *PORT;
  207. rt_base_t level;
  208. uint32_t u32IntAttribs;
  209. rt_int32_t irqindex;
  210. rt_err_t ret = RT_EOK;
  211. IRQn_Type irqn;
  212. if (nu_port_check(pin))
  213. return -(RT_ERROR);
  214. level = rt_hw_interrupt_disable();
  215. irqindex = nu_find_irqindex(pin);
  216. if (irqindex == -(RT_ERROR))
  217. {
  218. ret = -RT_ERROR;
  219. goto exit_nu_gpio_irq_enable;
  220. }
  221. PORT = (GPIO_T *)(GPIOA_BASE + (NU_GET_PORT(pin) * PORT_OFFSET));
  222. irqn = au32GPIRQ[NU_GET_PORT(pin)];
  223. if (enabled == PIN_IRQ_ENABLE)
  224. {
  225. if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_RISING)
  226. u32IntAttribs = GPIO_INT_RISING;
  227. else if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_FALLING)
  228. u32IntAttribs = GPIO_INT_FALLING;
  229. else if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_RISING_FALLING)
  230. u32IntAttribs = GPIO_INT_BOTH_EDGE;
  231. else if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_HIGH_LEVEL)
  232. u32IntAttribs = GPIO_INT_HIGH;
  233. else if (pin_irq_hdr_tab[irqindex].mode == PIN_IRQ_MODE_LOW_LEVEL)
  234. u32IntAttribs = GPIO_INT_LOW;
  235. else
  236. goto exit_nu_gpio_irq_enable;
  237. GPIO_EnableInt(PORT, NU_GET_PINS(pin), u32IntAttribs);
  238. rt_hw_interrupt_umask(irqn);
  239. }
  240. else
  241. {
  242. GPIO_DisableInt(PORT, NU_GET_PINS(pin));
  243. rt_hw_interrupt_mask(irqn);
  244. }
  245. exit_nu_gpio_irq_enable:
  246. rt_hw_interrupt_enable(level);
  247. return -(ret);
  248. }
  249. int rt_hw_gpio_init(void)
  250. {
  251. char szTmp[16];
  252. int i;
  253. rt_int32_t irqindex;
  254. for (irqindex = 0; irqindex < IRQ_MAX_NUM ; irqindex++)
  255. {
  256. pin_irq_hdr_tab[irqindex].pin = PIN_IRQ_PIN_NONE;
  257. pin_irq_hdr_tab[irqindex].hdr = RT_NULL;
  258. pin_irq_hdr_tab[irqindex].mode = PIN_IRQ_MODE_RISING;
  259. pin_irq_hdr_tab[irqindex].args = RT_NULL;
  260. }
  261. for (i = 0; i < NU_PORT_CNT ; i++)
  262. {
  263. IRQn_Type irqn = au32GPIRQ[i];
  264. rt_snprintf(szTmp, sizeof(szTmp), "gpio-%d", i);
  265. rt_hw_interrupt_install(irqn, nu_gpio_isr, (void *)(GPIOA_BASE + (i * PORT_OFFSET)), szTmp);
  266. }
  267. return rt_device_pin_register("gpio", &nu_gpio_ops, RT_NULL);
  268. }
  269. INIT_BOARD_EXPORT(rt_hw_gpio_init);
  270. #endif //#if (defined(BSP_USING_GPIO) && defined(RT_USING_PIN))