STM32 W5500 OTA功能 - bootloader及app的設計和實現
A bootloader that supports OTA with W5500.
Advantages of Bootloader with TCP/IP Support
Developing a bootloader with TCP/IP support offers several advantages:
Firmware Management via Network:
- TCP/IP facilitates efficient firmware updates through network connections.
- It enables streamlined management and updates of firmware located remotely.
Remote Monitoring:
- Utilizing TCP/IP features in the bootloader allows for remote monitoring and debugging of devices.
- Real-time access to logs, sensor data, and device status is possible remotely.
Challenges in Implementing TCP/IP in General Bootloaders
Code Size:
- Bootloaders are primarily designed for firmware updates and booting processes, necessitating a small code size.
- TCP/IP stacks are complex and require a substantial codebase, making integration into small bootloaders challenging.
Memory Constraints:
- Bootloaders often operate within limited memory space.
- TCP/IP stacks consume significant memory, posing difficulties in fitting them into constrained bootloader environments.
Feasibility of Developing a TCP/IP-enabled Bootloader with W5500
Built-in TCP/IP:
- W5500 embeds a hardware-based TCP/IP stack, offering convenient features that might be challenging to implement with additional software.
- Leveraging the built-in stack enables the integration of TCP/IP functionality into bootloaders with minimal code and memory footprint.
Implementation with Minimal Memory and Code:
- Using W5500's hardware stack allows developers to minimize code size and memory usage in the bootloader.
- Hardware stacks are generally more efficient and support faster data transmission compared to software implementations.
Developing a TCP/IP-enabled bootloader with W5500 not only streamlines network-based firmware management and remote monitoring but also ensures efficient operation in environments with limited memory resources.
Bootloader Test Code
typedef void (*pFunction)(void);
pFunction Jump_To_Bootloader;
uint32_t JumpAddress;
void func_jump2bootloader(void)
{
if (((*(__IO uint32_t*)FLASH_BASE_ADDR) & 0x2FFC0000 ) == 0x20000000)
{
__disable_irq();
JumpAddress = *(__IO uint32_t*) (FLASH_BASE_ADDR + 4);
Jump_To_Bootloader = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) FLASH_BASE_ADDR);
Jump_To_Bootloader();
}
}
void func_led_onoff_cross(void);
void func_led_onoff_sametime(void);
void func_custom_http_downloading_file_save(u8 state, u8 pageno, u8* cache, u32 len_cache_cont)//pageno start from 1
{
// func_usart2_dma_send_bytes(cache, len_cache_cont);
if(state == 0)//downloading
{
//write FLASH Backup file content
func_flash_write_datas(FLASH_APPBACKUP_ADDR + (pageno-1)*2048, (u16*)cache, SIZE_DOWNLOAD_CACHE/2);
}
else if(state == 1)//done
{
//write FLASH Backup file content
func_flash_write_datas(FLASH_APPBACKUP_ADDR + (pageno-1)*2048, (u16*)cache, (len_cache_cont%2) == 0 ? (len_cache_cont/2) : (len_cache_cont/2+1));
//write FLASH Record
{
u16 arrs[4];
u32 downloadsize = (pageno-1)*SIZE_DOWNLOAD_CACHE + len_cache_cont;
arrs[0] = 2;
arrs[1] = 0xFFFF;
arrs[2] = downloadsize >> 16;
arrs[3] = (u16)downloadsize;
func_flash_write_datas(FLASH_RECORD_ADDR, arrs, 4);
}
}
}
u8 buf[2048];
int main()
{
u8 state_k1_init;
u8 mac[6]={0, };
DHCP_Get dhcp_get;
//FIXME your file server ip
u8 srv_ip[] = {192, 168, 1, 109};
u16 srv_port = 8888;
NVIC_SetVectorTable(NVIC_VectTab_FLASH, (FLASH_APPCODE_ADDR - FLASH_BASE_ADDR));
init_led();
init_switchkeys();
init_system_spi();
func_w5500_reset();
// init_hardware_usart2_dma(115200);
getMacByLockCode(mac);
setSHAR(mac);
sysinit(txsize, rxsize);
setRTR(2000);
setRCR(3);
state_k1_init = func_get_switchkey1();
//USART DMA problem: 2 bytes missing
// func_usart2_dma_send_bytes(mac, 2);
// delay_ms(100);
//hook
init_hooks_http_download_file_save(func_custom_http_downloading_file_save);
//DHCP
for(;func_dhcp_get_ip_sub_gw(buf, sizeof(buf), 1, mac, &dhcp_get, 500) != 0;);
if(func_dhcp_get_ip_sub_gw(buf, sizeof(buf), 1, mac, &dhcp_get, 500) == 0)
{
setSUBR(dhcp_get.sub);
setGAR(dhcp_get.gw);
setSIPR(dhcp_get.lip);
close(1);
}
for(;;)
{
if(state_k1_init != func_get_switchkey1())
{
u8 res;
//downlaod bin file and reboot
memset(buf, 0 , sizeof(buf));
res = func_http_get_download_file(0, srv_ip, srv_port, "/file/APP_Download.bin_1.1.8", 5000, buf, sizeof(buf));
if(res == 0)
{
//jump to bootloader
func_jump2bootloader();
}
state_k1_init = func_get_switchkey1();
}
// func_led_onoff_cross();
func_led_onoff_sametime();
}
}
