Skip to content
Snippets Groups Projects
Commit 3b61d0a1 authored by Valerio Flamminii's avatar Valerio Flamminii
Browse files

final and tested version

parent 7de13fc5
Branches
No related tags found
No related merge requests found
Pipeline #8197 failed
...@@ -64,8 +64,7 @@ foreach(OPT_BOARD ${BOARDS}) ...@@ -64,8 +64,7 @@ foreach(OPT_BOARD ${BOARDS})
${SBS_BASE}/src/shared/drivers/i2c/I2CDriver-f7.cpp ${SBS_BASE}/src/shared/drivers/i2c/I2CDriver-f7.cpp
${SBS_BASE}/src/shared/drivers/i2c/I2C.cpp ${SBS_BASE}/src/shared/drivers/i2c/I2C.cpp
${SBS_BASE}/src/shared/drivers/WIZ5500/WIZ5500.cpp ${SBS_BASE}/src/shared/drivers/WIZ5500/WIZ5500.cpp
${SBS_BASE}/src/shared/drivers/qspi-flash/qspi-flash.cpp
${SBS_BASE}/src/tests/drivers/QuadSpi-flash/qspi-flash.cpp
# Events # Events
${SBS_BASE}/src/shared/events/EventBroker.cpp ${SBS_BASE}/src/shared/events/EventBroker.cpp
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
using namespace miosix; using namespace miosix;
using namespace Boardcore; using namespace Boardcore;
/* driver for MX25R3235FM1IL0 flash memory chip /* driver of MX25R3235FM1IL0 flash memory chip
* model of flash memory on compute unit: MX25R3235FM1IL0 4MB, device ID: * model of flash memory on compute unit: MX25R3235FM1IL0 4MB, device ID:
* 0xC22816 FLASH memory space organisation: * 0xC22816 FLASH memory space organisation:
* - number of byte in the memory: 4.194.304 >> about 4 MB * - number of byte in the memory: 4.194.304 >> about 4 MB
...@@ -35,12 +35,26 @@ using namespace Boardcore; ...@@ -35,12 +35,26 @@ using namespace Boardcore;
* - "sector" of about 4 KByte - number of sector: 1.024 * - "sector" of about 4 KByte - number of sector: 1.024
* - "block32" of about 32 KByte - number of block32: 128 * - "block32" of about 32 KByte - number of block32: 128
* - "block64" of about 64 KByte - number of block64: 64 * - "block64" of about 64 KByte - number of block64: 64
*
* NOTES:
* MX25R3235FM1IL0 flash memory can perform only two types of operations:
* - "erase" = it set to '1' every bit of selected area.
* - "program" = it set to '0' only some bits of selected area, in order to
* write the data value expected. This means that in order to store some data on
* this chip, you'll need to erase the selected area and then program that area
* 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
* method will take care about all erasing and programming sequences.
*/ */
namespace FlashMemory namespace FlashMemory
{ {
// device id of the flash // device ID of the flash
static const uint32_t DEVICE_ID = 0xC22816; static const uint32_t DEVICE_ID = 0xC22816;
static const uint32_t PAGES_PER_SECTOR = 16; static const uint32_t PAGES_PER_SECTOR = 16;
...@@ -63,7 +77,7 @@ static const uint32_t MEMORY_SIZE = BLOCK64_SIZE * BLOCK64_NUM; // about 4 MB ...@@ -63,7 +77,7 @@ static const uint32_t MEMORY_SIZE = BLOCK64_SIZE * BLOCK64_NUM; // about 4 MB
}; // namespace FlashMemory }; // namespace FlashMemory
// QUADSPI peripheral utility-stuff // QUADSPI peripheral utility-methods
namespace QSPI namespace QSPI
{ {
...@@ -89,81 +103,199 @@ class qspi_flash ...@@ -89,81 +103,199 @@ class qspi_flash
{ {
public: public:
// constructor /**
* @brief QUADSPI_FLASH class constructor
*/
qspi_flash(); qspi_flash();
// init qspi peripheral which is connected to the flash /**
* @brief Initialise QUADSPI peripheral in order to communicate with the
* memory
* @warning IT MUST BE EXECUTED BEFORE ANY OTHER OPERATION WITH THE MEMORY !
*/
void init(); void init();
// read unique device ID /**
* @brief read the unique ID of flash
* @param returns device ID
*/
uint32_t readID(); uint32_t readID();
// test the communication with the device by checking on its ID /**
* @brief check if the flash is working properly by checking on its own
* device ID
* @return true/false - if the test has been successful or not
* @warning it's recommended to check if flash is working before any
* operation !
*/
bool test(); bool test();
// write a vector into a sector of the flash /**
* @brief write an entire vector on the flash, starting by a specific
* sector. if vector size exceed the size of a single sector, the vector
* will be memorized on consecutive sectors of the memory, starting by
* sector_num
*
* @param vector std::vector 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,
* false = double ckeck disabled,
* It may slow down the execution still it's a recommended option.
*
* @warning each sector needed will be erased and then reprogrammed with
* vector data bytes, it means that you might lose some data stored into the
* sectors involved in the process.
*
* @return true/false - if the whole operation has been successful.
*/
bool write_vector(std::vector<uint8_t>& vector, uint32_t sector_num, bool write_vector(std::vector<uint8_t>& vector, uint32_t sector_num,
bool verify_write); bool verify_write);
// read an std::vector starting by a specific sectro number /**
* @brief copy a whole sector (4KB) from the flash to an std::vector.
* @param vector reference of the vector 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).
*/
bool read_sector(std::vector<uint8_t>& vector, uint32_t sector_num); bool read_sector(std::vector<uint8_t>& vector, uint32_t sector_num);
// program a page into the flash memory /**
* @brief program a page by setting (256 byte) at the starting address
* specified.
* @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.
* @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.
*/
bool page_program(std::vector<uint8_t>& vector, uint32_t start_address, bool page_program(std::vector<uint8_t>& vector, uint32_t start_address,
bool verify); bool verify);
// erase the entire memory chip - THIS OPERATION WILL TAKE A WHILE!! /**
* @brief erase the entire memory chip
* @return true/false - if the operation has been successful
* @warning THIS OPERATION WILL TAKE A WHILE !! (at least 30 sec)
*/
bool chip_erase(); bool chip_erase();
// erase the sector which contains the address (24 bit) specified /**
* @brief erase a specific sector (4KB)
* @param address generic address (24 bit) of the sector address space.
* @return true/false - if the operation has been successful
*/
bool sector_erase(uint32_t address); bool sector_erase(uint32_t address);
// erase a block (32K) which contains the address (24 bit) specified /**
* @brief erase a specific block (32KB)
* @param address generic address (24 bit) of the block address space.
* @warning THIS OPERATION COULD TAKE A WHILE
* @return true/false - if the operation has been successful
*/
bool block32_erase(uint32_t address); bool block32_erase(uint32_t address);
// erase a block (32K) which contains the address (24 bit) specified /**
* @brief erase a specific block (64KB)
* @param address generic address (24 bit) of the block address space.
* @warning THIS OPERATION COULD TAKE A WHILE!
* @return true/false - if the operation has been successful
*/
bool block64_erase(uint32_t address); bool block64_erase(uint32_t address);
// read a byte at a specific address (24 bit) in memory /**
* @brief read a single byte at a specific address
* @param address byte address (24 bit), it can be any address
* @return byte value
*/
uint8_t read_byte(uint32_t address); uint8_t read_byte(uint32_t address);
// program a byte at a specific address (24 bit) in memory /**
* @brief program a single byte at a specific address
* @param data byte value
* @param address byte address (24 bit), it can be any address
* @param verify double check on programmed byte. true = enabled, false =
* disabled.
* @return true/false - if the operation has been successful
*/
bool byte_program(uint8_t data, uint32_t address, bool verify); bool byte_program(uint8_t data, uint32_t address, bool verify);
// ATTENTION it may take a while! - makes the flash return to power-on /**
// default state * @brief make the flash go back to power-on default state. altough that's
* not a "must-do" operation, it may be used when you have done with the
* memory.
* @warning THIS FUNCTION MAY TAKE A WHILE !
*/
void software_reset(); void software_reset();
// check last erase operation result /**
* @brief check if the memory is currently executing any operation like
* program/erase
* @return true/false - if there's an operation in progress or not.
*/
bool isInProgress();
private:
/**
* @brief check result of last erase operation
* @return true = success / false = fail
*/
bool check_erase(); bool check_erase();
// check last program operation result /**
* @brief check result of last program operation
* @return true = success / false = fail
*/
bool check_program(); bool check_program();
// enable writing /**
* @brief enable modifying (program/erase) data on memory
* @warning This function issue a "write enable" command to the flash. In
* order to modify any data on memory you have to issue a "write enable"
* command, also you should always issue a "write disable" command, when you
* have done modifying data.
*/
void write_enable(); void write_enable();
// read status register of the flash memory /**
uint8_t read_status_reg(); * @brief disable modifying (program/erase) data on memory
* @warning This function issue a "write disable" command to the flash. In
// disable writing * order to modify any data on memory you have to issue a "write enable"
* command, also you should always issue a "write disable" command, when you
* have done modifying data.
*/
void write_disable(); void write_disable();
// read security register of the flash /**
* @brief read memory's status register
* @return status register value (8 bit)
*/
uint8_t read_status_reg();
/**
* @brief read memory's security register
* @return security register value (8 bit)
*/
uint8_t read_security_reg(); uint8_t read_security_reg();
private: /**
// wait till flash has executed the current operation * @brief wait till flash memory has done with the current operation
* (program/erase)
*/
void waitProgress(); void waitProgress();
// check if flash is executing some operation (program/erase or write // flag device initialised
// registers)
bool isInProgress();
// true = quadspi initialised - false = not initialised yet
bool initialised = false; bool initialised = false;
// most important flash memory commands // foundamental flash memory commands
enum Commands enum Commands
{ {
// read unique ID of the memory // read unique ID of the memory
......
...@@ -19,99 +19,64 @@ ...@@ -19,99 +19,64 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "qspi-flash.h" #include "drivers/qspi-flash/qspi-flash.h"
/*
* This is a simple test of "MX25R3235FM1IL0" flash memory chip on compute unit.
* it will ensure that flash is working by performing "write" and "read" vector
* operations.
*/
qspi_flash mymemory; qspi_flash mymemory;
int main() int main()
{ {
// init qspi-flash communication
mymemory.init(); mymemory.init();
// test if flash is working
if (mymemory.test())
{
// create a vector of ten bytes to write on memory
std::vector<uint8_t> v; std::vector<uint8_t> v;
v.reserve(20000); v.reserve(10);
for (uint32_t i = 0; i < v.capacity(); i++) for (uint32_t i = 0; i < v.capacity(); i++)
v.push_back(5); v.push_back(99);
v.resize(v.capacity()); v.resize(v.capacity()); // make sure that size match with capacity
/* // write vector "v" at 50th sector and double check on data
printf("vettore: \n"); if (mymemory.write_vector(v, 50, true) == false)
uint32_t i = 0;
for (i = 0; i < v.size(); i++)
{ {
printf("v[%d]: %d \n", i, v[i]); printf("ERROR - write operation failed !\n");
return -1;
} }
printf("vector size: %u\n", v.size());
printf("vector capacity: %d\n", v.capacity());
*/
// printf("result: %d\n", mymemory.write_vector(v, 1019, true)); // create a vector in which will be copied the bytes of 50th sector
// --------- read FUNZIONA -------------
std::vector<uint8_t> v2; std::vector<uint8_t> v2;
mymemory.read_sector(v2, 1023);
printf("\nvettore v2: \n"); // read 50th entire sector into the vector "v2"
if (mymemory.read_sector(v2, 50) == false)
{
printf("ERROR - read operation failed ! \n");
return -1;
}
// print first ten bytes of data in the vector "v2"
printf("\nvector v2: \n");
uint32_t a = 0; uint32_t a = 0;
for (a = 0; a < FlashMemory::SECTOR_SIZE; a++) for (a = 0; a < 10 && a < v2.size(); a++)
{ {
printf("v2[%d]: %d \n", a, v2[a]); printf("v2[%d]: %d \n", a, v2[a]);
} }
printf("v2 size: %d\n", v2.size()); printf("v2 size: %d\n", v2.size());
printf("v2 capacity: %d\n", v2.capacity()); printf("v2 capacity: %d\n", v2.capacity());
return 0;
// ------------- ATTENZIONE SU FUNZIONI DI LETTURA ----------------- }
// numero di bytes della flash = 2 ^ (FSIZE + 1) else
// impostare la corretta dimensione della flash è necessario al corretto {
// funzionamento delle operazioni di lettura dalla flash. tutte le printf("Error - flash memory is not working properly!\n");
// operazioni di lettura della memoria a partire da un indirizzo che non può return -1;
// essere contenuto nella memoria di dimensione indicata (FSIZE) non vengono }
// eseguite dalla periferica QUADSPI. esempio: se la dimensione impostata è
// di 4 byte allora gli indirizzi accettati sono: 0-3b.
// - read_sector funziona bene.
// - program_sector funzionano bene con verify_write
// - page_program funziona beneeeeee
// - readID() funziona bene con sleep(1ms)
// - test() funziona bene
// - studiare come aggiungere quadspi mode: non vale la pena ad oggi
// - waitProgress più veloce: funziona tutto ok
// ----------- TEST ------ lettura security register
// ho modificato byte_program e read_security_reg()
// senza sleep() non ci sono dati nella FIFO. con sleep arriva sempre il
// byte data. read_security_reg() sembra leggere il registro, da provare con
// suspend commands. se non va, check con rilettura dei dati.
// assumo che la lettura del security_register sia corretta, verifico la
// riuscita delle operazioni più importanti rileggendo i dati.
// su funzioni meno importanti controllare check_operation() e controllare
// bene gli argomenti siano corretti. Nelle altre controllo con verify.
// modifico byte_program con flag verify e controllo su argomenti: FUNZIONA
// testata
// modifico tutte le erase: FUNZIONANNO testate
// modifico read_byte: FUNZIONA testata
// page_program modificata: aggiunto verify flag FUNZIONA testata.
// test finali page_program, read_sector, e program_sector FUNZIONANO
// TESTATE.
// METTERE FLAG INITIALISED
// - commentare meglio e sistemare funzioni public e private.
// - forse aggiungere controllo anti loop operation.
while (true)
Thread::sleep(1000);
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment