Keyboard firmwares for Atmel AVR and Cortex-M
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

USBHAL_LPC40.cpp 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  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_LPC4088) || defined(TARGET_LPC4088_DM)
  19. #include "USBHAL.h"
  20. // Get endpoint direction
  21. #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
  22. #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
  23. // Convert physical endpoint number to register bit
  24. #define EP(endpoint) (1UL<<endpoint)
  25. // Power Control for Peripherals register
  26. #define PCUSB (1UL<<31)
  27. // USB Clock Control register
  28. #define DEV_CLK_EN (1UL<<1)
  29. #define PORT_CLK_EN (1UL<<3)
  30. #define AHB_CLK_EN (1UL<<4)
  31. // USB Clock Status register
  32. #define DEV_CLK_ON (1UL<<1)
  33. #define AHB_CLK_ON (1UL<<4)
  34. // USB Device Interupt registers
  35. #define FRAME (1UL<<0)
  36. #define EP_FAST (1UL<<1)
  37. #define EP_SLOW (1UL<<2)
  38. #define DEV_STAT (1UL<<3)
  39. #define CCEMPTY (1UL<<4)
  40. #define CDFULL (1UL<<5)
  41. #define RxENDPKT (1UL<<6)
  42. #define TxENDPKT (1UL<<7)
  43. #define EP_RLZED (1UL<<8)
  44. #define ERR_INT (1UL<<9)
  45. // USB Control register
  46. #define RD_EN (1<<0)
  47. #define WR_EN (1<<1)
  48. #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
  49. // USB Receive Packet Length register
  50. #define DV (1UL<<10)
  51. #define PKT_RDY (1UL<<11)
  52. #define PKT_LNGTH_MASK (0x3ff)
  53. // Serial Interface Engine (SIE)
  54. #define SIE_WRITE (0x01)
  55. #define SIE_READ (0x02)
  56. #define SIE_COMMAND (0x05)
  57. #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
  58. // SIE Command codes
  59. #define SIE_CMD_SET_ADDRESS (0xD0)
  60. #define SIE_CMD_CONFIGURE_DEVICE (0xD8)
  61. #define SIE_CMD_SET_MODE (0xF3)
  62. #define SIE_CMD_READ_FRAME_NUMBER (0xF5)
  63. #define SIE_CMD_READ_TEST_REGISTER (0xFD)
  64. #define SIE_CMD_SET_DEVICE_STATUS (0xFE)
  65. #define SIE_CMD_GET_DEVICE_STATUS (0xFE)
  66. #define SIE_CMD_GET_ERROR_CODE (0xFF)
  67. #define SIE_CMD_READ_ERROR_STATUS (0xFB)
  68. #define SIE_CMD_SELECT_ENDPOINT(endpoint) (0x00+endpoint)
  69. #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
  70. #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint) (0x40+endpoint)
  71. #define SIE_CMD_CLEAR_BUFFER (0xF2)
  72. #define SIE_CMD_VALIDATE_BUFFER (0xFA)
  73. // SIE Device Status register
  74. #define SIE_DS_CON (1<<0)
  75. #define SIE_DS_CON_CH (1<<1)
  76. #define SIE_DS_SUS (1<<2)
  77. #define SIE_DS_SUS_CH (1<<3)
  78. #define SIE_DS_RST (1<<4)
  79. // SIE Device Set Address register
  80. #define SIE_DSA_DEV_EN (1<<7)
  81. // SIE Configue Device register
  82. #define SIE_CONF_DEVICE (1<<0)
  83. // Select Endpoint register
  84. #define SIE_SE_FE (1<<0)
  85. #define SIE_SE_ST (1<<1)
  86. #define SIE_SE_STP (1<<2)
  87. #define SIE_SE_PO (1<<3)
  88. #define SIE_SE_EPN (1<<4)
  89. #define SIE_SE_B_1_FULL (1<<5)
  90. #define SIE_SE_B_2_FULL (1<<6)
  91. // Set Endpoint Status command
  92. #define SIE_SES_ST (1<<0)
  93. #define SIE_SES_DA (1<<5)
  94. #define SIE_SES_RF_MO (1<<6)
  95. #define SIE_SES_CND_ST (1<<7)
  96. USBHAL * USBHAL::instance;
  97. static volatile int epComplete;
  98. static uint32_t endpointStallState;
  99. static void SIECommand(uint32_t command) {
  100. // The command phase of a SIE transaction
  101. LPC_USB->DevIntClr = CCEMPTY;
  102. LPC_USB->CmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
  103. while (!(LPC_USB->DevIntSt & CCEMPTY));
  104. }
  105. static void SIEWriteData(uint8_t data) {
  106. // The data write phase of a SIE transaction
  107. LPC_USB->DevIntClr = CCEMPTY;
  108. LPC_USB->CmdCode = SIE_CMD_CODE(SIE_WRITE, data);
  109. while (!(LPC_USB->DevIntSt & CCEMPTY));
  110. }
  111. static uint8_t SIEReadData(uint32_t command) {
  112. // The data read phase of a SIE transaction
  113. LPC_USB->DevIntClr = CDFULL;
  114. LPC_USB->CmdCode = SIE_CMD_CODE(SIE_READ, command);
  115. while (!(LPC_USB->DevIntSt & CDFULL));
  116. return (uint8_t)LPC_USB->CmdData;
  117. }
  118. static void SIEsetDeviceStatus(uint8_t status) {
  119. // Write SIE device status register
  120. SIECommand(SIE_CMD_SET_DEVICE_STATUS);
  121. SIEWriteData(status);
  122. }
  123. static uint8_t SIEgetDeviceStatus(void) {
  124. // Read SIE device status register
  125. SIECommand(SIE_CMD_GET_DEVICE_STATUS);
  126. return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
  127. }
  128. void SIEsetAddress(uint8_t address) {
  129. // Write SIE device address register
  130. SIECommand(SIE_CMD_SET_ADDRESS);
  131. SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
  132. }
  133. static uint8_t SIEselectEndpoint(uint8_t endpoint) {
  134. // SIE select endpoint command
  135. SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
  136. return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
  137. }
  138. static uint8_t SIEclearBuffer(void) {
  139. // SIE clear buffer command
  140. SIECommand(SIE_CMD_CLEAR_BUFFER);
  141. return SIEReadData(SIE_CMD_CLEAR_BUFFER);
  142. }
  143. static void SIEvalidateBuffer(void) {
  144. // SIE validate buffer command
  145. SIECommand(SIE_CMD_VALIDATE_BUFFER);
  146. }
  147. static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status) {
  148. // SIE set endpoint status command
  149. SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
  150. SIEWriteData(status);
  151. }
  152. static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
  153. static uint16_t SIEgetFrameNumber(void) {
  154. // Read current frame number
  155. uint16_t lowByte;
  156. uint16_t highByte;
  157. SIECommand(SIE_CMD_READ_FRAME_NUMBER);
  158. lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
  159. highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
  160. return (highByte << 8) | lowByte;
  161. }
  162. static void SIEconfigureDevice(void) {
  163. // SIE Configure device command
  164. SIECommand(SIE_CMD_CONFIGURE_DEVICE);
  165. SIEWriteData(SIE_CONF_DEVICE);
  166. }
  167. static void SIEunconfigureDevice(void) {
  168. // SIE Configure device command
  169. SIECommand(SIE_CMD_CONFIGURE_DEVICE);
  170. SIEWriteData(0);
  171. }
  172. static void SIEconnect(void) {
  173. // Connect USB device
  174. uint8_t status = SIEgetDeviceStatus();
  175. SIEsetDeviceStatus(status | SIE_DS_CON);
  176. }
  177. static void SIEdisconnect(void) {
  178. // Disconnect USB device
  179. uint8_t status = SIEgetDeviceStatus();
  180. SIEsetDeviceStatus(status & ~SIE_DS_CON);
  181. }
  182. static uint8_t selectEndpointClearInterrupt(uint8_t endpoint) {
  183. // Implemented using using EP_INT_CLR.
  184. LPC_USB->EpIntClr = EP(endpoint);
  185. while (!(LPC_USB->DevIntSt & CDFULL));
  186. return (uint8_t)LPC_USB->CmdData;
  187. }
  188. static void enableEndpointEvent(uint8_t endpoint) {
  189. // Enable an endpoint interrupt
  190. LPC_USB->EpIntEn |= EP(endpoint);
  191. }
  192. static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
  193. static void disableEndpointEvent(uint8_t endpoint) {
  194. // Disable an endpoint interrupt
  195. LPC_USB->EpIntEn &= ~EP(endpoint);
  196. }
  197. static volatile uint32_t __attribute__((used)) dummyRead;
  198. uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
  199. // Read from an OUT endpoint
  200. uint32_t size;
  201. uint32_t i;
  202. uint32_t data = 0;
  203. uint8_t offset;
  204. LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | RD_EN;
  205. while (!(LPC_USB->RxPLen & PKT_RDY));
  206. size = LPC_USB->RxPLen & PKT_LNGTH_MASK;
  207. offset = 0;
  208. if (size > 0) {
  209. for (i=0; i<size; i++) {
  210. if (offset==0) {
  211. // Fetch up to four bytes of data as a word
  212. data = LPC_USB->RxData;
  213. }
  214. // extract a byte
  215. *buffer = (data>>offset) & 0xff;
  216. buffer++;
  217. // move on to the next byte
  218. offset = (offset + 8) % 32;
  219. }
  220. } else {
  221. dummyRead = LPC_USB->RxData;
  222. }
  223. LPC_USB->Ctrl = 0;
  224. if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
  225. SIEselectEndpoint(endpoint);
  226. SIEclearBuffer();
  227. }
  228. return size;
  229. }
  230. static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size) {
  231. // Write to an IN endpoint
  232. uint32_t temp, data;
  233. uint8_t offset;
  234. LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | WR_EN;
  235. LPC_USB->TxPLen = size;
  236. offset = 0;
  237. data = 0;
  238. if (size>0) {
  239. do {
  240. // Fetch next data byte into a word-sized temporary variable
  241. temp = *buffer++;
  242. // Add to current data word
  243. temp = temp << offset;
  244. data = data | temp;
  245. // move on to the next byte
  246. offset = (offset + 8) % 32;
  247. size--;
  248. if ((offset==0) || (size==0)) {
  249. // Write the word to the endpoint
  250. LPC_USB->TxData = data;
  251. data = 0;
  252. }
  253. } while (size>0);
  254. } else {
  255. LPC_USB->TxData = 0;
  256. }
  257. // Clear WR_EN to cover zero length packet case
  258. LPC_USB->Ctrl=0;
  259. SIEselectEndpoint(endpoint);
  260. SIEvalidateBuffer();
  261. }
  262. USBHAL::USBHAL(void) {
  263. // Disable IRQ
  264. NVIC_DisableIRQ(USB_IRQn);
  265. // fill in callback array
  266. epCallback[0] = &USBHAL::EP1_OUT_callback;
  267. epCallback[1] = &USBHAL::EP1_IN_callback;
  268. epCallback[2] = &USBHAL::EP2_OUT_callback;
  269. epCallback[3] = &USBHAL::EP2_IN_callback;
  270. epCallback[4] = &USBHAL::EP3_OUT_callback;
  271. epCallback[5] = &USBHAL::EP3_IN_callback;
  272. epCallback[6] = &USBHAL::EP4_OUT_callback;
  273. epCallback[7] = &USBHAL::EP4_IN_callback;
  274. epCallback[8] = &USBHAL::EP5_OUT_callback;
  275. epCallback[9] = &USBHAL::EP5_IN_callback;
  276. epCallback[10] = &USBHAL::EP6_OUT_callback;
  277. epCallback[11] = &USBHAL::EP6_IN_callback;
  278. epCallback[12] = &USBHAL::EP7_OUT_callback;
  279. epCallback[13] = &USBHAL::EP7_IN_callback;
  280. epCallback[14] = &USBHAL::EP8_OUT_callback;
  281. epCallback[15] = &USBHAL::EP8_IN_callback;
  282. epCallback[16] = &USBHAL::EP9_OUT_callback;
  283. epCallback[17] = &USBHAL::EP9_IN_callback;
  284. epCallback[18] = &USBHAL::EP10_OUT_callback;
  285. epCallback[19] = &USBHAL::EP10_IN_callback;
  286. epCallback[20] = &USBHAL::EP11_OUT_callback;
  287. epCallback[21] = &USBHAL::EP11_IN_callback;
  288. epCallback[22] = &USBHAL::EP12_OUT_callback;
  289. epCallback[23] = &USBHAL::EP12_IN_callback;
  290. epCallback[24] = &USBHAL::EP13_OUT_callback;
  291. epCallback[25] = &USBHAL::EP13_IN_callback;
  292. epCallback[26] = &USBHAL::EP14_OUT_callback;
  293. epCallback[27] = &USBHAL::EP14_IN_callback;
  294. epCallback[28] = &USBHAL::EP15_OUT_callback;
  295. epCallback[29] = &USBHAL::EP15_IN_callback;
  296. // Enable power to USB device controller
  297. LPC_SC->PCONP |= PCUSB;
  298. // Enable USB clocks
  299. LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN;
  300. while ((LPC_USB->USBClkSt & (DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN)) != (DEV_CLK_ON | AHB_CLK_ON | PORT_CLK_EN));
  301. // Select port USB2
  302. LPC_USB->StCtrl |= 3;
  303. // Configure pin P0.31 to be USB2
  304. LPC_IOCON->P0_31 &= ~0x07;
  305. LPC_IOCON->P0_31 |= 0x01;
  306. // Disconnect USB device
  307. SIEdisconnect();
  308. // Configure pin P0.14 to be Connect
  309. LPC_IOCON->P0_14 &= ~0x07;
  310. LPC_IOCON->P0_14 |= 0x03;
  311. // Connect must be low for at least 2.5uS
  312. wait(0.3);
  313. // Set the maximum packet size for the control endpoints
  314. realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
  315. realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
  316. // Attach IRQ
  317. instance = this;
  318. NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
  319. // Enable interrupts for device events and EP0
  320. LPC_USB->DevIntEn = EP_SLOW | DEV_STAT | FRAME;
  321. enableEndpointEvent(EP0IN);
  322. enableEndpointEvent(EP0OUT);
  323. }
  324. USBHAL::~USBHAL(void) {
  325. // Ensure device disconnected
  326. SIEdisconnect();
  327. // Disable USB interrupts
  328. NVIC_DisableIRQ(USB_IRQn);
  329. }
  330. void USBHAL::connect(void) {
  331. NVIC_EnableIRQ(USB_IRQn);
  332. // Connect USB device
  333. SIEconnect();
  334. }
  335. void USBHAL::disconnect(void) {
  336. NVIC_DisableIRQ(USB_IRQn);
  337. // Disconnect USB device
  338. SIEdisconnect();
  339. }
  340. void USBHAL::configureDevice(void) {
  341. SIEconfigureDevice();
  342. }
  343. void USBHAL::unconfigureDevice(void) {
  344. SIEunconfigureDevice();
  345. }
  346. void USBHAL::setAddress(uint8_t address) {
  347. SIEsetAddress(address);
  348. }
  349. void USBHAL::EP0setup(uint8_t *buffer) {
  350. endpointReadcore(EP0OUT, buffer);
  351. }
  352. void USBHAL::EP0read(void) {
  353. // Not required
  354. }
  355. void USBHAL::EP0readStage(void) {
  356. // Not required
  357. }
  358. uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
  359. return endpointReadcore(EP0OUT, buffer);
  360. }
  361. void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
  362. endpointWritecore(EP0IN, buffer, size);
  363. }
  364. void USBHAL::EP0getWriteResult(void) {
  365. // Not required
  366. }
  367. void USBHAL::EP0stall(void) {
  368. // This will stall both control endpoints
  369. stallEndpoint(EP0OUT);
  370. }
  371. EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
  372. return EP_PENDING;
  373. }
  374. EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
  375. //for isochronous endpoint, we don't wait an interrupt
  376. if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
  377. if (!(epComplete & EP(endpoint)))
  378. return EP_PENDING;
  379. }
  380. *bytesRead = endpointReadcore(endpoint, buffer);
  381. epComplete &= ~EP(endpoint);
  382. return EP_COMPLETED;
  383. }
  384. EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
  385. if (getEndpointStallState(endpoint)) {
  386. return EP_STALLED;
  387. }
  388. epComplete &= ~EP(endpoint);
  389. endpointWritecore(endpoint, data, size);
  390. return EP_PENDING;
  391. }
  392. EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
  393. if (epComplete & EP(endpoint)) {
  394. epComplete &= ~EP(endpoint);
  395. return EP_COMPLETED;
  396. }
  397. return EP_PENDING;
  398. }
  399. bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
  400. // Realise an endpoint
  401. LPC_USB->DevIntClr = EP_RLZED;
  402. LPC_USB->ReEp |= EP(endpoint);
  403. LPC_USB->EpInd = endpoint;
  404. LPC_USB->MaxPSize = maxPacket;
  405. while (!(LPC_USB->DevIntSt & EP_RLZED));
  406. LPC_USB->DevIntClr = EP_RLZED;
  407. // Clear stall state
  408. endpointStallState &= ~EP(endpoint);
  409. enableEndpointEvent(endpoint);
  410. return true;
  411. }
  412. void USBHAL::stallEndpoint(uint8_t endpoint) {
  413. // Stall an endpoint
  414. if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) {
  415. // Conditionally stall both control endpoints
  416. SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
  417. } else {
  418. SIEsetEndpointStatus(endpoint, SIE_SES_ST);
  419. // Update stall state
  420. endpointStallState |= EP(endpoint);
  421. }
  422. }
  423. void USBHAL::unstallEndpoint(uint8_t endpoint) {
  424. // Unstall an endpoint. The endpoint will also be reinitialised
  425. SIEsetEndpointStatus(endpoint, 0);
  426. // Update stall state
  427. endpointStallState &= ~EP(endpoint);
  428. }
  429. bool USBHAL::getEndpointStallState(uint8_t endpoint) {
  430. // Returns true if endpoint stalled
  431. return endpointStallState & EP(endpoint);
  432. }
  433. void USBHAL::remoteWakeup(void) {
  434. // Remote wakeup
  435. uint8_t status;
  436. // Enable USB clocks
  437. LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
  438. while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
  439. status = SIEgetDeviceStatus();
  440. SIEsetDeviceStatus(status & ~SIE_DS_SUS);
  441. }
  442. void USBHAL::_usbisr(void) {
  443. instance->usbisr();
  444. }
  445. void USBHAL::usbisr(void) {
  446. uint8_t devStat;
  447. if (LPC_USB->DevIntSt & FRAME) {
  448. // Start of frame event
  449. SOF(SIEgetFrameNumber());
  450. // Clear interrupt status flag
  451. LPC_USB->DevIntClr = FRAME;
  452. }
  453. if (LPC_USB->DevIntSt & DEV_STAT) {
  454. // Device Status interrupt
  455. // Must clear the interrupt status flag before reading the device status from the SIE
  456. LPC_USB->DevIntClr = DEV_STAT;
  457. // Read device status from SIE
  458. devStat = SIEgetDeviceStatus();
  459. //printf("devStat: %d\r\n", devStat);
  460. if (devStat & SIE_DS_SUS_CH) {
  461. // Suspend status changed
  462. if((devStat & SIE_DS_SUS) != 0) {
  463. suspendStateChanged(0);
  464. }
  465. }
  466. if (devStat & SIE_DS_RST) {
  467. // Bus reset
  468. if((devStat & SIE_DS_SUS) == 0) {
  469. suspendStateChanged(1);
  470. }
  471. busReset();
  472. }
  473. }
  474. if (LPC_USB->DevIntSt & EP_SLOW) {
  475. // (Slow) Endpoint Interrupt
  476. // Process each endpoint interrupt
  477. if (LPC_USB->EpIntSt & EP(EP0OUT)) {
  478. if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
  479. // this is a setup packet
  480. EP0setupCallback();
  481. } else {
  482. EP0out();
  483. }
  484. LPC_USB->DevIntClr = EP_SLOW;
  485. }
  486. if (LPC_USB->EpIntSt & EP(EP0IN)) {
  487. selectEndpointClearInterrupt(EP0IN);
  488. LPC_USB->DevIntClr = EP_SLOW;
  489. EP0in();
  490. }
  491. for (uint8_t num = 2; num < 16*2; num++) {
  492. if (LPC_USB->EpIntSt & EP(num)) {
  493. selectEndpointClearInterrupt(num);
  494. epComplete |= EP(num);
  495. LPC_USB->DevIntClr = EP_SLOW;
  496. if ((instance->*(epCallback[num - 2]))()) {
  497. epComplete &= ~EP(num);
  498. }
  499. }
  500. }
  501. }
  502. }
  503. #endif