378 lines
12 KiB
C
378 lines
12 KiB
C
/**
|
||
**************************************************************************
|
||
* @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;
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @}
|
||
*/
|