来自C ARM嵌入式的ASM功能

Bru*_*can 5 assembly arm

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

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

Bru*_*can 2

我等了8个小时都无法回答我自己的问题吗?无论如何,这就是我得到的并且它有效!这个函数中发生了很多事情。它基本上是一个使用 LUT 来获取正弦值的正弦波振荡器。它还使用指数值表,这些值通过连接到电位器进行控制的 ADC 进行分配。有一个 32 位相位累加器,它创建一个斜坡,然后缩放该斜坡以进行查找。正弦表(我没有包含太多)是截断为 14 位表大小的 16 位值。我确信这段代码中有很多优化需要完成,但至少它让我开始了。我在该函数的每次传递中生成 16 个 48k 正弦波样本,并填充一个缓冲区,该缓冲区(在该函数之外)传输到 DMA 并通过 Discovery 板载编解码器输出。我必须说,它听起来非常流畅。到目前为止,总指令周期似乎约为 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
Run Code Online (Sandbox Code Playgroud)