Simple USBHost library for Nucleo F446RE/F411RE/F401RE FRDM-KL46Z/KL25Z/F64F LPC4088/LPC1768

Dependencies:   FATFileSystem

Dependents:   F401RE-BTstack_example F401RE-USBHostMSD_HelloWorld

Fork of KL46Z-USBHost by Norimasa Okamoto

簡易USBホストライブラリです。
official-USBHostの下位互換で対応プログラムを僅かな修正で動かすことが出来ます。

Platforms

  • Nucleo F446RE
  • Nucleo F411RE
  • Nucleo F401RE
  • FRDM-K64F
  • FRDM-KL46Z
  • FRDM-KL25Z
  • LPC4088
  • LPC1768

Nucleo F446RE/F411RE/F401REのUSB接続方法

ST morphoUSB
U5V (CN10-8)VBUS (1 RED)
PA11 (CN10-14)DM  (2 WHITE)
PA12 (CN10-12)DP  (3 GREEN)
GND (CN10-20)GND (4 BLACK)

Examples

Import programF446RE-USBHostMouse_HelloWorld

USBHostMouse Hello World for ST-Nucleo-F446RE

Import programF401RE-USBHostMSD_HelloWorld

Simple USBHost MSD(USB flash drive) for Nucleo F401RE/FRDM-KL46Z test program

Import programF401RE-USBHostC270_example

Simple USBHost WebCam test program

Import programK64F_USBHostC270_example

Simple USBHost C270 example

Import programF401RE-BTstack_example

BTstack for Nucleo F401RE/FRDM-KL46Z example program

Import programUSBHostRSSI_example

Bluetooth device discovery example program.

Import programKL46Z-USBHostGPS_HelloWorld

Simple USBHost GPS Dongle Receiver for FRDM-KL46Z test program

Committer:
va009039
Date:
Mon Feb 03 13:00:16 2014 +0000
Revision:
9:7f9f64cf5ded
Parent:
8:6463cd1964c0
Child:
10:40c7f6788902
add interrupt write transfer.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 7:9a20482c9a7a 1 // Simple USBHost for FRDM-KL46Z
va009039 7:9a20482c9a7a 2 #include "USBHALHost.h"
va009039 7:9a20482c9a7a 3
va009039 7:9a20482c9a7a 4 template <bool>struct CtAssert;
va009039 7:9a20482c9a7a 5 template <>struct CtAssert<true> {};
va009039 7:9a20482c9a7a 6 #define CTASSERT(A) CtAssert<A>();
va009039 7:9a20482c9a7a 7
va009039 7:9a20482c9a7a 8
va009039 7:9a20482c9a7a 9 #ifdef _USB_DBG
va009039 7:9a20482c9a7a 10 #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
va009039 7:9a20482c9a7a 11 #define USB_DBG_HEX(A,B) debug_hex(A,B)
va009039 7:9a20482c9a7a 12 void debug_hex(uint8_t* buf, int size);
va009039 7:9a20482c9a7a 13 #else
va009039 7:9a20482c9a7a 14 #define USB_DBG(...) while(0)
va009039 7:9a20482c9a7a 15 #define USB_DBG_HEX(A,B) while(0)
va009039 7:9a20482c9a7a 16 #endif
va009039 7:9a20482c9a7a 17
va009039 8:6463cd1964c0 18 #ifdef _USB_TEST
va009039 7:9a20482c9a7a 19 #define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
va009039 7:9a20482c9a7a 20 #define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
va009039 8:6463cd1964c0 21 #else
va009039 8:6463cd1964c0 22 #define USB_TEST_ASSERT(A) while(0)
va009039 8:6463cd1964c0 23 #define USB_TEST_ASSERT_FALSE(A) while(0)
va009039 8:6463cd1964c0 24 #endif
va009039 7:9a20482c9a7a 25
va009039 9:7f9f64cf5ded 26 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
va009039 9:7f9f64cf5ded 27
va009039 7:9a20482c9a7a 28 #define BD_OWN_MASK (1<<7)
va009039 7:9a20482c9a7a 29 #define BD_DATA01_MASK (1<<6)
va009039 7:9a20482c9a7a 30 #define BD_KEEP_MASK (1<<5)
va009039 7:9a20482c9a7a 31 #define BD_NINC_MASK (1<<4)
va009039 7:9a20482c9a7a 32 #define BD_DTS_MASK (1<<3)
va009039 7:9a20482c9a7a 33 #define BD_STALL_MASK (1<<2)
va009039 7:9a20482c9a7a 34
va009039 7:9a20482c9a7a 35 #define TX 1
va009039 7:9a20482c9a7a 36 #define RX 0
va009039 7:9a20482c9a7a 37
va009039 7:9a20482c9a7a 38 #define EP0_BDT_IDX(dir, odd) (((2 * dir) + (1 * odd)))
va009039 7:9a20482c9a7a 39
va009039 7:9a20482c9a7a 40 #define SETUP_TOKEN 0x0D
va009039 7:9a20482c9a7a 41 #define IN_TOKEN 0x09
va009039 7:9a20482c9a7a 42 #define OUT_TOKEN 0x01
va009039 7:9a20482c9a7a 43
va009039 7:9a20482c9a7a 44 // for each endpt: 8 bytes
va009039 7:9a20482c9a7a 45 struct BDT {
va009039 7:9a20482c9a7a 46 uint8_t info; // BD[0:7]
va009039 7:9a20482c9a7a 47 uint8_t dummy; // RSVD: BD[8:15]
va009039 7:9a20482c9a7a 48 uint16_t byte_count; // BD[16:32]
va009039 7:9a20482c9a7a 49 uint32_t address; // Addr
va009039 7:9a20482c9a7a 50 void setBuffer(uint8_t* buf, int size) {
va009039 7:9a20482c9a7a 51 address = (uint32_t)buf;
va009039 7:9a20482c9a7a 52 byte_count = size;
va009039 7:9a20482c9a7a 53 }
va009039 7:9a20482c9a7a 54 uint8_t getStatus() {
va009039 7:9a20482c9a7a 55 return (info>>2)&0x0f;
va009039 7:9a20482c9a7a 56 }
va009039 7:9a20482c9a7a 57 };
va009039 7:9a20482c9a7a 58
va009039 7:9a20482c9a7a 59 __attribute__((__aligned__(512))) BDT bdt[64];
va009039 7:9a20482c9a7a 60
va009039 7:9a20482c9a7a 61 USBHALHost* USBHALHost::instHost;
va009039 7:9a20482c9a7a 62
va009039 7:9a20482c9a7a 63 USBHALHost::USBHALHost() {
va009039 7:9a20482c9a7a 64 instHost = this;
va009039 7:9a20482c9a7a 65 report.clear();
va009039 7:9a20482c9a7a 66 }
va009039 7:9a20482c9a7a 67
va009039 7:9a20482c9a7a 68 void USBHALHost::init() {
va009039 7:9a20482c9a7a 69 // Disable IRQ
va009039 7:9a20482c9a7a 70 NVIC_DisableIRQ(USB0_IRQn);
va009039 7:9a20482c9a7a 71
va009039 7:9a20482c9a7a 72 // choose usb src as PLL
va009039 7:9a20482c9a7a 73 SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK);
va009039 7:9a20482c9a7a 74
va009039 7:9a20482c9a7a 75 // enable OTG clock
va009039 7:9a20482c9a7a 76 SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;
va009039 7:9a20482c9a7a 77
va009039 7:9a20482c9a7a 78 // USB Module Configuration
va009039 7:9a20482c9a7a 79 // Reset USB Module
va009039 7:9a20482c9a7a 80 USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
va009039 7:9a20482c9a7a 81 while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
va009039 7:9a20482c9a7a 82
va009039 7:9a20482c9a7a 83 // Clear interrupt flag
va009039 7:9a20482c9a7a 84 USB0->ISTAT = 0xff;
va009039 7:9a20482c9a7a 85
va009039 7:9a20482c9a7a 86 // Set BDT Base Register
va009039 7:9a20482c9a7a 87 USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8);
va009039 7:9a20482c9a7a 88 USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16);
va009039 7:9a20482c9a7a 89 USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24);
va009039 7:9a20482c9a7a 90
va009039 7:9a20482c9a7a 91 // Set SOF threshold
va009039 7:9a20482c9a7a 92 USB0->SOFTHLD = USB_SOFTHLD_CNT(1);
va009039 7:9a20482c9a7a 93
va009039 7:9a20482c9a7a 94 // pulldown D+ and D-
va009039 7:9a20482c9a7a 95 USB0->USBCTRL = USB_USBCTRL_PDE_MASK;
va009039 7:9a20482c9a7a 96
va009039 7:9a20482c9a7a 97 USB0->USBTRC0 |= 0x40;
va009039 7:9a20482c9a7a 98
va009039 7:9a20482c9a7a 99 // Host mode
va009039 7:9a20482c9a7a 100 USB0->CTL |= USB_CTL_HOSTMODEEN_MASK;
va009039 7:9a20482c9a7a 101 // Desable SOF packet generation
va009039 7:9a20482c9a7a 102 USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
va009039 7:9a20482c9a7a 103
va009039 7:9a20482c9a7a 104 NVIC_SetVector(USB0_IRQn, (uint32_t)_usbisr);
va009039 7:9a20482c9a7a 105 NVIC_EnableIRQ(USB0_IRQn);
va009039 7:9a20482c9a7a 106
va009039 8:6463cd1964c0 107 bool lowSpeed = wait_attach();
va009039 7:9a20482c9a7a 108
va009039 7:9a20482c9a7a 109 for(int retry = 2; retry > 0; retry--) {
va009039 7:9a20482c9a7a 110 // Enable RESET
va009039 7:9a20482c9a7a 111 USB0->CTL |= USB_CTL_RESET_MASK;
va009039 7:9a20482c9a7a 112 wait_ms(500);
va009039 7:9a20482c9a7a 113 USB0->CTL &= ~USB_CTL_RESET_MASK;
va009039 7:9a20482c9a7a 114
va009039 7:9a20482c9a7a 115 // Enable SOF
va009039 7:9a20482c9a7a 116 USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
va009039 7:9a20482c9a7a 117 wait_ms(100);
va009039 7:9a20482c9a7a 118
va009039 7:9a20482c9a7a 119 // token transfer initialize
va009039 7:9a20482c9a7a 120 token_transfer_init();
va009039 7:9a20482c9a7a 121
va009039 7:9a20482c9a7a 122 USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK|
va009039 7:9a20482c9a7a 123 USB_INTEN_ERROREN_MASK;
va009039 7:9a20482c9a7a 124 USB0->ERREN |= USB_ERREN_PIDERREN_MASK|
va009039 7:9a20482c9a7a 125 USB_ERREN_CRC5EOFEN_MASK|
va009039 7:9a20482c9a7a 126 USB_ERREN_CRC16EN_MASK|
va009039 7:9a20482c9a7a 127 USB_ERREN_DFN8EN_MASK|
va009039 7:9a20482c9a7a 128 USB_ERREN_BTOERREN_MASK|
va009039 7:9a20482c9a7a 129 USB_ERREN_DMAERREN_MASK|
va009039 7:9a20482c9a7a 130 USB_ERREN_BTSERREN_MASK;
va009039 7:9a20482c9a7a 131
va009039 8:6463cd1964c0 132 if (addDevice(0, 0, lowSpeed)) {
va009039 7:9a20482c9a7a 133 break;
va009039 7:9a20482c9a7a 134 }
va009039 7:9a20482c9a7a 135 USB_DBG("retry=%d", retry);
va009039 7:9a20482c9a7a 136 USB_TEST_ASSERT(retry > 1);
va009039 7:9a20482c9a7a 137 }
va009039 7:9a20482c9a7a 138 }
va009039 7:9a20482c9a7a 139
va009039 8:6463cd1964c0 140 bool USBHALHost::wait_attach() {
va009039 7:9a20482c9a7a 141 attach_done = false;
va009039 7:9a20482c9a7a 142 USB0->INTEN = USB_INTEN_ATTACHEN_MASK;
va009039 9:7f9f64cf5ded 143 Timer t;
va009039 9:7f9f64cf5ded 144 t.reset();
va009039 9:7f9f64cf5ded 145 t.start();
va009039 9:7f9f64cf5ded 146 while(!attach_done) {
va009039 9:7f9f64cf5ded 147 if (t.read_ms() > 5*1000) {
va009039 9:7f9f64cf5ded 148 t.reset();
va009039 9:7f9f64cf5ded 149 USB_INFO("Please attach USB device.");
va009039 9:7f9f64cf5ded 150 }
va009039 9:7f9f64cf5ded 151 }
va009039 7:9a20482c9a7a 152 wait_ms(100);
va009039 7:9a20482c9a7a 153 USB_TEST_ASSERT_FALSE(USB0->CTL & USB_CTL_SE0_MASK);
va009039 8:6463cd1964c0 154 root_lowSpeed = (USB0->CTL & USB_CTL_JSTATE_MASK) ? false : true;
va009039 8:6463cd1964c0 155 return root_lowSpeed;
va009039 7:9a20482c9a7a 156 }
va009039 7:9a20482c9a7a 157
va009039 8:6463cd1964c0 158 void USBHALHost::setAddr(int _addr, bool _lowSpeed) {
va009039 8:6463cd1964c0 159 USB0->ADDR = (_lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(_addr);
va009039 7:9a20482c9a7a 160 }
va009039 7:9a20482c9a7a 161
va009039 8:6463cd1964c0 162 void USBHALHost::setEndpoint() {
va009039 8:6463cd1964c0 163 USB0->ENDPOINT[0].ENDPT = (root_lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00)|
va009039 8:6463cd1964c0 164 USB_ENDPT_RETRYDIS_MASK|
va009039 7:9a20482c9a7a 165 USB_ENDPT_EPCTLDIS_MASK|
va009039 7:9a20482c9a7a 166 USB_ENDPT_EPRXEN_MASK|
va009039 7:9a20482c9a7a 167 USB_ENDPT_EPTXEN_MASK|
va009039 7:9a20482c9a7a 168 USB_ENDPT_EPHSHK_MASK;
va009039 7:9a20482c9a7a 169 }
va009039 7:9a20482c9a7a 170
va009039 7:9a20482c9a7a 171 void USBHALHost::token_transfer_init() {
va009039 7:9a20482c9a7a 172 tx_ptr = ODD;
va009039 7:9a20482c9a7a 173 rx_ptr = ODD;
va009039 7:9a20482c9a7a 174 }
va009039 7:9a20482c9a7a 175
va009039 7:9a20482c9a7a 176 int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
va009039 8:6463cd1964c0 177 USBDeviceConnected* dev = ep->getDevice();
va009039 7:9a20482c9a7a 178 for(int retry = 0;; retry++) {
va009039 7:9a20482c9a7a 179 token_ready();
va009039 8:6463cd1964c0 180 USB0->ENDPOINT[0].ENDPT = (root_lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00) |
va009039 7:9a20482c9a7a 181 USB_ENDPT_RETRYDIS_MASK|
va009039 7:9a20482c9a7a 182 USB_ENDPT_EPRXEN_MASK|
va009039 7:9a20482c9a7a 183 USB_ENDPT_EPTXEN_MASK|
va009039 7:9a20482c9a7a 184 USB_ENDPT_EPHSHK_MASK;
va009039 7:9a20482c9a7a 185 CTASSERT(sizeof(SETUP_PACKET) == 8);
va009039 7:9a20482c9a7a 186 setup->wLength = wLength;
va009039 7:9a20482c9a7a 187 int idx = EP0_BDT_IDX(TX, tx_ptr);
va009039 7:9a20482c9a7a 188 bdt[idx].setBuffer((uint8_t*)setup, sizeof(SETUP_PACKET));
va009039 7:9a20482c9a7a 189 bdt[idx].info = BD_OWN_MASK |
va009039 7:9a20482c9a7a 190 BD_DTS_MASK; // always data0
va009039 7:9a20482c9a7a 191 token_done = false;
va009039 7:9a20482c9a7a 192 USB0->TOKEN = USB_TOKEN_TOKENPID(SETUP_TOKEN)|
va009039 7:9a20482c9a7a 193 USB_TOKEN_TOKENENDPT(ep->getAddress() & 0x7f);
va009039 7:9a20482c9a7a 194 while(!token_done);
va009039 7:9a20482c9a7a 195 LastStatus = bdt[idx].getStatus();
va009039 7:9a20482c9a7a 196 if (LastStatus == ACK) {
va009039 7:9a20482c9a7a 197 if (retry > 0) {
va009039 7:9a20482c9a7a 198 USB_DBG("retry=%d %02x", retry, prev_LastStatus);
va009039 7:9a20482c9a7a 199 }
va009039 7:9a20482c9a7a 200 break;
va009039 7:9a20482c9a7a 201 } else if (LastStatus == STALL) {
va009039 7:9a20482c9a7a 202 report.stall++;
va009039 7:9a20482c9a7a 203 return STALL;
va009039 7:9a20482c9a7a 204 }
va009039 7:9a20482c9a7a 205 if (retry > 10) {
va009039 7:9a20482c9a7a 206 USB_DBG("retry=%d", retry);
va009039 7:9a20482c9a7a 207 break;
va009039 7:9a20482c9a7a 208 }
va009039 7:9a20482c9a7a 209 prev_LastStatus = LastStatus;
va009039 7:9a20482c9a7a 210 wait_ms(100 * retry);
va009039 7:9a20482c9a7a 211 }
va009039 7:9a20482c9a7a 212 ep->setData01(DATA1); // next toggle
va009039 7:9a20482c9a7a 213 return LastStatus;
va009039 7:9a20482c9a7a 214 }
va009039 7:9a20482c9a7a 215
va009039 7:9a20482c9a7a 216 int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
va009039 7:9a20482c9a7a 217 for(int retry = 0;; retry++) {
va009039 7:9a20482c9a7a 218 token_ready();
va009039 7:9a20482c9a7a 219 int idx = EP0_BDT_IDX(RX, rx_ptr);
va009039 7:9a20482c9a7a 220 bdt[idx].setBuffer(data, size);
va009039 7:9a20482c9a7a 221 bdt[idx].info = BD_OWN_MASK|
va009039 7:9a20482c9a7a 222 BD_DTS_MASK|
va009039 7:9a20482c9a7a 223 (ep->getData01() == DATA1 ? BD_DATA01_MASK : 0);
va009039 7:9a20482c9a7a 224 token_done = false;
va009039 7:9a20482c9a7a 225 USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)|
va009039 7:9a20482c9a7a 226 USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f);
va009039 7:9a20482c9a7a 227 while(!token_done);
va009039 7:9a20482c9a7a 228 LastStatus = bdt[idx].getStatus();
va009039 7:9a20482c9a7a 229 int len = bdt[idx].byte_count;
va009039 7:9a20482c9a7a 230 if (LastStatus == DATA0 || LastStatus == DATA1) {
va009039 7:9a20482c9a7a 231 USB_TEST_ASSERT(ep->getData01() == LastStatus);
va009039 7:9a20482c9a7a 232 ep->setData01(LastStatus == DATA0 ? DATA1 : DATA0);
va009039 7:9a20482c9a7a 233 if (retry > 0) {
va009039 8:6463cd1964c0 234 //USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus);
va009039 7:9a20482c9a7a 235 }
va009039 7:9a20482c9a7a 236 return len;
va009039 7:9a20482c9a7a 237 } else if (LastStatus == STALL) {
va009039 7:9a20482c9a7a 238 report.stall++;
va009039 7:9a20482c9a7a 239 return -1;
va009039 7:9a20482c9a7a 240 } else if (LastStatus == NAK) {
va009039 7:9a20482c9a7a 241 report.nak++;
va009039 7:9a20482c9a7a 242 if (retry >= retryLimit) {
va009039 7:9a20482c9a7a 243 if (retryLimit > 0) {
va009039 7:9a20482c9a7a 244 USB_DBG("retry=%d retryLimit=%d", retry, retryLimit);
va009039 7:9a20482c9a7a 245 }
va009039 7:9a20482c9a7a 246 return -1;
va009039 7:9a20482c9a7a 247 }
va009039 7:9a20482c9a7a 248 wait_ms(100 * retry);
va009039 7:9a20482c9a7a 249 } else if (LastStatus == Bus_Timeout) {
va009039 7:9a20482c9a7a 250 if (retry >= retryLimit) {
va009039 7:9a20482c9a7a 251 if (retryLimit > 0) {
va009039 7:9a20482c9a7a 252 USB_DBG("Bus_Timeout retry=%d retryLimit=%d", retry, retryLimit);
va009039 7:9a20482c9a7a 253 }
va009039 7:9a20482c9a7a 254 return -1;
va009039 7:9a20482c9a7a 255 }
va009039 7:9a20482c9a7a 256 wait_ms(500 + 100 * retry);
va009039 7:9a20482c9a7a 257 } else {
va009039 7:9a20482c9a7a 258 return -1;
va009039 7:9a20482c9a7a 259 }
va009039 7:9a20482c9a7a 260 prev_LastStatus = LastStatus;
va009039 7:9a20482c9a7a 261 }
va009039 7:9a20482c9a7a 262 }
va009039 7:9a20482c9a7a 263
va009039 7:9a20482c9a7a 264 int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
va009039 7:9a20482c9a7a 265 for(int retry = 0;; retry++) {
va009039 7:9a20482c9a7a 266 token_ready();
va009039 7:9a20482c9a7a 267 int idx = EP0_BDT_IDX(TX, tx_ptr);
va009039 7:9a20482c9a7a 268 bdt[idx].setBuffer((uint8_t*)data, size);
va009039 7:9a20482c9a7a 269 bdt[idx].info = BD_OWN_MASK|
va009039 7:9a20482c9a7a 270 BD_DTS_MASK|
va009039 7:9a20482c9a7a 271 (ep->getData01() == DATA1 ? BD_DATA01_MASK : 0);
va009039 7:9a20482c9a7a 272 token_done = false;
va009039 7:9a20482c9a7a 273 USB0->TOKEN = USB_TOKEN_TOKENPID(OUT_TOKEN)|
va009039 7:9a20482c9a7a 274 USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f);
va009039 7:9a20482c9a7a 275 while(!token_done);
va009039 7:9a20482c9a7a 276 LastStatus = bdt[idx].getStatus();
va009039 7:9a20482c9a7a 277 int len = bdt[idx].byte_count;
va009039 7:9a20482c9a7a 278 //USB_DBG("len=%d %02x", len, LastStatus);
va009039 7:9a20482c9a7a 279 if (LastStatus == ACK) {
va009039 7:9a20482c9a7a 280 ep->toggleData01();
va009039 7:9a20482c9a7a 281 if (retry > 0) {
va009039 7:9a20482c9a7a 282 USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus);
va009039 7:9a20482c9a7a 283 }
va009039 7:9a20482c9a7a 284 return len;
va009039 7:9a20482c9a7a 285 } else if (LastStatus == STALL) {
va009039 7:9a20482c9a7a 286 report.stall++;
va009039 7:9a20482c9a7a 287 return -1;
va009039 7:9a20482c9a7a 288 } else if (LastStatus == NAK) {
va009039 7:9a20482c9a7a 289 report.nak++;
va009039 7:9a20482c9a7a 290 if (retry > retryLimit) {
va009039 7:9a20482c9a7a 291 USB_DBG("retry=%d retryLimit=%d", retry, retryLimit);
va009039 7:9a20482c9a7a 292 return -1;
va009039 7:9a20482c9a7a 293 }
va009039 7:9a20482c9a7a 294 wait_ms(100 * retry);
va009039 7:9a20482c9a7a 295 } else {
va009039 7:9a20482c9a7a 296 return -1;
va009039 7:9a20482c9a7a 297 }
va009039 7:9a20482c9a7a 298 prev_LastStatus = LastStatus;
va009039 7:9a20482c9a7a 299 }
va009039 7:9a20482c9a7a 300 }
va009039 7:9a20482c9a7a 301
va009039 7:9a20482c9a7a 302 int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
va009039 7:9a20482c9a7a 303 while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK); // TOKEN_BUSY ?
va009039 7:9a20482c9a7a 304 USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF
va009039 7:9a20482c9a7a 305 while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK));
va009039 7:9a20482c9a7a 306 USB0->SOFTHLD = 0; // this is needed as without this you can get errors
va009039 7:9a20482c9a7a 307 USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF
va009039 7:9a20482c9a7a 308
va009039 7:9a20482c9a7a 309 USB0->ENDPOINT[0].ENDPT = USB_ENDPT_EPCTLDIS_MASK|
va009039 7:9a20482c9a7a 310 USB_ENDPT_RETRYDIS_MASK|
va009039 7:9a20482c9a7a 311 USB_ENDPT_EPRXEN_MASK|
va009039 7:9a20482c9a7a 312 USB_ENDPT_EPTXEN_MASK;
va009039 7:9a20482c9a7a 313 int idx = EP0_BDT_IDX(RX, rx_ptr);
va009039 7:9a20482c9a7a 314 bdt[idx].setBuffer(data, size);
va009039 7:9a20482c9a7a 315 bdt[idx].info = BD_OWN_MASK|
va009039 7:9a20482c9a7a 316 BD_DTS_MASK; // always DATA0
va009039 7:9a20482c9a7a 317 token_done = false;
va009039 7:9a20482c9a7a 318 USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)|
va009039 7:9a20482c9a7a 319 USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f);
va009039 7:9a20482c9a7a 320 while(!token_done);
va009039 7:9a20482c9a7a 321 LastStatus = bdt[idx].getStatus();
va009039 7:9a20482c9a7a 322 int len = bdt[idx].byte_count;
va009039 7:9a20482c9a7a 323 if (LastStatus == DATA0) {
va009039 7:9a20482c9a7a 324 return len;
va009039 7:9a20482c9a7a 325 }
va009039 7:9a20482c9a7a 326 return -1;
va009039 7:9a20482c9a7a 327 }
va009039 7:9a20482c9a7a 328
va009039 7:9a20482c9a7a 329 void USBHALHost::token_ready() {
va009039 7:9a20482c9a7a 330 while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) { // TOKEN_BUSY ?
va009039 7:9a20482c9a7a 331 wait_ms(1);
va009039 7:9a20482c9a7a 332 }
va009039 7:9a20482c9a7a 333 USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF
va009039 7:9a20482c9a7a 334 while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK));
va009039 7:9a20482c9a7a 335 USB0->SOFTHLD = 0; // this is needed as without this you can get errors
va009039 7:9a20482c9a7a 336 USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF
va009039 7:9a20482c9a7a 337 }
va009039 7:9a20482c9a7a 338
va009039 7:9a20482c9a7a 339 void USBHALHost::_usbisr(void) {
va009039 7:9a20482c9a7a 340 if (instHost) {
va009039 7:9a20482c9a7a 341 instHost->UsbIrqhandler();
va009039 7:9a20482c9a7a 342 }
va009039 7:9a20482c9a7a 343 }
va009039 7:9a20482c9a7a 344
va009039 7:9a20482c9a7a 345 void USBHALHost::UsbIrqhandler() {
va009039 7:9a20482c9a7a 346 if (USB0->ISTAT & USB_ISTAT_TOKDNE_MASK) {
va009039 7:9a20482c9a7a 347 uint8_t stat = USB0->STAT;
va009039 7:9a20482c9a7a 348 ODD_EVEN next_ptr = (stat & USB_STAT_ODD_MASK) ? ODD : EVEN;
va009039 7:9a20482c9a7a 349 if (stat & USB_STAT_TX_MASK) {
va009039 7:9a20482c9a7a 350 tx_ptr = next_ptr;
va009039 7:9a20482c9a7a 351 } else {
va009039 7:9a20482c9a7a 352 rx_ptr = next_ptr;
va009039 7:9a20482c9a7a 353 }
va009039 7:9a20482c9a7a 354 USB0->ISTAT = USB_ISTAT_TOKDNE_MASK;
va009039 7:9a20482c9a7a 355 token_done = true;
va009039 7:9a20482c9a7a 356 }
va009039 7:9a20482c9a7a 357 if (USB0->ISTAT & USB_ISTAT_ATTACH_MASK) {
va009039 7:9a20482c9a7a 358 USB0->INTEN &= ~USB_INTEN_ATTACHEN_MASK;
va009039 7:9a20482c9a7a 359 USB0->ISTAT = USB_ISTAT_ATTACH_MASK;
va009039 7:9a20482c9a7a 360 attach_done = true;
va009039 7:9a20482c9a7a 361 }
va009039 7:9a20482c9a7a 362 if (USB0->ISTAT & USB_ISTAT_ERROR_MASK) {
va009039 7:9a20482c9a7a 363 uint8_t errstat = USB0->ERRSTAT;
va009039 7:9a20482c9a7a 364 if (errstat & USB_ERRSTAT_PIDERR_MASK) {
va009039 7:9a20482c9a7a 365 report.errstat_piderr++;
va009039 7:9a20482c9a7a 366 }
va009039 7:9a20482c9a7a 367 if (errstat & USB_ERRSTAT_CRC5EOF_MASK) {
va009039 7:9a20482c9a7a 368 report.errstat_crc5eof++;
va009039 7:9a20482c9a7a 369 }
va009039 7:9a20482c9a7a 370 if (errstat & USB_ERRSTAT_CRC16_MASK) {
va009039 7:9a20482c9a7a 371 report.errstat_crc16++;
va009039 7:9a20482c9a7a 372 }
va009039 7:9a20482c9a7a 373 if (errstat & USB_ERRSTAT_DFN8_MASK) {
va009039 7:9a20482c9a7a 374 report.errstat_dfn8++;
va009039 7:9a20482c9a7a 375 }
va009039 7:9a20482c9a7a 376 if (errstat & USB_ERRSTAT_BTOERR_MASK) {
va009039 7:9a20482c9a7a 377 report.errstat_btoerr++;
va009039 7:9a20482c9a7a 378 }
va009039 7:9a20482c9a7a 379 if (errstat & USB_ERRSTAT_DMAERR_MASK) {
va009039 7:9a20482c9a7a 380 report.errstat_dmaerr++;
va009039 7:9a20482c9a7a 381 }
va009039 7:9a20482c9a7a 382 if (errstat & USB_ERRSTAT_BTSERR_MASK) {
va009039 7:9a20482c9a7a 383 report.errstat_btoerr++;
va009039 7:9a20482c9a7a 384 }
va009039 7:9a20482c9a7a 385 USB0->ERRSTAT = errstat;
va009039 7:9a20482c9a7a 386 USB0->ISTAT = USB_ISTAT_ERROR_MASK;
va009039 7:9a20482c9a7a 387 }
va009039 7:9a20482c9a7a 388 }
va009039 7:9a20482c9a7a 389
va009039 7:9a20482c9a7a 390 void Report::clear() {
va009039 7:9a20482c9a7a 391 errstat_piderr = 0;
va009039 7:9a20482c9a7a 392 errstat_crc5eof = 0;
va009039 7:9a20482c9a7a 393 errstat_crc16 = 0;
va009039 7:9a20482c9a7a 394 errstat_dfn8 = 0;
va009039 7:9a20482c9a7a 395 errstat_btoerr = 0;
va009039 7:9a20482c9a7a 396 errstat_dmaerr = 0;
va009039 7:9a20482c9a7a 397 errstat_bsterr = 0;
va009039 7:9a20482c9a7a 398 //
va009039 7:9a20482c9a7a 399 nak = 0;
va009039 7:9a20482c9a7a 400 }
va009039 7:9a20482c9a7a 401
va009039 7:9a20482c9a7a 402 void Report::print_errstat() {
va009039 7:9a20482c9a7a 403 printf("ERRSTAT PID: %d, CRC5EOF: %d, CRC16: %d, DFN8: %d, BTO: %d, DMA: %d, BST: %d\n",
va009039 7:9a20482c9a7a 404 errstat_piderr, errstat_crc5eof,
va009039 7:9a20482c9a7a 405 errstat_crc16, errstat_dfn8,
va009039 7:9a20482c9a7a 406 errstat_btoerr, errstat_dmaerr, errstat_bsterr);
va009039 7:9a20482c9a7a 407 }
va009039 7:9a20482c9a7a 408
va009039 7:9a20482c9a7a 409 void debug_hex(uint8_t* buf, int size) {
va009039 8:6463cd1964c0 410 int n = 0;
va009039 7:9a20482c9a7a 411 for(int i = 0; i < size; i++) {
va009039 7:9a20482c9a7a 412 fprintf(stderr, "%02x ", buf[i]);
va009039 8:6463cd1964c0 413 if (++n >= 16) {
va009039 8:6463cd1964c0 414 fprintf(stderr, "\n");
va009039 8:6463cd1964c0 415 n = 0;
va009039 7:9a20482c9a7a 416 }
va009039 7:9a20482c9a7a 417 }
va009039 8:6463cd1964c0 418 if (n > 0) {
va009039 8:6463cd1964c0 419 fprintf(stderr, "\n");
va009039 8:6463cd1964c0 420 }
va009039 7:9a20482c9a7a 421 }
va009039 7:9a20482c9a7a 422