【i2s】Milk-V Duo添加speaker——max98357a解码器驱动

Success! I’ve created a userland program that uses mmap to poke the proper values as described by the pinmap spreadsheet and now I’m seeing I2S signals on the ETH TX/RX pins. Here’s the code:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

#define ETH_BASE_ADDRESS 0x03009000  // Base address of ETH registers on Duo

// Offsets for ETH registers
#define ETH_070 0x070
#define ETH_074 0x074
#define ETH_078 0x078
#define ETH_07C 0x07C
#define ETH_800 0x800
#define ETH_804 0x804
#define ETH_808 0x806

// word access macro
#define word(x) (x / sizeof(unsigned int))

int main() {
    int mem_fd;
    void *reg_map;

    // Open /dev/mem
    if ((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
        perror("can't open /dev/mem");
        return 1;
    }

    // Map registers to user space memory
    reg_map = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, ETH_BASE_ADDRESS);

    if (reg_map == MAP_FAILED) {
        perror("mmap error");
        close(mem_fd);
        return 1;
    }

    // Access ETH registers
    volatile unsigned int *eth_reg = (volatile unsigned int *)reg_map;
    unsigned int temp;

    // 0x03009804[0] = 1'b1 (rg_ephy_apb_rw_sel=1, use apb interface)
    temp = eth_reg[word(ETH_804)];
    printf("READ 804: 0x%08X\n", temp);
    temp |= 0x1;
    eth_reg[word(ETH_804)] = temp;
    printf("WRITE 804: 0x%08X\n", temp);

    // 0x03009808[4:0] = 5'b00001 (rg_ephy_pll_stable_cnt[4:0] = 5'd1 (10us))
    temp = eth_reg[word(ETH_808)];
    printf("READ 808: 0x%08X\n", temp);
    temp &= ~0x1F;
    temp |= 0x01;
    eth_reg[word(ETH_808)] = temp;
    printf("WRITE 808: 0x%08X\n", temp);

    // 0x03009800[2] = 0x0905 (rg_ephy_dig_rst_n=1, reset release, other keep default)
    temp = eth_reg[word(ETH_800)];
    printf("READ 800: 0x%08X\n", temp);
    temp = 0x0905;
    eth_reg[word(ETH_800)] = temp;
    printf("WRITE 808: 0x%08X\n", temp);
    
    // Delay 10us
    usleep(10);

    // 0x0300907C[12:8]= 5'b00101 (page_sel_mode0 = page 5)
    temp = eth_reg[word(ETH_07C)];
    printf("READ 07C: 0x%08X\n", temp);
    temp &= ~(0x1F << 8);
    temp |= (0x05 << 8);
    eth_reg[word(ETH_07C)] = temp;
    printf("WRITE 07C: 0x%08X\n", temp);
    
    // 0x03009078[11:0] = 0xF00 (set to gpio from top)
    temp = eth_reg[word(ETH_078)];
    printf("READ 078: 0x%08X\n", temp);
    temp &= ~0xFFF;
    temp |= 0xF00;
    eth_reg[word(ETH_078)] = temp;
    printf("WRITE 078: 0x%08X\n", temp);

    // 0x03009074[10:9 2:1]= 0x606 (set ephy rxp&rxm input&output enable)
    temp = eth_reg[word(ETH_074)];
    printf("READ 074: 0x%08X\n", temp);
    temp |= 0x606;
    eth_reg[word(ETH_074)] = temp;
    printf("WRITE 074: 0x%08X\n", temp);

    // 0x03009070[10:9 2:1]= 0x606 (set ephy rxp&rxm input&output enable)
    temp = eth_reg[word(ETH_070)];
    printf("READ 070: 0x%08X\n", temp);
    temp |= 0x606;
    eth_reg[word(ETH_070)] = temp;
    printf("WRITE 070: 0x%08X\n", temp);

    // Unmap memory
    munmap(reg_map, 4096);

    // Close /dev/mem
    close(mem_fd);

    return 0;
}

Just build this with the duo-examples SDK, upload it and run prior to using aplay . You can probably pull these register writes into the board_init.c code too.

4 Likes