Skip to content

Commit 09bc415

Browse files
committed
Unify iMX flash config and add Metro M7 1011
This unifies the flash config to the settings used by the Boot ROM. This makes the config unique per board which allows for changing quad enable and status bit differences per flash device. It also allows for timing differences due to the board layout. This change also tweaks linker layout to leave more ram space for the CircuitPython heap.
1 parent 66c2566 commit 09bc415

File tree

26 files changed

+1394
-961
lines changed

26 files changed

+1394
-961
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ jobs:
243243
- "metro_m0_express"
244244
- "metro_m4_airlift_lite"
245245
- "metro_m4_express"
246+
- "metro_m7_1011"
246247
- "metro_nrf52840_express"
247248
- "mini_sam_m4"
248249
- "monster_m4sk"

extmod/vfs_fat_diskio.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ DRESULT disk_write (
123123

124124
DRESULT disk_ioctl (
125125
bdev_t pdrv, /* Physical drive nmuber (0..) */
126-
BYTE cmd, /* Control code */
126+
BYTE cmd, /* Control code */
127127
void *buff /* Buffer to send/receive control data */
128128
)
129129
{
@@ -133,7 +133,7 @@ DRESULT disk_ioctl (
133133
}
134134

135135
// First part: call the relevant method of the underlying block device
136-
mp_obj_t ret = mp_const_none;
136+
mp_int_t out_value = 0;
137137
if (vfs->flags & FSUSER_HAVE_IOCTL) {
138138
// new protocol with ioctl
139139
static const uint8_t op_map[8] = {
@@ -144,9 +144,19 @@ DRESULT disk_ioctl (
144144
};
145145
uint8_t bp_op = op_map[cmd & 7];
146146
if (bp_op != 0) {
147-
vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op);
148-
vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
149-
ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl);
147+
if (vfs->flags & FSUSER_NATIVE) {
148+
bool (*f)(size_t, mp_int_t*) = (void*)(uintptr_t)vfs->u.ioctl[2];
149+
if (!f(bp_op, (mp_int_t*) &out_value)) {
150+
return RES_ERROR;
151+
}
152+
} else {
153+
vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op);
154+
vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
155+
mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl);
156+
if (ret != mp_const_none) {
157+
out_value = mp_obj_get_int(ret);
158+
}
159+
}
150160
}
151161
} else {
152162
// old protocol with sync and count
@@ -157,10 +167,13 @@ DRESULT disk_ioctl (
157167
}
158168
break;
159169

160-
case GET_SECTOR_COUNT:
161-
ret = mp_call_method_n_kw(0, 0, vfs->u.old.count);
170+
case GET_SECTOR_COUNT: {
171+
mp_obj_t ret = mp_call_method_n_kw(0, 0, vfs->u.old.count);
172+
if (ret != mp_const_none) {
173+
out_value = mp_obj_get_int(ret);
174+
}
162175
break;
163-
176+
}
164177
case GET_SECTOR_SIZE:
165178
// old protocol has fixed sector size of 512 bytes
166179
break;
@@ -177,16 +190,16 @@ DRESULT disk_ioctl (
177190
return RES_OK;
178191

179192
case GET_SECTOR_COUNT: {
180-
*((DWORD*)buff) = mp_obj_get_int(ret);
193+
*((DWORD*)buff) = out_value;
181194
return RES_OK;
182195
}
183196

184197
case GET_SECTOR_SIZE: {
185-
if (ret == mp_const_none) {
198+
if (out_value == 0) {
186199
// Default sector size
187200
*((WORD*)buff) = 512;
188201
} else {
189-
*((WORD*)buff) = mp_obj_get_int(ret);
202+
*((WORD*)buff) = out_value;
190203
}
191204
#if _MAX_SS != _MIN_SS
192205
// need to store ssize because we use it in disk_read/disk_write
@@ -202,7 +215,7 @@ DRESULT disk_ioctl (
202215
case IOCTL_INIT:
203216
case IOCTL_STATUS: {
204217
DSTATUS stat;
205-
if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
218+
if (out_value != 0) {
206219
// error initialising
207220
stat = STA_NOINIT;
208221
} else if (vfs->writeblocks[0] == MP_OBJ_NULL) {

ports/mimxrt10xx/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ INC += \
7575

7676
# NDEBUG disables assert() statements. This reduces code size pretty dramatically, per tannewt.
7777

78-
CFLAGS += -Os -DNDEBUG
78+
CFLAGS += -Os -DNDEBUG -ffreestanding
7979

8080
# TinyUSB defines
8181
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

ports/mimxrt10xx/boards/board.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
#include "py/mpconfig.h"
3535
#include "fsl_common.h"
36+
#include "fsl_flexspi_nor_config.h"
3637

3738
// Initializes board related state once on start up.
3839
void board_init(void);
@@ -45,4 +46,11 @@ bool board_requests_safe_mode(void);
4546
// Reset the state of off MCU components such as neopixels.
4647
void reset_board(void);
4748

49+
#define SEQUENCE(first, second, third, fourth) first, second, third, fourth
50+
#define TWO_EMPTY_STEPS 0x00000000
51+
#define EMPTY_SEQUENCE SEQUENCE(TWO_EMPTY_STEPS, TWO_EMPTY_STEPS, TWO_EMPTY_STEPS, TWO_EMPTY_STEPS)
52+
53+
// FlexSPI configuration that stores command info.
54+
extern const flexspi_nor_config_t qspiflash_config;
55+
4856
#endif // MICROPY_INCLUDED_MIMXRT10XX_BOARDS_BOARD_H

ports/mimxrt10xx/boards/feather_m7_1011/flash_config.c

Lines changed: 117 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
#include "fsl_flexspi_nor_boot.h"
9-
#include "fsl_flexspi_nor_config.h"
9+
#include "boards/board.h"
1010

1111

1212
__attribute__((section(".boot_hdr.ivt")))
@@ -35,88 +35,135 @@ const BOOT_DATA_T boot_data = {
3535
0xFFFFFFFF /* empty - extra data word */
3636
};
3737

38+
// Config for W25Q32JV with QSPI routed.
3839
__attribute__((section(".boot_hdr.conf")))
39-
// Values copied from https://github.com/PaulStoffregen/cores/blob/ddb23fa5d97dac763bc06e11b9b41f026bd51f0a/teensy4/bootdata.c#L39
4040
const flexspi_nor_config_t qspiflash_config = {
41+
.pageSize = 256u,
42+
.sectorSize = 4u * 1024u,
43+
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
44+
.blockSize = 0x00010000,
45+
.isUniformBlockSize = false,
4146
.memConfig =
4247
{
4348
.tag = FLEXSPI_CFG_BLK_TAG,
4449
.version = FLEXSPI_CFG_BLK_VERSION,
4550
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
46-
.csHoldTime = 1u,
47-
.csSetupTime = 2u,
48-
// Enable DDR mode, Wordaddressable, Safe configuration, Differential clock
51+
.csHoldTime = 3u,
52+
.csSetupTime = 3u,
53+
54+
.busyOffset = 0u, // Status bit 0 indicates busy.
55+
.busyBitPolarity = 0u, // Busy when the bit is 1.
56+
57+
.deviceModeCfgEnable = 1u,
58+
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
59+
.deviceModeSeq = {
60+
.seqId = 4u,
61+
.seqNum = 1u,
62+
},
63+
.deviceModeArg = 0x02, // Bit pattern for setting Quad Enable.
4964
.deviceType = kFlexSpiDeviceType_SerialNOR,
5065
.sflashPadType = kSerialFlash_4Pads,
51-
.serialClkFreq = kFlexSpiSerialClk_60MHz, // 03
66+
.serialClkFreq = kFlexSpiSerialClk_133MHz,
5267
.sflashA1Size = FLASH_SIZE,
5368
.lookupTable =
5469
{
5570
// FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1)
56-
// (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) |
57-
// FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
58-
// Read LUTs
59-
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
60-
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
61-
0,
62-
0,
63-
64-
0x24040405,
65-
0,
66-
0,
67-
0,
68-
69-
0,
70-
0,
71-
0,
72-
0,
73-
74-
0x00000406,
75-
0,
76-
0,
77-
0,
78-
79-
0,
80-
0,
81-
0,
82-
0,
83-
84-
0x08180420,
85-
0,
86-
0,
87-
0,
88-
89-
0,
90-
0,
91-
0,
92-
0,
93-
94-
0,
95-
0,
96-
0,
97-
0,
98-
99-
0x081804D8,
100-
0,
101-
0,
102-
0,
103-
104-
0x08180402,
105-
0x00002004,
106-
0,
107-
0,
108-
109-
0,
110-
0,
111-
0,
112-
0,
113-
114-
0x00000460,
71+
// The high 16 bits is command 1 and the low are command 0.
72+
// Within a command, the top 6 bits are the opcode, the next two are the number
73+
// of pads and then last byte is the operand. The operand's meaning changes
74+
// per opcode.
75+
76+
// Indices with ROM should always have the same function because the ROM
77+
// bootloader uses it.
78+
79+
// 0: ROM: Read LUTs
80+
// Quad version
81+
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */,
82+
RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */),
83+
FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */,
84+
READ_SDR, FLEXSPI_4PAD, 0x04),
85+
// Single fast read version, good for debugging.
86+
// FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */,
87+
// RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
88+
// FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */,
89+
// READ_SDR, FLEXSPI_1PAD, 0x04),
90+
TWO_EMPTY_STEPS,
91+
TWO_EMPTY_STEPS),
92+
93+
// 1: ROM: Read status
94+
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */,
95+
READ_SDR, FLEXSPI_1PAD, 0x02),
96+
TWO_EMPTY_STEPS,
97+
TWO_EMPTY_STEPS,
98+
TWO_EMPTY_STEPS),
99+
100+
// 2: Empty
101+
EMPTY_SEQUENCE,
102+
103+
// 3: ROM: Write Enable
104+
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */,
105+
STOP, FLEXSPI_1PAD, 0x00),
106+
TWO_EMPTY_STEPS,
107+
TWO_EMPTY_STEPS,
108+
TWO_EMPTY_STEPS),
109+
110+
// 4: Config: Write Status -2
111+
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x31 /* the command to send */,
112+
WRITE_SDR, FLEXSPI_1PAD, 0x01 /* number of bytes to write */),
113+
TWO_EMPTY_STEPS,
114+
TWO_EMPTY_STEPS,
115+
TWO_EMPTY_STEPS),
116+
117+
// 5: ROM: Erase Sector
118+
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */,
119+
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
120+
TWO_EMPTY_STEPS,
121+
TWO_EMPTY_STEPS,
122+
TWO_EMPTY_STEPS),
123+
124+
// 6: Empty
125+
EMPTY_SEQUENCE,
126+
127+
// 7: Empty
128+
EMPTY_SEQUENCE,
129+
130+
// 8: Block Erase
131+
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */,
132+
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
133+
TWO_EMPTY_STEPS,
134+
TWO_EMPTY_STEPS,
135+
TWO_EMPTY_STEPS),
136+
137+
// 9: ROM: Page program
138+
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */,
139+
RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */),
140+
141+
FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */,
142+
STOP, FLEXSPI_1PAD, 0),
143+
TWO_EMPTY_STEPS,
144+
TWO_EMPTY_STEPS),
145+
146+
// 10: Empty
147+
EMPTY_SEQUENCE,
148+
149+
// 11: ROM: Chip erase
150+
SEQUENCE(FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */,
151+
STOP, FLEXSPI_1PAD, 0),
152+
TWO_EMPTY_STEPS,
153+
TWO_EMPTY_STEPS,
154+
TWO_EMPTY_STEPS),
155+
156+
// 12: Empty
157+
EMPTY_SEQUENCE,
158+
159+
// 13: ROM: Read SFDP
160+
EMPTY_SEQUENCE,
161+
162+
// 14: ROM: Restore no cmd
163+
EMPTY_SEQUENCE,
164+
165+
// 15: ROM: Dummy
166+
EMPTY_SEQUENCE
115167
},
116168
},
117-
.pageSize = 256u,
118-
.sectorSize = 4u * 1024u,
119-
.ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
120-
.blockSize = 0x00010000,
121-
.isUniformBlockSize = false,
122169
};

0 commit comments

Comments
 (0)