diff --git a/src/shared/drivers/qspi-flash/qspi-flash.cpp b/src/shared/drivers/qspi-flash/qspi-flash.cpp index 040abbd72f04432f080b95367e929e0d1fcd3ccb..3978d08434b8efffcfaabfc8a82f7d2c07855fa5 100644 --- a/src/shared/drivers/qspi-flash/qspi-flash.cpp +++ b/src/shared/drivers/qspi-flash/qspi-flash.cpp @@ -25,11 +25,11 @@ using namespace miosix; using namespace Boardcore; using namespace FlashMemory; -void qspiFlash::enable() { Qspi->CR |= QUADSPI_CR_EN; } +void QspiFlash::enable() { Qspi->CR |= QUADSPI_CR_EN; } -void qspiFlash::disable() { Qspi->CR &= ~QUADSPI_CR_EN; } +void QspiFlash::disable() { Qspi->CR &= ~QUADSPI_CR_EN; } -void qspiFlash::abortReset() +bool QspiFlash::abortReset() { // abort possible ongoing command @@ -42,7 +42,7 @@ void qspiFlash::abortReset() dt = dt + 1; if (dt > 10000) { - return; + return false; } } @@ -52,11 +52,13 @@ void qspiFlash::abortReset() // reset configuration register Qspi->CCR = 0; + return true; + // transfer flag (TCF) will reset automatically and QUADSPI FIFO is flushed // if a transaction has been aborted. } -void qspiFlash::waitBusy() +bool QspiFlash::waitBusy() { // wait till QUADSPI has completed the current communication with the flash uint32_t dt = 0; // timeout @@ -65,12 +67,14 @@ void qspiFlash::waitBusy() dt = dt + 1; if (dt > 20000) { - return; + return false; } } + + return true; } -void qspiFlash::waitTransfer() +bool QspiFlash::waitTransfer() { // by setting data lenght register (DLR) you set how many bytes are expected // from memory. wait till all expected bytes have been tranferred. @@ -80,19 +84,18 @@ void qspiFlash::waitTransfer() dt = dt + 1; if (dt > 20000) { - return; + return false; } } // reset transfer complete flag (TCF) Qspi->FCR &= ~(1 << QUADSPI_FCR_CTCF_Pos); + + return true; } -qspiFlash::qspiFlash(QUADSPI_TypeDef* qspi) +QspiFlash::QspiFlash(QUADSPI_TypeDef* qspi) : Qspi{qspi} { - - Qspi = qspi; - /** * QSPI Flash pins * @@ -132,7 +135,7 @@ qspiFlash::qspiFlash(QUADSPI_TypeDef* qspi) flash_io3.speed(Speed::_100MHz); } -bool qspiFlash::test() +bool QspiFlash::test() { // check if memory has been initialised if (!initialised) @@ -143,7 +146,7 @@ bool qspiFlash::test() return readID() == DEVICE_ID; } -uint8_t qspiFlash::readStatusReg() +uint8_t QspiFlash::readStatusReg() { // status register can be read at any time and during every kind of @@ -158,20 +161,17 @@ uint8_t qspiFlash::readStatusReg() // reset peripheral abortReset(); - Qspi->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 + enable(); // Expect to receive 1 byte (flash status register) Qspi->DLR = 0; - // enable peripheral - enable(); - - // Trigger communication start by writing the instruction - Qspi->CCR |= Commands::READ_STATUS_REG << QUADSPI_CCR_INSTRUCTION_Pos; + Qspi->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 + Commands::READ_STATUS_REG; // read status reg command // wait till data trasfer is complete waitTransfer(); @@ -185,7 +185,7 @@ uint8_t qspiFlash::readStatusReg() return value; } -void qspiFlash::writeEnable() +void QspiFlash::writeEnable() { // 1 send wren command @@ -201,16 +201,11 @@ void qspiFlash::writeEnable() // reset peripheral abortReset(); - // indirect write mode, istruction on 1 wire, no data, no address, no - // alternate bytes - Qspi->CCR |= 1 << QUADSPI_CCR_IMODE_Pos; - - // enable peripheral enable(); - // start communication writing the instruction to CCR register - write - // enable command - Qspi->CCR |= Commands::WRITE_ENABLE; + // indirect write mode, istruction on 1 wire, no data, no address, no + // alternate bytes + Qspi->CCR |= 1 << QUADSPI_CCR_IMODE_Pos | Commands::WRITE_ENABLE; // wait for the communication to end waitBusy(); @@ -233,7 +228,7 @@ void qspiFlash::writeEnable() } } -void qspiFlash::init() +void QspiFlash::init() { // init peripheral clock @@ -244,6 +239,8 @@ void qspiFlash::init() // abort any operation abortReset(); + disable(); + // reset configuration registers Qspi->CR = 0; Qspi->DCR = 0; @@ -265,7 +262,7 @@ void qspiFlash::init() initialised = true; } -uint32_t qspiFlash::readID() +uint32_t QspiFlash::readID() { // check if memory has been initialised @@ -277,20 +274,17 @@ uint32_t qspiFlash::readID() // reset peripheral abortReset(); - Qspi->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 + enable(); // Expect to receive 3 bytes regarding ID of the flash Qspi->DLR = 2; - // enable peripheral - enable(); - - // Trigger communication by writing read ID command into CCR register - Qspi->CCR |= Commands::READ_ID << QUADSPI_CCR_INSTRUCTION_Pos; + Qspi->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 + Commands::READ_ID; // issue read id command // wait till communication is ended waitTransfer(); @@ -322,7 +316,7 @@ uint32_t qspiFlash::readID() } } -void qspiFlash::writeDisable() +void QspiFlash::writeDisable() { // 1 send wrid command @@ -338,15 +332,11 @@ void qspiFlash::writeDisable() // reset peripheral abortReset(); - // indirect write mode, istruction on 1 wire, no data, no address, no - // alternate bytes - Qspi->CCR |= 1 << QUADSPI_CCR_IMODE_Pos; - - // enable peripheral enable(); - // start communication writing writeDisable command to CCR register - Qspi->CCR |= Commands::WRITE_DISABLE; + // indirect write mode, istruction on 1 wire, no data, no address, no + // alternate bytes + Qspi->CCR |= 1 << QUADSPI_CCR_IMODE_Pos | Commands::WRITE_DISABLE; // wait till the communication has ended waitBusy(); @@ -369,7 +359,7 @@ void qspiFlash::writeDisable() } } -bool qspiFlash::isInProgress() +bool QspiFlash::isInProgress() { // check if memory is currently executing some operation. @@ -389,7 +379,7 @@ bool qspiFlash::isInProgress() return (statusReg & 1); } -uint8_t qspiFlash::readByte(uint32_t address) +uint8_t QspiFlash::readByte(uint32_t address) { // 1 send READ command @@ -411,20 +401,17 @@ uint8_t qspiFlash::readByte(uint32_t address) // reset peripheral abortReset(); - Qspi->CCR |= 1 << QUADSPI_CCR_FMODE_Pos | // Indirect read mode - QUADSPI_CCR_DMODE_0 | // data on a single line - QUADSPI_CCR_ADSIZE_1 | // 3-byte (24 bit) address - QUADSPI_CCR_ADMODE_0 | // address on a single line - QUADSPI_CCR_IMODE_0; // instruction on a single line - - // send read command - Qspi->CCR |= Commands::READ; + enable(); // just 1 byte of data is supposed to be transferred Qspi->DLR = 0; - // enable peripheral - enable(); + Qspi->CCR |= 1 << QUADSPI_CCR_FMODE_Pos | // Indirect read mode + QUADSPI_CCR_DMODE_0 | // data on a single line + QUADSPI_CCR_ADSIZE_1 | // 3-byte (24 bit) address + QUADSPI_CCR_ADMODE_0 | // address on a single line + QUADSPI_CCR_IMODE_0 | // instruction on a single line + Commands::READ; // issue read command // start communication by specifing the address Qspi->AR = address; @@ -441,7 +428,7 @@ uint8_t qspiFlash::readByte(uint32_t address) return value; } -bool qspiFlash::chipErase() +bool QspiFlash::chipErase() { // erase the entire flash memory chip @@ -467,14 +454,11 @@ bool qspiFlash::chipErase() // reset peripheral abortReset(); - // indirect write mode, no address, no data. all on one wire. - Qspi->CCR |= QUADSPI_CCR_IMODE_0; // istruction on one wire - - // enable peripheral enable(); - // write ERASE_CHIP command into CCR and start the communication - Qspi->CCR |= Commands::ERASE_CHIP; + // indirect write mode, no address, no data. all on one wire. + Qspi->CCR |= + QUADSPI_CCR_IMODE_0 | Commands::ERASE_CHIP; // chip erase command // wait till the communication has ended waitBusy(); @@ -503,7 +487,7 @@ bool qspiFlash::chipErase() return checkErase(); } -bool qspiFlash::sectorErase(uint32_t address) +bool QspiFlash::sectorErase(uint32_t address) { // 1 wait until the memory has finished any operation in progress @@ -527,24 +511,21 @@ bool qspiFlash::sectorErase(uint32_t address) // reset peripheral abortReset(); - // indirect write mode, 3-byte address , no data. all on one wire. - Qspi->CCR |= QUADSPI_CCR_IMODE_0 | // istruction on one wire - QUADSPI_CCR_ADSIZE_1 | // 3-byte address - QUADSPI_CCR_ADMODE_0; // address on a single line - - // enable peripheral enable(); - // add sector erase command to CCR register - Qspi->CCR |= Commands::SECTOR_ERASE; + // indirect write mode, 3-byte address , no data. all on one wire. + Qspi->CCR |= QUADSPI_CCR_IMODE_0 | // istruction on one wire + QUADSPI_CCR_ADSIZE_1 | // 3-byte address + QUADSPI_CCR_ADMODE_0 | // address on a single line + Commands::SECTOR_ERASE; // sector erase command - // start communication by writing the address in Qspi->AR + // start communication by specifying the address Qspi->AR = address; // wait for the transaction to end waitBusy(); - // disable data writing + // disable peripheral disable(); // wait till current erase operation has ended @@ -567,7 +548,7 @@ bool qspiFlash::sectorErase(uint32_t address) return checkErase(); } -bool qspiFlash::block32Erase(uint32_t address) +bool QspiFlash::block32Erase(uint32_t address) { // erase a 32K block of data, any address of the block is valid @@ -594,16 +575,13 @@ bool qspiFlash::block32Erase(uint32_t address) // reset peripheral abortReset(); - // indirect write mode, 3-byte address, no data. all on one wire. - Qspi->CCR |= QUADSPI_CCR_IMODE_0 | // istruction on one wire - QUADSPI_CCR_ADSIZE_1 | // 3-byte address - QUADSPI_CCR_ADMODE_0; // address on a single line - - // enable peripheral enable(); - // add block_32_erase command to CCR - Qspi->CCR |= Commands::BLOCK_32_ERASE; + // indirect write mode, 3-byte address, no data. all on one wire. + Qspi->CCR |= QUADSPI_CCR_IMODE_0 | // istruction on one wire + QUADSPI_CCR_ADSIZE_1 | // 3-byte address + QUADSPI_CCR_ADMODE_0 | // address on a single line + Commands::BLOCK_32_ERASE; // block 32 erase command // start communication by writing the address in Qspi->AR Qspi->AR = address; @@ -634,7 +612,7 @@ bool qspiFlash::block32Erase(uint32_t address) return checkErase(); } -bool qspiFlash::block64Erase(uint32_t address) +bool QspiFlash::block64Erase(uint32_t address) { // erase a 64K block of data, any address of the block is valid @@ -659,16 +637,13 @@ bool qspiFlash::block64Erase(uint32_t address) // reset peripheral abortReset(); - // indirect write mode, 3-byte address, no data. all on one wire. - Qspi->CCR |= QUADSPI_CCR_IMODE_0 | // istruction on one wire - QUADSPI_CCR_ADSIZE_1 | // 3-byte address - QUADSPI_CCR_ADMODE_0; // address on a single line - - // enable peripheral enable(); - // add BLOCK_64_ERASE command to CCR - Qspi->CCR |= Commands::BLOCK_64_ERASE; + // indirect write mode, 3-byte address, no data. all on one wire. + Qspi->CCR |= QUADSPI_CCR_IMODE_0 | // istruction on one wire + QUADSPI_CCR_ADSIZE_1 | // 3-byte address + QUADSPI_CCR_ADMODE_0 | // address on a single line + Commands::BLOCK_64_ERASE; // block erase command // start communication by writing the address in Qspi->AR Qspi->AR = address; @@ -699,7 +674,7 @@ bool qspiFlash::block64Erase(uint32_t address) return checkErase(); } -bool qspiFlash::byteProgram(uint8_t data, uint32_t address, bool verify) +bool QspiFlash::byteProgram(uint8_t data, uint32_t address, bool verify) { // double-check data may take some extra time ! @@ -728,17 +703,14 @@ bool qspiFlash::byteProgram(uint8_t data, uint32_t address, bool verify) // reset peripheral abortReset(); - // idirect write mode - Qspi->CCR |= QUADSPI_CCR_DMODE_0 | // data on a single line - QUADSPI_CCR_ADSIZE_1 | // address size 24 bit - QUADSPI_CCR_ADMODE_0 | // address on a single line - QUADSPI_CCR_IMODE_0; // instruction on a single line - - // enable peripheral enable(); - // add PAGE_PROGRAM command to CCR - Qspi->CCR |= Commands::PAGE_PROGRAM; + // idirect write mode + Qspi->CCR |= QUADSPI_CCR_DMODE_0 | // data on a single line + QUADSPI_CCR_ADSIZE_1 | // address size 24 bit + QUADSPI_CCR_ADMODE_0 | // address on a single line + QUADSPI_CCR_IMODE_0 | // instruction on a single line + Commands::PAGE_PROGRAM; // page program command // add address Qspi->AR = address; @@ -777,7 +749,7 @@ bool qspiFlash::byteProgram(uint8_t data, uint32_t address, bool verify) return checkProgram(); } -uint8_t qspiFlash::readSecurityReg() +uint8_t QspiFlash::readSecurityReg() { // security register can be read at any time and during every kind of @@ -794,18 +766,15 @@ uint8_t qspiFlash::readSecurityReg() // reset peripheral abortReset(); - Qspi->CCR |= QUADSPI_CCR_FMODE_0 | // Indirect read mode - QUADSPI_CCR_DMODE_0 | // data on one wire - QUADSPI_CCR_IMODE_0; // instruction on one wire + enable(); // Expect to receive 1 byte (flash security register value) Qspi->DLR = 0; - // enable peripheral - enable(); - - // start communication by adding READ_SECURITY_REG command to CCR - Qspi->CCR |= Commands::READ_SECURITY_REG; + Qspi->CCR |= QUADSPI_CCR_FMODE_0 | // Indirect read mode + QUADSPI_CCR_DMODE_0 | // data on one wire + QUADSPI_CCR_IMODE_0 | // instruction on one wire + Commands::READ_SECURITY_REG; // read security reg coommand // wait till data trasfer is complete waitTransfer(); @@ -822,7 +791,7 @@ uint8_t qspiFlash::readSecurityReg() return value; } -void qspiFlash::softwareReset() +void QspiFlash::softwareReset() { // if software reset is performed at the same time of another program/erase @@ -884,7 +853,7 @@ void qspiFlash::softwareReset() Thread::sleep(1); } -bool qspiFlash::checkErase() +bool QspiFlash::checkErase() { // ATTTENTION! - this function check only if the last erase operation has @@ -903,7 +872,7 @@ bool qspiFlash::checkErase() return reg & (1 << 6) ? false : true; } -bool qspiFlash::checkProgram() +bool QspiFlash::checkProgram() { // ATTTENTION! - this function check only if the last operation has been @@ -922,7 +891,7 @@ bool qspiFlash::checkProgram() return reg & (1 << 5) ? false : true; } -bool qspiFlash::readSector(uint8_t* vector, const size_t size, +bool QspiFlash::readSector(uint8_t* vector, const size_t size, uint32_t sectorNum) { @@ -942,26 +911,79 @@ bool qspiFlash::readSector(uint8_t* vector, const size_t size, } // vector's size must be large enough for a sector - if (size < SECTOR_SIZE) + if (size < SECTOR_SIZE || vector == nullptr) { return false; } - // computing correct address of the sector - uint32_t addr = SECTOR_SIZE * sectorNum; + // compute correct starting address of the sector + uint32_t startingAddr = SECTOR_SIZE * sectorNum; + + // check if memory has been initialised + if (!initialised) + { + return false; + } + + // reset peripheral + abortReset(); + + enable(); + + // an entire sector is expected to be received + Qspi->DLR = SECTOR_SIZE - 1; + + Qspi->CCR |= 1 << QUADSPI_CCR_FMODE_Pos | // Indirect read mode + QUADSPI_CCR_DMODE_0 | // data on a single line + QUADSPI_CCR_ADSIZE_1 | // 3-byte (24 bit) address + QUADSPI_CCR_ADMODE_0 | // address on a single line + QUADSPI_CCR_IMODE_0 | // instruction on a single line + Commands::READ; // issue read command + + // start communication by specifing the address + Qspi->AR = startingAddr; - // read the sector and copy its data to vector uint32_t index = 0; - for (index = 0; index < SECTOR_SIZE; index++) + + // reset transfer complete flag bit (TCF) + Qspi->FCR |= (1 << QUADSPI_FCR_CTCF_Pos); + + // loop until all bytes expected have been received and + // there are some data bytes to read + while (!(Qspi->SR & QUADSPI_SR_TCF) || + (((Qspi->SR & QUADSPI_SR_FLEVEL) >> 8) > 0)) { - vector[index] = readByte(addr); - addr++; + // if there are some bytes available stored in the FIFO + if (((Qspi->SR & QUADSPI_SR_FLEVEL) >> 8) > 0) + { + // save the first 4 bytes of data received from flash from FIFO + uint32_t dataBytes = Qspi->DR; + + // be sure that index doesn't exceed the size of sector + if (index <= (SECTOR_SIZE - 4)) + { + // copy dataBytes (32 bit) in four single byte in vector + vector[index++] = (uint8_t)dataBytes; // first byte + vector[index++] = (uint8_t)(dataBytes >> 8); // second byte + vector[index++] = (uint8_t)(dataBytes >> 16); // third byte + vector[index++] = (uint8_t)(dataBytes >> 24); // fourth byte + } + else + { + return false; + } + } } + // reset transfer complete flag bit (TCF) + Qspi->FCR |= (1 << QUADSPI_FCR_CTCF_Pos); + + disable(); + return true; } -bool qspiFlash::pageProgram(const uint8_t* vector, const size_t size, +bool QspiFlash::pageProgram(const uint8_t* vector, const size_t size, uint32_t startAddress, bool verify) { @@ -999,17 +1021,14 @@ bool qspiFlash::pageProgram(const uint8_t* vector, const size_t size, // reset peripheral abortReset(); - // idirect write mode - Qspi->CCR |= QUADSPI_CCR_DMODE_0 | // data on a single line - QUADSPI_CCR_ADSIZE_1 | // address size 24 bit - QUADSPI_CCR_ADMODE_0 | // address on a single line - QUADSPI_CCR_IMODE_0; // instruction on a single line - - // enable peripheral enable(); - // add page program command to CCR - Qspi->CCR |= Commands::PAGE_PROGRAM; + // idirect write mode + Qspi->CCR |= QUADSPI_CCR_DMODE_0 | // data on a single line + QUADSPI_CCR_ADSIZE_1 | // address size 24 bit + QUADSPI_CCR_ADMODE_0 | // address on a single line + QUADSPI_CCR_IMODE_0 | // instruction on a single line + Commands::PAGE_PROGRAM; // page program command // set number of bytes to be transferred - 1 Qspi->DLR = size - 1; @@ -1034,7 +1053,8 @@ bool qspiFlash::pageProgram(const uint8_t* vector, const size_t size, } // add a single byte to be sent into the QSPI FIFO - ((uint8_t*)&Qspi->DR)[0] = static_cast<uint8_t>(vector[i]); + *reinterpret_cast<volatile uint8_t*>(&Qspi->DR) = + static_cast<uint8_t>(vector[i]); } // wait for the end of communication @@ -1067,7 +1087,7 @@ bool qspiFlash::pageProgram(const uint8_t* vector, const size_t size, return checkProgram(); } -bool qspiFlash::write(const uint8_t* vector, const size_t size, +bool QspiFlash::write(const uint8_t* vector, const size_t size, uint32_t sectorNum, bool verify) { diff --git a/src/shared/drivers/qspi-flash/qspi-flash.h b/src/shared/drivers/qspi-flash/qspi-flash.h index 793972089f297353ecfdc9ca20a6680562821945..c013f08a35d36848df2d016acecc3088239e9959 100644 --- a/src/shared/drivers/qspi-flash/qspi-flash.h +++ b/src/shared/drivers/qspi-flash/qspi-flash.h @@ -45,9 +45,9 @@ using namespace Boardcore; * with the desired data. * you should also be aware that erasing a memory area could result in a data * loss. for example, to store a byte of data, you should: 1 erase selected - * sector - sector_erase(uint32_t address); 2 program the byte - - * 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 + * sector - sectorErase(uint32_t address); 2 program the byte - + * byteProgram(uint8_t data, uint32_t address, bool verify); if you want to + * store a vector of data bytes, you should use write(...) 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! @@ -57,36 +57,36 @@ namespace FlashMemory { // device ID of the flash -static const uint32_t DEVICE_ID = 0xC22816; +static constexpr uint32_t DEVICE_ID = 0xC22816; -static const uint32_t PAGES_PER_SECTOR = 16; -static const uint32_t SECTORS_PER_BLOCK32 = 8; +static constexpr uint32_t PAGES_PER_SECTOR = 16; +static constexpr uint32_t SECTORS_PER_BLOCK32 = 8; -static const uint32_t BLOCK32_NUM = 128; -static const uint32_t BLOCK64_NUM = 64; -static const uint32_t SECTORS_NUM = 1024; -static const uint32_t PAGES_NUM = 16384; -static const uint32_t BYTES_NUM = 4194304; +static constexpr uint32_t BLOCK32_NUM = 128; +static constexpr uint32_t BLOCK64_NUM = 64; +static constexpr uint32_t SECTORS_NUM = 1024; +static constexpr uint32_t PAGES_NUM = 16384; +static constexpr uint32_t BYTES_NUM = 4194304; // sizes of each area in byte -static const uint32_t PAGE_SIZE = 256; -static const uint32_t SECTOR_SIZE = PAGE_SIZE * PAGES_PER_SECTOR; -static const uint32_t BLOCK32_SIZE = SECTOR_SIZE * SECTORS_PER_BLOCK32; -static const uint32_t BLOCK64_SIZE = BLOCK32_SIZE * 2; +static constexpr uint32_t PAGE_SIZE = 256; +static constexpr uint32_t SECTOR_SIZE = PAGE_SIZE * PAGES_PER_SECTOR; +static constexpr uint32_t BLOCK32_SIZE = SECTOR_SIZE * SECTORS_PER_BLOCK32; +static constexpr uint32_t BLOCK64_SIZE = BLOCK32_SIZE * 2; -// memory size in byte -static const uint32_t MEMORY_SIZE = BLOCK64_SIZE * BLOCK64_NUM; // about 4 MB +// memory size in byte (is about 4 MB) +static constexpr uint32_t MEMORY_SIZE = BLOCK64_SIZE * BLOCK64_NUM; }; // namespace FlashMemory -class qspiFlash +class QspiFlash { public: /** - * @brief QUADSPI_FLASH class constructor + * @brief QspiFlash class constructor */ - qspiFlash(QUADSPI_TypeDef* qspi); + QspiFlash(QUADSPI_TypeDef* qspi); /** * @brief Initialise QUADSPI peripheral in order to communicate with the @@ -97,7 +97,7 @@ public: /** * @brief read the unique ID of flash - * @param returns device ID + * @returns device ID */ uint32_t readID(); @@ -169,8 +169,8 @@ public: /** * @brief erase the entire memory chip. since this operation is not so - * reliable and it may take a lot of time, you should use block32_erase() - * and block64_erase() methods. + * reliable and it may take a lot of time, you should use block32Erase() + * and block64Erase() methods. * @return true/false - if the operation has been successful * @warning THIS OPERATION WILL TAKE A WHILE !! (at least 1 min) */ @@ -287,16 +287,25 @@ private: // disable QUADSPI peripheral void disable(); - /* abort any ongoing operation and reset current - configuration of QUADSPI peripheral */ - void abortReset(); + /** + * @brief abort any ongoing operation and reset current configuration of + * QUADSPI peripheral + * @return true/false - if abort has been successful + */ + bool abortReset(); - // wait till the current operation on QUADSPI peripheral is ended - void waitBusy(); + /** + * @brief wait till the current operation on QUADSPI peripheral is ended + * @return true/false - if timeout expires + */ + bool waitBusy(); - // wait till all the expected bytes have been transferred by QUADSPI - // peripheral - void waitTransfer(); + /** + * @brief wait till all the expected bytes have been transferred by QUADSPI + * peripheral + * @return true/false - if timeout expires + */ + bool waitTransfer(); // 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 06e3b4eb0b3d3e1fea0470541d597efd8e3f5acb..266714ae73d47b4ed62187268da57fd3d33dcc68 100644 --- a/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp +++ b/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp @@ -27,11 +27,16 @@ * operations. */ -qspiFlash mymemory(QUADSPI); +QspiFlash mymemory(QUADSPI); + +// init all GPIO pins needed to communicate with flash memory +void initBoard(); int main() { + initBoard(); + // init qspi-flash communication mymemory.init(); @@ -48,7 +53,7 @@ int main() uint32_t i = 0; for (i = 0; i < vect_size; i++) { - vect[i] = 77; + vect[i] = i % 12; } // write vector "vect" @@ -60,17 +65,62 @@ int main() printf("write operaton succeded!\n"); - uint8_t b[6000] = {0}; - printf("read_sector: %d\n", mymemory.readSector(b, 6000, 884)); - - return 0; + uint8_t b[5000] = {0}; + uint32_t a = 0; + for (a = 0; a < 5000; a++) + { + b[a] = 55; + } + printf("read_sector: %d\n", mymemory.readSector(b, 5000, 883)); printf("array (b): \n"); - for (i = 0; i < 6000; i++) + for (i = 0; i < 5000; i++) { printf("b[%d]: %d\n", i, b[i]); } return 0; } +} + +void initBoard() +{ + + /** + * 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); } \ No newline at end of file