manufacturer of I/O-rich SBCs, operator interfaces, handheld instruments, and development tools for embedded control low cost single board computers, embedded controllers, and operator interfaces for scientific instruments & industrial control development tools for embedded control order our low cost I/O-rich embedded control products embedded controller manufacturer profile single board computers & embedded controllers development tools & starter kits for your embedded design operator interfaces with touchscreens and graphical user interface plug-in expansion modules for digital & analog I/O C language & Forth language integrated development tools, IDE single board and embedded computer accessories embedded controller enclosures, bezels, environmental gaskets

The C Programmer’s Guide to the QVGA Controller

Table of Contents

PART 1 GETTING STARTED

Introduction. How to Use This Manual

Chapter 1: Getting to Know Your QVGA

PART 2 PROGRAMMING THE QVGA CONTROLLER

Chapter 2: Your First Program

Chapter 3: The IDE: Writing, Compiling, Downloading and Debugging Programs

Chapter 4: Making Effective Use of Memory

Chapter 5: Programming the Graphical User Interface

Chapter 6: Real Time Programming

Chapter 7: Failure and Run-Time Error Recovery

PART 3 COMMUNICATIONS, MEASUREMENT, AND CONTROL

Chapter 8: Digital and Timer-Controlled I/O

Chapter 9: Data Acquisition Using the QVGA Controller

Chapter 10: Outputting Voltages with Digital to Analog Conversion

Chapter 11: Serial Communications

Chapter 12: The Battery-Backed Real Time Clock

PART 4: PUTTING IT ALL TOGETHER

Chapter 13: A Turnkeyed Application

Overview of the Application

Hardware Required for the Example Application

The Memory Map

8 Bit A/D Data Gathering Task

Pulse Width Modulation Task

Output Compare 3 Interrupt Code

Assembly Coding a Function Definition

Statistics Task

Build and Activate the Tasks

Define the main Routine

Compile the Program

Using SAVE, RESTORE and Write-Protection During Debugging

Configure the Board to Autostart the Program

Turnkeyed Application Code Listing

PART 5: REFERENCE DATA

Appendix A: QVGA Electrical Specifications

Appendix B: Connector Pinouts

Appendix C: Physical Dimensions

Appendix D: Schematics (pdf)

Chapter 13

<< Previous | Next>>

Chapter 13: A Turnkeyed Application

This chapter presents an application program that integrates a range of hardware and software features of the QVGA Controller. The application is "turnkeyed", meaning that it can be placed in Flash and configured to autostart each time the board is powered up. This chapter explains all of the elements of the program.

The example application reads a voltage using the 8 bit analog to digital (A/D) converter and outputs a pulse width modulated (PWM) signal that, when averaged using a simple resistor and capacitor, tracks the input voltage.  In addition, the program calculates and displays the mean and standard deviation of the input signal.  This application demonstrates how to:

  Use the pre-coded library routines

  Take advantage of the “Make” utility which automatically sets up a memory map that is compatible with a turnkeyed application in PROM

  Use the 8 bit A/D converter

  Use floating point mathematics to calculate means and standard deviations

  Write and install an interrupt routine that generates a PWM output

  Assembly-code an interrupt routine for increased performance

  Write to the liquid crystal display (LCD)

  Write the application using a modular multitasking approach

  Configure the application to automatically start upon power-up or reset

The program is called TURNKEY.C in the \MOSAIC\DEMOS_AND_DRIVERS\MISC\C EXAMPLES directory.  The commented application code is presented at the end of this chapter.  The text of this chapter will frequently refer to the code, offering background and explanation.  Some of the section titles in this chapter are keyed to the titled sections in the code which are set off with asterisks.

Overview of the Application

The main activities of this application are performed by 3 modular tasks and one interrupt routine:

     The first “data gathering” task collects data from channel 0 (or any other channel that you designate) of the 8 bit A/D converter (PORTE on the 68HC11), converts the 8 bit reading to its equivalent voltage, and saves it in a floating point variable called input_voltage.

     The second “output control” task calculates the duty cycle, high-time and low-time of a pulse width modulated (PWM) output signal so that its average value matches the latest input_voltage measured by the data gathering task.

     An interrupt attached to output compare 3 (OC3) controls the PWM output signal appearing at pin 5 of PORTA (PA5) of the 68HC11.  The interrupt service routine updates the OC3 timer registers based on the high-time and low-time calculated by the output control task.

     Once each second for ten seconds, the third “statistics” task samples the input voltage calculated by Task 1 and stores it as a floating point number in a FORTH_ARRAY called Last10Voltages. When 10 seconds have elapsed, this task calculates the mean and standard deviation of the 10 data points and writes them to the LCD display.  It then starts filling the array with new data, repeating the entire process.

There is one additional task that is always present in this application: the default task named FORTH_TASK that runs QED-Forth and executes main().  In the final  version of this application we put the QED-Forth task ASLEEP.  This prevents the end user of the system from gaining access to the Forth interpreter.  We use the interactive QED-Forth task during development and debugging; it allows us to execute commands and monitor the performance of the routines that are being tested.

Hardware Required for the Example Application

This sample application requires a QVGA Controller, a resistor, capacitor, potentiometer, and a voltmeter to verify proper operation.  An optional operational amplifier would allow the output signal to drive loads other than a high impedance voltmeter or oscilloscope.  Please be careful not to short pins together when working with the on-board connectors.

Figure xx  shows a functional schematic of the circuitry required, and points out the relevant pin numbers on the 40 pin digital and the 40 pin analog I/O connectors.  A 10 Kohm (or any other reasonably valued) potentiometer is connected to place a controllable voltage on AN0, which is channel 0 of the 8 bit A/D converter on the HC11.  The potentiometer is connected between +5VAN (the analog +5 Volt supply) and AGND (analog ground), with the potentiometer’s wiper connected to AN0 (pin 10 of the analog I/O connector). 

Figure

Figure 13‑0  Functional schematic of circuitry needed to verify proper operation of the example turnkeyed application program.

The PWM output appears on PA5 (that is, pin 5 of PORTA). A resistor and capacitor are connected as shown in Figure 11.1 to integrate the square-wave output signal to a steady average voltage across the capacitor.  The capacitor voltage can be measured with a high impedance voltmeter or oscilloscope.  The optional amplifier shown in the figure is needed if the output must drive lower impedance loads.  An optional amplifier can be used if the output must drive lower impedance loads.

The statistical report generated by Task 3 is sent to the LCD display.

The Memory Map

The first step in programming an application is assigning the memory areas that will be occupied by the object code, variable area, and also the heap which holds FORTH_ARRAYs in paged memory.  Fortunately, the Mosaic IDE Make Tool (invoked by clicking on the Make icon) automatically sets up a very versatile memory map.  For reference, here is a brief summary of the main memory areas allocated by the Make Tool:

  0x0000-0x7FFF (32K) in page 4 is the program’s object code which will eventually be in Flash.

  0x4600-0x7FFF (14.5K) in page 0x0F is the RAM heap area that holds FORTH_ARRAY data in paged memory.

  0x3000-0x45FF (5.5K) in page 0F is a reserved heap for the graphics display buffer.

  0x8E00-0xADFF (8K) is available common RAM (the C .data and .init sections) which hold C variables, C arrays, TASK areas, and pfa’s (parameter field areas) of FORTH_ARRAYs.

  0xB000-0xB3FF (1K) is 68HC11 on-chip RAM (the C .onchipRAM section); the top 48 bytes at 0xB3D0-0xB3FF are reserved.

  0xAEC0-0xAFFF (320 bytes) is available EEPROM (the C .eeprom section); EEPROM at 0xAE00-0xAEBF is reserved for startup utilities and interrupt revectoring.

  0x4000-0x7FFF (16K) on page 0x05 is used for QED-Forth debugging definitions that are present in the .DLF download file

  QED-Forth ROM occupies 0x0000-0x7FFF on page 0, 0x0000-0x2FFF on page 0x0F, and 0xB400-0xFFFF in common ROM.

While the object code ends up in Flash memory, the variable area and heap must always be located in RAM.  The variable area includes the areas where variable values are stored, where TASK areas (the tasks’ stacks, buffers, pointers, etc.) are allocated, and includes the parameter fields that hold addressing and dimensioning information associated with heap items.  The heap in paged memory holds FORTH_ARRAYS and other data structures.  Both variables and the contents of the heap must be subject to rapid change while the application is running, so they can never be placed in Flash.

Other Memory Areas

The upper half of page 5 is used to hold the QED-Forth definitions (names and object code) that facilitate interactive debugging. This region is typically not needed after debugging is done, and so is typically not included in the final Flash.  If interactive function calling capability is required in the final application (for example, if you want to give the end user or a customer service person the ability to execute interactive commands from a terminal), then this area can be included in nonvolatile Flash memory in the final turnkeyed system. 

While downloading an application, the object code area must be RAM so that the specified bytes can be stored in memory.  As described earlier , proper use of SAVE and RESTORE utilities can save you from having to re-download all of your code after a crash or mistaken command. 

Available PROM and RAM on the QVGA Controller

Obsolete : [

The QVGA Controller has 3 memory sockets labeled S1, S2, and S3.  Socket S1 accommodates the QED-Forth ROM which holds the development system as well as the runtime libraries.  This ROM must be present for the QVGA Controller to function.

Socket S2 holds a 32K, 128K, or 256K RAM, and at least 32K of RAM must be present in this socket for the QVGA Controller to operate.  This memory cannot be write-protected.  If a 32K RAM is installed, the onboard logic places 20K of it on page fifteen (0x0F) at addresses 0x3000 to 0x7FFF and the remainder is common RAM.  Some common RAM is reserved by QED-Forth, and some is overmapped by the 68HC11’s EEPROM.  11.5K of common RAM is located at addresses 8400H-ADFFH and B000H-B3FFH. If a 128K RAM is installed in socket S2, the three 32K pages numbered 1, 2, and 3 are also available.  If a 256K device is installed, pages 8, 9, 10, and 11 are added to the memory map.

Socket S3 is called the “RAM/ROM socket”.  It accommodates either RAM (typically during program development) or PROM (typically in your final product).  During program development and debugging, a 128K battery-backed RAM is typically installed in this socket.  The memory is addressed at pages 4, 5, 6, and 7, and each page contains 32 Kbytes.  Turning DIP switch #1 ON write-protects pages 4 and 5, and turning DIP switch #2 ON write-protects pages 6 and 7.  This socket is an ideal location for the object code that will end up as PROM in the final system. During program development, code can be compiled into the RAM in this socket, and the memory can be write-protected to emulate a PROM.  When the application is completely debugged, the contents can be burned into a PROM, and the PROM can be plugged into the socket.  Turning switch #3 ON configures the socket to accommodate a PROM.  The PROM size can be 32K (page 4 only), 64K (pages 4 and 5), or 128K (pages 4, 5, 6, and 7).

]

8 Bit A/D Data Gathering Task

The first section of the example application code uses the 8 bit analog to digital (A/D) converter to convert the voltage input derived from the external potentiometer (see Figure xx ) to a digital value between 0 and 255.  The task converts the 8 bit A/D reading into its equivalent floating point voltage which spans 0.0 to 5.0 Volts, and stores it in a variable called input_voltage.

We define some simple constants that specify the high and low reference voltages of the A/D, and the number of counts (28 = 256 counts). The CountToVolts() function converts the 8 bit A/D reading into its equivalent floating point voltage (a number between 0.0 and 5.0 Volts).  GatherData() is the activation routine for this task.  It calls AD8On() to power up the 8 bit A/D, and enters an infinite loop that acquires an A/D sample, converts it to a voltage, and stores it in the variable input_voltage which other tasks can read. 

A special storage operator named PokeFloatUninterrupted() is declared using the _protect keyword, which causes the compiler to disable interrupts before calling the function, and restore the global interrupt enable flag (the I bit in the Condition Code Register) to its prior condition after the function returns.  This uninterruptable function is used because the input_voltage variable holds data that is accessed by more than one task.  The uninterruptable store and fetch operators ensure that 32 bit data is not misread because of intervening interrupts or task switches.   

The Pause() cooperative task-switch command forces at least one task switch on each pass through the infinite loop of GatherData(); we also rely on the timeslicer to switch tasks every 5 ms.

Pulse Width Modulation Task

The goal is to create a PWM output whose average voltage is equal to the input voltage read by the data gathering task.  This code specifies the activity of the task that calculates the high-time and low-time parameters needed to generate the pulse width modulated output signal.  An interrupt routine (described in the next section) controls the output signal subject to the high- and low-times calculated by this task.  

We could perform all of the duty cycle computations in the interrupt service routine that controls the PWM output, but this is not a good practice.  Long interrupt service routines can delay the processor’s ability to respond to other interrupts in a timely manner.  The best approach is to perform the more time-consuming computational functions in foreground tasks so that the associated background interrupt service routines execute very rapidly. 

We define static integer variables to hold the high-time and low-time which, as their names imply, hold the number of timer counts that the PWM signal is high and low.  Floating point constants LOW_OUTPUT_VOLTAGE and HIGH_OUTPUT_VOLTAGE are defined to specify the voltage levels corresponding to logic level 0 and logic level 1; for maximum accuracy you could measure the voltage levels on PA5 (pin 5 of PORTA on the 68HC11) and set these constants accordingly.

The period of the PWM output is chosen to be 130 msec, which corresponds to 65,000 counts on the free-running timer.  The resident QED operating system automatically configures the free-running counter to increment every 2 microseconds.

We enforce a minimum time between interrupts via the constant MINIMUM_HIGH_OR_LOW_TIME which is approximately equal to the maximum number of timer counts divided by 256.  That is, we only require 8 bits of resolution from our PWM.  The benefit of imposing a minimum high or low time is that by doing so we can ensure that the minimum time between PWM interrupts is more than adequate to allow the service routine to execute.

We next define a routine that calculates the PWM duty cycle such that the average output signal matches the latest measured input_voltage. The HighAndLowTimes() function converts the calculated duty cycle into the parameters needed by the interrupt service routine, and SetPulseParameters() is the infinite loop that serves as the activation word for the PWM task.  Note once again that we have put Pause() in the loop so that both cooperative and timesliced multitasking are used.

Output Compare 3 Interrupt Code

This code defines an interrupt service routine and an installation routine for the OC3 (Output Compare 3) interrupt which controls the output signal.  We first define constants to name the relevant bit masks. The relevant 68HC11 hardware register names are defined in the QEDREGS.H file in the \FABIUS\INCLUDE\MOSAIC directory.

OC3Service() is the interrupt service routine that controls the state of the PA5 output bit.  It relies on the ability of the output compare (OC) function to automatically change the state of an associated PORTA output bit at a specified time.  Specifically, OC3 can be configured to automatically change the state of the output PA5 when the count in the TOC3 register matches the contents of the free-running counter (TCNT) register.  Setting the “mode bit” specified by the constant OC3_MODE_MASK in the timer control 1 (TCTL1) register enables the automatic output control function.  The OC3 “level bit” specifies whether the output bit will be set high or low upon a successful compare.  The OC3Service() routine simply reverses the state of the OC3 level bit (specified by the constant OC3_LEVEL_MASK) and adds the appropriate high_time or low_time increment to the OC3 register to specify when the next interrupt will occur.  Recall that high_time and low_time are calculated by the foreground PWM task, so the interrupt has very little to do and can execute rapidly (typically in under 50 µsec).

InstallOC3() enables direct hardware control of PA5 by setting the OC3 mode bit, calls ATTACH() to post OC3Service() as the OC3 interrupt handler routine, initializes PA5 by forcing an output compare, and enables the OC3 interrupt.  The main() routine defined at the end of the code example calls the InstallOC3() initialization routine each time the processor restarts.

Assembly Coding a Function Definition

AssembledOC3Service() is an assembly coded version of the interrupt service routine.  While it is only slightly faster than the high level version, it is included to illustrate how assembly coding is performed within this programming environment. 

Assembly mnemonics use the standard Motorola format as described in the Motorola 68HC11 book.  After the function is declared and the opening { is entered, the #asm preprocessor directive indicates that the following code is to be passed straight through to the assembler, bypassing the C compiler.  The #endasm preprocessor directive returns control to the compiler.  These preprocessor directives must appear alone on a line.  Each opcode instruction must occupy a separate line that starts with at least one tab or space.  Labels (such as branch destinations) should appear alone on a line, with no leading spaces.  The * is the comment character; text after the first * on a line is ignored. 

Assembly constants are defined using EQU (equate) statements.  Note that just above the function definition of AssembledOC3Service(), the required constants are defined as EQU statements within the delimiting #asm ... #endasm preprocessor directives.

Statistics Task

The code in this section continuously loads a matrix with one input voltage acquired in each of the last 10 seconds, and writes the mean and standard deviation of this data to the liquid crystal display every 10 seconds.  We define a single-row FORTH_ARRAY called Last10Voltages to hold the data; this array resides in the heap associated with the statistics task.  Two variables keep track of the current and prior matrix indices; these aid in managing storage of data into Last10Voltages.

The SetupDisplay() function writes the headings to the LCD display.  The STRING_TO_DISPLAY macro (defined in the INTRFACE.H file) makes it easy to write a text string to a portion of the display buffer in system RAM, and the UpdateDisplay() command writes the contents of the buffer to the LCD display.  CalcStats() calculates the latest calculated mean and standard deviation values, and ShowStats() writes them to the display.  ShowStats() uses sprintf() to convert the floating point numbers to ASCII strings that can be written to the display buffer.  The format is specified so that each floating point number will occupy the same number of spaces each time it is displayed. LogDataAndShowStats() fills the Last10Voltages array with measured voltages and calls the subsidiary functions to display the statistical results every 10 seconds.

Statistics() is the activation routine for the task; it dimensions and initializes the data array, sets up the display, and enters an infinite loop that logs the data and displays the statistics.  Pause() is included in the infinite loop so that both cooperative and timesliced task switching are used.

Build and Activate the Tasks

Now that we have defined the activation routines for the tasks, it is time to execute the TASK statement to name the tasks, allocate their 1K task areas in common RAM and set up the tasks.

The routine BuildTasks() initializes the user area and stack frame of each task, and links the tasks into a round-robin loop.  The first statement of this routine is very important:

 

NEXT_TASK  = TASKBASE;

When executed, this command makes the currently operating task (which will always be the default FORTH_TASK) the only task in the round-robin loop.  This sets a known startup condition from which the task loop may be constructed.

Note that the ReadInputTask and ControlOutputTask are built with a null heap specification because they do not access any heap items.  The StatisticsTask, however, does access a heap item.  It requires a heap specified by DEFAULT_HEAPSTART and DEFAULT_HEAPEND which are defined in the HEAP.H header file in the \FABIUS\INCLUDE\MOSAIC directory.  Note that we also use the same heap specification for the default FORTH_TASK; see the INIT_DEFAULT_HEAP() routine.  The FORTH_TASK is not active in the final application, so the sharing of this heap space does not cause a conflict during operation.

ActivateTasks() simply activates each of the three tasks with the appropriate action routine.  Each action routine is an infinite loop that performs the desired activity of the task. 

Define the main Routine

The main() function is the top level routine in the application.  After execution of the PRIORITY.AUTOSTART command as explained below, it will be called each time the board is powered up or reset.  The operating system always wakes up and enters the default FORTH_TASK whose task area starts at 0x8400 in common memory upon every restart, so the default QED-Forth task is always the task that calls main()

It is good programming practice to initialize all variables each time the application starts up; this is done by the InitVariables() function.  After initializing the variables, main() calls INIT_DEFAULT_HEAP() to initialize the heap of the FORTH_TASK, calls InitElapsedTime() to initialize the elapsed time clock to zero, installs and initializes the OC3 (PWM) interrupt service routine, and builds and activates the tasks. 

The next command in main() is

 

ColdOnReset()

which forces a COLD restart every time the machine is reset.  This enhances the operating security of a turnkeyed application by ensuring that every user variable and many hardware registers are initialized after every restart and reset.  This command may be commented out during debugging so that restarts do not cause QED-Forth to FORGET all of the defined functions in the application program. 

The main() function then puts the default FORTH_TASK asleep by executing:

 

STATUS = ASLEEP;

This takes effect once multitasking commences, and does not prevent execution of the remainder of main().  This command should be commented out during program development so that the awake QED-Forth task can be used to aid in debugging. 

The main() function then RELEASEs the FORTH_TASK’s control of the serial line.  This is not required in this simple application, but it would be necessary if another task required access to the serial port in the final application. For example, the RELEASE() statement would be required if the statistics task printed to the terminal instead of to the LCD display.

The final commands start the timeslicer (which also starts the elapsed time clock and globally enables interrupts) and Pause() to immediately transfer control to the next task in the round-robin loop.  The final Pause() is not essential in this simple application, but it does ensure smooth operation in applications where tasks other than QED-Forth require access to the serial port.

Compile the Program

To compile, assemble and link the program and create the download file, simply use your editor to open the TURNKEY.C file in the \MOSAIC\DEMOS_AND_DRIVERS\MISC\C EXAMPLES directory, and then click on the Make Tool.  When the compilation is complete, you can view the warning messages and highlight the associated source code lines.  (None of the warnings adversely affect the operation of this program.) 

Make sure that your QVGA Controller is turned on and is communicating with the Mosaic Terminal as described in Chapter xx . Then download the program to the QVGA Controller by using the terminal’s “Send Text File” menu item to send the TURNKEY.DLF file. 

Using SAVE, RESTORE and Write-Protection During Debugging

After downloading the program, you can interactively type SAVE from the terminal; this stores relevant memory map pointers into reserved locations in EEPROM.  You can proceed to interactively test each function in the program one at a time as described earlier . If a crash occurs, simply type RESTORE to bring back access to all of the interactively callable function names.  The use of SAVE and RESTORE can greatly reduce the number of times that you have to re-download your code during debugging.

Configure the Board to Autostart the Program

After debugging is completed interactively type the QED-Forth command:

CFA.FOR  main  PRIORITY.AUTOSTART

which installs main() as a routine that is automatically executed upon each restart or reset.  Note that the QED-Forth V4.xx greeting is suppressed when an autostart routine is installed (you could easily print your own greeting by modifying the main() function).  PRIORITY.AUTOSTART installs an autostart pattern in the top 6 bytes of page 4  which is in Flash in the final system.  The autostart pattern tells the operating system to automatically call main().

The PRIORITY.AUTOSTART command is used to configure systems that will go into production.  For one-of-a-kind prototypes, another QED-Forth command (called simply AUTOSTART) is available that installs the autostart pattern in EEPROM which resides in the 68HC11 chip itself.  Because the pattern installed by AUTOSTART is in the processor chip and not in Flash, it is not automatically transferred to a new board when the application Flash is plugged in.  In summary, the AUTOSTART command is convenient while debugging a prototype, but the PRIORITY.AUTOSTART command must be used when generating a Flash for a production system .

After executing the PRIORITY.AUTOSTART command, the main() routine can be invoked by resetting the QVGA Controller, thus starting the program.  If you need to remove the autostart vector (and the QED-Forth monitor is still active and responding to your commands, that is, if you didn’t put it ASLEEP), you can simply type:

NO.AUTOSTART

to remove any PRIORITY.AUTOSTART or AUTOSTART vectors.  If QED-Forth is not awake (and so does not respond to the terminal), you can remove the autostart vector by entering the special cleanup mode.  Note that the special cleanup mode configures the system to expect a baud rate of 9600 baud, so if you are using a different baud rate, you’ll need to interactively execute the command BAUD1.AT.STARTUP to re-establish the desired configuration.

You can monitor the operation of the turnkeyed program by connecting a voltmeter or oscilloscope across the output capacitor C1 as shown in Figure xx , and by watching the update of statistics every 10 seconds on your display. Adjusting the input potentiometer should result in an output voltage that tracks the input.

Generating a PROM for the Target System

Now that the application code has been debugged and turned into a completed turnkeyed application, generating your production system involves programming a single Flash or PROM device. 

Flash and PROM burners accept the image that is to be burned into the memory device in either Intel Hex or Motorola Hex (S1 or S2) formats.  These formats allow the memory contents to be saved and transferred as an ASCII text file with numbers represented in hexadecimal base.  Each line of a hex file contains numbers specifying the address and contents of a specified number of bytes (typically 32 bytes per line).

The QVGA Controller generates these ASCII hex files using the built-in routines DUMP.INTEL, DUMP.S1, and DUMP.S2.  The popular Intel Hex format uses 16 bit addresses so a single file can be used to program devices up to 64 Kbytes long.  The Motorola Hex format (also called S-record format) is also widely supported and is more flexible.  The Motorola S1 format uses 16 bit addresses. The S2 format uses 24 bit addresses, and so can be used to program larger devices.

Generating PROMs for Programs Compiled Via the Make Tool

If a program is compiled using the Make Tool, all of its C object code is typically located within the 32 Kbytes on page 4.  If the PRIORITY.AUTOSTART command was interactively executed, the Autostart Vector located at addresses 0x7FFA-0x7FFF at the top of page 4 specifies the execution address of the application program that will be automatically executed each time the processor starts up.

The goal is to capture the entire object area and the autostart vector in the hex file.  This is easy to do; simply follow these five steps:

    0.    From QED-Term, select “Receive Text File” from the “Transfers” menu.  Choose an appropriate directory and select a file name with a .TXT extension for your hex file, then click on “OK”.

    0.    From the terminal, type the following command to instruct the QVGA Controller to dump out an image of page 4 in Motorola S2 format:

HEX  0 4   DIN 0 8000  DUMP.S2

In response to this command QED-Forth outputs the formatted information.  The HEX keyword specifies that all of the following numbers are to be interpreted as hexadecimal.  The 0  4 specifies that the dump starts at address 0 on page 4.  The DIN 0 specifies that the reported starting address in the hex file is zero, so we’ll start programming the PROM or Flash from its beginning.  The 8000 specifies that 32 Kbytes are to be dumped.

    0.    After the QVGA Controller finishes transmitting the PROM image, select “Stop” from the “Transfers” menu of the Terminal program.

    0.    From TextPad, OPEN the file that you have just created, and edit out the echo of the QED-Forth commands at the top of the file, and the terminating “ok” at the bottom of the file.  What remains is the hex dump to be used by your device burner.

    0.    Use your device burner together with the dump file that you created to burn a 32 Kbyte Flash or PROM such as the 27C256, or a 64 Kbyte PROM such as the 27C512.  Use a PROM with an access time of 120 nano-seconds or faster.  (For example, the full part number of a Texas Instruments 32 Kbyte PROM with 120 ns access time is TMS 27C256-120JL).

If you prefer using the Intel Hex format, substitute the following command in step 2:

HEX  0000  4 0000   8000  DUMP.INTEL

where 0000 4 is the starting address on the QVGA Controller, 0000 is the 16 bit starting address in the PROM, and 8000 is the number of bytes in the 32 kilobyte page.  In response to this command QED-Forth outputs the formatted information.  All other steps remain the same.

Generating PROMs for Programs That Occupy More Than 32 Kbytes

The prior section detailed how to create a PROM image of the 32 Kbytes on page 4 of the QVGA Controller’s memory space.  Including additional memory pages in the dump file is accomplished by changing the QED-Forth command in Step 0. of the 5-step procedure .

You will probably need to include additional pages in your hex dump if you used the Build Tool (the Bricks icon) icon to compile your application, or if you used the Make Tool and you wish to include the QED-Forth interactive debugging headers or a graphics font table that resides on memory page 5.

To create a Motorola S2-record file representing pages 4 and 5, substitute the following commands in step 0. :

HEX  0 4   DIN 0 8000 DUMP.S2

Wait until the QVGA Controller’s output dump is done, then type:

0 5   DIN 8000 8000 DUMP.S2

Each command line dumps a 32K page starting at QED address 0 in pages 4 and 5, respectively.  The number following DIN specifies the 24 bit start address of each page in the PROM; note that the second command’s start address is 0x8000 greater than the preceding start address (0x8000 is the number of bytes in each 32 K page). These two S2 dumps can be sent to the device burner sequentially, or they can be concatenated by using the editor to remove the intermediate header record (which starts with “S1”) and the intermediate termination record (which starts with “S9”).

If your application’s object code extends onto page 6, you’ll need to use a 128 Kbyte PROM to hold your program.  In this case follow the same procedure just described, but after the dump of page 5 has completed, add the additional command line:

0 6   DIN 10000 8000 DUMP.S2

which dumps page 6 with the appropriate reported starting address (0x10000) in the PROM.  Page 7 can be dumped using the following command:

0 7   DIN 18000 8000 DUMP.S2

Move Into Production

Now to run your application install the Flash or PROM device in Socket 1.  Power up the QVGA Controller and it will automatically run your application.  Replicate your memory devices and you’re in production!

<< Previous | Next>>


Home|Site Map|Products|Manuals|Resources|Order|About Us
Copyright (c) 2006 Mosaic Industries, Inc.
Your source for single board computers, embedded controllers, and operator interfaces for instruments and automation