一个MCU与FPGA混合电路上电启动的问题及其解决办法探索[原创www.cnblogs.com/helesheng]

news/2025/9/21 17:25:55/文章来源:https://www.cnblogs.com/helesheng/p/19103793

最近在做一个同时需要MCU与FPGA的项目,具体说是FPGA作为MCU的FSMC(Flexible Static Memory Controller)接口的一个外设,通过SRAM接口与MCU通信。MCU用的是STM32中有FSMC接口的100pins器件STM32F103VET6,FPGA用的是国产安路小精灵系列的EF2L15。使用时发现当两种用同一路电源时,上电后MCU无法正常启动工作。现将我对问题的分析以及解决办法分享如下,以下原创内容欢迎网友转载,但请注明出处:https://www.cnblogs.com/helesheng 

1、寻找和分析原因

观察到一个现象:上电后FPGA开始稳定工作后,虽然MCU不能工作,但按下MCU的复位键后,MCU能够恢复工作。因此我推测是MCU在和FPGA连接后无法正常复位造成的。但FPGA的启动过程要经过比特流文件从Flash加载到查找表中的过程;而STM32的程序却是从Flash中一边不断取指,一边执行的。启动速度是STM32完胜,怎么会出现STM32反而被FPGA影响的情况呢?显然问题只能发生在FPGA比特流尚未加载完成,MCU发生复位的阶段。

两者相连的FSMC接口,大部分管脚是MCU作为主设备输出信号,FPGA作为从设备输入信号。但当我用示波器观察时却发现,在安路小精灵系列EF2L15进行比特流加载阶段,这些管脚居然在输出高电平!我将这些IO约束为禁止PULLUP的NONE模式,但发现没有什么卵用:比特流配置过程中它们仍然我行我素的输出高电平——想来也是,还没有完成比特流配置,FPGA怎么知道这些管脚的模式是什么。

既然无法在上电的最初阶段保证MCU的正确上电复位,我只能退而求其次:在FPGA完成比特流配置后,再对MCU进行复位。用示波器观察EF2L15的配置完成管脚DONE,我沮丧的发现:这么一个“小精灵”,它的配置时间居然达到了400ms以上,这是常见上电复位芯片无法达到的。(如:我自己比较喜欢的MAX809/810的复位时间都只有200ms左右)。

我又想,干脆让EF2L15加载完成后,再用FPGA管脚输出一个的复位信号给MCU好了(具体代码见下一小节)。令人意想不到的事情再次发生:采用这种方法后,JLINK无法下载和调试MCU了。仔细一考虑,这也有道理:上电过程完成后,FPGA的输出的复位信号钳置了MCU的复位管脚,让JLINK在调试时下载MCU程序后无法复位MCU,从而导致无法调试MCU了。

绕了个大弯子,似乎又回到了原点。在上面的尝试后,我得到了以下两种有效的解决方案:

2、两种解决办法

 方法一:缩短FPGA上电后比特流加载时间 + 延长MCU复位时间

既然无法保证将MCU复位时间延迟到400ms以上,把FPGA上电后比特流加载时间缩短也是一个不错的办法,在安路的官网上找到了这篇技术文档《TR404_ELF2 FLASH启动加载时间测试》,它提到有两种方法加快“小精灵”系列上电后比特流加载时间:a、提高读取比特流文件读取时钟;2、采用2位或4位比特流( mspix2或x4)加载代替1位比特流加载。

配置方法如下:

在TD中打开FPGA工程,Process菜单中的属性对话框中进行Properties Configuration,对mclk_freq_div进行配置,将其时钟频率配置到2.5MHz~24MHz之间的更高数值。

image

图1 Properties Configuration界面配置读取时钟频率

 在 TD 软件 Download 界面上,在识别到 EF2 系列芯片以后点击左边的“Attribute BlockEditor”,先点 Read,弹出的 boot_mode 属性中选择 mspix1/x2/x4,然后点击Program 按钮,如图2所示,然后在 TD 主界面重新生成 Bitstream。在 Download 界面中选择 bit 文件,下载模式选择PROGRAM FLASH 下载,如图 3 所示。

image

图2 boot_mode配置

image

图3 下载界面

 经过上述两部配置后,我的比特流加载时间被从400ms压缩到了20ms左右!

惊喜的发现,将比特流加载时间压缩到50ms以内后,不需要改动PCB,只要把STM32的复位电路从10KΩ+0.1uF改成10KΩ+1uF即可使MCU正常上电复位进入正常工作状态了。

 

方法二:FPGA加载后复位MCU

前面说过有一种思路是用FPGA在加载完比特流,开始运行以后,在输出一个复位MCU的信号。但这个方法的问题是,FPGA输出复位信号的管脚牵制了MCU的复位管脚,导致其无法通过JLINK调试和下载程序。参考STM32内部WWDG、IWDG和软件复位等多种信号共同控制系统总复位信号的电路,可以采用线与(Wired-AND)的方式管理来自FPGA的复位信号。即在MCU的复位电路上对地并联一个NPN晶体管或N沟道MOS管。参考下图4。

image

图5 “线与”方式实现来自FPGA的复位信号接入

 采用这个电路后,来自FPGA的复位信号不会将MCU的复位管脚钳置到高电平,只会在需要时(输出高电平)打开NMOS管,实现低电平复位MCU。其他时间来自按键或MCU内部的WWDG、IWDG和软件复位都可以将MCU的复位信号拉低,以实现复位。

2、两种解决办法优缺点比较

第一种方法最简单,无需改动电路,且能够降低系统上电到运行的延迟时间。但缺点是当FPGA的比特流较大时,比特流加载时间仍然有可能超过MCU上电复位延迟时间,导致MCU无法正常复位。第二种方法最可靠,但要增加电路或修改PCB。

 

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

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

相关文章

Unity Volume Rendering

Unity Volume Rendering如下内容是对 https://tips.hecomi.com/entry/2018/01/05/192332 进行翻译同时增补得到笔记体积渲染概述 体积渲染是一种在 2D 屏幕上渲染 3D Texture 的技术,其中 3D Texture 来源有:从 CT 扫…

JMX与RMI

JMX与RMIJMX -监控 Jconsole -Djava.rmi.server.hostname= ip-Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.port=XXX-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.aut…

深入解析:线程安全相关的注解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

go语言的结构体和指针

go语言的结构体和指针type Person struct {Name stringAge int }func updateName(p *Person, newName string) {p.Name = newName // 通过指针修改结构体字段 }func main() {p := Person{Name: "Tom", Age:…

通过主机监控发现路径遍历漏洞的实战技巧

本文介绍如何利用简单的Bash脚本监控主机在线状态,通过实时Telegram通知及时发现目标系统上线,并成功挖掘出Jira系统的路径遍历高危漏洞的实战经验。通过主机监控发现路径遍历漏洞 脚本功能概述 我最近编写了一个简单…

Code New Roman 字体的正确下载方式

Code New Roman 字体的上游已经不知所踪,而各大字体网站上流传的版本在 VS Code 里的显示效果也有些问题。(具体来说,字符的上边界会顶到一行的上边界。)但是我在网上冲浪时发现 Nerd Font 里有修复了这个问题的 r…

go语言中的数组类型

go语言中的数组类型var arr1 [3]int // 声明一个长度为3的整型数组 arr2 := [3]int{1, 2, 3} // 声明并初始化 arr3 := [...]string{"a", "b"} // 自动推断长度fmt.Printl…

多态是对于处理不同的变量,但是使用相同或者类似的方式。多态核心分为两种形式:编译时多态(静态多态)和运行时多态(动态多态)C++中多态通常使用虚函数或者指针(引用)实现。

多态是对于处理不同的变量,但是使用相同或者类似的方式。多态核心分为两种形式:编译时多态(静态多态)和运行时多态(动态多态)C++中多态通常使用虚函数或者指针(引用)实现。pre { white-space: pre !important;…

从 C++ 到 Python

从 C++ 到 Python 一、注释 #单行注释多行注释"""多行注释"""二、字符串 Hello, python! #单、双引号都可以,没有区别 #倾向于用单引号三、I/O与变量 #输出 print(Hello, python!) #Py…

在 Unity 中实现 0GC(零垃圾回收)对象池 — 实战指南 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Nipper 3.9.0 for Windows Linux - 网络设备漏洞评估

Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估 Nipper for routers, switches & firewalls | Nipper Network Configuration Audit Tool 请访…

c++单例实践

这篇文章为大家介绍`static` 关键字相关知识以及如何实现自己的C++单例类。C++单例实践 在日常开发中,虽然太多的单例调用会让代码的耦合度变高,但是例如日志类这种,单例模式就变得非常有。所以这篇文章为大家介绍s…

NOIP 模拟赛九

gcd+DP+数据结构/贪心+整体 DPReverse Card \((a+b)\mid b\cdot \gcd(a, b)\) 计数。 先化式子,记 \(g=\gcd(a, b), a=ag, b=bg\) 。 \(g(a+b)\mid g^2b\) ,即 \((a+b)\mid gb\) 。 又 \(\gcd(a + b, b)=\gcd(a, b) …

个人项目-软件工程第二次作业 - Nyanya-

这个作业属于哪个课程 计科23级34班这个作业要求在哪里 个人项目这个作业的目标 进行个人编程,设计论文查重算法Github仓库 https://github.com/username/PaperCheck一、PSP表格PSP2.1 Personal Software Process Sta…

go语言中的复杂数据类型

go语言中的复杂数据类型package mainimport ("fmt" )func main() {// 基本类型var a int = 10var b float64 = 3.14var c bool = truevar d byte = Avar e rune = 中var f string = "Hello, Go!"v…

详细介绍:互联网医院品牌IP的用户体验和生态构建

详细介绍:互联网医院品牌IP的用户体验和生态构建pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas",…

实用指南:认知语义学中的象似性对人工智能自然语言处理深层语义分析的影响与启示

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

支持 SSL 中等强度密码组(SWEET32) - 漏洞检查与修复

突发奇想,把漏洞修复的事情也记录一个文档,之前也修复过很多的漏洞,但是总是修复了就完事了,没有留存记录,以后的漏洞我会留一个tag专门记录,如果正好其他人也有遇到的这样的问题,可以很快速的有一个处理方向和…

C# WPF CommunityToolkit.MVVM (测试一)

MainWindow.xaml<Window x:Class="CommunityToolkit.MVVM_RelayCommand_测试.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.m…

linux kernel synchronization rcu

Read Copy Update /RCU 可以单个写,多个读,在内核中常用于更新链表。对比顺序锁,只能用指针访问资源,读数据无需加锁,避免多次读数据。 应用场景:多个读 少量写 写相较于读具有更高优先级 rcu保持数据指针的引用…