【问题标题】:ASM function from C ARM embedded来自 C ARM 嵌入式的 ASM 功能
【发布时间】:2012-06-13 12:20:49
【问题描述】:

我正在使用 STM32F4 并尝试从内部调用编写 ASM 函数 C. 该函数将在 C 函数内部调用,并且该函数也在中断中。 我正在推动和弹出 r4-r7。我还需要做其他事情吗? 我的假设是 r0-r3 不需要推动。我也在修改全局 使用 ASM 函数的变量。我的猜测是这些应该被宣布为 volatile。 欢迎任何提示。 我还注意到 ARM 概述的 Cortex M4 指令集与 GCC 编译器似乎可以使用的指令。 例如,没有回写即 r0,[r1],#4 后增量是非法的。 是否有允许哪些 ASM 指令的列表? 我假设 STM32F4 使用 thumb2

到目前为止,它似乎没有工作,我想知道可能的问题是什么 除了程序集中的错误

【问题讨论】:

  • 你试过了吗?什么没用?您说您正在尝试调用汇编函数,但您的其余问题听起来像是您正在尝试编写一个。请尝试更好地解释。
  • 您绝对应该将全局变量声明为 volatile,但我已经有一段时间没有使用 ARM asm 了,所以无法解决剩下的问题。
  • 没有理由声明一个全局变量volatile,除非它可以在程序控制流之外进行更改。调用汇编函数本身并不是要求volatile 的充分理由。 任何函数调用都可以改变全局的值。
  • @CarlNorum - 我考虑的不是程序集,而是在中断中调用它。
  • 啊哈——明白了。我在第一次阅读时错过了这一点。好电话。

标签: assembly arm


【解决方案1】:

您的问题的一些答案在“ARM 体系结构的过程调用标准”一书中。这是link

书上说前四个寄存器 r0-r3(和 FPU 的 s0-15)用于将参数值传递给子程序并从函数返回结果值。它们也可用于在例程中保存中间值(但通常仅在子例程调用之间)。寄存器 r4-r8、r10 和 r11(以及 FPU 的 s16-s31)用于保存例程的局部变量的值。子程序必须保存这些寄存器的内容。

现在关于volatile。我认为是的,您必须使用它来防止编译器优化可以“制动”您的程序逻辑。

关于你的正弦。英语不是我的自然语言,所以我不太明白你需要什么,但如果你需要一些快速和精确的正弦近似作为你的问题的一部分,你可能会对这篇文章感兴趣:http://devmaster.net/forums/topic/4648-fast-and-accurate-sinecosine/http://www. coranac.com/2009/07/sines/.

最后一个。我几乎完成了 Cortex-M4 的正弦逼近函数。它使用FPU,大约需要30个周期,并且在单个浮点范围内带来零错误。

【讨论】:

  • 感谢 cmets。关于正弦,我正在使用表格,因为这对我来说是目前最快的方式。我需要生成 384 正弦
  • 感谢 cmets。关于正弦,我正在使用表格,因为这对我来说是目前最快的方式。我正在研究加法合成,需要能够为每个 48k 采样率生成 24 个正弦波和 ADSR 包络,因此速度非常重要。
【解决方案2】:

等了 8 小时后才能回答我自己的问题? 无论如何,这就是我得到的,它有效! 这个函数有很多事情要做。它基本上是一个正弦波振荡器 对正弦值使用 LUT。它还使用一个指数值表,这些值是使用连接到控制罐的 ADC 分配的。有一个 32 位相位累加器,可创建 然后缩放以进行查找的斜坡。正弦表(我没有包括太多) 是将 16 位值截断为 14 位表大小。我确信在这段代码中有很多优化要做,但至少它让我开始了。 我在这个函数的每次传递中生成 16 个正弦波样本@48k 并填充一个缓冲区(在这个函数之外) 通过 Discovery 板载编解码器传输到 DMA 并输出。 我必须说它听起来非常流畅。总指令周期似乎在 1200 左右 迄今为止。如果我需要它们,我有多达 56000 个周期,所以这非常好。 我遇到困难的一件事是缩放正弦输出。正弦表是 int16_t 值,我希望能够将它乘以一个分数来获得音量控制。到目前为止,我没有尝试过使用 smul、mul 等。

    @ void get_sine(void)
        .align 2                    @ Align to word boundary
        .global get_sine       @ This makes it a real symbol
        .thumb_func
        .type get_sine STT_FUNC    @ Declare get_sine to be a function.

    get_sine:                  @ Start of function definition
        push    {r4-r7}
        ldr     r0,=pitch       @   get pitch address
        ldr     r1,=expoLUT     @   expo_tab address
        ldr     r7,[r0,#0]      @   pitch val into r7
        lsl     r7,r7,#2
        ldr     r7,[r1,r7]      @   move lookup expo tab value with r7 into r7

        ldr     r2,=sineLUT     @   sine_tab base addy
        ldr     r4,=WaveBuffer  @   storage array addy
        ldr     r5,=writePos    @   get writepos addr
        mov     r6,#0           @   clear increment r6

    outloop:
        ldr     r3,=phase       @   phase address to r3
        ldr     r1,[r3,#0]      @   get current phase
        add     r1,r1,r7        @   add current phase and ph_inc
        str     r1,[r3,#0]      @   store phase
        lsr     r0,r1,#18       @   shift it right by 18 into r0 for sine_tab lookup
        lsl     r0,r0,#2        @   align it
        ldr     r0,[r2,r0]      @   lookup sine val with r0 into r1
        lsl     r1,r0,#16       @   shift to left channel
        add     r0,r0,r1        @   add right channel
        ldr     r1,[r5,#0]      @   get writePos
        push    {r1}            @   push it before align
        lsl     r1,r1,#2        @   align address 4
        str     r0,[r4,r1]      @   store sine to WaveBuffer
        pop     {r1}            @   pop writepos back
        add     r1,r1,#1        @   increment array pointer writepos
        ldr     r3,=1024        @   load BUFFERSIZE compare
        cmp     r1,r3           @   skip if less than BUFFERSIZE
        bne     skip
        mov     r1,#0           @   clr writepos if >=BUFFERSIZE

    skip:
        str     r1,[r5,#0]      @   store writepos value
        add     r6,r6,#1        @   increment loop counter
        ldr     r0,=dataSize    @   get datasize counter addr
        ldr     r1,[r0,#0]      @   get val
        add     r1,r1,#1        @   increment datasize counter
        str     r1,[r0,#0]      @   store counter
        cmp     r6,#16          @   compare with 16 (i=0;i<16;i++)
        bne     outloop
        pop     {r4-r7}
        bx      lr



    .section .rodata
        sineLUT:
        @ Array goes in here. Type can be .byte, .hword or .word
        @ NOTE! No comma at the end of a line! This is important

    .word   0x0000,0x000c,0x0018,0x0024,0x0030,0x003c,0x0048,0x0054
    .word   0x0064,0x0070,0x007c,0x0088,0x0094,0x00a0,0x00ac,0x00bc
    .word   0x00c8,0x00d4,0x00e0,0x00ec,0x00f8,0x0104,0x0114,0x0120
    .word   0x012c,0x0138,0x0144,0x0150,0x015c,0x016c,0x0178,0x0184
    .word   0x0190,0x019c,0x01a8,0x01b4,0x01c4,0x01d0,0x01dc,0x01e8
    .word   0x01f4,0x0200,0x020c,0x021c,0x0228,0x0234,0x0240,0x024c
    .word

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2019-10-26
    • 2014-08-06
    相关资源
    最近更新 更多