22
22
23
23
#include " ../../inc/MarlinConfigPre.h"
24
24
25
+ /* *
26
+ * Adjust USB_DEBUG to select debugging verbosity.
27
+ * 0 - no debug messages
28
+ * 1 - basic insertion/removal messages
29
+ * 2 - show USB state transitions
30
+ * 3 - perform block range checking
31
+ * 4 - print each block access
32
+ */
33
+ #define USB_DEBUG 1
34
+ #define USB_STARTUP_DELAY 0
35
+
36
+ // uncomment to get 'printf' console debugging. NOT FOR UNO!
37
+ // #define HOST_DEBUG(...) {char s[255]; sprintf(s,__VA_ARGS__); SERIAL_ECHOLNPAIR("UHS:",s);}
38
+ // #define BS_HOST_DEBUG(...) {char s[255]; sprintf(s,__VA_ARGS__); SERIAL_ECHOLNPAIR("UHS:",s);}
39
+ // #define MAX_HOST_DEBUG(...) {char s[255]; sprintf(s,__VA_ARGS__); SERIAL_ECHOLNPAIR("UHS:",s);}
40
+
25
41
#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
26
42
43
+ #include " ../../Marlin.h"
27
44
#include " ../../core/serial.h"
45
+ #include " ../../module/temperature.h"
46
+
47
+ static_assert (USB_CS_PIN != -1 , " USB_CS_PIN must be defined" );
48
+ static_assert (USB_INTR_PIN != -1 , " USB_INTR_PIN must be defined" );
49
+
50
+ #if ENABLED(USE_UHS3_USB)
51
+ #define NO_AUTO_SPEED
52
+ #define UHS_MAX3421E_SPD 8000000 >> SPI_SPEED
53
+ #define UHS_DEVICE_WINDOWS_USB_SPEC_VIOLATION_DESCRIPTOR_DEVICE 1
54
+ #define UHS_HOST_MAX_INTERFACE_DRIVERS 2
55
+ #define MASS_MAX_SUPPORTED_LUN 1
56
+ #define USB_HOST_SERIAL MYSERIAL0
57
+
58
+ // Workaround for certain issues with UHS3
59
+ #define SKIP_PAGE3F // Required for IOGEAR media adapter
60
+ #define USB_NO_TEST_UNIT_READY // Required for removable media adapter
61
+ #define USB_HOST_MANUAL_POLL // Optimization to shut off IRQ automatically
62
+
63
+ // Workarounds for keeping Marlin's watchdog timer from barking...
64
+ void marlin_yield () {
65
+ thermalManager.manage_heater ();
66
+ }
67
+ #define SYSTEM_OR_SPECIAL_YIELD (...) marlin_yield();
68
+ #define delay (x ) safe_delay(x)
69
+
70
+ #define LOAD_USB_HOST_SYSTEM
71
+ #define LOAD_USB_HOST_SHIELD
72
+ #define LOAD_UHS_BULK_STORAGE
73
+
74
+ #define MARLIN_UHS_WRITE_SS (v ) WRITE(USB_CS_PIN, v)
75
+ #define MARLIN_UHS_READ_IRQ () READ(USB_INTR_PIN)
76
+
77
+ #include " lib-uhs3/UHS_host/UHS_host.h"
78
+
79
+ MAX3421E_HOST usb (USB_CS_PIN, USB_INTR_PIN);
80
+ UHS_Bulk_Storage bulk (&usb);
81
+
82
+ #define UHS_START (usb.Init() == 0 )
83
+ #define UHS_STATE (state ) UHS_USB_HOST_STATE_##state
84
+ #else
85
+ #include " lib-uhs2/Usb.h"
86
+ #include " lib-uhs2/masstorage.h"
28
87
29
- #include " lib/Usb.h"
30
- #include " lib/masstorage.h"
88
+ USB usb;
89
+ BulkOnly bulk (&usb);
90
+
91
+ #define UHS_START usb.start()
92
+ #define UHS_STATE (state ) USB_STATE_##state
93
+ #endif
31
94
32
95
#include " Sd2Card_FlashDrive.h"
33
96
34
97
#if HAS_DISPLAY
35
98
#include " ../../lcd/ultralcd.h"
36
99
#endif
37
100
38
- USB usb;
39
- BulkOnly bulk (&usb);
101
+ static enum {
102
+ UNINITIALIZED,
103
+ DO_STARTUP,
104
+ WAIT_FOR_DEVICE,
105
+ WAIT_FOR_LUN,
106
+ MEDIA_READY,
107
+ MEDIA_ERROR
108
+ } state;
109
+
110
+ #if USB_DEBUG >= 3
111
+ uint32_t lun0_capacity;
112
+ #endif
113
+
114
+ bool Sd2Card::usbStartup () {
115
+ if (state <= DO_STARTUP) {
116
+ SERIAL_ECHOPGM (" Starting USB host..." );
117
+ if (!UHS_START) {
118
+ SERIAL_ECHOLNPGM (" failed." );
119
+ #if EITHER(ULTRA_LCD, EXTENSIBLE_UI)
120
+ LCD_MESSAGEPGM (" USB start failed" );
121
+ #endif
122
+ return false ;
123
+ }
40
124
41
- Sd2Card::state_t Sd2Card::state;
125
+ // SPI quick test - check revision register
126
+ switch (usb.regRd (rREVISION)) {
127
+ case 0x01 : SERIAL_ECHOLNPGM (" rev.01 started" ); break ;
128
+ case 0x12 : SERIAL_ECHOLNPGM (" rev.02 started" ); break ;
129
+ case 0x13 : SERIAL_ECHOLNPGM (" rev.03 started" ); break ;
130
+ default : SERIAL_ECHOLNPGM (" started. rev unknown." ); break ;
131
+ }
132
+ state = WAIT_FOR_DEVICE;
133
+ }
134
+ return true ;
135
+ }
42
136
43
137
// The USB library needs to be called periodically to detect USB thumbdrive
44
138
// insertion and removals. Call this idle() function periodically to allow
45
139
// the USB library to monitor for such events. This function also takes care
46
140
// of initializing the USB library for the first time.
47
141
48
142
void Sd2Card::idle () {
49
- static uint32_t next_retry;
50
-
51
- switch (state) {
52
- case USB_HOST_DELAY_INIT:
53
- next_retry = millis () + 2000 ;
54
- state = USB_HOST_WAITING;
55
- break ;
56
- case USB_HOST_WAITING:
57
- if (ELAPSED (millis (), next_retry)) {
58
- next_retry = millis () + 2000 ;
59
- state = USB_HOST_UNINITIALIZED;
60
- }
61
- break ;
62
- case USB_HOST_UNINITIALIZED:
63
- SERIAL_ECHOPGM (" Starting USB host..." );
64
- if (!usb.start ()) {
65
- SERIAL_ECHOPGM (" Failed. Retrying in 2s." );
66
- #if HAS_DISPLAY
67
- LCD_MESSAGEPGM (" USB start failed" );
68
- #endif
69
- state = USB_HOST_DELAY_INIT;
143
+ usb.Task ();
144
+
145
+ const uint8_t task_state = usb.getUsbTaskState ();
146
+
147
+ #if USB_DEBUG >= 2
148
+ if (state > DO_STARTUP) {
149
+ static uint8_t laststate = 232 ;
150
+ if (task_state != laststate) {
151
+ laststate = task_state;
152
+ #define UHS_USB_DEBUG (x ) case UHS_STATE (x): SERIAL_ECHOLNPGM(#x); break
153
+ switch (task_state) {
154
+ UHS_USB_DEBUG (IDLE);
155
+ UHS_USB_DEBUG (RESET_DEVICE);
156
+ UHS_USB_DEBUG (RESET_NOT_COMPLETE);
157
+ UHS_USB_DEBUG (DEBOUNCE);
158
+ UHS_USB_DEBUG (DEBOUNCE_NOT_COMPLETE);
159
+ UHS_USB_DEBUG (WAIT_SOF);
160
+ UHS_USB_DEBUG (ERROR);
161
+ UHS_USB_DEBUG (CONFIGURING);
162
+ UHS_USB_DEBUG (CONFIGURING_DONE);
163
+ UHS_USB_DEBUG (RUNNING);
164
+ default :
165
+ SERIAL_ECHOLNPAIR (" UHS_USB_HOST_STATE: " , task_state);
166
+ break ;
167
+ }
70
168
}
71
- else
72
- state = USB_HOST_INITIALIZED;
73
- SERIAL_EOL ();
74
- break ;
75
- case USB_HOST_INITIALIZED:
76
- const uint8_t lastUsbTaskState = usb.getUsbTaskState ();
77
- usb.Task ();
78
- const uint8_t newUsbTaskState = usb.getUsbTaskState ();
79
-
80
- if (lastUsbTaskState == USB_STATE_RUNNING && newUsbTaskState != USB_STATE_RUNNING) {
81
- // the user pulled the flash drive. Make sure the bulk storage driver releases the address
82
- #ifdef USB_DEBUG
83
- SERIAL_ECHOLNPGM (" USB drive removed" );
169
+ }
170
+ #endif
171
+
172
+ static millis_t next_state_ms = millis ();
173
+
174
+ #define GOTO_STATE_AFTER_DELAY (STATE, DELAY ) do { state = STATE; next_state_ms = millis () + DELAY; }while (0 )
175
+
176
+ if (ELAPSED (millis (), next_state_ms)) {
177
+ GOTO_STATE_AFTER_DELAY (state, 250 ); // Default delay
178
+
179
+ switch (state) {
180
+
181
+ case UNINITIALIZED:
182
+ #ifndef MANUAL_USB_STARTUP
183
+ GOTO_STATE_AFTER_DELAY ( DO_STARTUP, USB_STARTUP_DELAY );
84
184
#endif
85
- // bulk.Release();
86
- }
87
- if (lastUsbTaskState != USB_STATE_RUNNING && newUsbTaskState == USB_STATE_RUNNING) {
88
- #ifdef USB_DEBUG
89
- SERIAL_ECHOLNPGM (" USB drive inserted" );
185
+ break ;
186
+
187
+ case DO_STARTUP: usbStartup (); break ;
188
+
189
+ case WAIT_FOR_DEVICE:
190
+ if (task_state == UHS_STATE (RUNNING)) {
191
+ #if USB_DEBUG >= 1
192
+ SERIAL_ECHOLNPGM (" USB device inserted" );
193
+ #endif
194
+ GOTO_STATE_AFTER_DELAY ( WAIT_FOR_LUN, 250 );
195
+ }
196
+ break ;
197
+
198
+ case WAIT_FOR_LUN:
199
+ /* USB device is inserted, but if it is an SD card,
200
+ * adapter it may not have an SD card in it yet. */
201
+ if (bulk.LUNIsGood (0 )) {
202
+ #if USB_DEBUG >= 1
203
+ SERIAL_ECHOLNPGM (" LUN is good" );
204
+ #endif
205
+ GOTO_STATE_AFTER_DELAY ( MEDIA_READY, 100 );
206
+ }
207
+ else {
208
+ #ifdef USB_HOST_MANUAL_POLL
209
+ // Make sure we catch disconnect events
210
+ usb.busprobe ();
211
+ usb.VBUS_changed ();
212
+ #endif
213
+ #if USB_DEBUG >= 1
214
+ SERIAL_ECHOLNPGM (" Waiting for media" );
215
+ #endif
216
+ #if EITHER(ULTRA_LCD, EXTENSIBLE_UI)
217
+ LCD_MESSAGEPGM (" Waiting for media" );
218
+ #endif
219
+ GOTO_STATE_AFTER_DELAY (state, 2000 );
220
+ }
221
+ break ;
222
+
223
+ case MEDIA_READY: break ;
224
+ case MEDIA_ERROR: break ;
225
+ }
226
+
227
+ if (state > WAIT_FOR_DEVICE && task_state != UHS_STATE (RUNNING)) {
228
+ // Handle device removal events
229
+ #if USB_DEBUG >= 1
230
+ SERIAL_ECHOLNPGM (" USB device removed" );
231
+ #endif
232
+ #if EITHER(ULTRA_LCD, EXTENSIBLE_UI)
233
+ if (state != MEDIA_READY)
234
+ LCD_MESSAGEPGM (" USB device removed" );
235
+ #endif
236
+ GOTO_STATE_AFTER_DELAY ( WAIT_FOR_DEVICE, 0 );
237
+ }
238
+
239
+ else if (state > WAIT_FOR_LUN && !bulk.LUNIsGood (0 )) {
240
+ // Handle media removal events
241
+ #if USB_DEBUG >= 1
242
+ SERIAL_ECHOLNPGM (" Media removed" );
243
+ #endif
244
+ #if EITHER(ULTRA_LCD, EXTENSIBLE_UI)
245
+ LCD_MESSAGEPGM (" Media removed" );
246
+ #endif
247
+ GOTO_STATE_AFTER_DELAY ( WAIT_FOR_DEVICE, 0 );
248
+ }
249
+
250
+ else if (task_state == UHS_STATE (ERROR)) {
251
+ #if EITHER(ULTRA_LCD, EXTENSIBLE_UI)
252
+ LCD_MESSAGEPGM (" Media read error" );
90
253
#endif
91
- }
92
- break ;
254
+ GOTO_STATE_AFTER_DELAY ( MEDIA_ERROR, 0 );
255
+ }
93
256
}
94
257
}
95
258
96
259
// Marlin calls this function to check whether an USB drive is inserted.
97
260
// This is equivalent to polling the SD_DETECT when using SD cards.
98
261
bool Sd2Card::isInserted () {
99
- return usb. getUsbTaskState () == USB_STATE_RUNNING ;
262
+ return state == MEDIA_READY ;
100
263
}
101
264
102
- // Marlin calls this to initialize an SD card once it is inserted.
103
- bool Sd2Card::init ( const uint8_t sckRateID /* =0 */ , const pin_t chipSelectPin /* =SD_CHIP_SELECT_PIN */ ) {
104
- if (! ready ()) return false ;
265
+ bool Sd2Card::ready () {
266
+ return state > DO_STARTUP;
267
+ }
105
268
106
- if (!bulk.LUNIsGood (0 )) {
107
- SERIAL_ECHOLNPGM (" LUN zero is not good" );
108
- return false ;
109
- }
269
+ // Marlin calls this to initialize an SD card once it is inserted.
270
+ bool Sd2Card::init (const uint8_t , const pin_t ) {
271
+ if (!isInserted ()) return false ;
110
272
273
+ #if USB_DEBUG >= 1
111
274
const uint32_t sectorSize = bulk.GetSectorSize (0 );
112
275
if (sectorSize != 512 ) {
113
276
SERIAL_ECHOLNPAIR (" Expecting sector size of 512. Got: " , sectorSize);
114
277
return false ;
115
278
}
279
+ #endif
116
280
117
- #ifdef USB_DEBUG
281
+ #if USB_DEBUG >= 3
118
282
lun0_capacity = bulk.GetCapacity (0 );
119
283
SERIAL_ECHOLNPAIR (" LUN Capacity (in blocks): " , lun0_capacity);
120
284
#endif
@@ -123,36 +287,36 @@ bool Sd2Card::init(const uint8_t sckRateID/*=0*/, const pin_t chipSelectPin/*=SD
123
287
124
288
// Returns the capacity of the card in blocks.
125
289
uint32_t Sd2Card::cardSize () {
126
- if (!ready ()) return 0 ;
127
- #ifndef USB_DEBUG
290
+ if (!isInserted ()) return false ;
291
+ #if USB_DEBUG < 3
128
292
const uint32_t
129
293
#endif
130
294
lun0_capacity = bulk.GetCapacity (0 );
131
295
return lun0_capacity;
132
296
}
133
297
134
298
bool Sd2Card::readBlock (uint32_t block, uint8_t * dst) {
135
- if (!ready ()) return false ;
136
- #ifdef USB_DEBUG
299
+ if (!isInserted ()) return false ;
300
+ #if USB_DEBUG >= 3
137
301
if (block >= lun0_capacity) {
138
302
SERIAL_ECHOLNPAIR (" Attempt to read past end of LUN: " , block);
139
303
return false ;
140
304
}
141
- #if USB_DEBUG > 1
305
+ #if USB_DEBUG >= 4
142
306
SERIAL_ECHOLNPAIR (" Read block " , block);
143
307
#endif
144
308
#endif
145
309
return bulk.Read (0 , block, 512 , 1 , dst) == 0 ;
146
310
}
147
311
148
312
bool Sd2Card::writeBlock (uint32_t block, const uint8_t * src) {
149
- if (!ready ()) return false ;
150
- #ifdef USB_DEBUG
313
+ if (!isInserted ()) return false ;
314
+ #if USB_DEBUG >= 3
151
315
if (block >= lun0_capacity) {
152
316
SERIAL_ECHOLNPAIR (" Attempt to write past end of LUN: " , block);
153
317
return false ;
154
318
}
155
- #if USB_DEBUG > 1
319
+ #if USB_DEBUG >= 4
156
320
SERIAL_ECHOLNPAIR (" Write block " , block);
157
321
#endif
158
322
#endif
0 commit comments