USB-SLAVE mstorage使用指南
USB介绍
sifli USB控制器目前支持DEVICE、HOST等设备。其中作为DEVICE时支持CDC、MSTORAGE、HID、WINUSB等相关功能。以下主要叙述USB作为MSTORAGE设备使用流程。 当前USB功能主要作为device的MSTORAGE设备使用,在PC上以可读写的U盘模式出现。PC上可以对该U盘里面的文件进行增加、删除、修改文件等操作,拔出U盘后并在HDK上的文件系统相应分区上保留对应的文件修改。
USB配置
USB的配置包括PINMUX与menuconfig的配置,其中时钟需要在60MHz的频率下运行,目前U盘模式只支持fatfs文件系统,暂时不支持littlefs文件系统。
PINMUX引脚配置
需要将相应的USB引脚配置为IO模式。
#if defined(BSP_USING_USBD) || defined(BSP_USING_USBH)
HAL_PIN_Set_Analog(PAD_PA01, 1);
HAL_PIN_Set_Analog(PAD_PA03, 1);
#endif
在563hdk中存在USB引脚与uart1引脚进行了复用,由于在sifli默认的代码中uart1用来作为HCPU的log打印;因此需要想要正常使用USB需要将uart1进行关闭"Enable UART1",打开"Enable UART4";“Enable UART4 RX DMA”,同时将HCPU的log换为uart4打印;“the device name gor console -> (uart4)”,HCPU相关配置如下。
USB功能代码流程
代码整体流程分为:
1)检测到插入时;callback(app_usb_function(USB_CONTROL_ENABLED)) ==> usb_start() ==> enabled_usb() ==> USB驱动 ==> PC挂载
2)检测到拔出时;callback(app_usb_function(USB_CONTROL_DISABLED)) ==> usb_stop() ==> disabled_usb() ==> USB驱动 ==> HDK卸载 ==> HDK挂载
app_usb_function接口实现如下:
void app_usb_function(void *on_off)
{
struct rt_device *usb_device;
uint8_t usb_stat = *(uint8_t *)on_off;
LOG_I("%s %d", __func__, usb_stat);
if (USB_CONTROL_ENABLED == usb_stat)
{
#ifdef BSP_PM_FREQ_SCALING
rt_pm_hw_device_start(); //关闭自动降频
#endif
usb_start();
}
if (USB_CONTROL_DISABLED == usb_stat)
{
usb_stop();
usb_ota_to_msg_app(); //上报OTA升级包事件
usb_to_msg_gui(NULL, 0, USB_GUI_MSG_ID); //上报USB事件ID
#ifdef BSP_PM_FREQ_SCALING
rt_pm_hw_device_stop(); //打开自动降频
#endif
}
}
USB检测可以根据使用情况分为USB检测引脚进行识别与USB充电接口识别;
1)使用USB检测引脚进行识别插入与拔出
//usb 检测引脚回调函数
static int irq_usb_service_callback(data_callback_arg_t *arg)
{
if (MSG_SERVICE_DATA_NTF_IND == arg->msg_id)
{
pin_common_msg_t pin_msg;
RT_ASSERT(arg != NULL);
RT_ASSERT(sizeof(pin_common_msg_t) == arg->data_len);
memcpy(&pin_msg, arg->data, arg->data_len);
if (pin_msg.id == INSERT_DETE_USB_PIN)
{
rt_usb_irq_pin_enable(0); //关闭中断
rt_thread_mdelay(200); //usb检测pin防抖延时
int read_pin = rt_pin_read(INSERT_DETE_USB_PIN);
if (read_pin == 1)
{
if (USB_CONTROL_DISABLED == usb_get_irq_state())
{
LOG_I("%s USB_CONTROL_PIN_IN", __func__);
usb_set_irq_state(USB_CONTROL_ENABLED);
app_usb_function(&usb_pin_state); //调用USB协议
}
}
else if (USB_CONTROL_ENABLED == usb_get_irq_state())
{
LOG_I("%s USB_CONTROL_PIN_OUT", __func__);
usb_set_irq_state(USB_CONTROL_DISABLED);
app_usb_function(&usb_pin_state);
}
rt_usb_irq_pin_enable(1);
}
}
.......
}
2)USB充电接口识别:
1、在收到充电事件ID时调用app_usb_function(USB_CONTROL_ENABLED);
2、在收到移除充电事件ID时调用app_usb_function(USB_CONTROL_DISABLED)
在USB使用时频率需要一直保持在60MHz运行,因此系统不能降频也不能进行睡眠,所以在检测到USB插入时候系统需要进入IDLE模式再开启USB使能进行USB协议检测,只有当USB协议检测成功后PC才能识别到当前U盘
void usb_start(void)
{
usb_timer_start(); //开启定时器;500ms检测一次USB协议
if (!usb_flag)
{
rt_kprintf("%s rt_pm_request
", __func__);
rt_pm_request(PM_SLEEP_MODE_IDLE); //系统进入IDLE模式
usb_flag = 1;
}
enabled_usb(); //使能USB协议
}
在拔出USB后需要对将加载到PC上的分区进行卸载后再重新再HDK上进行加载;
void usb_stop(void)
{
udevice_t usb_device;
disabled_usb();
if (USB_IN == device_status_get(USB_CONNECT_STATUS)) //成功在PC上加载过分区
{
usb_unmount_fs(); //先卸载分区
usb_mount_fs(); //重新加载分区
}
if (usb_flag)
{
#ifdef RT_USING_PM
LOG_I("%s rt_pm_release", __func__);
rt_pm_release(PM_SLEEP_MODE_IDLE); //退出IDLE
#endif
usb_flag = 0;
}
device_status_set(USB_CONNECT_STATUS, USB_OUT); //设置USB模块状态
usb_device = rt_usbd_find_device(usb_dcd);
RT_ASSERT(usb_device);
usb_device->state = USB_STATE_NOTATTACHED; // 重置USB协议状态
}
使能USB协议
static void enabled_usb(void)
{
struct rt_device *usb_device;
usb_device = rt_device_find("usb_reg");
if (usb_device)
rt_device_control(usb_device, RT_DEVICE_OFLAG_OPEN, NULL);
}
关闭USB协议
static void disabled_usb(void)
{
struct rt_device *usb_device;
usb_device = rt_device_find("usb_reg");
if (usb_device)
rt_device_control(usb_device, RT_DEVICE_OFLAG_CLOSE, NULL);
}
去检测是否有USB协议,当前服务函数为检测协议的定时器超时函数,用于检测USB的协议是否识别成功。再5S内没有识别到USB协议就证明插入的设备没有USB功能
/**
功能:定时检测USB协议
使用:开了一个定时器去定时检测USB协议是否识别成功
*/
static udcd_t usb_dcd;
int app_usb_init(void)
{
usb_dcd = (udcd_t)rt_device_find("usbd");
RT_ASSERT(usb_dcd);
}
static uint8_t usb_handler(void)
{
static uint8_t usb_protocol_flag = 0;
uint8_t usb_intput;
udevice_t usb_device;
usb_device = rt_usbd_find_device(usb_dcd); //usb_dcd是一个全局变量的USB设备指针,在初始化时去find该设备并赋值给usb_dcd
RT_ASSERT(usb_device);
rt_kprintf("%s,state=%d
", __func__, usb_device->state);
if (USB_STATE_CONFIGURED == usb_device->state) //USB协议识别成功
{
device_status_set(USB_CONNECT_STATUS, USB_IN); //设置USB 的状态
usb_protocol_flag = 0;
usb_to_msg_gui(NULL, 0, USB_GUI_MSG_ID); //上报USB识别成功的状态
usb_timer_stop(); //USB协议识别成功就关闭当前定时器
}
else //USB没有检测到协议
{
usb_protocol_flag ++;
if (10 == usb_protocol_flag) //5s内没有识别到协议
{
usb_stop(); //关闭USB模块
usb_timer_stop(); //关闭当前定时器
usb_protocol_flag = 0;
}
}
return 0;
}
在USB拔出后为了节约功耗需要将USB功能禁用并pinmux配置为如下
void BSP_USB_Power_Down(void)
{
#if defined(BSP_USING_USBD) && defined(BSP_USING_USBH)
HAL_PIN_Set(PAD_PA01, GPIO_A1, PIN_PULLUP, 1);
HAL_PIN_Set(PAD_PA03, GPIO_A3, PIN_PULLUP, 1);
#endif
}
USB OTA升级
USB作为OTA升级工具时,暂时可以分为资源差分升级、代码差分升级、全量升级等情况,客户可自己定义与实现相应的功能。具体实现为在通过usb数据线在pc上挂载系统指定的分区后将需要升级的文件放入指定的文件夹中,在拔出USB后会直接检测指定的文件夹里是否含有文件,如果有就执行系统升级,并上报GUI进行界面显示。
使用USB作为OTA的流程为:拔出USB callback(app_usb_function(USB_CONTROL_DISABLED)) ==> usb_read_ota_dir(检测是否有OTA文件) ==>usb_to_msg_gui(向UI上报OTA事件)==>usb_ota_all_file(执行升级)
/**
* @brief OTA check ID
*/
enum
{
USB_OTA_CHECK_ROOT = 0X01,
USB_OTA_CHECK_DYN = 0X02,
USB_OTA_CHECK_MUSIC = 0X04,
USB_OTA_CHECK_UDISK = 0X08,
USB_OTA_CHECK_MISC = 0X10,
USB_OTA_CHECK_HCPU = 0X20,
USB_OTA_MOVING_IDLE = 0XFF,
USB_OTA_MOVING_ING = 0xC0,
USB_OTA_MOVING_SUCC = 0x3F,
};
/**
* @brief OTA Upgrade Directory Contains resources and code
*/
#define USB_DIFF_RES_PATH "/udisk/diff_res"
#define USB_DIFF_CODE_PATH "/udisk/diff_code"
#define USB_DIFF_RES_ROOT_PATH "/udisk/diff_res/root" /**<root Resource upgrade directory */
#define USB_DIFF_RES_DYN_PATH "/udisk/diff_res/dyn" /**<dyn Resource upgrade directory */
#define USB_DIFF_RES_MUSIC_PATH "/udisk/diff_res/music" /**<music Resource upgrade directory */
#define USB_DIFF_RES_MISC_PATH "/udisk/diff_res/misc" /**<misc Resource upgrade directory */
#define USB_DIFF_RES_UDISK_PATH "/udisk/diff_res/udisk" /**<udisk Resource upgrade directory */
#define USB_DIFF_CODE_HCPU_PATH "/udisk/diff_code/hcpu" /**<hcpu code upgrade directory */
/**
* @brief Directory and corresponding ID for USB upgrade
*/
struct usb_diff_msg
{
char *path; /**升级文件的目录*/
char *dev_name; /**升级文件的device设备名*/
uint16_t id; /**check id*/
};
static struct usb_diff_msg usb_ota_msg[] =
{
{USB_DIFF_RES_ROOT_PATH, "root", USB_OTA_CHECK_ROOT},
{USB_DIFF_RES_DYN_PATH, "dyn", USB_OTA_CHECK_DYN},
{USB_DIFF_RES_MUSIC_PATH, "music", USB_OTA_CHECK_MUSIC},
{USB_DIFF_RES_UDISK_PATH, "udisk", USB_OTA_CHECK_UDISK},
{USB_DIFF_RES_MISC_PATH, "misc", USB_OTA_CHECK_MISC},
{USB_DIFF_CODE_HCPU_PATH, "code_pang", USB_OTA_CHECK_HCPU},
};
/**
功能:向UI发送消息接口
*/
void usb_ota_to_msg_app(void)
{
int ota_file_page_num = 0, file_len = 0, page_num = 0;
for (int i = 0; i < USB_OTAD_PATH_FILE_NUM; i ++)//遍历udisk上的所有文件夹
{
file_len = usb_read_ota_dir(usb_ota_msg[i].path, NULL); //读取指定目录是都有文件
page_num = file_len / USB_OTA_PACKAGE_SIZE; //计算升级的包数 512字节一包
if (file_len % USB_OTA_PACKAGE_SIZE) page_num++; //计算余数
ota_file_page_num += page_num; /*Calculate the total number of packages to upgrade*/
}
if (ota_file_page_num)
{
usb_to_msg_gui(NULL, ota_file_page_num, USB_GUI_OTA_ID);/*Send the total number of packages that need to be upgraded to the GUI*/
LOG_I("%s page num %d", __func__, ota_file_page_num);
usb_ota_all_file(usb_ota_msg, ota_file_page_num);/*Execute USB upgrade resources and code*/
}
}
在本次案例上主要展示在555平台flash为emmc模式。OTA细节流程为; 系统资源升级:发现有升级文件->使用读取文件系统的方式读取需要升级的文件->将读取的文件写入到相应的资源地址->写入kvdb标志用于开机检测->删除文件系统文件->重启 运行代码升级:发现有升级文件->使用读取文件系统的方式读取需要升级的文件->将读取的文件写入到emmc一段空白地址处->写入env标志位用于OTAmanager执行->写入kvdb标志用于开机检测->删除文件系统文件->重启 代码流程如下:
/*
功能:ota所有文件
参数:ota_msg->所有的升级目录信息;ota_page_max:总包数(512一个包)
*/
void usb_ota_all_file(struct usb_diff_msg ota_msg[], uint32_t ota_page_max)
{
uint32_t bin_size = 0;
ota_page_count = 0;
usb_ota_write_flag(0x00); //将check id 全部设置为0
for (int i = 0; i < USB_OTAD_PATH_FILE_NUM; i ++)
{
LOG_I("%s,path=%s", __func__, ota_msg[i].path);
bin_size = usb_ota_file_transfer(ota_msg[i], ota_page_max); //执行单个文件的升级
}
usb_ota_write_flag(usb_ota_read_flag() >> 0x2); //写入升级完成的标志 00xx xxxx:(7,8位:00升级完成;11升级中)
usb_ota_jump(usb_ota_get_type(), bin_size); //重启跳转
}
/*
功能:ota文件搬移与标志位写如
参数:ota_msg:需要升级的文件信息;page_max:总包数(512一个包)
返回:如果有执行代码(HCPU)的升级就返回该文件大小,没有就返回0.
*/
/*Performing an upgrade of a single file*/
static uint32_t usb_ota_file_transfer(struct usb_diff_msg ota_msg, uint32_t page_max)
{
uint32_t size = 0, ota_hcpu_size = 0;
uint8_t usb_check = 0;
char file_name[USB_DEVICE_NAME_LEN] = {0};
memset(file_name, 0x00, USB_DEVICE_NAME_LEN);
usb_check = usb_ota_read_flag(); //获取check ID
size = usb_read_ota_dir(ota_msg.path, file_name);
if (size)
{
LOG_I("%s ota_msg.path=%s,name=%s", __func__, ota_msg.path, file_name);
usb_check |= USB_OTA_MOVING_ING;/*Upgrading*/
usb_ota_write_flag(usb_check);/*Write upgrade flag*/
if (RT_EOK == usb_ota_moving_file(ota_msg, file_name, page_max)) //进行文件的搬移
{
LOG_I("%s moving succ !!!", __func__);
usb_check |= ota_msg.id;/*file upgrad succ*/
usb_ota_write_flag(usb_check);/*Write upgrade flag*/
if (0 == strcmp(ota_msg.dev_name, "code_pang"))
{
usb_ota_set_type(USB_OTA_TYPE_HCPU);
ota_hcpu_size = size;
}
else usb_ota_set_type(USB_OTA_TYPE_RES);
}
else
{
LOG_I("%s moving fail !!!", __func__);
usb_check |= (!ota_msg.id);/*file upgrad fail*/
usb_ota_write_flag(usb_check);/*Write upgrade flag*/
}
}
else
{
usb_check |= ota_msg.id;
usb_ota_write_flag(usb_check);/*Write upgrade flag*/
}
return ota_hcpu_size;
}
/*
功能:跳转以重启
参数:flag:升级的类型;len:执行代码升级的文件大小
*/
void usb_ota_jump(uint32_t flag, uint32_t len)
{
if (flag == USB_OTA_TYPE_HCPU)
{
/*jump to ota manager code*/
LOG_I("%s,USB_OTA_CODE_HCPU drv_reboot,file_size=%d", __func__, len);
dfu_ctrl_env_t *env = dfu_ctrl_get_env();
env->prog.state = DFU_CTRL_USB_INSTALL; //写入OTA manager的标志
env->prog.FW_version = len; //HCPU 代码大小
dfu_ctrl_update_prog_info(env); //保存env
drv_reboot(); //重启
}
else if (flag == USB_OTA_TYPE_RES)
{
/*Just restart the resource file*/
LOG_I("%s,USB_OTA_RES drv_reboot", __func__);
drv_reboot();
}
}
开机check检测
/**
* check ID:是由一个uint8_t的数以位作为每个文件的标志组成;
* check ID:uint8_t ID = 0x3f ; 1111 1111 :1-6位依次为文件 ROOT DYN MUSIC MISC UDISK HCPU的升级成功标志 1-升级成功 0-升级失败;7-8位 11-升级中;00升级完成,
* 在usb_ota_file_transfer()接口中没有升级此文件时候也会将该文件的标志置为1;因此0x3f是升级完成,在升级完成后会将check ID置为0xff。
*
*/
static void dfs_check_res_integrity(void)
{
uint8_t usb_ota_stater = 0;
usb_ota_stater = usb_ota_read_flag();
LOG_I("%s usb_ota_stater=%p", __func__, usb_ota_stater);
switch (usb_ota_stater)
{
case USB_OTA_MOVING_IDLE:
{
LOG_I("%s IDLE", __func__);
}
break;
case USB_OTA_MOVING_SUCC: //升级成功
{
LOG_I("%s Resource updated !", __func__);
usb_ota_write_flag(USB_OTA_MOVING_IDLE); //写入0xff
}
break;
default :
{
LOG_I("%s Upgrade failed, please upgrade again !", __func__);
usb_ota_to_msg_app(); //为其他值视为升级失败,就重新进入升级流程
}
break;
}
}
ota manager
此功能只会需要升级运行代码(HCPU代码)的时候才会进入,只是升级资源就直接覆盖后重启即可,在ota manager中需要将已经在指定的emmc地址段中读取数据后覆盖到APP运行地址中去。
uint8_t dfu_ctrl_reset_handler(void)
{
dfu_ctrl_env_t *env = dfu_ctrl_get_env();
RT_ASSERT(env->mode == DFU_CTRL_OTA_MODE);
uint16_t state = env->prog.state;
uint8_t status = DFU_ERR_GENERAL_ERR;
uint8_t is_jump = 0;
LOG_I("dfu_ctrl_reset_handler %d", state);
// dfu_ota_bootloader_ram_run_set(DFU_RAM_STATE_UPDATE_FAIL);
if (HAL_Get_backup(RTC_BAKCUP_OTA_FORCE_MODE) == 1)
{
HAL_Set_backup(RTC_BAKCUP_OTA_FORCE_MODE, 0);
dfu_flash_addr_reset(0);
dfu_ctrl_boot_to_user_fw();
}
...........
switch (state)
{
case DFU_CTRL_USB_INSTALL: //USB升级标志
{
#ifdef OTA_EMMC
env->callback(DFU_APP_RESET_IND, NULL); //打开UI
LOG_I("%s moving addr=%p,bin_size=%d
", __func__, HCPU_FLASH_CODE_START_ADDR, env->prog.FW_version);
uint8_t dfu_emmc_code_upgrade(dfu_ctrl_env_t *env, uint32_t size);
uint8_t dfu_upgrade_result = dfu_emmc_code_upgrade(env, env->prog.FW_version);//进行code升级
switch (dfu_upgrade_result)
{
case DFU_USB_FIND_FAIL: //升级失败
{
LOG_I("%s find fail!
", __func__);
env->prog.state = DFU_CTRL_IDLE; //写入标志位 回退之前的app,重启
env->prog.FW_version = 0;
dfu_ctrl_update_prog_info(env);
drv_reboot();
}
break;
case DFU_USB_FAIL: //在搬移过程中失败
{
LOG_I("%s fail!,env->prog.FW_version=%d
", __func__, env->prog.FW_version);
if (env->prog.FW_version == 0) env->prog.FW_version = 1;
else if (env->prog.FW_version == 5) //重启超过5次就不在重启了
{
LOG_I("%s while(1)
", __func__);
while (1) {;}
}
else env->prog.FW_version += 1;
dfu_ctrl_update_prog_info(env);
drv_reboot();
}
break;
}
#else
is_jump = 1;
#endif
}
break;
...........
return 0;
}
/**
* 功能:code升级
* 参数:env;size:文件大小
* 返回:升级结果
*/
uint8_t dfu_emmc_code_upgrade(dfu_ctrl_env_t *env, uint32_t size)
{
uint32_t page_num = size / DFU_EMMC_PAGE_MAX;
uint32_t emmc_offset = 0, nor_offset = 0, end_page_size = size % DFU_EMMC_PAGE_MAX;
if (end_page_size) page_num ++ ;
rt_device_t dev = rt_device_find("code_pang");
LOG_I("%s page_num=%d,dev=%p,name=%s", __func__, page_num, dev, dev->parent.name);
env->callback(DFU_APP_DL_END_AND_INSTALL_START_IND, NULL);
if (dev)
{
if (RT_EOK == rt_device_open(dev, RT_DEVICE_FLAG_RDWR))
{
int res = 0;
while (page_num --)
{
memset(code_buf, 0x00, DFU_EMMC_PAGE_MAX);
res = rt_device_read(dev, emmc_offset, (void *)code_buf, DFU_EMMC_PAGE_MAX / 512);//读取emmc里面的code
if (res > 0)
{
rt_flash_erase(HCPU_FLASH_CODE_START_ADDR + (nor_offset * DFU_EMMC_PAGE_MAX), DFU_EMMC_PAGE_MAX);//擦除nor
uint32_t wr_size = rt_flash_write(HCPU_FLASH_CODE_START_ADDR + (nor_offset * DFU_EMMC_PAGE_MAX), code_buf, DFU_EMMC_PAGE_MAX);//将代码写入nor上的app地址
if (wr_size != DFU_EMMC_PAGE_MAX)
{
LOG_I("%s write fail!,nor_offset=0x%x,ADDR=0x%x wr_size=%d", __func__, nor_offset, HCPU_FLASH_CODE_START_ADDR + (nor_offset * DFU_EMMC_PAGE_MAX), wr_size);
return DFU_USB_FAIL;
}
}
else
{
rt_device_close(dev);
LOG_I("%s read fail!,emmc_offset=0x%x,ADDR=0x%x res=%d", __func__, emmc_offset, HCPU_FLASH_CODE_START_ADDR, res);
return DFU_USB_FAIL;
}
emmc_offset += (DFU_EMMC_PAGE_MAX / 512);
nor_offset += 1;
dfu_install_progress_ind(nor_offset * DFU_EMMC_PAGE_MAX, size);//向UI发送进度
}
}
}
else
{
LOG_I("%s find code_pang fail!", __func__);
rt_device_close(dev);
return DFU_USB_FIND_FAIL;
}
LOG_I("%s emmc code moving sucss!", __func__);
env->callback(DFU_APP_INSTALL_COMPLETD_IND, NULL);
env->callback(DFU_APP_TO_USER, NULL);
env->prog.state = DFU_CTRL_IDLE;
env->prog.FW_state = DFU_CTRL_FW_INSTALLED;
env->prog.FW_version = 0;
env->is_force_update = 0;
dfu_ctrl_update_prog_info(env);//保存状态
dfu_ctrl_boot_to_user_fw();//重启
return DFU_USB_EOK;
}
USB OTA使用流程
一、插入USB,pc上正确识别到U盘。并且能正常打开里面的目录,目录如下;
#define USB_DIFF_RES_PATH "/udisk/diff_res"
#define USB_DIFF_CODE_PATH "/udisk/diff_code"
#define USB_DIFF_RES_ROOT_PATH "/udisk/diff_res/root" /**<root 图库 字体 等相关资源 */
#define USB_DIFF_RES_DYN_PATH "/udisk/diff_res/dyn" /**<dyn 资源升级目录 */
#define USB_DIFF_RES_MUSIC_PATH "/udisk/diff_res/music" /**<music 资源升级目录 */
#define USB_DIFF_RES_MISC_PATH "/udisk/diff_res/misc" /**<misc 资源升级目录 */
#define USB_DIFF_RES_UDISK_PATH "/udisk/diff_res/udisk" /**<udisk 资源升级目录 */
#define USB_DIFF_CODE_HCPU_PATH "/udisk/diff_code/hcpu" /**<hcpu 代码升级目录 hcpu已经包含了lcpu代码 */
二、将需要升级的文件放至对应的目录里面去。
三、拔出USB检测到有升级的文件后,自动进入copy界面 如果只有资源文件升级则就是copy界面完成后就自动重启。


然后重启到主界面

如果有code升级文件,那就先copy界面后再重启到ota manager界面进行安装,安装完成后重启



然后重启到主界面

常见报错
检测不到USB协议
检查一些USB的时钟是否开启,如果开启了查看USB的时钟频率是否为60MHz。在bsp_init.c中或者brv_io.c检查,并且检查一下是否有位置关闭了USB功能模块。
在bf0_hal_pcd.c中
HAL_RCC_DisableModule(RCC_MOD_USBC);
同时检查一下相关的USB引脚是否正确连接。
PC上识别到了mstorage设备,但是没有对应的U盘。
检查一下USB的协议通信是否正常,使用wireshark工具抓一下USB协议包。