diff --git a/TESTS/mbed_hal/qspi/flash_configs/Freescale/K82F/flash_config.h b/TESTS/mbed_hal/qspi/flash_configs/Freescale/K82F/flash_config.h new file mode 100644 index 0000000000..d31af6b399 --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/Freescale/K82F/flash_config.h @@ -0,0 +1,118 @@ +/* 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 "../../MX25RXX35F_config.h" + +/* Fast mode not supported in MX25U3235F */ +#undef FAST_MODE_ENABLE +#undef FAST_MODE_DISABLE + +#ifdef QSPI_SECTOR_COUNT +#undef QSPI_SECTOR_COUNT +#define QSPI_SECTOR_COUNT 1024 // for MX25U3235F +#endif + +/* The values for MX25U3235F are different, specify this here */ +#undef QSPI_COMMON_MAX_FREQUENCY +#undef QSPI_WRSR_MAX_TIME +#undef QSPI_PAGE_PROG_MAX_TIME +#undef QSPI_ERASE_SECTOR_MAX_TIME +#undef QSPI_ERASE_BLOCK_32_MAX_TIME +#undef QSPI_ERASE_BLOCK_64_MAX_TIME + +/* Implementation of these macros are slightly different for MX25U3235F */ +#undef EXTENDED_SPI_ENABLE +#undef EXTENDED_SPI_DISABLE + +/* Max frequency for basic rw operation in MX25U3235F */ +#define QSPI_COMMON_MAX_FREQUENCY 54000000 + +/* WRSR operations max time [us] (datasheet max time + 15%) */ +#define QSPI_WRSR_MAX_TIME 46000 // 40ms + +/* Write operations max time [us] (datasheet max time + 15%) */ +#define QSPI_PAGE_PROG_MAX_TIME 3450 // 3ms + +/* erase operations max time [us] (datasheet max time + 15%) */ +#define QSPI_ERASE_SECTOR_MAX_TIME 230000 // 200 ms +#define QSPI_ERASE_BLOCK_32_MAX_TIME 1150000 // 1s +#define QSPI_ERASE_BLOCK_64_MAX_TIME 2300000 // 2s + +#define EXTENDED_SPI_ENABLE() \ + \ + const int32_t reg_size = QSPI_STATUS_REG_SIZE; \ + uint8_t reg_data[reg_size] = { 0 }; \ + \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + reg_data[0] = STATUS_BIT_QE; \ + if (write_register(QSPI_CMD_WRSR, reg_data, \ + reg_size, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + memset(reg_data, 0, QSPI_STATUS_REG_SIZE); \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + return ((reg_data[0] & STATUS_BIT_QE) != 0 ? \ + QSPI_STATUS_OK : QSPI_STATUS_ERROR) + + + +#define EXTENDED_SPI_DISABLE() \ + \ + const int32_t reg_size = QSPI_STATUS_REG_SIZE; \ + uint8_t reg_data[reg_size] = { 0 }; \ + \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + reg_data[0] &= ~(STATUS_BIT_QE); \ + \ + if (write_register(QSPI_CMD_WRSR, reg_data, \ + reg_size, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + reg_data[0] = 0; \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + return ((reg_data[0] & STATUS_BIT_QE) == 0 ? \ + QSPI_STATUS_OK : QSPI_STATUS_ERROR) + +#endif // MBED_QSPI_FLASH_CONFIG_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/Freescale/KL82Z/flash_config.h b/TESTS/mbed_hal/qspi/flash_configs/Freescale/KL82Z/flash_config.h new file mode 100644 index 0000000000..9cbe04fabe --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/Freescale/KL82Z/flash_config.h @@ -0,0 +1,118 @@ +/* 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 "../../MX25RXX35F_config.h" + +/* Fast mode not supported in MX25L12845G */ +#undef FAST_MODE_ENABLE +#undef FAST_MODE_DISABLE + +#ifdef QSPI_SECTOR_COUNT +#undef QSPI_SECTOR_COUNT +#define QSPI_SECTOR_COUNT 4096 // for MX25L12845G +#endif + +/* The values for MX25U3235F are different, specify this here */ +#undef QSPI_COMMON_MAX_FREQUENCY +#undef QSPI_WRSR_MAX_TIME +#undef QSPI_PAGE_PROG_MAX_TIME +#undef QSPI_ERASE_SECTOR_MAX_TIME +#undef QSPI_ERASE_BLOCK_32_MAX_TIME +#undef QSPI_ERASE_BLOCK_64_MAX_TIME + +/* Implementation of these macros are slightly different for MX25L12845G */ +#undef EXTENDED_SPI_ENABLE +#undef EXTENDED_SPI_DISABLE + +/* Max frequency for basic rw operation based on max bus frequency of 24MHz */ +#define QSPI_COMMON_MAX_FREQUENCY 23000000 + +/* WRSR operations max time [us] (datasheet max time + 15%) */ +#define QSPI_WRSR_MAX_TIME 46000 // 40ms + +/* Write operations max time [us] (datasheet max time + 15%) */ +#define QSPI_PAGE_PROG_MAX_TIME 1000 // 0.75ms + +/* erase operations max time [us] (datasheet max time + 15%) */ +#define QSPI_ERASE_SECTOR_MAX_TIME 460000 // 400 ms +#define QSPI_ERASE_BLOCK_32_MAX_TIME 1150000 // 1s +#define QSPI_ERASE_BLOCK_64_MAX_TIME 2300000 // 2s + +#define EXTENDED_SPI_ENABLE() \ + \ + const int32_t reg_size = QSPI_STATUS_REG_SIZE; \ + uint8_t reg_data[reg_size] = { 0 }; \ + \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + reg_data[0] = STATUS_BIT_QE; \ + if (write_register(QSPI_CMD_WRSR, reg_data, \ + reg_size, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + memset(reg_data, 0, QSPI_STATUS_REG_SIZE); \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + return ((reg_data[0] & STATUS_BIT_QE) != 0 ? \ + QSPI_STATUS_OK : QSPI_STATUS_ERROR) + + + +#define EXTENDED_SPI_DISABLE() \ + \ + const int32_t reg_size = QSPI_STATUS_REG_SIZE; \ + uint8_t reg_data[reg_size] = { 0 }; \ + \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + reg_data[0] &= ~(STATUS_BIT_QE); \ + \ + if (write_register(QSPI_CMD_WRSR, reg_data, \ + reg_size, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + reg_data[0] = 0; \ + if (read_register(STATUS_REG, reg_data, \ + QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + \ + return ((reg_data[0] & STATUS_BIT_QE) == 0 ? \ + QSPI_STATUS_OK : QSPI_STATUS_ERROR) + +#endif // MBED_QSPI_FLASH_CONFIG_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h b/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h index fc7cdfa303..fcf08b642e 100644 --- a/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h +++ b/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h @@ -25,6 +25,10 @@ #include "STM/DISCO_F413ZH/flash_config.h" #elif defined(TARGET_EFM32GG11_STK3701) #include "SiliconLabs/EFM32GG11_STK3701/flash_config.h" +#elif defined(TARGET_K82F) +#include "Freescale/K82F/flash_config.h" +#elif defined(TARGET_KL82Z) +#include "Freescale/KL82Z/flash_config.h" #endif #endif // MBED_FLASH_CONFIGS_H diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PeripheralNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PeripheralNames.h index 8467700885..c9371be81a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PeripheralNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PeripheralNames.h @@ -106,6 +106,10 @@ typedef enum { SPI_2 = 2, } SPIName; +typedef enum { + QSPI_0 = 0 +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PeripheralPins.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PeripheralPins.c index 8eab4d62df..0a344682c2 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PeripheralPins.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PeripheralPins.c @@ -265,3 +265,29 @@ const PinMap PinMap_PWM[] = { {NC , NC , 0} }; + +const PinMap PinMap_QSPI_DATA[] = { + {PTE0, QSPI_0, 5}, + {PTE2, QSPI_0, 5}, + {PTE3, QSPI_0, 5}, + {PTE4, QSPI_0, 5}, + {PTE6, QSPI_0, 5}, + {PTE7, QSPI_0, 5}, + {PTE8, QSPI_0, 5}, + {PTE9, QSPI_0, 5}, + {PTE10, QSPI_0, 5}, + {NC , NC , 0} +}; + +const PinMap PinMap_QSPI_SCLK[] = { + {PTE1, QSPI_0, 5}, + {PTE7, QSPI_0, 5}, + {NC , NC , 0} +}; + +const PinMap PinMap_QSPI_SSEL[] = { + {PTE5, QSPI_0, 5}, + {PTE11, QSPI_0, 5}, + {NC , NC , 0} +}; + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PinNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PinNames.h index f9c5c7fc3f..7d012faf19 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PinNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/PinNames.h @@ -178,6 +178,14 @@ typedef enum { SPI_SCK = PTE1, SPI_PERSISTENT_MEM_CS = PTE5, + /**** QSPI FLASH pins ****/ + QSPI_FLASH1_IO0 = PTE2, + QSPI_FLASH1_IO1 = PTE4, + QSPI_FLASH1_IO2 = PTE3, + QSPI_FLASH1_IO3 = PTE0, + QSPI_FLASH1_SCK = PTE1, + QSPI_FLASH1_CSN = PTE5, + // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/device.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/device.h index 29a4e7a0b1..c1dc0fa8eb 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/device.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/device.h @@ -18,22 +18,9 @@ #ifndef MBED_DEVICE_H #define MBED_DEVICE_H - - - - - - - - - - -#define DEVICE_ID_LENGTH 24 - - - - - #include "objects.h" +#define DEVICE_ID_LENGTH 24 + + #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/mbed_overrides.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/mbed_overrides.c index c1fce3cd19..8948f4009d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/mbed_overrides.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/mbed_overrides.c @@ -62,3 +62,9 @@ void serial_clock_init(void) CLOCK_SetLpuartClock(2U); } +// Get the QSPI clock frequency +uint32_t qspi_get_freq(void) +{ + return CLOCK_GetFreq(kCLOCK_McgPll0Clk); +} + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/qspi_device.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/qspi_device.h new file mode 100644 index 0000000000..ed8f66ef2b --- /dev/null +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/TARGET_FRDM/qspi_device.h @@ -0,0 +1,77 @@ +/* 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_qspi.h" + +#define FLASH_SIZE 0x00400000U +#define FLASH_PAGE_SIZE 256U + +qspi_flash_config_t single_config = { + .flashA1Size = FLASH_SIZE, /* 4MB */ + .flashA2Size = 0, +#if defined(FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) && (FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) + .flashB1Size = FLASH_SIZE, + .flashB2Size = 0, +#endif +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TDH) || (!FSL_FEATURE_QSPI_HAS_NO_TDH) + .dataHoldTime = 0, +#endif + .CSHoldTime = 0, + .CSSetupTime = 0, + .cloumnspace = 0, + .dataLearnValue = 0, + .endian = kQSPI_64LittleEndian, + .enableWordAddress = false +}; + +/* Pre-defined LUT definitions */ +uint32_t lut[FSL_FEATURE_QSPI_LUT_DEPTH] = + { + /* Seq0 : Read */ + /* CMD: 0x03 - Read, Single pad */ + /* ADDR: 0x18 - 24bit address, Single pad */ + /* READ: 0x80 - Read 128 bytes, Single pad */ + /* JUMP_ON_CS: 0 */ + [0] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x03, QSPI_ADDR, QSPI_PAD_1, 0x18), + [1] = QSPI_LUT_SEQ(QSPI_READ, QSPI_PAD_1, 0x80, QSPI_JMP_ON_CS, QSPI_PAD_1, 0x0), + + /* Seq1: Page Program */ + /* CMD: 0x02 - Page Program, Single pad */ + /* ADDR: 0x18 - 24bit address, Single pad */ + /* WRITE: 0x80 - Write 128 bytes at one pass, Single pad */ + [4] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x02, QSPI_ADDR, QSPI_PAD_1, 0x18), + [5] = QSPI_LUT_SEQ(QSPI_WRITE, QSPI_PAD_1, 0x80, 0, 0, 0), + + /* Match MISRA rule */ + [63] = 0 + }; + +#endif /* _FSL_MBED_QSPI_DEVICE_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/device/MK82F25615.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/device/MK82F25615.h index ec05414e6b..737ee213d4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/device/MK82F25615.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/device/MK82F25615.h @@ -11013,7 +11013,14 @@ typedef struct { typedef struct { __IO uint32_t MCR; /**< Module Configuration Register, offset: 0x0 */ uint8_t RESERVED_0[4]; - __IO uint32_t IPCR; /**< IP Configuration Register, offset: 0x8 */ + union { /* offset: 0x8 */ + __IO uint32_t IPCR; /**< IP Configuration Register, offset: 0x8 */ + struct { + __IO uint16_t IDATZ; /**< IP data transfer size, offset: 0x8 */ + __IO uint8_t PAR_EN; /**< IP data transfer size, offset: 0xA */ + __IO uint8_t SEQID; /**< IP data transfer size, offset: 0xB */ + } IPCR_ACCESSBIT; + }; __IO uint32_t FLSHCR; /**< Flash Configuration Register, offset: 0xC */ __IO uint32_t BUF0CR; /**< Buffer0 Configuration Register, offset: 0x10 */ __IO uint32_t BUF1CR; /**< Buffer1 Configuration Register, offset: 0x14 */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_qspi.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_qspi.c index 748a1e7167..8f8a68a9d1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_qspi.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_qspi.c @@ -1,9 +1,12 @@ /* + * The Clear BSD License * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * 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. @@ -12,10 +15,11 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * 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 @@ -30,6 +34,12 @@ #include "fsl_qspi.h" +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.qspi" +#endif + + /******************************************************************************* * Definitations ******************************************************************************/ @@ -40,17 +50,11 @@ enum _qspi_transfer_state kQSPI_TxError /*!< Transfer error occured. */ }; -#define QSPI_AHB_BUFFER_REG(base, index) (*((uint32_t *)&(base->BUF0CR) + index)) +#define QSPI_AHB_BUFFER_REG(base, index) (((volatile uint32_t *)&((base)->BUF0CR))[(index)]) /******************************************************************************* * Prototypes ******************************************************************************/ -/*! -* @brief Get the instance number for QSPI. -* -* @param base QSPI base pointer. -*/ -uint32_t QSPI_GetInstance(QuadSPI_Type *base); /******************************************************************************* * Variables @@ -70,7 +74,7 @@ uint32_t QSPI_GetInstance(QuadSPI_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_QuadSPI_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_qspiBases); instance++) { if (s_qspiBases[instance] == base) { @@ -78,7 +82,7 @@ uint32_t QSPI_GetInstance(QuadSPI_Type *base) } } - assert(instance < FSL_FEATURE_SOC_QuadSPI_COUNT); + assert(instance < ARRAY_SIZE(s_qspiBases)); return instance; } @@ -102,12 +106,21 @@ void QSPI_Init(QuadSPI_Type *base, qspi_config_t *config, uint32_t srcClock_Hz) /* Configure QSPI */ QSPI_Enable(base, false); +#if !defined (FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL) || (!FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL) /* Set qspi clock source */ base->SOCCR = config->clockSource; /* Set the divider of QSPI clock */ base->MCR &= ~QuadSPI_MCR_SCLKCFG_MASK; - base->MCR |= QuadSPI_MCR_SCLKCFG(srcClock_Hz / config->baudRate - 1U); + + if (srcClock_Hz % config->baudRate) { + /* In case we cannot get the exact baudrate, get the closest lower value */ + base->MCR |= QuadSPI_MCR_SCLKCFG(srcClock_Hz / config->baudRate); + } else { + base->MCR |= QuadSPI_MCR_SCLKCFG(srcClock_Hz / config->baudRate - 1U); + } + +#endif /* FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL */ /* Set AHB buffer size and buffer master */ for (i = 0; i < FSL_FEATURE_QSPI_AHB_BUFFER_COUNT; i++) @@ -127,8 +140,11 @@ void QSPI_Init(QuadSPI_Type *base, qspi_config_t *config, uint32_t srcClock_Hz) /* Set watermark */ base->RBCT &= ~QuadSPI_RBCT_WMRK_MASK; base->RBCT |= QuadSPI_RBCT_WMRK(config->rxWatermark - 1); + +#if !defined (FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA) base->TBCT &= ~QuadSPI_TBCT_WMRK_MASK; base->TBCT |= QuadSPI_TBCT_WMRK(config->txWatermark - 1); +#endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */ /* Enable QSPI module */ if (config->enableQspi) @@ -178,9 +194,11 @@ void QSPI_SetFlashConfig(QuadSPI_Type *base, qspi_flash_config_t *config) base->SFB2AD = address; #endif /* FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE */ +#if !defined (FSL_FEATURE_QSPI_HAS_NO_SFACR) || (!FSL_FEATURE_QSPI_HAS_NO_SFACR) /* Set Word Addressable feature */ val = QuadSPI_SFACR_WA(config->enableWordAddress) | QuadSPI_SFACR_CAS(config->cloumnspace); base->SFACR = val; +#endif /* FSL_FEATURE_QSPI_HAS_NO_SFACR */ /* Config look up table */ base->LUTKEY = 0x5AF05AF0U; @@ -192,9 +210,13 @@ void QSPI_SetFlashConfig(QuadSPI_Type *base, qspi_flash_config_t *config) base->LUTKEY = 0x5AF05AF0U; base->LCKCR = 0x1U; +#if !defined (FSL_FEATURE_QSPI_HAS_NO_TDH) || (!FSL_FEATURE_QSPI_HAS_NO_TDH) /* Config flash timing */ val = QuadSPI_FLSHCR_TCSS(config->CSHoldTime) | QuadSPI_FLSHCR_TDH(config->dataHoldTime) | QuadSPI_FLSHCR_TCSH(config->CSSetupTime); +#else + val = QuadSPI_FLSHCR_TCSS(config->CSHoldTime) | QuadSPI_FLSHCR_TCSH(config->CSSetupTime); +#endif /* FSL_FEATURE_QSPI_HAS_NO_TDH */ base->FLSHCR = val; /* Set flash endianness */ @@ -207,7 +229,7 @@ void QSPI_SetFlashConfig(QuadSPI_Type *base, qspi_flash_config_t *config) void QSPI_SoftwareReset(QuadSPI_Type *base) { - volatile uint32_t i = 0; + uint32_t i = 0; /* Reset AHB domain and buffer domian */ base->MCR |= (QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_qspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_qspi.h index 40f5ee413c..be090e821e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_qspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_qspi.h @@ -1,9 +1,12 @@ /* + * The Clear BSD License * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * 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. @@ -12,10 +15,11 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * 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 @@ -44,10 +48,43 @@ /*! @name Driver version */ /*@{*/ -/*! @brief I2C driver version 2.0.1. */ -#define FSL_QSPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! @brief QSPI driver version 2.0.2. */ +#define FSL_QSPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*@}*/ +/*! @brief Macro functions for LUT table */ +#define QSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \ + (QuadSPI_LUT_INSTR0(cmd0) | QuadSPI_LUT_PAD0(pad0) | QuadSPI_LUT_OPRND0(op0) | QuadSPI_LUT_INSTR1(cmd1) | \ + QuadSPI_LUT_PAD1(pad1) | QuadSPI_LUT_OPRND1(op1)) + +/*! @brief Macro for QSPI LUT command */ +#define QSPI_CMD (0x1U) +#define QSPI_ADDR (0x2U) +#define QSPI_DUMMY (0x3U) +#define QSPI_MODE (0x4U) +#define QSPI_MODE2 (0x5U) +#define QSPI_MODE4 (0x6U) +#define QSPI_READ (0x7U) +#define QSPI_WRITE (0x8U) +#define QSPI_JMP_ON_CS (0x9U) +#define QSPI_ADDR_DDR (0xAU) +#define QSPI_MODE_DDR (0xBU) +#define QSPI_MODE2_DDR (0xCU) +#define QSPI_MODE4_DDR (0xDU) +#define QSPI_READ_DDR (0xEU) +#define QSPI_WRITE_DDR (0xFU) +#define QSPI_DATA_LEARN (0x10U) +#define QSPI_CMD_DDR (0x11U) +#define QSPI_CADDR (0x12U) +#define QSPI_CADDR_DDR (0x13U) +#define QSPI_STOP (0x0U) + +/*! @brief Macro for QSPI PAD */ +#define QSPI_PAD_1 (0x0U) +#define QSPI_PAD_2 (0x1U) +#define QSPI_PAD_4 (0x2U) +#define QSPI_PAD_8 (0x3U) + /*! @brief Status structure of QSPI.*/ enum _status_t { @@ -91,15 +128,19 @@ typedef enum _qspi_endianness /*! @brief QSPI error flags */ enum _qspi_error_flags { - kQSPI_DataLearningFail = QuadSPI_FR_DLPFF_MASK, /*!< Data learning pattern failure flag */ + kQSPI_DataLearningFail = (int)QuadSPI_FR_DLPFF_MASK, /*!< Data learning pattern failure flag */ kQSPI_TxBufferFill = QuadSPI_FR_TBFF_MASK, /*!< Tx buffer fill flag */ kQSPI_TxBufferUnderrun = QuadSPI_FR_TBUF_MASK, /*!< Tx buffer underrun flag */ kQSPI_IllegalInstruction = QuadSPI_FR_ILLINE_MASK, /*!< Illegal instruction error flag */ kQSPI_RxBufferOverflow = QuadSPI_FR_RBOF_MASK, /*!< Rx buffer overflow flag */ kQSPI_RxBufferDrain = QuadSPI_FR_RBDF_MASK, /*!< Rx buffer drain flag */ kQSPI_AHBSequenceError = QuadSPI_FR_ABSEF_MASK, /*!< AHB sequence error flag */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_AITEF) || (!FSL_FEATURE_QSPI_HAS_NO_AITEF) kQSPI_AHBIllegalTransaction = QuadSPI_FR_AITEF_MASK, /*!< AHB illegal transaction error flag */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_AITEF */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_AIBSEF) || (!FSL_FEATURE_QSPI_HAS_NO_AIBSEF) kQSPI_AHBIllegalBurstSize = QuadSPI_FR_AIBSEF_MASK, /*!< AHB illegal burst error flag */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_AIBSEF */ kQSPI_AHBBufferOverflow = QuadSPI_FR_ABOF_MASK, /*!< AHB buffer overflow flag */ #if defined(FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR) && (FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR) kQSPI_IPCommandUsageError = QuadSPI_FR_IUEF_MASK, /*!< IP command usage error flag */ @@ -108,16 +149,18 @@ enum _qspi_error_flags kQSPI_IPCommandTriggerDuringIPAccess = QuadSPI_FR_IPIEF_MASK, /*!< IP command trigger cannot be executed */ kQSPI_IPCommandTriggerDuringAHBGrant = QuadSPI_FR_IPGEF_MASK, /*!< IP command trigger during AHB grant error */ kQSPI_IPCommandTransactionFinished = QuadSPI_FR_TFF_MASK, /*!< IP command transaction finished flag */ - kQSPI_FlagAll = 0x8C83F8D1U /*!< All error flag */ + kQSPI_FlagAll = (int)0x8C83F8D1U /*!< All error flag */ }; /*! @brief QSPI state bit */ enum _qspi_flags { - kQSPI_DataLearningSamplePoint = QuadSPI_SR_DLPSMP_MASK, /*!< Data learning sample point */ + kQSPI_DataLearningSamplePoint = (int)QuadSPI_SR_DLPSMP_MASK, /*!< Data learning sample point */ kQSPI_TxBufferFull = QuadSPI_SR_TXFULL_MASK, /*!< Tx buffer full flag */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA) kQSPI_TxDMA = QuadSPI_SR_TXDMA_MASK, /*!< Tx DMA is requested or running */ kQSPI_TxWatermark = QuadSPI_SR_TXWA_MASK, /*!< Tx buffer watermark available */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */ kQSPI_TxBufferEnoughData = QuadSPI_SR_TXEDA_MASK, /*!< Tx buffer enough data available */ kQSPI_RxDMA = QuadSPI_SR_RXDMA_MASK, /*!< Rx DMA is requesting or running */ kQSPI_RxBufferFull = QuadSPI_SR_RXFULL_MASK, /*!< Rx buffer full */ @@ -135,14 +178,14 @@ enum _qspi_flags kQSPI_AHBAccess = QuadSPI_SR_AHB_ACC_MASK, /*!< AHB access */ kQSPI_IPAccess = QuadSPI_SR_IP_ACC_MASK, /*!< IP access */ kQSPI_Busy = QuadSPI_SR_BUSY_MASK, /*!< Module busy */ - kQSPI_StateAll = 0xEF897FE7U /*!< All flags */ + kQSPI_StateAll = (int)0xEF897FE7U /*!< All flags */ }; /*! @brief QSPI interrupt enable */ enum _qspi_interrupt_enable { kQSPI_DataLearningFailInterruptEnable = - QuadSPI_RSER_DLPFIE_MASK, /*!< Data learning pattern failure interrupt enable */ + (int)QuadSPI_RSER_DLPFIE_MASK, /*!< Data learning pattern failure interrupt enable */ kQSPI_TxBufferFillInterruptEnable = QuadSPI_RSER_TBFIE_MASK, /*!< Tx buffer fill interrupt enable */ kQSPI_TxBufferUnderrunInterruptEnable = QuadSPI_RSER_TBUIE_MASK, /*!< Tx buffer underrun interrupt enable */ kQSPI_IllegalInstructionInterruptEnable = @@ -150,10 +193,14 @@ enum _qspi_interrupt_enable kQSPI_RxBufferOverflowInterruptEnable = QuadSPI_RSER_RBOIE_MASK, /*!< Rx buffer overflow interrupt enable */ kQSPI_RxBufferDrainInterruptEnable = QuadSPI_RSER_RBDIE_MASK, /*!< Rx buffer drain interrupt enable */ kQSPI_AHBSequenceErrorInterruptEnable = QuadSPI_RSER_ABSEIE_MASK, /*!< AHB sequence error interrupt enable */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_AITEF) || (!FSL_FEATURE_QSPI_HAS_NO_AITEF) kQSPI_AHBIllegalTransactionInterruptEnable = QuadSPI_RSER_AITIE_MASK, /*!< AHB illegal transaction error interrupt enable */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_AITEF */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_AIBSEF) || (!FSL_FEATURE_QSPI_HAS_NO_AIBSEF) kQSPI_AHBIllegalBurstSizeInterruptEnable = QuadSPI_RSER_AIBSIE_MASK, /*!< AHB illegal burst error interrupt enable */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_AIBSEF */ kQSPI_AHBBufferOverflowInterruptEnable = QuadSPI_RSER_ABOIE_MASK, /*!< AHB buffer overflow interrupt enable */ #if defined(FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR) && (FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR) kQSPI_IPCommandUsageErrorInterruptEnable = QuadSPI_RSER_IUEIE_MASK, /*!< IP command usage error interrupt enable */ @@ -166,15 +213,21 @@ enum _qspi_interrupt_enable QuadSPI_RSER_IPGEIE_MASK, /*!< IP command trigger during AHB grant error */ kQSPI_IPCommandTransactionFinishedInterruptEnable = QuadSPI_RSER_TFIE_MASK, /*!< IP command transaction finished interrupt enable */ - kQSPI_AllInterruptEnable = 0x8C83F8D1U /*!< All error interrupt enable */ + kQSPI_AllInterruptEnable = (int)0x8C83F8D1U /*!< All error interrupt enable */ }; /*! @brief QSPI DMA request flag */ enum _qspi_dma_enable { +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA) kQSPI_TxBufferFillDMAEnable = QuadSPI_RSER_TBFDE_MASK, /*!< Tx buffer fill DMA */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */ kQSPI_RxBufferDrainDMAEnable = QuadSPI_RSER_RBDDE_MASK, /*!< Rx buffer drain DMA */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA) kQSPI_AllDDMAEnable = QuadSPI_RSER_TBFDE_MASK | QuadSPI_RSER_RBDDE_MASK /*!< All DMA source */ +#else + kQSPI_AllDDMAEnable = QuadSPI_RSER_RBDDE_MASK /* All DMA source */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */ }; /*! @brief Phrase shift number for DQS mode. */ @@ -229,7 +282,9 @@ typedef struct _qspi_flash_config uint32_t flashB2Size; /*!< Flash B2 size */ #endif /* FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE */ uint32_t lookuptable[FSL_FEATURE_QSPI_LUT_DEPTH]; /*!< Flash command in LUT */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TDH) || (!FSL_FEATURE_QSPI_HAS_NO_TDH) uint32_t dataHoldTime; /*!< Data line hold time. */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_TDH */ uint32_t CSHoldTime; /*!< CS line hold time */ uint32_t CSSetupTime; /*!< CS line setup time*/ uint32_t cloumnspace; /*!< Column space size */ @@ -257,6 +312,13 @@ extern "C" { * @{ */ +/*! +* @brief Get the instance number for QSPI. +* +* @param base QSPI base pointer. +*/ +uint32_t QSPI_GetInstance(QuadSPI_Type *base); + /*! * @brief Initializes the QSPI module and internal state. * @@ -462,9 +524,9 @@ static inline void QSPI_SetIPCommandAddress(QuadSPI_Type *base, uint32_t addr) * @param base Pointer to QuadSPI Type. * @param size IP command size. */ -static inline void QSPI_SetIPCommandSize(QuadSPI_Type *base, uint32_t size) +static inline void QSPI_SetIPCommandSize(QuadSPI_Type *base, uint16_t size) { - base->IPCR = ((base->IPCR & (~QuadSPI_IPCR_IDATSZ_MASK)) | QuadSPI_IPCR_IDATSZ(size)); + base->IPCR_ACCESSBIT.IDATZ = size; } /*! @brief Executes IP commands located in LUT table. @@ -546,6 +608,24 @@ static inline void QSPI_ClearCommandSequence(QuadSPI_Type *base, qspi_command_se base->SPTRCLR = seq; } +/*! + * @brief Enable or disable DDR mode. + * + * @param base QSPI base pointer + * @param eanble True means enable DDR mode, false means disable DDR mode. + */ +static inline void QSPI_EnableDDRMode(QuadSPI_Type *base, bool enable) +{ + if (enable) + { + base->MCR |= QuadSPI_MCR_DDR_EN_MASK; + } + else + { + base->MCR &= ~QuadSPI_MCR_DDR_EN_MASK; + } +} + /*!@ brief Set the RX buffer readout area. * * This function can set the RX buffer readout, from AHB bus or IP Bus. @@ -576,7 +656,10 @@ static inline void QSPI_WriteData(QuadSPI_Type *base, uint32_t data) /*! * @brief Receives a buffer of data bytes using a blocking method. - * @note This function blocks via polling until all bytes have been sent. + * @note This function blocks via polling until all bytes have been sent. Users shall notice that + * this receive size shall not bigger than 64 bytes. As this interface is used to read flash status registers. + * For flash contents read, please use AHB bus read, this is much more efficiency. + * * @param base QSPI base pointer * @param buffer The data bytes to send * @param size The number of data bytes to receive @@ -616,7 +699,10 @@ static inline void QSPI_TransferSendBlocking(QuadSPI_Type *base, qspi_transfer_t * @brief Reads data from the QSPI receive buffer in polling way. * * This function reads continuous data from the QSPI receive buffer/FIFO. This function is a blocking - * function and can return only when finished. This function uses polling methods. + * function and can return only when finished. This function uses polling methods. Users shall notice that + * this receive size shall not bigger than 64 bytes. As this interface is used to read flash status registers. + * For flash contents read, please use AHB bus read, this is much more efficiency. + * * @param base Pointer to QuadSPI Type. * @param xfer QSPI transfer structure. */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PeripheralNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PeripheralNames.h index ac0c713d85..025f8b03f4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PeripheralNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PeripheralNames.h @@ -95,6 +95,10 @@ typedef enum { DAC_0 = 0 } DACName; +typedef enum { + QSPI_0 = 0 +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PeripheralPins.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PeripheralPins.c index 1f3749556c..36ef59b3d6 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PeripheralPins.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PeripheralPins.c @@ -158,3 +158,28 @@ const PinMap PinMap_PWM[] = { {NC , NC , 0} }; +const PinMap PinMap_QSPI_DATA[] = { + {PTE0, QSPI_0, 5}, + {PTE2, QSPI_0, 5}, + {PTE3, QSPI_0, 5}, + {PTE4, QSPI_0, 5}, + {PTE6, QSPI_0, 5}, + {PTE7, QSPI_0, 5}, + {PTE8, QSPI_0, 5}, + {PTE9, QSPI_0, 5}, + {PTE10, QSPI_0, 5}, + {NC , NC , 0} +}; + +const PinMap PinMap_QSPI_SCLK[] = { + {PTE1, QSPI_0, 5}, + {PTE7, QSPI_0, 5}, + {NC , NC , 0} +}; + +const PinMap PinMap_QSPI_SSEL[] = { + {PTE5, QSPI_0, 5}, + {PTE11, QSPI_0, 5}, + {NC , NC , 0} +}; + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PinNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PinNames.h index 45b4a118e7..914e8fa4f3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PinNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/PinNames.h @@ -156,6 +156,14 @@ typedef enum { A4 = PTB1, A5 = PTB0, + /**** QSPI FLASH pins ****/ + QSPI_FLASH1_IO0 = PTE2, + QSPI_FLASH1_IO1 = PTE4, + QSPI_FLASH1_IO2 = PTE3, + QSPI_FLASH1_IO3 = PTE0, + QSPI_FLASH1_SCK = PTE1, + QSPI_FLASH1_CSN = PTE5, + // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/mbed_overrides.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/mbed_overrides.c index e7f22f54ea..8daa01d48c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/mbed_overrides.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/mbed_overrides.c @@ -63,3 +63,10 @@ void serial_clock_init(void) { CLOCK_SetLpuartClock(2U); } + +// Get the QSPI clock frequency +uint32_t qspi_get_freq(void) +{ + return CLOCK_GetFreq(kCLOCK_McgPll0Clk); +} + diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/qspi_device.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/qspi_device.h new file mode 100644 index 0000000000..69f3f00617 --- /dev/null +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_FRDM/qspi_device.h @@ -0,0 +1,77 @@ +/* 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_qspi.h" + +#define FLASH_SIZE 0x01000000U +#define FLASH_PAGE_SIZE 256U + +qspi_flash_config_t single_config = { + .flashA1Size = FLASH_SIZE, /* 16MB */ + .flashA2Size = 0, +#if defined(FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) && (FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) + .flashB1Size = FLASH_SIZE, + .flashB2Size = 0, +#endif +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TDH) || (!FSL_FEATURE_QSPI_HAS_NO_TDH) + .dataHoldTime = 0, +#endif + .CSHoldTime = 0, + .CSSetupTime = 0, + .cloumnspace = 0, + .dataLearnValue = 0, + .endian = kQSPI_64LittleEndian, + .enableWordAddress = false +}; + +/* Pre-defined LUT definitions */ +uint32_t lut[FSL_FEATURE_QSPI_LUT_DEPTH] = + { + /* Seq0 : Read */ + /* CMD: 0x03 - Read, Single pad */ + /* ADDR: 0x18 - 24bit address, Single pad */ + /* READ: 0x80 - Read 128 bytes, Single pad */ + /* JUMP_ON_CS: 0 */ + [0] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x03, QSPI_ADDR, QSPI_PAD_1, 0x18), + [1] = QSPI_LUT_SEQ(QSPI_READ, QSPI_PAD_1, 0x80, QSPI_JMP_ON_CS, QSPI_PAD_1, 0x0), + + /* Seq1: Page Program */ + /* CMD: 0x02 - Page Program, Single pad */ + /* ADDR: 0x18 - 24bit address, Single pad */ + /* WRITE: 0x80 - Write 128 bytes at one pass, Single pad */ + [4] = QSPI_LUT_SEQ(QSPI_CMD, QSPI_PAD_1, 0x02, QSPI_ADDR, QSPI_PAD_1, 0x18), + [5] = QSPI_LUT_SEQ(QSPI_WRITE, QSPI_PAD_1, 0x80, 0, 0, 0), + + /* Match MISRA rule */ + [63] = 0 + }; + +#endif /* _FSL_MBED_QSPI_DEVICE_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/device/MKL82Z7.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/device/MKL82Z7.h index e790851f6d..3e3a0b029e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/device/MKL82Z7.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/device/MKL82Z7.h @@ -7691,7 +7691,14 @@ typedef struct { typedef struct { __IO uint32_t MCR; /**< Module Configuration Register, offset: 0x0 */ uint8_t RESERVED_0[4]; - __IO uint32_t IPCR; /**< IP Configuration Register, offset: 0x8 */ + union { /* offset: 0x8 */ + __IO uint32_t IPCR; /**< IP Configuration Register, offset: 0x8 */ + struct { + __IO uint16_t IDATZ; /**< IP data transfer size, offset: 0x8 */ + __IO uint8_t PAR_EN; /**< IP data transfer size, offset: 0xA */ + __IO uint8_t SEQID; /**< IP data transfer size, offset: 0xB */ + } IPCR_ACCESSBIT; + }; __IO uint32_t FLSHCR; /**< Flash Configuration Register, offset: 0xC */ __IO uint32_t BUF0CR; /**< Buffer0 Configuration Register, offset: 0x10 */ __IO uint32_t BUF1CR; /**< Buffer1 Configuration Register, offset: 0x14 */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi.c index 00f511cd73..8f8a68a9d1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi.c @@ -1,9 +1,12 @@ /* + * The Clear BSD License * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * 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. @@ -12,10 +15,11 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * 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 @@ -30,6 +34,12 @@ #include "fsl_qspi.h" +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.qspi" +#endif + + /******************************************************************************* * Definitations ******************************************************************************/ @@ -40,25 +50,21 @@ enum _qspi_transfer_state kQSPI_TxError /*!< Transfer error occured. */ }; -#define QSPI_AHB_BUFFER_REG(base, index) (*((uint32_t *)&(base->BUF0CR) + index)) +#define QSPI_AHB_BUFFER_REG(base, index) (((volatile uint32_t *)&((base)->BUF0CR))[(index)]) /******************************************************************************* * Prototypes ******************************************************************************/ -/*! -* @brief Get the instance number for QSPI. -* -* @param base QSPI base pointer. -*/ -uint32_t QSPI_GetInstance(QuadSPI_Type *base); /******************************************************************************* * Variables ******************************************************************************/ /* Base pointer array */ static QuadSPI_Type *const s_qspiBases[] = QuadSPI_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Clock name array */ static const clock_ip_name_t s_qspiClock[] = QSPI_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -68,7 +74,7 @@ uint32_t QSPI_GetInstance(QuadSPI_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_QuadSPI_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_qspiBases); instance++) { if (s_qspiBases[instance] == base) { @@ -76,7 +82,7 @@ uint32_t QSPI_GetInstance(QuadSPI_Type *base) } } - assert(instance < FSL_FEATURE_SOC_QuadSPI_COUNT); + assert(instance < ARRAY_SIZE(s_qspiBases)); return instance; } @@ -86,8 +92,10 @@ void QSPI_Init(QuadSPI_Type *base, qspi_config_t *config, uint32_t srcClock_Hz) uint32_t i = 0; uint32_t val = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable QSPI clock */ CLOCK_EnableClock(s_qspiClock[QSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Do software reset to QSPI module */ QSPI_SoftwareReset(base); @@ -98,12 +106,21 @@ void QSPI_Init(QuadSPI_Type *base, qspi_config_t *config, uint32_t srcClock_Hz) /* Configure QSPI */ QSPI_Enable(base, false); +#if !defined (FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL) || (!FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL) /* Set qspi clock source */ base->SOCCR = config->clockSource; /* Set the divider of QSPI clock */ base->MCR &= ~QuadSPI_MCR_SCLKCFG_MASK; - base->MCR |= QuadSPI_MCR_SCLKCFG(srcClock_Hz / config->baudRate - 1U); + + if (srcClock_Hz % config->baudRate) { + /* In case we cannot get the exact baudrate, get the closest lower value */ + base->MCR |= QuadSPI_MCR_SCLKCFG(srcClock_Hz / config->baudRate); + } else { + base->MCR |= QuadSPI_MCR_SCLKCFG(srcClock_Hz / config->baudRate - 1U); + } + +#endif /* FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL */ /* Set AHB buffer size and buffer master */ for (i = 0; i < FSL_FEATURE_QSPI_AHB_BUFFER_COUNT; i++) @@ -123,8 +140,11 @@ void QSPI_Init(QuadSPI_Type *base, qspi_config_t *config, uint32_t srcClock_Hz) /* Set watermark */ base->RBCT &= ~QuadSPI_RBCT_WMRK_MASK; base->RBCT |= QuadSPI_RBCT_WMRK(config->rxWatermark - 1); + +#if !defined (FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA) base->TBCT &= ~QuadSPI_TBCT_WMRK_MASK; base->TBCT |= QuadSPI_TBCT_WMRK(config->txWatermark - 1); +#endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */ /* Enable QSPI module */ if (config->enableQspi) @@ -149,7 +169,9 @@ void QSPI_GetDefaultQspiConfig(qspi_config_t *config) void QSPI_Deinit(QuadSPI_Type *base) { QSPI_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(s_qspiClock[QSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void QSPI_SetFlashConfig(QuadSPI_Type *base, qspi_flash_config_t *config) @@ -165,14 +187,18 @@ void QSPI_SetFlashConfig(QuadSPI_Type *base, qspi_flash_config_t *config) base->SFA1AD = address; address += config->flashA2Size; base->SFA2AD = address; +#if defined(FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) && (FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) address += config->flashB1Size; base->SFB1AD = address; address += config->flashB2Size; base->SFB2AD = address; +#endif /* FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE */ +#if !defined (FSL_FEATURE_QSPI_HAS_NO_SFACR) || (!FSL_FEATURE_QSPI_HAS_NO_SFACR) /* Set Word Addressable feature */ val = QuadSPI_SFACR_WA(config->enableWordAddress) | QuadSPI_SFACR_CAS(config->cloumnspace); base->SFACR = val; +#endif /* FSL_FEATURE_QSPI_HAS_NO_SFACR */ /* Config look up table */ base->LUTKEY = 0x5AF05AF0U; @@ -184,9 +210,13 @@ void QSPI_SetFlashConfig(QuadSPI_Type *base, qspi_flash_config_t *config) base->LUTKEY = 0x5AF05AF0U; base->LCKCR = 0x1U; +#if !defined (FSL_FEATURE_QSPI_HAS_NO_TDH) || (!FSL_FEATURE_QSPI_HAS_NO_TDH) /* Config flash timing */ val = QuadSPI_FLSHCR_TCSS(config->CSHoldTime) | QuadSPI_FLSHCR_TDH(config->dataHoldTime) | QuadSPI_FLSHCR_TCSH(config->CSSetupTime); +#else + val = QuadSPI_FLSHCR_TCSS(config->CSHoldTime) | QuadSPI_FLSHCR_TCSH(config->CSSetupTime); +#endif /* FSL_FEATURE_QSPI_HAS_NO_TDH */ base->FLSHCR = val; /* Set flash endianness */ @@ -199,7 +229,7 @@ void QSPI_SetFlashConfig(QuadSPI_Type *base, qspi_flash_config_t *config) void QSPI_SoftwareReset(QuadSPI_Type *base) { - volatile uint32_t i = 0; + uint32_t i = 0; /* Reset AHB domain and buffer domian */ base->MCR |= (QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK); @@ -314,15 +344,27 @@ void QSPI_ReadBlocking(QuadSPI_Type *base, uint32_t *buffer, size_t size) { uint32_t i = 0; uint32_t j = 0; - uint32_t level = 0; + uint32_t temp = 0; + uint32_t level = (base->RBCT & QuadSPI_RBCT_WMRK_MASK) + 1U; while (i < size / 4) { /* Check if there is data */ - do + if ((size / 4 - i) < level) { - level = (base->RBSR & QuadSPI_RBSR_RDBFL_MASK) >> QuadSPI_RBSR_RDBFL_SHIFT; - } while (!level); + do + { + temp = (base->RBSR & QuadSPI_RBSR_RDBFL_MASK) >> QuadSPI_RBSR_RDBFL_SHIFT; + } while (!temp); + } + else + { + while ((QSPI_GetStatusFlags(base) & kQSPI_RxWatermark) == 0U) + { + } + } + + level = (level < (size / 4 - i)) ? level : (size / 4 - i); /* Data from RBDR */ if (base->RBCT & QuadSPI_RBCT_RXBRD_MASK) @@ -341,5 +383,8 @@ void QSPI_ReadBlocking(QuadSPI_Type *base, uint32_t *buffer, size_t size) } } i += level; + + /* Clear the Buffer */ + QSPI_ClearErrorFlag(base, kQSPI_RxBufferDrain); } } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi.h index aff961228d..be090e821e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi.h @@ -1,9 +1,12 @@ /* + * The Clear BSD License * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * 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. @@ -12,10 +15,11 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * 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 @@ -38,17 +42,49 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief I2C driver version 2.0.1. */ -#define FSL_QSPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! @brief QSPI driver version 2.0.2. */ +#define FSL_QSPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*@}*/ +/*! @brief Macro functions for LUT table */ +#define QSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \ + (QuadSPI_LUT_INSTR0(cmd0) | QuadSPI_LUT_PAD0(pad0) | QuadSPI_LUT_OPRND0(op0) | QuadSPI_LUT_INSTR1(cmd1) | \ + QuadSPI_LUT_PAD1(pad1) | QuadSPI_LUT_OPRND1(op1)) + +/*! @brief Macro for QSPI LUT command */ +#define QSPI_CMD (0x1U) +#define QSPI_ADDR (0x2U) +#define QSPI_DUMMY (0x3U) +#define QSPI_MODE (0x4U) +#define QSPI_MODE2 (0x5U) +#define QSPI_MODE4 (0x6U) +#define QSPI_READ (0x7U) +#define QSPI_WRITE (0x8U) +#define QSPI_JMP_ON_CS (0x9U) +#define QSPI_ADDR_DDR (0xAU) +#define QSPI_MODE_DDR (0xBU) +#define QSPI_MODE2_DDR (0xCU) +#define QSPI_MODE4_DDR (0xDU) +#define QSPI_READ_DDR (0xEU) +#define QSPI_WRITE_DDR (0xFU) +#define QSPI_DATA_LEARN (0x10U) +#define QSPI_CMD_DDR (0x11U) +#define QSPI_CADDR (0x12U) +#define QSPI_CADDR_DDR (0x13U) +#define QSPI_STOP (0x0U) + +/*! @brief Macro for QSPI PAD */ +#define QSPI_PAD_1 (0x0U) +#define QSPI_PAD_2 (0x1U) +#define QSPI_PAD_4 (0x2U) +#define QSPI_PAD_8 (0x3U) + /*! @brief Status structure of QSPI.*/ enum _status_t { @@ -92,31 +128,39 @@ typedef enum _qspi_endianness /*! @brief QSPI error flags */ enum _qspi_error_flags { - kQSPI_DataLearningFail = QuadSPI_FR_DLPFF_MASK, /*!< Data learning pattern failure flag */ - kQSPI_TxBufferFill = QuadSPI_FR_TBFF_MASK, /*!< Tx buffer fill flag */ - kQSPI_TxBufferUnderrun = QuadSPI_FR_TBUF_MASK, /*!< Tx buffer underrun flag */ - kQSPI_IllegalInstruction = QuadSPI_FR_ILLINE_MASK, /*!< Illegal instruction error flag */ - kQSPI_RxBufferOverflow = QuadSPI_FR_RBOF_MASK, /*!< Rx buffer overflow flag */ - kQSPI_RxBufferDrain = QuadSPI_FR_RBDF_MASK, /*!< Rx buffer drain flag */ - kQSPI_AHBSequenceError = QuadSPI_FR_ABSEF_MASK, /*!< AHB sequence error flag */ - kQSPI_AHBIllegalTransaction = QuadSPI_FR_AITEF_MASK, /*!< AHB illegal transaction error flag */ - kQSPI_AHBIllegalBurstSize = QuadSPI_FR_AIBSEF_MASK, /*!< AHB illegal burst error flag */ - kQSPI_AHBBufferOverflow = QuadSPI_FR_ABOF_MASK, /*!< AHB buffer overflow flag */ + kQSPI_DataLearningFail = (int)QuadSPI_FR_DLPFF_MASK, /*!< Data learning pattern failure flag */ + kQSPI_TxBufferFill = QuadSPI_FR_TBFF_MASK, /*!< Tx buffer fill flag */ + kQSPI_TxBufferUnderrun = QuadSPI_FR_TBUF_MASK, /*!< Tx buffer underrun flag */ + kQSPI_IllegalInstruction = QuadSPI_FR_ILLINE_MASK, /*!< Illegal instruction error flag */ + kQSPI_RxBufferOverflow = QuadSPI_FR_RBOF_MASK, /*!< Rx buffer overflow flag */ + kQSPI_RxBufferDrain = QuadSPI_FR_RBDF_MASK, /*!< Rx buffer drain flag */ + kQSPI_AHBSequenceError = QuadSPI_FR_ABSEF_MASK, /*!< AHB sequence error flag */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_AITEF) || (!FSL_FEATURE_QSPI_HAS_NO_AITEF) + kQSPI_AHBIllegalTransaction = QuadSPI_FR_AITEF_MASK, /*!< AHB illegal transaction error flag */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_AITEF */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_AIBSEF) || (!FSL_FEATURE_QSPI_HAS_NO_AIBSEF) + kQSPI_AHBIllegalBurstSize = QuadSPI_FR_AIBSEF_MASK, /*!< AHB illegal burst error flag */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_AIBSEF */ + kQSPI_AHBBufferOverflow = QuadSPI_FR_ABOF_MASK, /*!< AHB buffer overflow flag */ +#if defined(FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR) && (FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR) kQSPI_IPCommandUsageError = QuadSPI_FR_IUEF_MASK, /*!< IP command usage error flag */ +#endif /* FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR */ kQSPI_IPCommandTriggerDuringAHBAccess = QuadSPI_FR_IPAEF_MASK, /*!< IP command trigger during AHB access error */ kQSPI_IPCommandTriggerDuringIPAccess = QuadSPI_FR_IPIEF_MASK, /*!< IP command trigger cannot be executed */ kQSPI_IPCommandTriggerDuringAHBGrant = QuadSPI_FR_IPGEF_MASK, /*!< IP command trigger during AHB grant error */ kQSPI_IPCommandTransactionFinished = QuadSPI_FR_TFF_MASK, /*!< IP command transaction finished flag */ - kQSPI_FlagAll = 0x8C83F8D1U /*!< All error flag */ + kQSPI_FlagAll = (int)0x8C83F8D1U /*!< All error flag */ }; /*! @brief QSPI state bit */ enum _qspi_flags { - kQSPI_DataLearningSamplePoint = QuadSPI_SR_DLPSMP_MASK, /*!< Data learning sample point */ + kQSPI_DataLearningSamplePoint = (int)QuadSPI_SR_DLPSMP_MASK, /*!< Data learning sample point */ kQSPI_TxBufferFull = QuadSPI_SR_TXFULL_MASK, /*!< Tx buffer full flag */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA) kQSPI_TxDMA = QuadSPI_SR_TXDMA_MASK, /*!< Tx DMA is requested or running */ kQSPI_TxWatermark = QuadSPI_SR_TXWA_MASK, /*!< Tx buffer watermark available */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */ kQSPI_TxBufferEnoughData = QuadSPI_SR_TXEDA_MASK, /*!< Tx buffer enough data available */ kQSPI_RxDMA = QuadSPI_SR_RXDMA_MASK, /*!< Rx DMA is requesting or running */ kQSPI_RxBufferFull = QuadSPI_SR_RXFULL_MASK, /*!< Rx buffer full */ @@ -134,14 +178,14 @@ enum _qspi_flags kQSPI_AHBAccess = QuadSPI_SR_AHB_ACC_MASK, /*!< AHB access */ kQSPI_IPAccess = QuadSPI_SR_IP_ACC_MASK, /*!< IP access */ kQSPI_Busy = QuadSPI_SR_BUSY_MASK, /*!< Module busy */ - kQSPI_StateAll = 0xEF897FE7U /*!< All flags */ + kQSPI_StateAll = (int)0xEF897FE7U /*!< All flags */ }; /*! @brief QSPI interrupt enable */ enum _qspi_interrupt_enable { kQSPI_DataLearningFailInterruptEnable = - QuadSPI_RSER_DLPFIE_MASK, /*!< Data learning pattern failure interrupt enable */ + (int)QuadSPI_RSER_DLPFIE_MASK, /*!< Data learning pattern failure interrupt enable */ kQSPI_TxBufferFillInterruptEnable = QuadSPI_RSER_TBFIE_MASK, /*!< Tx buffer fill interrupt enable */ kQSPI_TxBufferUnderrunInterruptEnable = QuadSPI_RSER_TBUIE_MASK, /*!< Tx buffer underrun interrupt enable */ kQSPI_IllegalInstructionInterruptEnable = @@ -149,12 +193,18 @@ enum _qspi_interrupt_enable kQSPI_RxBufferOverflowInterruptEnable = QuadSPI_RSER_RBOIE_MASK, /*!< Rx buffer overflow interrupt enable */ kQSPI_RxBufferDrainInterruptEnable = QuadSPI_RSER_RBDIE_MASK, /*!< Rx buffer drain interrupt enable */ kQSPI_AHBSequenceErrorInterruptEnable = QuadSPI_RSER_ABSEIE_MASK, /*!< AHB sequence error interrupt enable */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_AITEF) || (!FSL_FEATURE_QSPI_HAS_NO_AITEF) kQSPI_AHBIllegalTransactionInterruptEnable = QuadSPI_RSER_AITIE_MASK, /*!< AHB illegal transaction error interrupt enable */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_AITEF */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_AIBSEF) || (!FSL_FEATURE_QSPI_HAS_NO_AIBSEF) kQSPI_AHBIllegalBurstSizeInterruptEnable = - QuadSPI_RSER_AIBSIE_MASK, /*!< AHB illegal burst error interrupt enable */ - kQSPI_AHBBufferOverflowInterruptEnable = QuadSPI_RSER_ABOIE_MASK, /*!< AHB buffer overflow interrupt enable */ + QuadSPI_RSER_AIBSIE_MASK, /*!< AHB illegal burst error interrupt enable */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_AIBSEF */ + kQSPI_AHBBufferOverflowInterruptEnable = QuadSPI_RSER_ABOIE_MASK, /*!< AHB buffer overflow interrupt enable */ +#if defined(FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR) && (FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR) kQSPI_IPCommandUsageErrorInterruptEnable = QuadSPI_RSER_IUEIE_MASK, /*!< IP command usage error interrupt enable */ +#endif /* FSL_FEATURE_QSPI_HAS_IP_COMMAND_USAGE_ERROR */ kQSPI_IPCommandTriggerDuringAHBAccessInterruptEnable = QuadSPI_RSER_IPAEIE_MASK, /*!< IP command trigger during AHB access error */ kQSPI_IPCommandTriggerDuringIPAccessInterruptEnable = @@ -163,15 +213,21 @@ enum _qspi_interrupt_enable QuadSPI_RSER_IPGEIE_MASK, /*!< IP command trigger during AHB grant error */ kQSPI_IPCommandTransactionFinishedInterruptEnable = QuadSPI_RSER_TFIE_MASK, /*!< IP command transaction finished interrupt enable */ - kQSPI_AllInterruptEnable = 0x8C83F8D1U /*!< All error interrupt enable */ + kQSPI_AllInterruptEnable = (int)0x8C83F8D1U /*!< All error interrupt enable */ }; /*! @brief QSPI DMA request flag */ enum _qspi_dma_enable { +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA) kQSPI_TxBufferFillDMAEnable = QuadSPI_RSER_TBFDE_MASK, /*!< Tx buffer fill DMA */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */ kQSPI_RxBufferDrainDMAEnable = QuadSPI_RSER_RBDDE_MASK, /*!< Rx buffer drain DMA */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA) kQSPI_AllDDMAEnable = QuadSPI_RSER_TBFDE_MASK | QuadSPI_RSER_RBDDE_MASK /*!< All DMA source */ +#else + kQSPI_AllDDMAEnable = QuadSPI_RSER_RBDDE_MASK /* All DMA source */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */ }; /*! @brief Phrase shift number for DQS mode. */ @@ -219,12 +275,16 @@ typedef struct QspiConfig /*! @brief External flash configuration items*/ typedef struct _qspi_flash_config { - uint32_t flashA1Size; /*!< Flash A1 size */ - uint32_t flashA2Size; /*!< Flash A2 size */ + uint32_t flashA1Size; /*!< Flash A1 size */ + uint32_t flashA2Size; /*!< Flash A2 size */ +#if defined(FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) && (FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) uint32_t flashB1Size; /*!< Flash B1 size */ uint32_t flashB2Size; /*!< Flash B2 size */ +#endif /* FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE */ uint32_t lookuptable[FSL_FEATURE_QSPI_LUT_DEPTH]; /*!< Flash command in LUT */ +#if !defined(FSL_FEATURE_QSPI_HAS_NO_TDH) || (!FSL_FEATURE_QSPI_HAS_NO_TDH) uint32_t dataHoldTime; /*!< Data line hold time. */ +#endif /* FSL_FEATURE_QSPI_HAS_NO_TDH */ uint32_t CSHoldTime; /*!< CS line hold time */ uint32_t CSSetupTime; /*!< CS line setup time*/ uint32_t cloumnspace; /*!< Column space size */ @@ -252,6 +312,13 @@ extern "C" { * @{ */ +/*! +* @brief Get the instance number for QSPI. +* +* @param base QSPI base pointer. +*/ +uint32_t QSPI_GetInstance(QuadSPI_Type *base); + /*! * @brief Initializes the QSPI module and internal state. * @@ -457,9 +524,9 @@ static inline void QSPI_SetIPCommandAddress(QuadSPI_Type *base, uint32_t addr) * @param base Pointer to QuadSPI Type. * @param size IP command size. */ -static inline void QSPI_SetIPCommandSize(QuadSPI_Type *base, uint32_t size) +static inline void QSPI_SetIPCommandSize(QuadSPI_Type *base, uint16_t size) { - base->IPCR = ((base->IPCR & (~QuadSPI_IPCR_IDATSZ_MASK)) | QuadSPI_IPCR_IDATSZ(size)); + base->IPCR_ACCESSBIT.IDATZ = size; } /*! @brief Executes IP commands located in LUT table. @@ -476,6 +543,7 @@ void QSPI_ExecuteIPCommand(QuadSPI_Type *base, uint32_t index); */ void QSPI_ExecuteAHBCommand(QuadSPI_Type *base, uint32_t index); +#if defined(FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) && (FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) /*! @brief Enables/disables the QSPI IP command parallel mode. * * @param base Pointer to QuadSPI Type. @@ -509,6 +577,7 @@ static inline void QSPI_EnableAHBParallelMode(QuadSPI_Type *base, bool enable) base->BFGENCR &= ~QuadSPI_BFGENCR_PAR_EN_MASK; } } +#endif /* FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE */ /*! @brief Updates the LUT table. * @@ -539,6 +608,24 @@ static inline void QSPI_ClearCommandSequence(QuadSPI_Type *base, qspi_command_se base->SPTRCLR = seq; } +/*! + * @brief Enable or disable DDR mode. + * + * @param base QSPI base pointer + * @param eanble True means enable DDR mode, false means disable DDR mode. + */ +static inline void QSPI_EnableDDRMode(QuadSPI_Type *base, bool enable) +{ + if (enable) + { + base->MCR |= QuadSPI_MCR_DDR_EN_MASK; + } + else + { + base->MCR &= ~QuadSPI_MCR_DDR_EN_MASK; + } +} + /*!@ brief Set the RX buffer readout area. * * This function can set the RX buffer readout, from AHB bus or IP Bus. @@ -569,7 +656,10 @@ static inline void QSPI_WriteData(QuadSPI_Type *base, uint32_t data) /*! * @brief Receives a buffer of data bytes using a blocking method. - * @note This function blocks via polling until all bytes have been sent. + * @note This function blocks via polling until all bytes have been sent. Users shall notice that + * this receive size shall not bigger than 64 bytes. As this interface is used to read flash status registers. + * For flash contents read, please use AHB bus read, this is much more efficiency. + * * @param base QSPI base pointer * @param buffer The data bytes to send * @param size The number of data bytes to receive @@ -609,7 +699,10 @@ static inline void QSPI_TransferSendBlocking(QuadSPI_Type *base, qspi_transfer_t * @brief Reads data from the QSPI receive buffer in polling way. * * This function reads continuous data from the QSPI receive buffer/FIFO. This function is a blocking - * function and can return only when finished. This function uses polling methods. + * function and can return only when finished. This function uses polling methods. Users shall notice that + * this receive size shall not bigger than 64 bytes. As this interface is used to read flash status registers. + * For flash contents read, please use AHB bus read, this is much more efficiency. + * * @param base Pointer to QuadSPI Type. * @param xfer QSPI transfer structure. */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/PeripheralPins.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/PeripheralPins.h index 97ef45eb62..ad78a7dc53 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/PeripheralPins.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/PeripheralPins.h @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #ifndef MBED_PERIPHERALPINS_H #define MBED_PERIPHERALPINS_H @@ -47,4 +47,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 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/objects.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/objects.h index 44ccb387bf..405f2e1778 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/objects.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/objects.h @@ -95,6 +95,12 @@ struct flash_s { flash_config_t flash_config; }; +#if DEVICE_QSPI +struct qspi_s { + uint32_t instance; +}; +#endif + #include "gpio_object.h" #ifdef __cplusplus diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/qspi_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/qspi_api.c new file mode 100644 index 0000000000..985dbba373 --- /dev/null +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/qspi_api.c @@ -0,0 +1,403 @@ +/* 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. + */ + +#if DEVICE_QSPI + +#include "qspi_api.h" +#include "mbed_error.h" +#include "cmsis.h" +#include "pinmap.h" +#include "PeripheralPins.h" +#include "qspi_device.h" + +/* Look-up table entry indices */ +#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 QuadSPI_Type *const qspi_addrs[] = QuadSPI_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) +{ + uint32_t clockSourceFreq = 0; + qspi_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; + } + + clockSourceFreq = qspi_get_freq(); + + /*Get QSPI default settings and configure the qspi */ + QSPI_GetDefaultQspiConfig(&config); + + /*Set AHB buffer size for reading data through AHB bus */ + config.AHBbufferSize[3] = FLASH_PAGE_SIZE; + + // tested all combinations, take first + obj->instance = qspi_data_first; + + QSPI_Init(qspi_addrs[obj->instance], &config, clockSourceFreq); + + /* Copy the pre-defined LUT table */ + memcpy(single_config.lookuptable, lut, sizeof(uint32_t) * FSL_FEATURE_QSPI_LUT_DEPTH); + + /*According to serial flash feature to configure flash settings */ + QSPI_SetFlashConfig(qspi_addrs[obj->instance], &single_config); + + qspi_frequency(obj, hz); + + 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) +{ + QSPI_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; + QuadSPI_Type *base = qspi_addrs[obj->instance]; + 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 > 16 || div < 1) { + status = QSPI_STATUS_INVALID_PARAMETER; + return status; + } + + + /* Configure QSPI */ + QSPI_Enable(base, false); + + /* Set the divider of QSPI clock */ + base->MCR &= ~QuadSPI_MCR_SCLKCFG_MASK; + base->MCR |= QuadSPI_MCR_SCLKCFG(div); + + QSPI_Enable(base, true); + + 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) +{ + uint32_t lut_seq[4] = {0, 0, 0, 0}; + uint8_t instr1 = QSPI_CMD, instr2 = 0; + uint8_t pad1 = command->instruction.bus_width, pad2 = 0; + uint8_t op1 = command->instruction.value, op2 = 0; + bool set_jmp_instr = false; + QuadSPI_Type *base = qspi_addrs[obj->instance]; + uint32_t addr = FSL_FEATURE_QSPI_AMBA_BASE; + + /* Check if the flash address is provided */ + if (command->address.disabled) { + /* Check if a second instruction is needed, this is for register accesses */ + if (tx_data != NULL && tx_size) { + instr2 = QSPI_WRITE; + pad2 = command->data.bus_width; + op2 = tx_size; + /* Read and write pointers of the TX buffer are reset to 0 */ + QSPI_ClearFifo(base, kQSPI_TxFifo); + /* Clear underrun error flag */ + QSPI_ClearErrorFlag(base, kQSPI_TxBufferUnderrun); + } + if (rx_data != NULL && rx_size) { + instr2 = QSPI_READ; + pad2 = command->data.bus_width; + op2 = rx_size; + /* Read and write pointers of the RX buffer are reset to 0 */ + QSPI_ClearFifo(base, kQSPI_RxFifo); + } + + /* Setup the LUT entry */ + lut_seq[0] = QSPI_LUT_SEQ(instr1, pad1, op1, instr2, pad2, op2); + } else { + instr2 = QSPI_ADDR; + pad2 = command->address.bus_width; + /* Number of address bits */ + op2 = (8 * (command->address.size + 1)); + addr += command->address.value; + + /* Setup the first LUT entry */ + lut_seq[0] = QSPI_LUT_SEQ(instr1, pad1, op1, instr2, pad2, op2); + + /* Clear the variables */ + instr1 = instr2 = 0; + pad1 = pad2 = 0; + op1 = op2 = 0; + + /* Check if a second LUT entry is needed */ + if (tx_data != NULL && tx_size) { + instr1 = QSPI_WRITE; + pad1 = command->data.bus_width; + op1 = 0x80; + /* Read and write pointers of the TX buffer are reset to 0 */ + QSPI_ClearFifo(base, kQSPI_TxFifo); + /* Clear underrun error flag */ + QSPI_ClearErrorFlag(base, kQSPI_TxBufferUnderrun); + } + if (rx_data != NULL && rx_size) { + instr1 = QSPI_READ; + pad1 = command->data.bus_width; + op1 = 0x80; + /* Read operations need a jump command at the end of the sequence */ + set_jmp_instr = true; + /* Read and write pointers of the TX buffer are reset to 0 */ + QSPI_ClearFifo(base, kQSPI_RxFifo); + } + + /* Setup more LUT entries if needed */ + if (instr1 != 0) { + /* Check if we need to add dummy entries */ + if (command->dummy_count > 0) { + instr2 = instr1; + pad2 = pad1; + op2 = op1; + + instr1 = QSPI_DUMMY; + pad1 = command->address.bus_width; + op1 = command->dummy_count; + } + /* Check if need to add jump command entry */ + if (set_jmp_instr) { + /* Need to add a jump command in the sequence */ + if (command->dummy_count > 0) { + /* Third LUT entry for jump command */ + lut_seq[2] = QSPI_LUT_SEQ(QSPI_JMP_ON_CS, QSPI_PAD_1, LUT3_SEQ_INDEX, 0, 0, 0); + } else { + /* As there is no dummy we have space in the second LUT entry to add jump command */ + instr2 = QSPI_JMP_ON_CS; + pad2 = QSPI_PAD_1; + op2 = 8; + } + } + /* Second LUT entry for read & write operations */ + lut_seq[1] = QSPI_LUT_SEQ(instr1, pad1, op1, instr2, pad2, op2); + } + } + + /* Update the LUT registers from index 8, prior entries have pre-defined LUT sequences + * which is used when the instruction is disabled + */ + if (!(command->instruction.disabled)) { + QSPI_UpdateLUT(base, LUT3_SEQ_INDEX, lut_seq); + } + + /* Setup the address */ + QSPI_SetIPCommandAddress(base, addr); + + /* Reset AHB domain and serial flash domain flops */ + QSPI_SoftwareReset(base); + while (QSPI_GetStatusFlags(base) & kQSPI_Busy) { + } +} + +qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length) +{ + uint32_t to_write = *length; + uint8_t *data_send = (uint8_t *)data; + QuadSPI_Type *base = qspi_addrs[obj->instance]; + + /* At least four words of data must be written to the TX buffer */ + if (to_write < MIN_SIZE) { + return QSPI_STATUS_INVALID_PARAMETER; + } + + /* Enforce word-sized access */ + if ((to_write & 0x3) != 0) { + return QSPI_STATUS_INVALID_PARAMETER; + } + + /* Prepare the write command */ + qspi_prepare_command(obj, command, data, to_write, NULL, 0); + + QSPI_SetIPCommandSize(base, to_write); + + if (to_write > (FSL_FEATURE_QSPI_TXFIFO_DEPTH * 4)) { + /* First write some data into TXFIFO to prevent underrun */ + QSPI_WriteBlocking(base, (uint32_t *)data_send, FSL_FEATURE_QSPI_TXFIFO_DEPTH * 4); + data_send += (FSL_FEATURE_QSPI_TXFIFO_DEPTH * 4); + to_write -= (FSL_FEATURE_QSPI_TXFIFO_DEPTH * 4); + } else { + QSPI_WriteBlocking(base, (uint32_t *)data_send, to_write); + to_write = 0; + } + + /* Start the program */ + if (command->instruction.disabled) { + /* If no instruction provided then use the pre-defined write sequence */ + QSPI_ExecuteIPCommand(base, LUT2_SEQ_INDEX); + } else { + /* Use the user-defined write sequence */ + QSPI_ExecuteIPCommand(base, LUT3_SEQ_INDEX); + } + + /* Write the remaining data to TXFIFO */ + if (to_write) { + QSPI_WriteBlocking(base, (uint32_t *)data_send, to_write); + } + + while (QSPI_GetStatusFlags(base) & (kQSPI_Busy | kQSPI_IPAccess)) { + } + + 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_QSPI_AMBA_BASE + command->address.value; + uint32_t to_read = *length; + QuadSPI_Type *base = qspi_addrs[obj->instance]; + + /* Enforce word-sized access */ + if ((to_read & 0x3) != 0) { + return QSPI_STATUS_INVALID_PARAMETER; + } + + /* Prepare for read command */ + qspi_prepare_command(obj, command, NULL, 0, data, to_read); + + /* Point to the read sequence in the LUT */ + if (command->instruction.disabled) { + /* If no instruction provided then use the pre-defined read sequence */ + QSPI_ExecuteAHBCommand(base, LUT1_SEQ_INDEX); + } else { + /* Use the user-defined write sequence */ + QSPI_ExecuteAHBCommand(base, LUT3_SEQ_INDEX); + } + + for (uint32_t i = 0; i < to_read / 4; i++) { + ((uint32_t*)data)[i] = *((uint32_t *)(dest_addr) + i); + } + + while (QSPI_GetStatusFlags(base) & (kQSPI_Busy | kQSPI_AHBAccess)) { + } + + 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) +{ + QuadSPI_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 sequence in the Look-up Table (LUT) */ + qspi_prepare_command(obj, command, tx_data, tx_size, rx_data, rx_size); + + /* Execute the sequence */ + QSPI_ExecuteIPCommand(base, LUT3_SEQ_INDEX); + while (QSPI_GetStatusFlags(base) & (kQSPI_Busy | kQSPI_IPAccess)) { + } + } else { + if (tx_data != NULL && tx_size) { + /* Transmit data to QSPI */ + /* Need to write at least 16 bytes into TX buffer */ + uint8_t val[MIN_SIZE]; + memset(val, 0, sizeof(val)); + memcpy(val, tx_data, tx_size); + + /* Setup the sequence in the Look-up Table (LUT) */ + qspi_prepare_command(obj, command, tx_data, tx_size, rx_data, rx_size); + + /* First write some data into TXFIFO to prevent from underrun */ + QSPI_WriteBlocking(base, (uint32_t *)val, MIN_SIZE); + + /* Use the user-defined write sequence */ + QSPI_ExecuteIPCommand(base, LUT3_SEQ_INDEX); + while (QSPI_GetStatusFlags(base) & (kQSPI_Busy | kQSPI_IPAccess)) { + } + } + + if (rx_data != NULL && rx_size) { + /* Receive data from QSPI */ + uint32_t val[MIN_SIZE / 4]; + memset(val, 0, sizeof(val)); + + /* Read data from the IP read buffers */ + QSPI_SetReadDataArea(base, kQSPI_ReadIP); + + /* Setup the sequence in the Look-up Table (LUT) */ + qspi_prepare_command(obj, command, tx_data, tx_size, rx_data, rx_size); + + /* Execute the sequence */ + QSPI_SetIPCommandSize(base, rx_size); + QSPI_ExecuteIPCommand(base, LUT3_SEQ_INDEX); + while (QSPI_GetStatusFlags(base) & (kQSPI_Busy | kQSPI_IPAccess)) { + } + + for (uint32_t i = 0, j =0; i < rx_size; i += 4, j++) { + val[j] = QSPI_ReadData(base); + } + + memcpy(rx_data, val, rx_size); + } + } + + return QSPI_STATUS_OK; +} + +#endif + diff --git a/targets/targets.json b/targets/targets.json index bb00b7a596..d1eea7b4cd 100755 --- a/targets/targets.json +++ b/targets/targets.json @@ -574,13 +574,14 @@ "is_disk_virtual": true, "inherits": ["Target"], "detect_code": ["0218"], - "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH", "QSPI"], "release_versions": ["2", "5"], "device_name": "MKL82Z128xxx7" }, "USENSE": { "inherits": ["KL82Z"], "extra_labels_remove": ["FRDM"], + "device_has_remove": ["QSPI"], "supported_form_factors": [] }, "KW24D": { @@ -758,7 +759,7 @@ "macros": ["CPU_MK82FN256VDC15", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0217"], - "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH", "QSPI"], "release_versions": ["2", "5"], "device_name": "MK82FN256xxx15" }, @@ -766,6 +767,7 @@ "inherits": ["K82F"], "extra_labels_remove": ["FRDM"], "components_remove": ["SPIF"], + "device_has_remove": ["QSPI"], "supported_form_factors": [] }, "FAMILY_STM32": { @@ -2195,7 +2197,7 @@ "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L471QG", - "bootloader_supported": true + "bootloader_supported": true }, "MTB_MTS_DRAGONFLY": { "inherits": ["FAMILY_STM32"], @@ -4507,7 +4509,7 @@ "extra_labels": ["TOSHIBA"], "macros": ["__TMPM4G9__"], "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], - "device_has": ["ANALOGIN", "ANALOGOUT", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SPI", "I2C", "I2CSLAVE", "STDIO_MESSAGES", "FLASH", "SLEEP", "USTICKER"], + "device_has": ["ANALOGIN", "ANALOGOUT", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SPI", "I2C", "I2CSLAVE", "STDIO_MESSAGES", "FLASH", "SLEEP", "USTICKER"], "device_name": "TMPM4G9F15FG", "detect_code": ["7016"], "release_versions": ["5"],