14、USBH HOST对接RTT系统(CDC+MSC)

USBH HOST对接RTT

将USBH host注册到RTT中需要进行以下几步.

  1. 实现设备驱动
  2. 设备注册.

1.1 CDC设备实现

1.1.1 CDC类实现思路

官方驱动修改思路.

  1. 将CDC类中的状态机一直置为接收状态.
  2. 接收完成后,通过USBH_CDC_ReceiveCallback函数通知上层应用.

设备实现思路.

  1. 通过官方提供的接收回调函数将接收到的数据存放到ringbuf内,用户可通过rt_device_read接口调用usbh_cdc_class_read函数读取缓冲区内容.
  2. 发送时指定发送数据,直接发送指定数据(无缓冲区).如有需要,可将发送数据存入指定缓冲区,然后创建一个线程用于发送.

1.1.2 CDC类驱动文件修改

修改usbh_cdc.c文件中的CDC_ProcessReception函数为如下所示.

static void CDC_ProcessReception(USBH_HandleTypeDef *phost)
{

    CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData[USBH_CDC_INDEX];
    USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
    switch(CDC_Handle->data_rx_state)
    {

    case CDC_RECEIVE_DATA:
        USBH_BulkReceiveData(phost,
                             CDC_Handle->pRxData,
                             CDC_Handle->DataItf.InEpSize,
                             CDC_Handle->DataItf.InPipe);

        CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT;

        break;

    case CDC_RECEIVE_DATA_WAIT:

        URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.InPipe);

        /*Check the status done for reception*/
        if(URB_Status == USBH_URB_DONE)
        {
            USBH_CDC_ReceiveCallback(phost);
            CDC_Handle->data_rx_state = CDC_RECEIVE_DATA;
        }

        break;

    default:
        break;
    }
}

1.1.3 CDC类设备文件实现

实现usbh_cdc_device.h.

#ifndef __USBH_CDC_DEVICE__H__
#define __USBH_CDC_DEVICE__H__

#include "usbh_core.h"

#define USBH_CDC_NAME	"USBH_CDC"


#define CDC_RX_BUFSIZE 256


#define CDC_DEVICE_CMD_GET_SPCAE_LEN 	(0X0100)
#define CDC_DEVICE_CMD_GET_DATA_LEN		(0X0200)
#define CDC_DEVICE_CMD_BUF_RESET		(0X0400)
#define CDC_DEVICE_CMD_GET_DEV_STATE	(0X0800)
#define CDC_DEVICE_CMD_START_RECV		(0X1000)
#define CDC_DEVICE_CMD_MASK				(CDC_DEVICE_CMD_START_RECV | CDC_DEVICE_CMD_GET_SPCAE_LEN | CDC_DEVICE_CMD_GET_DATA_LEN | CDC_DEVICE_CMD_BUF_RESET)


struct rt_cdc_device
{
    struct rt_device device;

    struct rt_ringbuffer rx_ringbuffer;

    uint8_t *p_rx_buf;
};
typedef struct rt_cdc_device *rt_cdc_device_t;

rt_cdc_device_t cdc_device_creat(void);
#endif

实现usbh_cdc_device.c.

#include "usbh_cdc_device.h"
#include "usbh_cdc.h"

extern USBH_HandleTypeDef hUsbHostHS;

static rt_err_t usbh_cdc_class_open(rt_device_t dev, rt_uint16_t oflag);
static rt_err_t usbh_cdc_class_close(rt_device_t dev);
static rt_size_t usbh_cdc_class_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
static rt_size_t usbh_cdc_class_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
static rt_err_t usbh_cdc_class_control(rt_device_t dev, int cmd, void *args);

static rt_cdc_device_t  cdc_device_t = RT_NULL;
rt_cdc_device_t cdc_device_creat()
{
    rt_err_t result = RT_EOK;

    cdc_device_t = rt_malloc(sizeof(struct rt_cdc_device));

    if(cdc_device_t == NULL)
    {
        USBH_ErrLog("cdc device init failed");
        rt_free(cdc_device_t);
        return RT_NULL;
    }

    rt_memset(cdc_device_t, 0, sizeof(struct rt_cdc_device));

    cdc_device_t->device.parent.type = RT_Object_Class_Device;
    cdc_device_t->device.type = RT_Device_Class_Char;
    cdc_device_t->device.open = usbh_cdc_class_open;
    cdc_device_t->device.close = usbh_cdc_class_close;
    cdc_device_t->device.write = usbh_cdc_class_write;
    cdc_device_t->device.read = usbh_cdc_class_read;
    cdc_device_t->device.control = usbh_cdc_class_control;

    result = rt_device_register(&(cdc_device_t->device), USBH_CDC_NAME, RT_DEVICE_FLAG_RDWR);

    if(result != RT_EOK)
    {
        USBH_DbgLog("cdc device register failed");
        rt_free(cdc_device_t);
        return RT_NULL;
    }

    USBH_DbgLog("cdc device init ok");

    return cdc_device_t;
}

static rt_err_t usbh_cdc_class_open(rt_device_t dev, rt_uint16_t oflag)
{
    rt_cdc_device_t cdc_handler = (rt_cdc_device_t)dev;
    cdc_handler->p_rx_buf = rt_malloc(CDC_RX_BUFSIZE);

    if(cdc_handler->p_rx_buf == NULL)
    {
        return RT_ENOMEM;
    }

    USBH_memset(cdc_handler->p_rx_buf, 0, CDC_RX_BUFSIZE);
    rt_ringbuffer_init(&(cdc_handler->rx_ringbuffer), cdc_handler->p_rx_buf, CDC_RX_BUFSIZE);

	USBH_CDC_Receive(&hUsbHostHS, NULL, 128);

    return RT_EOK;
}
static rt_err_t usbh_cdc_class_close(rt_device_t dev)
{
    rt_cdc_device_t cdc_handler = (rt_cdc_device_t)dev;

    if(cdc_handler->p_rx_buf)
        rt_free(cdc_handler->p_rx_buf);

    cdc_handler->p_rx_buf = RT_NULL;

    rt_ringbuffer_reset(&cdc_handler->rx_ringbuffer);
	
	USBH_Stop(&hUsbHostHS);
    return RT_EOK;
}

static rt_size_t usbh_cdc_class_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
    extern USBH_StatusTypeDef  USBH_CDC_Transmit(USBH_HandleTypeDef * phost, uint8_t * buf, uint32_t length);
	USBH_CDC_Stop(&hUsbHostHS);
    if(USBH_CDC_Transmit(&hUsbHostHS, (uint8_t *)buffer, size) == RT_EOK)
        return size;

    return 0;
}
void USBH_CDC_TransmitCallback(USBH_HandleTypeDef *phost)
{
	if(cdc_device_t)
		rt_device_control(&(cdc_device_t->device),CDC_DEVICE_CMD_START_RECV,NULL);
}
void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef * phost)
{
    extern CDC_HandleTypeDef usbh_cdc_handler;
    uint32_t len = USBH_CDC_GetLastReceivedDataSize(phost);

    if(len)
    {
        rt_ringbuffer_put(&(cdc_device_t->rx_ringbuffer), usbh_cdc_handler.pRxData, len);

        cdc_device_t->device.rx_indicate((rt_device_t)cdc_device_t, len);
    }
}

static rt_size_t usbh_cdc_class_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
    rt_cdc_device_t cdc_handler = (rt_cdc_device_t)dev;

    if(rt_ringbuffer_get(&(cdc_handler->rx_ringbuffer), buffer, size) == size)
        return size;
    else
        return 0;
}

static rt_err_t usbh_cdc_class_control(rt_device_t dev, int cmd, void *args)
{
    extern CDC_HandleTypeDef usbh_cdc_handler;

    rt_cdc_device_t cdc_handler = (rt_cdc_device_t)dev;
    uint32_t *len = (uint32_t *)args;
    struct rt_ringbuffer *p_ringbuf = NULL;
    rt_err_t status = RT_EOK;
    p_ringbuf = &(cdc_handler->rx_ringbuffer);

    switch(cmd & 0XFF00)
    {
    case CDC_DEVICE_CMD_BUF_RESET:
        rt_ringbuffer_reset(p_ringbuf);
        break;

    case CDC_DEVICE_CMD_GET_SPCAE_LEN:
        *len = rt_ringbuffer_space_len(p_ringbuf);
        break;

    case CDC_DEVICE_CMD_GET_DATA_LEN:
        *len = rt_ringbuffer_data_len(p_ringbuf);
        break;

    case CDC_DEVICE_CMD_GET_DEV_STATE:
        break;

    case CDC_DEVICE_CMD_START_RECV:
        USBH_CDC_Stop(&hUsbHostHS);
        USBH_CDC_Receive(&hUsbHostHS, NULL, 64);
        USBH_DbgLog("start recv");
    default:
        status = RT_EINVAL;
        break;
    }

    return status;
}

2.1 MSC类设备驱动实现

2.1.1 MSC类设备实现思路

沿用ST官方例程,在此基础上模仿SPI_FLASH,SD卡的设备驱动即可.

2.1.2 MSC类设备实现

msc类不需要对底层驱动进行修改,专注于设备层功能实现即可.

添加usbh_msc_device.c文件如下所示.

#include "usbh_msc_device.h"
#include "usbh_msc.h"

extern USBH_HandleTypeDef hUsbHostHS;
#define USB_DEFAULT_BLOCK_SIZE 512

static struct rt_msc_device msc_device_handler;
static rt_err_t usbh_msc_class_init(rt_device_t dev);
static rt_err_t usbh_msc_class_close(rt_device_t dev);
static rt_size_t usbh_msc_class_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
static rt_size_t usbh_msc_class_read(rt_device_t dev, rt_off_t pos,  void *buffer, rt_size_t size);
static rt_err_t usbh_msc_class_control(rt_device_t dev, int cmd, void *args);
rt_msc_device_t msc_device_init()
{
    rt_err_t result = RT_EOK;

    rt_memset(&msc_device_handler, 0, sizeof(struct rt_msc_device));

    msc_device_handler.dev.init    = usbh_msc_class_init;
    msc_device_handler.dev.close   = usbh_msc_class_close;
    msc_device_handler.dev.write   = usbh_msc_class_write;
    msc_device_handler.dev.read    = usbh_msc_class_read;
    msc_device_handler.dev.control = usbh_msc_class_control;

    if(result != RT_EOK)
    {
        USBH_ErrLog("msc device sem failed");
    }

    result = rt_device_register(&(msc_device_handler.dev), USBH_MSC_NAME, RT_DEVICE_FLAG_RDWR);

    if(result != RT_EOK)
    {
        USBH_ErrLog("msc device register failed");
        return NULL;
    }

    return &msc_device_handler;
}

static rt_err_t usbh_msc_class_close(rt_device_t dev)
{
    return RT_EOK;
}

static rt_err_t usbh_msc_class_init(rt_device_t dev)
{
    return RT_EOK;
}
static rt_size_t usbh_msc_class_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
    uint8_t lun;
    MSC_LUNTypeDef info;
    rt_err_t res = RT_ERROR;

    RT_ASSERT(dev != RT_NULL);
    RT_ASSERT(buffer != RT_NULL);

    lun = USBH_MSC_GetCurLUN(&hUsbHostHS);

//    rt_enter_critical();

    if(USBH_MSC_Write(&hUsbHostHS, lun, pos, (uint8_t *)buffer, size) == USBH_OK)
    {
        res = size;
    }
    else
    {
        USBH_MSC_GetLUNInfo(&hUsbHostHS, lun, &info);

        switch(info.sense.asc)
        {
        case SCSI_ASC_WRITE_PROTECTED:
            USBH_ErrLog("USB Disk is Write protected!");
            res = -RT_EBUSY;
            break;

        case SCSI_ASC_LOGICAL_UNIT_NOT_READY:
        case SCSI_ASC_MEDIUM_NOT_PRESENT:
        case SCSI_ASC_NOT_READY_TO_READY_CHANGE:
            USBH_ErrLog("USB Disk write is not ready!");
            res = -RT_EBUSY;
            break;

        default:
            res = -RT_ERROR;
            break;
        }
    }

//    rt_exit_critical();
    return res;
}
static rt_size_t usbh_msc_class_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
    uint8_t lun;
    MSC_LUNTypeDef info;
    rt_err_t res = RT_ERROR;

    RT_ASSERT(dev != RT_NULL);
    RT_ASSERT(buffer != RT_NULL);

    lun = USBH_MSC_GetCurLUN(&hUsbHostHS);

//    rt_enter_critical();

    if(USBH_MSC_Read(&hUsbHostHS, lun, pos, (uint8_t *)buffer, size) == USBH_OK)
    {
        res = size;
    }
    else
    {
        USBH_MSC_GetLUNInfo(&hUsbHostHS, lun, &info);

        switch(info.sense.asc)
        {
        case SCSI_ASC_LOGICAL_UNIT_NOT_READY:
        case SCSI_ASC_MEDIUM_NOT_PRESENT:
        case SCSI_ASC_NOT_READY_TO_READY_CHANGE:
            USBH_ErrLog("USB Disk read is not ready!");
            res = -RT_EBUSY;
            break;

        default:
            res = -RT_ERROR;
            break;
        }
    }

//    rt_exit_critical();
    return res;
}
static rt_err_t usbh_msc_class_control(rt_device_t dev, int cmd, void *args)
{
    uint8_t lun;
    MSC_LUNTypeDef info;
    rt_err_t res = RT_EOK;
    struct rt_device_blk_geometry *geometry = NULL;

    RT_ASSERT(dev != RT_NULL);

    lun = USBH_MSC_GetCurLUN(&hUsbHostHS);
    geometry = (struct rt_device_blk_geometry *) args;

    switch(cmd)
    {
        /* GET_SECTOR_COUNT  &  GET_SECTOR_SIZE & GET_BLOCK_SIZE*/
    case RT_DEVICE_CTRL_BLK_GETGEOME :
        if(USBH_MSC_GetLUNInfo(&hUsbHostHS, lun, &info) == USBH_OK)
        {
            geometry->sector_count = info.capacity.block_nbr;
            geometry->block_size = USB_DEFAULT_BLOCK_SIZE;
            geometry->bytes_per_sector = info.capacity.block_size;
        }
        else
        {
            res = RT_ERROR;
        }

        break;

        /* Get erase block size in unit of sector (DWORD) */
    case RT_DEVICE_CTRL_BLK_SYNC :
        break;

    case RT_DEVICE_CTRL_BLK_ERASE:

        break;

    default:
        res = RT_EINVAL;
    }

    return res;
}

添加usbh_msc_device.h文件如下所示.

#ifndef __USBh_MSC_DEVICE__H__
#define __USBh_MSC_DEVICE__H__
#include "usbh_core.h"

#define USBH_MSC_NAME	"USBH_MSC"
struct rt_msc_device
{
    struct rt_device 	 dev;
};
typedef struct rt_msc_device* rt_msc_device_t;
rt_msc_device_t msc_device_init(void);

#endif

至此,可通过RTT标准接口进行CDC通讯,及通过RTT文件系统标准接口对MSC从设备进行文件读写.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
USB host FATFS是指在STM32系列芯片上,通过USB主机模式使用FATFS文件系统的一种应用。引用中提到了关于在STM32F407VG芯片上使用Legacy library USB驱动的说明。在该驱动中,可以实现USB Host(全速)MSC(Mass Storage Class)和FATFS的移植。引用中提到了使用Legacy library USB库和Fatfs驱动的版本信息和一些相关的官方文档链接。引用中提到了USB OTG低级驱动程序的usb_bsp.h文件中声明的函数的实现,这些函数包括初始化GPIO、延时方法和中断启用/禁用等。引用中提到了USB库的usbh_usr.h文件中声明的处理来自用户层的库事件的函数实现,这些函数包括设备连接和断开、设备速度检测、设备描述信息获取、用户输入等。所以,USB MSC host FATFS是通过使用Legacy library USB驱动和Fatfs驱动,在STM32芯片上实现USB主机模式下使用FATFS文件系统的一种应用。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span> #### 引用[.reference_title] - *1* *2* *3* *4* [STM32 之四 标准外设版 USB 驱动 + MSC(Host) + Fatfs R0.13 移植](https://blog.csdn.net/ba_wang_mao/article/details/110402069)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值