Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

echoplayer: enable SD card using sdmmc_host

Enable pullups on SDMMC CMD/DATx lines and set output
speed to medium. Using HIGH and VERYHIGH speeds seems
to cause data corruption, with frequent CRC failures.

Change-Id: I732d19e03a2a857453755b68b6749497eafaef70

authored by

Aidan MacDonald and committed by
Solomon Peachy
6a8989f3 141b4a22

+138 -3
+1
firmware/SOURCES
··· 2038 2038 target/arm/stm32/echoplayer/clock-echoplayer.c 2039 2039 target/arm/stm32/echoplayer/lcd-echoplayer.c 2040 2040 target/arm/stm32/echoplayer/power-echoplayer.c 2041 + target/arm/stm32/echoplayer/sdmmc-echoplayer.c 2041 2042 target/arm/stm32/echoplayer/system-echoplayer.c 2042 2043 #endif 2043 2044
+3
firmware/export/config/echor1.h
··· 67 67 #define STORAGE_WANTS_ALIGN 68 68 #define STORAGE_NEEDS_BOUNCE_BUFFER 69 69 70 + /* One SD card slot */ 71 + #define SDMMC_HOST_NUM_SD_CONTROLLERS 1 72 + 70 73 /* RTC settings */ 71 74 #define CONFIG_RTC RTC_STM32H743 72 75 #define HAVE_RTC_ALARM
+14 -1
firmware/target/arm/stm32/echoplayer/clock-echoplayer.c
··· 27 27 #include "regs/stm32h743/rcc.h" 28 28 #include "regs/stm32h743/syscfg.h" 29 29 30 + #define PLL1Q_FREQ 48000000 31 + 30 32 /* Flag to use VOS0 */ 31 33 #define STM32H743_USE_VOS0 (CPU_FREQ > 400000000) 32 34 ··· 44 46 "HSE frequency not correct"); 45 47 _Static_assert(LCD_DOTCLOCK_FREQ == 6199200, 46 48 "PLL3 parameters not correct for dot clock"); 49 + _Static_assert(PLL1Q_FREQ == 48000000, 50 + "PLL1Q parameters not correct"); 47 51 48 52 /* 49 53 * Use HSE/4 input for PLL1 ··· 76 80 reg_writef(RCC_PLL1DIVR, 77 81 DIVN(80 - 1), /* 6 * 80 = 480 MHz */ 78 82 DIVP(1 - 1), /* 480 / 1 = 480 MHz */ 79 - DIVQ(8 - 1), /* 480 / 8 = 60 MHz */ 83 + DIVQ(10 - 1), /* 480 / 10 = 48 MHz */ 80 84 DIVR(1 - 1)); 81 85 82 86 reg_writef(RCC_PLL3FRACR, FRACN(1468)); ··· 159 163 160 164 static void init_periph_clock(void) 161 165 { 166 + reg_writef(RCC_D1CCIPR, SDMMCSEL_V(PLL1Q)); 162 167 reg_writef(RCC_D2CCIP1R, SPI45SEL_V(HSE)); 163 168 164 169 /* Enable AXI SRAM in sleep mode to allow DMA'ing out of it */ ··· 189 194 reg_writef(RCC_APB3LPENR, LTDCEN(enable)); 190 195 break; 191 196 197 + case STM_CLOCK_SDMMC1_KER: 198 + reg_writef(RCC_AHB3ENR, SDMMC1EN(enable)); 199 + reg_writef(RCC_AHB3LPENR, SDMMC1EN(enable)); 200 + break; 201 + 192 202 default: 193 203 panicf("%s: unsupported clock %d", __func__, (int)clock); 194 204 break; ··· 201 211 { 202 212 case STM_CLOCK_SPI5_KER: 203 213 return STM32_HSE_FREQ; 214 + 215 + case STM_CLOCK_SDMMC1_KER: 216 + return PLL1Q_FREQ; 204 217 205 218 default: 206 219 panicf("%s: unsupported clock %d", __func__, (int)clock);
+116
firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2025 by Aidan MacDonald 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #include "sdmmc_host.h" 22 + #include "sdmmc-stm32h7.h" 23 + #include "gpio-stm32h7.h" 24 + #include "nvic-arm.h" 25 + #include "regs/stm32h743/sdmmc.h" 26 + 27 + /* 300ms poll interval */ 28 + #define SDCARD_POLL_TICKS (300 * HZ / 1000) 29 + 30 + static struct sdmmc_host sdmmc1; 31 + static struct stm32h7_sdmmc_controller sdmmc1_ctl; 32 + 33 + static const struct sdmmc_controller_ops sdmmc_ops = { 34 + .set_power_enabled = stm32h7_sdmmc_set_power_enabled, 35 + .set_bus_width = stm32h7_sdmmc_set_bus_width, 36 + .set_bus_clock = stm32h7_sdmmc_set_bus_clock, 37 + .submit_command = stm32h7_sdmmc_submit_command, 38 + .abort_command = stm32h7_sdmmc_abort_command, 39 + }; 40 + 41 + static const struct sdmmc_host_config sdmmc_config INITDATA_ATTR = { 42 + .type = STORAGE_SD, 43 + .bus_voltages = SDMMC_BUS_VOLTAGE_3V2_3V3 | 44 + SDMMC_BUS_VOLTAGE_3V3_3V4, 45 + .bus_widths = SDMMC_BUS_WIDTH_1BIT | 46 + SDMMC_BUS_WIDTH_4BIT, 47 + .bus_clocks = SDMMC_BUS_CLOCK_400KHZ | 48 + SDMMC_BUS_CLOCK_25MHZ | 49 + SDMMC_BUS_CLOCK_50MHZ, 50 + .is_removable = true, 51 + }; 52 + 53 + /* 54 + * simple SD insertion poller 55 + */ 56 + struct sdmmc_poll 57 + { 58 + struct sdmmc_host *host; 59 + bool is_inserted; 60 + 61 + bool last_state; 62 + bool curr_state; 63 + }; 64 + 65 + static bool is_sdcard_inserted(void) 66 + { 67 + return gpio_get_level(GPIO_SDMMC_DETECT) == 0; 68 + } 69 + 70 + static int poll_sdcard_inserted(struct timeout *tmo) 71 + { 72 + struct sdmmc_poll *poll = (void *)tmo->data; 73 + 74 + poll->last_state = poll->curr_state; 75 + poll->curr_state = is_sdcard_inserted(); 76 + 77 + if (!poll->curr_state && poll->is_inserted) 78 + { 79 + poll->is_inserted = false; 80 + sdmmc_host_set_medium_present(poll->host, false); 81 + } 82 + else if (poll->curr_state && !poll->is_inserted && 83 + poll->curr_state == poll->last_state) 84 + { 85 + poll->is_inserted = true; 86 + sdmmc_host_set_medium_present(poll->host, true); 87 + } 88 + 89 + return SDCARD_POLL_TICKS; 90 + } 91 + 92 + static struct timeout sdcard_poll_timeout; 93 + static struct sdmmc_poll sdcard_poll; 94 + 95 + void sdmmc_host_target_init(void) 96 + { 97 + /* Initialize controller */ 98 + stm32h7_sdmmc_init(&sdmmc1_ctl, ITA_SDMMC1, STM_CLOCK_SDMMC1_KER, 99 + stm32h7_reset_sdmmc1, NULL); 100 + nvic_enable_irq(NVIC_IRQN_SDMMC1); 101 + 102 + /* Initialize card detect polling */ 103 + sdcard_poll.host = &sdmmc1; 104 + sdcard_poll.is_inserted = is_sdcard_inserted(); 105 + timeout_register(&sdcard_poll_timeout, poll_sdcard_inserted, 106 + SDCARD_POLL_TICKS, (intptr_t)&sdcard_poll); 107 + 108 + /* Initialize SD/MMC host driver */ 109 + sdmmc_host_init(&sdmmc1, &sdmmc_config, &sdmmc_ops, &sdmmc1_ctl); 110 + sdmmc_host_init_medium_present(&sdmmc1, sdcard_poll.is_inserted); 111 + } 112 + 113 + void sdmmc1_irq_handler(void) 114 + { 115 + stm32h7_sdmmc_irq_handler(&sdmmc1_ctl); 116 + }
+4 -2
firmware/target/arm/stm32/echoplayer/system-echoplayer.c
··· 32 32 #define F_ULPI GPIOF_FUNCTION(10, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) 33 33 #define F_MCO1 GPIOF_FUNCTION(0, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) 34 34 #define F_I2C1 GPIOF_FUNCTION(4, GPIO_TYPE_OPEN_DRAIN, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) 35 - #define F_SDMMC1 GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) 35 + #define F_SDMMC1 GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_UP) 36 + #define F_SDMMC1CK GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_DISABLED) 36 37 #define F_SAI1 GPIOF_FUNCTION(6, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) 37 38 #define F_SPI5 GPIOF_FUNCTION(5, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) 38 39 #define F_LCD_AF14 GPIOF_FUNCTION(14, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) ··· 93 94 /* I2C1 */ 94 95 STM_DEFPINS(GPIO_B, 0x00c0, F_I2C1), 95 96 /* SDMMC1 */ 96 - STM_DEFPINS(GPIO_C, 0x1f00, F_SDMMC1), 97 + STM_DEFPINS(GPIO_C, 0x1000, F_SDMMC1CK), 98 + STM_DEFPINS(GPIO_C, 0x0f00, F_SDMMC1), 97 99 STM_DEFPINS(GPIO_D, 0x0004, F_SDMMC1), 98 100 /* SAI1 */ 99 101 STM_DEFPINS(GPIO_E, 0x007c, F_SAI1),