USBHost_t36 USB Mass Storage Driver Experiments

I am setup for testing now. @mjs513 I am getting the same results as you. Everything seems to be working except un-plugging and replugging the flash drive. I can't remember, but has a powered hub been tried?

@wwatson - @yeahtuna -@KurtE
Now that I am awake I am able to do some more testing.

using the same sketch I tried two things to see where the issue might be.
1. I inserted/removed a USB drive directly into the USB socket on the Micromod board and it picked up the removal and replacement and reran the performTest() function, no issue
2. Then I inserted/removed a USB drive into the powered hub (NO MIDI TEENSY) attached and again it picked up the removal and replacement and reran the performTest() function, no issue
3. Now if I do the same thing with the Teensy 4.1 attached, it seems to hang the sketch when you remove and replace the USB Drive.

Now the interestin thing is in Case #3 above, if I hit one of the buttons on the T4.1(MIDI Sender) it continues with picking up the insertion of the drive but with freeze the TMM when it tries writing to the drive.

The solution in post #750 might be write but (1) don't know enough about USBHost to determine what the overall impact would be to other functions and (2) might just be curing the symptom instead of the root cause.
 
Sorry, been busy doing things like sleep ;)

Wondering if some of this in Midi is also a red herring, or symptoms of other problems...
Here are some random thoughts, on things to maybe look at, or try to see if we can isolate any issues.

Also wondering things like: you are using: MIDIDevice_BigBuffer midi1(myusb);
Do you need BigBuffer? or can you use: MIDIDevice? If you try that, does it have same issue?

Not queuing a data transfer on an RX pipe implies not receiving anything on that pipe. So unless there is some other place that queues one up...

Delaying for 10ms within an ISR is probably not a good thing to do. It will block everything except higher priority interrupts.

In most cases (maybe all), calls like queue_data_transfer and the like are called within the processing of the USB ISR, so you don't have the issue of having that ISR be triggered in the middle of the processing and be unprotected and the lists and the like corrupted.

However, wondering if maybe there are cases here where maybe it is not being called from the ISR but instead from: void USBHost::Task()
Note: this method simply iterates over the objects and calls their Task() method:
I don't believe MIDI does anything here, but we do have:
Code:
void USBDrive::Task()
This is where we try to find the code that finds that we have new drives and try to enumerate them, or ones that went away. In theory this should not be impacting the transfer lists...
But always famous last words... Could for example be condition where we are enumerating the drives partitions and the drive goes away...

So need to step back and experiment...
 
Now the interestin thing is in Case #3 above, if I hit one of the buttons on the T4.1(MIDI Sender) it continues with picking up the insertion of the drive but with freeze the TMM when it tries writing to the drive.

The solution in post #750 might be write but (1) don't know enough about USBHost to determine what the overall impact would be to other functions and (2) might just be curing the symptom instead of the root cause.

Thank-you again for taking the time to test. I've been making posts for months trying to get help resolving these issues, but few seem to really care. Much appreciated.

The 'solution' I mention in post #750 is not a real solution. I'm pretty sure removing those lines will prevent the teensy from seeing incoming MIDI. However, it hints at the underlying issue. There's something wrong with how the library is queuing up async transfers.
 
I switched over temporally to using a T3.6 attached to PC instead of the TMM.

In this case I can remove/replace the USB drive exactly once before it hangs. See next post for further info.
Code:
 === Task() Drive 0x1fff3ce0 connected ===
>> USBDrive::startFilesystems called 0x1fff3ce0
	>>Partition 1 VT:1 T:12 32 60062468
	>>USBFilesystem::claimPartition 0x1 called >>USBFilesystem::check_voltype_guid(1, 0x2002ff90)
+ Claimed

Try Partition list>>USBDrive::printPartionTable

Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,60062468
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
Starting Tests
Creating /testDir...SUCCESS
Writing to /testDir/file_0.txt
Writing to /testDir/file_1.txt
Writing to /testDir/file_2.txt
Writing to /testDir/file_3.txt
Writing to /testDir/file_4.txt
Writing to /testDir/file_5.txt
Writing to /testDir/file_6.txt
Writing to /testDir/file_7.txt
Writing to /testDir/file_8.txt
Removing /testDir...SUCCESS
Test completed in 220 miliseconds.
Remove and reinsert media to test again.
MIDI Device connected
Note On, ch=1, note=62, velocity=99
>>>>>>>> 1
Note Off, ch=1, note=62, velocity=0
>>>>>>>> 0
USBDrive::disconnect 0x1fff3ce0 0x1fff2884
	 0x1fff45e0 0x1fff2884
	 USBFilesystem::releasePartition 0x1fff2884 called

 === Task() Drive 0x1fff3ce0 connected ===
>> USBDrive::startFilesystems called 0x1fff3ce0
	>>Partition 1 VT:1 T:12 32 60062468
	>>USBFilesystem::claimPartition 0x1 called >>USBFilesystem::check_voltype_guid(1, 0x2002ff90)
+ Claimed

Try Partition list>>USBDrive::printPartionTable

Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,60062468
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
Starting Tests
Creating /testDir...SUCCESS
Writing to /testDir/file_0.txt
Writing to /testDir/file_1.txt
Writing to /testDir/file_2.txt
Writing to /testDir/file_3.txt
Writing to /testDir/file_4.txt
Writing to /testDir/file_5.txt
Writing to /testDir/file_6.txt
Writing to /testDir/file_7.txt
Writing to /testDir/file_8.txt
Removing /testDir...SUCCESS
Test completed in 196 miliseconds.
Remove and reinsert media to test again.
Note On, ch=1, note=62, velocity=99
>>>>>>>> 1
Note Off, ch=1, note=62, velocity=0
>>>>>>>> 0
Note On, ch=1, note=61, velocity=99
>>>>>>>> 1
Note Off, ch=1, note=61, velocity=0
>>>>>>>> 0
USBDrive::disconnect 0x1fff3ce0 0x1fff2884
	 0x1fff45e0 0x1fff2884
	 USBFilesystem::releasePartition 0x1fff2884 called
 
Part2.
After the second remove/replace you see that it seems to hang, after the removal but the LED is still blinking, So i hit a button on the T4 a few times and:
Code:
USBDrive::disconnect 0x1fff3ce0 0x1fff2884
	 0x1fff45e0 0x1fff2884
	 USBFilesystem::releasePartition 0x1fff2884 called
[COLOR="#FF0000"]Note On, ch=1, note=62, velocity=99
[/COLOR]>>>>>>>> 1

 === Task() Drive 0x1fff3ce0 connected ===
>> USBDrive::startFilesystems called 0x1fff3ce0
	>>Partition 1 VT:1 T:12 32 60062468
	>>USBFilesystem::claimPartition 0x1 called >>USBFilesystem::check_voltype_guid(1, 0x2002ff90)
+ Claimed

Try Partition list>>USBDrive::printPartionTable

Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,60062468
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
[COLOR="#FF0000"]Note Off, ch=1, note=62, velocity=0
[/COLOR]>>>>>>>> 0
Starting Tests
Creating /testDir...

Notice that as it is recieving input from the T4 it continues to recognize the drive - unfortunately it hangs at Creating/testDir....
 
Also wondering things like: you are using: MIDIDevice_BigBuffer midi1(myusb);
Do you need BigBuffer? or can you use: MIDIDevice? If you try that, does it have same issue?
I do need BigBuffer. A tested using several months ago using MIDIDevice, and was the same problem with the hub. I actually came up with a workaround get the hub working again, but not a proper fix.

Delaying for 10ms within an ISR is probably not a good thing to do. It will block everything except higher priority interrupts.
Of course it's a bad thing to do, but it's a hint.
However, wondering if maybe there are cases here where maybe it is not being called from the ISR but instead from: void USBHost::Task()
With the recent changes to the MassStorageDrive, I'm pretty sure all calls to queue transfers are coming from user code or Task().
 
@yeahtuna
Yeah - i agree its a hint but as @KurtE said more debugging is needed.

Also forgot to mention, the issue in post #755 happens with the TMM as the primary device.

also, on the T3.6 if BigBuffer is replaced by just Mididevice, the T3.6 doesn't see the T4.1 inputs.
 
I'm about to go to bed, but I also noticed that the MassStorageDriver is currently not checking for stalled transfers, instead treating them as complete. If a transfer is stalled, don't we need to retransfer?
 
Just for the record here is a picture of my TMM/T4.1 setup
midiUSBdrive_setup.jpg
 
Is the solution to the problem to ensure that all transfers are queued in the isr()?
Maybe not... But maybe some/all queue_data_transfer calls need to be protected.

For example maybe add optional parameter to queue...
like:
Code:
    static bool queue_Data_Transfer_Debug(Pipe_t *pipe, void *buffer,
                                    uint32_t len, USBDriver *driver,
                                    uint32_t line, bool disable_interrupt = true);
And have it default to disable the USB ISR during critical points. If that helps, then we can back through the ones that we know are from ISR, and pass false...

I'm about to go to bed, but I also noticed that the MassStorageDriver is currently not checking for stalled transfers, instead treating them as complete. If a transfer is stalled, don't we need to retransfer?
As for stalls, not sure if there is any support in there yet. I believe one of the last @wwatson changes was to avoid a startup stall...
 
There's a definite bug here: https://github.com/PaulStoffregen/USBHost_t36/blob/master/MassStorageDriver.cpp#L125

The IN endpoint number is being passed to new_Pipe() with the direction flag (0x80) intact when it should be masked off. When the endpoint number is used to initialize the queue head for the pipe, the Head of Reclamation List flag ends up mistakenly set. This could possibly be causing significantly slower speeds than necessary for bulk transfers.
 
Last edited:
There's a definite bug here: https://github.com/PaulStoffregen/USBHost_t36/blob/master/MassStorageDriver.cpp#L125

The IN endpoint number is being passed to new_Pipe() with the direction flag (0x80) intact when it should be masked off. When the endpoint number is used to initialize the queue head for the pipe, the Head of Reclamation List flag ends up mistakenly set.

Good catch. Have you changed it to see if it makes any differences?
Can you issue a PR back to @PaulStoffregen and maybe get it into the up coming release? Not sure if he would pull it in or not or if he maybe is already in the process of generating the release.
 
@PaulStoffregen - @KurtE - @jmarsh -@yeahtuna

Looks like that fix resolved the issue with removing and replacing the USB Drive while Midi is attached. Did it a few times including hitting the buttons and seems to got it.

Note my version also includes PR Fix certain USB flash drive usage failures. #114

Code:
 === Task() Drive 0x20005160 connected ===
>> USBDrive::startFilesystems called 0x20005160
	>>Partition 1 VT:1 T:12 32 60062468
	>>USBFilesystem::claimPartition 0x1 called >>USBFilesystem::check_voltype_guid(1, 0x20067fa0)
+ Claimed

Try Partition list>>USBDrive::printPartionTable

Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,60062468
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
Starting Tests
Creating /testDir...SUCCESS
Writing to /testDir/file_0.txt
Writing to /testDir/file_1.txt
Writing to /testDir/file_2.txt
Writing to /testDir/file_3.txt
Writing to /testDir/file_4.txt
Writing to /testDir/file_5.txt
Writing to /testDir/file_6.txt
Writing to /testDir/file_7.txt
Writing to /testDir/file_8.txt
Removing /testDir...SUCCESS
Test completed in 193 miliseconds.
Remove and reinsert media to test again.
MIDI Device connected
USBDrive::disconnect 0x20005160 0x20003a84
	 0x2000695c 0x20003a84
	 USBFilesystem::releasePartition 0x20003a84 called

 === Task() Drive 0x20005160 connected ===
>> USBDrive::startFilesystems called 0x20005160
	>>Partition 1 VT:1 T:12 32 60062468
	>>USBFilesystem::claimPartition 0x1 called >>USBFilesystem::check_voltype_guid(1, 0x20067fa0)
+ Claimed

Try Partition list>>USBDrive::printPartionTable

Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,60062468
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
Starting Tests
Creating /testDir...SUCCESS
Writing to /testDir/file_0.txt
Writing to /testDir/file_1.txt
Writing to /testDir/file_2.txt
Writing to /testDir/file_3.txt
Writing to /testDir/file_4.txt
Writing to /testDir/file_5.txt
Writing to /testDir/file_6.txt
Writing to /testDir/file_7.txt
Writing to /testDir/file_8.txt
Removing /testDir...SUCCESS
Test completed in 195 miliseconds.
Remove and reinsert media to test again.
USBDrive::disconnect 0x20005160 0x20003a84
	 0x2000695c 0x20003a84
	 USBFilesystem::releasePartition 0x20003a84 called

 === Task() Drive 0x20005160 connected ===
>> USBDrive::startFilesystems called 0x20005160
	>>Partition 1 VT:1 T:12 32 60062468
	>>USBFilesystem::claimPartition 0x1 called >>USBFilesystem::check_voltype_guid(1, 0x20067fa0)
+ Claimed

Try Partition list>>USBDrive::printPartionTable

Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,60062468
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
Starting Tests
Creating /testDir...SUCCESS
Writing to /testDir/file_0.txt
Writing to /testDir/file_1.txt
Writing to /testDir/file_2.txt
Writing to /testDir/file_3.txt
Writing to /testDir/file_4.txt
Writing to /testDir/file_5.txt
Writing to /testDir/file_6.txt
Writing to /testDir/file_7.txt
Writing to /testDir/file_8.txt
Removing /testDir...SUCCESS
Test completed in 196 miliseconds.
Remove and reinsert media to test again.
USBDrive::disconnect 0x20005160 0x20003a84
	 0x2000695c 0x20003a84
	 USBFilesystem::releasePartition 0x20003a84 called

 === Task() Drive 0x20005160 connected ===
>> USBDrive::startFilesystems called 0x20005160
	>>Partition 1 VT:1 T:12 32 60062468
	>>USBFilesystem::claimPartition 0x1 called >>USBFilesystem::check_voltype_guid(1, 0x20067fa0)
+ Claimed

Try Partition list>>USBDrive::printPartionTable

Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,60062468
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
Starting Tests
Creating /testDir...SUCCESS
Writing to /testDir/file_0.txt
Writing to /testDir/file_1.txt
Writing to /testDir/file_2.txt
Writing to /testDir/file_3.txt
Writing to /testDir/file_4.txt
Writing to /testDir/file_5.txt
Writing to /testDir/file_6.txt
Writing to /testDir/file_7.txt
Writing to /testDir/file_8.txt
Removing /testDir...SUCCESS
Test completed in 196 miliseconds.
Remove and reinsert media to test again.
Note On, ch=1, note=62, velocity=99
>>>>>>>> 1
Note Off, ch=1, note=62, velocity=0
>>>>>>>> 0
Note On, ch=1, note=62, velocity=99
>>>>>>>> 1
Note Off, ch=1, note=62, velocity=0
>>>>>>>> 0
Note On, ch=1, note=62, velocity=99
>>>>>>>> 1
Note Off, ch=1, note=62, velocity=0
>>>>>>>> 0
Note On, ch=1, note=62, velocity=99
>>>>>>>> 1
Note Off, ch=1, note=62, velocity=0
>>>>>>>> 0
USBDrive::disconnect 0x20005160 0x20003a84
	 0x2000695c 0x20003a84
	 USBFilesystem::releasePartition 0x20003a84 called

 === Task() Drive 0x20005160 connected ===
>> USBDrive::startFilesystems called 0x20005160
	>>Partition 1 VT:1 T:12 32 60062468
	>>USBFilesystem::claimPartition 0x1 called >>USBFilesystem::check_voltype_guid(1, 0x20067fa0)
+ Claimed

Try Partition list>>USBDrive::printPartionTable

Partition Table
	part,boot,bgnCHS[3],type,endCHS[3],start,length
FAT32:	1,0,0x0,0x21,0x0,0xC,0xFE,0xFF,0xFF,32,60062468
pt_#0:	2,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	3,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
pt_#0:	4,0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0,0
Starting Tests
Creating /testDir...SUCCESS
Writing to /testDir/file_0.txt
Writing to /testDir/file_1.txt
Writing to /testDir/file_2.txt
Writing to /testDir/file_3.txt
Writing to /testDir/file_4.txt
Writing to /testDir/file_5.txt
Writing to /testDir/file_6.txt
Writing to /testDir/file_7.txt
Writing to /testDir/file_8.txt
Removing /testDir...SUCCESS
Test completed in 197 miliseconds.
Remove and reinsert media to test again.
 
What about.movimg.the calls to msGetCSW() to the input or output callbacks. Wouldn't that be safer?

Again it is sort of on a case by case basis. For example already within: the USB Serial code. I know that: the ::write method, may queue a data transfer.
But it already protects itself, by disabling the USB interrupt during this. It also updates some other states as well.
 
Note: I just pushed up a new fork/branch: https://github.com/KurtE/USBHost_t36/tree/queue_transfer_protected
Where I updated:
Code:
bool USBHost::queue_Data_Transfer(Pipe_t *pipe, void *buffer, uint32_t len, USBDriver *driver)
{
	Transfer_t *transfer, *data, *next;
	uint8_t *p = (uint8_t *)buffer;
	uint32_t count;
	bool last = false;
	
	// We always want to do this while the interrupt is disabled. 
	// But only re-enable if it was enabled coming in. 
	[COLOR="#FF0000"]bool irq_was_enabled = NVIC_IS_ENABLED(IRQ_USBHS);
	NVIC_DISABLE_IRQ(IRQ_USBHS);[/COLOR]

	// TODO: option for zero length packet?  Maybe in Pipe_t fields?

	//println("new_Data_Transfer");
	// allocate qTDs
	transfer = allocate_Transfer();
	if (!transfer) {
	[COLOR="#FF0000"]	if (irq_was_enabled) NVIC_ENABLE_IRQ(IRQ_USBHS);[/COLOR]
		return false;
	}
	data = transfer;
	for (count=((len-1) >> 14); count; count--) {
		next = allocate_Transfer();
		if (!next) {
			// free already-allocated qTDs
			while (1) {
				next = (Transfer_t *)transfer->qtd.next;
				free_Transfer(transfer);
				if (transfer == data) break;
				transfer = next;
			}
			[COLOR="#FF0000"]if (irq_was_enabled) NVIC_ENABLE_IRQ(IRQ_USBHS);
            return false;[/COLOR]
        }
		data->qtd.next = (uint32_t)next;
		data = next;
	}
	// last qTD needs info for followup
	data->qtd.next = 1;
	data->pipe = pipe;
	data->buffer = buffer;
	data->length = len;
	data->setup.word1 = 0;
	data->setup.word2 = 0;
	data->driver = driver;
	// initialize all qTDs
	data = transfer;
	while (1) {
		uint32_t count = len;
		if (count > 16384) {
			count = 16384;
		} else {
			last = true;
		}
		init_qTD(data, p, count, pipe->direction, 0, last);
		if (last) break;
		p += count;
		len -= count;
		data = (Transfer_t *)(data->qtd.next);
	}
	bool return_value = queue_Transfer(pipe, transfer);
	[COLOR="#FF0000"]if (irq_was_enabled) NVIC_ENABLE_IRQ(IRQ_USBHS);
	return return_value;[/COLOR]
}
The idea is that this code will always run with the IRQ_USBHS disabled. But it only should re-enable the IRQ if the IRQ was enabled when this method
was called.

If anyone gets a chance to try it out, it would be great. Obviously too late for B4, but,,,
 
@KurtE

Tried your changes with the MIDI test sketches and didn't notice any issues crop up. So thats good.

Then I ran my mtp-test-integrityV2 test sketch and ran 2 writes:
Code:
Start Big write of 2048000 Bytes.........................
Big write /0_2MBfile.txt took  1.13 Sec for 2048000 Bytes : file3.size()=2048000
	Big write KBytes per second 1809.06 

Bytes Used: 23037280256, Bytes Total:30736957440

Start Big write of 25124864 Bytes............................................................
Big write /0_bigfile.txt took 13.90 Sec for 25124864 Bytes : file3.size()=25122816
	Big write KBytes per second 1807.02 

Bytes Used: 23062413312, Bytes Total:30736957440
 
There's a definite bug here: https://github.com/PaulStoffregen/USBHost_t36/blob/master/MassStorageDriver.cpp#L125

The IN endpoint number is being passed to new_Pipe() with the direction flag (0x80) intact when it should be masked off. When the endpoint number is used to initialize the queue head for the pipe, the Head of Reclamation List flag ends up mistakenly set. This could possibly be causing significantly slower speeds than necessary for bulk transfers.

Thank-you so much. This fixes the issue for me. I can't tell you how many hours I have spent pouring over the UBSHost code desperately trying to fix this issue.
 
Thanks @mjs513 I have also run a few more tests. Will try some more. So far not noticing anything.
 
Note: I just pushed up a new fork/branch: https://github.com/KurtE/USBHost_t36/tree/queue_transfer_protected
Where I updated:
Code:
bool USBHost::queue_Data_Transfer(Pipe_t *pipe, void *buffer, uint32_t len, USBDriver *driver)
{
	Transfer_t *transfer, *data, *next;
	uint8_t *p = (uint8_t *)buffer;
	uint32_t count;
	bool last = false;
	
	// We always want to do this while the interrupt is disabled. 
	// But only re-enable if it was enabled coming in. 
	[COLOR="#FF0000"]bool irq_was_enabled = NVIC_IS_ENABLED(IRQ_USBHS);
	NVIC_DISABLE_IRQ(IRQ_USBHS);[/COLOR]

	// TODO: option for zero length packet?  Maybe in Pipe_t fields?

	//println("new_Data_Transfer");
	// allocate qTDs
	transfer = allocate_Transfer();
	if (!transfer) {
	[COLOR="#FF0000"]	if (irq_was_enabled) NVIC_ENABLE_IRQ(IRQ_USBHS);[/COLOR]
		return false;
	}
	data = transfer;
	for (count=((len-1) >> 14); count; count--) {
		next = allocate_Transfer();
		if (!next) {
			// free already-allocated qTDs
			while (1) {
				next = (Transfer_t *)transfer->qtd.next;
				free_Transfer(transfer);
				if (transfer == data) break;
				transfer = next;
			}
			[COLOR="#FF0000"]if (irq_was_enabled) NVIC_ENABLE_IRQ(IRQ_USBHS);
            return false;[/COLOR]
        }
		data->qtd.next = (uint32_t)next;
		data = next;
	}
	// last qTD needs info for followup
	data->qtd.next = 1;
	data->pipe = pipe;
	data->buffer = buffer;
	data->length = len;
	data->setup.word1 = 0;
	data->setup.word2 = 0;
	data->driver = driver;
	// initialize all qTDs
	data = transfer;
	while (1) {
		uint32_t count = len;
		if (count > 16384) {
			count = 16384;
		} else {
			last = true;
		}
		init_qTD(data, p, count, pipe->direction, 0, last);
		if (last) break;
		p += count;
		len -= count;
		data = (Transfer_t *)(data->qtd.next);
	}
	bool return_value = queue_Transfer(pipe, transfer);
	[COLOR="#FF0000"]if (irq_was_enabled) NVIC_ENABLE_IRQ(IRQ_USBHS);
	return return_value;[/COLOR]
}
The idea is that this code will always run with the IRQ_USBHS disabled. But it only should re-enable the IRQ if the IRQ was enabled when this method
was called.

If anyone gets a chance to try it out, it would be great. Obviously too late for B4, but,,,

I'll try it out today, but I feel like it's using duct tape to fix a problem. Obviously commands need to begin in user code, but subsequent calls to queue_Data_Transfer should probably be done inside the callbacks so that they are initiated in the isr().

With the fix to pipeIn, my non-blocking USBDrive initialization is finally working. I must confess, however, that the pipeIn fix has made initialization about 500% faster, so the non-blocking initialization is not so important.

@wwatson
Are your drives initializing any faster, too?
 
@yeahtuna - I just got home from work, I might be called back in tonight:( I am really glad this has solved your issues:) I will try it out tonight if I can. I also have some retirement things to take care of first. Will be glad when I finally retire and have more time to help...

Edit: And learn:)
 
Last edited:
@yeahtuna - I just got home from work, I might be called back in tonight:( I am really glad this has solved your issues:) I will try it out tonight if I can. I also have some retirement things to take care of first. Will be glad when I finally retire and have more time to help...

Edit: And learn:)

Thought I saw something where you mentioned that but couldn't find it again. Congratulations. Been retired now for about 7 years. Missed it at first but that went away fairly quickly :)
 
Back
Top