Raspberry Pi3上的裸机金属音频输出可在AARCH64 asm上运行,但不能在C版本上运行

时间:2018-09-03 10:41:25

标签: c assembly raspberry-pi3 arm64 bare-metal

我已经尝试编写裸机内核已有一年多了,现在可以开始进行音频输出了。我已经用asm编写了代码,但是由于我不太擅长,所以我不确定如何将音频样本作为asm函数的参数传递。我试图用C重写它,但是它不起作用。这个问题确实是一个区别。我知道我的asm版本有效,但是音频示例已写入play_audio函数。我的目标是为音频创建一个不带参数的init函数,以及一个play_audio函数,该函数将指针指向音频函数的开头,并将指针指向音频文件的末尾。要播放的音频文件是16位无符号的int pcm文件。我尝试用于C音频部分的同一文件已在asm版本中成功使用。由于我将硬件pwm设置为以41400Hz的频率期望13位音频,因此可以将样本从16位转换为13位,因此这不是错误。

Not_working_audio.c

void init_audio_jack_c()//ERROR IN HERE
{
    //Set phone jack to pwm output
    uint32_t *gpio_addr = (uint32_t *)(PERIPHERAL_BASE + GPIO_BASE);
    uint32_t *gpio_gpfsel4_addr = gpio_addr + GPIO_GPFSEL4;
    *gpio_gpfsel4_addr = GPIO_FSEL0_ALT0 | GPIO_FSEL5_ALT0;

    //Set clock
    uint32_t *clock_manager_addr = (uint32_t *)(((PERIPHERAL_BASE + CM_BASE) & 0x0000FFFF) | ((PERIPHERAL_BASE + CM_BASE) & 0xFFFF0000));
    *(clock_manager_addr + CM_PWMDIV) = (CM_PASSWORD | 0x2000);

    *(clock_manager_addr + CM_PWMCTL) = ((CM_PASSWORD | CM_ENAB) | (CM_SRC_OSCILLATOR + CM_SRC_PLLCPER));

    //Set PWM
    uint32_t *pwm_manager_addr = (uint32_t *)(((PERIPHERAL_BASE + PWM_BASE) & 0x0000FFFF) | ((PERIPHERAL_BASE + PWM_BASE) & 0xFFFF0000));
    *(pwm_manager_addr + PWM_RNG1) = 0x1624;
    *(pwm_manager_addr + PWM_RNG2) = 0x1624;

    *(pwm_manager_addr + PWM_CTL) = PWM_USEF2 + PWM_PWEN2 + PWM_USEF1 + PWM_PWEN1 + PWM_CLRF1;

    printf("[INFO] Audio Init Finished");
}


int32_t play_16bit_unsigned_audio(uint16_t *start, uint16_t *end)
{
    if(end < start) 
    {
        printf("[ERROR] End is less than start.");
        return 1;
    }
    if((start - end) % 2 == 0)
    {
        printf("[ERROR] Isn't a multiple of two so it isn't 16bit");
        return 2;
    }

    uint16_t *end_of_file = (uint16_t *)(uint64_t)(((uint32_t)(uintptr_t)end & 0x0000FFFF) | ((uint32_t)(uintptr_t)end & 0xFFFF0000));

    //FIFO write
    while(start != end_of_file)
    {
        uint16_t sample = start[0];
        sample >>= 3;
        *(uint32_t *)((((uint32_t)(PERIPHERAL_BASE + PWM_BASE) & 0x0000FFFF) | ((uint32_t)(PERIPHERAL_BASE + PWM_BASE) & 0xFFFF0000)) + PWM_FIF1) = sample;

        start++;
        sample = start[0];
        sample >>= 3;
        *(uint32_t *)((((uint32_t)(PERIPHERAL_BASE + PWM_BASE) & 0x0000FFFF) | ((uint32_t)(PERIPHERAL_BASE + PWM_BASE) & 0xFFFF0000)) + PWM_FIF1) = sample;

        //FIFO wait
        while(*(uint32_t *)((((uint32_t)(PERIPHERAL_BASE + PWM_BASE) & 0x0000FFFF) | ((uint32_t)(PERIPHERAL_BASE + PWM_BASE) & 0xFFFF0000)) + PWM_STA) != PWM_FULL1);
        start++;
    }
    printf("[INFO] Completed Audio");
    return 0;
}

Working_audio.s

.section .text.init_audio_jack, "ax", %progbits
.balign 4
.globl init_audio_jack;
.type init_audio_jack, %function
init_audio_jack:
    mov w0,PERIPHERAL_BASE + GPIO_BASE
    mov w1,GPIO_FSEL0_ALT0
    orr w1,w1,GPIO_FSEL5_ALT0
    str w1,[x0,GPIO_GPFSEL4]

    // Set Clock
    mov w0, PERIPHERAL_BASE
    add w0, w0, CM_BASE
    and w0, w0, 0x0000FFFF

    mov w1, PERIPHERAL_BASE 
    add w1, w1, CM_BASE
    and w1, w1, 0xFFFF0000

    orr w0,w0,w1
    mov w1,CM_PASSWORD
    orr w1,w1,0x2000 // Bits 0..11 Fractional Part Of Divisor = 0, Bits 12..23 Integer Part Of Divisor = 2
    brk #0
    str w1,[x0,CM_PWMDIV]

    mov w1,CM_PASSWORD
    orr w1,w1,CM_ENAB
    orr w1,w1,CM_SRC_OSCILLATOR + CM_SRC_PLLCPER // Use 650MHz PLLC Clock
    str w1,[x0,CM_PWMCTL]

    // Set PWM
    mov w0, PERIPHERAL_BASE
    add w0, w0, PWM_BASE
    and w0, w0, 0x0000FFFF

    mov w1,PERIPHERAL_BASE
    add w1, w1, PWM_BASE
    and w1, w1, 0xFFFF0000

    orr w0,w0,w1
    mov w1,0x1624 // Range = 13bit 44100Hz Mono
    str w1,[x0,PWM_RNG1]
    str w1,[x0,PWM_RNG2]

    mov w1,PWM_USEF2 + PWM_PWEN2 + PWM_USEF1 + PWM_PWEN1 + PWM_CLRF1
    str w1,[x0,PWM_CTL]


.section .text.play_audio, "ax", %progbits
.balign 4
.globl play_audio;
.type play_audio, %function
play_audio:
    Loop:
        adr x1, _binary_src_audio_Interlude_bin_start // X1 = Sound Sample
        ldr w2, =_binary_src_audio_Interlude_bin_end
        and w2, w2, 0x0000FFFF // W2 = End Of Sound Sample
        ldr w3, =_binary_src_audio_Interlude_bin_end
        and w3, w3, 0xFFFF0000
        orr w2,w2,w3
        FIFO_Write:
            ldrh w3,[x1],2 // Write 2 Bytes To FIFO
            lsr w3,w3,3 // Convert 16bit To 13bit
            str w3,[x0,PWM_FIF1] // FIFO Address

            ldrh w3, [x1], 2
            lsr w3, w3, 3
            str w3, [x0, PWM_FIF1]
        FIFO_Wait:
            ldr w3,[x0,PWM_STA]
            tst w3,PWM_FULL1 // Test Bit 1 FIFO Full
            b.ne FIFO_Wait
        cmp w1,w2 // Check End Of Sound Sample
        b.ne FIFO_Write
    b Loop // Play Sample Again

在此先感谢任何可以提供帮助的人!

0 个答案:

没有答案