Add psram support
it seems to be a tad slower but what do you want....!
This commit is contained in:
parent
bcb13e295a
commit
9fb0ec8f60
2 changed files with 208 additions and 20 deletions
|
|
@ -55,6 +55,9 @@ set(HSTX_D2P 18 CACHE STRING "HSTX D2+ PIN")
|
|||
option(USE_VGA_RES "Video uses VGA (640x480) resolution" OFF)
|
||||
set(VIDEO_PIN 18 CACHE STRING "VGA Video GPIO base pin (followed by VS, CLK, HS)")
|
||||
|
||||
option(USE_PSRAM "Locate main Mac ram in PSRAM (only for rp2350 / pico 2)" OFF)
|
||||
set(PSRAM_CS 47 CACHE STRING "PSRAM Chip select pin")
|
||||
|
||||
# Pins for PIO-based USB host
|
||||
set(PIN_USB_HOST_DP 1 CACHE STRING "USB D+ PIN")
|
||||
set(PIN_USB_HOST_DM 2 CACHE STRING "USB D- PIN")
|
||||
|
|
@ -123,8 +126,6 @@ else()
|
|||
|
||||
add_compile_definitions(GPIO_VID_BASE=${VIDEO_PIN})
|
||||
set(VIDEO_SRC src/video_vga.c)
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
add_compile_definitions(PIN_USB_HOST_DP=${PIN_USB_HOST_DP})
|
||||
|
|
@ -132,6 +133,12 @@ add_compile_definitions(PIN_USB_HOST_DM=${PIN_USB_HOST_DM})
|
|||
add_compile_definitions(PICO_DEFAULT_PIO_USB_DP_PIN=${PIN_USB_HOST_DP})
|
||||
add_compile_definitions(PICO_DEFAULT_PIO_USB_DM_PIN=${PIN_USB_HOST_DM})
|
||||
|
||||
if (USE_PSRAM)
|
||||
add_compile_definitions(PIN_PSRAM_CS=${PSRAM_CS} USE_PSRAM=1)
|
||||
else()
|
||||
add_compile_definitions(USE_PSRAM=0)
|
||||
endif()
|
||||
|
||||
if (TARGET tinyusb_device)
|
||||
add_executable(firmware
|
||||
src/main.c
|
||||
|
|
|
|||
193
src/main.c
193
src/main.c
|
|
@ -53,6 +53,10 @@
|
|||
#include "hw_config.h"
|
||||
#endif
|
||||
|
||||
#if USE_PSRAM
|
||||
#include "hardware/structs/qmi.h"
|
||||
#include "hardware/structs/xip.h"
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Imports and data
|
||||
|
||||
|
|
@ -69,7 +73,12 @@ static const uint8_t umac_rom[] = {
|
|||
#include "umac-rom.h"
|
||||
};
|
||||
|
||||
#if USE_PSRAM
|
||||
static uint32_t umac_framebuffer_mirror[640*480/32];
|
||||
#define umac_ram ((uint8_t*)0x15000000)
|
||||
#else
|
||||
static uint8_t umac_ram[RAM_SIZE];
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -97,6 +106,27 @@ static int umac_cursor_x = 0;
|
|||
static int umac_cursor_y = 0;
|
||||
static int umac_cursor_button = 0;
|
||||
|
||||
#if USE_PSRAM
|
||||
static void copy_framebuffer() {
|
||||
#if DISP_WIDTH==640 && DISP_HEIGHT==480
|
||||
uint32_t *src = (uint32_t*)(umac_ram + umac_get_fb_offset()), *dest = umac_framebuffer_mirror;
|
||||
for(int i=0; i<640*480/32; i++) {
|
||||
*dest++ = *src++ ^ 0xfffffffful;
|
||||
}
|
||||
#elif DISP_WIDTH==512 && DISP_HEIGHT==384
|
||||
uint32_t *src = umac_ram + umac_get_fb_offset();
|
||||
for(i=0; i<384; i++) {
|
||||
uint32_t *dest = umac_framebuffer_mirror + 962 + 20 * i;
|
||||
for(j=0; j<16; i++) {
|
||||
*dest++ = *src++ ^ 0xfffffffful;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error Unsupported display geometry
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void poll_umac()
|
||||
{
|
||||
static absolute_time_t last_1hz = 0;
|
||||
|
|
@ -108,6 +138,9 @@ static void poll_umac()
|
|||
int64_t p_1hz = absolute_time_diff_us(last_1hz, now);
|
||||
int64_t p_vsync = absolute_time_diff_us(last_vsync, now);
|
||||
if (p_vsync >= 16667) {
|
||||
#if USE_PSRAM
|
||||
copy_framebuffer();
|
||||
#endif
|
||||
/* FIXME: Trigger this off actual vsync */
|
||||
umac_vsync_event();
|
||||
last_vsync = now;
|
||||
|
|
@ -251,11 +284,16 @@ static void core1_main()
|
|||
printf("Core 1 started\n");
|
||||
disc_setup(discs);
|
||||
|
||||
#if USE_PSRAM
|
||||
umac_init(umac_ram, (void *)umac_rom, discs);
|
||||
video_init((uint32_t *)(umac_framebuffer_mirror));
|
||||
#else
|
||||
umac_init(umac_ram, (void *)umac_rom, discs);
|
||||
/* Video runs on core 1, i.e. IRQs/DMA are unaffected by
|
||||
* core 0's USB activity.
|
||||
*/
|
||||
video_init((uint32_t *)(umac_ram + umac_get_fb_offset()));
|
||||
#endif
|
||||
|
||||
printf("Enjoyable Mac times now begin:\n\n");
|
||||
|
||||
|
|
@ -264,10 +302,155 @@ static void core1_main()
|
|||
}
|
||||
}
|
||||
|
||||
size_t psram_size;
|
||||
|
||||
size_t _psram_size;
|
||||
static void __no_inline_not_in_flash_func(setup_psram)(void) {
|
||||
_psram_size = 0;
|
||||
#if USE_PSRAM
|
||||
gpio_set_function(PIN_PSRAM_CS, GPIO_FUNC_XIP_CS1);
|
||||
uint32_t save = save_and_disable_interrupts();
|
||||
// Try and read the PSRAM ID via direct_csr.
|
||||
qmi_hw->direct_csr = 30 << QMI_DIRECT_CSR_CLKDIV_LSB |
|
||||
QMI_DIRECT_CSR_EN_BITS;
|
||||
// Need to poll for the cooldown on the last XIP transfer to expire
|
||||
// (via direct-mode BUSY flag) before it is safe to perform the first
|
||||
// direct-mode operation
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
|
||||
// Exit out of QMI in case we've inited already
|
||||
qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
|
||||
// Transmit as quad.
|
||||
qmi_hw->direct_tx = QMI_DIRECT_TX_OE_BITS |
|
||||
QMI_DIRECT_TX_IWIDTH_VALUE_Q << QMI_DIRECT_TX_IWIDTH_LSB |
|
||||
0xf5;
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
(void)qmi_hw->direct_rx;
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS);
|
||||
|
||||
// Read the id
|
||||
qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
|
||||
uint8_t kgd = 0;
|
||||
uint8_t eid = 0;
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
if (i == 0) {
|
||||
qmi_hw->direct_tx = 0x9f;
|
||||
} else {
|
||||
qmi_hw->direct_tx = 0xff;
|
||||
}
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_TXEMPTY_BITS) == 0) {
|
||||
}
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
if (i == 5) {
|
||||
kgd = qmi_hw->direct_rx;
|
||||
} else if (i == 6) {
|
||||
eid = qmi_hw->direct_rx;
|
||||
} else {
|
||||
(void)qmi_hw->direct_rx;
|
||||
}
|
||||
}
|
||||
// Disable direct csr.
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS | QMI_DIRECT_CSR_EN_BITS);
|
||||
|
||||
if (kgd != 0x5D) {
|
||||
restore_interrupts(save);
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable quad mode.
|
||||
qmi_hw->direct_csr = 30 << QMI_DIRECT_CSR_CLKDIV_LSB |
|
||||
QMI_DIRECT_CSR_EN_BITS;
|
||||
// Need to poll for the cooldown on the last XIP transfer to expire
|
||||
// (via direct-mode BUSY flag) before it is safe to perform the first
|
||||
// direct-mode operation
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
|
||||
// RESETEN, RESET and quad enable
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
|
||||
if (i == 0) {
|
||||
qmi_hw->direct_tx = 0x66;
|
||||
} else if (i == 1) {
|
||||
qmi_hw->direct_tx = 0x99;
|
||||
} else {
|
||||
qmi_hw->direct_tx = 0x35;
|
||||
}
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS);
|
||||
for (size_t j = 0; j < 20; j++) {
|
||||
asm ("nop");
|
||||
}
|
||||
(void)qmi_hw->direct_rx;
|
||||
}
|
||||
// Disable direct csr.
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS | QMI_DIRECT_CSR_EN_BITS);
|
||||
|
||||
qmi_hw->m[1].timing =
|
||||
QMI_M0_TIMING_PAGEBREAK_VALUE_1024 << QMI_M0_TIMING_PAGEBREAK_LSB | // Break between pages.
|
||||
3 << QMI_M0_TIMING_SELECT_HOLD_LSB | // Delay releasing CS for 3 extra system cycles.
|
||||
1 << QMI_M0_TIMING_COOLDOWN_LSB |
|
||||
1 << QMI_M0_TIMING_RXDELAY_LSB |
|
||||
16 << QMI_M0_TIMING_MAX_SELECT_LSB | // In units of 64 system clock cycles. PSRAM says 8us max. 8 / 0.00752 / 64 = 16.62
|
||||
7 << QMI_M0_TIMING_MIN_DESELECT_LSB | // In units of system clock cycles. PSRAM says 50ns.50 / 7.52 = 6.64
|
||||
2 << QMI_M0_TIMING_CLKDIV_LSB;
|
||||
qmi_hw->m[1].rfmt = (QMI_M0_RFMT_PREFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_PREFIX_WIDTH_LSB |
|
||||
QMI_M0_RFMT_ADDR_WIDTH_VALUE_Q << QMI_M0_RFMT_ADDR_WIDTH_LSB |
|
||||
QMI_M0_RFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_SUFFIX_WIDTH_LSB |
|
||||
QMI_M0_RFMT_DUMMY_WIDTH_VALUE_Q << QMI_M0_RFMT_DUMMY_WIDTH_LSB |
|
||||
QMI_M0_RFMT_DUMMY_LEN_VALUE_24 << QMI_M0_RFMT_DUMMY_LEN_LSB |
|
||||
QMI_M0_RFMT_DATA_WIDTH_VALUE_Q << QMI_M0_RFMT_DATA_WIDTH_LSB |
|
||||
QMI_M0_RFMT_PREFIX_LEN_VALUE_8 << QMI_M0_RFMT_PREFIX_LEN_LSB |
|
||||
QMI_M0_RFMT_SUFFIX_LEN_VALUE_NONE << QMI_M0_RFMT_SUFFIX_LEN_LSB);
|
||||
qmi_hw->m[1].rcmd = 0xeb << QMI_M0_RCMD_PREFIX_LSB |
|
||||
0 << QMI_M0_RCMD_SUFFIX_LSB;
|
||||
qmi_hw->m[1].wfmt = (QMI_M0_WFMT_PREFIX_WIDTH_VALUE_Q << QMI_M0_WFMT_PREFIX_WIDTH_LSB |
|
||||
QMI_M0_WFMT_ADDR_WIDTH_VALUE_Q << QMI_M0_WFMT_ADDR_WIDTH_LSB |
|
||||
QMI_M0_WFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M0_WFMT_SUFFIX_WIDTH_LSB |
|
||||
QMI_M0_WFMT_DUMMY_WIDTH_VALUE_Q << QMI_M0_WFMT_DUMMY_WIDTH_LSB |
|
||||
QMI_M0_WFMT_DUMMY_LEN_VALUE_NONE << QMI_M0_WFMT_DUMMY_LEN_LSB |
|
||||
QMI_M0_WFMT_DATA_WIDTH_VALUE_Q << QMI_M0_WFMT_DATA_WIDTH_LSB |
|
||||
QMI_M0_WFMT_PREFIX_LEN_VALUE_8 << QMI_M0_WFMT_PREFIX_LEN_LSB |
|
||||
QMI_M0_WFMT_SUFFIX_LEN_VALUE_NONE << QMI_M0_WFMT_SUFFIX_LEN_LSB);
|
||||
qmi_hw->m[1].wcmd = 0x38 << QMI_M0_WCMD_PREFIX_LSB |
|
||||
0 << QMI_M0_WCMD_SUFFIX_LSB;
|
||||
|
||||
restore_interrupts(save);
|
||||
|
||||
_psram_size = 1024 * 1024; // 1 MiB
|
||||
uint8_t size_id = eid >> 5;
|
||||
if (eid == 0x26 || size_id == 2) {
|
||||
_psram_size *= 8;
|
||||
} else if (size_id == 0) {
|
||||
_psram_size *= 2;
|
||||
} else if (size_id == 1) {
|
||||
_psram_size *= 4;
|
||||
}
|
||||
|
||||
// Mark that we can write to PSRAM.
|
||||
xip_ctrl_hw->ctrl |= XIP_CTRL_WRITABLE_M1_BITS;
|
||||
|
||||
// Test write to the PSRAM.
|
||||
volatile uint32_t *psram_nocache = (volatile uint32_t *)0x15000000;
|
||||
psram_nocache[0] = 0x12345678;
|
||||
volatile uint32_t readback = psram_nocache[0];
|
||||
if (readback != 0x12345678) {
|
||||
_psram_size = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// set_sys_clock_khz(250*1000, true);
|
||||
|
||||
setup_psram();
|
||||
|
||||
stdio_init_all();
|
||||
io_init();
|
||||
|
||||
|
|
@ -278,17 +461,15 @@ int main()
|
|||
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
|
||||
pio_cfg.tx_ch = 2;
|
||||
pio_cfg.pin_dp = PICO_DEFAULT_PIO_USB_DP_PIN;
|
||||
_Static_assert(PIN_USB_HOST_DP + 1 == PIN_USB_HOST_DM || PIN_USB_HOST_DP - 1 == PIN_USB_HOST_DM, "Permitted USB D+/D- configuration");
|
||||
pio_cfg.pinout = PIN_USB_HOST_DP + 1 == PIN_USB_HOST_DM ? PIO_USB_PINOUT_DPDM : PIO_USB_PINOUT_DMDP;
|
||||
|
||||
//#ifdef PICO_DEFAULT_PIO_USB_VBUSEN_PIN
|
||||
#ifdef PICO_DEFAULT_PIO_USB_VBUSEN_PIN
|
||||
gpio_init(PICO_DEFAULT_PIO_USB_VBUSEN_PIN);
|
||||
gpio_set_dir(PICO_DEFAULT_PIO_USB_VBUSEN_PIN, GPIO_OUT);
|
||||
gpio_put(PICO_DEFAULT_PIO_USB_VBUSEN_PIN, PICO_DEFAULT_PIO_USB_VBUSEN_STATE);
|
||||
//#endif
|
||||
|
||||
#if 0
|
||||
_Static_assert(PIN_USB_HOST_DP + 1 == PIN_USB_HOST_DM || PIN_USB_HOST_DP - 1 == PIN_USB_HOST_DM, "Permitted USB D+/D- configuration");
|
||||
pio_cfg.pinout = PIN_USB_HOST_DP + 1 == PIN_USB_HOST_DM ? PIO_USB_PINOUT_DPDM : PIO_USB_PINOUT_DMDP;
|
||||
#endif
|
||||
|
||||
tuh_configure(BOARD_TUH_RHPORT, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg);
|
||||
|
||||
tuh_init(BOARD_TUH_RHPORT);
|
||||
|
|
|
|||
Loading…
Reference in a new issue