|
|
|
|
|
|
|
|
extern void systick_isr(void); |
|
|
extern void systick_isr(void); |
|
|
extern void pendablesrvreq_isr(void); |
|
|
extern void pendablesrvreq_isr(void); |
|
|
void configure_cache(void); |
|
|
void configure_cache(void); |
|
|
|
|
|
void configure_external_ram(void); |
|
|
void unused_interrupt_vector(void); |
|
|
void unused_interrupt_vector(void); |
|
|
void usb_pll_start(); |
|
|
void usb_pll_start(); |
|
|
extern void analog_init(void); // analog.c |
|
|
extern void analog_init(void); // analog.c |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
SNVS_HPCR |= SNVS_HPCR_RTC_EN | SNVS_HPCR_HP_TS; |
|
|
SNVS_HPCR |= SNVS_HPCR_RTC_EN | SNVS_HPCR_HP_TS; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef ARDUINO_TEENSY41 |
|
|
|
|
|
configure_external_ram(); |
|
|
|
|
|
#endif |
|
|
startup_early_hook(); |
|
|
startup_early_hook(); |
|
|
while (millis() < 20) ; // wait at least 20ms before starting USB |
|
|
while (millis() < 20) ; // wait at least 20ms before starting USB |
|
|
usb_init(); |
|
|
usb_init(); |
|
|
|
|
|
|
|
|
SCB_MPU_RASR = MEM_CACHE_WBWA | READONLY | SIZE_16M; |
|
|
SCB_MPU_RASR = MEM_CACHE_WBWA | READONLY | SIZE_16M; |
|
|
|
|
|
|
|
|
SCB_MPU_RBAR = 0x70000000 | REGION(i++); // FlexSPI2 |
|
|
SCB_MPU_RBAR = 0x70000000 | REGION(i++); // FlexSPI2 |
|
|
SCB_MPU_RASR = MEM_CACHE_WBWA | READONLY | SIZE_256M; |
|
|
|
|
|
|
|
|
SCB_MPU_RASR = MEM_CACHE_WBWA | READONLY | NOEXEC | SIZE_256M; |
|
|
|
|
|
|
|
|
SCB_MPU_RBAR = 0x70000000 | REGION(i++); // FlexSPI2 |
|
|
SCB_MPU_RBAR = 0x70000000 | REGION(i++); // FlexSPI2 |
|
|
SCB_MPU_RASR = MEM_CACHE_WBWA | READWRITE | SIZE_16M; |
|
|
|
|
|
|
|
|
SCB_MPU_RASR = MEM_CACHE_WBWA | READWRITE | NOEXEC | SIZE_16M; |
|
|
|
|
|
|
|
|
// TODO: protect access to power supply config |
|
|
// TODO: protect access to power supply config |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SCB_CCR |= (SCB_CCR_IC | SCB_CCR_DC); |
|
|
SCB_CCR |= (SCB_CCR_IC | SCB_CCR_DC); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifdef ARDUINO_TEENSY41 |
|
|
|
|
|
|
|
|
|
|
|
#define LUT0(opcode, pads, operand) (FLEXSPI_LUT_INSTRUCTION((opcode), (pads), (operand))) |
|
|
|
|
|
#define LUT1(opcode, pads, operand) (FLEXSPI_LUT_INSTRUCTION((opcode), (pads), (operand)) << 16) |
|
|
|
|
|
#define CMD_SDR FLEXSPI_LUT_OPCODE_CMD_SDR |
|
|
|
|
|
#define ADDR_SDR FLEXSPI_LUT_OPCODE_RADDR_SDR |
|
|
|
|
|
#define READ_SDR FLEXSPI_LUT_OPCODE_READ_SDR |
|
|
|
|
|
#define WRITE_SDR FLEXSPI_LUT_OPCODE_WRITE_SDR |
|
|
|
|
|
#define DUMMY_SDR FLEXSPI_LUT_OPCODE_DUMMY_SDR |
|
|
|
|
|
#define PINS1 FLEXSPI_LUT_NUM_PADS_1 |
|
|
|
|
|
#define PINS4 FLEXSPI_LUT_NUM_PADS_4 |
|
|
|
|
|
|
|
|
|
|
|
FLASHMEM static void flexspi2_command(uint32_t index, uint32_t addr) |
|
|
|
|
|
{ |
|
|
|
|
|
FLEXSPI2_IPCR0 = addr; |
|
|
|
|
|
FLEXSPI2_IPCR1 = FLEXSPI_IPCR1_ISEQID(index); |
|
|
|
|
|
FLEXSPI2_IPCMD = FLEXSPI_IPCMD_TRG; |
|
|
|
|
|
while (!(FLEXSPI2_INTR & FLEXSPI_INTR_IPCMDDONE)); // wait |
|
|
|
|
|
FLEXSPI2_INTR = FLEXSPI_INTR_IPCMDDONE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
FLASHMEM static uint32_t flexspi2_psram_id(uint32_t addr) |
|
|
|
|
|
{ |
|
|
|
|
|
FLEXSPI2_IPCR0 = addr; |
|
|
|
|
|
FLEXSPI2_IPCR1 = FLEXSPI_IPCR1_ISEQID(3) | FLEXSPI_IPCR1_IDATSZ(4); |
|
|
|
|
|
FLEXSPI2_IPCMD = FLEXSPI_IPCMD_TRG; |
|
|
|
|
|
while (!(FLEXSPI2_INTR & FLEXSPI_INTR_IPCMDDONE)); // wait |
|
|
|
|
|
uint32_t id = FLEXSPI2_RFDR0; |
|
|
|
|
|
FLEXSPI2_INTR = FLEXSPI_INTR_IPCMDDONE | FLEXSPI_INTR_IPRXWA; |
|
|
|
|
|
return id & 0xFFFF; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
FLASHMEM void configure_external_ram() |
|
|
|
|
|
{ |
|
|
|
|
|
// initialize pins |
|
|
|
|
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_22 = 0xB0E1; // 100K pullup, medium drive, max speed |
|
|
|
|
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_23 = 0x10E1; // keeper, medium drive, max speed |
|
|
|
|
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_24 = 0xB0E1; // 100K pullup, medium drive, max speed |
|
|
|
|
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_25 = 0x00E1; // medium drive, max speed |
|
|
|
|
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_26 = 0x70E1; // 47K pullup, medium drive, max speed |
|
|
|
|
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_27 = 0x70E1; // 47K pullup, medium drive, max speed |
|
|
|
|
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_28 = 0x70E1; // 47K pullup, medium drive, max speed |
|
|
|
|
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_29 = 0x70E1; // 47K pullup, medium drive, max speed |
|
|
|
|
|
|
|
|
|
|
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_22 = 8 | 0x10; // ALT1 = FLEXSPI2_A_SS1_B (Flash) |
|
|
|
|
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_23 = 8 | 0x10; // ALT1 = FLEXSPI2_A_DQS |
|
|
|
|
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_24 = 8 | 0x10; // ALT1 = FLEXSPI2_A_SS0_B (RAM) |
|
|
|
|
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_25 = 8 | 0x10; // ALT1 = FLEXSPI2_A_SCLK |
|
|
|
|
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_26 = 8 | 0x10; // ALT1 = FLEXSPI2_A_DATA0 |
|
|
|
|
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_27 = 8 | 0x10; // ALT1 = FLEXSPI2_A_DATA1 |
|
|
|
|
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_28 = 8 | 0x10; // ALT1 = FLEXSPI2_A_DATA2 |
|
|
|
|
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_29 = 8 | 0x10; // ALT1 = FLEXSPI2_A_DATA3 |
|
|
|
|
|
|
|
|
|
|
|
IOMUXC_FLEXSPI2_IPP_IND_DQS_FA_SELECT_INPUT = 1; // GPIO_EMC_23 for Mode: ALT8, pg 986 |
|
|
|
|
|
IOMUXC_FLEXSPI2_IPP_IND_IO_FA_BIT0_SELECT_INPUT = 1; // GPIO_EMC_26 for Mode: ALT8 |
|
|
|
|
|
IOMUXC_FLEXSPI2_IPP_IND_IO_FA_BIT1_SELECT_INPUT = 1; // GPIO_EMC_27 for Mode: ALT8 |
|
|
|
|
|
IOMUXC_FLEXSPI2_IPP_IND_IO_FA_BIT2_SELECT_INPUT = 1; // GPIO_EMC_28 for Mode: ALT8 |
|
|
|
|
|
IOMUXC_FLEXSPI2_IPP_IND_IO_FA_BIT3_SELECT_INPUT = 1; // GPIO_EMC_29 for Mode: ALT8 |
|
|
|
|
|
IOMUXC_FLEXSPI2_IPP_IND_SCK_FA_SELECT_INPUT = 1; // GPIO_EMC_25 for Mode: ALT8 |
|
|
|
|
|
|
|
|
|
|
|
// turn on clock (TODO: increase clock speed later, slow & cautious for first release) |
|
|
|
|
|
CCM_CBCMR = (CCM_CBCMR & (CCM_CBCMR_FLEXSPI2_PODF_MASK | CCM_CBCMR_FLEXSPI2_CLK_SEL_MASK)) |
|
|
|
|
|
| CCM_CBCMR_FLEXSPI2_PODF(7) | CCM_CBCMR_FLEXSPI2_CLK_SEL(0); // 49.5 MHz |
|
|
|
|
|
CCM_CCGR7 |= CCM_CCGR7_FLEXSPI2(CCM_CCGR_ON); |
|
|
|
|
|
|
|
|
|
|
|
FLEXSPI2_MCR0 |= FLEXSPI_MCR0_MDIS; |
|
|
|
|
|
FLEXSPI2_MCR0 = (FLEXSPI2_MCR0 & ~(FLEXSPI_MCR0_AHBGRANTWAIT_MASK |
|
|
|
|
|
| FLEXSPI_MCR0_IPGRANTWAIT_MASK | FLEXSPI_MCR0_SCKFREERUNEN |
|
|
|
|
|
| FLEXSPI_MCR0_COMBINATIONEN | FLEXSPI_MCR0_DOZEEN |
|
|
|
|
|
| FLEXSPI_MCR0_HSEN | FLEXSPI_MCR0_ATDFEN | FLEXSPI_MCR0_ARDFEN |
|
|
|
|
|
| FLEXSPI_MCR0_RXCLKSRC_MASK | FLEXSPI_MCR0_SWRESET)) |
|
|
|
|
|
| FLEXSPI_MCR0_AHBGRANTWAIT(0xFF) | FLEXSPI_MCR0_IPGRANTWAIT(0xFF) |
|
|
|
|
|
| FLEXSPI_MCR0_RXCLKSRC(1) | FLEXSPI_MCR0_MDIS; |
|
|
|
|
|
FLEXSPI2_MCR1 = FLEXSPI_MCR1_SEQWAIT(0xFFFF) | FLEXSPI_MCR1_AHBBUSWAIT(0xFFFF); |
|
|
|
|
|
FLEXSPI2_MCR2 = (FLEXSPI_MCR2 & ~(FLEXSPI_MCR2_RESUMEWAIT_MASK |
|
|
|
|
|
| FLEXSPI_MCR2_SCKBDIFFOPT | FLEXSPI_MCR2_SAMEDEVICEEN |
|
|
|
|
|
| FLEXSPI_MCR2_CLRLEARNPHASE | FLEXSPI_MCR2_CLRAHBBUFOPT)) |
|
|
|
|
|
| FLEXSPI_MCR2_RESUMEWAIT(0x20) /*| FLEXSPI_MCR2_SAMEDEVICEEN*/; |
|
|
|
|
|
|
|
|
|
|
|
FLEXSPI2_AHBCR = FLEXSPI2_AHBCR & ~(FLEXSPI_AHBCR_READADDROPT | FLEXSPI_AHBCR_PREFETCHEN |
|
|
|
|
|
| FLEXSPI_AHBCR_BUFFERABLEEN | FLEXSPI_AHBCR_CACHABLEEN); |
|
|
|
|
|
uint32_t mask = (FLEXSPI_AHBRXBUFCR0_PREFETCHEN | FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK |
|
|
|
|
|
| FLEXSPI_AHBRXBUFCR0_MSTRID_MASK | FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK); |
|
|
|
|
|
FLEXSPI2_AHBRXBUF0CR0 = (FLEXSPI2_AHBRXBUF0CR0 & ~mask) |
|
|
|
|
|
| FLEXSPI_AHBRXBUFCR0_PREFETCHEN | FLEXSPI_AHBRXBUFCR0_BUFSZ(64); |
|
|
|
|
|
FLEXSPI2_AHBRXBUF1CR0 = (FLEXSPI2_AHBRXBUF0CR0 & ~mask) |
|
|
|
|
|
| FLEXSPI_AHBRXBUFCR0_PREFETCHEN | FLEXSPI_AHBRXBUFCR0_BUFSZ(64); |
|
|
|
|
|
FLEXSPI2_AHBRXBUF2CR0 = mask; |
|
|
|
|
|
FLEXSPI2_AHBRXBUF3CR0 = mask; |
|
|
|
|
|
|
|
|
|
|
|
// RX watermark = one 64 bit line |
|
|
|
|
|
FLEXSPI2_IPRXFCR = (FLEXSPI_IPRXFCR & 0xFFFFFFC0) | FLEXSPI_IPRXFCR_CLRIPRXF; |
|
|
|
|
|
// TX watermark = one 64 bit line |
|
|
|
|
|
FLEXSPI2_IPTXFCR = (FLEXSPI_IPTXFCR & 0xFFFFFFC0) | FLEXSPI_IPTXFCR_CLRIPTXF; |
|
|
|
|
|
|
|
|
|
|
|
FLEXSPI2_INTEN = 0; |
|
|
|
|
|
FLEXSPI2_FLSHA1CR0 = 0x2000; // 8 MByte |
|
|
|
|
|
FLEXSPI2_FLSHA1CR1 = FLEXSPI_FLSHCR1_CSINTERVAL(2) |
|
|
|
|
|
| FLEXSPI_FLSHCR1_TCSH(3) | FLEXSPI_FLSHCR1_TCSS(3); |
|
|
|
|
|
FLEXSPI2_FLSHA1CR2 = FLEXSPI_FLSHCR2_AWRSEQID(6) | FLEXSPI_FLSHCR2_AWRSEQNUM(0) |
|
|
|
|
|
| FLEXSPI_FLSHCR2_ARDSEQID(5) | FLEXSPI_FLSHCR2_ARDSEQNUM(0); |
|
|
|
|
|
|
|
|
|
|
|
FLEXSPI2_FLSHA2CR0 = 0x2000; // 8 MByte |
|
|
|
|
|
FLEXSPI2_FLSHA2CR1 = FLEXSPI_FLSHCR1_CSINTERVAL(2) |
|
|
|
|
|
| FLEXSPI_FLSHCR1_TCSH(3) | FLEXSPI_FLSHCR1_TCSS(3); |
|
|
|
|
|
FLEXSPI2_FLSHA2CR2 = FLEXSPI_FLSHCR2_AWRSEQID(6) | FLEXSPI_FLSHCR2_AWRSEQNUM(0) |
|
|
|
|
|
| FLEXSPI_FLSHCR2_ARDSEQID(5) | FLEXSPI_FLSHCR2_ARDSEQNUM(0); |
|
|
|
|
|
|
|
|
|
|
|
FLEXSPI2_MCR0 &= ~FLEXSPI_MCR0_MDIS; |
|
|
|
|
|
|
|
|
|
|
|
FLEXSPI2_LUTKEY = FLEXSPI_LUTKEY_VALUE; |
|
|
|
|
|
FLEXSPI2_LUTCR = FLEXSPI_LUTCR_UNLOCK; |
|
|
|
|
|
volatile uint32_t *luttable = &FLEXSPI2_LUT0; |
|
|
|
|
|
for (int i=0; i < 64; i++) luttable[i] = 0; |
|
|
|
|
|
FLEXSPI2_MCR0 |= FLEXSPI_MCR0_SWRESET; |
|
|
|
|
|
while (FLEXSPI2_MCR0 & FLEXSPI_MCR0_SWRESET) ; // wait |
|
|
|
|
|
|
|
|
|
|
|
FLEXSPI2_LUTKEY = FLEXSPI_LUTKEY_VALUE; |
|
|
|
|
|
FLEXSPI2_LUTCR = FLEXSPI_LUTCR_UNLOCK; |
|
|
|
|
|
|
|
|
|
|
|
// cmd index 0 = exit QPI mode |
|
|
|
|
|
FLEXSPI2_LUT0 = LUT0(CMD_SDR, PINS4, 0xF5); |
|
|
|
|
|
// cmd index 1 = reset enable |
|
|
|
|
|
FLEXSPI2_LUT4 = LUT0(CMD_SDR, PINS1, 0x66); |
|
|
|
|
|
// cmd index 2 = reset |
|
|
|
|
|
FLEXSPI2_LUT8 = LUT0(CMD_SDR, PINS1, 0x99); |
|
|
|
|
|
// cmd index 3 = read ID bytes |
|
|
|
|
|
FLEXSPI2_LUT12 = LUT0(CMD_SDR, PINS1, 0x9F) | LUT1(DUMMY_SDR, PINS1, 24); |
|
|
|
|
|
FLEXSPI2_LUT13 = LUT0(READ_SDR, PINS1, 1); |
|
|
|
|
|
// cmd index 4 = enter QPI mode |
|
|
|
|
|
FLEXSPI2_LUT16 = LUT0(CMD_SDR, PINS1, 0x35); |
|
|
|
|
|
// cmd index 5 = read QPI |
|
|
|
|
|
FLEXSPI2_LUT20 = LUT0(CMD_SDR, PINS4, 0xEB) | LUT1(ADDR_SDR, PINS4, 24); |
|
|
|
|
|
FLEXSPI2_LUT21 = LUT0(DUMMY_SDR, PINS4, 6) | LUT1(READ_SDR, PINS4, 1); |
|
|
|
|
|
// cmd index 6 = write QPI |
|
|
|
|
|
FLEXSPI2_LUT24 = LUT0(CMD_SDR, PINS4, 0x38) | LUT1(ADDR_SDR, PINS4, 24); |
|
|
|
|
|
FLEXSPI2_LUT25 = LUT0(WRITE_SDR, PINS4, 1); |
|
|
|
|
|
|
|
|
|
|
|
// look for the first PSRAM chip |
|
|
|
|
|
flexspi2_command(0, 0); // exit quad mode |
|
|
|
|
|
flexspi2_command(1, 0); // reset enable |
|
|
|
|
|
flexspi2_command(2, 0); // reset (is this really necessary?) |
|
|
|
|
|
if (flexspi2_psram_id(0) == 0x5D0D) { |
|
|
|
|
|
// first PSRAM chip is present, look for a second PSRAM chip |
|
|
|
|
|
flexspi2_command(4, 0); |
|
|
|
|
|
flexspi2_command(0, 0x800000); // exit quad mode |
|
|
|
|
|
flexspi2_command(1, 0x800000); // reset enable |
|
|
|
|
|
flexspi2_command(2, 0x800000); // reset (is this really necessary?) |
|
|
|
|
|
if (flexspi2_psram_id(0x800000) == 0x5D0D) { |
|
|
|
|
|
flexspi2_command(4, 0x800000); |
|
|
|
|
|
// Two PSRAM chips are present, 16 MByte |
|
|
|
|
|
} else { |
|
|
|
|
|
// One PSRAM chip is present, 8 MByte |
|
|
|
|
|
} |
|
|
|
|
|
// TODO: zero uninitialized EXTMEM variables |
|
|
|
|
|
// TODO: copy from flash to initialize EXTMEM variables |
|
|
|
|
|
// TODO: set up for malloc_extmem() |
|
|
|
|
|
} else { |
|
|
|
|
|
// No PSRAM |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#endif // ARDUINO_TEENSY41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FLASHMEM void usb_pll_start() |
|
|
FLASHMEM void usb_pll_start() |
|
|
{ |
|
|
{ |
|
|
while (1) { |
|
|
while (1) { |