drv_usb.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. * File : drv_usb.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2015, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2017-10-30 ZYH the first version
  13. * 2017-11-15 ZYH update to 3.0.0
  14. */
  15. #include "drv_usb.h"
  16. #include <rtthread.h>
  17. #include <rtdevice.h>
  18. #include "board.h"
  19. #define USB_DISCONNECT_PIN 30 //PA9
  20. static PCD_HandleTypeDef _stm_pcd;
  21. static struct udcd _stm_udc;
  22. static struct ep_id _ep_pool[] =
  23. {
  24. {0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED },
  25. {0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED},
  26. {0x1, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED},
  27. {0x2, USB_EP_ATTR_INT, USB_DIR_OUT, 64, ID_UNASSIGNED},
  28. {0x2, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED},
  29. {0x3, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED},
  30. {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED },
  31. };
  32. void USB_LP_CAN1_RX0_IRQHandler(void)
  33. {
  34. rt_interrupt_enter();
  35. HAL_PCD_IRQHandler(&_stm_pcd);
  36. rt_interrupt_leave();
  37. }
  38. void HAL_PCD_ResetCallback(PCD_HandleTypeDef *pcd)
  39. {
  40. /* open ep0 OUT and IN */
  41. HAL_PCD_EP_Open(pcd, 0x00, 0x40, EP_TYPE_CTRL);
  42. HAL_PCD_EP_Open(pcd, 0x80, 0x40, EP_TYPE_CTRL);
  43. rt_usbd_reset_handler(&_stm_udc);
  44. }
  45. void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
  46. {
  47. rt_usbd_ep0_setup_handler(&_stm_udc, (struct urequest*)hpcd->Setup);
  48. }
  49. void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  50. {
  51. if (epnum == 0)
  52. {
  53. rt_usbd_ep0_in_handler(&_stm_udc);
  54. }
  55. else
  56. {
  57. rt_usbd_ep_in_handler(&_stm_udc, 0x80|epnum,hpcd->IN_ep[epnum].xfer_count);
  58. }
  59. }
  60. void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
  61. {
  62. rt_usbd_connect_handler(&_stm_udc);
  63. }
  64. void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
  65. {
  66. // rt_usbd_sof_handler(&_stm_udc);
  67. }
  68. void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
  69. {
  70. rt_usbd_disconnect_handler(&_stm_udc);
  71. }
  72. void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  73. {
  74. if (epnum != 0)
  75. {
  76. rt_usbd_ep_out_handler(&_stm_udc, epnum, hpcd->OUT_ep[epnum].xfer_count);
  77. }
  78. else
  79. {
  80. rt_usbd_ep0_out_handler(&_stm_udc,hpcd->OUT_ep[0].xfer_count);
  81. }
  82. }
  83. void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state)
  84. {
  85. if(state == 1)
  86. {
  87. rt_pin_write(USB_DISCONNECT_PIN,PIN_HIGH);
  88. }
  89. else
  90. {
  91. rt_pin_write(USB_DISCONNECT_PIN,PIN_LOW);
  92. }
  93. }
  94. void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
  95. {
  96. if(pcdHandle->Instance==USB)
  97. {
  98. __HAL_RCC_GPIOA_CLK_ENABLE();
  99. rt_pin_mode(USB_DISCONNECT_PIN,PIN_MODE_OUTPUT);
  100. rt_pin_write(USB_DISCONNECT_PIN,PIN_LOW);
  101. /* Peripheral clock enable */
  102. __HAL_RCC_USB_CLK_ENABLE();
  103. /* Peripheral interrupt init */
  104. HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 5, 0);
  105. HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
  106. }
  107. }
  108. void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle)
  109. {
  110. if(pcdHandle->Instance==USB)
  111. {
  112. /* Peripheral clock disable */
  113. __HAL_RCC_USB_CLK_DISABLE();
  114. /* Peripheral interrupt Deinit*/
  115. HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
  116. }
  117. }
  118. static rt_err_t _ep_set_stall(rt_uint8_t address)
  119. {
  120. HAL_PCD_EP_SetStall(&_stm_pcd, address);
  121. return RT_EOK;
  122. }
  123. static rt_err_t _ep_clear_stall(rt_uint8_t address)
  124. {
  125. HAL_PCD_EP_ClrStall(&_stm_pcd, address);
  126. return RT_EOK;
  127. }
  128. static rt_err_t _set_address(rt_uint8_t address)
  129. {
  130. HAL_PCD_SetAddress(&_stm_pcd, address);
  131. return RT_EOK;
  132. }
  133. static rt_err_t _set_config(rt_uint8_t address)
  134. {
  135. return RT_EOK;
  136. }
  137. static rt_err_t _ep_enable(uep_t ep)
  138. {
  139. RT_ASSERT(ep != RT_NULL);
  140. RT_ASSERT(ep->ep_desc != RT_NULL);
  141. HAL_PCD_EP_Open(&_stm_pcd, ep->ep_desc->bEndpointAddress,
  142. ep->ep_desc->wMaxPacketSize, ep->ep_desc->bmAttributes);
  143. return RT_EOK;
  144. }
  145. static rt_err_t _ep_disable(uep_t ep)
  146. {
  147. RT_ASSERT(ep != RT_NULL);
  148. RT_ASSERT(ep->ep_desc != RT_NULL);
  149. HAL_PCD_EP_Close(&_stm_pcd, ep->ep_desc->bEndpointAddress);
  150. return RT_EOK;
  151. }
  152. static rt_size_t _ep_read(rt_uint8_t address, void *buffer)
  153. {
  154. rt_size_t size = 0;
  155. RT_ASSERT(buffer != RT_NULL);
  156. return size;
  157. }
  158. static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
  159. {
  160. HAL_PCD_EP_Receive(&_stm_pcd, address, buffer, size);
  161. return size;
  162. }
  163. static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
  164. {
  165. HAL_PCD_EP_Transmit(&_stm_pcd, address, buffer, size);
  166. return size;
  167. }
  168. static rt_err_t _ep0_send_status(void)
  169. {
  170. HAL_PCD_EP_Transmit(&_stm_pcd, 0x00, NULL, 0);
  171. return RT_EOK;
  172. }
  173. static rt_err_t _suspend(void)
  174. {
  175. return RT_EOK;
  176. }
  177. static rt_err_t _wakeup(void)
  178. {
  179. return RT_EOK;
  180. }
  181. static rt_err_t _init(rt_device_t device)
  182. {
  183. PCD_HandleTypeDef *pcd;
  184. /* Set LL Driver parameters */
  185. pcd = (PCD_HandleTypeDef*)device->user_data;
  186. pcd->Instance = USB;
  187. pcd->Init.dev_endpoints = 8;
  188. pcd->Init.speed = PCD_SPEED_FULL;
  189. pcd->Init.ep0_mps = DEP0CTL_MPS_8;
  190. pcd->Init.low_power_enable = DISABLE;
  191. pcd->Init.lpm_enable = DISABLE;
  192. pcd->Init.battery_charging_enable = DISABLE;
  193. /* Initialize LL Driver */
  194. HAL_PCD_Init(pcd);
  195. HAL_PCDEx_PMAConfig(pcd , 0x00 , PCD_SNG_BUF, 0x18);
  196. HAL_PCDEx_PMAConfig(pcd , 0x80 , PCD_SNG_BUF, 0x58);
  197. HAL_PCDEx_PMAConfig(pcd , 0x81 , PCD_SNG_BUF, 0x98);
  198. HAL_PCDEx_PMAConfig(pcd , 0x01 , PCD_SNG_BUF, 0x118);
  199. HAL_PCDEx_PMAConfig(pcd , 0x82 , PCD_SNG_BUF, 0xD8);
  200. HAL_PCDEx_PMAConfig(pcd , 0x02 , PCD_SNG_BUF, 0x158);
  201. HAL_PCDEx_PMAConfig(pcd , 0x83 , PCD_SNG_BUF, 0x198);
  202. HAL_PCD_Start(pcd);
  203. return RT_EOK;
  204. }
  205. const static struct udcd_ops _udc_ops =
  206. {
  207. _set_address,
  208. _set_config,
  209. _ep_set_stall,
  210. _ep_clear_stall,
  211. _ep_enable,
  212. _ep_disable,
  213. _ep_read_prepare,
  214. _ep_read,
  215. _ep_write,
  216. _ep0_send_status,
  217. _suspend,
  218. _wakeup,
  219. };
  220. int stm_usbd_register(void)
  221. {
  222. rt_memset((void *)&_stm_udc, 0, sizeof(struct udcd));
  223. _stm_udc.parent.type = RT_Device_Class_USBDevice;
  224. _stm_udc.parent.init = _init;
  225. _stm_udc.parent.user_data = &_stm_pcd;
  226. _stm_udc.ops = &_udc_ops;
  227. /* Register endpoint infomation */
  228. _stm_udc.ep_pool = _ep_pool;
  229. _stm_udc.ep0.id = &_ep_pool[0];
  230. rt_device_register((rt_device_t)&_stm_udc, "usbd", 0);
  231. rt_usb_device_init();
  232. return 0;
  233. }
  234. INIT_DEVICE_EXPORT(stm_usbd_register);