|
|
View previous topic :: View next topic |
Author |
Message |
peter_dufault
Joined: 25 Jul 2006 Posts: 6
|
const int16 array low byte only with TinyBLD |
Posted: Tue Jul 25, 2006 4:18 pm |
|
|
My system is: 18F4620, 20 MHz, CCS PCWH 3.249.
I've been working on it for some time, and I just started to add in the bootloader. I searched around and tried the TinyBLD bootloader, and it seemed to work very easily right away. However, my program does not operate properly when loaded using the bootloader. It looks like the main problem is that reads from a const int16 array only return the low byte.
Here are bits of my code along with the output:
Code: | //##### Somewhere in a .h file #####//
enum { /* CR_ */
CR_IDLE = 0,
CR_ACTIVE,
CR_IGNITER1,
CR_IGNITER2,
CR_CONVECTIONFAN,
CR_AIRCOMPRESSOR,
CR_EXHAUSTFAN,
CR_SPARE,
CR_PLATEMOTOR,
CR_FEEDMOTOR,
CR_LASTONE
};
/* In units of mA */
int16 const CR_LOW[10] = {0, 0, 300, 300, 250, 250, 800, 0, 1500, 500};
int16 const CR_HIGH[10] = {0, 0, 5000, 5000, 750, 750, 1600, 0, 3000, 1500};
//##### In a support file #####//
char IsCurrentWithinRange(char device) {
printf("device %d\r\n", device);
printf("test %ld\r\n", 5000);
printf("CR_LOW %ld\r\n", CR_LOW[device]);
printf("CR_HIGH %ld\r\n", CR_HIGH[device]);
printf("CurrentReading %ld\r\n", CurrentReading[device].int16_data);
if(CurrentReading[device].int16_data < CR_LOW[device]) {
return(0);
}
if(CurrentReading[device].int16_data > CR_HIGH[device]) {
return(0);
}
return(1);
}
//##### In main() #####//
if(!IsCurrentWithinRange(CR_IGNITER1)) {
IGN_FAIL = 1;
}
if(!IsCurrentWithinRange(CR_IGNITER2)) {
IGN_FAIL = 1;
}
//##### The output of my program #####//
device 2
test 5000
CR_LOW 44 /* Should be 300 */
CR_HIGH 136 /* Should be 5000 */
CurrentReading 493
device 3
test 5000
CR_LOW 44 /* Should be 300 */
CR_HIGH 136 /* Should be 5000 */
CurrentReading 506 |
The current readings of 493 mA and 506 mA are correct, and it falls within the 300 mA to 5000 mA test range. However, the int16 const values they are compared to are truncated to the low 8 bits. Mathematically it is 44 = 300 - 256, and 136 = 5000 - (19 * 256). I will proceed to look at disassembly and hex files. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 25, 2006 4:35 pm |
|
|
Can you provide a test program instead of code fragments ?
Post something that I can drop right into MPLAB and punch the
compile button, and it will compile. Then I can look at the .LST
file and see what's happening. Make sure the program is very
small -- no more code than what you've already posted. |
|
|
peter_dufault
Joined: 25 Jul 2006 Posts: 6
|
|
Posted: Wed Jul 26, 2006 12:59 am |
|
|
I put together an example that I expected would illustrate the problem, except that the test functioned as I wanted the original program to! Very disappointing.
I then spent the next 10 hours taking apart the program to see if the problem would be exposed in some other way. I don't have a clean example yet, but I can make it work or not work by enabling or disabling small sections of code.
At this time it seems like the problem is sensitive to other accesses to 16 bit variables. Additionally, there may be a sensitivity to the presense of interrupt handlers, even if the contents of them are empty. There also seems to be something going on with the configuration fuses.
I will continue to work on an example as compact as possible to exercise this problem. It's 2:00 am. I will get back to this in the morning. |
|
|
Ttelmah Guest
|
|
Posted: Wed Jul 26, 2006 2:56 am |
|
|
An 'empty' interrupt handler, can be a killer. Always put a 'dummy' function (like 'delay_cycles(1)'), into such a handler if declared. When you 'call' the interrupt handler, the compiler adds the code to clear the interrupt at the end of the handler. If there is no code at all in the handler, this can get missed...
Best Wishes |
|
|
peter_dufault
Joined: 25 Jul 2006 Posts: 6
|
|
Posted: Wed Jul 26, 2006 6:52 pm |
|
|
Well, I may have tracked down the problem. Eventually I got to where I would turn the problem on or off depending on how much code I commented out. It didn't really matter which code was removed. I wondered if there was a fuse issue. I had seen this thread: http://www.ccsinfo.com/forum/viewtopic.php?t=26242
which gave a clue about the EBTRB control bit in CONFIG7. It is the "Boot Block Table Read Protection bit" for 0x0 to 0x7FF. Note that it is active low to enable protection. In looking to how the fuses were set by the bootloader:
Code: | Fuse Settings from the bootloader
02 __CONFIG _CONFIG1H, _OSC_HS_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
19 __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOREN_OFF_2L
00 __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_1_2H
84 __CONFIG _CONFIG3H, _MCLRE_ON_3H & _PBADEN_OFF_3H & _CCP2MX_PORTBE_3H
80 __CONFIG _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVREN_OFF_4L & _XINST_OFF_4L
0F __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L & _CP2_OFF_5L
C0 __CONFIG _CONFIG5H, _CPB_OFF_5H
0F __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_OFF_6L
E0 __CONFIG _CONFIG6H, _WRTB_OFF_6H & _WRTC_OFF_6H
0F __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L & _EBTR2_OFF_7L
00 __CONFIG _CONFIG7H, _EBTRB_OFF_7H & _DEVID1 & _IDLOC0
|
It seems to imply that the block is set to no protection. However, the actual fuse data read back into PICKit says that it is set to protection mode. I then set it to _EBTRB_ON_7H. While it assembled, the result was the same. After staring at it for a while I realized that the DEVID1 and IDLOC0 constants don't belong in CONFIG7H at all. Here are the constants of interest:
Code: | _CONFIG7H EQU H'30000D'
_EBTRB_ON_7H EQU H'BF' ; Enabled
_EBTRB_OFF_7H EQU H'FF' ; Disabled
_DEVID1 EQU H'3FFFFE'
_IDLOC0 EQU H'200000'
|
So after some rework:
Code: | Fuse Settings from the bootloader
02 __CONFIG _CONFIG1H, _OSC_HS_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
19 __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOREN_OFF_2L
00 __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_1_2H
84 __CONFIG _CONFIG3H, _MCLRE_ON_3H & _PBADEN_OFF_3H & _CCP2MX_PORTBE_3H
80 __CONFIG _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVREN_OFF_4L & _XINST_OFF_4L
0F __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L & _CP2_OFF_5L
C0 __CONFIG _CONFIG5H, _CPB_OFF_5H
0F __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_OFF_6L
E0 __CONFIG _CONFIG6H, _WRTB_OFF_6H & _WRTC_OFF_6H
0F __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L & _EBTR2_OFF_7L
40 __CONFIG _CONFIG7H, _EBTRB_OFF_7H ; *** Fixed here ***
;_DEVID1 & _IDLOC0 ; *** Fixed here ***
|
It seems to work! In some of my tests, the transition between working and not working, even when I padded it with NOPs, produced outputs that had many changes spread throughout the code. I don't know PIC assembly well enough to interpret what was going on, but it looked like code had moved across the protected boundary that made some accesses work while others did not. I will alert the author of the TinyBLD bootloader about this issue (which only seems to effect the 18F2620 and 18F4620 bootloaders). Otherwise, it seems to work very well. |
|
|
Gabriel Caffese
Joined: 09 Oct 2003 Posts: 39 Location: LA PLATA, ARGENTINA
|
|
Posted: Sun Jul 30, 2006 8:57 pm |
|
|
Peter_dufault,
Tinybootloader doesn´t allow you to change fuses !!
You set them once, when programming Tinybootloader in 18F4620.
If you read the PIC fuses after updating code with the bootloader, you´ll see they are just the same that when programmed the PIC with the Tinybootloader, no matter what your code says.
Even with this, it´s the best one I´ve seen.
Gabriel.- |
|
|
peter_dufault
Joined: 25 Jul 2006 Posts: 6
|
|
Posted: Tue Aug 01, 2006 5:08 am |
|
|
Gabriel,
Yes, actually, my post was unclear. The code I listed on July 26 was from the TinyBLD source for the 18F2620 (also used for the 18F4620). The error I found was with the original source: somehow, the _DEVID1 and _IDLOC0 fuses got included in there. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|