tag 标签: spi nand flash

相关帖子
相关博文
  • 2024-10-16 18:07
    148 次阅读|
    0 个评论
    说起SD NAND FLASH常被联想到SD卡,SD NAND FLASH具备当前SD卡的基本功能,并具有更高的存储密度,更小的体积,通过芯片形式焊接在电路中稳定可靠,在电路中高度集成可SMT机贴片等优点。这一节我们主要是介绍一下SD NAND FLASH,该应用实例的SD NAND FLASH采用深圳市雷龙发展有限公司的CSNP1GCR01-AOW型号的存储芯片,雷龙发展在SD NAND FLASH中已经有多年的深厚研发经验和严格的测试流程。 一、SD NAND FLASH芯片简介 CSNP1GCR01-AOW是基于NAND FLASH 和SD 控制器的1Gb容量空间的存储芯片。比传统的NAND FLASH具有还有坏块管理,数据ECC功能和异常掉电保证数据安全存储等功能。封装尺寸为8mm x 6mm x0.75mm。 产品特点: 接口:具备1线或者4线SD标准2.0版本 供电:Vcc = 2.7V - 3.6V 默认模式:可变的时钟范围0~25MHz,高达12.5MB/s的接口速度(使用4线) 高速模式:可变的时钟范围0~50MHz,高达25MB/s的接口速度(使用4线) 工作温度范围:-40°C to +85°C 存储温度范围:-55°C to +125°C 标准电流:< 250uA 开关功能命令支持高速,商务和未来的一些功能 矫正存储区域的错误 内容保护机制兼容最安全的SDMI标准 支持SD NAND密码保护功能 使用机械开关进行写保护功能 内置写保护功能(永久和临时) 通用场景 应用程序特定命令 舒适擦除机制 通过下图的功能框图可以理解,SD NAND FLASH是通过Memory core来进行存储数据的,通过SD控制进行通讯接口的控制和存储的管理。 外部引脚位置和定义如下图所示: 机械尺寸如下图所示: 二、总结 本节主要介绍了SD NAND FLASH的基本功能特性,引脚定义和外形的机械尺寸,通过这个基本的描述可以对SD NAND FLASH有个初步的了解。下一节主要介绍,SD NAND FLASH的初始化过程。
  • 2024-8-16 16:04
    0 个评论
      在当今这个数字化飞速发展的时代,电子设备已成为我们日常生活中不可或缺的一部分。从智能手表到智能手机,从无人机到智能家居,各种高科技产品层出不穷,而这些设备的续航能力与性能表现直接关系到用户的使用体验。在此背景下,CS创世半导体推出的8GB SD NAND芯片,以其卓越的低功耗特性,成为了市场上的一颗璀璨明星,为电子设备的续航与性能提升开辟了新的路径。 低功耗:延长设备 生命 的秘密武器   在电子设备领域,低功耗一直是研发人员追求的目标之一。CS创世8GB SD NAND芯片以其惊人的低功耗表现,为这一难题提供了有效的解决方案。其读写电流仅为15mA,相较于市场上同类产品,这一数值显著降低了功耗水平。这意味着,在相同条件下,搭载创世8GB SD NAND芯片的设备能够拥有更长的使用时间,减少了频繁充电的烦恼,极大地提升了用户体验。特别是在运动耳机、相机等需要长时间运行且对电池寿命有严格要求的设备上,这一低功耗特性更是显得尤为重要。   小巧设计:空间与成本的双重优化   除了低功耗之外,CS创世8GB SD NAND芯片在设计上也展现出了非凡的创意与实用性。其封装尺寸仅为7*8.5毫米,仅有8个管脚,这种紧凑的设计使得它在各种小型设备中都能轻松找到立足之地。对于设计师而言,这意味着更大的布局灵活性,可以更加自由地规划电路板空间,实现产品的轻薄化设计。同时,小巧的封装也降低了生产成本,使得这款芯片在价格上更具竞争力,进一步推动了其在市场上的普及。   高性能:稳定与速度的双重保障   CS创世8GB SD NAND芯片不仅在功耗和设计上表现出色,在性能方面也同样令人瞩目。其内置的控制核心和高稳定性的存储单元,确保了数据传输的高效与稳定。在HD TUNE实测中,这款芯片的小文件读取速度可达到1.4MB/S,这一速度在同类产品中处于领先地位。对于需要快速数据传输的应用场景,如高清摄影、视频录制等,CS创世8GB SD NAND芯片无疑能够提供更流畅、更高效的体验。此外,其高稳定性和可靠性也保证了数据的安全存储,避免了因数据丢失或损坏而带来的损失。   广泛应用:满足多元化需求   CS创世8GB SD NAND芯片的低功耗、小巧设计及高性能特性,使其在各种电子设备中都有着广泛的应用前景。除了运动耳机和相机产品外,它还可以被广泛应用于智能穿戴设备、便携式医疗设备、无人机等领域。在这些领域中,低功耗和高效能成为了不可或缺的关键因素,而创世8GB SD NAND芯片正好满足了这些需求。   结语   综上所述,CS创世8GB SD NAND芯片以其卓越的低功耗特性、小巧的设计以及高性能表现,在电子设备领域展现出了强大的竞争力。它不仅延长了设备的续航时间,降低了对电池的依赖,还提升了数据传输的效率和稳定性。随着科技的不断进步和市场需求的日益多样化,CS创世8GB SD NAND芯片有望在未来发挥更加重要的作用,为电子设备的续航与性能提升贡献更多的力量。在这个追求高效、节能的时代里,CS创世8GB SD NAND芯片无疑将成为推动行业发展的重要力量之一。
  • 热度 1
    2024-7-8 18:12
    153 次阅读|
    0 个评论
    最近收到了一片国产工业级SD NAND,可以替代SD卡,容量大,贴片封装,非常适合做飞控"黑匣子"。 不用写驱动程序自带坏块管理的NAND Flash(贴片式TF卡),尺寸小巧,简单易用,兼容性强,稳定可靠,固件可定制,LGA-8封装,标准SDIO接口,兼容SPI/SD接口,兼容各大MCU平台,可替代普通TF卡/SD卡,尺寸6x8mm毫米,内置SLC晶圆擦写寿命10万次,通过1万次随机掉电测试耐高低温,支持工业级温度-40°~+85°,机贴手贴都非常方便,速度级别Class10(读取速度23.5MB/S写入速度12.3MB/S)标准的SD 2.0协议使得用户可以直接移植标准驱动代码,省去了驱动代码编程环节。支持TF卡启动的SOC都可以用SD NAND,厂商提供了STM32参考例程及原厂技术支持,主流容量:128MB/512MB/2GB/4GB/8GB,比TF卡稳定,比eMMC便宜。 飞控板上ESP32C3的SDIO接口暂时用不了,只能先用SPI接口驱动。 评估板做了个micro SD卡的接口,方便直接插到带卡槽的开发板上进行调试。 ESP32C3的SPI接口是硬件SPI,支持DMA,速度应该还可以,但是我用杜邦线连接的,肯定会影响信号质量,估计时钟很难跑到50MHz了。 接线: 编写测试程序: /* SD card and FAT filesystem example. This example uses SPI peripheral to communicate with SD card. This example code is in the Public Domain (or CC0 licensed, at your option.) Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ #include #include #include #include "esp_vfs_fat.h" #include "sdmmc_cmd.h" #define EXAMPLE_MAX_CHAR_SIZE 64 static const char *TAG = "example"; #define MOUNT_POINT "/sdcard" // Pin assignments can be set in menuconfig, see "SD SPI Example Configuration" menu. // You can also change the pin assignments here by changing the following 4 lines. #define PIN_NUM_MISO CONFIG_EXAMPLE_PIN_MISO #define PIN_NUM_MOSI CONFIG_EXAMPLE_PIN_MOSI #define PIN_NUM_CLK CONFIG_EXAMPLE_PIN_CLK #define PIN_NUM_CS CONFIG_EXAMPLE_PIN_CS static esp_err_t s_example_write_file(const char *path, char *data) { ESP_LOGI(TAG, "Opening file %s", path); FILE *f = fopen(path, "w"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file for writing"); return ESP_FAIL; } fprintf(f, data); fclose(f); ESP_LOGI(TAG, "File written"); return ESP_OK; } static esp_err_t s_example_read_file(const char *path) { ESP_LOGI(TAG, "Reading file %s", path); FILE *f = fopen(path, "r"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file for reading"); return ESP_FAIL; } char line ; fgets(line, sizeof(line), f); fclose(f); // strip newline char *pos = strchr(line, '\n'); if (pos) { *pos = '\0'; } ESP_LOGI(TAG, "Read from file: '%s'", line); return ESP_OK; } void app_main(void) { esp_err_t ret; // Options for mounting the filesystem. // If format_if_mount_failed is set to true, SD card will be partitioned and // formatted in case when mounting fails. esp_vfs_fat_sdmmc_mount_config_t mount_config = { #ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED .format_if_mount_failed = true, #else .format_if_mount_failed = false, #endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED .max_files = 5, .allocation_unit_size = 16 * 1024 }; sdmmc_card_t *card; const char mount_point ; cid.name); ret = s_example_write_file(file_hello, data); if (ret != ESP_OK) { return; } const char *file_foo = MOUNT_POINT"/foo.txt"; // Check if destination file exists before renaming struct stat st; if (stat(file_foo, &st) == 0) { // Delete it if it exists unlink(file_foo); } // Rename original file ESP_LOGI(TAG, "Renaming file %s to %s", file_hello, file_foo); if (rename(file_hello, file_foo) != 0) { ESP_LOGE(TAG, "Rename failed"); return; } ret = s_example_read_file(file_foo); if (ret != ESP_OK) { return; } // Format FATFS ret = esp_vfs_fat_sdcard_format(mount_point, card); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to format FATFS (%s)", esp_err_to_name(ret)); return; } if (stat(file_foo, &st) == 0) { ESP_LOGI(TAG, "file still exists"); return; } else { ESP_LOGI(TAG, "file doesnt exist, format done"); } const char *file_nihao = MOUNT_POINT"/nihao.txt"; memset(data, 0, EXAMPLE_MAX_CHAR_SIZE); cid.name); ret = s_example_write_file(file_nihao, data); if (ret != ESP_OK) { return; } //Open file for reading ret = s_example_read_file(file_nihao); if (ret != ESP_OK) { return; } // All done, unmount partition and disable SPI peripheral esp_vfs_fat_sdcard_unmount(mount_point, card); ESP_LOGI(TAG, "Card unmounted"); //deinitialize the bus after all devices are removed spi_bus_free(host.slot); } 这段代码是使用SPI(串行外设接口)与SD卡进行通信。它展示了如何挂载SD卡、写入文件、读取文件、重命名文件、格式化SD卡,最后卸载SD卡。 代码首先包含了必要的头文件,并定义了一些常量,如最大字符大小、SD卡的挂载点和SPI通信的引脚分配。 然后定义了两个辅助函数:s_example_write_file和s_example_read_file。s_example_write_file函数打开一个给定路径的文件,写入数据,然后关闭文件。如果无法打开文件,它会记录一个错误并返回失败状态。s_example_read_file函数打开一个给定路径的文件,从中读取一行,然后关闭文件。如果无法打开文件,它会记录一个错误并返回失败状态。 app_main函数是程序的主入口点。它首先定义了挂载SD卡的配置。然后初始化SPI总线和SD卡插槽。如果初始化失败,它会记录一个错误并返回。 接下来,它试图挂载SD卡。如果挂载失败,它会记录一个错误并返回。如果挂载成功,它会记录一个成功消息并打印SD卡的属性。 程序然后在SD卡上写入一个文件,检查另一个文件是否存在,如果存在则删除它,然后将第一个文件重命名为第二个文件。然后从第二个文件中读取。 程序接着格式化SD卡,并检查第二个文件是否仍然存在。如果存在,它会记录一个消息并返回。如果不存在,它会记录一个成功消息,写入第三个文件,并从第三个文件中读取。 最后,卸载SD卡并禁用SPI外设。 编译: 烧写到ESP32C3后运行,控制台输出: I (286) app_start: Starting scheduler on CPU0 I (291) main_task: Started on CPU0 I (291) main_task: Calling app_main() I (291) example: Initializing SD card I (301) example: Using SPI peripheral I (301) example: Mounting filesystem I (311) gpio: GPIO | InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 I (321) sdspi_transaction: cmd=52, R1 response: command not supported I (361) sdspi_transaction: cmd=5, R1 response: command not supported I (391) example: Filesystem mounted Name: CS064 Type: SDHC/SDXC Speed: 20.00 MHz (limit: 20.00 MHz) Size: 7382MB CSD: ver=2, sector_size=512, capacity=15118336 read_bl_len=9 SSR: bus_width=1 I (401) example: Opening file /sdcard/hello.txt I (411) example: File written I (411) example: Renaming file /sdcard/hello.txt to /sdcard/foo.txt I (411) example: Reading file /sdcard/foo.txt I (421) example: Read from file: 'Hello CS064!' I (421) vfs_fat_sdmmc: Formatting card, allocation unit size=16384 I (2911) example: file doesnt exist, format done I (2911) example: Opening file /sdcard/nihao.txt I (2921) example: File written I (2921) example: Reading file /sdcard/nihao.txt I (2921) example: Read from file: 'Nihao CS064!' I (2921) gpio: GPIO | InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 I (2931) example: Card unmounted I (2931) gpio: GPIO | InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (2941) gpio: GPIO | InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (2951) gpio: GPIO | InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 I (2961) main_task: Returned from app_main() 可以看到输出了存储卡信息: Name: CS064 Type: SDHC/SDXC Speed: 20.00 MHz (limit: 20.00 MHz) Size: 7382MB CSD: ver=2, sector_size=512, capacity=15118336 read_bl_len=9 SSR: bus_width=1 后面还输出了读写文件相应的信息。
  • 热度 1
    2023-12-6 18:18
    644 次阅读|
    0 个评论
    文章目录 前言 1 SD NAND概述 2 代码说明 3 记录Log 前言 本文基于 ESP32 芯片作为主控制器,测试 SD NAND 记录飞控 Log 功能。 关于 MCU 的存储方面,以前基本上用内置的 E2PROM,或者是外置的 NOR Flash 就可以。随着物联网的兴起,MCU 的应用越来越广泛,逐渐的 MCU 会涉及到大容量的存储需求,用来存储音频,图片(GUI)、视频缓存、协议栈等等。传统的 E2PROM 和 NOR Flash 就不够用了。这个时候 MCU 可能就需要用到 NAND Flash。 针对 MCU 需要使用大容量的存储需求,推荐一款简单易用、稳定可靠的 NAND Flash —— SD NAND 。 1 SD NAND概述 SD NAND 的架构,内部采用使用寿命最长、性能最稳定的 NAND Flash(SLC NAND Flash)晶圆,它的擦写寿命可以达到 5~10 万次。内置了 Flash 控制器和针对 NAND Flash 管理的 Firmware。对外采用通用性最强的 SD 接口(几乎所有 MCU 都带有 SD 接口)。 本文选择的是 CSNP32GCR01-AOW 芯片。 不用编写驱动程序,自带坏块管理的 NAND Flash(贴片式 TF 卡),尺寸小巧,简单易用,兼容性强,稳定可靠,固件可定制,LGA-8 封装,标准 SDIO 接口,兼容 SPI,兼容拔插式 TF卡/SD卡,可替代普通 TF卡/SD卡,尺寸 6.2x8mm。 内置平均读写算法,通过 1 万次随机掉电测试耐高低温,机贴手贴都非常方便,速度级别 Class10(读取速度 23.5MB/s,写入速度 12.3MB/s)。标准的 SD 2.0 协议使得用户可以直接移植标准驱动代码,省去了驱动代码编程环节。支持 TF 卡启动的 SOC 都可以用 SD NAND,提供 STM32 参考例程及原厂技术支持,容量:4GB, 比 TF 卡稳定,比 eMMC 便宜。 2 代码说明 1. 宏定义使能 SD 卡功能 #define HAL_ESP32_SDCARD 2. 挂载 SD 卡 bool sdcard_retry(void) { if(!card) return mount_sdcard; return true; } bool mount_sdcard { printf("............Try mount.\n"); sdmmc_host_t host = SDMMC_HOST_DEFAULT; host.max_freq_khz = SDMMC_FREQ_HIGHSPEED; sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT; slot_config.flags = SDMMC_SLOT_FLAG_INTERNAL_PULLUP; esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = false, .max_files = 5, .allocation_unit_size = 4 * 1024 }; esp_err_t ret = esp_vfs_fat_sdmmc_mount("/SDCARD", &host, &slot_config, &mount_config, &card); if (ret == ESP_OK) { mkdir("/SDCARD/APM", 0777); printf("sdcard is mounted\n"); update_fw; return true; } else { printf("sdcard is not mounted.\n"); return false; } } 3. 卸载 SD 卡 void sdcard_stop(void) { unmount_sdcard; } void unmount_sdcard { if (card != nullptr) { esp_vfs_fat_sdmmc_unmount; } } 3 记录Log 1. LOG目录建立 可以看到飞控已经在 SD NAND 中成功建立 LOG 目录。 2. LOG分析 飞机通电,翻滚机身,记录飞机的姿态角。 下载日志,加载到 Mission Planner 软件。选中 ATT 字段中的 Roll 和 Pitch。可以看到曲线跟随飞机姿态变化。 至此,使用 SD NAND 替代 SD 卡,测试飞控 LOG 记录功能完成。
  • 热度 10
    2023-6-16 16:11
    968 次阅读|
    0 个评论
    写在前面 对于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 #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 ); #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; 0)) xemacif_input(netif); if (dhcp_timoutcntr <= 0) { ip_addr.addr) == 0) { xil_printf("ERROR: DHCP request timed out\r\n"); ip_addr), gw)); } } #else gw)); #endif 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 ; 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 ; //挂载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 ; 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); 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; payload, 6))) { start_update_flag = 1; sent_msg("\r\nStart SD Update\r\n"); payload, 5))) { start_update_flag = 0; total_bytes = 0; sent_msg("Clear received data\r\n"); xil_printf("Clear received data\r\n"); } else { len) { len); len; next; } len); len; } 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卡模式,上电重启板卡程序,观察到板卡程序成功启动。 编辑 ​ ————————————————   如果看完文章之后还是有疑惑或不懂的地方,找深圳雷龙发展了解产品详情。