mirror of https://github.com/ARMmbed/mbed-os.git
commit
00c5b56e32
|
@ -0,0 +1,250 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 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://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.
|
||||
*/
|
||||
#ifndef MBED_QSPI_FLASH_MT25Q_H
|
||||
#define MBED_QSPI_FLASH_MT25Q_H
|
||||
#define QSPI_FLASH_CHIP_STRING "Micron MT25Q"
|
||||
// Command for reading status register
|
||||
#define QSPI_CMD_RDSR 0x05
|
||||
// Command for reading configuration register 0 (NONVOLATILE CONFIGURATION REGISTER)
|
||||
#define QSPI_CMD_RDCR0 0xB5
|
||||
// Command for reading configuration register 1 (VOLATILE CONFIGURATION REGISTER)
|
||||
#define QSPI_CMD_RDCR1 0x85
|
||||
// Command for reading configuration register 2 (ENHANCED VOLATILE CONFIGURATION REGISTER)
|
||||
#define QSPI_CMD_RDCR2 0x65
|
||||
// Command for writing status register
|
||||
#define QSPI_CMD_WRSR 0x01
|
||||
// Command for writing configuration register 0 (NONVOLATILE CONFIGURATION REGISTER)
|
||||
#define QSPI_CMD_WRCR0 0xB1
|
||||
// Command for writing configuration register 1 (VOLATILE CONFIGURATION REGISTER)
|
||||
#define QSPI_CMD_WRCR1 0x81
|
||||
// Command for writing configuration register 2 (ENHANCED VOLATILE CONFIGURATION REGISTER)
|
||||
#define QSPI_CMD_WRCR2 0x61
|
||||
// Command for setting Reset Enable
|
||||
#define QSPI_CMD_RSTEN 0x66
|
||||
// Command for setting Reset
|
||||
#define QSPI_CMD_RST 0x99
|
||||
// Command for setting write enable
|
||||
#define QSPI_CMD_WREN 0x06
|
||||
// Command for setting write disable
|
||||
#define QSPI_CMD_WRDI 0x04
|
||||
// WRSR operations max time [us] (datasheet max time + 15%)
|
||||
#define QSPI_WRSR_MAX_TIME 9200 // 8ms
|
||||
// general wait max time [us]
|
||||
#define QSPI_WAIT_MAX_TIME 100000 // 100ms
|
||||
// Commands for writing (page programming)
|
||||
#define QSPI_CMD_WRITE_1IO 0x02 // 1-1-1 mode
|
||||
#define QSPI_CMD_WRITE_1I2O 0xA2 // 1-1-2 mode
|
||||
#define QSPI_CMD_WRITE_2IO 0xD2 // 1-2-2 mode
|
||||
#define QSPI_CMD_WRITE_1I4O 0x32 // 1-1-4 mode
|
||||
#define QSPI_CMD_WRITE_4IO 0x38 // 1-4-4 mode
|
||||
#define QSPI_CMD_WRITE_DPI 0xD2 // 2-2-2 mode
|
||||
#define QSPI_CMD_WRITE_QPI 0x38 // 4-4-4 mode
|
||||
// write operations max time [us] (datasheet max time + 15%)
|
||||
#define QSPI_PAGE_PROG_MAX_TIME 2070 // 1.8ms
|
||||
#define QSPI_PAGE_SIZE 256 // 256B
|
||||
#define QSPI_SECTOR_SIZE 4096 // 4kB
|
||||
#define QSPI_SECTOR_COUNT 4096 // for 128Mb chip
|
||||
// Commands for reading
|
||||
#define QSPI_CMD_READ_1IO_FAST 0x0B // 1-1-1 mode
|
||||
#define QSPI_CMD_READ_1IO 0x03 // 1-1-1 mode
|
||||
#define QSPI_CMD_READ_1I2O 0x3B // 1-1-2 mode
|
||||
#define QSPI_CMD_READ_2IO 0xBB // 1-2-2 mode
|
||||
#define QSPI_CMD_READ_DPI 0xBB // 2-2-2 mode
|
||||
#define QSPI_CMD_READ_1I4O 0x6B // 1-1-4 mode
|
||||
#define QSPI_CMD_READ_4IO 0xEB // 1-4-4 mode
|
||||
#define QSPI_CMD_READ_QPI 0xEB // 4-4-4 mode
|
||||
#define QSPI_READ_1IO_DUMMY_CYCLE 0 // 1-1-1 mode
|
||||
#define QSPI_READ_FAST_DUMMY_CYCLE 8 // 1-1-1 mode
|
||||
#define QSPI_READ_1I2O_DUMMY_CYCLE 8 // 1-1-2 mode
|
||||
#define QSPI_READ_2IO_DUMMY_CYCLE 8 // 1-2-2 mode
|
||||
#define QSPI_READ_DPI_DUMMY_CYCLE 8 // 2-2-2 mode
|
||||
#define QSPI_READ_1I4O_DUMMY_CYCLE 8 // 1-1-4 mode
|
||||
#define QSPI_READ_4IO_DUMMY_CYCLE 10 // 1-4-4 mode
|
||||
#define QSPI_READ_QPI_DUMMY_CYCLE 10 // 4-4-4 mode
|
||||
// Commands for erasing
|
||||
#define QSPI_CMD_ERASE_SECTOR 0x20 // 4kB
|
||||
#define QSPI_CMD_ERASE_BLOCK_32 0x52 // 32kB
|
||||
#define QSPI_CMD_ERASE_BLOCK_64 0xD8 // 64kB
|
||||
#define QSPI_CMD_ERASE_CHIP 0x60 // or 0xC7
|
||||
// erase operations max time [us] (datasheet max time + 15%)
|
||||
#define QSPI_ERASE_SECTOR_MAX_TIME 460000 // 0.4s
|
||||
#define QSPI_ERASE_BLOCK_32_MAX_TIME 1150000 // 1s
|
||||
#define QSPI_ERASE_BLOCK_64_MAX_TIME 1150000 // 1s
|
||||
// max frequency for basic rw operation
|
||||
#define QSPI_COMMON_MAX_FREQUENCY 50000000
|
||||
#define QSPI_STATUS_REG_SIZE 1
|
||||
#define QSPI_CONFIG_REG_0_SIZE 2
|
||||
#define QSPI_CONFIG_REG_1_SIZE 1
|
||||
#define QSPI_CONFIG_REG_2_SIZE 1
|
||||
#define QSPI_MAX_REG_SIZE 2
|
||||
// status register
|
||||
#define STATUS_BIT_WIP (1 << 0) // write in progress bit
|
||||
#define STATUS_BIT_WEL (1 << 1) // write enable latch
|
||||
#define STATUS_BIT_BP0 (1 << 2) // Block protect
|
||||
#define STATUS_BIT_BP1 (1 << 3) // Block protect
|
||||
#define STATUS_BIT_BP2 (1 << 4) // Block protect
|
||||
#define STATUS_BIT_BP_TB (1 << 5) // Block protect top/bottom
|
||||
#define STATUS_BIT_BP3 (1 << 6) // Block protect
|
||||
#define STATUS_BIT_SRWD (1 << 7) // status register write protect
|
||||
// configuration register 0 (Nonvolatile Configuration Register)
|
||||
// bit 0, 1 reserved
|
||||
#define CONFIG0_BIT_DE (1 << 2) // Dual Enable 0 = Enabled / 1 = Disabled
|
||||
#define CONFIG0_BIT_QE (1 << 3) // Quad Enable 0 = Enabled / 1 = Disabled
|
||||
#define CONFIG0_BIT_RH (1 << 4) // Reset/hold
|
||||
#define CONFIG0_BIT_DTR (1 << 5) // Double transfer rate protocol
|
||||
#define CONFIG0_BIT_ODS0 (1 << 6) // Output driver strength
|
||||
#define CONFIG0_BIT_ODS1 (1 << 7) // Output driver strength
|
||||
#define CONFIG0_BIT_ODS2 (1 << 8) // Output driver strength
|
||||
#define CONFIG0_BIT_XIP_MODE0 (1 << 9) // XIP mode at power-on reset
|
||||
#define CONFIG0_BIT_XIP_MODE1 (1 << 10) // XIP mode at power-on reset
|
||||
#define CONFIG0_BIT_XIP_MODE2 (1 << 11) // XIP mode at power-on reset
|
||||
#define CONFIG0_BIT_DCYCLE0 (1 << 12) // Dummy Cycle
|
||||
#define CONFIG0_BIT_DCYCLE1 (1 << 13) // Dummy Cycle
|
||||
#define CONFIG0_BIT_DCYCLE2 (1 << 14) // Dummy Cycle
|
||||
#define CONFIG0_BIT_DCYCLE3 (1 << 15) // Dummy Cycle
|
||||
// configuration register 1 (Volatile Configuration Register)
|
||||
// bit 2, reserved
|
||||
#define CONFIG1_BIT_WRAP0 (1 << 0) // Output data wrap
|
||||
#define CONFIG1_BIT_WRAP1 (1 << 1) // Output data wrap
|
||||
#define CONFIG1_BIT_XIP (1 << 3) // 0 = Enable / 1 = Disable (default)
|
||||
#define CONFIG1_BIT_DCYCLE0 (1 << 4) // Number of dummy clock cycles
|
||||
#define CONFIG1_BIT_DCYCLE1 (1 << 5) // Number of dummy clock cycles
|
||||
#define CONFIG1_BIT_DCYCLE2 (1 << 6) // Number of dummy clock cycles
|
||||
#define CONFIG1_BIT_DCYCLE3 (1 << 7) // Number of dummy clock cycles
|
||||
// configuration register 2 (Enhanced Volatile Configuration Register)
|
||||
// bit 3, reserved
|
||||
#define CONFIG2_BIT_ODS0 (1 << 0) // Output driver strength 111 = 30 Ohms (Default)
|
||||
#define CONFIG2_BIT_ODS1 (1 << 1) // Output driver strength
|
||||
#define CONFIG2_BIT_ODS2 (1 << 2) // Output driver strength
|
||||
#define CONFIG2_BIT_RH (1 << 4) // Reset/hold
|
||||
#define CONFIG2_BIT_DTR (1 << 5) // Double transfer rate protocol
|
||||
#define CONFIG2_BIT_DE (1 << 6) // Dual I/O protocol 0 = Enabled / 1 = Disabled (Default, extended SPI protocol)
|
||||
#define CONFIG2_BIT_QE (1 << 7) // Quad I/O protocol 0 = Enabled / 1 = Disabled (Default, extended SPI protocol)
|
||||
#define DUAL_ENABLE() \
|
||||
\
|
||||
uint8_t reg_data[QSPI_CONFIG_REG_2_SIZE]; \
|
||||
\
|
||||
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
|
||||
if (read_register(QSPI_CMD_RDCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
if (write_enable(qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
reg_data[0] = reg_data[0] & ~(CONFIG2_BIT_DE); \
|
||||
if (write_register(QSPI_CMD_WRCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
qspi.cmd.configure(MODE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8); \
|
||||
WAIT_FOR(WRSR_MAX_TIME, qspi); \
|
||||
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
|
||||
if (read_register(QSPI_CMD_RDCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
return ((reg_data[0] & (CONFIG2_BIT_DE)) == 0 ? \
|
||||
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
|
||||
#define DUAL_DISABLE() \
|
||||
\
|
||||
uint8_t reg_data[QSPI_CONFIG_REG_2_SIZE]; \
|
||||
\
|
||||
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
|
||||
if (read_register(QSPI_CMD_RDCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
if (write_enable(qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
reg_data[0] = reg_data[0] | (CONFIG2_BIT_DE); \
|
||||
if (write_register(QSPI_CMD_WRCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); \
|
||||
WAIT_FOR(WRSR_MAX_TIME, qspi); \
|
||||
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
|
||||
if (read_register(QSPI_CMD_RDCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
return ((reg_data[0] & CONFIG2_BIT_DE) != 1 ? \
|
||||
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
|
||||
#define QUAD_ENABLE() \
|
||||
\
|
||||
uint8_t reg_data[QSPI_CONFIG_REG_2_SIZE]; \
|
||||
\
|
||||
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
|
||||
if (read_register(QSPI_CMD_RDCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
if (write_enable(qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
reg_data[0] = reg_data[0] & ~(CONFIG2_BIT_QE); \
|
||||
if (write_register(QSPI_CMD_WRCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
qspi.cmd.configure(MODE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8); \
|
||||
WAIT_FOR(WRSR_MAX_TIME, qspi); \
|
||||
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
|
||||
if (read_register(QSPI_CMD_RDCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
return ((reg_data[0] & (CONFIG2_BIT_QE)) == 0 ? \
|
||||
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
|
||||
#define QUAD_DISABLE() \
|
||||
\
|
||||
uint8_t reg_data[QSPI_CONFIG_REG_2_SIZE]; \
|
||||
\
|
||||
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
|
||||
if (read_register(QSPI_CMD_RDCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
if (write_enable(qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
reg_data[0] = reg_data[0] | (CONFIG2_BIT_QE); \
|
||||
if (write_register(QSPI_CMD_WRCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); \
|
||||
WAIT_FOR(WRSR_MAX_TIME, qspi); \
|
||||
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
|
||||
if (read_register(QSPI_CMD_RDCR2, reg_data, \
|
||||
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
return ((reg_data[0] & CONFIG2_BIT_QE) != 1 ? \
|
||||
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
|
||||
#endif // MBED_QSPI_FLASH_MT25Q_H
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* 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://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.
|
||||
*/
|
||||
#ifndef MBED_QSPI_FLASH_CONFIG_H
|
||||
#define MBED_QSPI_FLASH_CONFIG_H
|
||||
|
||||
#include "../../MT25Q_config.h"
|
||||
|
||||
#endif // MBED_QSPI_FLASH_CONFIG_H
|
|
@ -26,9 +26,11 @@
|
|||
#elif defined(TARGET_EFM32GG11_STK3701)
|
||||
#include "SiliconLabs/EFM32GG11_STK3701/flash_config.h"
|
||||
#elif defined(TARGET_K82F)
|
||||
#include "Freescale/K82F/flash_config.h"
|
||||
#include "NXP/K82F/flash_config.h"
|
||||
#elif defined(TARGET_KL82Z)
|
||||
#include "Freescale/KL82Z/flash_config.h"
|
||||
#include "NXP/KL82Z/flash_config.h"
|
||||
#elif defined(TARGET_LPC546XX)
|
||||
#include "NXP/LPC546XX/flash_config.h"
|
||||
#endif
|
||||
|
||||
#endif // MBED_FLASH_CONFIGS_H
|
||||
|
|
|
@ -50,4 +50,11 @@ extern const PinMap PinMap_SPI_SSEL[];
|
|||
/************PWM***************/
|
||||
extern const PinMap PinMap_PWM[];
|
||||
|
||||
#if DEVICE_QSPI
|
||||
/************QSPI***************/
|
||||
extern const PinMap PinMap_QSPI_DATA[];
|
||||
extern const PinMap PinMap_QSPI_SCLK[];
|
||||
extern const PinMap PinMap_QSPI_SSEL[];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "PortNames.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "PinNames.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -70,6 +71,12 @@ struct trng_s {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if DEVICE_QSPI
|
||||
struct qspi_s {
|
||||
uint32_t instance;
|
||||
};
|
||||
#endif
|
||||
|
||||
#include "gpio_object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -0,0 +1,342 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018, 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://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.
|
||||
*/
|
||||
|
||||
#if DEVICE_QSPI
|
||||
|
||||
#include "qspi_api.h"
|
||||
#include "mbed_error.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "PeripheralPins.h"
|
||||
#include "qspi_device.h"
|
||||
|
||||
/* Command table indices */
|
||||
#define COMMAND_READ_INDEX (0)
|
||||
#define COMMAND_WRITE_INDEX (1)
|
||||
|
||||
#define LUT1_SEQ_INDEX 0 // Pre-defined read sequence
|
||||
#define LUT2_SEQ_INDEX 4 // Pre-defined write sequence
|
||||
#define LUT3_SEQ_INDEX 8 // User-define sequence
|
||||
/* Minimum write size */
|
||||
#define MIN_SIZE 16 // At least four words of data must be written into the TX Buffer
|
||||
|
||||
/* Array of QSPI peripheral base address. */
|
||||
static SPIFI_Type *const qspi_addrs[] = SPIFI_BASE_PTRS;
|
||||
|
||||
extern uint32_t qspi_get_freq(void);
|
||||
|
||||
qspi_status_t qspi_init(qspi_t *obj, PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel, uint32_t hz, uint8_t mode)
|
||||
{
|
||||
spifi_config_t config = {0};
|
||||
|
||||
uint32_t qspiio0name = pinmap_peripheral(io0, PinMap_QSPI_DATA);
|
||||
uint32_t qspiio1name = pinmap_peripheral(io1, PinMap_QSPI_DATA);
|
||||
uint32_t qspiio2name = pinmap_peripheral(io2, PinMap_QSPI_DATA);
|
||||
uint32_t qspiio3name = pinmap_peripheral(io3, PinMap_QSPI_DATA);
|
||||
uint32_t qspiclkname = pinmap_peripheral(sclk, PinMap_QSPI_SCLK);
|
||||
uint32_t qspisselname = pinmap_peripheral(ssel, PinMap_QSPI_SSEL);
|
||||
|
||||
uint32_t qspi_data_first = pinmap_merge(qspiio0name, qspiio1name);
|
||||
uint32_t qspi_data_second = pinmap_merge(qspiio2name, qspiio3name);
|
||||
uint32_t qspi_data_third = pinmap_merge(qspiclkname, qspisselname);
|
||||
|
||||
if (qspi_data_first != qspi_data_second || qspi_data_second != qspi_data_third ||
|
||||
qspi_data_first != qspi_data_third) {
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (qspi_frequency(obj, hz) != QSPI_STATUS_OK) {
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Initialize SPIFI */
|
||||
SPIFI_GetDefaultConfig(&config);
|
||||
SPIFI_Init(SPIFI0, &config);
|
||||
|
||||
// tested all combinations, take first
|
||||
obj->instance = qspi_data_first;
|
||||
|
||||
pinmap_pinout(io0, PinMap_QSPI_DATA);
|
||||
pinmap_pinout(io1, PinMap_QSPI_DATA);
|
||||
pinmap_pinout(io2, PinMap_QSPI_DATA);
|
||||
pinmap_pinout(io3, PinMap_QSPI_DATA);
|
||||
|
||||
pinmap_pinout(sclk, PinMap_QSPI_SCLK);
|
||||
pinmap_pinout(ssel, PinMap_QSPI_SSEL);
|
||||
|
||||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
qspi_status_t qspi_free(qspi_t *obj)
|
||||
{
|
||||
SPIFI_Deinit(qspi_addrs[obj->instance]);
|
||||
|
||||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
qspi_status_t qspi_frequency(qspi_t *obj, int hz)
|
||||
{
|
||||
qspi_status_t status = QSPI_STATUS_OK;
|
||||
int div = qspi_get_freq() / hz;
|
||||
|
||||
if ((qspi_get_freq() % hz) != 0) {
|
||||
/* Incase the exact requested baud rate can be derived then set right div,
|
||||
* else set baudrate to the closest lower value
|
||||
*/
|
||||
div++;
|
||||
}
|
||||
|
||||
if (div > 256 || div < 1) {
|
||||
status = QSPI_STATUS_INVALID_PARAMETER;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Set the clock divider */
|
||||
CLOCK_SetClkDiv(kCLOCK_DivSpifiClk, div, false);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void qspi_prepare_command(qspi_t *obj, const qspi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size)
|
||||
{
|
||||
spifi_command_t spifi_command = {0};
|
||||
SPIFI_Type *base = qspi_addrs[obj->instance];
|
||||
bool use_memory_command = false;
|
||||
|
||||
/* Set the opcode & poll mode */
|
||||
spifi_command.opcode = command->instruction.value;
|
||||
spifi_command.isPollMode = false;
|
||||
|
||||
/* Check if this is a data transmit */
|
||||
if (tx_data != NULL && tx_size) {
|
||||
spifi_command.dataLen = tx_size;
|
||||
spifi_command.direction = kSPIFI_DataOutput;
|
||||
}
|
||||
|
||||
/* Check if this is a data receive */
|
||||
if (rx_data != NULL && rx_size) {
|
||||
spifi_command.dataLen = rx_size;
|
||||
spifi_command.direction = kSPIFI_DataInput;
|
||||
}
|
||||
|
||||
/* Check if we need to set dual bit */
|
||||
if ((command->instruction.bus_width == QSPI_CFG_BUS_DUAL) ||
|
||||
(command->address.bus_width == QSPI_CFG_BUS_DUAL) ||
|
||||
(command->data.bus_width == QSPI_CFG_BUS_DUAL)) {
|
||||
base->CTRL |= SPIFI_CTRL_DUAL_MASK;
|
||||
} else {
|
||||
base->CTRL &= ~SPIFI_CTRL_DUAL_MASK;
|
||||
}
|
||||
|
||||
if (command->address.disabled == true) {
|
||||
/* No flash address specified */
|
||||
spifi_command.type = kSPIFI_CommandOpcodeOnly;
|
||||
spifi_command.format = kSPIFI_CommandAllSerial;
|
||||
if ((command->instruction.bus_width == QSPI_CFG_BUS_DUAL) ||
|
||||
(command->instruction.bus_width == QSPI_CFG_BUS_QUAD)) {
|
||||
spifi_command.format = kSPIFI_CommandAllQuad;
|
||||
}
|
||||
} else {
|
||||
/* Set the address size */
|
||||
spifi_command.type = (spifi_command_type_t)(command->address.size + 2);
|
||||
|
||||
/* Default to 1-1-1 mode */
|
||||
spifi_command.format = kSPIFI_CommandAllSerial;
|
||||
|
||||
/* Check if it is 2-2-2 or 4-4-4 mode */
|
||||
if (((command->instruction.bus_width == QSPI_CFG_BUS_DUAL) &&
|
||||
(command->address.bus_width == QSPI_CFG_BUS_DUAL) &&
|
||||
(command->data.bus_width == QSPI_CFG_BUS_DUAL)) ||
|
||||
((command->instruction.bus_width == QSPI_CFG_BUS_QUAD) &&
|
||||
(command->address.bus_width == QSPI_CFG_BUS_QUAD) &&
|
||||
(command->data.bus_width == QSPI_CFG_BUS_QUAD))) {
|
||||
/* All quad/dual. All fields of the command are in quad/dual format. */
|
||||
spifi_command.format = kSPIFI_CommandAllQuad;
|
||||
}
|
||||
|
||||
/* Check if it is 1-2-2 or 1-4-4 mode */
|
||||
if (((command->instruction.bus_width == QSPI_CFG_BUS_SINGLE) &&
|
||||
(command->address.bus_width == QSPI_CFG_BUS_DUAL) &&
|
||||
(command->data.bus_width == QSPI_CFG_BUS_DUAL)) ||
|
||||
((command->instruction.bus_width == QSPI_CFG_BUS_SINGLE) &&
|
||||
(command->address.bus_width == QSPI_CFG_BUS_QUAD) &&
|
||||
(command->data.bus_width == QSPI_CFG_BUS_QUAD))) {
|
||||
/* Serial opcode. Opcode field is serial. Other fields are quad/dual. */
|
||||
spifi_command.format = kSPIFI_CommandOpcodeSerial;
|
||||
}
|
||||
|
||||
/* Check if it is 1-1-2 or 1-1-4 mode */
|
||||
if (((command->instruction.bus_width == QSPI_CFG_BUS_SINGLE) &&
|
||||
(command->address.bus_width == QSPI_CFG_BUS_SINGLE) &&
|
||||
(command->data.bus_width == QSPI_CFG_BUS_DUAL)) ||
|
||||
((command->instruction.bus_width == QSPI_CFG_BUS_SINGLE) &&
|
||||
(command->address.bus_width == QSPI_CFG_BUS_SINGLE) &&
|
||||
(command->data.bus_width == QSPI_CFG_BUS_QUAD))) {
|
||||
/* Quad/dual data. Data field is quad/dual, other fields are serial. */
|
||||
spifi_command.format = kSPIFI_CommandDataQuad;
|
||||
}
|
||||
|
||||
/* Check if this is a data receive */
|
||||
if (rx_data != NULL && rx_size) {
|
||||
uint32_t cycles_per_byte = 8;
|
||||
|
||||
if ((command->address.bus_width == QSPI_CFG_BUS_DUAL) &&
|
||||
(command->data.bus_width == QSPI_CFG_BUS_DUAL)) {
|
||||
cycles_per_byte = 4;
|
||||
}
|
||||
if ((command->address.bus_width == QSPI_CFG_BUS_QUAD) &&
|
||||
(command->data.bus_width == QSPI_CFG_BUS_QUAD)) {
|
||||
cycles_per_byte = 2;
|
||||
}
|
||||
|
||||
/* Set dummy bytes */
|
||||
spifi_command.intermediateBytes = command->dummy_count / cycles_per_byte;
|
||||
|
||||
use_memory_command = true;
|
||||
}
|
||||
|
||||
/* Set the flash address */
|
||||
SPIFI_SetCommandAddress(base, command->address.value);
|
||||
}
|
||||
|
||||
if (use_memory_command) {
|
||||
/* Setup command */
|
||||
SPIFI_SetMemoryCommand(base, &spifi_command);
|
||||
} else {
|
||||
/* Setup memory command */
|
||||
SPIFI_SetCommand(base, &spifi_command);
|
||||
}
|
||||
}
|
||||
|
||||
qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length)
|
||||
{
|
||||
uint32_t to_write = *length;
|
||||
uint32_t *data_send = (uint32_t *)data;
|
||||
SPIFI_Type *base = qspi_addrs[obj->instance];
|
||||
uint32_t i = 0;
|
||||
|
||||
/* Enforce word-sized access */
|
||||
if ((to_write & 0x3) != 0) {
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Use a pre-defined command is no write instruction is provided */
|
||||
if (command->instruction.disabled) {
|
||||
/* Set the flash address */
|
||||
SPIFI_SetCommandAddress(base, command->address.value);
|
||||
|
||||
/* If no instruction provided then use the pre-defined read sequence */
|
||||
preset_spifi_command[COMMAND_WRITE_INDEX].dataLen = to_write;
|
||||
SPIFI_SetCommand(base, &preset_spifi_command[COMMAND_WRITE_INDEX]);
|
||||
} else {
|
||||
/* Prepare the write command */
|
||||
qspi_prepare_command(obj, command, data, to_write, NULL, 0);
|
||||
}
|
||||
|
||||
/* Write the data */
|
||||
for (i = 0; i < to_write; i += 4, data_send++) {
|
||||
SPIFI_WriteData(base, *data_send);
|
||||
}
|
||||
|
||||
/* Wait for deasseration of CS */
|
||||
while (SPIFI_GetStatusFlag(base) & kSPIFI_CommandWriteFinished) {
|
||||
}
|
||||
|
||||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t *length)
|
||||
{
|
||||
uint32_t dest_addr = FSL_FEATURE_SPIFI_START_ADDR + command->address.value;
|
||||
uint32_t to_read = *length;
|
||||
SPIFI_Type *base = qspi_addrs[obj->instance];
|
||||
|
||||
/* Enforce word-sized access */
|
||||
if ((to_read & 0x3) != 0) {
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Use a pre-defined command is no read instruction is provided */
|
||||
if (command->instruction.disabled) {
|
||||
/* If no instruction provided then use the pre-defined read sequence */
|
||||
preset_spifi_command[COMMAND_READ_INDEX].dataLen = to_read;
|
||||
SPIFI_SetMemoryCommand(base, &preset_spifi_command[COMMAND_READ_INDEX]);
|
||||
} else {
|
||||
/* Prepare for read command */
|
||||
qspi_prepare_command(obj, command, NULL, 0, data, to_read);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < to_read / 4; i++) {
|
||||
((uint32_t*)data)[i] = *((uint32_t *)(dest_addr) + i);
|
||||
}
|
||||
|
||||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size)
|
||||
{
|
||||
SPIFI_Type *base = qspi_addrs[obj->instance];
|
||||
|
||||
if (tx_size > MIN_SIZE || rx_size > MIN_SIZE) {
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((tx_data == NULL || tx_size == 0) && (rx_data == NULL || rx_size == 0)) {
|
||||
/* Setup the command */
|
||||
qspi_prepare_command(obj, command, tx_data, tx_size, rx_data, rx_size);
|
||||
} else {
|
||||
if (tx_data != NULL && tx_size) {
|
||||
/* Transmit data to QSPI */
|
||||
uint8_t val[MIN_SIZE];
|
||||
|
||||
memset(val, 0, sizeof(val));
|
||||
memcpy(val, tx_data, tx_size);
|
||||
|
||||
/* Setup the command */
|
||||
qspi_prepare_command(obj, command, tx_data, tx_size, rx_data, rx_size);
|
||||
|
||||
for (uint32_t i = 0; i < tx_size; i++) {
|
||||
SPIFI_WriteDataByte(base, val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (rx_data != NULL && rx_size) {
|
||||
/* Receive data from QSPI */
|
||||
uint8_t val[MIN_SIZE];
|
||||
|
||||
memset(val, 0, sizeof(val));
|
||||
|
||||
/* Setup the command */
|
||||
qspi_prepare_command(obj, command, tx_data, tx_size, rx_data, rx_size);
|
||||
|
||||
for (uint32_t i = 0; i < rx_size; i++) {
|
||||
val[i] = SPIFI_ReadDataByte(base);
|
||||
}
|
||||
|
||||
memcpy(rx_data, val, rx_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for deasseration of CS */
|
||||
while (SPIFI_GetStatusFlag(base) & kSPIFI_CommandWriteFinished) {
|
||||
}
|
||||
|
||||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -105,6 +105,10 @@ typedef enum {
|
|||
SPI_1 = Flexcomm9
|
||||
} SPIName;
|
||||
|
||||
typedef enum {
|
||||
QSPI_0 = 0
|
||||
} QSPIName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -115,3 +115,21 @@ const PinMap PinMap_SPI_SSEL[] = {
|
|||
const PinMap PinMap_PWM[] = {
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************QSPI***************/
|
||||
const PinMap PinMap_QSPI_DATA[] = {
|
||||
{P0_24, QSPI_0, 6},
|
||||
{P0_25, QSPI_0, 6},
|
||||
{P0_28, QSPI_0, 6},
|
||||
{P0_27, QSPI_0, 6},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
const PinMap PinMap_QSPI_SCLK[] = {
|
||||
{P0_26, QSPI_0, 6},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
const PinMap PinMap_QSPI_SSEL[] = {
|
||||
{P0_23, QSPI_0, 6},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
|
|
|
@ -219,6 +219,14 @@ typedef enum {
|
|||
I2C_SCL = D15,
|
||||
I2C_SDA = D14,
|
||||
|
||||
/**** QSPI FLASH pins ****/
|
||||
QSPI_FLASH1_IO0 = P0_24,
|
||||
QSPI_FLASH1_IO1 = P0_25,
|
||||
QSPI_FLASH1_IO2 = P0_28,
|
||||
QSPI_FLASH1_IO3 = P0_27,
|
||||
QSPI_FLASH1_SCK = P0_26,
|
||||
QSPI_FLASH1_CSN = P0_23,
|
||||
|
||||
A0 = P0_16,
|
||||
A1 = P0_31,
|
||||
A2 = P1_0,
|
||||
|
|
|
@ -172,3 +172,12 @@ void BOARD_InitSDRAM(void)
|
|||
/* EMC Dynamc memory configuration. */
|
||||
EMC_DynamicMemInit(EMC, &dynTiming, &dynChipConfig, 1);
|
||||
}
|
||||
|
||||
// Get the QSPI clock frequency
|
||||
uint32_t qspi_get_freq(void)
|
||||
{
|
||||
CLOCK_AttachClk(kFRO_HF_to_SPIFI_CLK);
|
||||
|
||||
return CLOCK_GetFroHfFreq();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018, ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_MBED_QSPI_DEVICE_H_
|
||||
#define _FSL_MBED_QSPI_DEVICE_H_
|
||||
|
||||
#include "fsl_spifi.h"
|
||||
|
||||
#define FLASH_SIZE 0x00400000U
|
||||
#define FLASH_PAGE_SIZE 256U
|
||||
|
||||
/* Pre-defined commands */
|
||||
spifi_command_t preset_spifi_command[2] = {
|
||||
{FLASH_PAGE_SIZE, false, kSPIFI_DataInput, 0, kSPIFI_CommandAllSerial, kSPIFI_CommandOpcodeAddrThreeBytes, 0x3},
|
||||
{FLASH_PAGE_SIZE, false, kSPIFI_DataOutput, 0, kSPIFI_CommandAllSerial, kSPIFI_CommandOpcodeAddrThreeBytes, 0x2}
|
||||
};
|
||||
|
||||
#endif /* _FSL_MBED_QSPI_DEVICE_H_*/
|
|
@ -220,6 +220,10 @@ typedef enum _SYSCON_RSTn
|
|||
{ \
|
||||
kSHA_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for SHA peripheral */
|
||||
#define SPIFI_RSTS \
|
||||
{ \
|
||||
kSPIFI_RST_SHIFT_RSTn \
|
||||
} /* Reset bits for SPIFI peripheral */
|
||||
#define USB0D_RST \
|
||||
{ \
|
||||
kUSB0D_RST_SHIFT_RSTn \
|
||||
|
|
|
@ -1,35 +1,9 @@
|
|||
/*
|
||||
* The Clear BSD License
|
||||
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted (subject to the limitations in the disclaimer below) provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_spifi.h"
|
||||
|
@ -38,18 +12,15 @@
|
|||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.spifi"
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Get the SPIFI instance from peripheral base address.
|
||||
*
|
||||
* @param base SPIFI peripheral base address.
|
||||
* @return SPIFI instance.
|
||||
*/
|
||||
uint32_t SPIFI_GetInstance(SPIFI_Type *base);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
@ -62,9 +33,19 @@ static SPIFI_Type *const s_spifiBases[] = SPIFI_BASE_PTRS;
|
|||
static const clock_ip_name_t s_spifiClock[] = SPIFI_CLOCKS;
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
#if !(defined(FSL_FEATURE_SPIFI_HAS_NO_RESET) && FSL_FEATURE_SPIFI_HAS_NO_RESET)
|
||||
static const reset_ip_name_t s_spifiResets[] = SPIFI_RSTS;
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* brief Get the SPIFI instance from peripheral base address.
|
||||
*
|
||||
* param base SPIFI peripheral base address.
|
||||
* return SPIFI instance.
|
||||
*/
|
||||
uint32_t SPIFI_GetInstance(SPIFI_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
@ -83,8 +64,16 @@ uint32_t SPIFI_GetInstance(SPIFI_Type *base)
|
|||
return instance;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Get SPIFI default configure settings.
|
||||
*
|
||||
* param config SPIFI config structure pointer.
|
||||
*/
|
||||
void SPIFI_GetDefaultConfig(spifi_config_t *config)
|
||||
{
|
||||
/* Initializes the configure structure to zero. */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->timeout = 0xFFFFU;
|
||||
config->csHighTime = 0xFU;
|
||||
config->disablePrefetch = false;
|
||||
|
@ -95,6 +84,14 @@ void SPIFI_GetDefaultConfig(spifi_config_t *config)
|
|||
config->dualMode = kSPIFI_QuadMode;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPIFI with the user configuration structure.
|
||||
*
|
||||
* This function configures the SPIFI module with the user-defined configuration.
|
||||
*
|
||||
* param base SPIFI peripheral base address.
|
||||
* param config The pointer to the configuration structure.
|
||||
*/
|
||||
void SPIFI_Init(SPIFI_Type *base, const spifi_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
@ -104,6 +101,10 @@ void SPIFI_Init(SPIFI_Type *base, const spifi_config_t *config)
|
|||
CLOCK_EnableClock(s_spifiClock[SPIFI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
#if !(defined(FSL_FEATURE_SPIFI_HAS_NO_RESET) && FSL_FEATURE_SPIFI_HAS_NO_RESET)
|
||||
RESET_PeripheralReset(s_spifiResets[SPIFI_GetInstance(base)]);
|
||||
#endif
|
||||
|
||||
/* Reset the Command register */
|
||||
SPIFI_ResetCommand(base);
|
||||
|
||||
|
@ -114,6 +115,11 @@ void SPIFI_Init(SPIFI_Type *base, const spifi_config_t *config)
|
|||
SPIFI_CTRL_RFCLK(config->isReadFullClockCycle) | SPIFI_CTRL_FBCLK(config->isFeedbackClock);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Deinitializes the SPIFI regions.
|
||||
*
|
||||
* param base SPIFI peripheral base address.
|
||||
*/
|
||||
void SPIFI_Deinit(SPIFI_Type *base)
|
||||
{
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
|
@ -122,29 +128,84 @@ void SPIFI_Deinit(SPIFI_Type *base)
|
|||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Set SPIFI flash command.
|
||||
*
|
||||
* param base SPIFI peripheral base address.
|
||||
* param cmd SPIFI command structure pointer.
|
||||
*/
|
||||
void SPIFI_SetCommand(SPIFI_Type *base, spifi_command_t *cmd)
|
||||
{
|
||||
/* Wait for the CMD and MCINT flag all be 0 */
|
||||
while (SPIFI_GetStatusFlag(base) & (SPIFI_STAT_MCINIT_MASK | SPIFI_STAT_CMD_MASK))
|
||||
/* If SPIFI in memory mode, call reset function to abort memory mode */
|
||||
if (SPIFI_GetStatusFlag(base) & SPIFI_STAT_MCINIT_MASK)
|
||||
{
|
||||
SPIFI_ResetCommand(base);
|
||||
}
|
||||
|
||||
/* Wait for other command finished */
|
||||
while (SPIFI_GetStatusFlag(base) & SPIFI_STAT_CMD_MASK)
|
||||
{
|
||||
}
|
||||
|
||||
base->CMD = SPIFI_CMD_DATALEN(cmd->dataLen) | SPIFI_CMD_POLL(cmd->isPollMode) | SPIFI_CMD_DOUT(cmd->direction) |
|
||||
SPIFI_CMD_INTLEN(cmd->intermediateBytes) | SPIFI_CMD_FIELDFORM(cmd->format) |
|
||||
SPIFI_CMD_FRAMEFORM(cmd->type) | SPIFI_CMD_OPCODE(cmd->opcode);
|
||||
|
||||
/* Wait for the command written */
|
||||
while ((base->STAT & SPIFI_STAT_CMD_MASK) == 0U)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Set SPIFI flash AHB read command.
|
||||
*
|
||||
* Call this function means SPIFI enters to memory mode, while users need to use command, a SPIFI_ResetCommand shall
|
||||
* be called.
|
||||
*
|
||||
* param base SPIFI peripheral base address.
|
||||
* param cmd SPIFI command structure pointer.
|
||||
*/
|
||||
void SPIFI_SetMemoryCommand(SPIFI_Type *base, spifi_command_t *cmd)
|
||||
{
|
||||
/* Wait for the CMD and MCINT flag all be 0 */
|
||||
while (SPIFI_GetStatusFlag(base) & (SPIFI_STAT_MCINIT_MASK | SPIFI_STAT_CMD_MASK))
|
||||
/* Wait for the CMD flag be 0 */
|
||||
while (SPIFI_GetStatusFlag(base) & SPIFI_STAT_CMD_MASK)
|
||||
{
|
||||
}
|
||||
|
||||
base->MCMD = SPIFI_MCMD_POLL(0U) | SPIFI_MCMD_DOUT(0U) | SPIFI_MCMD_INTLEN(cmd->intermediateBytes) |
|
||||
SPIFI_MCMD_FIELDFORM(cmd->format) | SPIFI_MCMD_FRAMEFORM(cmd->type) | SPIFI_MCMD_OPCODE(cmd->opcode);
|
||||
|
||||
/* Wait for the command written */
|
||||
while ((base->STAT & SPIFI_STAT_MCINIT_MASK) == 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Write a halfword data in address of SPIFI.
|
||||
*
|
||||
* Users can write a halfword data into SPIFI address.
|
||||
*
|
||||
* param base SPIFI peripheral base address.
|
||||
* param data Data need be write.
|
||||
*/
|
||||
void SPIFI_WriteDataHalfword(SPIFI_Type *base, uint16_t data)
|
||||
{
|
||||
volatile uint8_t *dataReg = ((volatile uint8_t *)(&(base->DATA)));
|
||||
|
||||
*dataReg = (data & 0xFFU);
|
||||
dataReg++;
|
||||
*dataReg = ((data >> 8U) & 0xFFU);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Read a halfword data from serial flash.
|
||||
*
|
||||
* param base SPIFI peripheral base address.
|
||||
* return Data input from flash.
|
||||
*/
|
||||
uint16_t SPIFI_ReadDataHalfword(SPIFI_Type *base)
|
||||
{
|
||||
uint16_t val = 0;
|
||||
volatile uint8_t *dataReg = ((volatile uint8_t *)(&(base->DATA)));
|
||||
|
||||
val = ((*dataReg) | (uint16_t)((uint16_t)(*(dataReg + 1U)) << 8U));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
|
|
@ -1,35 +1,9 @@
|
|||
/*
|
||||
* The Clear BSD License
|
||||
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted (subject to the limitations in the disclaimer below) provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_SPIFI_H_
|
||||
#define _FSL_SPIFI_H_
|
||||
|
@ -47,8 +21,8 @@
|
|||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SPIFI driver version 2.0.0. */
|
||||
#define FSL_SPIFI_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*! @brief SPIFI driver version 2.0.2. */
|
||||
#define FSL_SPIFI_DRIVER_VERSION (MAKE_VERSION(2, 0, 2))
|
||||
/*@}*/
|
||||
|
||||
/*! @brief Status structure of SPIFI.*/
|
||||
|
@ -162,6 +136,14 @@ extern "C" {
|
|||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Get the SPIFI instance from peripheral base address.
|
||||
*
|
||||
* @param base SPIFI peripheral base address.
|
||||
* @return SPIFI instance.
|
||||
*/
|
||||
uint32_t SPIFI_GetInstance(SPIFI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Initializes the SPIFI with the user configuration structure.
|
||||
*
|
||||
|
@ -358,6 +340,29 @@ static inline void SPIFI_WriteData(SPIFI_Type *base, uint32_t data)
|
|||
base->DATA = data;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write a byte data in address of SPIFI.
|
||||
*
|
||||
* Users can write a byte data into SPIFI address.
|
||||
*
|
||||
* @param base SPIFI peripheral base address.
|
||||
* @param data Data need be write.
|
||||
*/
|
||||
static inline void SPIFI_WriteDataByte(SPIFI_Type *base, uint8_t data)
|
||||
{
|
||||
*((volatile uint8_t *)(&(base->DATA))) = data;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write a halfword data in address of SPIFI.
|
||||
*
|
||||
* Users can write a halfword data into SPIFI address.
|
||||
*
|
||||
* @param base SPIFI peripheral base address.
|
||||
* @param data Data need be write.
|
||||
*/
|
||||
void SPIFI_WriteDataHalfword(SPIFI_Type *base, uint16_t data);
|
||||
|
||||
/*!
|
||||
* @brief Read data from serial flash.
|
||||
*
|
||||
|
@ -372,6 +377,25 @@ static inline uint32_t SPIFI_ReadData(SPIFI_Type *base)
|
|||
return base->DATA;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read a byte data from serial flash.
|
||||
*
|
||||
* @param base SPIFI peripheral base address.
|
||||
* @return Data input from flash.
|
||||
*/
|
||||
static inline uint8_t SPIFI_ReadDataByte(SPIFI_Type *base)
|
||||
{
|
||||
return *((volatile uint8_t *)(&(base->DATA)));
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read a halfword data from serial flash.
|
||||
*
|
||||
* @param base SPIFI peripheral base address.
|
||||
* @return Data input from flash.
|
||||
*/
|
||||
uint16_t SPIFI_ReadDataHalfword(SPIFI_Type *base);
|
||||
|
||||
/* @} */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -1847,7 +1847,8 @@
|
|||
"SPISLAVE",
|
||||
"STDIO_MESSAGES",
|
||||
"FLASH",
|
||||
"TRNG"
|
||||
"TRNG",
|
||||
"QSPI"
|
||||
],
|
||||
"device_name": "LPC54628J512ET180",
|
||||
"post_binary_hook": { "function": "LPCTargetCode.lpc_patch" },
|
||||
|
@ -1865,6 +1866,7 @@
|
|||
"inherits": ["MCU_LPC546XX"],
|
||||
"extra_labels_remove": ["LPCXpresso"],
|
||||
"detect_code": ["8081"],
|
||||
"device_has_remove": ["QSPI"],
|
||||
"release_versions": ["2", "5"]
|
||||
},
|
||||
"NUCLEO_F030R8": {
|
||||
|
|
Loading…
Reference in New Issue