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 <gullradriel@hotmail.com>
This commit is contained in:
gullradriel 2023-11-19 15:08:29 +01:00 committed by GitHub
parent 650aacfaa7
commit 309f2fbd2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 582 additions and 512 deletions

View file

@ -343,6 +343,38 @@ void SetUIView::focus() {
button_save.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::SetConverterSettingsView(NavigationView& nav) { 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<SetQRCodeView>(); }}, {"QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav]() { nav.push<SetQRCodeView>(); }},
{"Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav]() { nav.push<SetRadioView>(); }}, {"Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav]() { nav.push<SetRadioView>(); }},
{"User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav]() { nav.push<SetUIView>(); }}, {"User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav]() { nav.push<SetUIView>(); }},
{"SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav]() { nav.push<SetSDCardView>(); }},
}); });
set_max_rows(2); // allow wider buttons set_max_rows(2); // allow wider buttons
} }

View file

@ -306,8 +306,43 @@ class SetUIView : public View {
Button button_cancel{ Button button_cancel{
{16 * 8, 16 * 16, 12 * 8, 32}, {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 { class SetConverterSettingsView : public View {

View file

@ -171,6 +171,9 @@ SystemStatusView::SystemStatusView(
pmem::load_persistent_settings_from_file(); 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 button_back.id = -1; // Special ID used by FocusManager
title.set_style(&Styles::bg_dark_grey); title.set_style(&Styles::bg_dark_grey);

View file

@ -49,11 +49,11 @@ SDCDriver SDCD1;
#if LPC_SDC_USE_SDC1 #if LPC_SDC_USE_SDC1
static const sdio_resources_t sdio_resources = { static const sdio_resources_t sdio_resources = {
.base = { .clk = &LPC_CGU->BASE_SDIO_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = 0 }, .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_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 }, .branch_peripheral = {.cfg = &LPC_CCU2->CLK_SDIO_CFG, .stat = &LPC_CCU2->CLK_SDIO_STAT},
.reset = { .output_index = 20 }, .reset = {.output_index = 20},
.interrupt = { .irq = SDIO_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SDC_SDIO_IRQ_PRIORITY) }, .interrupt = {.irq = SDIO_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SDC_SDIO_IRQ_PRIORITY)},
}; };
#endif #endif
@ -70,7 +70,8 @@ static void sdio_status_command_done_clear(void) {
} }
static void sdio_wait_for_command_done(void) { static void sdio_wait_for_command_done(void) {
while( !sdio_status_command_done() ); while (!sdio_status_command_done())
;
sdio_status_command_done_clear(); sdio_status_command_done_clear();
} }
@ -87,8 +88,7 @@ static void sdio_status_hardware_locked_write_error_clear(void) {
} }
static bool sdio_status_response_error(void) { static bool sdio_status_response_error(void) {
return LPC_SDMMC->RINTSTS & ( return LPC_SDMMC->RINTSTS & ((1U << 1) /* RE: Response error */
(1U << 1) /* RE: Response error */
| (1U << 6) /* RCRC: Response CRC error */ | (1U << 6) /* RCRC: Response CRC error */
| (1U << 8) /* RTO: Response time-out error */ | (1U << 8) /* RTO: Response time-out error */
); );
@ -126,14 +126,16 @@ static void sdio_reset_dma_and_fifo(void) {
(1U << 1) /* FIFO */ (1U << 1) /* FIFO */
| (1U << 2) /* DMA */ | (1U << 2) /* DMA */
; ;
while( LPC_SDMMC->CTRL & ((1U << 1) | (1U << 2)) ); while (LPC_SDMMC->CTRL & ((1U << 1) | (1U << 2)))
;
} }
static void sdio_reset(void) { static void sdio_reset(void) {
LPC_SDMMC->BMOD = (1U << 0); LPC_SDMMC->BMOD = (1U << 0);
LPC_SDMMC->CTRL = 0x7U; LPC_SDMMC->CTRL = 0x7U;
while( LPC_SDMMC->CTRL & 0x7U ); while (LPC_SDMMC->CTRL & 0x7U)
;
} }
static void sdio_reset_card(void) { static void sdio_reset_card(void) {
@ -152,7 +154,8 @@ static void sdio_interrupts_clear(void) {
} }
static void sdio_wait_for_command_accepted(void) { 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) { static void sdio_update_clock_registers_only(void) {
@ -174,8 +177,7 @@ static void sdio_cclk_disable(void) {
} }
static void sdio_clkdiv_set( static void sdio_clkdiv_set(
const size_t divider_0 const size_t divider_0) {
) {
LPC_SDMMC->CLKDIV = ((uint32_t)divider_0 & 0xff) << 0; LPC_SDMMC->CLKDIV = ((uint32_t)divider_0 & 0xff) << 0;
} }
@ -183,7 +185,7 @@ 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) { void sdio_cclk_set(const size_t divider_value) {
/* "Before issuing a new data transfer command, the software should /* "Before issuing a new data transfer command, the software should
* ensure that the card is not busy due to any previous data * ensure that the card is not busy due to any previous data
* transfer command. Before changing the card clock frequency, the * transfer command. Before changing the card clock frequency, the
@ -264,7 +266,7 @@ static bool_t sdc_llc_prepare_descriptors_chained(LPC_SDMMC_DESC_Type desc[],
const uint32_t buffer_size = LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES; const uint32_t buffer_size = LPC_SDC_SDIO_MAX_DESCRIPTOR_BYTES;
uint32_t p = (uint32_t)buffer; uint32_t p = (uint32_t)buffer;
for(uint32_t i=0; i<desc_count; i++) { for (uint32_t i = 0; i < desc_count; i++) {
uint32_t buffer_1_size = (byte_count > buffer_size) ? buffer_size : byte_count; uint32_t buffer_1_size = (byte_count > buffer_size) ? buffer_size : byte_count;
desc[i].DESC2 = p; //(buffer_1_size == 0) ? 0 : p; desc[i].DESC2 = p; //(buffer_1_size == 0) ? 0 : p;
p += buffer_1_size; p += buffer_1_size;
@ -272,11 +274,9 @@ static bool_t sdc_llc_prepare_descriptors_chained(LPC_SDMMC_DESC_Type desc[],
uint32_t buffer_2_size = 0; uint32_t buffer_2_size = 0;
desc[i].DESC1 = desc[i].DESC1 =
(buffer_1_size << 0) (buffer_1_size << 0) | (buffer_2_size << 13);
| (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 first_descriptor = (i == 0);
const bool_t last_descriptor = (byte_count == 0); const bool_t last_descriptor = (byte_count == 0);
@ -303,9 +303,7 @@ static bool_t sdc_llc_prepare_descriptors_chained(LPC_SDMMC_DESC_Type desc[],
* @retval CH_SUCCESS operation succeeded. * @retval CH_SUCCESS operation succeeded.
* @retval CH_FAILED operation failed. * @retval CH_FAILED operation failed.
*/ */
static bool_t sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n, static bool_t sdc_lld_wait_transaction_end(SDCDriver* sdcp, uint32_t n, uint32_t* resp) {
uint32_t *resp) {
/* Note the mask is checked before going to sleep because the interrupt /* Note the mask is checked before going to sleep because the interrupt
may have occurred before reaching the critical zone.*/ may have occurred before reaching the critical zone.*/
chSysLock(); chSysLock();
@ -317,7 +315,7 @@ static bool_t sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n,
chDbgAssert(sdcp->thread == NULL, chDbgAssert(sdcp->thread == NULL,
"sdc_lld_start_data_transaction(), #2", "not NULL"); "sdc_lld_start_data_transaction(), #2", "not NULL");
} }
if( !sdio_status_data_transfer_over() ) { if (!sdio_status_data_transfer_over()) {
chSysUnlock(); chSysUnlock();
return CH_FAILED; return CH_FAILED;
} }
@ -342,22 +340,22 @@ static bool_t sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n,
* *
* @notapi * @notapi
*/ */
static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) { static void sdc_lld_collect_errors(SDCDriver* sdcp, uint32_t sta) {
uint32_t errors = SDC_NO_ERROR; uint32_t errors = SDC_NO_ERROR;
if (sta & (1U << 6) ) if (sta & (1U << 6))
errors |= SDC_CMD_CRC_ERROR; errors |= SDC_CMD_CRC_ERROR;
if (sta & (1U << 7) ) if (sta & (1U << 7))
errors |= SDC_DATA_CRC_ERROR; errors |= SDC_DATA_CRC_ERROR;
if (sta & (1U << 8) ) if (sta & (1U << 8))
errors |= SDC_COMMAND_TIMEOUT; errors |= SDC_COMMAND_TIMEOUT;
if (sta & (1U << 9) ) if (sta & (1U << 9))
errors |= SDC_DATA_TIMEOUT; errors |= SDC_DATA_TIMEOUT;
if (sta & (1U << 11) ) if (sta & (1U << 11))
errors |= (SDC_TX_UNDERRUN | SDC_RX_OVERRUN); errors |= (SDC_TX_UNDERRUN | SDC_RX_OVERRUN);
if (sta & (1U << 13) ) if (sta & (1U << 13))
errors |= SDC_STARTBIT_ERROR; errors |= SDC_STARTBIT_ERROR;
if (sta & ((1U << 10) | (1U << 12) | (1U << 15)) ) /* HTO, HLE, EBE */ if (sta & ((1U << 10) | (1U << 12) | (1U << 15))) /* HTO, HLE, EBE */
errors |= SDC_UNHANDLED_ERROR; errors |= SDC_UNHANDLED_ERROR;
sdcp->errors |= errors; sdcp->errors |= errors;
@ -372,9 +370,9 @@ static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) {
* *
* @notapi * @notapi
*/ */
static void sdc_lld_error_cleanup(SDCDriver *sdcp, static void sdc_lld_error_cleanup(SDCDriver* sdcp,
uint32_t n, uint32_t n,
uint32_t *resp) { uint32_t* resp) {
uint32_t sta = LPC_SDMMC->RINTSTS; uint32_t sta = LPC_SDMMC->RINTSTS;
sdio_dma_interrupts_clear(); sdio_dma_interrupts_clear();
@ -389,14 +387,12 @@ static void sdc_lld_error_cleanup(SDCDriver *sdcp,
} }
static bool_t sdio_send_command( static bool_t sdio_send_command(
SDCDriver *sdcp, SDCDriver* sdcp,
const uint32_t cmd_and_flags, const uint32_t cmd_and_flags,
const uint32_t arg const uint32_t arg) {
) {
LPC_SDMMC->CMDARG = arg; LPC_SDMMC->CMDARG = arg;
LPC_SDMMC->CMD = LPC_SDMMC->CMD =
cmd_and_flags cmd_and_flags | (1U << 13) /* WAIT_PRVDATA_COMPLETE */
| (1U << 13) /* WAIT_PRVDATA_COMPLETE */
| (1U << 31) /* START_CMD */ | (1U << 31) /* START_CMD */
; ;
@ -410,7 +406,7 @@ static bool_t sdio_send_command(
/* TODO: Is HLE even possible if the stack is correct? Maybe make this a /* TODO: Is HLE even possible if the stack is correct? Maybe make this a
* debug-only block of code? * debug-only block of code?
*/ */
if( sdio_status_hardware_locked_write_error() ) { if (sdio_status_hardware_locked_write_error()) {
sdc_lld_collect_errors(sdcp, LPC_SDMMC->RINTSTS); sdc_lld_collect_errors(sdcp, LPC_SDMMC->RINTSTS);
sdio_status_hardware_locked_write_error_clear(); sdio_status_hardware_locked_write_error_clear();
return CH_FAILED; return CH_FAILED;
@ -419,7 +415,7 @@ static bool_t sdio_send_command(
sdio_wait_for_command_done(); sdio_wait_for_command_done();
/* TODO: If no response expected, why check for response errors? */ /* TODO: If no response expected, why check for response errors? */
if( sdio_status_response_error() ) { if (sdio_status_response_error()) {
sdc_lld_collect_errors(sdcp, LPC_SDMMC->RINTSTS); sdc_lld_collect_errors(sdcp, LPC_SDMMC->RINTSTS);
sdio_status_response_error_clear(); sdio_status_response_error_clear();
return CH_FAILED; return CH_FAILED;
@ -429,31 +425,27 @@ static bool_t sdio_send_command(
return CH_SUCCESS; return CH_SUCCESS;
} }
static bool_t sdc_lld_send_cmd_data(SDCDriver *sdcp, uint32_t cmd_and_flags, static bool_t sdc_lld_send_cmd_data(SDCDriver* sdcp, uint32_t cmd_and_flags, uint32_t arg, uint32_t* resp) {
uint32_t arg, uint32_t *resp) {
(void)sdcp; (void)sdcp;
const uint32_t status = sdio_send_command( const uint32_t status = sdio_send_command(
sdcp, sdcp,
/* RESPONSE_EXPECT | CHECK_RESPONSE_CRC | DATA_EXPECTED */ /* RESPONSE_EXPECT | CHECK_RESPONSE_CRC | DATA_EXPECTED */
cmd_and_flags | (1U << 6) | (1U << 8) | (1U << 9), cmd_and_flags | (1U << 6) | (1U << 8) | (1U << 9),
arg arg);
);
if( status == CH_SUCCESS ) { if (status == CH_SUCCESS) {
*resp = LPC_SDMMC->RESP0; *resp = LPC_SDMMC->RESP0;
} }
return status; return status;
} }
static bool_t sdc_lld_send_cmd_data_read(SDCDriver *sdcp, uint8_t cmd, static bool_t sdc_lld_send_cmd_data_read(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) {
uint32_t arg, uint32_t *resp) {
return sdc_lld_send_cmd_data(sdcp, cmd | (0U << 10), arg, 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, static bool_t sdc_lld_send_cmd_data_write(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) {
uint32_t arg, uint32_t *resp) {
return sdc_lld_send_cmd_data(sdcp, cmd | (1U << 10), arg, resp); return sdc_lld_send_cmd_data(sdcp, cmd | (1U << 10), arg, resp);
} }
@ -471,9 +463,7 @@ static bool_t sdc_lld_send_cmd_data_write(SDCDriver *sdcp, uint8_t cmd,
* *
* @notapi * @notapi
*/ */
static bool_t sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk, static bool_t sdc_lld_prepare_read(SDCDriver* sdcp, uint32_t startblk, uint32_t n, uint32_t* resp) {
uint32_t n, uint32_t *resp) {
/* Driver handles data in 512 bytes blocks (just like HC cards). But if we /* 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.*/ have not HC card than we must convert address from blocks to bytes.*/
if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY))
@ -482,13 +472,14 @@ static bool_t sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk,
if (n > 1) { if (n > 1) {
/* Send read multiple blocks command to card.*/ /* Send read multiple blocks command to card.*/
if (sdc_lld_send_cmd_data_read(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, if (sdc_lld_send_cmd_data_read(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK,
startblk, resp) || MMCSD_R1_ERROR(resp[0])) startblk, resp) ||
MMCSD_R1_ERROR(resp[0]))
return CH_FAILED; return CH_FAILED;
} } else {
else{
/* Send read single block command.*/ /* Send read single block command.*/
if (sdc_lld_send_cmd_data_read(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK, if (sdc_lld_send_cmd_data_read(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK,
startblk, resp) || MMCSD_R1_ERROR(resp[0])) startblk, resp) ||
MMCSD_R1_ERROR(resp[0]))
return CH_FAILED; return CH_FAILED;
} }
@ -509,9 +500,7 @@ static bool_t sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk,
* *
* @notapi * @notapi
*/ */
static bool_t sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk, static bool_t sdc_lld_prepare_write(SDCDriver* sdcp, uint32_t startblk, uint32_t n, uint32_t* resp) {
uint32_t n, uint32_t *resp) {
/* Driver handles data in 512 bytes blocks (just like HC cards). But if we /* 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.*/ have not HC card than we must convert address from blocks to bytes.*/
if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY))
@ -520,13 +509,14 @@ static bool_t sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk,
if (n > 1) { if (n > 1) {
/* Write multiple blocks command.*/ /* Write multiple blocks command.*/
if (sdc_lld_send_cmd_data_write(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, if (sdc_lld_send_cmd_data_write(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK,
startblk, resp) || MMCSD_R1_ERROR(resp[0])) startblk, resp) ||
MMCSD_R1_ERROR(resp[0]))
return CH_FAILED; return CH_FAILED;
} } else {
else{
/* Write single block command.*/ /* Write single block command.*/
if (sdc_lld_send_cmd_data_write(sdcp, MMCSD_CMD_WRITE_BLOCK, if (sdc_lld_send_cmd_data_write(sdcp, MMCSD_CMD_WRITE_BLOCK,
startblk, resp) || MMCSD_R1_ERROR(resp[0])) startblk, resp) ||
MMCSD_R1_ERROR(resp[0]))
return CH_FAILED; return CH_FAILED;
} }
@ -550,7 +540,7 @@ CH_IRQ_HANDLER(SDIO_IRQHandler) {
sdio_interrupts_set_mask(0); sdio_interrupts_set_mask(0);
chSysLockFromIsr(); chSysLockFromIsr();
if( SDCD1.thread != NULL ) { if (SDCD1.thread != NULL) {
chSchReadyI(SDCD1.thread); chSchReadyI(SDCD1.thread);
SDCD1.thread = NULL; SDCD1.thread = NULL;
} }
@ -569,7 +559,6 @@ CH_IRQ_HANDLER(SDIO_IRQHandler) {
* @notapi * @notapi
*/ */
void sdc_lld_init(void) { void sdc_lld_init(void) {
sdcObjectInit(&SDCD1); sdcObjectInit(&SDCD1);
SDCD1.resources = &sdio_resources; SDCD1.resources = &sdio_resources;
SDCD1.thread = NULL; SDCD1.thread = NULL;
@ -586,8 +575,7 @@ void sdc_lld_init(void) {
* *
* @notapi * @notapi
*/ */
void sdc_lld_start(SDCDriver *sdcp) { void sdc_lld_start(SDCDriver* sdcp) {
if (sdcp->state == BLK_STOP) { if (sdcp->state == BLK_STOP) {
base_clock_enable(&sdcp->resources->base); base_clock_enable(&sdcp->resources->base);
branch_clock_enable(&sdcp->resources->branch_register_if); branch_clock_enable(&sdcp->resources->branch_register_if);
@ -609,8 +597,7 @@ void sdc_lld_start(SDCDriver *sdcp) {
// UM10503 recommendation: SAMPLE_DELAY=0x8, DRV_DELAY=0xF // UM10503 recommendation: SAMPLE_DELAY=0x8, DRV_DELAY=0xF
// Datasheet recommendation: SAMPLE_DELAY=0x9, DRV_DELAY=0xD // Datasheet recommendation: SAMPLE_DELAY=0x9, DRV_DELAY=0xD
LPC_SCU->SDDELAY = LPC_SCU->SDDELAY =
(0x0 << 0) (0x0 << 0) | (0xa << 8) /* >6ns hold with low clk/dat/cmd output drive */
| (0xa << 8) /* >6ns hold with low clk/dat/cmd output drive */
; ;
LPC_SDMMC->CTRL = LPC_SDMMC->CTRL =
(1U << 4) /* INT_ENABLE */ (1U << 4) /* INT_ENABLE */
@ -621,7 +608,7 @@ void sdc_lld_start(SDCDriver *sdcp) {
LPC_SDMMC->FIFOTH = LPC_SDMMC->FIFOTH =
(((fifo_depth / 2) - 0) << 0) /* TX watermark */ (((fifo_depth / 2) - 0) << 0) /* TX watermark */
| (((fifo_depth / 2) - 1) << 16) /* RX watermark */ | (((fifo_depth / 2) - 1) << 16) /* RX watermark */
| ( 1U << 28) /* DMA multiple transaction burst size: 4 transfers */ | (1U << 28) /* DMA multiple transaction burst size: 4 transfers */
; ;
LPC_SDMMC->BMOD = LPC_SDMMC->BMOD =
@ -647,8 +634,7 @@ void sdc_lld_start(SDCDriver *sdcp) {
* *
* @notapi * @notapi
*/ */
void sdc_lld_stop(SDCDriver *sdcp) { void sdc_lld_stop(SDCDriver* sdcp) {
if (sdcp->state != BLK_STOP) { if (sdcp->state != BLK_STOP) {
interrupt_disable(&sdcp->resources->interrupt); interrupt_disable(&sdcp->resources->interrupt);
@ -672,11 +658,13 @@ void sdc_lld_stop(SDCDriver *sdcp) {
* *
* @notapi * @notapi
*/ */
void sdc_lld_start_clk(SDCDriver *sdcp) { void sdc_lld_start_clk(SDCDriver* sdcp) {
(void)sdcp; (void)sdcp;
sdio_cclk_set_400khz(); sdio_cclk_set_400khz();
/* TODO: Reset card using CMD0 + init flag? */ /* TODO: Reset card using CMD0 + init flag? */
if (sdio_send_command(sdcp, 0 | (1U << 15), 0) != CH_SUCCESS) for(;;); if (sdio_send_command(sdcp, 0 | (1U << 15), 0) != CH_SUCCESS)
for (;;)
;
} }
/** /**
@ -686,7 +674,7 @@ void sdc_lld_start_clk(SDCDriver *sdcp) {
* *
* @notapi * @notapi
*/ */
void sdc_lld_set_data_clk(SDCDriver *sdcp) { void sdc_lld_set_data_clk(SDCDriver* sdcp) {
(void)sdcp; (void)sdcp;
sdio_cclk_set_fast(); sdio_cclk_set_fast();
} }
@ -698,7 +686,7 @@ void sdc_lld_set_data_clk(SDCDriver *sdcp) {
* *
* @notapi * @notapi
*/ */
void sdc_lld_stop_clk(SDCDriver *sdcp) { void sdc_lld_stop_clk(SDCDriver* sdcp) {
(void)sdcp; (void)sdcp;
sdio_cclk_disable(); sdio_cclk_disable();
} }
@ -711,7 +699,7 @@ void sdc_lld_stop_clk(SDCDriver *sdcp) {
* *
* @notapi * @notapi
*/ */
void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) { void sdc_lld_set_bus_mode(SDCDriver* sdcp, sdcbusmode_t mode) {
(void)sdcp; (void)sdcp;
switch (mode) { switch (mode) {
@ -738,12 +726,12 @@ void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) {
* *
* @notapi * @notapi
*/ */
void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) { void sdc_lld_send_cmd_none(SDCDriver* sdcp, uint8_t cmd, uint32_t arg) {
(void)sdcp; (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 ) { if (status != CH_SUCCESS) {
chSysHalt(); chSysHalt();
} }
} }
@ -763,18 +751,16 @@ void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) {
* *
* @notapi * @notapi
*/ */
bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, bool_t sdc_lld_send_cmd_short(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) {
uint32_t *resp) {
(void)sdcp; (void)sdcp;
const uint32_t status = sdio_send_command( const uint32_t status = sdio_send_command(
sdcp, sdcp,
/* RESPONSE_EXPECT */ /* RESPONSE_EXPECT */
cmd | (1U << 6), cmd | (1U << 6),
arg arg);
);
if( status == CH_SUCCESS ) { if (status == CH_SUCCESS) {
*resp = LPC_SDMMC->RESP0; *resp = LPC_SDMMC->RESP0;
} }
@ -795,18 +781,16 @@ bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
* *
* @notapi * @notapi
*/ */
bool_t sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, bool_t sdc_lld_send_cmd_short_crc(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) {
uint32_t *resp) {
(void)sdcp; (void)sdcp;
const uint32_t status = sdio_send_command( const uint32_t status = sdio_send_command(
sdcp, sdcp,
/* RESPONSE_EXPECT | CHECK_RESPONSE_CRC */ /* RESPONSE_EXPECT | CHECK_RESPONSE_CRC */
cmd | (1U << 6) | (1U << 8), cmd | (1U << 6) | (1U << 8),
arg arg);
);
if( status == CH_SUCCESS ) { if (status == CH_SUCCESS) {
*resp = LPC_SDMMC->RESP0; *resp = LPC_SDMMC->RESP0;
} }
@ -827,22 +811,20 @@ bool_t sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
* *
* @notapi * @notapi
*/ */
bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg, bool_t sdc_lld_send_cmd_long_crc(SDCDriver* sdcp, uint8_t cmd, uint32_t arg, uint32_t* resp) {
uint32_t *resp) {
(void)sdcp; (void)sdcp;
const uint32_t status = sdio_send_command( const uint32_t status = sdio_send_command(
sdcp, sdcp,
/* RESPONSE_EXPECT | RESPONSE_LENGTH | CHECK_RESPONSE_CRC */ /* RESPONSE_EXPECT | RESPONSE_LENGTH | CHECK_RESPONSE_CRC */
cmd | (1U << 6) | (1U << 7) | (1U << 8), cmd | (1U << 6) | (1U << 7) | (1U << 8),
arg arg);
);
if( status == CH_SUCCESS ) { if (status == CH_SUCCESS) {
*(resp++) = LPC_SDMMC->RESP0; *(resp++) = LPC_SDMMC->RESP0;
*(resp++) = LPC_SDMMC->RESP1; *(resp++) = LPC_SDMMC->RESP1;
*(resp++) = LPC_SDMMC->RESP2; *(resp++) = LPC_SDMMC->RESP2;
*(resp ) = LPC_SDMMC->RESP3; *(resp) = LPC_SDMMC->RESP3;
} }
return status; return status;
@ -862,9 +844,7 @@ bool_t sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
* *
* @notapi * @notapi
*/ */
bool_t sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk, bool_t sdc_lld_read_aligned(SDCDriver* sdcp, uint32_t startblk, uint8_t* buf, uint32_t n) {
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? */
@ -927,9 +907,7 @@ error:
* *
* @notapi * @notapi
*/ */
bool_t sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk, bool_t sdc_lld_write_aligned(SDCDriver* sdcp, uint32_t startblk, const uint8_t* buf, uint32_t n) {
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.*/ /* Checks for errors and waits for the card to be ready for writing.*/
@ -990,8 +968,7 @@ error:
* *
* @notapi * @notapi
*/ */
bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk, bool_t sdc_lld_read(SDCDriver* sdcp, uint32_t startblk, uint8_t* buf, uint32_t n) {
uint8_t *buf, uint32_t n) {
return sdc_lld_read_aligned(sdcp, startblk, buf, n); return sdc_lld_read_aligned(sdcp, startblk, buf, n);
} }
@ -1009,8 +986,7 @@ bool_t sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
* *
* @notapi * @notapi
*/ */
bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk, bool_t sdc_lld_write(SDCDriver* sdcp, uint32_t startblk, const uint8_t* buf, uint32_t n) {
const uint8_t *buf, uint32_t n) {
return sdc_lld_write_aligned(sdcp, startblk, buf, n); return sdc_lld_write_aligned(sdcp, startblk, buf, n);
} }
@ -1025,19 +1001,18 @@ bool_t sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
* *
* @api * @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) { bool_t sdc_lld_is_card_inserted(SDCDriver* sdcp) {
(void)sdcp; (void)sdcp;
return (LPC_SDMMC->CDETECT & (1U << 0)) ? FALSE : TRUE; return (LPC_SDMMC->CDETECT & (1U << 0)) ? FALSE : TRUE;
} }
bool_t sdc_lld_is_write_protected(SDCDriver *sdcp) { bool_t sdc_lld_is_write_protected(SDCDriver* sdcp) {
(void)sdcp; (void)sdcp;
return (LPC_SDMMC->WRTPRT & (1U << 0)) ? TRUE : FALSE; return (LPC_SDMMC->WRTPRT & (1U << 0)) ? TRUE : FALSE;
} }

7
firmware/chibios/os/hal/include/hal.h Executable file → Normal file
View file

@ -205,11 +205,12 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void halInit(void); void halInit(void);
#if HAL_IMPLEMENTS_COUNTERS #if HAL_IMPLEMENTS_COUNTERS
bool_t halIsCounterWithin(halrtcnt_t start, halrtcnt_t end); bool_t halIsCounterWithin(halrtcnt_t start, halrtcnt_t end);
void halPolledDelay(halrtcnt_t ticks); void halPolledDelay(halrtcnt_t ticks);
#endif /* HAL_IMPLEMENTS_COUNTERS */ #endif /* HAL_IMPLEMENTS_COUNTERS */
void sdio_cclk_set(const size_t divider_value);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -40,6 +40,7 @@
#include <utility> #include <utility>
#include <ch.h> #include <ch.h>
#include <hal.h>
using namespace std; using namespace std;
@ -143,7 +144,7 @@ struct misc_config_t {
bool mute_audio : 1; bool mute_audio : 1;
bool disable_speaker : 1; bool disable_speaker : 1;
bool config_disable_external_tcxo : 1; bool config_disable_external_tcxo : 1;
bool UNUSED_3 : 1; bool config_sdcard_high_speed_io : 1;
bool UNUSED_4 : 1; bool UNUSED_4 : 1;
bool UNUSED_5 : 1; bool UNUSED_5 : 1;
bool UNUSED_6 : 1; bool UNUSED_6 : 1;
@ -394,6 +395,8 @@ void defaults() {
set_recon_update_ranges_when_recon(true); set_recon_update_ranges_when_recon(true);
set_recon_load_hamradios(true); set_recon_load_hamradios(true);
set_recon_match_mode(0); set_recon_match_mode(0);
set_config_sdcard_high_speed_io(false, true);
} }
void init() { void init() {
@ -581,6 +584,10 @@ bool config_disable_external_tcxo() {
return data->misc_config.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() { bool stealth_mode() {
return data->ui_config.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; 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) { void set_stealth_mode(bool v) {
data->ui_config.stealth_mode = 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_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("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_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 // receiver_model
pmem_dump_file.write_line("\n[Receiver Model]"); pmem_dump_file.write_line("\n[Receiver Model]");

View file

@ -174,6 +174,7 @@ uint8_t config_cpld();
void set_config_cpld(uint8_t i); void set_config_cpld(uint8_t i);
bool config_disable_external_tcxo(); bool config_disable_external_tcxo();
bool config_sdcard_high_speed_io();
bool config_splash(); bool config_splash();
bool config_converter(); bool config_converter();
bool config_updown_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_save_app_settings(bool v);
void set_show_bigger_qr_code(bool v); void set_show_bigger_qr_code(bool v);
void set_config_disable_external_tcxo(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); void set_config_splash(bool v);
bool config_converter(); bool config_converter();
bool config_updown_converter(); bool config_updown_converter();