MemoryAccess

MemoryAccess is a module written to enable you to Read and Write to Program memory

Although you can already access (read) program memory very easily using constant arrays the routines in this module offer a little more flexibility in some aspects as well as code usage savings. Before you start writing to program memory read and understand the limitations that this imposes. Like where you can write and why you have to clear memory first.


EraseBlock(address) // address is a word variable or constant

Erases a block of program memory usually 64 bytes at a time although can be up to 1024 (read the pic data sheet!!!)

Example

EraseBlock($200)

Note Note Note.....

It's particularly important to read the datasheet with respect to erasing. For example, the datasheet for the 18F452 says:

"The Most Significant 16 bits of the TBLPTR<21:6> point to the block being erased.TBLPTR<5:0> are ignored."

That is, the six bits ignored means you must start an erase block on multiples of 64 (six bits gives us a range 0..63). This means you could not start an erase block at $207. It would need to be $200, $240, $280, $2C0 and so on.


WriteAt(address,data) //OVERLOADED

Write to a specific address the contents of data which be (should) cover all data types except strings arrays etc. Address should be a word variable a constant or a label if you use the @ prefix.

Note that as you can write only in set memory lumps at a time eg 8 bytes then close the write the sub will handle it for you, each time you write the required number of bytes it will complete the write. If you finish a write that does not fall on a boundary then you need to close the write using CloseWrite(). Note once closed you cannot write more data with out erasing the memory first.

Example

    EraseBlock($200)

    Dim Address As Word
    Dim index As Byte

    Address = $200
    EraseBlock(Address)
    For index = 0 To 100 
        WriteAt(Address,index) 
        Inc (Address) 
    Next 
    CloseWrite   

CloseWrite() // finish writing the data to memory even if not on a boundary.


ReadByte(Address)

ReadWord(Address)

ReadLongWord(Address)

Read the appropriate number of bytes from Program memory. Address should be a word variable a constant or a label if you use the @ prefix.

Example

    Const myarray1(4) As Byte = (1,2,3,4)
    Const myarray2(4) As Word = (1000,2000,3000,4000)
    Const myarray3(4) As LongWord = (100000,200000,300000,400000)

    Dim Bytevar As Byte
    Dim Wordvar As Word
    Dim Longwordvar As LongWord
    Dim Address As Word

    Address = @myarray1                  
    Bytevar = ReadByte(Address + 1)        //  Bytevar = 2
    Wordvar = ReadWord(@myarray2)          //  Wordvar = 1000
    Longwordvar = ReadLongWord(@myarray3 + 8) // Longwordvar = 300000
{
*****************************************************************************
*  Name    : MemoryAccess.BAS                                               *
*  Author  : Tim Box                                                        *
*  Notice  : Copyright (c) 2007 TJB Systems Ltd                             *
*          : All Rights Reserved                                            *
*  Date    : 03/08/2007                                                     *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}


Module MemoryAccess

// module option - just put some values in here for testing...
    #option ROM_BLOCK_SIZE = 8
    #if Not (ROM_BLOCK_SIZE in (8, 16, 32, 64))
      #error ROM_BLOCK_SIZE, "Invalid option. ROM_BLOCK_SIZE must be 8, 16 or whatever..."
    #endif

// bring option into the program...
    Const 
        WriteBlockSize = ROM_BLOCK_SIZE - 1

// some local aliases...  
    Dim
      EEPGD As EECON1.7,
      WR As EECON1.1,
      WREN As EECON1.2 

// inline delay
    Inline Sub Delay()
      ASM
      GoTo $ + 2
      End ASM
    End Sub

// table read
    Inline Sub TableRead()
      ASM
      TBLRD*+
      End ASM
    End Sub

// table write
    Inline Sub TableWrite()
      ASM
      TBLWT*+
      End ASM
    End Sub

// Functions =======================

// read a byte from ROM  
    Public Function ReadByte (pAddress As TABLEPTR) As TABLAT
      EECON1 = 0
      EEPGD = 1
      TableRead
    End Function

// read a Word from ROM  
    Public Function ReadWord (pAddress As TABLEPTR) As Word
      EECON1 = 0
      EEPGD = 1
      TableRead
      result.Byte0 = TABLAT
      TableRead
      result.Byte1 = TABLAT
    End Function

// read a LongWord from ROM  
    Public Function ReadLongWord (pAddress As TABLEPTR) As LongWord
      EECON1 = 0
      EEPGD = 1
      TableRead
      result.Byte0 = TABLAT
      TableRead
      result.Byte1 = TABLAT
      TableRead
      result.Byte2 = TABLAT
      TableRead
      result.Byte3 = TABLAT
    End Function

// Subroutines ======================= 

// erase ROM block...
    Public Sub EraseBlock (pAddress As TABLEPTR)
      EECON1 = $94
      EECON2 = $55
      EECON2 = $AA
      WR = 1
      Delay
      WREN = 0
    End Sub

// close a write
    Public Sub CloseWrite()
      EECON1 = $84
      EECON2 = $55
      EECON2 = $AA
      WR = 1
      Delay
      WREN = 0
    End Sub

{
****************************************************************************
* Name    : WriteItem                                                      *
* Purpose : Write a byte to program memory                                 *
****************************************************************************
}
    Public Sub WriteItem (pValue As TABLAT)
      TableWrite       
      If (WriteBlockSize And Byte(TBLPTRL+1)) = 0 Then
         CloseWrite
      EndIf
      Inc(TABLEPTR)
    End Sub

{
****************************************************************************
* Name    : WriteAt (OVERLOAD)                                             *
* Purpose : Write a Byte at an address from program memory                 *
****************************************************************************
}    
    Public Inline Sub WriteAt (pAddress As TABLEPTR, pValue As TABLAT)
      WriteItem(TABLAT)
    End Sub


{
****************************************************************************
* Name    : WriteAt (OVERLOAD)                                             *
* Purpose : Write a Word at an address from Program memory                 *
****************************************************************************
}    
    Public Sub WriteAt (pAddress As TABLEPTR, pValue As Word)      
      WriteItem(pValue.byte0)
      WriteItem(pValue.byte1)
    End Sub

{
****************************************************************************
* Name    : WriteAt (OVERLOAD)                                             *
* Purpose : Write a LongWord at an address from Program memory             *
****************************************************************************
}
    Public Sub WriteAt (pAddress As TABLEPTR, pValue As LongWord)
      WriteItem(pValue.byte0)
      WriteItem(pValue.byte1)
      WriteItem(pValue.byte2)
      WriteItem(pValue.byte3)
    End Sub