【国民技术N32WB031_STB开发板评测】 GPIO翻转性能测试
<h2 data-line="1" dir="auto" id="n32wb03x%E7%9A%84gpio%E7%BF%BB%E8%BD%AC%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95">N32WB03x的GPIO翻转性能测试</h2><h3 data-line="3" dir="auto" id="%E5%89%8D%E8%A8%80">前言</h3>
<p data-line="4" dir="auto">某些情况下,需要使用GPIO来模拟一些外设,虽然这会占用较多的MCU。为了弄清mcu的GPIO翻转速度上限,还是有必要测试一下的。</p>
<h3 data-line="6" dir="auto" id="%E5%AE%98%E6%96%B9gpio%E7%BF%BB%E8%BD%AC%E5%B7%A5%E7%A8%8B">官方GPIO翻转工程</h3>
<p data-line="8" dir="auto">在这个目录下,有官方的GPIO翻转最高速度的工程</p>
<blockquote data-line="9" dir="auto">
<p data-line="9" dir="auto">N32WB03x_V1.3.0\5-Software Development Kit\N32WB03x_SDK_V1.3\projects\n32wb03x_EVAL\peripheral\GPIO\IOToggle_MaxFrequency</p>
</blockquote>
<p data-line="11" dir="auto">用keil打开这个工程,可以看到main.c程序</p>
<div class="parsedown-markdown">
<pre>
<code>int main(void)
{
/* -1- Enable GPIOx Clock (to be able to program the configuration registers) */
RCC_EnableAPB2PeriphClk(GPIOx_CLK, ENABLE);
/* -2- Configure GPIOx_PIN in output push-pull mode */
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIOx_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_HIGH;
GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);
/* -3- Toggle GPIOx_PIN in an infinite loop */
while (1)
{
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
}
}</code></pre>
</div>
<pre>
</pre>
<p data-line="53" dir="auto">然后编译烧录后,使用示波器测试,翻转速度在8Mhz左右。为了进一步测试上限,尝试将函数放到RAM里执行。</p>
<hr data-line="55" dir="auto" />
<h3 data-line="57" dir="auto" id="mcu%E7%9A%84%E7%A8%8B%E5%BA%8F%E5%9C%A8flash%E9%87%8C%E5%92%8Cram%E9%87%8C%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB">MCU的程序在Flash里和RAM里有什么区别?</h3>
<p data-line="59" dir="auto">由于MCU的资源都比较小,常见产品的Flash也是支持XIP的,也就是MCU可以直接在Flash里取指令并直接执行。所以并不像PC那样,必须将程序加载到RAM里才可以运行。同时因为很多MCU的速度远高于Flash的速度,为了提高执行效率,工程师们一般使用三种办法(如果有其他的办法,麻烦大家帮忙补充一下)。</p>
<ol data-line="60" dir="auto">
<li data-line="60" dir="auto">增加ICache,在核心与Flash之间增加指令缓冲,加快执行速度。</li>
<li data-line="61" dir="auto">使用部分SRAM作为零缓冲区,在mcu启动时自动将Flash的大部分加载到零缓冲区(缓冲区和Flash的数据同步由硬件自行完成,无需用户干预)。</li>
<li data-line="62" dir="auto">将一部分函数在mcu启动时从Flash加载到RAM里,在RAM里执行这些函数。</li>
</ol>
<h3 data-line="64" dir="auto" id="%E5%A6%82%E4%BD%95%E5%9C%A8keil%E4%B8%AD%E6%8C%87%E5%AE%9A%E9%83%A8%E5%88%86%E5%87%BD%E6%95%B0%E5%8A%A0%E8%BD%BD%E5%88%B0ram%E9%87%8C">如何在keil中指定部分函数加载到RAM里</h3>
<ol data-line="66" dir="auto">
<li data-line="66" dir="auto">点击 Options for Target..图标,然后在弹出的选项卡里选择Linker选项卡</li>
<li data-line="67" dir="auto">取消勾选左上角的Use Memory Layout from Target Dialog,然后点击下边sct文件旁边的edit按钮(见图片), 然后点击OK关闭选项卡</li>
<li data-line="68" dir="auto">修改.sct文件,自定义一个section(这里我们使用RAMCODE),放在RW_IRAM1段</li>
<li data-line="69" dir="auto">将#pragma arm section code = "RAMCODE"放在main函数前,#pragma arm section放在main函数后。</li>
</ol>
<p data-line="71" dir="auto">.sct的最终内容如下</p>
<div class="parsedown-markdown">
<pre>
<code>; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x01000000 0x00040000{ ; load region size_region
ER_IROM1 0x01000000 0x00040000{; load address = execution address
*.o (RESET, +First)
*(InRoot$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x0000C000{; RW data
*.o(RAMCODE)
.ANY (+RW +ZI)
}
}</code></pre>
</div>
<pre>
</pre>
<p data-line="91" dir="auto">main函数修改后最终内容如下</p>
<div class="parsedown-markdown">
<pre>
<code>#pragma arm section code = "RAMCODE"
int main(void)
{
/* -1- Enable GPIOx Clock (to be able to program the configuration registers) */
RCC_EnableAPB2PeriphClk(GPIOx_CLK, ENABLE);
/* -2- Configure GPIOx_PIN in output push-pull mode */
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIOx_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_HIGH;
GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);
/* -3- Toggle GPIOx_PIN in an infinite loop */
while (1)
{
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
GPIOA->POD = 1;
GPIOA->POD = 0;
}
}
#pragma arm section</code></pre>
</div>
<pre>
</pre>
<p data-line="135" dir="auto">编译烧录后,可以看到速度增加到9.25MHz,应该就是这个MCU的GPIO极限翻转速度了,详见截图。</p>
<p data-line="135" dir="auto"> </p>
放内存,放flash,还不如直接汇编来得实在一些吧。 lugl4313820 发表于 2023-5-12 19:14
放内存,放flash,还不如直接汇编来得实在一些吧。
<p>大佬可以试试汇编的GPIO速度是多少,菜鸡不会写汇编</p>
页:
[1]