diff --git a/CMakeLists.txt b/CMakeLists.txt index 12d4b7b1ed96e22020a88ca66637f59b45b6f7ef..0772a8044ff94f4963e019909be41fbb2e2a8603 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,6 +178,9 @@ sbs_target(test-ada stm32f429zi_skyward_death_stack_v3) add_executable(test-compute-unit src/tests/boards/test-compute-unit.cpp) sbs_target(test-compute-unit stm32f767zi_compute_unit) +add_executable(test-qspi-flash src/tests/boards/test-qspi-flash.cpp) +sbs_target(test-qspi-flash stm32f767zi_compute_unit) + #-----------------------------------------------------------------------------# # Tests - Drivers # #-----------------------------------------------------------------------------# diff --git a/src/tests/boards/test-qspi-flash.cpp b/src/tests/boards/test-qspi-flash.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce9cb787eae203ac4c19248226514027ff4d9606 --- /dev/null +++ b/src/tests/boards/test-qspi-flash.cpp @@ -0,0 +1,127 @@ +/* Copyright (c) 2015-2017 Skyward Experimental Rocketry + * Author: Luca Erbetta + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <miosix.h> + +using namespace miosix; + +/** + * QSPI Flash pins + * + * FLASH_NSS - PB10 - AF9 - QUADSPI_BK1_NCS + * FLASH_CLK - PF10 - AF9 - QUADSPI_CLK + * FLASH_IO0 - PF8 - AF10 - QUADSPI_BK1_IO0 + * FLASH_IO1 - PF9 - AF10 - QUADSPI_BK1_IO1 + * FLASH_IO2 - PF7 - AF9 - QUADSPI_BK1_IO2 + * FLASH_IO3 - PF6 - AF9 - QUADSPI_BK1_IO3 + */ + +GpioPin flash_ncs(GPIOB_BASE, 10); +GpioPin flash_sck(GPIOF_BASE, 10); +GpioPin flash_io0(GPIOF_BASE, 8); +GpioPin flash_io1(GPIOF_BASE, 9); +GpioPin flash_io2(GPIOF_BASE, 7); +GpioPin flash_io3(GPIOF_BASE, 6); + +#include <miosix.h> + +using namespace miosix; + +int main() +{ + flash_ncs.mode(Mode::ALTERNATE); + flash_ncs.alternateFunction(9); + flash_ncs.speed(Speed::_100MHz); + flash_sck.mode(Mode::ALTERNATE); + flash_sck.alternateFunction(9); + flash_sck.speed(Speed::_100MHz); + flash_io0.mode(Mode::ALTERNATE); + flash_io0.alternateFunction(10); + flash_io0.speed(Speed::_100MHz); + flash_io1.mode(Mode::ALTERNATE); + flash_io1.alternateFunction(10); + flash_io1.speed(Speed::_100MHz); + flash_io2.mode(Mode::ALTERNATE); + flash_io2.alternateFunction(9); + flash_io2.speed(Speed::_100MHz); + flash_io3.mode(Mode::ALTERNATE); + flash_io3.alternateFunction(9); + flash_io3.speed(Speed::_100MHz); + + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOFEN; + RCC->AHB3ENR |= RCC_AHB3ENR_QSPIEN; + RCC_SYNC(); + + delayMs(2 * 1000); + printf("Starting\n"); + + QUADSPI->CR |= QUADSPI_CR_ABORT; // Abort ongoing commands + + // Wait while aborted + while (QUADSPI->CR & QUADSPI_CR_ABORT) + ; + + // Reset + QUADSPI->CR = 0; + QUADSPI->DCR = 0; + QUADSPI->CCR = 0; + + // QSPI peripheral initialization + QUADSPI->CR |= + QUADSPI_CR_SSHIFT | // Wait a full cycle to read + 3 << QUADSPI_CR_PRESCALER_Pos; // QSPI clock = 216MHz / 3 = 72MHz + // QUADSPI->DCR |= + // 21 << QUADSPI_DCR_FSIZE_Pos; // Flash size 32Mb = 4MB = 2^(21+1) + // bytes + + // Enable the peripheral + QUADSPI->CR |= QUADSPI_CR_EN; + + // Send read ID command - 0x9Fcl + { + QUADSPI->CCR |= 1 << QUADSPI_CCR_FMODE_Pos | // Indirect read mode + 1 << QUADSPI_CCR_DMODE_Pos | // Data on 1-wire + 0 << QUADSPI_CCR_ABMODE_Pos | // No alternate bytes + 0 << QUADSPI_CCR_ADMODE_Pos | // No address + 1 << QUADSPI_CCR_IMODE_Pos; // Instruction on 1-wire + + QUADSPI->DLR = 23; // Expect to receive 24 bytes + + printf("CCR: %lx\n", QUADSPI->CCR); + + // Trigger communication start by writing the instruction + QUADSPI->CCR |= 0x9F << QUADSPI_CCR_INSTRUCTION_Pos; + + // Wait for the transaction to complete, and disable the peripheral. + int count = 0; + while (QUADSPI->SR & QUADSPI_SR_BUSY) + count++; + + // Disable the peripheral + QUADSPI->CR &= ~QUADSPI_CR_EN; + + printf("Data: 0x%lx %d\n", QUADSPI->DR, count); + } + + while (true) + Thread::sleep(1000); +}