99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

ZYNQ - 以太網遠程更新SD卡應用程序

寫在前面

對于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資源,

配置ZYNQ核

如使用相同型號的板卡,可設置該部分為相同配置。

配置引腳

勾選DDR,并設置為PYNQZ2板卡的DDR的信息,

配置DDR

取消勾選多余資源,點擊OK,完成硬件設計。如下圖:

硬件設計

然后我們進行generate output product 然后生成HDL封裝。這里沒有進行使用PL資源,也不需要進行綜合布局,在導出硬件時也不用包含bit流文件。

導出硬件

SDK軟件部分

打開SDK后,新建application project,這里為了方便lwip設置,可選用使用lwip的相關模板,這里選擇lwip tcp回環測試模板,保存新建工程。

新建工程

選中新建好的工程,選擇右擊選中設置板載支持包,除了勾選lwip的板級支持包外,還需勾選sd卡需要的文件模式支持包。

修改板級支持包

點擊standalone下的xilffs,可以對文件系統進行配置,這里可以使能長文件名有效,改變勾選為true。

修改板級支持包

保留模板例程的中的platform配置文件,刪除其余文件。

保留platform配置文件

修改main.c文件

修改main.c文件為如下:

#include 
#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 

//服務器端口
#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 
#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);
}

//將接收到的BOOT.bin文件寫入到SD中
int transfer_data()
{
    char msg[60];
    if (start_update_flag) {
        xil_printf("\r\nStart SD Update!\r\n");
        xil_printf("file size of BOOT.bin is %lu Bytes\r\n", total_bytes);
        sprintf(msg, "file size of BOOT.bin is %lu Bytes\r\n",total_bytes);
        sent_msg(msg);
        sd_write_data(rxbuffer,total_bytes);
        xil_printf("SD Update finish!\n");
        total_bytes = 0;
    }

    start_update_flag = 0;

    return 0;
}

//向客戶端回送信息
void sent_msg(const char *msg)
{
    err_t err;
    tcp_nagle_disable(c_pcb);
    if (tcp_sndbuf(c_pcb) > strlen(msg)) {
        err = tcp_write(c_pcb, msg, strlen(msg), TCP_WRITE_FLAG_COPY);
        if (err != ERR_OK)
            xil_printf("tcp_server: Error on tcp_write: %d\r\n", err);
        err = tcp_output(c_pcb);
        if (err != ERR_OK)
            xil_printf("tcp_server: Error on tcp_output: %d\r\n", err);
    } else
        xil_printf("no space in tcp_sndbuf\r\n");
}

//接收回調函數
static err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    struct pbuf *q;

    if (!p) {
        tcp_close(tpcb);
        tcp_recv(tpcb, NULL);
        xil_printf("tcp connection closed\r\n");
        return ERR_OK;
    }
    q = p;

    if (q->tot_len == 6 && !(memcmp("update", p->payload, 6))) {
        start_update_flag = 1;
        sent_msg("\r\nStart SD Update\r\n");
    } else if (q->tot_len == 5 && !(memcmp("clear", p->payload, 5))) {
        start_update_flag = 0;
        total_bytes = 0;
        sent_msg("Clear received data\r\n");
        xil_printf("Clear received data\r\n");
    } else {
        while (q->tot_len != q->len) {
            memcpy(&rxbuffer[total_bytes], q->payload, q->len);
            total_bytes += q->len;
            q = q->next;
        }
        memcpy(&rxbuffer[total_bytes], q->payload, q->len);
        total_bytes += q->len;
    }

    tcp_recved(tpcb, p->tot_len);
    pbuf_free(p);

    return ERR_OK;
}

err_t accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    xil_printf("tcp_server: Connection Accepted\r\n");
    c_pcb = newpcb;             //保存連接的客戶端PCB
    //設置接收回調
    tcp_recv(c_pcb, recv_callback);
    tcp_arg(c_pcb, NULL);

    return ERR_OK;
}

int start_application()
{
    struct tcp_pcb *pcb;
    err_t err;
    //掛載SD卡
    sd_mount();
    xil_printf("Successfully init SD\r\n");
    print_app_header();
    //創建TCP PCB
    pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
    if (!pcb) {
        xil_printf("Error creating PCB. Out of Memory\n\r");
        return -1;
    }

    //綁定端口號
    err = tcp_bind(pcb, IP_ANY_TYPE, SER_PORT);
    if (err != ERR_OK) {
        xil_printf("Unable to bind to port %d: err = %d\n\r", SER_PORT, err);
        return -2;
    }

    //此處不需要回調函數的任何參數
    tcp_arg(pcb, NULL);

    //偵聽連接
    pcb = tcp_listen(pcb);
    if (!pcb) {
        xil_printf("Out of memory while tcp_listen\n\r");
        return -3;
    }

    //指定用于傳入連接的回調
    tcp_accept(pcb, accept_callback);
    xil_printf("TCP server started @ port %d\n\r", SER_PORT);

    return 0;
}

完成代碼編寫后,進行燒寫驗證。

下載驗證

打開網絡調試助手,選擇協議類型為TCP客戶端,選擇遠程主機的IP地址和端口,選擇需要加載的應用程序的bin文件,勾選加載文件數據源,點擊發送。

發送完成后在發送框選擇輸入“update”更新SD卡的應用程序。

在串口終端中查看調試信息,表示SD卡程序更新完成。

調試信息

使用讀卡器查看貼片SD卡轉接卡是否正常存儲到SD卡中,讀取文件可知已經正常寫入。

將板卡啟動模式調整至SD卡模式,上電重啟板卡程序,觀察到板卡程序成功啟動。

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關注 7
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 国产a级淫片 | 波多野结衣伦理在线观看 | WWW国产精品内射老师 | 阿娇艳z门照片无码av4i | 日本免费三片在线播放 | 一及毛片| av免费播放网址 | 国产精品一区一区三区 | 日本永久免费a∨在线视频 91精品国产综合久久小仙女图片 | 色一欲一性一乱一区二区三区 | 国人国产免费AV影院 | 国产成人AV无码专区亚洲AV | 亚洲aⅴ久久精品蜜桃小仓由菜 | 国产美女久久 | 中文字幕五区 | 国产亚洲AV夜间福利香蕉149 | 久操网视频 | 一区二区三区免费在线看 | 艳妇乳肉豪妇荡乳AV无码福利 | 韩国激情高潮无遮挡hd | 一性一交一伦一色一情人 | 欧美一区二区三区 | 欧美日韩一区国产 | 久久网站av| 国产精品VA在线观看老妇女 | 边摸边吃奶边做爰视频网站 | 99久久精品免费看国产 | 久久99国产精品亚洲 | 97人人模人人爽人人少妇 | 午煮香蕉小辣椒 | 久久久一区二区三区 | 国产日产亚洲精华av | 韩国日本三级在线 | 伊人免费视频 | 午夜爽爽爽男女免费观看影院 | 亚洲精品中国国产嫩草影院美女 | 成年人视频免费在线观看 | 大地资源在线观看免费高清一 | 亚洲久悠悠色悠在线播放 | 亚洲精品日本无v一区 | 免费一级大片 |