usbx icon indicating copy to clipboard operation
usbx copied to clipboard

Device storage hot-plugging issue and files not updating in realtime.

Open maxkunes opened this issue 4 years ago • 4 comments

Hi!

I have a few issues with USBX's device storage class that I need some help resolving.

First and most importantly: If I connect my MCU board to my computer via USB to access the device storage filesystem I have set up through filex + usbx everything works fine. However, If I try to unplug the USB and plug it back in, sometimes the device fails to attach to windows properly. The windows error code is code 10 (this device cannot start). I haven't experimented enough to say anymore, but it seems It definitely breaks by around the 4th hotplug. Is there anything specifically I should be doing to support hotplugging the device storage class?

Secondly: Even if I flush my filesystem through filex, I can never see real-time changes in files that the MCU is writing to. (even if I also close those files and flush in between writes). However, rebooting my board or replugging in the USB will make the files update. I would be perfectly fine with the last solution, however, the first problem regarding hotplugging is making that solution pretty unusable.

And a third bonus question: On the custom board I'm working on, we only have one USB port that can act as a OTG device. In this case, we are using that port to access the board's filesystem from a PC using USBX. However, we have been thinking it would be nice to also be able to access serial output through CDC over that USB. But, as far as I can tell, there isn't a way to do that. Is there any way to effectively hub CDC and device storage over the one OTG port?

Extra info:

I'm giving USBX around 128k of uncached memory which I think should be plenty. I'm implementing media status and media flush but they are just returning UX_SUCCESS. Is this a problem? The board I'm working on is a derivative of the 1064 EVK board from NXP.

The rest of my USBX init code I'll paste below.

		UINT status =
			_ux_device_stack_initialize(usbfs_device_framework_high_speed, sizeof(usbfs_device_framework_high_speed), usbfs_device_framework_full_speed, sizeof(usbfs_device_framework_full_speed),
										usbfs_string_framework, sizeof(usbfs_string_framework), usbfs_language_id_framework, sizeof(usbfs_language_id_framework), nullptr);

		if (status != UX_SUCCESS)
			return false;

		/* Store the number of LUN in this device storage instance. */
		usbfs_storage_parameter.ux_slave_class_storage_parameter_number_lun = 1;

		/* Initialize the storage class parameters for reading/writing to the Flash
		 * Disk. */
		usbfs_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_last_lba = USBFS_LAST_BLOCK_INDEX;
		usbfs_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_block_length = USBFS_BLOCK_SIZE; // needs to be 512, not sure if this needs to match
																																	  // filessytem
		usbfs_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_type = 0;
		usbfs_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_removable_flag = 0x80;
		usbfs_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read = usbfs_media_read;
		usbfs_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write = usbfs_media_write;
		usbfs_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status = usbfs_media_status;
		usbfs_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_flush = usbfs_media_flush;

		/* Initilize the device storage class. The class is connected with interface
		 * 0 on configuration 1. */
		status = _ux_device_stack_class_register(_ux_system_slave_class_storage_name, _ux_device_class_storage_entry, 1, 0, (VOID *)&usbfs_storage_parameter);

		if (status != UX_SUCCESS)
			return false;

		_ux_dcd_mcimx6_initialize(usb_device_base());

		/* Init the USB interrupt. */
		usb_device_interrupt_setup(USB_DEVICE_INTERRUPT_PRIORITY);

maxkunes avatar Apr 23 '21 21:04 maxkunes

The strange thing about the first problem is that hotplugging seems to work fine in the example NXP device storage with USBX. However, I don't see any meaningful changes between the example and my code.

One thing is that I'm attaching USBX to the filesystem I use on the board. Essentially letting the USB port "view" the device's internal filesystem. Could this cause issues? NXP's example is just a ramdisk that only USB uses.

maxkunes avatar Apr 26 '21 19:04 maxkunes

Thanks for the feedback. Please check answers below:

About first problem: What's the hardware base for your code? When windows failed to start your disk where the code stops? If you have usb analyzer you can check if the storage failed on commands or sector data is corrupted to help on figure out the root cause. Since you are accessing your internal filesystem the driver for internal filesystem access may cause issue.

About second question: USB storage is not designed for a way to manage storage that can be easily sync with file system, since USB storage access disk sector by sector instead of by files. Recommended way to work with filex is : close volume before connect storage to host, re-mount volume after USB storage disconnected. The connection and disconnection can be seen in storage instance activate and deactivate callbacks.

About third question: I guess you need a storage and a CDC serial port when your board is connected to host PC (but not connecting USB serial bridge to your board). You can setup a composite device for that, e.g., modify device framework descriptor to add CDC interface descriptors (interface 1,2) after storage interface descriptor (interface 0), register CDC class driver for the added interfaces (register for interface 1). In this way after enumeration there will be storage disk and new COM port available on PC side.

xiaocq2001 avatar Jun 07 '21 06:06 xiaocq2001

@maxkunes Any feedback?

yuxin-azrtos avatar Oct 11 '21 06:10 yuxin-azrtos

@maxkunes Any feedback?

Sorry for the late response.

I'm still not sure about the hotplugging issue and I haven't got around to testing if this still is an issue as my codebase has progressed. It is not really a use-case I care much about, but noticed it at some point.

I really wish FileX could somehow play better with the device storage class. But I understand filesystem accessed is being done sector by sector with device storage. Is there any other USB class that accesses the filesystem on a higher level?

I've also noticed that USBX device storage + LevelX does not work great. This is because LevelX never gets a sector release from USB (for obvious reasons). So at some point, we start to see speed decreases due to many mapped sectors, even if the file was deleted via USB.

Regarding the 3rd question, thanks for the explanation about the composite device.

maxkunes avatar Jan 10 '22 01:01 maxkunes