I realize that SF doesn't have support for a 24-bit data type (which is really what the TBLPTRU/TBLPTRH/TBLPTRL register set is), and does table accesses using a 16-bit address.
There's the following alias in the device .bas files...
Code: Select all
public dim
TABLEPTR as TBLPTRL.AsWord
I've seen code posted that allows access to the full 24-bit program memory space...
Code: Select all
function ReadByte(pAddress as TABLEPTR) as byte
asm-
TBLRD *+
movff TABLAT, result
end asm
end function
function ReadByte(pAddress as longword) as byte
TBLPTRU = pAddress.Byte2
TBLPTRH = pAddress.Byte1
TBLPTRL = pAddress.Byte0
asm-
TBLRD *+
movff TABLAT, result
end asm
end function
The issue is, once the TBLPTRU register is set like this, it's never set back to $00, so any future table reads (or accesses to const data) fail since the TBLPTRU may be pointing to a different page of 64K space.
For example, if you have
Code: Select all
dim b as byte
b = ReadByte($1000) // accesses $001000 (assuming TBLPTRU=0)
b = ReadByte($200000) // accesses $200000
b = ReadByte($1000) // accesses $201000 **INCORRECT**
Code: Select all
const data_table() = (1,2,3,4,5,6,7,8)
dim b as byte
b = ReadByte($200000) // accesses $200000, sets TBLPTRU = $20
b = data_table(b) // doesn't work, as TBLPTRU isn't 0
SF uses the 16-bit TBLPTRH/TBLPTRL pair to access the 'const' data, and ignores the setting of TBLPTRU.
So it would seem that any functions that modify TBLPTRU must set it back to 0 when done
Code: Select all
function ReadByte(pAddress as longword) as byte
TBLPTRU = pAddress.Byte2
TBLPTRH = pAddress.Byte1
TBLPTRL = pAddress.Byte0
asm-
TBLRD *+
movff TABLAT, result
end asm
TBLPTRU = 0 // set upper TBLPTR back to 0 for normal SF access
end function
Code: Select all
interrupt intr()
dim b as byte
b = 1
b = data_table(b) // won't work if happens to interrupt ReadByte()!!!!
end interrupt
Code: Select all
function ReadByte(pAddress as longword) as byte
INTCON.7 = 0 // disable interrupts while using TBLPTRH
TBLPTRU = pAddress.Byte2
TBLPTRH = pAddress.Byte1
TBLPTRL = pAddress.Byte0
asm-
TBLRD *+
movff TABLAT, result
end asm
TBLPTRU = 0 // set upper TBLPTR to 0 for normal SF access
// reenable interrupts
// this is an issue, since maybe they weren't enabled to start with.
// really, we should have read the state of INTCON.7 before we cleared it,
// and only enable them here if they were enabled to start with
INTCON.7 = 1
end function
Code: Select all
interrupt intr()
dim b as byte
save(TBLPTRU)
TBLPTRU = $00 // needed for SF to access const data
b = 1
b = data_table(b)
restore
end interrupt
Since TBLPTRU is never initialized, SF relies on it being set to 0 by a RESET event, such as a power-on reset, MCLR, WDT timeout, etc. Usually not a problem, unless you try to restart your code using a 'goto 0' or you're using a bootloader which might have changed TBLPTRU...
Code: Select all
b = data_table(b) // this will fail the second time through
b = ReadByte($200000) // accesses $200000, sets TBLPTRU = $20
// restart
asm
goto 0
end asm