Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable SDIO Clocking #197

Merged
merged 5 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/BlueSCSI_platform_RP2040/BlueSCSI_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ bool is202309a();
// This can be used to implement simultaneous transfer to SCSI bus.
typedef void (*sd_callback_t)(uint32_t bytes_complete);
void platform_set_sd_callback(sd_callback_t func, const uint8_t *buffer);
void add_extra_sdio_delay(uint16_t additional_delay);

// Reprogram firmware in main program area.
#ifndef RP2040_DISABLE_BOOTLOADER
Expand Down
41 changes: 41 additions & 0 deletions lib/BlueSCSI_platform_RP2040/rp2040_sdio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
#define SDIO_DMA_CH 4
#define SDIO_DMA_CHB 5

#define PIO_INSTR_MASK_REMOVE_DELAY 0xF8FF
#define PIO_INSTR_MASK_GET_DELAY 0x700

#define PIO_INSTR_JMP_MASK 0xE000
#define PIO_INSTR_JMP_ADDR 0x1F

// Maximum number of 512 byte blocks to transfer in one request
#define SDIO_MAX_BLOCKS 256

Expand Down Expand Up @@ -931,3 +937,38 @@ void rp2040_sdio_init(int clock_divider)
irq_set_enabled(DMA_IRQ_1, true);
#endif
}

void rp2040_sdio_update_delays(pio_program program, uint32_t offset, uint16_t additional_delay) {
//log("Offset:", offset);
uint16_t instr_to_rewrite;
uint16_t existing_delay;
for (int i = 0; i < program.length; i++) {
instr_to_rewrite = program.instructions[i];
//log("Old Instr:", i, ":", (uint32_t)instr_to_rewrite);
if (instr_to_rewrite & PIO_INSTR_MASK_GET_DELAY) { // If there's a delay, increment it. Otherwise, leave it alone.
existing_delay = (instr_to_rewrite & PIO_INSTR_MASK_GET_DELAY) >> 8;
existing_delay += additional_delay;
instr_to_rewrite = (instr_to_rewrite & PIO_INSTR_MASK_REMOVE_DELAY) | (existing_delay << 8);

// Canonicalize JMP addresses
if ((instr_to_rewrite & PIO_INSTR_JMP_MASK) == 0) { // Highest three bits are zero on a JMP
uint32_t jmp_address = instr_to_rewrite & PIO_INSTR_JMP_ADDR;
jmp_address += offset;
instr_to_rewrite = (instr_to_rewrite & (~ PIO_INSTR_JMP_ADDR)) | jmp_address;
}

//log("New Instr:", i, ":", (uint32_t)instr_to_rewrite);
SDIO_PIO->instr_mem[offset + i] = instr_to_rewrite;
}
}
}

void rp2040_sdio_delay_increment(uint16_t additional_delay) {
/*
Rewrite in-place every SDIO instruction for all the SDIO programs.
These additional delay cycles effectively decrease the SDIO clock rate, which can be helpful in electrically noisy environments.
*/
rp2040_sdio_update_delays(cmd_rsp_program, g_sdio.pio_cmd_rsp_clk_offset, additional_delay);
rp2040_sdio_update_delays(rd_data_w_clock_program, g_sdio.pio_data_rx_offset, additional_delay);
rp2040_sdio_update_delays(sdio_tx_w_clock_program, g_sdio.pio_data_tx_offset, additional_delay);
}
3 changes: 3 additions & 0 deletions lib/BlueSCSI_platform_RP2040/rp2040_sdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,6 @@ sdio_status_t receive_status_register(uint8_t* sds);

// (Re)initialize the SDIO interface
void rp2040_sdio_init(int clock_divider = 1);

// Adds extra clock delay as specified in additional_delay
void rp2040_sdio_delay_increment(uint16_t additional_delay);
4 changes: 4 additions & 0 deletions lib/BlueSCSI_platform_RP2040/sd_card_sdio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ void platform_set_sd_callback(sd_callback_t func, const uint8_t *buffer)
m_stream_count_start = 0;
}

void add_extra_sdio_delay(uint16_t additional_delay) {
rp2040_sdio_delay_increment(additional_delay);
}

static sd_callback_t get_stream_callback(const uint8_t *buf, uint32_t count, const char *accesstype, uint32_t sector)
{
m_stream_count_start = m_stream_count;
Expand Down
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ default_envs = BlueSCSI_Pico

; BlueSCSI RP2040 hardware platform, based on the Raspberry Pi foundation RP2040 microcontroller
[env:BlueSCSI_Pico]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#196d31bbafaf60b84751b1a415d8dca2365debdf
platform_packages = platformio/toolchain-gccarmnoneeabi@1.120301.0
framework-arduinopico@https://github.com/BlueSCSI/arduino-pico-internal.git#e139b9c7816602597f473b3231032cca5d71a48a
framework = arduino
Expand Down
19 changes: 19 additions & 0 deletions src/BlueSCSI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,22 @@ static void reinitSCSI()
}
}

void check_and_apply_sdio_delay() {
long add_sdio_delay = ini_getl("SDIO", "AddClockDelay", 0, CONFIGFILE);
if (add_sdio_delay) {
if (add_sdio_delay < 0) {
log("---- WARNING: Negative numbers are not valid for AddClockDelay. Setting value to 0");
return;
}
if (add_sdio_delay > 2) {
add_sdio_delay = 2;
log("---- WARNING: Max value 2 exceeded for AddClockDelay. Setting value to 2.");
}
log("INFO: Injecting ", (uint16_t)add_sdio_delay, " additional wait state(s) on SDIO");
add_extra_sdio_delay((uint16_t) add_sdio_delay);
}
}

extern "C" void bluescsi_setup(void)
{
pio_clear_instruction_memory(pio0);
Expand Down Expand Up @@ -599,6 +615,7 @@ extern "C" void bluescsi_setup(void)
{
log("SD card without filesystem!");
}
check_and_apply_sdio_delay();

print_sd_info();

Expand Down Expand Up @@ -736,10 +753,12 @@ extern "C" void bluescsi_main_loop(void)
if (g_sdcard_present)
{
log("SD card reinit succeeded");
check_and_apply_sdio_delay();
print_sd_info();

reinitSCSI();
init_logfile();
LED_OFF();
}
else if (!g_romdrive_active)
{
Expand Down