Keyboard firmwares for Atmel AVR and Cortex-M
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

USBHAL_LPC11U.cpp 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /* Copyright (c) 2010-2011 mbed.org, MIT License
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  4. * and associated documentation files (the "Software"), to deal in the Software without
  5. * restriction, including without limitation the rights to use, copy, modify, merge, publish,
  6. * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
  7. * Software is furnished to do so, subject to the following conditions:
  8. *
  9. * The above copyright notice and this permission notice shall be included in all copies or
  10. * substantial portions of the Software.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
  13. * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  14. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  15. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  17. */
  18. #if defined(TARGET_LPC11UXX) || defined(TARGET_LPC11U6X) || defined(TARGET_LPC1347) || defined(TARGET_LPC1549)
  19. #if defined(TARGET_LPC1347) || defined(TARGET_LPC1549)
  20. #define USB_IRQ USB_IRQ_IRQn
  21. #else
  22. #define USB_IRQ USB_IRQn
  23. #endif
  24. #include "USBHAL.h"
  25. USBHAL * USBHAL::instance;
  26. #if defined(TARGET_LPC1549)
  27. static uint8_t usbmem[2048] __attribute__((aligned(2048)));
  28. #endif
  29. // Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
  30. #define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
  31. // Convert physical endpoint number to register bit
  32. #define EP(endpoint) (1UL<<endpoint)
  33. // Convert physical to logical
  34. #define PHY_TO_LOG(endpoint) ((endpoint)>>1)
  35. // Get endpoint direction
  36. #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
  37. #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
  38. // USB RAM
  39. #if defined(TARGET_LPC1549)
  40. #define USB_RAM_START ((uint32_t)usbmem)
  41. #define USB_RAM_SIZE sizeof(usbmem)
  42. #else
  43. #define USB_RAM_START (0x20004000)
  44. #define USB_RAM_SIZE (0x00000800)
  45. #endif
  46. // SYSAHBCLKCTRL
  47. #if defined(TARGET_LPC1549)
  48. #define CLK_USB (1UL<<23)
  49. #else
  50. #define CLK_USB (1UL<<14)
  51. #define CLK_USBRAM (1UL<<27)
  52. #endif
  53. // USB Information register
  54. #define FRAME_NR(a) ((a) & 0x7ff) // Frame number
  55. // USB Device Command/Status register
  56. #define DEV_ADDR_MASK (0x7f) // Device address
  57. #define DEV_ADDR(a) ((a) & DEV_ADDR_MASK)
  58. #define DEV_EN (1UL<<7) // Device enable
  59. #define SETUP (1UL<<8) // SETUP token received
  60. #define PLL_ON (1UL<<9) // PLL enabled in suspend
  61. #define DCON (1UL<<16) // Device status - connect
  62. #define DSUS (1UL<<17) // Device status - suspend
  63. #define DCON_C (1UL<<24) // Connect change
  64. #define DSUS_C (1UL<<25) // Suspend change
  65. #define DRES_C (1UL<<26) // Reset change
  66. #define VBUSDEBOUNCED (1UL<<28) // Vbus detected
  67. // Endpoint Command/Status list
  68. #define CMDSTS_A (1UL<<31) // Active
  69. #define CMDSTS_D (1UL<<30) // Disable
  70. #define CMDSTS_S (1UL<<29) // Stall
  71. #define CMDSTS_TR (1UL<<28) // Toggle Reset
  72. #define CMDSTS_RF (1UL<<27) // Rate Feedback mode
  73. #define CMDSTS_TV (1UL<<27) // Toggle Value
  74. #define CMDSTS_T (1UL<<26) // Endpoint Type
  75. #define CMDSTS_NBYTES(n) (((n)&0x3ff)<<16) // Number of bytes
  76. #define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff) // Buffer start address
  77. #define BYTES_REMAINING(s) (((s)>>16)&0x3ff) // Bytes remaining after transfer
  78. // USB Non-endpoint interrupt sources
  79. #define FRAME_INT (1UL<<30)
  80. #define DEV_INT (1UL<<31)
  81. static volatile int epComplete = 0;
  82. // One entry for a double-buffered logical endpoint in the endpoint
  83. // command/status list. Endpoint 0 is single buffered, out[1] is used
  84. // for the SETUP packet and in[1] is not used
  85. typedef struct {
  86. uint32_t out[2];
  87. uint32_t in[2];
  88. } PACKED EP_COMMAND_STATUS;
  89. typedef struct {
  90. uint8_t out[MAX_PACKET_SIZE_EP0];
  91. uint8_t in[MAX_PACKET_SIZE_EP0];
  92. uint8_t setup[SETUP_PACKET_SIZE];
  93. } PACKED CONTROL_TRANSFER;
  94. typedef struct {
  95. uint32_t maxPacket;
  96. uint32_t buffer[2];
  97. uint32_t options;
  98. } PACKED EP_STATE;
  99. static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS];
  100. // Pointer to the endpoint command/status list
  101. static EP_COMMAND_STATUS *ep = NULL;
  102. // Pointer to endpoint 0 data (IN/OUT and SETUP)
  103. static CONTROL_TRANSFER *ct = NULL;
  104. // Shadow DEVCMDSTAT register to avoid accidentally clearing flags or
  105. // initiating a remote wakeup event.
  106. static volatile uint32_t devCmdStat;
  107. // Pointers used to allocate USB RAM
  108. static uint32_t usbRamPtr = USB_RAM_START;
  109. static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here
  110. #define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m))
  111. void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size);
  112. void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) {
  113. if (size > 0) {
  114. do {
  115. *dst++ = *src++;
  116. } while (--size > 0);
  117. }
  118. }
  119. USBHAL::USBHAL(void) {
  120. NVIC_DisableIRQ(USB_IRQ);
  121. // fill in callback array
  122. epCallback[0] = &USBHAL::EP1_OUT_callback;
  123. epCallback[1] = &USBHAL::EP1_IN_callback;
  124. epCallback[2] = &USBHAL::EP2_OUT_callback;
  125. epCallback[3] = &USBHAL::EP2_IN_callback;
  126. epCallback[4] = &USBHAL::EP3_OUT_callback;
  127. epCallback[5] = &USBHAL::EP3_IN_callback;
  128. epCallback[6] = &USBHAL::EP4_OUT_callback;
  129. epCallback[7] = &USBHAL::EP4_IN_callback;
  130. #if defined(TARGET_LPC1549)
  131. /* Set USB PLL input to system oscillator */
  132. LPC_SYSCON->USBPLLCLKSEL = 0x01;
  133. /* Setup USB PLL (FCLKIN = 12MHz) * 4 = 48MHz
  134. MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2)
  135. FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz
  136. FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */
  137. LPC_SYSCON->USBPLLCTRL = (0x3 | (1UL << 6));
  138. /* Powerup USB PLL */
  139. LPC_SYSCON->PDRUNCFG &= ~(CLK_USB);
  140. /* Wait for PLL to lock */
  141. while(!(LPC_SYSCON->USBPLLSTAT & 0x01));
  142. /* enable USB main clock */
  143. LPC_SYSCON->USBCLKSEL = 0x02;
  144. LPC_SYSCON->USBCLKDIV = 1;
  145. /* Enable AHB clock to the USB block. */
  146. LPC_SYSCON->SYSAHBCLKCTRL1 |= CLK_USB;
  147. /* power UP USB Phy */
  148. LPC_SYSCON->PDRUNCFG &= ~(1UL << 9);
  149. /* Reset USB block */
  150. LPC_SYSCON->PRESETCTRL1 |= (CLK_USB);
  151. LPC_SYSCON->PRESETCTRL1 &= ~(CLK_USB);
  152. #else
  153. #if defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501)
  154. // USB_VBUS input with pull-down
  155. LPC_IOCON->PIO0_3 = 0x00000009;
  156. #endif
  157. // nUSB_CONNECT output
  158. LPC_IOCON->PIO0_6 = 0x00000001;
  159. // Enable clocks (USB registers, USB RAM)
  160. LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM;
  161. // Ensure device disconnected (DCON not set)
  162. LPC_USB->DEVCMDSTAT = 0;
  163. #endif
  164. // to ensure that the USB host sees the device as
  165. // disconnected if the target CPU is reset.
  166. wait(0.3);
  167. // Reserve space in USB RAM for endpoint command/status list
  168. // Must be 256 byte aligned
  169. usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256);
  170. ep = (EP_COMMAND_STATUS *)usbRamPtr;
  171. usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS);
  172. LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00;
  173. // Reserve space in USB RAM for Endpoint 0
  174. // Must be 64 byte aligned
  175. usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64);
  176. ct = (CONTROL_TRANSFER *)usbRamPtr;
  177. usbRamPtr += sizeof(CONTROL_TRANSFER);
  178. LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000;
  179. // Setup command/status list for EP0
  180. ep[0].out[0] = 0;
  181. ep[0].in[0] = 0;
  182. ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup);
  183. // Route all interrupts to IRQ, some can be routed to
  184. // USB_FIQ if you wish.
  185. LPC_USB->INTROUTING = 0;
  186. // Set device address 0, enable USB device, no remote wakeup
  187. devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS;
  188. LPC_USB->DEVCMDSTAT = devCmdStat;
  189. // Enable interrupts for device events and EP0
  190. LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT) | FRAME_INT;
  191. instance = this;
  192. //attach IRQ handler and enable interrupts
  193. NVIC_SetVector(USB_IRQ, (uint32_t)&_usbisr);
  194. }
  195. USBHAL::~USBHAL(void) {
  196. // Ensure device disconnected (DCON not set)
  197. LPC_USB->DEVCMDSTAT = 0;
  198. // Disable USB interrupts
  199. NVIC_DisableIRQ(USB_IRQ);
  200. }
  201. void USBHAL::connect(void) {
  202. NVIC_EnableIRQ(USB_IRQ);
  203. devCmdStat |= DCON;
  204. LPC_USB->DEVCMDSTAT = devCmdStat;
  205. }
  206. void USBHAL::disconnect(void) {
  207. NVIC_DisableIRQ(USB_IRQ);
  208. devCmdStat &= ~DCON;
  209. LPC_USB->DEVCMDSTAT = devCmdStat;
  210. }
  211. void USBHAL::configureDevice(void) {
  212. // Not required
  213. }
  214. void USBHAL::unconfigureDevice(void) {
  215. // Not required
  216. }
  217. void USBHAL::EP0setup(uint8_t *buffer) {
  218. // Copy setup packet data
  219. USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE);
  220. }
  221. void USBHAL::EP0read(void) {
  222. // Start an endpoint 0 read
  223. // The USB ISR will call USBDevice_EP0out() when a packet has been read,
  224. // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to
  225. // read the data.
  226. ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \
  227. | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
  228. }
  229. uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
  230. // Complete an endpoint 0 read
  231. uint32_t bytesRead;
  232. // Find how many bytes were read
  233. bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]);
  234. // Copy data
  235. USBMemCopy(buffer, ct->out, bytesRead);
  236. return bytesRead;
  237. }
  238. void USBHAL::EP0readStage(void) {
  239. // Not required
  240. }
  241. void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
  242. // Start and endpoint 0 write
  243. // The USB ISR will call USBDevice_EP0in() when the data has
  244. // been written, the USBDevice layer then calls
  245. // USBBusInterface_EP0getWriteResult() to complete the transaction.
  246. // Copy data
  247. USBMemCopy(ct->in, buffer, size);
  248. // Start transfer
  249. ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \
  250. | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in);
  251. }
  252. EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
  253. uint8_t bf = 0;
  254. uint32_t flags = 0;
  255. //check which buffer must be filled
  256. if (LPC_USB->EPBUFCFG & EP(endpoint)) {
  257. // Double buffered
  258. if (LPC_USB->EPINUSE & EP(endpoint)) {
  259. bf = 1;
  260. } else {
  261. bf = 0;
  262. }
  263. }
  264. // if isochronous endpoint, T = 1
  265. if(endpointState[endpoint].options & ISOCHRONOUS)
  266. {
  267. flags |= CMDSTS_T;
  268. }
  269. //Active the endpoint for reading
  270. ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \
  271. | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags;
  272. return EP_PENDING;
  273. }
  274. EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) {
  275. uint8_t bf = 0;
  276. if (!(epComplete & EP(endpoint)))
  277. return EP_PENDING;
  278. else {
  279. epComplete &= ~EP(endpoint);
  280. //check which buffer has been filled
  281. if (LPC_USB->EPBUFCFG & EP(endpoint)) {
  282. // Double buffered (here we read the previous buffer which was used)
  283. if (LPC_USB->EPINUSE & EP(endpoint)) {
  284. bf = 0;
  285. } else {
  286. bf = 1;
  287. }
  288. }
  289. // Find how many bytes were read
  290. *bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[bf]));
  291. // Copy data
  292. USBMemCopy(data, ct->out, *bytesRead);
  293. return EP_COMPLETED;
  294. }
  295. }
  296. void USBHAL::EP0getWriteResult(void) {
  297. // Not required
  298. }
  299. void USBHAL::EP0stall(void) {
  300. ep[0].in[0] = CMDSTS_S;
  301. ep[0].out[0] = CMDSTS_S;
  302. }
  303. void USBHAL::setAddress(uint8_t address) {
  304. devCmdStat &= ~DEV_ADDR_MASK;
  305. devCmdStat |= DEV_ADDR(address);
  306. LPC_USB->DEVCMDSTAT = devCmdStat;
  307. }
  308. EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
  309. uint32_t flags = 0;
  310. uint32_t bf;
  311. // Validate parameters
  312. if (data == NULL) {
  313. return EP_INVALID;
  314. }
  315. if (endpoint > LAST_PHYSICAL_ENDPOINT) {
  316. return EP_INVALID;
  317. }
  318. if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
  319. return EP_INVALID;
  320. }
  321. if (size > endpointState[endpoint].maxPacket) {
  322. return EP_INVALID;
  323. }
  324. if (LPC_USB->EPBUFCFG & EP(endpoint)) {
  325. // Double buffered
  326. if (LPC_USB->EPINUSE & EP(endpoint)) {
  327. bf = 1;
  328. } else {
  329. bf = 0;
  330. }
  331. } else {
  332. // Single buffered
  333. bf = 0;
  334. }
  335. // Check if already active
  336. if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
  337. return EP_INVALID;
  338. }
  339. // Check if stalled
  340. if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
  341. return EP_STALLED;
  342. }
  343. // Copy data to USB RAM
  344. USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size);
  345. // Add options
  346. if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) {
  347. flags |= CMDSTS_RF;
  348. }
  349. if (endpointState[endpoint].options & ISOCHRONOUS) {
  350. flags |= CMDSTS_T;
  351. }
  352. // Add transfer
  353. ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \
  354. endpointState[endpoint].buffer[bf]) \
  355. | CMDSTS_NBYTES(size) | CMDSTS_A | flags;
  356. return EP_PENDING;
  357. }
  358. EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
  359. uint32_t bf;
  360. // Validate parameters
  361. if (endpoint > LAST_PHYSICAL_ENDPOINT) {
  362. return EP_INVALID;
  363. }
  364. if (OUT_EP(endpoint)) {
  365. return EP_INVALID;
  366. }
  367. if (LPC_USB->EPBUFCFG & EP(endpoint)) {
  368. // Double buffered // TODO: FIX THIS
  369. if (LPC_USB->EPINUSE & EP(endpoint)) {
  370. bf = 1;
  371. } else {
  372. bf = 0;
  373. }
  374. } else {
  375. // Single buffered
  376. bf = 0;
  377. }
  378. // Check if endpoint still active
  379. if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
  380. return EP_PENDING;
  381. }
  382. // Check if stalled
  383. if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
  384. return EP_STALLED;
  385. }
  386. return EP_COMPLETED;
  387. }
  388. void USBHAL::stallEndpoint(uint8_t endpoint) {
  389. // FIX: should this clear active bit?
  390. if (IN_EP(endpoint)) {
  391. ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S;
  392. ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S;
  393. } else {
  394. ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S;
  395. ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S;
  396. }
  397. }
  398. void USBHAL::unstallEndpoint(uint8_t endpoint) {
  399. if (LPC_USB->EPBUFCFG & EP(endpoint)) {
  400. // Double buffered
  401. if (IN_EP(endpoint)) {
  402. ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0
  403. ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0
  404. if (LPC_USB->EPINUSE & EP(endpoint)) {
  405. ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
  406. } else {
  407. ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
  408. }
  409. } else {
  410. ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0
  411. ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0
  412. if (LPC_USB->EPINUSE & EP(endpoint)) {
  413. ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
  414. } else {
  415. ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
  416. }
  417. }
  418. } else {
  419. // Single buffered
  420. if (IN_EP(endpoint)) {
  421. ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
  422. } else {
  423. ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
  424. }
  425. }
  426. }
  427. bool USBHAL::getEndpointStallState(unsigned char endpoint) {
  428. if (IN_EP(endpoint)) {
  429. if (LPC_USB->EPINUSE & EP(endpoint)) {
  430. if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) {
  431. return true;
  432. }
  433. } else {
  434. if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) {
  435. return true;
  436. }
  437. }
  438. } else {
  439. if (LPC_USB->EPINUSE & EP(endpoint)) {
  440. if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) {
  441. return true;
  442. }
  443. } else {
  444. if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) {
  445. return true;
  446. }
  447. }
  448. }
  449. return false;
  450. }
  451. bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) {
  452. uint32_t tmpEpRamPtr;
  453. if (endpoint > LAST_PHYSICAL_ENDPOINT) {
  454. return false;
  455. }
  456. // Not applicable to the control endpoints
  457. if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
  458. return false;
  459. }
  460. // Allocate buffers in USB RAM
  461. tmpEpRamPtr = epRamPtr;
  462. // Must be 64 byte aligned
  463. tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
  464. if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
  465. // Out of memory
  466. return false;
  467. }
  468. // Allocate first buffer
  469. endpointState[endpoint].buffer[0] = tmpEpRamPtr;
  470. tmpEpRamPtr += maxPacket;
  471. if (!(options & SINGLE_BUFFERED)) {
  472. // Must be 64 byte aligned
  473. tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
  474. if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
  475. // Out of memory
  476. return false;
  477. }
  478. // Allocate second buffer
  479. endpointState[endpoint].buffer[1] = tmpEpRamPtr;
  480. tmpEpRamPtr += maxPacket;
  481. }
  482. // Commit to this USB RAM allocation
  483. epRamPtr = tmpEpRamPtr;
  484. // Remaining endpoint state values
  485. endpointState[endpoint].maxPacket = maxPacket;
  486. endpointState[endpoint].options = options;
  487. // Enable double buffering if required
  488. if (options & SINGLE_BUFFERED) {
  489. LPC_USB->EPBUFCFG &= ~EP(endpoint);
  490. } else {
  491. // Double buffered
  492. LPC_USB->EPBUFCFG |= EP(endpoint);
  493. }
  494. // Enable interrupt
  495. LPC_USB->INTEN |= EP(endpoint);
  496. // Enable endpoint
  497. unstallEndpoint(endpoint);
  498. return true;
  499. }
  500. void USBHAL::remoteWakeup(void) {
  501. // Clearing DSUS bit initiates a remote wakeup if the
  502. // device is currently enabled and suspended - otherwise
  503. // it has no effect.
  504. LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
  505. }
  506. static void disableEndpoints(void) {
  507. uint32_t logEp;
  508. // Ref. Table 158 "When a bus reset is received, software
  509. // must set the disable bit of all endpoints to 1".
  510. for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) {
  511. ep[logEp].out[0] = CMDSTS_D;
  512. ep[logEp].out[1] = CMDSTS_D;
  513. ep[logEp].in[0] = CMDSTS_D;
  514. ep[logEp].in[1] = CMDSTS_D;
  515. }
  516. // Start of USB RAM for endpoints > 0
  517. epRamPtr = usbRamPtr;
  518. }
  519. void USBHAL::_usbisr(void) {
  520. instance->usbisr();
  521. }
  522. void USBHAL::usbisr(void) {
  523. // Start of frame
  524. if (LPC_USB->INTSTAT & FRAME_INT) {
  525. // Clear SOF interrupt
  526. LPC_USB->INTSTAT = FRAME_INT;
  527. // SOF event, read frame number
  528. SOF(FRAME_NR(LPC_USB->INFO));
  529. }
  530. // Device state
  531. if (LPC_USB->INTSTAT & DEV_INT) {
  532. LPC_USB->INTSTAT = DEV_INT;
  533. if (LPC_USB->DEVCMDSTAT & DSUS_C) {
  534. // Suspend status changed
  535. LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
  536. if((LPC_USB->DEVCMDSTAT & DSUS) != 0) {
  537. suspendStateChanged(1);
  538. }
  539. }
  540. if (LPC_USB->DEVCMDSTAT & DRES_C) {
  541. // Bus reset
  542. LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
  543. suspendStateChanged(0);
  544. // Disable endpoints > 0
  545. disableEndpoints();
  546. // Bus reset event
  547. busReset();
  548. }
  549. }
  550. // Endpoint 0
  551. if (LPC_USB->INTSTAT & EP(EP0OUT)) {
  552. // Clear EP0OUT/SETUP interrupt
  553. LPC_USB->INTSTAT = EP(EP0OUT);
  554. // Check if SETUP
  555. if (LPC_USB->DEVCMDSTAT & SETUP) {
  556. // Clear Active and Stall bits for EP0
  557. // Documentation does not make it clear if we must use the
  558. // EPSKIP register to achieve this, Fig. 16 and NXP reference
  559. // code suggests we can just clear the Active bits - check with
  560. // NXP to be sure.
  561. ep[0].in[0] = 0;
  562. ep[0].out[0] = 0;
  563. // Clear EP0IN interrupt
  564. LPC_USB->INTSTAT = EP(EP0IN);
  565. // Clear SETUP (and INTONNAK_CI/O) in device status register
  566. LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
  567. // EP0 SETUP event (SETUP data received)
  568. EP0setupCallback();
  569. } else {
  570. // EP0OUT ACK event (OUT data received)
  571. EP0out();
  572. }
  573. }
  574. if (LPC_USB->INTSTAT & EP(EP0IN)) {
  575. // Clear EP0IN interrupt
  576. LPC_USB->INTSTAT = EP(EP0IN);
  577. // EP0IN ACK event (IN data sent)
  578. EP0in();
  579. }
  580. for (uint8_t num = 2; num < 5*2; num++) {
  581. if (LPC_USB->INTSTAT & EP(num)) {
  582. LPC_USB->INTSTAT = EP(num);
  583. epComplete |= EP(num);
  584. if ((instance->*(epCallback[num - 2]))()) {
  585. epComplete &= ~EP(num);
  586. }
  587. }
  588. }
  589. }
  590. #endif