It is currently 25 Apr 2019 21:28

All times are UTC + 1 hour




Post new topic Reply to topic  [ 2 posts ] 
Author Message
PostPosted: 13 Jan 2019 09:22 
Offline

Joined: 28 Oct 2007 03:16
Posts: 144
Location: West Australia
Working code follows for three different serial flash memory.
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
////////////////////////////////////////////////////////////////////////////////
// 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);}                                              //                                                                             
////////////////////////////////////////////////////////////////////////////////

Then the Serial_Flash.c file that drives the flash memory:
////////////////////////////////////////////////////////////////////////////////
// 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;                                                                //
}                                                                             //
////////////////////////////////////////////////////////////////////////////////

And last the Serial_Flash.h file:
////////////////////////////////////////////////////////////////////////////////
// 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);                                        //
////////////////////////////////////////////////////////////////////////////////

All this is in the Mikro SDK and Libstock but I find them confusing.
Let me know if this is useful?
Regards Bill Legge


Top
 Profile  
 
PostPosted: 16 Jan 2019 15:29 
Offline
mikroElektronika team
User avatar

Joined: 25 Jan 2008 09:56
Posts: 10209
Hi,

Nice job indeed, I'm sure our users will appreciate this as much as we do.

Regards,
Filip.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: