diff --git a/src/shared/drivers/qspi-flash/qspi-flash.cpp b/src/shared/drivers/qspi-flash/qspi-flash.cpp index 1b23868e8721d4103f6f02a92937b003f096e93d..2f07a30ac76362f7e90010183fb950c898bac262 100644 --- a/src/shared/drivers/qspi-flash/qspi-flash.cpp +++ b/src/shared/drivers/qspi-flash/qspi-flash.cpp @@ -561,7 +561,7 @@ bool qspi_flash::sector_erase(uint32_t address) { Thread::sleep(1); dt = dt + 1; - if (dt >= 260) // max sector erase cycle time = 240 ms + if (dt >= 1000) // max sector erase cycle time = 240 ms { software_reset(); // device forced reset to default status return false; @@ -926,12 +926,12 @@ bool qspi_flash::check_program() return reg & (1 << 5) ? false : true; } -bool qspi_flash::read_sector(std::vector<uint8_t>& vector, uint32_t sector_num) +bool qspi_flash::read_sector(uint8_t* vector, const size_t size, + uint32_t sector_num) { - // read an entire sector of the flash and then copy it into a std::vector - // that will modify the vector and his elements. - // that fix size and capacity of the vector to SECTOR_SIZE. + // read an entire sector of the flash and then copy it into a vector whose + // size is equal or greater than the size of a sector. // check if memory has been initialised if (initialised == false) @@ -945,19 +945,10 @@ bool qspi_flash::read_sector(std::vector<uint8_t>& vector, uint32_t sector_num) return false; } - // reserve enough bytes to retain a sector of the flash, also - // make sure that size parameter of vector match with the capacity. - if (vector.capacity() < SECTOR_SIZE) + // vector's size must be large enough for a sector + if (size < SECTOR_SIZE) { - vector.reserve(SECTOR_SIZE); - vector.resize(vector.capacity()); - } - - // if vector capacity is larger than the size of a sector - if (vector.capacity() >= SECTOR_SIZE) - { - vector.resize(SECTOR_SIZE); - vector.shrink_to_fit(); + return false; } // computing correct address of the sector @@ -965,7 +956,7 @@ bool qspi_flash::read_sector(std::vector<uint8_t>& vector, uint32_t sector_num) // read the sector and copy its data to vector uint32_t index = 0; - for (index = 0; index < vector.capacity(); index++) + for (index = 0; index < SECTOR_SIZE; index++) { vector[index] = read_byte(addr); addr++; @@ -974,13 +965,14 @@ bool qspi_flash::read_sector(std::vector<uint8_t>& vector, uint32_t sector_num) return true; } -bool qspi_flash::page_program(std::vector<uint8_t>& vector, +bool qspi_flash::page_program(const uint8_t* vector, const size_t size, uint32_t start_address, bool verify) { - // program a vector (max size = 256 bytes) starting by a specific page - // address. WEL bit is set to zero automatically after the program - // operation. the address specified must be a starting + // program a vector (max size = 256 bytes) on flash memory starting by a + // specific page address. + // WEL bit is set to zero automatically after the program + // operation. The address specified must be a starting // address of a page !!!! // check if memory has been initialised @@ -997,12 +989,12 @@ bool qspi_flash::page_program(std::vector<uint8_t>& vector, if (start_address >= MEMORY_SIZE) return false; - // empty vector - if (vector.size() == 0) + // empty vector or null pointer + if (size == 0 || vector == nullptr) return false; // vector bigger than a page size - if (vector.size() > PAGE_SIZE) + if (size > PAGE_SIZE) return false; // enable data writing @@ -1024,14 +1016,14 @@ bool qspi_flash::page_program(std::vector<uint8_t>& vector, QUADSPI->CCR |= Commands::PAGE_PROGRAM; // set number of bytes to be transferred - 1 - QUADSPI->DLR = vector.size() - 1; + QUADSPI->DLR = size - 1; // adding starting address QUADSPI->AR = start_address; // load data vector into the QUADSPI FIFO (buffer) uint16_t i = 0; - for (i = 0; i < vector.size(); i++) + for (i = 0; i < size; i++) { // if FIFO is full - wait till it has at least a byte available. @@ -1058,7 +1050,7 @@ bool qspi_flash::page_program(std::vector<uint8_t>& vector, { Thread::sleep(1); dt = dt + 1; - if (dt >= 20) // max page program cycle time = 10ms + if (dt >= 50) // max page program cycle time = 10ms { software_reset(); // device forced reset to default status return false; @@ -1068,9 +1060,8 @@ bool qspi_flash::page_program(std::vector<uint8_t>& vector, // if verify flag is set, double check on written data if (verify == true) { - for (i = 0; i < vector.size(); i++) + for (i = 0; i < size; i++) { - if (read_byte(start_address + i) != vector[i]) return false; } @@ -1080,12 +1071,10 @@ bool qspi_flash::page_program(std::vector<uint8_t>& vector, return check_program(); } -bool qspi_flash::write_vector(std::vector<uint8_t>& vector, uint32_t sector_num, - bool verify_write) +bool qspi_flash::write_vector(const uint8_t* vector, const size_t size, + uint32_t sector_num, bool verify_write) { - // store a vector of bytes into the flash memory - // check if memory has been initialised if (initialised == false) { @@ -1093,83 +1082,91 @@ bool qspi_flash::write_vector(std::vector<uint8_t>& vector, uint32_t sector_num, } // wrong sector_num specified - if (sector_num < 0 || sector_num >= SECTORS_NUM) + if (sector_num >= SECTORS_NUM) { return false; } - // if the vector doesn't have elements - if (vector.size() == 0 || vector.capacity() == 0) + // check that vector is valid and not empty + if ((vector == nullptr) || size == 0) { return false; } // if the vector is bigger than the flash capacity - if (vector.size() > MEMORY_SIZE) + if (size > MEMORY_SIZE) + { return false; + } // if the whole vector is bigger than the rest of sectors starting by // sector_num - if (vector.size() > (SECTOR_SIZE * (SECTORS_NUM - sector_num))) + if (size > (SECTOR_SIZE * (SECTORS_NUM - sector_num))) + { return false; + } // compute starting address uint32_t const start_address = SECTOR_SIZE * sector_num; // compute number of sectors needed to store the vector, then add one more // to store the last part of vector - uint32_t sectors_needed = vector.size() / SECTOR_SIZE; - if ((vector.size() % SECTOR_SIZE) != 0) + uint32_t sectors_needed = size / SECTOR_SIZE; + if ((size % SECTOR_SIZE) != 0) + { sectors_needed += 1; + } // erase all sectors needed to store the entire vector uint32_t sector_index = 0; for (sector_index = 0; sector_index < sectors_needed; sector_index++) { if (sector_erase(SECTOR_SIZE * (sector_num + sector_index)) == false) + { return false; + } } // compute the number of pages needed to store the entire vector, then add - // one more to store the vector last part. - uint32_t pages_needed = vector.size() / PAGE_SIZE; - if ((vector.size() % PAGE_SIZE) != 0) + // one more to store the vector last part + uint32_t pages_needed = size / PAGE_SIZE; + if ((size % PAGE_SIZE) != 0) + { pages_needed += 1; + } - // create a copy vector with capacity as a page size - std::vector<uint8_t> v; - v.reserve(PAGE_SIZE); - v.resize(0); - - // for every page needed, first copy data bytes from "vector" to a copy - // vector "v" and then program the page. + // split vector in pages and then program them on flash but the last one uint32_t page = 0; - uint32_t elem = 0; - for (page = 0; page < pages_needed; page++) + for (page = 0; page < pages_needed - 1; page++) { - v.resize(0); - uint32_t start_elem = page * PAGE_SIZE; - // copying 256 bytes from "vector" to "v" - for (elem = start_elem; - (elem < start_elem + PAGE_SIZE) && (elem < vector.size()); elem++) - { - v.push_back(vector[elem]); - } - - // program the page stored into "v" on flash - if (page_program(v, start_address + (page * PAGE_SIZE), false) == false) + if (page_program(vector + (page * PAGE_SIZE), PAGE_SIZE, + start_address + (page * PAGE_SIZE), false) == false) return false; } + // program the last page, cause probably it has a different size + // than others. + /* + * a little explanation of parameters: + * 1 - make the pointer point to the start byte of last page. + * 2 - is the size of last page which store the vector final part. + * 3 - calculate the start address of last page. + */ + if (page_program( + vector + ((pages_needed - 1) * PAGE_SIZE), size % PAGE_SIZE, + start_address + ((pages_needed - 1) * PAGE_SIZE), false) == false) + { + return false; + } + // if verify_write is true: // check that the bytes written into the flash match with the ones in the // vector. if (verify_write) { - uint32_t index = 0; uint32_t addr = start_address; - for (index = 0; index < vector.size(); index++) + for (index = 0; index < size; index++) { if (read_byte(addr) != vector[index]) { diff --git a/src/shared/drivers/qspi-flash/qspi-flash.h b/src/shared/drivers/qspi-flash/qspi-flash.h index cc8afb94de21776d3a3a413029cd370679d1af0a..896e2eeae7d8f63189ce08af70823956e4517e30 100644 --- a/src/shared/drivers/qspi-flash/qspi-flash.h +++ b/src/shared/drivers/qspi-flash/qspi-flash.h @@ -138,7 +138,7 @@ public: * will be memorized on consecutive sectors of the memory, starting by * sector_num * - * @param vector std::vector to be saved in memory + * @param vector array to be saved in memory * @param sector_num number of the starting sector [0 - 1024] * @param verify_write double check on saved data flag, * true = double check enabled, @@ -151,37 +151,40 @@ public: * * @return true/false - if the whole operation has been successful. */ - bool write_vector(std::vector<uint8_t>& vector, uint32_t sector_num, - bool verify_write); + bool write_vector(const uint8_t* vector, const size_t size, + uint32_t sector_num, bool verify_write); /** - * @brief copy a whole sector (4KB) from the flash to an std::vector. - * @param vector reference of the vector which will store the sector. + * @brief copy a whole sector (4KB) from flash into a vector whose size is + * greater or equal to the size of a sector in memory. + * @param vector array which will store the sector. * @param sector_num number of the sector which has to be copied into the * vector [0 - 1024] * @return true/false - if the operation has been successful. - * @warning this function modify the vector passed! it will also fix its - * size and capacity to the size of an entire sector of the flash (4096 - * bytes). + * @warning the vector size must be enough to contain a whole sector! + * @warning This function modify the vector passed! */ - bool read_sector(std::vector<uint8_t>& vector, uint32_t sector_num); + bool read_sector(uint8_t* vector, const size_t size, uint32_t sector_num); /** - * @brief program a page by setting (256 byte) at the starting address - * specified. + * @brief program a page (256 bytes) on memory at the starting address + * specified. if vector size is smaller than a whole page size there will be + * no effects on other bytes of the page. * @param vector vector of data bytes to be programmed - its size must not * be bigger than a page size (256 byte). * @param start_address starting address of the page to be programmed. must - * be a starting address. + * be a starting address! * @param verify double check on programmed data. true = enabled, false = * disabled. * @return true/false - if the operation has been successful. * @warning start_address must be a starting address of a page! - * if vector size is smaller than a page size there will be no effects on - * other bytes of the page. + * This function is only intended to program some bytes on flash by + * resetting some bits to "0". If you want to store a page of data you'll + * need to erase the sector associated with this page and then reprogram the + * page. */ - bool page_program(std::vector<uint8_t>& vector, uint32_t start_address, - bool verify); + bool page_program(const uint8_t* vector, const size_t size, + uint32_t start_address, bool verify); /** * @brief erase the entire memory chip. since this operation is not so @@ -229,6 +232,9 @@ public: * @param verify double check on programmed byte. true = enabled, false = * disabled. * @return true/false - if the operation has been successful + * @warning This function is only intended to program some bytes on flash by + * resetting some bits to "0". If you want to store a byte of data, you'll + * need to perform an erase operation and then program the byte. */ bool byte_program(uint8_t data, uint32_t address, bool verify); diff --git a/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp b/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp index 3f60f1e674d567d822445bb67ff64a6ae9410e45..7585b5cb09f152ed0639653ad15e7e5f0db0dfb0 100644 --- a/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp +++ b/src/tests/drivers/QuadSpi-Flash/test-Qflash.cpp @@ -31,11 +31,11 @@ qspi_flash mymemory; int main() { - // aggiunti software_reset con timeout: disaccoppiano le operazioni, anche - // senza delay - permettendo alle operazioni di erase che falliscono di non - // far fallire le altre operazioni successive. chip_erase se fallisce dopo - // circa 10 sec fa fallire alcune operazioni come write_vector() e - // page_program. + + // change API from std::vector to normal arrays with no dynamic allocation. + // sector_erase() timeout values increased due to some problems + // with write_vector(). + // read_sector and write_vector tested ! // init qspi-flash communication mymemory.init(); @@ -47,50 +47,33 @@ int main() // 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); - for (uint32_t i = 0; i < v.capacity(); i++) - v.push_back(99); - v.resize(v.capacity()); // make sure that size match with capacity + // create a vector + const size_t vect_size = 5000; + uint8_t vect[vect_size] = {0}; + uint32_t i = 0; + for (i = 0; i < vect_size; i++) + { + vect[i] = 77; + } - // write vector "v" at 50th sector and double check on data - if (mymemory.write_vector(v, 88, true) == false) + // write vector "vect" + if (mymemory.write_vector(vect, vect_size, 883, true) == false) { printf("ERROR - write operation failed !\n"); return -1; } - // create a vector in which will be copied the bytes of 50th sector - std::vector<uint8_t> v2; + printf("write operaton succeded!\n"); - // read 50th entire sector into the vector "v2" - if (mymemory.read_sector(v2, 88) == false) - { - printf("ERROR - read operation failed ! \n"); - return -1; - } + uint8_t b[6000] = {0}; + printf("read_sector: %d\n", mymemory.read_sector(b, 6000, 884)); - // print first ten bytes of data in the vector "v2" - printf("\nvector v2: \n"); - uint32_t a = 0; - for (a = 0; a < 10 && a < v2.size(); a++) + printf("array (b): \n"); + for (i = 0; i < 6000; i++) { - printf("v2[%d]: %d \n", a, v2[a]); - if (v2[a] != 99) - { - printf("ERROR - data mismatch !\n"); - return -1; - } + printf("b[%d]: %d\n", i, b[i]); } - 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 - { - printf("Error - flash memory is not working properly!\n"); - return -1; - } } \ No newline at end of file