Access MRAM via FT4222H USB-to-QSPI bridge === ### 1. Download FT4222H Linux library and user guide [libft4222-linux-1.4.4.44.tgz](https://www.ftdichip.com/Support/SoftwareExamples/libft4222-linux-1.4.4.44.tgz) [User Guide for LibFT4222](https://www.ftdichip.com/Support/Documents/AppNotes/AN_329_User_Guide_for_LibFT4222.pdf) ### 2. Install library, compile sample code and test (source code ft4222_mram.c modified from spim.c) Install libft4222 ```bash= mkdir libft4222 tar zxvf libft4222-linux-1.4.4.44.tgz -C libft4222 cd libft4222 sudo ./install4222.sh ``` Compile ```bash= gcc ft4222_mram.c -o ft4222_mram -lft4222 -Wl,-rpath,/usr/local/lib ``` example code ```c= #define CMD_READ 0x03 #define CMD_WRITE 0x02 #define MRAM_SIZE 0x100000 #define BUF_SIZE 0x100 static int mram_qpie(FT_HANDLE ftHandle) { FT4222_STATUS ftStatus; int success = 1; uint16 sizeTransferred; uint16 bytesToTransceive; uint16 bytesTransceived; uint8 command[1] = {0x38}; uint8 response[4] = {0}; bytesToTransceive = 4; ftStatus = FT4222_SPIMaster_SingleWrite(ftHandle, command, 1, &sizeTransferred, 1); if((ftStatus!=FT4222_OK) || (sizeTransferred != 1)) { success = 0; goto exit; } printf("\nChange MRAM to QSPI mode.\n"); exit: return success; } static int qspi_rdid(FT_HANDLE ftHandle) { FT4222_STATUS ftStatus; int success = 1; uint16 bytesToTransceive; uint32 sizeOfRead; uint8 command[1] = {0x9F}; uint8 response[4] = {0}; bytesToTransceive = 4; ftStatus = FT4222_SPIMaster_MultiReadWrite(ftHandle, response, &command[0], 0, 1, bytesToTransceive, &sizeOfRead); if((ftStatus!=FT4222_OK) || (sizeOfRead != bytesToTransceive)) { success = 0; goto exit; } printf("\nQSPI RDID:\n"); hexdump(response, 4); exit: return success; } static int qspi_rdsn(FT_HANDLE ftHandle) { FT4222_STATUS ftStatus; int success = 1; uint16 bytesToTransceive; uint32 sizeOfRead; uint8 command[1] = {0xC3}; uint8 response[8] = {0}; bytesToTransceive = 8; ftStatus = FT4222_SPIMaster_MultiReadWrite(ftHandle, response, &command[0], 0, 1, bytesToTransceive, &sizeOfRead); if((ftStatus!=FT4222_OK) || (sizeOfRead != bytesToTransceive)) { success = 0; goto exit; } printf("\nQSPI RDSN:\n"); hexdump(response, 8); exit: return success; } static int qspi_ruid(FT_HANDLE ftHandle) { FT4222_STATUS ftStatus; int success = 1; uint16 bytesToTransceive; uint32 sizeOfRead; uint8 command[1] = {0x4C}; uint8 response[8] = {0}; bytesToTransceive = 8; ftStatus = FT4222_SPIMaster_MultiReadWrite(ftHandle, response, &command[0], 0, 1, bytesToTransceive, &sizeOfRead); if((ftStatus!=FT4222_OK) || (sizeOfRead != bytesToTransceive)) { success = 0; goto exit; } printf("\nQSPI RUID:\n"); hexdump(response, 8); exit: return success; } #define BYTES_TO_WRITE (1024 * 1) static int mram_qspi_write(FT_HANDLE ftHandle, int addr, char *buf, int len) { FT4222_STATUS ftStatus; int success = 1; uint32 sizeOfRead; uint16 bytesToTransceive; uint16 bytesTransceived; uint8 command[BYTES_TO_WRITE + 4] = {0}; uint8 response[BYTES_TO_WRITE] = {0}; int i; for (i = 0; i < len; i++) { command[i + 4] = buf[i]; } command[0] = CMD_WRITE; command[1] = (addr >> 16) & 0xFF; command[2] = (addr >> 8) & 0xFF; command[3] = addr & 0xFF; bytesToTransceive = BYTES_TO_WRITE; ftStatus = FT4222_SPIMaster_MultiReadWrite(ftHandle, response, &command[0], 0, len + 4, 0, &sizeOfRead); if((ftStatus!=FT4222_OK)) { success = 0; goto exit; } printf("\nwrite %d bytes\n", len); exit: return success; } static int mram_qspi_read(FT_HANDLE ftHandle, int addr, int len) { FT4222_STATUS ftStatus; int success = 1; uint32 sizeOfRead; uint16 bytesToTransceive; uint16 bytesTransceived; uint8 command[4]; uint8 response[BYTES_TO_WRITE] = {0}; command[0] = CMD_READ; command[1] = (addr >> 16) & 0xFF; command[2] = (addr >> 8) & 0xFF; command[3] = addr & 0xFF; bytesToTransceive = len; ftStatus = FT4222_SPIMaster_MultiReadWrite(ftHandle, response, &command[0], 0, 4, bytesToTransceive, &sizeOfRead); if((ftStatus!=FT4222_OK) || (sizeOfRead != bytesToTransceive)) { success = 0; goto exit; } printf("\nRead %d bytes:\n", bytesToTransceive); //hexdump(response, bytesToTransceive); hex_dump(response, bytesToTransceive, 32, "RX"); exit: return success; } ``` Change clock rate `base clock = 60MHz` ```c= typedef enum FT4222_SPIClock { CLK_NONE = 0, CLK_DIV_2, // 1/2 System Clock CLK_DIV_4, // 1/4 System Clock CLK_DIV_8, // 1/8 System Clock CLK_DIV_16, // 1/16 System Clock CLK_DIV_32, // 1/32 System Clock CLK_DIV_64, // 1/64 System Clock CLK_DIV_128, // 1/128 System Clock CLK_DIV_256, // 1/256 System Clock CLK_DIV_512, // 1/512 System Clock } FT4222_SPIClock; // Configure the FT4222 as an SPI Master. ft4222Status = FT4222_SPIMaster_Init( ftHandle, SPI_IO_SINGLE, // 1 channel CLK_DIV_4, // 60 MHz / 4 == 15 MHz CLK_IDLE_LOW, // clock idles at logic 0 CLK_LEADING, // data captured on rising edge SLAVE_SELECT(0)); // Use SS0O for slave-select ``` Enable MRAM QPIE before putting FT4222H to QSPI mode ```c= mram_qpie(ftHandle); ftStatus = FT4222_SPIMaster_SetLines(ftHandle,SPI_IO_QUAD); if (FT_OK != ftStatus) { printf("set spi quad line failed!\n"); return 0; } ``` Test ```bash= sudo ./ft4222_mram 1 sudo ./ft4222_mram ```