Skip to content

Commit

Permalink
MXRT1050: Add support for Flash driver
Browse files Browse the repository at this point in the history
Signed-off-by: Mahesh Mahadevan <[email protected]>
  • Loading branch information
mmahadevan108 committed Feb 3, 2020
1 parent e46e482 commit 42a90cc
Show file tree
Hide file tree
Showing 5 changed files with 572 additions and 5 deletions.
374 changes: 374 additions & 0 deletions targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/flash_api.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,374 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "flash_api.h"
#include "mbed_toolchain.h"
#include "mbed_critical.h"

#if DEVICE_FLASH

#include "fsl_flexspi.h"
#include "fsl_cache.h"
#include "flash_defines.h"

AT_QUICKACCESS_SECTION_CODE(void flexspi_update_lut_ram(void));
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_write_enable_ram(uint32_t baseAddr));
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_wait_bus_busy_ram(void));
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_flash_erase_sector_ram(uint32_t address));
AT_QUICKACCESS_SECTION_CODE(static void flexspi_lower_clock_ram(void));
AT_QUICKACCESS_SECTION_CODE(static void flexspi_clock_update_ram(void));
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_flash_page_program_ram(uint32_t address,
const uint32_t *src,
uint32_t size));
AT_QUICKACCESS_SECTION_CODE(void flexspi_nor_flash_read_data_ram(uint32_t addr,
uint32_t *buffer,
uint32_t size));

void flexspi_update_lut_ram(void)
{
flexspi_config_t config;

memset(&config, 0, sizeof(config));

/*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;
/*Allow AHB read start address do not follow the alignment requirement. */
config.ahbConfig.enableReadAddressOpt = true;
config.ahbConfig.enableAHBBufferable = true;
config.ahbConfig.enableAHBCachable = true;
/* enable diff clock and DQS */
config.enableSckBDiffOpt = true;
config.rxSampleClock = kFLEXSPI_ReadSampleClkExternalInputFromDqsPad;
config.enableCombination = true;
FLEXSPI_Init(FLEXSPI, &config);

/* Configure flash settings according to serial flash feature. */
FLEXSPI_SetFlashConfig(FLEXSPI, &deviceconfig, kFLEXSPI_PortA1);

/* Update LUT table. */
FLEXSPI_UpdateLUT(FLEXSPI, 0, customLUT, CUSTOM_LUT_LENGTH);

FLEXSPI_SoftwareReset(FLEXSPI);

/* Wait for bus idle. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
}

status_t flexspi_nor_write_enable_ram(uint32_t baseAddr)
{
flexspi_transfer_t flashXfer;
status_t status = kStatus_Success;

memset(&flashXfer, 0, sizeof(flashXfer));

/* Write enable */
flashXfer.deviceAddress = baseAddr;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 2;
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE;

status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);

return status;
}

status_t flexspi_nor_wait_bus_busy_ram(void)
{
/* Wait status ready. */
bool isBusy = false;
uint32_t readValue = 0;
status_t status = kStatus_Success;
flexspi_transfer_t flashXfer;

memset(&flashXfer, 0, sizeof(flashXfer));

flashXfer.deviceAddress = 0;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Read;
flashXfer.SeqNumber = 2;
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS;
flashXfer.data = &readValue;
flashXfer.dataSize = 2;

do {
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);

if (status != kStatus_Success) {
return status;
}

if (readValue & 0x8000) {
isBusy = false;
} else {
isBusy = true;
}

if (readValue & 0x3200) {
status = kStatus_Fail;
break;
}

} while (isBusy);

return status;

}

status_t flexspi_nor_flash_erase_sector_ram(uint32_t address)
{
status_t status = kStatus_Success;
flexspi_transfer_t flashXfer;

memset(&flashXfer, 0, sizeof(flashXfer));

/* Write enable */
status = flexspi_nor_write_enable_ram(address);
if (status != kStatus_Success) {
return status;
}

flashXfer.deviceAddress = address;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 4;
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR;

status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
if (status != kStatus_Success) {
return status;
}

status = flexspi_nor_wait_bus_busy_ram();

/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);

return status;
}

static void flexspi_lower_clock_ram(void)
{
unsigned int reg = 0;

/* Wait for bus idle. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}

FLEXSPI_Enable(FLEXSPI, false);

/* Disable FlexSPI clock */
CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK;

/* flexspi clock 66M, DDR mode, internal clock 33M. */
reg = CCM->CSCMR1;
reg &= ~CCM_CSCMR1_FLEXSPI_PODF_MASK;
reg |= CCM_CSCMR1_FLEXSPI_PODF(3);
CCM->CSCMR1 = reg;

/* Enable FlexSPI clock */
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;

FLEXSPI_Enable(FLEXSPI, true);

/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);

/* Wait for bus idle. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
}

static void flexspi_clock_update_ram(void)
{
/* Program finished, speed the clock to 133M. */
/* Wait for bus idle before change flash configuration. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
FLEXSPI_Enable(FLEXSPI, false);
/* Disable FlexSPI clock */
CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK;

/* flexspi clock 260M, DDR mode, internal clock 130M. */
CCM->CSCMR1 &= ~CCM_CSCMR1_FLEXSPI_PODF_MASK;

/* Enable FlexSPI clock */
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;

FLEXSPI_Enable(FLEXSPI, true);

/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);

/* Wait for bus idle. */
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
}
}

status_t flexspi_nor_flash_page_program_ram(uint32_t address, const uint32_t *src, uint32_t size)
{
status_t status = kStatus_Success;
flexspi_transfer_t flashXfer;
uint32_t offset = 0;

memset(&flashXfer, 0, sizeof(flashXfer));

flexspi_lower_clock_ram();

while (size > 0) {
/* Write enable */
status = flexspi_nor_write_enable_ram(address + offset);

if (status != kStatus_Success) {
return status;
}

/* Prepare page program command */
flashXfer.deviceAddress = address + offset;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 2;
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM;
flashXfer.data = (uint32_t *)(src + offset);
flashXfer.dataSize = BOARD_FLASH_PAGE_SIZE;

status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);

if (status != kStatus_Success) {
return status;
}

status = flexspi_nor_wait_bus_busy_ram();

if (status != kStatus_Success) {
return status;
}

size -= BOARD_FLASH_PAGE_SIZE;
offset += BOARD_FLASH_PAGE_SIZE;
}

flexspi_clock_update_ram();

return status;
}

void flexspi_nor_flash_read_data_ram(uint32_t addr, uint32_t *buffer, uint32_t size)
{
memcpy(buffer, (void *)addr, size);
}

int32_t flash_init(flash_t *obj)
{
flexspi_update_lut_ram();

return 0;
}

int32_t flash_erase_sector(flash_t *obj, uint32_t address)
{
status_t status = kStatus_Success;
int32_t ret = 0;

core_util_critical_section_enter();

status = flexspi_nor_flash_erase_sector_ram(address - FlexSPI_AMBA_BASE);

if (status != kStatus_Success) {
ret = -1;
} else {
DCACHE_InvalidateByRange(address, BOARD_FLASH_SECTOR_SIZE);
}

core_util_critical_section_exit();

return ret;
}

int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
{
status_t status = kStatus_Success;
int32_t ret = 0;

core_util_critical_section_enter();

status = flexspi_nor_flash_page_program_ram(address - FlexSPI_AMBA_BASE, (uint32_t *)data, size);

if (status != kStatus_Success) {
ret = -1;
} else {
DCACHE_InvalidateByRange(address, size);
}

core_util_critical_section_exit();

return ret;
}

int32_t flash_read(flash_t *obj, uint32_t address, uint8_t *data, uint32_t size)
{
flexspi_nor_flash_read_data_ram(address, (uint32_t *)data, size);

return 0;
}

int32_t flash_free(flash_t *obj)
{
return 0;
}

uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
{
uint32_t sectorsize = MBED_FLASH_INVALID_SIZE;
uint32_t devicesize = BOARD_FLASH_SIZE;
uint32_t startaddr = BOARD_FLASH_START_ADDR;

if ((address >= startaddr) && (address < (startaddr + devicesize))) {
sectorsize = BOARD_FLASH_SECTOR_SIZE;
}

return sectorsize;
}

uint32_t flash_get_page_size(const flash_t *obj)
{
return BOARD_FLASH_PAGE_SIZE;
}

uint32_t flash_get_start_address(const flash_t *obj)
{
return BOARD_FLASH_START_ADDR;
}

uint32_t flash_get_size(const flash_t *obj)
{
return BOARD_FLASH_SIZE;
}

uint8_t flash_get_erase_value(const flash_t *obj)
{
(void)obj;

return 0xFF;
}

#endif //DEVICE_FLASH

Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ struct trng_s {
uint8_t dummy;
};

#if DEVICE_FLASH
struct flash_s {
uint8_t dummy;
};
#endif

#include "gpio_object.h"

#ifdef __cplusplus
Expand Down
Loading

0 comments on commit 42a90cc

Please sign in to comment.