mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #10435 from morser499/pr/cy-smif
Add support for QSPI to Cypress Boardspull/10525/head
commit
40f8cb95a8
|
@ -0,0 +1,191 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-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_S25FL512S_H
|
||||
#define MBED_QSPI_FLASH_S25FL512S_H
|
||||
|
||||
#define QSPI_FLASH_CHIP_STRING "Cypress S25FL512S"
|
||||
#define QSPI_FLASH_CYPRESS_S25FL512S
|
||||
|
||||
// Command for reading configuration register
|
||||
#define QSPI_CMD_RDCR0 0x35 // To read Quad (QE) enable bit
|
||||
// Command for writing status/configuration register
|
||||
#define QSPI_CMD_WRSR 0x01 // To write Qual (QE) enable bit
|
||||
// Command for reading status register
|
||||
#define QSPI_CMD_RDSR 0x05 // To read WIP bit of status register 1
|
||||
|
||||
|
||||
|
||||
// Command for reading security register
|
||||
#define QSPI_CMD_RDSCUR 0x2B
|
||||
|
||||
// Command for setting Reset Enable
|
||||
#define QSPI_CMD_RSTEN 0x66
|
||||
// Command for setting Reset
|
||||
#define QSPI_CMD_RST 0xF0 //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 2300000 // 2.3 seconds
|
||||
// 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_1I4O 0x32 // 1-1-4 mode // 1-4-4 is not supported by S25FL512S
|
||||
|
||||
// write operations max time [us] (datasheet max time + 15%)
|
||||
#define QSPI_PAGE_PROG_MAX_TIME 1500 // 1.5ms
|
||||
|
||||
#define QSPI_PAGE_SIZE 512 // 512B
|
||||
#define QSPI_SECTOR_SIZE 262144 // 256kB
|
||||
#define QSPI_SECTOR_COUNT 256 // 64 MB
|
||||
|
||||
// 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_2IO 0xBB // 1-2-2 mode - dual I/O
|
||||
#define QSPI_CMD_READ_1I2O 0x3B // 1-1-2 mode - dual output
|
||||
#define QSPI_CMD_READ_4IO 0xEB // 1-4-4 mode - quad I/O
|
||||
#define QSPI_CMD_READ_1I4O 0x6B // 1-1-4 mode - quad output
|
||||
|
||||
// Alt (mode) value for quad I/O read
|
||||
#define QSPI_ALT_READ_4IO 0x01 // 1-4-4 mode only
|
||||
|
||||
#define QSPI_READ_1IO_DUMMY_CYCLE 0
|
||||
#define QSPI_READ_FAST_DUMMY_CYCLE 8
|
||||
#define QSPI_READ_2IO_DUMMY_CYCLE 4 // dual I/O
|
||||
#define QSPI_READ_1I2O_DUMMY_CYCLE 8 // dual output
|
||||
#define QSPI_READ_4IO_DUMMY_CYCLE 6 // quad I/O - 2 cycles for Mode or Alt (4 bits per cycle x 2 cycles = 1 byte) + 4 dummy cycles
|
||||
#define QSPI_READ_1I4O_DUMMY_CYCLE 8 // quad output
|
||||
|
||||
// Commands for erasing
|
||||
#define QSPI_CMD_ERASE_SECTOR 0xD8 // 256kB
|
||||
#define QSPI_CMD_ERASE_CHIP 0x60 // or 0xC7
|
||||
|
||||
// erase operations max time [us] (datasheet max time + 15%)
|
||||
#define QSPI_ERASE_SECTOR_MAX_TIME 2990000 // 1.15*2600 ~ 2900 ms
|
||||
|
||||
// max frequency for basic rw operation (for fast mode)
|
||||
#define QSPI_COMMON_MAX_FREQUENCY 50000000
|
||||
|
||||
#define QSPI_STATUS_REG_SIZE 1
|
||||
#define QSPI_CONFIG_REG_0_SIZE 1
|
||||
#define QSPI_SECURITY_REG_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) //
|
||||
#define STATUS_BIT_BP1 (1 << 3) //
|
||||
#define STATUS_BIT_BP2 (1 << 4) //
|
||||
#define STATUS_BIT_BP3 (1 << 5) //
|
||||
#define STATUS_BIT_QE (1 << 1) // Quad Enable
|
||||
#define STATUS_BIT_SRWD (1 << 7) // status register write protect
|
||||
|
||||
// configuration register 0
|
||||
// bit 0, 1, 2, 4, 5, 7 reserved
|
||||
#define CONFIG0_BIT_TB (1 << 3) // Top/Bottom area protect
|
||||
#define CONFIG0_BIT_DC (1 << 6) // Dummy Cycle
|
||||
|
||||
// configuration register 1
|
||||
// bit 0, 2, 3, 4, 5, 6, 7 reserved
|
||||
#define CONFIG1_BIT_LH (1 << 1) // 0 = Ultra Low power mode, 1 = High performance mode
|
||||
|
||||
|
||||
|
||||
#define QUAD_IO_ENABLE() \
|
||||
\
|
||||
const int32_t reg_size = QSPI_STATUS_REG_SIZE + QSPI_CONFIG_REG_0_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 (read_register(CONFIG_REG0, reg_data + QSPI_STATUS_REG_SIZE, \
|
||||
QSPI_CONFIG_REG_0_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
if (write_enable(qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
reg_data[1] |= 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(CONFIG_REG0, 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 QUAD_IO_DISABLE() \
|
||||
\
|
||||
const int32_t reg_size = QSPI_STATUS_REG_SIZE + QSPI_CONFIG_REG_0_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 (read_register(CONFIG_REG0, reg_data + QSPI_STATUS_REG_SIZE, \
|
||||
QSPI_CONFIG_REG_0_SIZE, qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
if (write_enable(qspi) != QSPI_STATUS_OK) { \
|
||||
return QSPI_STATUS_ERROR; \
|
||||
} \
|
||||
\
|
||||
reg_data[1] &= ~(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(CONFIG_REG0, 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_S25FL512S_H
|
|
@ -58,5 +58,8 @@
|
|||
#elif defined(TARGET_LPC546XX)
|
||||
#include "NXP/LPC546XX/flash_config.h"
|
||||
|
||||
#elif (defined(TARGET_CY8CPROTO_062_4343W) || defined(TARGET_CY8CKIT_062_WIFI_BT) || defined(TARGET_CY8CKIT_062_BLE))
|
||||
#include "S25FL512S_config.h"
|
||||
|
||||
#endif
|
||||
#endif // MBED_FLASH_CONFIGS_H
|
||||
|
|
|
@ -483,6 +483,41 @@ Case cases[] = {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WRITE_1_1_4
|
||||
Case("qspi write(1-1-4)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-1-1)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-1-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
#ifdef READ_2_2_2
|
||||
Case("qspi write(1-1-4)/x1 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x4 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(2-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(2-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
#endif
|
||||
Case("qspi write(1-1-4)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-1-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(1-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
#ifdef READ_4_4_4
|
||||
Case("qspi write(1-1-4)/x1 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x4 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(4-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-1-4)/x1 read(4-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WRITE_1_4_4
|
||||
Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
|
||||
Case("qspi write(1-4-4)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "flash_configs/flash_configs.h"
|
||||
#include "mbed.h"
|
||||
|
||||
static qspi_status_t quad_io_enable(Qspi &qspi);
|
||||
static qspi_status_t quad_io_disable(Qspi &qspi);
|
||||
static qspi_status_t extended_enable(Qspi &qspi);
|
||||
static qspi_status_t extended_disable(Qspi &qspi);
|
||||
static qspi_status_t dual_enable(Qspi &qspi);
|
||||
|
@ -201,7 +203,9 @@ qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi)
|
|||
|
||||
qspi_status_t mode_enable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
|
||||
{
|
||||
if (is_extended_mode(inst_width, addr_width, data_width)) {
|
||||
if (is_quad_io_mode(inst_width, addr_width, data_width)) {
|
||||
return quad_io_enable(qspi);
|
||||
} else if (is_extended_mode(inst_width, addr_width, data_width)) {
|
||||
return extended_enable(qspi);
|
||||
} else if (is_dual_mode(inst_width, addr_width, data_width)) {
|
||||
return dual_enable(qspi);
|
||||
|
@ -214,7 +218,9 @@ qspi_status_t mode_enable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_widt
|
|||
|
||||
qspi_status_t mode_disable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
|
||||
{
|
||||
if (is_extended_mode(inst_width, addr_width, data_width)) {
|
||||
if (is_quad_io_mode(inst_width, addr_width, data_width)) {
|
||||
return quad_io_disable(qspi);
|
||||
} else if (is_extended_mode(inst_width, addr_width, data_width)) {
|
||||
return extended_disable(qspi);
|
||||
} else if (is_dual_mode(inst_width, addr_width, data_width)) {
|
||||
return dual_disable(qspi);
|
||||
|
@ -225,6 +231,24 @@ qspi_status_t mode_disable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_wid
|
|||
}
|
||||
}
|
||||
|
||||
static qspi_status_t quad_io_enable(Qspi &qspi)
|
||||
{
|
||||
#ifdef QUAD_IO_ENABLE
|
||||
QUAD_IO_ENABLE();
|
||||
#else
|
||||
return QSPI_STATUS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static qspi_status_t quad_io_disable(Qspi &qspi)
|
||||
{
|
||||
#ifdef QUAD_IO_DISABLE
|
||||
QUAD_IO_DISABLE();
|
||||
#else
|
||||
return QSPI_STATUS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static qspi_status_t extended_enable(Qspi &qspi)
|
||||
{
|
||||
#ifdef EXTENDED_SPI_ENABLE
|
||||
|
@ -298,6 +322,11 @@ qspi_status_t fast_mode_disable(Qspi &qspi)
|
|||
#endif
|
||||
}
|
||||
|
||||
bool is_quad_io_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
|
||||
{
|
||||
return (inst_width == QSPI_CFG_BUS_SINGLE) && ((addr_width == QSPI_CFG_BUS_QUAD) || (data_width == QSPI_CFG_BUS_QUAD));
|
||||
}
|
||||
|
||||
bool is_extended_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
|
||||
{
|
||||
return (inst_width == QSPI_CFG_BUS_SINGLE) && ((addr_width != QSPI_CFG_BUS_SINGLE) || (data_width != QSPI_CFG_BUS_SINGLE));
|
||||
|
|
|
@ -62,6 +62,9 @@ struct Qspi {
|
|||
#ifdef QSPI_CMD_WRITE_2IO
|
||||
#define WRITE_1_2_2 MODE_1_2_2, QSPI_CMD_WRITE_2IO
|
||||
#endif
|
||||
#ifdef QSPI_CMD_WRITE_1I4O // Quad page program - command: 0x32
|
||||
#define WRITE_1_1_4 MODE_1_1_4, QSPI_CMD_WRITE_1I4O
|
||||
#endif
|
||||
#ifdef QSPI_CMD_WRITE_4IO
|
||||
#define WRITE_1_4_4 MODE_1_4_4, QSPI_CMD_WRITE_4IO
|
||||
#endif
|
||||
|
@ -147,6 +150,7 @@ qspi_status_t fast_mode_disable(Qspi &qspi);
|
|||
|
||||
qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi);
|
||||
|
||||
bool is_quad_io_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
|
||||
bool is_extended_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
|
||||
bool is_dual_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
|
||||
bool is_quad_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
|
||||
|
|
|
@ -38,6 +38,18 @@
|
|||
"QSPI_FREQ": "32000000",
|
||||
"QSPI_MIN_READ_SIZE": "4",
|
||||
"QSPI_MIN_PROG_SIZE": "4"
|
||||
},
|
||||
"CY8CPROTO_062_4343W": {
|
||||
"QSPI_FREQ": "50000000",
|
||||
"QSPI_MIN_PROG_SIZE": "512"
|
||||
},
|
||||
"CY8CKIT_062_WIFI_BT": {
|
||||
"QSPI_FREQ": "50000000",
|
||||
"QSPI_MIN_PROG_SIZE": "512"
|
||||
},
|
||||
"CY8CKIT_062_BLE": {
|
||||
"QSPI_FREQ": "50000000",
|
||||
"QSPI_MIN_PROG_SIZE": "512"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,13 @@ extern const PinMap PinMap_SPI_SCLK[];
|
|||
extern const PinMap PinMap_SPI_SSEL[];
|
||||
#endif
|
||||
|
||||
//*** QSPI ***
|
||||
#if DEVICE_QSPI
|
||||
extern const PinMap PinMap_QSPI_SCLK[];
|
||||
extern const PinMap PinMap_QSPI_DATA[];
|
||||
extern const PinMap PinMap_QSPI_SSEL[];
|
||||
#endif
|
||||
|
||||
//*** ADC ***
|
||||
#if DEVICE_ANALOGIN
|
||||
extern const PinMap PinMap_ADC[];
|
||||
|
|
|
@ -112,6 +112,10 @@ typedef enum {
|
|||
ADC_0 = (int)SAR_BASE,
|
||||
} ADCName;
|
||||
|
||||
typedef enum {
|
||||
SMIF_0 = (int)SMIF0_BASE,
|
||||
} SMIFName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -463,3 +463,32 @@ const PinMap PinMap_ADC[] = {
|
|||
};
|
||||
#endif // DEVICE_ANALOGIN
|
||||
|
||||
#if DEVICE_QSPI
|
||||
const PinMap PinMap_QSPI_SCLK[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_7, SMIF_0, CY_PIN_OUT_FUNCTION(P11_7_SMIF_SPI_CLK, 0)},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_data pins are defined in the order 0 to 7
|
||||
const PinMap PinMap_QSPI_DATA[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_6, SMIF_0, CY_PIN_OUT_FUNCTION(P11_6_SMIF_SPI_DATA0, 0)}, // spi_data0
|
||||
{P11_5, SMIF_0, CY_PIN_OUT_FUNCTION(P11_5_SMIF_SPI_DATA1, 0)}, // spi_data1
|
||||
{P11_4, SMIF_0, CY_PIN_OUT_FUNCTION(P11_4_SMIF_SPI_DATA2, 0)}, // spi_data2
|
||||
{P11_3, SMIF_0, CY_PIN_OUT_FUNCTION(P11_3_SMIF_SPI_DATA3, 0)}, // spi_data3
|
||||
{P12_0, SMIF_0, CY_PIN_OUT_FUNCTION(P12_0_SMIF_SPI_DATA4, 0)}, // spi_data4
|
||||
{P12_1, SMIF_0, CY_PIN_OUT_FUNCTION(P12_1_SMIF_SPI_DATA5, 0)}, // spi_data5
|
||||
{P12_2, SMIF_0, CY_PIN_OUT_FUNCTION(P12_2_SMIF_SPI_DATA6, 0)}, // spi_data6
|
||||
{P12_3, SMIF_0, CY_PIN_OUT_FUNCTION(P12_3_SMIF_SPI_DATA7, 0)}, // spi_data7
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_select pins are defined in the order 0 to 3
|
||||
const PinMap PinMap_QSPI_SSEL[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_2, SMIF_0, CY_PIN_OUT_FUNCTION(P11_2_SMIF_SPI_SELECT0, 0)}, // spi_select0
|
||||
{P11_1, SMIF_0, CY_PIN_OUT_FUNCTION(P11_1_SMIF_SPI_SELECT1, 0)}, // spi_select1
|
||||
{P11_0, SMIF_0, CY_PIN_OUT_FUNCTION(P11_0_SMIF_SPI_SELECT2, 0)}, // spi_select2
|
||||
{P12_4, SMIF_0, CY_PIN_OUT_FUNCTION(P12_4_SMIF_SPI_SELECT3, 0)}, // spi_select3
|
||||
{NC, NC, 0}
|
||||
};
|
||||
#endif // DEVICE_QSPI
|
||||
|
||||
|
|
|
@ -226,6 +226,13 @@ typedef enum {
|
|||
QSPI_IO_2 = P11_4,
|
||||
QSPI_IO_3 = P11_3,
|
||||
QSPI_SEL = P11_2,
|
||||
|
||||
QSPI_FLASH1_IO0 = QSPI_IO_0,
|
||||
QSPI_FLASH1_IO1 = QSPI_IO_1,
|
||||
QSPI_FLASH1_IO2 = QSPI_IO_2,
|
||||
QSPI_FLASH1_IO3 = QSPI_IO_3,
|
||||
QSPI_FLASH1_SCK = QSPI_CLK,
|
||||
QSPI_FLASH1_CSN = QSPI_SEL,
|
||||
|
||||
// Standardized interfaces names
|
||||
STDIO_UART_TX = UART_TX,
|
||||
|
|
|
@ -106,6 +106,10 @@ typedef enum {
|
|||
DAC_0 = (int)CTDAC0_BASE,
|
||||
} DACName;
|
||||
|
||||
typedef enum {
|
||||
SMIF_0 = (int)SMIF0_BASE,
|
||||
} SMIFName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -364,3 +364,32 @@ const PinMap PinMap_DAC[] = {
|
|||
{NC, NC, 0}
|
||||
};
|
||||
#endif // DEVICE_ANALOGIN
|
||||
|
||||
#if DEVICE_QSPI
|
||||
const PinMap PinMap_QSPI_SCLK[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_7, SMIF_0, CY_PIN_OUT_FUNCTION(P11_7_SMIF_SPI_CLK, 0)},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_data pins are defined in the order 0 to 7
|
||||
const PinMap PinMap_QSPI_DATA[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_6, SMIF_0, CY_PIN_OUT_FUNCTION(P11_6_SMIF_SPI_DATA0, 0)}, // spi_data0
|
||||
{P11_5, SMIF_0, CY_PIN_OUT_FUNCTION(P11_5_SMIF_SPI_DATA1, 0)}, // spi_data1
|
||||
{P11_4, SMIF_0, CY_PIN_OUT_FUNCTION(P11_4_SMIF_SPI_DATA2, 0)}, // spi_data2
|
||||
{P11_3, SMIF_0, CY_PIN_OUT_FUNCTION(P11_3_SMIF_SPI_DATA3, 0)}, // spi_data3
|
||||
{P12_0, SMIF_0, CY_PIN_OUT_FUNCTION(P12_0_SMIF_SPI_DATA4, 0)}, // spi_data4
|
||||
{P12_1, SMIF_0, CY_PIN_OUT_FUNCTION(P12_1_SMIF_SPI_DATA5, 0)}, // spi_data5
|
||||
{P12_2, SMIF_0, CY_PIN_OUT_FUNCTION(P12_2_SMIF_SPI_DATA6, 0)}, // spi_data6
|
||||
{P12_3, SMIF_0, CY_PIN_OUT_FUNCTION(P12_3_SMIF_SPI_DATA7, 0)}, // spi_data7
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_select pins are defined in the order 0 to 3
|
||||
const PinMap PinMap_QSPI_SSEL[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_2, SMIF_0, CY_PIN_OUT_FUNCTION(P11_2_SMIF_SPI_SELECT0, 0)}, // spi_select0
|
||||
{P11_1, SMIF_0, CY_PIN_OUT_FUNCTION(P11_1_SMIF_SPI_SELECT1, 0)}, // spi_select1
|
||||
{P11_0, SMIF_0, CY_PIN_OUT_FUNCTION(P11_0_SMIF_SPI_SELECT2, 0)}, // spi_select2
|
||||
{P12_4, SMIF_0, CY_PIN_OUT_FUNCTION(P12_4_SMIF_SPI_SELECT3, 0)}, // spi_select3
|
||||
{NC, NC, 0}
|
||||
};
|
||||
#endif // DEVICE_QSPI
|
||||
|
|
|
@ -215,6 +215,13 @@ typedef enum {
|
|||
QSPI_IO_2 = P11_4,
|
||||
QSPI_IO_3 = P11_3,
|
||||
QSPI_SEL = P11_2,
|
||||
|
||||
QSPI_FLASH1_IO0 = QSPI_IO_0,
|
||||
QSPI_FLASH1_IO1 = QSPI_IO_1,
|
||||
QSPI_FLASH1_IO2 = QSPI_IO_2,
|
||||
QSPI_FLASH1_IO3 = QSPI_IO_3,
|
||||
QSPI_FLASH1_SCK = QSPI_CLK,
|
||||
QSPI_FLASH1_CSN = QSPI_SEL,
|
||||
|
||||
// Standardized interfaces names
|
||||
STDIO_UART_TX = UART_TX,
|
||||
|
|
|
@ -106,6 +106,10 @@ typedef enum {
|
|||
DAC_0 = (int)CTDAC0_BASE,
|
||||
} DACName;
|
||||
|
||||
typedef enum {
|
||||
SMIF_0 = (int)SMIF0_BASE,
|
||||
} SMIFName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -434,3 +434,32 @@ const PinMap PinMap_DAC[] = {
|
|||
{NC, NC, 0}
|
||||
};
|
||||
#endif // DEVICE_ANALOGIN
|
||||
|
||||
#if DEVICE_QSPI
|
||||
const PinMap PinMap_QSPI_SCLK[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_7, SMIF_0, CY_PIN_OUT_FUNCTION(P11_7_SMIF_SPI_CLK, 0)},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_data pins are defined in the order 0 to 7
|
||||
const PinMap PinMap_QSPI_DATA[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_6, SMIF_0, CY_PIN_OUT_FUNCTION(P11_6_SMIF_SPI_DATA0, 0)}, // spi_data0
|
||||
{P11_5, SMIF_0, CY_PIN_OUT_FUNCTION(P11_5_SMIF_SPI_DATA1, 0)}, // spi_data1
|
||||
{P11_4, SMIF_0, CY_PIN_OUT_FUNCTION(P11_4_SMIF_SPI_DATA2, 0)}, // spi_data2
|
||||
{P11_3, SMIF_0, CY_PIN_OUT_FUNCTION(P11_3_SMIF_SPI_DATA3, 0)}, // spi_data3
|
||||
{P12_0, SMIF_0, CY_PIN_OUT_FUNCTION(P12_0_SMIF_SPI_DATA4, 0)}, // spi_data4
|
||||
{P12_1, SMIF_0, CY_PIN_OUT_FUNCTION(P12_1_SMIF_SPI_DATA5, 0)}, // spi_data5
|
||||
{P12_2, SMIF_0, CY_PIN_OUT_FUNCTION(P12_2_SMIF_SPI_DATA6, 0)}, // spi_data6
|
||||
{P12_3, SMIF_0, CY_PIN_OUT_FUNCTION(P12_3_SMIF_SPI_DATA7, 0)}, // spi_data7
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_select pins are defined in the order 0 to 3
|
||||
const PinMap PinMap_QSPI_SSEL[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_2, SMIF_0, CY_PIN_OUT_FUNCTION(P11_2_SMIF_SPI_SELECT0, 0)}, // spi_select0
|
||||
{P11_1, SMIF_0, CY_PIN_OUT_FUNCTION(P11_1_SMIF_SPI_SELECT1, 0)}, // spi_select1
|
||||
{P11_0, SMIF_0, CY_PIN_OUT_FUNCTION(P11_0_SMIF_SPI_SELECT2, 0)}, // spi_select2
|
||||
{P12_4, SMIF_0, CY_PIN_OUT_FUNCTION(P12_4_SMIF_SPI_SELECT3, 0)}, // spi_select3
|
||||
{NC, NC, 0}
|
||||
};
|
||||
#endif // DEVICE_QSPI
|
||||
|
|
|
@ -226,6 +226,13 @@ typedef enum {
|
|||
QSPI_IO_2 = P11_4,
|
||||
QSPI_IO_3 = P11_3,
|
||||
QSPI_SEL = P11_2,
|
||||
|
||||
QSPI_FLASH1_IO0 = QSPI_IO_0,
|
||||
QSPI_FLASH1_IO1 = QSPI_IO_1,
|
||||
QSPI_FLASH1_IO2 = QSPI_IO_2,
|
||||
QSPI_FLASH1_IO3 = QSPI_IO_3,
|
||||
QSPI_FLASH1_SCK = QSPI_CLK,
|
||||
QSPI_FLASH1_CSN = QSPI_SEL,
|
||||
|
||||
// Standardized interfaces names
|
||||
STDIO_UART_TX = UART_TX,
|
||||
|
|
|
@ -112,6 +112,10 @@ typedef enum {
|
|||
ADC_0 = (int)SAR_BASE,
|
||||
} ADCName;
|
||||
|
||||
typedef enum {
|
||||
SMIF_0 = (int)SMIF0_BASE,
|
||||
} SMIFName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -463,3 +463,32 @@ const PinMap PinMap_ADC[] = {
|
|||
};
|
||||
#endif // DEVICE_ANALOGIN
|
||||
|
||||
#if DEVICE_QSPI
|
||||
const PinMap PinMap_QSPI_SCLK[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_7, SMIF_0, CY_PIN_OUT_FUNCTION(P11_7_SMIF_SPI_CLK, 0)},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_data pins are defined in the order 0 to 7
|
||||
const PinMap PinMap_QSPI_DATA[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_6, SMIF_0, CY_PIN_OUT_FUNCTION(P11_6_SMIF_SPI_DATA0, 0)}, // spi_data0
|
||||
{P11_5, SMIF_0, CY_PIN_OUT_FUNCTION(P11_5_SMIF_SPI_DATA1, 0)}, // spi_data1
|
||||
{P11_4, SMIF_0, CY_PIN_OUT_FUNCTION(P11_4_SMIF_SPI_DATA2, 0)}, // spi_data2
|
||||
{P11_3, SMIF_0, CY_PIN_OUT_FUNCTION(P11_3_SMIF_SPI_DATA3, 0)}, // spi_data3
|
||||
{P12_0, SMIF_0, CY_PIN_OUT_FUNCTION(P12_0_SMIF_SPI_DATA4, 0)}, // spi_data4
|
||||
{P12_1, SMIF_0, CY_PIN_OUT_FUNCTION(P12_1_SMIF_SPI_DATA5, 0)}, // spi_data5
|
||||
{P12_2, SMIF_0, CY_PIN_OUT_FUNCTION(P12_2_SMIF_SPI_DATA6, 0)}, // spi_data6
|
||||
{P12_3, SMIF_0, CY_PIN_OUT_FUNCTION(P12_3_SMIF_SPI_DATA7, 0)}, // spi_data7
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_select pins are defined in the order 0 to 3
|
||||
const PinMap PinMap_QSPI_SSEL[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_2, SMIF_0, CY_PIN_OUT_FUNCTION(P11_2_SMIF_SPI_SELECT0, 0)}, // spi_select0
|
||||
{P11_1, SMIF_0, CY_PIN_OUT_FUNCTION(P11_1_SMIF_SPI_SELECT1, 0)}, // spi_select1
|
||||
{P11_0, SMIF_0, CY_PIN_OUT_FUNCTION(P11_0_SMIF_SPI_SELECT2, 0)}, // spi_select2
|
||||
{P12_4, SMIF_0, CY_PIN_OUT_FUNCTION(P12_4_SMIF_SPI_SELECT3, 0)}, // spi_select3
|
||||
{NC, NC, 0}
|
||||
};
|
||||
#endif // DEVICE_QSPI
|
||||
|
||||
|
|
|
@ -209,6 +209,13 @@ typedef enum {
|
|||
QSPI_IO_2 = P11_4,
|
||||
QSPI_IO_3 = P11_3,
|
||||
QSPI_SEL = P11_2,
|
||||
|
||||
QSPI_FLASH1_IO0 = QSPI_IO_0,
|
||||
QSPI_FLASH1_IO1 = QSPI_IO_1,
|
||||
QSPI_FLASH1_IO2 = QSPI_IO_2,
|
||||
QSPI_FLASH1_IO3 = QSPI_IO_3,
|
||||
QSPI_FLASH1_SCK = QSPI_CLK,
|
||||
QSPI_FLASH1_CSN = QSPI_SEL,
|
||||
|
||||
// Standardized interfaces names
|
||||
STDIO_UART_TX = UART_TX,
|
||||
|
|
|
@ -106,6 +106,10 @@ typedef enum {
|
|||
DAC_0 = (int)CTDAC0_BASE,
|
||||
} DACName;
|
||||
|
||||
typedef enum {
|
||||
SMIF_0 = (int)SMIF0_BASE,
|
||||
} SMIFName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -434,3 +434,32 @@ const PinMap PinMap_DAC[] = {
|
|||
{NC, NC, 0}
|
||||
};
|
||||
#endif // DEVICE_ANALOGIN
|
||||
|
||||
#if DEVICE_QSPI
|
||||
const PinMap PinMap_QSPI_SCLK[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_7, SMIF_0, CY_PIN_OUT_FUNCTION(P11_7_SMIF_SPI_CLK, 0)},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_data pins are defined in the order 0 to 7
|
||||
const PinMap PinMap_QSPI_DATA[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_6, SMIF_0, CY_PIN_OUT_FUNCTION(P11_6_SMIF_SPI_DATA0, 0)}, // spi_data0
|
||||
{P11_5, SMIF_0, CY_PIN_OUT_FUNCTION(P11_5_SMIF_SPI_DATA1, 0)}, // spi_data1
|
||||
{P11_4, SMIF_0, CY_PIN_OUT_FUNCTION(P11_4_SMIF_SPI_DATA2, 0)}, // spi_data2
|
||||
{P11_3, SMIF_0, CY_PIN_OUT_FUNCTION(P11_3_SMIF_SPI_DATA3, 0)}, // spi_data3
|
||||
{P12_0, SMIF_0, CY_PIN_OUT_FUNCTION(P12_0_SMIF_SPI_DATA4, 0)}, // spi_data4
|
||||
{P12_1, SMIF_0, CY_PIN_OUT_FUNCTION(P12_1_SMIF_SPI_DATA5, 0)}, // spi_data5
|
||||
{P12_2, SMIF_0, CY_PIN_OUT_FUNCTION(P12_2_SMIF_SPI_DATA6, 0)}, // spi_data6
|
||||
{P12_3, SMIF_0, CY_PIN_OUT_FUNCTION(P12_3_SMIF_SPI_DATA7, 0)}, // spi_data7
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
// Ensure that the spi_select pins are defined in the order 0 to 3
|
||||
const PinMap PinMap_QSPI_SSEL[] = { // does not use PERI clock, uses HFCLK2
|
||||
{P11_2, SMIF_0, CY_PIN_OUT_FUNCTION(P11_2_SMIF_SPI_SELECT0, 0)}, // spi_select0
|
||||
{P11_1, SMIF_0, CY_PIN_OUT_FUNCTION(P11_1_SMIF_SPI_SELECT1, 0)}, // spi_select1
|
||||
{P11_0, SMIF_0, CY_PIN_OUT_FUNCTION(P11_0_SMIF_SPI_SELECT2, 0)}, // spi_select2
|
||||
{P12_4, SMIF_0, CY_PIN_OUT_FUNCTION(P12_4_SMIF_SPI_SELECT3, 0)}, // spi_select3
|
||||
{NC, NC, 0}
|
||||
};
|
||||
#endif // DEVICE_QSPI
|
||||
|
|
|
@ -198,6 +198,13 @@ typedef enum {
|
|||
QSPI_IO_2 = P11_4,
|
||||
QSPI_IO_3 = P11_3,
|
||||
QSPI_SEL = P11_2,
|
||||
|
||||
QSPI_FLASH1_IO0 = QSPI_IO_0,
|
||||
QSPI_FLASH1_IO1 = QSPI_IO_1,
|
||||
QSPI_FLASH1_IO2 = QSPI_IO_2,
|
||||
QSPI_FLASH1_IO3 = QSPI_IO_3,
|
||||
QSPI_FLASH1_SCK = QSPI_CLK,
|
||||
QSPI_FLASH1_CSN = QSPI_SEL,
|
||||
|
||||
// Standardized interfaces names
|
||||
STDIO_UART_TX = UART_TX,
|
||||
|
|
|
@ -135,6 +135,16 @@ struct spi_s {
|
|||
};
|
||||
#endif // DEVICE_SPI
|
||||
|
||||
#if DEVICE_QSPI
|
||||
#include "cy_smif.h"
|
||||
|
||||
struct qspi_s {
|
||||
SMIF_Type *base;
|
||||
cy_stc_smif_context_t context;
|
||||
cy_en_smif_slave_select_t slaveSelect;
|
||||
};
|
||||
#endif // DEVICE_QSPI
|
||||
|
||||
#if DEVICE_I2C
|
||||
#include "cy_scb_i2c.h"
|
||||
|
||||
|
|
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2019 Cypress Semiconductor Corporation
|
||||
* 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 "mbed_assert.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "PeripheralPins.h"
|
||||
#include "cy_smif_memslot.h"
|
||||
#include "cy_smif.h"
|
||||
|
||||
#define TIMEOUT_10_MS (10000UL) /* in microseconds, timeout for all blocking functions */
|
||||
#define SMIF_MAX_RX_COUNT (65536UL)
|
||||
#define QSPI_DESELECT_DELAY (7UL)
|
||||
|
||||
#define QSPI_PIN_MAP_IDX0 (0UL)
|
||||
#define QSPI_PIN_MAP_IDX1 (1UL)
|
||||
#define QSPI_PIN_MAP_IDX2 (2UL)
|
||||
#define QSPI_PIN_MAP_IDX3 (3UL)
|
||||
#define QSPI_PIN_MAP_IDX4 (4UL)
|
||||
#define QSPI_PIN_MAP_IDX5 (5UL)
|
||||
#define QSPI_PIN_MAP_IDX6 (6UL)
|
||||
#define QSPI_PIN_MAP_IDX7 (7UL)
|
||||
|
||||
/* Default QSPI configuration */
|
||||
static const cy_stc_smif_config_t default_qspi_config =
|
||||
{
|
||||
.mode = (uint32_t)CY_SMIF_NORMAL,
|
||||
.deselectDelay = QSPI_DESELECT_DELAY,
|
||||
.rxClockSel = (uint32_t)CY_SMIF_SEL_INV_INTERNAL_CLK,
|
||||
.blockEvent = (uint32_t)CY_SMIF_BUS_ERROR,
|
||||
};
|
||||
|
||||
|
||||
static uint32_t get_addr_size(qspi_address_size_t size)
|
||||
{
|
||||
uint32_t addr_size = 0;
|
||||
|
||||
switch(size) {
|
||||
case QSPI_CFG_ADDR_SIZE_8:
|
||||
addr_size = 1;
|
||||
break;
|
||||
|
||||
case QSPI_CFG_ADDR_SIZE_16:
|
||||
addr_size = 2;
|
||||
break;
|
||||
|
||||
case QSPI_CFG_ADDR_SIZE_24:
|
||||
addr_size = 3;
|
||||
break;
|
||||
|
||||
case QSPI_CFG_ADDR_SIZE_32:
|
||||
addr_size = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
addr_size = 0;
|
||||
}
|
||||
|
||||
return addr_size;
|
||||
}
|
||||
|
||||
static uint32_t get_alt_size(qspi_alt_size_t size)
|
||||
{
|
||||
uint32_t alt_size = 0;
|
||||
|
||||
switch(size) {
|
||||
case QSPI_CFG_ALT_SIZE_8:
|
||||
alt_size = 1;
|
||||
break;
|
||||
|
||||
case QSPI_CFG_ALT_SIZE_16:
|
||||
alt_size = 2;
|
||||
break;
|
||||
|
||||
case QSPI_CFG_ALT_SIZE_24:
|
||||
alt_size = 3;
|
||||
break;
|
||||
|
||||
case QSPI_CFG_ALT_SIZE_32:
|
||||
alt_size = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
alt_size = 0;
|
||||
}
|
||||
|
||||
return alt_size;
|
||||
}
|
||||
|
||||
static cy_en_smif_txfr_width_t get_cy_bus_width(qspi_bus_width_t bus_width)
|
||||
{
|
||||
cy_en_smif_txfr_width_t cy_bus_width = CY_SMIF_WIDTH_SINGLE;
|
||||
|
||||
switch(bus_width) {
|
||||
case QSPI_CFG_BUS_SINGLE:
|
||||
cy_bus_width = CY_SMIF_WIDTH_SINGLE;
|
||||
break;
|
||||
|
||||
case QSPI_CFG_BUS_DUAL:
|
||||
cy_bus_width = CY_SMIF_WIDTH_DUAL;
|
||||
break;
|
||||
|
||||
case QSPI_CFG_BUS_QUAD:
|
||||
cy_bus_width = CY_SMIF_WIDTH_QUAD;
|
||||
break;
|
||||
|
||||
default:
|
||||
cy_bus_width = CY_SMIF_WIDTH_SINGLE;
|
||||
}
|
||||
|
||||
return cy_bus_width;
|
||||
}
|
||||
|
||||
static void convert_to_cy_cmd_config(const qspi_command_t *qspi_command, cy_stc_smif_mem_cmd_t *const cy_cmd_config)
|
||||
{
|
||||
// This function does not check 'disabled' of each sub-structure in qspi_command_t
|
||||
// It is the responsibility of the caller to check it.
|
||||
cy_cmd_config->command = qspi_command->instruction.value;
|
||||
cy_cmd_config->cmdWidth = get_cy_bus_width(qspi_command->instruction.bus_width);
|
||||
cy_cmd_config->addrWidth = get_cy_bus_width(qspi_command->address.bus_width);
|
||||
cy_cmd_config->mode = qspi_command->alt.value;
|
||||
cy_cmd_config->modeWidth = get_cy_bus_width(qspi_command->alt.bus_width);
|
||||
cy_cmd_config->dummyCycles = qspi_command->dummy_count;
|
||||
cy_cmd_config->dataWidth = get_cy_bus_width(qspi_command->data.bus_width);
|
||||
|
||||
}
|
||||
|
||||
static void uint32_to_byte_array(uint32_t value, uint8_t *byteArray, uint32_t startPos, uint32_t size)
|
||||
{
|
||||
do {
|
||||
size--;
|
||||
byteArray[size + startPos] = (uint8_t)value;
|
||||
value >>= 0x08;
|
||||
} while(size > 0);
|
||||
}
|
||||
|
||||
static qspi_status_t validate_and_find_slaveselect(cy_en_smif_slave_select_t *slaveSelect, PinName ssel){
|
||||
if (ssel == PinMap_QSPI_SSEL[QSPI_PIN_MAP_IDX0].pin) {
|
||||
*slaveSelect = CY_SMIF_SLAVE_SELECT_0;
|
||||
} else if(ssel == PinMap_QSPI_SSEL[QSPI_PIN_MAP_IDX1].pin) {
|
||||
*slaveSelect = CY_SMIF_SLAVE_SELECT_1;
|
||||
} else if(ssel == PinMap_QSPI_SSEL[QSPI_PIN_MAP_IDX2].pin) {
|
||||
*slaveSelect = CY_SMIF_SLAVE_SELECT_2;
|
||||
} else if(ssel == PinMap_QSPI_SSEL[QSPI_PIN_MAP_IDX3].pin) {
|
||||
*slaveSelect = CY_SMIF_SLAVE_SELECT_3;
|
||||
} else {
|
||||
MBED_ERROR( MBED_MAKE_ERROR(MBED_MODULE_APPLICATION, MBED_ERROR_CODE_INVALID_ARGUMENT), "Invalid slave select (ssel) pin." );
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
static qspi_status_t validate_pins_and_find_dataselect(cy_en_smif_data_select_t *dataSelect, PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk){
|
||||
bool isQuadSpi = false;
|
||||
|
||||
// ----------------------
|
||||
// io0 | DATA_SELx
|
||||
// ----------------------
|
||||
// spi_data0 | DATA_SEL0
|
||||
// spi_data2 | DATA_SEL1
|
||||
// spi_data4 | DATA_SEL2
|
||||
// spi_data6 | DATA_SEL3
|
||||
// ----------------------
|
||||
//
|
||||
// valid combinations (io0, io1, io2, io3)
|
||||
// ----------------------------
|
||||
// spi_data0, spi_data1, NC, NC - single SPI or Dual SPI
|
||||
// spi_data2, spi_data3, NC, NC - single SPI or Dual SPI
|
||||
// spi_data4, spi_data5, NC, NC - single SPI or Dual SPI
|
||||
// spi_data6, spi_data7, NC, NC - single SPI or Dual SPI
|
||||
// spi_data0, spi_data1, spi_data2, spi_data3, ssel0 - Quad SPI
|
||||
// spi_data4, spi_data5, spi_data6, spi_data7, ssel2 - Quad SPI
|
||||
|
||||
if (sclk != PinMap_QSPI_SCLK[QSPI_PIN_MAP_IDX0].pin) {
|
||||
goto qspi_pin_error;
|
||||
}
|
||||
|
||||
if ( (io2 != NC) && (io3 != NC) ){
|
||||
isQuadSpi = true;
|
||||
}
|
||||
|
||||
if (io0 == PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX0].pin) {
|
||||
if (io1 != PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX1].pin) {
|
||||
goto qspi_pin_error;
|
||||
}
|
||||
|
||||
if (isQuadSpi) {
|
||||
if ((io2 != PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX2].pin) || (io3 != PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX3].pin)) {
|
||||
goto qspi_pin_error;
|
||||
}
|
||||
}
|
||||
|
||||
*dataSelect = CY_SMIF_DATA_SEL0;
|
||||
} else if(io0 == PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX2].pin) {
|
||||
// quad spi is not valid in this case
|
||||
if (io1 != PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX3].pin) {
|
||||
goto qspi_pin_error;
|
||||
}
|
||||
|
||||
*dataSelect = CY_SMIF_DATA_SEL1;
|
||||
} else if(io0 == PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX4].pin) {
|
||||
if (io1 != PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX5].pin) {
|
||||
goto qspi_pin_error;
|
||||
}
|
||||
|
||||
if (isQuadSpi){
|
||||
if ((io2 != PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX6].pin) || (io3 != PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX7].pin)) {
|
||||
goto qspi_pin_error;
|
||||
}
|
||||
}
|
||||
|
||||
*dataSelect = CY_SMIF_DATA_SEL2;
|
||||
} else if(io0 == PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX6].pin) {
|
||||
// quad spi is not valid in this case
|
||||
if (io1 != PinMap_QSPI_DATA[QSPI_PIN_MAP_IDX7].pin) {
|
||||
goto qspi_pin_error;
|
||||
}
|
||||
|
||||
*dataSelect = CY_SMIF_DATA_SEL3;
|
||||
} else {
|
||||
goto qspi_pin_error; // invalid io0
|
||||
}
|
||||
|
||||
return QSPI_STATUS_OK;
|
||||
|
||||
qspi_pin_error:
|
||||
MBED_ERROR( MBED_MAKE_ERROR(MBED_MODULE_APPLICATION, MBED_ERROR_CODE_INVALID_ARGUMENT),
|
||||
"Invalid QSPI pin list. For single or dual SPI, io0 & io1 must be valid and io2 & io3 must be NC. For quad SPI, all pins must be valid." );
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
cy_en_smif_data_select_t dataSelect = CY_SMIF_DATA_SEL0;
|
||||
|
||||
MBED_ASSERT(obj);
|
||||
MBED_ASSERT(io0 != (PinName)NC);
|
||||
MBED_ASSERT(io1 != (PinName)NC);
|
||||
|
||||
// single SPI or Dual SPI - io0 & io1 must be valid and io2 & io3 must be NC.
|
||||
// Quad SPI - all IOs must be valid.
|
||||
if (io2 != (PinName)NC) {
|
||||
MBED_ASSERT(io3 != (PinName)NC);
|
||||
} else {
|
||||
MBED_ASSERT(io3 == (PinName)NC);
|
||||
}
|
||||
|
||||
MBED_ASSERT(sclk != (PinName)NC);
|
||||
MBED_ASSERT(ssel != (PinName)NC);
|
||||
|
||||
// mode (CPOL and CPHA) is not supported in PSoC 6
|
||||
MBED_ASSERT(mode == 0u);
|
||||
|
||||
// No pin-wise instance check is done since PSoC 6 has only one SMIF instance.
|
||||
// But all the pins are checked against the pin map
|
||||
if ( QSPI_STATUS_OK != validate_and_find_slaveselect(&obj->slaveSelect, ssel) ) {
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (QSPI_STATUS_OK != validate_pins_and_find_dataselect(&dataSelect, io0, io1, io2, io3, sclk)) {
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// configure drive mode for the pins
|
||||
pin_function(io0, pinmap_function(io0, PinMap_QSPI_DATA));
|
||||
pin_function(io1, pinmap_function(io1, PinMap_QSPI_DATA));
|
||||
pin_function(io2, pinmap_function(io2, PinMap_QSPI_DATA));
|
||||
pin_function(io3, pinmap_function(io3, PinMap_QSPI_DATA));
|
||||
pin_function(sclk, pinmap_function(sclk, PinMap_QSPI_SCLK));
|
||||
pin_function(ssel, pinmap_function(ssel, PinMap_QSPI_SSEL));
|
||||
|
||||
obj->base = SMIF0;
|
||||
cy_en_smif_status_t smif_status = Cy_SMIF_Init(obj->base, &default_qspi_config, TIMEOUT_10_MS, &obj->context);
|
||||
if (CY_SMIF_SUCCESS != smif_status) {
|
||||
return QSPI_STATUS_ERROR;
|
||||
}
|
||||
|
||||
Cy_SMIF_SetDataSelect(obj->base, obj->slaveSelect, dataSelect); // Configures data select
|
||||
Cy_SMIF_Enable(obj->base, &obj->context);
|
||||
|
||||
return qspi_frequency(obj, hz);
|
||||
}
|
||||
|
||||
qspi_status_t qspi_free(qspi_t *obj)
|
||||
{
|
||||
Cy_SMIF_DeInit(obj->base);
|
||||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
qspi_status_t qspi_frequency(qspi_t *obj, int hz)
|
||||
{
|
||||
// Not implemented yet
|
||||
// PSoC supports only divide by 1, 2, 4, and 8.
|
||||
|
||||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
// Address passed through 'command' is not used, instead the value in 'addr' is used.
|
||||
static qspi_status_t smif_command_transfer(qspi_t *obj, const qspi_command_t *command, uint32_t addr, bool endOfTransfer)
|
||||
{
|
||||
// Does not support command->instruction.diabled
|
||||
if (command->instruction.disabled) {
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
uint8_t cmd_param[8] = {0}; // max address size is 4 bytes and max alt size is 4 bytes
|
||||
uint32_t startPos = 0;
|
||||
uint32_t addr_size = 0;
|
||||
uint32_t alt_size = 0;
|
||||
cy_en_smif_txfr_width_t bus_width = CY_SMIF_WIDTH_SINGLE;
|
||||
cy_stc_smif_mem_cmd_t cy_cmd_config;
|
||||
|
||||
convert_to_cy_cmd_config(command, &cy_cmd_config);
|
||||
|
||||
// Does not support different bus_width for address and alt.
|
||||
// bus_width is selected based on what (address or alt) is enabled.
|
||||
// If both are enabled, bus_width of alt is selected.
|
||||
|
||||
// It is either possible to support 1 byte alt with different bus_width
|
||||
// by sending the alt byte as command as done in Cy_SMIF_Memslot_CmdRead()
|
||||
// in cy_smif_memslot.c or support multiple bytes of alt with same bus_width
|
||||
// as address by passing the alt bytes as cmd_param to Cy_SMIF_TransmitCommand().
|
||||
// Second approach is implemented here. This restriction is because of the way
|
||||
// PDL API is implemented.
|
||||
if (!command->address.disabled && !command->alt.disabled) {
|
||||
if (cy_cmd_config.addrWidth != cy_cmd_config.modeWidth) {
|
||||
return QSPI_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
if (!command->address.disabled) {
|
||||
addr_size = get_addr_size(command->address.size);
|
||||
uint32_to_byte_array(addr, cmd_param, startPos, addr_size);
|
||||
startPos += addr_size;
|
||||
bus_width = cy_cmd_config.addrWidth;
|
||||
}
|
||||
|
||||
if (!command->alt.disabled) {
|
||||
alt_size = get_alt_size(command->alt.size);
|
||||
uint32_to_byte_array(cy_cmd_config.mode, cmd_param, startPos, alt_size);
|
||||
bus_width = cy_cmd_config.modeWidth;
|
||||
}
|
||||
|
||||
uint32_t cmpltTxfr = ((endOfTransfer) ? 1UL : 0UL);
|
||||
cy_en_smif_status_t smifStatus = Cy_SMIF_TransmitCommand( obj->base, cy_cmd_config.command,
|
||||
cy_cmd_config.cmdWidth, cmd_param, (addr_size + alt_size),
|
||||
bus_width, obj->slaveSelect, cmpltTxfr, &obj->context);
|
||||
|
||||
if (CY_SMIF_SUCCESS != smifStatus) {
|
||||
return QSPI_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
// length can be up to 65536.
|
||||
qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length)
|
||||
{
|
||||
cy_en_smif_status_t smifStatus = CY_SMIF_SUCCESS;
|
||||
qspi_status_t status = smif_command_transfer(obj, command, command->address.value, false);
|
||||
|
||||
if (QSPI_STATUS_OK == status) {
|
||||
if (command->dummy_count > 0u) {
|
||||
smifStatus = Cy_SMIF_SendDummyCycles(obj->base, command->dummy_count);
|
||||
}
|
||||
|
||||
if (CY_SMIF_SUCCESS == smifStatus) {
|
||||
smifStatus = Cy_SMIF_TransmitDataBlocking(obj->base, (uint8_t *)data, *length,
|
||||
get_cy_bus_width(command->data.bus_width), &obj->context);
|
||||
|
||||
if (CY_SMIF_SUCCESS != smifStatus) {
|
||||
status = QSPI_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// no restriction on the value of length. This function splits the read into multiple
|
||||
// chunked transfers.
|
||||
qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t *length)
|
||||
{
|
||||
cy_en_smif_status_t smifStatus = CY_SMIF_SUCCESS;
|
||||
qspi_status_t status = QSPI_STATUS_OK;
|
||||
uint32_t chunk = 0;
|
||||
size_t read_bytes = *length;
|
||||
uint32_t addr = command->address.value;
|
||||
|
||||
// SMIF can read only up to 65536 bytes in one go. Split the larger read
|
||||
// into multiple chunks
|
||||
while (read_bytes > 0) {
|
||||
chunk = (read_bytes > SMIF_MAX_RX_COUNT) ? (SMIF_MAX_RX_COUNT) : read_bytes;
|
||||
|
||||
// Address is passed outside command during a read of more than 65536 bytes. Since that
|
||||
// read has to be split into multiple chunks, the address value needs to be incremented
|
||||
// after every chunk has been read. This requires either modifying the address stored in
|
||||
// 'command' passed to read() which is not possible since command is a const pointer or
|
||||
// to create a copy of the command object. Instead of copying the object, the address is
|
||||
// passed separately.
|
||||
status = smif_command_transfer(obj, command, addr, false);
|
||||
|
||||
if (QSPI_STATUS_OK == status) {
|
||||
if (command->dummy_count > 0u) {
|
||||
smifStatus = Cy_SMIF_SendDummyCycles(obj->base, command->dummy_count);
|
||||
}
|
||||
|
||||
if (CY_SMIF_SUCCESS == smifStatus) {
|
||||
smifStatus = Cy_SMIF_ReceiveDataBlocking(obj->base, (uint8_t *)data, chunk,
|
||||
get_cy_bus_width(command->data.bus_width), &obj->context);
|
||||
if (CY_SMIF_SUCCESS != smifStatus) {
|
||||
status = QSPI_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
read_bytes -= chunk;
|
||||
addr += chunk;
|
||||
data = (uint8_t *)data + chunk;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
qspi_status_t status = QSPI_STATUS_OK;
|
||||
|
||||
if ((tx_data == NULL || tx_size == 0) && (rx_data == NULL || rx_size == 0)) {
|
||||
// only command, no rx or tx
|
||||
status = smif_command_transfer(obj, command, command->address.value, true);
|
||||
}
|
||||
else {
|
||||
if (tx_data != NULL && tx_size) {
|
||||
status = qspi_write(obj, command, tx_data, &tx_size);
|
||||
if (status != QSPI_STATUS_OK) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (rx_data != NULL && rx_size) {
|
||||
status = qspi_read(obj, command, rx_data, &rx_size);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
const PinMap *qspi_master_sclk_pinmap(void)
|
||||
{
|
||||
return PinMap_QSPI_SCLK;
|
||||
}
|
||||
|
||||
const PinMap *qspi_master_ssel_pinmap(void)
|
||||
{
|
||||
return PinMap_QSPI_SSEL;
|
||||
}
|
||||
|
||||
const PinMap *qspi_master_data0_pinmap(void)
|
||||
{
|
||||
return PinMap_QSPI_DATA;
|
||||
}
|
||||
|
||||
const PinMap *qspi_master_data1_pinmap(void)
|
||||
{
|
||||
return PinMap_QSPI_DATA;
|
||||
}
|
||||
|
||||
const PinMap *qspi_master_data2_pinmap(void)
|
||||
{
|
||||
return PinMap_QSPI_DATA;
|
||||
}
|
||||
|
||||
const PinMap *qspi_master_data3_pinmap(void)
|
||||
{
|
||||
return PinMap_QSPI_DATA;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/** @}*/
|
|
@ -8182,6 +8182,7 @@
|
|||
"ANALOGOUT",
|
||||
"I2C",
|
||||
"I2C_ASYNCH",
|
||||
"QSPI",
|
||||
"SPI",
|
||||
"SPI_ASYNCH",
|
||||
"STDIO_MESSAGES",
|
||||
|
@ -8219,6 +8220,7 @@
|
|||
},
|
||||
"CY8CKIT_062_WIFI_BT": {
|
||||
"inherits": ["MCU_PSOC6_M4"],
|
||||
"components_add": ["QSPIF"],
|
||||
"features": ["BLE"],
|
||||
"supported_form_factors": ["ARDUINO"],
|
||||
"extra_labels_add": ["PSOC6_01", "WICED", "CYW43XXX", "CYW4343X", "CORDIO"],
|
||||
|
@ -8297,6 +8299,7 @@
|
|||
},
|
||||
"CY8CPROTO_062_4343W": {
|
||||
"inherits": ["CY8CMOD_062_4343W"],
|
||||
"components_add": ["QSPIF"],
|
||||
"detect_code": ["1901"],
|
||||
"hex_filename": "psoc6_02_cm0p_sleep.hex",
|
||||
"post_binary_hook": {
|
||||
|
@ -8305,6 +8308,7 @@
|
|||
},
|
||||
"CY8CKIT_062_BLE": {
|
||||
"inherits": ["MCU_PSOC6_M4"],
|
||||
"components_add": ["QSPIF"],
|
||||
"supported_form_factors": ["ARDUINO"],
|
||||
"extra_labels_add": ["PSOC6_01"],
|
||||
"macros_add": ["CY8C6347BZI_BLD53", "PSOC6_DYNSRM_DISABLE=1"],
|
||||
|
@ -8359,7 +8363,7 @@
|
|||
"supported_form_factors": ["ARDUINO"],
|
||||
"extra_labels_add": ["PSOC6_FUTURE", "CY8C63XX", "FUTURE_SEQUANA"],
|
||||
"extra_labels_remove": ["PSOC6"],
|
||||
"device_has_remove": ["TRNG", "CRC"],
|
||||
"device_has_remove": ["TRNG", "CRC", "QSPI"],
|
||||
"macros_add": ["CY8C6347BZI_BLD53"],
|
||||
"detect_code": ["6000"],
|
||||
"post_binary_hook": {
|
||||
|
@ -8388,7 +8392,7 @@
|
|||
"supported_form_factors": ["ARDUINO"],
|
||||
"extra_labels_add": ["PSOC6_FUTURE", "CY8C63XX", "CORDIO"],
|
||||
"extra_labels_remove": ["PSOC6"],
|
||||
"device_has_remove": ["TRNG", "CRC"],
|
||||
"device_has_remove": ["TRNG", "CRC", "QSPI"],
|
||||
"macros_add": ["CY8C6347BZI_BLD53"],
|
||||
"detect_code": ["6000"],
|
||||
"hex_filename": "psoc63_m0_default_1.03.hex",
|
||||
|
|
Loading…
Reference in New Issue