This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

elm chan FatFs on SD Card USB MSC implementation detected but not refreshed

Genius 4170 points
Other Parts Discussed in Thread: MSP430F5529

Hello all,

I have a question i just cannot get my head around right now.

I am working with MSP430F5529, which has an USB module onboard. I am working with CCS 6.1 just for the notice.

Now I did simply integrate the USB composite CDC MSC example, which is already using elm-chans FatFs implementation via SPI to SD card.

This all works pretty nice ( after a lot of debugging and coding and sweat and tears :) ).

Now what is not working , but I would really like to have that, is if I build a file on SDcard with my MSP430:

	f_mount(0, &fatfs);		/* Give a work area to the default drive */
	if (f_open(&File, "textertester.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {	/* Create a file */
		unsigned int bw, btw;
		f_write(&File, "test\r\n", 11, &bw);	/* Write data to the file */
		f_close(&File);					/* Close the file */
	}

so now there is: textertester.txt on the SDcard , I know that for sure, BUT  

my windows explorer is not showing that new data, unless I pull out the SDcard and put it in again, or the same with the USB connector.

Now how can I get the windows explorer to "live" refresh the data contect of the connected MSC SDcard? Anyone ever done that? For a running product that would be a huge plus, not having to pull and push the connectors all the time to see the new logged data :)

Now I will share my workaround with you; I did simulate in the code, that the card has been pulled out and after a while been pushed in again, that works, BUT then windows does create a popup with connected removable device each time i create a new file, I can live with that but I would rather prefer another solution.

Dont bother if you never seen the elm chan TI-code, but if you have maybe you can point out somethings I could do more easily.

As always I will keep updates about my successes in here, I try to figure out today how to implement it.

Thanks for helping and reading.

seb

				// an removal has been detected
		        mediaInfo.mediaPresent = kUSBMSC_MEDIA_NOT_PRESENT;
		        mediaInfo.mediaChanged = 0x01;

			    uint8_t state;

			    Scsi_Read_Capacity_10[0].lLba[0] = (uint8_t)(mediaInfo.lastBlockLba >> 24);
			    Scsi_Read_Capacity_10[0].lLba[1] = (uint8_t)(mediaInfo.lastBlockLba >> 16);
			    Scsi_Read_Capacity_10[0].lLba[2] = (uint8_t)(mediaInfo.lastBlockLba >> 8);
			    Scsi_Read_Capacity_10[0].lLba[3] = (uint8_t)(mediaInfo.lastBlockLba);

			    Scsi_Read_Capacity_10[0].bLength[0] = (uint8_t)(mediaInfo.bytesPerBlock >> 24);
			    Scsi_Read_Capacity_10[0].bLength[1] = (uint8_t)(mediaInfo.bytesPerBlock >> 16);
			    Scsi_Read_Capacity_10[0].bLength[2] = (uint8_t)(mediaInfo.bytesPerBlock >> 8);
			    Scsi_Read_Capacity_10[0].bLength[3] = (uint8_t)(mediaInfo.bytesPerBlock);

			    MscControl[0].lbaSize = (uint16_t)Scsi_Read_Capacity_10[0].bLength[2] <<
			                              8 | Scsi_Read_Capacity_10[0].bLength[3];

			    //If the 0 was reported as not removable, then leave mediaPresent/mediaChanged as
			    //their initialized defaults.
			    if (USBMSC_config.LUN[0].removable){

			            //Set Unit Attention flag. This flag is used in Scsi_Request_Sense().
			            MscState.bUnitAttention = TRUE;
			            MscState.Scsi_Status = SCSI_FAILED;
			            state = USBMSC_getState();

			            if (state ==  kUSBMSC_readInProgress || state ==
			                kUSBMSC_writeInProgress){
			                if (McsCbw.bmCBWFlags == 0x80){		// DIRECTION_IN
			                    usbStallInEndpoint(MSC0_INTFNUM);
			                } else {
			                    usbStallOutEndpoint(MSC0_INTFNUM);
			                }

			                Msc_ResetStateMachine();
			                Msc_ResetFlags();
			                Msc_ResetStruct();
			                MscState.isMSCConfigured = TRUE;

			                Scsi_Send_CSW(MSC0_INTFNUM);
			            }
//			        }
			        MscControl[0].bMediaPresent = mediaInfo.mediaPresent;
			    }

			    MscControl[0].bWriteProtected = mediaInfo.writeProtected;
//			    mscProcessBuffer(); // Handle READ/WRITE cmds from the host
				while(!(P1IN & BIT2)){
					__no_operation();

					mscProcessBuffer(); // Handle READ/WRITE cmds from the host
				}

				__no_operation();
				while((P1IN & BIT2));
				// an insertion has been detected
		        mediaInfo.mediaPresent = kUSBMSC_MEDIA_PRESENT;
		        mediaInfo.mediaChanged = 0x01;

			    Scsi_Read_Capacity_10[0].lLba[0] = (uint8_t)(mediaInfo.lastBlockLba >> 24);
			    Scsi_Read_Capacity_10[0].lLba[1] = (uint8_t)(mediaInfo.lastBlockLba >> 16);
			    Scsi_Read_Capacity_10[0].lLba[2] = (uint8_t)(mediaInfo.lastBlockLba >> 8);
			    Scsi_Read_Capacity_10[0].lLba[3] = (uint8_t)(mediaInfo.lastBlockLba);

			    Scsi_Read_Capacity_10[0].bLength[0] = (uint8_t)(mediaInfo.bytesPerBlock >> 24);
			    Scsi_Read_Capacity_10[0].bLength[1] = (uint8_t)(mediaInfo.bytesPerBlock >> 16);
			    Scsi_Read_Capacity_10[0].bLength[2] = (uint8_t)(mediaInfo.bytesPerBlock >> 8);
			    Scsi_Read_Capacity_10[0].bLength[3] = (uint8_t)(mediaInfo.bytesPerBlock);

			    MscControl[0].lbaSize = (uint16_t)Scsi_Read_Capacity_10[0].bLength[2] <<
			                              8 | Scsi_Read_Capacity_10[0].bLength[3];

	        	/// wenn Karte eingesteckt wird einmal hier rein und naschliessend auch ins nächste
	            MscState.bUnitAttention = TRUE;
	            MscState.Scsi_Status = SCSI_FAILED;

			    if (USBMSC_config.LUN[0].removable){
	                       //Or if media still present, but has changed...

			            //Set Unit Attention flag. This flag is used in Scsi_Request_Sense().
			            MscState.bUnitAttention = TRUE;
			            MscState.Scsi_Status = SCSI_FAILED;
			            state = USBMSC_getState();

			            if (state ==  kUSBMSC_readInProgress || state ==
			                kUSBMSC_writeInProgress){
			                if (McsCbw.bmCBWFlags == 0x80){		// DIRECTION_IN
			                    usbStallInEndpoint(MSC0_INTFNUM);
			                } else {
			                    usbStallOutEndpoint(MSC0_INTFNUM);
			                }

			                Msc_ResetStateMachine();
			                Msc_ResetFlags();
			                Msc_ResetStruct();
			                MscState.isMSCConfigured = TRUE;

			                Scsi_Send_CSW(MSC0_INTFNUM);
			            }
//			        }
			        MscControl[0].bMediaPresent = mediaInfo.mediaPresent;
			    }

			    MscControl[0].bWriteProtected = mediaInfo.writeProtected;

				while(!(P1IN & BIT2)){
					__no_operation();

					mscProcessBuffer(); // Handle READ/WRITE cmds from the host
				}

  • Windows (and every other OS) assumes that it has full control over the storage device, so it caches everything.

    You must not change any data while the storage device is connected to a host, and you cannot rely on any new data from the host actually showing up before the device is unmounted.

    There is no alternative to simulating unplugging the card or the device.

  • Thanks for the advice, I got pretty much the same other on other forums, and I am not beeing able to debug the code to a point where I find the "one" magic function, which suddenly makes the file system appear and disappear.

    I guess USB works pretty complicted as it jumps various times into IRQ and different routines while polling, and I can impossibly debug that with step by step debugging, since USB is also time dependend on the PC host and stuff.

    So I will find out how much time is needed minimum in order to pretend the SD card was removed for the PC and that I will implement after each file manipulation.


    Although I would like to have code that works in my proposed way, I am sadly not capable of writing my own USB stack, let alone a FatFs stack :), especially not if the product is suppoed to be running in 2 weeks :)

    But maybe some more people than just me have that problem, so feel free to post and maybe we find a solution otgether.
  • #1 update:
    I just teste it on my smartphone, android, connected via USB to PC. Of course I dont know the USB controller nor the RTOS nor nothing, but I know that when i create a text file on the android phone it will be detected on the PC immediatly without any reconnecting.
    Damn others get exactly what I wanna :) can it be that a HID device could help, I got now clue, but it seems others do so
  • Modern Android version do not use MSC, but PTP or MTP, which are similar to network file systems, so the host PC expects there to be changes.

    And the answer to the obvious follow-up question is "no".

  • :) first I thought well yeah you are right there is no MPT stack for the MSP430, but now I at least found some companies which are doing MPT stacks for embedded systems, not that I myself would be able to code something like that in my sacred time.
    There is one called hitex, they at least got MSP430 on their homepage, but I am not sure yet if they can provide a MPT stack for those controllers, right now I am convinced that not, but lets wait or you know more, since I couldnt find out a whole lot about the MPT stack think besides its android usage.
  • Hi there, just wanted to add my Code for workaround the refresh windows Problem.

    I was just playing around, so I am not really sure if it always works, but till now it is, but i am 100% convinced it is not fool proof yet :)

    Basically what I do is simulate in a very very fast way that the card had been ejected, so windows is not popping anything, and if you press F5 the new files are appearing on screen.

    It must be somewhat interrupt driven, although that would definetly cause me troubles later, since I dont know the timings for sure, and therefore got no clue when is happening what, maybe some of you get my point, a lot wont I know it, you have to pretty knee deep in coding to understand the TI USB code, but Ill post it anyway:

    				f_mount(0, &fatfs);		/* Give a work area to the default drive */
    
    				if (f_open(&File, "refugees_welcome.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {	/* Create a file */
    
    
    					f_write(&File, "as long as its a globalized world we living in", 22, &bw);	/* Write data to the file */
    
    					f_close(&File);								/* Close the file */
    					
    					
    				}
    	
    				// an removal has been detected
    		        mediaInfo.mediaPresent = kUSBMSC_MEDIA_NOT_PRESENT;
    		        mediaInfo.mediaChanged = 0x01;
    
    			    Scsi_Read_Capacity_10[0].lLba[0] = (uint8_t)(mediaInfo.lastBlockLba >> 24);
    			    Scsi_Read_Capacity_10[0].lLba[1] = (uint8_t)(mediaInfo.lastBlockLba >> 16);
    			    Scsi_Read_Capacity_10[0].lLba[2] = (uint8_t)(mediaInfo.lastBlockLba >> 8);
    			    Scsi_Read_Capacity_10[0].lLba[3] = (uint8_t)(mediaInfo.lastBlockLba);
    
    			    Scsi_Read_Capacity_10[0].bLength[0] = (uint8_t)(mediaInfo.bytesPerBlock >> 24);
    			    Scsi_Read_Capacity_10[0].bLength[1] = (uint8_t)(mediaInfo.bytesPerBlock >> 16);
    			    Scsi_Read_Capacity_10[0].bLength[2] = (uint8_t)(mediaInfo.bytesPerBlock >> 8);
    			    Scsi_Read_Capacity_10[0].bLength[3] = (uint8_t)(mediaInfo.bytesPerBlock);
    
    			    MscControl[0].lbaSize = (uint16_t)Scsi_Read_Capacity_10[0].bLength[2] <<
    			                              8 | Scsi_Read_Capacity_10[0].bLength[3];
    				//Set Unit Attention flag. This flag is used in Scsi_Request_Sense().
    				MscState.bUnitAttention = TRUE;
    				MscState.Scsi_Status = SCSI_FAILED;
    				MscControl[0].bMediaPresent = mediaInfo.mediaPresent;
    			    MscControl[0].bWriteProtected = mediaInfo.writeProtected;
    
    				// an insertion has been detected
    		        mediaInfo.mediaPresent = kUSBMSC_MEDIA_PRESENT;
    		        mediaInfo.mediaChanged = 0x01;
    
    			    Scsi_Read_Capacity_10[0].lLba[0] = (uint8_t)(mediaInfo.lastBlockLba >> 24);
    			    Scsi_Read_Capacity_10[0].lLba[1] = (uint8_t)(mediaInfo.lastBlockLba >> 16);
    			    Scsi_Read_Capacity_10[0].lLba[2] = (uint8_t)(mediaInfo.lastBlockLba >> 8);
    			    Scsi_Read_Capacity_10[0].lLba[3] = (uint8_t)(mediaInfo.lastBlockLba);
    
    			    Scsi_Read_Capacity_10[0].bLength[0] = (uint8_t)(mediaInfo.bytesPerBlock >> 24);
    			    Scsi_Read_Capacity_10[0].bLength[1] = (uint8_t)(mediaInfo.bytesPerBlock >> 16);
    			    Scsi_Read_Capacity_10[0].bLength[2] = (uint8_t)(mediaInfo.bytesPerBlock >> 8);
    			    Scsi_Read_Capacity_10[0].bLength[3] = (uint8_t)(mediaInfo.bytesPerBlock);
    
    			    MscControl[0].lbaSize = (uint16_t)Scsi_Read_Capacity_10[0].bLength[2] <<
    			                              8 | Scsi_Read_Capacity_10[0].bLength[3];
    
    				//Set Unit Attention flag. This flag is used in Scsi_Request_Sense().
    				MscState.bUnitAttention = TRUE;
    				MscState.Scsi_Status = SCSI_FAILED;
    			    MscControl[0].bMediaPresent = mediaInfo.mediaPresent;
    			    MscControl[0].bWriteProtected = mediaInfo.writeProtected;

    First I open or create the new file, -> that must already be IRQ driven, after that, I got now clue if the transfer of information is ready yet, but I suppose so, well after that I simply cutted the code for SD card removable and insertion and parsed it.

    It amazingly works, but all I do as you can see is set new values to variables, there is no function call included, I am amazed myself, So I am sure some IRQ calles will be made during thta time otherwise it could never work.

    So maybe someone has more insight and wants to share it as well.

    Thanks for reading.

    seb

  • #update:

    it seems like only the scsi module needs some trigger reactions:

    MscState.bUnitAttention = TRUE;
    MscState.Scsi_Status = SCSI_FAILED;

    those 2 lines cut it, then it works as well, dont know yet what the timing of this is, i will try to put a lot of file in a series cue and test if all of them are on the sd card afterwards :)

**Attention** This is a public forum