前言
在原本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的代码工程。