usbh_hal.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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. #include <stddef.h>
  15. #include <stdint.h>
  16. #include <assert.h>
  17. #include <string.h>
  18. #include "hal/usbh_hal.h"
  19. #include "hal/usbh_ll.h"
  20. /* -----------------------------------------------------------------------------
  21. ------------------------------- Macros and Types -------------------------------
  22. ----------------------------------------------------------------------------- */
  23. // -------------------------------- Constants ----------------------------------
  24. #define CORE_REG_GSNPSID 0x4F54400A
  25. #define CORE_REG_GHWCFG1 0x00000000
  26. #define CORE_REG_GHWCFG2 0x224DD930
  27. #define CORE_REG_GHWCFG3 0x00C804B5
  28. #define CORE_REG_GHWCFG4 0xD3F0A030
  29. // ------------------------------ Configurable ---------------------------------
  30. #define CHAN_MAX_SLOTS 16
  31. /*
  32. FIFO lengths configured as follows:
  33. RXFIFO (Receive FIFO)
  34. - Recommended: (((LPS/4) + 2) * NUM_PACKETS) + (NUM_CHAN * 2) + (NUM_BULK_CTRL * 1)
  35. - Actual: Assume (LPS = 64), (NUM_CHAN = 8), (NUM_BULK_CTRL = 8):
  36. NPTXFIFO (Non-periodic TX FIFO)
  37. - Recommended: (((LPS/4) + 2) * 2) Fit two largest packet sizes (and each packets overhead info)
  38. - Actual: Assume LPS is 64 (is the MPS for CTRL/BULK/INTR in FS)
  39. PTXFIFO (Periodic TX FIFO)
  40. - Recommended: ((LPS/4) + 2) * NUM_PACKETS
  41. - Actual: Assume a single LPS of 64 (quarter of ISO MPS), then 2 packets worth of overhead
  42. REGFIFO (Register storage)
  43. - Recommended: 4 * NUM_CHAN
  44. - Actual: Assume NUM_CHAN is 8
  45. */
  46. #define HW_FIFO_LEN 256
  47. #define RX_FIFO_LEN 92
  48. #define NPTX_FIFO_LEN 36
  49. #define PTX_FIFO_LEN 72
  50. #define REG_FIFO_LEN 32
  51. _Static_assert((RX_FIFO_LEN + NPTX_FIFO_LEN + PTX_FIFO_LEN + REG_FIFO_LEN) <= HW_FIFO_LEN, "Sum of FIFO lengths not equal to HW_FIFO_LEN");
  52. /**
  53. * The following core interrupts will be enabled (listed LSB to MSB). Some of these
  54. * interrupts are enabled later than others.
  55. * - USB_LL_INTR_CORE_PRTINT
  56. * - USB_LL_INTR_CORE_HCHINT
  57. * - USB_LL_INTR_CORE_DISCONNINT
  58. * The following PORT interrupts cannot be masked, listed LSB to MSB
  59. * - USBH_LL_INTR_HPRT_PRTCONNDET
  60. * - USBH_LL_INTR_HPRT_PRTENCHNG
  61. * - USBH_LL_INTR_HPRT_PRTOVRCURRCHNG
  62. */
  63. #define CORE_INTRS_EN_MSK (USB_LL_INTR_CORE_DISCONNINT)
  64. //Interrupts that pertain to core events
  65. #define CORE_EVENTS_INTRS_MSK (USB_LL_INTR_CORE_DISCONNINT | \
  66. USB_LL_INTR_CORE_HCHINT)
  67. //Interrupt that pertain to host port events
  68. #define PORT_EVENTS_INTRS_MSK (USBH_LL_INTR_HPRT_PRTCONNDET | \
  69. USBH_LL_INTR_HPRT_PRTENCHNG | \
  70. USBH_LL_INTR_HPRT_PRTOVRCURRCHNG)
  71. /**
  72. * The following channel interrupt bits are currently checked (in order LSB to MSB)
  73. * - USBH_LL_INTR_CHAN_XFERCOMPL
  74. * - USBH_LL_INTR_CHAN_CHHLTD
  75. * - USBH_LL_INTR_CHAN_AHBERR
  76. * - USBH_LL_INTR_CHAN_STALL
  77. * - USBH_LL_INTR_CHAN_BBLEER
  78. * - USBH_LL_INTR_CHAN_BNAINTR
  79. * - USBH_LL_INTR_CHAN_XCS_XACT_ERR
  80. *
  81. * - Not all bits are unmaskable under scatter/gather
  82. * - Those bits proxy their interrupt through the USBH_LL_INTR_CHAN_CHHLTD bit
  83. * - USBH_LL_INTR_CHAN_XCS_XACT_ERR is always unmasked
  84. */
  85. #define CHAN_INTRS_EN_MSK (USBH_LL_INTR_CHAN_XFERCOMPL | \
  86. USBH_LL_INTR_CHAN_CHHLTD | \
  87. USBH_LL_INTR_CHAN_BNAINTR)
  88. #define CHAN_INTRS_ERROR_MSK (USBH_LL_INTR_CHAN_AHBERR | \
  89. USBH_LL_INTR_CHAN_STALL | \
  90. USBH_LL_INTR_CHAN_BBLEER | \
  91. USBH_LL_INTR_CHAN_BNAINTR | \
  92. USBH_LL_INTR_CHAN_XCS_XACT_ERR)
  93. /* -----------------------------------------------------------------------------
  94. --------------------------------- Core (Global) --------------------------------
  95. ----------------------------------------------------------------------------- */
  96. // ---------------------------- Private Functions ------------------------------
  97. static void set_defaults(usbh_hal_context_t *hal)
  98. {
  99. usbh_ll_internal_phy_conf(hal->wrap_dev); //Enable and configure internal PHY
  100. //GAHBCFG register
  101. usb_ll_en_dma_mode(hal->dev);
  102. usb_ll_set_hbstlen(hal->dev, 0); //INCR16 AHB burst length
  103. //GUSBCFG register
  104. usb_ll_dis_hnp_cap(hal->dev); //Disable HNP
  105. usb_ll_dis_srp_cap(hal->dev); //Disable SRP
  106. //Enable interruts
  107. usb_ll_dis_intrs(hal->dev, 0xFFFFFFFF); //Mask all interrupts first
  108. usb_ll_en_intrs(hal->dev, CORE_INTRS_EN_MSK); //Unmask global interrupts
  109. usb_ll_intr_read_and_clear(hal->dev); //Clear interrupts
  110. usb_ll_en_global_intr(hal->dev); //Enable interrupt signal
  111. //Enable host mode
  112. usb_ll_set_host_mode(hal->dev);
  113. }
  114. // ---------------------------- Public Functions -------------------------------
  115. void usbh_hal_init(usbh_hal_context_t *hal)
  116. {
  117. //Check if a peripheral is alive by reading the core ID registers
  118. usbh_dev_t *dev = &USBH;
  119. uint32_t core_id = usb_ll_get_controller_core_id(dev);
  120. assert(core_id == CORE_REG_GSNPSID);
  121. //Initialize HAL context
  122. memset(hal, 0, sizeof(usbh_hal_context_t));
  123. hal->dev = dev;
  124. hal->wrap_dev = &USB_WRAP;
  125. set_defaults(hal);
  126. }
  127. void usbh_hal_deinit(usbh_hal_context_t *hal)
  128. {
  129. //Disable and clear global interrupt
  130. usb_ll_dis_intrs(hal->dev, 0xFFFFFFFF); //Disable all interrupts
  131. usb_ll_intr_read_and_clear(hal->dev); //Clear interrupts
  132. usb_ll_dis_global_intr(hal->dev); //Disable interrupt signal
  133. hal->dev = NULL;
  134. hal->wrap_dev = NULL;
  135. }
  136. void usbh_hal_core_soft_reset(usbh_hal_context_t *hal)
  137. {
  138. usb_ll_core_soft_reset(hal->dev);
  139. while (usb_ll_check_core_soft_reset(hal->dev)) {
  140. ; //Wait until core reset is done
  141. }
  142. while (!usb_ll_check_ahb_idle(hal->dev)) {
  143. ; //Wait until AHB Master bus is idle before doing any other operations
  144. }
  145. //Set the default bits
  146. set_defaults(hal);
  147. //Clear all the flags
  148. hal->flags.val = 0;
  149. }
  150. /* -----------------------------------------------------------------------------
  151. ---------------------------------- Host Port ----------------------------------
  152. ----------------------------------------------------------------------------- */
  153. static inline void debounce_lock_enable(usbh_hal_context_t *hal)
  154. {
  155. //Disable the hprt (connection) and disconnection interrupts to prevent repeated triggerings
  156. usb_ll_dis_intrs(hal->dev, USB_LL_INTR_CORE_PRTINT | USB_LL_INTR_CORE_DISCONNINT);
  157. hal->flags.dbnc_lock_enabled = 1;
  158. }
  159. void usbh_hal_port_enable(usbh_hal_context_t *hal)
  160. {
  161. //Host Configuration
  162. usbh_ll_hcfg_set_defaults(hal->dev);
  163. //Todo: Set frame list entries and ena per sched
  164. //Configure HFIR
  165. usbh_ll_hfir_set_defaults(hal->dev);
  166. //Config FIFO sizes
  167. usb_ll_set_rx_fifo_size(hal->dev, RX_FIFO_LEN);
  168. usb_ll_set_nptx_fifo_size(hal->dev, RX_FIFO_LEN, NPTX_FIFO_LEN);
  169. usbh_ll_set_ptx_fifo_size(hal->dev, RX_FIFO_LEN + NPTX_FIFO_LEN, PTX_FIFO_LEN);
  170. }
  171. /* -----------------------------------------------------------------------------
  172. ----------------------------------- Channel ------------------------------------
  173. ------------------------------------------------------------------------------*/
  174. // --------------------------- Channel Allocation ------------------------------
  175. //Allocate a channel
  176. bool usbh_hal_chan_alloc(usbh_hal_context_t *hal, usbh_hal_chan_t *chan_obj, void *chan_ctx)
  177. {
  178. //Attempt to allocate channel
  179. if (hal->channels.num_allocd == USBH_HAL_NUM_CHAN) {
  180. return false; //Out of free channels
  181. }
  182. int chan_idx = -1;
  183. for (int i = 0; i < USBH_HAL_NUM_CHAN; i++) {
  184. if (hal->channels.hdls[i] == NULL) {
  185. hal->channels.hdls[i] = chan_obj;
  186. chan_idx = i;
  187. hal->channels.num_allocd++;
  188. break;
  189. }
  190. }
  191. assert(chan_idx != -1);
  192. //Initialize channel object
  193. memset(chan_obj, 0, sizeof(usbh_hal_chan_t));
  194. chan_obj->flags.chan_idx = chan_idx;
  195. chan_obj->regs = usbh_ll_get_chan_regs(hal->dev, chan_idx);
  196. chan_obj->chan_ctx = chan_ctx;
  197. //Note: EP characteristics configured separately
  198. //Clean and unmask the channel's interrupt
  199. usbh_ll_chan_intr_read_and_clear(chan_obj->regs); //Clear the interrupt bits for that channel
  200. usbh_ll_haintmsk_en_chan_intr(hal->dev, 1 << chan_obj->flags.chan_idx);
  201. usbh_ll_chan_set_intr_mask(chan_obj->regs, CHAN_INTRS_EN_MSK); //Unmask interrupts for this channel
  202. usbh_ll_chan_set_pid(chan_obj->regs, 0); //Set the initial PID to zero
  203. usbh_ll_chan_hctsiz_init(chan_obj->regs); //Set the non changing parts of the HCTSIZ registers (e.g., do_ping and sched info)
  204. return true;
  205. }
  206. //Returns object memory
  207. void usbh_hal_chan_free(usbh_hal_context_t *hal, usbh_hal_chan_t *chan_obj)
  208. {
  209. //Can only free a channel when in the disabled state and descriptor list released
  210. assert(!chan_obj->slot.flags.slot_acquired
  211. && !chan_obj->flags.active
  212. && !chan_obj->flags.error_pending);
  213. //Deallocate channel
  214. hal->channels.hdls[chan_obj->flags.chan_idx] = NULL;
  215. hal->channels.num_allocd--;
  216. assert(hal->channels.num_allocd >= 0);
  217. }
  218. // ---------------------------- Channel Control --------------------------------
  219. void usbh_hal_chan_set_ep_char(usbh_hal_chan_t *chan_obj, usbh_hal_ep_char_t *ep_char)
  220. {
  221. //Cannot change ep_char whilst channel is still active or in error
  222. assert(!chan_obj->flags.active && !chan_obj->flags.error_pending);
  223. //Set the endpoint characteristics of the pipe
  224. usbh_ll_chan_hcchar_init(chan_obj->regs,
  225. ep_char->dev_addr,
  226. ep_char->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK,
  227. ep_char->mps,
  228. ep_char->type,
  229. ep_char->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK);
  230. }
  231. /* -----------------------------------------------------------------------------
  232. ------------------------------- Transfers Slots --------------------------------
  233. ------------------------------------------------------------------------------*/
  234. void usbh_hal_chan_activate(usbh_hal_chan_t *chan_obj, int num_to_skip)
  235. {
  236. //Cannot enable a channel that has already been enabled or is pending error handling
  237. assert(!chan_obj->flags.active && !chan_obj->flags.error_pending);
  238. assert(chan_obj->slot.flags.slot_acquired);
  239. //Update the descriptor list index and check if it's within bounds
  240. chan_obj->slot.flags.cur_qtd_idx += num_to_skip;
  241. assert(chan_obj->slot.flags.cur_qtd_idx < chan_obj->slot.flags.qtd_list_len);
  242. chan_obj->flags.active = 1;
  243. //Set start address of the QTD list and starting QTD index
  244. usbh_ll_chan_set_dma_addr_non_iso(chan_obj->regs, chan_obj->slot.xfer_desc_list, chan_obj->slot.flags.cur_qtd_idx);
  245. //Start the channel
  246. usbh_ll_chan_start(chan_obj->regs);
  247. }
  248. bool usbh_hal_chan_request_halt(usbh_hal_chan_t *chan_obj)
  249. {
  250. //Cannot request halt on a channel that is pending error handling
  251. assert(!chan_obj->flags.error_pending);
  252. if (usbh_ll_chan_is_active(chan_obj->regs)) {
  253. usbh_ll_chan_halt(chan_obj->regs);
  254. chan_obj->flags.halt_requested = 1;
  255. return false;
  256. }
  257. return true;
  258. }
  259. /* -----------------------------------------------------------------------------
  260. -------------------------------- Event Handling --------------------------------
  261. ----------------------------------------------------------------------------- */
  262. usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal)
  263. {
  264. uint32_t intrs_core = usb_ll_intr_read_and_clear(hal->dev); //Read and clear core interrupts
  265. uint32_t intrs_port = 0;
  266. if (intrs_core & USB_LL_INTR_CORE_PRTINT) {
  267. //There are host port interrupts. Read and clear those as well.
  268. intrs_port = usbh_ll_hprt_intr_read_and_clear(hal->dev);
  269. }
  270. //Note: Do not change order of checks. Regressing events (e.g. enable -> disabled, connected -> connected)
  271. //always take precendance. ENABLED < DISABLED < CONN < DISCONN < OVRCUR
  272. usbh_hal_port_event_t event = -1;
  273. //Check if this is a core or port event
  274. if ((intrs_core & CORE_EVENTS_INTRS_MSK) || (intrs_port & PORT_EVENTS_INTRS_MSK)) {
  275. //Do not change the order of the following checks. Some events/interrupts take precedence over others
  276. if (intrs_core & USB_LL_INTR_CORE_DISCONNINT) {
  277. event = USBH_HAL_PORT_EVENT_DISCONN;
  278. debounce_lock_enable(hal);
  279. //Mask the port connection and disconnection interrupts to prevent repeated triggering
  280. } else if (intrs_port & USBH_LL_INTR_HPRT_PRTOVRCURRCHNG) {
  281. //Check if this is an overcurrent or an overcurrent cleared
  282. if (usbh_ll_hprt_get_port_overcur(hal->dev)) {
  283. event = USBH_HAL_PORT_EVENT_OVRCUR;
  284. } else {
  285. event = USBH_HAL_PORT_EVENT_OVRCUR_CLR;
  286. }
  287. } else if (intrs_port & USBH_LL_INTR_HPRT_PRTENCHNG) {
  288. if (usbh_ll_hprt_get_port_en(hal->dev)) { //Host port was enabled
  289. event = USBH_HAL_PORT_EVENT_ENABLED;
  290. } else { //Host port has been disabled
  291. event = USBH_HAL_PORT_EVENT_DISABLED;
  292. }
  293. } else if (intrs_port & USBH_LL_INTR_HPRT_PRTCONNDET && !hal->flags.dbnc_lock_enabled) {
  294. event = USBH_HAL_PORT_EVENT_CONN;
  295. debounce_lock_enable(hal);
  296. }
  297. }
  298. if (intrs_core & USB_LL_INTR_CORE_HCHINT) {
  299. //One or more channels have pending interrupts. Store the mask of those channels
  300. hal->channels.chan_pend_intrs_msk = usbh_ll_get_chan_intrs_msk(hal->dev);
  301. event = USBH_HAL_PORT_EVENT_CHAN;
  302. }
  303. return event;
  304. }
  305. usbh_hal_chan_t *usbh_hal_get_chan_pending_intr(usbh_hal_context_t *hal)
  306. {
  307. int chan_num = __builtin_ffs(hal->channels.chan_pend_intrs_msk);
  308. if (chan_num) {
  309. hal->channels.chan_pend_intrs_msk &= ~(1 << (chan_num - 1)); //Clear the pending bit for that channel
  310. return hal->channels.hdls[chan_num - 1];
  311. } else {
  312. return NULL;
  313. }
  314. }
  315. usbh_hal_chan_event_t usbh_hal_chan_decode_intr(usbh_hal_chan_t *chan_obj)
  316. {
  317. uint32_t chan_intrs = usbh_ll_chan_intr_read_and_clear(chan_obj->regs);
  318. usbh_hal_chan_event_t chan_event;
  319. //Currently, all cases where channel interrupts occur will also halt the channel
  320. assert(chan_intrs & USBH_LL_INTR_CHAN_CHHLTD);
  321. chan_obj->flags.active = 0;
  322. //Note: Do not change the current checking order of checks. Certain interrupts (e.g., errors) have precedence over others
  323. if (chan_intrs & CHAN_INTRS_ERROR_MSK) { //One of the error interrupts has occurred.
  324. //Note: Errors are uncommon, so we check against the entire interrupt mask to reduce frequency of entering this call path
  325. //Store the error in hal context
  326. usbh_hal_chan_error_t error;
  327. if (chan_intrs & USBH_LL_INTR_CHAN_AHBERR) {
  328. error = USBH_HAL_CHAN_ERROR_AHB;
  329. } else if (chan_intrs & USBH_LL_INTR_CHAN_STALL) {
  330. error = USBH_HAL_CHAN_ERROR_STALL;
  331. } else if (chan_intrs & USBH_LL_INTR_CHAN_BBLEER) {
  332. error = USBH_HAL_CHAN_ERROR_PKT_BBL;
  333. } else if (chan_intrs & USBH_LL_INTR_CHAN_BNAINTR) {
  334. error = USBH_HAL_CHAN_ERROR_BNA;
  335. } else { //USBH_LL_INTR_CHAN_XCS_XACT_ERR
  336. error = USBH_HAL_CHAN_ERROR_XCS_XACT;
  337. }
  338. //Update flags
  339. chan_obj->error = error;
  340. chan_obj->flags.error_pending = 1;
  341. //Save the error to be handled later
  342. chan_event = USBH_HAL_CHAN_EVENT_ERROR;
  343. } else if (chan_obj->flags.halt_requested) { //A halt was previously requested and has not been fulfilled
  344. chan_obj->flags.halt_requested = 0;
  345. chan_event = USBH_HAL_CHAN_EVENT_HALT_REQ;
  346. } else if (chan_intrs & USBH_LL_INTR_CHAN_XFERCOMPL) {
  347. int cur_qtd_idx = usbh_ll_chan_get_ctd(chan_obj->regs);
  348. //Store current qtd index
  349. chan_obj->slot.flags.cur_qtd_idx = cur_qtd_idx;
  350. if (cur_qtd_idx == 0) {
  351. //If the transfer descriptor list has completed, the CTD index should be 0 (wrapped around)
  352. chan_event = USBH_HAL_CHAN_EVENT_SLOT_DONE;
  353. } else {
  354. chan_event = USBH_HAL_CHAN_EVENT_SLOT_HALT;
  355. }
  356. } else {
  357. //Channel halted suddenly (i.e,, a disconnect)
  358. chan_event = USBH_HAL_CHAN_EVENT_SUDDEN_HLT;
  359. }
  360. return chan_event;
  361. }