usbh_hal.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. // Copyright 2020 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #pragma once
  15. #ifdef __cplusplus
  16. extern "C" {
  17. #endif
  18. /*
  19. NOTE: Thread safety is the responsibility fo the HAL user. All USB Host HAL
  20. functions must be called from critical sections unless specified otherwise
  21. */
  22. #include <stdlib.h>
  23. #include <stddef.h>
  24. #include "soc/usbh_struct.h"
  25. #include "soc/usb_wrap_struct.h"
  26. #include "hal/usbh_ll.h"
  27. #include "hal/usb_types_private.h"
  28. #include "hal/assert.h"
  29. // ------------------------------------------------ Macros and Types ---------------------------------------------------
  30. // ------------------ Constants/Configs --------------------
  31. #define USBH_HAL_DMA_MEM_ALIGN 512
  32. #define USBH_HAL_FRAME_LIST_MEM_ALIGN 512 //The frame list needs to be 512 bytes aligned (contrary to the databook)
  33. #define USBH_HAL_NUM_CHAN 8
  34. #define USBH_HAL_XFER_DESC_SIZE (sizeof(usbh_ll_dma_qtd_t))
  35. #define USBH_HAL_FIFO_TOTAL_USABLE_LINES 200 //Although we have a 256 lines, only 200 lines are usuable due to EPINFO_CTL
  36. /**
  37. * @brief FIFO size configuration structure
  38. */
  39. typedef struct {
  40. uint32_t rx_fifo_lines; /**< Size of the RX FIFO in terms the number of FIFO lines */
  41. uint32_t nptx_fifo_lines; /**< Size of the Non-periodic FIFO in terms the number of FIFO lines */
  42. uint32_t ptx_fifo_lines; /**< Size of the Periodic FIFO in terms the number of FIFO lines */
  43. } usbh_hal_fifo_config_t;
  44. // --------------------- HAL States ------------------------
  45. /**
  46. * @brief Channel states
  47. */
  48. typedef enum {
  49. USBH_HAL_CHAN_STATE_HALTED = 0, /**< The channel is halted. No transfer descriptor list is being executed */
  50. USBH_HAL_CHAN_STATE_ACTIVE, /**< The channel is active. A transfer descriptor list is being executed */
  51. USBH_HAL_CHAN_STATE_ERROR, /**< The channel is in the error state */
  52. } usbh_hal_chan_state_t;
  53. // --------------------- HAL Events ------------------------
  54. /**
  55. * @brief Host port HAL events
  56. */
  57. typedef enum {
  58. USBH_HAL_PORT_EVENT_NONE, /**< No event occurred, or could not decode interrupt */
  59. USBH_HAL_PORT_EVENT_CHAN, /**< A channel event has occurred. Call the the channel event handler instead */
  60. USBH_HAL_PORT_EVENT_CONN, /**< The host port has detected a connection */
  61. USBH_HAL_PORT_EVENT_DISCONN, /**< The host port has been disconnected */
  62. USBH_HAL_PORT_EVENT_ENABLED, /**< The host port has been enabled (i.e., connected to a device that has been reset. Started sending SOFs) */
  63. USBH_HAL_PORT_EVENT_DISABLED, /**< The host port has been disabled (no more SOFs). Could be due to disable/reset request, or a port error (e.g. port babble condition. See 11.8.1 of USB2.0 spec) */
  64. USBH_HAL_PORT_EVENT_OVRCUR, /**< The host port has encountered an overcurrent condition */
  65. USBH_HAL_PORT_EVENT_OVRCUR_CLR, /**< The host port has been cleared of the overcurrent condition */
  66. } usbh_hal_port_event_t;
  67. /**
  68. * @brief Channel events
  69. */
  70. typedef enum {
  71. USBH_HAL_CHAN_EVENT_CPLT, /**< The channel has completed execution of a transfer descriptor that had the USBH_HAL_XFER_DESC_FLAG_HOC flag set. Channel is now halted */
  72. USBH_HAL_CHAN_EVENT_ERROR, /**< The channel has encountered an error. Channel is now halted. */
  73. USBH_HAL_CHAN_EVENT_HALT_REQ, /**< The channel has been successfully halted as requested */
  74. USBH_HAL_CHAN_EVENT_NONE, /**< No event (interrupt ran for internal processing) */
  75. } usbh_hal_chan_event_t;
  76. // --------------------- HAL Errors ------------------------
  77. /**
  78. * @brief Channel errors
  79. */
  80. typedef enum {
  81. USBH_HAL_CHAN_ERROR_XCS_XACT = 0, /**< Excessive (three consecutive) transaction errors (e.g., no response, bad CRC etc */
  82. USBH_HAL_CHAN_ERROR_BNA, /**< Buffer Not Available error (i.e., An inactive transfer descriptor was fetched by the channel) */
  83. USBH_HAL_CHAN_ERROR_PKT_BBL, /**< Packet babbler error (packet exceeded MPS) */
  84. USBH_HAL_CHAN_ERROR_STALL, /**< STALL response received */
  85. } usbh_hal_chan_error_t;
  86. // ------------- Transfer Descriptor Related ---------------
  87. /**
  88. * @brief Flags used to describe the type of transfer descriptor to fill
  89. */
  90. #define USBH_HAL_XFER_DESC_FLAG_IN 0x01 /**< Indicates this transfer descriptor is of the IN direction */
  91. #define USBH_HAL_XFER_DESC_FLAG_SETUP 0x02 /**< Indicates this transfer descriptor is an OUT setup */
  92. #define USBH_HAL_XFER_DESC_FLAG_HOC 0x04 /**< Indicates that the channel will be halted after this transfer descriptor completes */
  93. /**
  94. * @brief Status value of a transfer descriptor
  95. *
  96. * A transfer descriptor's status remains unexecuted until the entire transfer descriptor completes (either successfully
  97. * or an error). Therefore, if a channel halt is requested before a transfer descriptor completes, the transfer
  98. * descriptor remains unexecuted.
  99. */
  100. #define USBH_HAL_XFER_DESC_STS_SUCCESS USBH_LL_QTD_STATUS_SUCCESS
  101. #define USBH_HAL_XFER_DESC_STS_PKTERR USBH_LL_QTD_STATUS_PKTERR
  102. #define USBH_HAL_XFER_DESC_STS_BUFFER_ERR USBH_LL_QTD_STATUS_BUFFER
  103. #define USBH_HAL_XFER_DESC_STS_NOT_EXECUTED USBH_LL_QTD_STATUS_NOT_EXECUTED
  104. // -------------------- Object Types -----------------------
  105. /**
  106. * @brief Endpoint characteristics structure
  107. */
  108. typedef struct {
  109. union {
  110. struct {
  111. usb_priv_xfer_type_t type: 2; /**< The type of endpoint */
  112. uint32_t bEndpointAddress: 8; /**< Endpoint address (containing endpoint number and direction) */
  113. uint32_t mps: 11; /**< Maximum Packet Size */
  114. uint32_t dev_addr: 8; /**< Device Address */
  115. uint32_t ls_via_fs_hub: 1; /**< The endpoint is on a LS device that is routed through an FS hub.
  116. Setting this bit will lead to the addition of the PREamble packet */
  117. uint32_t reserved2: 2;
  118. };
  119. uint32_t val;
  120. };
  121. struct {
  122. usb_hal_interval_t interval; /**< The interval of the endpoint */
  123. uint32_t phase_offset_frames; /**< Phase offset in number of frames */
  124. } periodic; /**< Characteristic for periodic (interrupt/isochronous) endpoints only */
  125. } usbh_hal_ep_char_t;
  126. /**
  127. * @brief Channel object
  128. */
  129. typedef struct {
  130. //Channel control, status, and information
  131. union {
  132. struct {
  133. uint32_t active: 1; /**< Debugging bit to indicate whether channel is enabled */
  134. uint32_t halt_requested: 1; /**< A halt has been requested */
  135. uint32_t error_pending: 1; /**< The channel is waiting for the error to be handled */
  136. uint32_t reserved: 1;
  137. uint32_t chan_idx: 4; /**< The index number of the channel */
  138. uint32_t reserved24: 24;
  139. };
  140. uint32_t val;
  141. } flags; /**< Flags regarding channel's status and information */
  142. usb_host_chan_regs_t *regs; /**< Pointer to the channel's register set */
  143. usbh_hal_chan_error_t error; /**< The last error that occurred on the channel */
  144. usb_priv_xfer_type_t type; /**< The transfer type of the channel */
  145. void *chan_ctx; /**< Context variable for the owner of the channel */
  146. } usbh_hal_chan_t;
  147. /**
  148. * @brief HAL context structure
  149. */
  150. typedef struct {
  151. //Context
  152. usbh_dev_t *dev; /**< Pointer to base address of DWC_OTG registers */
  153. usb_wrap_dev_t *wrap_dev; /**< Pointer to base address of USB Wrapper registers */
  154. //Host Port related
  155. uint32_t *periodic_frame_list; /**< Pointer to scheduling frame list */
  156. usb_hal_frame_list_len_t frame_list_len; /**< Length of the periodic scheduling frame list */
  157. union {
  158. struct {
  159. uint32_t dbnc_lock_enabled: 1; /**< Debounce lock enabled */
  160. uint32_t fifo_sizes_set: 1; /**< Whether the FIFO sizes have been set or not */
  161. uint32_t periodic_sched_enabled: 1; /**< Periodic scheduling (for interrupt and isochronous transfers) is enabled */
  162. uint32_t reserved: 5;
  163. uint32_t reserved24: 24;
  164. };
  165. uint32_t val;
  166. } flags;
  167. //Channel related
  168. struct {
  169. int num_allocd; /**< Number of channels currently allocated */
  170. uint32_t chan_pend_intrs_msk; /**< Bit mask of channels with pending interrupts */
  171. usbh_hal_chan_t *hdls[USBH_HAL_NUM_CHAN]; /**< Handles of each channel. Set to NULL if channel has not been allocated */
  172. } channels;
  173. } usbh_hal_context_t;
  174. // -------------------------------------------------- Core (Global) ----------------------------------------------------
  175. /**
  176. * @brief Initialize the HAL context and check if DWC_OTG is alive
  177. *
  178. * Entry:
  179. * - The peripheral must have been reset and clock un-gated
  180. * - GPIO pins configured
  181. * - Interrupt allocated but DISABLED (in case of an unknown interupt state)
  182. * Exit:
  183. * - Checks to see if DWC_OTG is alive, and if HW version/config is correct
  184. * - HAl context initialized
  185. * - Sets default values to some global and OTG registers (GAHBCFG and GUSBCFG)
  186. * - Umask global interrupt signal
  187. * - Put DWC_OTG into host mode. Require 25ms delay before this takes effect.
  188. * - State -> USBH_HAL_PORT_STATE_OTG
  189. * - Interrupts cleared. Users can now enable their ISR
  190. *
  191. * @param[inout] hal Context of the HAL layer
  192. */
  193. void usbh_hal_init(usbh_hal_context_t *hal);
  194. /**
  195. * @brief Deinitialize the HAL context
  196. *
  197. * Entry:
  198. * - All channels must be properly disabled, and any pending events handled
  199. * Exit:
  200. * - DWC_OTG global interrupt disabled
  201. * - HAL context deinitialized
  202. *
  203. * @param hal Context of the HAL layer
  204. */
  205. void usbh_hal_deinit(usbh_hal_context_t *hal);
  206. /**
  207. * @brief Issue a soft reset to the controller
  208. *
  209. * This should be called when the host port encounters an error event or has been disconnected. Before calling this,
  210. * users are responsible for safely freeing all channels as a soft reset will wipe all host port and channel registers.
  211. * This function will result in the host port being put back into same state as after calling usbh_hal_init().
  212. *
  213. * @note This has nothing to do with a USB bus reset. It simply resets the peripheral
  214. *
  215. * @param hal Context of the HAL layer
  216. */
  217. void usbh_hal_core_soft_reset(usbh_hal_context_t *hal);
  218. /**
  219. * @brief Set FIFO sizes
  220. *
  221. * This function will set the sizes of each of the FIFOs (RX FIFO, Non-periodic TX FIFO, Periodic TX FIFO) and must be
  222. * called at least once before allocating the channel. Based on the type of endpoints (and the endpionts' MPS), there
  223. * may be situations where this function may need to be called again to resize the FIFOs. If resizing FIFOs dynamically,
  224. * it is the user's responsibility to ensure there are no active channels when this function is called.
  225. *
  226. * @note The totol size of all the FIFOs must be less than or equal to USBH_HAL_FIFO_TOTAL_USABLE_LINES
  227. * @note After a port reset, the FIFO size registers will reset to their default values, so this function must be called
  228. * again post reset.
  229. *
  230. * @param hal Context of the HAL layer
  231. * @param fifo_config FIFO configuration
  232. */
  233. void usbh_hal_set_fifo_size(usbh_hal_context_t *hal, const usbh_hal_fifo_config_t *fifo_config);
  234. // ---------------------------------------------------- Host Port ------------------------------------------------------
  235. // ------------------ Host Port Control --------------------
  236. /**
  237. * @brief Initialize the host port
  238. *
  239. * - Will enable the host port's interrupts allowing port and channel events to occur
  240. *
  241. * @param hal Context of the HAL layer
  242. */
  243. static inline void usbh_hal_port_init(usbh_hal_context_t *hal)
  244. {
  245. //Configure Host related interrupts
  246. usbh_ll_haintmsk_dis_chan_intr(hal->dev, 0xFFFFFFFF); //Disable interrupts for all channels
  247. usb_ll_en_intrs(hal->dev, USB_LL_INTR_CORE_PRTINT | USB_LL_INTR_CORE_HCHINT);
  248. }
  249. /**
  250. * @brief Deinitialize the host port
  251. *
  252. * - Will disable the host port's interrupts preventing further port aand channel events from ocurring
  253. *
  254. * @param hal Context of the HAL layer
  255. */
  256. static inline void usbh_hal_port_deinit(usbh_hal_context_t *hal)
  257. {
  258. //Disable Host port and channel interrupts
  259. usb_ll_dis_intrs(hal->dev, USB_LL_INTR_CORE_PRTINT | USB_LL_INTR_CORE_HCHINT);
  260. }
  261. /**
  262. * @brief Toggle the host port's power
  263. *
  264. * @param hal Context of the HAL layer
  265. * @param power_on Whether to power ON or OFF the port
  266. */
  267. static inline void usbh_hal_port_toggle_power(usbh_hal_context_t *hal, bool power_on)
  268. {
  269. if (power_on) {
  270. usbh_ll_hprt_en_pwr(hal->dev);
  271. } else {
  272. usbh_ll_hprt_dis_pwr(hal->dev);
  273. }
  274. }
  275. /**
  276. * @brief Toggle reset signal on the bus
  277. *
  278. * The reset signal should be held for at least 10ms
  279. * Entry:
  280. * - Host port detects a device connection or Host port is already enabled
  281. * Exit:
  282. * - On release of the reset signal, a USBH_HAL_PORT_EVENT_ENABLED will be generated
  283. *
  284. * @note If the host port is already enabled, then issuing a reset will cause it be disabled and generate a
  285. * USBH_HAL_PORT_EVENT_DISABLED event. The host port will not be enabled until the reset signal is released (thus
  286. * generating the USBH_HAL_PORT_EVENT_ENABLED event)
  287. *
  288. * @param hal Context of the HAL layer
  289. * @param enable Enable/disable reset signal
  290. */
  291. static inline void usbh_hal_port_toggle_reset(usbh_hal_context_t *hal, bool enable)
  292. {
  293. HAL_ASSERT(hal->channels.num_allocd == 0); //Cannot reset if there are still allocated channels
  294. usbh_ll_hprt_set_port_reset(hal->dev, enable);
  295. }
  296. /**
  297. * @brief Enable the host port
  298. *
  299. * Entry:
  300. * - Host port enabled event triggered following a reset
  301. * Exit:
  302. * - Host port enabled to operate in scatter/gather DMA mode
  303. * - DMA fifo sizes configured
  304. *
  305. * @param hal Context of the HAL layer
  306. */
  307. void usbh_hal_port_enable(usbh_hal_context_t *hal);
  308. /**
  309. * @brief Disable the host port
  310. *
  311. * Exit:
  312. * - Host port disabled event triggered
  313. *
  314. * @param hal Context of the HAL layer
  315. */
  316. static inline void usbh_hal_port_disable(usbh_hal_context_t *hal)
  317. {
  318. usbh_ll_hprt_port_dis(hal->dev);
  319. }
  320. /**
  321. * @brief Suspend the host port
  322. *
  323. * @param hal Context of the HAL layers
  324. */
  325. static inline void usbh_hal_port_suspend(usbh_hal_context_t *hal)
  326. {
  327. usbh_ll_hprt_set_port_suspend(hal->dev);
  328. }
  329. /**
  330. * @brief Toggle resume signal on the bus
  331. *
  332. * Hosts should hold the resume signal for at least 20ms
  333. *
  334. * @note If a remote wakeup event occurs, the resume signal is driven and cleared automatically.
  335. *
  336. * @param hal Context of the HAL layer
  337. * @param enable Enable/disable resume signal
  338. */
  339. static inline void usbh_hal_port_toggle_resume(usbh_hal_context_t *hal, bool enable)
  340. {
  341. if (enable) {
  342. usbh_ll_hprt_set_port_resume(hal->dev);
  343. } else {
  344. usbh_ll_hprt_clr_port_resume(hal->dev);
  345. }
  346. }
  347. /**
  348. * @brief Check whether the resume signal is being driven
  349. *
  350. * If a remote wakeup event occurs, the core will automatically drive and clear the resume signal for the required
  351. * amount of time. Call this function to check whether the resume signal has completed.
  352. *
  353. * @param hal Context of the HAL layer
  354. * @return true Resume signal is still being driven
  355. * @return false Resume signal is no longer driven
  356. */
  357. static inline bool usbh_hal_port_check_resume(usbh_hal_context_t *hal)
  358. {
  359. return usbh_ll_hprt_get_port_resume(hal->dev);
  360. }
  361. // ---------------- Host Port Scheduling -------------------
  362. /**
  363. * @brief Sets the periodic scheduling frame list
  364. *
  365. * @note This function must be called before attempting configuring any channels to be period via
  366. * usbh_hal_chan_set_ep_char()
  367. *
  368. * @param hal Context of the HAL layer
  369. * @param frame_list Base address of the frame list
  370. * @param frame_list_len Number of entries in the frame list (can only be 8, 16, 32, 64)
  371. */
  372. static inline void usbh_hal_port_set_frame_list(usbh_hal_context_t *hal, uint32_t *frame_list, usb_hal_frame_list_len_t len)
  373. {
  374. //Clear and save frame list
  375. hal->periodic_frame_list = frame_list;
  376. hal->frame_list_len = len;
  377. }
  378. /**
  379. * @brief Get the pointer to the periodic scheduling frame list
  380. *
  381. * @param hal Context of the HAL layer
  382. * @return uint32_t* Base address of the periodic scheduling frame list
  383. */
  384. static inline uint32_t *usbh_hal_port_get_frame_list(usbh_hal_context_t *hal)
  385. {
  386. return hal->periodic_frame_list;
  387. }
  388. /**
  389. * @brief Enable periodic scheduling
  390. *
  391. * @note The periodic frame list must be set via usbh_hal_port_set_frame_list() should be set before calling this
  392. * function
  393. * @note This function must be called before activating any periodic channels
  394. *
  395. * @param hal Context of the HAL layer
  396. */
  397. static inline void usbh_hal_port_periodic_enable(usbh_hal_context_t *hal)
  398. {
  399. HAL_ASSERT(hal->periodic_frame_list != NULL);
  400. usbh_ll_set_frame_list_base_addr(hal->dev, (uint32_t)hal->periodic_frame_list);
  401. usbh_ll_hcfg_set_num_frame_list_entries(hal->dev, hal->frame_list_len);
  402. usbh_ll_hcfg_en_perio_sched(hal->dev);
  403. hal->flags.periodic_sched_enabled = 1;
  404. }
  405. /**
  406. * @brief Disable periodic scheduling
  407. *
  408. * Disabling periodic scheduling will save a bit of DMA bandwith (as the controller will no longer fetch the schedule
  409. * from the frame list).
  410. *
  411. * @note Before disabling periodic scheduling, it is the user's responsibility to ensure that all periodic channels have
  412. * halted safely.
  413. *
  414. * @param hal Context of the HAL layer
  415. */
  416. static inline void usbh_hal_port_periodic_disable(usbh_hal_context_t *hal)
  417. {
  418. HAL_ASSERT(hal->flags.periodic_sched_enabled);
  419. usbh_ll_hcfg_dis_perio_sched(hal->dev);
  420. hal->flags.periodic_sched_enabled = 0;
  421. }
  422. static inline uint32_t usbh_hal_port_get_cur_frame_num(usbh_hal_context_t *hal)
  423. {
  424. return usbh_ll_get_frm_num(hal->dev);
  425. }
  426. // --------------- Host Port Status/State ------------------
  427. /**
  428. * @brief Check if a device is currently connected to the host port
  429. *
  430. * This function is intended to be called after one of the following events followed by an adequate debounce delay
  431. * - USBH_HAL_PORT_EVENT_CONN
  432. * - USBH_HAL_PORT_EVENT_DISCONN
  433. *
  434. * @note No other connection/disconnection event will occur again until the debounce lock is disabled via
  435. * usbh_hal_disable_debounce_lock()
  436. *
  437. * @param hal Context of the HAL layer
  438. * @return true A device is connected to the host port
  439. * @return false A device is not connected to the host port
  440. */
  441. static inline bool usbh_hal_port_check_if_connected(usbh_hal_context_t *hal)
  442. {
  443. return usbh_ll_hprt_get_conn_status(hal->dev);
  444. }
  445. /**
  446. * @brief Check the speed (LS/FS) of the device connected to the host port
  447. *
  448. * @note This function should only be called after confirming that a device is connected to the host port
  449. *
  450. * @param hal Context of the HAL layer
  451. * @return usb_priv_speed_t Speed of the connected device (FS or LS only on the esp32-s2 and esp32-s3)
  452. */
  453. static inline usb_priv_speed_t usbh_hal_port_get_conn_speed(usbh_hal_context_t *hal)
  454. {
  455. return usbh_ll_hprt_get_speed(hal->dev);
  456. }
  457. /**
  458. * @brief Disable the debounce lock
  459. *
  460. * This function must be called after calling usbh_hal_port_check_if_connected() and will allow connection/disconnection
  461. * events to occur again. Any pending connection or disconenction interrupts are cleared.
  462. *
  463. * @param hal Context of the HAL layer
  464. */
  465. static inline void usbh_hal_disable_debounce_lock(usbh_hal_context_t *hal)
  466. {
  467. hal->flags.dbnc_lock_enabled = 0;
  468. //Clear Conenction and disconenction interrupt in case it triggered again
  469. usb_ll_intr_clear(hal->dev, USB_LL_INTR_CORE_DISCONNINT);
  470. usbh_ll_hprt_intr_clear(hal->dev, USBH_LL_INTR_HPRT_PRTENCHNG);
  471. //Reenable the hprt (connection) and disconnection interrupts
  472. usb_ll_en_intrs(hal->dev, USB_LL_INTR_CORE_PRTINT | USB_LL_INTR_CORE_DISCONNINT);
  473. }
  474. // ----------------------------------------------------- Channel -------------------------------------------------------
  475. // ----------------- Channel Allocation --------------------
  476. /**
  477. * @brief Allocate a channel
  478. *
  479. * @param[in] hal Context of the HAL layer
  480. * @param[inout] chan_obj Empty channel object
  481. * @param[in] chan_ctx Context variable for the allocator of the channel
  482. * @return true Channel successfully allocated
  483. * @return false Failed to allocate channel
  484. */
  485. bool usbh_hal_chan_alloc(usbh_hal_context_t *hal, usbh_hal_chan_t *chan_obj, void *chan_ctx);
  486. /**
  487. * @brief Free a channel
  488. *
  489. * @param[in] hal Context of the HAL layer
  490. * @param[in] chan_obj Channel object
  491. */
  492. void usbh_hal_chan_free(usbh_hal_context_t *hal, usbh_hal_chan_t *chan_obj);
  493. // ---------------- Channel Configuration ------------------
  494. /**
  495. * @brief Get the context variable of the channel
  496. *
  497. * @param[in] chan_obj Channel object
  498. * @return void* The context variable of the channel
  499. */
  500. static inline void *usbh_hal_chan_get_context(usbh_hal_chan_t *chan_obj)
  501. {
  502. return chan_obj->chan_ctx;
  503. }
  504. /**
  505. * @brief Get the current state of a channel
  506. *
  507. * @param chan_obj Channel object
  508. * @return usbh_hal_chan_state_t State of the channel
  509. */
  510. static inline usbh_hal_chan_state_t usbh_hal_chan_get_state(usbh_hal_chan_t *chan_obj)
  511. {
  512. if (chan_obj->flags.error_pending) {
  513. return USBH_HAL_CHAN_STATE_ERROR;
  514. } else if (chan_obj->flags.active) {
  515. return USBH_HAL_CHAN_STATE_ACTIVE;
  516. } else {
  517. return USBH_HAL_CHAN_STATE_HALTED;
  518. }
  519. }
  520. /**
  521. * @brief Set the endpoint information for a particular channel
  522. *
  523. * This should be called when a channel switches target from one EP to another
  524. *
  525. * @note the channel must be in the disabled state in order to change its EP
  526. * information
  527. *
  528. * @param hal Context of the HAL layer
  529. * @param chan_obj Channel object
  530. * @param ep_char Endpoint characteristics
  531. */
  532. void usbh_hal_chan_set_ep_char(usbh_hal_context_t *hal, usbh_hal_chan_t *chan_obj, usbh_hal_ep_char_t *ep_char);
  533. /**
  534. * @brief Set the direction of the channel
  535. *
  536. * This is a convenience function to flip the direction of a channel without
  537. * needing to reconfigure all of the channel's EP info. This is used primarily
  538. * for control transfers.
  539. *
  540. * @note This function should only be called when the channel is halted
  541. *
  542. * @param chan_obj Channel object
  543. * @param is_in Whether the direction is IN
  544. */
  545. static inline void usbh_hal_chan_set_dir(usbh_hal_chan_t *chan_obj, bool is_in)
  546. {
  547. //Cannot change direction whilst channel is still active or in error
  548. HAL_ASSERT(!chan_obj->flags.active && !chan_obj->flags.error_pending);
  549. usbh_ll_chan_set_dir(chan_obj->regs, is_in);
  550. }
  551. /**
  552. * @brief Set the next Packet ID of the channel (e.g., DATA0/DATA1)
  553. *
  554. * This should be called when a channel switches target from one EP to another
  555. * or when change stages for a control transfer
  556. *
  557. * @note The channel should only be called when the channel is in the
  558. * halted state.
  559. *
  560. * @param chan_obj Channel object
  561. * @param pid PID of the next DATA packet (DATA0 or DATA1)
  562. */
  563. static inline void usbh_hal_chan_set_pid(usbh_hal_chan_t *chan_obj, int pid)
  564. {
  565. //Cannot change pid whilst channel is still active or in error
  566. HAL_ASSERT(!chan_obj->flags.active && !chan_obj->flags.error_pending);
  567. //Update channel object and set the register
  568. usbh_ll_chan_set_pid(chan_obj->regs, pid);
  569. }
  570. /**
  571. * @brief Get the next PID of a channel
  572. *
  573. * Returns the next PID (DATA0 or DATA1) of the channel. This function should be
  574. * used when the next PID of a pipe needs to be saved (e.g., when switching pipes
  575. * on a channel)
  576. *
  577. * @param chan_obj Channel object
  578. * @return uint32_t Starting PID of the next transfer (DATA0 or DATA1)
  579. */
  580. static inline uint32_t usbh_hal_chan_get_pid(usbh_hal_chan_t *chan_obj)
  581. {
  582. HAL_ASSERT(!chan_obj->flags.active && !chan_obj->flags.error_pending);
  583. return usbh_ll_chan_get_pid(chan_obj->regs);
  584. }
  585. // ------------------- Channel Control ---------------------
  586. /**
  587. * @brief Activate a channel
  588. *
  589. * Activating a channel will cause the channel to start executing transfer descriptors.
  590. *
  591. * @note This function should only be called on channels that were previously halted
  592. * @note An event will be generated when the channel is halted
  593. *
  594. * @param chan_obj Channel object
  595. * @param xfer_desc_list A filled transfer descriptor list
  596. * @param desc_list_len Transfer descriptor list length
  597. * @param start_idx Index of the starting transfer descriptor in the list
  598. */
  599. void usbh_hal_chan_activate(usbh_hal_chan_t *chan_obj, void *xfer_desc_list, int desc_list_len, int start_idx);
  600. /**
  601. * @brief Get the index of the current transfer descriptor
  602. *
  603. * @param chan_obj Channel object
  604. * @return int Descriptor index
  605. */
  606. static inline int usbh_hal_chan_get_qtd_idx(usbh_hal_chan_t *chan_obj)
  607. {
  608. return usbh_ll_chan_get_ctd(chan_obj->regs);
  609. }
  610. /**
  611. * @brief Request to halt a channel
  612. *
  613. * This function should be called in order to halt a channel. If the channel is already halted, this function will
  614. * return true. If the channel is still active, this function will return false and users must wait for the
  615. * USBH_HAL_CHAN_EVENT_HALT_REQ event before treating the channel as halted.
  616. *
  617. * @note When a transfer is in progress (i.e., the channel is active) and a halt is requested, the channel will halt
  618. * after the next USB packet is completed. If the transfer has more pending packets, the transfer will just be
  619. * marked as USBH_HAL_XFER_DESC_STS_NOT_EXECUTED.
  620. *
  621. * @param chan_obj Channel object
  622. * @return true The channel is already halted
  623. * @return false The halt was requested, wait for USBH_HAL_CHAN_EVENT_HALT_REQ
  624. */
  625. bool usbh_hal_chan_request_halt(usbh_hal_chan_t *chan_obj);
  626. /**
  627. * @brief Get a channel's error
  628. *
  629. * @param chan_obj Channel object
  630. * @return usbh_hal_chan_error_t The type of error the channel has encountered
  631. */
  632. static inline usbh_hal_chan_error_t usbh_hal_chan_get_error(usbh_hal_chan_t *chan_obj)
  633. {
  634. HAL_ASSERT(chan_obj->flags.error_pending);
  635. return chan_obj->error;
  636. }
  637. /**
  638. * @brief Clear a channel of it's error
  639. *
  640. * @param chan_obj Channel object
  641. */
  642. static inline void usbh_hal_chan_clear_error(usbh_hal_chan_t *chan_obj)
  643. {
  644. //Can only clear error when an error has occurred
  645. HAL_ASSERT(chan_obj->flags.error_pending);
  646. chan_obj->flags.error_pending = 0;
  647. }
  648. // -------------------------------------------- Transfer Descriptor List -----------------------------------------------
  649. /**
  650. * @brief Fill a single entry in a transfer descriptor list
  651. *
  652. * - Depending on the transfer type, a single transfer descriptor may corresponds
  653. * - A stage of a transfer (for control transfers)
  654. * - A frame of a transfer interval (for interrupt and isoc)
  655. * - An entire transfer (for bulk transfers)
  656. * - Check the various USBH_HAL_XFER_DESC_FLAG_ flags for filling a specific type of descriptor
  657. * - For IN transfer entries, set the USBH_HAL_XFER_DESC_FLAG_IN. The transfer size must also be an integer multiple of
  658. * the endpoint's MPS
  659. *
  660. * @note Critical section is not required for this function
  661. *
  662. * @param desc_list Transfer descriptor list
  663. * @param desc_idx Transfer descriptor index
  664. * @param xfer_data_buff Transfer data buffer
  665. * @param xfer_len Transfer length
  666. * @param flags Transfer flags
  667. */
  668. static inline void usbh_hal_xfer_desc_fill(void *desc_list, uint32_t desc_idx, uint8_t *xfer_data_buff, int xfer_len, uint32_t flags)
  669. {
  670. usbh_ll_dma_qtd_t *qtd_list = (usbh_ll_dma_qtd_t *)desc_list;
  671. if (flags & USBH_HAL_XFER_DESC_FLAG_IN) {
  672. usbh_ll_set_qtd_in(&qtd_list[desc_idx],
  673. xfer_data_buff, xfer_len,
  674. flags & USBH_HAL_XFER_DESC_FLAG_HOC);
  675. } else {
  676. usbh_ll_set_qtd_out(&qtd_list[desc_idx],
  677. xfer_data_buff,
  678. xfer_len,
  679. flags & USBH_HAL_XFER_DESC_FLAG_HOC,
  680. flags & USBH_HAL_XFER_DESC_FLAG_SETUP);
  681. }
  682. }
  683. /**
  684. * @brief Clear a transfer descriptor (sets all its fields to NULL)
  685. *
  686. * @param desc_list Transfer descriptor list
  687. * @param desc_idx Transfer descriptor index
  688. */
  689. static inline void usbh_hal_xfer_desc_clear(void *desc_list, uint32_t desc_idx)
  690. {
  691. usbh_ll_dma_qtd_t *qtd_list = (usbh_ll_dma_qtd_t *)desc_list;
  692. usbh_ll_set_qtd_null(&qtd_list[desc_idx]);
  693. }
  694. /**
  695. * @brief Parse a transfer decriptor's results
  696. *
  697. * @param desc_list Transfer descriptor list
  698. * @param desc_idx Transfer descriptor index
  699. * @param[out] xfer_rem_len Remaining length of the transfer in bytes
  700. * @param[out] xfer_status Status of the transfer
  701. *
  702. * @note Critical section is not required for this function
  703. */
  704. static inline void usbh_hal_xfer_desc_parse(void *desc_list, uint32_t desc_idx, int *xfer_rem_len, int *xfer_status)
  705. {
  706. usbh_ll_dma_qtd_t *qtd_list = (usbh_ll_dma_qtd_t *)desc_list;
  707. usbh_ll_get_qtd_status(&qtd_list[desc_idx], xfer_rem_len, xfer_status);
  708. //Clear the QTD to prevent it from being read again
  709. usbh_ll_set_qtd_null(&qtd_list[desc_idx]);
  710. }
  711. // ------------------------------------------------- Event Handling ----------------------------------------------------
  712. /**
  713. * @brief Decode global and host port interrupts
  714. *
  715. * - Reads and clears global and host port interrupt registers
  716. * - Decodes the interrupt bits to determine what host port event occurred
  717. *
  718. * @note This should be the first interrupt decode function to be run
  719. *
  720. * @param hal Context of the HAL layer
  721. * @return usbh_hal_port_event_t Host port event
  722. */
  723. usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal);
  724. /**
  725. * @brief Gets the next channel with a pending interrupt
  726. *
  727. * If no channel is pending an interrupt, this function will return NULL. If one or more channels are pending an
  728. * interrupt, this function returns one of the channel's objects. Call this function repeatedly until it returns NULL.
  729. *
  730. * @param hal Context of the HAL layer
  731. * @return usbh_hal_chan_t* Channel object. NULL if no channel are pending an interrupt.
  732. */
  733. usbh_hal_chan_t *usbh_hal_get_chan_pending_intr(usbh_hal_context_t *hal);
  734. /**
  735. * @brief Decode a particular channel's interrupt
  736. *
  737. * - Reads and clears the interrupt register of the channel
  738. * - Returns the corresponding event for that channel
  739. *
  740. * @param chan_obj Channel object
  741. * @note If the host port has an error (e.g., a sudden disconnect or an port error), any active channels will not
  742. * receive an interrupt. Each active channel must be manually halted.
  743. * @return usbh_hal_chan_event_t Channel event
  744. */
  745. usbh_hal_chan_event_t usbh_hal_chan_decode_intr(usbh_hal_chan_t *chan_obj);
  746. #ifdef __cplusplus
  747. }
  748. #endif