drv_usbh.c 6.9 KB

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