USB是目前最常用的PC外围接口,现在已经有不少的MCU已经内置了USB的SIE。虽然480M的HighSpeed接口不多,但也基本上都可以做到12M的FullSpeed接口,对于一般的应用可以满足了。但USB接口如果协议处理的不好的话,速度甚至可能比串口还要慢。这里就介绍一下如何定义USB协议,以达到更快的效率。
【理论依据】
对于可靠的传输的话,对快的速度就是使用批量传输了。理论上,1ms内,FullSpeed的USB接口可以传输最多1023字节的数据。但是,如果只传输一个字节的数据的话,使用的时间也同样是1ms。所以,竟可能地使用大数据包,是有效利用USB带宽的不二法宝。当然,这就要求USB设备具有足够大的缓冲RAM,而现在的ARM芯片基本上都具有比较丰富的RAM资源。
【USB协议】
这里拿Versaloon的USB_TO_SPI接口做的51编程器作为例子。
对于设备,需要能够一次处理很多操作的能力,命令处理函数可以这样实现:
index = 0; while(index < len) { command = dat[index++]; switch(command) { case USB_TO_XXX_INIT: ...... case USB_TO_XXX_CONFIG: ...... case USB_TO_XXX_FINI: ...... case USB_TO_XXX_IN_OUT: ...... } index += command_data_length; }<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> |
当收到一个命令包时,设备会一直解析命令,并执行。这样,就可以在一个命令包中放尽可能多的命令。
【上位机处理】
上位机需要做的就是收集需要执行的操作,等到必须有一个返回结果的时候,才发送命令。
下面是使用字节方式,对S51执行ISP的字节方式编程的代码:
j = 0; for(i = addr_start; i < addr_end; i++) { cmd_buf[0] = 0x40; cmd_buf[1] = (uint8)(i >> 8); cmd_buf[2] = (uint8)(i >> 0); cmd_buf[3] = s5x_flash_buffer; spi_io(cmd_buf, 4, NULL, 0, 0); delay_us(s5x_flash_byte_delay_us);
j++; if((j >= s5x_chip_param.flash_page_size) || (i == (addr_end - 1))) { if(ERROR_OK != commit()) { LOG_ERROR("fail to program flash in byte mode\n"); ret = ERROR_FAIL; goto leave_program_mode; } j = 0; } } |
其中:spi_io只是用于收集要执行的命令,并不会发送相应的USB命令。当足够多的命令收集完之后(这里是大于S51一个页的数据对应的SPI操作命令),才调用commit,这个函数就是把缓冲的命令一次性的发给设备,并读取设备的执行结果。
实际测试下来,对S51的执行ISP编程时,使用字节方式和使用页方式,速度上差别非常小。这就是因为,USB传输的时间要比正真执行操作的时间要多,提高USB传输的效率,比提高执行SPI操作的效率来的更加有效。
结果(4016字节):
用户1482250 2010-7-8 22:10
用户131114 2008-11-5 22:35
用户131114 2008-11-5 22:31
用户75050 2008-11-5 22:00
用户131114 2008-11-4 20:02