Ubuntu下STM32开发调试环境安装

    Linux绝对是开发者的上帝之鞭!但想要做到使用起来得心应手,比对window真的还差一些。但对于真正的开发者来说,这些还真都不是事!

    前面我们说过要在Ubuntu上搭建STM32的开发调试环境,比对前面的系统框图,配置起来,也就清晰并且轻松多了。但Ubuntu就是Ubuntu,比起Windows的<下一步>&<下一步>还是麻烦不少。这样吧,给大家搞一个python脚本吧... ...

    先上流程图:

再贴代码:

#
# This script is created by haibojiang
# email:32191103@qq.com
# Tel:15940146108
#
#!/usr/bin/env python3
import os
import subprocess
import sys
import time
from pathlib import Path

# 颜色定义
COLORS = {
    'HEADER': '\033[95m',
    'OKBLUE': '\033[94m',
    'OKCYAN': '\033[96m',
    'OKGREEN': '\033[92m',
    'WARNING': '\033[93m',
    'FAIL': '\033[91m',
    'ENDC': '\033[0m',
    'BOLD': '\033[1m',
    'UNDERLINE': '\033[4m'
}

def print_color(text, color):
    print(f"{COLORS[color]}{text}{COLORS['ENDC']}")

def run_command(cmd, description, exit_on_fail=True):
    print_color(f"▶ {description}...", "OKBLUE")
    print_color(f"$ {cmd}", "OKCYAN")
    
    try:
        process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        while True:
            output = process.stdout.readline()
            if output == b'' and process.poll() is not None:
                break
            if output:
                print(output.decode().strip())
        
        return_code = process.poll()
        if return_code != 0:
            print_color(f"✖ 命令执行失败,返回码: {return_code}", "FAIL")
            if exit_on_fail:
                sys.exit(1)
            return False
        print_color("✔ 完成", "OKGREEN")
        return True
    except Exception as e:
        print_color(f"✖ 执行命令时出错: {str(e)}", "FAIL")
        if exit_on_fail:
            sys.exit(1)
        return False

def check_installation(package):
    try:
        subprocess.check_output(f"which {package}", shell=True)
        return True
    except subprocess.CalledProcessError:
        return False

def install_stlink():
    if check_installation("st-flash") and check_installation("st-util"):
        print_color("✔ ST-LINK 工具已安装", "OKGREEN")
        return
    
    print_color("▶ 安装 ST-LINK 工具...", "HEADER")
    
    # 安装依赖
    run_command("sudo apt-get update", "更新软件包列表")
    run_command("sudo apt-get install -y cmake usbutils libusb-1.0-0-dev", "安装编译依赖")
    
    # 克隆并编译 stlink
    stlink_dir = Path.home() / "stlink"
    if not stlink_dir.exists():
        run_command(f"git clone https://github.com/stlink-org/stlink {stlink_dir}", "克隆 stlink 仓库")
    else:
        print_color("✔ stlink 目录已存在,跳过克隆", "OKGREEN")
    
    os.chdir(stlink_dir)
    run_command("make release", "编译 stlink")
    run_command("sudo make install", "安装 stlink")
    run_command("sudo cp config/udev/rules.d/49-stlinkv* /etc/udev/rules.d/", "配置 udev 规则")
    run_command("sudo udevadm control --reload-rules", "重新加载 udev 规则")
    run_command("sudo udevadm trigger", "触发 udev 规则")
    
    print_color("✔ ST-LINK 工具安装完成", "OKGREEN")

def install_jlink():
    if check_installation("JLinkExe"):
        print_color("✔ J-LINK 软件已安装", "OKGREEN")
        return
    
    print_color("▶ 安装 J-LINK 软件...", "HEADER")
    
    # 下载 J-LINK (需要用户手动下载,因为需要接受许可协议)
    jlink_deb = "JLink_Linux_V788a_x86_64.deb"
    jlink_url = "https://www.segger.com/downloads/jlink/JLink_Linux_V788a_x86_64.deb"
    
    download_path = Path.home() / "Downloads" / jlink_deb
    if not download_path.exists():
        print_color("⚠ 请从以下 URL 手动下载 J-LINK 软件并接受许可协议:", "WARNING")
        print_color(jlink_url, "OKBLUE")
        print_color(f"请将下载的 {jlink_deb} 文件保存到 {download_path}", "OKBLUE")
        input("按 Enter 键继续安装 (确保文件已下载)...")
    
    if not download_path.exists():
        print_color("✖ 未找到 J-LINK 安装文件,跳过 J-LINK 安装", "FAIL")
        return
    
    run_command(f"sudo dpkg -i {download_path}", "安装 J-LINK 软件包")
    run_command("sudo apt-get install -f", "修复依赖关系")
    
    # 添加用户到 dialout 组
    run_command(f"sudo usermod -a -G dialout {os.getenv('USER')}", "将用户添加到 dialout 组")
    
    print_color("✔ J-LINK 软件安装完成", "OKGREEN")
    print_color("⚠ 请注销并重新登录以使组更改生效", "WARNING")

def install_toolchain():
    if check_installation("arm-none-eabi-gcc"):
        print_color("✔ ARM 工具链已安装", "OKGREEN")
        return
    
    print_color("▶ 安装 ARM 工具链...", "HEADER")
    
    run_command("sudo apt-get update", "更新软件包列表")
    run_command("sudo apt-get install -y gcc-arm-none-eabi binutils-arm-none-eabi gdb-arm-none-eabi libnewlib-arm-none-eabi", "安装 ARM 工具链")
    
    print_color("✔ ARM 工具链安装完成", "OKGREEN")

def install_openocd():
    if check_installation("openocd"):
        print_color("✔ OpenOCD 已安装", "OKGREEN")
        return
    
    print_color("▶ 安装 OpenOCD...", "HEADER")
    
    run_command("sudo apt-get update", "更新软件包列表")
    run_command("sudo apt-get install -y openocd", "安装 OpenOCD")
    
    print_color("✔ OpenOCD 安装完成", "OKGREEN")

def generate_config_files():
    print_color("▶ 生成配置文件...", "HEADER")
    
    project_dir = Path.cwd()
    
    # 创建 openocd 配置文件
    openocd_cfg = project_dir / "openocd.cfg"
    with open(openocd_cfg, "w") as f:
        f.write("""# OpenOCD 配置文件 for STM32F407
source [find interface/stlink-v2.cfg]
# source [find interface/jlink.cfg]  # 取消注释以使用 J-LINK

transport select hla_swd

source [find target/stm32f4x.cfg]

reset_config srst_nogate

# 启用 SWO 跟踪 (如果使用)
# tpiu config internal uart off 168000000 1680000
""")
    print_color(f"✔ 已创建 OpenOCD 配置文件: {openocd_cfg}", "OKGREEN")
    
    # 创建 gdb 初始化文件
    gdbinit = project_dir / "gdbinit"
    with open(gdbinit, "w") as f:
        f.write("""# GDB 初始化文件 for STM32F407
target extended-remote :3333
monitor reset halt
load
monitor reset halt
break main
""")
    print_color(f"✔ 已创建 GDB 初始化文件: {gdbinit}", "OKGREEN")
    
    # 创建烧录脚本
    flash_sh = project_dir / "flash.sh"
    with open(flash_sh, "w") as f:
        f.write("""#!/bin/bash
# STM32F407 烧录脚本

# 使用 ST-LINK
arm-none-eabi-gdb -x gdbinit your_firmware.elf

# 使用 J-LINK 的替代命令
# JLinkExe -device STM32F407VG -if SWD -speed 4000 -autoconnect 1 -CommanderScript flash.jlink
""")
    flash_sh.chmod(0o755)  # 使脚本可执行
    print_color(f"✔ 已创建烧录脚本: {flash_sh}", "OKGREEN")
    
    # 创建 J-LINK 烧录脚本
    jlink_flash = project_dir / "flash.jlink"
    with open(jlink_flash, "w") as f:
        f.write("""// J-LINK 烧录脚本
device STM32F407VG
speed 4000
if swd
connect
halt
loadfile your_firmware.hex
r
q
""")
    print_color(f"✔ 已创建 J-LINK 烧录脚本: {jlink_flash}", "OKGREEN")
    
    print_color("✔ 配置文件生成完成", "OKGREEN")

def main():
    print_color("="*60, "HEADER")
    print_color(" STM32F407 Ubuntu 开发环境自动配置脚本", "HEADER")
    print_color("="*60, "HEADER")
    print()
    
    # 检查是否为 Ubuntu
    try:
        with open("/etc/os-release") as f:
            if "Ubuntu" not in f.read():
                print_color("⚠ 此脚本专为 Ubuntu 设计,其他发行版可能不兼容", "WARNING")
    except FileNotFoundError:
        print_color("⚠ 无法确定操作系统类型,继续执行但可能不兼容", "WARNING")
    
    # 检查 sudo 权限
    print_color("▶ 检查 sudo 权限...", "OKBLUE")
    try:
        subprocess.check_call("sudo -v", shell=True)
        print_color("✔ 已获得 sudo 权限", "OKGREEN")
    except subprocess.CalledProcessError:
        print_color("✖ 需要 sudo 权限来运行此脚本", "FAIL")
        sys.exit(1)
    
    # 安装组件
    install_toolchain()
    install_stlink()
    # install_jlink()
    install_openocd()
    
    # 生成配置文件
    generate_config_files()
    
    print()
    print_color("="*60, "HEADER")
    print_color(" 环境配置完成!", "OKGREEN")
    print_color("="*60, "HEADER")
    print()
    
    # 使用说明
    print_color("使用说明:", "HEADER")
    print("1. 将 STM32F407 开发板通过 ST-LINK 或 J-LINK 连接到电脑")
    print("2. 确保你的工程目录包含编译生成的 ELF 或 HEX 文件")
    print()
    print_color("调试方法:", "OKBLUE")
    print("- 使用 OpenOCD 和 GDB:")
    print("  1. 在一个终端中运行: openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg")
    print("  2. 在另一个终端中运行: arm-none-eabi-gdb -x gdbinit your_firmware.elf")
    print()
    print_color("烧录方法:", "OKBLUE")
    print("- 使用 ST-LINK:")
    print("  st-flash write your_firmware.bin 0x8000000")
    print("  或运行: ./flash.sh")
    print()
    print("- 使用 J-LINK:")
    print("  JLinkExe -device STM32F407VG -if SWD -speed 4000 -autoconnect 1 -CommanderScript flash.jlink")
    print()
    print_color("提示:", "WARNING")
    print("- 首次使用 J-LINK 可能需要注销并重新登录")
    print("- 确保你的用户有访问调试器的权限 (通常在 dialout 组)")
    print("- 如果遇到权限问题,尝试重新插拔调试器或运行:")
    print("  sudo udevadm control --reload-rules && sudo udevadm trigger")

if __name__ == "__main__":
    main()

Ubuntu1~20.04.2 & python3 测试通过。后续调试过程慢慢追加

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值