Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC configuration #9

Open
VaZso opened this issue Jan 28, 2019 · 7 comments
Open

MSC configuration #9

VaZso opened this issue Jan 28, 2019 · 7 comments
Labels
question Further information is requested

Comments

@VaZso
Copy link

VaZso commented Jan 28, 2019

Hello,

Could you please help me how to configure an MSC device properly?

I hope you may have something which may be used as example configuration showing basic requirements of device setup.
I think I miss some configuration to define or doing it completely wrong as my MCU generates HardFault.

So, if you may have something which can be used for proper device initialization, I would be happy.

Thank you your help in advance.

@benedekkupper benedekkupper added the question Further information is requested label Jan 28, 2019
@benedekkupper
Copy link
Member

benedekkupper commented Jan 29, 2019

As long as all the pointers are set correctly in your application, there shouldn't be any HardFaults caused by the library. In this case please post it as a ticket with relevant stack trace and a way to reproduce.

According to the documentation of USBD_MSC_MountInterface() "The interface reference shall have its USBD_MSC_IfHandleType::Config structure and USBD_MSC_IfHandleType::LUs reference properly set before this function is called".

The USBD_MSC_LUType - where LU stands for Logical Unit, a single piece of block storage - defines the mass storage API, with calls identical to other block file systems, e.g. FatFS. Its Status field should point to a struct that has up-to-date information about the block storage's state. The Inquiry field isn't that obvious, so here's an example:

const USBD_SCSI_StdInquiryType inquiry = {
    .PeriphType = SCSI_PERIPH_SBC_2,
    .RMB = 1,
    .Version = 2,
    .RespDataFormat = 2,
    .AddLength = sizeof(USBD_SCSI_StdInquiryType) - 4,
    .VendorId = "IC",
    .ProductId = "Mass Storage",
    .VersionId = "1.00"
};

Keep in mind that the string lengths are fixed in this struct.

@VaZso
Copy link
Author

VaZso commented Jan 30, 2019

Sorry for disturbed you, I have just thought you may have a working configuration which may be used as an example.
I have also thought my configuration may contain faults.

Anyway, my basic configuration was good including setting of inquiry, however, I have replaced inquiry with your code later because I still don't know if the change of ID strings may cause problems for example under Windows.

The hardfault happened when host tried to enumerate the device.

The last step before HardFault was the second call of this cycle of init in usbd_msc.c:
for (lun = 0; lun <= itf->Config.MaxLUN; lun++) { USBD_SAFE_CALLBACK(MSC_GetLU(itf, lun)->Init, lun); }

The cause was in the configuration of my MSC interface itself by setting Config.MaxLUN to 1 which should has been 0 in my case.

Here is a skeleton for anyone who wants a starting point of MSC device setup (you may put in the project in this or modified form):
msc_if.zip

Correctly adding another LU also works under Linux (not tested further).

I have an SPI flash on my board in the size of 64 Mbit.
I have used the code above and completed Init_dev, Read_dev and Write_dev functions to access my flash and it worked perfectly well - I could put on a filesystem and ran a test using F3 (H2tesw-like software).

Currently, I have two VCPs and one MSC on the same board which all work perfectly and simultaneously.

They also work under Windows 10, but Windows 7 and Windows XP drivers don't really seem to like my two VCP interfaces anyway. However, they work if I only have one VCP interface attached.
Mass Storage works out of the box under Linux and all Windows I have tried so far.

Thank you your reply and sorry for disturbed you.

@benedekkupper
Copy link
Member

Since the MSC LU implementations heavily depend on the medium type it wouldn't have made much sense to send a solution most of which you will have to rewrite anyway.

I have quickly checked your msc_if skeleton, I have one comment to add: do not initialize the interface structure this way:

USBD_MSC_IfHandleType hmsc_if = {
	.Base.AltCount = 1,
        .LUs=msc_lu,
        /* all other fields are implicitly set to zero, initial value stored in flash */
}, *const msc_if = &hmsc_if;

As this implicitly defines all other fields of the struct (which includes a 512 bytes buffer) as zeroes, and stores the entire initial value in flash, therefore wasting more than half kB of program memory. A better solution is to define the variable without an initial value and set all necessary fields of the interface structure during startup, before calling the USBD_MSC_MountInterface() method.

@VaZso
Copy link
Author

VaZso commented Jan 31, 2019

You are correct, thank you.
The buffer costs relatively much space in flash by initializing that way.
I have corrected it. :)

Anyway, I think providing similar code as example may be useful as starting point even if the code is not complete as at least device-specific handlers are missing.

@MarcoPio
Copy link

I am trying to get a MSC + CDC composite that must work against MS Windows. Currently the device is enumerated and some descriptors are read (I have an USB analyzer) the VCP is detected I see on bus just after set configuration some line coding commands. However the MSC is not started (usually a "get max LUN" I saw on other devices..,)
I used the msc_if from VaZso (Thank you) and my UsbDevice_Init looks like:

`/* Initialize the device */
USBD_Init(UsbDevice, dev_cfg);

/* All fields of Config have to be properly set up */
msc_if->Config.InEpNum = 0x81;
msc_if->Config.OutEpNum = 0x01;
msc_if->Config.MaxLUN = 0;

/* Mount the interfaces to the device */
USBD_MSC_MountInterface(msc_if, UsbDevice);

console_if->Config.InEpNum  = 0x82;
console_if->Config.OutEpNum = 0x02;
console_if->Config.NotEpNum = 0x83;

/* Mount the interfaces to the device */
USBD_CDC_MountInterface(console_if, UsbDevice);

`
shortly on the bus i have :
get device descriptor with device class = defined in interface (0)
then
get config descriptor where
3 interfaces
itf 0 = class mass storage (2 ep)
itf 1 = class cdc and control (1 ep)
itf 2 = class cdc data (2 ep)

So can you give some suggestion or working example?

@benedekkupper
Copy link
Member

I don't have a public project with MSC, but others have successfully integrated it, e.g. https://github.com/Smoothieware/SmoothieV2/blob/master/Firmware/Hal/usb/msc_if.c
Make sure that msc_if->Base.AltCount = 1 and msc_if->LUs are also properly set.

@MarcoPio
Copy link

I have msc_if->Base.AltCount = 1 and msc_if->LUs properly setted.
I saw the Smoothie project and they have VCP+DFU or MSC stand alone.
I used their hdev_cfg values and this was sufficient to making appear MSC along VCP on Windows.
What I understood is that if VID and PID are 0x483 , 0x5740 from ST then the composite device is not recognized by Windows.
Changing VID to a different number worked for me.
Do you have any suggestion for VID and PID values to use as general rule ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants