USB MSD class with external FLASH

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

USB MSD class with external FLASH

Jump to solution
5,271 Views
brentwilliams
Contributor II

Hello, I am using a K20 on a custom board with an external FLASH.  I would like to have this external FLASH be a MSD. 

I have gotten the RAM DISK example working.  I have also separately gotten MFS working with the external FLASH.

From other threads it appears you cannot use a MSD directly with MFS.  Is this correct?

Has anyone found a work around or a solution for having a external FLASH act as a MSD?

Thanks,

Brent

0 Kudos
1 Solution
3,113 Views
Martin_
NXP Employee
NXP Employee

Yes, that is right. In response to a USB attach event, perhaps you can uninstall MFS, so the PC gains full control of the data storage. Then in response to a USB detach, MFS can be installed back.

-Martin

View solution in original post

0 Kudos
28 Replies
2,562 Views
Martin_
NXP Employee
NXP Employee

if you implement an MSD device, you won't need the file system. File system is controlled completely by the host in this case. As shown in the \usb\device\examples\msd\ , all you would need is to fseek to the requested location and write/read the data "from host to data storage"/"from data storage to host".

What you might do is to map MQX flashx driver to your external Flash. Then you would be able to use flashx device for fseek(), fwrite() and fread() calls. In response to USB_MSC_DEVICE_READ_REQUEST, it would fseek() to required location in flashx and read the required amount of data (as replacement of USB_mem_copy). In response to USB_MSC_DEVICE_WRITE_REQUEST, it would fseek() to required location and write the required amount of data to flashx, an so forth.

mqx\source\io\flashx has examples for various external flash memories.

0 Kudos
2,562 Views
brentwilliams
Contributor II

Thanks for your response Martin.  I am in process of overlaying the flashx driver with my low-level driver and trying it out.

One follow up question.  As you stated, the HOST (in this case the PC) is controlling the file system.  Once I disconnect from the HOST (the PC), I take it I would need to then install MFS to have access to the file system (i.e. I need something "controlling" the file system once I am no longer connected to a PC)?

Thanks again,

Brent

0 Kudos
3,114 Views
Martin_
NXP Employee
NXP Employee

Yes, that is right. In response to a USB attach event, perhaps you can uninstall MFS, so the PC gains full control of the data storage. Then in response to a USB detach, MFS can be installed back.

-Martin

0 Kudos
2,562 Views
brentwilliams
Contributor II

thanks Martin

0 Kudos
2,562 Views
brentwilliams
Contributor II

Hi Martin,

I am running into a road block with the USB MSD utilizing the flashX driver per your suggestion.

Below is from the MQX USB Device User’s Manual:

To use MSD class layer API functions from the application:

  1. Call USB_Class_MSC_Init() to initialize the class driver, all the layers below it, and the device
  2. Event callback functions are also passed as a parameter to this function.
  3. When the callback function is called with the USB_APP_ENUM_COMPLETE event, the

application should move into the ready state.

  1. Callback function is called with the USB_MSC_DEVICE_READ_REQUEST event to copy data

from the storage device before sending it to the USB bus. It reads data from the mass storage device

to the driver buffer.

  1. Callback function is called with the USB_MSC_DEVICE_WRITE_REQUEST event to copy data

from the USB driver buffer to the Storage device. It reads data from the driver buffer to the mass

storage device.

Specifically my issue is that the callback is called from an interrupt handler routine that for the RAM Disk simply (for a read) copies from RAM to the buffer passed into the callback.  In my case, the flashX driver is calling the MQX SPI driver which utilizes semaphores.  MQX (with good reason) will not allow you to potentially block on a semaphore in an interrupt handler.  The end result is I cannot use the flashX driver from the callback and utilize the fseek(), fwrite(), fread() functions.

My next thought was when the callback is issued to simply have it signal a Task which will perform the fseek(),fwrite(), fread(). This gets around the first problem, but I encounter another.  Specifically it takes too much time to go through the flashX layer, custom SPI layer, MQX SPI layer before the next callback occurs.

Looking at the low-level MQX USB driver code for MSD (usb_msc.c).  I see the following in an interrupt handler:

             msc_obj_ptr->param_callback.callback(USB_MSC_DEVICE_READ_REQUEST, (void*)&lba_data, msc_obj_ptr->param_callback.arg);

error = USB_MSC_Bulk_Send_Data(msc_obj_ptr->msc_handle,lba_data.buff_ptr,lba_data.size);

The first is where the callback occurs.  The second is where the data, copied into the buffer in the callback, is sent back to the HOST.

All this occurring via the interrupt and callback which does not leave much overhead to get the data in the callback buffer.

I have been going through the documentation trying to understand how to work around this.

Has anyone else had similar issues (have not been able to get up onto the message boards due to maintenance)?

Any thoughts?

Thanks,

Brent W.

0 Kudos
2,562 Views
danielchai
Senior Contributor I

Hi Brent,

Did you get it to work? Now I am trying to use the NAND Flash instead of the RAM.

But when it format it, it said can not format it.

-Daniel

0 Kudos
2,562 Views
brentwilliams
Contributor II

Hi Daniel,

I have been working with Freescale to try and come up with a solution.  The current design for the MQX MSD requires that any reads/writes to the MSD take place within a callback function (void Bulk_Transaction_Callback in their example code).  This takes place within an interrupt context.  This means, if your driver that accesses the NAND flash utilizes semaphores, then it won't work.  MQX (with good reason) will not let you potentially block from within an interrupt context.

This is what I am running into.  My external FLASH is connected via a SPI bus.  The MQX low-level SPI driver (as well as the flashx driver) use semaphores.  When called from the callback they return an error due to the semaphore functions being called in an interrupt context.  I am thinking that the only solution is to remove the MQX low-level SPI driver and created a simple polling SPI driver that does not use semaphores.

I don't like the idea that you have to access your MSD device from an interrupt context.

Brent

0 Kudos
2,562 Views
dereksnell
NXP Employee
NXP Employee

Hi Brent,

Regarding the callback issue within the interrupt context, what about using a synchronization service to signal another task to use the driver?  Something like a lwevent, or a message?  The interrupt can signal the task, and then return.  The task can then execute using the existing drivers to access the flash, and then the semaphores would run in the task context.

Just a thought.  Thanks

0 Kudos
2,561 Views
brentwilliams
Contributor II

Thanks for the input Derek, I had tried that also.  The issue is with the design of the MQX USB stack.

For example in a read case:

1)  A USB interrupt goes off

2) USB interrupt handler does two things

     a) calls callback function (this is where I signaled another task to perform the read)

     b) once callback function returns, the interrupt handler sends out the "read" data to the USB host (PC).

Both of these are done from an interrupt context (USB interrupt). 

The issue here is that I don't have the data yet.  Even though I signaled the thread to do the read/write, it won't start until the interrupt handler has returned (i.e. done it's thing) and is scheduled to do so.

I had tried taking the send data back to USB Host out of the stack and doing this in Thread, but that did not work.

Brent

0 Kudos
2,561 Views
michaelbrudevol
Contributor II

The solution I used was to read the USB interrupt status (which is 32-bits) and then pass that off to a (high priority) task using an lwevent.  Then you move the processing of the status from the USB interrupt to that task.  This means your processing will no longer occur in an interrupt context and you can access blocking drivers.  I am using the EHCI driver - did not test with KHCI.

0 Kudos
2,556 Views
danielchai
Senior Contributor I

Hi Michael,

Could you explain how you read the USB interrupt status and where?

Did you read the USB interrupt status in the main loop?

Thank you.

-Daniel

0 Kudos
2,556 Views
michaelbrudevol
Contributor II

My changes were done to the ehci driver, but looks like the khci is similar enough - hope it works.

You do have to modify the driver, that's the only way to get out of interrupt context in a simple fashion.

In function _usb_device_usbfs_isr, take the value of error and use it to set an lwevent.  Move everything in the isr that comes after that to your high priority task.  I recommend creating the task within the khci driver to keep it contained.  Init your lwevent when you create the task.  You might choose to disable the interrupt in the ISR and re-enable at the bottom of your task.  May or may not matter.

0 Kudos
2,556 Views
primozrebec
Contributor III

Just to confirm that this solution works for me (for now:) ) on khci driver.

0 Kudos
2,556 Views
primozrebec
Contributor III

Did anybody succeed to make USB MSD with external SPI flash work? I am using MQX 4.0.1., USB MSD device profile, FLASHX driver and SPI driver to access NOR flash HW.

What i've found and tested until now:

- USB MSD device works fine, because i can run RAM DISK example successfully

- My SPI driver to NOR flash works as it should. I've modified SPI example that comes with MQX package.

- I believe i have successfully ported FLASHX driver to use with external SPI flash.

- I did modifications in USB khci SW in order to use blocking drivers with USB MSD.

- I've followed recommendations from this thread: Re: Using Micron's external Flash with MQX

Problem is that i cannot format USB disk when using USB MSD with external flash architecture. Windows always returns error that cannot format disk... I did some debugging on this and i can see reading and writing data to/from flash during disk format process. I've checked the addresses that are used to access flash during read, write and block erase commands and all seem reasonable. Is there anything i missed? Please, advise.

Best,

Primoz

0 Kudos
2,556 Views
primozrebec
Contributor III

Hi all,

i have finally made this design work. There was a bug in MQX FlashX driver. See the following code snippet of »_io_flashx_write_partial_sector« function that can be found in flashx.c source file. I have also updated FlashX driver with low-level driver read() function call for reading from flash instead of using _mem_copy … This functionality is not implemented in original driver.

    else if ((file_ptr->FLAGS & FLASHX_FLASH_BUFFER_ENABLED) && (file_ptr->FLAGS & FLASHX_SECTOR_CACHE_ENABLED)) {

        /* Writing using delayed write */

        if (!_allocate_sector_cache(fd_ptr))

            return (_mem_size) IO_ERROR;

      

        /* Buffering= delayed write caching */

        if ((file_ptr->DIRTY_DATA) && (file_ptr->CACHE_BLOCK != block_number || file_ptr->CACHE_SECTOR != sector_number)) {

            _io_flashx_flush_buffer(fd_ptr);

        }

     

        /* Read the sector for partial write from flash into RAM */      

     

       //BUGFIX: update sector buffer content from flash only if sector buffer is not dirty yet!

        if(file_ptr->DIRTY_DATA == FALSE) {

                dev_ptr->READ(dev_ptr, (pointer)sector_dest_ptr, file_ptr->CACHE_PTR,sector_size);

        }

      

        file_ptr->CACHE_BLOCK  = block_number;

        file_ptr->CACHE_SECTOR = sector_number;

        file_ptr->CACHE_FILE_SECTOR = file_sector;

Somebody may find this helpful.

Best,

Primoz.

0 Kudos
2,556 Views
varaprasadvenka
Contributor I

Hi Primoz,

  We are also using USB_CDC example with N25Q Nor flash ,but  we used micron flash driver instead of MQX FlashX driver, (That flash driver is working well after integration) Facing similar issue unable to format by windows.

Thought some mistake in call back handler integration with flash apis it would be great if you share the usbcdc workspace  with flash integration or at least  disk.c and disk.h files for reference

Thanks in advance...

Regards

Venkata Vara Prasad

0 Kudos
2,556 Views
danielchai
Senior Contributor I

Thank you Michael.

-Daniel

0 Kudos
2,556 Views
brentwilliams
Contributor II

Thanks Michael

0 Kudos
2,561 Views
brentwilliams
Contributor II

Good thought Michael, I will try that.

0 Kudos
2,561 Views
danielchai
Senior Contributor I

Hi Brent,

Did you try the Michael's method? Does it work?

Thank you.

-Daniel

0 Kudos