mirror of
https://github.com/linux-sunxi/u-boot-sunxi.git
synced 2024-02-12 11:16:03 +08:00
fastboot download speed-up
This commit is contained in:
@ -1076,46 +1076,68 @@ static void fastboot_rx_error(void)
|
||||
*/
|
||||
static int fastboot_rx(void)
|
||||
{
|
||||
int ret = FASTBOOT_INACTIVE;
|
||||
int ret = FASTBOOT_OK;
|
||||
u8 old_ep_index = 0;
|
||||
int err = 1;
|
||||
const unsigned total_download_size = fastboot_interface->total_download_size;
|
||||
unsigned int left_download_size = fastboot_interface->left_download_size;
|
||||
unsigned char* rxBuf = fastboot_fifo_bulk_ep;
|
||||
u32 fifoAddr = 0;
|
||||
u32 recordLen = 0;
|
||||
|
||||
if(total_download_size){//download command data size is 0
|
||||
DMSG_DEBUG("total_download_size=0x%x, left_download_size=0x%x\n", total_download_size, left_download_size);
|
||||
rxBuf = fastboot_interface->transfer_buffer + (total_download_size - left_download_size);
|
||||
}
|
||||
|
||||
old_ep_index = USBC_GetActiveEp(udc.bsp);
|
||||
USBC_SelectActiveEp(udc.bsp, BULK_OUT_EP_INDEX);
|
||||
|
||||
if(USBC_Dev_IsReadDataReady(udc.bsp, USBC_EP_TYPE_RX)){
|
||||
u16 count = 0;
|
||||
u32 fifo = 0;
|
||||
USBC_SelectActiveEp(udc.bsp, BULK_OUT_EP_INDEX);
|
||||
fifoAddr = USBC_SelectFIFO(udc.bsp, BULK_OUT_EP_INDEX);
|
||||
|
||||
while(USBC_Dev_IsReadDataReady(udc.bsp, USBC_EP_TYPE_RX)
|
||||
&& USBC_ReadLenFromFifo(udc.bsp, USBC_EP_TYPE_RX)
|
||||
/*&& left_download_size*/)
|
||||
{
|
||||
u16 fifoCnt = 0;
|
||||
int fifo_size = fastboot_fifo_size();
|
||||
|
||||
ret = FASTBOOT_OK;
|
||||
fifoCnt = USBC_ReadLenFromFifo(udc.bsp, USBC_EP_TYPE_RX);
|
||||
USBC_ReadPacket(udc.bsp, fifoAddr, fifoCnt, rxBuf);
|
||||
|
||||
count = USBC_ReadLenFromFifo(udc.bsp, USBC_EP_TYPE_RX);
|
||||
fifo = USBC_SelectFIFO(udc.bsp, BULK_OUT_EP_INDEX);
|
||||
USBC_ReadPacket(udc.bsp, fifo, count, (void *)fastboot_fifo_bulk_ep);
|
||||
|
||||
if(count > fifo_size){
|
||||
if(fifoCnt > fifo_size){
|
||||
fastboot_rx_error();
|
||||
}else{
|
||||
ReadDataStatusComplete(udc.bsp, USBC_EP_TYPE_RX, 1);
|
||||
ret = FASTBOOT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
ReadDataStatusComplete(udc.bsp, USBC_EP_TYPE_RX, 1);
|
||||
|
||||
/* Pass this up to the interface's handler */
|
||||
if (fastboot_interface &&
|
||||
fastboot_interface->rx_handler) {
|
||||
if(!fastboot_interface->rx_handler(fastboot_fifo_bulk_ep, count)){
|
||||
err = 0;
|
||||
}
|
||||
if (fastboot_interface && fastboot_interface->rx_handler)
|
||||
{
|
||||
if(fastboot_interface->rx_handler(rxBuf, fifoCnt))
|
||||
{
|
||||
ret = FASTBOOT_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(err){
|
||||
DMSG_PANIC("err: rx_handler failed\n");
|
||||
ret = FASTBOOT_ERROR;
|
||||
}
|
||||
if(total_download_size)
|
||||
{
|
||||
fastboot_interface->left_download_size -= fifoCnt;
|
||||
rxBuf += fifoCnt;
|
||||
recordLen += fifoCnt;
|
||||
}
|
||||
/*break;*/
|
||||
}
|
||||
|
||||
if(FASTBOOT_OK != ret){
|
||||
DMSG_PANIC("err: rx_handler failed\n");
|
||||
}
|
||||
|
||||
USBC_SelectActiveEp(udc.bsp, old_ep_index);
|
||||
|
||||
DMSG_DEBUG("recordLen=0x%x\n", recordLen);//how many bytes received in one time
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1734,6 +1756,8 @@ int fastboot_init(struct cmd_fastboot_interface *interface)
|
||||
fastboot_interface->nand_oob_size = 64;
|
||||
fastboot_interface->transfer_buffer = (unsigned char *) FASTBOOT_TRANSFER_BUFFER;
|
||||
fastboot_interface->transfer_buffer_size = FASTBOOT_TRANSFER_BUFFER_SIZE;
|
||||
fastboot_interface->total_download_size = 0;
|
||||
fastboot_interface->left_download_size = 0;
|
||||
|
||||
udc.usb_base = FASTBOOT_USB_BASE;
|
||||
udc.sram_base = FASTBOOT_SRAM_BASE;
|
||||
|
@ -65,6 +65,8 @@
|
||||
#endif
|
||||
#ifdef CONFIG_FASTBOOT
|
||||
|
||||
#define dbg(fmt...) //printf("L%d,", __LINE__),printf(fmt)
|
||||
#define msg(fmt...) printf("FastBot:"fmt)
|
||||
#define MY_DEBUG
|
||||
/* Use do_reset for fastboot's 'reboot' command */
|
||||
extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
|
||||
@ -99,8 +101,8 @@ static struct cmd_fastboot_interface interface =
|
||||
.transfer_buffer_size = 0,
|
||||
};
|
||||
|
||||
static unsigned int download_size;
|
||||
static unsigned int download_bytes;
|
||||
static unsigned int download_size; //Total size to download
|
||||
static unsigned int download_bytes; //size already download
|
||||
static unsigned int download_bytes_unpadded;
|
||||
static unsigned int download_error;
|
||||
static unsigned int continue_booting;
|
||||
@ -804,43 +806,44 @@ static int rx_handler (const unsigned char *buffer, unsigned int buffer_size)
|
||||
{
|
||||
int ret = 1;
|
||||
unsigned char tmp_buffer;
|
||||
char response[65]; /* Use 65 instead of 64 null gets dropped strcpy's need the extra byte */
|
||||
static unsigned _promptSz = 1U<<20;
|
||||
#ifdef DEBUG
|
||||
printf("fast boot rx handle storage_type is %d\n",storage_type);
|
||||
#endif
|
||||
/* Use 65 instead of 64
|
||||
null gets dropped
|
||||
strcpy's need the extra byte */
|
||||
char response[65];
|
||||
|
||||
tmp_buffer=buffer;
|
||||
if (download_size)
|
||||
if (download_size)//RX data should be a download cmd data, or a kind of command
|
||||
{
|
||||
/* Something to download */
|
||||
if (buffer_size)
|
||||
{
|
||||
/* Handle possible overflow */
|
||||
unsigned int transfer_size =
|
||||
download_size - download_bytes;
|
||||
unsigned int transfer_size = download_size - download_bytes;
|
||||
|
||||
if(!download_bytes){
|
||||
_promptSz = ((download_size>>3) < (2U<<20)) ? (download_size>>3) : (2U<<20);//prompt 8 times for each download
|
||||
}
|
||||
|
||||
if (buffer_size < transfer_size)
|
||||
transfer_size = buffer_size;
|
||||
|
||||
/* Save the data to the transfer buffer */
|
||||
memcpy (interface.transfer_buffer + download_bytes,
|
||||
buffer, transfer_size);
|
||||
/*memcpy (interface.transfer_buffer + download_bytes, buffer, transfer_size);FIXME: donn't copy to speed up!!*/
|
||||
|
||||
download_bytes += transfer_size;
|
||||
|
||||
/* Check if transfer is done */
|
||||
if (download_bytes >= download_size) {
|
||||
/* Reset global transfer variable,
|
||||
Keep download_bytes because it will be
|
||||
if (download_bytes >= download_size)
|
||||
{
|
||||
/* Reset global transfer variable, Keep download_bytes because it will be
|
||||
used in the next possible flashing command */
|
||||
download_size = 0;
|
||||
/* The download buffer and cmd buffer is the same one
|
||||
since the partition name ends without a trailing 0 byte
|
||||
we need to clear the buffer after download finished
|
||||
for the next possible command. */
|
||||
/* The download buffer and cmd buffer is the same one since the partition name ends without a trailing 0 byte
|
||||
we need to clear the buffer after download finished for the next possible command. */
|
||||
memset(tmp_buffer, 0, transfer_size);
|
||||
dbg("transfer_size=0x%x\n", transfer_size);
|
||||
interface.total_download_size = interface.left_download_size = 0;
|
||||
|
||||
if (download_error) {
|
||||
/* There was an earlier error */
|
||||
@ -852,62 +855,28 @@ static int rx_handler (const unsigned char *buffer, unsigned int buffer_size)
|
||||
}
|
||||
fastboot_tx_status(response, strlen(response));
|
||||
|
||||
printf ("\ndownloading of %d MB finished\n",
|
||||
download_bytes >> 20);
|
||||
printf ("\ndownloading of %d MB finished\n", download_bytes >> 20);
|
||||
|
||||
#if 0 /* We don't need to pad */
|
||||
#if defined(CONFIG_STORAGE_NAND)
|
||||
/* Pad to block length
|
||||
In most cases, padding the download to be
|
||||
block aligned is correct. The exception is
|
||||
when the following flash writes to the oob
|
||||
area. This happens when the image is a
|
||||
YAFFS image. Since we do not know what
|
||||
the download is until it is flashed,
|
||||
go ahead and pad it, but save the true
|
||||
size in case if should have
|
||||
been unpadded */
|
||||
download_bytes_unpadded = download_bytes;
|
||||
if (interface.nand_block_size)
|
||||
{
|
||||
if (download_bytes %
|
||||
interface.nand_block_size)
|
||||
{
|
||||
unsigned int pad = interface.nand_block_size - (download_bytes % interface.nand_block_size);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < pad; i++)
|
||||
{
|
||||
if (download_bytes >= interface.transfer_buffer_size)
|
||||
break;
|
||||
|
||||
interface.transfer_buffer[download_bytes] = 0;
|
||||
download_bytes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* #if 0 */
|
||||
}
|
||||
|
||||
/* Provide some feedback */
|
||||
if (download_bytes &&
|
||||
0 == (download_bytes %
|
||||
(16 * interface.nand_block_size)))
|
||||
download_bytes >= _promptSz)
|
||||
{
|
||||
/* Some feeback that the
|
||||
download is happening */
|
||||
/* Some feeback that the download is happening */
|
||||
if (download_error)
|
||||
printf("X\n");
|
||||
else
|
||||
printf("downloading %d MB ...\r", download_bytes >> 20);
|
||||
{
|
||||
printf("Downloading %d MB ...\r", download_bytes >> 20);
|
||||
_promptSz += ((download_size>>3) > (2U<<20)) ? (2U<<20) :(download_size>>3);//prompt 8 times for each download
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ignore empty buffers */
|
||||
printf ("Warning empty download buffer\n");
|
||||
printf ("Ignoring\n");
|
||||
printf ("Warning:Ignoring empty download buffer\n");
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
@ -1022,11 +991,8 @@ static int rx_handler (const unsigned char *buffer, unsigned int buffer_size)
|
||||
download_bytes = 0;
|
||||
/* Reset error */
|
||||
download_error = 0;
|
||||
#ifdef MY_DEBUG
|
||||
printf("download_size = %d\n", download_size);
|
||||
#endif
|
||||
|
||||
printf ("Starting download of %d MB\n", download_size >> 20);
|
||||
msg("Starting download of %d MB\n", download_size >> 20);
|
||||
|
||||
if (0 == download_size)
|
||||
{
|
||||
@ -1044,6 +1010,8 @@ static int rx_handler (const unsigned char *buffer, unsigned int buffer_size)
|
||||
/* The default case, the transfer fits
|
||||
completely in the interface buffer */
|
||||
sprintf(response, "DATA%08x", download_size);
|
||||
interface.total_download_size = interface.left_download_size = download_size;
|
||||
dbg("download_size = 0x%xBytes\n", download_size);
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
@ -1616,9 +1584,9 @@ int do_fastboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
if (2 == argc) {
|
||||
long try_seconds;
|
||||
char *try_seconds_end;
|
||||
|
||||
/* Check for timeout */
|
||||
try_seconds = simple_strtol(argv[1],
|
||||
&try_seconds_end, 10);
|
||||
try_seconds = simple_strtol(argv[1], &try_seconds_end, 10);
|
||||
if ((try_seconds_end != argv[1]) &&
|
||||
(try_seconds >= 0)) {
|
||||
check_timeout = 1;
|
||||
@ -1648,7 +1616,8 @@ int do_fastboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
timeout_endtime = get_ticks();
|
||||
timeout_endtime += timeout_ticks;
|
||||
|
||||
while (1) {
|
||||
while (1)
|
||||
{
|
||||
uint64_t current_time = 0;
|
||||
poll_status = fastboot_poll();
|
||||
|
||||
|
@ -146,7 +146,8 @@ struct cmd_fastboot_interface
|
||||
|
||||
Set by board */
|
||||
unsigned int transfer_buffer_size;
|
||||
|
||||
unsigned int total_download_size;//in bytes, store length in "downlad command"
|
||||
unsigned int left_download_size;//in bytes, store length not downladed yet, should always <= total_download_size
|
||||
};
|
||||
|
||||
/* Android-style flash naming */
|
||||
|
Reference in New Issue
Block a user