lyjunnan 发表于 2021-10-15 16:24:45

STM32的USB主机读取STM32的USB从机的文件

项目描述:使用STM32的USB主机设备连接STM32的USB从机设备,都是大容量存储类设备,并且都移植了FATFS文件操作系统
目前实现了主机外接U盘可以成功枚举并且正常读写文件,从机接上电脑也可成功枚举且正常读写文件,但是主机接从机时,显示枚举成功,但是获取不到从机的容量(通过FATFS提供的API)与读写文件(通过FATFS提供的API),在枚举成功后挂载从机文件系统返回FR_DISK_ERR,这一块应该是代码的问题,但是没法确定问题的所在,求教大神指点一二,谢谢

eric2013 发表于 2021-10-16 09:24:03

从机不用加FatFS。

lyjunnan 发表于 2021-10-17 20:27:24

eric2013 发表于 2021-10-16 09:24
从机不用加FatFS。

目前这个产品中从机是主要设备,运行过程中会使用文件系统读取配置文件与字库文件,所以必须使用文件系统,而主机只是作为生产的工装模块来用,不会量产,只是给从机传递配置文件与字库文件的。。。目前缺芯状况太严重了,只能使用国产替代了,而这个替代的芯片的USB只有从机功能,所以只能这样来搞。。。
如果从机不用文件系统,是否可以被主机识别并正常读写文件,你这边之前有没有做过这样的测试,还请指点一二

eric2013 发表于 2021-10-18 15:27:21

lyjunnan 发表于 2021-10-17 20:27
目前这个产品中从机是主要设备,运行过程中会使用文件系统读取配置文件与字库文件,所以必须使用文件系统 ...

方便的话,我看下你的USB接口文件实现,仅接口文件实现。

lyjunnan 发表于 2021-10-19 13:59:09

eric2013 发表于 2021-10-18 15:27
方便的话,我看下你的USB接口文件实现,仅接口文件实现。

主机芯片用的是STM32F105RBT6, 从机用的是国产的一款M4内核的但是USB只有从机的芯片,为了改善SPI Flash的写入速度,在文件系统与USB的几个地方做了修改
ffconfig.h
#define        _MIN_SS                512
#define        _MAX_SS                4096
diskiio.c
#define FLASH_SECTOR_SIZE   4096
#define FLASH_BLOCK_SIZE    16                
#define FLASH_SECTOR_COUNT1024               
DRESULT disk_read(
    BYTE pdrv,      /* Physical drive nmuber (0..) */
    BYTE *buff,   /* Data buffer to store read data */
    DWORD sector,   /* Sector address (LBA) */
    UINT count      /* Number of sectors to read (1..128) */
)
{
    u8 res = 0;
    if(!count)return RES_PARERR; //count不能等于0,否则返回参数错误
    switch(pdrv)
    {
    case FLASH_1:                        //外部flash0
      for(; count > 0; count--)
      {
            W25QXX_Read(buff, sector * FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE, 1);
            sector++;
            buff += FLASH_SECTOR_SIZE;
      }
      res = 0;
      break;
    case FLASH_2:                        //内部flash1
      for(; count > 0; count--)
      {
            W25QXX_Read(buff, sector * FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE, 2);
            sector++;
            buff += FLASH_SECTOR_SIZE;
      }
      res = 0;
      break;
    case USB_DISK:
      res = USBH_UDISK_Read((u8*)buff, sector, count);
      break;
    default:
      res = 1;
    }
    //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
    if(res == 0x00)return RES_OK;
    else return RES_ERROR;
}
//读写函数参数一样
#if _USE_IOCTL
DRESULT disk_ioctl(
    BYTE pdrv,      /* Physical drive nmuber (0..) */
    BYTE cmd,       /* Control code */
    void *buff      /* Buffer to send/receive control data */
)
{
    DRESULT res;
    if(pdrv == FLASH_1) //外部FLASH0
    {
      switch(cmd)
      {
                        case CTRL_SYNC:
                                res = RES_OK;
                                break;
                        case GET_SECTOR_SIZE:
                                *(WORD*)buff = FLASH_SECTOR_SIZE;
                                res = RES_OK;
                                break;
                        case GET_BLOCK_SIZE:
                                *(WORD*)buff = FLASH_BLOCK_SIZE;
                                res = RES_OK;
                                break;
                        case GET_SECTOR_COUNT:
                                *(DWORD*)buff = FLASH_SECTOR_COUNT;
                                res = RES_OK;
                                break;
                        default:
                                res = RES_PARERR;
                                break;
      }
    }
    else if(pdrv == FLASH_2)//外部FLASH1
    {
      switch(cmd)
      {
                        case CTRL_SYNC:
                                res = RES_OK;
                                break;
                        case GET_SECTOR_SIZE:
                                *(WORD*)buff = FLASH_SECTOR_SIZE;
                                res = RES_OK;
                                break;
                        case GET_BLOCK_SIZE:
                                *(WORD*)buff = FLASH_BLOCK_SIZE;
                                res = RES_OK;
                                break;
                        case GET_SECTOR_COUNT:
                                *(DWORD*)buff = FLASH_SECTOR_COUNT;
                                res = RES_OK;
                                break;
                        default:
                                res = RES_PARERR;
                                break;
      }
    }
    else if(pdrv == USB_DISK)
    {
      switch(cmd)
      {
                        case CTRL_SYNC:
                                res = RES_OK;
                                break;
                        case GET_SECTOR_SIZE:
                                *(WORD*)buff = 4096;
                                res = RES_OK;
                                break;
                        case GET_BLOCK_SIZE:
                                *(WORD*)buff = 4096;
                                res = RES_OK;
                                break;
                        case GET_SECTOR_COUNT:
                                *(DWORD*)buff = (DWORD) USBH_MSC_Param.MSCapacity;
                                res = RES_OK;
                                break;
                        default:
                                res = RES_PARERR;
                                break;
      }
    }
    else res = RES_ERROR; //其他的不支持
    return res;
}
usbh_msc_usr.c
void USBH_USR_DeInit(void)
{
        USBH_USR_ApplicationState = USH_USR_FS_INIT;
}

extern USBH_HOST                USB_Host;
uint8_t USBH_UDISK_Status(void)
{
        return HCD_IsDeviceConnected((USB_OTG_CORE_HANDLE*)&USB_OTG_Core);
}
uint8_t USBH_UDISK_Read(uint8_t *buf, uint32_t sector, uint32_t cnt)
{
        u8 res = 1;
        if(HCD_IsDeviceConnected((USB_OTG_CORE_HANDLE*)&USB_OTG_Core) )
        {
                do
                {
                        res = USBH_MSC_Read10((USB_OTG_CORE_HANDLE*)&USB_OTG_Core, buf, sector, 4096 * cnt);
                        USBH_MSC_HandleBOTXfer((USB_OTG_CORE_HANDLE*)&USB_OTG_Core ,&USB_Host);
                  
                        if(!HCD_IsDeviceConnected((USB_OTG_CORE_HANDLE*)&USB_OTG_Core))
                        {
                                res = 1;
                                break;
                        }      
                }
                while(res == USBH_MSC_BUSY );
        }else res = 1;

        if(res == USBH_MSC_OK)
                res = 0;
        return res;
}
uint8_t USBH_UDISK_Write(uint8_t* buf,uint32_t sector,uint32_t cnt)
{
        uint8_t res=1;
        if(HCD_IsDeviceConnected((USB_OTG_CORE_HANDLE*)&USB_OTG_Core))//连接还存在,且是APP测试状态
        {                  
                do
                {
                        res=USBH_MSC_Write10((USB_OTG_CORE_HANDLE*)&USB_OTG_Core,buf,sector, 4096 * cnt);
                        USBH_MSC_HandleBOTXfer((USB_OTG_CORE_HANDLE*)&USB_OTG_Core ,&USB_Host);                     
                        if(!HCD_IsDeviceConnected((USB_OTG_CORE_HANDLE*)&USB_OTG_Core))
                        {
                                res=1;
                                break;
                        };   
                }while(res==USBH_MSC_BUSY);
        }else res=1;                  
        if(res==USBH_MSC_OK)res=0;       
        return res;
}
usb_host处理函数的一部分
void USB_Application(void)
{
    uint8_t res = 1;
        uint32_t total, free;
        uint8_t file = 1;
        uint8_t sta = 0;
        if(Enum_Done == 1)
        {               
                delay_ms(10);
                res = exf_get_free("2:", &total, &free);
                SEGGER_RTT_SetTerminal(2);
                SEGGER_RTT_printf(0, "> Rrturn exf_get_free is :%d\r\n", res);
                if(res == 0)
                {       
                        /* 检测到磁盘并可以正常获取磁盘状态,LED常亮 */
                        led_toggle_flag = DISABLE;
                        led_on();
                        SEGGER_RTT_SetTerminal(2);
                        SEGGER_RTT_printf(0, "> U Disk FATFS OK!\r\n");
                        SEGGER_RTT_printf(0, "> U Disk Total Size: %d KB\r\n", total);
                        SEGGER_RTT_printf(0, "> U Disk Total Size: %d KB\r\n", free);
                       
                        exf_scan_files("2:");       
                }
         }


从机文件系统和主机差不多,USB这是修改了mass_mal.c中的这个函数
uint16_t MAL_GetStatus (uint8_t lun)
{
    switch(lun)
    {
                case 0:
                        Mass_Memory_Size = 1024 * 1024 * 4;        //4M字节
                        Mass_Block_Size = 4096;                        //设置SPI FLASH的操作扇区大小为4096
                        Mass_Block_Count= Mass_Memory_Size / Mass_Block_Size;
            break;
                default:
                        return MAL_FAIL;
    }
    return MAL_OK;
}
目前有点进展,主机插上从机偶尔会正常检索从机的文件,有时又不正常
不正常的情况就是在主机处理程序获取从机磁盘容量那一块 res = exf_get_free("2:", &total, &free);,返回值1(FR_DISK_ERR),查了FATFS官网有如下说明
C:\Users\Administrator\Desktop\1.jpg

eric2013 发表于 2021-10-20 10:30:40

lyjunnan 发表于 2021-10-19 13:59
主机芯片用的是STM32F105RBT6, 从机用的是国产的一款M4内核的但是USB只有从机的芯片,为了改善SPI Flash ...

exf_get_free是你自己封装的函数吧,fatfs没有这个函数。

你应该封装的是f_getfree

lyjunnan 发表于 2021-10-21 13:42:04

eric2013 发表于 2021-10-20 10:30
exf_get_free是你自己封装的函数吧,fatfs没有这个函数。

你应该封装的是f_getfree

是的,调用f_mount也是一样的情况

eric2013 发表于 2021-10-22 09:50:56

lyjunnan 发表于 2021-10-21 13:42
是的,调用f_mount也是一样的情况

别的问题,不清楚了。
页: [1]
查看完整版本: STM32的USB主机读取STM32的USB从机的文件