K1Guitar/AT32F403ARCT7_BOOT/project/src/msc_diskio.c

378 lines
12 KiB
C
Raw Normal View History

/**
**************************************************************************
* @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 <string.h>
#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:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 iFlash, 2 eFlash
//LCD_Fill(0,72,TFT_WIDTH,TFT_HEIGHT,TFT_BLACK);//<2F><><EFBFBD><EFBFBD>
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:
// ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
break;
case UFI_MODE_DOWN_FINISH:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IAP_CURR_STATE = IAP_STATE_IDEL;
break;
case UFI_MODE_DOWN_VERIFY:
// У<><D0A3> FLASH
IAP_CURR_STATE = IAP_STATE_VERIFY_PACKET;
break;
case UFI_MODE_REBOOT:
IAP_CURR_STATE = IAP_STATE_REBOOT;
break;
}
}
else
{
// <20><><EFBFBD><EFBFBD> format Disk 0 <20>ŵ<EFBFBD>д<EFBFBD><D0B4>
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);//<2F><><EFBFBD><EFBFBD>
// 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);//<2F><><EFBFBD><EFBFBD>
// 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);//<2F><><EFBFBD><EFBFBD>
// 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);//<2F><><EFBFBD><EFBFBD>
// 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;
}
/**
* @}
*/
/**
* @}
*/