I think this bug was first noticed by RangerBob in the thread "Getting USB working in 18F87J50" (http://www.sfcompiler.co.uk/forum/viewtopic.php?t=710),
but I just thought I'd point out that it affects ALL processors, and not just the 87J50 (since it just bit me in the backside while working on another pic).
The issue is that the proper bank select isn't being set for register accesses to the location right before the upper access bank area.
For most processors with the access bank in two $80 byte chunks, this is the register at $F7F (which for most processors isn't used...no harm, no foul).
However, for most of the "J" series parts (USB), and ones with CANbus or LCD controls, the access bank is split at $60 bytes, and the upper SFR area ($F5F) is used. No matter what I tried, while I could get the .idf file to report the proper access bank usage, the code generator would always goof-up access to this reg, and incorrectly assume it was in the access bank (which it isn't).
The code below can be used to demonstrate the issue.
Code: Select all
//
// access bank test
//
'device = 18F452
device = 18F4685
'device = 18F87J50
'device = 18F66J11
'device = 18F8390
// this entry in the SF 18Fxxxx.bas file controls the access bank usage
'#variable _maxaccess = $80
'#variable _maxaccess = $60
// registers around the top access bank
dim
REG_AT_AB_MINUS2 as byte absolute ($1000 - (256-_maxaccess) - 2),
REG_AT_AB_MINUS1 as byte absolute ($1000 - (256-_maxaccess) - 1), // THIS IS THE PROBLEM AREA
REG_AT_AB_START as byte absolute ($1000 - (256-_maxaccess)),
REG_AT_AB_PLUS1 as byte absolute ($1000 - (256-_maxaccess) + 1)
// ram vars in the lower access bank. these are not a problem, they're
// just here to verify that SF allocates and accesses them properly.
// reserve a big chunk to take up most of the lower access bank (minus system vars)
const SYS_VAR_SIZE = $1a
dim dummy(_maxaccess-SYS_VAR_SIZE-1) as byte
// these should be right around the end of the lower access bank
dim
var_at_ab_end_minus1 as byte,
var_at_ab_end as byte,
var_at_ab_end_plus1 as byte
main:
' upper access bank
' reg NOT in access bank (req's bank select)... correct
REG_AT_AB_MINUS2 = 1
' this reg is the last one NOT in access bank...req's bank select
REG_AT_AB_MINUS1 = 2 // THIS IS WHERE THE ERROR OCCURS
' start of upper access bank (no bank select req'd)... correct
REG_AT_AB_START = 3
' also in upper access bank... correct
REG_AT_AB_PLUS1 = 4
' lower access bank
var_at_ab_end_minus1 = 1 ' use access bank ok
var_at_ab_end = 2 ' last var to use access bank
var_at_ab_end_plus1 = 3 ' this one should need a bank select
' so dummy array doesn't get optimized out...
clear(dummy)
Code: Select all
{
****************************************************************************
* Name : SetRAMPtr *
* Purpose : Helper routine for setting RAM *
****************************************************************************
}
inline sub SetRAMPtr(pAddress as FSR0, pValue as INDF0)
end sub
{
****************************************************************************
* Name : GetRAMPtr *
* Purpose : Helper routine for getting RAM byte *
****************************************************************************
}
inline function GetRAMPtr(pAddress as FSR0) as INDF0
end function
' use indirect addressing to access the problem register
SetRAMPtr(@REG_AT_AB_MINUS1, $55)
dummy(0) = GetRamPtr(@REG_AT_AB_MINUS1)
Jerry
edit note: added '@' addressof operator to examples