ECEN 4610/4620 – Academic Year 2012-2013
  Home     Projects     Schedule     Policies     FAQ     Resources  
Write your HC11 code in C!
Before you begin, remember that we have all the documentation for the Dunfield software available as hard copies in the lab. Just ask for it!

Chances are, most of your project's code could be written in C without a significant performance or size penalty. Some timing-critical or speed-critical routines may require the precision of assembly coding, but these sections of code are few and far between. If you want to use C code on your HC11 microcontroller, read on...

The compiler we recommend is Dunfield Micro C (available from the TAs and Tom). This compiler is written by the same guy who wrote the asm11 assembler mentioned in the HC11 Dunfield Quickstart. The Micro C compiler is NOT an ANSI C compiler, though it is close. It supports one-byte and two-byte integers natively, with larger numbers available if you use special routines. Floating point is not supported. However, all the standard control structures (if, case, while, for, etc.) are fully implemented, along with basic math (+,-,*,/,%,etc.) and logic (&,|,^,etc.). Refer to the MICRO-C documentation for more information about these things.

Compiler Configuration
Before you start coding, there are a few Dunfield files that you'll have to modify. These files specify where your stack will be located, where RAM and ROM start, and other things that the compiler needs to know in order to map your code to your memory space.

In the MC\LIB11 directory, open 6811RLM.ASM. The very bottom of the file looks like this:

6811RLM.ASM

*#map2 Set address of un-initialized variables * Set up the origin of external RAM based variables. * Eliminate this statement if you are NOT using external RAM * and want all variables allocated in internal RAM. * ORG $4000 External RAM begins here
The HC11E0 has 512 Bytes of internal RAM, located located at 0x0000 to 0x01FF. It also has 64 B of registers located at 0x1000 to 0x103F. So, addresses 0x0200 to 0x0FFF and 0x1040 to 0xFFFF are unused. I assume that your Flash/EPROM will be mapped to 0x8000 through 0xFFFF, leaving 0x1040 through 0x7FFF as the largest unused chunk of address space. I will also assume that your external RAM will be located there. You'll probably want to use your external RAM to store variables, so change $4000 to the starting (lowest) address of your external RAM. (If your external RAM is in your memory map right after the register block, then the starting address will be $1040.) If you don't want to use external RAM at all, then comment that line out by prefacing it with a *.

Next, open 6811RLP.asm. The first few lines are:

6811RLP.ASM (original)

?REGS EQU $0000 68HC711D3 internal registers ?parm EQU $0040 Parameter to runtime library ?temp EQU ?parm+2 Temporary register ORG $0100 Place code in memory here ?begin LDS #$7FFF Initial stack goes here
Obviously, Dave Dunfield was thinking of the HC711D3 when he made this file. Since we're using the HC11E0, several things must change. First, the register block (REGS) must be changed to $1000. Next, the internal RAM start address (?parm) should be changed to $0000. The starting address of your code (ORG) should be $8000 (the lowest address in your Flash/EPROM). Make sure that the stack address (?begin) corresponds to the last byte of external RAM. You'll end up with a file looking like this:
6811RLP.ASM (modified)

?REGS EQU $1000 68HC11E0 internal registers ?parm EQU $0000 Parameter to runtime library ?temp EQU ?parm+2 Temporary register ORG $8000 Place code in memory here ?begin LDS #$7FFF Initial stack goes here
Finally, open 6811RLS.asm. At the bottom, you'll see a few lines that are marked "For stand-alone ROM system, uncomment the following". Make sure they are uncommented, or your code will not be located in the right place in memory!

Preliminary Programming
Now that the environment is set up correctly, you can try writing and compiling a simple program. This program, for example, prints "Hello World!" to the serial port and then blinks an LED connected to Port X, Pin Y. I'll call this one hello.c:

hello.c

#include <6811reg.h> #include <6811io.h> // MUST be included to use printf, sprintf, concat int main() { unsigned char temp; BAUD = 0x30; // 9600b SCCR1 = 0x00; // 8-bit mode SCCR2 = 0x0C; // enable Tx/Rx, no interrupts printf("Hello, world!\n"); temp = 0; while(1) { if(temp%2) PORTA = PORTA | 0x10; // turn on Port A, pin 4 else PORTA = PORTA & ~(0x10); // turn off Port A, pin 4 temp++; } return 0; }
To get a hex file from this C program, you'll have to issue the following commands. I assume that you installed Micro C into C:\MC, and that you are currently in the same directory as your hello.c file:
C:\MC\mcp hello.c hello.tmp -l -c l=C:\MC                      // the preprocessor
C:\MC\mcc11 hello.tmp hello.asm -l -c -s                       // the compiler
del hello.tmp                                                  // remove the temp file
C:\MC\slink hello.asm hello.tmp l=C:\MC\lib11 i=extindex.lib   // the linker
C:\MC\asm11 hello.tmp -f                                       // the assembler
del hello.tmp                                                  // remove the temp file
If your project uses more than one C file, you have to run all of the C files through the preprocessor and compiler separately, then pass them to the linker together (e.g. C:\MC\slink hello.asm hello2.asm hello3.asm hello.tmp l=C:\MC\lib11 i=extindex.lib). To learn more about this process, read the MICRO-C documentation.

Now, you should have three new files: hello.asm, hello.hex, and hello.lst. Hopefully, no errors were reported. Open up hello.lst and scroll through it. You can see how your code starts at 0x8000 and goes through approximately 0x8276 (~630 bytes). You can now take the hex file and burn it to a Flash or EPROM and run it on your board.

Tricky Things and Other Tips
The Dunfield compiler has a few quirks that you should be aware of. A more complete listing is in the MICRO-C documentation.

  1. When using printf/sprintf/concat, you MUST '#include <6811io.h>'.
    (If you don't include this file, your code will compile normally, but the printf instructions will produce garbage.)
  2. Watch your usage of signed/unsigned variables.
    (I suggest declaring all your chars and ints as unsigned, unless you have a specific reason not to. When doing math with signed and unsigned variables, you have to be careful. Refer to the quirks section of the manual for more specifics.)
  3. Initializing at declaration time makes a constant.
    (Saying 'char a = 0;' will cause 'a' to be placed in ROM, meaning you will never be able to change 'a' to any other value. If you want to be able to modify 'a', break the above statement into two lines: 'char a; a = 0;'.)
  4. Docmentation
    (Dave Dunfield has documented almost every aspect of his program. Take the time to read through the MICRO-C documentation. At the very least, go to them first when you think you've found a compiler bug. Chances are, he's already written about your issue.)
  5. Libraries
    (Micro C has a nice set of libraries that you can use. Read the MICRO-C documentation on the libraries and be amazed! You will save a lot of time if you use his hand-optimized routines instead of trying to write and debug your own.)
  6. printf vs. putstr
    (If you do not need the formatting capabilities of printf (e.g. printf("%u.%u",a,b)) then you should use putstr(). This is another library function, and is much quicker and less memory-intensive than printf.)
Written by Cameron McKay
Last modified Aug. 24, 2005