Flash运行时阻塞

如果您看了我的上一篇博文,您就应该了解Flash Player运行时的帧频和Timer计时是不精确的;其原因之一是AVM虚拟机每次分配的时间片间隔不是一个固定的值;另一个原因则可能是一次时间片所运行的代码较大,如果一个时间片的时间执行不完,则时间片就会延长并占用后面的时间片。

在这篇文章里,我给“时间片执行不完而延长该时间片,并造成帧频、Timer暂时停止”的情况起了个名词叫“Flash运行时阻塞”(这个名词或许并不完全恰当,如果您有更适合的词语,可以告诉我)。如果您没有看过我之前的博文,下面有两个链接,您有必要看一下:

执行模型之可变跑道

Flash Player帧频、Timer计时 的时间间隔测试

Flash运行时阻塞也会分为多种情况,比如:单次时间片所运行的代码量大,在给定的时间片内执行不完、计算机配置较低或运行过多的程序造成Flash所获得的CPU资源较少、Flash加载外部大数据文件等,本文的重点是关于Flash加载外部数据时,所造成的阻塞测试,其他几种情况较容易理解,我就暂时不进行测试了,有兴趣的朋友可以试一下。

AS3中,与加载外部数据有关的类有Loader、URLLoader、FileReference、NetConnection、SharedObject、Socket、XMLSocket等,另外我还测试了Flex中的SWFLoader和开源文件加载类BulkLoader,下面列出我的测试代码,后面总结一下。我使用的是Flex开发工具,创建了一个Flex项目。

对于这几个类的测试方式,大都是类似的,我就不全部列出了,我们看一下URLLoader在加载的时候对Timer计时和帧频的影响:

上面代码中我加载的是一个100M左右的rar文件,在代码的32行,Timer计时和URLLoader加载是同时开始的,但测试结果的前3行我们可以看出Timer计时并没有隔100多毫秒就运行,而是等待了将近3秒才开始第一次计时,而这3秒内,URLLoader加载完毕,由此可以证明URLLoader在加载的过程中,Timer计时被阻塞了。如果只针对于Timer你还不相信URLLoader会阻塞Flash的运行,那么我们来看一下ENTER_FRAME事件的执行效果。下面的代码跟上面Timer的测试代码类似,只是把Timer的部分换成了ENTER_FRAME事件。

前4行测试结果中显示,ENTER_FRAME事件也被阻塞了,如果您仍然认为URLLoader是异步加载的,并且对这个测试结果抱有怀疑的话,您可以动手测试一下,多动手往往能发现一些很有趣的事情。对于上面URLLoader阻塞ENTER_FRAME事件的测试,您或许注意到测试结果的第二行执行了一次ENTER_FRAME事件,如果您看过“执行模型之可变跑道”这篇文章,或许知道其中的原因,在这里我解释一下:对于ENTER_FRAME事件,会在每帧开始的时候最先执行;URLLoader调用load方法后,会在下一帧开始时执行加载,ENTER_FRAME事件是在每帧的最开始执行的,所以会先于load加载,这就是为什么第二句会是ENTER_FRAME事件trace出来的。很明显,这并不影响数据加载阻塞了ENTER_FRAME事件。

我使用类似的方式测试了Loader、SWFLoader、BulkLoader,它们在加载大数据的时候都会阻塞ENTER_FRAME事件和Timer计时事件,这里我就不给出测试代码了。

FileReference是AS3中用来上传下载文件的类,经过测试,在上传文件的过程中,FileReferece并不影响Timer和ENTER_FRAME事件,下载暂时未测试。

NetConnection不是加载外部数据的类,我主要想测试一下它的connect方法,测试证明connect在连接远程服务器时不影响Timer和ENTER_FRAME事件(即使连接服务器端所用的时间很长或根本连接不上服务器)。

在使用远程SharedObject时,多个用户连接该共享对象,如果某个用户使用SharedObject的send方法发送一个大数据时,发送者和接收者的Timer和ENTER_FRAME事件都会被阻塞。

Socket和XMLSocket因为时间的关系,我目前还没有做测试,有兴趣的朋友可以测一下,不要忘记告诉我结果哈。另外如果您觉得还有其他类会出现阻塞的情况,请一块分享。

总结一下:对于Flash运行时阻塞,一直认为是代码执行时间过长引起的,现在看来可能会存在多种情况造成阻塞。如果您觉得您的Flash应用程序有的时候会比较卡,并且会从外部加载一些数据,可以检查一下是否是因为加载的外部数据量较大造成的呢?比如 如果使用Loader加载多个可显示对象,并且网速比较慢的情况下(由此可见,网速慢也是引起Flash应用程序卡的一个原因)。

<think>我们正在讨论MCU在写Flash能否保持外设通信正常运行的问题。首先需要明确MCU的架构和资源分配情况。根据引用[1],FSMC接口用于MCU与FPGA之间的通讯,FPGA模拟成NANDFlash。在写Flash,MCU通过FSMC接口与外部存储器(如FPGA模拟的NANDFlash)进行通信。但是,Flash写操作通常需要一定的序控制,并且可能会占用系统总线。引用[3]提到,MCU有多个外设,如GPIO、UART、定时器等,这些外设可以独立工作。但是,当MCU执行Flash写操作,需要注意以下几点:1.**Flash写操作的特点**:内部Flash的写操作通常需要特定的序,并且在此期间,CPU可能无法访问Flash(因为Flash正在被写入)。因此,如果代码正在从Flash执行,那么在写Flash期间,CPU必须暂停执行,或者从RAM运行代码。2.**外设通信的维持**:外设通信(如UART、SPI、I2C等)通常由外设控制器独立处理,只要外设控制器能够正常工作,并且数据缓冲区被及填充,通信就可以继续。但是,如果写Flash操作占用了系统总线,或者导致CPU暂停,那么外设通信可能会受到影响。3.**具体实现**:-如果MCU支持双区(DualBank)Flash,那么在一个区进行写操作,CPU可以从另一个区执行代码,这样就不会中断程序的执行,从而可以继续处理外设通信。-如果MCU没有双区Flash,那么在执行Flash写操作,CPU必须暂停(或者从RAM运行代码)。此,如果外设通信的中断服务程序(ISR)也在Flash中,则无法执行。因此,需要将处理外设通信的代码(如ISR)放到RAM中执行。4.**外设控制器的独立性**:一些外设(如DMA)可以在CPU不参与的情况下进行数据传输。因此,如果外设通信配置了DMA,那么即使CPU暂停,DMA仍然可以继续传输数据,从而维持通信。5.**中断处理**:在写Flash期间,如果中断被禁用,那么外设通信的中断将无法被响应。因此,在写Flash的关键操作中,如果必须禁用中断,那么外设通信可能会被中断。为了避免这种情况,需要尽量减少中断禁用的间,或者将写Flash操作分成小块进行,并在操作间隙允许中断响应。总结:-如果MCU有双区Flash,并且代码运行在非写入区,那么外设通信可以正常维持。-如果没有双区Flash,则需要将关键代码(包括外设通信的中断服务程序)放到RAM中执行,并且写Flash不能长间禁用中断。-使用DMA来维持外设通信可以在CPU不参与的情况下继续数据传输。因此,答案是:在合理的软件设计下,MCU在写Flash可以保持外设通信正常运行。具体实现需要根据MCU的架构和资源进行设计。相关问题:1.如何将代码放在RAM中执行?2.MCU双区Flash的工作原理是什么?3.如何配置DMA以维持外设通信?</think>### MCU写Flash能否保持外设通信正常运行? MCU在写内部Flash**能否维持外设通信**取决于以下关键因素: #### 1. **Flash写操作的本质限制** - **总线冲突**:Flash控制器通常需要独占AHB/APB总线进行写操作,此CPU无法访问Flash。若外设通信依赖总线(如DMA传输),则会被阻塞[^1]。 - **中断延迟**:Flash写操作需数十微秒(典型值),期间若禁用全局中断(常见于关键操作),外设中断无法响应。 - **执行暂停**:当代码从Flash执行,写操作会暂停CPU流水线(除非代码在RAM运行)。 #### 2. **可行的解决方案** - **双区Flash架构**(如STM32H7系列): ```c // 示例:双区交替写操作 HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError); // 擦除Bank1 while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)); // 等待完成 HAL_FLASH_Program(...); // 写Bank1 // 此CPU可从Bank2执行代码,维持外设通信 ``` - ✅ **优势**:一个Bank写操作,CPU从另一Bank执行代码,外设通信可正常进行。 - ❌ **限制**:需MCU硬件支持,且软件需分区设计。 - **RAM执行关键代码**: - 将**中断服务程序(ISR)** 和**通信协议栈**链接到RAM(通过`__attribute__((section(".ramfunc")))`)。 - ✅ **优势**:Flash写操作期间,RAM代码仍可响应外设中断(如UART接收)。 - **DMA辅助通信**: - 配置外设(如UART、SPI)使用DMA传输,减少CPU干预: ```c HAL_UART_Receive_DMA(&huart1, rx_buf, len); // UART通过DMA接收数据 ``` - ✅ **优势**:DMA在后台搬运数据,即使CPU暂停仍可维持通信[^3]。 - **分段写入与中断管理**: - 将Flash写操作拆分为多段(每段<100μs),在段间短暂启用中断: ```c for (int i=0; i<data_len; i+=chunk_size) { HAL_FLASH_Program(...); // 写入一小块数据 __enable_irq(); // 短暂允许中断 __disable_irq(); // 继续写操作 } ``` - ⚠️ **风险**:频繁中断切换可能影响Flash写入效率。 #### 3. **外设类型的影响** | 外设类型 | 维持通信可能性 | 依赖条件 | |----------------|----------------|------------------------------| | **UART/I2C** | ★★★★☆ | 需DMA或RAM执行ISR | | **SPI** | ★★★☆☆ | 从设备需容忍钟暂停 | | **USB/CAN** | ★★☆☆☆ | 严格序要求,易因延迟失败 | | **GPIO轮询** | ★★★★★ | 只要CPU执行即可响应 | #### 4. **最佳实践建议** 1. **优先使用双区Flash**(若硬件支持) 2. **关键通信代码移至RAM** 3. **使能外设DMA**减少CPU依赖 4. **避免全局中断长关闭**,分段操作 5. **实性要求高的通信**(如USB)建议在写Flash前暂停 > **结论**:通过合理的软硬件设计(双区Flash/RAM执行/DMA),**MCU在写Flash可维持多数外设通信**,但对序严格的外设(如USB)仍有风险,需针对性优化[^1][^3]。 --- ###
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值