diff --git a/TESTS/mbed_hal/qspi/flash_configs/MX25R6435F_config.h b/TESTS/mbed_hal/qspi/flash_configs/MX25R6435F_config.h new file mode 100644 index 0000000000..6cd588d487 --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/MX25R6435F_config.h @@ -0,0 +1,192 @@ +/* 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_MX25R6435F_H +#define MBED_QSPI_FLASH_MX25R6435F_H + + +#define QSPI_FLASH_CHIP_STRING "macronix MX25R6435F" + +// Command for reading status register +#define QSPI_CMD_RDSR 0x05 +// Command for reading configuration register +#define QSPI_CMD_RDCR0 0x15 +// Command for writing status/configuration register +#define QSPI_CMD_WRSR 0x01 +// 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 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 34500 // 30ms +// 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_4IO 0x38 // 1-4-4 mode + +// write operations max time [us] (datasheet max time + 15%) +#define QSPI_PAGE_PROG_MAX_TIME 11500 // 10ms + +#define QSPI_PAGE_SIZE 256 // 256B + +// 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 +#define QSPI_CMD_READ_1I2O 0x3B // 1-1-2 mode +#define QSPI_CMD_READ_4IO 0xEB // 1-4-4 mode +#define QSPI_CMD_READ_1I4O 0x6B // 1-1-4 mode + +#define QSPI_READ_1IO_DUMMY_CYCLE 0 +#define QSPI_READ_FAST_DUMMY_CYCLE 8 +#define QSPI_READ_2IO_DUMMY_CYCLE 4 +#define QSPI_READ_1I2O_DUMMY_CYCLE 8 +#define QSPI_READ_4IO_DUMMY_CYCLE 6 +#define QSPI_READ_1I4O_DUMMY_CYCLE 8 + +// Commands for erasing +#define QSPI_CMD_ERASE_SECTOR 0x20 // 4kB +#define QSPI_CMD_ERASE_BLOCK_32 0x52 // 32kB +#define QSPI_CMD_ERASE_BLOCK_64 0xD8 // 64kB +#define QSPI_CMD_ERASE_CHIP 0x60 // or 0xC7 + +// erase operations max time [us] (datasheet max time + 15%) +#define QSPI_ERASE_SECTOR_MAX_TIME 276000 // 240 ms +#define QSPI_ERASE_BLOCK_32_MAX_TIME 3450000 // 3s +#define QSPI_ERASE_BLOCK_64_MAX_TIME 4025000 // 3.5s + +// max frequency for basic rw operation +#define QSPI_COMMON_MAX_FREQUENCY 32000000 + +#define QSPI_STATUS_REG_SIZE 1 +#define QSPI_CONFIG_REG_0_SIZE 2 +#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 << 6) // 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 + + +// single quad enable flag for both dual and quad mode +#define QUAD_ENABLE() \ + \ + uint8_t reg_data[QSPI_STATUS_REG_SIZE]; \ + \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + reg_data[0] = STATUS_BIT_QE; \ + qspi.cmd.build(QSPI_CMD_WRSR); \ + \ + if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), \ + reg_data, QSPI_STATUS_REG_SIZE, NULL, 0) != 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 QUAD_DISABLE() \ + \ + uint8_t reg_data[QSPI_STATUS_REG_SIZE]; \ + \ + if (write_enable(qspi) != QSPI_STATUS_OK) { \ + return QSPI_STATUS_ERROR; \ + } \ + WAIT_FOR(WRSR_MAX_TIME, qspi); \ + \ + reg_data[0] = 0; \ + qspi.cmd.build(QSPI_CMD_WRSR); \ + \ + if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), \ + reg_data, QSPI_STATUS_REG_SIZE, NULL, 0) != 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) + + + +#define FAST_MODE_ENABLE() \ + \ + qspi_status_t ret; \ + const int32_t reg_size = QSPI_STATUS_REG_SIZE + QSPI_CONFIG_REG_0_SIZE; \ + uint8_t reg_data[reg_size]; \ + \ + 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; \ + } \ + \ + reg_data[2] |= CONFIG1_BIT_LH; \ + qspi.cmd.build(QSPI_CMD_WRSR); \ + \ + return qspi_command_transfer(&qspi.handle, qspi.cmd.get(), \ + reg_data, reg_size, NULL, 0) + + + +#endif // MBED_QSPI_FLASH_MX25R6435F_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/N25Q128A_config.h b/TESTS/mbed_hal/qspi/flash_configs/N25Q128A_config.h new file mode 100644 index 0000000000..138844abe6 --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/N25Q128A_config.h @@ -0,0 +1,182 @@ +/* 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_N25Q128A_H +#define MBED_QSPI_FLASH_N25Q128A_H + + +#define QSPI_FLASH_CHIP_STRING "Micron N25Q128A" + +// Command for reading status register +#define QSPI_CMD_RDSR 0x05 +// Command for reading configuration register 0 (NONVOLATILE CONFIGURATION REGISTER) +#define QSPI_CMD_RDCR0 0xB5 +// Command for reading configuration register 1 (VOLATILE CONFIGURATION REGISTER) +#define QSPI_CMD_RDCR1 0x85 +// Command for reading configuration register 2 (ENHANCED VOLATILE CONFIGURATION REGISTER) +#define QSPI_CMD_RDCR2 0x65 +// Command for writing status +#define QSPI_CMD_WRSR 0x01 +// Command for writing configuration register 0 (NONVOLATILE CONFIGURATION REGISTER) +#define QSPI_CMD_WRCR0 0xB1 +// Command for writing configuration register 1 (VOLATILE CONFIGURATION REGISTER) +#define QSPI_CMD_WRCR1 0x81 +// Command for writing configuration register 2 (ENHANCED VOLATILE CONFIGURATION REGISTER) +#define QSPI_CMD_WRCR2 0x61 +// Command for 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 0x99 + +// Command for setting write enable +#define QSPI_CMD_WREN 0x06 +// Command for setting write disable +#define QSPI_CMD_WRDI 0x04 + +// WRSR operations max time [us] (datasheet max time + 15%) +#define QSPI_WRSR_MAX_TIME 9200 // 8ms +// general wait max time [us] +#define QSPI_WAIT_MAX_TIME 100000 // 100ms + + +// Commands for writing (page programming) +#define QSPI_CMD_WRITE_1IO 0x02 // 1-1-1 mode +#define QSPI_CMD_WRITE_2IO 0xD2 // 1-2-2 mode +#define QSPI_CMD_WRITE_4IO 0x12 // 1-4-4 mode + +// write operations max time [us] (datasheet max time + 15%) +#define QSPI_PAGE_PROG_MAX_TIME 5750 // 5ms + +#define QSPI_PAGE_SIZE 256 // 256B + +// 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 +#define QSPI_CMD_READ_1I2O 0x3B // 1-1-2 mode +#define QSPI_CMD_READ_4IO 0xEB // 1-4-4 mode +#define QSPI_CMD_READ_1I4O 0x6B // 1-1-4 mode + + +#define QSPI_READ_1IO_DUMMY_CYCLE 0 +#define QSPI_READ_FAST_DUMMY_CYCLE 8 +// 8 dummy (10 dummy when quad SPI protocol is enabled) +#define QSPI_READ_2IO_DUMMY_CYCLE 8 +#define QSPI_READ_1I2O_DUMMY_CYCLE 8 +#define QSPI_READ_4IO_DUMMY_CYCLE 10 +#define QSPI_READ_1I4O_DUMMY_CYCLE 8 + +// Commands for erasing +#define QSPI_CMD_ERASE_SECTOR 0x20 // 4kB +#define QSPI_CMD_ERASE_BLOCK_32 0x52 // 32kB +#define QSPI_CMD_ERASE_BLOCK_64 0xD8 // 64kB +#define QSPI_CMD_ERASE_CHIP 0x60 // or 0xC7 + +// erase operations max time [us] (datasheet max time + 15%) +#define QSPI_ERASE_SECTOR_MAX_TIME 276000 // 240 ms +#define QSPI_ERASE_BLOCK_32_MAX_TIME 3000000 // 3s +#define QSPI_ERASE_BLOCK_64_MAX_TIME 3500000 // 3.5s + +// max frequency for basic rw operation +#define QSPI_COMMON_MAX_FREQUENCY 50000000 + +#define QSPI_STATUS_REG_SIZE 1 +#define QSPI_CONFIG_REG_0_SIZE 2 +#define QSPI_CONFIG_REG_1_SIZE 1 +#define QSPI_CONFIG_REG_2_SIZE 1 +#define QSPI_MAX_REG_SIZE 2 + +// status register +#define STATUS_BIT_WIP (1 << 0) // write in progress bit +#define STATUS_BIT_WEL (1 << 1) // write enable latch +#define STATUS_BIT_BP0 (1 << 2) // block +#define STATUS_BIT_BP1 (1 << 3) // +#define STATUS_BIT_BP2 (1 << 4) // +#define STATUS_BIT_BP_TB (1 << 5) // Block protect top/bottom +#define STATUS_BIT_BP3 (1 << 6) // +#define STATUS_BIT_SRWD (1 << 7) // status register write protect + +// configuration register 0 (Nonvolatile Configuration Register) +// bit 1, 5, reserved +#define CONFIG0_BIT_LOCK (1 << 0) // Lock nonvolatile configuration register +#define CONFIG0_BIT_DE (1 << 2) // Dual Enable 0 = Enabled / 1 = Disabled +#define CONFIG0_BIT_QE (1 << 3) // Quad Enable 0 = Enabled / 1 = Disabled +#define CONFIG0_BIT_RH (1 << 4) // Reset/hold +#define CONFIG0_BIT_ODS0 (1 << 6) // Output driver strength +#define CONFIG0_BIT_ODS1 (1 << 7) // Output driver strength +#define CONFIG0_BIT_ODS2 (1 << 8) // Output driver strength +#define CONFIG0_BIT_XIP_MODE0 (1 << 9) // XIP mode at power-on reset +#define CONFIG0_BIT_XIP_MODE1 (1 << 10) // XIP mode at power-on reset +#define CONFIG0_BIT_XIP_MODE2 (1 << 11) // XIP mode at power-on reset +#define CONFIG0_BIT_DCYCLE0 (1 << 12) // Dummy Cycle +#define CONFIG0_BIT_DCYCLE1 (1 << 13) // Dummy Cycle +#define CONFIG0_BIT_DCYCLE2 (1 << 14) // Dummy Cycle +#define CONFIG0_BIT_DCYCLE3 (1 << 15) // Dummy Cycle +#define CONFIG0_BITS_DEFAULT 0xFFFF // reg default state + + +// configuration register 1 (Volatile Configuration Register) +// bit 2, reserved +#define CONFIG1_BIT_WRAP0 (1 << 0) // Output data wrap +#define CONFIG1_BIT_WRAP1 (1 << 1) // Output data wrap +#define CONFIG1_BIT_XIP (1 << 3) // 0 = Enable / 1 = Disable (default) +#define CONFIG1_BIT_DCYCLE0 (1 << 4) // Number of dummy clock cycles +#define CONFIG1_BIT_DCYCLE1 (1 << 5) // Number of dummy clock cycles +#define CONFIG1_BIT_DCYCLE2 (1 << 6) // Number of dummy clock cycles +#define CONFIG1_BIT_DCYCLE3 (1 << 7) // Number of dummy clock cycles +#define CONFIG1_BITS_DEFAULT 0xB // reg default state + + +// configuration register 2 (Enhanced Volatile Configuration Register) +// bit 5, reserved +#define CONFIG2_BIT_ODS0 (1 << 0) // Output driver strength 111 = 30 Ohms (Default) +#define CONFIG2_BIT_ODS1 (1 << 1) // Output driver strength +#define CONFIG2_BIT_ODS2 (1 << 2) // Output driver strength +#define CONFIG2_BIT_VPP (1 << 3) // VPP accelerator 1 = Disabled (Default) +#define CONFIG2_BIT_RH (1 << 4) // Reset/hold +#define CONFIG2_BIT_DE (1 << 6) // Dual I/O protocol 0 = Enabled / 1 = Disabled (Default, extended SPI protocol) +#define CONFIG2_BIT_QE (1 << 7) // Quad I/O protocol 0 = Enabled / 1 = Disabled (Default, extended SPI protocol) +#define CONFIG2_BITS_DEFAULT 0xDF // reg default state + + +#define DUAL_ENABLE() \ + /* TODO: add implementation */ \ + return QSPI_STATUS_OK + + +#define DUAL_DISABLE() \ + /* TODO: add implementation */ \ + return QSPI_STATUS_OK + + +#define QUAD_ENABLE() \ + /* TODO: add implementation */ \ + return QSPI_STATUS_OK + + +#define QUAD_DISABLE() \ + /* TODO: add implementation */ \ + return QSPI_STATUS_OK + + +#define FAST_MODE_ENABLE() \ + /* TODO: add implementation */ \ + return QSPI_STATUS_OK + + +#endif // MBED_QSPI_FLASH_N25Q128A_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/NORDIC/NRF52840_DK/flash_config.h b/TESTS/mbed_hal/qspi/flash_configs/NORDIC/NRF52840_DK/flash_config.h new file mode 100644 index 0000000000..ed288ba50a --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/NORDIC/NRF52840_DK/flash_config.h @@ -0,0 +1,33 @@ +/* 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 "../../MX25R6435F_config.h" + +// NRF doesn't uses read/write opcodes, instead it uses commands id's. +// Before sending it to H/W opcodes are mapped to id's in Mbed hal qspi implementation +// +// for more details see: +// targets\TARGET_NORDIC\TARGET_NRF5x\TARGET_SDK_14_2\device\nrf52840_bitfields.h +// targets\TARGET_NORDIC\TARGET_NRF5x\qspi_api.c + +// NRF doesn't support read 1IO (opcode 0x03) +#undef QSPI_CMD_READ_1IO +#define QSPI_CMD_READ_1IO QSPI_CMD_READ_1IO_FAST + + +#endif // MBED_QSPI_FLASH_CONFIG_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/STM/DISCO_F413ZH/flash_config.h b/TESTS/mbed_hal/qspi/flash_configs/STM/DISCO_F413ZH/flash_config.h new file mode 100644 index 0000000000..67d8c317d6 --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/STM/DISCO_F413ZH/flash_config.h @@ -0,0 +1,22 @@ +/* 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 "../../N25Q128A_config.h" + + +#endif // MBED_QSPI_FLASH_CONFIG_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/STM/DISCO_L475VG_IOT01A/flash_config.h b/TESTS/mbed_hal/qspi/flash_configs/STM/DISCO_L475VG_IOT01A/flash_config.h new file mode 100644 index 0000000000..76cb739bb5 --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/STM/DISCO_L475VG_IOT01A/flash_config.h @@ -0,0 +1,22 @@ +/* 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 "../../MX25R6435F_config.h" + + +#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 new file mode 100644 index 0000000000..deced43d7f --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h @@ -0,0 +1,28 @@ +/* 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_FLASH_CONFIGS_H +#define MBED_FLASH_CONFIGS_H + +#if defined(TARGET_DISCO_L475VG_IOT01A) +#include "STM/DISCO_L475VG_IOT01A/flash_config.h" +#elif defined(TARGET_NRF52840) +#include "NORDIC/NRF52840_DK/flash_config.h" +#elif defined(TARGET_DISCO_F413ZH) +#include "STM/DISCO_F413ZH/flash_config.h" +#endif + +#endif // MBED_FLASH_CONFIGS_H diff --git a/TESTS/mbed_hal/qspi/main.cpp b/TESTS/mbed_hal/qspi/main.cpp new file mode 100644 index 0000000000..0d1db1db35 --- /dev/null +++ b/TESTS/mbed_hal/qspi/main.cpp @@ -0,0 +1,468 @@ +/* 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. + */ + +#if !DEVICE_QSPI +#error [NOT_SUPPORTED] QSPI not supported for this target +#endif + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" +#include "qspi_test.h" +#include "qspi_test_utils.h" + +#include "mbed.h" +#include "qspi_api.h" + + +#if !defined(QSPI_FLASH_CHIP_STRING) +#error [NOT_SUPPORTED] QSPI test not supported for this target +#endif + +using namespace utest::v1; + +// uncomment to enable verbose mode +//#define QSPI_TEST_LOG_DATA +//#define QSPI_TEST_LOG_FLASH_TIME +//#define QSPI_TEST_LOG_FLASH_STATUS + + +// max write size is usually page size +#define DATA_SIZE_256 (QSPI_PAGE_SIZE) +#define DATA_SIZE_1024 (QSPI_PAGE_SIZE * 4) + +uint8_t tx_buf[DATA_SIZE_1024]; +uint8_t rx_buf[DATA_SIZE_1024]; + + +// write address should be page aligned +#define TEST_FLASH_ADDRESS 0x0 + +#define TEST_REPEAT_SINGLE 1 +#define TEST_REPEAT_MULTIPLE 16 + +// write block of data in single write operation +#define WRITE_SINGLE 1 +// write block of data in adjacent locations in multiple write operations +#define WRITE_MULTIPLE 4 + +// read block of data in single read operation +#define READ_SINGLE 1 +// read block of data in adjacent locations in multiple read operations +#define READ_MULTIPLE 4 + + +// some target defines QSPI pins as integers thus conversion needed +#define QPIN_0 static_cast(QSPI_PIN_IO0) +#define QPIN_1 static_cast(QSPI_PIN_IO1) +#define QPIN_2 static_cast(QSPI_PIN_IO2) +#define QPIN_3 static_cast(QSPI_PIN_IO3) +#define QSCK static_cast(QSPI_PIN_SCK) +#define QCSN static_cast(QSPI_PIN_CSN) + + +static void log_data(const char *str, uint8_t *data, uint32_t size) +{ + utest_printf("%s: ", str); + for (uint32_t j = 0; j < size; j++) { + utest_printf("%02X ", data[j]); + } + utest_printf("\r\n"); +} + + +static void _qspi_write_read_test(Qspi &qspi, qspi_bus_width_t write_inst_width, qspi_bus_width_t write_addr_width, + qspi_bus_width_t write_data_width, qspi_bus_width_t write_alt_width, uint32_t write_cmd, + qspi_address_size_t write_addr_size, qspi_alt_size_t write_alt_size, int write_frequency, + uint32_t write_count, qspi_bus_width_t read_inst_width, qspi_bus_width_t read_addr_width, + qspi_bus_width_t read_data_width, qspi_bus_width_t read_alt_width, uint32_t read_cmd, + int read_dummy_cycles, qspi_address_size_t read_addr_size, qspi_alt_size_t read_alt_size, + int read_frequency, uint32_t read_count, uint32_t test_count, uint32_t data_size, + uint32_t flash_addr) +{ + qspi_status_t ret = QSPI_STATUS_OK; + + Timer timer; + int erase_time = 0, write_time = 0, read_time = 0; + size_t buf_len = data_size; + + for (uint32_t tc = 0; tc < test_count; tc++) { + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + + srand(ticker_read(get_us_ticker_data())); + for (uint32_t i = 0; i < data_size; i++) { + tx_buf[i] = (uint8_t)(rand() & 0xFF); + } + + ret = write_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + timer.reset(); + timer.start(); + + ret = erase(SECTOR_ERASE, flash_addr, qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(SECTOR_ERASE_MAX_TIME, qspi); + + timer.stop(); + erase_time = timer.read_us(); + + if (write_frequency != QSPI_NONE) { + qspi_frequency(&qspi.handle, write_frequency); + WAIT_FOR(WAIT_MAX_TIME, qspi); + } + + const uint32_t write_size = data_size / write_count; + for (uint32_t wc = 0, write_start = flash_addr; wc < write_count; wc++, write_start += write_size) { + ret = write_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + timer.reset(); + timer.start(); + + buf_len = write_size; + qspi.cmd.configure(write_inst_width, write_addr_width, write_data_width, write_alt_width, write_addr_size, write_alt_size); + qspi.cmd.build(write_cmd, write_start); + ret = qspi_write(&qspi.handle, qspi.cmd.get(), tx_buf + wc * write_size, &buf_len); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + TEST_ASSERT_EQUAL(write_size, buf_len); + + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + WAIT_FOR(PAGE_PROG_MAX_TIME, qspi); + + timer.stop(); + write_time = timer.read_us(); + } + + if (read_frequency != QSPI_NONE) { + qspi_frequency(&qspi.handle, read_frequency); + WAIT_FOR(WAIT_MAX_TIME, qspi); + } + + memset(rx_buf, 0, sizeof(rx_buf)); + const uint32_t read_size = data_size / read_count; + qspi.cmd.configure(read_inst_width, read_addr_width, read_data_width, read_alt_width, read_addr_size, read_alt_size, read_dummy_cycles); + for (uint32_t rc = 0, read_start = flash_addr; rc < read_count; rc++, read_start += read_size) { + timer.reset(); + timer.start(); + + buf_len = read_size; + qspi.cmd.build(read_cmd, read_start); + ret = qspi_read(&qspi.handle, qspi.cmd.get(), rx_buf + rc * read_size, &buf_len); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + TEST_ASSERT_EQUAL(read_size, buf_len); + + timer.stop(); + read_time = timer.read_us(); + } + + for (uint32_t i = 0; i < data_size; i++) { + if (tx_buf[i] != rx_buf[i]) { + log_data("tx data", tx_buf, data_size); + log_data("rx data", rx_buf, data_size); + utest_printf("erase/write/read time: %d/%d/%d [us]\r\n", erase_time, write_time, read_time); + TEST_ASSERT_EQUAL(tx_buf[i], rx_buf[i]); + } + } + +#ifdef QSPI_TEST_LOG_FLASH_TIME + utest_printf("erase/write/read time: %d/%d/%d [us]\r\n", erase_time, write_time, read_time); +#endif + +#ifdef QSPI_TEST_LOG_DATA + log_data("tx data", tx_buf, data_size); + log_data("rx data", rx_buf, data_size); + utest_printf("rx/tx data match\r\n"); +#endif + } +} + + +template < qspi_bus_width_t write_inst_width, + qspi_bus_width_t write_addr_width, + qspi_bus_width_t write_data_width, + qspi_bus_width_t write_alt_width, + unsigned int write_cmd, + qspi_address_size_t write_addr_size, + qspi_alt_size_t write_alt_size, + int write_frequency, + uint32_t write_count, + qspi_bus_width_t read_inst_width, + qspi_bus_width_t read_addr_width, + qspi_bus_width_t read_data_width, + qspi_bus_width_t read_alt_width, + unsigned int read_cmd, + int read_dummy_cycles, + qspi_address_size_t read_addr_size, + qspi_alt_size_t read_alt_size, + int read_frequency, + uint32_t read_count, + uint32_t test_count, + uint32_t data_size, + uint32_t flash_addr> +void qspi_write_read_test(void) +{ + qspi_status_t ret; + Qspi qspi; + qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + + if (is_dual_cmd(write_inst_width, write_addr_width, write_data_width) || + is_dual_cmd(read_inst_width, read_addr_width, read_data_width)) { + ret = dual_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + } + + if (is_quad_cmd(write_inst_width, write_addr_width, write_data_width) || + is_quad_cmd(read_inst_width, read_addr_width, read_data_width)) { + ret = quad_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + } + + ret = write_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + ret = fast_mode_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + +#ifdef QSPI_TEST_LOG_FLASH_STATUS + //utest_printf("Status register:\r\n"); + log_register(STATUS_REG, QSPI_STATUS_REG_SIZE, qspi, "Status register"); + //utest_printf("Config register 0:\r\n"); + log_register(CONFIG_REG0, QSPI_CONFIG_REG_0_SIZE, qspi, "Config register 0"); +#ifdef CONFIG_REG1 + //utest_printf("Config register 1:\r\n"); + log_register(CONFIG_REG1, QSPI_CONFIG_REG_1_SIZE, qspi, "Config register 1"); +#endif +#ifdef CONFIG_REG2 + //utest_printf("Config register 2:\r\n"); + log_register(CONFIG_REG2, QSPI_CONFIG_REG_2_SIZE, qspi, "Config register 2"); +#endif +#endif + + _qspi_write_read_test(qspi, write_inst_width, write_addr_width, write_data_width, write_alt_width, write_cmd, + write_addr_size, write_alt_size, write_frequency, write_count, read_inst_width, + read_addr_width, read_data_width, read_alt_width, read_cmd, read_dummy_cycles, + read_addr_size, read_alt_size, read_frequency, read_count, test_count, + data_size, flash_addr); + + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + + if (is_dual_cmd(write_inst_width, write_addr_width, write_data_width) || + is_dual_cmd(read_inst_width, read_addr_width, read_data_width)) { + ret = dual_disable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + } + + if (is_quad_cmd(write_inst_width, write_addr_width, write_data_width) || + is_quad_cmd(read_inst_width, read_addr_width, read_data_width)) { + ret = quad_disable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + } + + qspi_free(&qspi.handle); +} + + +void qspi_init_free_test(void) +{ + Qspi qspi; + qspi_status_t ret; + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + ret = qspi_free(&qspi.handle); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + ret = qspi_free(&qspi.handle); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + ret = qspi_free(&qspi.handle); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + +#ifdef QSPI_TEST_LOG_FLASH_STATUS + //utest_printf("Status register:\r\n"); + log_register(STATUS_REG, QSPI_STATUS_REG_SIZE, qspi, "Status register"); + //utest_printf("Config register 0:\r\n"); + log_register(CONFIG_REG0, QSPI_CONFIG_REG_0_SIZE, qspi, "Config register 0"); +#ifdef CONFIG_REG1 + //utest_printf("Config register 1:\r\n"); + log_register(CONFIG_REG1, QSPI_CONFIG_REG_1_SIZE, qspi, "Config register 1"); +#endif +#ifdef CONFIG_REG2 + //utest_printf("Config register 2:\r\n"); + log_register(CONFIG_REG2, QSPI_CONFIG_REG_2_SIZE, qspi, "Config register 2"); +#endif +#endif + + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, 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); + qspi_free(&qspi.handle); +} + + +void qspi_frequency_test(void) +{ + Qspi qspi; + qspi_status_t ret; + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS); + + ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY / 2); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS); + + ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY / 4); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS); + + ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY / 8); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS); + + qspi_free(&qspi.handle); +} + + +void qspi_memory_id_test() +{ + utest_printf("*** %s memory config loaded ***\r\n", QSPI_FLASH_CHIP_STRING); +} + + +Case cases[] = { + Case("qspi memory id test", qspi_memory_id_test), + Case("qspi init/free test", qspi_init_free_test), + Case("qspi frequency setting test", qspi_frequency_test), + // read/x1 write/x1 - read/write block of data in single write/read operation + // read/x4 write/x4 - read/write block of data in adjacent locations in multiple write/read operations + // repeat/xN - test repeat count (new data pattern each time) + Case("qspi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test), +#ifdef QSPI_CMD_WRITE_2IO + Case("qspi write(1-2-2)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-2-2)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test), +#endif +#ifdef QSPI_CMD_WRITE_4IO + Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test), +#endif +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(180, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + Harness::run(specification); +} + diff --git a/TESTS/mbed_hal/qspi/qspi_test.h b/TESTS/mbed_hal/qspi/qspi_test.h new file mode 100644 index 0000000000..9ab3076d74 --- /dev/null +++ b/TESTS/mbed_hal/qspi/qspi_test.h @@ -0,0 +1,98 @@ +/* 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. + */ + +/** \addtogroup hal_qspi_tests + * @{ + */ +#ifndef MBED_QSPI_TEST_H +#define MBED_QSPI_TEST_H + +#include "qspi_api.h" +#include "qspi_test_utils.h" + + +#if DEVICE_QSPI + +/** Test that qspi_init/qspi_free can be called multiple times. + * + * Given board provides QSPI. + * When qspi_init/qspi_free is called multiple times. + * Then qspi_init/qspi_free are successfully performed (no exception is generated). + * + */ +void qspi_init_free_test(void); + +/** Test qspi frequency setting. + * + * Given board provides QSPI, with QSPI already initialized. + * When set QSPI frequency. + * Then freguency setting is successfully performed (no exception is generated). + * + */ +void qspi_frequency_test(void); + +/** Template for write/read tests + * + * Test single write/read operation of a block of data to/from the specific memory address + * Given board provides QSPI, with QSPI already initialized. + * When perform write and then read operations. + * Then data is successfully written and then read (no exception is generated) and the read data is valid. + * + * Test multiple write/read operation of a block of data to/from the same specific memory address + * Given board provides QSPI, with QSPI already initialized. + * When perform write and then read operations. + * Then data is successfully written and then read (no exception is generated) and the read data is valid. + * + * Test multiple adjacent write and single read operation of a block of data to/from the specific memory address + * Given board provides QSPI, with QSPI already initialized. + * When perform write and then read operations. + * Then data is successfully written and then read (no exception is generated) and the read data is valid. + * + * Test single write and multiple adjacent read operation of a block of data to/from the specific memory address + * Given board provides QSPI, with QSPI already initialized. + * When perform write and then read operations. + * Then data is successfully written and then read (no exception is generated) and the read data is valid. + * + */ +template < qspi_bus_width_t write_inst_width, + qspi_bus_width_t write_addr_width, + qspi_bus_width_t write_data_width, + qspi_bus_width_t write_alt_width, + unsigned int write_cmd, + qspi_address_size_t write_addr_size, + qspi_alt_size_t write_alt_size, + int write_frequency, + uint32_t write_count, + qspi_bus_width_t read_inst_width, + qspi_bus_width_t read_addr_width, + qspi_bus_width_t read_data_width, + qspi_bus_width_t read_alt_width, + unsigned int read_cmd, + int read_dummy_cycles, + qspi_address_size_t read_addr_size, + qspi_alt_size_t read_alt_size, + int read_frequency, + uint32_t read_count, + uint32_t test_count, + uint32_t data_size, + uint32_t flash_addr> +void qspi_write_read_test(void); + +#endif + +#endif + +/** @}*/ diff --git a/TESTS/mbed_hal/qspi/qspi_test_utils.cpp b/TESTS/mbed_hal/qspi/qspi_test_utils.cpp new file mode 100644 index 0000000000..8ee85f7ffc --- /dev/null +++ b/TESTS/mbed_hal/qspi/qspi_test_utils.cpp @@ -0,0 +1,233 @@ +/* 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. + */ + +#include "utest/utest.h" + +#include "hal/qspi_api.h" +#include "qspi_test_utils.h" + +#include "unity/unity.h" + +#include // for memset + +#include "flash_configs/flash_configs.h" +#include "mbed.h" + + +void QspiCommand::configure(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, + qspi_bus_width_t data_width, qspi_bus_width_t alt_width, + qspi_address_size_t addr_size, qspi_alt_size_t alt_size, + int dummy_cycles) +{ + memset(&_cmd, 0, sizeof(qspi_command_t)); + _cmd.instruction.disabled = _cmd.address.disabled = _cmd.alt.disabled = true; + + _cmd.instruction.bus_width = inst_width; + _cmd.address.bus_width = addr_width; + _cmd.address.size = addr_size; + _cmd.alt.bus_width = alt_width; + _cmd.alt.size = alt_size; + _cmd.data.bus_width = data_width; + _cmd.dummy_count = dummy_cycles; +} + +void QspiCommand::build(int instruction, int address, int alt) +{ + _cmd.instruction.disabled = (instruction == QSPI_NONE); + if (!_cmd.instruction.disabled) { + _cmd.instruction.value = instruction; + } + + _cmd.address.disabled = (address == QSPI_NONE); + if (!_cmd.address.disabled) { + _cmd.address.value = address; + } + + _cmd.alt.disabled = (alt == QSPI_NONE); + if (!_cmd.alt.disabled) { + _cmd.alt.value = alt; + } +} + +qspi_command_t *QspiCommand::get() +{ + return &_cmd; +} + + +qspi_status_t read_register(uint32_t cmd, uint8_t *buf, uint32_t size, Qspi &q) +{ + q.cmd.build(cmd); + return qspi_command_transfer(&q.handle, q.cmd.get(), NULL, 0, buf, size); +} + +qspi_status_t write_register(uint32_t cmd, uint8_t *buf, uint32_t size, Qspi &q) +{ + q.cmd.build(cmd); + return qspi_command_transfer(&q.handle, q.cmd.get(), buf, size, NULL, 0); +} + + +QspiStatus flash_wait_for(uint32_t time_us, Qspi &qspi) +{ + uint8_t reg[QSPI_STATUS_REG_SIZE]; + qspi_status_t ret; + uint32_t curr_time; + + const ticker_data_t *const ticker = get_us_ticker_data(); + const uint32_t start = ticker_read(ticker); + + memset(reg, 255, QSPI_STATUS_REG_SIZE); + do { + ret = read_register(STATUS_REG, reg, QSPI_STATUS_REG_SIZE, qspi); + curr_time = ticker_read(ticker); + } while (((reg[0] & STATUS_BIT_WIP) != 0) && ((curr_time - start) < time_us)); + + if (((reg[0] & STATUS_BIT_WIP) == 0) && (ret == QSPI_STATUS_OK)) { + return sOK; + } else if (ret != QSPI_STATUS_OK) { + return sError; + } else if ((curr_time - start) >= time_us) { + return sTimeout; + } + return sUnknown; +} + +void flash_init(Qspi &qspi) +{ + uint8_t status[QSPI_STATUS_REG_SIZE]; + qspi_status_t ret; + + qspi.cmd.build(QSPI_CMD_RDSR); + ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, status, QSPI_STATUS_REG_SIZE); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + qspi.cmd.build(QSPI_CMD_RSTEN); + ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + WAIT_FOR(WRSR_MAX_TIME, qspi); + + qspi.cmd.build(QSPI_CMD_RST); + ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + WAIT_FOR(WAIT_MAX_TIME, qspi); +} + + +qspi_status_t write_enable(Qspi &qspi) +{ + uint8_t reg[QSPI_STATUS_REG_SIZE]; + qspi.cmd.build(QSPI_CMD_WREN); + + if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + WAIT_FOR(WRSR_MAX_TIME, qspi); + + memset(reg, 0, QSPI_STATUS_REG_SIZE); + if (read_register(STATUS_REG, reg, QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + + return ((reg[0] & STATUS_BIT_WEL) != 0 ? QSPI_STATUS_OK : QSPI_STATUS_ERROR); +} + +qspi_status_t write_disable(Qspi &qspi) +{ + uint8_t reg[QSPI_STATUS_REG_SIZE]; + qspi.cmd.build(QSPI_CMD_WRDI); + + if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + WAIT_FOR(WRSR_MAX_TIME, qspi); + + memset(reg, 0, QSPI_STATUS_REG_SIZE); + if (read_register(STATUS_REG, reg, QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + + return ((reg[0] & STATUS_BIT_WEL) == 0 ? QSPI_STATUS_OK : QSPI_STATUS_ERROR); +} + +void log_register(uint32_t cmd, uint32_t reg_size, Qspi &qspi, const char *str) +{ + qspi_status_t ret; + static uint8_t reg[QSPI_MAX_REG_SIZE]; + + ret = read_register(cmd, reg, reg_size, qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + for (uint32_t j = 0; j < reg_size; j++) { + utest_printf("%s byte %u (MSB first): ", str != NULL ? str : "", j); + for (int i = 0; i < 8; i++) { + utest_printf("%s ", ((reg[j] & (1 << (7 - i))) & 0xFF) == 0 ? "0" : "1"); + } + utest_printf("\r\n"); + } +} + +qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi) +{ + qspi.cmd.build(erase_cmd, flash_addr); + return qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0); +} + +qspi_status_t dual_enable(Qspi &qspi) +{ +#ifdef DUAL_ENABLE + DUAL_ENABLE(); +#else + QUAD_ENABLE(); +#endif +} + +qspi_status_t dual_disable(Qspi &qspi) +{ +#ifdef DUAL_DISABLE + DUAL_DISABLE(); +#else + QUAD_DISABLE(); +#endif + +} + +qspi_status_t quad_enable(Qspi &qspi) +{ + QUAD_ENABLE(); +} + +qspi_status_t quad_disable(Qspi &qspi) +{ + QUAD_DISABLE(); +} + +qspi_status_t fast_mode_enable(Qspi &qspi) +{ + FAST_MODE_ENABLE(); +} + +bool is_dual_cmd(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width) +{ + return (inst_width == QSPI_CFG_BUS_DUAL) || (addr_width == QSPI_CFG_BUS_DUAL) || (data_width == QSPI_CFG_BUS_DUAL); +} + +bool is_quad_cmd(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width) +{ + return (inst_width == QSPI_CFG_BUS_QUAD) || (addr_width == QSPI_CFG_BUS_QUAD) || (data_width == QSPI_CFG_BUS_QUAD); +} diff --git a/TESTS/mbed_hal/qspi/qspi_test_utils.h b/TESTS/mbed_hal/qspi/qspi_test_utils.h new file mode 100644 index 0000000000..7f54a439f4 --- /dev/null +++ b/TESTS/mbed_hal/qspi/qspi_test_utils.h @@ -0,0 +1,147 @@ +/* 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_TEST_UTILS_H +#define MBED_QSPI_TEST_UTILS_H + +#include "flash_configs/flash_configs.h" +#include "unity/unity.h" + +#define QSPI_NONE (-1) + +enum QspiStatus { + sOK, + sError, + sTimeout, + sUnknown +}; + +class QspiCommand { +public: + void configure(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width, + qspi_bus_width_t alt_width, qspi_address_size_t addr_size, qspi_alt_size_t alt_size, + int dummy_cycles = 0); + + void build(int instruction, int address = QSPI_NONE, int alt = QSPI_NONE); + + qspi_command_t *get(); + +private: + qspi_command_t _cmd; +}; + +struct Qspi { + qspi_t handle; + QspiCommand cmd; +}; + +// MODE_Command_Address_Data_Alt +#define MODE_1_1_1 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE +#define MODE_1_1_2 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL +#define MODE_1_2_2 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL +#define MODE_1_1_4 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_SINGLE +#define MODE_1_4_4 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD + +#define WRITE_1_1_1 MODE_1_1_1, QSPI_CMD_WRITE_1IO +#ifdef QSPI_CMD_WRITE_2IO +#define WRITE_1_2_2 MODE_1_2_2, QSPI_CMD_WRITE_2IO +#endif +#ifdef QSPI_CMD_WRITE_4IO +#define WRITE_1_4_4 MODE_1_4_4, QSPI_CMD_WRITE_4IO +#endif + + +#define READ_1_1_1 MODE_1_1_1, QSPI_CMD_READ_1IO, QSPI_READ_1IO_DUMMY_CYCLE +#define READ_1_1_2 MODE_1_1_2, QSPI_CMD_READ_1I2O, QSPI_READ_1I2O_DUMMY_CYCLE +#define READ_1_2_2 MODE_1_2_2, QSPI_CMD_READ_2IO, QSPI_READ_2IO_DUMMY_CYCLE +#define READ_1_1_4 MODE_1_1_4, QSPI_CMD_READ_1I4O, QSPI_READ_1I4O_DUMMY_CYCLE +#define READ_1_4_4 MODE_1_4_4, QSPI_CMD_READ_4IO, QSPI_READ_4IO_DUMMY_CYCLE + + +#define ADDR_SIZE_8 QSPI_CFG_ADDR_SIZE_8 +#define ADDR_SIZE_16 QSPI_CFG_ADDR_SIZE_16 +#define ADDR_SIZE_24 QSPI_CFG_ADDR_SIZE_24 +#define ADDR_SIZE_32 QSPI_CFG_ADDR_SIZE_32 + +#define ALT_SIZE_8 QSPI_CFG_ALT_SIZE_8 +#define ALT_SIZE_16 QSPI_CFG_ALT_SIZE_16 +#define ALT_SIZE_24 QSPI_CFG_ALT_SIZE_24 +#define ALT_SIZE_32 QSPI_CFG_ALT_SIZE_32 + +#define STATUS_REG QSPI_CMD_RDSR +#define CONFIG_REG0 QSPI_CMD_RDCR0 +#ifdef QSPI_CMD_RDCR1 +#define CONFIG_REG1 QSPI_CMD_RDCR1 +#endif +#ifdef QSPI_CMD_RDCR2 +#define CONFIG_REG2 QSPI_CMD_RDCR2 +#endif +#define SECURITY_REG QSPI_CMD_RDSCUR + +#ifndef QSPI_CONFIG_REG_1_SIZE +#define QSPI_CONFIG_REG_1_SIZE 0 +#endif + +#ifndef QSPI_CONFIG_REG_2_SIZE +#define QSPI_CONFIG_REG_2_SIZE 0 +#endif + + +#define SECTOR_ERASE QSPI_CMD_ERASE_SECTOR +#define BLOCK_ERASE QSPI_CMD_ERASE_BLOCK_64 + + +#define SECTOR_ERASE_MAX_TIME QSPI_ERASE_SECTOR_MAX_TIME +#define BLOCK32_ERASE_MAX_TIME QSPI_ERASE_BLOCK_32_MAX_TIME +#define BLOCK64_ERASE_MAX_TIME QSPI_ERASE_BLOCK_64_MAX_TIME +#define PAGE_PROG_MAX_TIME QSPI_PAGE_PROG_MAX_TIME +#define WRSR_MAX_TIME QSPI_WRSR_MAX_TIME +#define WAIT_MAX_TIME QSPI_WAIT_MAX_TIME + + + +qspi_status_t read_register(uint32_t cmd, uint8_t *buf, uint32_t size, Qspi &q); +qspi_status_t write_register(uint32_t cmd, uint8_t *buf, uint32_t size, Qspi &q); + +QspiStatus flash_wait_for(uint32_t time_us, Qspi &qspi); + +void flash_init(Qspi &qspi); + +qspi_status_t write_enable(Qspi &qspi); + +qspi_status_t write_disable(Qspi &qspi); + +void log_register(uint32_t cmd, uint32_t reg_size, Qspi &qspi, const char *str = NULL); + +qspi_status_t dual_enable(Qspi &qspi); + +qspi_status_t dual_disable(Qspi &qspi); + +qspi_status_t quad_enable(Qspi &qspi); + +qspi_status_t quad_disable(Qspi &qspi); + +qspi_status_t fast_mode_enable(Qspi &qspi); + +qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi); + +bool is_dual_cmd(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width); + +bool is_quad_cmd(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width); + +#define WAIT_FOR(timeout, q) TEST_ASSERT_EQUAL_MESSAGE(sOK, flash_wait_for(timeout, q), "flash_wait_for failed!!!") + + +#endif // MBED_QSPI_TEST_UTILS_H diff --git a/doxyfile_options b/doxyfile_options index fb8d1f7bca..b3d9e2bfea 100644 --- a/doxyfile_options +++ b/doxyfile_options @@ -2093,6 +2093,7 @@ PREDEFINED = DOXYGEN_ONLY \ DEVICE_SPI \ DEVICE_SPI_ASYNCH \ DEVICE_SPISLAVE \ + DEVICE_QSPI \ DEVICE_STORAGE \ "MBED_DEPRECATED_SINCE(d, m)=" \ "MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=" \ diff --git a/doxygen_options.json b/doxygen_options.json index 6884a64883..971748f333 100644 --- a/doxygen_options.json +++ b/doxygen_options.json @@ -6,7 +6,7 @@ "SEARCH_INCLUDES": "YES", "INCLUDE_PATH": "", "INCLUDE_FILE_PATTERNS": "", - "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"", + "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"", "EXPAND_AS_DEFINED": "", "SKIP_FUNCTION_MACROS": "NO", "STRIP_CODE_COMMENTS": "NO", diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp new file mode 100644 index 0000000000..e0cb3b62d1 --- /dev/null +++ b/drivers/QSPI.cpp @@ -0,0 +1,288 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-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. + */ + +#include "drivers/QSPI.h" +#include "platform/mbed_critical.h" +#include + +#if DEVICE_QSPI + +namespace mbed { + +QSPI *QSPI::_owner = NULL; +SingletonPtr QSPI::_mutex; + +QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel, int mode) : _qspi() +{ + _qspi_io0 = io0; + _qspi_io1 = io1; + _qspi_io2 = io2; + _qspi_io3 = io3; + _qspi_clk = sclk; + _qspi_cs = ssel; + _inst_width = QSPI_CFG_BUS_SINGLE; + _address_width = QSPI_CFG_BUS_SINGLE; + _address_size = QSPI_CFG_ADDR_SIZE_24; + _alt_width = QSPI_CFG_BUS_SINGLE; + _alt_size = QSPI_CFG_ALT_SIZE_8; + _data_width = QSPI_CFG_BUS_SINGLE; + _num_dummy_cycles = 0; + _mode = mode; + _hz = ONE_MHZ; + _initialized = false; + + //Go ahead init the device here with the default config + bool success = _initialize(); + MBED_ASSERT(success); +} + +qspi_status_t QSPI::configure_format(qspi_bus_width_t inst_width, qspi_bus_width_t address_width, qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width, int dummy_cycles) +{ + qspi_status_t ret_status = QSPI_STATUS_OK; + + lock(); + _inst_width = inst_width; + _address_width = address_width; + _address_size = address_size; + _alt_width = alt_width; + _alt_size = alt_size; + _data_width = data_width; + _num_dummy_cycles = dummy_cycles; + + unlock(); + + return ret_status; +} + +qspi_status_t QSPI::set_frequency(int hz) +{ + qspi_status_t ret_status = QSPI_STATUS_OK; + + if (_initialized) { + lock(); + _hz = hz; + //If the same owner, just change freq. + //Otherwise we may have to change mode as well, so call _acquire + if (_owner == this) { + if (QSPI_STATUS_OK != qspi_frequency(&_qspi, _hz)) { + ret_status = QSPI_STATUS_ERROR; + } + } else { + _acquire(); + } + unlock(); + } else { + ret_status = QSPI_STATUS_ERROR; + } + + return ret_status; +} + +qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) +{ + qspi_status_t ret_status = QSPI_STATUS_ERROR; + + if (_initialized) { + if ((rx_length != NULL) && (rx_buffer != NULL)) { + if (*rx_length != 0) { + lock(); + if (true == _acquire()) { + _build_qspi_command(-1, address, -1); + if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) { + ret_status = QSPI_STATUS_OK; + } + } + unlock(); + } + } else { + ret_status = QSPI_STATUS_INVALID_PARAMETER; + } + } + + return ret_status; +} + +qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length) +{ + qspi_status_t ret_status = QSPI_STATUS_ERROR; + + if (_initialized) { + if ((tx_length != NULL) && (tx_buffer != NULL)) { + if (*tx_length != 0) { + lock(); + if (true == _acquire()) { + _build_qspi_command(-1, address, -1); + if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) { + ret_status = QSPI_STATUS_OK; + } + } + unlock(); + } + } else { + ret_status = QSPI_STATUS_INVALID_PARAMETER; + } + } + + return ret_status; +} + +qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length) +{ + qspi_status_t ret_status = QSPI_STATUS_ERROR; + + if (_initialized) { + if ((rx_length != NULL) && (rx_buffer != NULL)) { + if (*rx_length != 0) { + lock(); + if (true == _acquire()) { + _build_qspi_command(instruction, address, alt); + if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) { + ret_status = QSPI_STATUS_OK; + } + } + unlock(); + } + } else { + ret_status = QSPI_STATUS_INVALID_PARAMETER; + } + } + + return ret_status; +} + +qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length) +{ + qspi_status_t ret_status = QSPI_STATUS_ERROR; + + if (_initialized) { + if ((tx_length != NULL) && (tx_buffer != NULL)) { + if (*tx_length != 0) { + lock(); + if (true == _acquire()) { + _build_qspi_command(instruction, address, alt); + if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) { + ret_status = QSPI_STATUS_OK; + } + } + unlock(); + } + } else { + ret_status = QSPI_STATUS_INVALID_PARAMETER; + } + } + + return ret_status; +} + +qspi_status_t QSPI::command_transfer(unsigned int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) +{ + qspi_status_t ret_status = QSPI_STATUS_ERROR; + + if (_initialized) { + lock(); + if (true == _acquire()) { + _build_qspi_command(instruction, address, -1); //We just need the command + if (QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) { + ret_status = QSPI_STATUS_OK; + } + } + unlock(); + } + + return ret_status; +} + +void QSPI::lock() +{ + _mutex->lock(); +} + +void QSPI::unlock() +{ + _mutex->unlock(); +} + +// Note: Private helper function to initialize qspi HAL +bool QSPI::_initialize() +{ + if (_mode != 0 && _mode != 1) { + _initialized = false; + return _initialized; + } + + qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode); + if (QSPI_STATUS_OK == ret) { + _initialized = true; + } else { + _initialized = false; + } + + return _initialized; +} + +// Note: Private function with no locking +bool QSPI::_acquire() +{ + if (_owner != this) { + //This will set freq as well + _initialize(); + _owner = this; + } + + return _initialized; +} + +void QSPI::_build_qspi_command(int instruction, int address, int alt) +{ + memset(&_qspi_command, 0, sizeof(qspi_command_t)); + //Set up instruction phase parameters + _qspi_command.instruction.bus_width = _inst_width; + if (instruction != -1) { + _qspi_command.instruction.value = instruction; + _qspi_command.instruction.disabled = false; + } else { + _qspi_command.instruction.disabled = true; + } + + //Set up address phase parameters + _qspi_command.address.bus_width = _address_width; + _qspi_command.address.size = _address_size; + if (address != -1) { + _qspi_command.address.value = address; + _qspi_command.address.disabled = false; + } else { + _qspi_command.address.disabled = true; + } + + //Set up alt phase parameters + _qspi_command.alt.bus_width = _alt_width; + _qspi_command.alt.size = _alt_size; + if (alt != -1) { + _qspi_command.alt.value = alt; + _qspi_command.alt.disabled = false; + } else { + _qspi_command.alt.disabled = true; + } + + _qspi_command.dummy_count = _num_dummy_cycles; + + //Set up bus width for data phase + _qspi_command.data.bus_width = _data_width; +} + +} // namespace mbed + +#endif diff --git a/drivers/QSPI.h b/drivers/QSPI.h new file mode 100644 index 0000000000..c166e4bc55 --- /dev/null +++ b/drivers/QSPI.h @@ -0,0 +1,224 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-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_H +#define MBED_QSPI_H + +#include "platform/platform.h" + +#if defined (DEVICE_QSPI) || defined(DOXYGEN_ONLY) + +#include "hal/qspi_api.h" +#include "platform/PlatformMutex.h" +#include "platform/SingletonPtr.h" +#include "platform/NonCopyable.h" + +#define ONE_MHZ 1000000 + +namespace mbed { + +/** \addtogroup drivers */ + +/** A QSPI Driver, used for communicating with QSPI slave devices + * + * The default format is set to Quad-SPI(1-1-1), and a clock frequency of 1MHz + * Most QSPI devices will also require Chip Select which is indicated by ssel. + * + * @note Synchronization level: Thread safe + * + * Example: + * @code + * // Write 4 byte array to a QSPI slave, and read the response, note that each device will have its specific read/write/alt values defined + * + * #include "mbed.h" + * + * // hardware ssel (where applicable) + * QSPI qspi_device(QSPI_PIN_IO0, QSPI_PIN_IO1, QSPI_PIN_IO2, QSPI_PIN_IO3, QSPI_PIN_SCK, QSPI_PIN_CSN); // io0, io1, io2, io3, sclk, ssel + * + * + * int main() { + * char tx_buf[] = { 0x11, 0x22, 0x33, 0x44 }; + * char rx_buf[4]; + * int buf_len = sizeof(tx_buf); + * + * int result = qspi_device.write( 0x12 , 0x100000 , 0 , tx_buf, &buf_len ); + * if( !result ) printf("Write failed"); + * int result = qspi_device.read( 0x13 , 0x100000 , 0 , rx_buf, &buf_len ); + * if( !result ) printf("Read failed"); + * + * } + * @endcode + * @ingroup drivers + */ +class QSPI : private NonCopyable { + +public: + + /** Create a QSPI master connected to the specified pins + * + * io0-io3 is used to specify the Pins used for Quad SPI mode + * + * @param io0 1st IO pin used for sending/receiving data during data phase of a transaction + * @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction + * @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction + * @param io3 4th IO pin used for sending/receiving data during data phase of a transaction + * @param sclk QSPI Clock pin + * @param ssel QSPI chip select pin + * @param mode Mode specifies the SPI mode(Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1) + * default value = 0 + * + */ + QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel = NC, int mode = 0); + + /** Configure the data transmission format + * + * @param inst_width Bus width used by instruction phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD) + * @param address_width Bus width used by address phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD) + * @param address_size Size in bits used by address phase(Valid values are QSPI_CFG_ADDR_SIZE_8, QSPI_CFG_ADDR_SIZE_16, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_ADDR_SIZE_32) + * @param alt_width Bus width used by alt phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD) + * @param alt_size Size in bits used by alt phase(Valid values are QSPI_CFG_ADDR_SIZE_8, QSPI_CFG_ADDR_SIZE_16, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_ADDR_SIZE_32) + * @param data_width Bus width used by data phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD) + * @param dummy_cycles Number of dummy clock cycles to be used after alt phase + * + */ + qspi_status_t configure_format(qspi_bus_width_t inst_width, + qspi_bus_width_t address_width, + qspi_address_size_t address_size, + qspi_bus_width_t alt_width, + qspi_alt_size_t alt_size, + qspi_bus_width_t data_width, + int dummy_cycles); + + /** Set the qspi bus clock frequency + * + * @param hz SCLK frequency in hz (default = 1MHz) + * @returns + * Returns QSPI_STATUS_SUCCESS on successful, fails if the interface is already init-ed + */ + qspi_status_t set_frequency(int hz = ONE_MHZ); + + /** Read from QSPI peripheral with the preset read_instruction and alt_value + * + * @param address Address to be accessed in QSPI peripheral + * @param rx_buffer Buffer for data to be read from the peripheral + * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read + * + * @returns + * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. + */ + qspi_status_t read(unsigned int address, char *rx_buffer, size_t *rx_length); + + /** Write to QSPI peripheral using custom write instruction + * + * @param address Address to be accessed in QSPI peripheral + * @param tx_buffer Buffer containing data to be sent to peripheral + * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written + * + * @returns + * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. + */ + qspi_status_t write(unsigned int address, const char *tx_buffer, size_t *tx_length); + + /** Read from QSPI peripheral using custom read instruction, alt values + * + * @param instruction Instruction value to be used in instruction phase + * @param alt Alt value to be used in instruction phase + * @param address Address to be accessed in QSPI peripheral + * @param rx_buffer Buffer for data to be read from the peripheral + * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read + * + * @returns + * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. + */ + qspi_status_t read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length); + + /** Write to QSPI peripheral using custom write instruction, alt values + * + * @param instruction Instruction value to be used in instruction phase + * @param alt Alt value to be used in instruction phase + * @param address Address to be accessed in QSPI peripheral + * @param tx_buffer Buffer containing data to be sent to peripheral + * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written + * + * @returns + * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. + */ + qspi_status_t write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length); + + /** Perform a transaction to write to an address(a control register) and get the status results + * + * @param instruction Instruction value to be used in instruction phase + * @param address Some instruction might require address. Use -1 for ignoring the address value + * @param tx_buffer Buffer containing data to be sent to peripheral + * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written + * @param rx_buffer Buffer for data to be read from the peripheral + * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read + * + * @returns + * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. + */ + qspi_status_t command_transfer(unsigned int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length); + +protected: + /** Acquire exclusive access to this SPI bus + */ + virtual void lock(void); + + /** Release exclusive access to this SPI bus + */ + virtual void unlock(void); + +public: + virtual ~QSPI() + { + } + +protected: + qspi_t _qspi; + + bool acquire(void); + static QSPI *_owner; + static SingletonPtr _mutex; + qspi_bus_width_t _inst_width; //Bus width for Instruction phase + qspi_bus_width_t _address_width; //Bus width for Address phase + qspi_address_size_t _address_size; + qspi_bus_width_t _alt_width; //Bus width for Alt phase + qspi_alt_size_t _alt_size; + qspi_bus_width_t _data_width; //Bus width for Data phase + qspi_command_t _qspi_command; //QSPI Hal command struct + unsigned int _num_dummy_cycles; //Number of dummy cycles to be used + int _hz; //Bus Frequency + int _mode; //SPI mode + bool _initialized; + PinName _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs; //IO lines, clock and chip select + +private: + /* Private acquire function without locking/unlocking + * Implemented in order to avoid duplicate locking and boost performance + */ + bool _acquire(void); + bool _initialize(); + + /* + * This function builds the qspi command struct to be send to Hal + */ + inline void _build_qspi_command(int instruction, int address, int alt); +}; + +} // namespace mbed + +#endif + +#endif diff --git a/hal/qspi_api.h b/hal/qspi_api.h new file mode 100644 index 0000000000..24ba473545 --- /dev/null +++ b/hal/qspi_api.h @@ -0,0 +1,194 @@ + +/** \addtogroup hal */ +/** @{*/ +/* mbed Microcontroller Library + * Copyright (c) 2017 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_API_H +#define MBED_QSPI_API_H + +#include "device.h" +#include + +#if DEVICE_QSPI + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup hal_qspi QSPI HAL + * @{ + */ + +/** QSPI HAL object + */ +typedef struct qspi_s qspi_t; + +/** QSPI Bus width + * + * Some parts of commands provide variable bus width + */ +typedef enum qspi_bus_width { + QSPI_CFG_BUS_SINGLE, + QSPI_CFG_BUS_DUAL, + QSPI_CFG_BUS_QUAD, +} qspi_bus_width_t; + +/** Address size in bits + */ +typedef enum qspi_address_size { + QSPI_CFG_ADDR_SIZE_8, + QSPI_CFG_ADDR_SIZE_16, + QSPI_CFG_ADDR_SIZE_24, + QSPI_CFG_ADDR_SIZE_32, +} qspi_address_size_t; + +/** Alternative size in bits + */ +typedef enum qspi_alt_size { + QSPI_CFG_ALT_SIZE_8, + QSPI_CFG_ALT_SIZE_16, + QSPI_CFG_ALT_SIZE_24, + QSPI_CFG_ALT_SIZE_32, +} qspi_alt_size_t; + +/** QSPI command + * + * Defines a frame format. It consists of instruction, address, alternative, dummy count and data + */ +typedef struct qspi_command { + struct { + qspi_bus_width_t bus_width; /**< Bus width for the instruction >*/ + uint8_t value; /**< Instruction value >*/ + bool disabled; /**< Instruction phase skipped if disabled is set to true >*/ + } instruction; + struct { + qspi_bus_width_t bus_width; /**< Bus width for the address >*/ + qspi_address_size_t size; /**< Address size >*/ + uint32_t value; /**< Address value >*/ + bool disabled; /**< Address phase skipped if disabled is set to true >*/ + } address; + struct { + qspi_bus_width_t bus_width; /**< Bus width for alternative >*/ + qspi_alt_size_t size; /**< Alternative size >*/ + uint32_t value; /**< Alternative value >*/ + bool disabled; /**< Alternative phase skipped if disabled is set to true >*/ + } alt; + uint8_t dummy_count; /**< Dummy cycles count >*/ + struct { + qspi_bus_width_t bus_width; /**< Bus width for data >*/ + } data; +} qspi_command_t; + +/** QSPI return status + */ +typedef enum qspi_status { + QSPI_STATUS_ERROR = -1, /**< Generic error >*/ + QSPI_STATUS_INVALID_PARAMETER = -2, /**< The parameter is invalid >*/ + QSPI_STATUS_OK = 0, /**< Function executed sucessfully >*/ +} qspi_status_t; + +/** Initialize QSPI peripheral. + * + * It should initialize QSPI pins (io0-io3, sclk and ssel), set frequency, clock polarity and phase mode. The clock for the peripheral should be enabled + * + * @param obj QSPI object + * @param io0 Data pin 0 + * @param io1 Data pin 1 + * @param io2 Data pin 2 + * @param io3 Data pin 3 + * @param sclk The clock pin + * @param ssel The chip select pin + * @param hz The bus frequency + * @param mode Clock polarity and phase mode (0 - 3) + * @return QSPI_STATUS_OK if initialisation successfully executed + QSPI_STATUS_INVALID_PARAMETER if invalid parameter found + QSPI_STATUS_ERROR otherwise + */ +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); + +/** Deinitilize QSPI peripheral + * + * It should release pins that are associated with the QSPI object, and disable clocks for QSPI peripheral module that was associated with the object + * + * @param obj QSPI object + * @return QSPI_STATUS_OK if deinitialisation successfully executed + QSPI_STATUS_INVALID_PARAMETER if invalid parameter found + QSPI_STATUS_ERROR otherwise + */ +qspi_status_t qspi_free(qspi_t *obj); + +/** Set the QSPI baud rate + * + * Actual frequency may differ from the desired frequency due to available dividers and the bus clock + * Configures the QSPI peripheral's baud rate + * @param obj The SPI object to configure + * @param hz The baud rate in Hz + * @return QSPI_STATUS_OK if frequency was set + QSPI_STATUS_INVALID_PARAMETER if invalid parameter found + QSPI_STATUS_ERROR otherwise + */ +qspi_status_t qspi_frequency(qspi_t *obj, int hz); + +/** Send a command and block of data + * + * @param obj QSPI object + * @param command QSPI command + * @param data TX buffer + * @param[in,out] length in - TX buffer length in bytes, out - number of bytes written + * @return QSPI_STATUS_OK if the data has been succesfully sent + QSPI_STATUS_INVALID_PARAMETER if invalid parameter found + QSPI_STATUS_ERROR otherwise + */ +qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length); + +/** Send a command (and optionally data) and get the response. Can be used to send/receive device specific commands + * + * @param obj QSPI object + * @param command QSPI command + * @param tx_data TX buffer + * @param tx_size TX buffer length in bytes + * @param rx_data RX buffer + * @param rx_size RX buffer length in bytes + * @return QSPI_STATUS_OK if the data has been succesfully sent + QSPI_STATUS_INVALID_PARAMETER if invalid parameter found + QSPI_STATUS_ERROR otherwise + */ +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); + +/** Receive a command and block of data + * + * @param obj QSPI object + * @param command QSPI command + * @param data RX buffer + * @param[in,out] length in - RX buffer length in bytes, out - number of bytes read + * @return QSPI_STATUS_OK if data has been succesfully received + QSPI_STATUS_INVALID_PARAMETER if invalid parameter found + QSPI_STATUS_ERROR otherwise + */ +qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t *length); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +/** @}*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h index 2a5f319abd..4241cdcf47 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h @@ -227,6 +227,13 @@ typedef enum { A4 = p30, A5 = p31, + QSPI_FLASH_IO0 = P0_20, + QSPI_FLASH_IO1 = P0_21, + QSPI_FLASH_IO2 = P0_22, + QSPI_FLASH_IO3 = P0_23, + QSPI_FLASH_SCK = P0_19, + QSPI_FLASH_CSN = P0_17, + // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h index 201402a18e..203602ec0a 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h @@ -2748,6 +2748,136 @@ // +// QSPI_ENABLED - nrf_drv_qspi - QSPI peripheral driver. +//========================================================== +#ifndef QSPI_ENABLED +#define QSPI_ENABLED 1 +#endif +#if QSPI_ENABLED +// QSPI_CONFIG_SCK_DELAY - tSHSL, tWHSL and tSHWL in number of 16 MHz periods (62.5 ns). <0-255> + + +#ifndef QSPI_CONFIG_SCK_DELAY +#define QSPI_CONFIG_SCK_DELAY 1 +#endif + +// QSPI_CONFIG_READOC - Number of data lines and opcode used for reading. + +// <0=> FastRead +// <1=> Read2O +// <2=> Read2IO +// <3=> Read4O +// <4=> Read4IO + +#ifndef QSPI_CONFIG_READOC +#define QSPI_CONFIG_READOC 4 +#endif + +// QSPI_CONFIG_WRITEOC - Number of data lines and opcode used for writing. + +// <0=> PP +// <1=> PP2O +// <2=> PP4O +// <3=> PP4IO + +#ifndef QSPI_CONFIG_WRITEOC +#define QSPI_CONFIG_WRITEOC 3 +#endif + +// QSPI_CONFIG_ADDRMODE - Addressing mode. + +// <0=> 24bit +// <1=> 32bit + +#ifndef QSPI_CONFIG_ADDRMODE +#define QSPI_CONFIG_ADDRMODE 0 +#endif + +// QSPI_CONFIG_MODE - SPI mode. + +// <0=> Mode 0 +// <1=> Mode 1 + +#ifndef QSPI_CONFIG_MODE +#define QSPI_CONFIG_MODE 0 +#endif + +// QSPI_CONFIG_FREQUENCY - Frequency divider. + +// <0=> 32MHz/1 +// <1=> 32MHz/2 +// <2=> 32MHz/3 +// <3=> 32MHz/4 +// <4=> 32MHz/5 +// <5=> 32MHz/6 +// <6=> 32MHz/7 +// <7=> 32MHz/8 +// <8=> 32MHz/9 +// <9=> 32MHz/10 +// <10=> 32MHz/11 +// <11=> 32MHz/12 +// <12=> 32MHz/13 +// <13=> 32MHz/14 +// <14=> 32MHz/15 +// <15=> 32MHz/16 + +#ifndef QSPI_CONFIG_FREQUENCY +#define QSPI_CONFIG_FREQUENCY 1 +#endif + +// QSPI_PIN_SCK - SCK pin value. +#ifndef QSPI_PIN_SCK +#define QSPI_PIN_SCK NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_CSN - CSN pin value. +#ifndef QSPI_PIN_CSN +#define QSPI_PIN_CSN NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_IO0 - IO0 pin value. +#ifndef QSPI_PIN_IO0 +#define QSPI_PIN_IO0 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_IO1 - IO1 pin value. +#ifndef QSPI_PIN_IO1 +#define QSPI_PIN_IO1 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_IO2 - IO2 pin value. +#ifndef QSPI_PIN_IO2 +#define QSPI_PIN_IO2 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_IO3 - IO3 pin value. +#ifndef QSPI_PIN_IO3 +#define QSPI_PIN_IO3 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef QSPI_CONFIG_IRQ_PRIORITY +#define QSPI_CONFIG_IRQ_PRIORITY 7 +#endif + +#endif //QSPI_ENABLED + +// + +// + // TIMER_ENABLED - nrf_drv_timer - TIMER periperal driver //========================================================== #ifndef TIMER_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h index 47e6276a82..39c4b60f67 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/objects.h @@ -142,6 +142,17 @@ struct flash_s { uint32_t placeholder; }; +#if DEVICE_QSPI + +#include "nrf_drv_qspi.h" + +struct qspi_s { + uint32_t placeholder; + //nrf_drv_qspi_config_t config; +}; + +#endif + #include "gpio_object.h" #ifdef __cplusplus diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c new file mode 100644 index 0000000000..39e25df550 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2017 Nordic Semiconductor ASA + * 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, except as embedded into a Nordic Semiconductor ASA + * integrated circuit in a product or a software update for such product, 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 Nordic Semiconductor ASA nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary or object form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * 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. + * + */ + +#include "qspi_api.h" + +#if DEVICE_QSPI + +#include "nrf_drv_common.h" +#include "nrf_drv_qspi.h" + +/* +TODO + - config inside obj - nordic headers have some problems with inclusion + - free - is it really empty, nothing to do there? + - prepare command - support more protocols that nordic can do (now limited) + - nordic does not support + - alt + - dummy cycles +*/ + +#define MBED_HAL_QSPI_HZ_TO_CONFIG(hz) ((32000000/(hz))-1) +#define MBED_HAL_QSPI_MAX_FREQ 32000000UL + +// NRF supported R/W opcodes +#define FAST_READ_opcode 0x0B +#define READ2O_opcode 0x3B +#define READ2IO_opcode 0xBB +#define READ4O_opcode 0x6B +#define READ4IO_opcode 0xEB + +#define PP_opcode 0x02 +#define PP2O_opcode 0xA2 +#define PP4O_opcode 0x32 +#define PP4IO_opcode 0x38 + +static nrf_drv_qspi_config_t config; + +// Private helper function to track initialization +static ret_code_t _qspi_drv_init(void); + +qspi_status_t qspi_prepare_command(qspi_t *obj, const qspi_command_t *command, bool write) +{ + // we need to remap opcodes to NRF ID's + // most commmon are 1-1-1, 1-1-4, 1-4-4 + + // 1-1-1 + if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE && + command->address.bus_width == QSPI_CFG_BUS_SINGLE && + command->data.bus_width == QSPI_CFG_BUS_SINGLE) { + if (write) { + if (command->instruction.value == PP_opcode) { + config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + } else { + if (command->instruction.value == FAST_READ_opcode) { + config.prot_if.readoc = NRF_QSPI_READOC_FASTREAD; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + } + // 1-1-4 + } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE && + command->address.bus_width == QSPI_CFG_BUS_SINGLE && + command->data.bus_width == QSPI_CFG_BUS_QUAD) { + // 1_1_4 + if (write) { + if (command->instruction.value == PP4O_opcode) { + config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP4O; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + } else { + if (command->instruction.value == READ4O_opcode) { + config.prot_if.readoc = NRF_QSPI_READOC_READ4O; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + } + // 1-4-4 + } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE && + command->address.bus_width == QSPI_CFG_BUS_QUAD && + command->data.bus_width == QSPI_CFG_BUS_QUAD) { + // 1_4_4 + if (write) { + if (command->instruction.value == PP4IO_opcode) { + config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP4IO; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + } else { + if (command->instruction.value == READ4IO_opcode) { + config.prot_if.readoc = NRF_QSPI_READOC_READ4IO; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + } + // 1-1-2 + } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE && + command->address.bus_width == QSPI_CFG_BUS_SINGLE && + command->data.bus_width == QSPI_CFG_BUS_DUAL) { + // 1-1-2 + if (write) { + if (command->instruction.value == PP2O_opcode) { + config.prot_if.writeoc = NRF_QSPI_WRITEOC_PP2O; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + } else { + if (command->instruction.value == READ2O_opcode) { + config.prot_if.readoc = NRF_QSPI_READOC_READ2O; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + } + // 1-2-2 + } else if (command->instruction.bus_width == QSPI_CFG_BUS_SINGLE && + command->address.bus_width == QSPI_CFG_BUS_DUAL && + command->data.bus_width == QSPI_CFG_BUS_DUAL) { + // 1-2-2 + if (write) { + // 1-2-2 write is not supported + return QSPI_STATUS_INVALID_PARAMETER; + } else { + if (command->instruction.value == READ2IO_opcode) { + config.prot_if.readoc = NRF_QSPI_READOC_READ2IO; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + } + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + + // supporting only 24 or 32 bit address + if (command->address.size == QSPI_CFG_ADDR_SIZE_24) { + config.prot_if.addrmode = NRF_QSPI_ADDRMODE_24BIT; + } else if (command->address.size == QSPI_CFG_ADDR_SIZE_32) { + config.prot_if.addrmode = NRF_QSPI_ADDRMODE_32BIT; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + + //Configure QSPI with new command format + ret_code_t ret_status = _qspi_drv_init(); + if (ret_status != NRF_SUCCESS ) { + if (ret_status == NRF_ERROR_INVALID_PARAM) { + return QSPI_STATUS_INVALID_PARAMETER; + } else { + return QSPI_STATUS_ERROR; + } + } + + return QSPI_STATUS_OK; +} + +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) +{ + (void)(obj); + if (hz > MBED_HAL_QSPI_MAX_FREQ) { + return QSPI_STATUS_INVALID_PARAMETER; + } + + // memset(config, 0, sizeof(config)); + + config.pins.sck_pin = (uint32_t)sclk; + config.pins.csn_pin = (uint32_t)ssel; + config.pins.io0_pin = (uint32_t)io0; + config.pins.io1_pin = (uint32_t)io1; + config.pins.io2_pin = (uint32_t)io2; + config.pins.io3_pin = (uint32_t)io3; + config.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY; + + config.phy_if.sck_freq = (nrf_qspi_frequency_t)MBED_HAL_QSPI_HZ_TO_CONFIG(hz); + config.phy_if.sck_delay = 0x05; + config.phy_if.dpmen = false; + config.phy_if.spi_mode = mode == 0 ? NRF_QSPI_MODE_0 : NRF_QSPI_MODE_1; + + //Use _qspi_drv_init private function to initialize + ret_code_t ret = _qspi_drv_init(); + if (ret == NRF_SUCCESS ) { + return QSPI_STATUS_OK; + } else if (ret == NRF_ERROR_INVALID_PARAM) { + return QSPI_STATUS_INVALID_PARAMETER; + } else { + return QSPI_STATUS_ERROR; + } +} + +qspi_status_t qspi_free(qspi_t *obj) +{ + (void)(obj); + // possibly here uninit from SDK driver + return QSPI_STATUS_OK; +} + +qspi_status_t qspi_frequency(qspi_t *obj, int hz) +{ + config.phy_if.sck_freq = (nrf_qspi_frequency_t)MBED_HAL_QSPI_HZ_TO_CONFIG(hz); + + // use sync version, no handler + ret_code_t ret = _qspi_drv_init(); + if (ret == NRF_SUCCESS ) { + return QSPI_STATUS_OK; + } else if (ret == NRF_ERROR_INVALID_PARAM) { + return QSPI_STATUS_INVALID_PARAMETER; + } else { + return QSPI_STATUS_ERROR; + } +} + +qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length) +{ + qspi_status_t status = qspi_prepare_command(obj, command, true); + if (status != QSPI_STATUS_OK) { + return status; + } + + // write here does not return how much it transfered, we return transfered all + ret_code_t ret = nrf_drv_qspi_write(data, *length, command->address.value); + if (ret == NRF_SUCCESS ) { + return QSPI_STATUS_OK; + } else { + return QSPI_STATUS_ERROR; + } +} + +qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t *length) +{ + qspi_status_t status = qspi_prepare_command(obj, command, false); + if (status != QSPI_STATUS_OK) { + return status; + } + + ret_code_t ret = nrf_drv_qspi_read(data, *length, command->address.value); + if (ret == NRF_SUCCESS ) { + return QSPI_STATUS_OK; + } else { + return QSPI_STATUS_ERROR; + } +} + +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) +{ + ret_code_t ret_code; + uint8_t data[8]; + uint32_t data_size = tx_size + rx_size; + + nrf_qspi_cinstr_conf_t qspi_cinstr_config; + qspi_cinstr_config.opcode = command->instruction.value; + qspi_cinstr_config.io2_level = true; + qspi_cinstr_config.io3_level = true; + qspi_cinstr_config.wipwait = false; + qspi_cinstr_config.wren = false; + + if(!command->address.disabled && data_size == 0) { + // erase command with address + if (command->address.size == QSPI_CFG_ADDR_SIZE_24) { + qspi_cinstr_config.length = NRF_QSPI_CINSTR_LEN_4B; + } else if (command->address.size == QSPI_CFG_ADDR_SIZE_32) { + qspi_cinstr_config.length = NRF_QSPI_CINSTR_LEN_5B; + } else { + return QSPI_STATUS_INVALID_PARAMETER; + } + for (uint32_t i = 0; i < (uint32_t)qspi_cinstr_config.length - 1; ++i) { + data[i] = ((uint8_t *)&command->address.value)[i]; + } + } else if (data_size < 9) { + qspi_cinstr_config.length = (nrf_qspi_cinstr_len_t)(NRF_QSPI_CINSTR_LEN_1B + data_size); + // preparing data to send + for (uint32_t i = 0; i < tx_size; ++i) { + data[i] = ((uint8_t *)tx_data)[i]; + } + } else { + return QSPI_STATUS_ERROR; + } + + ret_code = nrf_drv_qspi_cinstr_xfer(&qspi_cinstr_config, data, data); + if (ret_code != NRF_SUCCESS) { + return QSPI_STATUS_ERROR; + } + + // preparing received data + for (uint32_t i = 0; i < rx_size; ++i) { + // Data is sending as a normal SPI transmission so there is one buffer to send and receive data. + ((uint8_t *)rx_data)[i] = data[i]; + } + + return QSPI_STATUS_OK; +} + +// Private helper function to track initialization +static ret_code_t _qspi_drv_init(void) +{ + static bool _initialized = false; + ret_code_t ret = NRF_ERROR_INVALID_STATE; + + if(_initialized) { + //NRF implementation prevents calling init again. But we need to call init again to program the new command settings in the IFCONFIG registers. + //So, we have to uninit qspi first and call init again. + nrf_drv_qspi_uninit(); + } + ret = nrf_drv_qspi_init(&config, NULL , NULL); + if( ret == NRF_SUCCESS ) + _initialized = true; + return ret; +} + + +#endif + +/** @}*/ diff --git a/targets/TARGET_STM/PeripheralPins.h b/targets/TARGET_STM/PeripheralPins.h index f96b84890b..d1d5f2ea84 100644 --- a/targets/TARGET_STM/PeripheralPins.h +++ b/targets/TARGET_STM/PeripheralPins.h @@ -80,4 +80,10 @@ extern const PinMap PinMap_CAN_RD[]; extern const PinMap PinMap_CAN_TD[]; #endif +#ifdef DEVICE_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_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_NUCLEO_F412ZG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_NUCLEO_F412ZG/PeripheralNames.h index c85180daf4..fd90f158b8 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_NUCLEO_F412ZG/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_NUCLEO_F412ZG/PeripheralNames.h @@ -68,6 +68,10 @@ typedef enum { CAN_2 = (int)CAN2_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_NUCLEO_F412ZG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_NUCLEO_F412ZG/PeripheralPins.c index e930f1049d..60b2bb5ce8 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_NUCLEO_F412ZG/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_NUCLEO_F412ZG/PeripheralPins.c @@ -347,3 +347,48 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PG_12, CAN_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN2)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0 + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1 + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS + {PC_4, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2 + {PC_5, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3 + {PC_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0 + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1 + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2 + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3 + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO0 + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO1 + {PG_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to USB_PowerSwitchOn [STMPS2151STR_EN] + {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO2 + {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO3 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK + {PD_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS + {PG_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to USB_PowerSwitchOn [STMPS2151STR_EN] + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralNames.h index 22ad0b3f55..3493e2cd25 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralNames.h @@ -79,6 +79,10 @@ typedef enum { CAN_3 = (int)CAN3_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralPins.c index 3f5be12738..1f1b0edb2b 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PeripheralPins.c @@ -399,3 +399,48 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PG_12, CAN_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN2)}, // Connected to WIFI_DRDY {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 // Connected to ARD_A1 + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0 // Connected to SD_CMD + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1 // Connected to DFSDM2_DATIN1 + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to ARD_D4 + {PC_4, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2 // Connected to ARD_A5 + {PC_5, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3 // Connected to LED2_GREEN + {PC_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 // Connected to SD_D0 + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 // Connected to SD_D1 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 // Connected to SD_D2 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS // Connected to SD_D3 + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 // Connected to PSRAM_A16 [IS66WV51216EBLL_A16] + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 // Connected to PSRAM_A17 [IS66WV51216EBLL_A17] + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 // Connected to QSPI_BK1_IO3 [N25Q128A13EF840F_DQ3] + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 // Connected to QSPI_BK1_IO2 [N25Q128A13EF840F_DQ2] + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0 // Connected to LCD_PSRAM_D4 + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1 // Connected to LCD_PSRAM_D5 + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2 // Connected to LCD_PSRAM_D6 + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3 // Connected to LCD_PSRAM_D7 + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 // Connected to ARD_D0 + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 // Connected to ARD_D1 + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO0 // Connected to QSPI_BK1_IO0 [N25Q128A13EF840F_DQ0] + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO1 // Connected to QSPI_BK1_IO1 [N25Q128A13EF840F_DQ1] + {PG_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_BK1_NCS [N25Q128A13EF840F_S] +// {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO2 // Connected to STDIO_UART_RX +// {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO3 // Connected to STDIO_UART_TX + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK // Connected to ARD_A4 + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK // Connected to QSPI_CLK [N25Q128A13EF840F_C] + {PD_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK // Connected to CODEC_CK [WM8994ECS_BCLK1] + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to ARD_D4 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS // Connected to SD_D3 + {PG_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_BK1_NCS [N25Q128A13EF840F_S] + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PinNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PinNames.h index c207cc1b8c..1d8185833f 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_DISCO_F413ZH/PinNames.h @@ -303,6 +303,14 @@ typedef enum { SYS_WKUP2 = PC_0, SYS_WKUP3 = PC_1, + /**** QSPI FLASH pins ****/ + QSPI_PIN_IO0 = PF_8, + QSPI_PIN_IO1 = PF_9, + QSPI_PIN_IO2 = PE_2, + QSPI_PIN_IO3 = PD_13, + QSPI_PIN_SCK = PB_2, + QSPI_PIN_CSN = PG_6, + // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_NUCLEO_F413ZH/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_NUCLEO_F413ZH/PeripheralNames.h index 22ad0b3f55..3493e2cd25 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_NUCLEO_F413ZH/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_NUCLEO_F413ZH/PeripheralNames.h @@ -79,6 +79,10 @@ typedef enum { CAN_3 = (int)CAN3_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_NUCLEO_F413ZH/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_NUCLEO_F413ZH/PeripheralPins.c index 7849e9a665..c36385da88 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_NUCLEO_F413ZH/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/TARGET_NUCLEO_F413ZH/PeripheralPins.c @@ -399,3 +399,48 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PG_12, CAN_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN2)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0 + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1 + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS + {PC_4, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2 + {PC_5, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3 + {PC_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0 + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1 + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2 + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3 + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO0 + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO1 + {PG_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to USB_PowerSwitchOn [STMPS2151STR_EN] + {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO2 + {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO3 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK + {PD_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS + {PG_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to USB_PowerSwitchOn [STMPS2151STR_EN] + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/objects.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/objects.h index 9b3aa0b3f9..0c132e93fd 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/objects.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F413xH/objects.h @@ -44,6 +44,16 @@ struct trng_s { RNG_HandleTypeDef handle; }; +struct qspi_s { + QSPI_HandleTypeDef handle; + PinName io0; + PinName io1; + PinName io2; + PinName io3; + PinName sclk; + PinName ssel; +}; + #include "common_objects.h" #ifdef __cplusplus diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/PeripheralNames.h index 0382c324ea..baa8cfb032 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/PeripheralNames.h @@ -89,6 +89,10 @@ typedef enum { CAN_2 = (int)CAN2_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/PeripheralPins.c index 5c950eaba3..bfb40065cf 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/PeripheralPins.c @@ -309,3 +309,25 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PB_13, CAN_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN2)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE/PeripheralNames.h index 0382c324ea..baa8cfb032 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE/PeripheralNames.h @@ -89,6 +89,10 @@ typedef enum { CAN_2 = (int)CAN2_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE/PeripheralPins.c index cf27af8c35..91dee64454 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE/PeripheralPins.c @@ -380,3 +380,42 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PD_1, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0 + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1 + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2 + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3 + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO0 + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO1 + {PG_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to USB_PowerSwitchOn [STMPS2151STR_EN] + {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO2 + {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO3 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK + {PD_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS + {PG_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to USB_PowerSwitchOn [STMPS2151STR_EN] + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralNames.h index ce3afd5658..39455e98e6 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralNames.h @@ -92,6 +92,10 @@ typedef enum { CAN_2 = (int)CAN2_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c index 1f3690e4d0..8d2e24426d 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PeripheralPins.c @@ -388,3 +388,44 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PH_13, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to D21 {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_BK1_NCS [N25Q128A13EF840F_S] +// {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_NCS // Connected to STDIO_UART_TX + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 // Connected to uSD_D1 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 // Connected to uSD_D2 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS // Connected to uSD_D3 + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO0 + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO1 + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 // Connected to MIC_CK [MP34DT01TR_CLK] + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 // Connected to AUDIO_RST [CS43L22_RESET] + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO0 // Connected to D4 + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO1 // Connected to D5 + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO2 // Connected to D6 + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK2_IO3 // Connected to D7 + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO3 // Connected to QSPI_BK1_IO3 [N25Q128A13EF840F_DQ3] + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_IO2 // Connected to QSPI_BK1_IO2 [N25Q128A13EF840F_DQ2] + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO0 // Connected to QSPI_BK1_IO0 [N25Q128A13EF840F_DQ0] + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_IO1 // Connected to QSPI_BK1_IO1 [N25Q128A13EF840F_DQ1] + {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO2 // Connected to USART6_RX + {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO3 // Connected to ARDUINO USART6_TX + {PH_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO0 // Connected to SDCKE0 [MT48LC4M32B2B5-6A_CKE] + {PH_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_IO1 // Connected to SDNE0 [MT48LC4M32B2B5-6A_CS] + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_CLK + {PF_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_CLK // Connected to QSPI_CLK [N25Q128A13EF840F_C] + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_BK1_NCS [N25Q128A13EF840F_S] +// {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK1_NCS // Connected to STDIO_UART_TX + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QSPI)}, // QUADSPI_BK2_NCS // Connected to uSD_D3 + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PinNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PinNames.h index 5d8187d616..58ebf4e8f6 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/TARGET_DISCO_F469NI/PinNames.h @@ -406,6 +406,13 @@ typedef enum { SYS_TRACED3_ALT0 = PE_6, SYS_WKUP = PA_0, + QSPI_FLASH_IO0 = PF_8, + QSPI_FLASH_IO1 = PF_9, + QSPI_FLASH_IO2 = PF_7, + QSPI_FLASH_IO3 = PF_6, + QSPI_FLASH_SCK = PF_10, + QSPI_FLASH_CSN = PB_6, + // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/objects.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/objects.h index bea7fef547..106be4c446 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/objects.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F469xI/objects.h @@ -58,6 +58,16 @@ struct trng_s { RNG_HandleTypeDef handle; }; +struct qspi_s { + QSPI_HandleTypeDef handle; + PinName io0; + PinName io1; + PinName io2; + PinName io3; + PinName sclk; + PinName ssel; +}; + #include "common_objects.h" #ifdef __cplusplus diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralNames.h index 0c00d43bf5..771553bb53 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralNames.h @@ -93,6 +93,10 @@ typedef enum { CAN_2 = (int)CAN2_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralPins.c index 6c9c3bec71..9781b7dd46 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralPins.c @@ -406,3 +406,41 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PH_13, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to DCMI_PWR_EN {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0] + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_NCS [N25Q128A13EF840E_S] + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to SDMMC1_D1 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to SDMMC_D2 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS // Connected to SDMMC_D3 + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to QSPI_D0 [N25Q128A13EF840E_DQ0] + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to QSPI_D1 [N25Q128A13EF840E_DQ1] + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to QSPI_D3 [N25Q128A13EF840E_DQ3] + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to QSPI_D2 [N25Q128A13EF840E_DQ2] + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO0 // Connected to FMC_D4 [MT48LC4M32B2B5-6A_DQ4] + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO1 // Connected to FMC_D5 [MT48LC4M32B2B5-6A_DQ5] + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO2 // Connected to FMC_D6 [MT48LC4M32B2B5-6A_DQ6] + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO3 // Connected to FMC_D7 [MT48LC4M32B2B5-6A_DQ7] + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to ARDUINO A5 + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to ARDUINO A4 + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to ARDUINO A3 + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to ARDUINO A2 + {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO2 // Connected to DCMI_VSYNC + {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO3 // Connected to RMII_TXD1 [LAN8742A-CZ-TR_TXD1] + {PH_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO0 // Connected to NC2 + {PH_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO1 // Connected to FMC_SDNE0 [MT48LC4M32B2B5-6A_CS] + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_CLK // Connected to QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_NCS [N25Q128A13EF840E_S] + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS // Connected to SDMMC_D3 + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/PeripheralNames.h index 66fc3645d5..1665800aa2 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/PeripheralNames.h @@ -93,6 +93,10 @@ typedef enum { CAN_2 = (int)CAN2_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/PeripheralPins.c index b532122f88..3d8218d176 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/PeripheralPins.c @@ -378,3 +378,39 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PD_1, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0] + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO0 + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO1 + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO2 + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO3 + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO2 + {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO3 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/objects.h b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/objects.h index 2894691118..2e538dcf5b 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/objects.h +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/objects.h @@ -58,6 +58,16 @@ struct trng_s { RNG_HandleTypeDef handle; }; +struct qspi_s { + QSPI_HandleTypeDef handle; + PinName io0; + PinName io1; + PinName io2; + PinName io3; + PinName sclk; + PinName ssel; +}; + #include "common_objects.h" #ifdef __cplusplus diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F756xG/TARGET_NUCLEO_F756ZG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F756xG/TARGET_NUCLEO_F756ZG/PeripheralNames.h index 66fc3645d5..1665800aa2 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F756xG/TARGET_NUCLEO_F756ZG/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F756xG/TARGET_NUCLEO_F756ZG/PeripheralNames.h @@ -93,6 +93,10 @@ typedef enum { CAN_2 = (int)CAN2_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F756xG/TARGET_NUCLEO_F756ZG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F756xG/TARGET_NUCLEO_F756ZG/PeripheralPins.c index b532122f88..3d8218d176 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F756xG/TARGET_NUCLEO_F756ZG/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F756xG/TARGET_NUCLEO_F756ZG/PeripheralPins.c @@ -378,3 +378,39 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PD_1, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0] + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO0 + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO1 + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO2 + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO3 + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO2 + {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO3 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F767xI/TARGET_NUCLEO_F767ZI/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F767xI/TARGET_NUCLEO_F767ZI/PeripheralNames.h index 2383be6c21..f0584fe465 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F767xI/TARGET_NUCLEO_F767ZI/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F767xI/TARGET_NUCLEO_F767ZI/PeripheralNames.h @@ -94,6 +94,10 @@ typedef enum { CAN_3 = (int)CAN3_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F767xI/TARGET_NUCLEO_F767ZI/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F767xI/TARGET_NUCLEO_F767ZI/PeripheralPins.c index 5e12d2c985..c11e39acbd 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F767xI/TARGET_NUCLEO_F767ZI/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F767xI/TARGET_NUCLEO_F767ZI/PeripheralPins.c @@ -418,3 +418,42 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PD_1, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0] + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_NCS + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO0 + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO1 + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO2 + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO3 + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO2 + {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO3 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_CLK + {PF_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_NCS + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/PeripheralNames.h index 2383be6c21..f0584fe465 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/PeripheralNames.h @@ -94,6 +94,10 @@ typedef enum { CAN_3 = (int)CAN3_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/PeripheralPins.c index 1920db8a2c..6c2ac77d70 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/PeripheralPins.c @@ -450,3 +450,44 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PH_13, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to D21 {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0] + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_NCS [N25Q128A13EF840E_S] + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to ULPI_D3 [USB3320C-EZK_D3] + {PC_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to QSPI_D0 [N25Q128A13EF840E_DQ0] + {PC_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to QSPI_D1 [MT25QL512ABB1EW9_DQ1] + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS // Connected to DFSDM_DATIN5 [TP5] + {PD_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to SPDIF_TX [TP20] + {PD_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to AUDIO_SCL [WM8994ECS/R_SCLK] + {PD_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to QSPI_D3 [N25Q128A13EF840E_DQ3] + {PE_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to QSPI_D2 [N25Q128A13EF840E_DQ2] + {PE_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO0 // Connected to FMC_D4 [MT48LC4M32B2B5-6A_DQ4] + {PE_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO1 // Connected to FMC_D5 [MT48LC4M32B2B5-6A_DQ5] + {PE_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO2 // Connected to FMC_D6 [MT48LC4M32B2B5-6A_DQ6] + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO3 // Connected to FMC_D7 [MT48LC4M32B2B5-6A_DQ7] + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to ARD_D3/PWM + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to ARD_D6/PWM + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to ARDUINO A3 + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to ARDUINO A2 + {PG_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO2 // Connected to uSD_D0 + {PG_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO3 // Connected to RMII_TXD1 [LAN8742A-CZ-TR_TXD1] + {PH_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO0 // Connected to FMC_SDCKE0 [MT48LC4M32B2B5-6A_CKE] + {PH_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_IO1 // Connected to FMC_SDNE0 [MT48LC4M32B2B5-6A_CS] + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_CLK // Connected to QSPI_CLK + {PF_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_CLK // Connected to ARDUINO A1 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_NCS [N25Q128A13EF840E_S] + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to ULPI_D3 [USB3320C-EZK_D3] + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK2_NCS // Connected to DFSDM_DATIN5 [TP5] + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L432xC/TARGET_NUCLEO_L432KC/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L432xC/TARGET_NUCLEO_L432KC/PeripheralNames.h index 4c8d454ccc..045a699cb4 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L432xC/TARGET_NUCLEO_L432KC/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L432xC/TARGET_NUCLEO_L432KC/PeripheralNames.h @@ -71,6 +71,10 @@ typedef enum { CAN_1 = (int)CAN1_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L432xC/TARGET_NUCLEO_L432KC/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L432xC/TARGET_NUCLEO_L432KC/PeripheralPins.c index cb5bbaff5b..175a8747bf 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L432xC/TARGET_NUCLEO_L432KC/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L432xC/TARGET_NUCLEO_L432KC/PeripheralPins.c @@ -204,3 +204,24 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PA_12, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { +// {PA_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to STDIO_UART_TX + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 + {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PA_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { +// {PA_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to STDIO_UART_TX + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L433xC/TARGET_NUCLEO_L433RC_P/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L433xC/TARGET_NUCLEO_L433RC_P/PeripheralNames.h index bc71becee7..049b2f31f5 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L433xC/TARGET_NUCLEO_L433RC_P/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L433xC/TARGET_NUCLEO_L433RC_P/PeripheralNames.h @@ -76,6 +76,10 @@ typedef enum { CAN_1 = (int)CAN1_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L433xC/TARGET_NUCLEO_L433RC_P/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L433xC/TARGET_NUCLEO_L433RC_P/PeripheralPins.c index 405e6778ad..6dddb43f74 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L433xC/TARGET_NUCLEO_L433RC_P/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L433xC/TARGET_NUCLEO_L433RC_P/PeripheralPins.c @@ -259,3 +259,27 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PB_9, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { +// {PA_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to STDIO_UART_TX + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to SMPS_PG [ADP5301ACBZ_OUTOK] + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to SMPS_SW [TS3A44159PWR_IN1_2] + {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { +// {PA_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK // Connected to STDIO_UART_RX + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { +// {PA_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to STDIO_UART_TX + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralNames.h index 2a66882a1c..04b09f6539 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralNames.h @@ -83,6 +83,10 @@ typedef enum { CAN_1 = (int)CAN1_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralPins.c index a21e78ce22..3861e7a9d5 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PeripheralPins.c @@ -340,3 +340,29 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PD_1, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to PMOD_SPI2_SCK {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to ARD_D12 [SPI1_MISO] + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to ARD_D11 [SPI1_MOSI] + {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to ARD_D3 [INT_EXT10] + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to ARD_D6 [ADC1_IN6] + {PE_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to OQUADSPI_BK1_IO0 [MX25R6435F_IO0] + {PE_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to QUADSPI_BK1_IO1 [MX25R6435F_IO1] + {PE_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to QUAD_SPI_BK1_IO2 [MX25R6435F_IO2] + {PE_15, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to QUAD_SPI_BK1_IO3 [MX25R6435F_IO3] + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK // Connected to INTERNAL_I2C2_SCL [VL53L0X_SCL] + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK // Connected to QUADSPI_CLK [MX25R6435F_SCLK] + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_NCS // Connected to INTERNAL_I2C2_SDA [VL53L0X_SDA] + {PE_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_NCS // Connected to QUADSPI_NCS [MX25R6435F_SCLK] + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h index 6bc541ec78..7b69f7ea21 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h @@ -240,6 +240,14 @@ typedef enum { SPI_SCK = D13, SPI_CS = D10, PWM_OUT = D9, +#ifdef DEVICE_QSPI + QSPI_PIN_IO0 = PE_12, + QSPI_PIN_IO1 = PE_13, + QSPI_PIN_IO2 = PE_14, + QSPI_PIN_IO3 = PE_15, + QSPI_PIN_SCK = PE_10, + QSPI_PIN_CSN = PE_11, +#endif /**** USB pins ****/ USB_OTG_FS_DM = PA_11, diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/objects.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/objects.h index e68c4eb619..61c29a5fba 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/objects.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/objects.h @@ -58,6 +58,16 @@ struct trng_s { RNG_HandleTypeDef handle; }; +struct qspi_s { + QSPI_HandleTypeDef handle; + PinName io0; + PinName io1; + PinName io2; + PinName io3; + PinName sclk; + PinName ssel; +}; + #include "common_objects.h" #ifdef __cplusplus diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralNames.h index bc8f43ffa8..553aab47cf 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralNames.h @@ -83,6 +83,10 @@ typedef enum { CAN_1 = (int)CAN1_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_R_BASE, +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralPins.c index 1207a19095..58bb3cbe88 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_DISCO_L476VG/PeripheralPins.c @@ -340,3 +340,29 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PD_1, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to MEMS_SCK [L3GD20_SCL/SPC] {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to SEG23 [GH08172T_SEG23] + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to SEG0 [GH08172T_SEG0] + {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to SEG21 [GH08172T_SEG21] + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to SEG2 [GH08172T_SEG2] + {PE_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to QSPI_D0 [N25Q128A13EF840E_DQ0] + {PE_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to QSPI_D1 [N25Q128A13EF840E_DQ1] + {PE_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to QSPI_D2 [N25Q128A13EF840E_DQ2] + {PE_15, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to QSPI_D3 [N25Q128A13EF840E_DQ3] + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK // Connected to MFX_I2C_SLC [MFX_V2_I2C_SCL] + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK // Connected to QSPI_CLK [N25Q128A13EF840E_C] + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_NCS // Connected to MFX_I2C_SDA [MFX_V2_I2C_SDA] + {PE_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_NCS // Connected to QSPI_CS [N25Q128A13EF840E_S\#] + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PeripheralNames.h index bc8f43ffa8..2300627c5b 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PeripheralNames.h @@ -83,6 +83,10 @@ typedef enum { CAN_1 = (int)CAN1_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_BASE +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PeripheralPins.c index 008265a2ac..76ec6e2d10 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PeripheralPins.c @@ -305,3 +305,23 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PB_9, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 + {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_NCS + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/objects.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/objects.h index ece5f1679f..cd0f1a783c 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/objects.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/objects.h @@ -58,6 +58,16 @@ struct trng_s { RNG_HandleTypeDef handle; }; +struct qspi_s { + QSPI_HandleTypeDef handle; + PinName io0; + PinName io1; + PinName io2; + PinName io3; + PinName sclk; + PinName ssel; +}; + #include "common_objects.h" #ifdef __cplusplus diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_NUCLEO_L486RG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_NUCLEO_L486RG/PeripheralNames.h index bc8f43ffa8..2300627c5b 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_NUCLEO_L486RG/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_NUCLEO_L486RG/PeripheralNames.h @@ -83,6 +83,10 @@ typedef enum { CAN_1 = (int)CAN1_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_BASE +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_NUCLEO_L486RG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_NUCLEO_L486RG/PeripheralPins.c index 008265a2ac..76ec6e2d10 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_NUCLEO_L486RG/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_NUCLEO_L486RG/PeripheralPins.c @@ -305,3 +305,23 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PB_9, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 + {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_NCS + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_DISCO_L496AG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_DISCO_L496AG/PeripheralPins.c index a8254ebd4d..6b99293215 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_DISCO_L496AG/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_DISCO_L496AG/PeripheralPins.c @@ -421,3 +421,49 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PH_13, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to ARD_D9 {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { +// {PA_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to STDIO_UART_TX + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to QSPI_BK1_IO3 [MX25R6435FM2IL0_SIO3] + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to QSPI_BK1_IO2 [MX25R6435FM2IL0_SIO2] + {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to QSPI_BK1_IO1 [MX25R6435FM2IL0_SIO1] + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to QSPI_BK1_IO0 [MX25R6435FM2IL0_SIO0] + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_BK1_NCS [MX25R6435FM2IL0_CS] + {PC_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO0 // Connected to ADCx_IN2 + {PC_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO1 // Connected to DF_CKOUT + {PC_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO2 // Connected to ARD_A2 + {PC_4, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO3 // Connected to ARD_A0 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_QUADSPI)}, // QUADSPI_BK2_NCS // Connected to uSD_D3 + {PD_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_NCS + {PD_4, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO0 // Connected to OE [OE_IS66WV51216EBLL] + {PD_5, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO1 // Connected to WE [WE_IS66WV51216EBLL] +// {PD_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_QUADSPI)}, // QUADSPI_BK2_IO1 // Connected to STDIO_UART_RX +// {PD_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO2 // Connected to STDIO_UART_RX + {PD_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO3 // Connected to LCD_NE + {PE_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to D8 [D8_IS66WV51216EBLL] + {PE_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 // Connected to D9 [D9_IS66WV51216EBLL] + {PE_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 // Connected to D10 [D10_IS66WV51216EBLL] + {PE_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 // Connected to D11 [D11_IS66WV51216EBLL] + {PE_15, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 // Connected to D12 [D12_IS66WV51216EBLL] + {PH_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_QUADSPI)}, // QUADSPI_BK2_IO0 // Connected to STMOD_INT + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PA_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK // Connected to QSPI_CLK [MX25R6435FM2IL0_SCLK] + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK // Connected to SAI1_SCK_A + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK // Connected to D7 [D7_IS66WV51216EBLL] + {PF_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_QUADSPI)}, // QUADSPI_CLK // Connected to ARD_A3 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { +// {PA_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to STDIO_UART_TX + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to QSPI_BK1_NCS [MX25R6435FM2IL0_CS] + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_QUADSPI)}, // QUADSPI_BK2_NCS // Connected to uSD_D3 + {PD_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_NCS + {PE_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Connected to D8 [D8_IS66WV51216EBLL] + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_NUCLEO_L496ZG/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_NUCLEO_L496ZG/PeripheralNames.h index b3a010be10..73046c23d4 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_NUCLEO_L496ZG/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_NUCLEO_L496ZG/PeripheralNames.h @@ -85,6 +85,10 @@ typedef enum { CAN_2 = (int)CAN2_BASE } CANName; +typedef enum { + QSPI_1 = (int)QSPI_BASE +} QSPIName; + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_NUCLEO_L496ZG/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_NUCLEO_L496ZG/PeripheralPins.c index c1d0424246..0c36de6fe9 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_NUCLEO_L496ZG/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L496xG/TARGET_NUCLEO_L496ZG/PeripheralPins.c @@ -409,3 +409,52 @@ MBED_WEAK const PinMap PinMap_CAN_TD[] = { {PD_1, CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, {NC, NC, 0} }; + +//*** QUADSPI *** + +MBED_WEAK const PinMap PinMap_QSPI_DATA[] = { + {PA_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {PA_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 + {PA_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 + {PB_0, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {PB_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Only STM32L496ZG, not STM32L496ZG-P + {PC_1, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO0 + {PC_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO1 + {PC_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO2 + {PC_4, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO3 + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_QUADSPI)}, // QUADSPI_BK2_NCS + {PD_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_NCS + {PD_4, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO0 + {PD_5, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO1 + {PD_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_QUADSPI)}, // QUADSPI_BK2_IO1 + {PD_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO2 + {PD_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_IO3 + {PE_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {PE_12, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {PE_13, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {PE_14, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 + {PE_15, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 + {PF_6, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3 + {PF_7, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2 + {PF_8, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0 + {PF_9, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1 + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = { + {PA_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK + {PB_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK + {PE_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK + {PF_10, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_QUADSPI)}, // QUADSPI_CLK + {NC, NC, 0} +}; + +MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = { + {PA_2, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {PB_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS // Only STM32L496ZG, not STM32L496ZG-P + {PC_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_QUADSPI)}, // QUADSPI_BK2_NCS + {PD_3, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK2_NCS + {PE_11, QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS + {NC, NC, 0} +}; diff --git a/targets/TARGET_STM/qspi_api.c b/targets/TARGET_STM/qspi_api.c new file mode 100644 index 0000000000..da8570c026 --- /dev/null +++ b/targets/TARGET_STM/qspi_api.c @@ -0,0 +1,321 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017, 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" + +/* Max amount of flash size is 4Gbytes */ +/* hence 2^(31+1), then FLASH_SIZE_DEFAULT = 1<<31 */ +#define QSPI_FLASH_SIZE_DEFAULT 0x80000000 + +void qspi_prepare_command(const qspi_command_t *command, QSPI_CommandTypeDef *st_command) +{ + // TODO: shift these around to get more dynamic mapping + switch (command->instruction.bus_width) { + case QSPI_CFG_BUS_SINGLE: + st_command->InstructionMode = QSPI_INSTRUCTION_1_LINE; + break; + case QSPI_CFG_BUS_DUAL: + st_command->InstructionMode = QSPI_INSTRUCTION_2_LINES; + break; + case QSPI_CFG_BUS_QUAD: + st_command->InstructionMode = QSPI_INSTRUCTION_4_LINES; + break; + default: + st_command->InstructionMode = QSPI_INSTRUCTION_NONE; + break; + } + + st_command->Instruction = command->instruction.value; + st_command->DummyCycles = command->dummy_count, + // these are target specific settings, use default values + st_command->SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + st_command->DdrMode = QSPI_DDR_MODE_DISABLE; + st_command->DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + + switch (command->address.bus_width) { + case QSPI_CFG_BUS_SINGLE: + st_command->AddressMode = QSPI_ADDRESS_1_LINE; + break; + case QSPI_CFG_BUS_DUAL: + st_command->AddressMode = QSPI_ADDRESS_2_LINES; + break; + case QSPI_CFG_BUS_QUAD: + st_command->AddressMode = QSPI_ADDRESS_4_LINES; + break; + default: + st_command->AddressMode = QSPI_ADDRESS_NONE; + break; + } + + if (command->address.disabled == true) { + st_command->AddressMode = QSPI_ADDRESS_NONE; + st_command->AddressSize = 0; + } else { + st_command->Address = command->address.value; + /* command->address.size needs to be shifted by QUADSPI_CCR_ADSIZE_Pos */ + st_command->AddressSize = (command->address.size << QUADSPI_CCR_ADSIZE_Pos) & QUADSPI_CCR_ADSIZE_Msk; + } + + switch (command->alt.bus_width) { + case QSPI_CFG_BUS_SINGLE: + st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_1_LINE; + break; + case QSPI_CFG_BUS_DUAL: + st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_2_LINES; + break; + case QSPI_CFG_BUS_QUAD: + st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; + break; + default: + st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + break; + } + + if (command->alt.disabled == true) { + st_command->AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + st_command->AlternateBytesSize = 0; + } else { + st_command->AlternateBytes = command->alt.value; + /* command->AlternateBytesSize needs to be shifted by QUADSPI_CCR_ABSIZE_Pos */ + st_command->AlternateBytesSize = (command->alt.size << QUADSPI_CCR_ABSIZE_Pos) & QUADSPI_CCR_ABSIZE_Msk; + st_command->AlternateBytesSize = command->alt.size; + } + + switch (command->data.bus_width) { + case QSPI_CFG_BUS_SINGLE: + st_command->DataMode = QSPI_DATA_1_LINE; + break; + case QSPI_CFG_BUS_DUAL: + st_command->DataMode = QSPI_DATA_2_LINES; + break; + case QSPI_CFG_BUS_QUAD: + st_command->DataMode = QSPI_DATA_4_LINES; + break; + default: + st_command->DataMode = QSPI_DATA_NONE; + break; + } + + st_command->NbData = 0; +} + + +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) +{ + // Enable interface clock for QSPI + __HAL_RCC_QSPI_CLK_ENABLE(); + + // Reset QSPI + __HAL_RCC_QSPI_FORCE_RESET(); + __HAL_RCC_QSPI_RELEASE_RESET(); + + // Reset handle internal state + obj->handle.State = HAL_QSPI_STATE_RESET; + obj->handle.Lock = HAL_UNLOCKED; + + // Set default QSPI handle values + obj->handle.Init.ClockPrescaler = 1; + obj->handle.Init.FifoThreshold = 1; + obj->handle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; + obj->handle.Init.FlashSize = POSITION_VAL(QSPI_FLASH_SIZE_DEFAULT) - 1; + obj->handle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_5_CYCLE; + obj->handle.Init.ClockMode = QSPI_CLOCK_MODE_0; +#ifdef QSPI_DUALFLASH_ENABLE + obj->handle.Init.FlashID = QSPI_FLASH_ID_1; + obj->handle.Init.DualFlash = QSPI_DUALFLASH_DISABLE; +#endif + + obj->handle.Init.ClockMode = mode == 0 ? QSPI_CLOCK_MODE_0 : QSPI_CLOCK_MODE_3; + + QSPIName qspiio0name = (QSPIName)pinmap_peripheral(io0, PinMap_QSPI_DATA); + QSPIName qspiio1name = (QSPIName)pinmap_peripheral(io1, PinMap_QSPI_DATA); + QSPIName qspiio2name = (QSPIName)pinmap_peripheral(io2, PinMap_QSPI_DATA); + QSPIName qspiio3name = (QSPIName)pinmap_peripheral(io3, PinMap_QSPI_DATA); + QSPIName qspiclkname = (QSPIName)pinmap_peripheral(sclk, PinMap_QSPI_SCLK); + QSPIName qspisselname = (QSPIName)pinmap_peripheral(ssel, PinMap_QSPI_SSEL); + + QSPIName qspi_data_first = (QSPIName)pinmap_merge(qspiio0name, qspiio1name); + QSPIName qspi_data_second = (QSPIName)pinmap_merge(qspiio2name, qspiio3name); + QSPIName qspi_data_third = (QSPIName)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; + } + + // tested all combinations, take first + obj->handle.Instance = (QUADSPI_TypeDef *)qspi_data_first; + + // pinmap for pins (enable clock) + obj->io0 = io0; + pinmap_pinout(io0, PinMap_QSPI_DATA); + obj->io1 = io1; + pinmap_pinout(io1, PinMap_QSPI_DATA); + obj->io2 = io2; + pinmap_pinout(io2, PinMap_QSPI_DATA); + obj->io3 = io3; + pinmap_pinout(io3, PinMap_QSPI_DATA); + + obj->sclk = sclk; + pinmap_pinout(sclk, PinMap_QSPI_SCLK); + obj->ssel = ssel; + pinmap_pinout(ssel, PinMap_QSPI_SSEL); + + if (HAL_QSPI_Init(&obj->handle) != HAL_OK) { + return QSPI_STATUS_ERROR; + } + qspi_frequency(obj, hz); + return QSPI_STATUS_OK; +} + +qspi_status_t qspi_free(qspi_t *obj) +{ + if(HAL_QSPI_DeInit(&obj->handle) != HAL_OK) { + return QSPI_STATUS_ERROR; + } + + // Reset QSPI + __HAL_RCC_QSPI_FORCE_RESET(); + __HAL_RCC_QSPI_RELEASE_RESET(); + + // Disable interface clock for QSPI + __HAL_RCC_QSPI_CLK_DISABLE(); + + // Configure GPIOs + pin_function(obj->io0, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + pin_function(obj->io1, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + pin_function(obj->io2, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + pin_function(obj->io3, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + pin_function(obj->sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + pin_function(obj->ssel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + + (void)(obj); + return QSPI_STATUS_OK; +} + +qspi_status_t qspi_frequency(qspi_t *obj, int hz) +{ + qspi_status_t status = QSPI_STATUS_OK; + + // HCLK drives QSPI + int div = HAL_RCC_GetHCLKFreq() / hz; + if (div > 256 || div < 1) { + status = QSPI_STATUS_INVALID_PARAMETER; + return status; + } + + obj->handle.Init.ClockPrescaler = div - 1; + + if (HAL_QSPI_Init(&obj->handle) != HAL_OK) { + status = QSPI_STATUS_ERROR; + } + return status; +} + +qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length) +{ + QSPI_CommandTypeDef st_command; + qspi_prepare_command(command, &st_command); + + st_command.NbData = *length; + qspi_status_t status = QSPI_STATUS_OK; + + if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + status = QSPI_STATUS_ERROR; + return status; + } + + if (HAL_QSPI_Transmit(&obj->handle, (uint8_t *)data, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + status = QSPI_STATUS_ERROR; + } + + return status; +} + +qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t *length) +{ + QSPI_CommandTypeDef st_command; + qspi_prepare_command(command, &st_command); + + st_command.NbData = *length; + qspi_status_t status = QSPI_STATUS_OK; + + if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + status = QSPI_STATUS_ERROR; + return status; + } + + if (HAL_QSPI_Receive(&obj->handle, data, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + status = QSPI_STATUS_ERROR; + } + + 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 + QSPI_CommandTypeDef st_command; + qspi_prepare_command(command, &st_command); + + st_command.NbData = 1; + st_command.DataMode = QSPI_DATA_NONE; /* Instruction only */ + if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + status = QSPI_STATUS_ERROR; + return status; + } + } else { + // often just read a register, check if we need to transmit anything prior reading + if (tx_data != NULL && tx_size) { + size_t tx_length = tx_size; + status = qspi_write(obj, command, tx_data, &tx_length); + if (status != QSPI_STATUS_OK) { + return status; + } + } + + if (rx_data != NULL && rx_size) { + size_t rx_length = rx_size; + status = qspi_read(obj, command, rx_data, &rx_length); + } + } + return status; +} + +#endif + +/** @}*/ diff --git a/targets/targets.json b/targets/targets.json index 85b6623557..aee085e1b1 100755 --- a/targets/targets.json +++ b/targets/targets.json @@ -1260,7 +1260,7 @@ }, "detect_code": ["0743"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH", "QSPI"], "release_versions": ["2", "5"], "device_name": "STM32F413ZH" }, @@ -1987,7 +1987,7 @@ }, "detect_code": ["0788"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH", "QSPI"], "release_versions": ["2", "5"], "device_name": "STM32F469NI" }, @@ -2081,7 +2081,7 @@ }, "detect_code": ["0815"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "EMAC", "SERIAL_ASYNCH", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "EMAC", "SERIAL_ASYNCH", "TRNG", "FLASH", "QSPI"], "release_versions": ["2", "5"], "device_name": "STM32F746NG", "overrides": { @@ -2145,7 +2145,7 @@ "supported_form_factors": ["ARDUINO"], "detect_code": ["0764"], "macros_add": ["USBHOST_OTHER", "TWO_RAM_REGIONS"], - "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH", "QSPI"], "release_versions": ["2", "5"], "device_name": "STM32L475VG", "bootloader_supported": true @@ -2172,7 +2172,7 @@ }, "detect_code": ["0820"], "macros_add": ["USBHOST_OTHER", "TWO_RAM_REGIONS"], - "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH", "QSPI"], "release_versions": ["2", "5"], "device_name": "STM32L476VG", "bootloader_supported": true @@ -3978,7 +3978,8 @@ "SPI_ASYNCH", "STCLK_OFF_DURING_SLEEP", "TRNG", - "USTICKER" + "USTICKER", + "QSPI" ], "extra_labels": [ "NORDIC", diff --git a/tools/targets/STM32_gen_PeripheralPins.py b/tools/targets/STM32_gen_PeripheralPins.py index 6ec8a0b0d2..5fddb018d3 100644 --- a/tools/targets/STM32_gen_PeripheralPins.py +++ b/tools/targets/STM32_gen_PeripheralPins.py @@ -26,10 +26,10 @@ import textwrap from xml.dom.minidom import parse, Node from argparse import RawTextHelpFormatter -GENPINMAP_VERSION = "1.2" +GENPINMAP_VERSION = "1.3" ADD_DEVICE_IFDEF = 0 -ADD_QSPI_FEATURE = 0 +ADD_QSPI_FEATURE = 1 mcu_file="" mcu_list = [] #'name' @@ -779,7 +779,6 @@ def print_can(l): out_c_file.write( "#endif\n" ) def print_qspi(l): - prev_s = '' for p in l: result = get_gpio_af_num(p[1], p[2]) if result != 'NOTFOUND': @@ -789,21 +788,12 @@ def print_qspi(l): CommentedLine = "//" if "RCC_OSC" in PinLabel[p[1]]: CommentedLine = "//" - s1 = "%-17s" % (CommentedLine + " {" + p[0] + ',') + s1 = "%-16s" % (CommentedLine + " {" + p[0] + ',') # p[2] : QUADSPI_BK1_IO3 / QUADSPI_CLK / QUADSPI_NCS - instance = p[2].split('_')[1].replace("BK", "") - instance = instance.replace("CLK", "1") - instance = instance.replace("NCS", "1") - s1 += "%-7s" % ('QSPI_' + instance + ',') + s1 += "%-8s" % ('QSPI_1,') + result = result.replace("GPIO_AF10_OTG_FS", "GPIO_AF10_QSPI") s1 += 'STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, ' + result +')},' - #check duplicated lines, only signal differs - if (prev_s == s1): - s1 = '|' + p[2] - else: - if len(prev_s)>0: - out_c_file.write('\n') - prev_s = s1 - s1 += ' // ' + p[2] + s1 += ' // ' + p[2] if p[1] in PinLabel.keys(): s1 += ' // Connected to ' + PinLabel[p[1]] s1 += '\n' @@ -980,6 +970,7 @@ def parse_BoardFile(fileName): PinLabel[EachPin] = PinData[EachPin]["GPIO_Label"] if "STLK_RX" in PinLabel[EachPin] or "STLK_TX" in PinLabel[EachPin]: + # Patch waiting for CubeMX correction if "RX" in PinData[EachPin]["Signal"]: PinLabel[EachPin] = "STDIO_UART_RX" else: @@ -1001,6 +992,7 @@ def parse_BoardFile(fileName): elif "USART2_TX" in PinLabel[EachPin]: PinLabel[EachPin] = "STDIO_UART_TX" elif "STLINK_RX" in PinLabel[EachPin] or "STLINK_TX" in PinLabel[EachPin]: + # Patch waiting for CubeMX correction if "RX" in PinData[EachPin]["Signal"]: PinLabel[EachPin] = "STDIO_UART_RX" else: