Голый металлический аудиовыход на Raspberry Pi3, работающий в AARCH64 ASM, но не в версии C - PullRequest
0 голосов
/ 03 сентября 2018

Я уже больше года пытаюсь написать голое железное ядро, и я дошел до того, что готов начать работу над выводом звука. Я написал код в asm, однако, так как я не силен в этом, я не уверен, как я могу передать аудиосэмплы в качестве аргументов функции asm. Я пытался переписать его на C, однако он не работает. Эта проблема действительно заметила разницу. Я знаю, что моя версия asm работает, но аудио образец записывается в функцию play_audio. Моя цель состоит в том, чтобы иметь функцию init для аудио без аргументов и функцию play_audio, которая принимает указатель на начало аудиофункции и указатель на конец аудиофайла. Аудиофайл для воспроизведения - это 16-битный неподписанный файл int pcm. Тот же файл, который я пытаюсь использовать для аудио части C, успешно используется в версии asm. Так как я установил аппаратный pwm для ожидания 13-битного звука на частоте 41400 Гц, есть сдвиг для преобразования семпла с 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

Заранее спасибо всем, кто может помочь!

...