Skip to content

Commit 3aa0d7a

Browse files
committed
MXRT1050: Add support for Flash driver
Signed-off-by: Mahesh Mahadevan <[email protected]>
1 parent e46e482 commit 3aa0d7a

File tree

5 files changed

+568
-5
lines changed

5 files changed

+568
-5
lines changed
Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2019 ARM Limited
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "flash_api.h"
19+
#include "mbed_toolchain.h"
20+
#include "mbed_critical.h"
21+
22+
#if DEVICE_FLASH
23+
24+
#include "fsl_flexspi.h"
25+
#include "fsl_cache.h"
26+
#include "flash_defines.h"
27+
28+
AT_QUICKACCESS_SECTION_CODE(void flexspi_update_lut_ram(void));
29+
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_write_enable_ram(uint32_t baseAddr));
30+
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_wait_bus_busy_ram(void));
31+
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_flash_erase_sector_ram(uint32_t address));
32+
AT_QUICKACCESS_SECTION_CODE(static void flexspi_lower_clock_ram(void));
33+
AT_QUICKACCESS_SECTION_CODE(static void flexspi_clock_update_ram(void));
34+
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_flash_page_program_ram(uint32_t address,
35+
const uint32_t *src,
36+
uint32_t size));
37+
AT_QUICKACCESS_SECTION_CODE(void flexspi_nor_flash_read_data_ram(uint32_t addr,
38+
uint32_t *buffer,
39+
uint32_t size));
40+
41+
void flexspi_update_lut_ram(void)
42+
{
43+
flexspi_config_t config;
44+
45+
memset(&config, 0, sizeof(config));
46+
47+
/*Get FLEXSPI default settings and configure the flexspi. */
48+
FLEXSPI_GetDefaultConfig(&config);
49+
50+
/*Set AHB buffer size for reading data through AHB bus. */
51+
config.ahbConfig.enableAHBPrefetch = true;
52+
/*Allow AHB read start address do not follow the alignment requirement. */
53+
config.ahbConfig.enableReadAddressOpt = true;
54+
config.ahbConfig.enableAHBBufferable = true;
55+
config.ahbConfig.enableAHBCachable = true;
56+
/* enable diff clock and DQS */
57+
config.enableSckBDiffOpt = true;
58+
config.rxSampleClock = kFLEXSPI_ReadSampleClkExternalInputFromDqsPad;
59+
config.enableCombination = true;
60+
FLEXSPI_Init(FLEXSPI, &config);
61+
62+
/* Configure flash settings according to serial flash feature. */
63+
FLEXSPI_SetFlashConfig(FLEXSPI, &deviceconfig, kFLEXSPI_PortA1);
64+
65+
/* Update LUT table. */
66+
FLEXSPI_UpdateLUT(FLEXSPI, 0, customLUT, CUSTOM_LUT_LENGTH);
67+
68+
FLEXSPI_SoftwareReset(FLEXSPI);
69+
70+
/* Wait for bus idle. */
71+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
72+
}
73+
}
74+
75+
status_t flexspi_nor_write_enable_ram(uint32_t baseAddr)
76+
{
77+
flexspi_transfer_t flashXfer;
78+
status_t status = kStatus_Success;
79+
80+
memset(&flashXfer, 0, sizeof(flashXfer));
81+
82+
/* Write enable */
83+
flashXfer.deviceAddress = baseAddr;
84+
flashXfer.port = kFLEXSPI_PortA1;
85+
flashXfer.cmdType = kFLEXSPI_Command;
86+
flashXfer.SeqNumber = 2;
87+
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE;
88+
89+
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
90+
91+
return status;
92+
}
93+
94+
status_t flexspi_nor_wait_bus_busy_ram(void)
95+
{
96+
/* Wait status ready. */
97+
bool isBusy = false;
98+
uint32_t readValue = 0;
99+
status_t status = kStatus_Success;
100+
flexspi_transfer_t flashXfer;
101+
102+
memset(&flashXfer, 0, sizeof(flashXfer));
103+
104+
flashXfer.deviceAddress = 0;
105+
flashXfer.port = kFLEXSPI_PortA1;
106+
flashXfer.cmdType = kFLEXSPI_Read;
107+
flashXfer.SeqNumber = 2;
108+
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS;
109+
flashXfer.data = &readValue;
110+
flashXfer.dataSize = 2;
111+
112+
do {
113+
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
114+
115+
if (status != kStatus_Success) {
116+
return status;
117+
}
118+
119+
if (readValue & 0x8000) {
120+
isBusy = false;
121+
} else {
122+
isBusy = true;
123+
}
124+
125+
if (readValue & 0x3200) {
126+
status = kStatus_Fail;
127+
break;
128+
}
129+
130+
} while (isBusy);
131+
132+
return status;
133+
134+
}
135+
136+
status_t flexspi_nor_flash_erase_sector_ram(uint32_t address)
137+
{
138+
status_t status = kStatus_Success;
139+
flexspi_transfer_t flashXfer;
140+
141+
memset(&flashXfer, 0, sizeof(flashXfer));
142+
143+
/* Write enable */
144+
status = flexspi_nor_write_enable_ram(address);
145+
if (status != kStatus_Success) {
146+
return status;
147+
}
148+
149+
flashXfer.deviceAddress = address;
150+
flashXfer.port = kFLEXSPI_PortA1;
151+
flashXfer.cmdType = kFLEXSPI_Command;
152+
flashXfer.SeqNumber = 4;
153+
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR;
154+
155+
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
156+
if (status != kStatus_Success) {
157+
return status;
158+
}
159+
160+
status = flexspi_nor_wait_bus_busy_ram();
161+
162+
/* Do software reset. */
163+
FLEXSPI_SoftwareReset(FLEXSPI);
164+
165+
return status;
166+
}
167+
168+
static void flexspi_lower_clock_ram(void)
169+
{
170+
unsigned int reg = 0;
171+
172+
/* Wait for bus idle. */
173+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
174+
}
175+
176+
FLEXSPI_Enable(FLEXSPI, false);
177+
178+
/* Disable FlexSPI clock */
179+
CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK;
180+
181+
/* flexspi clock 66M, DDR mode, internal clock 33M. */
182+
reg = CCM->CSCMR1;
183+
reg &= ~CCM_CSCMR1_FLEXSPI_PODF_MASK;
184+
reg |= CCM_CSCMR1_FLEXSPI_PODF(3);
185+
CCM->CSCMR1 = reg;
186+
187+
/* Enable FlexSPI clock */
188+
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;
189+
190+
FLEXSPI_Enable(FLEXSPI, true);
191+
192+
/* Do software reset. */
193+
FLEXSPI_SoftwareReset(FLEXSPI);
194+
195+
/* Wait for bus idle. */
196+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
197+
}
198+
}
199+
200+
static void flexspi_clock_update_ram(void)
201+
{
202+
/* Program finished, speed the clock to 133M. */
203+
/* Wait for bus idle before change flash configuration. */
204+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
205+
}
206+
FLEXSPI_Enable(FLEXSPI, false);
207+
/* Disable FlexSPI clock */
208+
CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK;
209+
210+
/* flexspi clock 260M, DDR mode, internal clock 130M. */
211+
CCM->CSCMR1 &= ~CCM_CSCMR1_FLEXSPI_PODF_MASK;
212+
213+
/* Enable FlexSPI clock */
214+
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;
215+
216+
FLEXSPI_Enable(FLEXSPI, true);
217+
218+
/* Do software reset. */
219+
FLEXSPI_SoftwareReset(FLEXSPI);
220+
221+
/* Wait for bus idle. */
222+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
223+
}
224+
}
225+
226+
status_t flexspi_nor_flash_page_program_ram(uint32_t address, const uint32_t *src, uint32_t size)
227+
{
228+
status_t status = kStatus_Success;
229+
flexspi_transfer_t flashXfer;
230+
uint32_t offset = 0;
231+
232+
memset(&flashXfer, 0, sizeof(flashXfer));
233+
234+
flexspi_lower_clock_ram();
235+
236+
while (size > 0) {
237+
if (status != kStatus_Success) {
238+
return status;
239+
}
240+
241+
/* Write enable */
242+
status = flexspi_nor_write_enable_ram(address + offset);
243+
244+
/* Prepare page program command */
245+
flashXfer.deviceAddress = address + offset;
246+
flashXfer.port = kFLEXSPI_PortA1;
247+
flashXfer.cmdType = kFLEXSPI_Write;
248+
flashXfer.SeqNumber = 2;
249+
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM;
250+
flashXfer.data = (uint32_t *)(src + offset);
251+
flashXfer.dataSize = BOARD_FLASH_PAGE_SIZE;
252+
253+
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
254+
255+
if (status != kStatus_Success) {
256+
return status;
257+
}
258+
259+
status = flexspi_nor_wait_bus_busy_ram();
260+
261+
size -= BOARD_FLASH_PAGE_SIZE;
262+
offset += BOARD_FLASH_PAGE_SIZE;
263+
}
264+
265+
flexspi_clock_update_ram();
266+
267+
return status;
268+
}
269+
270+
void flexspi_nor_flash_read_data_ram(uint32_t addr, uint32_t *buffer, uint32_t size)
271+
{
272+
memcpy(buffer, (void *)addr, size);
273+
}
274+
275+
int32_t flash_init(flash_t *obj)
276+
{
277+
flexspi_update_lut_ram();
278+
279+
return 0;
280+
}
281+
282+
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
283+
{
284+
status_t status = kStatus_Success;
285+
int32_t ret = 0;
286+
287+
core_util_critical_section_enter();
288+
289+
status = flexspi_nor_flash_erase_sector_ram(address - FlexSPI_AMBA_BASE);
290+
291+
if (status != kStatus_Success) {
292+
ret = -1;
293+
} else {
294+
DCACHE_InvalidateByRange(address, BOARD_FLASH_SECTOR_SIZE);
295+
}
296+
297+
core_util_critical_section_exit();
298+
299+
return ret;
300+
}
301+
302+
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
303+
{
304+
status_t status = kStatus_Success;
305+
int32_t ret = 0;
306+
307+
core_util_critical_section_enter();
308+
309+
status = flexspi_nor_flash_page_program_ram(address - FlexSPI_AMBA_BASE, (uint32_t *)data, size);
310+
311+
if (status != kStatus_Success) {
312+
ret = -1;
313+
} else {
314+
DCACHE_InvalidateByRange(address, size);
315+
}
316+
317+
core_util_critical_section_exit();
318+
319+
return ret;
320+
}
321+
322+
int32_t flash_read(flash_t *obj, uint32_t address, uint8_t *data, uint32_t size)
323+
{
324+
flexspi_nor_flash_read_data_ram(address, (uint32_t *)data, size);
325+
326+
return 0;
327+
}
328+
329+
int32_t flash_free(flash_t *obj)
330+
{
331+
return 0;
332+
}
333+
334+
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
335+
{
336+
uint32_t sectorsize = MBED_FLASH_INVALID_SIZE;
337+
uint32_t devicesize = BOARD_FLASH_SIZE;
338+
uint32_t startaddr = BOARD_FLASH_START_ADDR;
339+
340+
if ((address >= startaddr) && (address < (startaddr + devicesize))) {
341+
sectorsize = BOARD_FLASH_SECTOR_SIZE;
342+
}
343+
344+
return sectorsize;
345+
}
346+
347+
uint32_t flash_get_page_size(const flash_t *obj)
348+
{
349+
return BOARD_FLASH_PAGE_SIZE;
350+
}
351+
352+
uint32_t flash_get_start_address(const flash_t *obj)
353+
{
354+
return BOARD_FLASH_START_ADDR;
355+
}
356+
357+
uint32_t flash_get_size(const flash_t *obj)
358+
{
359+
return BOARD_FLASH_SIZE;
360+
}
361+
362+
uint8_t flash_get_erase_value(const flash_t *obj)
363+
{
364+
(void)obj;
365+
366+
return 0xFF;
367+
}
368+
369+
#endif //DEVICE_FLASH
370+

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/objects.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ struct trng_s {
6666
uint8_t dummy;
6767
};
6868

69+
#if DEVICE_FLASH
70+
struct flash_s {
71+
uint8_t dummy;
72+
};
73+
#endif
74+
6975
#include "gpio_object.h"
7076

7177
#ifdef __cplusplus

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/device.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919
#define MBED_DEVICE_H
2020

2121
#define DEVICE_ID_LENGTH 24
22-
#define BOARD_FLASH_SIZE (0x4000000U)
22+
/* 4MB reserved for mbed-os */
23+
#define BOARD_FLASH_SIZE (0x3C00000U)
24+
#define BOARD_FLASH_START_ADDR (0x60400000U)
25+
26+
#define BOARD_FLASH_PAGE_SIZE (512)
27+
#define BOARD_FLASH_SECTOR_SIZE (262144)
28+
2329
#define BOARD_ENET_PHY_ADDR (2)
2430

2531
#include "objects.h"

0 commit comments

Comments
 (0)