The issue is most likely with the TBLPTR register settings, which is used by SF to read code/const strings.
In the 18F, the table ptr is a 24-bit value comprised of three 8-bit registers: TBLPTRU, TBLPTRH, and TBLPTRL. This gives you full access to the 16M address space of the 18F, which you need to get to things like the eeprom, config words, and unitID.
SF only uses 16-bits (TBLPTRH:TBLPTRL) to access const strings, assuming they're all in the bottom 64K (0000-FFFF) of memory space. It never touches or initializes TBLPTRU, so if the bootloader has changed it from the default of 0, bad things will happen.
Here's a replacement for system.bas that include initialization of TBLPTRU at startup:
Code: Select all
{
****************************************************************
* Name : System.bas *
* Author : David John Barker *
* Notice : Copyright (c) 2006 Mecanique *
* : All Rights Reserved *
* Date : 22/08/2007 *
* Version : 1.3 *
* Notes : 1.1 Added macro param check contants *
* : 1.2 JM added CONFIG_WDT_ON/CONFIG_WDT_OFF macros *
* : to support devices that use WDTEN instead of WDT *
* : The list of devices is from MPLAB 8.66 *
* : 1.3 JM added SYSTEM_ENABLE_DEFAULT_WDT to allow *
* : for more control of the WDT function, including *
* : restoring previous default functionality *
* : added TBLPTRU initialization *
****************************************************************
}
module sys
public const Nil = 0
public type TEvent = event()
// these are the 25 system registers used by the compiler
public dim
SB_SV0 as byte absolute $00,
SB_SV0H as byte absolute $01,
SB_SV0HH as byte absolute $02,
SB_SV0HHH as byte absolute $03,
SB_SV1 as byte absolute $04,
SB_SV1H as byte absolute $05,
SB_SV2 as byte absolute $06,
SB_SV2H as byte absolute $07,
SB_SV2HH as byte absolute $08,
SB_SV2HHH as byte absolute $09,
SB_SV3 as byte absolute $0A,
SB_SV3H as byte absolute $0B,
SB_SV3HH as byte absolute $0C,
SB_SV3HHH as byte absolute $0D,
SB_SV4 as byte absolute $0E,
SB_SV4H as byte absolute $0F,
SB_SV5 as byte absolute $10,
SB_SV5H as byte absolute $11,
SB_SV5HH as byte absolute $12,
SB_SV5HHH as byte absolute $13,
SB_SV6 as byte absolute $14,
SB_SV6H as byte absolute $15,
SB_SV6HH as byte absolute $16,
SB_SV6HHH as byte absolute $17,
SB_SV7 as byte absolute $18
// more user friendly naming of system registers...
public dim
D0 as SB_SV0,
D1 as SB_SV0H,
D2 as SB_SV0HH,
D3 as SB_SV0HHH,
D4 as SB_SV1,
D5 as SB_SV1H,
D6 as SB_SV2,
D7 as SB_SV2H,
D8 as SB_SV2HH,
D9 as SB_SV2HHH,
D10 as SB_SV3,
D11 as SB_SV3H,
D12 as SB_SV3HH,
D13 as SB_SV3HHH,
D14 as SB_SV4,
D15 as SB_SV4H,
D16 as SB_SV5,
D17 as SB_SV5H,
D18 as SB_SV5HH,
D19 as SB_SV5HHH,
D20 as SB_SV6,
D21 as SB_SV6H,
D22 as SB_SV6HH,
D23 as SB_SV6HHH,
D24 as SB_SV7
// macro CheckParam() constants
// check arg constants
// ex: CheckParam(MyByteValue, cpConst or cpInteger, "This is not an integer constant")
public const
cpConst = $01,
cpVariable = $02,
cpArray = $04,
cpSize01 = $08,
cpSize08 = $10,
cpSize16 = $20,
cpSize32 = $40,
cpInteger = $0100,
cpReal = $0200,
cpString = $0400,
cpChar = $0800,
cpBoolean = $1000
// error/message type constants
// ex: CheckParam(etError, "invalid macro parameter")
public const
etError = 0,
etWarning = 1,
etMessage = 2,
etHint = 3
{
****************************************************************************
* Name : ClrWDT *
* Purpose : Clear the watch dog timer *
****************************************************************************
}
//
// Setting this option true will enable blocking routines like delayus() and
// delayms() to include a CLRWDT instruction in the loop. Setting it false
// (which is the default setting if left unspecifed) will result in the routines
// not including a CLRWDT, so long delay calls may result in a watchdog reset
// depending on the wdt timeout settings.
//
#option WDT = false
#if IsOption(WDT) and not (WDT in (true, false))
#error WDT, "Invalid option. WDT must be true or false."
#endif
// v1.3
// This option controls the handling of the previous 'option WDT'.
// The default handling of 'option WDT' is to:
// - enable the config WDT/WDTEN setting if WDT=true,
// - the ClrWDT() sub performs a 'clrwdt' instruction only if WDT=true.
// If you disable the default handling (#option SYSTEM_ENABLE_DEFAULT_WDT = false),
// then the config setting is not touched, and ClrWDT() will always perform a 'clrwdt'
// instruction. This allows for situations where you may not want the config setting
// changed, or you always want to force blocking function to tickle the wdog
//
#option SYSTEM_ENABLE_DEFAULT_WDT = true
// v1.2 WDT vs WDTEN setting
// assume the device uses 'config WDT'
#variable _USE_WDTEN = false
// these 112 devices use WDTEN instead of WDT (MPLAB 8.66)
#if _device in(18F13K22, 18F13K50, 18F14K22, 18F14K50, 18F2331, 18F23K20, 18F23K22, 18F2431)
#variable _USE_WDTEN = true
#elseif _device in(18F24J10, 18F24J11, 18F24J50, 18F24K20, 18F24K22, 18F25J10, 18F25J11, 18F25J50)
#variable _USE_WDTEN = true
#elseif _device in(18F25K20, 18F25K22, 18F25K80, 18F26J11, 18F26J13, 18F26J50, 18F26J53, 18F26K20)
#variable _USE_WDTEN = true
#elseif _device in(18F26K22, 18F26K80, 18F27J13, 18F27J53, 18F4331, 18F43K20, 18F43K22, 18F4431)
#variable _USE_WDTEN = true
#elseif _device in(18F44J10, 18F44J11, 18F44J50, 18F44K20, 18F44K22, 18F45J10, 18F45J11, 18F45J50)
#variable _USE_WDTEN = true
#elseif _device in(18F45K20, 18F45K22, 18F45K80, 18F46J11, 18F46J13, 18F46J50, 18F46J53, 18F46K20)
#variable _USE_WDTEN = true
#elseif _device in(18F46K22, 18F46K80, 18F47J13, 18F47J53, 18F63J11, 18F63J90, 18F64J11, 18F64J90)
#variable _USE_WDTEN = true
#elseif _device in(18F65J10, 18F65J11, 18F65J15, 18F65J50, 18F65J90, 18F65K22, 18F65K80, 18F65K90)
#variable _USE_WDTEN = true
#elseif _device in(18F66J10, 18F66J11, 18F66J15, 18F66J16, 18F66J50, 18F66J55, 18F66J90, 18F66J93)
#variable _USE_WDTEN = true
#elseif _device in(18F66K22, 18F66K80, 18F66K90, 18F67J10, 18F67J11, 18F67J50, 18F67J90, 18F67J93)
#variable _USE_WDTEN = true
#elseif _device in(18F67K22, 18F67K90, 18F83J11, 18F83J90, 18F84J11, 18F84J90, 18F85J10, 18F85J11)
#variable _USE_WDTEN = true
#elseif _device in(18F85J15, 18F85J50, 18F85J90, 18F85K22, 18F85K90, 18F86J10, 18F86J11, 18F86J15)
#variable _USE_WDTEN = true
#elseif _device in(18F86J16, 18F86J50, 18F86J55, 18F86J72, 18F86J90, 18F86J93, 18F86K22, 18F86K90)
#variable _USE_WDTEN = true
#elseif _device in(18F87J10, 18F87J11, 18F87J50, 18F87J72, 18F87J90, 18F87J93, 18F87K22, 18F87K90)
#variable _USE_WDTEN = true
#endif // _device
// define macros that use the appropriate config statement for the current device
// these can be used in place of 'config WDT' or 'config WDTEN'
#if (_USE_WDTEN)
public macro CONFIG_WDT_ON()
config WDTEN = on
end macro
public macro CONFIG_WDT_OFF()
config WDTEN = off
end macro
public macro CONFIG_WDT(x)
config WDTEN = x
end macro
#else
public macro CONFIG_WDT_ON()
config WDT = on
end macro
public macro CONFIG_WDT_OFF()
config WDT = off
end macro
public macro CONFIG_WDT(x)
config WDT = x
end macro
#endif
// WDT option
#if (SYSTEM_ENABLE_DEFAULT_WDT)
// default handling
// if WDT option is set, then enable the wdt configuration setting
#if (WDT)
CONFIG_WDT_ON()
#endif
// ClrWDT() execution is based on WDT option
public inline sub ClrWDT()
#if (WDT)
asm
clrwdt
end asm
#endif
end sub
#else // default handling disabled
// don't change configuration setting (may have to change 'config' manually)
// ClrWDT() always executes 'clrwdt'
public inline sub ClrWDT()
asm
clrwdt
end asm
end sub
#endif
{
****************************************************************************
* Name : NOP *
* Purpose : Single NOP instruction *
****************************************************************************
}
public inline sub Nop()
asm
Nop
end asm
end sub
//
// SF initialization
// v1.3
TBLPTRU = $00
Or, to be safe, modify the bootloader to make sure the TBLPTR registers are all 0 before running the application since system.bas may not be included automatically unless you directly 'include' it.
Although, this would apply more to the issue RangerBob is seeing... The simple app you've posted Graham shouldn't be running afoul of this.