Closed harbaum closed 1 year ago
Many echi cpu works fine, check it by yourself
I am not sure I understand you correctly.
So the BL616 EHCI host is not supported and problems like this will not be addressed? And you suggest to use a different MCU or to fix any issues myself, correct?
Which MCU would you suggest to use with cherryUSB in host mode?
No problem in BL616, and others like d1s/hpm6750 and so on with ehci.Just check by yourself.
I am checking this myself. This report is a result of tests with real hardware. I use a BL616 in host mode with various USB devices as I am going to decide if we build a device based on that chip
Most USB host tests are unstable. Some very basic tests work. That's how I did the joystick demo: https://m.youtube.com/shorts/Z1DRsI0xd8o
But hubs, mass storage and even some joysticks run into timeouts.
I am checking real hardware and would like to understand if the BL616 is supported in a way that we can base a project on it.
So what do you mean by "check it yourself" other than using the BL616 to do tests with real USB devices?
I do not want to waste my time on these unofficial board, no one knows if the board usb is ok, so solve by yourself.
I do not want to waste my time on these unofficial board, no one knows if the board usb is ok, so solve by yourself.
Ah ... now we are getting somewhere. This is some internal conflict between Bouffalo and SiPeed. Interesting. So only Bouffalo's own dev kit is supported? This would mean that we cannot use the BL616 for our own designs, since there won't be any support then?
BTW: The delay actually doesn't hurt as much as expected. I copied your SD card test over to the USB demo and get these results with my delay in place:
[I/USB] EHCI HCIVERSION:0100
[I/USB] EHCI HCSPARAMS:000001
[I/USB] EHCI HCCPARAMS:0006
[I/USB] New high-speed device on Hub 1, Port 1 connected
[I/USB] New device found,idVendor:054c,idProduct:0243,bcdDevice:0100
[I/USB] The device has 1 interfaces
[I/USB] Enumeration success, start loading class driver
[I/USB] Loading msc class driver
[I/USB] Get max LUN:1
[I/USB] Ep=81 Attr=02 Mps=512 Interval=255 Mult=00
[I/USB] Ep=02 Attr=02 Mps=512 Interval=255 Mult=00
[I/USB] Capacity info:
[I/USB] Block num:7831552,block size:512
[I/USB] Register MSC Class:/dev/sda
[I/USB] ******************** be about to write test... **********************
[I/USB] Write Test Succeed!
[I/USB] Single data size:32768 Byte, Write the number:1024, Total size:32768 KB
[I/USB] Time:9846ms, Write Speed:3328 KB/s
[I/USB] ******************** be about to read test... **********************
[I/USB] Read Test Succeed!
[I/USB] Single data size:32768Byte, Read the number:1024, Total size:32768 KB
[I/USB] Time:4289ms, Read Speed:7640 KB/s
[I/USB] ******************** be about to check test... **********************
[I/USB] Check Test Succeed!
[I/USB] All Data Is Good!
3.3MBytes/s writing and 7.6 MBytes/s reading doesn't sound too bad for some cheap little microcontroller.
BTW: What is the official board for the BL616? I see someone testing a BL616DK at https://codingfield.com/blog/2023-01/getting-started-with-bl618dk/, but that seems to be in fact a BL618 and I don't see where this can be purchased nor are there any schematics, so I cannot compare the USB implementation of the official board with the unofficial one from SiPeed.
Furthermore, I doubt that this is a hardware issue, as this tiny delay makes everything work way more reliable. Without delay, the system won't barely see the flash drive at all. With delay, it reads and writes 32 MBytes without any trouble.
You can design sch and pcb by yourself, m0s dock is designed only for debugger.
I don't understand that. What kind of debugger?
cklink, daplink, usb2uart
You can flash the M0S dock without any debugger and just flash it via USB as I explain e.g. at https://github.com/harbaum/Pacman-TangNano9k/tree/main/m0sdock_usb_joystick
Would you consider the Ai-M62-12F a valid device and accept feedback for it? Full specs.
I really like to test the stuff before designing a new device.
I mean that M0s is only a usb device, its function is a debugger or a usb2uart, thanks, please stop for this issue.
I'll stop now. Just to make this clear: There is no BL616 based board that I could use and get cherryusb support for, right? If there is one, then please tell me. The BL616 seems to have much potential and it seems to be one of the few cheap chips that can do high speed USB. But without support this chip is of course way less useful.
Hi, i have updated ehci driver just now, you can have a tryand copy them to sdk to see if it works or not. PS: if you want to use usb host, recommand you to use ai-thinker board.
Thanks a lot. I recently received the ai thinker boards and will give the updated version a try asap ...
I just tested on the M0S and now USB host isn't working at all, anymore. No events are reported. And adding my old delay also doesn't help.
I tried a) using the entire latest cherryusb from github master and b) using only the latest ehci from github master. This makes no difference. Neither works.
I'll try again on Monday using the AI Thinker board instead of the M0S.
Thanks for your support!
If there's anything I can help in debugging, please say so.
I think it is your incorrect copying....
please do not modify usb_config in bouffalo sdk, it is not a standard ehci. Only copy files in ehci directory, all of our ehci chips like hpm,nuc,d1 are all ok.
Ok, i know what is wrong, please modify CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
in usb_config.h, in bouffalo_sdk it is CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
, it is a spelling error.
If you have other problems, you can contact my twitter, maybe solve problems more quickly.
Ok, i know what is wrong, please modify
CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
in usb_config.h, in bouffalo_sdk it isCONFIG_USB_ECHI_HCOR_RESERVED_DISABLE
, it is a spelling error.
Ah! Yes, now it works without my delay patch. Great. The simple demos from the SDK now work.
I have ported the more complex fatfs test from the SD card demo to the USB host demo. I do see sporadic write errors in the big file there. The SD card has a very similar problem but when reading (writing seems to work fine with SD card). See https://github.com/bouffalolab/bouffalo_sdk/issues/170
Since the errors are very similar (chunks 32 bytes get lost during reading from SD card and during writing to USB stick) I think this is not an issue with USB, but with the BL616 in general. So I won't bother you with that.
If you have other problems, you can contact my twitter, maybe solve problems more quickly
I don't have a twitter account. Do you use discord?
Sorry, i do not have and join for some reason. Maybe only in github, could you give my repo a star and push some issues here, i feel sorry for only this way.
No problem. I gave this repo a star.
This is the code for the updated usb_host.c demo from the bouffalo SDK which will do extensive USB file testing and finally fail. I can open an issue for this (is this what you mean by "push some issues"?).
But as I said, I see the same problem with the SD card, so I don't think it's a USB specific issue. It is either a problem with the SDK in general or with the BL616 itself.
#include "usbh_core.h"
#include "usbh_msc.h"
#include "ff.h"
#include "diskio.h"
USB_NOCACHE_RAM_SECTION FATFS fs;
USB_NOCACHE_RAM_SECTION FIL fnew;
UINT fnum;
FRESULT res_msc = 0;
int MSC_disk_status() { return 0; }
int MSC_disk_initialize() { return 0; }
int MSC_disk_read(BYTE *buff, LBA_t sector, UINT count) {
struct usbh_msc *msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
// USB_LOG_INFO("MSC_disk_read(%p,%d,%d)\r\n", buff, sector, count);
return usbh_msc_scsi_read10(msc_class, sector, buff, count);
}
int MSC_disk_write(const BYTE *buff, LBA_t sector, UINT count) {
struct usbh_msc *msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
// USB_LOG_INFO("MSC_disk_write(%p,%d,%d)\r\n", buff, sector, count);
return usbh_msc_scsi_write10(msc_class, sector, buff, count);
}
int MSC_disk_ioctl(BYTE cmd, void *buff) {
USB_LOG_INFO("MSC_disk_ioctl(%d,%p)\r\n", cmd, buff);
switch (cmd) {
// Get R/W sector size (WORD)
case GET_SECTOR_SIZE:
break;
// Get erase block size in unit of sector (DWORD)
case GET_BLOCK_SIZE:
break;
case GET_SECTOR_COUNT:
break;
case CTRL_SYNC:
break;
default:
break;
}
return 0;
}
DSTATUS Translate_Result_Code(int result)
{
return result;
}
#define SDU_DATA_CHECK 1
char test_data[512] =
"I've been reading books of old \r\n\
The legends and the myths \r\n\
Achilles and his gold \r\n\
Hercules and his gifts \r\n\
Spiderman's control \r\n\
And Batman with his fists \r\n\
And clearly I don't see myself upon that list\r\n\
But she said, where'd you wanna go?\r\n\
How much you wanna risk?\r\n\
I'm not looking for somebody\r\n\
With some superhuman gifts\r\n\
Some superhero\r\n\
Some fairytale bliss\r\n\
Just something I can turn to\r\n\
Somebody I can kiss\r\n\
I want something just like this\r\n\r\n";
BYTE RW_Buffer[32 * 1024] = { 0 };
#if SDU_DATA_CHECK
BYTE Check_Buffer[sizeof(RW_Buffer)] = { 0 };
#endif
static void hexdump(const unsigned char *buf, int len) {
static const char hexdigits[] = "0123456789abcdef";
char str[68];
int i;
if (!len) return;
for (i = 0; i < len; i++) {
str[((i % 16) * 3) + 0] = hexdigits[buf[i] >> 4];
str[((i % 16) * 3) + 1] = hexdigits[buf[i] & 0xf];
str[((i % 16) * 3) + 2] = ' ';
str[(i % 16) + 49] = isprint(buf[i]) ? buf[i] : '.';
if ((i + 1) % 16 == 0) {
str[47] = ' ';
str[48] = ' ';
str[65] = '\0';
printf("%08x%-2c%s\r\n", i-15, ' ', str);
str[0] = ' ';
}
}
}
int usb_msc_fatfs_test()
{
uint32_t time_node, i, j;
FRESULT ret;
FATFS_DiskioDriverTypeDef MSC_DiskioDriver = { NULL };
MSC_DiskioDriver.disk_status = MSC_disk_status;
MSC_DiskioDriver.disk_initialize = MSC_disk_initialize;
MSC_DiskioDriver.disk_write = MSC_disk_write;
MSC_DiskioDriver.disk_read = MSC_disk_read;
MSC_DiskioDriver.disk_ioctl = MSC_disk_ioctl;
MSC_DiskioDriver.error_code_parsing = Translate_Result_Code;
disk_driver_callback_init(DEV_USB, &MSC_DiskioDriver);
res_msc = f_mount(&fs, "/usb", 1);
if (res_msc != FR_OK) {
USB_LOG_RAW("mount fail,res:%d\r\n", res_msc);
return -1;
}
/* full test data to buff */
for (uint32_t size = 0; size < sizeof(RW_Buffer); size += sizeof(test_data)) {
memcpy(&RW_Buffer[size], test_data, sizeof(test_data));
#if SDU_DATA_CHECK
memcpy(&Check_Buffer[size], test_data, sizeof(test_data));
#endif
}
#if 1
/* write test */
USB_LOG_INFO("\r\n");
USB_LOG_INFO("******************** be about to write test... **********************\r\n");
ret = f_open(&fnew, "/usb/test_file_2.txt", FA_CREATE_ALWAYS | FA_WRITE);
if (ret == FR_OK) {
time_node = (uint32_t)bflb_mtimer_get_time_ms();
/*write into file*/
// ret = f_write(&fnew, RW_Buffer, 1024, &fnum);
for (i = 0; i < 1024; i++) {
ret = f_write(&fnew, RW_Buffer, sizeof(RW_Buffer), &fnum);
if (ret) {
break;
}
}
/* close file */
ret |= f_close(&fnew);
/* get time */
time_node = (uint32_t)bflb_mtimer_get_time_ms() - time_node;
if (ret == FR_OK) {
USB_LOG_INFO("Write Test Succeed! \r\n");
USB_LOG_INFO("Single data size:%d Byte, Write the number:%d, Total size:%d KB\r\n", sizeof(RW_Buffer), i, sizeof(RW_Buffer) * i >> 10);
USB_LOG_INFO("Time:%dms, Write Speed:%d KB/s \r\n", time_node, ((sizeof(RW_Buffer) * i) >> 10) * 1000 / time_node);
} else {
USB_LOG_ERR("Fail to write files(%d) num:%d\n", ret, i);
goto unmount;
}
} else {
USB_LOG_ERR("Fail to open or create files: %d.\r\n", ret);
goto unmount;
}
#endif
#if 1
/* read test */
USB_LOG_INFO("\r\n");
USB_LOG_INFO("******************** be about to read test... **********************\r\n");
ret = f_open(&fnew, "/usb/test_file.txt", FA_OPEN_EXISTING | FA_READ);
if (ret == FR_OK) {
time_node = (uint32_t)bflb_mtimer_get_time_ms();
// ret = f_read(&fnew, RW_Buffer, 1024, &fnum);
for (i = 0; i < 1024; i++) {
ret = f_read(&fnew, RW_Buffer, sizeof(RW_Buffer), &fnum);
if (ret) {
break;
}
}
/* close file */
ret |= f_close(&fnew);
/* get time */
time_node = (uint32_t)bflb_mtimer_get_time_ms() - time_node;
if (ret == FR_OK) {
USB_LOG_INFO("Read Test Succeed! \r\n");
USB_LOG_INFO("Single data size:%dByte, Read the number:%d, Total size:%d KB\r\n", sizeof(RW_Buffer), i, sizeof(RW_Buffer) * i >> 10);
USB_LOG_INFO("Time:%dms, Read Speed:%d KB/s \r\n", time_node, ((sizeof(RW_Buffer) * i) >> 10) * 1000 / time_node);
} else {
USB_LOG_ERR("Fail to read file: (%d), num:%d\n", ret, i);
goto unmount;
}
} else {
USB_LOG_ERR("Fail to open files.\r\n");
goto unmount;
}
#endif
/* check data */
#if SDU_DATA_CHECK
USB_LOG_INFO("\r\n");
USB_LOG_INFO("******************** be about to check test... **********************\r\n");
ret = f_open(&fnew, "/usb/test_file_2.txt", FA_OPEN_EXISTING | FA_READ);
if (ret == FR_OK) {
for (i = 0; i < 1024; i++) {
memset(RW_Buffer, 0x55, sizeof(RW_Buffer));
ret = f_read(&fnew, RW_Buffer, sizeof(RW_Buffer), &fnum);
if (ret) break;
for (j = 0; j < sizeof(RW_Buffer); j++) {
if (RW_Buffer[j] != Check_Buffer[j]) {
break;
}
}
if (j < sizeof(RW_Buffer)) {
break;
}
}
/* close file */
ret |= f_close(&fnew);
if (ret == FR_OK) {
if (i < 1024 || j < sizeof(RW_Buffer)) {
USB_LOG_INFO("Check Test Error! \r\n");
USB_LOG_INFO("Data Error! Num:%d/1024, Byte:%d($%04x)/%d\r\n", i, j, j, sizeof(RW_Buffer));
hexdump(RW_Buffer, 32768);
// hexdump(Check_Buffer, 32768);
} else {
USB_LOG_INFO("Check Test Succeed! \r\n");
USB_LOG_INFO("All Data Is Good! \r\n");
}
} else {
USB_LOG_ERR("Fail to read file: (%d), num:%d\n", ret, i);
goto unmount;
}
} else {
USB_LOG_ERR("Fail to open files.\r\n");
goto unmount;
}
#endif
f_mount(NULL, "/usb", 1);
return 0;
unmount:
f_mount(NULL, "/usb", 1);
return -1;
}
static void usbh_msc_thread(void *argument)
{
int ret;
struct usbh_msc *msc_class;
while (1) {
// clang-format off
find_class:
// clang-format on
msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
if (msc_class == NULL) {
USB_LOG_RAW("do not find /dev/sda\r\n");
usb_osal_msleep(2000);
continue;
}
usb_msc_fatfs_test();
while (1) {
msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
if (msc_class == NULL) {
goto find_class;
}
usb_osal_msleep(2000);
}
}
}
void usbh_msc_run(struct usbh_msc *msc_class) { }
void usbh_msc_stop(struct usbh_msc *msc_class) { }
void usbh_class_test(void) {
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, NULL);
}
I think it is cache problem, and you should set USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX before RW_Buffer, at least usb host need. You can refer to my demo, it is a limitation.
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX RW_Buffer[32*1024];
And i must say, all of buffer for usb, must be in nocache ram section, thanks.
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_write_buffer[25 * 100];
USB_NOCACHE_RAM_SECTION FATFS fs;
USB_NOCACHE_RAM_SECTION FIL fnew;
And MSC_disk_ioctl must be implemented for GET_SECTOR_SIZE , GET_SECTOR_SIZE and GET_SECTOR_COUNT.
Using a small no-cache transfer buffer makes the MSC demo work with full filesystem support and ends in a successful 32MB read/write test.
Thanks a lot!
Using
bflb_l1c_dcache_clean_range((void *)(RW_Buffer), sizeof(RW_Buffer));
and
bflb_l1c_dcache_invalidate_range((void *)(RW_Buffer), sizeof(RW_Buffer));
works even better and has much less impact on the performance.
Right, with cache, you must do these. But many users do not know cache, this is why exists nocache ram.
How long is a cache line on the BL616? Sometimes you align to 32 bytes (e.g. in the USB) and sometimes to 64 bytes (e.g. in SDH).
How long is a cache line on the BL616? Sometimes you align to 32 bytes (e.g. in the USB) and sometimes to 64 bytes (e.g. in SDH).
Cache line 32, so set 32 or 64 is ok, just you like.
I do see many timeouts when using the USB host on a BL616. This can be "fixed" by adding a delay to EHCI usbh_submit_urb() like so:
This makes the setup stable and e.g. running FATFS on top of MSC just works fine. But I am sure this delay is not a good solution and this will sure have a massive negative impact on performance.
I am seeing this on the current master, integrated into the latest bouffalo SDK.
Example usbhost with fatfs enabled. Without this delay:
With the delay: