Nucleo-F413ZH 工程版测评(上)

ST的STM32产品线更新很快,旧的还没玩热,新的就出来了。得益于STM32系列封装的引脚兼容性,Nucleo系列的板子不用大改,就可以搭配新产品发布。F413作为目前F4系列当中片上SRAM容量最高的型号,我比较感兴趣;虽然接触过的Nucleo板子已经有4款了,Nucleo-144还没有玩过,这次论坛有活动,就申请了一个来玩玩。

和 Nucleo-64 板子摆在一起,差别很容易看出来:

因为144pin的封装尺寸更大,以及为了引出更多的I/O口,PCB宽度没变但加长了。芯片两侧的"ST Zio"连接,正面是双排孔,背面是双排针,用来连接扩展板;若和Nucleo-64的排座对齐,重叠部分是兼容的(下面扩出来一些,内侧再多一排)。包装里面附带的硬纸上也把这个连接口的定义以及MCU Pin对应附上了,方便随手查阅(不然得翻手册)。

光靠着个Zio连接还是不足以把所有I/O都引出来,于是板子外侧还有两排"ST morphoheaders"。不过这些焊盘全是空着的,不像Nucleo-64那样已焊上了插针。值得提一下的是,在PCB背面,此处每个焊盘位置旁边都丝印标出了pin的定义,这样实验的时候查起来方便多了。ST手册上说,MCU的每个I/O引脚都能在morphoheaders里面找到。

对比Nucleo-64主要还有其它的差异:
(1)板载 USB OTG FS 接口(micro-USB),可以直接做USB开发实验了。弥补了Nucleo-64需要做扩展卡的缺憾。
(2)User LED从1个变为3个。
(3)电源选择除了U5V, E5V外增加了VIN (7V~12V, 板载LDO)。
(4)以太网支持,不过因为F413并不包含MII,这部分相关元件没有焊。

STM32F413ZH, 这个开发板上的MCU是ES版本(Engineering Sample, 工程样品)。反正是评测嘛,样品就样品

. 简要特性可以从ST网站上的这张图看出了:

片上设备基本上和F412一样,明显是增大了Flash ROM和SRAM容量。最高频率和F410, F411都是同样的100MHz. F4内核没什么多说的,了解一款MCU要看看系统结构图:

注意 320kB 的SRAM是怎么组成的:256kB的SRAM1,和64kB的SRAM2. 程序可以在Flash、SRAM1和SRAM2中执行。我不肯定在FSMC上挂的外部ROM/RAM中能否执行程序。
软件开发环境:我依旧是用"原始"的GCC-ARM,直接访问寄存器的。为了玩F413需要获得: (1)寄存器定义的头文件, (2)启动代码,包含中断向量表定义, (3)GNU LD的Linker script. 这些文件可以从ST网站上下载最新版本的 STM32CubeF4 开发包, 或者 STM32F4 DSP and standard peripherals library 来获取。烧写程序使用 ST-Link Utility 的命令行工具比较方便,比我以前用STVP快。

周末写点程序来测试。点灯就不在话下了,先跑个无聊的计算程序吧

这个子程序计算 sin(x)*sin(x)+cos(x)*cos(x) 的值,理论上应该总是等于1, 实际上会有一点误差。对一定数量的输入数据进行计算,把误差累计然后返回。给主程序的数据交互是32-bit整型,计算则转换成float (单精度)型进行。STM32F413 SRAM大,我以为可以随便折腾,一开始是调用CMSIS的数学函数库来计算,Link的时候发现它要把巨大的常数表放到程序里。FLASH可以装下,RAM就吃不消了(因为我要把程序也放到RAM运行,进行对比),所以暂时弃之,只用GCC自带的数学库了。

主程序里面循环处理,每次随机生成16384个整型数(使用RNG随机数发生器),调用 test() 进行计算,并使用Timer5测计算过程消耗的时钟周期数。因为RNG需要使用比较快的时钟,我就配置了PLL,给它40MHz时钟。CPU时钟使用25MHz,AHB,APB也是用25MHz没分频。结果出乎我意料,25MHz下,16384个数的“无聊”计算消耗了大约13秒钟!我故意没有使用Cortex-M4F的浮点处理器,用默认的软件计算浮点方式,而且没有优化(里面隐含了许多double, float类型转换),但也没想到这么慢。可惜身边已经没有486计算机了,不然我要拿Turbo C 2.0写同样的程序算算对比下。

计算的结果,我用Matlab进行了同样的运算测试,和MCU输出的结果一致,精度符合预期。也就是单精度浮点表示的 sin(x)*sin(x)+cos(x)*cos(x) 与1的误差在 1.5e-8 左右。初步认为GCC的这个软件浮点库还是靠谱的。

 如手册中这一个图,Cortex-M4 核有三条AHB-Lite总线:I-bus, D-bus, S-bus. 经过Bus Matrix, I-bus 和 D-bus 都连到Flash模块。Flash和SRAM不同的是,它有两个总线接口。也就意味着,CPU核心可以同时从Flash读取指令和数据。虽然AHB总线宽度是32-bit,但是STM32F4 Flash存储的内部总线是128-bit的,因此在同频率下有更大的读取能力,通过预读取减少等待。实际效果如何待我测试一番。
就用这个无聊的计算程序来测,CPU频率我分别通过PLL配置调整到25MHz, 50MHz, 和100MHz。在50MHz下,Flash必须插入一个等待周期才能访问;而100MHz需要三个等待周期(在FLASH_ACR寄存器中设置). 毫无疑问,Flash等待周期加入后,程序是会变慢一点的,尽管频率提高了执行是更快,从计算消耗的周期上可以看出来。

时钟 不开启加速 打开Prefetch Prefetch, 使用Cache
25MHz (0 wait) 292822094 292922399
50MHz (1 wait) 313416305 310388296 297956680
100MHz (3 wait) 368267330 345938261 308417992

ST的Flash模块是有加速器功能的,它有Prefetch,就是预读取;还有D-cache和I-cache缓存,弥补Flash本身的等待。在25MHz也就是Flash没有等待周期的时候,Prefetch和Cache的效果并不明显。但到50MHz时,效果就显示出来了。100MHz时,效果更明显,最大获得近20%的性能提升。通过加速器的确减少了Flash等待周期带来的影响,接近0 wait state的执行效率。
那么和没有等待周期的SRAM比如何?如果简单地把程序代码装到SRAM1或者SRAM2中(0x20000000以上)运行,我发现甚至比Flash wait state=3, 不开启加速器的执行还要慢。为什么呢?因为SRAM只有一条总线接口,数据和指令公用了。Cortex-M4在运行的时候,需要从Flash或SRAM中读指令执行,也需要从Flash或SRAM中读取常数,还要从SRAM中读写变量、堆栈。当通道只有一条的时候,指令和数据就需要错开来访问。如果是Cortex-M0,因为它只有一条总线,用Flash还是用SRAM放程序运行没有差别;但对Cortex-M4就不同,前面已经提过了。Flash因为有两个总线接口,可以把指令和常数分开走,而SRAM中的变量又可以走S-bus,所以效率就高一些。用SRAM放程序又放数据,就容易堵车了。
不过呢,STM32F413比它前面几个弟兄要强一点,它有两块SRAM: 256kB的SRAM1, 64kB的SRAM2. 用一块SRAM放指令,另一块SRAM放数据,是否可以减少堵车呢?手册上是这么提了:

关键点:一定要在Remap的条件下,才可以用I-bus和D-bus来访问SRAM.
我的测试结果:

Flash 开启加速 SRAM默认 SRAM Remap
25MHz 292922399 337820882 292552526
50MHz 297956680 337788972 292580180
100MHz 308417992 337738861 292581401

终于,使用两块SRAM分别放程序和数据,SRAM中运行速度超过了Flash一点点。通过这个实验,我也更体会到总线的重要性。

在SRAM中运行程序通常是不必要的,但某些情况下的确能带来好处。还是上面的程序,测量一下计算时消耗的电流——把JP5跳线冒拔下,用电流表接入就可以了——结果我没有事先料到。

Flash运行,加速器开 SRAM运行, Flash PwrDown
25MHz 8.20mA 5.40mA
50MHz 13.94mA 9.58mA
100MHz 24.86mA 17.91mA

使用HSI 16MHz作为PLL输入时钟,PLL VCO频率200MHz,分频输出作为系统时钟。三个频率下APB时钟分别为25MHz, 25MHz, 50MHz (因为Timer5用到的APB1最高就50MHz了)。在SRAM中运行程序时,我将Flash设为Deep Power Down模式,这样减少了电流消耗,竟然相当明显。
看下ST手册里面的数据,对照参考,我的测量处于正常范围内。

因为除了Core本身,还有片上其它硬件在消耗电流,所以影响总电流的因素很多。随频率变化的趋势是一致的。Flash部分加速器的配置也会影响电流。而且我测试出来好象不开加速器消耗的电流会更多

 从手册里的数据表看,开加速器但不用Prefetch是比较省电流的,不过我没这样做测试。

测试Sleep模式电流,使用 WFI 指令来休眠,Timer中断唤醒。我只测试了SRAM运行模式下的(Flash Power Down了):

Freq 25MHz 50MHz 100MHz
SLEEP 电流 2.01mA 3.10mA 5.29mA

因为我是评测,还有降低Sleep模式电流的方法就不弄了。对比运行状态看个大概。

Stop模式可以降更多的电流,但片上设备基本上都不能干活了。进入Stop模式需要写 System Control Block中的SCR寄存器DEEPSLEEP位:
        SCB->SCR|=1<<SCB_SCR_SLEEPDEEP_Pos;
再使用 WFI 指令,电流就大大下降,我测到 185uA 了。这还是不够低,配置 PWR_CR 寄存器中 FPDS 位,将Flash设为Deep power down后,电流降一点,到 162uA了。再设 LPDS 位,使用Low Power的稳压器,降到 93uA.
但是手册上的电流在这个条件下典型应该是 19.7uA, 还差那么多呢?我怀疑问题出在 I/O 引脚上。STM32未用的引脚得给一个固定的电平,否则可能额外消耗电流。我把没使用的引脚都设成输入并加了上拉,可能和板子上的连接有不搭配的地方。对照电路图查了一遍,发现有外部下拉电阻的,都改后Stop模式电流降低到了 36.6uA.
还是差那么点。后来我找到原因是 PH0 这个口(Ext时钟输入)连到 ST-Link上的 MCO,也就是从 ST-Link 供给了 8MHz 的时钟。于是这个pin始终是被一个时钟驱动的…… 因为板子不是自己的,我就不拿烙铁焊掉那个0欧电阻去验证我的想法了。

Standby 模式,连稳压器都关掉,SRAM内容丢失…… 我测到电流是 2.2uA. 尽管够低了,这个模式实在用处不大了哈

进入这个模式除了设DEEPSLEEP位外,再写 PWR->CR |= PWR_CR_PDDS;

(0)

相关推荐