drv_usbh.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2017-10-30 ZYH the first version
  9. * 2019-12-19 tyustli port to stm32 series
  10. */
  11. #include "drv_usbh.h"
  12. #include "board.h"
  13. #define LOG_TAG "drv.usb.host"
  14. #define DBG_LVL DBG_INFO
  15. #include <drv_log.h>
  16. #include <usb_host.h>
  17. #include <completion.h>
  18. static HCD_HandleTypeDef stm32_hhcd_fs;
  19. static struct rt_completion urb_completion;
  20. static volatile rt_bool_t connect_status = RT_FALSE;
  21. void OTG_FS_IRQHandler(void)
  22. {
  23. rt_interrupt_enter();
  24. HAL_HCD_IRQHandler(&stm32_hhcd_fs);
  25. rt_interrupt_leave();
  26. }
  27. void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
  28. {
  29. uhcd_t hcd = (uhcd_t)hhcd->pData;
  30. if (!connect_status)
  31. {
  32. connect_status = RT_TRUE;
  33. LOG_D("usb connected");
  34. rt_usbh_root_hub_connect_handler(hcd, OTG_FS_PORT, RT_FALSE);
  35. }
  36. }
  37. void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
  38. {
  39. uhcd_t hcd = (uhcd_t)hhcd->pData;
  40. if (connect_status)
  41. {
  42. connect_status = RT_FALSE;
  43. LOG_D("usb disconnnect");
  44. rt_usbh_root_hub_disconnect_handler(hcd, OTG_FS_PORT);
  45. }
  46. }
  47. void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
  48. {
  49. rt_completion_done(&urb_completion);
  50. }
  51. static rt_err_t drv_reset_port(rt_uint8_t port)
  52. {
  53. LOG_D("reset port");
  54. HAL_HCD_ResetPort(&stm32_hhcd_fs);
  55. return RT_EOK;
  56. }
  57. static int drv_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
  58. {
  59. int timeout = timeouts;
  60. while (1)
  61. {
  62. if (!connect_status)
  63. {
  64. return -1;
  65. }
  66. rt_completion_init(&urb_completion);
  67. HAL_HCD_HC_SubmitRequest(&stm32_hhcd_fs,
  68. pipe->pipe_index,
  69. (pipe->ep.bEndpointAddress & 0x80) >> 7,
  70. pipe->ep.bmAttributes,
  71. token,
  72. buffer,
  73. nbytes,
  74. 0);
  75. rt_completion_wait(&urb_completion, timeout);
  76. rt_thread_mdelay(1);
  77. if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == HC_NAK)
  78. {
  79. LOG_D("nak");
  80. if (pipe->ep.bmAttributes == USB_EP_ATTR_INT)
  81. {
  82. rt_thread_delay((pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) > 0 ? (pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) : 1);
  83. }
  84. HAL_HCD_HC_Halt(&stm32_hhcd_fs, pipe->pipe_index);
  85. HAL_HCD_HC_Init(&stm32_hhcd_fs,
  86. pipe->pipe_index,
  87. pipe->ep.bEndpointAddress,
  88. pipe->inst->address,
  89. USB_OTG_SPEED_FULL,
  90. pipe->ep.bmAttributes,
  91. pipe->ep.wMaxPacketSize);
  92. continue;
  93. }
  94. else if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == HC_STALL)
  95. {
  96. LOG_D("stall");
  97. pipe->status = UPIPE_STATUS_STALL;
  98. if (pipe->callback != RT_NULL)
  99. {
  100. pipe->callback(pipe);
  101. }
  102. return -1;
  103. }
  104. else if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == URB_ERROR)
  105. {
  106. LOG_D("error");
  107. pipe->status = UPIPE_STATUS_ERROR;
  108. if (pipe->callback != RT_NULL)
  109. {
  110. pipe->callback(pipe);
  111. }
  112. return -1;
  113. }
  114. else if(URB_DONE == HAL_HCD_HC_GetURBState(&stm32_hhcd_fs, pipe->pipe_index))
  115. {
  116. LOG_D("ok");
  117. pipe->status = UPIPE_STATUS_OK;
  118. if (pipe->callback != RT_NULL)
  119. {
  120. pipe->callback(pipe);
  121. }
  122. size_t size = HAL_HCD_HC_GetXferCount(&stm32_hhcd_fs, pipe->pipe_index);
  123. if (pipe->ep.bEndpointAddress & 0x80)
  124. {
  125. return size;
  126. }
  127. else if (pipe->ep.bEndpointAddress & 0x00)
  128. {
  129. return size;
  130. }
  131. return nbytes;
  132. }
  133. continue;
  134. }
  135. }
  136. static rt_uint16_t pipe_index = 0;
  137. static rt_uint8_t drv_get_free_pipe_index(void)
  138. {
  139. rt_uint8_t idx;
  140. for (idx = 1; idx < 16; idx++)
  141. {
  142. if (!(pipe_index & (0x01 << idx)))
  143. {
  144. pipe_index |= (0x01 << idx);
  145. return idx;
  146. }
  147. }
  148. return 0xff;
  149. }
  150. static void drv_free_pipe_index(rt_uint8_t index)
  151. {
  152. pipe_index &= ~(0x01 << index);
  153. }
  154. static rt_err_t drv_open_pipe(upipe_t pipe)
  155. {
  156. pipe->pipe_index = drv_get_free_pipe_index();
  157. HAL_HCD_HC_Init(&stm32_hhcd_fs,
  158. pipe->pipe_index,
  159. pipe->ep.bEndpointAddress,
  160. pipe->inst->address,
  161. USB_OTG_SPEED_FULL,
  162. pipe->ep.bmAttributes,
  163. pipe->ep.wMaxPacketSize);
  164. /* Set DATA0 PID token*/
  165. if (stm32_hhcd_fs.hc[pipe->pipe_index].ep_is_in)
  166. {
  167. stm32_hhcd_fs.hc[pipe->pipe_index].toggle_in = 0;
  168. }
  169. else
  170. {
  171. stm32_hhcd_fs.hc[pipe->pipe_index].toggle_out = 0;
  172. }
  173. return RT_EOK;
  174. }
  175. static rt_err_t drv_close_pipe(upipe_t pipe)
  176. {
  177. HAL_HCD_HC_Halt(&stm32_hhcd_fs, pipe->pipe_index);
  178. drv_free_pipe_index(pipe->pipe_index);
  179. return RT_EOK;
  180. }
  181. static struct uhcd_ops _uhcd_ops =
  182. {
  183. drv_reset_port,
  184. drv_pipe_xfer,
  185. drv_open_pipe,
  186. drv_close_pipe,
  187. };
  188. static rt_err_t stm32_hcd_init(rt_device_t device)
  189. {
  190. HAL_StatusTypeDef state;
  191. HCD_HandleTypeDef *hhcd = (HCD_HandleTypeDef *)device->user_data;
  192. hhcd->Instance = USB_OTG_FS;
  193. hhcd->Init.Host_channels = 8;
  194. hhcd->Init.speed = HCD_SPEED_FULL;
  195. hhcd->Init.dma_enable = DISABLE;
  196. hhcd->Init.phy_itface = HCD_PHY_EMBEDDED;
  197. hhcd->Init.Sof_enable = DISABLE;
  198. state = HAL_HCD_Init(hhcd);
  199. if (state != HAL_OK)
  200. {
  201. return -RT_ERROR;
  202. }
  203. HAL_HCD_Start(hhcd);
  204. #ifdef USBH_USING_CONTROLLABLE_POWER
  205. rt_pin_mode(USBH_POWER_PIN, PIN_MODE_OUTPUT);
  206. rt_pin_write(USBH_POWER_PIN, PIN_LOW);
  207. #endif
  208. return RT_EOK;
  209. }
  210. int stm_usbh_register(void)
  211. {
  212. rt_err_t res = -RT_ERROR;
  213. uhcd_t uhcd = (uhcd_t)rt_malloc(sizeof(struct uhcd));
  214. if (uhcd == RT_NULL)
  215. {
  216. rt_kprintf("uhcd malloc failed\r\n");
  217. return -RT_ERROR;
  218. }
  219. rt_memset((void *)uhcd, 0, sizeof(struct uhcd));
  220. uhcd->parent.type = RT_Device_Class_USBHost;
  221. uhcd->parent.init = stm32_hcd_init;
  222. uhcd->parent.user_data = &stm32_hhcd_fs;
  223. uhcd->ops = &_uhcd_ops;
  224. uhcd->num_ports = OTG_FS_PORT;
  225. stm32_hhcd_fs.pData = uhcd;
  226. res = rt_device_register(&uhcd->parent, "usbh", RT_DEVICE_FLAG_DEACTIVATE);
  227. if (res != RT_EOK)
  228. {
  229. rt_kprintf("register usb host failed res = %d\r\n", res);
  230. return -RT_ERROR;
  231. }
  232. rt_usb_host_init("usbh");
  233. return RT_EOK;
  234. }
  235. INIT_DEVICE_EXPORT(stm_usbh_register);