initialize psram (doesn't get used yet)
This commit is contained in:
parent
94381019f4
commit
c4734c7fc7
2 changed files with 146 additions and 0 deletions
|
|
@ -10,6 +10,7 @@
|
||||||
#define HAS_USBHOST 1
|
#define HAS_USBHOST 1
|
||||||
#define HAS_USBPIO 1
|
#define HAS_USBPIO 1
|
||||||
|
|
||||||
|
#define PSRAM_CHIP_SELECT (47u)
|
||||||
//#define ILI9341 1
|
//#define ILI9341 1
|
||||||
//#define ST7789 1
|
//#define ST7789 1
|
||||||
//#define SWAP_JOYSTICK 1
|
//#define SWAP_JOYSTICK 1
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@
|
||||||
#include "pico.h"
|
#include "pico.h"
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "hardware/adc.h"
|
#include "hardware/adc.h"
|
||||||
|
#include "hardware/structs/qmi.h"
|
||||||
|
#include "hardware/structs/xip.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
@ -1433,12 +1436,154 @@ static bool emu_eraseConfig(void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t _psram_size;
|
||||||
|
static void __no_inline_not_in_flash_func(setup_psram)(void) {
|
||||||
|
_psram_size = 0;
|
||||||
|
#ifdef PSRAM_CHIP_SELECT
|
||||||
|
gpio_set_function(PSRAM_CHIP_SELECT, 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
|
||||||
|
}
|
||||||
|
|
||||||
/********************************
|
/********************************
|
||||||
* Initialization
|
* Initialization
|
||||||
********************************/
|
********************************/
|
||||||
void emu_init(void)
|
void emu_init(void)
|
||||||
{
|
{
|
||||||
|
setup_psram();
|
||||||
|
|
||||||
//board_init();
|
//board_init();
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue