M25P80 on the EasyPICFusionv7 board accessed by SW13. 8 Mbit.
SST26VF064B on the FLASH2 Click. 64Mbit.
W25Q64FV from TronixLabs in Australia. 64Mbit.
All use SPI3 but have different chip select pins - see the Serial_Flash.h file to comment/uncomment.
Commands are the same except for some of the ERASE commands.
I have used SerialFlash_E64() that erases 64Mbytes on all the chips.
I have also used SerialFlash_ChipErase() that is common.
If you use other erase commands my code may not work?
First the file Test_Serial_Flash.c
Code: Select all
////////////////////////////////////////////////////////////////////////////////
// Project: SERIAL_FLASH //
// File: Test_Serial_Flash.c //
// Function: Read and write to serial flash memory //
// M25P80(on board EasyPICFusionv7 or W25Q64FV //
// or SST26VF064B on FLASH2 Click //
// Set Up: See attached Notes.c //
// MCU: 32MX795F512L //
// Board: EasyPIC_Fusionv7 //
// Power: 3.3V for MCU and TFT //
// Xtal: Running at 80MHz //
// Compiler: mikroC PRO for PIC32 version 4.0.0 //
// Programmer: ICD3 or on-board //
// Author: WVL //
// Date: 11 Jan 2019 //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Brief set up //
// Select flash type by commemt/uncomment #defines in Serial_Flash.h //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#include "Serial_Flash.h" // constants, pin allocations, prototypes //
#include "Serial_Flash.c" // functions //
#include "Notes.c" // memory details and set up //
#define HEARTBEAT LatG0_bit // flashed for looping //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function prototype - direct PrintOut to UART2 on USBA //
void U2(char c); //
////////////////////////////////////////////////////////////////////////////////
// Function prototype - direct PrintOut to UART5 on MikroBus 2 - right //
void U5(char c); //
////////////////////////////////////////////////////////////////////////////////
void main(){
char x = 0;
char y = 99; // seed for random number
char read = 0;
char write = 0;
unsigned int a = 0;
unsigned int b = 0;
unsigned int c = 0;
unsigned short my_string[25]; // conversion unsigned long to string
unsigned long test_address = 0; // test byte read and write
unsigned long array_start = 0; // test page read and write
char test_page[300]; // to test 256 byte page write
char read_page[300]; // for page read
// Init MCU
AD1PCFG = 0xFFFF; // 1=digital 0=analog
JTAGEN_bit = 0; // disable JTAG
// Ports and pins
TRISA = 0;
TRISB = 0;
TRISC = 0;
TRISD = 0;
TRISE = 0;
TRISF = 0;
TRISG = 0;
LATD0_bit = 0; // WP Write Protect pin for FLASH2 Click
LATC1_bit = 1; // Hold pin for FLASH2 Click
// Init peripherals
UART5_Init(9600); // used MikroBus2 U5Tx/RF13 U5Rx/Rf12 not used U2Tx/RF5 U2Rx/RF4
delay_ms(100);
Printout(U5,"Test_Serial_Flash_Memory now running\r\n");
for(x=0;x<10;x++){
HEARTBEAT = ~HEARTBEAT;
delay_ms(100);
}
// Init serial flash using SPI3
// Uses SPI3 on SDO3/RF8 SDI3/RF2 SCK3/RD5 and on MikroBus sockets
// SPI clock is 80/8 = 10MHz, slow but OK
SerialFlash_Start();
SerialFlash_WriteSR(0);
SerialFlash_UnlockSST();
Printout(U5,"Starting SerialFlash_ChipErase()\r\n");
Printout(U5,"Some flash memory takes a long tims to bulk erase\r\n");
SerialFlash_ChipErase(); // all bytes set to 0xFF
Printout(U5,"SerialFlash_ChipErase() completed\r\n");
delay_ms(20);
test_address = 2000; // assign value after declaration
while(1){
// Test read and write to W25Q64FV or M25P80 or SST26VF064B
SerialFlash_WriteByte(write,test_address);
read = SerialFlash_ReadByte(test_address);
// Display results
Printout(U5,"Test byte read and write\r\n");
a = write;
b = read;
LongWordToStrWithZeros(test_address, my_string);
Printout(U5,"Write:%u Read:%u Address:%s\r\n",a,b,my_string);
// Generate 256 random bytes for write/read test
srand(y); // new sequence of random ints
for(c=0;c<=255;c++)test_page[c] = rand();
// Test page read and write to W25Q64FV or M25P80 or SST26VF064B
// Using page 1000. Start address = 1000*256 = 256,000
array_start = 256000UL;
// All flash memory uses 0xD8 to erase 64kByte
// So erase from 256,000/65,536 = 3.9 ie sector 3
// Start address is = 3*65,536 = 196,608
// Size of sector varies between flash memories
// But the command byte 0xD8 erases 64kbytes in all chips
// The function SerialFlash_E64KB uses this commonality
SerialFlash_E64KB(196608UL); // erase the area we are writing to
SerialFlash_WriteArray(array_start,&test_page,256);
// Display results
Printout(U5,"Test array read and write\r\n");
for(c=0;c<256;c++){
read = SerialFlash_ReadByte(array_start);
a = test_page[c];
b = read;
LongWordToStrWithZeros(array_start, my_string);
Printout(U5,"test_page:[%u]%u \tread_page:[%u]%u at Addresss:%s\r\n",c,a,c,b,my_string);
array_start++;
}
// Housekeeping
test_address++; // increment address for byte write/read
write++; // increment data for byte write
y++; // increment seed for random array
HEARTBEAT = ~HEARTBEAT;
delay_ms(1000);
}
}
////////////////////////////////////////////////////////////////////////////////
// Function - direct PrintOut stream to the PC via UART2 //
void U2(char c){UART2_Write(c);} //
////////////////////////////////////////////////////////////////////////////////
// Function - direct PrintOut stream to the PC via UART5 //
void U5(char c){UART5_Write(c);} //
////////////////////////////////////////////////////////////////////////////////
Code: Select all
////////////////////////////////////////////////////////////////////////////////
// Project: SERIAL_FLASH //
// File: Serial_Flash.c //
// Function: Read and write to serial flash memory //
// M25P80(on board EasyPICFusionv7 or W25Q64FV //
// or SST26VF064B on FLASH2 Click //
// Set Up: See attached Notes.c //
// MCU: 32MX795F512L //
// Board: EasyPIC_Fusionv7 //
// Power: 3.3V for MCU and TFT //
// Xtal: Running at 80MHz //
// Compiler: mikroC PRO for PIC32 version 4.0.0 //
// Programmer: ICD3 or on-board //
// Author: WVL //
// Date: 11 Jan 2019 //
////////////////////////////////////////////////////////////////////////////////
#include <built_in.h> // decomposition of 20 bit address into 8 bits
////////////////////////////////////////////////////////////////////////////////
// Other files needed: //
// Serial_Flash.h that defines function prototypes and CS //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// SerialFlash Commands //
static const unsigned short CMD_RDID = 0x9F; // Read ID //
static const unsigned short CMD_RDSR = 0x05; // Read status register //
static const unsigned short CMD_WRSR = 0x01; // Write status register //
static const unsigned short CMD_READ = 0x03; // Read Byte - any number //
static const unsigned short CMD_WRITE = 0x02; // Page Write - 1 to 256 bytes //
static const unsigned short CMD_WREN = 0x06; // Write enable //
static const unsigned short CMD_E64KB = 0xD8; // Erase 64kBytes //
static const unsigned short CMD_ERASE = 0xC7; // Bulk erase //
// SerialFlash Commands for Flash2 Click SST26VF064B //
static const unsigned short CMD_REEN = 0x66; // Reset enable //
static const unsigned short CMD_RST = 0x99; // Reset command //
static const unsigned short CMD_ULBFR = 0x98; // Global unlock //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Functions for Flash2 Click SST26VF064B //
////////////////////////////////////////////////////////////////////////////////
// Function - Reset the memory //
void SerialFlash_Reset(){ //
CS = 0; //
SPI3_Write(CMD_REEN); // reset enable //
CS = 1; //
delay_ms(1); //
CS = 0; //
SPI3_Write(CMD_RST); // reset command //
CS = 1; //
return; //
} //
////////////////////////////////////////////////////////////////////////////////
// Function - Write to the status register //
void SerialFlash_WriteSR(char status){ //
CS = 0; //
SPI3_Write(CMD_WRSR); // write to status register //
SPI3_Write(0); // dummy byte //
SPI3_Write(status); // write status //
CS = 1; //
} //
////////////////////////////////////////////////////////////////////////////////
// Initialize SPI bus and serial flash on SPI3 //
// Max speed is 50HMz, use 80/2 = 40MHz //
// M25P80 memory only accepts two SPI formats: //
// _SPI_CLK_IDLE_HIGH,_SPI_ACTIVE_2_IDLE) //
// _SPI_CLK_IDLE_LOW, _SPI_IDLE_2_ACTIVE) //
// Uses SPI3 with MOSI/RF8 MISO/RF2 SCK3/RD15 //
void SerialFlash_Start() { //
SPI3_Init_Advanced(_SPI_MASTER,_SPI_8_BIT,8,_SPI_SS_DISABLE,\
_SPI_DATA_SAMPLE_MIDDLE,_SPI_CLK_IDLE_LOW,_SPI_IDLE_2_ACTIVE); //
Delay_ms(100); //
CS = 1; // CS bit disabled //
SerialFlash_WriteEnable(); // CS cycled and WREN sent to chip //
SerialFlash_Reset(); //
Delay_ms(10); //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function - SerialFlash_WriteEnable() //
void SerialFlash_WriteEnable(){ //
CS = 0; //
SPI3_Write(CMD_WREN); //
CS = 1; //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function - SerialFlash_IsWriteBusy() //
// Bit 0 of the status register 1=busy 0=done //
char SerialFlash_IsWriteBusy(){ //
char temp; //
CS = 0; //
SPI3_Write(CMD_RDSR); //
temp = SPI3_Read(0); //
CS = 1; //
return (temp&0x01); //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function - Unlock memory on SST26VF064B/FLASH2 Click //
void SerialFlash_UnlockSST(){ //
SerialFlash_WriteEnable(); //
CS = 0; //
SPI3_Write(CMD_ULBFR); //
CS = 1; //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function - SerialFlash_WriteByte() Function that writes a single byte //
// Input: Data to be written and the address to which to store the data //
void SerialFlash_WriteByte(char _data, unsigned long address){ //
SerialFlash_WriteEnable(); //
CS = 0; //
SPI3_Write(CMD_WRITE); //
SPI3_Write(Higher(address)); //
SPI3_Write(Hi(address)); //
SPI3_Write(Lo(address)); //
SPI3_Write(_data); //
CS = 1; //
// Wait for write end //
while(SerialFlash_isWriteBusy()); //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function - SerialFlash_ReadByte() reads the byte from the address //
// Input: address to be read. Output: byte data from the address //
char SerialFlash_ReadByte(unsigned long address){ //
char temp; //
CS = 0; //
SPI3_Write(CMD_READ); //
SPI3_Write(Higher(address)); //
SPI3_Write(Hi(address)); //
SPI3_Write(Lo(address)); //
temp = SPI3_Read(0); //
CS = 1; //
return temp; //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function -SerialFlash_WriteWord()writes 2 succesive bytes of word variable //
// Input: Word data to be written and the address to which to store the data //
void SerialFlash_WriteWord(unsigned int _data, unsigned long address){ //
SerialFlash_WriteByte(Hi(_data),address); //
SerialFlash_WriteByte(Lo(_data),address+1); //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function - SerialFlash_ReadWord()reads the word from the address //
// Input: read address. Output: word data stored in two successive addresses //
unsigned int SerialFlash_ReadWord(unsigned long address){ //
unsigned int temp; //
Hi(temp) = SerialFlash_ReadByte(address); //
Lo(temp) = SerialFlash_ReadByte(address+1); //
return temp; //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function - SerialFlash_WriteArray() writes data to successive addresses //
// Input: address of the begining, pointer to buffer containing data //
// and number of bytes to be written //
// Output: 1 - if write succeeded, 0 - if write failed //
char SerialFlash_WriteArray(unsigned long address, char *pData, unsigned int nCount){
unsigned long addr; //
char *pD; //
unsigned int counter; //
addr = address; //
pD = pData; //
// WRITE //
for(counter = 0; counter < nCount; counter++){ //
SerialFlash_WriteByte(*pD++, addr++); //
} //
// VERIFY //
for (counter=0; counter < nCount; counter++){ //
if (*pData != SerialFlash_ReadByte(address)) //
return 0; //
pData++; //
address++; //
} //
return 1; //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function SerialFlash_ReadArray() reads data from successive addresses //
// Input: address of the begining, pointer to buffer where to store read data,//
// and number of bytes to be read. Output: none //
void SerialFlash_ReadArray(unsigned long address, char *pData, unsigned int nCount){
CS = 0; //
SPI3_Write(CMD_READ); //
SPI3_Write(Higher(address)); //
SPI3_Write(Hi(address)); //
SPI3_Write(Lo(address)); //
while(nCount--){ //
*pData++ = SPI3_Read(0); //
} //
CS = 1; //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function - Erase 64kBytes from input address //
void SerialFlash_E64KB(unsigned long address){ //
SerialFlash_WriteEnable(); //
CS = 0; //
SPI3_Write(CMD_E64KB); //
SPI3_Write(Higher(address)); //
SPI3_Write(Hi(address)); //
SPI3_Write(Lo(address)); //
CS = 1; //
// Wait for write end //
while(SerialFlash_IsWriteBusy()); //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function - SerialFlash_ChipErase() sends Chip Erase command //
void SerialFlash_ChipErase(void){ //
SerialFlash_WriteEnable(); //
CS = 0; //
SPI3_Write(CMD_ERASE); //
CS = 1; //
// Wait for write end //
while(SerialFlash_IsWriteBusy()); //
} //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Function SerialFlash_ReadID() reads the CHIP ID //
// Input: none Output: ID byte value //
char SerialFlash_ReadID(void){ //
char temp; //
CS = 0; //
SPI3_Write(CMD_RDID); //
temp = SPI3_Read(0); //
CS = 1; //
return temp; //
} //
////////////////////////////////////////////////////////////////////////////////
Code: Select all
////////////////////////////////////////////////////////////////////////////////
// Project: SERIAL_FLASH //
// File: Serial_Flash.h //
// Function: Read and write to serial flash memory //
// M25P80(on board EasyPICFusionv7 or W25Q64FV //
// or SST26VF064B on FLASH2 Click //
// Set Up: See attached Notes.c //
// MCU: 32MX795F512L //
// Board: EasyPIC_Fusionv7 //
// Power: 3.3V for MCU and TFT //
// Xtal: Running at 80MHz //
// Compiler: mikroC PRO for PIC32 version 4.0.0 //
// Programmer: ICD3 or on-board //
// Author: WVL //
// Date: 11 Jan 2019 //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Conditional compilation. Comment un-comment to define your chip type //
#define M25P80 // CS is RD14 //
//#define W25Q64FV // CS is RC2 //
//#define FLASH2 // CS is RC2 //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// EasyPICFusionv7 board has RD14 hardwired as CS by SW13 //
#ifdef M25P80 //
sbit CS at LATD14_bit; // set on SW13 //
#endif //
#ifdef W25Q64FV //
sbit CS at LATC2_bit; // left hand MikroBus socket //
#endif //
#ifdef FLASH2 //
sbit CS at LATC2_bit; // left hand MikroBus socket //
#endif //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Prototypes for serial flash functions //
void SerialFlash_Start(); //
void SerialFlash_WriteEnable(); //
char SerialFlash_IsWriteBusy_(); //
void SerialFlash_UnlockSST(); //
void SerialFlash_WriteByte(unsigned char _data, unsigned long address); //
char SerialFlash_ReadByte(unsigned long address); //
void SerialFlash_WriteWord(unsigned int _data, unsigned long address); //
unsigned int SerialFlash_ReadWord(unsigned long address); //
char SerialFlash_WriteArray(unsigned long address,char*pData, unsigned int nCount);
void SerialFlash_ReadArray(unsigned long address, char*pData, unsigned int nCount);
void SerialFlash_E64KB(unsigned long address); //
void SerialFlash_ChipErase(void); //
char SerialFlash_ReadID(void); //
// Prototypes for Flash2 Click SST26VF064B //
void SerialFlash_Reset(); //
void SerialFlash_WriteSR(char status); //
////////////////////////////////////////////////////////////////////////////////
Let me know if this is useful?
Regards Bill Legge