Combining LUFA and FATfs for USB drive

Go To Last Post
32 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The goal of my project is to create a data logger that saves ADC readings and a timestamp to a USB drive (not SD/MMC). I have an Atmel AT90USBKey for this purpose. I have done some homework and found that using LUFA and FATFs seems to be a good option. What I am having problems with is combining the two. I have been able to run both the MassStorageHost (which makes the board a host) and the TempDataLogger (which takes readings and stores them to onboard flash) examples from LUFA without any problem.

My plan is to base the project off the MassStorageHost demo. It will wait until a flash drive is plugged in, and then start recording from the ADC. It will stop when once the drive is full or is removed. Through the onboard flash, I have been able to get the ADC to give me the readings and the frequency of readings I am looking for and also the timestamp. The last part of making it save to a portable drive is my roadblock.

I have done a few searches on this forum for similar projects. I did found a couple, but no code examples were provided or no follow up was made from the poster. I will consider changing to SD/MMC if it comes down to it, but I would need to order the parts within a few days from now in order to meet my deadline. Hopefully, someone can point me in the right direction.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's not too hard to link up FatFS to the Mass Storage Host class drivers -- all you really need to do is add the files to the MassStorageHost demo project, and then edit the FatFS diskio.c file so that the block read/write functions call the appropriate Mass Storage Host Class driver block read/write functions. When I get home I'll try to cook up a demo for you.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks! As I said this is that last piece of the puzzle.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's too late (nearly 2AM) for me to test this, but it should work. When a mass storage device is inserted it should create a new blank file called "LUFA.txt" on it. If that works, you can use that code as a base and use the regular FATFs file functions to create, open, write to and close files.

You can also look at the Projects/Incomplete/StandaloneProgrammer for another example, which supports both host and device mass storage modes and uses streams to abstract out the exact storage medium from the application.

- Dean :twisted:

Attachment(s): 

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you, Dean. It would be very nice to find such example inside the LUFA package. I've spent 2 days looking for it on the web.

Ilm.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser wrote:
It's too late (nearly 2AM) for me to test this, but it should work. When a mass storage device is inserted it should create a new blank file called "LUFA.txt" on it. If that works, you can use that code as a base and use the regular FATFs file functions to create, open, write to and close files.

You can also look at the Projects/Incomplete/StandaloneProgrammer for another example, which supports both host and device mass storage modes and uses streams to abstract out the exact storage medium from the application.

- Dean :twisted:

hi Dean

I want to use this project in LUFA-120730 version ,
i copy this project file in LUFA-120730\LUFA-120730\Demos\Host\ClassDriver directory then comipile the source but compiler says "make.exe: *** No rule to make target `MassStorageHost.elf', needed by `elf'. Stop."!?

would you say that how do i do it ?

thanks
mojtaba

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Mojtaba,

That's a very, very old demo, and isn't really compatible with the latest version of LUFA (although it could be upgraded). It would be better however if you instead worked off the latest LUFA Host mode MassStorage class driver demo. Copy over the FatFS library into the project, add it to the makefile and use this diskio.c wrapper file to link FatFS to it:

https://code.google.com/p/blueto...

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Dean!

I wanted to use the new release of LUFA (version 130303) so I searched for demos and I saw your bluetooth-explorerbot project. I wanted the same application of LUFA as a mass storage host and able to read/write on FAT32 devices. My problem is, not all flash drives are successful in getting past enumeration(?).

what i did is port the new lufa on your project and removed some components like bluetooth and ported it on my hardware.
On my Sandisk Cruzer Blade 4GB flash drive, the error is at the Post-config function whenever it calls MS_Host_ResetMSInterface.

On my Kingston DT101 G2 8GB Flash drive, the error is at the function MassStorage_USBTask whenever it calls MS_Host_ReadDeviceCapacity.

I'm using AT90USB1287 for my application and I hope you could help me on this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry I'm late on this - full inbox, empty energy reserves.

Mass Storage Devices and USB are a bit of a crapshoot, with every vendor doing every possible variation and crazy implementation from the standard; it's a damned wonder they all work at all under most OSes. That makes my job a lot harder however, as it's impossible to know what crazy scheme they'll think of next so that I can code defensively (one implementation had the USB stack and SCSI layer coded as a state machine, hard-wired to the Windows enumeration process).

Can you tell me what the error is exactly? That sounds very much like the stick is too large, as 4GB is the latest size that fits into a 32-bit integer.

My library's MS_Host_ReadDeviceCapacity() function issues a 32-bit READ CAPACITY (10) SCSI command, which is limited in the maximum size it can support. Try a READ CAPACITY (16) instead:

void GetCapacity(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
                 const uint8_t LUNIndex)
{
	if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
	  return HOST_SENDCONTROL_DeviceDisconnected;

	uint8_t ErrorCode;

	MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
		{
			.DataTransferLength = CPU_TO_LE32(sizeof(SCSI_Capacity_t)),
			.Flags              = MS_COMMAND_DIR_DATA_IN,
			.LUN                = LUNIndex,
			.SCSICommandLength  = 16,
			.SCSICommandData    =
				{
					0x9E,                   // SCSI_CMD_READ_CAPACITY_16,
					0x00,                   // Reserved
					0x00,                   // MSB of Logical block address
					0x00,
					0x00,
					0x00,
					0x00,
					0x00,
					0x00,
					0x00,                   // LSB of Logical block address
					0x00,                   // MSB of Allocation Length
					0x00,
					0x00,
					0x0F,                   // LSB of Allocation Length
					0x00,                   // Partial Medium Indicator
					0x00                    // Unused (control)
				}
		};

	struct
	{
		uint64_t Blocks;
		uint32_t BlockSize
	} DeviceCapacity;

	if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, &DeviceCapacity)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	DeviceCapacity.Blocks    = BE64_TO_CPU(DeviceCapacity->Blocks);
	DeviceCapacity.BlockSize = BE32_TO_CPU(DeviceCapacity->BlockSize);

	return PIPE_RWSTREAM_NoError;
}

You will need to provide your own implementation of a BE64_TO_CPU() to reverse the endianness of the device block count.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Dean,

I have installed the LUFA library in Atmel Studio 6.1. It made my life easier since I don't have to study about makefiles. Thumbs up on that one.

I have purchased an AT90USBKEY to make it a mass storage host. I used your low level mass storage demo as my guide. I am having some problems with regards to the MassStorageHost_Task function. Some of my flash drives are having errors in the MassStore_MassStorageReset and like the earlier post, in the MassStore_ReadCapacity part.

Your help would be very much appreciated. Thank you in advance!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Same as my previous response - if your sticks are over 4GB in size, you'll need the alternative ReadCapacity function above. I'll make a note to roll this into the next release.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your response Dean.

How about for the MassStore_MassStorageReset?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Dean!

Thank you very much for your answer!

I tried using the code you provided but the error still occurs on MS_Host_SendCommand and returns ErrorCode = 1. the same is true with the original code. I'm already trying the Mass Storage Host Demo itself and the same error occurs.

As for the MS_Host_ResetMSInterface problem I encountered before, error occurs when calling USB_Host_ClearEndpointStall. It returns an ErrorCode = 3 after DataOutPipe is selected.

I tried other 4GB flash drives, some doesnt have any problems but some does in MS_Host_ResetMSInterface. returned ErrorCode = 3 after calling USB_Host_ClearEndpointStall.

Out of desperation, I tried commenting out the MS_Host_ResetMSInterface return call after it was called. I tested it by writing "Hello World" on a txt file every time a flash disk is connected. And Voila! it works!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Thank you for your response Dean.

How about for the MassStore_MassStorageReset?

That shouldn't need tweaking, as it's not at the SCSI layer. If it fails you can probably just ignore it, since it most likely means the target device firmware is buggy.

Quote:

As for the MS_Host_ResetMSInterface problem I encountered before, error occurs when calling USB_Host_ClearEndpointStall. It returns an ErrorCode = 3 after DataOutPipe is selected.

Can you obtain the value of Pipe_GetBoundEndpointAddress() after the IN and OUT pipes have been selected, as well as the full descriptors of the problematic device? Sounds like the function is returning an incorrect endpoint address which is then causing a bad CLEAR FEATURE control request to be issued.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Dean!

I'm sorry for the late response. I was confused a little with full descriptors so I read more on USB descriptors. :)

Well I tried what you said and here is what I did:

uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
{
	uint8_t ErrorCode;
	uint8_t address;

	USB_ControlRequest = (USB_Request_Header_t)
		{
			.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
			.bRequest      = MS_REQ_MassStorageReset,
			.wValue        = 0,
			.wIndex        = MSInterfaceInfo->State.InterfaceNumber,
			.wLength       = 0,
		};

	Pipe_SelectPipe(PIPE_CONTROLPIPE);

	if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
	  return ErrorCode;

	Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
	
	address = Pipe_GetBoundEndpointAddress();
	if ((ErrorCode = USB_Host_ClearEndpointStall(address)) != HOST_SENDCONTROL_Successful)
	  return ErrorCode;

	Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
	
	address = Pipe_GetBoundEndpointAddress();
	if ((ErrorCode = USB_Host_ClearEndpointStall(address)) != HOST_SENDCONTROL_Successful)
	  return ErrorCode;
	  
	

	return HOST_SENDCONTROL_Successful;
}

so I got the addresses and a part of the descriptors I think.

Case 1 (Sandisk 4GB):
Error after selecting IN Pipe;

address is 1

MSInterfaceInfo->
Config.DataINPipe.Address = 129
Config.DataINPipe.Size = 64
Config.DataINPipe.EndpointAddress = 129
Config.DataINPipe.Type = 2
Config.DataINPipe.Banks = 1

Case 2 (Silicon Power 4GB):
Error after selecting OUT Pipe;

address is 130

MSInterfaceInfo->
Config.DataINPipe.Address = 2
Config.DataINPipe.Size = 64
Config.DataINPipe.EndpointAddress = 2
Config.DataINPipe.Type = 2
Config.DataINPipe.Banks = 1

I see that the address is different with the endpointaddress. I hope this helps...

Last Edited: Tue. May 14, 2013 - 06:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Dean!

I think we have a breakthrough... I think...

I checked this part of Pipe_AVR8.h:

static inline uint8_t Pipe_GetBoundEndpointAddress(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetBoundEndpointAddress(void)
{
    uint8_t UPCFG0X_Temp = UPCFG0X;
				
     return (((UPCFG0X_Temp >> PEPNUM0) & PIPE_EPNUM_MASK) | ((UPCFG0X_Temp & PEPNUM1) ? ENDPOINT_DIR_OUT : ENDPOINT_DIR_IN));
}

and looked at your previous implementation of this function and the difference is the last half of the return statement.
And considering Case 2 of my previous post, the ternary if statement results in a false thus choosing ENDPOINT_DIR_IN. Which is not consistent considering we selected the OUT pipe.

So I tried to understand what you are trying to do here. And this statement

(UPCFG0X_Temp & PEPNUM1)

might be better off like this.

(UPCFG0X_Temp & (1 << PEPNUM1))

So, it ended up as this:

static inline uint8_t Pipe_GetBoundEndpointAddress(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetBoundEndpointAddress(void)
{
	uint8_t UPCFG0X_Temp = UPCFG0X;
				
	return (((UPCFG0X_Temp >> PEPNUM0) & PIPE_EPNUM_MASK) | ((UPCFG0X_Temp & PEPNUM1) ? ENDPOINT_DIR_OUT : ENDPOINT_DIR_IN));
}

tada!

I'm not so sure about this but the previous errors were gone. I hope so...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nuts, I found one problem with that (bad bit name) a few days ago:

https://github.com/abcminiuser/l...

But missed the lack of shift in both cases. I'll fix that tonight, thanks! What name would you like on the changelog?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh! haha!
The good thing is I was on the right track! haha

decerri would be fine.

I would be sending this forum url right now to show my colleagues that the great Dean has acknowledged my persistence. ha!

Thank you very much! this has greatly helped my work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Dean,

I tried to communicate a 8GB FLASH to at90usb host, and modify your above codes here "My library's MS_Host_ReadDeviceCapacity() function issues a 32-bit READ CAPACITY (10) SCSI command, which is limited in the maximum size it can support. Try a READ CAPACITY (16) instead: ".

Now it's detected and recognize the vendor by host but couldn't read capacity and return "SCSI command error (Read Capacity)".

this is the output of serial screen:

    Mass Storage Host Demo running.

    Device Attached.

    Getting Config Data.

    Mass Storage Disk Enumerated.

    Total LUNs: 1 - Using first LUN in device.
    Vendor "hp ", Product "v210w "
    Waiting until ready..
    .
    Retrieving Capacity...
    SCSI command error (Read Capacity).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can you post the exact command and data you are sending?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Can you post the exact command and data you are sending?

- Dean Twisted Evil

I use LUFA-130901 and run this project:
LUFA-130901\Demos\Host\LowLevel\MassStorageHost

according to your above post i turn this function at MassStoreCommands.c:

uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex,
                               SCSI_Capacity_t* const CapacityPtr)
{
	uint8_t ErrorCode = PIPE_RWSTREAM_NoError;

	/* Create a CBW with a SCSI command to issue READ CAPACITY command */
	MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
		{
			.Signature          = MS_CBW_SIGNATURE,
			.DataTransferLength = sizeof(SCSI_Capacity_t),
			.Flags              = MS_COMMAND_DIR_DATA_IN,
			.LUN                = LUNIndex,
			.SCSICommandLength  = 10,
			.SCSICommandData    =
				{
					SCSI_CMD_READ_CAPACITY_10,
					0x00,                   // Reserved
					0x00,                   // MSB of Logical block address
					0x00,
					0x00,
					0x00,                   // LSB of Logical block address
					0x00,                   // Reserved
					0x00,                   // Reserved
					0x00,                   // Partial Medium Indicator
					0x00                    // Unused (control)
				}
		};

	/* Send the command and any data to the attached device */
	if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, CapacityPtr)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	/* Endian-correct the read data */
	CapacityPtr->Blocks    = SwapEndian_32(CapacityPtr->Blocks);
	CapacityPtr->BlockSize = SwapEndian_32(CapacityPtr->BlockSize);

	return ErrorCode;
}

to:

uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex,
                               SCSI_Capacity_t* const CapacityPtr)
{
	uint8_t ErrorCode = PIPE_RWSTREAM_NoError;

	/* Create a CBW with a SCSI command to issue READ CAPACITY command */
	MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
		{
			.Signature          = MS_CBW_SIGNATURE,
			.DataTransferLength = CPU_TO_LE32(sizeof(SCSI_Capacity_t)),
			.Flags              = MS_COMMAND_DIR_DATA_IN,
			.LUN                = LUNIndex,
			.SCSICommandLength  = 16,
			.SCSICommandData    =
				{
			   0x9E,                   // SCSI_CMD_READ_CAPACITY_16, 
               0x00,                   // Reserved 
               0x00,                   // MSB of Logical block address 
               0x00, 
               0x00, 
               0x00, 
               0x00, 
               0x00, 
               0x00, 
               0x00,                   // LSB of Logical block address 
               0x00,                   // MSB of Allocation Length 
               0x00, 
               0x00, 
               0x0F,                   // LSB of Allocation Length 
               0x00,                   // Partial Medium Indicator 
               0x00                    // Unused (control) 
	
				}
		};


	/* Send the command and any data to the attached device */
	if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, CapacityPtr)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	/* Endian-correct the read data */
	CapacityPtr->Blocks    = SwapEndian_64(CapacityPtr->Blocks);
	CapacityPtr->BlockSize = SwapEndian_32(CapacityPtr->BlockSize);

	return ErrorCode;
}

and add this macro at Endianness.h

#define SWAPENDIAN_64(x)            (uint64_t)((((x) & 0xFF00000000000000UL) >> 56UL) | (((x) & 0x00FF000000000000UL) >> 40UL) | \
			                                               (((x) & 0x0000FF0000000000UL) >> 24UL)  | (((x)& 0x000000FF00000000UL) >> 8UL) | \
														   (((x) & 0x00000000FF000000UL) << 8UL) |  (((x) & 0x0000000000FF0000UL) >> 24UL) | \
			                                               (((x) & 0x000000000000FF00UL) >> 40UL)  |(((x) & 0x00000000000000FFUL) >> 56UL) )

also this function:

static inline uint64_t SwapEndian_64(const uint64_t DDWord) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
			static inline uint64_t SwapEndian_64(const uint64_t DDWord)
			{
				if (GCC_IS_COMPILE_CONST(DDWord))
				  return SWAPENDIAN_64(DDWord);

				uint8_t Temp;

				union
				{
					uint64_t DDWord;
					uint8_t  Bytes[8];
				} Data;

				Data.DDWord = DDWord;

				Temp = Data.Bytes[0];
				Data.Bytes[0] = Data.Bytes[7];
				Data.Bytes[7] = Temp;
				
				Temp = Data.Bytes[1];
				Data.Bytes[1] = Data.Bytes[6];
				Data.Bytes[6] = Temp;
				
				Temp = Data.Bytes[2];
				Data.Bytes[2] = Data.Bytes[5];
				Data.Bytes[5] = Temp;

				Temp = Data.Bytes[3];
				Data.Bytes[3] = Data.Bytes[4];
				Data.Bytes[4] = Temp;

				return Data.DDWord;
			}

and turn this structure in MassStorageClassHost.h :

typedef struct
			{
				uint32_t Blocks; /**< Number of blocks in the addressed LUN of the device. */
				uint32_t BlockSize; /**< Number of bytes in each block in the addressed LUN. */
			} SCSI_Capacity_t;

to:

typedef struct
			{
				uint64_t Blocks; /**< Number of blocks in the addressed LUN of the device. */
				uint32_t BlockSize; /**< Number of bytes in each block in the addressed LUN. */
			} SCSI_Capacity_t;

Quote:
Quote:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looking at:

http://www.seagate.com/staticfil...

It seems I missed the SERVICE ACTION value on the second SCSI command byte. Try:

         .SCSICommandData    =
            {
               0x9E,                   // SCSI_CMD_READ_CAPACITY_16,
               0x10,                   // Reserved / SERVICE_ACTION
               0x00,                   // MSB of Logical block address
               0x00,
               0x00,
               0x00,
               0x00,
               0x00,
               0x00,
               0x00,                   // LSB of Logical block address
               0x00,                   // MSB of Allocation Length
               0x00,
               0x00,
               0x0F,                   // LSB of Allocation Length
               0x00,                   // Partial Medium Indicator
               0x00                    // Unused (control)
            }

In place of the SCSI command you are currently using (second byte is now 0x10). I haven't got any equipment here to test at the moment myself, unfortunately.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you so much for your attention,
It doesn't work and send this comment on screen:

SCSI command error (Read Capacity).

Quote:
I haven't got any equipment here to test at the moment myself, unfortunately.

I'm ready for any test!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually, thinking about this some more - the READ CAPACITY (10) should work, although I am extremely tired today. The block size should always be 512 bytes for USB sticks, and the capacity is returned as the last block address. If you issue the READ CAPACITY (10) does the command succeed but return an invalid capacity?

The theoretical limit for the READ CAPACITY (10) would be a block address of 0xFFFFFFFE, or 2TB with 512 byte blocks.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can run the demo for 8GB FLASH,
Now i want to make file and write to it by FATFS,
I add FATFS (last version of it has usbio.c file).
and add this routin in MassStorageHost_Task(void):

	if (f_mount(&FatFs, "", 1) == FR_OK) {

			puts_P(PSTR("mount FR_OK.\r\n"));
				if (f_open(&Fil, "newfile.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {	/* Create a file */
				
					
					f_write(&Fil, "It works!\r\n", 11, &bw);	/* Write data to the file */
		
					f_close(&Fil);								/* Close the file */

					if (bw == 11) {		/* Lights green LED if data written well */
					
					}
				}
			}

but after running it doesn't work and even no display mount FR_OK. on serial screen.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So what is the return value of f_mount() then?

Possible alternatives acording to the documentation are: FR_INVALID_DRIVE, FR_DISK_ERR, FR_NOT_READY or FR_NO_FILESYSTEM.

Surely you are not only writing to your serial debug screen if things go OK, but also write to it when thingws go wrong. And writing any possibly available data about WHAT goes wrong and HOW?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

and it return 1 on screen:
result : 1
result : 1

that 1 Point to :
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So now you might be able to generate enough initiative/energy to go through the code and see where in the code being called by f_mount() the value 1/FR_DISK_ERR is returned.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes,
it works correctly, thank you so much to great Dean!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And the problem/solution was? (It's only fair to end a case you got help with solving by reporting the solution. This might help future readers with similar problems.)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You make it all sound so easy Dean, but how do I actually copy the FatFs library(FATFs folder) into my AS7 project(LUFA Host mass storage demo) and then add it to the makefile.

 

Reference comments from a current forum post -

 

https://www.avrfreaks.net/forum/h...

 

It would be great if you could help me go further with the USB host mass storage class driver - Ray :defo not twisted:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dean is not around here, much, any more. Have not seen him for quite a while. 

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!