Merge pull request #3522 from tannewt/imx_metro

Unify iMX RT flash config and add Metro M7 1011
This commit is contained in:
Scott Shawcroft 2020-10-09 13:48:58 -07:00 committed by GitHub
commit 699f19f44a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 1458 additions and 1025 deletions

View File

@ -243,6 +243,7 @@ jobs:
- "metro_m0_express"
- "metro_m4_airlift_lite"
- "metro_m4_express"
- "metro_m7_1011"
- "metro_nrf52840_express"
- "mini_sam_m4"
- "monster_m4sk"

View File

@ -123,7 +123,7 @@ DRESULT disk_write (
DRESULT disk_ioctl (
bdev_t pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
@ -133,7 +133,7 @@ DRESULT disk_ioctl (
}
// First part: call the relevant method of the underlying block device
mp_obj_t ret = mp_const_none;
mp_int_t out_value = 0;
if (vfs->flags & FSUSER_HAVE_IOCTL) {
// new protocol with ioctl
static const uint8_t op_map[8] = {
@ -144,9 +144,19 @@ DRESULT disk_ioctl (
};
uint8_t bp_op = op_map[cmd & 7];
if (bp_op != 0) {
vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op);
vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl);
if (vfs->flags & FSUSER_NATIVE) {
bool (*f)(size_t, mp_int_t*) = (void*)(uintptr_t)vfs->u.ioctl[2];
if (!f(bp_op, (mp_int_t*) &out_value)) {
return RES_ERROR;
}
} else {
vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op);
vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl);
if (ret != mp_const_none) {
out_value = mp_obj_get_int(ret);
}
}
}
} else {
// old protocol with sync and count
@ -157,10 +167,13 @@ DRESULT disk_ioctl (
}
break;
case GET_SECTOR_COUNT:
ret = mp_call_method_n_kw(0, 0, vfs->u.old.count);
case GET_SECTOR_COUNT: {
mp_obj_t ret = mp_call_method_n_kw(0, 0, vfs->u.old.count);
if (ret != mp_const_none) {
out_value = mp_obj_get_int(ret);
}
break;
}
case GET_SECTOR_SIZE:
// old protocol has fixed sector size of 512 bytes
break;
@ -177,16 +190,16 @@ DRESULT disk_ioctl (
return RES_OK;
case GET_SECTOR_COUNT: {
*((DWORD*)buff) = mp_obj_get_int(ret);
*((DWORD*)buff) = out_value;
return RES_OK;
}
case GET_SECTOR_SIZE: {
if (ret == mp_const_none) {
if (out_value == 0) {
// Default sector size
*((WORD*)buff) = 512;
} else {
*((WORD*)buff) = mp_obj_get_int(ret);
*((WORD*)buff) = out_value;
}
#if _MAX_SS != _MIN_SS
// need to store ssize because we use it in disk_read/disk_write
@ -202,7 +215,7 @@ DRESULT disk_ioctl (
case IOCTL_INIT:
case IOCTL_STATUS: {
DSTATUS stat;
if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
if (out_value != 0) {
// error initialising
stat = STA_NOINIT;
} else if (vfs->writeblocks[0] == MP_OBJ_NULL) {

View File

@ -75,7 +75,7 @@ INC += \
# NDEBUG disables assert() statements. This reduces code size pretty dramatically, per tannewt.
CFLAGS += -Os -DNDEBUG
CFLAGS += -Os -DNDEBUG -ffreestanding
# TinyUSB defines
CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX -DCFG_TUD_MIDI_RX_BUFSIZE=512 -DCFG_TUD_CDC_RX_BUFSIZE=512 -DCFG_TUD_MIDI_TX_BUFSIZE=512 -DCFG_TUD_CDC_TX_BUFSIZE=512 -DCFG_TUD_MSC_BUFSIZE=1024

View File

@ -33,6 +33,7 @@
#include "py/mpconfig.h"
#include "fsl_common.h"
#include "fsl_flexspi_nor_config.h"
// Initializes board related state once on start up.
void board_init(void);
@ -45,4 +46,11 @@ bool board_requests_safe_mode(void);
// Reset the state of off MCU components such as neopixels.
void reset_board(void);
#define SEQUENCE(first, second, third, fourth) first, second, third, fourth
#define TWO_EMPTY_STEPS 0x00000000
#define EMPTY_SEQUENCE SEQUENCE(TWO_EMPTY_STEPS, TWO_EMPTY_STEPS, TWO_EMPTY_STEPS, TWO_EMPTY_STEPS)
// FlexSPI configuration that stores command info.
extern const flexspi_nor_config_t qspiflash_config;
#endif // MICROPY_INCLUDED_MIMXRT10XX_BOARDS_BOARD_H

View File

@ -6,7 +6,7 @@
*/
#include "fsl_flexspi_nor_boot.h"
#include "fsl_flexspi_nor_config.h"
#include "boards/board.h"
__attribute__((section(".boot_hdr.ivt")))
@ -35,88 +35,135 @@ const BOOT_DATA_T boot_data = {
0xFFFFFFFF /* empty - extra data word */
};
// Config for W25Q32JV with QSPI routed.
__attribute__((section(".boot_hdr.conf")))
// Values copied from https://github.com/PaulStoffregen/cores/blob/ddb23fa5d97dac763bc06e11b9b41f026bd51f0a/teensy4/bootdata.c#L39
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 1u,
.csSetupTime = 2u,
// Enable DDR mode, Wordaddressable, Safe configuration, Differential clock
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz, // 03
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) |
// FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
// Read LUTs
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
0,
0,
0x24040405,
0,
0,
0,
0,
0,
0,
0,
0x00000406,
0,
0,
0,
0,
0,
0,
0,
0x08180420,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x081804D8,
0,
0,
0,
0x08180402,
0x00002004,
0,
0,
0,
0,
0,
0,
0x00000460,
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
.blockSize = 0x00010000,
.isUniformBlockSize = false,
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.busyOffset = 0u, // Status bit 0 indicates busy.
.busyBitPolarity = 0u, // Busy when the bit is 1.
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {
.seqId = 4u,
.seqNum = 1u,
},
.deviceModeArg = 0x02, // Bit pattern for setting Quad Enable.
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_133MHz,
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// The high 16 bits is command 1 and the low are command 0.
// Within a command, the top 6 bits are the opcode, the next two are the number
// of pads and then last byte is the operand. The operand's meaning changes
// per opcode.
// Indices with ROM should always have the same function because the ROM
// bootloader uses it.
// 0: ROM: Read LUTs
// Quad version
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
READ_SDR, FLEXSPI_4PAD, 0x04),
// Single fast read version, good for debugging.
// FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
// RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
// READ_SDR, FLEXSPI_1PAD, 0x04),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 1: ROM: Read status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
READ_SDR, FLEXSPI_1PAD, 0x02),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 2: Empty
EMPTY_SEQUENCE,
// 3: ROM: Write Enable
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
STOP, FLEXSPI_1PAD, 0x00),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 4: Config: Write Status -2
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x31 /* the command to send */,
WRITE_SDR, FLEXSPI_1PAD, 0x01 /* number of bytes to write */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 5: ROM: Erase Sector
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 6: Empty
EMPTY_SEQUENCE,
// 7: Empty
EMPTY_SEQUENCE,
// 8: Block Erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 9: ROM: Page program
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 10: Empty
EMPTY_SEQUENCE,
// 11: ROM: Chip erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 12: Empty
EMPTY_SEQUENCE,
// 13: ROM: Read SFDP
EMPTY_SEQUENCE,
// 14: ROM: Restore no cmd
EMPTY_SEQUENCE,
// 15: ROM: Dummy
EMPTY_SEQUENCE
},
},
};

View File

@ -6,7 +6,7 @@
*/
#include "fsl_flexspi_nor_boot.h"
#include "fsl_flexspi_nor_config.h"
#include "boards/board.h"
__attribute__((section(".boot_hdr.ivt")))
@ -35,88 +35,135 @@ const BOOT_DATA_T boot_data = {
0xFFFFFFFF /* empty - extra data word */
};
// Config for W25Q64JV with QSPI routed.
__attribute__((section(".boot_hdr.conf")))
// Values copied from https://github.com/PaulStoffregen/cores/blob/ddb23fa5d97dac763bc06e11b9b41f026bd51f0a/teensy4/bootdata.c#L39
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 1u,
.csSetupTime = 2u,
// Enable DDR mode, Wordaddressable, Safe configuration, Differential clock
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz, // 03
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) |
// FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
// Read LUTs
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
0,
0,
0x24040405,
0,
0,
0,
0,
0,
0,
0,
0x00000406,
0,
0,
0,
0,
0,
0,
0,
0x08180420,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x081804D8,
0,
0,
0,
0x08180402,
0x00002004,
0,
0,
0,
0,
0,
0,
0x00000460,
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
.blockSize = 0x00010000,
.isUniformBlockSize = false,
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.busyOffset = 0u, // Status bit 0 indicates busy.
.busyBitPolarity = 0u, // Busy when the bit is 1.
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {
.seqId = 4u,
.seqNum = 1u,
},
.deviceModeArg = 0x02,
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_133MHz,
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// The high 16 bits is command 1 and the low are command 0.
// Within a command, the top 6 bits are the opcode, the next two are the number
// of pads and then last byte is the operand. The operand's meaning changes
// per opcode.
// Indices with ROM should always have the same function because the ROM
// bootloader uses it.
// 0: ROM: Read LUTs
// Quad version
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
READ_SDR, FLEXSPI_4PAD, 0x04),
// Single fast read version, good for debugging.
// FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
// RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
// READ_SDR, FLEXSPI_1PAD, 0x04),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 1: ROM: Read status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
READ_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 2: Empty
EMPTY_SEQUENCE,
// 3: ROM: Write Enable
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
STOP, FLEXSPI_1PAD, 0x00),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 4: Config: Write Status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x31 /* the command to send */,
WRITE_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 5: ROM: Erase Sector
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 6: Empty
EMPTY_SEQUENCE,
// 7: Empty
EMPTY_SEQUENCE,
// 8: Block Erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 9: ROM: Page program
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 10: Empty
EMPTY_SEQUENCE,
// 11: ROM: Chip erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 12: Empty
EMPTY_SEQUENCE,
// 13: ROM: Read SFDP
EMPTY_SEQUENCE,
// 14: ROM: Restore no cmd
EMPTY_SEQUENCE,
// 15: ROM: Dummy
EMPTY_SEQUENCE
},
},
};

View File

@ -6,7 +6,7 @@
*/
#include "fsl_flexspi_nor_boot.h"
#include "fsl_flexspi_nor_config.h"
#include "boards/board.h"
__attribute__((section(".boot_hdr.ivt")))
@ -35,88 +35,135 @@ const BOOT_DATA_T boot_data = {
0xFFFFFFFF /* empty - extra data word */
};
// Config for W25Q64JV with QSPI routed.
__attribute__((section(".boot_hdr.conf")))
// Values copied from https://github.com/PaulStoffregen/cores/blob/ddb23fa5d97dac763bc06e11b9b41f026bd51f0a/teensy4/bootdata.c#L39
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 1u,
.csSetupTime = 2u,
// Enable DDR mode, Wordaddressable, Safe configuration, Differential clock
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz, // 03
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) |
// FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
// Read LUTs
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
0,
0,
0x24040405,
0,
0,
0,
0,
0,
0,
0,
0x00000406,
0,
0,
0,
0,
0,
0,
0,
0x08180420,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x081804D8,
0,
0,
0,
0x08180402,
0x00002004,
0,
0,
0,
0,
0,
0,
0x00000460,
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
.blockSize = 0x00010000,
.isUniformBlockSize = false,
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.busyOffset = 0u, // Status bit 0 indicates busy.
.busyBitPolarity = 0u, // Busy when the bit is 1.
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {
.seqId = 4u,
.seqNum = 1u,
},
.deviceModeArg = 0x02,
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_133MHz,
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// The high 16 bits is command 1 and the low are command 0.
// Within a command, the top 6 bits are the opcode, the next two are the number
// of pads and then last byte is the operand. The operand's meaning changes
// per opcode.
// Indices with ROM should always have the same function because the ROM
// bootloader uses it.
// 0: ROM: Read LUTs
// Quad version
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
READ_SDR, FLEXSPI_4PAD, 0x04),
// Single fast read version, good for debugging.
// FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
// RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
// READ_SDR, FLEXSPI_1PAD, 0x04),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 1: ROM: Read status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
READ_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 2: Empty
EMPTY_SEQUENCE,
// 3: ROM: Write Enable
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
STOP, FLEXSPI_1PAD, 0x00),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 4: Config: Write Status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x31 /* the command to send */,
WRITE_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 5: ROM: Erase Sector
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 6: Empty
EMPTY_SEQUENCE,
// 7: Empty
EMPTY_SEQUENCE,
// 8: Block Erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 9: ROM: Page program
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 10: Empty
EMPTY_SEQUENCE,
// 11: ROM: Chip erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 12: Empty
EMPTY_SEQUENCE,
// 13: ROM: Read SFDP
EMPTY_SEQUENCE,
// 14: ROM: Restore no cmd
EMPTY_SEQUENCE,
// 15: ROM: Dummy
EMPTY_SEQUENCE
},
},
};

View File

@ -6,7 +6,8 @@
*/
#include "fsl_flexspi_nor_boot.h"
#include "fsl_flexspi_nor_config.h"
#include "boards/board.h"
__attribute__((section(".boot_hdr.ivt")))
/*************************************
@ -34,88 +35,135 @@ const BOOT_DATA_T boot_data = {
0xFFFFFFFF /* empty - extra data word */
};
// Config for AT25SF128A with QSPI routed.
__attribute__((section(".boot_hdr.conf")))
// Values copied from https://github.com/PaulStoffregen/cores/blob/ddb23fa5d97dac763bc06e11b9b41f026bd51f0a/teensy4/bootdata.c#L39
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 1u,
.csSetupTime = 2u,
// Enable DDR mode, Wordaddressable, Safe configuration, Differential clock
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz, // 03
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) |
// FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
// Read LUTs
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
0,
0,
0x24040405,
0,
0,
0,
0,
0,
0,
0,
0x00000406,
0,
0,
0,
0,
0,
0,
0,
0x08180420,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x081804D8,
0,
0,
0,
0x08180402,
0x00002004,
0,
0,
0,
0,
0,
0,
0x00000460,
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
.blockSize = 0x00010000,
.isUniformBlockSize = false,
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.busyOffset = 0u, // Status bit 0 indicates busy.
.busyBitPolarity = 0u, // Busy when the bit is 1.
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {
.seqId = 4u,
.seqNum = 1u,
},
.deviceModeArg = 0x02,
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz,
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// The high 16 bits is command 1 and the low are command 0.
// Within a command, the top 6 bits are the opcode, the next two are the number
// of pads and then last byte is the operand. The operand's meaning changes
// per opcode.
// Indices with ROM should always have the same function because the ROM
// bootloader uses it.
// 0: ROM: Read LUTs
// Quad version
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
READ_SDR, FLEXSPI_4PAD, 0x04),
// Single fast read version, good for debugging.
// FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
// RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
// READ_SDR, FLEXSPI_1PAD, 0x04),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 1: ROM: Read status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
READ_SDR, FLEXSPI_1PAD, 0x02),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 2: Empty
EMPTY_SEQUENCE,
// 3: ROM: Write Enable
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
STOP, FLEXSPI_1PAD, 0x00),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 4: Config: Write Status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x31 /* the command to send */,
WRITE_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 5: ROM: Erase Sector
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 6: Empty
EMPTY_SEQUENCE,
// 7: Empty
EMPTY_SEQUENCE,
// 8: Block Erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 9: ROM: Page program
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 10: Empty
EMPTY_SEQUENCE,
// 11: ROM: Chip erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 12: Empty
EMPTY_SEQUENCE,
// 13: ROM: Read SFDP
EMPTY_SEQUENCE,
// 14: ROM: Restore no cmd
EMPTY_SEQUENCE,
// 15: ROM: Dummy
EMPTY_SEQUENCE
},
},
};

View File

@ -6,7 +6,7 @@
*/
#include "fsl_flexspi_nor_boot.h"
#include "fsl_flexspi_nor_config.h"
#include "boards/board.h"
__attribute__((section(".boot_hdr.ivt")))
@ -35,92 +35,135 @@ const BOOT_DATA_T boot_data = {
0xFFFFFFFF /* empty - extra data word */
};
// Config for IS25LP064A with QSPI routed.
__attribute__((section(".boot_hdr.conf")))
// Values copied from https://github.com/PaulStoffregen/cores/blob/ddb23fa5d97dac763bc06e11b9b41f026bd51f0a/teensy4/bootdata.c#L39
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
#ifdef BOARD_USING_SECONDARY_QSPI_PINMUX
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromInternally,
#else
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
#endif
.csHoldTime = 1u,
.csSetupTime = 2u,
// Enable DDR mode, Wordaddressable, Safe configuration, Differential clock
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz, // 03
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) |
// FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
// Read LUTs
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
0,
0,
0x24040405,
0,
0,
0,
0,
0,
0,
0,
0x00000406,
0,
0,
0,
0,
0,
0,
0,
0x08180420,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x081804D8,
0,
0,
0,
0x08180402,
0x00002004,
0,
0,
0,
0,
0,
0,
0x00000460,
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
.blockSize = 0x00010000,
.isUniformBlockSize = false,
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.busyOffset = 0u, // Status bit 0 indicates busy.
.busyBitPolarity = 0u, // Busy when the bit is 1.
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {
.seqId = 4u,
.seqNum = 1u,
},
.deviceModeArg = 0x40,
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_30MHz,
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// The high 16 bits is command 1 and the low are command 0.
// Within a command, the top 6 bits are the opcode, the next two are the number
// of pads and then last byte is the operand. The operand's meaning changes
// per opcode.
// Indices with ROM should always have the same function because the ROM
// bootloader uses it.
// 0: ROM: Read LUTs
// Quad version
// SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
// RADDR_SDR, FLEXSPI_4PAD, 24 bits to transmit ),
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
// READ_SDR, FLEXSPI_4PAD, 0x04),
// Single fast read version, good for debugging.
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
READ_SDR, FLEXSPI_1PAD, 0x04),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 1: ROM: Read status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
READ_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 2: Empty
EMPTY_SEQUENCE,
// 3: ROM: Write Enable
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
STOP, FLEXSPI_1PAD, 0x00),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 4: Config: Write Status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01 /* the command to send */,
WRITE_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 5: ROM: Erase Sector
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 6: Empty
EMPTY_SEQUENCE,
// 7: Empty
EMPTY_SEQUENCE,
// 8: Block Erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 9: ROM: Page program
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 10: Empty
EMPTY_SEQUENCE,
// 11: ROM: Chip erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 12: Empty
EMPTY_SEQUENCE,
// 13: ROM: Read SFDP
EMPTY_SEQUENCE,
// 14: ROM: Restore no cmd
EMPTY_SEQUENCE,
// 15: ROM: Dummy
EMPTY_SEQUENCE
},
},
};

View File

@ -6,10 +6,10 @@
*/
#include "fsl_flexspi_nor_boot.h"
#include "fsl_flexspi_nor_config.h"
#include "boards/board.h"
__attribute__((section(".boot_hdr.ivt")))
/*************************************
* IVT Data
*************************************/
@ -35,88 +35,135 @@ const BOOT_DATA_T boot_data = {
0xFFFFFFFF /* empty - extra data word */
};
// Config for IS25WP064A with QSPI routed.
__attribute__((section(".boot_hdr.conf")))
// Values copied from https://github.com/PaulStoffregen/cores/blob/ddb23fa5d97dac763bc06e11b9b41f026bd51f0a/teensy4/bootdata.c#L39
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 1u,
.csSetupTime = 2u,
// Enable DDR mode, Wordaddressable, Safe configuration, Differential clock
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz, // 03
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) |
// FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
// Read LUTs
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
0,
0,
0x24040405,
0,
0,
0,
0,
0,
0,
0,
0x00000406,
0,
0,
0,
0,
0,
0,
0,
0x08180420,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x081804D8,
0,
0,
0,
0x08180402,
0x00002004,
0,
0,
0,
0,
0,
0,
0x00000460,
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
.blockSize = 0x00010000,
.isUniformBlockSize = false,
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.busyOffset = 0u, // Status bit 0 indicates busy.
.busyBitPolarity = 0u, // Busy when the bit is 1.
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {
.seqId = 4u,
.seqNum = 1u,
},
.deviceModeArg = 0x40,
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz,
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// The high 16 bits is command 1 and the low are command 0.
// Within a command, the top 6 bits are the opcode, the next two are the number
// of pads and then last byte is the operand. The operand's meaning changes
// per opcode.
// Indices with ROM should always have the same function because the ROM
// bootloader uses it.
// 0: ROM: Read LUTs
// Quad version
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
READ_SDR, FLEXSPI_4PAD, 0x04),
// Single fast read version, good for debugging.
// FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
// RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
// READ_SDR, FLEXSPI_1PAD, 0x04),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 1: ROM: Read status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
READ_SDR, FLEXSPI_1PAD, 0x02),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 2: Empty
EMPTY_SEQUENCE,
// 3: ROM: Write Enable
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
STOP, FLEXSPI_1PAD, 0x00),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 4: Config: Write Status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01 /* the command to send */,
WRITE_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 5: ROM: Erase Sector
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 6: Empty
EMPTY_SEQUENCE,
// 7: Empty
EMPTY_SEQUENCE,
// 8: Block Erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 9: ROM: Page program
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 10: Empty
EMPTY_SEQUENCE,
// 11: ROM: Chip erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 12: Empty
EMPTY_SEQUENCE,
// 13: ROM: Read SFDP
EMPTY_SEQUENCE,
// 14: ROM: Restore no cmd
EMPTY_SEQUENCE,
// 15: ROM: Dummy
EMPTY_SEQUENCE
},
},
};

View File

@ -0,0 +1,52 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
* Copyright (c) 2019 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "boards/board.h"
#include "mpconfigboard.h"
#include "shared-bindings/microcontroller/Pin.h"
void board_init(void) {
// SWD Pins
common_hal_never_reset_pin(&pin_GPIO_AD_13);//SWDIO
common_hal_never_reset_pin(&pin_GPIO_AD_12);//SWCLK
// FLEX flash
common_hal_never_reset_pin(&pin_GPIO_SD_12);
common_hal_never_reset_pin(&pin_GPIO_SD_11);
common_hal_never_reset_pin(&pin_GPIO_SD_10);
common_hal_never_reset_pin(&pin_GPIO_SD_09);
common_hal_never_reset_pin(&pin_GPIO_SD_08);
common_hal_never_reset_pin(&pin_GPIO_SD_07);
common_hal_never_reset_pin(&pin_GPIO_SD_06);
}
bool board_requests_safe_mode(void) {
return false;
}
void reset_board(void) {
}

View File

@ -0,0 +1,179 @@
/*
* Copyright 2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexspi_nor_boot.h"
#include "boards/board.h"
__attribute__((section(".boot_hdr.ivt")))
/*************************************
* IVT Data
*************************************/
const ivt image_vector_table = {
IVT_HEADER, /* IVT Header */
IMAGE_ENTRY_ADDRESS, /* Image Entry Function */
IVT_RSVD, /* Reserved = 0 */
(uint32_t)DCD_ADDRESS, /* Address where DCD information is stored */
(uint32_t)BOOT_DATA_ADDRESS, /* Address where BOOT Data Structure is stored */
(uint32_t)&image_vector_table, /* Pointer to IVT Self (absolute address */
(uint32_t)CSF_ADDRESS, /* Address where CSF file is stored */
IVT_RSVD /* Reserved = 0 */
};
__attribute__((section(".boot_hdr.boot_data")))
/*************************************
* Boot Data
*************************************/
const BOOT_DATA_T boot_data = {
FLASH_BASE, /* boot start location */
FLASH_SIZE, /* size */
PLUGIN_FLAG, /* Plugin flag*/
0xFFFFFFFF /* empty - extra data word */
};
// Config for W25Q16JV with QSPI routed.
__attribute__((section(".boot_hdr.conf")))
const flexspi_nor_config_t qspiflash_config = {
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
.blockSize = 0x00010000,
.isUniformBlockSize = false,
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.busyOffset = 0u, // Status bit 0 indicates busy.
.busyBitPolarity = 0u, // Busy when the bit is 1.
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {
.seqId = 4u,
.seqNum = 1u,
},
.deviceModeArg = 0x0200,
.configCmdEnable = 1u,
.configModeType[0] = kDeviceConfigCmdType_Generic,
.configCmdSeqs[0] = {
.seqId = 2u,
.seqNum = 1u,
},
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz,
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// The high 16 bits is command 1 and the low are command 0.
// Within a command, the top 6 bits are the opcode, the next two are the number
// of pads and then last byte is the operand. The operand's meaning changes
// per opcode.
// Indices with ROM should always have the same function because the ROM
// bootloader uses it.
// 0: ROM: Read LUTs
// Quad version
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
READ_SDR, FLEXSPI_4PAD, 0x04),
// Single fast read version, good for debugging.
// FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
// RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
// READ_SDR, FLEXSPI_1PAD, 0x04),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 1: ROM: Read status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
READ_SDR, FLEXSPI_1PAD, 0x02),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 2: Empty
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x35 /* the command to send */,
DUMMY_SDR, FLEXSPI_1PAD, 8),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 3: ROM: Write Enable
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
STOP, FLEXSPI_1PAD, 0x00),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 4: Config: Write Status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01 /* the command to send */,
WRITE_SDR, FLEXSPI_1PAD, 0x02),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 5: ROM: Erase Sector
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 6: Empty
EMPTY_SEQUENCE,
// 7: Empty
EMPTY_SEQUENCE,
// 8: Block Erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 9: ROM: Page program
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 10: Empty
EMPTY_SEQUENCE,
// 11: ROM: Chip erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 12: Empty
EMPTY_SEQUENCE,
// 13: ROM: Read SFDP
EMPTY_SEQUENCE,
// 14: ROM: Restore no cmd
EMPTY_SEQUENCE,
// 15: ROM: Dummy
EMPTY_SEQUENCE
},
},
};

View File

@ -0,0 +1,20 @@
#define MICROPY_HW_BOARD_NAME "Metro MIMXRT1011"
#define MICROPY_HW_MCU_NAME "IMXRT1011DAE5A"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO_00)
// If you change this, then make sure to update the linker scripts as well to
// make sure you don't overwrite code
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define BOARD_FLASH_SIZE (2 * 1024 * 1024)
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO_02)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO_01)
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO_AD_06)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO_AD_04)
#define DEFAULT_SPI_BUS_MISO (&pin_GPIO_AD_03)
#define DEFAULT_UART_BUS_RX (&pin_GPIO_09)
#define DEFAULT_UART_BUS_TX (&pin_GPIO_10)

View File

@ -0,0 +1,12 @@
USB_VID = 0x239A
USB_PID = 0x80E2
USB_PRODUCT = "Metro M7 1011"
USB_MANUFACTURER = "Adafruit"
CHIP_VARIANT = MIMXRT1011DAE5A
CHIP_FAMILY = MIMXRT1011
FLASH = W25Q16JV
# Include these Python libraries in the firmware
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ESP32SPI
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests

View File

@ -0,0 +1,59 @@
#include "shared-bindings/board/__init__.h"
#include "boards/board.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
// Analog
{ MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO_AD_02) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO_AD_01) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO_AD_00) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO_AD_05) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO_AD_10) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO_AD_08) },
// Digital
{ MP_OBJ_NEW_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO_09) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO_09) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO_10) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO_10) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO_13) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO_12) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO_SD_00) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO_SD_01) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO_SD_02) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO_11) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO_08) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO_07) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO_06) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO_05) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO_04) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D13),MP_ROM_PTR(&pin_GPIO_03) },
// ESP control
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_CS), MP_ROM_PTR(&pin_GPIO_AD_14) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_GPIO0), MP_ROM_PTR(&pin_GPIO_SD_05) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_BUSY), MP_ROM_PTR(&pin_GPIO_AD_11) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RESET), MP_ROM_PTR(&pin_GPIO_AD_07) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_TX), MP_ROM_PTR(&pin_GPIO_09) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RX), MP_ROM_PTR(&pin_GPIO_10) },
// SPI
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO_AD_06) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO_AD_03) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO_AD_04) },
// UART
{ MP_OBJ_NEW_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO_10) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO_09) },
// I2C
{ MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO_01) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO_02) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO_00) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);

View File

@ -6,12 +6,8 @@
*/
#include "fsl_flexspi_nor_boot.h"
#include "fsl_flexspi_nor_config.h"
#include "boards/board.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.xip_device"
#endif
__attribute__((section(".boot_hdr.ivt")))
/*************************************
@ -39,88 +35,145 @@ const BOOT_DATA_T boot_data = {
0xFFFFFFFF /* empty - extra data word */
};
// Config for W25Q16JV with QSPI routed.
__attribute__((section(".boot_hdr.conf")))
// Values copied from https://github.com/PaulStoffregen/cores/blob/ddb23fa5d97dac763bc06e11b9b41f026bd51f0a/teensy4/bootdata.c#L39
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 1u,
.csSetupTime = 2u,
// Enable DDR mode, Wordaddressable, Safe configuration, Differential clock
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz, // 03
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) |
// FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
// Read LUTs
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
0,
0,
0x24040405,
0,
0,
0,
0,
0,
0,
0,
0x00000406,
0,
0,
0,
0,
0,
0,
0,
0x08180420,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x081804D8,
0,
0,
0,
0x08180402,
0x00002004,
0,
0,
0,
0,
0,
0,
0x00000460,
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
.blockSize = 0x00010000,
.isUniformBlockSize = false,
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.busyOffset = 0u, // Status bit 0 indicates busy.
.busyBitPolarity = 0u, // Busy when the bit is 1.
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {
.seqId = 4u,
.seqNum = 1u,
},
.deviceModeArg = 0x0200,
.configCmdEnable = 1u,
.configModeType[0] = kDeviceConfigCmdType_Generic,
.configCmdSeqs[0] = {
.seqId = 2u,
.seqNum = 1u,
},
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz,
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// The high 16 bits is command 1 and the low are command 0.
// Within a command, the top 6 bits are the opcode, the next two are the number
// of pads and then last byte is the operand. The operand's meaning changes
// per opcode.
// Indices with ROM should always have the same function because the ROM
// bootloader uses it.
// 0: ROM: Read LUTs
// Quad version
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
READ_SDR, FLEXSPI_4PAD, 0x04),
// Single fast read version, good for debugging.
// FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
// RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
// READ_SDR, FLEXSPI_1PAD, 0x04),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 1: ROM: Read status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
READ_SDR, FLEXSPI_1PAD, 0x02),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 2: Empty
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x35 /* the command to send */,
DUMMY_SDR, FLEXSPI_1PAD, 8),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 3: ROM: Write Enable
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
STOP, FLEXSPI_1PAD, 0x00),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 4: Config: Write Status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01 /* the command to send */,
WRITE_SDR, FLEXSPI_1PAD, 0x02),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 5: ROM: Erase Sector
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 6: Empty
EMPTY_SEQUENCE,
// 7: Empty
EMPTY_SEQUENCE,
// 8: Block Erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 9: ROM: Page program
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 10: Empty
EMPTY_SEQUENCE,
// 11: ROM: Chip erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 12: Empty
EMPTY_SEQUENCE,
// 13: ROM: Read SFDP
EMPTY_SEQUENCE,
// 14: ROM: Restore no cmd
EMPTY_SEQUENCE,
// 15: ROM: Dummy
EMPTY_SEQUENCE
},
},
};

View File

@ -6,12 +6,8 @@
*/
#include "fsl_flexspi_nor_boot.h"
#include "fsl_flexspi_nor_config.h"
#include "boards/board.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.xip_device"
#endif
__attribute__((section(".boot_hdr.ivt")))
/*************************************
@ -39,88 +35,135 @@ const BOOT_DATA_T boot_data = {
0xFFFFFFFF /* empty - extra data word */
};
// Config for W25Q64JV with QSPI routed.
__attribute__((section(".boot_hdr.conf")))
// Values copied from https://github.com/PaulStoffregen/cores/blob/ddb23fa5d97dac763bc06e11b9b41f026bd51f0a/teensy4/bootdata.c#L39
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 1u,
.csSetupTime = 2u,
// Enable DDR mode, Wordaddressable, Safe configuration, Differential clock
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz, // 03
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) |
// FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
// Read LUTs
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
0,
0,
0x24040405,
0,
0,
0,
0,
0,
0,
0,
0x00000406,
0,
0,
0,
0,
0,
0,
0,
0x08180420,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x081804D8,
0,
0,
0,
0x08180402,
0x00002004,
0,
0,
0,
0,
0,
0,
0x00000460,
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
.blockSize = 0x00010000,
.isUniformBlockSize = false,
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.busyOffset = 0u, // Status bit 0 indicates busy.
.busyBitPolarity = 0u, // Busy when the bit is 1.
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {
.seqId = 4u,
.seqNum = 1u,
},
.deviceModeArg = 0x02,
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_60MHz,
.sflashA1Size = FLASH_SIZE,
.lookupTable =
{
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
// The high 16 bits is command 1 and the low are command 0.
// Within a command, the top 6 bits are the opcode, the next two are the number
// of pads and then last byte is the operand. The operand's meaning changes
// per opcode.
// Indices with ROM should always have the same function because the ROM
// bootloader uses it.
// 0: ROM: Read LUTs
// Quad version
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
READ_SDR, FLEXSPI_4PAD, 0x04),
// Single fast read version, good for debugging.
// FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
// RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
// READ_SDR, FLEXSPI_1PAD, 0x04),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 1: ROM: Read status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
READ_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 2: Empty
EMPTY_SEQUENCE,
// 3: ROM: Write Enable
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
STOP, FLEXSPI_1PAD, 0x00),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 4: Config: Write Status
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x31 /* the command to send */,
WRITE_SDR, FLEXSPI_1PAD, 0x01),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 5: ROM: Erase Sector
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 6: Empty
EMPTY_SEQUENCE,
// 7: Empty
EMPTY_SEQUENCE,
// 8: Block Erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 9: ROM: Page program
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 10: Empty
EMPTY_SEQUENCE,
// 11: ROM: Chip erase
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
STOP, FLEXSPI_1PAD, 0),
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS,
TWO_EMPTY_STEPS),
// 12: Empty
EMPTY_SEQUENCE,
// 13: ROM: Read SFDP
EMPTY_SEQUENCE,
// 14: ROM: Restore no cmd
EMPTY_SEQUENCE,
// 15: ROM: Dummy
EMPTY_SEQUENCE
},
},
};

View File

@ -62,7 +62,6 @@ SECTIONS
KEEP(*(.isr_vector)) /* Startup code */
*(EXCLUDE_FILE(
*flexspi_nor_flash_ops.o
*fsl_flexspi.o
) .text*) /* .text* sections (code) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
@ -84,7 +83,6 @@ SECTIONS
{
. = ALIGN(4);
*(.data*) /* .data* sections */
*flexspi_nor_flash_ops.o(.text*)
*fsl_flexspi.o(.text*)
. = ALIGN(4);
} > OCRAM AT> FLASH_FIRMWARE
@ -110,7 +108,6 @@ SECTIONS
.itcm :
{
. = ALIGN(4);
*(.itcm.*)
. = ALIGN(4);

View File

@ -9,23 +9,10 @@
#include "fsl_flexspi.h"
#include "internal_flash.h"
#include "boards/board.h"
#include "supervisor/linker.h"
#define FLASH_QUAD_ENABLE 0x02
#define FLASH_BUSY_STATUS_POL 1
#define FLASH_BUSY_STATUS_OFFSET 0
static inline void flexspi_clock_init(void)
{
/* Switch to PLL2 for XIP to avoid hardfault during re-initialize clock. */
CLOCK_InitSysPfd(kCLOCK_Pfd2, 24); /* Set PLL2 PFD2 clock 396MHZ. */
CLOCK_SetMux(kCLOCK_FlexspiMux, 0x2); /* Choose PLL2 PFD2 clock as flexspi source clock. */
CLOCK_SetDiv(kCLOCK_FlexspiDiv, 2); /* flexspi clock 133M. */
}
extern flexspi_device_config_t deviceconfig;
extern const uint32_t customLUT[CUSTOM_LUT_LENGTH];
status_t flexspi_nor_write_enable(FLEXSPI_Type *base, uint32_t baseAddr)
status_t PLACE_IN_ITCM(flexspi_nor_write_enable)(FLEXSPI_Type *base, uint32_t baseAddr)
{
flexspi_transfer_t flashXfer;
status_t status;
@ -35,14 +22,14 @@ status_t flexspi_nor_write_enable(FLEXSPI_Type *base, uint32_t baseAddr)
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE;
flashXfer.seqIndex = ROM_INDEX_WRITEENABLE;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
return status;
}
status_t flexspi_nor_wait_bus_busy(FLEXSPI_Type *base)
status_t PLACE_IN_ITCM(flexspi_nor_wait_bus_busy)(FLEXSPI_Type *base)
{
/* Wait status ready. */
bool isBusy;
@ -54,7 +41,7 @@ status_t flexspi_nor_wait_bus_busy(FLEXSPI_Type *base)
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Read;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READSTATUSREG;
flashXfer.seqIndex = ROM_INDEX_READSTATUSREG;
flashXfer.data = &readValue;
flashXfer.dataSize = 1;
@ -66,72 +53,15 @@ status_t flexspi_nor_wait_bus_busy(FLEXSPI_Type *base)
{
return status;
}
if (FLASH_BUSY_STATUS_POL)
{
if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET))
{
isBusy = true;
}
else
{
isBusy = false;
}
}
else
{
if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET))
{
isBusy = false;
}
else
{
isBusy = true;
}
}
size_t busyBit = readValue & (1U << qspiflash_config.memConfig.busyOffset);
isBusy = (qspiflash_config.memConfig.busyBitPolarity == 0 && busyBit != 0) ||
(qspiflash_config.memConfig.busyBitPolarity == 1 && busyBit == 0);
} while (isBusy);
return status;
}
status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base)
{
flexspi_transfer_t flashXfer;
status_t status;
uint32_t writeValue = FLASH_QUAD_ENABLE;
/* Write enable */
status = flexspi_nor_write_enable(base, 0);
if (status != kStatus_Success)
{
return status;
}
/* Enable quad mode. */
flashXfer.deviceAddress = 0;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG;
flashXfer.data = &writeValue;
flashXfer.dataSize = 1;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
if (status != kStatus_Success)
{
return status;
}
status = flexspi_nor_wait_bus_busy(base);
/* Do software reset. */
FLEXSPI_SoftwareReset(base);
return status;
}
status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address)
status_t PLACE_IN_ITCM(flexspi_nor_flash_erase_sector)(FLEXSPI_Type *base, uint32_t address)
{
status_t status;
flexspi_transfer_t flashXfer;
@ -141,7 +71,7 @@ status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address)
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITEENABLE;
flashXfer.seqIndex = ROM_INDEX_WRITEENABLE;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
@ -154,7 +84,7 @@ status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address)
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASESECTOR;
flashXfer.seqIndex = ROM_INDEX_ERASESECTOR;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
if (status != kStatus_Success)
@ -170,7 +100,7 @@ status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address)
return status;
}
status_t flexspi_nor_flash_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src, uint32_t length)
status_t PLACE_IN_ITCM(flexspi_nor_flash_page_program)(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src)
{
status_t status;
flexspi_transfer_t flashXfer;
@ -188,48 +118,7 @@ status_t flexspi_nor_flash_program(FLEXSPI_Type *base, uint32_t dstAddr, const u
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD;
flashXfer.data = (uint32_t *)src;
flashXfer.dataSize = length;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
if (status != kStatus_Success)
{
return status;
}
status = flexspi_nor_wait_bus_busy(base);
/* Do software reset. */
#if defined(FSL_FEATURE_SOC_OTFAD_COUNT)
base->AHBCR |= FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK;
base->AHBCR &= ~(FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK);
#else
FLEXSPI_SoftwareReset(base);
#endif
return status;
}
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src)
{
status_t status;
flexspi_transfer_t flashXfer;
/* Write enable */
status = flexspi_nor_write_enable(base, dstAddr);
if (status != kStatus_Success)
{
return status;
}
/* Prepare page program command */
flashXfer.deviceAddress = dstAddr;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD;
flashXfer.seqIndex = ROM_INDEX_PAGEPROGRAM;
flashXfer.data = (uint32_t *)src;
flashXfer.dataSize = FLASH_PAGE_SIZE;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
@ -251,92 +140,3 @@ status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, co
return status;
}
status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId)
{
uint32_t temp;
flexspi_transfer_t flashXfer;
flashXfer.deviceAddress = 0;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Read;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READID;
flashXfer.data = &temp;
flashXfer.dataSize = 1;
status_t status = FLEXSPI_TransferBlocking(base, &flashXfer);
*vendorId = temp;
/* Do software reset. */
#if defined(FSL_FEATURE_SOC_OTFAD_COUNT)
base->AHBCR |= FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK;
base->AHBCR &= ~(FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK);
#else
FLEXSPI_SoftwareReset(base);
#endif
return status;
}
status_t flexspi_nor_erase_chip(FLEXSPI_Type *base)
{
status_t status;
flexspi_transfer_t flashXfer;
/* Write enable */
status = flexspi_nor_write_enable(base, 0);
if (status != kStatus_Success)
{
return status;
}
flashXfer.deviceAddress = 0;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASECHIP;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
if (status != kStatus_Success)
{
return status;
}
status = flexspi_nor_wait_bus_busy(base);
return status;
}
void flexspi_nor_flash_init(FLEXSPI_Type *base)
{
flexspi_config_t config;
flexspi_clock_init();
/*Get FLEXSPI default settings and configure the flexspi. */
FLEXSPI_GetDefaultConfig(&config);
/*Set AHB buffer size for reading data through AHB bus. */
config.ahbConfig.enableAHBPrefetch = true;
config.ahbConfig.enableAHBBufferable = true;
config.ahbConfig.enableReadAddressOpt = true;
config.ahbConfig.enableAHBCachable = true;
#ifdef BOARD_USING_SECONDARY_QSPI_PINMUX
config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally;
#else
config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;
#endif
FLEXSPI_Init(base, &config);
/* Configure flash settings according to serial flash feature. */
FLEXSPI_SetFlashConfig(base, &deviceconfig, kFLEXSPI_PortA1);
/* Update LUT table. */
FLEXSPI_UpdateLUT(base, 0, customLUT, CUSTOM_LUT_LENGTH);
/* Do software reset. */
FLEXSPI_SoftwareReset(base);
}

View File

@ -30,6 +30,7 @@
#include <string.h>
#include <stdio.h>
#include "boards/board.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "py/mphal.h"
@ -50,125 +51,14 @@ extern uint32_t __fatfs_flash_length[];
uint8_t _flash_cache[SECTOR_SIZE] __attribute__((aligned(4)));
uint32_t _flash_page_addr = NO_CACHE;
static bool init_done = false;
flexspi_device_config_t deviceconfig = {
.flexspiRootClk = 133000000,
.flashSize = (BOARD_FLASH_SIZE / 1024),
.CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
.CSInterval = 2,
.CSHoldTime = 3,
.CSSetupTime = 3,
.dataValidTime = 0,
.columnspace = 0,
.enableWordAddress = 0,
.AWRSeqIndex = 0,
.AWRSeqNumber = 0,
.ARDSeqIndex = NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD,
.ARDSeqNumber = 1,
.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
.AHBWriteWaitInterval = 0,
};
const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
/* Normal read mode -SDR */
/* Normal read mode -SDR */
[4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x03, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 1] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Fast read mode - SDR */
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0B, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST + 1] = FLEXSPI_LUT_SEQ(
kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x08, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
/* Fast read quad mode - SDR */
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xEB, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] = FLEXSPI_LUT_SEQ(
kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x06, kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04),
/* Read extend parameters */
[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUS] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x81, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
/* Write Enable */
[4 * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Erase Sector */
[4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x20, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
/* Page Program - single mode */
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE + 1] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Page Program - quad mode */
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD + 1] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Read ID */
[4 * NOR_CMD_LUT_SEQ_IDX_READID] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
/* Enable Quad mode */
[4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x31, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),
/* Read status register */
[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
/* Erase whole chip */
[4 * NOR_CMD_LUT_SEQ_IDX_ERASECHIP] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xC7, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
};
extern status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
extern status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src);
extern status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId);
extern status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base);
extern status_t flexspi_nor_erase_chip(FLEXSPI_Type *base);
extern void flexspi_nor_flash_init(FLEXSPI_Type *base);
void supervisor_flash_init(void) {
if (init_done)
return;
SCB_DisableDCache();
status_t status;
uint8_t vendorID = 0;
flexspi_nor_flash_init(FLEXSPI);
/* Get vendor ID. */
status = flexspi_nor_get_vendor_id(FLEXSPI, &vendorID);
if (status != kStatus_Success) {
printf("flexspi_nor_get_vendor_id fail %ld\r\n", status);
return;
}
/* Enter quad mode. */
__disable_irq();
status = flexspi_nor_enable_quad_mode(FLEXSPI);
if (status != kStatus_Success)
{
printf("flexspi_nor_enable_quad_mode fail %ld\r\n", status);
return;
}
__enable_irq();
SCB_EnableDCache();
init_done = true;
void PLACE_IN_ITCM(supervisor_flash_init)(void) {
// Update the LUT to make sure all entries are available.
FLEXSPI_UpdateLUT(FLEXSPI, 0, (const uint32_t*) &qspiflash_config.memConfig.lookupTable, 64);
}
static inline uint32_t lba2addr(uint32_t block) {
@ -183,7 +73,7 @@ uint32_t supervisor_flash_get_block_count(void) {
return CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE;
}
void port_internal_flash_flush(void) {
void PLACE_IN_ITCM(port_internal_flash_flush)(void) {
if (_flash_page_addr == NO_CACHE) return;
status_t status;
@ -211,6 +101,7 @@ void port_internal_flash_flush(void) {
DCACHE_CleanInvalidateByRange(_flash_page_addr, SECTOR_SIZE);
}
_flash_page_addr = NO_CACHE;
}
mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {

View File

@ -34,20 +34,11 @@
#define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms
#define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2)
#define CUSTOM_LUT_LENGTH 60
#define FLASH_PAGE_SIZE 256
#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 7
#define NOR_CMD_LUT_SEQ_IDX_READ_FAST 13
#define NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD 0
#define NOR_CMD_LUT_SEQ_IDX_READSTATUS 1
#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE 2
#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 3
#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE 6
#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD 4
#define NOR_CMD_LUT_SEQ_IDX_READID 8
#define NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG 9
#define NOR_CMD_LUT_SEQ_IDX_READSTATUSREG 12
#define NOR_CMD_LUT_SEQ_IDX_ERASECHIP 5
#define ROM_INDEX_WRITEENABLE 3
#define ROM_INDEX_ERASESECTOR 5
#define ROM_INDEX_PAGEPROGRAM 9
#define ROM_INDEX_READSTATUSREG 1
#endif // MICROPY_INCLUDED_MIMXRT10XX_INTERNAL_FLASH_H

View File

@ -72,7 +72,8 @@
#define NO_EXECUTION 1
#define EXECUTION 0
// Shareable if the memory system manages coherency.
// Shareable if the memory system manages coherency. This means shared between memory bus masters,
// not just CPUs.
#define NOT_SHAREABLE 0
#define SHAREABLE 1
@ -207,9 +208,11 @@ __attribute__((used, naked)) void Reset_Handler(void) {
MPU->RBAR = ARM_MPU_RBAR(13, 0x20000000U);
MPU->RASR = ARM_MPU_RASR(EXECUTION, ARM_MPU_AP_FULL, NORMAL, NOT_SHAREABLE, CACHEABLE, BUFFERABLE, NO_SUBREGIONS, ARM_MPU_REGION_SIZE_32KB);
// This is OCRAM.
// This is OCRAM. We mark it as shareable so that it isn't cached. This makes USB work at the
// cost of 1/4 speed OCRAM accesses. It will leave more room for caching data from the flash
// too which might be a net win.
MPU->RBAR = ARM_MPU_RBAR(14, 0x20200000U);
MPU->RASR = ARM_MPU_RASR(EXECUTION, ARM_MPU_AP_FULL, NORMAL, NOT_SHAREABLE, CACHEABLE, BUFFERABLE, NO_SUBREGIONS, ARM_MPU_REGION_SIZE_512KB);
MPU->RASR = ARM_MPU_RASR(EXECUTION, ARM_MPU_AP_FULL, NORMAL, SHAREABLE, CACHEABLE, BUFFERABLE, NO_SUBREGIONS, ARM_MPU_REGION_SIZE_512KB);
// We steal 64k from FlexRAM for ITCM and DTCM so disable those memory regions here.
MPU->RBAR = ARM_MPU_RBAR(15, 0x20280000U);
@ -322,19 +325,22 @@ void reset_cpu(void) {
reset();
}
supervisor_allocation* port_fixed_stack(void) {
return NULL;
}
extern uint32_t _ld_heap_start, _ld_heap_end, _ld_stack_top, _ld_stack_bottom;
uint32_t *port_stack_get_limit(void) {
return &_ld_heap_start;
return &_ld_stack_bottom;
}
uint32_t *port_stack_get_top(void) {
return &_ld_stack_top;
}
supervisor_allocation _fixed_stack;
supervisor_allocation* port_fixed_stack(void) {
_fixed_stack.ptr = port_stack_get_limit();
_fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t);
return &_fixed_stack;
}
uint32_t *port_heap_get_bottom(void) {
return &_ld_heap_start;
}

View File

@ -50,10 +50,6 @@ void init_usb_hardware(void) {
phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK);
phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06);
usb_phy->TX = phytx;
// Temporarily disable the data cache until we can sort out all of the spots in TinyUSB that
// need the cache invalidated or cleaned.
SCB_DisableDCache();
}
void USB_OTG1_IRQHandler(void) {

View File

@ -29,6 +29,7 @@
#include "py/gc.h"
#include "py/mpconfig.h"
#include "supervisor/background_callback.h"
#include "supervisor/linker.h"
#include "supervisor/shared/tick.h"
#include "shared-bindings/microcontroller/__init__.h"
@ -63,7 +64,7 @@ void background_callback_add(background_callback_t *cb, background_callback_fun
}
static bool in_background_callback;
void background_callback_run_all() {
void PLACE_IN_ITCM(background_callback_run_all)() {
if (!callback_head) {
return;
}

View File

@ -105,13 +105,19 @@ void filesystem_init(bool create_allowed, bool force_create) {
// set label
#ifdef CIRCUITPY_DRIVE_LABEL
f_setlabel(&vfs_fat->fatfs, CIRCUITPY_DRIVE_LABEL);
res = f_setlabel(&vfs_fat->fatfs, CIRCUITPY_DRIVE_LABEL);
#else
f_setlabel(&vfs_fat->fatfs, "CIRCUITPY");
res = f_setlabel(&vfs_fat->fatfs, "CIRCUITPY");
#endif
if (res != FR_OK) {
return;
}
// inhibit file indexing on MacOS
f_mkdir(&vfs_fat->fatfs, "/.fseventsd");
res = f_mkdir(&vfs_fat->fatfs, "/.fseventsd");
if (res != FR_OK) {
return;
}
make_empty_file(&vfs_fat->fatfs, "/.metadata_never_index");
make_empty_file(&vfs_fat->fatfs, "/.Trashes");
make_empty_file(&vfs_fat->fatfs, "/.fseventsd/no_log");
@ -119,7 +125,10 @@ void filesystem_init(bool create_allowed, bool force_create) {
make_sample_code_file(&vfs_fat->fatfs);
// create empty lib directory
f_mkdir(&vfs_fat->fatfs, "/lib");
res = f_mkdir(&vfs_fat->fatfs, "/lib");
if (res != FR_OK) {
return;
}
// and ensure everything is flushed
supervisor_flash_flush();

View File

@ -88,9 +88,6 @@ static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_blo
mp_uint_t flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
if (block_num == 0) {
if (num_blocks > 1) {
return 1; // error
}
// fake the MBR so we can decide on our own partition table
for (int i = 0; i < 446; i++) {
@ -104,9 +101,13 @@ mp_uint_t flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_bloc
dest[510] = 0x55;
dest[511] = 0xaa;
return 0; // ok
if (num_blocks > 1) {
dest += 512;
num_blocks -= 1;
// Fall through and do a read from flash.
} else {
return 0; // Done and ok.
}
}
return supervisor_flash_read_blocks(dest, block_num - PART1_START_BLOCK, num_blocks);
}
@ -159,16 +160,37 @@ STATIC mp_obj_t supervisor_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_n
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_writeblocks_obj, supervisor_flash_obj_writeblocks);
bool flash_ioctl(size_t cmd, mp_int_t* out_value) {
*out_value = 0;
switch (cmd) {
case BP_IOCTL_INIT:
supervisor_flash_init();
break;
case BP_IOCTL_DEINIT:
supervisor_flash_flush();
break; // TODO properly
case BP_IOCTL_SYNC:
supervisor_flash_flush();
break;
case BP_IOCTL_SEC_COUNT:
*out_value = flash_get_block_count();
break;
case BP_IOCTL_SEC_SIZE:
*out_value = supervisor_flash_get_block_size();
break;
default:
return false;
}
return true;
}
STATIC mp_obj_t supervisor_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) {
mp_int_t cmd = mp_obj_get_int(cmd_in);
switch (cmd) {
case BP_IOCTL_INIT: supervisor_flash_init(); return MP_OBJ_NEW_SMALL_INT(0);
case BP_IOCTL_DEINIT: supervisor_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly
case BP_IOCTL_SYNC: supervisor_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0);
case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(flash_get_block_count());
case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(supervisor_flash_get_block_size());
default: return mp_const_none;
mp_int_t out_value;
if (flash_ioctl(cmd, &out_value)) {
return MP_OBJ_NEW_SMALL_INT(out_value);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_ioctl_obj, supervisor_flash_obj_ioctl);
@ -200,4 +222,5 @@ void supervisor_flash_init_vfs(fs_user_mount_t *vfs) {
vfs->writeblocks[2] = (mp_obj_t)flash_write_blocks; // native version
vfs->u.ioctl[0] = (mp_obj_t)&supervisor_flash_obj_ioctl_obj;
vfs->u.ioctl[1] = (mp_obj_t)&supervisor_flash_obj;
vfs->u.ioctl[2] = (mp_obj_t)flash_ioctl; // native version
}