M25P128Module

SwordfishUser.M25P128Module History

Hide minor edits - Show changes to output

Changed line 2 from:
[[http://www.intersema.ch/index.php?option=com_rubberdoc&view=doc&id=41&format=raw | link text]]
to:
Deleted line 1:
%center%http://www.ohararp.com/images/WEATHER_A.JPG"Easypic4 Dev Board"\\
Changed line 2 from:
to:
%center%http://www.ohararp.com/images/WEATHER_A.JPG"Easypic4 Dev Board"\\
Changed lines 2-3 from:
%center%http://www.ohararp.com/images/WEATHER_A.JPG"Easypic4 Dev Board"\\
to:
Changed lines 2-4 from:
to:
%center%http://www.ohararp.com/images/WEATHER_A.JPG"Easypic4 Dev Board"\\

[[http://www.intersema.ch/index.php?option=com_rubberdoc&view=doc&id=41&format=raw | link text]]
Changed lines 8-9 from:
This module was created to share with others the great datalogging potential of this little chip in conjunction with the SF compiler.  This chip is accessed in a manner very similar to a Serial EEPROM.  I did want to point out several distinct difference that could cause trouble for people.
to:
This module was created by Timothy Box and converted to SF by Ryan O'Hara to share with others the great datalogging potential of this little chip in conjunction with the SF compiler.  This chip is accessed in a manner very similar to a Serial EEPROM.  I did want to point out several distinct difference that could cause trouble for people.
Deleted lines 6-7:

Changed lines 1-4 from:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"\\
to:
%center%http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"\\

%lfloat% http://www.sfcompiler.co.uk/wiki/uploads/StevenWright/download.gif

Added lines 7-8:

Changed line 1 from:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"
to:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"\\
Changed line 13 from:
to:
!!! Code
Added line 100:
!!! Module
Changed line 1 from:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128" | '''Figure 1'''
to:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128 Schematic"
Added line 4:
!!! Introduction
Changed lines 6-7 from:
1. Each sector of memory must have been previously erased before writing to that page.  This means                you cannot write to several addresss and then "backup" to rewrite to the first address.  The entire sector must be erased before you can return rewrite to the first address.
to:
1. Each sector of memory must have been previously erased before writing to that page.  This means                you cannot write to several address and then "backup" to rewrite to the first address.  The entire sector must be erased before you can return rewrite to the first address.
Changed lines 10-12 from:
3. Finally, if you are using this chip in conjunction with a usb connection, when the

to:
3. Finally, if you are using this chip in conjunction with a usb connection, when the BulkErase command is issued it can take a fair amount of time (30 seconds or so) to earse all the data memory.  You must somehow poll the usb line to keep the usb connection alive when this command is used.

Changed lines 2-12 from:
to:
[[http://www.ohararp.com/files/M25P128.pdf | M25P128 Datasheet]]

This module was created to share with others the great datalogging potential of this little chip in conjunction with the SF compiler.  This chip is accessed in a manner very similar to a Serial EEPROM.  I did want to point out several distinct difference that could cause trouble for people.

1. Each sector of memory must have been previously erased before writing to that page.  This means                you cannot write to several addresss and then "backup" to rewrite to the first address.  The entire sector must be erased before you can return rewrite to the first address.

2. When you use the WriteBytes command you can begin at any address within a sector/page.  However, caution must be taken so that you do not write over a page boundary.

3. Finally, if you are using this chip in conjunction with a usb connection, when the

Added lines 1-2:
http://www.ohararp.com/images/M25P128_SCH.JPG"M25P128" | '''Figure 1'''
Changed line 367 from:
Public Function ReadBytes(pM25PDataAddress As LongWord,ByRef pM25PDataIn() As Byte,pBytesToRead As LongWord) As Byte
to:
Public Sub ReadBytes(pM25PDataAddress As LongWord,ByRef pM25PDataIn() As Byte,pBytesToRead As LongWord)
Changed line 389 from:
End Function
to:
End Sub
Changed line 8 from:
   OSC = HSPLL, // HS Oscillator
to:
   OSC = HSPLL, // HS Oscillator
Changed line 13 from:
   WDT    = OFF, // Watchdog Timer Disabled
to:
   WDT       = OFF, // Watchdog Timer Disabled
Changed lines 15-17 from:
   WDTPS  = 256,      // 15000 x 4mS  = 60 seconds
    LVP
     = OFF,     // Low_Voltage Programming
   PBADEN  = OFF      // PORTB Digital 
to:
   WDTPS      = 256,         // 15000 x 4mS  = 60 seconds
   LVP         = OFF,        // Low_Voltage Programming
    PBADEN      = OFF   
      // PORTB Digital 
Changed lines 2-15 from:
{
*****************************************************************************
*  Name
   : M25P128.BAS                                               
*  Author  : Ryan O'Hara                                                 
*
  Notice  : Copyright (c) 2009  - OHARARP LLC                           
*          : All Rights Reserved                                         
*  Date    : 1/16/2009                                                   
*  Version : 1.0                                                         
*  Notes  : This code was originally developed by Tim Box and ported to SF                                                             
*          : by Ryan O'Hara
*          : This handy little chip provides up to 128Mb -> 16MB of Flash memory                                                             
*****************************************************************************
}
Module M25P128
to:
// DEVICE AND CLOCK
Device = 18F2620
Clock =  40

// DEVICE FUSE CONFIG
Config
    OSC = HSPLL, // HS Oscillator
    FCMEN = OFF, // Failsafe Clock Monitor Disabled
    IESO = OFF, // Int/Ext Oscillator Switch Over Disabled
    PWRT = OFF, // Power Up Timer Disabled
    BOREN = OFF, // Brownout Reset Disabled
    WDT    = OFF, // Watchdog Timer Disabled
    MCLRE = ON, // MCLR Enabled
    WDTPS  = 256,      // 15000 x 4mS  = 60 seconds
    LVP    = OFF,      // Low_Voltage Programming
    PBADEN  = OFF     // PORTB Digital 
Added line 20:
   #option WDT = True
Added lines 23-105:
// INCLUDES
    Include "UTILS.BAS"
    Include "SUART.bas"
    Include "CONVERT.bas"
    Include "SHIFT.bas"
    Include "M25P128.BAS"
 
// ALIAS
    Dim LED_FIX As PORTB.2
    Dim LED_NOFIX As PORTB.3
    Dim IDX As LongWord

    Dim ID As LongWord
    Dim M25PData(256) As Byte
   
Sub SETUP()
    SetAllDigital()
 
    M25P128.Init()
    SetTX(PORTB.7)
    SetRX(PORTB.6)
    SetBaudrate(sbr38400)
    SetMode(umTrue)
End Sub
//------------------------------------------------------------------------------
SETUP()

// Serial Startup
For IDX = 0 To 4
    Toggle(LED_FIX)
    Toggle(LED_NOFIX)
    UART.Write("HELLO WORLD",13,10)
    DelayMS(1000)
Next

// Read ID
For IDX = 0 To 4
    ID = M25P128.ReadId()
    UART.Write("C - ",BinToStr(ID.BYTE0,8),"|",BinToStr(ID.BYTE1,8),"|",BinToStr(ID.BYTE2,8),13,10)
Next

// Erase the First Sector
M25P128.SectorErase(0)

// Write Some Data to RAM
For IDX = 0 To 255
    M25PData(IDX) = IDX
Next
   
// Write the Data to the M25P128
M25P128.WriteBytes(128,M25PData)

// Read 256 Bytes from Address 0
M25P128.ReadBytes(128,M25PData,256)

// Write the Data to the Serial Port 
UART.Write("READ BYTE - ")       
For IDX = 0 To 255
    UART.Write(DecToStr(M25PData(IDX)),",")
Next   
UART.Write(13,10,13,10)

End=]

=code [=
{
*****************************************************************************
*  Name    : M25P128.BAS                                                 
*  Author  : Ryan O'Hara                                                 
*  Notice  : Copyright (c) 2009  - OHARARP LLC                           
*          : All Rights Reserved                                         
*  Date    : 1/16/2009                                                   
*  Version : 1.0                                                         
*  Notes  : This code was originally developed by Tim Box and ported to SF                                                             
*          : by Ryan O'Hara
*          : This handy little chip provides up to 128Mb -> 16MB of Flash memory                                                             
*****************************************************************************
}
Module M25P128
   
// OPTIONS
    #option SHIFT_MAX = 8   

Changed lines 315-316 from:
End Sub  ]
to:
End Sub
=]
Added lines 1-315:
=code [=
{
*****************************************************************************
*  Name    : M25P128.BAS                                                 
*  Author  : Ryan O'Hara                                                 
*  Notice  : Copyright (c) 2009  - OHARARP LLC                           
*          : All Rights Reserved                                         
*  Date    : 1/16/2009                                                   
*  Version : 1.0                                                         
*  Notes  : This code was originally developed by Tim Box and ported to SF                                                             
*          : by Ryan O'Hara
*          : This handy little chip provides up to 128Mb -> 16MB of Flash memory                                                             
*****************************************************************************
}
Module M25P128
   
// OPTIONS
    #option SHIFT_MAX = 8   

// IMPORT MODULES
    Include "SHIFT.BAS"

// DEFAULT MODULE OPTIONS - USER OPTIONS CAN OVERRIDE THESE VALUES...   
    #option M25P_CS  = PORTC.2                    // use 10k ohms pull-up resistor
    #option M25P_CLK  = PORTC.3                    // use 10k ohms pull-down resistor
    #option M25P_SDI  = PORTC.4                    //
    #option M25P_SDO  = PORTC.5                    //
       
    // Validate CS pin...
    #if IsOption(M25P_CS) And Not IsValidPortPin(M25P_CS)
      #error M25P_CS, "Invalid option. CS must be a valid port pin."
    #endif

        // Validate CLK pin...
    #if IsOption(M25P_CLK) And Not IsValidPortPin(M25P_CLK)
      #error M25P_CLK, "Invalid option. CLK must be a valid port pin."
    #endif
           
        // Validate SDI pin...
    #if IsOption(M25P_SDI) And Not IsValidPortPin(M25P_SDI)
      #error M25P_SDI, "Invalid option. DI must be a valid port pin."
    #endif
       
        // Validate SDO pin...
    #if IsOption(M25P_SDO) And Not IsValidPortPin(M25P_SDO)
      #error M25P_SDO, "Invalid option. DO must be a valid port pin."
    #endif         
// ======= M25P128 Instructions ==================================
Const
    M25P_WREN = $06,              ' Write M25PEnable
    M25P_WRDI = $04,              ' Write M25PDisable
    M25P_RDID = $9F,              ' Read Identification
    M25P_RDSR = $05,              ' Read STATUS Register
    M25P_WRSR = $01,              ' Write STATUS Register
    M25P_Read = $03,              ' Read Data Bytes
    M25P_Read_Fast = $0B,          ' Read Data Bytes At Higher Speed
    M25P_PP = $02,                ' PAGE Program
    M25P_SE = $D8,                ' Sector Erase
    M25P_BE = $C7,                ' Bulk Erase
    M25P_Dummy = $FF              ' Dummy Byte for Fast Read

// Variables used with commands to the M25P128
    Dim M25PStatus As Byte
    Dim M25PIndex As Byte                                      ' Index Counter   
    Dim SRWD As M25PStatus.7                                    ' Status Register Write M25PDisable
    Dim BP2 As M25PStatus.4                                    ' The Block Protect (BP2, BP1, BP0) bits
    Dim BP1 As M25PStatus.3
    Dim BP0 As M25PStatus.2
    Dim WEL As M25PStatus.1                                    ' The Write M25PEnable Latch
    Dim WIP As M25PStatus.0                                    ' The Write In Progress

// Bring port and pin options into the module... 
    Dim CS As M25P_CS.M25P_CS@
    Dim CLK As M25P_CLK.M25P_CLK@ 
    Dim SDI As M25P_SDI.M25P_SDI@
    Dim SDO As M25P_SDO.M25P_SDO@
{
****************************************************************************
* Name    : Disable(PRIVATE)                                             
* Purpose : Disable the M25P128                                         
****************************************************************************
}
Sub M25PDisable()
    High(CS)                                                    ' M25PDisable the chip again
End Sub
{
****************************************************************************
* Name    : Enable(PRIVATE)                                             
* Purpose : Enable the M25P128                                           
****************************************************************************
}   
Sub M25PEnable()
    Low(CS)                                                    ' M25PEnable the chip
End Sub
{
****************************************************************************
* Name    : Write(PRIVATE)                                               
* Purpose : Write M25PEnable the M25P128                                 
****************************************************************************
}
Sub WriteEnable()
    M25PEnable()                                                ' M25PEnable the chip
    Shift.Out(MSB_FIRST,M25P_WREN,8)                            ' Send the WREN command
    M25PDisable()                                              ' M25PDisable the chip again
End Sub                                                        ' All done return
{
****************************************************************************
* Name    : WriteDisble(PRIVATE)                                         
* Purpose : Write M25PDisable the M25P128                               
****************************************************************************

Sub WriteDisable()   
    M25PEnable()                                                ' M25PEnable the chip
    Shift.Out(MSB_FIRST,M25P_WRDI,8)                            ' Send the WRDI command
    M25PDisable()                                              ' M25PDisable the chip again
End Sub 
{
****************************************************************************
* Name    : ReadID                                                       
* Purpose : Read the 24 Bit Id of the M25P128                           
****************************************************************************
}       
Public Function ReadId() As LongWord   
    M25PEnable()                                                ' M25PEnable the chip
    Shift.Out(MSB_FIRST,M25P_RDID,8)                            ' Send the RDID command
    ReadId.BYTE0 = Shift.In(MSB_POST,8)                        ' readin the 24 bit ID data
    ReadId.BYTE1 = Shift.In(MSB_POST,8)
    ReadId.BYTE2 = Shift.In(MSB_POST,8)                        ' M25PDisable the chip again
    M25PDisable()
End Function
{
****************************************************************************
* Name    : ReadStatus(PRIVATE)                                         
* Purpose : Read the Read Status Register of the the M25P128             
****************************************************************************
}   
Sub ReadStatus()
    M25PEnable()                                                ' M25PEnable the chip
    Shift.Out(MSB_FIRST,M25P_RDSR,8)                            ' Send the RDSR command
    M25PStatus = Shift.In(MSB_POST,8)
End Sub
{
****************************************************************************
* Name    : ReReadStatus(PRIVATE)                                   
* Purpose : ReRead the Read Status Register of the the M25P128           
****************************************************************************
}   
Sub ReReadStatus()
    M25PStatus = Shift.In(MSB_POST,8)
End Sub
{
****************************************************************************
* Name    : BulkErase                                               
* Purpose : Erase the Entire M25P128 DATA - TAKES AWHILE TO OPERATE     
****************************************************************************
}   
Public Sub BulkErase()
    ReadStatus()                                                ' Check its Not in the middle of a current Write
    While WIP = 1
        ReReadStatus()
    Wend
    M25PDisable()                                              ' M25PDisable To ensure the Read STATUS is stopped
    DelayUS(4)
    M25PEnable()                                                ' M25PEnable the chip again
    WriteEnable()
    M25PEnable()                                                ' M25PEnable the chip
    Shift.Out(MSB_FIRST,M25P_BE,8)                              ' Sent the Bulk erase instruction
    M25PDisable()                                              ' M25PDisable the chip To start the erase 
End Sub
{
****************************************************************************
* Name    : SectorErase                                             
* Purpose : Erase the One Sector of the M25P128 DATA                     
****************************************************************************
}
Public Sub SectorErase(pM25PDataAddress As LongWord)
    ReadStatus()                                            ' Check its not in the middle of a current write
    While WIP = 1
        ReReadStatus()
    Wend
    M25PDisable()                                              ' M25PDisable to ensure the read status is stopped
    DelayUS(4)
    M25PEnable()                                                ' M25PEnable the chip again
    WriteEnable()
    M25PEnable()                                                ' M25PEnable the chip
    Shift.Out(MSB_FIRST,M25P_SE,8)                              ' Sent the Sector erase instruction
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8)                ' Send the address
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)                ' The whole sector that the address is in will be
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)                ' Erased
    M25PDisable()                                                ' M25PDisable the chip to start the erase
End Sub
{
****************************************************************************
* Name    : WriteStatus                                             
* Purpose : Make areas of the M25P128 Data read only                     
****************************************************************************
}
Sub WriteStatus(pM25PWriteByte As Byte)
    WriteEnable()
    M25PEnable()                                                ' M25PEnable the chip
    Shift.Out(MSB_FIRST,pM25PWriteByte,8)
    M25PDisable()                                              ' M25PDisable the chip again
End Sub         
{
****************************************************************************
* Name    : WriteByte                                               
* Purpose : Write a single byte and the specified address               
****************************************************************************
}
Public Sub WriteByte(pM25PDataAddress As LongWord,pM25PWriteByte As Byte)
    ReadStatus()                                            ' Check its not in the middle of a current write
    While WIP = 1 
        ReReadStatus()
    Wend
    M25PDisable()                                              ' M25PDisable to ensure the read status is stopped
    DelayUS(4)
    M25PEnable()                                                ' M25PEnable the chip again
    WriteEnable()                                              ' Write M25PEnable the device
    M25PEnable()                                                ' M25PEnable the device
    Shift.Out(MSB_FIRST,M25P_PP,8)                              ' Sent the Page Write instruction
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8)              ' Send the address
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
    Shift.Out(MSB_FIRST,pM25PWriteByte,8)                      ' Finaly the data
    M25PDisable()                                              ' Finish the write by bringing the CS line high
End Sub
{
****************************************************************************
* Name    : WriteBytes                                               
* Purpose : Write up to 255 bytes from the  specified address           
* CAUTION : OVERLAPPING A PAGE BOUNDARY CAN CAUSE SERIOUS ERRORS         
****************************************************************************
}   
Public Sub WriteBytes(pM25PDataAddress As LongWord,ByRef pM25PDataOut() As Byte)
    ReadStatus()                                                ' Check its not in the middle of a current write
    While WIP = 1
        ReReadStatus()
    Wend
        M25PDisable()                                          ' M25PDisable to ensure the read status is stopped
    DelayUS(4)
    M25PEnable()                                                ' M25PEnable the chip again
    WriteEnable()                                              ' Write M25PEnable the device
    M25PEnable()                                                ' M25PEnable the device
    Shift.Out(MSB_FIRST,M25P_PP,8)                              ' Sent the Page Write instruction
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8)              ' Send the address
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
 
    For M25PIndex = 0 To Bound(pM25PDataOut)                    ' Via FRS0 send all the data requested
        Shift.Out(MSB_FIRST,pM25PDataOut(M25PIndex),8)
    Next
    M25PDisable()                                              ' Finish the write by bringing the CS line high
End Sub       
{
****************************************************************************
* Name    : ReadByte                                                 
* Purpose : Read a single byte at the specified address               
****************************************************************************
}
Public Function ReadByte(pM25PDataAddress As LongWord) As Byte
    ReadStatus()                                                ' Check its not in the middle of a current write
    While WIP = 1
        ReReadStatus()
    Wend
    M25PDisable()                                              ' M25PDisable to ensure the read status is stopped
    DelayUS(4)
    M25PEnable()                                                ' M25PEnable the chip again 
    Shift.Out(MSB_FIRST,M25P_Read,8)                            ' Sent the data read instruction
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8)              ' Send the address
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
    ReadByte = Shift.In(MSB_POST,8)                            ' Read the byte in
    M25PDisable()                                               
End Function
{
****************************************************************************
* Name    : ReadBytes                                               
* Purpose : Read a multiple bytes byte at the specified address         
****************************************************************************
}   
Public Function ReadBytes(pM25PDataAddress As LongWord,ByRef pM25PDataIn() As Byte,pBytesToRead As LongWord) As Byte
    If pBytesToRead > Bound(pM25PDataIn()) Then                'Check to make sure you do not overfill the array
        pBytesToRead = Bound(pM25PDataIn())
    EndIf
   
    ReadStatus()                                                ' Check its not in the middle of a current write
    While WIP = 1
        ReReadStatus()
    Wend
    M25PDisable()                                              ' M25PDisable to ensure the read status is stopped
    DelayUS(4)
    M25PEnable()                                                ' M25PEnable the chip again 
    Shift.Out(MSB_FIRST,M25P_Read_Fast,8)                      ' Sent the data read instruction
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE2,8)              ' Send the address
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE1,8)
    Shift.Out(MSB_FIRST,pM25PDataAddress.BYTE0,8)
    Shift.Out(MSB_FIRST,M25P_Dummy,8)
   
    For M25PIndex = 0 To pBytesToRead - 1                     
        pM25PDataIn(M25PIndex) = Shift.In(MSB_POST,8)
    Next
    M25PDisable()                                               
End Function
{
****************************************************************************
* Name    : Init                                                         
* Purpose : Setup the Port Pins                                         
****************************************************************************
}
Public Sub Init()
    Output(CS)
    Shift.SetClock(CLK,TRUE) //initialise shiftOUT clock pin, IDLE HIGH
    Shift.SetInput(SDI)
    Shift.SetOutput(SDO) //initialise shiftOUT pin
End Sub  ]