Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C ARM上的高效复制,两次16位回迁还是1次32位回迁?_C_Performance_Assembly_Embedded_Arm - Fatal编程技术网

C ARM上的高效复制,两次16位回迁还是1次32位回迁?

C ARM上的高效复制,两次16位回迁还是1次32位回迁?,c,performance,assembly,embedded,arm,C,Performance,Assembly,Embedded,Arm,我正在研究一个使用ARM7TDMI处理器的嵌入式系统 在时间关键型ISR中,我需要将硬件寄存器中的24个16位值快照(拷贝)到SRAM中。这些值是连续的,可以作为数组处理 数据总线(到SRAM和硬件寄存器)是16位的,我们在ARM模式(8/32)下运行 在商店里,我们正在讨论复制数据的最佳方法:16位数量或32位数量 我的论点是ARM处于32位模式,因此它将使用一条指令进行2次16位回迁,比使用两条16位指令每次进行一次回迁快。 另外,要获取的指令数量是原来的一半,这将减少1/2的时间 有人有数

我正在研究一个使用ARM7TDMI处理器的嵌入式系统

在时间关键型ISR中,我需要将硬件寄存器中的24个16位值快照(拷贝)到SRAM中。这些值是连续的,可以作为数组处理

数据总线(到SRAM和硬件寄存器)是16位的,我们在ARM模式(8/32)下运行

在商店里,我们正在讨论复制数据的最佳方法:16位数量或32位数量

我的论点是ARM处于32位模式,因此它将使用一条指令进行2次16位回迁,比使用两条16位指令每次进行一次回迁快。
另外,要获取的指令数量是原来的一半,这将减少1/2的时间

有人有数据支持这两种方法吗? (我的示波器都已分配,因此我无法在嵌入式系统上进行测量。由于ISR每毫秒中断一次,我也无法运行大量时间。) *(由于我们的JTAG Jet探针无法提供精确的分析方法,因此分析比较困难)*

示例代码-16 it副本: 示例代码,32位副本: 详细信息:ARM7TDMI处理器以8/32位模式运行,IAR EW编译器

注意:代码被展开以防止指令缓存重新加载。
注意:汇编语言列表显示,使用常量索引访问内存比使用递增指针更有效

编辑1:测试 根据Chris Stratton的评论,我们在16位FPGA寄存器上进行32位取数时遇到问题,因此无法进行32位优化

也就是说,我使用DMA进行了分析。使用DMA控制器的性能增益为30 us(微秒)。在我们的项目中,我们希望获得更大的时间节省,所以这种优化是不值得的。这个实验表明,如果我们有更多的数据要传输,DMA将非常有用,或者可以并行传输


有趣的是,DMA需要17条指令来设置

如果速度是最重要的,那么如果硬件能够支持,那么最好的选择就是汇编语言例程,比如:

; Assume R0 holds source base and R1 holds destination base
PUSH   {R4-R7}
LDMIA R0,{R2-R7}
STMIA R1,{R2-R7}
LDMIA R0,{R2-R7}
STMIA R1,{R2-R7}
POP    {R4-R7}

我相信在ARM7TDMI上,当使用32位总线时,LDR需要三个周期,STR需要两个周期;使用LDRMIA/STRIA加载或存储n个字需要3+n个周期。因此,12个LDR和12个STR将需要60个周期,但上述序列应需要50个周期(包括寄存器保存/恢复)。我预计使用16位总线会给每个32位加载或存储增加额外的周期惩罚,但如果LDM*和STM*指令将每个32位操作拆分为两个16位操作,那么它们的执行速度仍将比离散加载和存储快得多,尤其是当代码必须从16位内存中提取时。

关闭中断,并测量主代码的性能。你可能应该考虑使用DMA,而不是…这是最快的。你知道寄存器在两种模式下都可以访问吗?在我使用的一些手臂部件上,有些SFR需要特定的访问宽度。此外,您可能想考虑在基于块的传输中,基于DMA的MEMCPY实现变得有价值(可能大于这个,但是?)@ MulkLakaT-似乎代码在中断处理程序中,而不是主程序。应该可以编写测试代码,在主循环中不必要地花费大量时间来完成这项工作,但是有理由不给出相同的结果。也许有一个硬件周期计数器可以访问以进行稀疏测试基准测试?@ChrisStratton:寄存器与内存映射的FPGA相连,32位提取将读取2个连续寄存器。另外,48字节是值得用DMA控制器复制的(设置至少需要6条指令)。某些硬件需要以特定的宽度读取。但是,我不能相信代码在ISR中运行的方式与在主循环中运行的方式有任何不同。代码就是代码。如果硬件阻塞了读取,那么尝试优化它就没有意义了——最好改用DMA。您能提供一个使用内联汇编的C语言示例吗?我们的车间编码标准更喜欢内联装配,而不是创建新的装配文件。您可以使用GNU语法,就像IAR编译器使用GNU语法一样。只需查看并使用memcpy(),它可以优化axi/amba总线上的最佳大小传输。连接到axi/amba总线的供应商逻辑将处理相同/更大的传输。总线将等待(必须将较小总线上的延迟和多个周期添加到supercat所指示的数字)。通常,四寄存器ldmia/stmia对用于快速复制循环。gameboy advance主要使用16位总线,并清楚地表明thumb运行得更快,但您的代码是数据周期重而不是指令周期重,因此您可以获得thumb优势,但主要问题是数据周期。使用128位(4个字)或更大的传输应该会将您推向数据与指令的边缘。如果您在编写代码时使用了该代码,而编译器没有进行优化,那么您的指令量很大,应该使用thumb。您将获得一些性能提升,但不如提高拷贝的效率(只需使用memcpy)。
uint32_t * p_data_from_hardware = (uint32_t *)&data_from_hardware[0];
uint32_t volatile * p_hardware_32_ptr = (uint32_t volatile *) p_hardware;
p_data_from_hardware[0] = p_hardware_32_ptr[0];
p_data_from_hardware[1] = p_hardware_32_ptr[1];
p_data_from_hardware[2] = p_hardware_32_ptr[2];
p_data_from_hardware[3] = p_hardware_32_ptr[3];
//...
p_data_from_hardware[ 8] = p_hardware_32_ptr[ 8];
p_data_from_hardware[ 9] = p_hardware_32_ptr[ 9];
p_data_from_hardware[10] = p_hardware_32_ptr[10];
p_data_from_hardware[11] = p_hardware_32_ptr[11];
; Assume R0 holds source base and R1 holds destination base
PUSH   {R4-R7}
LDMIA R0,{R2-R7}
STMIA R1,{R2-R7}
LDMIA R0,{R2-R7}
STMIA R1,{R2-R7}
POP    {R4-R7}