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