嵌入式开发是一项复杂且具有挑战性的工作,尤其是在调试过程中,开发者需要面对各种硬件与软件的交互问题。为了有效提高调试效率,使用自动化工具和脚本可以大大简化流程。在这篇文章中,我将分享几种常见的 Python 脚本,它们能够帮助嵌入式开发者进行调试优化。我们将涵盖串口日志收集、内存监控、性能测试、日志分析等方面的内容。
一、功能分享:
1. 串口日志收集脚本
在嵌入式系统开发中,串口通常用于输出调试信息。使用 Python 脚本可以自动化收集这些日志数据,实时监控并分析串口数据。
ps:这个脚本通过 pyserial
库与嵌入式设备建立串口连接,实时读取串口输出的数据。如果发现包含 "ERROR" 的信息,脚本会停止并输出错误提示。此脚本适用于实时监控和自动化日志收集,帮助调试过程中捕捉异常
import serial
import time
def collect_uart_data(port='/dev/ttyUSB0', baudrate=115200, timeout=1):
# 打开串口连接
with serial.Serial(port, baudrate, timeout=timeout) as ser:
print(f"Connected to {port} at {baudrate} baudrate.")
while True:
if ser.in_waiting > 0:
data = ser.readline().decode('utf-8').strip() # 读取串口数据
print(f"Received: {data}")
if "ERROR" in data: # 判断是否有错误信息
print("Error detected!")
break
time.sleep(0.1)
if __name__ == "__main__":
collect_uart_data()
2. 实时内存使用监控脚本
在嵌入式系统中,内存使用情况对系统的稳定性至关重要。很多时候系统的崩溃无外乎就两个原因:第一是系统时序的紊乱;第二就是内存泄漏和过度使用可能会导致系统崩溃。实时监控系统内存使用情况,可以很大程度上改善这个现象。
ps:使用 psutil
库实时监控系统内存的使用情况。如果内存使用超过设定的阈值(例如这里我设置的80%),则输出警告信息。可以帮助开发者避免因内存不足而导致的系统崩溃,尤其在内存紧张的嵌入式系统中。
import psutil
import time
def monitor_memory_usage():
while True:
memory = psutil.virtual_memory() # 获取内存使用情况
print(f"Memory Usage: {memory.percent}%")
if memory.percent > 80: # 如果内存使用超过80%
print("Warning: Memory usage is too high!")
time.sleep(1)
if __name__ == "__main__":
monitor_memory_usage()
3. 自动化日志分析
随着嵌入式开发项目的推进,生成的日志文件往往会非常庞大。通过 Python 脚本,我们可以自动分析这些日志文件,快速筛选出错误、警告或其他重要信息,节省人工查找的时间。
ps:该通过正则表达式查找日志文件中的错误信息(如 "ERROR")和警告信息(如 "WARNING")。开发者可以快速定位到日志中的问题,而无需手动逐行检查。
import re
def analyze_log_file(log_file):
with open(log_file, 'r') as file:
logs = file.readlines()
error_pattern = re.compile(r'ERROR') # 查找错误日志
warning_pattern = re.compile(r'WARNING') # 查找警告日志
error_logs = [line for line in logs if error_pattern.search(line)]
warning_logs = [line for line in logs if warning_pattern.search(line)]
if error_logs:
print("Errors found in the log:")
for error in error_logs:
print(error.strip())
else:
print("No errors found.")
if warning_logs:
print("\nWarnings found in the log:")
for warning in warning_logs:
print(warning.strip())
else:
print("No warnings found.")
if __name__ == "__main__":
analyze_log_file('device_log.txt') # 提供日志文件路径
4. 性能测试脚本
性能是嵌入式系统中非常关键的一个方面。通过对代码执行时间的监测,开发者可以发现性能瓶颈并进行优化。以下 Python 脚本模拟了对某个函数的性能测试。
ps:通过 time.time()
来测量函数执行的时间,帮助开发者发现函数执行的瓶颈。通过这种方式,可以对嵌入式系统中的关键代码进行性能评估和优化。
import time
def test_function():
# 模拟耗时的任务
total = 0
for i in range(1000000):
total += i
return total
def measure_performance(func):
start_time = time.time() # 获取当前时间
result = func()
end_time = time.time() # 结束时间
elapsed_time = end_time - start_time # 计算时间差
print(f"Function executed in {elapsed_time:.6f} seconds")
return result
if __name__ == "__main__":
measure_performance(test_function)
二、应用与迁移:
为了方便可以直接迁移到不同的嵌入式项目中,进行实际应用。以下是一些建议,帮助调试脚本,使它们能够更好地适应各种嵌入式项目。(大佬忽略)
1. 模块化设计与功能封装
将不同的调试任务功能封装成独立的模块(Python 类或函数),这样可以确保每个脚本只负责一个特定的任务。通过模块化设计,脚本可以方便地在不同的项目中调用和复用。
例如,日志收集、内存监控、性能测试等功能可以分别封装成不同的 Python 模块。用户只需要根据项目需要导入相应的模块。
# uart_logger.py
import serial
import time
class UartLogger:
def __init__(self, port='/dev/ttyUSB0', baudrate=115200, timeout=1):
self.port = port
self.baudrate = baudrate
self.timeout = timeout
self.ser = None
def start_logging(self):
self.ser = serial.Serial(self.port, self.baudrate, timeout=self.timeout)
print(f"Connected to {self.port} at {self.baudrate} baudrate.")
while True:
if self.ser.in_waiting > 0:
data = self.ser.readline().decode('utf-8').strip() # 读取串口数据
print(f"Received: {data}")
if "ERROR" in data: # 判断是否有错误信息
print("Error detected!")
break
time.sleep(0.1)
def stop_logging(self):
if self.ser:
self.ser.close()
print("Connection closed.")
from uart_logger import UartLogger
logger = UartLogger(port='/dev/ttyUSB1', baudrate=9600)
logger.start_logging()
直接使用UartLogger
类封装了串口日志收集功能,使用时只需创建该类的实例并调用 start_logging()
方法即可。stop_logging()
方法用于关闭串口连接
2. 配置文件与参数化
为了增强脚本的灵活性,可以通过配置文件(如 .ini
、.json
或 .yaml
格式的文件)来管理不同项目的配置参数。这样,可以通过修改配置文件而不需要改动代码本身,从而在不同的项目中快速适配。
示例:配置文件 (config.json
)
{
"uart": {
"port": "/dev/ttyUSB0",
"baudrate": 115200,
"timeout": 1
},
"memory_monitor": {
"threshold": 80
}
}
# config.py
import json
def load_config(config_file='config.json'):
with open(config_file, 'r') as f:
config = json.load(f)
return config
# uart_logger.py
from config import load_config
import serial
import time
class UartLogger:
def __init__(self, config):
self.port = config['uart']['port']
self.baudrate = config['uart']['baudrate']
self.timeout = config['uart']['timeout']
self.ser = None
def start_logging(self):
self.ser = serial.Serial(self.port, self.baudrate, timeout=self.timeout)
print(f"Connected to {self.port} at {self.baudrate} baudrate.")
while True:
if self.ser.in_waiting > 0:
data = self.ser.readline().decode('utf-8').strip() # 读取串口数据
print(f"Received: {data}")
if "ERROR" in data: # 判断是否有错误信息
print("Error detected!")
break
time.sleep(0.1)
def stop_logging(self):
if self.ser:
self.ser.close()
print("Connection closed.")
if __name__ == "__main__":
config = load_config()
logger = UartLogger(config)
logger.start_logging()
# main.py
from uart_logger import UartLogger
from config import load_configconfig = load_config('config.json')
logger = UartLogger(config)
logger.start_logging()
解释:在这个例子中,config.json
文件用来存储串口连接的相关配置。通过 load_config
函数加载配置后,UartLogger
类可以使用这些配置参数,确保脚本能够在不同的项目中灵活配置和使用。