/** ************************************************************************** * @file msc_diskio.c * @version v2.1.1 * @date 2022-07-22 * @brief usb mass storage disk function ************************************************************************** * Copyright notice & Disclaimer * * The software Board Support Package (BSP) that is made available to * download from Artery official website is the copyrighted work of Artery. * Artery authorizes customers to use, copy, and distribute the BSP * software and its related documentation for the purpose of design and * development in conjunction with Artery microcontrollers. Use of the * software is governed by this copyright notice and the following disclaimer. * * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. * ************************************************************************** */ #include #include "msc_diskio.h" #include "msc_bot_scsi.h" #include "W25Q128.h" #define MountDisk 0 //============================================================================== // //============================================================================== void flash_read(uint32_t read_addr, uint8_t *p_buffer, uint16_t num_read) { uint16_t i; for(i = 0; i < num_read; i++) { p_buffer[i] = *(uint8_t*)(read_addr); read_addr += 1; } } uint8_t flash_write(uint32_t write_addr, uint8_t *p_buffer, uint16_t num_Write) { uint32_t idx = 0; flash_status_type status = FLASH_OPERATE_DONE; flash_unlock(); status = flash_sector_erase(write_addr ); // 2K Erase if(status != FLASH_OPERATE_DONE) return 0; status = flash_sector_erase(write_addr + 0x800); // 2K Erase if(status != FLASH_OPERATE_DONE) return 0; for(idx = 0; idx < num_Write; idx += 4) { status = flash_word_program((uint32_t)(write_addr + idx), *((uint32_t *)(p_buffer+idx))); if(status != FLASH_OPERATE_DONE) return 0; } flash_lock(); return 1; } //============================================================================== /** @addtogroup AT32F415_periph_examples * @{ */ char strSignature[] = "RYAN"; iap_struct_type* pIAP; iap_struct_type IAP = {0,}; iap_info_struct_type DL_Info = {{'R','Y','A','N'},0,}; iap_state_machine IAP_CURR_STATE = IAP_STATE_IDEL; /** @addtogroup 415_USB_device_msc * @{ */ uint32_t sector_size = 2048; uint32_t msc_flash_size; uint8_t scsi_inquiry[MSC_SUPPORT_MAX_LUN][SCSI_INQUIRY_DATA_LENGTH] = { /* lun = 0 */ { 0x00, /* peripheral device type (direct-access device) */ 0x80, /* removable media bit */ 0x00, /* ansi version, ecma version, iso version */ 0x00, /* respond data format */ SCSI_INQUIRY_DATA_LENGTH - 5, /* additional length */ 0x00, 0x00, 0x00, /* reserved */ 'D', '.', 'R', 'y', 'a', 'n', ' ', ' ', /* vendor information "AT32" */ 'I', 'A', 'P', ' ', 'D', 'e', 'v', 'i', 'c', 'e', ' ', ' ', ' ', ' ', ' ', ' ', /* Product identification "Disk" */ '1', '.', '0', '0' /* product revision level */ } }; /** * @brief get disk inquiry * @param lun: logical units number * @retval inquiry string */ uint8_t *get_inquiry(uint8_t lun) { if(lun < MSC_SUPPORT_MAX_LUN) return (uint8_t *)scsi_inquiry[lun]; else return NULL; } /** * @brief disk read * @param lun: logical units number * @param addr: logical address * @param read_buf: pointer to read buffer * @param len: read length * @retval status of usb_sts_type */ int8_t msc_disk_read(uint8_t lun, uint32_t addr, uint8_t *read_buf, uint32_t len) { uint8_t *Address; uint8_t buff[32]; switch(lun) { case 0: #if MountDisk flash_spi_read(read_buf,addr,len); #else if(addr == 0x00000000) { switch(IAP.cmd[0]) { case UFI_MODE_GET_VERSION: Address = (uint8_t*)0x08008400; memcpy(buff,Address,32); if( strcmp((const char *)buff,"SLL_SR80\x00")!= 0) { memcpy((void *)&buff[0],"SLL_SR80\x00",9); memcpy((void *)&buff[16],"None\x00",5); } memcpy(read_buf,buff,32); IAP.cmd[0] = UFI_MODE_NORMAL; break; case UFI_MODE_NORMAL: default: memset(read_buf,0xFF,len); break; } } else if((addr >= 0x00108000)&&(addr < 0x00140000)) { if(IAP_CURR_STATE == IAP_STATE_VERIFY_PACKET) { flash_read(addr-0x00100000,read_buf,len); } else memset(read_buf,0xFF,len); } else if(addr >= 0x01000000) { if(IAP_CURR_STATE == IAP_STATE_VERIFY_PACKET) { // flash_spi_read(read_buf,addr-0x01000000,len); W25Q128_Read(read_buf,addr-0x01000000,len); } else memset(read_buf,0xFF,len); } else memset(read_buf,0xFF,len); #endif break; case 1: break; } return USB_OK; } /** * @brief disk write * @param lun: logical units number * @param addr: logical address * @param buf: pointer to write buffer * @param len: write length * @retval status of usb_sts_type */ int8_t msc_disk_write(uint8_t lun, uint32_t addr, uint8_t *buf, uint32_t len) { // char str[20] = {0}; // uint8_t Percentage; uint16_t FileType; switch(lun) { case 0: #if MountDisk // flash_spi_write(buf,addr,len); W25Q128_WriteSector_4K(buf,addr,len); #else if(addr == 0x00000000) { pIAP = (iap_struct_type*)buf; if(strcmp((const char*)pIAP->header,strSignature) == 0x00) { memcpy(IAP.header,buf,8); switch(IAP.cmd[0]) { case UFI_MODE_SET_INFO: //LCD_Text(0,48,"CID: ",true,TFT_WHITE, TFT_BLACK,0xFF); pIAP->pdata[12] = 0; //LCD_Text(60,48,(const char*)pIAP->pdata,true,TFT_WHITE, TFT_BLACK,0xFF); break; case UFI_MODE_DOWN_INFO: // �������� 1 iFlash, 2 eFlash //LCD_Fill(0,72,TFT_WIDTH,TFT_HEIGHT,TFT_BLACK);//���� FileType = *(uint16_t*)&pIAP->pdata[0]; if(FileType == 1) { // LCD_Text(0,72,"FW Upgrade ",true,TFT_WHITE, TFT_BLACK,0xFF); // // Size // DL_Info.iFileSize = *(uint32_t*)&pIAP->pdata[4]; // sprintf(str,"Size : %dK", DL_Info.iFileSize/1024); // LCD_Text(0,96,str,true,TFT_WHITE, TFT_BLACK,0xFF); // // CRC // DL_Info.iFileCRC = *(uint16_t*)&pIAP->pdata[2]; // sprintf(str,"CRC : 0x%04X", DL_Info.iFileCRC); // LCD_Text(0,120,str,true,TFT_WHITE, TFT_BLACK,0xFF); // // PCnt // DL_Info.iFilePacket = *(uint32_t*)&pIAP->pdata[8]; } if(FileType == 2) { // LCD_Text(0,72,"RES Upgrade ",true,TFT_WHITE, TFT_BLACK,0xFF); // // Size // DL_Info.eFileSize = *(uint32_t*)&pIAP->pdata[4]; // sprintf(str,"Size : %dK", DL_Info.eFileSize/1024); // LCD_Text(0,96,str,true,TFT_WHITE, TFT_BLACK,0xFF); // // CRC // DL_Info.eFileCRC = *(uint16_t*)&pIAP->pdata[2]; // sprintf(str,"CRC : 0x%04X", DL_Info.eFileCRC); // LCD_Text(0,120,str,true,TFT_WHITE, TFT_BLACK,0xFF); // // PCnt // DL_Info.eFilePacket = *(uint32_t*)&pIAP->pdata[8]; } IAP_CURR_STATE = IAP_STATE_DOWNLOAD_PACKET; break; case UFI_MODE_DOWN_ABORT: // ȡ������ break; case UFI_MODE_DOWN_FINISH: // �������� IAP_CURR_STATE = IAP_STATE_IDEL; break; case UFI_MODE_DOWN_VERIFY: // У�� FLASH IAP_CURR_STATE = IAP_STATE_VERIFY_PACKET; break; case UFI_MODE_REBOOT: IAP_CURR_STATE = IAP_STATE_REBOOT; break; } } else { // ���� format Disk 0 �ŵ�д�� return USB_FAIL; } } else if((addr >= 0x00108000)&&(addr < 0x00140000)) { if(IAP_CURR_STATE == IAP_STATE_DOWNLOAD_PACKET) { if(addr == 0x00108000) { // LCD_Text(0,168,"FW DL ",true,TFT_WHITE, TFT_BLACK,0xFF); // LCD_drawRoundRect(16,200,208,24,5,TFT_WHITE); // // LCD_fillRoundRect(20,178,200,20,5,TFT_WHITE);//���� // LCD_TextCenter(228,"0%",true,TFT_WHITE, TFT_BLACK,0xFF); } else { // Percentage = ((addr - 0x00108000) / 4096) * 100 / (DL_Info.iFilePacket-1); // sprintf(str,"%d%%", Percentage); // LCD_fillRoundRect(20,204,2*Percentage,16,5,TFT_WHITE);//���� // LCD_TextCenter(228,str,true,TFT_WHITE, TFT_BLACK,0xFF); } flash_write( 0x08000000 + (addr - 0x00100000),buf,len); } } else if((addr >= 0x01000000)&&(addr < 0x02000000)) { if(IAP_CURR_STATE == IAP_STATE_DOWNLOAD_PACKET) { if(addr == 0x01000000) { // LCD_Text(0,168,"RES DL ",true,TFT_WHITE, TFT_BLACK,0xFF); // LCD_drawRoundRect(16,200,208,24,5,TFT_WHITE); // // LCD_fillRoundRect(20,178,200,20,5,TFT_WHITE);//���� // LCD_TextCenter(228,"0%",true,TFT_WHITE, TFT_BLACK,0xFF); } else { // Percentage = ((addr - 0x01000000) / 4096) * 100 / (DL_Info.eFilePacket-1); // sprintf(str,"%d%%", Percentage); // LCD_fillRoundRect(20,204,2*Percentage,16,5,TFT_WHITE);//���� // LCD_TextCenter(228,str,true,TFT_WHITE, TFT_BLACK,0xFF); } // flash_spi_write(buf,(addr-0x01000000),len); W25Q128_Erase_Sector((addr-0x01000000)); W25Q128_Write(buf,(addr-0x01000000),len); } } #endif break; case 1: break; } return USB_OK; } /** * @brief disk capacity * @param lun: logical units number * @param blk_nbr: pointer to number of block * @param blk_size: pointer to block size * @retval status of usb_sts_type */ int8_t msc_disk_capacity(uint8_t lun, uint32_t *blk_nbr, uint32_t *blk_size) { switch(lun) { case 0: #if MountDisk /* 普通 U 盘模式:直接把 W25Q128 (16MB) 挂出来 */ *blk_nbr = (uint32_t)(0x01000000 / 0x1000); *blk_size = 0x1000; #else /* IAP 虚拟磁盘模式 (32MB): - 0x00000000 : 命令/信息块 (RYAN 签名) - 0x00100000~0x00140000 : 固件区 -> 内部 flash 0x08000000+ - 0x01000000~0x02000000 : 资源区 -> W25Q128 0x00000000+ 容量必须覆盖到资源区末端 0x01FFFFFF,故取 0x02000000 */ *blk_nbr = (uint32_t)(0x02000000 / 0x1000); *blk_size = 0x1000; #endif break; default: break; } return USB_OK; } /** * @} */ /** * @} */