drv_whc.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. * 2022-10-5 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_WHC)
  14. #include <rthw.h>
  15. #include "drv_whc.h"
  16. #include "drv_sys.h"
  17. #include "nu_bitutil.h"
  18. /* Private define ---------------------------------------------------------------*/
  19. enum
  20. {
  21. WHC_START = -1,
  22. #if defined(BSP_USING_WHC0)
  23. WHC0_IDX,
  24. #endif
  25. #if defined(BSP_USING_WHC1)
  26. WHC1_IDX,
  27. #endif
  28. WHC_CNT
  29. };
  30. /* Private typedef --------------------------------------------------------------*/
  31. struct nu_whc_priv
  32. {
  33. char *name;
  34. WHC_T *base;
  35. IRQn_Type irqn;
  36. uint32_t rstidx;
  37. rt_device_t psChDev[WHC_CH];
  38. };
  39. typedef struct nu_whc_priv *nu_whc_priv_t;
  40. struct nu_whc
  41. {
  42. struct rt_device dev;
  43. nu_whc_priv_t psPriv;
  44. uint32_t u32WhcChNum;
  45. void *pvTxBuf;
  46. };
  47. typedef struct nu_whc *nu_whc_t;
  48. static struct nu_whc_priv nu_whc_priv_arr [] =
  49. {
  50. #if defined(BSP_USING_WHC0)
  51. {
  52. .name = "whc0",
  53. .base = WHC0,
  54. .irqn = WHC0_IRQn,
  55. .rstidx = WHC0_RST,
  56. },
  57. #endif
  58. #if defined(BSP_USING_WHC1)
  59. {
  60. .name = "whc1",
  61. .base = WHC1,
  62. .irqn = WHC1_IRQn,
  63. .rstidx = WHC1_RST,
  64. },
  65. #endif
  66. }; /* nu_whc_priv */
  67. /**
  68. * All WHC interrupt service routine
  69. */
  70. static void nu_whc_isr(int vector, void *param)
  71. {
  72. nu_whc_priv_t psNuWhcPriv = (nu_whc_priv_t)param;
  73. volatile uint32_t vu32Intsts = psNuWhcPriv->base->INTSTS;
  74. uint32_t irqidx;
  75. while ((irqidx = nu_ctz(vu32Intsts)) != 32)
  76. {
  77. uint32_t u32IsrBitMask = 1 << irqidx ;
  78. switch (irqidx)
  79. {
  80. /* Process TX-complete interrupt event */
  81. case WHC_INTSTS_TX0IF_Pos:
  82. case WHC_INTSTS_TX1IF_Pos:
  83. case WHC_INTSTS_TX2IF_Pos:
  84. case WHC_INTSTS_TX3IF_Pos:
  85. {
  86. uint32_t u32ChNum = irqidx - WHC_INTSTS_TX0IF_Pos;
  87. rt_device_t device = psNuWhcPriv->psChDev[u32ChNum];
  88. nu_whc_t psWhc = (nu_whc_t)device;
  89. if (device->tx_complete && psWhc->pvTxBuf)
  90. {
  91. device->tx_complete(device, psWhc->pvTxBuf);
  92. psWhc->pvTxBuf = RT_NULL;
  93. }
  94. }
  95. break;
  96. /* Process RX-indicate interrupt event */
  97. case WHC_INTSTS_RX0IF_Pos:
  98. case WHC_INTSTS_RX1IF_Pos:
  99. case WHC_INTSTS_RX2IF_Pos:
  100. case WHC_INTSTS_RX3IF_Pos:
  101. {
  102. uint32_t u32ChNum = irqidx - WHC_INTSTS_RX0IF_Pos;
  103. rt_device_t device = psNuWhcPriv->psChDev[u32ChNum];
  104. if (device->rx_indicate)
  105. {
  106. device->rx_indicate(device, 1);
  107. }
  108. }
  109. break;
  110. default:
  111. break;
  112. }
  113. /* Clear interrupt bit. */
  114. WHC_CLR_INT_FLAG(psNuWhcPriv->base, u32IsrBitMask);
  115. /* Clear served bit */
  116. vu32Intsts &= ~(u32IsrBitMask);
  117. }
  118. }
  119. rt_err_t nu_whc_init(rt_device_t dev)
  120. {
  121. return RT_EOK;
  122. }
  123. rt_err_t nu_whc_open(rt_device_t dev, rt_uint16_t oflag)
  124. {
  125. nu_whc_t psWhc = (nu_whc_t)dev;
  126. nu_whc_priv_t psWhcPriv = psWhc->psPriv;
  127. WHC_ENABLE_INT(psWhcPriv->base, WHC_INTEN_TX0IEN_Msk << psWhc->u32WhcChNum |
  128. WHC_INTEN_RX0IEN_Msk << psWhc->u32WhcChNum);
  129. return RT_EOK;
  130. }
  131. rt_err_t nu_whc_close(rt_device_t dev)
  132. {
  133. nu_whc_t psWhc = (nu_whc_t)dev;
  134. nu_whc_priv_t psWhcPriv = psWhc->psPriv;
  135. WHC_DISABLE_INT(psWhcPriv->base, WHC_INTEN_TX0IEN_Msk << psWhc->u32WhcChNum |
  136. WHC_INTEN_RX0IEN_Msk << psWhc->u32WhcChNum);
  137. return RT_EOK;
  138. }
  139. rt_ssize_t nu_whc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  140. {
  141. nu_whc_t psWhc = (nu_whc_t)dev;
  142. nu_whc_priv_t psWhcPriv = psWhc->psPriv;
  143. if ((sizeof(nu_whc_msg) != size) || ((uint32_t)buffer & 0x3))
  144. goto exit_nu_whc_read;
  145. if (WHC_Recv(psWhcPriv->base, psWhc->u32WhcChNum, (uint32_t *)buffer) < 0)
  146. goto exit_nu_whc_read;
  147. return size;
  148. exit_nu_whc_read:
  149. return 0;
  150. }
  151. rt_ssize_t nu_whc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  152. {
  153. nu_whc_t psWhc = (nu_whc_t)dev;
  154. nu_whc_priv_t psWhcPriv = psWhc->psPriv;
  155. if ((sizeof(nu_whc_msg) != size) || ((uint32_t)buffer & 0x3))
  156. goto exit_nu_whc_write;
  157. psWhc->pvTxBuf = (void *)buffer;
  158. if (WHC_Send(psWhcPriv->base, psWhc->u32WhcChNum, (uint32_t *)buffer) < 0)
  159. goto exit_nu_whc_write;
  160. return size;
  161. exit_nu_whc_write:
  162. return 0;
  163. }
  164. rt_err_t nu_whc_control(rt_device_t dev, int cmd, void *args)
  165. {
  166. return RT_EOK;
  167. }
  168. static rt_err_t whc_register(nu_whc_priv_t psWhcPriv)
  169. {
  170. int i;
  171. char szDevName[16];
  172. for (i = 0; i < WHC_CH; i++)
  173. {
  174. nu_whc_t psWhc;
  175. rt_device_t device = rt_device_create(RT_Device_Class_Miscellaneous, sizeof(struct nu_whc) - sizeof(struct rt_device));
  176. RT_ASSERT(device);
  177. psWhcPriv->psChDev[i] = device;
  178. psWhc = (nu_whc_t)device;
  179. psWhc->psPriv = psWhcPriv;
  180. psWhc->u32WhcChNum = i;
  181. device->type = RT_Device_Class_Miscellaneous;
  182. device->rx_indicate = RT_NULL;
  183. device->tx_complete = RT_NULL;
  184. #ifdef RT_USING_DEVICE_OPS
  185. device->ops = RT_NULL;
  186. #else
  187. device->init = nu_whc_init;
  188. device->open = nu_whc_open;
  189. device->close = nu_whc_close;
  190. device->read = nu_whc_read;
  191. device->write = nu_whc_write;
  192. device->control = nu_whc_control;
  193. #endif
  194. device->user_data = (void *)psWhcPriv;
  195. rt_snprintf(szDevName, sizeof(szDevName), "%s-%d", psWhcPriv->name, psWhc->u32WhcChNum);
  196. RT_ASSERT(rt_device_register(device, szDevName, RT_DEVICE_FLAG_STANDALONE) == RT_EOK);
  197. }
  198. return RT_EOK;
  199. }
  200. /**
  201. * Hardware Sem Initialization
  202. */
  203. int rt_hw_whc_init(void)
  204. {
  205. int i;
  206. for (i = (WHC_START + 1); i < WHC_CNT; i++)
  207. {
  208. nu_whc_priv_t psNuWhcPriv = &nu_whc_priv_arr[i];
  209. whc_register(psNuWhcPriv);
  210. rt_hw_interrupt_install(psNuWhcPriv->irqn, nu_whc_isr, psNuWhcPriv, psNuWhcPriv->name);
  211. rt_hw_interrupt_umask(nu_whc_priv_arr[i].irqn);
  212. }
  213. return 0;
  214. }
  215. INIT_BOARD_EXPORT(rt_hw_whc_init);
  216. #endif //#if defined(BSP_USING_WHC)