百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

大功率晶闸管,i.MXRT,LCD花屏,Cortex-M7技术文章分享

liebian365 2025-01-20 14:30 13 浏览 0 评论

大功率晶闸管参数解析之开关特性

编者按

功率二极管晶闸管广泛应用于AC/DC变换器、UPS、交流静态开关、SVC和电解氢等场合,但大多数工程师对这类双极性器件的了解不及对IGBT的了解,为此我们组织了6篇连载,包括正向特性,动态特性,控制特性,保护以及损耗与热特性。内容摘自英飞凌英文版应用指南AN2012-01《双极性半导体技术信息》。

3.4载流子存储效应和开关特性

当功率半导体的工作状态变化时,由于载流子存储效应,电流和电压的稳态值不会立即改变。

此外,晶闸管触发时只有门极结构附近的小块区域导通。由此产生的开关损耗必须以热的形式从半导体中散发出去。

3.4.1 开通

3.4.1.1 二极管

从非导通或阻断状态转入导通状态时,由于载流子存储效应,二极管处产生电压峰值(见图20)。

图20.二极管开通过程示意图

3.4.1.1.1 正向恢复电压峰值VFRM

VFRM是正向回复期间产生的最高电压值。该值随着结温和电流变化率的升高而增大。

电网 (50/60Hz)的电流变化率适中,VFRM可以忽略不计。但是在 di/dt>>1000A/μs的快速开关(IGBT、GTO和IGCT)自动换向变流器中,该值可能达到几百伏。虽然正向恢复电压仅存在几微秒,且不会显著增大二极管的总损耗,设计变流器时仍需考虑该值对开关半导体的影响。

针对这些应用优化的二极管图表包含了正向恢复电压和电流变化率之间的函数关系。

3.4.1.1.2 通态恢复时间tfr

根据DIN IEC 60747-2,tfr是指突然从关断状态切换为规定的通态时,二极管完全导通且出现静态通态电压vF所需的时间(见图20)。

3.4.1.2 晶闸管

在正向断态电压VD下通过变化率为diG/dt且强度为iGM的门极电流启动开通过程。对于光触发晶闸管,这同样适用于施加在激光二极管上的规定触发脉冲。在门极控制延迟时间tgd内,晶闸管上的阻断电压下降至90%(见图21)。最初只有门极结构周围的一小块区域导通,因此可使用初始电流密度和通态电流(di/dt)cr的临界上升率来衡量晶闸管在开通期间的稳健性。

图21.晶闸管开通过程示意图

a.具有关断负载电路的门极电流

b.具有快速上升通态电流的门极电流(另见3.3.1.8)

图22.门极控制延迟时间tgd与最大门极电流iGM之间的典型关系曲线

a.最大值 b.典型值

3.4.1.2.1 门极控制延迟时间tgd

tgd是指从门极电流达到其最大值

IGM的10%时起,到阳极-阴极电压下降至施加的正向断态电压VD的90%以下的间隔时间(见图21)。

门极控制延迟时间随着门极电流(对于LTTs为光功率)的增加而显著减小(见图22)。

在大功率晶闸管中,tgd也随VD而变。

数据手册中给出的值是依据DIN IEC 60747–6定义的,仅在Tvj=25°C和规定的触发脉冲下有效。

3.4.1.2.2 通态电流临界上升率(di/dt)cr

一旦电压因晶闸管触发而崩溃,门极结构附近的一小块阴极区域就开始传导通态电流。然后此导电区域向外扩散,扩散速度通常为0.1mm/μs,具体取决于电流密度。因此系统的载流能力最初是有限的。但是,如果不超过数据手册中规定的临界电流转换速率值,晶闸管就不会受损或损坏。对于S型晶闸管和具有大方形截面的晶闸管,门极得到分散(指条结构)。因此,这些类型表现出更高的(di/dt)cr。

根据DIN IEC 60747-6,临界电流上升时间(di/dt)cr与阻尼正弦半波期间加载的通态电流有关。它被定义为在以下条件下,穿过上升通态电流10%和50%这两个点的直线的角度(见图21,图47)。

结温:Tvj=Tvj max

正向断态电压:VD=0.67VDRM

峰值电流:iTM=2ITAVM

重复频率:f0=50Hz

在单独数据手册中定义了触发脉冲(另见3.3.1.8)。

例外:用正向断态电压VD=VDRM测试光触发晶闸管。

3.4.1.2.3 重复开通电流IT(RC)M

IT(RC)M是指以某个不确定上升率开通后随即产生的最大允许通态电流峰值。通常,这种通态电流是因RC缓冲电路放电产生的。最大允许重复开通电流还适用于以下达到通态电流临界上升率(di/dt)cr的电流急升情况。

对于英飞凌元件,适用以下值:

IT(RC)M=100A

例外:型号命名为T...1N或T...3N的元件

IT(RC)M=150A

对于超过60Hz的应用,须减小临界电流上升时间(di/dt)cr和重复开通电流IT(RC)M。应要求提供针对特定条件的详细信息。

3.4.1.2.4 断态电压临界上升率(dv/dt)cr

(dv/dt)cr是正向施加的电压上升率最大值,该值在0%至67%VDRM区间内几乎呈线性,此时晶闸管不会切换到通态。

对于电压指数上升,它是一条从最大值的0%开始,到63%结束的线,并且与指数函数相交。

它适用于触发电路开路和最高允许结温。超过(dv/dt)cr可能导致器件损坏。

例外:除过压保护(BOD)以外,光触发晶闸管还集成了dv/dt保护功能。当dv/dt升高时,此功能可使晶闸管在整个门极结构上安全触发。

3.4.2 关断

通常通过施加反向电压来启动关断功能。晶闸管或二极管的负载电流不会在过零时停止,而是作为反向恢复电流继续沿反向流动,直到载流子离开结区。

软度系数FRRS描述的是关断过程中电流上升率的关系。

3.4.2.1 恢复电荷Qr

Qr是半导体从通态转换到反向断态后流出半导体的电荷总量。该值随着结温、通态电流幅值和下降时间的增大而增大。除非另有说明,否则规定值仅在VR=0.5VRRM和VRM=0.8VRRM的条件下有效。为此指定了采用合适设计的RC缓冲电路。对于型号命名为T...1N、T...3N和D...1N的元件,数据手册中规定的值为最大值,该值在生产过程中经过100%测试。

恢复电荷Qr主要随结温Tvj和衰减电流的下降率而变(见图24和图25)。

图23.晶闸管和二极管的关断过程示意图

图24.归一化到Qr(Tvj max)的恢复电荷Qr与Tvj的典型关系曲线

图25.归一化到Qr(di/dt=10A/μs)的恢复电荷Qr与di/dt的典型关系曲线

3.4.2.2 反向恢复电流峰值IRM

IRM是反向恢复电流的最大值。Qr的关系曲线和工作条件也适用。如果图中未显示IRM,可通过以下公式大致确定IRM的值:

对于型号命名为T...1N、T...3N和D...1N的元件,数据手册中规定的值为最大值,该值在生产过程中经过100%测试。

反向恢复电流峰值IRM主要随结温Tvj和衰减电流的下降率而变(见图26和图27)。

图26.归一化到IRM(Tvj max)的反向恢复电流峰值IRM与Tvj的典型关系曲线

图27.归一化到IRM(di/dt=10A/μs)的反向恢复电流峰值IRM与di/dt的典型关系曲线

3.4.2.3 反向恢复时间trr

trr是指从电流过零时起,到穿过反向衰减恢复电流的90%和25%这两个点的直线过零时的时间间隔(见图23)。如果没有规定trr,可通过以下公式大致计算该值……

查看原文:https://www.dianyuan.com/eestar/article-8191.html


i.MXRT三位数系列Boot之Serial ISP模式

在上一篇文章 Boot配置(ISP Pin, OTP) 里痞子衡为大家介绍了i.MXRTxxx Boot的行为配置,其中第1.2节里讲了Boot有三类行为模式:Serial ISP、Serial Boot、Device Boot,后两种都是跟App启动执行相关的行为模式,而Serial ISP模式则是相对独立的Flash下载功能,有了Serial ISP,便可省去专用Flash编程器,今天痞子衡就来详细聊一聊Serial ISP模式。

痞子衡在前面已经讲过Serial ISP模式是一种串行编程模式,在这种模式下,BootROM通过指定的UART/SPI/I2C/USB-HID口来接收来自Host(恩智浦提供了上位机工具blhost.exe或者MCUBootUtility)的Application数据,并将数据下载进i.MXRTxxx支持的所有外部非易失性存储器中,为后续从外部存储器启动做准备。

一、进入Serial ISP模式

i.MXRTxxx上电永远是从ROM启动去执行BootROM程序,最顶层的Boot行为模式由OTP memory里的PRIMARY_BOOT_SRC[3:0]位和芯片外部ISP[2:0]管脚状态共同决定。假设我们正处于研发阶段,PRIMARY_BOOT_SRC[3:0]并未烧写,那想进入Serial ISP模式最直接的方式便是将ISP[2:0]输入状态拨成3'b110,在设计i.MXRTxxx的硬件板时ISP[2:0] pins应设计成可通过拨码开关选择输入电平,下图是RT600-EVK板(Rev.E)的参考设计:

拨码开关SW5应拨向SW_DIP-6的6,即设置ISP[2:0]=3'b110,此时便直接进入了Serial ISP模式。

二、blhost的使用

进入了Serial ISP模式,此时便可以用恩智浦提供的host工具与BootROM进行命令交互,host工具在 MCUBootUtility包 里。下载好MCUBootUtility包之后,在\MCUBootUtility\Tools\blhost2_3\win下可以找到用于与BootROM通信的blhost.exe。

2.1 支持的通信外设pinout

BootROM支持四种通信外设,分别是UART/SPI/I2C/USB-HID(其中UART和USB比较常用),pinout如下(Pinout适用RT600):

2.2 blhost用法

blhost.exe是命令行工具,使用blhost可以通过上述UART/SPI/I2C/USB-HID口与BootROM进行通信与命令交互。  

在命令行下打开blhost.exe,输入-?命令可以看到blhost使用帮助,blhost支持的命令很多:

PS D:\NXP-MCUBootUtility\tools\blhost2_3\win> .\blhost.exe
usage: D:\NXP-MCUBootUtility\tools\blhost2_3\win\blhost.exe
                                                                      [-?|--help]
                                                                      [-p|--port <name>[,<speed>]]
                                                                      [-u|--usb [[[<vid>,]<pid>]]]
                                                                      [-t|--timeout <ms>]
                                                                      -- command <args...>

Options:
  -?/--help                    Show this help
  -p/--port <name>[,<speed>]   Connect to target over UART. Specify COM port
                               and optionally baud rate
                                 (default=57600)
                                 If -ftbi, then port is BusPal port
  --ftdi spi[,<speed>,<polarity>,<phase>,lsb|msb] |
              i2c[,<address>,<speed>]
                               Use SPI or I2C for BusPal<-->Target link
                               All parameters between square brackets are
                               optional, but preceding parameters must be
                               present or marked with a comma.
                               (ex. -b spi,1000,0,1) (ex. --ftdi spi,1000,,lsb)
                                 spi:  speed(KHz),
                                       polarity(0=active_high | 1=active_low),
                                       phase(0=rising_edge | 1=falling_edge),
                                       "lsb" | "msb"
                                       (default=100,1,1,msb)
                                 i2c:  address(7-bit hex), speed(KHz)
                                       (default=0x10,100)
  -u/--usb [[[<vid>,]<pid>] | [<path>]]
                               Connect to target over USB HID device denoted by
                               vid/pid (default=0x15a2,0x0073) or device path
  -t/--timeout <ms>            Set packet timeout in milliseconds
                                 (default=5000)

Memory ID:
  Internal Memory              Device internal memory space
    0                            Internal Memory
                                 (Default selected memory)
    16 (0x10)                    Execute-only region on internal flash
                                 (Only used for flash-erase-all)
  Mapped External Memory       The memories that are remapped to internal space,
                               and must be accessed by internal addresses.
                               (IDs in this group are only used for flash-erase-all and
                               configure-memory, and ignored by write-memory, read-memory,
                               flash-erase-region and flash-image(use default 0))
    1                            QuadSPI Memory
    9                            FlexSPI NOR Memory
  Unmapped External Memory     Memories which cannot be remapped to internal space,
                               and only can be accessed by memories' addresses.
                               (Must be specified for all commands with <memoryId> argument)
    272 (0x110)                  SPI NOR/EEPROM Memory
    288 (0x120)                  uSDHC SD Memory
    289 (0x121)                  uSDHC MMC Memory

** Note that not all memories are supported on all platforms.

Command:
  reset                        Reset the chip
  get-property <tag> [<memoryId> | <index>]
                               Return bootloader specific property.
                               <memoryId> and <index> are required by some properties.
                               <memoryId> = 0, <index> = 0, if not specified.
                               <memoryId> and <index> are ignored for the other properties.
                               If <index> is over the range supported by the device, bootloader
                               will treat as <index> = 0.

    1                          Bootloader version
    2                          Available peripherals
    3                          Start of program flash, <index> is required
    4                          Size of program flash, <index> is required
    5                          Size of flash sector, <index> is required
    6                          Blocks in flash array, <index> is required
    7                          Available commands
    9                          Last Error
    10                         Verify Writes flag
    11                         Max supported packet size
    14                         Start of RAM, <index> is required
    15                         Size of RAM, <index> is required
    23                         QuadSpi initialization status
    24                         Target version
    25                         External memory attrubutes, <memoryId> is required
    27                         Flash page size, <index> is required
    28                         Interrupt notifier pin
    29                         FFR key store update option
  set-property <tag> <value>
    10                         Verify Writes flag
    28                         Interrupt notifier pin
                               <value>:
                                   bit[31] for enablement, 0: disable, 1: enable
                                   bit[7:0] for GPIO pin index
                                   bit[15:8] for GPIO port index
    29                         FFR key store update option
                               <value>:
                                   0 for Keyprovisioning
                                   1 for write-memory
  flash-erase-region <addr> <byte_count> [memory_id]
                               Erase a region of flash according to [memory_id].
  flash-erase-all [memory_id]  Erase all flash according to [memory_id],
                               excluding protected regions.
  read-memory <addr> <byte_count> [<file>] [memory_id]
                               Read memory according to [memory_id] and write to file
                               or stdout if no file specified
  write-memory <addr> [<file>[,byte_count]| {{<hex-data>}}] [memory_id]
                               Write memory according to [memory_id] from file
                               or string of hex values,
                               e.g. data.bin (writes entire file)
                               e.g. data.bin 8 (writes first 8 bytes from file)
                               e.g. "{{11 22 33 44}}" (w/quotes)
                               e.g. {{11223344}} (no spaces)
  fill-memory <addr> <byte_count> <pattern> [word | short | byte]
                               Fill memory with pattern; size is
                               word (default), short or byte
  receive-sb-file <file>       Receive SB file
  execute <addr> <arg> <stackpointer>
                               Execute at address with arg and stack pointer
  call <addr> <arg>            Call address with arg
  configure-memory <memory_id> <internal_addr>
                               Apply configuration block at internal memory address
                               <internal_addr> to memory with ID <memory_id>
  key-provisioning <operation> [arguments...]
                               <enroll>
                                   Key provisioning enroll. No argument for this operation
                               <set_user_key> <type> <file>[,<size>]
                                   Send the user key specified by <type> to bootloader. <file> is
                                   the binary file containing user key plaintext. If <size> is not
                                   specified, the entire <file> will be sent. Otherwise, only send
                                   the first <size> bytes
                               <set_key> <type> <size>
                                   Generate <size> bytes of the key specified by <type>
                               <write_key_nonvolatile> [memoryID]
                                   Write the key to a nonvolatile memory
                               <read_key_nonvolatile> [memoryID]
                                   Load the key from a nonvolatile memory to bootloader
                               <write_key_store> <file>[,<size>]
                                   Send the key store to bootloader. <file> is the binary file
                                   containing key store. If <size> is not specified, the entire
                                   <file> will be sent. Otherwise, only send the first <size> bytes
                               <read_key_store> <file>
                                   Read the key store from bootloader to host(PC). <file> is the
                                   binary file to store the key store
  flash-image <file> [erase] [memory_id]
                               Write a formated image <file> to memory with ID
                               <memory_id>. Supported file types: SRecord
                               (.srec and .s19) and HEX (.hex). Flash is erased
                               before writing if [erase]=erase. The erase unit
                               size depends on the target and the minimum erase
                               unit size is 1K.
  list-memory                  List all on-chip Flash and RAM regions, and off-chip
                               memories, supported by current device.
                               Only the configured off-chip memory will be list.
  efuse-program-once <addr> <data> [nolock/lock]
                               Program one word of OCOTP Field
                               <addr> is ADDR of OTP word, not the shadowed memory address.
                               <data> is hex digits without prefix '0x'
  efuse-read-once <addr>
                               Read one word of OCOTP Field
                               <addr> is ADDR of OTP word, not the shadowed memory address.
  generate-key-blob <dek_file> <blob_file>
                               Generate the Blob for given Dek Key
                               <dek_file> - input, a binary Dek Key (128 Bits) generated by CST tool.
                               <blob_file> - output, a generated blob (72 Bytes) in binary format.

** Note that not all commands/properties are supported on all platforms.

当使用串口转USB模块连接i.MXRTxxx的Flexcomm UART0或者使用USB Cable连接上USB1口后可以看到PC设备管理器会识别出相关设备:

让我们尝试一下使用blhost与BootROM通信,先试一下USB通信……

查看原文:https://www.dianyuan.com/eestar/article-8263.html


什么是定位LCD花屏显示问题的第一大法?

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是i.MXRT1170上LCD花屏显示问题的分析解决经验

痞子衡最近这段时间在参与一个基于i.MXRT1170的大项目(先保个密),需要做一个开机动画功能,板子连接的LCD屏分辨率是1280x480,因为开机动画要求达到30fps,并且要画质清晰,如果是从SD卡里读mp4或者jpeg去解码,这么高分辨率的图像(暂不考虑低分辨率的图片再用PXP模块去拉伸的方案)解码耗时比较长,恐怕难以达成30fps,所以痞子衡打算直接把图片的裸rgb数据事先存在Flash里,然后LCD模块直接去刷Flash里的数据去显示。

板子上的SPI NOR Flash有两种,默认是八线DDR高性能Flash,还有一个可选的四线SDR普通Flash,痞子衡做好的代码在默认高性能Flash上跑得没问题,换到另一块rework为普通四线Flash上就出问题了,显示完全是花屏,没有一点图片的影子,到底是怎么回事?跟着痞子衡一起去发现答案吧。

一、项目板卡简图

先来看一下这个项目板卡简图,简图里只示意了痞子衡今天要分享的LCD问题相关的器件,显示屏是TM103XDKP13控制器驱动的LVDS接口屏,跟i.MXRT连接的话需要有一个RGB2LVDS转接。Flash都是选的旺宏的,一个是MX25UW51345(200MHz,8bit,DDR),还有一个是MX25U25645(133MHz,4bit,SDR)。此外还有两个16bit的W9825G6KH组成的32bit SDRAM做显存,总容量是64MB。

二、在Flash中准备好图片裸数据

首先我们需要在Flash中存入图片数据,1280x480-24bpp (rgb888)图片一张的裸数据大小是1800KB,32MB的Flash最大可以存18张图片,为了给程序存储留点空间,我们就存17张,从Flash偏移0x100000处开始存图片。

2.1 截取一段mp4视频

痞子衡本地有一个NXP十周年宣传视频(MP4格式),原始分辨率是1920x1080,可以先用ffmpeg或者格式工厂将其转换成1280x480,然后可以直接用Windows自带的图片软件里的Trim功能截取其中一段,30fps帧率的视频截取1秒就够了。

2.2 使用ScreenToGif软件分离出图片

这时候可以用非常好用的GIF制作软件ScreenToGif打开这个1秒的MP4,可以看到一共有31张图片,可以删掉其中一些留下17张,然后将其保存为图片(当前版本仅能保存为png格式),可以再用格式工厂软件将图片格式转为jpg,存在D:/nxp_logo文件夹下。

2.3 Python脚本转成rgb888裸数据

有了17张jpg图片,这时候写一个Python脚本(jpg2rgb.py),借助Image库将17张jpg图片中的rgb数据全部抽取出来保存在一个bin文件中,下面脚本使用命令为 python jpg2rgb.py D:/nxp_logo/ -o startup_video_white_rgb888_17f.bin 。

import sys, os
import argparse
import Image

parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-o", "--output", required=True, metavar="PATH", type=argparse.FileType('wb'))
parser.add_argument("input", help="JPEG Image folder.")
args = parser.parse_args()

imgFiles = []

# 获取指定文件夹中所有jpg图片路径
imgFolder = os.path.abspath(args.input)
inputFiles = os.listdir(imgFolder)
for idx in range(len(inputFiles)):
    imgFiles.append(os.path.join(imgFolder, inputFiles[idx]))

for idx in range(len(imgFiles)):
    # 使用Image库打开jpg图片
    imgObj = Image.open(imgFiles[idx])
    pixelBuf = imgObj.getdata()
    # 抽取rgb裸数据写入bin文件
    for i in range(len(pixelBuf)):
        for j in range(len(pixelBuf[i])):
            args.output.write(chr(pixelBuf[i][len(pixelBuf[i]) - j - 1]))
args.output.close()

2.4 将图片裸数据bin文件下载进Flash

现在可以借助MCUBootUtility的通用编程器功能将startup_video_white_rgb888_17f.bin文件烧录进Flash里0x100000处偏移的地方。至此,准备工作已经就绪。

三、引出LCD花屏显示问题

现在让我们开始设计开机动画程序,可以基于 \SDK_2.x.x_MIMXRT1170-EVK\boards\evkmimxrt1170\jpeg_examples\sd_jpeg 例程,将其中的LCD配置,Pinmux配置稍微改一下,适配这个项目的板子,然后主函数可以精简如下(sd卡读,libjpeg解码函数全部去掉):

#define APP_FB_HEIGHT 480
#define APP_FB_WIDTH  1280
/* LCD frame buffer byte per pixel, RGB888 format, 24-bit. */
#define APP_FB_BPP 3

const uint32_t s_imagePics = 17;
const uint32_t s_imageStartAddr = 0x30100000;

int main(void)
{
    uint8_t *imageAddr = (uint8_t *)s_imageStartAddr;
    uint32_t imageBytes = APP_FB_HEIGHT * APP_FB_WIDTH * APP_FB_BPP;

    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_BootClockRUN();
    BOARD_ResetDisplayMix();
    APP_InitDisplay();

    while (1)
    {
        /* Wait for the previous set frame buffer active. */
        while (s_newFrameShown == false);

        /* Now new frame is ready, pass it to LCDIF. */
        s_newFrameShown = false;
        g_dc.ops->setFrameBuffer(&g_dc, 0, imageAddr);

        imageAddr += imageBytes;
        if ((uint32_t)imageAddr >= (s_imageStartAddr + imageBytes * s_imagePics))
        {
            break;
        }
    }
}

static void APP_BufferSwitchOffCallback(void *param, void *switchOffBuffer)
{
    s_newFrameShown = true;
}

这时候把代码下载进高性能DDR Flash的那块板子,我们的代码可以链接到TCM里执行,这样不占用运行时Flash访问带宽,不与LCD抢带宽。断电重启可以看到在60Hz的LCD刷新率下,开机动画效果显示杠杠的……

查看原文:https://www.dianyuan.com/eestar/article-8188.html


从XIP切到TCM执行,还能再提升Cortex-M7性能吗?

今天跟大家聊的这个话题还是跟痞子衡最近这段时间参与的一个基于i.MXRT1170的大项目有关,痞子衡在做其中的开机动画功能,之前写过一篇文章 《降低刷新率是定位LCD花屏显示问题的第一大法》 介绍了开机动画功能的实现以及LCD显示注意事项,在此功能上,痞子衡想进一步测试从芯片上电到LCD屏显示第一幅完整图像的时间,这个时间我们暂且称为1st UI时间,该时间的长短对项目有重要意义。

痞子衡分别测试了代码在XIP执行下和在TCM里执行下的1st UI时间,得到的结果竟然是XIP执行比TCM执行还要快50ms,这是怎么回事?这完全颠覆了我们的理解,i.MXRT上TCM是与内核同频的,Flash速度远低于TCM。如果是XIP执行,即使有I-Cache加速,也最多与TCM执行一样快,怎么可能做到比TCM执行快这么多。于是痞子衡便开始深挖这个奇怪的现象,然后发现了进一步提升代码执行性能的秘密。

一、引出计时差异问题

痞子衡的开机动画程序是基于 \SDK_2.x.x_MIMXRT1170-EVK\boards\evkmimxrt1170\jpeg_examples\sd_jpeg 例程的,只是去了SD卡和libjpeg库相关代码。工程有两个build,一个是TCM里执行(即debug),另一个是XIP执行(即flexspi_nor_debug)。

项目板上的Flash型号是MX25UW51345G,痞子衡将其配成Octal mode, DDR, 166MHz用于启动。项目板上还有两个LED灯,痞子衡在LED灯上飞了两根线,连同POR引脚一起连上示波器,用于精确测量1st UI各部分时间组成。

示波器通道1连接POR引脚,表明1st UI时间起点;通道2连接LED1 GPIO,表明ROM启动时间(进入用户APP的时间点);通道3连接LED2 GPIO,做两次电平变化,分别是1st图像帧开始和结束的时间点。翻转LED GPIO代码位置如下:

void light_led(uint32_t ledIdx, uint8_t ledVal);

void SystemInit (void) {
    // 将LED1置1,标示ROM启动时间
    light_led(1, 1);

    SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2));

    // ...
}

void APP_InitDisplay(void)
{
    // ...

    g_dc.ops->enableLayer(&g_dc, 0);

    // 将LED2置1,标示1st图像帧开始时间点
    light_led(2, 1);
}

int main(void)
{
    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_BootClockRUN();
    BOARD_ResetDisplayMix();

    APP_InitDisplay();

    while (1)
 {
     // ...
 }
}

static void APP_BufferSwitchOffCallback(void *param, void *switchOffBuffer)
{
    s_newFrameShown = true;

    // 将LED2置0,标示1st图像帧结束时间点
    light_led(2, 0);
}

上图是痞子衡抓到的波形(30Hz,XIP),痞子衡一共做了四次测试,分别是30Hz LCD刷新率下的XIP/TCM以及60Hz LCD刷新率下的XIP/TCM,结果如下表所示。表中的Init Time一栏表示的是开机动画程序代码执行时间(从SystemInit()函数开始执行到APP_InitDisplay()函数结束的时间),可以看到TCM执行比XIP执行慢近50ms,这便是奇怪问题所在。

二、定位计时差异问题

对于开机动画代码,XIP执行比TCM执行快这个结果,痞子衡是不相信的,于是痞子衡便用二分法逐步查找,发现时间差异是BOARD_InitLcdPanel()函数里的DelayMs()调用引起的,这些人为插入的延时是LCD屏控制器手册里的要求,总延时时间应该是153ms,但是这个函数的执行在XIP下(153ms)和TCM里(203ms)时间不同。

static void BOARD_InitLcdPanel(void)
{
    // ...

#if (DEMO_PANEL ==  DEMO_PANEL_TM103XDKP13)
    // ...

    /* Power LCD on */    
    GPIO_PinWrite(LCD_RESET_GPIO, LCD_RESET_GPIO_PIN, 1);
    DelayMs(2);
    GPIO_PinWrite(LCD_RESET_GPIO, LCD_RESET_GPIO_PIN, 0);
    DelayMs(5);
    GPIO_PinWrite(LCD_RESET_GPIO, LCD_RESET_GPIO_PIN, 1);
    DelayMs(6);
    GPIO_PinWrite(LCD_STBYB_GPIO, LCD_STBYB_GPIO_PIN, 1);
    DelayMs(140);
#endif
    // ...
}

所以现在的问题就是为何在TCM里执行DelayMs(153)需要203ms,而XIP执行下是精确的。让我们进一步查看DelayMs()函数的原型,这个函数其实调用的是SDK_DelayAtLeastUs()函数,SDK_DelayAtLeastUs()函数从命名上看就很有意思,AtLeast即保证软延时一定能满足用户设置的时间,但也可能超过这个时间。为何是AtLeast设计,其实这里就涉及到Cortex-M7内核一个很重要的特性 - 指令双发射,软件延时的本质是靠CPU执行指令来消耗时间,但是CPU拿指令到底是单发射还是双发射有一定的不确定性,因此无法做到精确,如果以全双发射来计算,就能得出最小延时时间。

#define DelayMs                  VIDEO_DelayMs

#if defined(__ICCARM__)
static void DelayLoop(uint32_t count)
{
    __ASM volatile("    MOV    R0, %0" : : "r"(count));
    __ASM volatile(
        "loop:                          \n"
        "    SUBS   R0, R0, #1          \n"
        "    CMP    R0, #0              \n"
        "    BNE    loop                \n");
}
#endif

void SDK_DelayAtLeastUs(uint32_t delay_us, uint32_t coreClock_Hz)
{
    assert(0U != delay_us);
    uint64_t count = USEC_TO_COUNT(delay_us, coreClock_Hz);
    assert(count <= UINT32_MAX);

#if (__CORTEX_M == 7)
    count = count / 3U * 2U;
#else
    count = count / 4;
#endif
    DelayLoop(count);
}

void VIDEO_DelayMs(uint32_t ms)
{
    SDK_DelayAtLeastUs(ms * 1000U, SystemCoreClock);
}

分析到现在,问题已经转化成为何XIP下执行指令双发射概率比TCM里执行指令双发射概率更大,关于这个现象并没有在ARM官方文档里查找到相关信息,DelayLoop()循环里只是3条指令,XIP下执行肯定是在Cache line里,这跟在TCM里执行并没有什么区别。让我们再去看看两个工程的map文件,找到DelayLoop()函数链接地址,这个函数在两个测试工程下链接地址对齐不一样,这意味着测试条件不完全相同,或许这是一个解决问题的线索。

XIP执行工程(flexspi_nor_debug),DelayLoop()函数地址8字节对齐……

查看原文:https://www.dianyuan.com/eestar/article-8187.html


更多精彩内容,尽在电子星球 APP(https://www.eestar.com/)

六篇技术文章,让你秒懂电容的脾气秉性

七篇DIY技术文章献给你,让你脑洞全开

五篇文章帮你开启DSP的学习思路

汇总篇:关于PID知识,重点在此

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: