|
| Home / How To / Education |
 | Getting Started with the Motorola 68HC11 microcontroller Gary Livick 19 Oct 2000
|
The TCOMP and the Super TCOMP are single board computers built around the Motorola 68HC11 microcontroller. Many people who purchase a TCOMP do so intending to use the computer as a controller for a device of some kind. TCOMPs often find themselves pressed into service as the "brains" in small autonomous robots.
Unlike the case where the user of a TCOMP or Super TCOMP is a computer science student or professional, the person who uses the computer as part of a larger system often finds him- or herself overwhelmed in esoteric microcontroller detail. While it may be that the computer scientist is interested in exploring every nuance of a processor such as the HC11 for its own sake, the systems type user generally is more interested in getting a project completed in an effective, timely manner. And while the detail-oriented computer scientist is already well equipped to deal with a new and unfamiliar processor by virtue of past experience with similar types, the systems engineer is more commonly in possession of general knowledge in the field of his or her endeavor, with little or no experience in microcontrollers at the application level.
This instruction is intended for the systems-type user, and other people needing an introductory level of explanation for whatever reason. What we will do is start from the beginning, assume no prior knowledge, and go from there. Some topics require the reader to enter commands from the computer keyboard, and each actual keystroke will be provided where it seems necessary. The intent is to over-simplify and over-explain, using elementary analogies as needed. At times this may become irritating for some, but others will be happy with the detail.
|
Step 1| What does that tell us? 19 Oct 2000 | What does that tell us? It tells us that if we "and" port A with our mask, no matter what the rest of the pins are doing, my answer tells me just the state of pin 0. In this case, pin 0 is 1, which means the pullup resistor is holding it high, and the pushbutton, which would have grounded it, is not depressed. If the pushbutton was depressed when a read of port A took place, the "and" would have looked like this instead:
11001000
00000001
00000000
So if the pin is depressed, when we "and" we get 0. Otherwise we get 1. Again, repeated below, these are the two lines that do that check for us. So far, we haven't used the label "LABEL," but we'll get to that later. These are our two lines:
LABEL LDAA #%00000001 ; this is the mask I'll use to look at port A
ANDA $1000 ; logical "and." If port A anded with the mask = 0, pin zero is on.
OK, on to the next step. Once we see if pin 0 is on or off, we have the HC11 make a decision. This is called a "conditional branch:"
BEQ LITEON ; if 0, branch to the area of the program that turns on the LED
|
Step 2| The ground rules 19 Oct 2000 | We will discuss the TCOMP computer and the Super TCOMP interchangeably. They work identically when doing what we are going to do. We will only work with the expanded system, writing programs into the 32K of external RAM. We will not talk much about EEPROM or ROM, or on-chip RAM, accept to explain what they are. We won't be using the ROM or EEPROM features of the TCOMP in this exercise. We will only run the TCOMP computer in either special bootstrap or expanded mode, and leave the special test mode and single chip mode for another time. If you have no clue what any of this means, you are in the right place.
|
Step 3| What we are going to do 19 Oct 2000 | There is more than enough to cover as it is, so we will limit the scope of our work to topics of immediate use. We will begin by talking about the way the HC11 works at an introductory level. Then we will discuss very basic programming, and how to get programs we write into the TCOMP and get them to run. We will use the most common of the freeware packages available to do this.
We'll build an external pushbutton circuit and an LED circuit for later use in explaining input and output programming, and connect them to the board. We will write a simple program in assembly language that actually does something, get connected to the TCOMP, load it in and make it run. We will also learn how to manipulate the program in the TCOMP after it has been loaded.
|
Step 4| What we won't be talking much about 19 Oct 2000 | Other than just mentioning them where appropriate, we will not discuss higher level languages such as C or BASIC. We will not go into any detail about the hardware features of the HC11, such as the timers, counters and so on. We will not talk about interrupts or the SPI/SCI systems. We won't talk about the A/D converters. We will only work with simple digital inputs and outputs. These are all important topics, and are part of what makes the HC11 such a powerful device. However, a 500 page book shown in appendix A, Microcomputer Engineering, is the place to learn them. Here, we want to learn what the author of that book won't teach you: how to get connected.
|
Step 5| What you should expect 19 Oct 2000 | When we are finished, you will be able to write a very simple program in assembly language and run an assembler to convert it to object code for the HC11. You will know how to build and connect simple LED and pushbutton circuits so you can experiment with I/O (real-world inputs and outputs). You will be able to run PCBUG11 to load programs into external RAM, and edit or run them from within the PCBUG application. Plus, you will pick up tons of buzz-words that will be encountered again in your own studies.
|
Step 6| OK, let's build some things 19 Oct 2000 | Find a good electronics store in your area. There is at least one in every town of any size. Radio Shack is not what we are looking for. If you can find a store near you that would be best, but if you live in a village so small that the lights dim on Main Street when someone pushes your doorbell, you will have to get yourself a Mouser or DigiKey catalog and shop from there. Even though you can get what you need this time at a place like Radio Shack, there will come a day when you are going to need things that you can't find there.
Once in the store (or catalog), turn on the old shopping gene. Buy a few LED's, nothing fancy, in a couple of different colors. We are only going to need one for now, but you will want more for your own experiments later. Find a couple of small pushbutton switches. The printed circuit board kind will work nicely, with normally open single-pole, single throw contacts. If you wind up with a switch that has more than two leads, either have and know how to use an ohm meter, or have the store where you buy it identify the normally open leads for you. Next, get a few 1000 ohm 1/8 watt resistors.
Ask the guy behind the counter (or look in the catalog index) for a 64-pin length of single in-line strip sockets with .100" spacing. We'll use those to make sockets on the ends of some of our wires. Now, find yourself some .030 rosin core solder and an inexpensive 12 to 15 watt soldering iron. The soldering iron can be had for $11.00 or $12.00 for an adequate one. Don't go getting one of the $150.00 ones just yet. If you want to splurge, get a soldering iron that has a ground.
Find a small roll of solid, 22 gauge hookup wire, any color. Also get some wire cutters/strippers that will work for wire sizes from 16 to 26-gauge. Finally, get some 1/8" diameter heat shrink tubing.
At home, lay out your new stuff and get ready to build a couple of circuits. Be careful where you plug in your soldering iron, because besides soldering, it also will work very nicely for wood burning. The kitchen table is not a good place to be doing this, even if you are careful. Go for the ceramic tile counter top, or use the cutting board.
Find the LED you want to use. Since the program we will write later on is called FROG1, a green one would be nice. Now pick the thing up and have a look at the leads. Hey, one is longer than the other! The LED is a diode, and it only conducts current in one direction. Hook it up backwards, and it just lies there and does nothing but make you think your batteries are dead. It has a polarity; the long lead is the positive lead (+), and the other is the negative (- or 'common') lead. The way I remember it is: the long lead is long enough to make the + but the short lead can only make the -.
Dig out one of your new 1K ohm resistors. We are going to solder it to the positive lead of the LED. In the future, just remember that the resistor is soldered to the positive lead of the LED because we are about to cut that lead a lot shorter. Now clip the positive lead of the LED and one of the leads of the resistor so that when you are done soldering the two components together, the other lead of the resistor can be cut to the same length as the negative lead of the LED and have at least 3/8" of resistor lead left. Later, we will plug the LED/resistor assembly into the TCOMP, and we want the leads to be the same length.
Ready? Solder away. If you haven't soldered before, you may find that you can't do it so well. Here's a hint: as the soldering iron is heating up for the first time, melt a little solder on the tip just as it is getting hot enough. This is called 'tinning' and is necessary to keep the tip from corroding and to help in heat transfer. That's all the hints. If you don't already know how to solder, and don't have anyone to show you how, practice a few weeks on wire and parts you don't care much about, and then come back.
Find your pushbutton switch and the hookup wire. Cut two lengths of wire about 4" long, strip about 1/8" of insulation off one end of each. Solder one of the wires to a lead of your switch, and the second wire to the other lead. Now, from the free ends of the wires, trim off about 1/8" of insulation.
Next, we need to put some strip socket pieces on the ends of the wires so we can connect to the headers on the TCOMP. Notice that the strip socket you bought is serrated so that it can be cut easily. It's a trick! As soon as you look at the strip with a cutting instrument in your hands, it will break in the wrong spot. Somehow, and very carefully, cut four individual sockets from the strip with a very sharp knife or Xacto blade. If you have a Dremmel, dig it out. You finally get to use it.
Cut four pieces of heat shrink tubing, each about long, and slide them up the leads of both the LED/resistor assembly and the pushbutton assembly. Then solder the sockets to the leads of your pushbutton and LED assemblies. After you have soldered them in place, slide the heat shrink tubing down over the bare area on each socket (to keep the wires from shorting together later), and shrink the tubing in place with a match.
OK, let's connect this stuff to the TCOMP. Find the layout drawing that came with your board, and locate the pin diagram for interface header J8. Note that the pins on the right half of J8 are for port A, and there are a pair of + and - pins as well. The left half of J8 is for port D. Push either lead of the pushbutton assembly onto the - pin in the port D area of J8 and the other lead onto pin 0 of port A. Next, plug the + lead of the LED/resistor assembly (the lead with the resistor soldered to it) onto pin 6 of port A, and the other lead onto the - pin on J8. If you want to see the LED light up, and can't wait until later when we'll have the computer doing it, sneak the positive lead of the LED over to the + pin on J8 and enjoy. It's seems to be good for the soul for some reason.
Now, turn on your TCOMP. The LED may come on, or may not. It may flash, or may not. That is because your TCOMP has no program in it yet and, if its running, it's executing garbage. Whatever it's doing is normal.
|
Step 7| Numbering systems 19 Oct 2000 |
The HC11 is an "8 bit" computer. That means that each word in the computer's written language has 8 "letters" in it. When it is talking to you, when you are talking to it, when it is talking to itself, the communication is always with words that contain 8 "letters" in them. The letters in the computer's alphabet, 8 per each word, are more simple than the 26 letters we use in our alphabet. There are only two letters, and in fact those letters are actually numbers, just 1 and 0. These are easy numbers for the computer to use, because the computer is composed of a huge number of transistors that are either turned on (1) or turned off (0). An 8 bit computer looks at 8 transistors at a time, records whether they are on or off (1 or 0) and passes the results around where they are needed. So an 8 bit computer word (called a byte) looks like this, for example: 00001101. This byte of data, composed of 8 bits, actually represents a number that you and I are familiar with, but appears in a form that is convenient for the computer. Written like this, it is referred to as the "binary" form of the number.
Just as the computer uses binary numbers as a matter of convenience, humans use a numbering system that is convenient for them. Since we have ten fingers to count with, we use a numbering system based on ten. Numbers represented in the form humans are most comfortable with are termed "decimal," utilizing the numbers 0 thru 9 to constitute them. The binary number given above, 00001101, is 13 in decimal. 00000000 is decimal zero, 00000001 is decimal one, 00000010 is two, 00000011 is three, etc., until we pack the whole word: 111111111 is the decimal number 255.
There are other numbering bases that are used besides base 2 (binary) and base 10 (decimal), but the only one that is of interest to us is called "hexadecimal," with a base of 16. Hexadecimal numbers are represented by the numbers 0-9 and the letters A-F. (Take off your shoes and count 'em. It adds up to sixteen if you start from 0.) Now it gets tricky. To represent a binary number in hexadecimal, we break an 8 bit binary word into two syllables. Thus 00001101 becomes 0000-1101. Now, look at the "least significant" syllable (meaning it has the least effect on the value of the number), 1101. That number in decimal is 13 as we said. In hexadecimal it is $C, with the dollar sign telling us it's hex. (Ok, this is basic I know, but lets just do it: 0000=$0, 0001=$1, 0010=$2, 0011=$3, 0100=$4, 0101=$5, 0110=$6, 0111=$7, 1000=$8, 1001=$9, 1010=$A, 1011=$B, 1100=$C, 1101=$D, 1110=$E, 1111=$F.) The "most significant" syllable is 0000, which in hex is $0. To read the whole binary number in hexadecimal, we combine the two hex parts (don't add them, just place them next to each other). Thus 00001101 becomes $0C. If the binary number was 11011001, the hex number would be $D9. Someday, you'll discover this is handy.
Congratulations, that's all you need to know for now, and just about all you will ever need to know, about these types of numbering systems. Except that we usually put a % in front of all binary numbers and nothing in front of decimal numbers: %00001101 = $0C = 13. But really, that's it.
|
Step 8| Programming languages, compilers, and that sort of thing 19 Oct 2000 | Especially when trying to learn on our own, all the technical terminology used by our computer science buddies in their writings gets us lost quick. So lets just cover the basics in English.
The computer only knows 1's and 0's. Don't tell it anything else or it will barf. It only "hears" or "speaks" using those two numbers, but as a matter of convenience, it does communicate 8 of them at a time. That makes it an 8 bit computer, as we've already said. If you were to look at any memory location in the computer (more on that later), you would find the same thing no matter where you looked; 10100111, or some other 8 bit binary number such as that. In the very early hobbyist's computers, there were a series of 8 toggle switches on the front of the computer, and a couple of other switches to tell the computer to load the number you just signified by setting the 8 toggle switches into memory. That is how programs were loaded in, one byte at a time. It worked alright, aside from the fact that it was very slow for the human to do it this way, and the results were often overwhelmed with errors in the entry.
Programming a computer by entering data with switches was called machine language programming. It was tedious, and programs were necessarily short, but if you wanted to own a reasonably priced computer in those days (the kit was $2000 in 1978 as I recall), this is the way you did your program entry. But that was then, this is now, and we have a better way of doing it.
Each memory location in the computer has something in it. It may be garbage, which it will be if we or the computer didn't put something there on purpose. If we put it there, it may be an "instruction" for the computer to do something, like add two numbers, or it may be a "constant" that we put there, say $C8 for example. If the computer put it there, it is almost certainly data.
An instruction is called an OpCode, for operation code, and it tells the computer to do something. (It is usually written 'op code,' but we'll use this other form for now so it stands out.) Each instruction has a hexadecimal number in a book somewhere that we can recognize more easily than we can the equivalent binary number that the computer will recognize. For instance, there is an OpCode that tells the computer to store a number, located in one of its internal scratch pad areas called an "accumulator," into a location in memory. This OpCode is $B7 (remember the $ signifies that the number is in hexadecimal form). When the computer gets to that instruction as it is executing a program, it will store what is in its "accumulator A" (there are other accumulators) into a specific address in memory. So, when we are writing our program on a piece of paper, we scribble down the hex number $B7 when we want to store the contents of accumulator A into memory somewhere (we give it the address to store into immediately after the instruction). This beats having to write out the machine language version of that operation, which is %10110111. We can get to know $B7, and not have to look it up, so that saves time as well. Programming can get to be fun! We'll just write everything in OpCodes, and be done with it. All we need then is some kind of program to change the hex OpCode numbers into binary numbers the computer needs to see, and load them into the computer memory. There is a program that does this conversion for us, and it is called a "loader."
But wait, why not make the system even easier to use? How about if instead of saying $B7, which is admittedly more simple to remember, and type, than the binary equivalent, we use a "mnemonic" instead that looks more like what we want the computer to do. Lets say we create a mnemonic for $B7, and call it STAA. We'll use STAA when we want the computer to store what is in accumulator A into memory. That will make it much easier to visualize what we're doing, and also make the program easier to read later. It just so happens that there is a system of these mnemonics, and it is called "assembly language." That is a big term. You hear it all the time. It sounds like a big deal, but it isn't. Assembly language is simply the most basic practical method of writing programs. Being the most basic, it gives the programmer the tightest possible control over the operation of the computer, at a price of course. Writing in assembly is slow and tedious.
Each CPU family has a set of OpCodes that are recognized by that CPU family, called its "instruction set." The HC11 found in the TCOMP has it's own set, the 68030 Mac chip has its set, the Intel 8080 has its own set. If we are to program in assembly, we need to know what our set is, and the format for each instruction. In appendix A, there is an Internet pointer to the HC11 OpCode mnemonics set.
Ok, now we have a practical way to write programs in a language that has some intuitive feel to it, but we still have to get them into the computer. No matter what we did to convenience ourselves, the computer still only knows 1's and 0's. The simple loader program we once used to convert hex OpCodes into binary and load them into the computer will barf when we try to stuff an assembly language program into it written in mnemonics. No problem. We will just use another program to take our assembly language code and convert it into an OpCode program. The program that does this is called an "assembler" or "cross-assembler," which for us are synonymous names. When the assembler is running and it gets to our STAA instruction , it changes it into a $B7. Then the loader program we use later will convert the $B7 into binary.
That's it. That's all we need to know for now. We will write the program we'll do shortly in assembly, run it through an assembler to convert it to OpCodes, then run that file through the loader and into the computer. The actual mechanics will be this: we will write the assembly program using the DOS editor, and give the file name a .asm suffix. Then we'll run it though an assembler called AS11, a Motorola freeware program, which will return the assembled program in a file for us with our original name, but with a .s19 suffix. Then we will load it into memory using the loader features of PCBUG11a, a PC-based monitor that also comes from Motorola.
As an aside, we should also mention another term that you may have heard of; "compiler." If we are writing in a higher level language, such as BASIC or C, when we get to the stage where we want to load a program into the TCOMP, we must first translate the BASIC or C program into assembly language. The program that does this is called a "compiler," or "cross-compiler." After compiling the program, we take the same steps to assemble and load it that we do with assembly language programs.
There are several other mystery terms running around, such as linker, make-file and so on. Those terms and subjects you can learn as you need to. Generally, by the time you are actually using those types of things, you will be working at a high enough level that they'll be hidden from you.
|
Step 9| A few details about the Motorola MC68HC11 microcontroller 19 Oct 2000 | The HC11 has on it a number of hardware ports; ports A, B, C, D and E. By 'hardware,' we mean that these ports are designed to communicate directly with the outside world. Some of these ports are dedicated to certain tasks when the HC11 is used as we are using it, and are not available for us to use for reading sensors or driving electrical devices. For instance, part of port D is taken up with RS 232 communications, and ports B and C are entirely unavailable when we use the 32K of RAM that is on the TCOMP board. Of the unused ports, some are hard wired as digital outputs, some are digital inputs, some can be programmed to be either, and some can be used for digital or analog input. One of the ports, port A, has some very special capabilities called "input capture" and "output compare," abbreviated IC and OC. These special features do things for us when we require fancy timing of output events that are either too cumbersome or too time consuming to do in software. In addition, they run very quickly, and let us capture inputs we otherwise might have trouble detecting. And although these special features of port A use the 2 MHz clock signal from the HC11, they otherwise run external to the computer itself, not taking up any processing time. That is to say their operation is not part of some program being run in the computer, although the special port features are set up (configured) in software. The presence of these special features, such as the A/D conversion and the IC/OC ports, are part of the reason why the HC11 is called a "microcontroller." Small computers without special port features are called "microprocessors" or "microcomputers."
As stated in the introduction, we are not going to work with the complicated features of the HC11, such as the IC/OC capabilities. We only want to know that some of them are there. Once we get through the process of learning to write simple programs, getting connected to the HC11, etc., you can learn about these other things at your leisure. You will undoubtedly want to use some of them at some point in time.
Now, lets begin a discussion of the kinds of memory present on the TCOMP, and how it is utilized. Think of memory as the worlds largest mail room, with thousands of pigeon holes, each one just big enough for an eight bit binary number. Each of these boxes has an address on it, a little tag with a hex number. We can get the computer to put things in any slot, or take things out of any slot, after first giving it the address of the slot we want to work with. Remember we said that the computer, being an eight bit device, only deals with numbers that are eight bits long? Well, for addressing purposes, what the HC11 does is put two eight bit numbers together to make a sixteen bit number. With sixteen bits, the computer can address 64K mail slots. The actual number of the highest numbered slot (in hexadecimal, the format we usually use to address memory) is FFFF. The lowest slot address is 0000. So the memory space is from 0000 to FFFF. Interestingly, the HC11 uses a little of this space for itself. More on that later. The rest of the memory addresses are available for us to use as well, but we generally do not use all of them. The internal 512 bytes of RAM in the E1 chip is one of those places we won't use. PCBUG will use the internal RAM, and we could use some of it too, but we won't. There is also a small EEPROM on the chip which can be used, but it falls in address space that we want to use for something else (external RAM), so we won't be using that either.
Now, some of you who have been around the barn a time or two will know that EEPROM consists of 512 bytes of non-volatile memory, and you might want to use it. Go ahead. The rest of us, knowing nothing of EEPROM, are going to keep on knowing nothing. Why? Because we have a great big 32 kilobyte RAM chip on the TCOMP board that we are going to use for our memory. What ever we put in there will stay there until we take it out, write over it, or unplug the battery that keeps it backed up. If you are using the Super-T, there is a long-life lithium battery on board that keeps the RAM memory safe. For about ten years or so, long after your Super-T has been buried under old sweaters in the closet, there will be programs and data in there just waiting to be let out. Kinda creepy when you think about it. There really is something alive in the closet.
Even though there is 64K of memory address space available, it is rare that more than 32K is used although it can be done with a little added complexity. But most people and board makers seem to be satisfied with 32K of memory, which is easy to implement. As you will discover on your own, 32K is lots of space.
The memory in our 32K RAM storage area starts at address $8000 and goes to $FFFF. We can use all of it except for a few addresses at the very top of the space, which are used by the HC11 for storage of some important data; the reset vector and the interrupt vectors. We will talk about the reset vector in detail later.
|
Step 10| scratch-pad areas 19 Oct 2000 | e will now talk about two scratch-pad areas in the HC11, accumulator A and accumulator B. These are areas where the computer does some work. Lets say we want to add two numbers together, and store them in memory for later use (say, in the next microsecond, or not for a few years). In words, what we say is, "Computer! Add 2 plus 6 and put it in memory location $8000." In assembly language, it goes;
LDAA #$02
ADAA #$06
STAA $8000
Boy, doesn't that look simple? We say, LDAA #$02, which means put the hex number 2 in accumulator A (hex 2 is the same as decimal 2), ADAA #$06, which means add hex 6 to what is already in accumulator A, and then go to that big mail room and STAA $8000, meaning find the slot with the address $8000 and put the contents of accumulator A in there. Implicit in the store command is that if something was already in the slot with the address $8000, it is overwritten with the transfer of the new number.
We could do the same thing using accumulator B. The instructions change to:
LDAB #$02
ADDB #$06
STAB $8000
The lesson learned here is that accumulators A and B are places where we work on things. There are other places like these two accumulators, but as usual, we aren't going to talk about them much, if at all, because they work in similar ways.
Now, just a little about the I/O ports on the HC11. There are physical inputs and outputs on the chip, as we've said, that allow the computer to both send out information and get it back in. Lets just focus on port A, since that is all we are going to use for now. Look at the drawing that came with your board, the one showing the plan view with the location of the output connectors, and locate the part that shows what signals are available at output connector J8. Among other things, you will see that port A pins 0 through 7 are there. Hmmm, 0 to 7, that makes 8 pins. Eight bit computer, 8 bit ports. Yep, makes sense. Some of these pins are digital inputs, some are digital outputs. Pin 6 is a digital output, and pin 0 is a digital input. The pushbutton and LED circuits we built earlier are plugged into those two ports, so suddenly we find ourselves quite interested in them.
Lets say I want to turn on (assert is the term) pin 6 so the LED connected to that pin will light up. When I show you the assembly language routine for doing this, you are going to get a huge surprise. The address for port A is in the mail room along with the rest of the slots numbered from $0000 to $FFFF! In words, we tell the computer this: "Computer! Load the hex number $40 into accumulator A, then write that number to port A." Note from before that the hex number $40 is the same as the binary number %0100 0000 (space added for clarity). The one is in the sixth position (we number from 0 at the extreme right of the binary number to 7 at the extreme left). The pin we want to assert is pin 6 of port A. When we "write" $40 to port A, pin 6 will go to +5 volts, and an LED connected to that port will illuminate.
The assembly language code to do that looks like this:
LDAA #$40
STAA $1000
See? We load accumulator A with $40 (the # is known as "immediate addressing," and causes the number following to be stored in accumulator A. If we didn't have the # sign there, the computer would think we wanted to store the number located in memory address $0040 into accumulator A, and it would do just that). Then the computer stores it's contents into the memory location with the address $1000. Egad. I just told you that we were going to write to port A, and here we stored into a location within our range of memory instead. But it turns out that the HC11 uses part of its memory space for its own purposes, just as we said before. And it uses, among other things, address $1000 as the location for port A. Storing into address $1000 is how the HC11 writes to port A.
Recall that the range of memory addresses from $0000 to $FFFF constitutes the minimum and maximum range of the "memory map" of the HC11. When input and output port addresses are located withing the memory map of a computer, then the computer has what is known as "memory-mapped I/O." That's a really fun buzz word, isn't it? "Memory-mapped I/O," one of my personal favorites. It means that we treat the I/O port addresses like any other address in memory. And we don't have to worry about accidently trying to store our own programs or data in memory-mapped area for port A, because we have chosen our external RAM space to be at addresses starting at $8000, well above $1000. That is why we did it.
OK, we did an output from the computer. If we want to see if there is a real-world signal present on pin 0 of port A, an input pin, it gets just slightly more complicated. The assembly language code to see the state of all the pins on port A looks like this:
LDAA $1000
That's it. The state of each pin is stored in accumulator A. The contents of accumulator A may now look like this: 00001111. But it is necessary to realize that input pins 0 through 3 are always going to be high (5 volts on them) without anything connected to them at all. Find the schematic for the TCOMP (or Super-T, they are the same in this area). Next find the port A connections in the lower left-hand part of the drawing. Notice the resistors that are connected to each of pins 0 through 3 with the other ends connected to +5 volts? Pins 0 through 3 are all input pins, and those resistors are called pullup resistors. The resistors "pull up" the voltage on pins 1 thru 3 to 5 volts. The reason for this is that we don't want those pins to float, we want something definite on them. We can't tie them to ground, because then any external voltage applied to one of the pins would be shorted dead to ground and something would fry. So we have to tie them high with pullup resistors, giving us the situation where if there is no input present on one of our input pins, the pin will be high (1). (Of course, that is contra-intuitive; its on if its off. Better get used to it, though. You will see it again many times in your microcontroller career!) If we want to change the state of this pin with an external device such as a pushbutton switch, we have to have that device ground the pin. Look at how we have the pushbutton switch wired, and you'll see that is what it does; ground the pin it's connected to. That makes the computer see that pin as 0 (low). It's not a problem, though. You'll see soon how we deal with this in assembly language.
|
Step 11| Our very first assembly language program 19 Oct 2000 | We have a pushbutton connected to pin 0 of port A, and an LED connected to pin 6 of port A from earlier. Lets see if we can make them do something.
Turn on your computer under WIN95, WIN98 or whatever you've got, and create a new folder on the C drive called TCOMP. Then, open a DOS window and CD your way over to the TCOMP directory. If you are really green, like your author, do that by typing "CD.." until you are all the way down to the C root directory, then type CD TCOMP, and you are in. Open up a text editor under DOS by typing "edit FROG1.asm" at the DOS prompt. (Archaic it may be, but there is a reason for it; some programs written for PC's are not upward compatible! Gasp. Some people cannot get some of the tools were going to use to run on fast machines under the high-zoot operating systems. You may be one of them, and we don't want you frustrated.) Type in the program that is shown below, and save it to C:\TCOMP\FROG1.asm as you quit the editor. If you aren't familiar with the editor, try using the TAB key and the ALT key when you get stuck. There isn't much to it. Note that we are going to put other stuff in the TCOMP directory, so be sure to create it. And be sure to indent the program as shown when you are typing.
ORG $FFFE
FDB $8000
ORG $8000 ; I can put comments in after a semicolon, so I will
LABEL LDAA #%00000001 ; this is the mask I'll use to look at port A
ANDA $1000 ; logical "and." If port A anded with the mask = 0, pin zero is on.
BEQ LITEON ; if 0, branch to the area of the program that turns on the LED
LDAA #%01000000 ; otherwise, load a mask to check pin 6
ANDA $1000 ; check to see if the lite is on already
BEQ LABEL ; it isn't. Go back and start over
LDAA #%01000000 ; otherwise, load in a mask to change bit 6
ORA $1000 ; change only bit 6, making it 0
STAA $1000 ; write the result to port A, which turns off pin 6
BRA LABEL ; branch always back to the start
LITEON LDAA #%01000000 ; load a mask to use
ORA $1000 ; without changing the other bits, set bit 6 to 1
STAA $1000 ; write the result to port A, turning on pin 6 and the LED
BRA LABEL ; go back and repeat forever
This looks impossible if you haven't worked with assembly language before, but like everything else, it's simple after learning a little about it. Lets study it one line at a time.
We will talk about the first two lines in detail later. For now, just know that they tell the TCOMP where to start running its program when the power to the board is cycled or the reset switch on the board is pressed.
|
Step 12| The third line says this 19 Oct 2000 | ORG $8000
There are two things to say about this line. First, notice that we tabbed over a few spaces before we typed this instruction. We did this because anything that is placed at the first character position on a line is understood to be a "label". Since this is not a label, a label being a name for a particular line, it can't be located in the first character position. Although we could have started this line in the second character position and have been ok, when dealing with non-label instructions it is common for readability purposes to tab over a bit, which is what we did.
The second thing to say about this line is what it means. This is a specific type of instruction that tells the assembler, the program we will use to convert our program to machine language, at what memory location to begin loading our program when we get to that point. Remember that we are using 32K of external ram on the TCOMP, and that it starts at address $8000? This tells the assembler to convert the assembly language program in such a way that it will load in starting at address $8000. That's all it means; the origin (ORG) of the program is to be at $8000. This instruction is to the assembler, not the computer, and is not an OpCode. It will not load into the HC11 memory.
The next line of the program causes something to be loaded into accumulator A:
LABEL LDAA #%00000001 ; this is the mask we'll use to look at port A
We have done this very thing before, so it is not new to you. What we did is "load immediate," the # sign obviously meaning "immediate," the binary number %00000001 into accumulator A. In the comment to this line, we call this binary number a "mask," which means in effect we are going to look through it and see what we can see. In front of the line is the label for this line which we cleverly called LABEL. It could have been called something else, like SHOE or GRAPE. Generally, we pick a label that has some meaning for us. A better name for this line might have been START. We'll be more careful how we assign our next labels so they will mean something.
The next line will loose you for sure, so spend some time looking at it. There's quite an important concept involved here.
ANDA $1000 ; logical "and." If port A anded with the mask = 0, pin zero is on.
What this line says is to logical "and" the contents of accumulator A with the contents of memory address $1000. Note that if we had placed a # in front of the number $1000, then what we would have been saying is to "and" with the number $1000, not with what is located in address $1000.
Before we discuss what "and" is, I want to remind you that the HC11 has memory-mapped I/O, and that address $1000 is the location of port A.
Now, what is a "logical 'and'" and what can it do for us? What we are wanting to do in general in this section of the program is look at the state of pin 0 of port A, where we have hooked a pushbutton switch. If we push this switch, we will ground pin 0, and the value of pin 0 will be 0 when the HC11 reads the port. If we are not holding the button down when the HC11 does a read of the port, pin 0 will be high, or 1. It is held that way by the pullup resistor on this pin. It would be nice if we could just tell the computer to check this pin on this port, and see what it says. It isn't quite that simple, because the computer looks at all 8 pins at once, not just one of them. Somehow, we need to isolate pin 0 in software, so we can just check that one and see if it is 1 or 0. That is where the "and" comes in.
If we "and" the two numbers 1 and 0, we get 0. If we "and" 0 and 0, we get 0. If we "and" 1 and 1, we get 1. What we are saying with the "and" instruction is "if the first number is 1 and the second number is 1, then the result is 1. Otherwise, the result of the and is 0." Let's take this further, and be prepared for a surprise.
Lets "and" the binary number %11001001 with our mask, %00000001, and see what we get. It looks like this:
11001001 (assume this is what port A looks like when we read it)
00000001 (our mask)
00000001
|
Step 13| BEQ means "branch if the result of the previous operation was equal to 0" 19 Oct 2000 | BEQ means "branch if the result of the previous operation was equal to 0" to the line with the label LITEON. If the 'AND' operation from the previous line came back 0, the computer would skip to the line with the label LITEON and continue executing from there. It is obvious what is going on because of the more considered assignment of the label name. If the pushbutton was depressed, the AND operation would be 0, as we saw above, and the computer would jump to a section of the program somewhere labeled LITEON, and probably turn on the LED.
If the AND operation didn't produce a 0, then the line with the BEQ instruction is ignored and the next line after it is executed. That gets us to the next line in our program:
LDAA #%01000000 ; otherwise, load a mask to check pin 6
All this means is to load the accumulator with the mask we've given it. Remember that the # means to load the number which follows, not the contents of a memory location with that number as an address.
The next lines are:
ANDA $1000 ; AND the mask with port A. If we get 1, the LED is on
BEQ LABEL ; if it isn't on, AND equaled 0. Go back and start over
Reading the address $1000 gives us the existing state of all eight pins on port A. ANDing port A with the mask will tell us if the LED is on or off. It could be on, because we may have pushed the button at some time in the past, and the LED would still be on. If it is off, the AND will return a 0 and the next line, BEQ LABEL, will send us back to the start of the program. But if it is on, the BEQ LABEL line is skipped (not executed is a better way of saying it), and we drop through to the next line.
If we got here, it is because the LED is on and we want to turn it off.:
LDAA #$01000000 ; load a mask again
EORA $1000 ; exclusive OR port A with contents of accumulator and put the
; results back in the accumulator
We want bit 6 to be 0, because that is the pin the LED is connected to. If we just said something like LDAA #%00000000 and then said STAA $1000, that would turn off pin 6 alright, and all the rest of the output pins as well. That would be a problem if we had a lot more LED's hooked up and we didn't want to turn them all off as well. So what we do is use an OpCode called the "exclusive or," EOR.
What the "exclusive or" does, also known as EORA in mnemonic form ('A' because we are using the operator with accumulator A), is to perform a bitwise check of each bit between what is already in accumulator A (the mask), with data somewhere in memory, in this case at address $1000, our memory-mapped I/O location for port A. The result of each bit-wise comparison is 1 if either one or the other of the compared bits is one, but 0 if both the bits are 1 or both bits are 0.
Lets assume that port A looked like this when we read it: %11001001. We know that bit 6 is 1 already, because the LED is on. Otherwise we wouldn't be doing this. Now, let's "EORA" what we see on port A with our mask, %01000000 and see how it comes out.
11001001
01000000
10001001
|
Step 14| All we changed was bit 6 19 Oct 2000 | See? All we changed was bit 6, and we turned it off. The rest of the bits are unaffected. Selectively changing bits like this is called "bit packing." Since the result of the EORA operation, 10001001, is now in accumulator A, lets put it back out on the port. This will shut off pin 6 without changing any other pin:
STAA $1000 ; write the result to port A, which turns off pin 6
BRA LABEL ; branch always (BRA) back to the start
BRA is an unconditional branch. It means "branch always." Anytime we run into one of these, we are off to somewhere no matter what.
So that's about it, except for the first two lines of code which we'll discuss in just a bit, and a small routine that turns on the LED for us.
To execute the LITEON routine, we are sliding a new OpCode in here that you haven't seen before in exactly this form, the "OR" function. It's like the EOR OpCode with an exception. With the OR function, a bit-wise comparison of two bytes of data will return 1 in each bit position where the two compared bits in the same position are either or both 1, and 0 otherwise. For example:
10110000 (assume port A looks like this)
01000000 (our mask)
11110000 (the result--pin 6 is now on)
In assembly, it looks like this:
LITEON LDAA #%01000000 ; load a mask to use
ORA $1000 ; without changing the other bits, set bit 6 to 1
STAA $1000 ; write the result to port A, turning on pin 6 and the LED
BRA LABEL ; go back and repeat forever
Let's look at the whole thing in complete form one more time. Isn't it a masterpiece?
ORG $FFFE
FDB $8000
ORG $8000 ; I can put comments in after a semicolon, so I will
LABEL LDAA #%00000001 ; this is the mask I'll use to look at port A
ANDA $1000 ; logical "and." If port A anded with the mask = 0, pin zero is on.
BEQ LITEON ; if 0, branch to the area of the program that turns on the LED
LDAA #%01000000 ; otherwise, load a mask to check pin 6
ANDA $1000 ; check to see if the lite is on already
BEQ LABEL ; it isn't. Go back and start over
LDAA #%01000000 ; otherwise, load in a mask to change bit 6
ORA $1000 ; change only bit 6, making it 0
STAA $1000 ; write the result to port A, which turns off pin 6
BRA LABEL ; branch always back to the start
LITEON LDAA #%01000000 ; load a mask to use
ORA $1000 ; without changing the other bits, set bit 6 to 1
STAA $1000 ; write the result to port A, turning on pin 6 and the LED
BRA LABEL ; go back and repeat forever
Now let's deal with the first two lines of the program, which we have put off until now. After we have the program loaded into the TCOMP, we want it to run when we turn the board on. The HC11 chip doesn't have a "run" switch on it. The toggle switch on the board is just to turn the power off and on. Instead of having a "run" switch, the HC11 chip has a factory feature that makes it run as soon as power is applied to it. All it needs to know is where to start executing code.
If we have our program in memory someplace, and we want it to run when power is applied to the HC11, we have to tell the HC11 where our program starts so it knows where to begin execution on power-up. At the start of our program, we put the statement ORG $8000 because that is were we decided to have our program begin loading into memory. We could just as well have it located at $B600 (the start of EEPROM if we were using it, which we aren't, but in your later research you will see programs loaded there all the time). We could also have caused it to load at $A000, or anywhere else in our address space between $8000 and $FFFF that isn't being used by the HC11 for its own purposes. Unless we tell the HC11 where to start, it will not start at the beginning of our program. It will start someplace for sure, and execute garbage, but that doesn't do us much good.
When we cycle power to the board, it is called "resetting" the board. In mathematics, a line with both magnitude and direction is called a "vector." A vector points at something. The address we give the computer that tells it where to begin executing after a reset is called the "reset vector." We have been glossing over comments about how the HC11 uses some addresses in our memory space between $8000 and $FFFF for its own purposes, and the location of the reset vector is one of them. It is located at the very top of our space, taking up addresses $FFFE and $FFFF. Remember that addresses require two 8 bit words to specify them (the HC11 uses 16 bit addressing for memory)? Because of this, it takes two spots in memory to contain the reset vector; $FFFE and $FFFF.
The first two lines of our code store the reset vector:
ORG $FFFE
FDB $8000
|
Step 15| What that means is; 19 Oct 2000 | What that means is; starting at address $FFFE, form a double-byte constant with the value $8000. $8000 is a double-byte constant as we see. The first byte, $80, will be stored at $FFFE, and the rest of it, $00, will be stored at $FFFF. Each location can only hold a single byte, so it takes two memory locations to store a double byte-constant.
Now, when we reset the board, the HC11 will look for the reset vector at address $FFFE and pull out a byte at that and the subsequent address, coming up with $8000. It will then go to that address and begin executing what it finds, which is our program, FROG1. Couldn't be easier.
We have learned a lot. We can get things into the computer from the real world, we can get information out to the real world, and we can get the computer to make some decisions. We can read individual pins and change individual pins on port A. There is lots more to learn about assembly language programming, but that is all we need to learn to finish what we set out to do. This was a big step, but it could have been bigger.
The code as written is sloppy and wasteful. When you write code for real, and not just for the purpose of explanation, you must pay very close attention to how long it will take for your code to execute. Half the reason for writing in assembly to begin with is so that the code will execute lightning fast. In the instruction set chart for the HC11, each OpCode has listed next to it a number indicating how many "ticks" (clock cycles at microsecond each) it will take for that particular OpCode to execute. You can add them up, and see how long it will take to run through part of all of your program. Sometimes there are OpCodes that do the same things as other OpCodes in slightly different ways. They are really meant for specific applications, and the programmer is expected to pick the fastest one that suits the particular need. It is easy to pick the wrong one, and even though it might still work, maybe it does so at the expense of a microsecond of execution time.
Some may be wondering where a microsecond here or there could matter. RADAR is one such place, and in fact if a microsecond as the best resolution available, one can forget direct RADAR or LASER control entirely. However, SONAR is another matter. It is possible to direct control SONAR, because sound waves are relatively slow. Another example comes to mind that might express the value of program execution time. A couple of years ago, a system was demonstrated that could be used to locate a sniper with a high-powered rifle. It was done by using a computer and some kind of ranging device to track a single inbound rifle projectile. If memory serves, before the projectile impacted, a solution was available giving both the azimuth and range to the origin of the round to near perfect accuracy.
So the point is made. First learn to write in assembly, then learn to do it well.
Assembling FROG1.asm with AS11:
Somewhere you have a disk running around that you got from Ray's with your board. On it are a bunch of files that you can move onto your computer now. Start up under Windows, and, if you haven't already, create a subdirectory called C:\TCOMP\ and put everything off the floppy in there. Put Tiny4th and SBASIC in their own directories within C:\TCOMP\ so they are out of the way. Now extract the pcbug11a.zip file by clicking on it. Make sure the destination file is C:\TCOMP\.
Done? If so, there is now a program called AS11 in the C:\TCOMP\ directory that we will use to assemble FROG1.asm. FROG1.asm should be in this same directory (if it isn't, move it there now). Our program, FROG1, is called the source file or "source code," just so you know the terms. AS11 will turn it into OpCodes. AS11 will create a file for us with the same name as our original file, but with a .s19 suffix. The new file is called an "object file."
Before we assemble our source file with AS11, we want to back down the technology ladder a bit. I am a Macintosh person, and I'm writing this in part because there are often times I can't get my darn PC to do what I want. Sometimes that is because I don't know what I'm doing, and sometimes its because the PC can't do what I want from the Windows environment. All the 'help' stuff around regarding what we are about to do assumes a moderate level of PC expertise that not everyone has. If we try to do this in Win95 or Win98, it may or may not work. Even if we open a DOS shell from Windows, it still may not work. Those who are really hot can see if they can get things to run at a higher level, but the rest of us are going back to the days of yesteryear.
Shut down your computer now, and reboot in the DOS SAFE mode. Do this by holding down the F8 function key right after you push the ON button on your PC, and before you see anything appear on your screen. Shortly you will get a message that you have bypassed your start-up files. Now pick the selection that says "safe mode command prompt only." You should then get a DOS command prompt >. Get to the directory that has our program and other files in it by typing CD TCOMP. Check to see if you are there by typing DIR\P and keep hitting the return key until you get to the end of it. You should see some files with names that kind of mean something to you by now. We in? Good.
Now, run the assembler by typing it's name with the name of the file we want to assemble, thus: AS11 FROG1.ASM. If there are errors, AS11 will give us a hint what the errors were, such as "unrecognized mnemonic (13)", which means that it didn't recognize the instruction on line 13 of our source file. If that happens to you now, the program as written above is correct, so you have a typo in the program, or something else wrong in the way you entered it. If it does run, you will get back a command prompt, and there will be a new file named FROG1.S19 in the C:\TCOMP\ directory. Go ahead and open the new file by typing EDIT FROG1.S19. What you are looking at is an object file in hex. If you look at it long enough, you will be able to pick out some of our program embedded in there, along with some other things that have to do with parity checking, and so on. If it was really necessary, this could be read and converted back into the original object code, although it would be missing comments, ORG statements and other assembler directives, and there would be some modifications to the code made by the assembler. Ok, now close after hitting the ALT key to bring up the menus. We are done with this part.
|
Step 16| Connecting the TCOMP and placing the HC11 into the "special bootstrap" mode 19 Oct 2000 | First off, before we can download a file, you need to connect the TCOMP to your computer. If you are brave (I am), go ahead and connect the 9-pin end of your special TCOMP communications cable to COM1 on the back of your clone with it running. (If you are not so brave, shut everything off first and then plug it in.) If the mouse is in the way, just unplug it. We don't need it anyway. The other end of the TCOMP communications cable has a female 4-pin receptacle, and that goes on the male 4-pin header right next to the toggle switch on your board. The arrow on the receptacle goes closest to the toggle switch. If you didn't purchase an assembled cable with your board, and are not sure which way is which with your receptacle, just guess. If it's the wrong way, we'll correct it later on.
Making sure the battery pack for your TCOMP is connected to the board, turn the TCOMP on with the toggle switch. The power LED on the board should light up. If the LED doesn't light, it is a good time to panic. Make sure the center conductor on your power plug is positive, and make sure your batteries are good and installed correctly in your holder, and try again. If you still get no LED illumination on the board, it's time to get out the volt meter and figure out what is going on.
Now, with everything turned on and plugged in, and your PC running in DOS SAFE mode, we are going to put the board into a mode to accept serial data from the RS232 port of your computer. To do this, we put the HC11 in "special bootstrap" mode. We won't go into an explanation about what happens exactly, because we don't need the esoteric detail. All we really need to know is that we need to be in this mode to download programs. To set this mode, we are going to depress the two pushbuttons on the board in a certain sequence that will put us there. The pushbutton closest to the toggle switch is the 'reset' button. Find it, and get to know it's name and location. The other button, the one farther away from the toggle switch, is called the "mode" button. Now, holding your breath and making sure the cat is out of the way, hold down the mode button. While you are holding it, depress and release the reset button. Now release the mode button. The TCOMP is now running in "special bootstrap" mode and is waiting for things to come down the serial line from your PC in a format it can handle.
Downloading the object file FROG1.s19 into the TCOMP:
Having set up for downloading, we are going to start up PCBUG. PCBUG is an interactive software package that we can use to download and run programs on the HC11. We can also use it to look into and change memory on the board, and do some other things as well. Start up PCBUG now by typing PCBUG11a. You will see a list of options on the screen as PCBUG opens. The first question you see is; "Is the talker installed on your board? (Y/N): __." The answer to this is 'no.'
We have no need to know what a "talker" is, but if we don't discuss it, you will always wonder. On the HC11, there is a small area of RAM memory, taking up the first 512 bytes of address space in the case of the E1 chip (other chips have only 256 bytes). In the first 240 bytes of this RAM space, PCBUG will load a small program called a "talker." This program is for the HC11 to use for communicating with PCBUG, the application running on your PC. Each family of HC11's has its own flavor of talker, as you can tell from all the talker names in the TCOMP directory.
So, there you have it. The talker gets loaded into RAM first thing, and stays until we shut off the board. Given that the contents of RAM are volatile, the talker is lost when power is removed from the board. It is possible to load a talker into the EEPROM memory on the board. This type of memory is not volatile, so the talker will still be there when power is applied to the board next time. That is the question that is asked above when PCBUG first starts up; "is the talker installed on your board." It isn't, so PCBUG will install the talker into RAM to allow the board to communicate with PCBUG.
The second question asked is; "Do you wish to use the XIRQ interrupt? (Y/N):__." Since we have not discussed interrupts, the answer to this is no. Most likely, you will never use this feature.
The third thing you see on the screen is a table with the title; "MCU boot talkers available." There is a list of all the different kinds of HC11 chips for which talker programs are present in our file, with a number next to each of them for us to choose from. '3' is the correct choice in this case since we are using a chip in the range of 68HC11E0/1/8/9 that is listed next to that choice. So, where it asks; "which device are you using? :" we type in 3. When we do that, PCBUG responds with "-E" to tell us what our selection was.
The next option presented is; "PC Communications Port : 1. COM1," and on the next line,
"Which communications port are you using? : __." Here we type in 1.
|
Step 17| The last question is 19 Oct 2000 | | The last question is; "Assume an 8 MHz crystal in use? (Y/N) : __." We use an 8 MHz crystal on the board as our clock, so the answer is yes.
The final line is "Press ESC to quit or any other key to run PCBUG11." Press "enter" and lets see what happens.
If you see one communications error message after another, and then a final statement that says "Last Error : General Communications Failure," then the PC is not talking to the TCOMP. This will be for one of two reasons when we run in DOS SAFE mode. The first and most likely cause is that the TCOMP was not properly placed in the "special bootstrap" mode. So, start over by pressing and holding the "mode" pushbutton (the one farthest from the toggle switch), press and release the "reset" pushbutton, and then release the "mode" pushbutton. Then at the command prompt in PCBUG, type "restart." Restarting PCBUG like this usually works, but if it doesn't, and you get the same communication error warnings, quit PCBUG by typing "quit," and start over again. Try this three of four times, and if you still can't get on-line, it could be that you have either built your cable improperly or plugged it in backwards. Switch the 4 pin receptacle on the cable where it attaches to the board end-for-end, and try it again. (Having the cable plugged in backwards doesn't seem to hurt anything, so don't be concerned about damaging your board if you turn it around.)
Eventually, you will find yourselff communicating with the board. From now on it will be easy. A lot of people have trouble getting to this point, and you can see why.
Now, we have to change a few things before we can download into our external RAM. We originally set our board to operate in the "special bootstrap" mode so we could talk to it via the RS232, and get PCBUG going. But when running in this mode we are unable to address the external 32K of RAM located in the address space from $8000 to $FFFF. We need to put the HC11 into another operating mode, the "expanded" mode, to do that. All we need to do to get the HC11 into the expanded mode from PCBUG is to type in the following two instructions in the command window:
EEPROM $103C $103F, with a carriage return, and then:
MS $103C $E5 with a carriage return. That's it.
Now, we can load in our FROG1.s19 object file by typing:
LOADS FROG1.S19 with a carriage return.
If you watch the screen on your PC, you can see that things are happening. Now, how do we run the program?
If you look at the status area, about mid-screen on the right hand side, you will see that the processor is stopped. There are two ways to get the program to run. The first way is to just reset the board by pushing the reset switch (don't do this, we're just explaining). This cycles power to part of the HC11, and since the board is hard-wired to start up in the expanded mode, the HC11 will retrieve the location of our program from memory (the reset vector), jump to that location, and begin to run. If you did that now, you could push the button we have connected to port A, pin 0, and you would see the LED we have connected to port A, pin 6 come on. But there is a better way to run the program when all we want to do is test it and possibly do some editing. The problem with just pushing the reset switch on the board to run the program is that we dump the contents of the on-chip RAM when we do that, which is where our talker program is running, and we'll loose communication with the board. We can't examine or edit the program currently residing in memory if we can't talk to the board. So instead of running the program by pushing the reset switch, lets start it up by using a feature of PCBUG that lets us run and stop program execution. Type "G $8000" with a carriage return now.
|
Step 18| program counter 19 Oct 2000 | a register in the HC11 that tells the CPU what line in the program will be executed next, is loaded with the address $8000 when we type "g $8000, and the HC11 begins executing instructions at that location in memory. Go ahead and do this. Notice that the status window now indicates that the processor is running. If you depress our new pushbutton you will see the LED come on.
Now type "S" with a carriage return to stop execution. The processor stops, and the status window indicates that it is not running. Pushing the button that we added has no effect.
This feature of being able to control the processor from your PC is known as "interactivity," and it's pretty rare in the HC11 world. It is probably the most powerful aspect of PCBUG.
More fun with PCBUG:
We could almost stop here, but there are a few things that you can do within PCBUG that are worth demonstrating. The first thing that we should know is that, since we are typing in hex numbers all the time and have to keep putting the $ sign in front, we can configure PCBUG to accept hex numbers by default. That way we can type in 8000 and have it interpreted as $8000. We do this by typing in "CONTROL BASE HEX" with a carriage return while PCBUG is running. Do that now.
With PCBUG we can look at the contents of individual memory locations. Since we have already loaded our program into RAM starting at location $8000, lets look at $8000 and see what is in there. First, type "CLS" to get the other stuff off the terminal window (the upper screen). Then type "MD 8000" (we don't need the $ since we set hex to be the default number base) with a carriage return and take a look. It says in the terminal window:
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
8000 86 01 B4 10 00 27 11 86 40 B4 10 00 27 F2 86 40
What we are seeing is the contents of the first sixteen memory locations containing our program. At $8000 is the hexadecimal form of LDAA, at $8001 is the hex number $01, etc. If you look back at our program, you will see that the first line of code that you'd expect to be loaded into RAM is LDAA #%00000001. LDAA is hex 86, and %00000001 is the same as hex 01. We are looking at our program in RAM! But boy, is it tough to read this way. If we really want to see what is loaded in RAM, there is an easier way to read it.
Clear the terminal window again with the CLS command, and lets disassemble the first sixteen memory locations and see if we can get something easier to read. Since we 'assembled' our assembly language mnemonic file to get it to look like what we have just seen, perhaps 'disassembling' will get us back where we started. Type in "DASM 8000 800F" and hit the carriage return. We are telling PCBUG to disassemble from $8000 to $800F, and this is what shows up in the terminal window:
8000 8601 LDAA #$01
8002 B41000 ANDA > $1000
8005 2711 BEQ $8018
8007 8640 LDAA #$40
8009 B41000 ANDA > $1000
800C 27F2 BEQ $8000
800E 8640 LDAA #$40
There is our program. It doesn't look exactly the same as our original source code, but it is discernable. All the comments are missing (comments are for us, and the assembler ignores them), and the labels have been replaced with the actual locations in memory for the jump-to addresses. And the binary numbers we used to make it easy to see what we were doing with our masks have been replaced with hex numbers. But there it is, otherwise identical. If something is not right because we made a mistake, or we want to change the program slightly, we can fix it here.
How? Lets say that on the first entry we noticed that we had made a mistake and typed into our program LDAA #%00000011. When it was later assembled and loaded, the first line above would look like this:
8000 8603 LDAA #$03
To correct the mistake, we would type in:
"MS 8000 86" (MS for 'memory set') with a carriage return, and then "01" with a carriage return.
That would correct the program without us having to go back out, fix the source file, compile it, and then reload it under PCBUG. That is a pretty powerful capability of interactivity. You can alter and test code right from PCBUG. There are some major limitations, of course. For instance, you cannot insert lines of code. But still, there is a lot that you can do with it.
Another feature of PCBUG that is handy for debugging is the ability to see and change the most active HC11 registers. What these registers do is largely outside our range of knowledge at this point, but lets look at them anyway, because some of them we do understand. Later, when you have gotten very good at assembly language and the fine details of the HC11, this feature of PCBUG can be very useful.
In the middle of the screen between the top and bottom windows you see a line of windows with the headers:
PC ACCA ACCB x y ccr (s x h I n z v c) SP
Each window has something in it. The first window is the "program counter," or PC. That is the address of the next instruction that will be run by the HC11 when it is restarted. Right now, the program counter probably has $0000 in it, because it only updates when we ask it to, or on start-up of PCBUG. We know it should say something in the range of $8000 plus, because we have been running programs up in that area, and even though it is stopped, the PC should have the number of the next instruction it would have run in it's window. To get the current contents of the program counter, and the other registers listed above, type in "RD" with a carriage return. You will see something like this, and as a matter of fact, if your program happened to stop at line $8008, this is almost exactly what you would see:
PC ACCA ACCB x y ccr (s x h I n z v c) SP
$8009 $40 $2C $1000 $8000 $40 % . 1 . . . . . . $01FF
|
Step 19| The first register is the program counter 19 Oct 2000 | The first register is the program counter, as we said. If we stopped at line $8008, the address of the next instruction to be executed is $8009, and that's what the program counter points to. The second register, accumulator A, has $40 in it. The third register is accumulator B. This register has something in it, but it didn't get there by anything we are doing. It is what is known as "garbage." It is just a random number that has no meaning for us. The rest of the registers you will learn about as you advance in your own studies. Just remember that you can access them from PCBUG.
Not only can we read these registers, we can also change them if we want, even if a program is executing when we do it (not a good idea, but you can). This may be a handy thing when debugging a program, as you can force the contents of accumulator A to be something that will cause the program to branch in a conditional statement, like BEQ for instance. That might be one reason to use this feature. You can also coerce a program to run from a certain line by changing the PC to the desired start point, and then typing "G" to get the program to run from that point. Let's try it.
At the PCBUG command line, type RM. This allows us to edit the register contents, and you will see the cursor blinking in the PC register. You can move to the other registers at will by using the tab key. Type in 800E and press enter to replace whatever is currently in the PC. Then type G, and the program will begin executing from that spot.
Now, one final thing we can do with PCBUG is to use its built-in text editor and assembler. We can use these features to enter our assembly language source file from within PCBUG, assemble it, and run it. We have no need of either the DOS editor or AS11. Lets see how it functions.
To type in our program, FROG1, we do it just as it is written with two exceptions. We cannot add comments to the lines, and we don't need the ORG statements. To start out, we need to put the reset vector at $FFFE and $FFFF that will direct the HC11 to our program on startup. To make this interesting, we'll install our program in RAM starting at address $9000 this time, so we need to set the reset vector to that address.
Type CLS to get a terminal window, unless you just like looking at all that stuff. Then invoke the assembler on PCBUG by typing "ASM $FFFE" on the command line (you can leave out the $ sign if you want, as we have set the default to hex). This will start the assembler, and it will assemble what you type next and place it at $FFFE. Then you type "FDB $9000" just like we did in our original program. Look at the screen and see what happened. It is all explained there. The ASM $FFFE took the place of our ORG statement, and we placed the reset vector at $FFFE and $FFFF. Press the escape button on your PC to get out of the assembler so we can start the assembler again in a new location.
To type in the main program, start by invoking the assembler thus: "ASM $9000." Then start typing in the program with a carriage return after each line. Don't forget the labels, and be sure to tab in away from the first character position if what you are typing is not a label. When you get done, press the escape key.
Now, type "G 9000" and see if the program runs. When you press the button we connected to the board, our LED should light up. If it doesn't light up, then a mistake was made in typing the program. Type "DASM 9000 900F" to get the first part of your program up on the screen. If you see the error, correct it with the MS command and try again. If you don't find the error in the first part of the program, type DASM again with the address of the next block of code you want to see (9010 in this case) and look again for your error.
That's it for the loading and debugging features of PCBUG. It is actually quite a powerful tool. It even lets you leave the PCBUG application running while you go out into DOS to do something else, such as fix your FROG1.asm file, and reassemble it using AS11. To shell out to DOS to do some work while still connected to your board with PCBUG, just type in DOS on the PCBUG command line you will find yourself in the DOS environment. Do whatever you need to do, and then type "exit" at the DOS prompt to get back into PCBUG.
When you are all done using PCBUG, type "quit Y" to exit.
|
Step 20| Now, a surprise 19 Oct 2000 | Now, a surprise. You know how when we start up PCBUG we have to answer several questions, and then when we are running we have to change to hex base? And then we have to set the HC11 so it will run in expanded mode to accept programs into external RAM? Well, there is a small program that came on your TCOMP disk that does it all for you. (If you have an older board and disk that you got awhile back, or you are trying to do this with a Botboard II or some other board, you may not have the file. If that is the case, the programs are at the end in APPENDIX B for you to type into your computer.) Set up your TCOMP and place it in "special bootstrap" mode. Then running from the DOS SAFE mode, and in the C:\TCOMP\ directory, type in TCOMP.BAT and stand clear. Before you know it (computers are really fast) you are all ready to go.
That's it, we are completely done. Except for one thing.... Really, this is the last thing.
Setting the CONFIG register with the WIPE application:
Remember in the "ground rules" at the beginning we said that we were only going to use the TCOMP to run programs that we loaded into the 32K of expanded RAM? And that we were not going to be using the EEPROM at all? The reason given for this is still valid: we have lots of external RAM, so we don't need the added complexity of using the on-chip EEPROM. It isn't very big anyway. It's only advantage is that what is placed there stays there forever, but in the case of the Super-TCOMP, the RAM is backed by a lithium battery that will probably hold the memory for ten years or more. So, using the EEPROM for practical applications when we have a large external RAM on the board makes no sense. And the very fact that it is there, used or not, is a problem for us that we need to take care of. The problem is that the address space for the EEPROM is fixed, and we can't move it in software. On the E1, the 512 bytes of EEPROM are located starting at address $B600. This address is above the base of our RAM, which starts at $8000, and below the top of it at $FFFF. We have to write programs in such a way that we don't store into the space reserved for EEPROM by accident. Storing into EEPROM, which we don't need to do anyway, takes some special preparations that we don't want to bother with. Attempting to store into EEPROM space accidently will just wreak havoc. So, to make sure we never run into the problem of trying to store into space reserved for EEPROM, we will shut the EEPROM off.
We will use the program called "WIPE" that came on your disk to disable the EEPROM. WIPE has some things about it that we need to explain. It's simple but, as usual, can be confusing.
The "switch" to shut off the EEPROM is in a memory location on the HC11 called the CONFIG register. If you want to check this register while running in PCBUG, it is located at $103F. You can read it from PCBUG, but you can't change it from there. But WIPE will change the CONFIG register for us.
Again, we'll run this application from a DOS SAFE mode. Once in SAFE mode, get to C:\TCOMP\. Turn on your board, and make sure it's connected as before. Place the board in "special bootstrap" mode as we have done all along. Now, run WIPE by typing in its name at the DOS prompt: WIPE. When it starts up, the WIPE screen says:
***************************************************************************
Do you want to:
(1) Erase EEPROM and change CONFIG register
(2) Defeat F8HC11 Autostart
Enter choice by depressing a 1 or 2 key
***************************************************************************
The correct selection for this is 1. The next screen says:
***************************************************************************
These are the current WIPE settings
(X) Crystal frequency of the MPU is 8 MHz
(C) Communications port selected is COM1
(P) CONFIG register to be programmed for:
security mode disabled
cop system disabled
internal ROM enabled
EEPROM enabled
If these setting match the MPU configuration
depress the enter key
To change a setting depress the key in ()
of the parameter to be changed.
***************************************************************************
We will see the above screen appear again later. This screen shows the crystal frequency, the COM port setting and the current setting of the CONFIG register. The first time through, the frequency and the COM port will be correct, but the CONFIG register will be wrong. We need to change it, so type in 'P' with a carriage return, and you'll get the next screen:
***************************************************************************
The CONFIG register of the ()68HC11xx may be programmed as follows:
B7 B6 B5 B4 B3 B2 B1 B0
| x | x | x | x | NOSEC | NOCOP | ROMON | EEON |
B3 SECURITY, 1 = DISABLED 0 = ENABLED
B2 COP, 1 = DISABLED 0 = ENABLED
B1 ROM, 1 = INTERNAL 0 = EXTERNAL
B0 EEPROM, 1 = ENABLED 0 = DISABLED
MAKE YOUR SELECTION AS A 4 DIGIT BINARY PATTERN, IE 1101
***************************************************************************
Study the above for a minute. See that only 4 bits of the CONFIG register are used? Bits 7, 6, 5, and 4 can be anything (that's what the x's mean in those bit positions), and the other 4 bits determine the setting of the register. The settings we want will have "security" and "COP" disabled. Those are features only used by professionals. Bit 1 controls the ROM, meaning "read-only memory." The correct setting for ROM is 0. Bit 0 turns the EEPROM on or off. We want that off, so the correct setting of Bit 0 is 0. So we type in 1100 and get the next screen.
***************************************************************************
GROUND MODA AND MODB THEN DO A RESET.
DEPRESS ANY KEY WHEN READY TO CONTINUE
***************************************************************************
For us, that means put the HC11 in the "special bootstrap mode," which we do in the usual fashion: hold down the mode pushbutton, press and release the reset pushbutton, then release the mode button. That places the board in the special bootstrap mode and we are ready to proceed. So, press any key after that and get the next screen:
***************************************************************************
Started download of program to MPU
Completed download of program to MPU
MPU NOT RESPONDING
CHECK CONFIGURATION BEFORE DISCARDING
RESTORE MODA AND MODB TO OPERATION
AND RESET MPU
DO YOU WANT TO RUN WIPE AGAIN (Y/N)?
***************************************************************************
Here, you type in Y. Go through the process a second time, and check the stated condition of the CONFIG register when you get to the appropriate screen. Just to be safe, I make the change again, as I never really trust it the first time. The final time through, when it asks at the end if you want to run wipe again, type in N. Then, just to make sure, go into PCBUG, and check the CONFIG register at address $103F. It should say 0C. If it says 0D, which is the setting of the stock chip, then something didn't work right and you need to run WIPE again.
|
Step 21| Conclusion: 19 Oct 2000 | nce you have accomplished the above, you are ready to go on your own. The references given in Appendix A that pertain to assembly language are all you will need to extend your programming prowess to the level of expert. Assembly language programming should be learned well, even if the language ultimately used for the bulk of your programming is something like C. There will always be occasions when you want to study someone else's work that is written in assembly, or talk directly with your TCOMP, which again requires expertise in assembly. And when using Interactive C, or some other interpreted language that executes instructions fairly slowly, there are some things that simply cannot be done without embedding assembly language routines in your code. So the time spent learning assembly will be well spent.
A personal note from the author:
I learned all this the hard way, which was to dig and dig and dig until I finally got it. Many hours have been spent just in learning that the foolproof way to get PCBUG to run on a fast computer is to run in the DOS SAFE mode. I have yet to see that published anywhere, and it may be that we are the only ones who know it.
It will be very aggravating sometimes to take even the smallest step in advancing your knowledge of the TCOMP. However, the sense of satisfaction gained from learning well something as complex as this device comes in equal proportion. Hopefully, you have avoided the most common pitfalls of the new user of the HC11 by having gotten this far. But do not think that you have avoided all difficulties -- they have just begun. We are working with a very powerful computer at the lowest level of interaction. It is expected by both the publishers of data for the HC11, the programmers of tools for the HC11, and by the HC11 itself, that you, the user, are an expert. As a result, each new thing you learn will come only after dedicated effort on your part. When you have mastered it, you'll become a member of a very exclusive and elite group of people. Good luck, and have fun.
|
| |
|
|