本帖最后由 egoistaw 于 2026-5-21 17:52 编辑
关于NetX FTP读写问题以及传输速率慢的探讨最近正在将开发环境切换到vscode + gcc + make + cmake + openocd。方便让AI Agent接手项目。
测试到H743的SD卡和FTP时,踩了不少旧坑
1.SD卡请先格式化成FAT或EXFAT格式。
2.FTP可以看到SD卡目录及文件,但不能读写?
原因: SDMMC1不支持访问AXI之外的其他RAM。NetX Packet Pool Buffer被我放到了SRAM1_2_3(RAM_D2)里,SDMMC无法访问,报超时。 解决方案: NetX Packet Pool Buffer也放到AXI-SRAM。或者不用DMA。或者用一个AXI-SRAM里的buff复制代发代收。 备注: 1.为什么目录能看到?因为目录传输使用fx_media_open时传入的buffer,它被我正确放在了AXI_SRAM里。 2.ETH收发描述符反而不能放到AXI-SRAM里,只能放到SRAM1_2_3(RAM_D2)。
3.16G卡正常,32G内存卡却报SDMMC_ERROR_RX_OVERRUN?
原因: 依旧是SDMMC1不支持访问AXI之外的其他RAM。FX_MEDIA sdio_disk这个变量被放到了DTCMRAM里,无法被SDMMC访问 。 CubeMX生成的CMAKE项目的ld文件里,各种内存区域默认使用DTCMRAM。这个RAM大家都知道有多坑,不能被各种DMA访问。 解决方案: 手动将LD文件里用到DTCMRAM的替换成AXI-SRAM(RAM)。 备注: GCC的ld文件里,自己指定的各种 (NOLOAD)区域不会上电自动清零,所以对需要重置状态的各种变量,需要自己手动memset(ptr, 0, size); 包括上述FX_MEDIA等。
下面讨论NetX FTP传输速率的问题。问题: 默认配置下,上传文件大概260KB/S,下载文件大概1.5MB/S。相比SD卡读写速度和网速来说,有点太慢了。 排查:- 改优化等级,没有效果。
- 加大fx_media_open的缓存,没有效果。
- 拉大NX_FTP_DATA_WINDOW_SIZE,没有效果。
- 打印SD读写信息,会发现写入时是以1或2扇区为单位写入的。
- 查看_nx_ftp_server_command_process的源码。
原因分析: NetX FTP是简单的把收到的每一帧Packet(最多1460字节)拆成1024字节+436字节(对应两个连续512字节扇区和一个不满的扇区) 这两部分写入的。每一帧都要DMA启停2次,非常耗时,而且这样写入会不会严重内存碎片化? 解决方案: 不改动源码是没有办法解决的。如果影响不大,频率不高就迁就用吧。 优化写入的主要思路是添加一个buff,例如32KB,攒满了再统一写入。下面自己尝试修改源码验证猜想。 [C] 纯文本查看 复制代码 #define COALESCING_BUFFER_SIZE (1024*64) // 必须大于1460 否则会出错且无意义
static ULONG coalescing_buf[COALESCING_BUFFER_SIZE/sizeof(ULONG)];
static UINT coalescing_buf_len = 0;
​
// 在case NX_FTP_STOR: 里的fx_file_open前调用
UINT fx_file_coalescing_init(void)
{
coalescing_buf_len = 0;
return FX_SUCCESS;
}
​
// 在_nx_ftp_server_data_socket_cleanup函数里的fx_file_close前调用
UINT fx_file_coalescing_write_flush(FX_FILE *file_ptr)
{
if (coalescing_buf_len == 0)
return FX_SUCCESS;
​
return fx_file_write(file_ptr, coalescing_buf, coalescing_buf_len);
}
​
// 替代_nx_ftp_server_data_process函数里的fx_file_write
UINT fx_file_coalescing_write(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG size)
{
UINT status;
UINT copy_len;
UINT left_len;
​
if (coalescing_buf_len + size > COALESCING_BUFFER_SIZE)
copy_len = COALESCING_BUFFER_SIZE - coalescing_buf_len;
else
copy_len = size;
​
left_len = size - copy_len;
​
memcpy((UCHAR*)coalescing_buf + coalescing_buf_len, buffer_ptr, copy_len);
​
coalescing_buf_len += copy_len;
​
if (left_len > 0)
{
status = fx_file_coalescing_write_flush(file_ptr);
if (status != FX_SUCCESS)
return status;
​
memcpy((UCHAR*)coalescing_buf, buffer_ptr + copy_len, left_len);
​
coalescing_buf_len = left_len;
}
​
return FX_SUCCESS;
}
​
​用法: 根据注释在相应的地方调用。 #define NX_FTP_MAX_CLIENTS 1 // 不允许多客户端访问 #define NX_FTP_DATA_WINDOW_SIZE (20*1024) 记得在ftp的server_logout回调里调用fx_media_flush(&sdio_disk)。
测试效果: 写入速度由260KB/S提升至3MB/S
|