diff --git a/src/shared/drivers/qspi-flash/qspi-flash.cpp b/src/shared/drivers/qspi-flash/qspi-flash.cpp index e975e25d618052842e18cc07023dba039c4e8973..3f9fe9701be841e65513370ef00412462250994a 100644 --- a/src/shared/drivers/qspi-flash/qspi-flash.cpp +++ b/src/shared/drivers/qspi-flash/qspi-flash.cpp @@ -25,24 +25,6 @@ using namespace miosix; using namespace Boardcore; using namespace FlashMemory; -/** - * 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); - void QSPI::enable() { QUADSPI->CR |= QUADSPI_CR_EN; } void QSPI::disable() { QUADSPI->CR &= ~QUADSPI_CR_EN; } @@ -50,26 +32,6 @@ void QSPI::disable() { QUADSPI->CR &= ~QUADSPI_CR_EN; } void QSPI::init() { - // init GPIO peripheral pins - 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); - // init peripheral clock ClockUtils::enablePeripheralClock((QUADSPI_TypeDef*)QSPI_BASE); @@ -77,17 +39,8 @@ void QSPI::init() Thread::sleep(1); - // abort possible ongoing command - QUADSPI->CR |= QUADSPI_CR_ABORT; - - // Wait while aborted - while (QUADSPI->CR & QUADSPI_CR_ABORT) - { - ; - } - - // disable peripheral - QSPI::disable(); + // abort any operation + QSPI::abort_reset(); // reset configuration registers QUADSPI->CR = 0; @@ -116,9 +69,14 @@ void QSPI::abort_reset() QUADSPI->CR |= QUADSPI_CR_ABORT; // Wait while aborted + uint32_t dt = 0; // timeout while (QUADSPI->CR & QUADSPI_CR_ABORT) { - ; + dt = dt + 1; + if (dt > 10000) + { + return; + } } // to be sure that the peripheral is disabled @@ -133,10 +91,15 @@ void QSPI::abort_reset() void QSPI::waitBusy() { - // wait till QUADSPI has completed the current communication with the flash. + // wait till QUADSPI has completed the current communication with the flash + uint32_t dt = 0; // timeout while (QUADSPI->SR & (1 << QUADSPI_SR_BUSY_Pos)) { - ; + dt = dt + 1; + if (dt > 20000) + { + return; + } } } @@ -144,16 +107,61 @@ void QSPI::waitTransfer() { // by setting data lenght register (DLR) you set how many bytes are expected // from memory. wait till all expected bytes have been tranferred. + uint32_t dt = 0; // timeout while (!(QUADSPI->SR & (1 << QUADSPI_SR_TCF_Pos))) { - ; + dt = dt + 1; + if (dt > 20000) + { + return; + } } // reset transfer complete flag (TCF) QUADSPI->FCR &= ~(1 << QUADSPI_FCR_CTCF_Pos); } -qspi_flash::qspi_flash() { ; } +qspi_flash::qspi_flash() +{ + + /** + * 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); + + // init GPIO peripheral pins + 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); +} bool qspi_flash::test() { @@ -163,7 +171,7 @@ bool qspi_flash::test() return false; } - return readID() == DEVICE_ID ? true : false; + return readID() == DEVICE_ID; } uint8_t qspi_flash::read_status_reg() @@ -243,9 +251,15 @@ void qspi_flash::write_enable() // check status register until bit WEL = 1 uint8_t status = read_status_reg(); + uint8_t dt = 0; // timeout while (!(status & (1 << 1))) { Thread::sleep(1); + dt = dt + 1; + if (dt >= 5) + { + return; + } status = read_status_reg(); } } @@ -301,7 +315,7 @@ uint32_t qspi_flash::readID() QSPI::disable(); // the ID bytes order must be inverted - uint8_t lb = myID & (255U); // lowest byte + uint8_t lb = myID; // lowest byte uint8_t mb = (myID >> 8) & (255U); // middle byte uint8_t hb = (myID >> 16) & (255U); // highest byte @@ -350,9 +364,15 @@ void qspi_flash::write_disable() // check status register till bit WEL = 0 uint8_t status = read_status_reg(); + uint8_t dt = 0; // timeout while (status & (1 << 1)) { Thread::sleep(1); + dt = dt + 1; + if (dt >= 5) + { + return; + } status = read_status_reg(); } } @@ -377,22 +397,6 @@ bool qspi_flash::isInProgress() return (status_reg & 1) ? true : false; } -void qspi_flash::waitProgress() -{ - - // check if memory has been initialised - if (initialised == false) - { - return; - } - - // wait till any operation is in progress - while (isInProgress()) - { - Thread::sleep(1); - } -} - uint8_t qspi_flash::read_byte(uint32_t address) { @@ -461,9 +465,6 @@ bool qspi_flash::chip_erase() return false; } - // wait for any ongoing operation - waitProgress(); - // enable data writing write_enable(); @@ -486,7 +487,16 @@ bool qspi_flash::chip_erase() QSPI::disable(); // wait till current erase operation has ended - waitProgress(); + uint32_t dt = 0; // timeout + while (isInProgress()) + { + Thread::sleep(1); + dt = dt + 1; + if (dt >= 130000) // (2 min and 10sec) mac chip erase time = 2 min + { + return false; + } + } // disable data writing write_disable(); @@ -513,9 +523,6 @@ bool qspi_flash::sector_erase(uint32_t address) if ((address < 0) || (address > FlashMemory::MEMORY_SIZE)) return false; - // wait for any ongoing operation - waitProgress(); - // enable data writing write_enable(); @@ -543,7 +550,16 @@ bool qspi_flash::sector_erase(uint32_t address) QSPI::disable(); // wait till current erase operation has ended - waitProgress(); + uint32_t dt = 0; // timeout + while (isInProgress()) + { + Thread::sleep(1); + dt = dt + 1; + if (dt >= 260) // max sector erase cycle time = 240 ms + { + return false; + } + } // disable data writing write_disable(); @@ -571,9 +587,6 @@ bool qspi_flash::block32_erase(uint32_t address) if ((address < 0) || (address > FlashMemory::MEMORY_SIZE)) return false; - // wait till any ongiong operation has ended - waitProgress(); - // enable data writing write_enable(); @@ -600,8 +613,17 @@ bool qspi_flash::block32_erase(uint32_t address) // disable peripheral QSPI::disable(); - // wait till the current erase operation has been executed - waitProgress(); + // wait till current erase operation has ended + uint32_t dt = 0; // timeout + while (isInProgress()) + { + Thread::sleep(1); + dt = dt + 1; + if (dt >= 3000) // block_32 erase cycle max time = 1.8s + { + return false; + } + } // disable data writing write_disable(); @@ -629,9 +651,6 @@ bool qspi_flash::block64_erase(uint32_t address) if ((address < 0) || (address > FlashMemory::MEMORY_SIZE)) return false; - // wait for any ongoing operation to end - waitProgress(); - // enable data writing write_enable(); @@ -658,8 +677,17 @@ bool qspi_flash::block64_erase(uint32_t address) // didable peripheral QSPI::disable(); - // wait till the current erase operation has been completed - waitProgress(); + // wait till current erase operation has ended + uint32_t dt = 0; // timeout + while (isInProgress()) + { + Thread::sleep(1); + dt = dt + 1; + if (dt >= 4500) // erase block_64K cycle max time = 3.5s + { + return false; + } + } // disable data writing write_disable(); @@ -687,10 +715,9 @@ bool qspi_flash::byte_program(uint8_t data, uint32_t address, bool verify) // check on address range if ((address < 0) || (address > FlashMemory::MEMORY_SIZE)) + { return false; - - // wait for any operation in progress - waitProgress(); + } // enable data writing write_enable(); @@ -719,8 +746,16 @@ bool qspi_flash::byte_program(uint8_t data, uint32_t address, bool verify) // wait for the communication to end QSPI::waitBusy(); - // wait till the current program operation has ended - waitProgress(); + // wait till current program operation has ended + uint32_t dt = 0; // timeout + while (isInProgress()) + { + dt = dt + 1; + if (dt >= 5000) // max program byte cycle time = 100us + { + return false; + } + } // disable data writing write_disable(); @@ -804,8 +839,6 @@ void qspi_flash::software_reset() } // -------------------- send RSTEN command ------------------------- - // wait till any ongoing operation with the flash is ended - waitProgress(); // reset peripheral QSPI::abort_reset(); @@ -991,9 +1024,14 @@ bool qspi_flash::page_program(std::vector<uint8_t>& vector, { // if FIFO is full - wait till it has at least a byte available. + uint32_t dt = 0; // timeout while (((QUADSPI->SR & QUADSPI_SR_FLEVEL) >> 8) >= 32) { - ; + dt = dt + 1; + if (dt >= 10000) + { + return false; + } } // add a single byte to be sent into the QSPI FIFO @@ -1003,8 +1041,17 @@ bool qspi_flash::page_program(std::vector<uint8_t>& vector, // wait for the end of communication QSPI::waitBusy(); - // wait till the end of current program operation - waitProgress(); + // wait till current program operation has ended + uint32_t dt = 0; // timeout + while (isInProgress()) + { + Thread::sleep(1); + dt = dt + 1; + if (dt >= 20) // max page program cycle time = 10ms + { + return false; + } + } // if verify flag is set, double check on written data if (verify == true) diff --git a/src/shared/drivers/qspi-flash/qspi-flash.h b/src/shared/drivers/qspi-flash/qspi-flash.h index 87108b7770a586b2449dc804ea85ce762eec601a..6c996b0dd1d3908c20bc88a12b009ca6b6f8f6d0 100644 --- a/src/shared/drivers/qspi-flash/qspi-flash.h +++ b/src/shared/drivers/qspi-flash/qspi-flash.h @@ -49,6 +49,8 @@ using namespace Boardcore; * byte_program(uint8_t data, uint32_t address, bool verify); if you want to * store a vector of data bytes, you should use write_vector(...) function, this * method will take care about all erasing and programming sequences. + * IT'S ALWAYS RECOMMENDED TO CHECK ON RESULTS OF METHODS (true/false) TO BE + * SURE THAT AN ACTION HAS BEEN PROPERLY PERFORMED! */ namespace FlashMemory @@ -286,12 +288,6 @@ private: */ uint8_t read_security_reg(); - /** - * @brief wait till flash memory has done with the current operation - * (program/erase) - */ - void waitProgress(); - // flag device initialised bool initialised = false; diff --git a/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp b/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp index 15745c2c1d9f6c45620c922e83419ce1963220fa..c92f7eae5d80825737906c79822ce115ee8d7584 100644 --- a/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp +++ b/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp @@ -31,6 +31,23 @@ qspi_flash mymemory; int main() { + // solo testare i timeout + // finire di mettere timeout poi test e commit + // ATTENZIONE SUL TIMEOUT DELLA FUNZIONE WAITPROGRESS() e ritorno false + // sulle funzioni. + // testare funzioni senza utilizzo di waitPogress() e nuovi timeout, + // eliminare waitProgress() e while in page_program. controllare che non sia + // possibile chiamare funzioni con operazioni ancora in corso. + + /* + uint32_t t = 0; + while(1) { + t = t + 1; + printf("%u\n", t); + } + + return 0; + */ // init qspi-flash communication mymemory.init(); @@ -39,6 +56,9 @@ int main() if (mymemory.test()) { + // read device id + printf("\nID: %x\n", mymemory.readID()); + // create a vector of ten bytes to write on memory std::vector<uint8_t> v; v.reserve(10); @@ -47,7 +67,7 @@ int main() v.resize(v.capacity()); // make sure that size match with capacity // write vector "v" at 50th sector and double check on data - if (mymemory.write_vector(v, 50, true) == false) + if (mymemory.write_vector(v, 88, true) == false) { printf("ERROR - write operation failed !\n"); return -1; @@ -57,7 +77,7 @@ int main() std::vector<uint8_t> v2; // read 50th entire sector into the vector "v2" - if (mymemory.read_sector(v2, 50) == false) + if (mymemory.read_sector(v2, 88) == false) { printf("ERROR - read operation failed ! \n"); return -1; @@ -69,9 +89,15 @@ int main() for (a = 0; a < 10 && a < v2.size(); a++) { printf("v2[%d]: %d \n", a, v2[a]); + if (v2[a] != 99) + { + printf("ERROR - data mismatch !\n"); + return -1; + } } printf("v2 size: %d\n", v2.size()); printf("v2 capacity: %d\n", v2.capacity()); + printf("\n- flash memory is working properly !\n"); return 0; } else