Merge pull request #8683 from NXPmicro/feature-qspi-lpc546xx

Feature qspi lpc546xx
pull/8803/head
Martin Kojtal 2018-11-19 13:11:44 +00:00 committed by GitHub
commit 00c5b56e32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 878 additions and 76 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -105,6 +105,10 @@ typedef enum {
SPI_1 = Flexcomm9
} SPIName;
typedef enum {
QSPI_0 = 0
} QSPIName;
#ifdef __cplusplus
}
#endif

View File

@ -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}
};

View File

@ -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,

View File

@ -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();
}

View File

@ -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_*/

View File

@ -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 \

View File

@ -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;
}

View File

@ -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)

View File

@ -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": {