Skip to content

Commit

Permalink
Merge pull request #197 from BlueSCSI/SDIODelayConfig
Browse files Browse the repository at this point in the history
Configurable SDIO Clocking
  • Loading branch information
erichelgeson authored Sep 28, 2024
2 parents 58ae67e + e58d60e commit 1bf6c57
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 1 deletion.
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/[email protected]
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

0 comments on commit 1bf6c57

Please sign in to comment.