The high-level language Forth is very suited to real-time systems and exists for most processors but finds its main home in embedded systems. It is small enough to fit in a target system and debugging is interactive. Programmer productivity is increased making software cost-efficient. Unlike BASIC it is readily supports the multitasking and interrupts generally needed in control applications.
Programming of the TDS2020F is done in interactive American National Standard Forth (ANS Forth), coupled with structured assembler language and multitasking if and when required. Both are on the board. Read this section even if you are an old hand at Forth since it gives an overview of the word sets included. Another section summarises available stack manipulation words on TDS2020F. Control structures, logic and mathematical functions follow it.
This manual supplements the guide to ANS Forth 'Forth Programmer's Handbook' by E.K. Conklin and Elizabeth Rather, which provides a detailed technical reference. All TDS2020F programmers will find this a useful manual to have, although it is not essential.
ANS Forth is defined in document ANSI X3.215-1994 of the American National Standards Institute. This is the official document and ultimate reference (and expensive) but a freely available preliminary version is on the CD in directory \essentials\ANSForth.
By its very nature Forth differs from one implementation to the next, if only in the number of words implemented in the kernel. The TDS2020F contains ANS Forth (about 6k) plus many other words that assist in typical control and data collection applications (about 10k). The definition of the language used can be found in the WORD LIST, page 352. For each Forth word the stack conditions before and after using the word are given and a description tells you what it does. In all there are over 500 Forth words pre-defined.
When using 'Forth Programmer's Handbook' or other book to learn Forth, always keep an eye on the word list in this manual, its importance cannot be over-emphasised because that is your ultimate guide to the syntax of each word.
American National Standard Forth was published in December 1994 and TDS2020F conforms. See ANS FORTH DOCUMENTATION, page 344, for official system documentation. Standardisation gives you the possibility of writing software that will work on other Forth systems and using libraries not originally written for TDS2020F.
Charles Moore invented Forth in the early seventies. The first widely diffused version was Fig-Forth defined in 1978 by the Forth Interest Group. Further efforts were made in 1979 and 1983 resulting in Forth-79 and Forth-83, and several public domain Forths based on these three made the language widely available. In parallel, commercial vendors did not necessarily adopt any of these definitions of the language. Although called 'standards', a self-elected committee produced them with not enough representation from commercial users of Forth.
Proper standardisation started in 1987 under the auspices of the American National Standards Institute Inc. The committee gradually refined its definition of Forth over a period of 7 years in consultation with amateur, professional and commercial interests. The result is a consensus which all can accept. Elizabeth Rather of Forth Inc. (joint author of the book mentioned above) chaired the committee, which included Charles Moore. Organisations participating in making the Standard included Ford Motor Company, NASA/Goddard Space Flight Center, Harris Semiconductor, IBM Corporation and IEEE as well as many individuals and Forth vendors.
ANS Forth has improvements on earlier versions but the changes are not overwhelming. Differences between Forths are small and annoying rather than major problems as with some other languages, particularly BASIC. However the existence of an official version is now makes others obsolescent, and in common with other suppliers Triangle Digital Support Ltd has made ANS Forth the standard for its TDS2020F flagship 16-bit embedded computer.
The difficult task of converting TDS2020F's pre-emptive multitasker to ANS Forth took only a few hours, illustrating the closeness of Forth versions. We expect Forth application programmers to have little difficulty in adapting to the Standard no matter where they come from in the Forth community.
NEW FEATURES OF ANS FORTH
ANS Forth includes innovations so a programmer should not be content to just modify his code to the Standard, but also take advantage of new features. Here we concentrate on new features of most interest to TDS2020F programmers, but users of ANS Forth on PCs and other systems should investigate ANS Forth's standardised file handling, memory allocation and other new words.
The most important to real-time system programmers (i.e. most Forth users) is the new CATCH and THROW mechanism, a way of handling exceptions without having to propagate flags up through multiple levels of nesting. These are dealt with later in ERROR HANDLING, page 144.
Apart from CATCH and THROW there are other surprises in ANS Forth that are not found in any of the previous major Forths. For instance NOT has gone because it used to have two uses, that of negating the sense of a flag and that of doing a one's complement operation. In ANS Forth these are made available by 0= and INVERT respectively. Also END-CODE does not appear, although like most Forth systems TDS2020F includes it to neatly end CODE definitions written in assembler.
Perhaps the biggest surprise is the extension of control-flow structures. Referring to CONTROL STRUCTURES, page 136, the first two diagrams show previously used patterns and the last one some of the new extended versions allowed under ANS Forth.
You can have multiple WHILEs within a BEGIN . REPEAT loop for example, provided each additional WHILE is matched by an extra THEN . The extra conditions mean that you can get out of a loop on either of two (or more) conditions without having to logically combine them first with AND or OR .
On TDS2020F all these control structures, including the extended ones, are also available for use in assembler within CODE definitions.
Words can remain unnamed in ANS Forth, the word :NONAME is used instead of a colon to start a definition. During compilation the execution token is left on the stack (it used to be called a code field address, or cfa). You can use this to refer to the word in subsequent definitions. For example:
VARIABLE TEMP \ to hold execution token
:NONAME ." quick brown fox jumped " ; \ - xt
TEMP ! \ keep execution token
: TEST ." The " [ TEMP @ , ] ." over the lazy dog" ;
The second word defined cannot be found in the dictionary (it has no name) but it is called by the word TEST which when executed will display 'The quick brown fox jumped over the lazy dog'.
ANS Forth allows a computer to have more than one data space, and on TDS2020F both a dictionary space and a RAM space are defined. The former, holding the program, may end up in Flash-EEPROM or EPROM but the latter will remain available for variables and so on. The words , ALIGN ALLOT C, CREATE HERE UNUSED can access both dictionary and RAM spaces. Swap from one to the other with the words ROM and RAM (not themselves ANS Forth words). The dictionary space is active at power-up. See USE OF VARIABLES below for an example.
Although FORGET (to cut back the dictionary) exists as an option in ANS Forth (it is in library file #ANS.TDS) its use is declared obsolescent. A better tool is the new word MARKER . In debugging a program you mark the start of a section being worked on by MARKER TASK where TASK is just a name you choose to refer to that part of the source file. You can have any number of sections marked with different names. Type TASK (or whatever name was chosen) to delete the last part of the dictionary, right back to where the name was defined.
By putting TASK MARKER TASK as the first line of the file you can both eliminate the last compilation and mark the start of the new one.
String handling is defined in ANS Forth and TDS2020F provides all standard words. These include fast assembler versions of COMPARE and SEARCH since they are often used with input from serial communication streams.
The PAD in ANS Forth is not used at all by the system. It is a transitory area of at least 84 bytes always available to the applications programmer for intermediate steps.
The kernel contains most of the ANS Forth words, but some have to be compiled from #ANS.TDS. The file #EXTEND.TDS contains non-ANS Forth words, but they are expected by many Forth programmers. Some are for backwards compatibility with earlier versions.
USE OF VARIABLES
When the word VARIABLE is used in Forth, two bytes are often allocated in line with the dictionary (the compiled program). This cannot be done with a system such as TDS2020F where the final program will end up in Flash-EEPROM because the variable could not be readily changed. Instead there is a separate area in RAM for variables, with VDP being a user variable pointing at the next free position for a variable. Think about it as Variables Dictionary Pointer.
ALLOT is similar but not the same because it can either move the dictionary pointer DP forward to allocate an array of Flash-EEPROM memory or move VDP to make the allotted area in RAM for use as an array of variables. Use ROM and RAM to switch between the two areas. For example to allocate two arrays INPUT and OUTPUT of 256 bytes each and a variable POINTER you could do the following:
RAM 254 ALLOT ROM
RAM 254 ALLOT ROM
To use these see this example:
INPUT 54 + C@ \ fetch data from 54th byte of array
OUTPUT POINTER @ + C! \ store data to the byte of
\ OUTPUT indicated by POINTER
Variables are not initialised either at compile-time (you in the lab) or at run-time (your equipment in the field). It is important to initialise all variables in the word executed on power-up before entering the main loop.
The ANS Forth words VALUE and TO give better variables than use of the three words VARIABLE @ ! . They are more readable and both writing and reading the variable are half the speed. Examples:
See VALUE, page 428, for more information.
There is another memory map mainly used with the TDS2020DV, in particular see THE PART1/PART2 CONFIGURATION, page 238, but here we describe the normal map for Flash-EEPROM systems.
The MEMORY MAPS, page 53, graphically show where the dictionary goes. In summary, when you switch on the TDS2020F, the Forth is from hex 0000 to 3FFF and the application dictionary starts at 8800 (see maps 2, 3 & 5). However the area 8800 to 88A5 has the interrupt branch table and cold start parameters, so if you type HEX HERE U. on powering up the system you will get 88A6 as the start of the usable dictionary.
The next 29k bytes (almost) up to FB7F are available for the application program. If you get near the limit, a message like '90 left' will advise you how many bytes are still available and eventually 'DICT FULL' will warn of a full dictionary. For larger programs, up to 45k bytes, use the Part1/Part2 mechanism referred to above.
By default, variables start at hex FDF6 and the last byte is FF7F (space for 197 16-bit variables). When more variables are wanted use a RAM in the 32-pin socket. See PCB LINKS, page 48, to install the correct size-128k bytes (order code RAM128K) is suggested. Compile one of the utility routines #EXTVAR.TDS or #EXTVALU.TDS before declaring further variables. Up to 32768 16-bit variables can now be made using 64k bytes of the extended RAM from F0000 to FFFFF.
The H8/532 processor is a 16-bit machine, but each address represents one byte. Single byte transfers can be made to and from any address but 16-bit data must be moved on even addresses.
The most important cases are ! and @ . Do not use them on odd addresses. The words ALIGN and ALIGNED are available to ensure that addresses are on 16-bit boundaries, see WORD LIST, page 375, for details. As an example, these words are used in the Forth ROM to ensure that the scratchpad memory area given by PAD always starts at an even address. Likewise WORD does not necessarily transfer input text to the next dictionary location as is usual, that address might be odd. Instead it uses one byte further on if necessary.
It is sometimes convenient to read and write 16-bit stack values to odd addresses, and the words !ODD and @ODD are provided for this purpose. Unlike ! and @ they will work with any address but are slower.
WRITING TO FLASH-EEPROM
The word !ODD has an additional feature. If the Flash-EEPROM is present in the 28-pin socket (and not locked) it will write a 16-bit value to the non-volatile memory using the correct write algorithm. Like some other words with this capability, it is based on a special headless version of C! . If you explicitly need this function, call it from the kernel as follows:
: XC! ( char ca -- )
\ Store the 8 lower bits of char
The following words are built upon this version of C! so also have the Flash-EEPROM write capability. The list may not be complete or accurate in some circumstances.
LOOP CREATE CODE !ODD CMOVE CMOVE> PLACE WORD C, HOLD <ACCEPT> S" C" POSTPONE ' CREATE INTERPRET # SIGN ACCEPT QUERY ." COMPILE, COMPILE LEAVE LITERAL IF UNTIL REPEAT ELSE ['] DOES> MARKER VARIABLE CONSTANT
Apart from interrupts, the processor can generate three exceptions. See ERROR HANDLING, page 144, for full details.
q Access of an odd address with a 16-bit transfer request (see above).
q Execution of an invalid instruction.
q Internal watchdog.
You can make the system take any action you want on these three exceptions in either of two ways:
q Place code to be executed on exception after the previously executed CATCH , see ERROR HANDLING, page 144.
q Change the INTERRUPT JUMP TABLE, page 170, to execute your own code.
Compile file #DOGCOLD.TDS before your application to change the default action into a full cold start. The file can also be used as a model when you want exceptions to vector to your own routines.
PERIPHERALS NEEDING E CLOCK
Most TDS2020F instructions are not synchronised with the E clocks because those are too slow. The microcycle time is only 102ns whereas the E clocks have an 814ns period. There are special assembler and Forth instructions that you must employ when addressing peripherals that use the E clocks. In high level Forth use PC! and PC@ to store and fetch one byte, think of them as 'Peripheral Character Store' etc.
All the addresses from addresses 8160 to 81FF in the TDS9 Gate Array on the TDS2020F computer need these instructions, see MEMORY MAPS, page 53, for details. If you add peripheral chips that input any of the following signals, also use the special access words. The LCD and keyboard words already have E clock synchronisation built into them:
R/W* E E* RD* WR* CS8180* CS81A0* CS81B0* CS81C0
Here are examples of use:
$81A0 PC@ \ get byte from addr $81A0 to top of stack
23 $81A0 PC! \ put byte 23 to address $81A0
B $81A0 )) R3 MOVFPE, \ MOVe From Peripheral with E
\ clock. Moves byte in from
\ address $81A0 to register 3
B $81A0 )) R3 MOVTPE, \ MOVe To Peripheral with E
\ clock. Moves byte out to
\ addr $81A0 from register 3
SHORT-FORM HEX AND ASCII LITERALS
An important addition in the TDS2020F is the ability to directly specify hex numbers without changing base. You just put a dollar sign in front of the number. For example the following word KEEP will store decimal 34 into address hex FE00:
: KEEP 34 $FE00 ! ;
The alternative usually used in Forth will still work but is unsightly-it hinders good documentation:
: KEEP 34 [ HEX ] FE00 [ DECIMAL ] ! ;
Apart from hex, you can also directly specify ASCII and control characters. An ASCII literal is specified by the prefix " and a control character with the prefix ^ . The following example puts decimal 65 (ASCII A) and 03 (Ctrl+C) on the stack and then prints them out. Try it:
"A ^C . .
Since TDS2020F is used in real-time applications a way of measuring exact execution speed is provided to monitor the time budget of your software.
The word 0TIME notes the current time from timer 3 and ?TIME does the same, subtracting the time found by 0TIME . The resulting execution period from one to the other is then converted to microseconds and the overhead taken by these two words is subtracted. The result is the time needed by the code sandwiched between the two. For example:
: TEST 1000 2000 0TIME UM* ?TIME U. 2DROP ;
Execution of TEST shows the time in microseconds taken by UM* . Always use this pair in a colon definition as shown. Since the overhead caused by these words is different between implementations, for instance use of Flash Forth or the TDS2020DV piggyback, they are smarter than briefly described here and will return the correct number of microseconds irrespective of the hardware environment.
There is a maximum of 53333�s and a longer delay should either be broken into parts or it should be measured by reading the on-card clock in ticks, mins and days before and after the event.
Some typical execution times are given in the table. All measurements were made on a stand-alone system with Forth and application in the microprocessor: