Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
瑞萨_RA6M4
开发板评测
USB主机_host
【开发板评测】Renesas RA6M4开发板之USB-H
发布于 2022-04-03 22:17:02 浏览:1921
订阅该版
[tocm] 感谢RT-Thread和瑞萨举办的开发板评测活动,非常高兴被选中来参与这次活动。 ## 开发板资源介绍 这次是第二次接触这块开发板了,但是还是第一次仔细观察这块开发板。 先贴两张手册中的图,开发板上方是一个板载的JLink调试接口和usb host/device 接口,下方有两个PMOD接口、按键、LED、光线传感器和一个电位计。 一共四排大排针,把芯片所有引脚都印出来了,这还是非常不错的。 ![正面外观.png](https://oss-club.rt-thread.org/uploads/20220403/e95d32e1206dc221ab7ac5bfcb560f70.png.webp) 背面则留出了很多可供修改的跳线。 ![背面.png](https://oss-club.rt-thread.org/uploads/20220403/3aa68e107764f346a62792e8e354f0da.png.webp) 在芯片下面的位置,有四排兼容Arduino扩展接口的排针位置,**但是J12排针上下摆反了**,这摆反了让所有Arduino扩展设备都无法使用,可以说是白设计了。 倒是也可以补救,J12排针不焊接,然后自己重连一下线。 ![Arduino接口2.png](https://oss-club.rt-thread.org/uploads/20220403/0af2590ceeb89b63c0bdd38081d50f04.png.webp) ![Arduino接口.png](https://oss-club.rt-thread.org/uploads/20220403/f21441fa174f381b503a4dc48156c468.png.webp) ![ArduinoPCB.png](https://oss-club.rt-thread.org/uploads/20220403/6bf32fb17e1b10a2cfb4e3bd7965c15c.png.webp) 中间的芯片是R7FA6M4AF3CFB 144Pin LQFP封装,Cortex-M33内核,最高运行主频200Mhz,带有1MB Program Memory,8KB Data Flash和256KB的RAM。芯片内部的资源该有的都有,12位的AD和DA也是比较标准的配置,这个Octa SPI和SSIE接口一般还是比较少见的,能实际应用起来的话,体验应该不错。在安全方面,集成了一个加密引擎和Arm TrustZone,在需要安全的场景下也是可以应付的。 芯片是带有一个Ethernet MAC/DMA controller的,内部没有集成PHY,在EK-RA6M4开发板上是加了PHY芯片和RJ45接口的,如果这块板子上能增加一个RJ45的接口,想必能做更多的应用。 ## USB-H功能模块的硬件介绍 这次评测的内容是USB host,先来看看这部分模块的介绍。 这边的电路并不算复杂,这里有两个跳线排针,板子丝印也已经标记出来了,是用于切换usb_vbus的供电来源的,J21连通J16连接23脚,则为usb device模式,供电从外部usb接口的5v获得;J21断开J16连接12引脚则为usb host模式,从板子5V经过一个AP2151限流电源开关芯片转到5V_FS,然后外接供到micro usb接口上。 这里的AP2151用P500引脚来做开关控制引脚,用P501来接收过流报警信号,**这两个脚貌似和SDIO接口的引脚冲突了**,如果要同时使用usb host和SDHI功能,那么这里需要特别注意,板子这里也有考虑到,只需要断开R17和R19,放弃usb host外部电源的控制功能,就能同时使用SDHI功能了。 micro usb接口进来是另一个AP2151来做过流保护,经过一个共模电感,接到了芯片的USB_DP和USB_DM引脚上。 ![usb_fs_interface.png](https://oss-club.rt-thread.org/uploads/20220403/f7046c00598bf505a4709cb384b648a8.png.webp) ![usb_fs_interface_pcb.png](https://oss-club.rt-thread.org/uploads/20220403/d69007b9b23f4ad9b1326417ee7b5187.png.webp) 芯片中集成了一个USB IP,可以使用Full Speed的速度,有usb host和peripheral两种模式可以选,带有两个FIFO,传输时可以使用DMA通道。 ![usbfs_block.png](https://oss-club.rt-thread.org/uploads/20220406/5b9b009dbf3af8b7463304efd60261f3.png.webp) ## USB-H功能模块的使用说明 #### 环境搭建 关于开发环境的搭建,已经有很多优秀的教程了,在这里也就不细说了。步骤不复杂,安装了RT-Thread Studio后,从SDK管理器中找到CPK-RA6M4开发板的BSP下载,然后安装瑞萨提供的FSP,推荐直接安装附带RASC的FSP软件包。由于RASC中不带CPK-RA6M4的BSP,所以安装了RASC后需要手动将CPK-RA6M4的BSP复制到RASC中。 #### RASC FSP 介绍 RASC全称RA Smart Configurator,是瑞萨提供的一款用于快速配置FSP并生成工程的软件,和ST的Cube MX类似。FSP会附带有一份文档,介绍了FSP的架构和提供的API,有的还附带了简单的例程,可以直接复制对API进行测试使用。FSP里面直接提供有usb hcdc、hhid和hmsc的中间件接口,可以快速地开发应用。其中MSC的中间件需要配合RTOS,目前看来只适配好了FreeRTOS,其他的RTOS还需要自己做兼容。也提供了更底层的usb basic接口,可以进行更底层的控制。 ![usb_api.png](https://oss-club.rt-thread.org/uploads/20220403/2d0d8b4719b5c468b8ddf920d9581e78.png) #### 例程编写 编写的例程是使用FSP提供的usb hcdc中间件,实现了一个可使用usb串口设备的usb主机。 首先在RT-Thread Studio上新建一个基于开发板的项目,选择CPK-RA6M4开发板,建立一个模板工程。编译下载后,可以看到LED灯在闪烁,同时可以在串口终端上使用rtt的FinSH控制台。 下一步,打开RASC,在stacks页面,添加一个usb hcdc的驱动栈。 ![rasc_stacks.png](https://oss-club.rt-thread.org/uploads/20220403/7d6c59f3cc1b3759541eee69024b21c1.png.webp) 这时候会提示有错误,usb模块使用的UCLK时钟频率不是48MHz的,需要在Clocks页面进行配置。**将PLL2时钟源选择为HOCO,分频系数调到2,倍频系数调到24,即可得到240Mhz的输出时钟。将UCLK的时钟源选择为PLL2,再进行5倍分频,即可得到usb模块需要的48MHz时钟了。** ![rasc_clocks.png](https://oss-club.rt-thread.org/uploads/20220403/3aec4cf4ab8d7ec604929964d35a5220.png) 然后我们可以在Pins的页面中查看USB_FS0组件的引脚相关设置。根据原理图,需要将`USB_VBUSEN`设置为P500引脚,`USB_OVRCURA`设置为P501引脚,`USB_VBUS`是usbd使用的,用于检测usb是否有供电接入,这里不设置应该也是没关系的。 ![rasc_pins.png](https://oss-club.rt-thread.org/uploads/20220403/9a36e11b9506c4454914f190eed9b7ee.png) 保存点击`Generate Project Content`按钮,RASC会帮我们更新工程中的FSP代码,`ra` 、`ra_cfg`、`ra_gen`三个文件夹的内容会有所改变。下一步是将更新后的FSP代码加入到工程编译。如果项目资源管理器中设置了对不参与构建的文件进行隐藏,那么新文件在项目资源管理器中是看不到的,需要打开导航器,在导航器中对需要加入构建的文件或文件夹点击右键->资源配置->添加构建。我们需要将`ra/fsp/src/r_usb_basic`和`r_usb_hcdc`中的文件加入构建,在`r_usb_basic`的`src`文件夹下还有`driver`和`hw`两个文件夹,都需要加入构建。这时编译会报有头文件找不到,在工程配置中手动添加一个头文件路径即可。 由于rtt还未对这款开发板的usb host进行支持,所以不需要打开rtt设置中的usb主机模式开关,如果打开了,还会有因宏命名与FSP中的重名导致的编译警告。 到这里,前期的配置准备工作就已经完成了,需要开始写代码了。在`src`文件夹下新建一个`usbh_cdc_demo.c`文件用于编写我们的例程。 根据FSP中的API文档介绍,需要一直调用`R_USB_EventGet`接口来保持底层usb驱动栈的正常工作。所以我们创建一个线程来进行这个操作。 ```c int thread_sample_init() { rt_err_t result; /* 初始化线程 1 */ /* 线程的入口是 usb_basic_example,参数是 RT_NULL * 线程栈是 usbh_cdc_demo_stack * 优先级是 20,时间片是 10 个 OS Tick */ result = rt_thread_init(&usbh_cdc_demo, "thread1", usb_basic_example, RT_NULL, &usbh_cdc_demo_stack[0], sizeof(usbh_cdc_demo_stack), 20, 10); /* 启动线程 */ if (result == RT_EOK) rt_thread_startup(&usbh_cdc_demo); return 0; } ``` 在线程中使用一个状态机,根据每次的`event`来进行不同的操作,这也是瑞萨提供的例程的写法。 ```c void usb_basic_example (void* parameter) { usb_status_t event, last_event = 0; usb_event_info_t event_info; g_usb_on_usb.open(&g_basic0_ctrl, &g_basic0_cfg); while (1) { /* Get USB event data */ g_usb_on_usb.eventGet(&event_info, &event); if (last_event != event) { rt_kprintf("%4d UsbEvent %s\n", loop_count++, e_usb_status_msg[event]); last_event = event; } /* Handle the received event (if any) */ switch (event) { case USB_STATUS_CONFIGURED: usbh_event_notify_handler(USBH_EVENT_ATTACHED, event_info.device_address); /* Configure virtual UART settings */ set_line_coding(&g_basic0_ctrl, event_info.device_address); /* CDC Class request "SetLineCoding" */ device_address = event_info.device_address; rt_kprintf("%4d device_address:%d\n", loop_count++, event_info.device_address); break; case USB_STATUS_DETACH: usbh_event_notify_handler(USBH_EVENT_REMOVED, event_info.device_address); device_address = event_info.device_address; rt_kprintf("%4d device_address:%d\n", loop_count++, event_info.device_address); break; case USB_STATUS_READ_COMPLETE: if (USB_CLASS_HCDC == event_info.type) { if (event_info.data_size > 0) { /* Send the received data back to the connected peripheral */ g_usb_on_usb.write(&g_basic0_ctrl, g_snd_buf, event_info.data_size, event_info.device_address); rt_kprintf("%4d usb_cdc rcvget:%s\n", loop_count++, g_rcv_buf); } else { /* Send the data reception request when the zero-length packet is received. */ g_usb_on_usb.read(&g_basic0_ctrl, g_rcv_buf, CDC_DATA_LEN, event_info.device_address); } } else /* USB_HCDCC */ { /* Control Class notification "SerialState" receive start */ g_usb_on_usb.read(&g_basic0_ctrl, (uint8_t *) &g_serial_state, USB_HCDC_SERIAL_STATE_MSG_LEN, event_info.device_address); } break; case USB_STATUS_WRITE_COMPLETE: /* Start receive operation */ g_usb_on_usb.read(&g_basic0_ctrl, g_rcv_buf, CDC_DATA_LEN, event_info.device_address); rt_kprintf("%4d usb_cdc sent done, start read\n", loop_count++); break; case USB_STATUS_REQUEST_COMPLETE: rt_kprintf("%4d request_type %x\n", loop_count++, (event_info.setup.request_type & USB_BREQUEST)); if (USB_CDC_SET_LINE_CODING == (event_info.setup.request_type & USB_BREQUEST)) { /* Set virtual RTS/DTR signal state */ set_control_line_state(&g_basic0_ctrl, event_info.device_address); /* CDC Class request "SetControlLineState" */ } /* Check Complete request "SetControlLineState" */ else if (USB_CDC_SET_CONTROL_LINE_STATE == (event_info.setup.request_type & USB_BREQUEST)) { /* Read back virtual UART settings */ get_line_coding(&g_basic0_ctrl, event_info.device_address); /* CDC Class request "SetLineCoding" */ } else if (USB_CDC_GET_LINE_CODING == (event_info.setup.request_type & USB_BREQUEST)) { /* Now that setup is complete, start loopback operation */ g_usb_on_usb.read(&g_basic0_ctrl, g_snd_buf, CDC_DATA_LEN, event_info.device_address); //g_usb_on_usb.pipeRead(&g_basic0_ctrl, g_snd_buf, CDC_DATA_LEN, USB_PIPE2); } else { /* Unsupported request */ } break; default: /* Other event */ break; } } } ``` 在插入usb设备后,拿到的`event`会变为`USB_STATUS_CONFIGURED`,这时候FSP已经帮我们枚举好了设备,可以直接进行控制。下一步是发送`SetLineCoding`和`SetControlLineState`来配置串口,例如波特率和奇偶校验位等。使用`hostControlTransfer`发起一个控制传输。 ```c void set_line_coding (usb_instance_ctrl_t * p_ctrl, uint8_t device_address) { usb_setup_t setup; g_com_parm.dwdte_rate = (usb_hcdc_line_speed_t) COM_SPEED; g_com_parm.bchar_format = (usb_hcdc_stop_bit_t) COM_STOP_BIT; g_com_parm.bparity_type = (usb_hcdc_parity_bit_t) COM_PARITY_BIT; g_com_parm.bdata_bits = (usb_hcdc_data_bit_t) COM_DATA_BIT; setup.request_type = SET_LINE_CODING; /* bRequestCode:SET_LINE_CODING, bmRequestType */ setup.request_value = 0x0000; /* wValue:Zero */ setup.request_index = 0x0000; /* wIndex:Interface */ setup.request_length = LINE_CODING_LENGTH; /* Data:Line Coding Structure */ /* Request Control transfer */ g_usb_on_usb.hostControlTransfer(p_ctrl, &setup, (uint8_t *) &g_com_parm, device_address); } ``` 所有配置工作都结束后,就可以使用`R_USB_Read`和`R_USB_Write`两个接口来接收和发送串口数据了。简单地在FinSH中添加一个命令来方便我们测试。 ```c void send_msg(int argc, char**argv) { fsp_err_t ret; strcpy((char*)g_snd_buf, argv[1]); memset(g_rcv_buf, 0, 100); ret = g_usb_on_usb.write(&g_basic0_ctrl, g_snd_buf, strlen(argv[1]), device_address); if(ret == FSP_SUCCESS) { rt_kprintf("send ok\n"); } else { rt_kprintf("fail\n"); } } MSH_CMD_EXPORT(send_msg, send_msg); ``` 刚好模板工程中的按键也是开启使用的状态,我们增加一个回调来按键发送串口数据。 ```c void irq_callback_test(void *args) { char *cmdd[2]; char **cmd = cmdd; static int send_count = 0; char cmd_name[] = "send_msg"; static char send[30] = "hello usb cdc"; cmdd[0] = cmd_name; cmdd[1] = send; sprintf(send, "hello usb cdc %4d", send_count++); send_msg(2, cmd); } void icu_sample(void) { /* init */ rt_uint32_t pin = rt_pin_get(USER_INPUT); rt_kprintf("\n pin number : 0x%04X \n", pin); rt_err_t err = rt_pin_attach_irq(pin, PIN_IRQ_MODE_RISING, irq_callback_test, RT_NULL); if(RT_EOK != err) { rt_kprintf("\n attach irq failed. \n"); } err = rt_pin_irq_enable(pin, PIN_IRQ_ENABLE); if(RT_EOK != err) { rt_kprintf("\n enable irq failed. \n"); } } MSH_CMD_EXPORT(icu_sample, icu sample); ``` 编译下载,使用一个micro usb转USB-A的otg连接线,就可以接入一个usb串口设备使用了。刚好手上还有上次参加开发者大会的活动获得的板子,于是在上面简单写了一个usbd_cdc的程序,将它们连接起来。 ![demo_usb.jpg](https://oss-club.rt-thread.org/uploads/20220403/9412f51a6c70f3e35803e29f5b0e0794.jpg.webp) ![IMG_0533.png](https://oss-club.rt-thread.org/uploads/20220403/a67e5197085c19953ba20ed9198340d9.png) #### CheeryUSB 移植尝试 打开RT-Thread Settings,在里面找到`CherryUSB`软件包,添加到工程中,保存后,RT-Thread会自动从github上拉取CheeryUSB的源码放置到`packages/CherryUSB-latest`目录下,然后将需要构建的文件加入到构建中。需要包括`core`、`osal`、`port`、`class`四个文件夹下的文件,其中`core`是协议栈的核心实现部分,`osal`是操作系统抽象层,`port`存放移植需要实现的内容,`class`则是针对不同的usb设备类型编写的驱动代码。`osal/usb_osal_rtthread.c`文件表明`CheeryUSB`对RT-Thread系统是有完善支持的。 ![cherryusb.png](https://oss-club.rt-thread.org/uploads/20220406/4af4e64583d949903e5a1b10bf604b24.png.webp) usb host的部分,`CherryUSB`的作者还没出教程,这部分的文档也还没有,只能继续观察已有的代码来猜测着移植。一开始像直接借助FSP的usb_basic来做移植,直接使用`R_USB_Open`、`R_USB_Read`等API,结果发现FSP已经封装得很好了,细节操作都没暴露出来,把整个设备枚举的过程都隐藏了起来,每个API的操作也都加了很多条件判断,不便于移植。那就只能看寄存器手册,通过直接操作寄存器来完成操作了。 自己对USB协议只能说稍有了解,对`CheeryUSB`和瑞萨系列芯片的寄存器也都不熟悉,移植起来确实非常困难,只能一直读FSP的代码,对着寄存器手册去理解。 后续时间也不充裕,还是没能成功移植`CheeryUSB`,只能再到后面等待其他大佬来搞了。 ## 性能测试 原本想要做的功能是usb hmsc的,也就是可以外接U盘等存储设备,如果是这样的话,就可以进行一些读写测速来测试性能指标了。但是现在换成了usb hcdc,手上现有的usb 串口工具波特率调不到很高,也没有使用DMA来做传输,感觉测试不到最快传输速度,所以这个环节只能略过了。 ## 代码与参考资料 源码已经开源到了github上,感兴趣的同学可以参考。[cpk-ra6m4-usbh-cdc-demo](https://github.com/VxTeemo/cpk-ra6m4-usbh-cdc-demo) [Renesas USB MCU USB Basic Host and Peripheral Driver using.pdf](https://oss-club.rt-thread.org/uploads/20220406/12e477786db53794f1bb48c6c1b66fd9.pdf) [r12uz0090cc0110-ra6m4-manual.pdf](https://oss-club.rt-thread.org/uploads/20220406/bd0c6707ec63aa179b2a337d5dbd2233.pdf) [RA6M4_datasheet.pdf](https://oss-club.rt-thread.org/uploads/20220406/0fa9ca3da04f687db684a4e6f9230725.pdf) [RA6M4_Group_User’s_Manual_Hardware.pdf](https://oss-club.rt-thread.org/uploads/20220406/92c2218e2db4b08cff4b6f34cb61268b.pdf) [CPK-RA6M4 MCU评估板原理图.pdf](https://oss-club.rt-thread.org/uploads/20220406/460d66bee9aa09a6036f302890ebc737.pdf) ## 心得体会 [上次参加开发者大会的时候](https://club.rt-thread.org/ask/article/3250.html),也是用的同一块开发板,现场实现了一个智能网关,最后的笔记本快要没电了,为了充电,是把笔记本放到了有两张椅子并排的一块空间,蹲在地上完成的。这次在家的工作环境竟然也是如此,和之前简直一模一样哈哈哈。 ![share.jpg](https://oss-club.rt-thread.org/uploads/20220406/9b2f2a10e80c65a24bd5e51127772c8f.jpg.webp) 拿到开发板后,感觉领取到的任务还是具有一定挑战性的,首先是usb这个外设并没有现成的驱动,而且我自己对usb协议也不算很熟悉。在摸索了一段时间后,最初的目标是打算做一个usb存储设备的主机,可以用来读取U盘等usb存储设备,在FSP中添加了usb hmsc的栈时发现必须要带操作系统而现在支持的只有FreeRTOS,并且使用的文件系统是FATFS。RT-Thread里面使用的文件系统是elm chan FatFs,尝试加进去之后做下移植,以前只移植过有完善支持的文件系统,对这种情况还是不大处理得了,于是作罢。只能将任务难度降低,先完成一个usb hcdc的例程。 在编写例程的过程中,也去了解了一下[CherryUSB](https://github.com/sakumisu/CherryUSB),这是一个非常优秀的usb device/host驱动,于是便尝试将RA6M4也添加支持。观察了一下工程结构,需要在`port`文件夹下编写移植代码,之前群里也有人说RA6M4的usb IP是叫做`fsdev`,里面确实有这么一个文件夹,只有usb device的实现,里面操作的寄存器和现在这款单片机是对不上的,到处搜了一圈也没有关于`fsdev`和RA6M4 usb IP相关的内容,只能继续凭着感觉移植。 做为一名打工人,这个评测时间刚好卡在了Q1结束需要冲KPI的节点上,后两周实在是抽不出什么时间来继续完善代码,也可以从commit时间看出写代码的时间都非常的阴间,甚至可以看到凌晨三点编译的代码,总体来说这次的评测体验还是非常不错的,希望后面还能继续有机会参加活动。 芯片中还有设计用于存储数据的8KB Data Flash,可以不用将ROM做数据空间使用了,无需外接SPI存储芯片就可以实现方便的非易失数据存储,也不需要考虑和代码共用空间产生的种种问题,甚至还能更好地实现平衡磨损,这个设计还是很不错的。 在RASC中新增了usb的stack之后,rt-thread studio并不能自动识别新增文件并加入到构建中,其他的模块好像是没问题的,不知道是不是usb驱动这边多了一层`hw`和`driver`文件夹的原因。需要手动添加构建就可以解决。 现在大部分设备都已经使用type-c接口了,micro usb的设备越来越少,现在手上有一堆type-c转USB-A的转接头,但是为了这次测试,还是需要另外购买micro usb转USB-A的转接头。micro usb接口相比type-c接口确实是有更稳定、兼容性更强等优点,但个人还是希望能升级到type-c接口
4
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
scoutteemo
这家伙很懒,什么也没写!
文章
3
回答
0
被采纳
0
关注TA
发私信
相关文章
1
RT-Thread Studio USBHOST问题。
2
STM32F407遇到USB读取U盘无法读取问题
3
解决usbhost 无法使用hid设备的问题,
4
usbhost无法设别NTFS格式的U盘吗?
5
stm32f767配置usb host
6
有偿开发基于RT-thread+M3 实现 USB host RNDIS
7
No class register on usb device
8
USB Host 鼠标键盘枚举无法获取HID设备描述符
9
RT-Thread Studio USBHOST
10
USB host设备调试问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
SFUD
msh
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1518
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
549
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
3
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部