Bootloader上位机,基于UDS实现,DoCAN(包括源码和发布的小程序)

Bootloader上位机,基于UDS实现,DoCAN(包括源码和发布的小程序). 可根据自己的程序扩展和重新设计升级流程.

先扔个硬核的:我撸的这套Bootloader上位机底层基于SocketCAN搞DoCAN通信,支持ISO15765-2的分包重组。上位机界面用PyQt5糊的,核心就三个模块------协议栈、文件解析器、状态机。

看这个处理UDS正响应的代码片段:

python 复制代码
def handle_positive_response(self, service_id, data):
    if service_id == 0x31:  # 例程控制
        if self.current_routine == ROUTINE_ERASE_MEMORY:
            self._send_request(0x31, [0x01, 0xFF, 0x00])  # 触发下载
    elif service_id == 0x34:  # 下载请求
        self.block_counter += 1
        self._send_next_data_block()
    elif service_id == 0x36:  # 退出传输
        self._verify_flash()

注意那个block_counter自增的位置,必须在收到正确响应后才更新。之前翻车过在发送时就计数,结果网络丢包直接导致数据错位,烧了ECU的boot区(幸亏提前焊了测试座)。

文件传输用了个骚操作------动态分块算法。根据当前通信延迟自动调整块大小,实测从32字节到4096字节弹性变化。看这个自适应逻辑:

python 复制代码
def _calculate_optimal_block_size(self, last_transfer_time):
    if last_transfer_time < 0.1:
        return min(self.max_block_size, self.current_block_size * 2)
    elif last_transfer_time > 0.5:
        return max(self.min_block_size, self.current_block_size // 2)
    else:
        return self.current_block_size

别小看这几行,配合硬件在环测试能提升30%刷写速度。但要注意ECU端的buffer容量,有次给某国产芯片设了2048的分块,结果把CAN控制器缓冲区撑爆了,后来加了个预设参数表才解决。

说到坑点,时间参数必须死磕ISO14229:

  • P2Server超时默认50ms
  • P2*Server延长超时需要协商
  • S3Server保活间隔建议3000ms

我在代码里搞了个时间守护线程,用优先级队列管理定时任务:

python 复制代码
class TimingWheel(Thread):
    def __init__(self):
        super().__init__()
        self.tasks = PriorityQueue()
    
    def add_task(self, delay, callback):
        deadline = time.time() + delay/1000
        self.tasks.put((deadline, callback))
    
    def run(self):
        while not self.exit_flag:
            now = time.time()
            if not self.tasks.empty():
                deadline, callback = self.tasks.queue[0]
                if now >= deadline:
                    self.tasks.get()
                    callback()
            time.sleep(0.001)

这玩意儿比传统定时器省资源,特别是在同时处理多个ECU会话时。但要注意Python的GIL锁问题,回调函数里千万别搞阻塞操作。

最后安利下我的升级流程验证方案------三步校验法:

  1. 传输后立即CRC32校验
  2. 重启ECU后回读比对
  3. 执行目标程序的自我签名验证

源码里有个贼好用的debug模式,开启后会记录所有交互报文。有次客户现场出问题,直接拿日志文件喂给回放脚本,十分钟就定位到网关的报文过滤问题。

代码仓库里还藏了个彩蛋:在关于页面连续点击版本号三次,会弹出CAN总线压力测试工具。这个本来是给自己调试用的,结果好几个客户当正式功能在用了(笑)。

相关推荐
yngsqq3 个月前
Lisp 与 C# 交互中,类型码(TypeCode)的映射关系
开发语言·c#·lisp
Hóng xīng qiáo3 个月前
swVBA自学笔记014、Lisp适合对SolidWorks进行二次开发吗 ?
开发语言·笔记·lisp
skywalk81633 个月前
升级DrRacket8.10到8.18版本@Ubuntu24.04
linux·运维·服务器·lisp·racket
开开心心就好6 个月前
高效批量转换Word到PDF的方法
javascript·安全·智能手机·pdf·word·objective-c·lisp
skywalk81636 个月前
arc3.2语言sort的时候报错:(sort < `(2 9 3 7 5 1)) 需要写成这种:(sort > (pair (list 3 2)))
开发语言·lisp·arc
chem41118 个月前
Conmon lisp Demo
服务器·数据库·lisp
莲动渔舟8 个月前
Nyquist插件基础:打印格式化字符串(LISP语言)
开发语言·lisp·音频处理·audacity
莲动渔舟8 个月前
Nyquist插件基础:LISP语法-自定义函数
服务器·开发语言·lisp·音频处理·audacity
莲动渔舟8 个月前
Nyquist插件基础:LISP语法-运算符
开发语言·lisp·音频处理·audacity