usbd_stm32wb55_devfs.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /* This file is the part of the Lightweight USB device Stack for STM32 microcontrollers
  2. *
  3. * Copyright ©2016 Dmitry Filimonchuk <dmitrystu[at]gmail[dot]com>
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. * http://www.apache.org/licenses/LICENSE-2.0
  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. */
  15. #include <stdint.h>
  16. #include <stdbool.h>
  17. #include "stm32.h"
  18. #include "usb.h"
  19. #if defined(USBD_STM32WB55)
  20. #ifndef USB_PMASIZE
  21. #pragma message "PMA memory size is not defined. Use 1k by default"
  22. #define USB_PMASIZE 0x400
  23. #endif
  24. #if !defined(RCC_APB1ENR1_USBFSEN)
  25. #define RCC_APB1ENR1_USBFSEN RCC_APB1ENR1_USBEN
  26. #define RCC_APB1RSTR1_USBFSRST RCC_APB1RSTR1_USBRST
  27. #endif
  28. #define USB_EP_SWBUF_TX USB_EP_DTOG_RX
  29. #define USB_EP_SWBUF_RX USB_EP_DTOG_TX
  30. #define EP_TOGGLE_SET(epr, bits, mask) *(epr) = (*(epr) ^ (bits)) & (USB_EPREG_MASK | (mask))
  31. #define EP_TX_STALL(epr) EP_TOGGLE_SET((epr), USB_EP_TX_STALL, USB_EPTX_STAT)
  32. #define EP_RX_STALL(epr) EP_TOGGLE_SET((epr), USB_EP_RX_STALL, USB_EPRX_STAT)
  33. #define EP_TX_UNSTALL(epr) EP_TOGGLE_SET((epr), USB_EP_TX_NAK, USB_EPTX_STAT | USB_EP_DTOG_TX)
  34. #define EP_RX_UNSTALL(epr) EP_TOGGLE_SET((epr), USB_EP_RX_VALID, USB_EPRX_STAT | USB_EP_DTOG_RX)
  35. #define EP_DTX_UNSTALL(epr) EP_TOGGLE_SET((epr), USB_EP_TX_VALID, USB_EPTX_STAT | USB_EP_DTOG_TX | USB_EP_SWBUF_TX)
  36. #define EP_DRX_UNSTALL(epr) EP_TOGGLE_SET((epr), USB_EP_RX_VALID | USB_EP_SWBUF_RX, USB_EPRX_STAT | USB_EP_DTOG_RX | USB_EP_SWBUF_RX)
  37. #define EP_TX_VALID(epr) EP_TOGGLE_SET((epr), USB_EP_TX_VALID, USB_EPTX_STAT)
  38. #define EP_RX_VALID(epr) EP_TOGGLE_SET((epr), USB_EP_RX_VALID, USB_EPRX_STAT)
  39. #define STATUS_VAL(x) (USBD_HW_BC | (x))
  40. typedef struct {
  41. uint16_t addr;
  42. uint16_t cnt;
  43. } pma_rec;
  44. typedef union pma_table {
  45. struct {
  46. pma_rec tx;
  47. pma_rec rx;
  48. };
  49. struct {
  50. pma_rec tx0;
  51. pma_rec tx1;
  52. };
  53. struct {
  54. pma_rec rx0;
  55. pma_rec rx1;
  56. };
  57. } pma_table;
  58. /** \brief Helper function. Returns pointer to the buffer descriptor table.
  59. */
  60. inline static pma_table *EPT(uint8_t ep) {
  61. return (pma_table*)((ep & 0x07) * 8 + USB1_PMAADDR);
  62. }
  63. /** \brief Helper function. Returns pointer to the endpoint control register.
  64. */
  65. inline static volatile uint16_t *EPR(uint8_t ep) {
  66. return (uint16_t*)((ep & 0x07) * 4 + USB1_BASE);
  67. }
  68. /** \brief Helper function. Returns next available PMA buffer.
  69. *
  70. * \param sz uint16_t Requested buffer size.
  71. * \return uint16_t Buffer address for PMA table.
  72. * \note PMA buffers grown from top to bottom like stack.
  73. */
  74. static uint16_t get_next_pma(uint16_t sz) {
  75. unsigned _result = USB_PMASIZE;
  76. for (int i = 0; i < 8; i++) {
  77. pma_table *tbl = EPT(i);
  78. if ((tbl->rx.addr) && (tbl->rx.addr < _result)) _result = tbl->rx.addr;
  79. if ((tbl->tx.addr) && (tbl->tx.addr < _result)) _result = tbl->tx.addr;
  80. }
  81. return (_result < (unsigned)(0x020 + sz)) ? 0 : (_result - sz);
  82. }
  83. static uint32_t getinfo(void) {
  84. if (!(RCC->APB1ENR1 & RCC_APB1ENR1_USBFSEN)) return STATUS_VAL(0);
  85. if (USB->BCDR & USB_BCDR_DPPU) return STATUS_VAL(USBD_HW_ENABLED | USBD_HW_SPEED_FS);
  86. return STATUS_VAL(USBD_HW_ENABLED);
  87. }
  88. static void ep_setstall(uint8_t ep, bool stall) {
  89. volatile uint16_t *reg = EPR(ep);
  90. /* ISOCHRONOUS endpoint can't be stalled or unstalled */
  91. if (USB_EP_ISOCHRONOUS == (*reg & USB_EP_T_FIELD)) return;
  92. /* If it's an IN endpoint */
  93. if (ep & 0x80) {
  94. /* DISABLED endpoint can't be stalled or unstalled */
  95. if (USB_EP_TX_DIS == (*reg & USB_EPTX_STAT)) return;
  96. if (stall) {
  97. EP_TX_STALL(reg);
  98. } else {
  99. /* if it's a doublebuffered endpoint */
  100. if ((USB_EP_KIND | USB_EP_BULK) == (*reg & (USB_EP_T_FIELD | USB_EP_KIND))) {
  101. /* set endpoint to VALID and clear DTOG_TX & SWBUF_TX */
  102. EP_DTX_UNSTALL(reg);
  103. } else {
  104. /* set endpoint to NAKED and clear DTOG_TX */
  105. EP_TX_UNSTALL(reg);
  106. }
  107. }
  108. } else {
  109. if (USB_EP_RX_DIS == (*reg & USB_EPRX_STAT)) return;
  110. if (stall) {
  111. EP_RX_STALL(reg);
  112. } else {
  113. /* if it's a doublebuffered endpoint */
  114. if ((USB_EP_KIND | USB_EP_BULK) == (*reg & (USB_EP_T_FIELD | USB_EP_KIND))) {
  115. /* set endpoint to VALID, clear DTOG_RX, set SWBUF_RX */
  116. EP_DRX_UNSTALL(reg);
  117. } else {
  118. /* set endpoint to VALID and clear DTOG_RX */
  119. EP_RX_UNSTALL(reg);
  120. }
  121. }
  122. }
  123. }
  124. static bool ep_isstalled(uint8_t ep) {
  125. if (ep & 0x80) {
  126. return (USB_EP_TX_STALL == (USB_EPTX_STAT & *EPR(ep)));
  127. } else {
  128. return (USB_EP_RX_STALL == (USB_EPRX_STAT & *EPR(ep)));
  129. }
  130. }
  131. static void enable(bool enable) {
  132. if (enable) {
  133. RCC->APB1ENR1 |= RCC_APB1ENR1_USBFSEN;
  134. RCC->APB1RSTR1 |= RCC_APB1RSTR1_USBFSRST;
  135. RCC->APB1RSTR1 &= ~RCC_APB1RSTR1_USBFSRST;
  136. USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM | USB_CNTR_ERRM |
  137. #if !defined(USBD_SOF_DISABLED)
  138. USB_CNTR_SOFM |
  139. #endif
  140. USB_CNTR_SUSPM | USB_CNTR_WKUPM;
  141. } else if (RCC->APB1ENR1 & RCC_APB1ENR1_USBFSEN) {
  142. USB->BCDR = 0;
  143. RCC->APB1RSTR1 |= RCC_APB1RSTR1_USBFSRST;
  144. RCC->APB1ENR1 &= ~RCC_APB1ENR1_USBFSEN;
  145. }
  146. }
  147. static uint8_t connect(bool connect) {
  148. uint8_t res;
  149. USB->BCDR = USB_BCDR_BCDEN | USB_BCDR_DCDEN;
  150. if (USB->BCDR & USB_BCDR_DCDET) {
  151. USB->BCDR = USB_BCDR_BCDEN | USB_BCDR_PDEN;
  152. if (USB->BCDR & USB_BCDR_PS2DET) {
  153. res = usbd_lane_unk;
  154. } else if (USB->BCDR & USB_BCDR_PDET) {
  155. USB->BCDR = USB_BCDR_BCDEN | USB_BCDR_SDEN;
  156. if (USB->BCDR & USB_BCDR_SDET) {
  157. res = usbd_lane_dcp;
  158. } else {
  159. res = usbd_lane_cdp;
  160. }
  161. } else {
  162. res = usbd_lane_sdp;
  163. }
  164. } else {
  165. res = usbd_lane_dsc;
  166. }
  167. USB->BCDR = (connect) ? USB_BCDR_DPPU : 0;
  168. return res;
  169. }
  170. static void setaddr (uint8_t addr) {
  171. USB->DADDR = USB_DADDR_EF | addr;
  172. }
  173. static bool ep_config(uint8_t ep, uint8_t eptype, uint16_t epsize) {
  174. volatile uint16_t *reg = EPR(ep);
  175. pma_table *tbl = EPT(ep);
  176. /* epsize must be 2-byte aligned */
  177. epsize = (~0x01U) & (epsize + 1);
  178. switch (eptype) {
  179. case USB_EPTYPE_CONTROL:
  180. *reg = USB_EP_CONTROL | (ep & 0x07);
  181. break;
  182. case USB_EPTYPE_ISOCHRONUS:
  183. *reg = USB_EP_ISOCHRONOUS | (ep & 0x07);
  184. break;
  185. case USB_EPTYPE_BULK:
  186. *reg = USB_EP_BULK | (ep & 0x07);
  187. break;
  188. case USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF:
  189. *reg = USB_EP_BULK | USB_EP_KIND | (ep & 0x07);
  190. break;
  191. default:
  192. *reg = USB_EP_INTERRUPT | (ep & 0x07);
  193. break;
  194. }
  195. /* if it TX or CONTROL endpoint */
  196. if ((ep & 0x80) || (eptype == USB_EPTYPE_CONTROL)) {
  197. uint16_t _pma;
  198. _pma = get_next_pma(epsize);
  199. if (_pma == 0) return false;
  200. tbl->tx.addr = _pma;
  201. tbl->tx.cnt = 0;
  202. if ((eptype == USB_EPTYPE_ISOCHRONUS) ||
  203. (eptype == (USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF))) {
  204. _pma = get_next_pma(epsize);
  205. if (_pma == 0) return false;
  206. tbl->tx1.addr = _pma;
  207. tbl->tx1.cnt = 0;
  208. EP_DTX_UNSTALL(reg);
  209. } else {
  210. EP_TX_UNSTALL(reg);
  211. }
  212. }
  213. if (!(ep & 0x80)) {
  214. uint16_t _rxcnt;
  215. uint16_t _pma;
  216. if (epsize > 62) {
  217. /* using 32-byte blocks. epsize must be 32-byte aligned */
  218. epsize = (~0x1FU) & (epsize + 0x1FU);
  219. _rxcnt = 0x8000 - 0x400 + (epsize << 5);
  220. } else {
  221. _rxcnt = epsize << 9;
  222. }
  223. _pma = get_next_pma(epsize);
  224. if (_pma == 0) return false;
  225. tbl->rx.addr = _pma;
  226. tbl->rx.cnt = _rxcnt;
  227. if ((eptype == USB_EPTYPE_ISOCHRONUS) ||
  228. (eptype == (USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF))) {
  229. _pma = get_next_pma(epsize);
  230. if (_pma == 0) return false;
  231. tbl->rx0.addr = _pma;
  232. tbl->rx0.cnt = _rxcnt;
  233. EP_DRX_UNSTALL(reg);
  234. } else {
  235. EP_RX_UNSTALL(reg);
  236. }
  237. }
  238. return true;
  239. }
  240. static void ep_deconfig(uint8_t ep) {
  241. pma_table *ept = EPT(ep);
  242. *EPR(ep) &= ~USB_EPREG_MASK;
  243. ept->rx.addr = 0;
  244. ept->rx.cnt = 0;
  245. ept->tx.addr = 0;
  246. ept->tx.cnt = 0;
  247. }
  248. static uint16_t pma_read (uint8_t *buf, uint16_t blen, pma_rec *rx) {
  249. uint16_t *pma = (void*)(USB1_PMAADDR + rx->addr);
  250. uint16_t rxcnt = rx->cnt & 0x03FF;
  251. rx->cnt &= ~0x3FF;
  252. if (blen > rxcnt) {
  253. blen = rxcnt;
  254. }
  255. rxcnt = blen;
  256. while (blen) {
  257. uint16_t _t = *pma;
  258. *buf++ = _t & 0xFF;
  259. if (--blen) {
  260. *buf++ = _t >> 8;
  261. pma++;
  262. blen--;
  263. } else break;
  264. }
  265. return rxcnt;
  266. }
  267. static int32_t ep_read(uint8_t ep, void *buf, uint16_t blen) {
  268. pma_table *tbl = EPT(ep);
  269. volatile uint16_t *reg = EPR(ep);
  270. switch (*reg & (USB_EPRX_STAT | USB_EP_T_FIELD | USB_EP_KIND)) {
  271. /* doublebuffered bulk endpoint */
  272. case (USB_EP_RX_VALID | USB_EP_BULK | USB_EP_KIND):
  273. /* switching SWBUF if EP is NAKED */
  274. switch (*reg & (USB_EP_DTOG_RX | USB_EP_SWBUF_RX)) {
  275. case 0:
  276. case (USB_EP_DTOG_RX | USB_EP_SWBUF_RX):
  277. *reg = (*reg & USB_EPREG_MASK) | USB_EP_SWBUF_RX;
  278. break;
  279. default:
  280. break;
  281. }
  282. if (*reg & USB_EP_SWBUF_RX) {
  283. return pma_read(buf, blen, &(tbl->rx1));
  284. } else {
  285. return pma_read(buf, blen, &(tbl->rx0));
  286. }
  287. /* isochronous endpoint */
  288. case (USB_EP_RX_VALID | USB_EP_ISOCHRONOUS):
  289. if (*reg & USB_EP_DTOG_RX) {
  290. return pma_read(buf, blen, &(tbl->rx1));
  291. } else {
  292. return pma_read(buf, blen, &(tbl->rx0));
  293. }
  294. /* regular endpoint */
  295. case (USB_EP_RX_NAK | USB_EP_BULK):
  296. case (USB_EP_RX_NAK | USB_EP_CONTROL):
  297. case (USB_EP_RX_NAK | USB_EP_INTERRUPT):
  298. {
  299. int32_t res = pma_read(buf, blen, &(tbl->rx));
  300. /* setting endpoint to VALID state */
  301. EP_RX_VALID(reg);
  302. return res;
  303. }
  304. /* invalid or not ready */
  305. default:
  306. return -1;
  307. }
  308. }
  309. static void pma_write(uint8_t *buf, uint16_t blen, pma_rec *tx) {
  310. uint16_t *pma = (void*)(USB1_PMAADDR + tx->addr);
  311. tx->cnt = blen;
  312. while (blen > 1) {
  313. *pma++ = buf[1] << 8 | buf[0];
  314. buf += 2;
  315. blen -= 2;
  316. }
  317. if (blen) *pma = *buf;
  318. }
  319. static int32_t ep_write(uint8_t ep, void *buf, uint16_t blen) {
  320. pma_table *tbl = EPT(ep);
  321. volatile uint16_t *reg = EPR(ep);
  322. switch (*reg & (USB_EPTX_STAT | USB_EP_T_FIELD | USB_EP_KIND)) {
  323. /* doublebuffered bulk endpoint */
  324. case (USB_EP_TX_NAK | USB_EP_BULK | USB_EP_KIND):
  325. if (*reg & USB_EP_SWBUF_TX) {
  326. pma_write(buf, blen, &(tbl->tx1));
  327. } else {
  328. pma_write(buf, blen, &(tbl->tx0));
  329. }
  330. *reg = (*reg & USB_EPREG_MASK) | USB_EP_SWBUF_TX;
  331. break;
  332. /* isochronous endpoint */
  333. case (USB_EP_TX_VALID | USB_EP_ISOCHRONOUS):
  334. if (!(*reg & USB_EP_DTOG_TX)) {
  335. pma_write(buf, blen, &(tbl->tx1));
  336. } else {
  337. pma_write(buf, blen, &(tbl->tx0));
  338. }
  339. break;
  340. /* regular endpoint */
  341. case (USB_EP_TX_NAK | USB_EP_BULK):
  342. case (USB_EP_TX_NAK | USB_EP_CONTROL):
  343. case (USB_EP_TX_NAK | USB_EP_INTERRUPT):
  344. pma_write(buf, blen, &(tbl->tx));
  345. EP_TX_VALID(reg);
  346. break;
  347. /* invalid or not ready */
  348. default:
  349. return -1;
  350. }
  351. return blen;
  352. }
  353. static uint16_t get_frame (void) {
  354. return USB->FNR & USB_FNR_FN;
  355. }
  356. static void evt_poll(usbd_device *dev, usbd_evt_callback callback) {
  357. uint8_t _ev, _ep;
  358. uint16_t _istr = USB->ISTR;
  359. _ep = _istr & USB_ISTR_EP_ID;
  360. if (_istr & USB_ISTR_CTR) {
  361. volatile uint16_t *reg = EPR(_ep);
  362. if (*reg & USB_EP_CTR_TX) {
  363. *reg &= (USB_EPREG_MASK ^ USB_EP_CTR_TX);
  364. _ep |= 0x80;
  365. _ev = usbd_evt_eptx;
  366. } else {
  367. *reg &= (USB_EPREG_MASK ^ USB_EP_CTR_RX);
  368. _ev = (*reg & USB_EP_SETUP) ? usbd_evt_epsetup : usbd_evt_eprx;
  369. }
  370. } else if (_istr & USB_ISTR_RESET) {
  371. USB->ISTR &= ~USB_ISTR_RESET;
  372. USB->BTABLE = 0;
  373. for (int i = 0; i < 8; i++) {
  374. ep_deconfig(i);
  375. }
  376. _ev = usbd_evt_reset;
  377. #if !defined(USBD_SOF_DISABLED)
  378. } else if (_istr & USB_ISTR_SOF) {
  379. _ev = usbd_evt_sof;
  380. USB->ISTR &= ~USB_ISTR_SOF;
  381. #endif
  382. } else if (_istr & USB_ISTR_WKUP) {
  383. _ev = usbd_evt_wkup;
  384. USB->CNTR &= ~USB_CNTR_FSUSP;
  385. USB->ISTR &= ~USB_ISTR_WKUP;
  386. } else if (_istr & USB_ISTR_SUSP) {
  387. _ev = usbd_evt_susp;
  388. USB->ISTR &= ~USB_ISTR_SUSP;
  389. USB->CNTR |= USB_CNTR_FSUSP;
  390. } else if (_istr & USB_ISTR_ERR) {
  391. USB->ISTR &= ~USB_ISTR_ERR;
  392. _ev = usbd_evt_error;
  393. } else {
  394. return;
  395. }
  396. callback(dev, _ev, _ep);
  397. }
  398. static uint32_t fnv1a32_turn (uint32_t fnv, uint32_t data ) {
  399. for (int i = 0; i < 4 ; i++) {
  400. fnv ^= (data & 0xFF);
  401. fnv *= 16777619;
  402. data >>= 8;
  403. }
  404. return fnv;
  405. }
  406. static uint16_t get_serialno_desc(void *buffer) {
  407. struct usb_string_descriptor *dsc = buffer;
  408. uint16_t *str = dsc->wString;
  409. uint32_t fnv = 2166136261;
  410. fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x00));
  411. fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x04));
  412. fnv = fnv1a32_turn(fnv, *(uint32_t*)(UID_BASE + 0x14));
  413. for (int i = 28; i >= 0; i -= 4 ) {
  414. uint16_t c = (fnv >> i) & 0x0F;
  415. c += (c < 10) ? '0' : ('A' - 10);
  416. *str++ = c;
  417. }
  418. dsc->bDescriptorType = USB_DTYPE_STRING;
  419. dsc->bLength = 18;
  420. return 18;
  421. }
  422. __attribute__((externally_visible)) const struct usbd_driver usbd_devfs = {
  423. getinfo,
  424. enable,
  425. connect,
  426. setaddr,
  427. ep_config,
  428. ep_deconfig,
  429. ep_read,
  430. ep_write,
  431. ep_setstall,
  432. ep_isstalled,
  433. evt_poll,
  434. get_frame,
  435. get_serialno_desc,
  436. };
  437. #endif //USBD_STM32WB55