⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 appendxa.htm

📁 嵌入式软件开发.rar
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<head>
<title>Appendix A</title>
</head>
<body>
<h1><a name="appendix_a">Appendix A The Cosmic Compiler</a></h1>
<p>
In programming microcontrollers, one of the major tasks of the programmer is to make 
use of the peripheral components found on the chip.  Most chips have components like 
timers, serial communications ports, serial peripheral ports, analog to digital converters, 
even electrically erasable programmable read only memory-EEPROM.  We will find it 
very convenient to treat these components as objects and access them by merely sending 
instruction messages to an appropriate object.  We have seen before that most treatment 
of objects in published material has to do with data structures treated as objects.  We 
cannot avoid this important use of objects. 
<p>	In Chapter 2, all of the objects treated were designed to operate on a large 
computer.  In later chapters, none of the objects will work with a large computer.  These 
objects are all designed to operate on a micro controller, the M68HC16, to be exact.  The 
processors considered for use in this text included the M68HC11, the M68HC16 and the 
M683XX chips.  The M683XX family has one major advantage when it comes to OOP 
for a microcontroller.  It is a large enough computer that you can buy C++ compilers for 
it.  The other chips are significantly smaller in internal CPU structure, but they have 
peripheral components that are similar, and in the case of the M68HC16, as exactly the 
same as those found on the M683XX parts.  These chips are so small that there will 
probably never be a C++ compiler written for them, but in today's market, these chips are 
much more popular than even the M683XX chips.  The M68HC16 has an internal 
structure that is quite similar to that of the M683XX family.  They both have an 
intermodule bus which interconnects the CPU with the chip peripherals.  The peripherals 
are all memory mapped are placed in the highest memory page in both sets of chips.  The 
peripheral components are exactly the same on the M68HC16 and the M683XX chips.  
We can, therefore, create header files to access the registers and bits within the registers 
for these chips, and with the exception of an offset to the beginning of each module, the 
header files for both the M68HC16 and the M683XX family of chips will be the same.

<p>The compiler used for this text is the Cosmic M68HC16 compiler.   This compiler 
creates excellent code for the M68HC16.  Cosmic also sells compatible compilers for the 
M68HC11 and the M683XX chips.  It is not the intent of this text to teach you the ins and 
outs of any compiler, but enough of the compiler will be discussed to allow you to work 
with it.  The operation of the compiler is complicated by the nature of the M68HC16 
chip.  This chip was designed to be compatible with the M68HC11.  The major additions 
to the M68HC16 was the intermodule bus, the bus peripherals, a truly sixteen-bit CPU 
and expanded memory access.  The M68HC16 can access up to 1 megabyte of data 
memory and 1 megabyte of program memory.  This memory is broken into sixteen blocks 
of 65 kilobytes  each.  Such a memory organization requires that the compiler handle 
these blocks or pages of memory.  The data are addressed either directly (called extended 
addressing on this chip) or indexed.  In either case, a twenty-bit address is needed to 
access any byte in memory.  The basic computer has three index registers, a program 
counter, and a stack pointer that are each sixteen-bits wide.  To give these registers the 
necessary width to access the total memory range, the chip designers provided each 
register with a four-bit extension register.  These registers are known as the XK, YK, ZK, 
PK, and SK respectively.  Additionally, for extended memory addressing, there is a four-
bit extension register called the EK.  These four bits are appended to the address of any 
direct  data access.  The contents of the extension registers are always the most 
significant four bits of any address.
<p>	Depending on the program, the size of the data memory used, the program 
memory used, and so forth, these extension registers are usually set to some value at 
initialization of the program and then changed only when necessary while the program 
executes.  It is possible in some instances to set the extension registers for all data 
accesses and never change them during execution.  For example, if all of the data storage 
can be contained within a single 65 kilobyte page the extensions probably need never be 
changed.  On the other hand, if the data storage spreads over several pages, the program 
will contain many changes to the respective extension registers during normal execution.  
<p>	The compiler needs a means of identification of data that potentially will require 
extension register modification when being accessed by the program.  If a variable is to 
be placed in a memory location that requires a full twenty-bit address, the variable is 
identified by the flag @far when it is declared.    
<p>	Extensive use is made of header files created specifically for each chip.  A 
complete set of header files for the M68HC16 can be found in Appendix B.  A listing of  
a portion of the file gpt.h is shown below.  This file allows access to the General Purpose 
Timer on the M68HC16.  Quite a bit of the file is not shown here because it is repetition 
of bit definitions similar to those shown below.  Note that this header begins with the 
usual conditional compile directives to prevent its inclusion in the code stream more than 
one time.  Two type definitions of structures create two new types that will be used later.  
Note that these types contain individual bit fields, and these fields are named.  The names 
of the fields are taken directly from the GPT Manual .  The names of the registers are 
also found  in the Manual.  Therefore, the GPT Manual is the documentation upon which 
all code for the operation of the General Purpose Timer in the M68HC16 will be based.
<p>	There are some unused bits in the bit fields defined by the structures.  It is 
necessary to name these unused fields with unique names.  Here, we will use a name 
Nul1gpt or Nul2gpt to create names that will probably not be used elsewhere in any 
program.  
<pre><code>
	#ifndef GPT_H
	#define GPT_H

	typedef struct
	{
	     unsigned Nul1gpt : 4;
	     unsigned VBA     : 4;
	     unsigned IRL     : 3;
	     unsigned Nul2gpt : 1;
	     unsigned PAB     : 4;
	}ICRreg ;

	typedef struct
	{
		unsigned PWA : 8;
		unsigned PWB : 8;
	} Bytes;

	#define GPT_MCR (*(@far MCR_Register*)(GPT_Register+0))
	#define ICR (*(@far ICRreg*)(GPT_Register+4))
	#define PDDR (*(@far Register*)(GPT_Register+6))
	#define OC1M (*(@far Register*)(GPT_Register+8))
	#define OC1D OC1M
	#define TCNT (*(@far unsigned volatile int*)(GPT_Register+0xa))
	#define PACTL (*(@far Register*)(GPT_Register+0xc))
	#define PACNT (*(@far unsigned volatile char*)(GPT_Register+0xd))
	#define TIC1 (*(@far unsigned int*)(GPT_Register+0xe))
	#define TIC2 (*(@far unsigned int*)(GPT_Register+0x10))
	#define TIC3 (*(@far unsigned int*)(GPT_Register+0x12))
	#define TOC1 (*(@far unsigned int*)(GPT_Register+0x14))
	#define TOC2 (*(@far unsigned int*)(GPT_Register+0x16))
	#define TOC3 (*(@far unsigned int*)(GPT_Register+0x18))
	#define TOC4 (*(@far unsigned int*)(GPT_Register+0x1a))
	#define TI4O5 (*(@far unsigned int*)(GPT_Register+0x1c))
	#define TCTL1 (*(@far Register*)(GPT_Register+0x1e))
	#define TCTL2 TCTL1
	#define TMSK1 (*(@far Register*)(GPT_Register+0x20))
	#define TMSK2 TMSK1
	#define TFLG1 (*(@far volatile Register*)(GPT_Register+0x22))
	#define TFLG2 TFLG1
	#define CFORC (*(@far Register*)(GPT_Register+0x24))
	#define PWMC CFORC
	#define PWMA (*(@far Bytes*)(GPT_Register+0x26))
	#define PWMA PWMB
	#define PWMCNT (*(@far unsigned int*)(GPT_Register+0x28))
	#define PWMABUF (*(@far Bytes*)(GPT_Register+0x2a))
	#define PWMBBUF PWMABUF
	#define PRESCALER (*(@far unsigned int*)(GPT_Register+0x2c))

	/* MCR bit definitions 0x0 */

	#define STOP bit15
	#define FRZ1 bit14
	#define FRZ0 bit13
	#define STOPP bit12
	#define INCP bit11
	#define SUPV bit7

	/* PDDR bit definitions 0x6 */

	#define DDRI4O5 bit15
	#define DDRO4 bit14
	#define DDRO3 bit13
	#define DDRO2 bit12
	#define DDRO1 bit11
	#define DDRI3 bit10
	#define DDRI2 bit9
	#define DDRI1 bit8
		.
		.
		.

	#endif
</code></pre>
<h4><pre>
	Listing 1.  <a href="appendxb.htm#gpt_h">General Purpose Timer Header File</a>
</pre></h4>
<p>	This file is used in conjunction with a header file designed for the specific chip 
being used.  One of the addresses defined in the chip header file is the beginning address 
of  each module in the chip.  In this case, GPT_Register is the beginning address of the 
General Purpose Timer control registers.  All of the registers needed to run the timer are 
located at an offset from the GPT_Register.  These registers are all located in the top half 
of the top page of memory.  In other words, the addresses of these registers are above the 
address 0xf8000.  As such, access to the registers require a full twenty-bit address.    
Therefore, when forcing the addresses to have the specific type needed at each memory 
location, the @far must be included in the cast operation.  Also, note that the type 
Register is used as a type for several addresses.  This type is defined in the header file for 
the chip, and in the case of the M68HC16, a Register is a collection of sixteen bits in a 
single memory location.  You will also notice that there are several instances where a 
memory location is given two names.  When this happens, the memory location is made 
up of two M68HC11 type registers:  one eight-bit register in the most significant bits and 
one eight-bit register in the least significant bits of the sixteen-bit register.  When the bits 
are defined you will find them in the range of 8 through 15 for one register and 0 through 
7 for the other.  
<p>A header file hc16h.h must be included as the first line of code in any program.  
This file contains the basic register definitions along with all of the offsets to the various 
peripheral control memory areas.  For example, the beginning of the general purpose 
timer control registers can be found at the address GPT_Register.  This value along with 
all of the beginning addresses of the other peripherals are found in this file.  Other 
peripherals included with this chip are the System Integration Module (sim.h), the 
Analog to Digital Converter module (adc.h), the Queued Serial Interface Module 
(qsim.h) and the Static Ram Module (sram.h).  If the program is to make access to any of 
these modules, the appropriate header file must be included.  
<p>	The compiler is a command line operation.  The general command line interface 
to the compiler is as follows:
<pre><code>
	c [options] <filename.c>
</code></pre>
<p>There are many options that are needed to compile code for our purposes.  A batch file 
that contains all of the necessary options is quite useful here.  The contents of this batch 
file are
<pre><code>
	c -dlistcs -dxdebug -dmodm +o %1.c
</code></pre>
<p>The option -dlistcs causes the compiler to create  a listing file that contains the C 
program interleaved with the corresponding assembly code.  It is planned to execute and 
debug the code on an evaluation board called the  EVB16.  The software for access to 
this board will permit limited source level debugging.  To create the files needed to do 
the debug operations, the -dxdebug option must be included in the command line.  The -
dmodm option causes the compiler to create code with the medium memory module.  In 
this module, the program can contain up to 1 megabyte of code, but the directly 
accessable volatile ram memory must be limited to 65 kilobytes.  This arrangement is 
usually satisfactory for most applications.  The +o option instructs the compiler to create 
a relocatable object module, and the %1.c entry is the file name entered on the 
commmand line when the batch file is executed.  
<p>The -dxdebug command causes the listing file to be greatly increased in size. If 
you are trying to get a clean compile and are not planning to debug the program, it is 
probably best to leave out the -dxdebug option.
<p>	The next phase of the compile procedure is the linking operation. It is in this 
phase that program and data modules are placed at specific memory locations.  The 
linkng operation is probably best controlled by a command file.  Listed below is a typical 
command file needed to link the code.  Note first that a special version of this file is 
needed for each program that you want to link.  In this case, there are three lines with the 
name timetest included.  timetest is the name of the program being linked.  Also, note 
that there is a file vectiot.o being linked into the program.  This file also must be written 
specially for each program that you will link.  Perhaps the start-up routine crts.o will also 
have to be written as a unique program for your individual program. 
<p>	In this linker, a # sign causes the remainder of the line to be a comment.  Each 
line is commented to help explain the operation that takes place at that point in the link 
procedure.  The first three lines are essentially book keeping operations.  The +h option 
causes the program to be linked into multiple output segments.  The second line notifies 
the linker of the maximum program size, and the third line causes memory banking 
options to be implemented.  The next two lines control the outputs from the linker.  A 
map file named timetest.ma will be generated and the output linked file will be named 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -