RT-Thread:GD32E103 移植USB HOST

本文详细介绍了如何在RT-Thread框架中集成USB-Host功能,并通过添加GD32E103的驱动和支持,使用户能够使用DFS进行文件操作。步骤包括外部源文件的复制、路径配置、源码修改和驱动整合,最后成功实现了USB设备的驱动和文件系统的挂载与卸载。
摘要由CSDN通过智能技术生成


前言

在原本RTT框架下添加USB-Host,并且可以使用dfs。

一、复制外部源文件到工程中

1、复制之前博文中写到的《GD32E103的Flash芯片上挂载文件系统》的工程并将文件夹命名为test。
在这里插入图片描述
2、在rt-thread-rt-smart\bsp\test\drivers文件夹中新建MSC_Host文件夹,并复制官方USBFS例程中inc、src文件到里面,具体路径看截图。
在这里插入图片描述
在这里插入图片描述
3、将src文件中的main.c移到applications文件夹中,并命名为usb_host.c,新建usb_host.h也放在里面。
在这里插入图片描述
4、将rt-thread-rt-smart\bsp\test\drivers\MSC_Host\src中的gd32e10x_it.c删除。
在这里插入图片描述
5、将图中路径的udisk.c文件复制到rt-thread-rt-smart\bsp\test\Libraries\GD32E10x_usbfs_driver\Source中,并在rt-thread-rt-smart\bsp\test\Libraries\GD32E10x_usbfs_driver\Include中新建一个udisk.h头文件。
在这里插入图片描述

二、添加源文件和头文件路径

1、打开工程。这里注意一下,我强迫症把原本工程中USER_DEV文件夹里面的gd25qxx.c文件移动到Applications中了,其实这只是个人问题,对工程本身没什么影响。
在这里插入图片描述
2、新建文件夹USB_Dirver,并将图中文件添加到工程中,具体路径自己找,反正都在test文件夹下。
3、在Drivers文件夹下添加图中文件。
4、将usb_host.c文件添加到Applications。
在这里插入图片描述
5、添加头文件路径在这里插入图片描述

三、修改源码

1、删除usb_host.c中的main函数,添加代码

#define USB_DEVICE_CONTROLLER_NAME      "usbd"
#define USB_THREAD_STACK_SIZE     1024

/*!
    \brief      this function handles USBFS interrupt
    \param[in]  none
    \param[out] none
    \retval     none
*/
void  USBFS_IRQHandler (void)
{
	/* enter interrupt */
    rt_interrupt_enter();

    usbh_isr (&usb_core_dev);
	
	/* leave interrupt */
    rt_interrupt_leave();
}

/*!
    \brief      this function handles Timer0 update interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void TIMER0_UP_TIMER9_IRQHandler(void)
{
	/* enter interrupt */
    rt_interrupt_enter();
	
    timer_delay_irq();
	
	/* leave interrupt */
    rt_interrupt_leave();
}

/*!
    \brief      rt_usbh_thread_entry routine
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void rt_usbh_thread_entry(void* parameter)
{
	rt_err_t res = -RT_ERROR;
	rt_device_t dev = RT_NULL;
	
	dev = (rt_device_t)rt_malloc(sizeof(struct rt_device));
	if (dev == RT_NULL)
	{
		rt_kprintf("dev malloc failed\r\n");
		return;
	}
	
	rt_memset(dev, 0, sizeof(struct rt_device));
		
	res = rt_device_register(dev, "usbh", RT_DEVICE_FLAG_DEACTIVATE);
    if (res != RT_EOK)
    {
        rt_kprintf("register usb host failed res = %d\r\n", res);
    }
	
	dev->init = rt_udisk_init;
	dev->read = rt_udisk_read;
	dev->write = rt_udisk_write;
	dev->control = rt_udisk_control;
	
    while(1)
    {    
		host_state_polling_fun(&usb_core_dev, &usb_host, &usbh_state_core);
		rt_thread_mdelay(100);
    }
}

/*!
    \brief      usb_host_init routine
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usb_host_init(void)
{
	/* allocate memory for the usbh_usr_struct */
    if((usbh_usr = (usbh_usr_struct *)rt_malloc(sizeof(usbh_usr_struct))) == RT_NULL)
    {
        rt_kprintf("malloc memory for usbh_usr_struct failed!\r\n");
		return;
    }
    rt_memset(usbh_usr, 0, sizeof(usbh_usr_struct));
	
	/* allocate memory for the usbh_data_in_buffer */
    if((usbh_data_in_buffer = (uint8_t *)rt_malloc(USBH_DATA_BUFFER_SIZE)) == RT_NULL)
    {
        rt_kprintf("malloc memory for usbh_data_in_buffer failed!\r\n");
		return;
    }
    rt_memset(usbh_data_in_buffer, 0, USBH_DATA_BUFFER_SIZE);
	
	/* allocate memory for the usbh_data_in_buffer */
    if((usbh_data_out_buffer = (uint8_t *)rt_malloc(USBH_DATA_BUFFER_SIZE)) == RT_NULL)
    {
        rt_kprintf("malloc memory for usbh_data_out_buffer failed!\r\n");
		return;
    }
    rt_memset(usbh_data_out_buffer, 0, USBH_DATA_BUFFER_SIZE);
	
	/* usb rcu init */
    usb_rcu_init();

    /* timer nvic initialization */
    timer_nvic_init();

    /* configure GPIO pin used for switching VBUS power */
    usb_hwp_vbus_config(&usb_core_dev);
	
    /* host de-initializations */
    usbh_deinit(&usb_core_dev, &usb_host, &usbh_state_core);

    /* start the USB core */
    hcd_init(&usb_core_dev, USB_FS_CORE_ID);
	
    /* init usr call back */
    usb_host.usr_cb->init();

    /* enable interrupts */
    usb_hwp_interrupt_enable(&usb_core_dev);
	
	rt_thread_t thread = rt_thread_create("usbh", rt_usbh_thread_entry, RT_NULL, 
										  USB_THREAD_STACK_SIZE, 8, 20);
		
	if(thread != RT_NULL)
	{
		/* startup usb host thread */
		rt_thread_startup(thread);
	}
}
MSH_CMD_EXPORT(usb_host_init,udisk init);

int udisk_mount(void)
{
	/*查找Flash设备*/
	if(rt_device_find("usbh") != RT_NULL) 
	{
		/*挂载Flash*/
		if(dfs_mount("usbh", UDISK_MOUNTPOINT, "elm", 0, 0) == 0)
		{
			rt_kprintf("flash mount success!\n");
		} 
		else 
		{
			rt_kprintf("flash mount failed!\n");
		}
	}
	
	return 0;
}
MSH_CMD_EXPORT(udisk_mount,udisk mount);

void udisk_unmount(void)
{
	if(dfs_unmount(UDISK_MOUNTPOINT) == 0)
	{
		rt_kprintf("unmount %s success!\n",UDISK_MOUNTPOINT);
	} 
	else 
	{
		rt_kprintf("unmount %s failed!\n",UDISK_MOUNTPOINT);
	}
}
MSH_CMD_EXPORT(udisk_unmount,udisk unmount);

2、修改usb_host.c文件最上面的头文件为图中文件。
在这里插入图片描述
3、在usb_host.h文件中添加代码。

#ifndef __USB_HOST_H
#define __USB_HOST_H

#include <rtthread.h>
#include "usb_delay.h" 
#include "usbh_core.h"
#include "usbh_usr.h"
#include "usbh_msc_core.h"
#include "usbh_std.h"
#include "usbh_ctrl.h"
#include "usbh_int.h"
#include "diskio.h"
#include "string.h"
#include "udisk.h"

void usb_host_init(void);

#endif

4、根据提示删除usb_conf.h中的#include “gd32e103r_start.h”,删除后如图所示。
在这里插入图片描述
5、修改udisk.c最上面代码,修改成图中代码。
在这里插入图片描述
6、添加以下代码到udisk.h中

#ifndef __UDISK_H
#define __UDISK_H

#include <rtthread.h>
#include <dfs_fs.h>

int udisk_get_id(void);
void udisk_free_id(int id);
rt_err_t rt_udisk_init(rt_device_t dev);
rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer,rt_size_t size);
rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buffer,rt_size_t size);
rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args);

#endif

7、添加全局宏USE_USBFS
在这里插入图片描述
8、将以下出现的函数替换掉usbh_usr.c中一样的函数。

/*!
    \brief      user operation for host-mode initialization
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_init(void)
{
	
}

/*!
    \brief      user operation for device attached
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_device_connected(void)
{
	usbh_usr->connected_status = USBH_USR_CONNECTED;
	rt_kprintf("udisk connected\r\n");
}

/*!
    \brief      user operation for device disconnect event
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_device_disconnected (void)
{
	usbh_usr->connected_status = USBH_USR_DISCONNECTED;
	usbh_usr->init_status = USBH_USR_NOT_READY;
	rt_kprintf("udisk disconnected\r\n");
}

/*!
    \brief      user action for application state entry
    \param[in]  none
    \param[out] none
    \retval     user response for user key
*/
usbh_user_status_enum usbh_user_userinput(void)
{
	//未就绪,准备初始化
	if(usbh_usr->init_status == USBH_USR_NOT_READY)
		return USBH_USER_RESP_OK;

	return USBH_USER_NO_RESP;
}

/*!
    \brief      demo application for mass storage
    \param[in]  pudev: pointer to device
    \param[in]  id: no use here
    \param[out] none
    \retval     status
*/
int usbh_usr_msc_application(usb_core_handle_struct *pudev, uint8_t id)
{
	if(usbh_usr->init_status == USBH_USR_NOT_READY)
	{
		rt_kprintf("usbh msc init successfully.\r\n");
		usbh_usr->init_status = USBH_USR_READY;
	}
	
    return 0;
}

/*!
    \brief      deinit user state and associated variables
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_deinit(void)
{
	
}

9、删除usbh_usr.c中explore_disk函数,注意也要删除对应头文件explore_disk函数声明。
10、修改usbh_usr.c图中部分。在这里插入图片描述

#include <rtthread.h>
#include <string.h>
#include "usbh_usr.h"
#include "ff.h"
#include "usbh_msc_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"

usbh_usr_struct *usbh_usr;

11、在usbh_usr.h中添加以下代码。在这里插入图片描述

#include "ff.h"
#include "usbh_core.h"
#include "usb_conf.h"
#include "usbh_msc_core.h"
#include "usb_std.h"
#include <stdio.h>

#define USBH_USR_CONNECTED			1
#define USBH_USR_DISCONNECTED		0

#define USBH_USR_READY				1
#define USBH_USR_NOT_READY			0

12、编译根据提示的FALSE和TRUE修改成RT_FALSE和RT_TRUE。
13、修改usbh_msc_scsi.c和usbh_msc_scsi.h。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
14、在rt_config.h添加以下代码
在这里插入图片描述

#define RT_USBH_MSTORAGE
#define UDISK_MOUNTPOINT "/udisk"

15、修改udisk.c中rt_udisk_read、rt_udisk_write、rt_udisk_control函数

/**
 * This function will read some data from a device.
 *
 * @param dev the pointer of device driver structure
 * @param pos the position of reading
 * @param buffer the data buffer to save read data
 * @param size the size of buffer
 *
 * @return the actually read size on successful, otherwise negative returned.
 */
rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer,
    rt_size_t size)
{
    BYTE status = USBH_MSC_OK;

	if (hcd_is_device_connected(&usb_core_dev)) 
        stat &= ~USBH_MSC_STA_NOINIT;
	
    if (!size)
		return 0;
	
    if (stat & USBH_MSC_STA_NOINIT)
		return 0;

    if (hcd_is_device_connected(&usb_core_dev))
	{
        do
		{
            status = usbh_msc_read10(&usb_core_dev, buffer, pos, 512 * size);
            usbh_msc_handle_botxfer(&usb_core_dev, &usb_host,  &usbh_state_core);

            if(!hcd_is_device_connected(&usb_core_dev))
			{
                return 0;
            }
        }
        while(USBH_MSC_BUSY == status);
    }

    if(USBH_MSC_OK == status)
		return size;

    return 0;
}

/**
 * This function will write some data to a device.
 *
 * @param dev the pointer of device driver structure
 * @param pos the position of written
 * @param buffer the data buffer to be written to device
 * @param size the size of buffer
 *
 * @return the actually written size on successful, otherwise negative returned.
 */
rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buffer,
    rt_size_t size)
{
    BYTE status = USBH_MSC_OK;
	
	if (hcd_is_device_connected(&usb_core_dev)) 
        stat &= ~USBH_MSC_STA_NOINIT;
	
    if (!size) 
		return 0;
	
    if (stat & USBH_MSC_STA_NOINIT) 
		return 0;
	
    if (stat & USBH_MSC_STA_PROTECT) 
		return 0;

    if (hcd_is_device_connected(&usb_core_dev)) 
	{
        do 
		{
            status = usbh_msc_write10(&usb_core_dev, (BYTE*)buffer, pos, 512 * size);
            usbh_msc_handle_botxfer(&usb_core_dev, &usb_host,  &usbh_state_core);

            if (!hcd_is_device_connected(&usb_core_dev)) 
			{
                return 0;
            }
        } while(USBH_MSC_BUSY == status);
    }

    if (USBH_MSC_OK == status) 
		return size;

    return 0;
}

/**
 * This function will execute SCSI_INQUIRY_CMD command to get inquiry data.
 *
 * @param intf the interface instance.
 * @param buffer the data buffer to save inquiry data
 *
 * @return the error code, RT_EOK on successfully.
 */
rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args)
{
    if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
    {
        struct rt_device_blk_geometry *geometry;

        geometry = (struct rt_device_blk_geometry *)args;
        if (geometry == RT_NULL) return -RT_ERROR;

        geometry->bytes_per_sector = SECTOR_SIZE;
        geometry->block_size = 512;
        geometry->sector_count = 512;
    }

    return RT_EOK;
}

16、删除udisk.c中rt_udisk_run和rt_udisk_stop函数。
16、在udisk.c中添加以下代码。
在这里插入图片描述

static volatile USBH_MSC_DSTATUS stat = USBH_MSC_STA_NOINIT; /* disk status */

extern usb_core_handle_struct          usb_core_dev;
extern usbh_host_struct                usb_host;
extern usbh_state_handle_struct        usbh_state_core;

17、添加代码到udisk.h。

#ifndef __UDISK_H
#define __UDISK_H

#include <rtthread.h>
#include <dfs_fs.h>

int udisk_get_id(void);
void udisk_free_id(int id);
rt_err_t rt_udisk_init(rt_device_t dev);
rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer,rt_size_t size);
rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buffer,rt_size_t size);
rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args);

#endif

18、删掉udisk.c中udisk_get_id、udisk_free_id和rt_udisk_init函数的static。
19、修改可挂载数量为3。
在这里插入图片描述
20、扩大动态内存为31k。
在这里插入图片描述

21、编译通过,运行测试。
在这里插入图片描述
22、源码下载,里面有一个未移植USB-Host代码工程,一个是已移植USB-Host的代码工程。

四、源码下载

源码----

总结

下班躺尸...
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小破孩 != ERR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值