I had some code that suddenly got bigger and slower and all I'd done was change the size of an array, though no variables ended up placed anywhere but bank 0.
I tracked it down to some uses of porta which were getting both RP0 and RP1 cleared each time before it was used. Even though in some cases, the flow of control made it obviously unnecessary, the initial clear was necessary due to accessing trisa a while back in the call tree. What was particularly bad was the bank switching instructions were inside a loop.
The simplest solution was to force a local variable that is set before the loop into bank 0 only RAM so the bank switching is done to set this variable. The extra unwanted bank switching then went away. All other access in the loop turned out to be in locations which are shared between banks.
Another solution was to force the array I'd changed out into bank 1 and yet another was to use a global variable for the bit count which just happened to be in bank 0 only RAM.
Here is the offending function. It makes no difference whether the C or assembly version is used:
CODE
#pragma OPTIMIZE "a"
void WriteByte(unsigned char byte)
{
unsigned char bitCount = 8;
#if 1
do {
DATA1 = byte.7;
// Ts(500nS) might be marginal if the clock is a bit fast
CLK1 = 1;
byte <<= 1; // Th/Thmin are both 500nS
CLK1 = 0;
} while ( --bitCount != 0 );
#else
_asm {
loop:
btfsc _byte,7
bsf _porta,2; DATA1
btfss _byte,7
bcf _porta,2
bcf _status,C; Not actually needed, but it ensures Ts
bsf _porta,1; CLK1
rlf _byte, F
bcf _porta,1
decfsz _bitCount, F
goto loop
}
#endif
}
And the code it produces:
CODE
ORG 0x00000044
0044 WriteByte_00000
0044 ; { WriteByte; function begin
0044 3008 MOVLW 0x08
0045 00F6 MOVWF WriteByte_00000_1_bitCount
0046 label7
0046 1FF5 BTFSS WriteByte_00000_arg_byte,7
0047 284B GOTO label8
0048 1283 BCF STATUS, RP0
0049 1303 BCF STATUS, RP1
004A 1505 BSF gbl_porta,2
004B label8
004B 1BF5 BTFSC WriteByte_00000_arg_byte,7
004C 2850 GOTO label9
004D 1283 BCF STATUS, RP0
004E 1303 BCF STATUS, RP1
004F 1105 BCF gbl_porta,2
0050 label9
0050 1283 BCF STATUS, RP0
0051 1303 BCF STATUS, RP1
0052 1485 BSF gbl_porta,1
0053 1003 BCF STATUS,C
0054 0DF5 RLF WriteByte_00000_arg_byte, F
0055 1085 BCF gbl_porta,1
0056 03F6 DECF WriteByte_00000_1_bitCount, F
0057 1D03 BTFSS STATUS,Z
0058 2846 GOTO label7
0059 0008 RETURN
005A ; } WriteByte function end
Simply changing unsigned char bitCount to unsigned char bitCount@0x20 produces:
CODE
ORG 0x00000046
0046 WriteByte_00000
0046 ; { WriteByte; function begin
0046 3008 MOVLW 0x08
0047 1283 BCF STATUS, RP0
0048 1303 BCF STATUS, RP1
0049 00A0 MOVWF WriteByte_00000_1_bitCount
004A label7
004A 1BF6 BTFSC WriteByte_00000_arg_byte,7
004B 1505 BSF gbl_porta,2
004C 1FF6 BTFSS WriteByte_00000_arg_byte,7
004D 1105 BCF gbl_porta,2
004E 1485 BSF gbl_porta,1
004F 1003 BCF STATUS,C
0050 0DF6 RLF WriteByte_00000_arg_byte, F
0051 1085 BCF gbl_porta,1
0052 03A0 DECF WriteByte_00000_1_bitCount, F
0053 1D03 BTFSS STATUS,Z
0054 284A GOTO label7
0055 0008 RETURN
0056 ; } WriteByte function end
I realise that this is a difficult case to analyse, but nowhere in the loop is anything but bank 0 used. In such a case, the bank select could be moved outside the loop.
Orin.