Friday, June 3, 2011

Bumped into a Hi-Tech C Compiler bug

Am developing a circuit using the PIC10F222. Since I don't want to code in assembly I chose to use Hi-Tech C Compiler for PIC 10-12-16 (freebie version) v9.81 within Microchip's MPLAB IDE (v.8.66). I'm still developing the software but when I compiled the very short initial code I got an error message saying that "TRIS" is an "undefined identifier." The offending line that tripped the compiler was "TRIS = 0b10". I couldn't understand why it would be flagged as an error since that's the correct syntax to initialize the TRISIO register (which is not accessible directly) according to Hi-Tech User Manual (DS51865B-page 53): THE TRIS INSTRUCTIONS

Some PIC devices use a TRIS instruction to load the TRIS register. The <htc.h> header file will ensure a special definition for a C object called TRIS. PICC will automatically use the TRIS instruction when an appropriate processor is selected and the TRIS register is accessed.

For example, to make all the bits on the output port high impedance, the following code can be used.

TRIS = 0xFF;

This will load the appropriate value into the W register and then call the TRIS instruction.

Those PIC devices which have more than one output port may have definitions for objects: TRISA, TRISB and TRISC, depending on the exact number of ports available. This objects are used in the same manner as described above.

Given that last paragraph I changed TRIS to TRISIO, TRISA, TRISB, and TRISC. Still got the same error. I also changed the numerical values to decimal and hex. I even closed MPLAB and opened it again. None of these licked the problem. Finally since I have v9.80 installed I tried that to compile the program.

Lo and behold! The error message disappeared. When I opened the include file for the 10F22x for v.9.80 I found out that TRIS and TRISIO are defined therein, but they aren't in the 10F222 include file for v.9.81. Oddly though, while OPTION is defined in v.9.80 and isn't in v9.81, the latter nevertheless understood that command and correctly compiled it.

So there. That's a bug in version 9.81.

Having opened the include files for both versions, I was vexed to find out that there are a number of differences in the defines. For instance for the configuration bits, v9.80 lists the following:
// Configuration Mask Definitions
/* Internal oscillator frequency select */
#define OSC_8MHZ 0xFFF // internal osc is 8MHz
#define OSC_4MHZ 0xFFE // internal osc is 4MHz

/* Master clear pullup enable */
#define MCPUEN  0xFFD // pullup enable
#define MCPUDIS  0xFFF // pullup disable

#define WDTEN  0xFFF // watchdog timer enable
#define WDTDIS  0xFFB // watchdog timer disable

/* code protection */
#define PROTECT  0xFF7 // protect the program code
#define UNPROTECT 0xFFF // do not protect the program code

/* MCLR Pin function */
#define MCLREN  0xFFF // master clear reset enable
#define MCLRDIS  0xFEF // master clear reset disable

while v9.81 has these:
// Configuration mask definitions

// Config Register: CONFIG
#define CONFIG               0x0FFF
// Internal Oscillator Frequency Select bit
// 8 MHz
#define IOSCFS_8MHZ          0xFFFF
// 4 MHz
#define IOSCFS_4MHZ          0xFFFE
// Master Clear Pull-up Enable bit
// Pull-up disabled
#define MCPU_OFF             0xFFFF
// Pull-up enabled
#define MCPU_ON              0xFFFD
// Watchdog Timer Enable bit
// WDT enabled
#define WDT_ON               0xFFFF
// WDT disabled
#define WDT_OFF              0xFFFB
// Code protection bit
// Code protection off
#define CP_OFF               0xFFFF
// Code protection on
#define CP_ON                0xFFF7
// GP3/MCLR Pin Function Select bit
// GP3/MCLR pin function is MCLR
#define MCLRE_ON             0xFFFF
// GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD
#define MCLRE_OFF            0xFFEF

None of the bit names are the same!

Since I'm using the ADC, the line "GO_nDONE = 1"--which is perfectly fine in v9.81--was flagged as an error in v9.80 because it only recognizes "GODONE." Now try compiling "GODONE = 1" in v9.81. What do you think will happen? You guessed it. You get a build fail. 

For who knows what reason, Microchip not only demands we have a photographic memory to remember all those changing (or alternate) defines, it's also made it a hair-tearing ordeal to port firmware from one compiler version to the next. This is yet another reason I really would rather stick to mikroC if not for the fact that mikro doesn't support the baseline PICs and has a 2K code limit.


  1. If you define _LEGACY_HEADERS before including the header htc.h the old names will work.
    Note: I have no idea if the new names will also work.

    Tim S.