模组最新固件和取消spi协议脚本
author孙春阳 <snickersun@163.com>
Thu, 4 Dec 2025 12:41:59 +0000 (20:41 +0800)
committer孙春阳 <snickersun@163.com>
Thu, 4 Dec 2025 12:41:59 +0000 (20:41 +0800)
cat1modem/leiniao/EG800AKCN91LCR07A01M04_OCPU_QPY_BETA1022_20251203-2243.zip [new file with mode: 0644]
cat1modem/src/LeiNiao/spi_protocol.py [deleted file]
cat1modem/src/LeiNiao/spi_protocol_api.py [deleted file]
cat1modem/src/LeiNiao/spi_protocol_sender.py [deleted file]
cat1modem/src/LeiNiao/spi_protocol_test.py [deleted file]
cat1modem/src/LeiNiao/spi_protocol_test_2mb.py [deleted file]

diff --git a/cat1modem/leiniao/EG800AKCN91LCR07A01M04_OCPU_QPY_BETA1022_20251203-2243.zip b/cat1modem/leiniao/EG800AKCN91LCR07A01M04_OCPU_QPY_BETA1022_20251203-2243.zip
new file mode 100644 (file)
index 0000000..6d23c62
Binary files /dev/null and b/cat1modem/leiniao/EG800AKCN91LCR07A01M04_OCPU_QPY_BETA1022_20251203-2243.zip differ
diff --git a/cat1modem/src/LeiNiao/spi_protocol.py b/cat1modem/src/LeiNiao/spi_protocol.py
deleted file mode 100644 (file)
index 5efb065..0000000
+++ /dev/null
@@ -1,560 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-SPI通信协议实现
-支持可靠的数据传输,包含CRC16校验、自动重传机制
-"""
-
-import log
-import utime
-from machine import SPI
-
-# struct模块在嵌入式Python中可能不可用,实现替代方案
-try:
-    import struct
-except ImportError:
-    # 如果struct模块不可用,实现一个简单的替代
-    class _SimpleStruct:
-        @staticmethod
-        def pack(fmt, *args):
-            """简单的pack实现,支持大端序格式"""
-            result = bytearray()
-            i = 0
-            for c in fmt:
-                if c == '>':  # 大端序,忽略
-                    continue
-                elif c == 'B':  # unsigned char (1 byte)
-                    result.append(args[i] & 0xFF)
-                    i += 1
-                elif c == 'H':  # unsigned short (2 bytes, big-endian)
-                    val = args[i] & 0xFFFF
-                    result.append((val >> 8) & 0xFF)
-                    result.append(val & 0xFF)
-                    i += 1
-                elif c == 'I':  # unsigned int (4 bytes, big-endian)
-                    val = args[i] & 0xFFFFFFFF
-                    result.append((val >> 24) & 0xFF)
-                    result.append((val >> 16) & 0xFF)
-                    result.append((val >> 8) & 0xFF)
-                    result.append(val & 0xFF)
-                    i += 1
-            return bytes(result)
-        
-        @staticmethod
-        def unpack(fmt, data):
-            """简单的unpack实现,支持大端序格式"""
-            result = []
-            i = 0
-            for c in fmt:
-                if c == '>':  # 大端序,忽略
-                    continue
-                elif c == 'B':  # unsigned char (1 byte)
-                    result.append(data[i])
-                    i += 1
-                elif c == 'H':  # unsigned short (2 bytes, big-endian)
-                    val = (data[i] << 8) | data[i + 1]
-                    result.append(val)
-                    i += 2
-                elif c == 'I':  # unsigned int (4 bytes, big-endian)
-                    val = (data[i] << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | data[i + 3]
-                    result.append(val)
-                    i += 4
-            return tuple(result)
-    
-    struct = _SimpleStruct()
-
-# 设置日志输出级别
-log.basicConfig(level=log.INFO)
-clog = log.getLogger("spiprotocol")
-
-# 协议常量
-SPI_PROTOCOL_MAGIC = 0xAA
-SPI_PROTOCOL_VERSION = 0x01
-
-# 包类型
-PKT_TYPE_DATA = 0x01
-PKT_TYPE_ACK = 0x02
-PKT_TYPE_NACK = 0x03
-PKT_TYPE_EOT = 0x04
-
-# 标志位
-FLAG_FIRST = 0x01  # 第一包
-FLAG_LAST = 0x02   # 最后一包
-FLAG_RETRANSMIT = 0x04  # 重传包
-
-# 包大小限制(减小以适应嵌入式环境)
-MAX_PACKET_SIZE = 4 * 1024  # 4KB(减小以节省内存)
-HEADER_SIZE = 16
-DATA_CRC_SIZE = 2
-MAX_DATA_SIZE = MAX_PACKET_SIZE - HEADER_SIZE - DATA_CRC_SIZE  # 4080 bytes
-
-# 重传参数
-MAX_RETRY_COUNT = 3
-ACK_TIMEOUT_BASE_MS = 500  # 基础超时500ms
-ACK_TIMEOUT_PER_KB_MS = 10  # 每KB增加10ms,最大2s
-
-
-def crc16_ccitt(data, initial=0xFFFF):
-    """
-    CRC16-CCITT计算(多项式0x1021)
-    
-    Args:
-        data: 要计算的数据(bytes或bytearray)
-        initial: 初始值,默认0xFFFF
-    
-    Returns:
-        int: CRC16值
-    """
-    crc = initial
-    polynomial = 0x1021
-    
-    for byte in data:
-        crc ^= (byte << 8)
-        for _ in range(8):
-            if crc & 0x8000:
-                crc = (crc << 1) ^ polynomial
-            else:
-                crc <<= 1
-            crc &= 0xFFFF
-    
-    return crc
-
-
-class SpiProtocolSender:
-    """
-    SPI协议发送端
-    处理数据分包、重传、校验等
-    """
-    
-    def __init__(self, spi_obj, spi_channel=2, spi_mode=0, spi_clk=8):
-        """
-        初始化SPI协议发送端
-        
-        Args:
-            spi_obj: SPI对象(如果为None则自动创建)
-            spi_channel: SPI通道,默认2
-            spi_mode: SPI模式,默认0
-            spi_clk: SPI时钟频率,默认8(1.625MHz)
-        """
-        self.spi_obj = spi_obj
-        self.spi_channel = spi_channel
-        self.spi_mode = spi_mode
-        self.spi_clk = spi_clk
-        self.seq_num = 0
-        self.stats = {
-            'total_packets': 0,
-            'retry_packets': 0,
-            'error_packets': 0,
-            'total_bytes': 0
-        }
-    
-    def __init_spi(self):
-        """初始化SPI对象"""
-        if self.spi_obj is None:
-            try:
-                self.spi_obj = SPI(self.spi_channel, self.spi_mode, self.spi_clk)
-                clog.info("SPI initialized: channel={}, mode={}, clk={}".format(
-                    self.spi_channel, self.spi_mode, self.spi_clk))
-                return True
-            except Exception as e:
-                clog.error("Failed to initialize SPI: {}".format(e))
-                return False
-        return True
-    
-    def __create_header(self, pkt_type, flags, seq_num, data_len):
-        """
-        创建协议包头
-        
-        Args:
-            pkt_type: 包类型
-            flags: 标志位
-            seq_num: 序列号
-            data_len: 数据长度
-        
-        Returns:
-            bytes: 包头数据(16字节)
-        """
-        # 包头结构(前14字节,用于CRC16计算)
-        header = struct.pack('>BBBBII',
-                            SPI_PROTOCOL_MAGIC,
-                            SPI_PROTOCOL_VERSION,
-                            pkt_type,
-                            flags,
-                            seq_num,
-                            data_len)
-        
-        # 计算包头CRC16(前14字节)
-        header_crc = crc16_ccitt(header)
-        
-        # 完整包头(16字节)
-        full_header = header + struct.pack('>HH', header_crc, 0)  # Reserved=0
-        
-        return full_header
-    
-    def __send_packet(self, pkt_type, flags, seq_num, data=None):
-        """
-        发送数据包(包含重传逻辑)
-        
-        Args:
-            pkt_type: 包类型
-            flags: 标志位
-            seq_num: 序列号
-            data: 数据负载(bytes/bytearray,可选)
-        
-        Returns:
-            bool: 发送是否成功
-        """
-        if data is None:
-            data = b''
-        
-        data_len = len(data)
-        if data_len > MAX_DATA_SIZE:
-            clog.error("Data too large: {} bytes, max: {} bytes".format(
-                data_len, MAX_DATA_SIZE))
-            return False
-        
-        # 创建包头
-        header = self.__create_header(pkt_type, flags, seq_num, data_len)
-        
-        # 计算数据CRC16
-        data_crc = crc16_ccitt(data) if data_len > 0 else 0
-        
-        # 组装完整数据包
-        packet = header + data
-        if data_len > 0:
-            packet += struct.pack('>H', data_crc)
-        
-        # 重传逻辑
-        retry_count = 0
-        while retry_count <= MAX_RETRY_COUNT:
-            try:
-                # 发送数据包
-                packet_len = len(packet)
-                if hasattr(self.spi_obj, 'write'):
-                    self.spi_obj.write(packet, packet_len)
-                elif hasattr(self.spi_obj, 'write_read'):
-                    read_buf = bytearray(packet_len)
-                    try:
-                        self.spi_obj.write_read(read_buf, packet, packet_len, 5)
-                    except TypeError:
-                        self.spi_obj.write_read(read_buf, packet, packet_len)
-                else:
-                    clog.error("SPI object does not have write or write_read method")
-                    return False
-                
-                # 等待并接收ACK/NACK响应
-                # 超时时间根据数据包大小动态调整
-                timeout_ms = ACK_TIMEOUT_BASE_MS + (data_len // 1024) * ACK_TIMEOUT_PER_KB_MS
-                if timeout_ms > 2000:
-                    timeout_ms = 2000
-                
-                # 读取ACK/NACK响应(16字节包头)
-                # 注意:在SPI Slave模式下,从设备不能主动发起传输
-                # 需要通过write_read触发MCU响应,MCU在传输过程中返回ACK/NACK
-                ack_received = False
-                ack_type = None
-                start_time = utime.time() * 1000  # 转换为毫秒
-                max_retries = timeout_ms // 50  # 每50ms重试一次
-                retry_count_ack = 0
-                
-                while retry_count_ack < max_retries and ((utime.time() * 1000) - start_time) < timeout_ms:
-                    # 尝试读取ACK/NACK响应
-                    ack_buffer = bytearray(HEADER_SIZE)
-                    try:
-                        if hasattr(self.spi_obj, 'write_read'):
-                            # 使用write_read同时发送和接收,触发MCU响应
-                            dummy_data = bytearray(HEADER_SIZE)  # 发送空数据
-                            try:
-                                self.spi_obj.write_read(ack_buffer, dummy_data, HEADER_SIZE, 50)
-                            except TypeError:
-                                self.spi_obj.write_read(ack_buffer, dummy_data, HEADER_SIZE)
-                            
-                            # 解析ACK/NACK响应
-                            if len(ack_buffer) >= HEADER_SIZE:
-                                magic, version, pkt_type, flags, ack_seq_num, ack_data_len, ack_crc, reserved = \
-                                    struct.unpack('>BBBBIIHH', ack_buffer)
-                                
-                                if magic == SPI_PROTOCOL_MAGIC and version == SPI_PROTOCOL_VERSION:
-                                    # 校验CRC
-                                    calculated_crc = crc16_ccitt(ack_buffer[:14])
-                                    if calculated_crc == ack_crc:
-                                        if pkt_type == PKT_TYPE_ACK and ack_seq_num == seq_num:
-                                            ack_received = True
-                                            ack_type = PKT_TYPE_ACK
-                                            break
-                                        elif pkt_type == PKT_TYPE_NACK and ack_seq_num == seq_num:
-                                            ack_received = True
-                                            ack_type = PKT_TYPE_NACK
-                                            break
-                        elif hasattr(self.spi_obj, 'read'):
-                            # 尝试直接读取(如果支持)
-                            bytes_read = self.spi_obj.read(ack_buffer, HEADER_SIZE, 50)
-                            if bytes_read >= HEADER_SIZE:
-                                magic, version, pkt_type, flags, ack_seq_num, ack_data_len, ack_crc, reserved = \
-                                    struct.unpack('>BBBBIIHH', ack_buffer)
-                                
-                                if magic == SPI_PROTOCOL_MAGIC and version == SPI_PROTOCOL_VERSION:
-                                    calculated_crc = crc16_ccitt(ack_buffer[:14])
-                                    if calculated_crc == ack_crc:
-                                        if pkt_type == PKT_TYPE_ACK and ack_seq_num == seq_num:
-                                            ack_received = True
-                                            ack_type = PKT_TYPE_ACK
-                                            break
-                                        elif pkt_type == PKT_TYPE_NACK and ack_seq_num == seq_num:
-                                            ack_received = True
-                                            ack_type = PKT_TYPE_NACK
-                                            break
-                    except Exception as e:
-                        # 读取失败,继续等待
-                        pass
-                    
-                    retry_count_ack += 1
-                    utime.sleep_ms(50)  # 延迟50ms后重试
-                
-                # 检查ACK/NACK
-                if not ack_received:
-                    # 超时,未收到ACK/NACK
-                    # 注意:在SPI Slave模式下,ACK/NACK机制可能需要硬件支持
-                    # 这里暂时假设发送成功(简化实现)
-                    clog.warning("Packet {} ACK timeout after {}ms (assuming success for now)".format(seq_num, timeout_ms))
-                    # 在实际硬件测试中,如果ACK机制不工作,可以暂时假设成功
-                    # TODO: 完善ACK/NACK接收机制
-                elif ack_type == PKT_TYPE_NACK:
-                    # 收到NACK,需要重传
-                    clog.warning("Packet {} received NACK, retransmitting".format(seq_num))
-                    retry_count += 1
-                    if retry_count <= MAX_RETRY_COUNT:
-                        continue
-                    else:
-                        return False
-                
-                # 发送成功(收到ACK或超时但假设成功)
-                if retry_count > 0:
-                    self.stats['retry_packets'] += 1
-                    clog.info("Packet {} retransmitted {} times, now successful".format(seq_num, retry_count))
-                
-                self.stats['total_packets'] += 1
-                self.stats['total_bytes'] += data_len
-                return True
-                
-            except Exception as e:
-                retry_count += 1
-                if retry_count <= MAX_RETRY_COUNT:
-                    clog.warning("Failed to send packet {}, retry {}/{}: {}".format(
-                        seq_num, retry_count, MAX_RETRY_COUNT, e))
-                    utime.sleep_ms(50)  # 重传前短暂延迟
-                else:
-                    clog.error("Failed to send packet {} after {} retries: {}".format(
-                        seq_num, MAX_RETRY_COUNT, e))
-                    self.stats['error_packets'] += 1
-                    return False
-        
-        return False
-    
-    def send_data(self, data_source, timeout=60):
-        """
-        发送数据(统一接口,不区分文件/流)
-        
-        Args:
-            data_source: 数据源,支持:
-                - bytes/bytearray: 内存中的数据
-                - 可迭代对象: 如response.content(网络流)
-                - 文件对象: 如open()返回的对象
-            timeout: 总超时时间(秒)
-        
-        Returns:
-            bool: 发送是否成功
-        """
-        if not self.__init_spi():
-            return False
-        
-        try:
-            # 重置序列号
-            self.seq_num = 0
-            self.stats = {
-                'total_packets': 0,
-                'retry_packets': 0,
-                'error_packets': 0,
-                'total_bytes': 0
-            }
-            
-            # 处理数据源
-            if isinstance(data_source, (bytes, bytearray)):
-                # 内存数据:转换为可迭代
-                data_iter = iter([data_source])
-            elif hasattr(data_source, 'read'):
-                # 文件对象:按小块读取(避免大内存分配)
-                CHUNK_READ_SIZE = 1024  # 每次读取1KB,减少内存占用
-                def file_iter():
-                    while True:
-                        chunk = data_source.read(CHUNK_READ_SIZE)
-                        if not chunk:
-                            break
-                        yield chunk
-                data_iter = file_iter()
-            else:
-                # 可迭代对象(如网络流)
-                data_iter = data_source
-            
-            # 数据缓冲区(限制大小,避免大内存分配)
-            MAX_BUFFER_SIZE = MAX_DATA_SIZE  # 缓冲区最大不超过一个数据包大小
-            buffer = bytearray()
-            is_first = True
-            start_time = utime.time()
-            
-            clog.info("Starting SPI protocol data transmission...")
-            
-            # 处理数据流
-            for chunk in data_iter:
-                if not chunk:
-                    continue
-                
-                # 检查超时
-                if utime.time() - start_time > timeout:
-                    clog.error("Transmission timeout after {} seconds".format(timeout))
-                    return False
-                
-                # 添加到缓冲区
-                buffer.extend(chunk)
-                
-                # 当缓冲区达到最大数据包大小时,发送一个包
-                # 使用循环确保及时发送,避免缓冲区过大
-                while len(buffer) >= MAX_DATA_SIZE:
-                    # 提取一个完整的数据包
-                    packet_data = bytes(buffer[:MAX_DATA_SIZE])
-                    buffer = buffer[MAX_DATA_SIZE:]
-                    
-                    # 确定标志位
-                    flags = 0
-                    if is_first:
-                        flags |= FLAG_FIRST
-                        is_first = False
-                    
-                    # 发送数据包
-                    if not self.__send_packet(PKT_TYPE_DATA, flags, self.seq_num, packet_data):
-                        clog.error("Failed to send packet {}".format(self.seq_num))
-                        return False
-                    
-                    self.seq_num += 1
-                    
-                    # 每发送64KB打印一次进度
-                    if self.stats['total_bytes'] % (64 * 1024) < MAX_DATA_SIZE:
-                        clog.info("SPI TX Progress: {} bytes, {} packets".format(
-                            self.stats['total_bytes'], self.stats['total_packets']))
-                
-                # 如果缓冲区仍然很大(接近限制),强制发送一个包
-                # 这样可以避免缓冲区无限增长
-                if len(buffer) > MAX_BUFFER_SIZE:
-                    # 发送一个完整的数据包
-                    packet_data = bytes(buffer[:MAX_DATA_SIZE])
-                    buffer = buffer[MAX_DATA_SIZE:]
-                    
-                    flags = 0
-                    if is_first:
-                        flags |= FLAG_FIRST
-                        is_first = False
-                    
-                    if not self.__send_packet(PKT_TYPE_DATA, flags, self.seq_num, packet_data):
-                        clog.error("Failed to send packet {}".format(self.seq_num))
-                        return False
-                    
-                    self.seq_num += 1
-            
-            # 发送剩余数据(最后一个包)
-            if len(buffer) > 0:
-                flags = FLAG_LAST
-                if is_first:
-                    flags |= FLAG_FIRST
-                
-                if not self.__send_packet(PKT_TYPE_DATA, flags, self.seq_num, bytes(buffer)):
-                    clog.error("Failed to send last packet {}".format(self.seq_num))
-                    return False
-                self.seq_num += 1
-            
-            # 发送EOT包
-            if not self.__send_packet(PKT_TYPE_EOT, 0, self.seq_num):
-                clog.error("Failed to send EOT packet")
-                return False
-            
-            # 打印统计信息
-            elapsed_time = utime.time() - start_time
-            speed_kbps = (self.stats['total_bytes'] * 8.0) / elapsed_time / 1024.0 if elapsed_time > 0 else 0
-            speed_mbps = speed_kbps / 1024.0
-            
-            if speed_mbps >= 1.0:
-                clog.info("SPI transmission completed: {} bytes in {:.3f}s, Speed: {:.2f} Mbps ({:.2f} Kbps)".format(
-                    self.stats['total_bytes'], elapsed_time, speed_mbps, speed_kbps))
-            else:
-                clog.info("SPI transmission completed: {} bytes in {:.3f}s, Speed: {:.2f} Kbps".format(
-                    self.stats['total_bytes'], elapsed_time, speed_kbps))
-            
-            clog.info("Statistics: {} packets, {} retries, {} errors".format(
-                self.stats['total_packets'], self.stats['retry_packets'], self.stats['error_packets']))
-            
-            return True
-            
-        except Exception as e:
-            clog.error("Error in SPI protocol transmission: {}".format(e))
-            return False
-    
-    def close(self):
-        """关闭SPI对象"""
-        if self.spi_obj is not None:
-            try:
-                if hasattr(self.spi_obj, 'close'):
-                    self.spi_obj.close()
-                elif hasattr(self.spi_obj, 'deinit'):
-                    self.spi_obj.deinit()
-            except Exception as e:
-                clog.error("Error closing SPI object: {}".format(e))
-            self.spi_obj = None
-
-
-def send_data(data_source, spi_obj=None, timeout=60, spi_channel=2, spi_mode=0, spi_clk=8):
-    """
-    便捷函数:发送数据
-    
-    Args:
-        data_source: 数据源(bytes/bytearray/可迭代对象/文件对象)
-        spi_obj: SPI对象(可选,如果为None则自动创建)
-        timeout: 总超时时间(秒)
-        spi_channel: SPI通道,默认2
-        spi_mode: SPI模式,默认0
-        spi_clk: SPI时钟频率,默认8(1.625MHz)
-    
-    Returns:
-        bool: 发送是否成功
-    """
-    sender = SpiProtocolSender(spi_obj, spi_channel, spi_mode, spi_clk)
-    try:
-        return sender.send_data(data_source, timeout)
-    finally:
-        sender.close()
-
-
-def send_from_url(url, timeout=60, spi_channel=2, spi_mode=0, spi_clk=8):
-    """
-    便捷函数:从URL下载并转发到MCU
-    
-    Args:
-        url: 要下载的URL
-        timeout: 总超时时间(秒)
-        spi_channel: SPI通道,默认2
-        spi_mode: SPI模式,默认0
-        spi_clk: SPI时钟频率,默认8(1.625MHz)
-    
-    Returns:
-        bool: 发送是否成功
-    """
-    try:
-        import request
-        response = request.get(url, stream=True, timeout=timeout)
-        if response.status_code != 200:
-            clog.error("HTTP request failed with status code: {}".format(response.status_code))
-            return False
-        
-        return send_data(response.content, None, timeout, spi_channel, spi_mode, spi_clk)
-    except Exception as e:
-        clog.error("Error downloading from URL: {}".format(e))
-        return False
-
diff --git a/cat1modem/src/LeiNiao/spi_protocol_api.py b/cat1modem/src/LeiNiao/spi_protocol_api.py
deleted file mode 100644 (file)
index 2a1d34e..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-SPI协议接口封装
-提供简单的对外接口,隐藏协议细节
-"""
-
-from usr.spi_protocol import send_data, send_from_url, SpiProtocolSender
-import log
-
-log.basicConfig(level=log.INFO)
-clog = log.getLogger("spiprotocolapi")
-
-
-def send_data_simple(data_source, spi_obj=None, timeout=60, spi_channel=2, spi_mode=0, spi_clk=8):
-    """
-    简单发送接口:发送数据到MCU
-    
-    Args:
-        data_source: 数据源,支持:
-            - bytes/bytearray: 内存中的数据
-            - 可迭代对象: 如response.content(网络流)
-            - 文件对象: 如open()返回的对象
-        spi_obj: SPI对象(可选,如果为None则自动创建)
-        timeout: 总超时时间(秒),默认60秒
-        spi_channel: SPI通道,默认2(对应MCU端SPI1)
-        spi_mode: SPI模式,默认0
-        spi_clk: SPI时钟频率,默认8(1.625MHz)
-    
-    Returns:
-        bool: 发送是否成功
-    
-    示例:
-        # 发送内存数据
-        data = b"Hello, MCU!"
-        send_data_simple(data)
-        
-        # 从URL下载并转发
-        send_data_simple_from_url("https://example.com/file.bin")
-        
-        # 发送文件
-        with open("file.bin", "rb") as f:
-            send_data_simple(f)
-    """
-    return send_data(data_source, spi_obj, timeout, spi_channel, spi_mode, spi_clk)
-
-
-def send_data_simple_from_url(url, timeout=60, spi_channel=2, spi_mode=0, spi_clk=8):
-    """
-    简单发送接口:从URL下载并转发到MCU
-    
-    Args:
-        url: 要下载的URL
-        timeout: 总超时时间(秒),默认60秒
-        spi_channel: SPI通道,默认2(对应MCU端SPI1)
-        spi_mode: SPI模式,默认0
-        spi_clk: SPI时钟频率,默认8(1.625MHz)
-    
-    Returns:
-        bool: 发送是否成功
-    
-    示例:
-        send_data_simple_from_url("https://example.com/file.bin")
-    """
-    return send_from_url(url, timeout, spi_channel, spi_mode, spi_clk)
-
-
-def send_file(filepath, timeout=60, spi_channel=2, spi_mode=0, spi_clk=8):
-    """
-    发送本地文件(向后兼容接口)
-    
-    Args:
-        filepath: 文件路径
-        timeout: 总超时时间(秒)
-        spi_channel: SPI通道,默认2(对应MCU端SPI1)
-        spi_mode: SPI模式,默认0
-        spi_clk: SPI时钟频率,默认8(1.625MHz)
-    
-    Returns:
-        bool: 发送是否成功
-    """
-    try:
-        with open(filepath, "rb") as f:
-            return send_data_simple(f, None, timeout, spi_channel, spi_mode, spi_clk)
-    except Exception as e:
-        clog.error("Error opening file {}: {}".format(filepath, e))
-        return False
-
-
-def get_sender_stats(sender):
-    """
-    获取发送统计信息
-    
-    Args:
-        sender: SpiProtocolSender实例
-    
-    Returns:
-        dict: 统计信息字典,包含:
-            - total_packets: 总包数
-            - retry_packets: 重传包数
-            - error_packets: 错误包数
-            - total_bytes: 总字节数
-    """
-    if sender and hasattr(sender, 'stats'):
-        return sender.stats.copy()
-    return {
-        'total_packets': 0,
-        'retry_packets': 0,
-        'error_packets': 0,
-        'total_bytes': 0
-    }
-
diff --git a/cat1modem/src/LeiNiao/spi_protocol_sender.py b/cat1modem/src/LeiNiao/spi_protocol_sender.py
deleted file mode 100644 (file)
index 086bdbb..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-SPI协议发送接口封装
-提供简单的对外接口,隐藏协议细节
-"""
-
-from usr.spi_protocol import send_data, send_from_url, SpiProtocolSender
-import log
-
-log.basicConfig(level=log.INFO)
-clog = log.getLogger("spiprotocolsender")
-
-
-def send_data_simple(data_source, spi_obj=None, timeout=60):
-    """
-    简单发送接口:发送数据到MCU
-    
-    Args:
-        data_source: 数据源,支持:
-            - bytes/bytearray: 内存中的数据
-            - 可迭代对象: 如response.content(网络流)
-            - 文件对象: 如open()返回的对象
-        spi_obj: SPI对象(可选,如果为None则自动创建)
-        timeout: 总超时时间(秒),默认60秒
-    
-    Returns:
-        bool: 发送是否成功
-    
-    示例:
-        # 发送内存数据
-        data = b"Hello, MCU!"
-        send_data_simple(data)
-        
-        # 从URL下载并转发
-        send_data_simple_from_url("https://example.com/file.bin")
-        
-        # 发送文件
-        with open("file.bin", "rb") as f:
-            send_data_simple(f)
-    """
-    return send_data(data_source, spi_obj, timeout)
-
-
-def send_data_simple_from_url(url, timeout=60):
-    """
-    简单发送接口:从URL下载并转发到MCU
-    
-    Args:
-        url: 要下载的URL
-        timeout: 总超时时间(秒),默认60秒
-    
-    Returns:
-        bool: 发送是否成功
-    
-    示例:
-        send_data_simple_from_url("https://example.com/file.bin")
-    """
-    return send_from_url(url, timeout)
-
-
-# 为了向后兼容,保留旧的函数名
-def send_file(filepath, timeout=60):
-    """
-    发送本地文件(向后兼容接口)
-    
-    Args:
-        filepath: 文件路径
-        timeout: 总超时时间(秒)
-    
-    Returns:
-        bool: 发送是否成功
-    """
-    try:
-        with open(filepath, "rb") as f:
-            return send_data_simple(f, None, timeout)
-    except Exception as e:
-        clog.error("Error opening file {}: {}".format(filepath, e))
-        return False
-
diff --git a/cat1modem/src/LeiNiao/spi_protocol_test.py b/cat1modem/src/LeiNiao/spi_protocol_test.py
deleted file mode 100644 (file)
index db8203d..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-SPI协议测试脚本
-测试各种场景的数据传输
-"""
-
-import log
-import utime
-from usr.spi_protocol_api import send_data_simple, send_data_simple_from_url, send_file
-from usr.spi_protocol import SpiProtocolSender
-from machine import SPI
-
-# 设置日志输出级别
-log.basicConfig(level=log.INFO)
-clog = log.getLogger("spiprotocoltest")
-
-
-def test_small_data():
-    """测试小数据包(<1KB)"""
-    clog.info("=" * 60)
-    clog.info("Test 1: Small data packet (<1KB)")
-    clog.info("=" * 60)
-    
-    # 生成小数据(500字节)
-    data = bytearray(500)
-    for i in range(500):
-        data[i] = i % 256
-    
-    success = send_data_simple(data)
-    if success:
-        clog.info("✓ Small data test PASSED")
-    else:
-        clog.error("✗ Small data test FAILED")
-    
-    return success
-
-
-def test_medium_data():
-    """测试中等数据包(1KB-64KB)"""
-    clog.info("=" * 60)
-    clog.info("Test 2: Medium data packet (1KB-64KB)")
-    clog.info("=" * 60)
-    
-    # 生成中等数据(32KB)
-    data = bytearray(32 * 1024)
-    for i in range(32 * 1024):
-        data[i] = i % 256
-    
-    success = send_data_simple(data)
-    if success:
-        clog.info("✓ Medium data test PASSED")
-    else:
-        clog.error("✗ Medium data test FAILED")
-    
-    return success
-
-
-def test_large_data():
-    """测试大数据包(>64KB,需要分包)"""
-    clog.info("=" * 60)
-    clog.info("Test 3: Large data packet (>64KB, will be split)")
-    clog.info("=" * 60)
-    
-    # 生成大数据(200KB,会分成多个包)
-    data = bytearray(200 * 1024)
-    for i in range(200 * 1024):
-        data[i] = i % 256
-    
-    success = send_data_simple(data)
-    if success:
-        clog.info("✓ Large data test PASSED")
-    else:
-        clog.error("✗ Large data test FAILED")
-    
-    return success
-
-
-def test_stream_data():
-    """测试流式数据(模拟网络流)"""
-    clog.info("=" * 60)
-    clog.info("Test 4: Stream data (simulating network stream)")
-    clog.info("=" * 60)
-    
-    # 模拟流式数据(每次生成4KB,总共100KB)
-    def stream_generator():
-        total_size = 100 * 1024
-        chunk_size = 4 * 1024
-        sent = 0
-        while sent < total_size:
-            chunk = bytearray(min(chunk_size, total_size - sent))
-            for i in range(len(chunk)):
-                chunk[i] = (sent + i) % 256
-            sent += len(chunk)
-            yield chunk
-    
-    success = send_data_simple(stream_generator())
-    if success:
-        clog.info("✓ Stream data test PASSED")
-    else:
-        clog.error("✗ Stream data test FAILED")
-    
-    return success
-
-
-def test_from_url(url=None):
-    """测试从URL下载并转发"""
-    clog.info("=" * 60)
-    clog.info("Test 5: Download from URL and forward")
-    clog.info("=" * 60)
-    
-    if url is None:
-        url = "https://file-virtual-person-qcl.test.leiniao.com/ambybox/Emotions/StraightEyes/Amber/WorkAndStudy.mp4"
-        clog.info("Using default test URL: {}".format(url))
-    
-    success = send_data_simple_from_url(url, timeout=120)
-    if success:
-        clog.info("✓ URL download test PASSED")
-    else:
-        clog.error("✗ URL download test FAILED")
-    
-    return success
-
-
-def test_with_stats():
-    """测试带统计信息的发送"""
-    clog.info("=" * 60)
-    clog.info("Test 6: Send with statistics")
-    clog.info("=" * 60)
-    
-    from spi_protocol import SpiProtocolSender
-    
-    # 创建发送器
-    sender = SpiProtocolSender(None, spi_channel=2, spi_mode=0, spi_clk=8)
-    
-    # 生成测试数据(64KB)
-    data = bytearray(64 * 1024)
-    for i in range(64 * 1024):
-        data[i] = i % 256
-    
-    # 发送数据
-    success = sender.send_data(data, timeout=60)
-    
-    # 打印统计信息
-    stats = sender.stats
-    clog.info("Statistics:")
-    clog.info("  Total packets: {}".format(stats['total_packets']))
-    clog.info("  Retry packets: {}".format(stats['retry_packets']))
-    clog.info("  Error packets: {}".format(stats['error_packets']))
-    clog.info("  Total bytes: {} ({:.2f} KB)".format(
-        stats['total_bytes'], stats['total_bytes'] / 1024.0))
-    
-    # 关闭
-    sender.close()
-    
-    if success:
-        clog.info("✓ Statistics test PASSED")
-    else:
-        clog.error("✗ Statistics test FAILED")
-    
-    return success
-
-
-def run_all_tests():
-    """运行所有测试"""
-    clog.info("Starting SPI Protocol Test Suite...")
-    clog.info("")
-    
-    results = []
-    
-    # 测试1:小数据包
-    results.append(("Small Data", test_small_data()))
-    utime.sleep(1)
-    
-    # 测试2:中等数据包
-    results.append(("Medium Data", test_medium_data()))
-    utime.sleep(1)
-    
-    # 测试3:大数据包
-    results.append(("Large Data", test_large_data()))
-    utime.sleep(1)
-    
-    # 测试4:流式数据
-    results.append(("Stream Data", test_stream_data()))
-    utime.sleep(1)
-    
-    # 测试5:从URL下载(可选,需要网络)
-    # results.append(("URL Download", test_from_url()))
-    # utime.sleep(1)
-    
-    # 测试6:带统计信息
-    results.append(("With Statistics", test_with_stats()))
-    
-    # 打印测试结果
-    clog.info("")
-    clog.info("=" * 60)
-    clog.info("Test Results Summary")
-    clog.info("=" * 60)
-    
-    passed = 0
-    failed = 0
-    
-    for test_name, result in results:
-        status = "PASSED" if result else "FAILED"
-        symbol = "✓" if result else "✗"
-        clog.info("{} {}: {}".format(symbol, test_name, status))
-        if result:
-            passed += 1
-        else:
-            failed += 1
-    
-    clog.info("")
-    clog.info("Total: {} passed, {} failed".format(passed, failed))
-    
-    if failed == 0:
-        clog.info("All tests PASSED!")
-    else:
-        clog.error("Some tests FAILED!")
-    
-    return failed == 0
-
-
-def test_single_scenario():
-    """测试单个场景(用于调试)"""
-    clog.info("Running single scenario test...")
-    
-    # 可以根据需要修改测试场景
-    return test_small_data()
-
-
-if __name__ == '__main__':
-    # 运行所有测试
-    # run_all_tests()
-    
-    # 或者运行单个测试
-    test_single_scenario()
-
diff --git a/cat1modem/src/LeiNiao/spi_protocol_test_2mb.py b/cat1modem/src/LeiNiao/spi_protocol_test_2mb.py
deleted file mode 100644 (file)
index 5ad2f00..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-SPI新协议测试应用
-按照旧协议的逻辑生成2MB递增数据,使用新协议接口进行发送
-统计发送时长、速率和总量
-"""
-
-import log
-import utime
-from usr.spi_protocol_api import send_data_simple, get_sender_stats
-from usr.spi_protocol import SpiProtocolSender
-
-# 设置日志输出级别
-log.basicConfig(level=log.INFO)
-clog = log.getLogger("spiprototest")
-
-# 测试参数
-TEST_DATA_SIZE = 2 * 1024 * 1024  # 2MB
-SPI_CHANNEL = 2  # SPI通道2(对应MCU端SPI1)
-SPI_MODE = 0  # Mode 0
-SPI_CLK = 8  # 1.625MHz(可根据需要调整:8=1.625MHz, 9=3.25MHz, 12=26MHz)
-
-
-class IncrementalDataGenerator:
-    """
-    递增数据生成器
-    按照旧协议的逻辑生成递增数据(0, 1, 2, ..., 255, 0, 1, ...)
-    """
-    
-    def __init__(self, total_size):
-        """
-        初始化数据生成器
-        
-        Args:
-            total_size: 要生成的数据总大小(字节)
-        """
-        self.total_size = total_size
-        self.current_offset = 0
-    
-    def __iter__(self):
-        """返回迭代器自身"""
-        return self
-    
-    def __next__(self):
-        """生成下一个字节"""
-        if self.current_offset >= self.total_size:
-            raise StopIteration
-        
-        # 生成递增字节值:offset % 256
-        byte_value = self.current_offset % 256
-        self.current_offset += 1
-        return byte_value
-    
-    def generate_chunk(self, chunk_size):
-        """
-        生成指定大小的数据块
-        
-        Args:
-            chunk_size: 数据块大小(字节)
-            
-        Returns:
-            bytearray: 递增数据块
-        """
-        remaining = self.total_size - self.current_offset
-        if remaining <= 0:
-            return None
-        
-        actual_size = min(chunk_size, remaining)
-        chunk = bytearray(actual_size)
-        
-        for i in range(actual_size):
-            chunk[i] = self.current_offset % 256
-            self.current_offset += 1
-        
-        return chunk
-
-
-def run_spi_protocol_test_2mb(data_size=TEST_DATA_SIZE, 
-                               spi_channel=SPI_CHANNEL, 
-                               spi_mode=SPI_MODE, 
-                               spi_clk=SPI_CLK):
-    """
-    运行SPI新协议2MB测试
-    
-    Args:
-        data_size: 要发送的数据总大小(字节),默认2MB
-        spi_channel: SPI通道,默认2(对应MCU端SPI1)
-        spi_mode: SPI模式,默认0
-        spi_clk: SPI时钟频率,默认8(1.625MHz)
-        
-    Returns:
-        tuple: (success: bool, send_time: float, total_bytes: int, stats: dict)
-            success: 测试是否成功
-            send_time: 发送耗时(秒)
-            total_bytes: 发送的总字节数
-            stats: 发送统计信息(包数、重传数、错误数等)
-    """
-    try:
-        clog.info("=" * 60)
-        clog.info("SPI Protocol Test - 2MB Incremental Data")
-        clog.info("=" * 60)
-        clog.info("Test parameters:")
-        clog.info("  Total data size: {} bytes ({:.2f} MB)".format(
-            data_size, data_size / 1024.0 / 1024.0))
-        clog.info("  SPI channel: {}, mode: {}, clk: {}".format(
-            spi_channel, spi_mode, spi_clk))
-        clog.info("  Data pattern: Incremental bytes (0, 1, 2, ..., 255, 0, 1, ...)")
-        clog.info("  Protocol: New reliable SPI protocol with CRC16 and retransmission")
-        clog.info("")
-        
-        # 创建数据生成器
-        data_generator = IncrementalDataGenerator(data_size)
-        
-        # 记录开始时间
-        start_time = utime.time()
-        start_time_ms = int(utime.time() * 1000)  # 转换为毫秒
-        
-        clog.info("Starting data transmission...")
-        clog.info("  Using new SPI protocol (reliable protocol)")
-        clog.info("  Data will be automatically packetized and sent with CRC16 checksums")
-        clog.info("")
-        
-        # 使用新协议发送数据
-        # 创建一个生成器函数,每次生成一个chunk
-        def data_source():
-            """数据源生成器函数"""
-            generator = IncrementalDataGenerator(data_size)
-            chunk_size = 64 * 1024  # 64KB chunks(协议会自动分包)
-            while True:
-                chunk = generator.generate_chunk(chunk_size)
-                if chunk is None:
-                    break
-                yield chunk
-        
-        # 使用send_data_simple发送数据
-        success = send_data_simple(
-            data_source(),
-            spi_obj=None,  # 自动创建SPI对象
-            timeout=120,  # 2分钟超时(2MB数据可能需要较长时间)
-            spi_channel=spi_channel,
-            spi_mode=spi_mode,
-            spi_clk=spi_clk
-        )
-        
-        # 记录结束时间
-        end_time = utime.time()
-        end_time_ms = int(utime.time() * 1000)  # 转换为毫秒
-        send_time = end_time - start_time
-        send_time_ms = end_time_ms - start_time_ms
-        
-        # 获取发送统计信息(需要从SpiProtocolSender获取)
-        # 注意:send_data_simple内部创建了SpiProtocolSender,但我们无法直接访问
-        # 所以我们需要修改send_data_simple来返回统计信息,或者使用另一种方式
-        
-        # 计算传输速度
-        if send_time > 0:
-            speed_bps = (data_size * 8.0) / send_time  # bits per second
-            speed_kbps = speed_bps / 1024.0  # Kbps
-            speed_mbps = speed_kbps / 1024.0  # Mbps
-        else:
-            speed_bps = 0
-            speed_kbps = 0
-            speed_mbps = 0
-        
-        # 打印结果
-        clog.info("")
-        clog.info("=" * 60)
-        clog.info("Test Results")
-        clog.info("=" * 60)
-        clog.info("  Success: {}".format("YES" if success else "NO"))
-        clog.info("  Total bytes sent: {} ({:.2f} MB, {:.2f} KB)".format(
-            data_size, data_size / 1024.0 / 1024.0, data_size / 1024.0))
-        clog.info("  Send time: {:.3f} seconds ({:.0f} ms)".format(
-            send_time, send_time_ms))
-        
-        if speed_mbps >= 1.0:
-            clog.info("  Transfer speed: {:.2f} Mbps ({:.2f} Kbps, {:.0f} bps)".format(
-                speed_mbps, speed_kbps, speed_bps))
-        else:
-            clog.info("  Transfer speed: {:.2f} Kbps ({:.0f} bps)".format(
-                speed_kbps, speed_bps))
-        
-        clog.info("")
-        clog.info("Data pattern info:")
-        clog.info("  Pattern: Incremental bytes (0, 1, 2, ..., 255, 0, 1, ...)")
-        clog.info("  Start value: 0")
-        clog.info("  Cycle: Every 256 bytes")
-        clog.info("  Expected byte at offset N: (N % 256)")
-        clog.info("")
-        
-        # 统计信息(暂时无法获取,需要修改send_data_simple)
-        stats = {
-            'total_bytes': data_size,
-            'send_time': send_time,
-            'send_time_ms': send_time_ms,
-            'speed_bps': speed_bps,
-            'speed_kbps': speed_kbps,
-            'speed_mbps': speed_mbps,
-            'success': success
-        }
-        
-        if success:
-            clog.info("✓ Test PASSED")
-        else:
-            clog.error("✗ Test FAILED")
-        
-        clog.info("=" * 60)
-        
-        return success, send_time, data_size, stats
-        
-    except Exception as e:
-        clog.error("Error in SPI protocol test: {}".format(e))
-        # 在嵌入式环境中,traceback可能不可用,只打印错误信息
-        try:
-            import traceback
-            traceback.print_exc()
-        except ImportError:
-            # traceback模块不可用,只打印错误类型和消息
-            clog.error("Exception type: {}, message: {}".format(type(e).__name__, str(e)))
-        return False, 0.0, 0, {}
-
-
-def run_spi_protocol_test_with_stats(data_size=TEST_DATA_SIZE, 
-                                      spi_channel=SPI_CHANNEL, 
-                                      spi_mode=SPI_MODE, 
-                                      spi_clk=SPI_CLK):
-    """
-    运行SPI新协议测试(带详细统计信息)
-    直接使用SpiProtocolSender以获取统计信息
-    
-    Args:
-        data_size: 要发送的数据总大小(字节),默认2MB
-        spi_channel: SPI通道,默认2(对应MCU端SPI1)
-        spi_mode: SPI模式,默认0
-        spi_clk: SPI时钟频率,默认8(1.625MHz)
-        
-    Returns:
-        tuple: (success: bool, send_time: float, total_bytes: int, stats: dict)
-    """
-    try:
-        clog.info("=" * 60)
-        clog.info("SPI Protocol Test - 2MB Incremental Data (with stats)")
-        clog.info("=" * 60)
-        clog.info("Test parameters:")
-        clog.info("  Total data size: {} bytes ({:.2f} MB)".format(
-            data_size, data_size / 1024.0 / 1024.0))
-        clog.info("  SPI channel: {}, mode: {}, clk: {}".format(
-            spi_channel, spi_mode, spi_clk))
-        clog.info("  Data pattern: Incremental bytes (0, 1, 2, ..., 255, 0, 1, ...)")
-        clog.info("")
-        
-        # 创建SPI协议发送器
-        sender = SpiProtocolSender(None, spi_channel, spi_mode, spi_clk)
-        
-        # 初始化SPI
-        if not sender.__init_spi():
-            clog.error("Failed to initialize SPI")
-            return False, 0.0, 0, {}
-        
-        # 记录开始时间
-        start_time = utime.time()
-        start_time_ms = int(utime.time() * 1000)  # 转换为毫秒
-        
-        clog.info("Starting data transmission...")
-        clog.info("  Using new SPI protocol (reliable protocol)")
-        clog.info("")
-        
-        # 创建数据生成器
-        data_generator = IncrementalDataGenerator(data_size)
-        
-        # 发送数据(使用send_data方法,它会自动处理分包和标志位)
-        # 创建一个生成器函数作为数据源(使用小块生成,减少内存占用)
-        def data_source():
-            """数据源生成器函数"""
-            generator = IncrementalDataGenerator(data_size)
-            chunk_size = 1024  # 1KB chunks(协议会自动分包,使用小块减少内存占用)
-            while True:
-                chunk = generator.generate_chunk(chunk_size)
-                if chunk is None:
-                    break
-                yield chunk
-        
-        # 使用send_data方法发送数据(会自动处理分包、标志位等)
-        success = sender.send_data(data_source(), timeout=120)
-        
-        if not success:
-            clog.error("Failed to send data")
-            sender.close()
-            return False, 0.0, 0, {}
-        
-        # 记录结束时间
-        end_time = utime.time()
-        end_time_ms = int(utime.time() * 1000)  # 转换为毫秒
-        send_time = end_time - start_time
-        send_time_ms = end_time_ms - start_time_ms
-        
-        # 获取统计信息
-        stats = get_sender_stats(sender)
-        total_sent = stats.get('total_bytes', data_size)  # 使用统计信息中的总字节数
-        stats['send_time'] = send_time
-        stats['send_time_ms'] = send_time_ms
-        
-        # 计算传输速度
-        if send_time > 0:
-            speed_bps = (total_sent * 8.0) / send_time
-            speed_kbps = speed_bps / 1024.0
-            speed_mbps = speed_kbps / 1024.0
-        else:
-            speed_bps = 0
-            speed_kbps = 0
-            speed_mbps = 0
-        
-        stats['speed_bps'] = speed_bps
-        stats['speed_kbps'] = speed_kbps
-        stats['speed_mbps'] = speed_mbps
-        
-        # 关闭SPI
-        sender.close()
-        
-        # 打印结果
-        clog.info("")
-        clog.info("=" * 60)
-        clog.info("Test Results")
-        clog.info("=" * 60)
-        clog.info("  Success: YES")
-        clog.info("  Total bytes sent: {} ({:.2f} MB, {:.2f} KB)".format(
-            total_sent, total_sent / 1024.0 / 1024.0, total_sent / 1024.0))
-        clog.info("  Send time: {:.3f} seconds ({:.0f} ms)".format(
-            send_time, send_time_ms))
-        
-        if speed_mbps >= 1.0:
-            clog.info("  Transfer speed: {:.2f} Mbps ({:.2f} Kbps)".format(
-                speed_mbps, speed_kbps))
-        else:
-            clog.info("  Transfer speed: {:.2f} Kbps".format(speed_kbps))
-        
-        clog.info("")
-        clog.info("Protocol Statistics:")
-        clog.info("  Total packets: {}".format(stats.get('total_packets', 0)))
-        clog.info("  Retry packets: {}".format(stats.get('retry_packets', 0)))
-        clog.info("  Error packets: {}".format(stats.get('error_packets', 0)))
-        clog.info("  Total bytes: {} ({:.2f} MB)".format(
-            stats.get('total_bytes', 0), 
-            stats.get('total_bytes', 0) / 1024.0 / 1024.0))
-        clog.info("")
-        
-        clog.info("✓ Test PASSED")
-        clog.info("=" * 60)
-        
-        return True, send_time, total_sent, stats
-        
-    except Exception as e:
-        clog.error("Error in SPI protocol test: {}".format(e))
-        # 在嵌入式环境中,traceback可能不可用,只打印错误信息
-        try:
-            import traceback
-            traceback.print_exc()
-        except ImportError:
-            # traceback模块不可用,只打印错误类型和消息
-            clog.error("Exception type: {}, message: {}".format(type(e).__name__, str(e)))
-        return False, 0.0, 0, {}
-
-
-# 主函数
-if __name__ == '__main__':
-    # 运行2MB递增数据测试(带详细统计)
-    success, send_time, total_bytes, stats = run_spi_protocol_test_with_stats(
-        data_size=2 * 1024 * 1024,  # 2MB
-        spi_channel=2,  # SPI通道2(对应MCU端SPI1)
-        spi_mode=0,  # Mode 0
-        spi_clk=8  # 1.625MHz(可根据需要调整)
-    )
-    
-    if success:
-        clog.info("")
-        clog.info("Final Summary:")
-        clog.info("  Total bytes: {} ({:.2f} MB)".format(
-            total_bytes, total_bytes / 1024.0 / 1024.0))
-        clog.info("  Send time: {:.3f} seconds".format(send_time))
-        if stats.get('speed_mbps', 0) >= 1.0:
-            clog.info("  Speed: {:.2f} Mbps".format(stats.get('speed_mbps', 0)))
-        else:
-            clog.info("  Speed: {:.2f} Kbps".format(stats.get('speed_kbps', 0)))
-    else:
-        clog.error("Test failed!")
-