New SDK fsl_usb_device_msd_class problem in USB_MSC_DEVICE_WRITE_REQUEST

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

New SDK fsl_usb_device_msd_class problem in USB_MSC_DEVICE_WRITE_REQUEST

703 Views
danielecortella
Contributor V

Hi all,

i'm using the new SDK library with le MSD library. My problem is in the function:

uint8_t msd1_class_specific_callback(uint8_t event_type, uint16_t value, uint8_t ** data, uint32_t * size, void * arg)

{

...................................................

    /* Prepare the storage device buffer for USB transfer */

  case USB_MSC_DEVICE_WRITE_REQUEST:

#ifdef msd1_RAM_DISK_DEMO              /* USB RAM disk PEx demo project (This code is possible to enable by 'USB RAM disk demo' property). */

  lba_data_ptr = (lba_app_struct_t *)size;

  if(data != NULL) {

  *data = (uint8_t *)&msd1_StorageDisk[lba_data_ptr->offset];

  }

#else

  /* copy data from USb buffer to Storage device

  (Called before after recv_data on BULK OUT endpoints)*/

  lba_data_ptr = (lba_app_struct_t*) size;

  *data = (uint8_t *) &buffer_out;

  //printf("offset=0x%08X,offset>>9=0x%08X\r\n",lba_data_ptr->offset,lba_data_ptr->offset>>9);

  if ((lba_data_ptr->offset >> 9) == FATTable0Sec0) { /* write new file */

  new_file = TRUE;

  printf("new_file=TRUE\r\n");

  } /* EndIf */

  if (((lba_data_ptr->offset >> 9) == FATRootDirSec0)

  && (new_file == TRUE)) {

  /* read file size of the file was received */

  /* search for the file entry was received */

  /* each file entry contain 32 bytes */

  for (i = lba_data_ptr->size - 32; i > 0; i -= 32) {

  if (*(lba_data_ptr->buff_ptr + i) != 0) {

  break;

  } /* EndIf */

  } /* Endfor */

  /* the file size field is offet 28 of file entry */

#if (defined MCU_MK60N512VMD100)

  file_size = *(uint_32*)( lba_data_ptr->buff_ptr + i + 28);

#else

  file_size = BYTESWAP32( *(uint_32* )(lba_data_ptr->buff_ptr + i + 28));

  printf("file_size=0x%08X\r\n", file_size);

#endif

  new_file = FALSE;

  } /* EndIf */

  if ((lba_data_ptr->offset >> 9) == FATDataSec0) {

  erase_flash();

  filetype = UNKNOWN;

  printf("\n\tOpen Image File");

  } /* EndIf */

  if ((lba_data_ptr->offset >> 9) >= FATDataSec0) {

  /* parse and flash an array to flash memory */

  if (FLASH_IMAGE_SUCCESS == error) {

  printf("\r\nbufsize=%d\r\n", lba_data_ptr->size);

  printf("bufaddr=0x%08X\r\n", lba_data_ptr->buff_ptr);

  //dumpBuf(lba_data_ptr->buff_ptr, lba_data_ptr->size, 16);

  error = FlashApplication(lba_data_ptr->buff_ptr, lba_data_ptr->size);

  }

  } /* EndIf */

  /* rest of file */

  //printf("Rest of file\r\n");

  if (((lba_data_ptr->offset >> 9) - FATDataSec0)

  == ((file_size - 1) / 512)) {

  boot_complete = TRUE;     //tranfer file done

  if (BootloaderStatus == BootloaderReady) {

  BootloaderStatus = BootloaderSuccess;

  }

  /* print flashing status */

  if (BootloaderStatus != BootloaderSuccess) {

  printf("\nFlash image file fail!");

  } else {

  printf("\nFlash image file complete!");

  printf("\nPress RESET button to enter application mode.");

  } /* EndIf */

  } /* EndIf */

#endif

      break;

.................................................

}

where the USB_MSC_DEVICE_WRITE_REQUEST is called. This call is done by the :

  • USB_MSC_LBA_Transfer function with msc_obj_ptr->class_specific_callback.callback(USB_MSC_DEVICE_WRITE_REQUEST,  USB_REQ_VAL_INVALID,&msc_obj_ptr->msd_buff.msc_bulk_out_ptr,(uint32_t *)&lba_data, msc_obj_ptr->class_specific_callback.arg);
  • USB_Service_Bulk_Out function with msc_obj_ptr->class_specific_callback.callback(USB_MSC_DEVICE_WRITE_REQUEST,  USB_REQ_VAL_INVALID,&msc_obj_ptr->msd_buff.msc_bulk_out_ptr, NULL, msc_obj_ptr->class_specific_callback.arg);

function in usb_msc.c. As visible the call is different and in USB_Service_Bulk_Out the parameter of size and offset are declare as NULL. Why this? my problem is than that i can't write correctly the data.

Thanks

Daniele

0 Kudos
2 Replies

421 Views
danielecortella
Contributor V

Hi nobody can help me? My problem is that i have to write data to memory,

i have the file msd1_msc where i have the function msd1_class_specific_callback, here there is the :

case USB_MSC_DEVICE_WRITE_REQUEST:

lba_data_ptr = (lba_app_struct_t*) size;

  if (n = strstr(g_msc_bulk_out_buff, "S0160000426C696E6B204669726D776172652E73726563C1")) {

   flag_srec = TRUE;

  }

  *data = g_msc_bulk_out_buff;

if (n = strstr(g_msc_bulk_out_buff, "S0160000426C696E6B204669726D776172652E73726563C1")) {

   flag_srec = TRUE;

  }

used to prepare the buffer where write the data, and the :

case USB_DEV_EVENT_DATA_RECEIVED:

  lba_data_ptr = (lba_app_struct_t*) size;

  if (n = strstr(g_msc_bulk_out_buff, "S0160000426C696E6B204669726D776172652E73726563C1")) {

  flag_srec = TRUE;

  }

where i have to write the buffer to the memory. In usb_msc.c i have this code:

//#ifdef MUTILE_BUFFER

#if ((OS_ADAPTER_ACTIVE_OS == OS_ADAPTER_SDK) && (!USE_RTOS)) || (OS_ADAPTER_ACTIVE_OS == OS_ADAPTER_BM)

                lba_app_struct_t lba_data2;

                if (msc_obj_ptr->transfer_remaining)

                {

                    msc_obj_ptr->class_specific_callback.callback(USB_MSC_DEVICE_WRITE_REQUEST,

                        USB_REQ_VAL_INVALID,&msc_obj_ptr->msd_buff.msc_bulk_out_ptr, NULL, msc_obj_ptr->class_specific_callback.arg);

                    if (msc_obj_ptr->msd_buff.msc_bulk_out_ptr != NULL)

                    {

                        have_transfer = 1;

                        msc_obj_ptr->current_offset += event->len;

                        lba_data2.offset = msc_obj_ptr->current_offset;

                        lba_data2.size = (msc_obj_ptr->msd_buff.msc_bulk_out_size > MSD_RECV_MAX_TRANS_LENGTH) ?

                            MSD_RECV_MAX_TRANS_LENGTH : msc_obj_ptr->msd_buff.msc_bulk_out_size; /* whichever is smaller */

                        lba_data2.size = (msc_obj_ptr->transfer_remaining > lba_data2.size) ?

                            lba_data2.size : msc_obj_ptr->transfer_remaining; /* whichever is smaller */

                        lba_data2.buff_ptr = msc_obj_ptr->msd_buff.msc_bulk_out_ptr;

                        if(msc_obj_ptr->current_offset < (msc_obj_ptr->device_info.total_lba_device_supports * msc_obj_ptr->device_info.length_of_each_lab_of_device))

                        {

                            (void)USB_MSC_Bulk_Recv_Data(msc_obj_ptr->controller_handle,

                                                         lba_data2.buff_ptr,lba_data2.size);

                        }

                        else

                        {

                            msc_obj_ptr->need_out_stall_flag = FALSE; /* clear the flag */

                            msc_obj_ptr->out_stall_flag = TRUE; /* clear the flag */

                            msc_obj_ptr->out_flag = FALSE; /* clear send flag */

                            msc_obj_ptr->stall_status = (uint8_t)STALL_IN_DATA_PHASE;

                            usb_device_stall_endpoint(msc_obj_ptr->controller_handle,msc_obj_ptr->bulk_out_endpoint,USB_RECV);

                        }

                    }

                }

#endif

                msc_obj_ptr->class_specific_callback.callback(USB_DEV_EVENT_DATA_RECEIVED,

                    USB_REQ_VAL_INVALID,NULL,(uint32_t *)&lba_data1, msc_obj_ptr->class_specific_callback.arg);

            }

in USB_MSC_DEVICE_WRITE_REQUEST i can see the string S0160000426C696E6B204669726D776172652E73726563C1 before do the *data = g_msc_bulk_out_buff; so the data arrived before prepare the buffer to save this, the problem is that they didn't arrive in USB_DEV_EVENT_DATA_RECEIVED because the function USB_MSC_Bulk_Recv_Data is called so is changed the content of the buffer .... What i have to do? I have contact the Freescale support but it didn't help me .... He said is not an expert about this code .... HELP PLEASE!

0 Kudos

421 Views
mjbcswitzerland
Specialist V

Hi Daniele

The SDK USB code is very difficult to follow and maintain and I don't think there will be any support unless Freescale has a team working on it that can help you directly.

Generally it is difficult to say what parts are operational for productive use and which are base examples for further work, which will need to be developed before fully operational.

However what I can say is that USB-MSD is in fact quite simple and in case you find that the investment is too high, or your projects are delayed too long due to the need to debug or correct or extend the present references do remember that there are supported sources that are designed to allow easy use and are proven in industrial applications. The follow code is the USB-MSD implementation in the uTasker project as reference which shows that the application/class in fact needs only a fairly small amount of code and can be written in a way that the USB details themselves are almost completely hidden. This code also allows operation of multiple USB-MSD LUMs (eg. on SD card, in internal Flash and or external SPI Flash). It is HW independent and runs on any KL, K or Coldfire V2 with USB.

The uTasker project allows the USB operation to be simulated using VisualStudio, including USB enumeration, USB interrupts, memory usage by USB etc. and so also enables easy understanding of the operations or aids in developing, testing and debuging additional code without HW complications. Problems can be analysed remotely and problem cases played back as scripts.

If your developments are for hobby or as a student assignment you may find that it will be an interesting excercise to analse the USB base that you have and rework it once you fully undertand it. If you are programming professionally I would look at proven and supported sources so that you don't need to invest time in solving fundamental problems and can complete your actual application/product development. If you don't think the uTasker project is suitable you can contact various USB stack manufacturers who can supply professional quality code with personal support so that you don't lose any time: See Micrium, Segger, MQX (USB stacks with or without File System support).

Regards

Mark

    while (fnMsgs(USBPortID_MSD) != 0) {                                 // handle USB-MSD host receptions
        if (ulWriteBlock != 0) {                                         // write data expected
            static unsigned char ucBuffer[512];                          // intermediate buffer to collect each sector content
            Length = fnRead(USBPortID_MSD, &ucBuffer[iContent], (QUEUE_TRANSFER)(512 - iContent)); // read the content directly to the intermediate buffer
            ulWriteBlock -= Length;
            iContent += Length;
            if (iContent >= 512) {                                       // input buffer is complete
                fnWriteSector(ucActiveLUN, ucBuffer, ulLogicalBlockAdr++); // commit the buffer content to the media
                iContent = 0;                                            // reset intermediate buffer
                if (ulWriteBlock != 0) {                                 // block not complete
                    uTaskerStateChange(OWN_TASK, UTASKER_ACTIVATE);      // {17} yield after a write when further data is expected but schedule again immediately to read any remaining queue content
                    return;
                }
            }
            if (ulWriteBlock != 0) {                                     // more data expected
                continue;
            }                                                            // allow CSW to be sent after a complete transfer has completed
        }
        else {
            USB_MASS_STORAGE_CBW *ptrCBW;
            Length = fnRead(USBPortID_MSD, ucInputMessage, LARGE_MESSAGE); // read the content
            ptrCBW = (USB_MASS_STORAGE_CBW *)ucInputMessage;
            uMemcpy(&csw.dCBWTag, ptrCBW->dCBWTag, sizeof(csw.dCBWTag)); // save the tag
            csw.dCSWDataResidue[0] = 0;
            csw.dCSWDataResidue[1] = 0;
            csw.dCSWDataResidue[2] = 0;
            csw.dCSWDataResidue[3] = 0;
            csw.bCSWStatus = CSW_STATUS_COMMAND_PASSED;                  // set for success
            fnFlush(USBPortID_MSD, FLUSH_TX);                            // always flush the tx buffer to ensure message alignment in buffer before responding
            ucActiveLUN = ptrCBW->dCBWLUN;                               // the logical unit number to use
            if (ptrCBW->dmCBWFlags & CBW_IN_FLAG) {
                switch (ptrCBW->CBWCB[CBW_OperationCode]) {
                case UFI_FORMAT_UNIT:
                    break;
                case UFI_INQUIRY:
                    {
                        CBW_INQUIRY_COMMAND *ptrInquiry = (CBW_INQUIRY_COMMAND *)ptrCBW->CBWCB;
                        unsigned char ucLogicalUnitNumber = (ptrInquiry->ucLogicalUnitNumber_EVPD >> 5); // the logical unit number being requested
                        QUEUE_TRANSFER inquiry_length;
                        unsigned char *ptrInquiryData = fnGetPartition(ucLogicalUnitNumber, &inquiry_length);
                        if (ptrInquiryData == 0) {                       // partition doesn't exist
                            csw.bCSWStatus = CSW_STATUS_COMMAND_FAILED;
                        }
                        else {
                            fnWrite(USBPortID_MSD, ptrInquiryData, inquiry_length); // respond to the request and then return 
                        }
                    }
                    break;
                case UFI_MODE_SENSE_6:                                   // {15}
                    {
                        MODE_PARAMETER_6 SelectDataWP;
                        uMemcpy(&SelectDataWP, &SelectData, sizeof(SelectData));
                        if (ptrDiskInfo[ucActiveLUN]->usDiskFlags & WRITE_PROTECTED_SD_CARD) {
                            SelectDataWP.ucWP_DPOFUA = PAR6_WRITE_PROTECTED; // the medium is write protected
                        }
                        fnWrite(USBPortID_MSD, (unsigned char *)&SelectDataWP, sizeof(SelectData)); // respond to the request and then return 
                    }
                    break;
                case UFI_START_STOP:
                case UFI_MODE_SELECT:
                case UFI_PRE_ALLOW_REMOVAL:
                    break;
                case UFI_READ_10:
                case UFI_READ_12:
                    {                                
                        CBW_READ_10 *ptrRead = (CBW_READ_10 *)ptrCBW->CBWCB;
                        if (ptrRead->ucOperationCode == UFI_READ_12) {
                            CBW_READ_12 *ptrRead = (CBW_READ_12 *)ptrCBW->CBWCB;
                            ulReadBlock = ((ptrRead->ucTransferLength[0] << 24) | (ptrRead->ucTransferLength[1] << 16) | (ptrRead->ucTransferLength[2] << 8) | ptrRead->ucTransferLength[3]);
                        }
                        else {
                            ulReadBlock = ((ptrRead->ucTransferLength[0] << 8) | ptrRead->ucTransferLength[1]); // the total number of blocks to be returned
                        }
                        fnContinueMedia();
                        continue;                                        // the transfer has not completed so don't send termination stage yet
                    }
                    break;
                case UFI_READ_CAPACITY:
                    {
                        CBW_READ_CAPACITY_DATA formatData;
                        unsigned long ulLastSector = (ptrDiskInfo[ucActiveLUN]->ulSD_sectors - 1);
                        formatData.ucBlockLengthInBytes[0] = 0;
                        formatData.ucBlockLengthInBytes[1] = 0;
                        formatData.ucBlockLengthInBytes[2] = (unsigned char)(ptrDiskInfo[ucActiveLUN]->utFAT.usBytesPerSector >> 8);
                        formatData.ucBlockLengthInBytes[3] = (unsigned char)(ptrDiskInfo[ucActiveLUN]->utFAT.usBytesPerSector);
                        formatData.ucLastLogicalBlockAddress[0] = (unsigned char)(ulLastSector >> 24);
                        formatData.ucLastLogicalBlockAddress[1] = (unsigned char)(ulLastSector >> 16);
                        formatData.ucLastLogicalBlockAddress[2] = (unsigned char)(ulLastSector >> 8);
                        formatData.ucLastLogicalBlockAddress[3] = (unsigned char)(ulLastSector);
                        fnWrite(USBPortID_MSD, (unsigned char *)&formatData, sizeof(formatData));
                    }
                    break;
                case UFI_READ_FORMAT_CAPACITY:
                    {
                        CBW_FORMAT_CAPACITIES *ptrCapacities = (CBW_FORMAT_CAPACITIES *)ptrCBW->CBWCB;
                        unsigned short usLengthAccepted = ((ptrCapacities->ucAllocationLength[0] << 8) | (ptrCapacities->ucAllocationLength[1]));
                        CBW_CAPACITY_LIST mediaCapacity;
                        uMemcpy(&mediaCapacity, &formatCapacityNoMedia, sizeof(CBW_CAPACITY_LIST)); // assume no disk
                        if (ptrDiskInfo[ucActiveLUN]->usDiskFlags & (DISK_MOUNTED | DISK_UNFORMATTED)) { // {16}
                            if (ptrDiskInfo[ucActiveLUN]->usDiskFlags & DISK_FORMATTED) {
                                mediaCapacity.capacityDescriptor.ucDescriptorCode = DESC_CODE_FORMATTED_MEDIA;
                            }
                            else {
                                mediaCapacity.capacityDescriptor.ucDescriptorCode = DESC_CODE_UNFORMATTED_MEDIA;
                            }
                            mediaCapacity.capacityDescriptor.ucNumberOfBlocks[3] = (unsigned char)ptrDiskInfo[ucActiveLUN]->ulSD_sectors;
                            mediaCapacity.capacityDescriptor.ucNumberOfBlocks[2] = (unsigned char)(ptrDiskInfo[ucActiveLUN]->ulSD_sectors >> 8);
                            mediaCapacity.capacityDescriptor.ucNumberOfBlocks[1] = (unsigned char)(ptrDiskInfo[ucActiveLUN]->ulSD_sectors >> 16);
                            mediaCapacity.capacityDescriptor.ucNumberOfBlocks[0] = (unsigned char)(ptrDiskInfo[ucActiveLUN]->ulSD_sectors >> 24);
                        }                                
                        if (usLengthAccepted > sizeof(CBW_CAPACITY_LIST)) {
                            usLengthAccepted = sizeof(CBW_CAPACITY_LIST);
                        }
                        fnWrite(USBPortID_MSD, (unsigned char *)&mediaCapacity, usLengthAccepted);
                    }
                    break;
                case UFI_REQUEST_SENSE:
                    {
                        CBW_RETURN_SENSE_DATA present_sense_data;
                        uMemcpy(&present_sense_data, &sense_data_OK, sizeof(sense_data_OK));
                        if ((ptrDiskInfo[ucActiveLUN]->usDiskFlags & (DISK_MOUNTED | DISK_UNFORMATTED)) == 0) {
                            present_sense_data.ucValid_ErrorCode = (CURRENT_ERRORS); // set that the disk is presently in a non-useable state
                            present_sense_data.ucSenseKey = SENSE_NOT_READY;
                            present_sense_data.ucAdditionalSenseCode = DESC_MEDIUM_NOT_PRESENT;
                        }
                        fnWrite(USBPortID_MSD, (unsigned char *)&present_sense_data, sizeof(present_sense_data));
                    }
                    break;
                case UFI_REZERO_UNIT:
                case UFI_SEEK_10:
                case UFI_SEND_DIAGNOSTIC:
                case UFI_VERIFY:
                case UFI_WRITE_AND_VERIFY:
                default:
                    break;
                }
            }
            else {                                                       // OUT types
                switch (ptrCBW->CBWCB[CBW_OperationCode]) {
                case UFI_TEST_UNIT_READY:
                    if ((ptrDiskInfo[ucActiveLUN]->usDiskFlags & (DISK_MOUNTED | DISK_UNFORMATTED)) == 0) { // if the partition is not ready
                        csw.bCSWStatus = CSW_STATUS_COMMAND_FAILED;
                    }
                    break;
                case UFI_WRITE_10:
                case UFI_WRITE_12:
                    {
                        CBW_WRITE_10 *ptrWrite = (CBW_WRITE_10 *)ptrCBW->CBWCB;
                        if (ptrWrite->ucOperationCode == UFI_WRITE_12) {
                            CBW_WRITE_12 *ptrWrite = (CBW_WRITE_12 *)ptrCBW->CBWCB;
                            ulWriteBlock = ((ptrWrite->ucTransferLength[0] << 24) | (ptrWrite->ucTransferLength[1] << 16) | (ptrWrite->ucTransferLength[2] << 8) | ptrWrite->ucTransferLength[3]);
                        }
                        else {
                            ulWriteBlock = ((ptrWrite->ucTransferLength[0] << 8) | ptrWrite->ucTransferLength[1]); // the total number of blocks to be returned
                        }
                        ulWriteBlock *= 512;                             // convert to byte count
                    }
                    continue;                                            // data will follow so don't reply with CSW stage yet
                }
            }
        }
        fnWrite(USBPortID_MSD, (unsigned char *)&csw, sizeof(csw));      // close with CSW stage
    }