基于Tkinter制作简易的串口bootloader上位机

news2024/10/6 5:56:20

文章目录

    • 前言
    • 1.测试设备
      • 1.1 UART Bootloaer软件架构图
      • 1.2 UART Bootloader流程图
      • 1.3 通信数据处理
        • 1.3.1 S19文件的简单介绍
        • 1.3.2 S19文件的传输方式
        • 1.3.2 接收数据之后的处理
      • 1.4 链接文件设置
        • 1.4.1 Bootloader设置
        • 1.4.2 Application设置
    • 2.上位机
      • 2.1 参考资料
      • 2.2 Tkinter简介
      • 2.3 上位机开发
        • 2.3.1 环境准备
        • 2.3.2 用户界面开发
        • 2.3.3 串口发送实现
        • 2.3.4 异常情况的处理
        • 2.3.5 总结
    • 3.升级测试
    • 4.例程分享

前言

最开始打算使用pyqt5制作bootloader上位机的,但是折腾开发环境太麻烦,对应的资料太多太杂,导致进展缓慢。后来在网上发现了基于tkinter的串口助手项目以及适合新手的tkinter学习网站,决定尝试使用tkinter,终于在春节的这段时间折腾出来一个简易的串口bootloader上位机。

1.测试设备

NXP官网有发布基于S32K148EVB的串口bootloader例程以及对应的应用笔记AN12218,链接如下:

  • AN12218: S32K1xx Bootloader – Application Note (nxp.com)
  • AN12218SW, Application note software for AN12218 (nxp.com)

但是笔者手上只有S32K144的官方开发板,所以针对AN12218的软件做了一些简单修改,适配S32K144EVB-Q100,修改后的S32K144例程会和上位机源码一起在文末分享出来。

下面简要介绍下S32K144的串口bootloader例程。

1.1 UART Bootloaer软件架构图

该串口bootloader例程采用了分层设计,整体的软件架构图如下图:

软件架构

每层的说明如下:

  • Bootloader:检查5S内是否有数据输入,超过5s没有数据或者应用程序升级完成,就跳转到应用程序。
  • Communication handling / Memory handling:处理接收的数据并写入到对应的Flash中
  • Microcontroller drivers:提供MCU的UART驱动和Flash驱动

1.2 UART Bootloader流程图

该串口bootloader例程的整体流程如下:

bootloader流程图

  1. 首先初始化需要用到的通信外设,并开启超时功能。
  2. 如果在超时时间(默认为5S)内,通信接口收到数据,就下载传输过来的APP固件。
  3. 如果超时发生或者APP固件下载完成,就将配置过的寄存器设置为复位时的状态,然后跳转到用户程序。

这个例程有一个需要注意的问题,如果上电后5s内没有收到数据,程序就会跳到一段没有代码的地址处(默认为0x2000)运行,从而跑飞。如果想要继续测试升级功能,需要手动复位下MCU。

1.3 通信数据处理

该串口bootloader例程升级的APP固件需要使用S19文件格式,并且对于S19文件的解析基本都在MCU端,上位机对S19文件的处理不多。

1.3.1 S19文件的简单介绍

  1. S19文件内容为ASCII编码,截取部分S19内容如下:

S19文件内容

  1. S19文件每行的构成如下图,以上图的hello_s32k144.srec的第一行为例,S0就是type,15是count,0000是Address,68656C6C6F5F7333326B3134342E73726563就是实际要传输的data,最后的C0是Checksum。

S19文件构成

有关S19文件的进一步介绍可以查看下图或者网上搜索,相关资料非常丰富。
S19文件解析

1.3.2 S19文件的传输方式

对于S19每行的内容,上位机按如下两种方式发送:

  • Type(S0-S9)部分数据按照字符形式发送,如S1,MCU的串口接收到的就是"S"(0x53),“1”(0x31)
  • Count/Address/Data/Checksum部分数据将字符类型转变成十六进制的数字类型进行发送,如132000,MCU的串口接收到的就是0x13,0x20,0x00

MCU端也按照如上两种方式接收。

1.3.2 接收数据之后的处理

接收到S19之后MCU的处理流程如下图:

数据处理流程

  1. MCU会预先定义一个结构体,用来存储每次收到的数据,并按照S19的格式进行存储,然后校验Checksum(CRC校验)。
  2. 如果校验成功,按照地址刷写flash,并发送ACK(0x41);如果校验失败,发送CRC错误码(0x45)。
  3. 当S19所有行的数据都发送完毕之后,跳出通信数据处理函数。

AN12218文档中关于MCU的响应码描述有误,具体参考comm.h文件中的宏定义,如下:

/* Error codes */
#define ERR_OK 	0x41
#define ERR_CRC	0x45

1.4 链接文件设置

对于bootloader以及APP工程,还需要约定各自的地址地址,防止相互干扰。S32DS因为采用的GCC编译器,所以对于工程地址的修改,只需要修改链接文件即可。

1.4.1 Bootloader设置

  1. Bootloader的代码如果放在P-flash中,链接文件保持原样。

bootloader链接文件(P-flash)

  1. Bootloader的代码如果放在D-flash中,链接文件按如下方式修改,可以按需要修改m_text段的大小。

bootloader链接文件(D-flash)

1.4.2 Application设置

  1. 应用层代码从0x00002000处开始运行,链接文件修改如下:

APP链接文件

  1. 上述配置的应用层代码只能在调试模式下查看效果,如果想要在非调试模式下查看代码效果(即制作伪APP工程),需要修改中断向量位置和flash配置区域,如下所示:

伪APP链接文件

有关下位机的功能介绍以及注意事项上文已介绍完毕,接下来介绍上位机部分。

2.上位机

2.1 参考资料

本次制作串口上位机参考的gitee上面的项目链接如下:

  • Python_Tkinter_UART: 基于Python Tkinter serial的UART调试助手

关于tkinter的新手学习资料,推荐如下:

  • Tkinter教程(biancheng.net)

2.2 Tkinter简介

Tkinter 是 Python 自带的标准库,因此无须另行安装,它支持跨平台运行,不仅可以在 Windows 平台上运行,还支持在 Linux 和 Mac 平台上运行。

Tkinter适用于有Python基础,想做个图形化界面程序,但不会C++、C#的人员快速开发一些简单的小工具。对于复杂、绚丽的图形界面程序,使用tkinter开发比较吃力。

2.3 上位机开发

2.3.1 环境准备

本次使用的python版本为3.6.6,因为要使用串口,还得安装下python serial模块,在命令行输入如下命令即可。

pip install pyserial

如果后续想打包成exe文件,还需要安装pyinstaller模块,方法同上。

2.3.2 用户界面开发

用户界面的布局如下:

主窗口放置了三个容器,其中

  • 容器1主要存放串口信息、文件选择按钮和发送按钮;
  • 容器2主要包含文件升级的情况;
  • 容器3主要存放升级进度条,升级信息情况和作者信息。

截取容器1的实现代码如下:

# a frame contains COM's information, start/stop button, and select files button/label
frame_COMinf = tk.Frame(window)
frame_COMinf.grid(row = 1, column = 1)

labelCOM = tk.Label(frame_COMinf,text="Port: ")
self.COM = tk.StringVar(value = "COM15")
ertryCOM = tk.Entry(frame_COMinf, textvariable = self.COM)
labelCOM.grid(row = 1, column = 1, padx = 5, pady = 3)
ertryCOM.grid(row = 1, column = 2, padx = 5, pady = 3)

labelBaudrate = tk.Label(frame_COMinf,text="Baudrate: ")
self.Baudrate = tk.IntVar(value = 19200)
ertryBaudrate = tk.Entry(frame_COMinf, textvariable = self.Baudrate)
labelBaudrate.grid(row = 1, column = 3, padx = 5, pady = 3)
ertryBaudrate.grid(row = 1, column = 4, padx = 5, pady = 3)

labelParity = tk.Label(frame_COMinf,text="Parity: ")
self.Parity = tk.StringVar(value ="NONE")
comboParity = ttk.Combobox(frame_COMinf, width = 17, textvariable=self.Parity)
comboParity["values"] = ("NONE","ODD","EVEN","MARK","SPACE")
comboParity["state"] = "readonly"
labelParity.grid(row = 2, column = 1, padx = 5, pady = 3)
comboParity.grid(row = 2, column = 2, padx = 5, pady = 3)

labelStopbits = tk.Label(frame_COMinf,text="Stopbits: ")
self.Stopbits = tk.StringVar(value ="1")
comboStopbits = ttk.Combobox(frame_COMinf, width = 17, textvariable=self.Stopbits)
comboStopbits["values"] = ("1","1.5","2")
comboStopbits["state"] = "readonly"
labelStopbits.grid(row = 2, column = 3, padx = 5, pady = 3)
comboStopbits.grid(row = 2, column = 4, padx = 5, pady = 3)

self.buttonSelect = tk.Button(frame_COMinf, text="Select Files", relief="raised", command=self.processButtonSelect)
self.buttonSelect.grid(row = 3, column = 1, padx = 5, pady = 3)
self.labelFile = tk.Label(frame_COMinf, anchor = "w", relief="sunken", width = 30, wraplength = 200, justify = "left")
self.labelFile.grid(row = 3, column = 2, columnspan = 2, padx = 5, pady = 3, sticky = tk.W)
self.fileName = ""
        
self.buttonSS = tk.Button(frame_COMinf, text = "Start", command = self.processButtonSS)
self.buttonSS.grid(row = 3, column = 4, padx = 5, pady = 3, sticky = tk.E)

2.3.3 串口发送实现

整个通信流程如下:

  1. 上位机和测试设备之间使用UART通信,上位机需要逐行读取S19文件并转换成字节串发送出去。
  2. 上位机将一行数据发送给测试设备之后,会收到测试设备回复的字节。如果发送的数据校验无误,测试设备回复0x41,否则回复0x45。
  3. 上位机如果收到0x45的回复,需要重复发送这一行的数据,直至收到0x41的回复。

截取串口发送的实现代码如下:

self.OutputText.insert(tk.END,"Start sending the file !\r\n")
self.progressbarSend['maximum']=len(self.str_appFile)
for appFile_line in range(len(self.str_appFile)):
    self.progressbarSend["value"] = appFile_line + 1
    strToSend = self.str_appFile[appFile_line].strip()
    self.OutputText.insert(tk.END,"The data of line "+str(appFile_line+1)+ " was sent!\r\n")
    # dispaly update
    self.OutputText.yview_moveto(1)
    bytesToSend_type = strToSend[0:2].encode(encoding='ASCII')
    self.ser.write(bytesToSend_type)
    bytesToSend_data = bytes.fromhex(strToSend[2:])
    self.ser.write(bytesToSend_data)
    time.sleep(0.05)

2.3.4 异常情况的处理

用户实际在操作上位机时,有时并不一定按开发者预想的方式进行,所以需要考虑一些异常情况并处理。

本次上位机demo主要考虑了如下几种异常情况:

  • 串口信息填写错误,导致没有可用的串口
  • 用户点击选择文件按钮之后并没有选择文件
  • 用户点击开始按钮之前没有选择文件
  • 文件传输过程中点击停止按钮会关闭串口导致WriteUART函数运行异常

截取文件选择按钮的回调函数代码如下:

def processButtonSelect(self):
    self.fileName = filedialog.askopenfilename(filetypes = [("SREC","*.srec")])
    if self.fileName != "":
        self.labelFile.config(text = self.fileName)
        appFile = open(self.fileName, mode="r")
        self.str_appFile = appFile.readlines()
        appFile.close()
    else:
        self.labelFile.config(text = "You have not selected any files!")

2.3.5 总结

上位机的整体实现思路如下面的思维导图所示:

3.升级测试

准备一块S32K144EVB-Q100的板子,烧录好串口bootloader程序,连接上电脑。接下来的操作如下GIF所示:

由于测试设备的串口bootloader代码中对每行传输的有效数据字节限制在37以内,所以如果每次传输的有效数据字节超过37也会回复0x45。

4.例程分享

此次文中提到的测试设备的程序以及上位机源码已分享到gitee,链接接如下:

  • https://gitee.com/Yingming_Cai/tkinter_-s32k144-evb_-bootloader/tree/master

如果觉得本文对您有用,,不妨给个一键三连!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/179809.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++初阶:vector类

文章目录1 vector介绍2 实现vector2.1 类的定义2.2 默认成员函数2.2.1 构造函数2.2.2 析构函数2.2.3 拷贝构造2.2.4 赋值重载2.3访问接口2.4 容量接口2.5 修改接口2.5.1 尾插尾删2.5.2 任意位置插入2.5.3 任意位置删除2.6 其他接口1 vector介绍 1 vector是表示可变大小数组的序…

每日学术速递1.26

CV - 计算机视觉 今天带来的是北航IRIP实验室被国际人工智能联合会议IJCAI-ECAI 2022接收的3篇论文。 IJCAI 是人工智能领域中最主要的学术会议之一,原为单数年召开,自2015年起改为每年召开,本次IJCAI与ECAI一起召开。IJCAI官网显示&#xf…

【Linux】冯诺依曼体系结构与操作系统概念理解

👑作者主页:安 度 因 🏠学习社区:StackFrame 📖专栏链接:Linux 文章目录一、前言二、冯诺依曼体系结构1、体系简述2、内存的重要性3、硬件方案解释软件行为4、体系结构中的数据流动5、拓展三、操作系统简述…

ch1 操作系统启动

lab1 实验准备 按照实验解压后进入oslab中,按照make编译。 cd /home/shiyanlou/oslab/ tar -zxvf hit-oslab-linux-20110823.tar.gz \-C /home/shiyanlou/ ./run cd ./linux-0.11/ make all make clean ..... make all运行脚本即可启动内核 调试 汇编级调试和C语…

贪心算法的题目

每一步都做出一个局部最优的选择,最终的结果就是全局最优 只有一部分问题才能用贪心算法(严格来讲,一个问题能不能用贪心算法需要证明的) 2022.8.30 蔚来笔试题: 有a个y,b个o,c个u,用这些字母拼成一个字符串&#xf…

Anaconda软件中的 Environments 及 Jupyter Lab使用方法介绍

来源:投稿 作者:助教-Frank 编辑:学姐 本篇是打造舒适的AI开发环境系列-软件篇1 上期内容:学人工智能电脑&主机八大件配置选择指南 本文的重点: (1)Environments使用中如何安装python包.; (2)Jupyter Lab如何在…

Kettle(6):表输入组件——mysql转mysql

1 需求 前面我们已经将Excel中数据抽取到了MySQL的t_user表中。 现在有了新需求,要将MySQL数据库中的 t_user 表中的数据抽取出来,装载到另外一张表 t_user1中。 2 构建Kettle数据流图 2.1 从核心对象的输入组件中,将「表输入」组件拖拽到中…

电脑下载软件用什么软件好?安卓手机下载软件用哪个软件好?IDM下载器说:在做的都是弟弟

大年初五,迎财神,先祝大家新的一年财源滚滚,接下来为大家分享超级经典的IDM下载器,电脑端毫无争议的下载工具,安卓平台idm也是力压群雄,下面就为大家详细分享下: 1:1DM下载器&#x…

微服务统一登陆认证怎么做

[微服务统一登陆认证怎么做}?JWT 无状态登录原理 1.1.什么是有状态? 有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session…

notepad++在行首行尾添加字符 | 选中列

目录 1、首行/尾行添加字符 1【使用快捷键 CtrlH】 2【^为行首、$为行尾】 3、查找模式选中正则表达式 2、Notepad中列选(竖选) 1、首行/尾行添加字符 1【使用快捷键 CtrlH】 或者鼠标 2【^为行首、$为行尾】 3、查找模式选中正则表达式 2、Notepad中列选(竖…

深度学习入门(一)感知机

该文将介绍感知机A(perceptron)这一算法。感知机是由美国学者Frank Rosenblatt在1957年提出来的。为何我们现在还要学习这一很久以前就有的 算 法 呢 ? 因 为 感 知 机 也 是 作 为 神 经 网 络(深 度 学 习)的起源的算…

详解Windows通过命令行查看电脑连接过的WIfI密码

CONTENT打开命令行进入命令行下的netsh工具查看连接过的WiFi名称指定WiFi名称查看密码在Windows操作系统中(PS:Windows Vista及以后的Windows系统)可以通过命令行工具netsh查看和更改电脑的无线连接设置,包括WiFi。本篇博客将详细…

C语言进阶——文件管理

每当我们写好一段代码运行结束之后,再次运行的时候就会发现,之前在终端上输入的数据都会消失,那么如何把之前输入的数据保存下来呢? 我们一般把数据持久化的方式有把数据存放在磁盘文件中、存放到数据库。打印等方式进行保存。 …

Java---微服务---elasticsearch安装部署

elasticsearch安装部署1.部署单点es1.1.创建网络1.2.加载镜像1.3.运行2.部署kibana2.1.部署2.2.DevTools3.安装IK分词器3.1.在线安装ik插件(较慢)3.2.离线安装ik插件(推荐)1)查看数据卷目录2)下载并解压缩分…

RocketMQ源码本地搭建调试

1 GitHub源码 git clone https://github.com/apache/rocketmq.git导入IDEA,可在命令行执行mvn compile一下,保证源码能够正确编译。本次我使用的master分支的版本-4.8.0。下面我们开始准备启动Namesrv。 2 启动Namesrv 到namesrv模块找到NamesrvStart…

web游戏---canvas基础图形

基础 canvas标签 canvas是H5中新推出的标签,这个提供一块画布,可以在上面绘制图案,通过这种方式制作web游戏带来的性能消耗比操作DOM要小的多。 如果知做浏览器游戏,为了保证性能最好使用画布来制作。 坐标系 画布的坐标系和…

ThinkPadE540重装系统

过年这段时间,帮家里人重装了一下win10系统,在这里记录一下,方便今后还要使用。 先准备两个U盘,一个存储电脑的文件(以防文件丢失),一个空u盘(制作重装系统的) 一.下载镜…

【5-卷积神经网络】北京大学TensorFlow2.0

课程地址:【北京大学】Tensorflow2.0_哔哩哔哩_bilibiliPython3.7和TensorFlow2.1六讲:神经网络计算:神经网络的计算过程,搭建第一个神经网络模型神经网络优化:神经网络的优化方法,掌握学习率、激活函数、损…

Junit单元测试框架【基础篇】

Junit单元测试框架【基础篇】🍎一.Junit单元测试框架🍒1.1 注解🍒1.2 断言🍒1.3 用例执行顺序🍒1.4 测试套件🍉1.4.1 指定类🍉1.4.1 指定包🍒1.5 参数化🍉1.5.1 单参数&a…

VBA提高篇_07 Goto跳转 / Exit退出 /VBA错误处理

文章目录使用逻辑变量控制循环使用Goto语句任意跳转捷径:使用Exit语句跳出结构保险: 使用错误处理改善用户体验On Error Goto Lablex:On Error Resume Next使用逻辑变量控制循环 使用Goto语句任意跳转 经常在错误处理时使用 捷径:使用Exit语句跳出结构 注意: 避免使用while…w…