查看:
327
|
回复:
0
|
ZYNQ - 以太网远程更新贴片SD卡/TF卡应用程序
|
|
发表于2023-06-15 18:18:28
|
显示全部楼层
1#
电梯直达
写在前面 对于ZYNQ系列的板卡固化,可以通过JTAG接口,使用SDK固化到FLASH中,或者可将SD卡取出将SD卡中保存的固化工程进行修改,但在很多情况下,离线更新会很不方便,本文借鉴网上常见的远程更新QSPI FLASH的相关示例,对表贴式SD卡的应用程序进行了在线更新的操作适配,便于ZYNQ设备进行远程更新保存在表贴式SD卡中的固化程序。 传统SD卡与表贴SD卡区别 对于传统SD卡,直接将SD卡取出,使用读卡器进行脱机更新很方便,但是由于SD卡插拔时容易损坏,对于一些需要SD卡设备,但需要高可靠性的应用场景,使用传统的SD卡托很容易造成卡托和TF卡的脱落,很难保持SD卡长时间的稳定读取。 相比传统的SD卡,使用表贴式的SD卡,将会增加系统的可靠性和稳定性,这里硬件方案选择雷龙公司的NAND Flash(贴片式TF卡)CSNP4GCR01-AMW,产品说明如下:编辑相比传统的SD卡,表贴式SD卡除了保留了SD卡大容量容易读写操作的特点外,在PCB板上的占用面积也相比传统表贴卡托的面积要小。对传统的SD卡的电路设计可实现快速替代。 程序简述说明 程序大体框架借鉴了正点原子的远程更新的例程架构,只对更新QSPI的部分进行改写替换,替换成对SD卡的固化程序进行更新的相关代码。本文使用的板卡为PYNQ-Z2,这里只是为了验证表贴SD卡的功能,使用转接板对传统的SD卡进行了替代。相关样片和转接板样品可在雷龙公司官网进行申请试用。 大致实现功能为:用 LWIP 协议栈的 tcp 协议实现远程更新 表贴SD卡的功能,当输入“ update”命令时更新 SD卡并反馈信息,当输入“ clear”命令时之前传输的数据无效。 硬件平台搭建 新建工程,创建 block design。添加ZYNQ7 IP,对zynq进行初始化配置,对应板卡配置勾选SD,UART以及ENET资源,编辑如使用相同型号的板卡,可设置该部分为相同配置。编辑勾选DDR,并设置为PYNQZ2板卡的DDR的信息,编辑取消勾选多余资源,点击OK,完成硬件设计。如下图:编辑然后我们进行generate output product 然后生成HDL封装。这里没有进行使用PL资源,也不需要进行综合布局,在导出硬件时也不用包含bit流文件。SDK软件部分打开SDK后,新建application project,这里为了方便lwip设置,可选用使用lwip的相关模板,这里选择lwip tcp回环测试模板,保存新建工程。编辑选中新建好的工程,选择右击选中设置板载支持包,除了勾选lwip的板级支持包外,还需勾选sd卡需要的文件模式支持包。编辑点击standalone下的xilffs,可以对文件系统进行配置,这里可以使能长文件名有效,改变勾选为true。 保留模板例程的中的platform配置文件,删除其余文件。编辑修改main.c文件修改main.c文件为如下: #include <stdio.h> #include "xparameters.h" #include "netif/xadapter.h" #include "platform.h" #include "platform_config.h" #include "lwipopts.h" #include "xil_printf.h" #include "sleep.h" #include "lwip/priv/tcp_priv.h" #include "lwip/init.h" #include "lwip/inet.h" #if LWIP_IPV6==1 #include "lwip/ip6_addr.h" #include "lwip/ip6.h" #else #if LWIP_DHCP==1 #include "lwip/dhcp.h" extern volatile int dhcp_timoutcntr; #endif #define DEFAULT_IP_ADDRESS "192.168.1.10" #define DEFAULT_IP_MASK "255.255.255.0" #define DEFAULT_GW_ADDRESS "192.168.1.1" #endif /* LWIP_IPV6 */ extern volatile int TcpFastTmrFlag; extern volatile int TcpSlowTmrFlag; void platform_enable_interrupts(void); void start_application(void); void print_app_header(void); int transfer_data(); struct netif server_netif; #if LWIP_IPV6==1 static void print_ipv6(char *msg, ip_addr_t *ip) { print(msg); xil_printf(" %s\n\r", inet6_ntoa(*ip)); } #else static void print_ip(char *msg, ip_addr_t *ip) { print(msg); xil_printf("%d.%d.%d.%d\r\n", ip4_addr1(ip), ip4_addr2(ip), ip4_addr3(ip), ip4_addr4(ip)); } static void print_ip_settings(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw) { print_ip("Board IP: ", ip); print_ip("Netmask : ", mask); print_ip("Gateway : ", gw); } static void assign_default_ip(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw) { int err; xil_printf("Configuring default IP %s \r\n", DEFAULT_IP_ADDRESS); err = inet_aton(DEFAULT_IP_ADDRESS, ip); if (!err) xil_printf("Invalid default IP address: %d\r\n", err); err = inet_aton(DEFAULT_IP_MASK, mask); if (!err) xil_printf("Invalid default IP MASK: %d\r\n", err); err = inet_aton(DEFAULT_GW_ADDRESS, gw); if (!err) xil_printf("Invalid default gateway address: %d\r\n", err); } #endif /* LWIP_IPV6 */ int main(void) { struct netif *netif; //设置开发板的MAC地址 unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 }; netif = &server_netif; init_platform(); print_app_header(); //初始化lwIP lwip_init(); //将网络接口添加到netif,并将其设置为默认值 if (!xemac_add(netif, NULL, NULL, NULL, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) { xil_printf("Error adding N/W interface\r\n"); return -1; } #if LWIP_IPV6==1 netif->ip6_autoconfig_enabled = 1; netif_create_ip6_linklocal_address(netif, 1); netif_ip6_addr_set_state(netif, 0, IP6_ADDR_VALID); print_ipv6("\n\rlink local IPv6 address is:", &netif->ip6_addr[0]); #endif /* LWIP_IPV6 */ netif_set_default(netif); //使能中断 platform_enable_interrupts(); //指定网络是否已启动 netif_set_up(netif); #if (LWIP_IPV6==0) #if (LWIP_DHCP==1) //创建新的DHCP客户端 dhcp_start(netif); dhcp_timoutcntr = 2; while (((netif->ip_addr.addr) == 0) && (dhcp_timoutcntr > 0)) xemacif_input(netif); if (dhcp_timoutcntr <= 0) { if ((netif->ip_addr.addr) == 0) { xil_printf("ERROR: DHCP request timed out\r\n"); assign_default_ip(&(netif->ip_addr), &(netif->netmask), &(netif->gw)); } } #else assign_default_ip(&(netif->ip_addr), &(netif->netmask), &(netif->gw)); #endif print_ip_settings(&(netif->ip_addr), &(netif->netmask), &(netif->gw)); #endif /* LWIP_IPV6 */ //启动应用程序 start_application(); while (1) { if (TcpFastTmrFlag) { tcp_fasttmr(); TcpFastTmrFlag = 0; } if (TcpSlowTmrFlag) { tcp_slowtmr(); TcpSlowTmrFlag = 0; } xemacif_input(netif); transfer_data(); } cleanup_platform(); return 0; }添加remote_update.h文件#ifndef REMOTE_UPDATE_H_ #define REMOTE_UPDATE_H_ #include "xparameters.h" #include "xtime_l.h" #include "xstatus.h" #include <stdio.h> //服务器端口 #define SER_PORT 5678 //接收的最大文件大小16MB #define MAX_FLASH_LEN 16*1024*1024 void sent_msg(const char *msg); #endif添加remote_update.c文件#include "remote_update.h" #include "xparameters.h" #include "ff.h" #include "string.h" #include <stdio.h> #include "lwip/err.h" #include "lwip/tcp.h" #include "xil_printf.h" u8 start_update_flag = 0; u8 rxbuffer[MAX_FLASH_LEN]; u32 total_bytes = 0; #define FILE_NAME "BOOT.bin" struct tcp_pcb *c_pcb; FATFS fs; void print_app_header() { xil_printf("-----SD remote update demo------\n"); } //挂载sd卡 void sd_mount(){ FRESULT status; BYTE work[FF_MAX_SS]; //挂载sd卡,注册文件系统对象 status=f_mount(&fs,"",1); if(status != FR_OK){ printf("%d\n",status); printf("It isn't FAT format\n"); f_mkfs("",FM_FAT32,0,work,sizeof work); f_mount(&fs,"",1); } } //写数据 void sd_write_data(u8 wr_dat[], u32 wr_len){ FIL fil; UINT bw; //创建或者打开文件 f_open(&fil,FILE_NAME,FA_CREATE_ALWAYS | FA_WRITE | FA_READ); //移动读写指针 f_lseek(&fil, 0); //写数据 f_write(&fil,wr_dat,wr_len,&bw); //关闭文件 f_close(&fil); } |
|