前面我們實現了SPIFLASH的讀寫,現在我們繼續添加功能,移植xmodem,實現片內mem的導入導出,SPI FLASH的導入導出。這樣我們就可dump出片內RAM和FLASH的內容,同時也可以導入; 可以導出SPI FLASH的內容,同時也可以導入。這樣即可實現自由的進行鏡像的下載修改等操作。
代碼見:https://github.com/qinyunti/stm32f429-boot.git
我們依舊使用之前積累的輪子,參見
https://mp.weixin.qq.com/s/QSYKxND3DTyQZ0JtnSqkzQ XMODEM協議介紹與高效高可移植非阻塞版本實現
具體代碼見xmodem.c/h
shell_func.c中添加函數聲明
static void rxmemfunc(uint8_t* param);static void sxmemfunc(uint8_t* param);
g_shell_cmd_list_ast中添加兩個命令行
{ (uint8_t*)"rxmem", rxmemfunc, (uint8_t*)"rxmem addr[hex] len"},{ (uint8_t*)"sxmem", sxmemfunc, (uint8_t*)"sxmem addr[hex] len"},
實現如下
static uint8_t rxtx_buf[1029];static uint32_t getms(void){return get_ticks();}static uint32_t io_read(uint8_t* buffer, uint32_t len){return uart_read(1,buffer, len);}static void io_read_flush(void){uint8_t tmp;while(0 != uart_read(1,&tmp, 1));}static uint32_t io_write(uint8_t* buffer, uint32_t len){uart_send(1,buffer, len);return len;}static uint32_t mem_read(uint32_t addr, uint8_t* buffer, uint32_t len){memcpy(buffer, (uint8_t*)addr, len);return len;}static uint32_t mem_write(uint32_t addr, uint8_t* buffer, uint32_t len){memcpy((uint8_t*)addr, buffer, len);return len;}static void rxmemfunc(uint8_t* param){uint32_t addr;uint32_t len;int res = 0;if(2 == sscanf((const char*)param, "%*s %x %d", &addr, &len))char* p =(char*)param;while(1){ /* 跳過%*s部分 */if((*p > 'z') || (*p < 'a')){break;}else{p++;}}long tmp;xatoi(&p, &tmp);addr = tmp;xatoi(&p, &tmp);len = tmp;{xprintf("rxmem to 0x%x %d\r\n",addr,len);xmodem_cfg_st cfg={.buffer = rxtx_buf,.crccheck = 1,.getms = getms,.io_read = io_read,.io_read_flush = io_read_flush,.io_write = io_write,.start_timeout = 60,.packet_timeout = 1000,.ack_timeout = 1000,.mem_write = mem_write,.addr = addr,.totallen = len,};xmodem_init_rx(&cfg);while((res = xmodem_rx()) == 0);xprintf("res:%d\r\n",res);}}static void sxmemfunc(uint8_t* param){uint32_t addr;uint32_t len;int res = 0;if(2 == sscanf((const char*)param, "%*s %x %d", &addr, &len))char* p =(char*)param;while(1){ /* 跳過%*s部分 */if((*p > 'z') || (*p < 'a')){break;}else{p++;}}long tmp;xatoi(&p, &tmp);addr = tmp;xatoi(&p, &tmp);len = tmp;{xprintf("sxmem to 0x%x %d\r\n",addr,len);xmodem_cfg_st cfg={.buffer = rxtx_buf,.plen = 1024,.getms = getms,.io_read = io_read,.io_read_flush = io_read_flush,.io_write = io_write,.start_timeout = 60,.packet_timeout = 1000,.ack_timeout = 5000,.mem_read = mem_read,.addr = addr,.totallen = len,};xmodem_init_tx(&cfg);while((res = xmodem_tx()) == 0);xprintf("res:%d\r\n",res);}}
測試
導入一個文件到0x90000000處
rxmem 0x90000000 778028

然后再導出
sxmem 0x90000000 778028

對比導入導出的文件
可以看到完全一樣,除了導出時按照xmodem協議最后不足一包大小填充了0x1A

shell_func.c中添加函數聲明
static void rxspiflashfunc(uint8_t* param);static void sxspiflashfunc(uint8_t* param);
g_shell_cmd_list_ast中添加兩個命令行
{ (uint8_t*)"rxspiflash", rxspiflashfunc, (uint8_t*)"rxspiflash addr[hex] len"},{ (uint8_t*)"sxspiflash", sxspiflashfunc, (uint8_t*)"sxspiflash addr[hex] len"},
實現如下
static uint32_t flash_read(uint32_t addr, uint8_t* buffer, uint32_t len){flash_itf_read(buffer, addr, len);return len;}static uint32_t flash_write(uint32_t addr, uint8_t* buffer, uint32_t len){flash_itf_write(buffer, addr, len);return len;}static void rxspiflashfunc(uint8_t* param){uint32_t addr;uint32_t len;int res = 0;if(2 == sscanf((const char*)param, "%*s %lx %d", &addr, &len))char* p =(char*)param;while(1){ /* 跳過%*s部分 */if((*p > 'z') || (*p < 'a')){break;}else{p++;}}long tmp;xatoi(&p, &tmp);addr = tmp;xatoi(&p, &tmp);len = tmp;{xmodem_cfg_st cfg={.buffer = rxtx_buf,.crccheck = 1,.getms = getms,.io_read = io_read,.io_read_flush = io_read_flush,.io_write = io_write,.start_timeout = 60,.packet_timeout = 1000,.ack_timeout = 1000,.mem_write = flash_write,.addr = addr,.totallen = len,};xmodem_init_rx(&cfg);while((res = xmodem_rx()) == 0);xprintf("res:%d\r\n",res);}}static void sxspiflashfunc(uint8_t* param){uint32_t addr;uint32_t len;int res = 0;if(2 == sscanf((const char*)param, "%*s %lx %d", &addr, &len))char* p =(char*)param;while(1){ /* 跳過%*s部分 */if((*p > 'z') || (*p < 'a')){break;}else{p++;}}long tmp;xatoi(&p, &tmp);addr = tmp;xatoi(&p, &tmp);len = tmp;{xmodem_cfg_st cfg={.buffer = rxtx_buf,.plen = 1024,.getms = getms,.io_read = io_read,.io_read_flush = io_read_flush,.io_write = io_write,.start_timeout = 60,.packet_timeout = 1000,.ack_timeout = 1000,.mem_read = flash_read,.addr = addr,.totallen = len,};xmodem_init_tx(&cfg);while((res = xmodem_tx()) == 0);xprintf("res:%d\r\n",res);}}
測試
導入一個文件到spiflash 0位置處
rxspiflash 0 11797

然后導出
sxspiflash 0 11797

對比導入導出,除了最后一點xmodem包不足時填充不一樣其他都完全一樣

得益于我們積累的輪子,所以很快就可以移植xmodem,實現片內mem和spi flash的導入導出。具備該能力之后我們就可以方便的導入導出片內mem用于調試等,以及方便的導入導出SPIFLASH實現燒錄鏡像等功能。