ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

SmartFusion2 M2S010-MKR-KIT例程实战:从点灯到调试的完整链路

SmartFusion2 M2S010-MKR-KIT例程实战:从点灯到调试的完整链路

简介:面向 Microsemi SmartFusion2 平台,这份 M2S010-MKR-KIT 开发板配套的 FirstProj 入门例程源码,适合嵌入式工程师与 FPGA 初学者快速掌握片上系统的开发要领。压缩包共四十六个文件,以 C 源文件与头文件为主,配合链接脚本和汇编启动代码,另有 Libero 工程配置、硬件平台定义文件及两篇 Markdown 说明文档,总体约十点二兆字节。目录按固件驱动、CMSIS 标准外设库、硬件抽象层等模块划分,结构清晰,便于按需查阅。目前已有九百二十人学习下载,常被用来熟悉 SmartFusion2 的软硬件协同设计流程。例程详细展示了启动代码编写、时钟与通用输入输出端口初始化、FPGA 配置比特流加载等核心环节,并附带可运行的基础示例。对照源码动手实践,能够理解 ARM Cortex-M3 内核如何与 FPGA 逻辑交互,掌握 Libero SoC 工具链的基本用法,为后续实现自定义硬件逻辑与复杂控制算法打下坚实基础。

1. 第一次拿到 M2S010-MKR-KIT,先别急着点灯,把例程当“工程解剖课”来上

第一次拿到 M2S010-MKR-KIT 这块 SmartFusion2 开发板,大多数人不是兴奋,是懵。板子上一颗芯片同时装着 ARM Cortex-M3 内核和一块 FPGA fabric,而手边的 M2S010-MKR-KIT_FirstProj-master_SmartFusion2开发例程源码,标题看着完整,点进去却发现 Libero、SoftConsole、MSS、eNVM 这些词全都陌生。这个例程不复杂,通常就是初始化时钟、点一颗 LED、串口回环。它的价值在于演示一条完整链路:从 FPGA 侧建立工程、约束管脚、生成编程文件,到 ARM 侧写 C 代码、烧进 eNVM、让 MSS 核心和 FPGA 逻辑在同一颗芯片里协同跑起来。适合两类人:从嵌入式转过来想用 SoC FPGA 的人,以及评估 SmartFusion2 能否替代“MCU + FPGA”双芯片方案的产品工程师。跑通它不难,难的是知道哪些参数必须自己改,哪些可以一辈子不动。下面按我实际排查的顺序讲这条链路。

2. 先看懂 M2S010 这颗 SoC FPGA:MSS 硬核、fabric 与 MKR-KIT 板级资源

2.1 一颗芯片里同时放 ARM 硬核和 FPGA:为什么这种结构适合工控

SmartFusion2 的“融合”和普通 FPGA 里塞一个软核完全是两码事。M2S010 内部有一个硬核的 ARM Cortex-M3 微控制器子系统(MSS),它不是用 LUT 搭出来的软核,而是芯片出厂时就固定的硅片模块。MSS 里除了 Cortex-M3 内核,还包括 eNVM、eSRAM、DDR 控制器、AHB 总线矩阵和一组固定外设。另一侧才是可编程的 FPGA fabric,也就是传统意义上能随意改逻辑的那部分电路。

这两部分之间的互连不是 PCB 上的走线,而是片内的 AHB 总线桥。Cortex-M3 可以直接发起对 FPGA 侧自定义寄存器的读写,地址就映射在 MSS 的地址空间里。这种结构对工控场景特别友好:ARM 侧跑协议栈、跑状态机、跑网络栈,FPGA 侧做实时性要求高的 IO 扩展、编码器接口、PWM 输出或者自定义并口协议。两边通过总线沟通,省掉了外部 MCU 与 FPGA 之间的电平转换和数据线,也省掉了跨芯片通信的时延。

选择硬核而不是软核,最直接的理由是确定性和启动速度。硬核 Cortex-M3 的指令周期、中断延迟、总线仲裁都是固定的,不占 FPGA 逻辑资源。FPGA 上电后需要加载配置,而 MSS 的启动代码存在片内 eNVM 里,上电即可执行。很多工业设备要求从复位到 IO 就绪控制在毫秒级,SoftCore 做不到这种表现,双芯片方案又要多一个 MCU 上电等待的时间。

2.2 MKR-KIT 板级资源:例程里能直接摸到的外设

MKR-KIT 是 Microsemi 官方面向快速原型设计的板卡,外形上带 Arduino 兼容的排针布局,方便直接插扩展板。板上常见的资源包括一颗 M2S010 主控、DDR 内存颗粒、SPI Flash、USB 转串口、几个用户 LED、两个按键,以及 PMOD 和 Arduino 风格 IO 接口。FirstProj 这个例程一般只用到板载 LED、按键和 UART,正好是让新手建立“最小系统”概念的三件套。

拿到例程源码后,第一件事不是看代码,而是打开板卡的原理图 PDF,找到 LED 的网络标号。通常板载 LED 一端经过电阻连到 MSS GPIO 或 FPGA IO,另一端接电源或地,要确认是高电平点亮还是低电平点亮。这个信息决定代码里写set_output(1)还是set_output(0)。类似的还有 UART 的 TX/RX 是否通过 USB 转串口芯片引出、是否默认连接到了调试器的虚拟串口。

MKR-KIT 的板级设计决定了例程的“最短路径”:板上的 LED、按键、UART 都被直接引到 MSS 或 fabric 的固定管脚上,例程源码里的约束文件就是为这块板子定制的。所以如果你用的是其他板子,第一件事不是改代码,而是把例程里的.pdc约束文件删掉,用自己板卡的原理图重新生成一份管脚约束。这个习惯能省掉后面一大半玄学问题。

经常有人问 MKR-KIT 和普通 SmartFusion2 评估板的区别。MKR-KIT 的定位是快速原型,扩展接口丰富、板型紧凑,适合做验证;而面向严苛工业环境的设计,通常会把核心板做成自定义的 4 层或 6 层板。例程的价值在于它展示了“这颗芯片怎么被完整跑起来”的参考设计,而不是让你把这套板子直接搬进产品。

2.3 为什么叫 M2S010 而不是 M2S050:选型与资源边界

SmartFusion2 家族里型号的后三位数字大致对应 FPGA 逻辑资源的级别,M2S010 属于中小规模型号。对比家族里的 M2S050、M2S060,M2S010 的 LUT 数量少一些,可用 IO 也少一些,但 MSS 硬核部分基本一致。这个差异带来的结果是:例程在 M2S010 上综合、布局布线毫无压力,但如果你把工程换成更大规模的器件,直接换型号运行大概率会在一堆 IP 核配置上报错,因为工具会提示引脚和 Bank 定义冲突。

M2S010 适合什么设计?我一般用它做中小规模的接口转换、IO 扩展、多串口集线器、工业现场总线桥接这类场景。fabric 里放几个 FIFO、一个简单的 SPI 从机、几路定时器,再加上 ARM 侧的应用代码,资源刚好合适。如果你打算在 FPGA fabric 里做图像缩放、AI 加速或者复杂协议栈,那 M2S010 大概率不够,直接考虑家族里更大的型号更现实。

了解资源边界还有个实际用途:判断例程里哪些部分是你改得动的、哪些是不能动的。FirstProj 的 MSS 子系统和启动流程在所有 SmartFusion2 型号上几乎一致,这部分代码可以复用;而 FPGA 侧的逻辑规模、约束管脚数量和时序约束则要重新评估。选型不是越大越好,先看 ARM 侧需要跑什么软件,再算 fabric 里还剩多少资源给自定义逻辑,顺序应该反过来,先确定 fabric 里跑什么,再选芯片。

3. 在 Libero SoC 里复现 FirstProj:Tcl 脚本、约束导入与比特流生成

3.1 安装 Libero SoC 版本与许可证:两个让新手止步的细节

Libero SoC 是 SmartFusion2 的 FPGA 开发套件,里面集成了 Synopsys 的综合工具、布局布线工具和 FlashPro 编程工具链。ARM 侧代码开发则用另一套独立的 SoftConsole 环境。很多新手装完 Libero 之后发现综合按钮是灰色的,大概率不是软件装错了,而是许可证没有覆盖对应功能。

安装时先确认例程是用哪个主版本生成的。FirstProj 这类老例程通常在工程文件或 README 里注明了 Libero SoC 的版本号。我一般会尽量用同主版本的工具去打开它,而不是直接升级到最新版。老工程在新版本中打开时,工具会弹窗提示升级 IP 核,升级之后综合结果、管脚约束甚至时序收敛性都可能变化。如果只是跑通例程,保持原版本最省事;如果你要做产品化开发,再考虑统一升级到长期维护版本。

许可证方面,去 Microchip 官网申请 SmartFusion2 的 Libero License,把 license 文件放到工具默认搜索路径下,并设置环境变量指向它。最容易踩的坑是 License Manager 里显示许可证有效,但综合工具仍报 license 错误,这时要检查环境变量是否被其他版本的软件覆盖了,或者 hostname/MAC 绑定是否与申请时填写的一致。安装顺序也有讲究:先装 FlashPro 驱动,再装 Libero,最后装 SoftConsole,否则调试器识别会出现兼容性怪问题。

3.2 用“新建工程 + 导入源码”替代直接双击工程文件

很多人拿到例程包双击.libero工程文件,然后直接点综合,这是第一个翻车点。旧工程文件里记录了绝对路径、IP 核版本号、工具链版本信息,换一个版本的 Libero 打开时,自动迁移过程会不知不觉更新你的 IP 核配置,看起来一切正常,但生成的比特流已经不是例程作者验证过的那一套了。

我一般会新建一个干净工程,把 HDL 源文件、约束文件、IP 核配置文件手动导入。这样路径完全可控,出错时也能定位到具体文件。Libero 支持 Tcl 命令,常用操作可以直接脚本化,这里有一个可以照抄的模板:

# 新建一个 M2S010 空工程 new_project -name firstproj_work -location ./workspace/firstproj_work \ -device M2S010 -package 144TQ -speed STDN -family SmartFusion2 \ -die M2S010 -core 144TQ -tolerance 0 # 导入 HDL 源文件(VHDL/Verilog 均可) import_files -hdl_source { \ ./rtl/firstproj_top.v \ ./rtl/mss_top.v \ ./rtl/led_ctrl.v } # 导入管脚约束和时序约束 import_files -pdc {./constraints/mkr_kit.pdc} import_files -sdc {./constraints/mkr_kit.sdc} # 指定顶层模块,必须和 RTL 里的模块名完全一致 set_top_module firstproj_top # 依次执行综合、布局布线、时序验证 run_tool -name SYNTHESIZE run_tool -name PLACE_AND_ROUTE run_tool -name VERIFY_TIMING

这段脚本的逻辑很简单:先创建一个干净的工程,再把源码和约束文件放进去,指定顶层模块,最后跑完整流程。参数说明里要注意-device必须和板卡丝印上的型号一致,封装和速度等级可以从芯片表面的丝印读出,写错时布局布线工具会直接报错。set_top_module后面跟的名字必须和你的顶层模块名称完全一致,包括大小写,否则工具默认选一个错误模块当作顶层,管脚约束全部对不上。

如果你不想用 Tcl,完全可以在 GUI 界面按同样顺序操作:新建工程、添加文件、导入约束、设置顶层、双击综合、双击布局布线。Tcl 脚本的好处是可以做回归:改一行管脚约束后重新跑全套流程,不需要手动点那么多按钮。

3.3 看懂 FirstProj 的工程层次:顶层、MSS 子系统与约束文件

Libero 工程左侧的 Design Hierarchy 窗口会显示整个设计的树状结构。例程的顶层一般是一个 HDL 模块,里面例化了 MSS 子系统和少量 FPGA 逻辑模块。MSS 子系统在工程里表现为一个被加密或者生成过的 IP 核实例,你双击它可以打开 MSS Configurator 的图形化界面,在那里可以配置 Cortex-M3 的外围设备。

MSS Configurator 是例程里最关键的黑匣子之一。界面里左侧是外设列表,右侧是地址空间和中断连接。FirstProj 的典型配置是使能一个 MSS UART、一个 MSS GPIO 或二合一 GPIO、一组 Timer,DDR 控制器默认使能。你在界面里勾选的每一个选项,都会生成对应的寄存器初始化代码和数据结构。如果例程运行后某个外设不工作,先回这里看外设是否被勾选,而不是急着改 C 代码。

约束文件则决定了 FPGA 引脚映射。例程里的.pdc文件通常包含几十行 SET_IO 描述,把 LED、按键、PMOD、UART 的 FPGA 引脚映射到具体封装管脚。你自己的板子改版时最容易出错的就是这里:多写了引脚或者写错了封装位置,布局布线阶段会报无法布通。我习惯是每一条约束都对着原理图核对一遍,确认是芯片管脚号而不是排针编号。顺便说一句,SDC 时序约束也要检查,例程里针对 50MHz 或 100MHz 时钟写的约束,不一定适配你自己板子上的时钟频率。

3.4 综合、布局布线与生成比特流的顺序,以及失败时看哪一行

流程顺序固定为:综合(Synthesis)→ 布局布线(Place and Route)→ 时序验证(Verify Timing)→ 生成比特流(Generate Bitstream)。每个阶段都生成一份日志文件。综合阶段报错通常是语法错误、模块未定义、IP 核配置缺失;布局布线阶段报错大多是管脚约束问题、IO Bank 电压配置问题或者复用冲突;时序验证不通过则说明时钟约束写得不合理,或者逻辑路径太长。

入行头两年我遇到布局布线失败,总以为是工具玄学,后来发现九成是约束文件引用了不存在的管脚,剩下一些是管脚被同时分配给了两个模块。日志里的定位信息非常明确,关键是用对筛选命令。在 Linux 环境下我习惯这样提取错误信息:

grep -iE "error|critical|failed" ./impl/place_route.log | head -40

执行之后先看错误行前面的文件路径和行号,再去那个文件的对应位置修改。很多“综合失败”其实只是某一个 IP 核的配置没跟上,比如 DDR 配置里的芯片型号选错了,导致时序约束无法匹配到实际器件。此时去 MSS Configurator 的 DDR 配置页重新选择内存颗粒型号并确认时序参数,再重新生成 IP 核即可。

例程跑完布局布线和时序验证后,Libero 会生成.stp、.job和比特流文件。这些文件是后续烧录动作的输入。很多新人以为生成完比特流就可以点灯了,实际上 SmartFusion2 是 SoC 芯片,FPGA 侧配置和 ARM 侧固件都需要写入片内,下一步要转入 SoftConsole 编译工程,再把两部分通过 FlashPro 一起烧录进去。

4. 从复位向量到 main():FirstProj 的启动链路与第一颗 LED 到底怎么点亮的

4.1 MSS 的地址映射:eNVM、eSRAM 和 DDR 各在什么位置

SmartFusion2 的 Cortex-M3 侧有一张完整的地址映射表。例程生成的mss_regs.h和链接脚本里会给出具体基地址,不同封装和配置下略有差异。对照例程和手册,常规布局大致如下:

区域地址范围用途
eNVM0x0000_0000 起始区间存储 ARM 启动代码和固件
eSRAM0x2000_0000 起始区间片上 SRAM,存放运行时变量、栈
AHB 外设0x4000_0000 起始区间MSS 内部外设寄存器,如 UART、GPIO、Timer
DDR由 DDR 控制器配置映射大容量程序和数据内存
FPGA fabric 接口FIC 配置窗口,可自定义地址访问 FPGA 侧自定义寄存器

新手常犯的错误是在 main() 里直接访问 DDR 地址,却没有先把 DDR 控制器初始化好。例程的启动流程里包含一段 DDR PLL 和时序训练代码,这段代码在 main() 之前执行。如果你拿到例程后把启动文件里的 DDR 初始化注释掉,后面程序可能前几百字节正常,超过一定范围就 HardFault。

链接脚本决定了哪些段放在 eNVM、哪些段放在 eSRAM。嵌入式工程里.text和.rodata一般放 eNVM,.data和.bss放 eSRAM。修改链接脚本时要注意保留启动代码对.data的拷贝逻辑,否则变量初始化全部失效。例程默认的分散加载文件已经经过验证,除非你要把大量数据放 DDR,否则不建议动它。

4.2 上电后 SmartFusion2 干了什么:启动源、FPGA 配置和 DDR 初始化的先后顺序

M2S010 的启动序列和纯 MCU 不一样。上电复位后,片内 ROM Bootloader 先拿到控制权,根据启动模式引脚和 eNVM 中的启动配置,决定从哪个存储介质加载代码。FirstProj 的典型配置是从 eNVM 引导应用固件。

Bootloader 完成引导后,Cortex-M3 开始执行应用程序的启动代码。这一步通常由 SoftConsole 工程中的汇编文件和system_startup相关源码完成。启动代码做的事情包括:设置栈指针、拷贝数据段、清零 BSS 段、配置 PLL 时钟树、使能 FIC 接口并等待 FPGA fabric 配置完成、初始化 DDR 控制器,最后跳转到 main()。

FPGA fabric 的配置在 SoC FPGA 上是个容易被忽视的环节。MSS 通过配置接口把比特流送入 fabric,配置完成后 FIC 总线才能对外通信。如果例程的启动代码里包含等待 fabric 配置完成的循环,不要删掉它,否则 main() 里访问 FPGA 侧寄存器时总线挂死。查看串口打印信息时,如果看到启动日志停在某一处,往往就是 fabric 配置失败或 DDR 初始化挂起。

4.3 FirstProj 里点第一颗 LED 的完整链路

FirstProj 的代码量很小,核心逻辑就是把 MSS GPIO 配置成输出,然后翻转电平。下面是一个可直接编译运行的 LED 闪烁示例,基于 SoftConsole 的 MSS HAL 库:

#include "mss_gpio.h" #include "mss_uart.h" /* 示例:假定 LED 连接在 MSS_GPIO_0,高电平点亮 */ #define LED_PIN MSS_GPIO_0 static void delay_loop(volatile uint32_t n) { while (n--) { __asm volatile ("nop"); } } int main(void) { /* 使能 MSS GPIO 外设并配置为输出模式 */ MSS_GPIO_init(); MSS_GPIO_config(LED_PIN, MSS_GPIO_OUTPUT_MODE); /* 先输出一次低电平,确认管脚可控 */ MSS_GPIO_set_output(LED_PIN, 0); while (1) { MSS_GPIO_set_output(LED_PIN, 1); delay_loop(2000000u); MSS_GPIO_set_output(LED_PIN, 0); delay_loop(2000000u); } }

这段代码里,MSS_GPIO_init()负责打开 GPIO 外设的时钟和 AHB 访问权限,不做这一步,读写寄存器无效。MSS_GPIO_config()把引脚设为输出模式,并且会同时处理内部上下拉的配置。之后MSS_GPIO_set_output()写数据寄存器,引脚电平随之变化。

参数说明:LED_PIN具体是哪个 GPIO 索引,取决于板卡原理图。例程源码里的 LED 定义通常写在板级头文件里,如果要移植到自己的板子,改成你的硬件对应的宏。delay_loop是粗暴的软件延时,依赖内核时钟频率,不精确也不推荐用于正式产品,但用它验证最小系统最高效。正式工程里应该改用 MSS Timer 外设做定时翻转。

4.4 修改例程时保留哪些初始化步骤:启动代码里“删了就翻车”的清单

围绕 FirstProj 改代码时,我总结出一份启动相关内容的保留清单,按重要性排列如下:

步骤内容删掉后的后果
时钟树配置PLL、CCC、AHB/APB 分频外设时钟错乱,串口波特率全错
DDR 初始化DDR PLL、时序训练main() 访问 DDR 地址直接 HardFault
FIC fabric 等待等待 FPGA 配置完成访问 fabric 寄存器挂死
MSS GPIO 时钟使能MSS_GPIO_init()点灯无反应,读写寄存器无效果
UART 分频配置CD/UIB 寄存器设置串口乱码或完全无输出

很多人拿到例程第一件事是把亮灯循环改成自己的业务逻辑,结果灯亮了、业务却不正常,回头查下来是某个外设的时钟没有打开。MSS 外设默认是关闭状态的,所有外设使用前都要显式使能时钟。例程里这些初始化代码分散在main()、system_startup和 BSP 文件里,改动时要先看清楚调用顺序,再动笔。

另外,FPGA 侧逻辑如果也要修改,先改 Libero 工程里的 HDL,再重新生成比特流,最后再去 SoftConsole 里编译 ARM 代码。两个工具链的产物最终在烧录阶段合到一起,只改其中一侧而忘记重新生成另一侧,是例程二次开发最常见的返工原因。

5. 烧录、调试与常见问题排查:eNVM、JTAG 和串口的翻车实录

5.1 FlashPro 识别不到器件:连接与驱动的三个坑

用 FlashPro 连接 MKR-KIT 时,Libero 或 FlashPro Express 提示 No device detected,这种情况我遇到过几次。第一个坑是驱动版本问题。FlashPro 编程器有自己的 USB 驱动,安装 Libero 时如果勾选了全部组件,通常没问题;但如果你用的是精简安装或者后来重装过系统,驱动可能没装上。到设备管理器看一眼是否有带感叹号的设备,没有的话就是驱动缺失。

第二个坑是 JTAG 链连接。MKR-KIT 上 JTAG 接口如果经过延长线或者转接板,信号质量会明显下降,导致 IDCODE 扫描到一半出错。这时表现为 FlashPro 灯正常、板卡电源灯也亮,但工具就是识别不到芯片。替换一根短线或者直接拔插一次接头,有时候就能解决。第三个坑是目标芯片的电源域没有完全上电。SmartFusion2 有多个电源域,JTAG 接口需要核心电压稳定后扫描链才正常,板卡上如果还有其他外设拉低了某路电源,JTAG 同样失联。排查顺序是:驱动、线缆、电源、IDCODE。

5.2 烧录 eNVM 成功但板子不上电运行:启动模式配置在捣鬼

FlashPro 提示烧录成功,但重新上电后板子毫无反应,这是 SecondProject 阶段最容易让人怀疑人生的一个问题。现象很明确,烧录过程没有报错,但芯片复位后既不执行应用程序,LED 也不闪。

原因多半不在烧录本身,而在启动配置。SmartFusion2 的 Boot Mode 由配置位和管脚电平共同决定,如果在 MSS Configurator 里把启动源配成了 SPI Flash 或者 Fabric 启动,而代码实际想在 eNVM 里运行,复位后 Bootloader 找不到有效引导代码,芯片就停在等待状态。另一个类似情况是板上的模式拨码和配置不符,硬件强行拉高了某个启动选择引脚。

解决方法是回到 MSS Configurator,检查 Boot Mode 设置,确认选择从 eNVM 启动。重新生成工程后,需要把 FP3 里的编程文件也一并重新生成,然后擦除芯片再完整烧录一遍。注意 FlashPro 烧录和 Libero 生成的编程文件是两套概念,烧录时要手动选择包含 eNVM 固件的文件,而不是只烧 FPGA bitstream。推荐的做法是每次改动启动配置后,执行 FlashPro Express 的擦除命令,再编程,避免残留的配置干扰判断。

5.3 串口打印乱码:时钟源与波特率的“玄学”

串口回环是例程里最直观的验证方式,但它也是乱码重灾区。现象往往是能输出,但字符错位、换行符变成乱码、或时好时坏,而不是完全无输出。不一致的根本原因是 UART 波特率计算出的分频值和实际时钟不符。

SmartFusion2 的 MSS UART 时钟可以来自内部 RC 振荡器,也可以来自外部晶振经过 PLL 后的输出。例程默认的时钟配置假设外部 50MHz 晶振,但你的板子上如果用的是 24MHz 晶振,或者 PLL 配置被修改,波特率就会偏差。CD 和 UIB 两个分频寄存器控制 UART 的波特率,它们的值由 UART 时钟频率和目标波特率计算得出。我经常用一段简单代码来核对实际配置:

/* 示意代码:读取 UART 分频寄存器并还原实际波特率 */ /* 以 MSS_UART_BASE 的偏移为例,具体偏移见例程生成的 mss_regs.h */ #define UART_CD_REG (*(volatile uint32_t *)(MSS_UART_BASE + 0x0Cu)) #define UART_UIB_REG (*(volatile uint32_t *)(MSS_UART_BASE + 0x10u)) uint32_t pclk = 50000000u; /* PLL 输出的 UART 时钟,按实际配置修改 */ uint32_t actual_baud = pclk / ((UART_CD_REG + 1u) * (UART_UIB_REG ? UART_UIB_REG : 1u));

这段代码只是辅助排查,计算出结果后和终端软件设置的波特率对比。偏差超过 2% 就会随机乱码。从不稳定的乱码到固定错误的乱码,排查路径完全不同:前者优先怀疑电气连接和电源噪声,后者优先怀疑时钟源和分频值。另外,串口助手的本地回显设置也会造成假乱码,如果 TX 和 RX 短接自测,显示的内容是正常字符就不该怀疑硬件。

5.4 SoftConsole 里 Cannot access target:调试会话与复位信号的坑

点灯程序烧录成功,但在 SoftConsole 里点击 Debug 时提示 Cannot access target,这是 ARM 调试器常见的翻车现场。最常见的原因是上一次调试会话没有正常关闭,调试器固件里还保存着断点和寄存器现场,重新上电后目标没有被正确复位。解决方法是断开调试器、完全关闭 SoftConsole,重新给板卡上电,再启动一个新的调试会话。

第二个原因是代码里意外禁用了调试接口,或者把 JTAG 相关引脚复用成了 GPIO。如果某个版本的固件里配置了调试口禁用,且你已经把它烧进 eNVM,下次连接时芯片将拒绝调试请求。这时只能通过 FlashPro 的专有恢复流程擦除 eNVM,回到可调试状态。这里有一个血泪经验:早期调试阶段,不要在代码里关闭调试接口,等整个系统稳定后再考虑安全措施也不迟。

第三个原因是板卡复位信号被外部电路拉低。MKR-KIT 上有复位按键、复位芯片和可能的外部复位驱动电路,如果某个调试器同时接了复位线,而复位线逻辑电平不匹配,目标会一直处于复位状态,调试器自然连不上。用万用表量一下 NRST 管脚的电平,如果持续为低,断开外部复位源的干扰再试。调试连不上时,我通常按“上电顺序重来、关闭多余会话、擦除芯片”三步执行,能覆盖绝大多数情况。

6. 例程跑通之后怎么验货:DDR 带宽、APB 访问与一个改板习惯

例程能点灯、能回环,只说明链路通了,不说明你能改它。我更建议花半天时间围绕例程做三个验证,它们直接暴露你对这颗 SoC 的理解还有多少盲区。

第一个验证是 DDR 读写与带宽。在启动代码完成 DDR 初始化后,写一个简单的 1MB 内存搬运测试,用 Cortex-M3 的 DWT 计数器记录指令周期数,算出实际读写速度。这个测试能确认 DDR 控制器的配置是否真的正确,而不只是“能跑”。我第一次在 M2S010 上做这个测试时,因为没有把 DDR 初始化放在 main() 之前,程序跳进 HardFault,调试器里看寄存器才知道是地址翻译未生效,后来把初始化移到启动序列里才解决。

第二个验证是到 FPGA fabric 的 APB/AHB 访问。在 Libero 里添加一个简单的寄存器模块,比如一个 32 位只读版本号寄存器加一个 32 位读写寄存器,通过 FIC 接口映射到 MSS 地址空间。然后用 ARM 侧代码往写寄存器里写数据,再读回来对比。这个验证能确认 FIC 窗口地址、总线路权和字节序都没有问题。很多后续项目的通信不稳定,根源都是这一步没做扎实。

第三个验证是把软件延时换成 MSS Timer 中断,用逻辑分析仪观察 LED 翻转的周期误差。软件延时的跳动可能高达百分之几,Timer 中断的抖动则小得多,这也是从“跑通例程”过渡到“写正式固件”的分水岭。

我后来养成一个习惯:每次拿到新板子,第一周不做业务功能,只把三件事跑通——启动日志完整打印、内存读写测试全通过、GPIO 通过 Timer 精确翻转。这三件事对应 SoC FPGA 的时钟树、存储子系统和中断系统,确认无误后再开始写应用。这个习惯帮我挡掉了后面至少三轮改版返工。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表