恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
复旦微FMQL PS侧裸机开发:IAR工具链实战系列前言
首页
资讯中心
/
复旦微FMQL PS侧裸机开发:IAR工具链实战系列前言
复旦微FMQL PS侧裸机开发:IAR工具链实战系列前言
发布时间:2026/9/25 5:24:49
在嵌入式的工具链选择上我一直是个“实用主义至上”的人。所以当我拿到一块复旦微FMQL开发板准备用IAR做PS侧裸机开发的时候身边不少朋友的第一反应都是国产Zynq用IAR能行吗这大概也是很多刚接触FMQL的工程师心里最大的疑问。这里先解释一下标题里的PS不是Photoshop而是Zynq这种SoC FPGA架构里的Processing System也就是芯片里的ARM处理器子系统PL则是可编程逻辑也就是FPGA那部分。这篇是系列的第一篇前言我会把这个系列到底要做什么、FMQL这颗芯片该怎么理解、为什么选IAR裸机这条路、开发前需要准备什么以及后面几期打算怎么写一次说清楚。如果你正在评估国产SoC FPGA或者已经拿到FMQL的开发板但对ARM侧的开发方式还有点拿不准这篇内容会比较适合你。1. 项目背景为什么我会选复旦微FMQL1.1 复旦微FMQL到底是个什么东西简单说复旦微FMQL是国产SoC FPGA里非常有代表性的一类芯片。它内部同时集成了一个ARM处理器核心和一片可编程逻辑阵列整体架构思路对标的就是Zynq-7000那一代产品所以你在网上经常能看到“国产Zynq”这个叫法。我手头这块是FMQL20S400不同批次的FMQL型号在逻辑资源规模和ARM核主频上会有差异具体以官方选型手册为准PS侧跑的是一个带浮点运算能力的ARM处理器核心PL侧则是有着相当规模LUT、DSP和BRAM的FPGA逻辑。这种芯片最大的价值在于“一个片上系统搞定需要CPUFPGA配合的活儿”不用再在外面挂两颗主控芯片也不需要把ARM和FPGA之间的通信做成跨芯片的并行总线或者高速串行链路。从实际应用来看FMQL最常见的场景就是“ARM负责协议栈和业务逻辑FPGA负责高速数据采集、信号处理和并行计算”。比如工业控制里的多轴运动控制ARM侧跑EtherCAT主站或者Modbus协议FPGA侧做编码器计数、PWM输出和位置闭环再比如通信、机器视觉、仪器仪表领域FPGA把ADC采集、滤波、FFT做完ARM侧负责图像识别算法、网络上传和用户交互。如果一个产品只需要单片机加一个简单FPGA那确实用不上FMQL但如果你的系统需要“高吞吐数据通路复杂业务流程”同时存在FMQL这种架构就是最贴合需求的选择。1.2 PS、PL以及ARM和FPGA怎么分工我经常用“厨房分工”来给刚入门的同事解释PS和PL。ARM核就像大厨擅长判断和决策什么时候起锅、盐放多少、菜品接单顺序都由它管但一个人切菜备料速度有限。FPGA则是那组“流水线工位”切丝、切丁、腌肉、摆盘全都是并行进行的吞吐量极高但你要让它自己决定今天做什么菜它没这个能力。PS和PL之间就是大厨和工位的关系。在FMQL这颗芯片里PS和PL不是两个独立芯片放在同一块板子上而是通过芯片内部的AXI总线直接连在一起。也就是说ARM侧可以把FPGA里的逻辑资源当作自己的“外设寄存器”来访问读写一个AXI地址就能让PL侧的逻辑干一件事反过来FPGA侧也可以通过AXI互联发起对PS侧DDR内存的访问。比如机器视觉系统里PL把摄像头数据实时搬到DDR的固定区域ARM侧的算法程序直接从这块内存读数据数据不需要经过外部总线拷贝延迟低且带宽高。这个写系列的过程中我会把PS访问PL、PL访问PS外挂DDR这类话题单独拆开讲因为这里是SoC FPGA开发中最有嚼头也是坑最多的地方。1.3 为什么值得开一个系列来写其实复旦微FMQL的硬件资料和官方SDK是能拿到的网上也有零散的介绍但大多数文档还是“器件手册式”的写法告诉你寄存器叫什么、地址是多少却不太会告诉你“一个没有任何FPGA背景的ARM工程师怎么把手里的IAR工程跑起来”。再加上FMQL的开发方式和传统单片机有一些重要差异比如上电启动顺序、DDR初始化、链接脚本的RAM空间定义任何一个环节没搞对程序就黑屏白屏完全不知道问题出在哪。我决定把这个过程完整记录下来一方面是自己踩坑的记录避免过一段时间忘了又要重新查另一方面也是因为这套组合确实有门槛我希望后来的人能在我整理的基础上少走一点弯路。这个系列不会只写点灯和串口这种皮毛也不会一上来就搬Linux。核心路线是先用IAR把PS侧裸机程序跑通把ARM核的启动流程、时钟配置、DDR初始化、中断控制器、GPIO、UART、定时器都过一遍然后再往里走讲PS和PL之间的AXI通信、共享内存、中断协作最后再根据进度决定是否切入Linux或者轻量级RTOS。抛掉操作系统的干扰用最直接的方式理解这颗芯片的ARM侧是怎么工作的这是整个系列的基调。2. 选型思考为什么是IAR为什么是裸机2.1 IAR for ARM到底能不能玩FMQL PS侧开发如果你去查复旦微的官方资料会发现他们更多推荐的是Linaro GCC工具链或者自家的SDK环境很少有人提IAR。这并不奇怪因为国内做SoC FPGA的工程师很多是从FPGA背景转过来的习惯的是Vivado、ISE那一套ARM侧开发则倾向于用GCC和Linux。但如果你的技术底子是STM32这类单片机出身那IAR是你最顺手、最有肌肉记忆的开发工具。IAR for ARM本来就是一个通用ARM编译器只要目标芯片是ARM内核它都能编译区别只在于你有没有这个内核对应的设备描述文件、启动文件和链接脚本。我自己就是因为常年用IAR觉得Keil在某些大型工程的组织方式上不够利索GCC的Makefile系统又要花额外精力维护而IAR的工程管理、编译器优化选项、调试器集成度都比较均衡。FMQL的PS侧是标准ARM核IAR完全有能力编译出能跑的裸机程序。这一步走通之后后续调试体验其实比命令行工具链舒服不少。当然我这么说不是让你无脑选IAR如果你本身熟悉GCC用VS Code加交叉编译器也能达到同样的目的工具只是手段。这个系列选IAR纯粹是因为它在Windows下IDE体验好、导入官方库方便、配合J-Link调试很顺畅适合大多数嵌入式工程师的上手习惯。2.2 裸机还是Linux这里面的取舍很现实很多拿到FMQL的人都会纠结一个问题PS侧到底跑Linux还是裸机我的看法是先不用急着二选一裸机不是一个比Linux“低级”的方案而是一种完全不同的产品决策。跑Linux的好处是生态丰富、文件系统、网络协议栈、驱动框架都现成但坏处也很明显启动时间慢、实时性不可控、开发调试时需要维护设备树和内核对团队的软件能力要求更高。如果你的产品只需要开机后几百毫秒内干活或者有严格的中断响应时间要求又不需要复杂的文件系统那裸机反而是更合适的选择。我见过不少工程师一上来就在FMQL上跑Linux结果发现外设驱动就要折腾一两周最后不得不回来用裸机。先裸机把PS侧每个外设都摸清楚就算未来真的上了Linux你也会对底层硬件行为有更准确的理解排查内核问题的时候会轻松很多。尤其是FMQL这种集成芯片PS侧的时钟、DDR控制器、中断控制器都是要主动初始化的这些知识CFG操作在裸机环境里看得清清楚楚放到Linux里就成了黑盒。2.3 几种开发方案的真实对比为了让还没入坑的朋友有个直观判断我把几种常用的FMQL PS侧开发方案放在一起比较一下。这里不是要分个高下而是想让你根据自己团队的技术栈先想清楚哪条路对你最友好。方案优势劣势适合人群IAR J-LinkIDE集成度高、调试体验好、单片机工程师上手快IAR是商业授权设备支持包可能需要自己找从STM32等MCU转SoC FPGA的工程师GCC交叉编译 Makefile/CMake免费开源、可脚本化、方便持续集成调试器配置麻烦、工程组织要靠自己、新手容易卡在工具链上熟悉命令行开发的Linux玩家官方SDKEclipse类图形界面原厂配套、BSP驱动全、基本零门槛环境依赖重、调试和代码编辑体验一般走官方推荐路线的项目工程师Keil MDK也是ARM IDE、资源多对Cortex-A级别的支持不如IAR成熟、大工程编译速度一般纯粹习惯Keil且不接受改变的人我这里再补充一个个人观点选工具链的时候真正应该看重的是“能不能断点停在汇编那行、能不能看寄存器和内存、能不能让你快速明白程序为什么跑飞”。IAR在这一点上做得很成熟配合J-Link能在调试窗口里直接看到C代码和汇编的对应关系、外设寄存器的实时值对裸机开发来说是实打实的效率提升。3. 开工前的环境准备3.1 软件清单不是装了IAR就能直接开工很多人拿到FMQL开发板后第一件事就是装IAR然后发现自己连芯片型号都找不到。这不是因为IAR不认识复旦微而是因为IAR默认的设备库更新速度没那么快你需要先找到复旦微官方提供的IAR设备支持包装好之后才能在Target设备列表里看到FMQL系列。除了IAR本身我建议你提前把下面这几类软件都准备好IAR Embedded Workbench for ARM版本尽量新。我这次用的是9.60.4新版本对新款调试器固件兼容性更好对Cortex-A9这种应用处理器级别的内核支持也更完整。复旦微官方设备支持包以及对应的BSP驱动库。IAR的设备描述文件、Flash Loader、启动文件模板都在这个包里。J-Link驱动软件。如果用J-Link调试SEGGER的驱动和J-Link Commander最好装上部分奇怪问题可以在命令行里直接发命令排查。一个串口终端工具。裸机开发里printf重定向到UART是标配常用的SecureCRT、MobaXterm、串口助手都行能看16进制和ASCII显示就行。还有一个容易忽略的IAR的license。IAR是商业软件得用正版授权或者合法的评估license公司如果没有授权可以用官方社区版的替代或者老老实实申请评估序列号。千万别去下载网上那些来路不明的注册机既可能踩法律风险也不能保证编译工具链的完整性。3.2 硬件清单其实没比单片机复杂多少FMQL裸机开发前期不需要很贵的硬件。开发板厂家一般会送配套电源、JTAG调试口和串口引出你额外需要准备的其实就两样调试器和串口线。调试器方面我用的是SEGGER J-Link。FMQL的PS侧是ARM核JTAG的TCK、TMS、TDI、TDO引脚都会引到调试接口上J-Link完全可以识别。如果你的开发板没有独立JTAG口而是用板载的调试器芯片那看具体是哪一种CMSIS-DAP还是FTDI方案在IAR的Debugger设置里选对对应的驱动类型就行。另外提醒一句别图便宜买劣质拷贝J-Link固件和驱动一更新就会出现掉线、断连调试裸机程序最怕这种玄学问题。串口线要特别注意电平标准FMQL的PS侧UART引脚一般是1.8V或者3.3V电平如果你的USB转串口模块是5V供电信号要确认是否兼容最好选带电平转换功能、支持3.3V/1.8V切换的模块。稳压电源的输出纹波也要关注FMQL启动时对电源上电时序有一定要求开发板上的电源管理电路一般会处理好但外接电源电压不干净会导致PS偶尔启动异常这个坑在后面排查部分会再提到。3.3 IAR新建工程的最小流程一开始不要在工程配置上追求完美先跑通再说。我在IAR里建FMQL PS侧工程核心步骤大概是这样打开IAR选择File-New-Project模板选Empty project工具链选ARM。在Project-Options-General Options-Target里选择合适的FMQL设备前提是设备支持包装好了。选择设备后IAR会自动使用对应的寄存器描述文件和启动配置。把官方BSP里的启动文件和链接脚本加入工程。IAR的链接脚本后缀是.icf这个文件决定了你的代码段、数据段、堆栈放在哪个地址区域非常重要。官方BSP里通常有现成的模板别自己从零写先拿来用。配置Debugger在Options-Debugger里选择J-Link/J-Trace然后在对应的Driver设置里选择Cortex-A9接口下载速度先别拉满设到1MHz左右比较稳。确认C/C Compiler里的优化选项最开始建议用Low或者None方便调试时变量实时刷新。把Include路径指向BSP的include目录。几步操作完理论上一个空壳工程就能编译通过了。然后你在这个骨架里加自己的main函数、加外设初始化代码整个开发流程就清晰了。提示新建工程这一步最容易出问题的是.icf文件和启动文件不匹配。如果你的.icf文件定义的内存区域起始地址和FMQL实际DDR初始化之后的地图对不上程序一启动就访问非法地址直接hardfault。这部分属于启动流程核心知识下一章展开说。3.4 调试器配置的三个关键项IAR的调试器配置说简单也简单说复杂也复杂关键参数字段就三个。第一个是连接接口。FMQL的JTAG支持JTAG模式和SWD模式Cortex-A9通常用JTAG模式我在IAR里选择J-Link后默认接口如果没有选对连接会卡在“正在探测CPU”这一步。插上J-Link但识别不到设备十有八九是接口模式选错了。第二个是时钟频率。不是频率越高越好。调试器时钟设置太高容易因为线缆过长或者信号干扰导致连接不稳定我一般先用默认的自动协商不行就手动降到1MHz以下稳定之后再逐步调高。第三个是复位行为。裸机程序下载后需要复位一次让CPU从头执行IAR里可以选择“复位并停止”或者“运行到main”。在开发初期我建议选“运行到main”它能帮你避过启动文件里那些晦涩的CPU初始化过程直接停在C语言入口对调试体验的提升非常明显。4. 把第一个裸机程序跑起来4.1 点灯MIO和EMIO其实和单片机点灯一样FMQL的PS侧有很多互联引脚叫MIO可以配置成GPIO、UART、SPI等功能还有一部分引脚是走EMIO也就是通过PL侧的IO连出去的。如果只是验证最基础的PS能不能跑直接操作MIO管脚上的GPIO点一盏LED就够。因为PS侧的外设控制器的寄存器映射地址是固定的裸机程序里点灯的本质就是三件事使能GPIO外设时钟、把MIO引脚配置成输出模式、往数据寄存器写1或0。这一套逻辑和你在STM32上操作GPIO一模一样只不过FMQL的地址不是像STM32那样从0x40000000开始而是从0xE000A000这类地址偏移开始具体以芯片手册为准。在IAR里通过Debugger的寄存器窗口直接修改GPIO数据寄存器能立即看到LED亮灭这是验证调试链路是否正常的最快方式。不过点灯之前有一个前提把PS侧的全局时钟使能配置好。FMQL不像单片机那样上电后外设时钟全开很多外设控制器的时钟默认是关着的不去打开时钟就直接操作寄存器你会在总线上卡死或者读回全0。这个“先开时钟再配外设”的习惯是FMQL裸机开发和STM32开发之间最大的思维差异一定得记住。4.2 串口输出printf重定向的完整套路裸机开发没有比串口更重要的调试手段了。我用IAR做printf重定向已经养成固定套路FMQL上同样适用。你需要做两件事第一初始化UART控制器包括波特率、数据位、停止位以及对应的MIO引脚复用第二把标准库的fputc或者_write函数重定向到UART发送寄存器上。具体到IAR比较省事的做法是在工程里实现一个底层发送函数比如在代码里写一个简单的putchar实现轮询UART的发送FIFO空标志位然后把数据写进去。有的BSP库已经封装好了串口驱动你只要调用库函数把UART初始化好再在自己实现的重定向函数里调用这个库函数发送字符就行。有一点很关键IAR工程默认可能开启了半主机模式semihosting这时候printf会尝试通过调试器回传到IDE控制台而不是从串口发出表现就是板子上串口毫无反应。解决方法是链接选项里禁用半主机或者使用支持重定向的库配置。我习惯在main函数最开始就加一行串口初始化然后用printf打一条启动日志包含编译时间和当前时钟频率。这样每次连接调试器、每次重新上电第一眼就能确认串口链路通不通、时钟初始化对不对。只要这行日志能正常打印后续调试所有外设就有了一个“看得见”的观察窗口。4.3 时钟树、DDR初始化和启动流程简述这一节本来是后面要专门展开讲的但前言里我觉得有必要先给个概念因为它是FMQL裸机开发最特别的地方。FMQL复位之后PS侧的ARM核并不是以最终工作频率运行的而是以比较低的内置参考时钟启动。要让CPU全速跑、要让DDR可用你得在启动文件里配置PLL锁相环、时钟分频器、DDR控制器时序参数。这里要敲一下黑板很多第一次用FMQL的人会把代码放到DDR里但DDR控制器还没初始化CPU一取指就访问到一个无效地址程序直接跑飞。正确的流程应该是启动文件先做必要的CPU模式设置然后配置时钟初始化DDR控制器之后再进入main函数此时你的.icf文件里定义的DDR内存空间才是真实可用的。这个流程跟PC上BIOS先初始化内存再加载操作系统是一个道理。你在IAR里虽然看不到这些启动细节但只要启动文件用的官方模板基本路径就没错。后续系列我会专门写一篇FMQL的启动流程分析从复位向量、MMU、异常向量到PLL配置、DDR参数选择一条条拆清楚。5. 前期踩坑实录IAR FMQL最容易翻车的4件事5.1 芯片型号在IAR里找不到这个问题很多人第一次用FMQL时都会遇到。安装IAR后Target设备列表里没有复旦微FMQL并不是IAR不支持国产芯片而是缺少设备支持描述文件。解决办法是先确认官方BSP包是否正确安装然后在IAR里用Project-Options-General Options-Target通过“手动添加设备描述文件”的方式把复旦微的设备包加进去。如果这样还不行也有一个变通方法选择通用Cortex-A9内核。IAR编译时只要用对了ARM指令集链接脚本的地址定义正确代码运行效果是一样的只不过部分调试信息没有专用设备那么全。5.2 能编译但J-Link连接不上连接不上通常有几种原因。第一接口模式不对或者线序接错FMQL的JTAG引脚虽然引出来了但不同开发板的丝印排序可能不一样对照原理图确认一遍最稳妥。第二调试器供电不足。J-Link给目标板提供参考电压的引脚如果有接触不良J-Link就无法确认目标电压自然识别不到芯片。第三目标板本身没复位进入正常状态。FMQL的启动配置引脚如果被外部跳线设置成了从某种非易失存储器启动而该存储器里是空数据或者无效数据内核可能会一直处于异常状态。这种时候可以先通过调试器强制复位再尝试连接如果不行就把启动模式跳到JTAG调试模式。5.3 程序跑起来了但只要访问DDR就hardfault这个现象一眼看上去像代码问题实际上基本都是DDR初始化没做好。我调试时遇到过一种情况程序点灯和串口都正常但一旦定义一个大数组往里面写数据跑不了几下就崩。后来查下来是DDR控制器的时序参数和实际内存颗粒不匹配读写的训练没有通过表面上看内存“能访问”但偶发错误不断累积最终导致hardfault。这个问题的排查方法比较麻烦建议先确认IAR里.icf文件定义的内存区域起始地址是否和你配置的DDR控制器基地址一致再做一遍内存读写测试。如果你只是做PS侧简单裸机程序前期甚至可以先只使用芯片内部的RAM和OCM区域不碰外挂DDR先把逻辑调通再引入DDR。5.4 printf不输出或者输出乱码printf没输出最常见的原因就是我前面说的半主机模式编译链接时库使用了半主机方式printf的数据通过调试器回传而不是UART串口上自然没有内容。解决方法是链接选项里选择支持“无半主机”的库配置或者在代码里显式禁用半主机。输出乱码则多半是波特率配置问题尤其是FMQL时钟树还没完全配好的时候UART的外设时钟源不是整数值计算出来的分频结果误差偏大乱码就会出现。建议串口调试时先把波特率降到9600误差容忍度更高等时钟配置稳定后再用115200。注意FMQL裸机开发里有一个很容易被忽略但又很关键的原则——做任何外设操作之前先确认对应外设的时钟是否使能。这不仅适用于GPIO和UART也适用于中断控制器、定时器、DMA这些模块。养成“时钟优先”的习惯后很多古怪问题都能从根本上避免。6. 一系列踩坑之后我对这套组合的几点真实看法说实话刚开始用IAR做FMQL PS侧裸机开发的时候我心里也是打鼓的。毕竟复旦微的FMQL定位偏高端大家更习惯的方式是用官方工具链或者LinuxIAR裸机这种组合显得有点像“非主流”。但一个系列跑下来我的体会是这套组合不仅走得通而且对特定背景的人特别友好。如果你之前一直在用IAR写单片机程序你会发现自己大部分的工程管理经验、调试习惯、代码组织方式都能直接搬到FMQL上唯一要适应的是FMQL芯片的启动流程和内存地图以及被ARM核和外设总线带宽进一步提升后的调试思维。一旦跨过这个坎你会发现FMQL没有想象中那么神秘它本质上就是一个性能更强的ARM处理器外面挂了一片你可以当作“可重构外设”来用的FPGA仅此而已。最后再分享一个小技巧在IAR里同时打开反汇编窗口、寄存器窗口和内存窗口把窗口布局保存成一个调试布局每次调试固件更新时直接调出这套布局看代码和硬件状态的速度会快很多。后续这个系列我会按计划深入FMQL的启动流程、中断系统、GPIO和UART完整驱动、定时器、以及PS与PL的AXI通信和共享内存实战尽量每一篇都把原理讲透把坑填平。如果你在跟着文章操作的过程中发现了不同版本芯片或工具链的差异欢迎在评论区指出来一起把这条路趟得更平。