From 309f2fbd2c4d5460871746a8a0becc7686760419 Mon Sep 17 00:00:00 2001 From: gullradriel <3157857+gullradriel@users.noreply.github.com> Date: Sun, 19 Nov 2023 15:08:29 +0100 Subject: [PATCH] support for a sdcard speed option (#1594) * support for a sdcard speed option * trying to link sdio_cclk_set from file * changed io to IO in checkbox text * changed order so high speed option is read after pmem is restored from sd * test button * took out unneeded comment * force behavior of test button --------- Co-authored-by: GullCode --- firmware/application/apps/ui_settings.cpp | 33 + firmware/application/apps/ui_settings.hpp | 39 +- firmware/application/ui_navigation.cpp | 3 + .../os/hal/platforms/LPC43xx/sdc_lld.c | 987 +++++++++--------- firmware/chibios/os/hal/include/hal.h | 7 +- .../common/portapack_persistent_memory.cpp | 23 +- .../common/portapack_persistent_memory.hpp | 2 + 7 files changed, 582 insertions(+), 512 deletions(-) mode change 100755 => 100644 firmware/chibios/os/hal/include/hal.h diff --git a/firmware/application/apps/ui_settings.cpp b/firmware/application/apps/ui_settings.cpp index 6facf199..7446f6ad 100644 --- a/firmware/application/apps/ui_settings.cpp +++ b/firmware/application/apps/ui_settings.cpp @@ -343,6 +343,38 @@ void SetUIView::focus() { button_save.focus(); } +/* SetSDCardView *********************************************/ + +SetSDCardView::SetSDCardView(NavigationView& nav) { + add_children({&labels, + &checkbox_sdcard_speed, + &button_test_sdcard_high_speed, + &text_sdcard_test_status, + &button_save, + &button_cancel}); + + checkbox_sdcard_speed.set_value(pmem::config_sdcard_high_speed_io()); + + button_test_sdcard_high_speed.on_select = [&nav, this](Button&) { + pmem::set_config_sdcard_high_speed_io(true, false); + text_sdcard_test_status.set("!! HIGH SPEED MODE ON !!"); + }; + + button_save.on_select = [&nav, this](Button&) { + pmem::set_config_sdcard_high_speed_io(checkbox_sdcard_speed.value(), true); + send_system_refresh(); + nav.pop(); + }; + + button_cancel.on_select = [&nav, this](Button&) { + nav.pop(); + }; +} + +void SetSDCardView::focus() { + button_save.focus(); +} + /* SetConverterSettingsView ******************************/ SetConverterSettingsView::SetConverterSettingsView(NavigationView& nav) { @@ -636,6 +668,7 @@ SettingsMenuView::SettingsMenuView(NavigationView& nav) { {"QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav]() { nav.push(); }}, {"Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav]() { nav.push(); }}, {"User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav]() { nav.push(); }}, + {"SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav]() { nav.push(); }}, }); set_max_rows(2); // allow wider buttons } diff --git a/firmware/application/apps/ui_settings.hpp b/firmware/application/apps/ui_settings.hpp index 899ec877..3473d219 100644 --- a/firmware/application/apps/ui_settings.hpp +++ b/firmware/application/apps/ui_settings.hpp @@ -306,8 +306,43 @@ class SetUIView : public View { Button button_cancel{ {16 * 8, 16 * 16, 12 * 8, 32}, - "Cancel", - }; + "Cancel"}; +}; + +class SetSDCardView : public View { + public: + SetSDCardView(NavigationView& nav); + + void focus() override; + + std::string title() const override { return "SD Card"; }; + + private: + Labels labels{ + // 01234567890123456789012345678 + {{1 * 8, 120 - 48}, " HIGH SPEED SDCARD IO ", Color::light_grey()}, + {{1 * 8, 120 - 32}, " May or may not work !! ", Color::light_grey()}}; + + Checkbox checkbox_sdcard_speed{ + {2 * 8, 120}, + 20, + "enable high speed IO"}; + + Button button_test_sdcard_high_speed{ + {2 * 8, 152, 27 * 8, 32}, + "TEST BUTTON (NO PMEM SAVE)"}; + + Text text_sdcard_test_status{ + {2 * 8, 198, 28 * 8, 16}, + ""}; + + Button button_save{ + {2 * 8, 16 * 16, 12 * 8, 32}, + "Save"}; + + Button button_cancel{ + {16 * 8, 16 * 16, 12 * 8, 32}, + "Cancel"}; }; class SetConverterSettingsView : public View { diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 60648296..b30389c1 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -171,6 +171,9 @@ SystemStatusView::SystemStatusView( pmem::load_persistent_settings_from_file(); } + // force apply of selected sdcard speed override at UI startup + pmem::set_config_sdcard_high_speed_io(pmem::config_sdcard_high_speed_io(), false); + button_back.id = -1; // Special ID used by FocusManager title.set_style(&Styles::bg_dark_grey); diff --git a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c index 8927604c..fcbb886f 100644 --- a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c +++ b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/sdc_lld.c @@ -49,11 +49,11 @@ SDCDriver SDCD1; #if LPC_SDC_USE_SDC1 static const sdio_resources_t sdio_resources = { - .base = { .clk = &LPC_CGU->BASE_SDIO_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = 0 }, - .branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_SDIO_CFG, .stat = &LPC_CCU1->CLK_M4_SDIO_STAT }, - .branch_peripheral = { .cfg = &LPC_CCU2->CLK_SDIO_CFG, .stat = &LPC_CCU2->CLK_SDIO_STAT }, - .reset = { .output_index = 20 }, - .interrupt = { .irq = SDIO_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SDC_SDIO_IRQ_PRIORITY) }, + .base = {.clk = &LPC_CGU->BASE_SDIO_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = 0}, + .branch_register_if = {.cfg = &LPC_CCU1->CLK_M4_SDIO_CFG, .stat = &LPC_CCU1->CLK_M4_SDIO_STAT}, + .branch_peripheral = {.cfg = &LPC_CCU2->CLK_SDIO_CFG, .stat = &LPC_CCU2->CLK_SDIO_STAT}, + .reset = {.output_index = 20}, + .interrupt = {.irq = SDIO_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SDC_SDIO_IRQ_PRIORITY)}, }; #endif @@ -62,44 +62,44 @@ static const sdio_resources_t sdio_resources = { /*===========================================================================*/ static bool sdio_status_command_done(void) { - return (LPC_SDMMC->RINTSTS & (1U << 2)) != 0; + return (LPC_SDMMC->RINTSTS & (1U << 2)) != 0; } static void sdio_status_command_done_clear(void) { - LPC_SDMMC->RINTSTS = (1U << 2); + LPC_SDMMC->RINTSTS = (1U << 2); } static void sdio_wait_for_command_done(void) { - while( !sdio_status_command_done() ); - sdio_status_command_done_clear(); + while (!sdio_status_command_done()) + ; + sdio_status_command_done_clear(); } static bool sdio_status_data_transfer_over(void) { - return (LPC_SDMMC->RINTSTS & (1U << 3)) != 0; + return (LPC_SDMMC->RINTSTS & (1U << 3)) != 0; } static bool sdio_status_hardware_locked_write_error(void) { - return (LPC_SDMMC->RINTSTS & (1U << 12)) != 0; + return (LPC_SDMMC->RINTSTS & (1U << 12)) != 0; } static void sdio_status_hardware_locked_write_error_clear(void) { - LPC_SDMMC->RINTSTS = (1U << 12); + LPC_SDMMC->RINTSTS = (1U << 12); } static bool sdio_status_response_error(void) { - return LPC_SDMMC->RINTSTS & ( - (1U << 1) /* RE: Response error */ - | (1U << 6) /* RCRC: Response CRC error */ - | (1U << 8) /* RTO: Response time-out error */ - ); + return LPC_SDMMC->RINTSTS & ((1U << 1) /* RE: Response error */ + | (1U << 6) /* RCRC: Response CRC error */ + | (1U << 8) /* RTO: Response time-out error */ + ); } static void sdio_status_response_error_clear(void) { - LPC_SDMMC->RINTSTS |= - (1U << 1) /* RE: Response error */ - | (1U << 6) /* RCRC: Response CRC error */ - | (1U << 8) /* RTO: Response time-out error */ - ; + LPC_SDMMC->RINTSTS |= + (1U << 1) /* RE: Response error */ + | (1U << 6) /* RCRC: Response CRC error */ + | (1U << 8) /* RTO: Response time-out error */ + ; } // static void sdio_reset_rgu(void) { @@ -122,174 +122,174 @@ static void sdio_status_response_error_clear(void) { // } static void sdio_reset_dma_and_fifo(void) { - LPC_SDMMC->CTRL |= - (1U << 1) /* FIFO */ - | (1U << 2) /* DMA */ - ; - while( LPC_SDMMC->CTRL & ((1U << 1) | (1U << 2)) ); + LPC_SDMMC->CTRL |= + (1U << 1) /* FIFO */ + | (1U << 2) /* DMA */ + ; + while (LPC_SDMMC->CTRL & ((1U << 1) | (1U << 2))) + ; } static void sdio_reset(void) { - LPC_SDMMC->BMOD = (1U << 0); + LPC_SDMMC->BMOD = (1U << 0); - LPC_SDMMC->CTRL = 0x7U; - while( LPC_SDMMC->CTRL & 0x7U ); + LPC_SDMMC->CTRL = 0x7U; + while (LPC_SDMMC->CTRL & 0x7U) + ; } static void sdio_reset_card(void) { - /* Controls SD_RST signal, for MMC4.4 cards */ - LPC_SDMMC->RST_N = 0; - halPolledDelay(10); - LPC_SDMMC->RST_N = 1; + /* Controls SD_RST signal, for MMC4.4 cards */ + LPC_SDMMC->RST_N = 0; + halPolledDelay(10); + LPC_SDMMC->RST_N = 1; } static void sdio_interrupts_set_mask(const uint32_t mask) { - LPC_SDMMC->INTMASK = mask; + LPC_SDMMC->INTMASK = mask; } static void sdio_interrupts_clear(void) { - LPC_SDMMC->RINTSTS = 0xffffffffU; + LPC_SDMMC->RINTSTS = 0xffffffffU; } static void sdio_wait_for_command_accepted(void) { - while( LPC_SDMMC->CMD & (1U << 31) ); + while (LPC_SDMMC->CMD & (1U << 31)) + ; } static void sdio_update_clock_registers_only(void) { - LPC_SDMMC->CMDARG = 0; - LPC_SDMMC->CMD = - (1U << 13) /* WAIT_PRVDATA_COMPLETE */ - | (1U << 21) /* UPDATE_CLOCK_REGISTERS_ONLY */ - | (1U << 31) /* START_CMD */ - ; - sdio_wait_for_command_accepted(); + LPC_SDMMC->CMDARG = 0; + LPC_SDMMC->CMD = + (1U << 13) /* WAIT_PRVDATA_COMPLETE */ + | (1U << 21) /* UPDATE_CLOCK_REGISTERS_ONLY */ + | (1U << 31) /* START_CMD */ + ; + sdio_wait_for_command_accepted(); } static void sdio_cclk_enable(void) { - LPC_SDMMC->CLKENA |= (1U << 0); + LPC_SDMMC->CLKENA |= (1U << 0); } static void sdio_cclk_disable(void) { - LPC_SDMMC->CLKENA &= ~(1U << 0); + LPC_SDMMC->CLKENA &= ~(1U << 0); } static void sdio_clkdiv_set( - const size_t divider_0 -) { - LPC_SDMMC->CLKDIV = ((uint32_t)divider_0 & 0xff) << 0; + const size_t divider_0) { + LPC_SDMMC->CLKDIV = ((uint32_t)divider_0 & 0xff) << 0; } static void sdio_clksrc_set(const size_t divider_index) { - LPC_SDMMC->CLKSRC = ((divider_index & 3) << 0); + LPC_SDMMC->CLKSRC = ((divider_index & 3) << 0); } -static void sdio_cclk_set(const size_t divider_value) { - /* "Before issuing a new data transfer command, the software should - * ensure that the card is not busy due to any previous data - * transfer command. Before changing the card clock frequency, the - * software must ensure that there are no data or command transfers - * in progress." - */ - /* "To avoid glitches in the card clock outputs (cclk_out), the - * software should use the following steps when changing the card - * clock frequency:" - */ - sdio_cclk_disable(); - sdio_clksrc_set(0); - sdio_update_clock_registers_only(); +void sdio_cclk_set(const size_t divider_value) { + /* "Before issuing a new data transfer command, the software should + * ensure that the card is not busy due to any previous data + * transfer command. Before changing the card clock frequency, the + * software must ensure that there are no data or command transfers + * in progress." + */ + /* "To avoid glitches in the card clock outputs (cclk_out), the + * software should use the following steps when changing the card + * clock frequency:" + */ + sdio_cclk_disable(); + sdio_clksrc_set(0); + sdio_update_clock_registers_only(); - sdio_clkdiv_set(divider_value); - sdio_update_clock_registers_only(); + sdio_clkdiv_set(divider_value); + sdio_update_clock_registers_only(); - sdio_cclk_enable(); - sdio_update_clock_registers_only(); + sdio_cclk_enable(); + sdio_update_clock_registers_only(); } static void sdio_cclk_set_400khz(void) { - sdio_cclk_set(255); + sdio_cclk_set(255); } static void sdio_cclk_set_fast(void) { #if defined(PORTAPACK_FAST_SDIO) - /* 200MHz / (2 * 2) = 50MHz */ - /* TODO: Adjust SCU pin configurations: pull-up/down, slew, glitch filter? */ - sdio_cclk_set(2); + /* 200MHz / (2 * 2) = 50MHz */ + /* TODO: Adjust SCU pin configurations: pull-up/down, slew, glitch filter? */ + sdio_cclk_set(2); #else - /* 200MHz / (2 * 4) = 25MHz */ - sdio_cclk_set(4); + /* 200MHz / (2 * 4) = 25MHz */ + sdio_cclk_set(4); #endif } static void sdio_width_set_1bit(void) { - LPC_SDMMC->CTYPE = - (0U << 0) /* CARD_WIDTH0 */ - | (0U << 16) /* CARD_WIDTH1 */ - ; + LPC_SDMMC->CTYPE = + (0U << 0) /* CARD_WIDTH0 */ + | (0U << 16) /* CARD_WIDTH1 */ + ; } static void sdio_width_set_4bit(void) { - LPC_SDMMC->CTYPE = - (1U << 0) /* CARD_WIDTH0 */ - | (0U << 16) /* CARD_WIDTH1 */ - ; + LPC_SDMMC->CTYPE = + (1U << 0) /* CARD_WIDTH0 */ + | (0U << 16) /* CARD_WIDTH1 */ + ; } static void sdio_width_set_8bit(void) { - LPC_SDMMC->CTYPE = - (0U << 0) /* CARD_WIDTH0 */ - | (1U << 16) /* CARD_WIDTH1 */ - ; + LPC_SDMMC->CTYPE = + (0U << 0) /* CARD_WIDTH0 */ + | (1U << 16) /* CARD_WIDTH1 */ + ; } static void sdio_dma_disable(void) { - LPC_SDMMC->BMOD &= ~(1U << 7); + LPC_SDMMC->BMOD &= ~(1U << 7); } static void sdio_dma_interrupts_clear(void) { - LPC_SDMMC->IDSTS = - (1U << 0) /* TI: Transmit interrupt */ - | (1U << 1) /* RI: Receive interrupt */ - | (1U << 2) /* FBE: Fatal bus error interrupt */ - | (1U << 4) /* DU: Descriptor unavailable interrupt */ - | (1U << 5) /* CES: Card error summary */ - | (1U << 8) /* NIS: Normal interrupt summary */ - | (1U << 9) /* AIS: Abnormal interrupt summary */ - ; + LPC_SDMMC->IDSTS = + (1U << 0) /* TI: Transmit interrupt */ + | (1U << 1) /* RI: Receive interrupt */ + | (1U << 2) /* FBE: Fatal bus error interrupt */ + | (1U << 4) /* DU: Descriptor unavailable interrupt */ + | (1U << 5) /* CES: Card error summary */ + | (1U << 8) /* NIS: Normal interrupt summary */ + | (1U << 9) /* AIS: Abnormal interrupt summary */ + ; } static bool_t sdc_llc_prepare_descriptors_chained(LPC_SDMMC_DESC_Type desc[], const uint32_t desc_count, const uint8_t* const buffer, uint32_t byte_count) { - const uint32_t buffer_size = LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES; - uint32_t p = (uint32_t)buffer; + const uint32_t buffer_size = LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES; + uint32_t p = (uint32_t)buffer; - for(uint32_t i=0; i buffer_size) ? buffer_size : byte_count; - desc[i].DESC2 = p; //(buffer_1_size == 0) ? 0 : p; - p += buffer_1_size; - byte_count -= buffer_1_size; + for (uint32_t i = 0; i < desc_count; i++) { + uint32_t buffer_1_size = (byte_count > buffer_size) ? buffer_size : byte_count; + desc[i].DESC2 = p; //(buffer_1_size == 0) ? 0 : p; + p += buffer_1_size; + byte_count -= buffer_1_size; - uint32_t buffer_2_size = 0; - desc[i].DESC1 = - (buffer_1_size << 0) - | (buffer_2_size << 13) - ; + uint32_t buffer_2_size = 0; + desc[i].DESC1 = + (buffer_1_size << 0) | (buffer_2_size << 13); - desc[i].DESC3 = (uint32_t)&desc[i+1]; + desc[i].DESC3 = (uint32_t)&desc[i + 1]; - const bool_t first_descriptor = (i == 0); - const bool_t last_descriptor = (byte_count == 0); - desc[i].DESC0 = - (last_descriptor ? 0 : (1U << 1)) /* Disable interrupt on completion */ - | (last_descriptor ? (1U << 2) : 0) /* Last descriptor */ - | (first_descriptor ? (1U << 3) : 0) /* First descriptor */ - | (1U << 4) /* ! Second address chained */ - | (1U << 31) /* Descriptor is owned by DMA controller */ - ; - } + const bool_t first_descriptor = (i == 0); + const bool_t last_descriptor = (byte_count == 0); + desc[i].DESC0 = + (last_descriptor ? 0 : (1U << 1)) /* Disable interrupt on completion */ + | (last_descriptor ? (1U << 2) : 0) /* Last descriptor */ + | (first_descriptor ? (1U << 3) : 0) /* First descriptor */ + | (1U << 4) /* ! Second address chained */ + | (1U << 31) /* Descriptor is owned by DMA controller */ + ; + } - return (byte_count == 0) ? CH_SUCCESS : CH_FAILED; + return (byte_count == 0) ? CH_SUCCESS : CH_FAILED; } /** @@ -303,35 +303,33 @@ static bool_t sdc_llc_prepare_descriptors_chained(LPC_SDMMC_DESC_Type desc[], * @retval CH_SUCCESS operation succeeded. * @retval CH_FAILED operation failed. */ -static bool_t sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, - uint32_t *resp) { +static bool_t sdc_lld_wait_transaction_end(SDCDriver* sdcp, uint32_t n, uint32_t* resp) { + /* Note the mask is checked before going to sleep because the interrupt + may have occurred before reaching the critical zone.*/ + chSysLock(); + if (LPC_SDMMC->INTMASK != 0) { + chDbgAssert(sdcp->thread == NULL, + "sdc_lld_start_data_transaction(), #1", "not NULL"); + sdcp->thread = chThdSelf(); + chSchGoSleepS(THD_STATE_SUSPENDED); + chDbgAssert(sdcp->thread == NULL, + "sdc_lld_start_data_transaction(), #2", "not NULL"); + } + if (!sdio_status_data_transfer_over()) { + chSysUnlock(); + return CH_FAILED; + } - /* Note the mask is checked before going to sleep because the interrupt - may have occurred before reaching the critical zone.*/ - chSysLock(); - if (LPC_SDMMC->INTMASK != 0) { - chDbgAssert(sdcp->thread == NULL, - "sdc_lld_start_data_transaction(), #1", "not NULL"); - sdcp->thread = chThdSelf(); - chSchGoSleepS(THD_STATE_SUSPENDED); - chDbgAssert(sdcp->thread == NULL, - "sdc_lld_start_data_transaction(), #2", "not NULL"); - } - if( !sdio_status_data_transfer_over() ) { + /* TODO: Check that DMA is completed? */ + + sdio_interrupts_clear(); chSysUnlock(); - return CH_FAILED; - } - /* TODO: Check that DMA is completed? */ + /* Finalize transaction.*/ + if (n > 1) + return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); - sdio_interrupts_clear(); - chSysUnlock(); - - /* Finalize transaction.*/ - if (n > 1) - return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); - - return CH_SUCCESS; + return CH_SUCCESS; } /** @@ -342,25 +340,25 @@ static bool_t sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, * * @notapi */ -static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { - uint32_t errors = SDC_NO_ERROR; +static void sdc_lld_collect_errors(SDCDriver* sdcp, uint32_t sta) { + uint32_t errors = SDC_NO_ERROR; - if (sta & (1U << 6) ) - errors |= SDC_CMD_CRC_ERROR; - if (sta & (1U << 7) ) - errors |= SDC_DATA_CRC_ERROR; - if (sta & (1U << 8) ) - errors |= SDC_COMMAND_TIMEOUT; - if (sta & (1U << 9) ) - errors |= SDC_DATA_TIMEOUT; - if (sta & (1U << 11) ) - errors |= (SDC_TX_UNDERRUN | SDC_RX_OVERRUN); - if (sta & (1U << 13) ) - errors |= SDC_STARTBIT_ERROR; - if (sta & ((1U << 10) | (1U << 12) | (1U << 15)) ) /* HTO, HLE, EBE */ - errors |= SDC_UNHANDLED_ERROR; + if (sta & (1U << 6)) + errors |= SDC_CMD_CRC_ERROR; + if (sta & (1U << 7)) + errors |= SDC_DATA_CRC_ERROR; + if (sta & (1U << 8)) + errors |= SDC_COMMAND_TIMEOUT; + if (sta & (1U << 9)) + errors |= SDC_DATA_TIMEOUT; + if (sta & (1U << 11)) + errors |= (SDC_TX_UNDERRUN | SDC_RX_OVERRUN); + if (sta & (1U << 13)) + errors |= SDC_STARTBIT_ERROR; + if (sta & ((1U << 10) | (1U << 12) | (1U << 15))) /* HTO, HLE, EBE */ + errors |= SDC_UNHANDLED_ERROR; - sdcp->errors |= errors; + sdcp->errors |= errors; } /** @@ -372,89 +370,83 @@ static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { * * @notapi */ -static void sdc_lld_error_cleanup(SDCDriver *sdcp, +static void sdc_lld_error_cleanup(SDCDriver* sdcp, uint32_t n, - uint32_t *resp) { - uint32_t sta = LPC_SDMMC->RINTSTS; + uint32_t* resp) { + uint32_t sta = LPC_SDMMC->RINTSTS; - sdio_dma_interrupts_clear(); - sdio_dma_disable(); + sdio_dma_interrupts_clear(); + sdio_dma_disable(); - sdio_interrupts_clear(); - sdio_interrupts_set_mask(0); + sdio_interrupts_clear(); + sdio_interrupts_set_mask(0); - sdc_lld_collect_errors(sdcp, sta); - if (n > 1) - sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); + sdc_lld_collect_errors(sdcp, sta); + if (n > 1) + sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp); } static bool_t sdio_send_command( - SDCDriver *sdcp, - const uint32_t cmd_and_flags, - const uint32_t arg -) { - LPC_SDMMC->CMDARG = arg; - LPC_SDMMC->CMD = - cmd_and_flags - | (1U << 13) /* WAIT_PRVDATA_COMPLETE */ - | (1U << 31) /* START_CMD */ - ; + SDCDriver* sdcp, + const uint32_t cmd_and_flags, + const uint32_t arg) { + LPC_SDMMC->CMDARG = arg; + LPC_SDMMC->CMD = + cmd_and_flags | (1U << 13) /* WAIT_PRVDATA_COMPLETE */ + | (1U << 31) /* START_CMD */ + ; - /* TODO: If waiting for command done, and not caring about HLE, why not - * just wait for command done? - * Or is it a matter of the status flags being relevant to the last - * command if we're still waiting for this one to be accepted? - */ - sdio_wait_for_command_accepted(); + /* TODO: If waiting for command done, and not caring about HLE, why not + * just wait for command done? + * Or is it a matter of the status flags being relevant to the last + * command if we're still waiting for this one to be accepted? + */ + sdio_wait_for_command_accepted(); - /* TODO: Is HLE even possible if the stack is correct? Maybe make this a - * debug-only block of code? - */ - if( sdio_status_hardware_locked_write_error() ) { - sdc_lld_collect_errors(sdcp, LPC_SDMMC->RINTSTS); - sdio_status_hardware_locked_write_error_clear(); - return CH_FAILED; - } + /* TODO: Is HLE even possible if the stack is correct? Maybe make this a + * debug-only block of code? + */ + if (sdio_status_hardware_locked_write_error()) { + sdc_lld_collect_errors(sdcp, LPC_SDMMC->RINTSTS); + sdio_status_hardware_locked_write_error_clear(); + return CH_FAILED; + } - sdio_wait_for_command_done(); + sdio_wait_for_command_done(); - /* TODO: If no response expected, why check for response errors? */ - if( sdio_status_response_error() ) { - sdc_lld_collect_errors(sdcp, LPC_SDMMC->RINTSTS); - sdio_status_response_error_clear(); - return CH_FAILED; - } + /* TODO: If no response expected, why check for response errors? */ + if (sdio_status_response_error()) { + sdc_lld_collect_errors(sdcp, LPC_SDMMC->RINTSTS); + sdio_status_response_error_clear(); + return CH_FAILED; + } - /* TODO: Clear interrupt? Wait for completion? */ - return CH_SUCCESS; + /* TODO: Clear interrupt? Wait for completion? */ + return CH_SUCCESS; } -static bool_t sdc_lld_send_cmd_data(SDCDriver *sdcp, uint32_t cmd_and_flags, - uint32_t arg, uint32_t *resp) { - (void)sdcp; +static bool_t sdc_lld_send_cmd_data(SDCDriver* sdcp, uint32_t cmd_and_flags, uint32_t arg, uint32_t* resp) { + (void)sdcp; - const uint32_t status = sdio_send_command( - sdcp, - /* RESPONSE_EXPECT | CHECK_RESPONSE_CRC | DATA_EXPECTED */ - cmd_and_flags | (1U << 6) | (1U << 8) | (1U << 9), - arg - ); + const uint32_t status = sdio_send_command( + sdcp, + /* RESPONSE_EXPECT | CHECK_RESPONSE_CRC | DATA_EXPECTED */ + cmd_and_flags | (1U << 6) | (1U << 8) | (1U << 9), + arg); - if( status == CH_SUCCESS ) { - *resp = LPC_SDMMC->RESP0; - } + if (status == CH_SUCCESS) { + *resp = LPC_SDMMC->RESP0; + } - return status; + return status; } -static bool_t sdc_lld_send_cmd_data_read(SDCDriver *sdcp, uint8_t cmd, - uint32_t arg, uint32_t *resp) { - return sdc_lld_send_cmd_data(sdcp, cmd | (0U << 10), arg, resp); +static bool_t sdc_lld_send_cmd_data_read(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) { + return sdc_lld_send_cmd_data(sdcp, cmd | (0U << 10), arg, resp); } -static bool_t sdc_lld_send_cmd_data_write(SDCDriver *sdcp, uint8_t cmd, - uint32_t arg, uint32_t *resp) { - return sdc_lld_send_cmd_data(sdcp, cmd | (1U << 10), arg, resp); +static bool_t sdc_lld_send_cmd_data_write(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) { + return sdc_lld_send_cmd_data(sdcp, cmd | (1U << 10), arg, resp); } /** @@ -471,28 +463,27 @@ static bool_t sdc_lld_send_cmd_data_write(SDCDriver *sdcp, uint8_t cmd, * * @notapi */ -static bool_t sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { +static bool_t sdc_lld_prepare_read(SDCDriver* sdcp, uint32_t startblk, uint32_t n, uint32_t* resp) { + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; + if (n > 1) { + /* Send read multiple blocks command to card.*/ + if (sdc_lld_send_cmd_data_read(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, + startblk, resp) || + MMCSD_R1_ERROR(resp[0])) + return CH_FAILED; + } else { + /* Send read single block command.*/ + if (sdc_lld_send_cmd_data_read(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK, + startblk, resp) || + MMCSD_R1_ERROR(resp[0])) + return CH_FAILED; + } - if (n > 1) { - /* Send read multiple blocks command to card.*/ - if (sdc_lld_send_cmd_data_read(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return CH_FAILED; - } - else{ - /* Send read single block command.*/ - if (sdc_lld_send_cmd_data_read(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return CH_FAILED; - } - - return CH_SUCCESS; + return CH_SUCCESS; } /** @@ -509,28 +500,27 @@ static bool_t sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, * * @notapi */ -static bool_t sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, - uint32_t n, uint32_t *resp) { +static bool_t sdc_lld_prepare_write(SDCDriver* sdcp, uint32_t startblk, uint32_t n, uint32_t* resp) { + /* Driver handles data in 512 bytes blocks (just like HC cards). But if we + have not HC card than we must convert address from blocks to bytes.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) + startblk *= MMCSD_BLOCK_SIZE; - /* Driver handles data in 512 bytes blocks (just like HC cards). But if we - have not HC card than we must convert address from blocks to bytes.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) - startblk *= MMCSD_BLOCK_SIZE; + if (n > 1) { + /* Write multiple blocks command.*/ + if (sdc_lld_send_cmd_data_write(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, + startblk, resp) || + MMCSD_R1_ERROR(resp[0])) + return CH_FAILED; + } else { + /* Write single block command.*/ + if (sdc_lld_send_cmd_data_write(sdcp, MMCSD_CMD_WRITE_BLOCK, + startblk, resp) || + MMCSD_R1_ERROR(resp[0])) + return CH_FAILED; + } - if (n > 1) { - /* Write multiple blocks command.*/ - if (sdc_lld_send_cmd_data_write(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return CH_FAILED; - } - else{ - /* Write single block command.*/ - if (sdc_lld_send_cmd_data_write(sdcp, MMCSD_CMD_WRITE_BLOCK, - startblk, resp) || MMCSD_R1_ERROR(resp[0])) - return CH_FAILED; - } - - return CH_SUCCESS; + return CH_SUCCESS; } /*===========================================================================*/ @@ -538,25 +528,25 @@ static bool_t sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, /*===========================================================================*/ CH_IRQ_HANDLER(SDIO_IRQHandler) { - CH_IRQ_PROLOGUE(); + CH_IRQ_PROLOGUE(); - /* Don't clear interrupt flags, just mask off flags to disable interrupts - * until the the handler thread can deal with them. - */ - /* TODO: Does this kill future interrupts if thread is ever NULL? In that - * case, would it be wise in that case to clear the interrupts instead of - * masking them? - */ - sdio_interrupts_set_mask(0); + /* Don't clear interrupt flags, just mask off flags to disable interrupts + * until the the handler thread can deal with them. + */ + /* TODO: Does this kill future interrupts if thread is ever NULL? In that + * case, would it be wise in that case to clear the interrupts instead of + * masking them? + */ + sdio_interrupts_set_mask(0); - chSysLockFromIsr(); - if( SDCD1.thread != NULL ) { - chSchReadyI(SDCD1.thread); - SDCD1.thread = NULL; - } - chSysUnlockFromIsr(); + chSysLockFromIsr(); + if (SDCD1.thread != NULL) { + chSchReadyI(SDCD1.thread); + SDCD1.thread = NULL; + } + chSysUnlockFromIsr(); - CH_IRQ_EPILOGUE(); + CH_IRQ_EPILOGUE(); } /*===========================================================================*/ @@ -569,14 +559,13 @@ CH_IRQ_HANDLER(SDIO_IRQHandler) { * @notapi */ void sdc_lld_init(void) { + sdcObjectInit(&SDCD1); + SDCD1.resources = &sdio_resources; + SDCD1.thread = NULL; - sdcObjectInit(&SDCD1); - SDCD1.resources = &sdio_resources; - SDCD1.thread = NULL; - - /* Assuming there's a global reset when the hardware is initialized. - */ - /* sdio_reset_rgu(); */ + /* Assuming there's a global reset when the hardware is initialized. + */ + /* sdio_reset_rgu(); */ } /** @@ -586,58 +575,56 @@ void sdc_lld_init(void) { * * @notapi */ -void sdc_lld_start(SDCDriver *sdcp) { +void sdc_lld_start(SDCDriver* sdcp) { + if (sdcp->state == BLK_STOP) { + base_clock_enable(&sdcp->resources->base); + branch_clock_enable(&sdcp->resources->branch_register_if); + branch_clock_enable(&sdcp->resources->branch_peripheral); + peripheral_reset(&sdcp->resources->reset); - if (sdcp->state == BLK_STOP) { - base_clock_enable(&sdcp->resources->base); - branch_clock_enable(&sdcp->resources->branch_register_if); - branch_clock_enable(&sdcp->resources->branch_peripheral); - peripheral_reset(&sdcp->resources->reset); + LPC_SDMMC->CLKENA = (1U << 16); /* CCLK_LOW_POWER */ - LPC_SDMMC->CLKENA = (1U << 16); /* CCLK_LOW_POWER */ + sdio_reset(); + sdio_reset_card(); - sdio_reset(); - sdio_reset_card(); + // Test jig tests: + // SAMPLE_DELAY Write Read SDC FAIL OK + // 0 OK OK OK 3 + // 2 OK OK OK 1 + // 3 OK OK OK 1 + // 4 OK f_read 1 0x2 3 2 (20170424 fails, 20170522 OK) + // 5 OK f_read 1 0x2 1 + // UM10503 recommendation: SAMPLE_DELAY=0x8, DRV_DELAY=0xF + // Datasheet recommendation: SAMPLE_DELAY=0x9, DRV_DELAY=0xD + LPC_SCU->SDDELAY = + (0x0 << 0) | (0xa << 8) /* >6ns hold with low clk/dat/cmd output drive */ + ; + LPC_SDMMC->CTRL = + (1U << 4) /* INT_ENABLE */ + | (1U << 25) /* USE_INTERNAL_DMAC */ + ; - // Test jig tests: - // SAMPLE_DELAY Write Read SDC FAIL OK - // 0 OK OK OK 3 - // 2 OK OK OK 1 - // 3 OK OK OK 1 - // 4 OK f_read 1 0x2 3 2 (20170424 fails, 20170522 OK) - // 5 OK f_read 1 0x2 1 - // UM10503 recommendation: SAMPLE_DELAY=0x8, DRV_DELAY=0xF - // Datasheet recommendation: SAMPLE_DELAY=0x9, DRV_DELAY=0xD - LPC_SCU->SDDELAY = - (0x0 << 0) - | (0xa << 8) /* >6ns hold with low clk/dat/cmd output drive */ - ; - LPC_SDMMC->CTRL = - (1U << 4) /* INT_ENABLE */ - | (1U << 25) /* USE_INTERNAL_DMAC */ - ; + const uint32_t fifo_depth = 32; + LPC_SDMMC->FIFOTH = + (((fifo_depth / 2) - 0) << 0) /* TX watermark */ + | (((fifo_depth / 2) - 1) << 16) /* RX watermark */ + | (1U << 28) /* DMA multiple transaction burst size: 4 transfers */ + ; - const uint32_t fifo_depth = 32; - LPC_SDMMC->FIFOTH = - (((fifo_depth / 2) - 0) << 0) /* TX watermark */ - | (((fifo_depth / 2) - 1) << 16) /* RX watermark */ - | ( 1U << 28) /* DMA multiple transaction burst size: 4 transfers */ - ; + LPC_SDMMC->BMOD = + (4U << 2) /* Descriptor skip length = 4 */ + | (1U << 7) /* DE: DMA Enable */ + | (1U << 8) /* Burst length = 4 */ + ; - LPC_SDMMC->BMOD = - (4U << 2) /* Descriptor skip length = 4 */ - | (1U << 7) /* DE: DMA Enable */ - | (1U << 8) /* Burst length = 4 */ - ; + sdio_cclk_set_400khz(); - sdio_cclk_set_400khz(); + /* TODO: Choose which interrupts to enable! */ + sdio_interrupts_set_mask(0); + sdio_interrupts_clear(); - /* TODO: Choose which interrupts to enable! */ - sdio_interrupts_set_mask(0); - sdio_interrupts_clear(); - - interrupt_enable(&sdcp->resources->interrupt); - } + interrupt_enable(&sdcp->resources->interrupt); + } } /** @@ -647,22 +634,21 @@ void sdc_lld_start(SDCDriver *sdcp) { * * @notapi */ -void sdc_lld_stop(SDCDriver *sdcp) { +void sdc_lld_stop(SDCDriver* sdcp) { + if (sdcp->state != BLK_STOP) { + interrupt_disable(&sdcp->resources->interrupt); - if (sdcp->state != BLK_STOP) { - interrupt_disable(&sdcp->resources->interrupt); + /* Quickest way to return peripheral and card to known (and low power) + * state is to reset both. Right? + */ + sdio_reset(); + sdio_reset_card(); - /* Quickest way to return peripheral and card to known (and low power) - * state is to reset both. Right? - */ - sdio_reset(); - sdio_reset_card(); - - peripheral_reset(&sdcp->resources->reset); - branch_clock_disable(&sdcp->resources->branch_peripheral); - branch_clock_disable(&sdcp->resources->branch_register_if); - base_clock_disable(&sdcp->resources->base); - } + peripheral_reset(&sdcp->resources->reset); + branch_clock_disable(&sdcp->resources->branch_peripheral); + branch_clock_disable(&sdcp->resources->branch_register_if); + base_clock_disable(&sdcp->resources->base); + } } /** @@ -672,11 +658,13 @@ void sdc_lld_stop(SDCDriver *sdcp) { * * @notapi */ -void sdc_lld_start_clk(SDCDriver *sdcp) { - (void)sdcp; - sdio_cclk_set_400khz(); - /* TODO: Reset card using CMD0 + init flag? */ - if (sdio_send_command(sdcp, 0 | (1U << 15), 0) != CH_SUCCESS) for(;;); +void sdc_lld_start_clk(SDCDriver* sdcp) { + (void)sdcp; + sdio_cclk_set_400khz(); + /* TODO: Reset card using CMD0 + init flag? */ + if (sdio_send_command(sdcp, 0 | (1U << 15), 0) != CH_SUCCESS) + for (;;) + ; } /** @@ -686,9 +674,9 @@ void sdc_lld_start_clk(SDCDriver *sdcp) { * * @notapi */ -void sdc_lld_set_data_clk(SDCDriver *sdcp) { - (void)sdcp; - sdio_cclk_set_fast(); +void sdc_lld_set_data_clk(SDCDriver* sdcp) { + (void)sdcp; + sdio_cclk_set_fast(); } /** @@ -698,9 +686,9 @@ void sdc_lld_set_data_clk(SDCDriver *sdcp) { * * @notapi */ -void sdc_lld_stop_clk(SDCDriver *sdcp) { - (void)sdcp; - sdio_cclk_disable(); +void sdc_lld_stop_clk(SDCDriver* sdcp) { + (void)sdcp; + sdio_cclk_disable(); } /** @@ -711,22 +699,22 @@ void sdc_lld_stop_clk(SDCDriver *sdcp) { * * @notapi */ -void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { - (void)sdcp; +void sdc_lld_set_bus_mode(SDCDriver* sdcp, sdcbusmode_t mode) { + (void)sdcp; - switch (mode) { - case SDC_MODE_1BIT: - sdio_width_set_1bit(); - break; + switch (mode) { + case SDC_MODE_1BIT: + sdio_width_set_1bit(); + break; - case SDC_MODE_4BIT: - sdio_width_set_4bit(); - break; + case SDC_MODE_4BIT: + sdio_width_set_4bit(); + break; - case SDC_MODE_8BIT: - sdio_width_set_8bit(); - break; - } + case SDC_MODE_8BIT: + sdio_width_set_8bit(); + break; + } } /** @@ -738,14 +726,14 @@ void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { * * @notapi */ -void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { - (void)sdcp; +void sdc_lld_send_cmd_none(SDCDriver* sdcp, uint8_t cmd, uint32_t arg) { + (void)sdcp; - const uint32_t status = sdio_send_command(sdcp, cmd, arg); + const uint32_t status = sdio_send_command(sdcp, cmd, arg); - if( status != CH_SUCCESS ) { - chSysHalt(); - } + if (status != CH_SUCCESS) { + chSysHalt(); + } } /** @@ -763,22 +751,20 @@ void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { * * @notapi */ -bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - (void)sdcp; +bool_t sdc_lld_send_cmd_short(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) { + (void)sdcp; - const uint32_t status = sdio_send_command( - sdcp, - /* RESPONSE_EXPECT */ - cmd | (1U << 6), - arg - ); + const uint32_t status = sdio_send_command( + sdcp, + /* RESPONSE_EXPECT */ + cmd | (1U << 6), + arg); - if( status == CH_SUCCESS ) { - *resp = LPC_SDMMC->RESP0; - } + if (status == CH_SUCCESS) { + *resp = LPC_SDMMC->RESP0; + } - return status; + return status; } /** @@ -795,22 +781,20 @@ bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, * * @notapi */ -bool_t sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - (void)sdcp; +bool_t sdc_lld_send_cmd_short_crc(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) { + (void)sdcp; - const uint32_t status = sdio_send_command( - sdcp, - /* RESPONSE_EXPECT | CHECK_RESPONSE_CRC */ - cmd | (1U << 6) | (1U << 8), - arg - ); + const uint32_t status = sdio_send_command( + sdcp, + /* RESPONSE_EXPECT | CHECK_RESPONSE_CRC */ + cmd | (1U << 6) | (1U << 8), + arg); - if( status == CH_SUCCESS ) { - *resp = LPC_SDMMC->RESP0; - } + if (status == CH_SUCCESS) { + *resp = LPC_SDMMC->RESP0; + } - return status; + return status; } /** @@ -827,25 +811,23 @@ bool_t sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, * * @notapi */ -bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, - uint32_t *resp) { - (void)sdcp; +bool_t sdc_lld_send_cmd_long_crc(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) { + (void)sdcp; - const uint32_t status = sdio_send_command( - sdcp, - /* RESPONSE_EXPECT | RESPONSE_LENGTH | CHECK_RESPONSE_CRC */ - cmd | (1U << 6) | (1U << 7) | (1U << 8), - arg - ); + const uint32_t status = sdio_send_command( + sdcp, + /* RESPONSE_EXPECT | RESPONSE_LENGTH | CHECK_RESPONSE_CRC */ + cmd | (1U << 6) | (1U << 7) | (1U << 8), + arg); - if( status == CH_SUCCESS ) { - *(resp++) = LPC_SDMMC->RESP0; - *(resp++) = LPC_SDMMC->RESP1; - *(resp++) = LPC_SDMMC->RESP2; - *(resp ) = LPC_SDMMC->RESP3; - } + if (status == CH_SUCCESS) { + *(resp++) = LPC_SDMMC->RESP0; + *(resp++) = LPC_SDMMC->RESP1; + *(resp++) = LPC_SDMMC->RESP2; + *(resp) = LPC_SDMMC->RESP3; + } - return status; + return status; } /** @@ -862,55 +844,53 @@ bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, * * @notapi */ -bool_t sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t n) { +bool_t sdc_lld_read_aligned(SDCDriver* sdcp, uint32_t startblk, uint8_t* buf, uint32_t n) { + chDbgCheck((n <= (LPC_SDC_SDIO_DESCRIPTOR_COUNT * LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES / MMCSD_BLOCK_SIZE)), "max transaction size"); - chDbgCheck((n <= (LPC_SDC_SDIO_DESCRIPTOR_COUNT * LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES / MMCSD_BLOCK_SIZE)), "max transaction size"); + /* TODO: Handle SDHC block indexing? */ - /* TODO: Handle SDHC block indexing? */ + /* Checks for errors and waits for the card to be ready for reading.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return CH_FAILED; - /* Checks for errors and waits for the card to be ready for reading.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return CH_FAILED; + sdio_reset_dma_and_fifo(); - sdio_reset_dma_and_fifo(); + /* Prepares the DMA channel for writing.*/ + LPC_SDMMC_DESC_Type desc[LPC_SDC_SDIO_DESCRIPTOR_COUNT]; + if (sdc_llc_prepare_descriptors_chained(desc, sizeof(desc) / sizeof(desc[0]), buf, n * MMCSD_BLOCK_SIZE) == TRUE) + goto error; - /* Prepares the DMA channel for writing.*/ - LPC_SDMMC_DESC_Type desc[LPC_SDC_SDIO_DESCRIPTOR_COUNT]; - if (sdc_llc_prepare_descriptors_chained(desc, sizeof(desc) / sizeof(desc[0]), buf, n * MMCSD_BLOCK_SIZE) == TRUE) - goto error; + LPC_SDMMC->DBADDR = (uint32_t)&desc; /* DMA is now armed? */ - LPC_SDMMC->DBADDR = (uint32_t)&desc; /* DMA is now armed? */ + /* Setting up data transfer.*/ + sdio_interrupts_clear(); + sdio_interrupts_set_mask( + (1U << 3) /* DTO: Data transfer over */ + | (1U << 7) /* DCRC: Data CRC error */ + | (1U << 9) /* DRTO: Data read time-out */ + | (1U << 10) /* HTO: Data starvation-by-host time-out */ + | (1U << 11) /* FRUN: FIFO underrun/overrun */ + | (1U << 13) /* SBE: Start-bit error */ + | (1U << 15) /* EBE: End-bit error / write no CRC */ + ); - /* Setting up data transfer.*/ - sdio_interrupts_clear(); - sdio_interrupts_set_mask( - (1U << 3) /* DTO: Data transfer over */ - | (1U << 7) /* DCRC: Data CRC error */ - | (1U << 9) /* DRTO: Data read time-out */ - | (1U << 10) /* HTO: Data starvation-by-host time-out */ - | (1U << 11) /* FRUN: FIFO underrun/overrun */ - | (1U << 13) /* SBE: Start-bit error */ - | (1U << 15) /* EBE: End-bit error / write no CRC */ - ); + /* TODO: Initialize once, not every time? */ + LPC_SDMMC->BLKSIZ = MMCSD_BLOCK_SIZE; - /* TODO: Initialize once, not every time? */ - LPC_SDMMC->BLKSIZ = MMCSD_BLOCK_SIZE; + LPC_SDMMC->BYTCNT = n * MMCSD_BLOCK_SIZE; - LPC_SDMMC->BYTCNT = n * MMCSD_BLOCK_SIZE; + /* Talk to card what we want from it.*/ + uint32_t resp[1]; + if (sdc_lld_prepare_read(sdcp, startblk, n, resp) == TRUE) + goto error; + if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE) + goto error; - /* Talk to card what we want from it.*/ - uint32_t resp[1]; - if (sdc_lld_prepare_read(sdcp, startblk, n, resp) == TRUE) - goto error; - if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE) - goto error; - - return CH_SUCCESS; + return CH_SUCCESS; error: - sdc_lld_error_cleanup(sdcp, n, resp); - return CH_FAILED; + sdc_lld_error_cleanup(sdcp, n, resp); + return CH_FAILED; } /** @@ -927,53 +907,51 @@ error: * * @notapi */ -bool_t sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t n) { +bool_t sdc_lld_write_aligned(SDCDriver* sdcp, uint32_t startblk, const uint8_t* buf, uint32_t n) { + chDbgCheck((n <= (LPC_SDC_SDIO_DESCRIPTOR_COUNT * LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES / MMCSD_BLOCK_SIZE)), "max transaction size"); - chDbgCheck((n <= (LPC_SDC_SDIO_DESCRIPTOR_COUNT * LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES / MMCSD_BLOCK_SIZE)), "max transaction size"); + /* Checks for errors and waits for the card to be ready for writing.*/ + if (_sdc_wait_for_transfer_state(sdcp)) + return CH_FAILED; - /* Checks for errors and waits for the card to be ready for writing.*/ - if (_sdc_wait_for_transfer_state(sdcp)) - return CH_FAILED; + sdio_reset_dma_and_fifo(); - sdio_reset_dma_and_fifo(); + /* Prepares the DMA channel for writing.*/ + LPC_SDMMC_DESC_Type desc[LPC_SDC_SDIO_DESCRIPTOR_COUNT]; + if (sdc_llc_prepare_descriptors_chained(desc, sizeof(desc) / sizeof(desc[0]), buf, n * MMCSD_BLOCK_SIZE) == TRUE) + goto error; - /* Prepares the DMA channel for writing.*/ - LPC_SDMMC_DESC_Type desc[LPC_SDC_SDIO_DESCRIPTOR_COUNT]; - if (sdc_llc_prepare_descriptors_chained(desc, sizeof(desc) / sizeof(desc[0]), buf, n * MMCSD_BLOCK_SIZE) == TRUE) - goto error; + LPC_SDMMC->DBADDR = (uint32_t)&desc; /* DMA is now armed? */ - LPC_SDMMC->DBADDR = (uint32_t)&desc; /* DMA is now armed? */ + /* Setting up data transfer.*/ + sdio_interrupts_clear(); + sdio_interrupts_set_mask( + (1U << 3) /* DTO: Data transfer over */ + | (1U << 7) /* DCRC: Data CRC error */ + | (1U << 9) /* DRTO: Data read time-out */ + | (1U << 10) /* HTO: Data starvation-by-host time-out */ + | (1U << 11) /* FRUN: FIFO underrun/overrun */ + | (1U << 13) /* SBE: Start-bit error */ + | (1U << 15) /* EBE: End-bit error / write no CRC */ + ); - /* Setting up data transfer.*/ - sdio_interrupts_clear(); - sdio_interrupts_set_mask( - (1U << 3) /* DTO: Data transfer over */ - | (1U << 7) /* DCRC: Data CRC error */ - | (1U << 9) /* DRTO: Data read time-out */ - | (1U << 10) /* HTO: Data starvation-by-host time-out */ - | (1U << 11) /* FRUN: FIFO underrun/overrun */ - | (1U << 13) /* SBE: Start-bit error */ - | (1U << 15) /* EBE: End-bit error / write no CRC */ - ); + /* TODO: Initialize once, not every time? */ + LPC_SDMMC->BLKSIZ = MMCSD_BLOCK_SIZE; - /* TODO: Initialize once, not every time? */ - LPC_SDMMC->BLKSIZ = MMCSD_BLOCK_SIZE; + LPC_SDMMC->BYTCNT = n * MMCSD_BLOCK_SIZE; - LPC_SDMMC->BYTCNT = n * MMCSD_BLOCK_SIZE; + /* Talk to card what we want from it.*/ + uint32_t resp[1]; + if (sdc_lld_prepare_write(sdcp, startblk, n, resp) == TRUE) + goto error; + if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE) + goto error; - /* Talk to card what we want from it.*/ - uint32_t resp[1]; - if (sdc_lld_prepare_write(sdcp, startblk, n, resp) == TRUE) - goto error; - if (sdc_lld_wait_transaction_end(sdcp, n, resp) == TRUE) - goto error; - - return CH_SUCCESS; + return CH_SUCCESS; error: - sdc_lld_error_cleanup(sdcp, n, resp); - return CH_FAILED; + sdc_lld_error_cleanup(sdcp, n, resp); + return CH_FAILED; } /** @@ -990,9 +968,8 @@ error: * * @notapi */ -bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t n) { - return sdc_lld_read_aligned(sdcp, startblk, buf, n); +bool_t sdc_lld_read(SDCDriver* sdcp, uint32_t startblk, uint8_t* buf, uint32_t n) { + return sdc_lld_read_aligned(sdcp, startblk, buf, n); } /** @@ -1009,9 +986,8 @@ bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, * * @notapi */ -bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t n) { - return sdc_lld_write_aligned(sdcp, startblk, buf, n); +bool_t sdc_lld_write(SDCDriver* sdcp, uint32_t startblk, const uint8_t* buf, uint32_t n) { + return sdc_lld_write_aligned(sdcp, startblk, buf, n); } /** @@ -1025,21 +1001,20 @@ bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, * * @api */ -bool_t sdc_lld_sync(SDCDriver *sdcp) { +bool_t sdc_lld_sync(SDCDriver* sdcp) { + (void)sdcp; - (void)sdcp; - - return CH_SUCCESS; + return CH_SUCCESS; } -bool_t sdc_lld_is_card_inserted(SDCDriver *sdcp) { - (void)sdcp; - return (LPC_SDMMC->CDETECT & (1U << 0)) ? FALSE : TRUE; +bool_t sdc_lld_is_card_inserted(SDCDriver* sdcp) { + (void)sdcp; + return (LPC_SDMMC->CDETECT & (1U << 0)) ? FALSE : TRUE; } -bool_t sdc_lld_is_write_protected(SDCDriver *sdcp) { - (void)sdcp; - return (LPC_SDMMC->WRTPRT & (1U << 0)) ? TRUE : FALSE; +bool_t sdc_lld_is_write_protected(SDCDriver* sdcp) { + (void)sdcp; + return (LPC_SDMMC->WRTPRT & (1U << 0)) ? TRUE : FALSE; } #endif /* HAL_USE_SDC */ diff --git a/firmware/chibios/os/hal/include/hal.h b/firmware/chibios/os/hal/include/hal.h old mode 100755 new mode 100644 index 01b0b63f..3c062cd3 --- a/firmware/chibios/os/hal/include/hal.h +++ b/firmware/chibios/os/hal/include/hal.h @@ -205,11 +205,12 @@ #ifdef __cplusplus extern "C" { #endif - void halInit(void); +void halInit(void); #if HAL_IMPLEMENTS_COUNTERS - bool_t halIsCounterWithin(halrtcnt_t start, halrtcnt_t end); - void halPolledDelay(halrtcnt_t ticks); +bool_t halIsCounterWithin(halrtcnt_t start, halrtcnt_t end); +void halPolledDelay(halrtcnt_t ticks); #endif /* HAL_IMPLEMENTS_COUNTERS */ +void sdio_cclk_set(const size_t divider_value); #ifdef __cplusplus } #endif diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 3acf263f..55294cab 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -40,6 +40,7 @@ #include #include +#include using namespace std; @@ -143,7 +144,7 @@ struct misc_config_t { bool mute_audio : 1; bool disable_speaker : 1; bool config_disable_external_tcxo : 1; - bool UNUSED_3 : 1; + bool config_sdcard_high_speed_io : 1; bool UNUSED_4 : 1; bool UNUSED_5 : 1; bool UNUSED_6 : 1; @@ -394,6 +395,8 @@ void defaults() { set_recon_update_ranges_when_recon(true); set_recon_load_hamradios(true); set_recon_match_mode(0); + + set_config_sdcard_high_speed_io(false, true); } void init() { @@ -581,6 +584,10 @@ bool config_disable_external_tcxo() { return data->misc_config.config_disable_external_tcxo; } +bool config_sdcard_high_speed_io() { + return data->misc_config.config_sdcard_high_speed_io; +} + bool stealth_mode() { return data->ui_config.stealth_mode; } @@ -646,6 +653,19 @@ void set_config_disable_external_tcxo(bool v) { data->misc_config.config_disable_external_tcxo = v; } +void set_config_sdcard_high_speed_io(bool v, bool save) { + if (v) { + /* 200MHz / (2 * 2) = 50MHz */ + /* TODO: Adjust SCU pin configurations: pull-up/down, slew, glitch filter? */ + sdio_cclk_set(2); + } else { + /* 200MHz / (2 * 4) = 25MHz */ + sdio_cclk_set(4); + } + if (save) + data->misc_config.config_sdcard_high_speed_io = v; +} + void set_stealth_mode(bool v) { data->ui_config.stealth_mode = v; } @@ -1015,6 +1035,7 @@ bool debug_dump() { pmem_dump_file.write_line("misc_config config_audio_mute: " + to_string_dec_int(config_audio_mute())); pmem_dump_file.write_line("misc_config config_speaker_disable: " + to_string_dec_int(config_speaker_disable())); pmem_dump_file.write_line("ui_config config_disable_external_tcxo: " + to_string_dec_uint(config_disable_external_tcxo())); + pmem_dump_file.write_line("ui_config config_sdcard_high_speed_io: " + to_string_dec_uint(config_sdcard_high_speed_io())); // receiver_model pmem_dump_file.write_line("\n[Receiver Model]"); diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index 84b321c7..4c5e50ee 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -174,6 +174,7 @@ uint8_t config_cpld(); void set_config_cpld(uint8_t i); bool config_disable_external_tcxo(); +bool config_sdcard_high_speed_io(); bool config_splash(); bool config_converter(); bool config_updown_converter(); @@ -193,6 +194,7 @@ void set_load_app_settings(bool v); void set_save_app_settings(bool v); void set_show_bigger_qr_code(bool v); void set_config_disable_external_tcxo(bool v); +void set_config_sdcard_high_speed_io(bool v, bool save); void set_config_splash(bool v); bool config_converter(); bool config_updown_converter();