| Jackrabbit (BL1800 Series) Getting Started |
4. Software Reference
4.1 More About Dynamic C
Dynamic C has been in use worldwide since 1989. Dynamic C is specially designed for programming embedded systems. Dynamic C features quick compile and interactive debugging in the real environment. A complete reference to Dynamic C is contained in the Dynamic C Reference Manual.
Dynamic C for RabbitTM processors uses the standard Rabbit programming interface. This is a 10-pin connector that connects to the Rabbit serial port A. It is possible to reset and cold-boot a Rabbit processor via the programming port. No software needs to be present in the target system. More details are available in the Rabbit 2000 Microprocessor User's Manual.
Dynamic C cold-boots the target system and compiles the BIOS. The BIOS is a basic program of a few thousand bytes in length that provides the debugging and communication facilities that Dynamic C needs. Once the BIOS has been compiled, the user can compile his own program and test it. If the BIOS fails because of a crash, a new cold boot and BIOS compile can be done at any time.
Each type of Rabbit microprocessor system can have a different BIOS, or the BIOS program can be customized by using #define options. The Jackrabbit board is supplied with one BIOS, and a flash memory and a RAM memory to hold the program. RAM memory is useful for holding a program while debugging is being done because it is more flexible than flash memory.
Dynamic C does not use include files, rather it has libraries which are used for the same purpose, that is, to supply function prototypes to programs before they are compiled. Libraries are much easier to use compared to include files.
Dynamic C supports assembly language, either as separate programs or as fragments embedded in C programs. Interrupt routines may be written in Dynamic C or in assembly language.
4.1.1 Operating System Framework
Dynamic C does not include an operating system in the usual sense of a complex software system that is resident in memory. The user has complete control of what is loaded as a part of his program, other than those routines that support loading and debugging and which are inactive at embedded run time. However, certain routines are very basic and normally should always be present and active.
- Periodic interrupt routine. This interrupt routine is driven by the Rabbit periodic interrupt facility, and when enabled creates an interrupt every 16 ticks of the 32.768 kHz oscillator, or every 488 µs. This routine drives three long global variables that keep track of the time: SEC_TIMER, MS_TIMER, and TICK_TIMER that respectively count seconds, milliseconds, and 488 µs ticks. These variables are needed by virtually all functions that measure time. The SEC_TIMER is set to seconds elapsed since 1 Jan 1980, and thus also keeps track of the time and date. The periodic interrupt routine must be disabled when the microprocessor enters sleepy mode and the processor clock is operating at 32.768 kHz. The interrupt routine cannot complete at this slow speed before the next tick of the periodic interrupt. In this situation, the hardware real-time clock can be read directly to provide the time.
- Watchdog support routines. Although the Rabbit watchdog can be disabled, this is not recommended since the watchdog is an essential facility for recovering from crashes. Very few systems are crash-free in real life.
4.2 I/O Drivers
The Jackrabbit board contains four high-power digital output channels, two D/A converter output channels, and one A/D converter input channel. These I/O channels can be accessed using the functions found in the JRIO.LIB library.
4.2.1 Initialization
The function jrioInit() must be called before any other function from the JRIO.LIB library. This function initializes the digital outputs and sets up the driver for the analog input/outputs. The digital outputs correspond to the Rabbit processor's port E bits 0-3, and the analog I/O uses timer B; bits 1, 2, and 4 of port D; and bits 6 and 7 of port E.
The function void jrioInit() initializes the I/O drivers for Jackrabbit. In particular, it sets up parallel port D bits 1, 2, and 4 for analog output, port E bits 0-3 for digital output, and starts up the pulse-width modulation routines for the A/D and D/A channels. Note that these routines can consume up to 20% of the CPU's processing power; the routines use timer B and the B1 and B2 match registers.
4.2.2 Digital Output
The Jackrabbit board contains four high-power digital output drivers, HV0-HV3, on header J4. These can be turned on and off with the following functions from the library JRIO.LIB.
HV0, HV1, and HV2 are open-collector sinking outputs, and are able to sink up to 1 A (200 mA for the BL1810 and BL1820) from a 30 V source connected to the K line on header J4. HV3 is a sourcing output that is able to source up to 500 mA (100 mA for the BL1810 and BL1820) from a 30 V source connected to the K line.
void digOut(int channel, int value)
- sets the state of a digital output bit.
- jrioInit must be called first.
- channel is the output channel number (0-3 on the Jackrabbit).
- value is the output value (0 or 1).
void digOn(int channel)
- sets the state of a digital output bit to on (1).
- jrioInit must be called first.
- channel is the output channel number (0-3 on the Jackrabbit).
void digOff(int channel)
- sets the state of a digital output bit to off (0).
- jrioInit must be called first.
- channel is the output channel number (0-3 on the Jackrabbit).
NOTE See the sample program JRIOTEST.C for an example of using the digital output functions. 4.2.3 Analog Output
The two analog output channels on the Jackrabbit (DA0 and DA1 on header J5) are controlled by a pulse-width modulation (PWM) driver. This requires the use of some fraction of the CPU cycles when the driver is running (up to 20% when both D/A channels are used). A voltage is selected by giving a value from 0 to 1024 to the driver, corresponding roughly to 0.1 V to 3.5 V on DA0. Because of the PWM interrupt frequency, the PWM driver can provide a continuous range of voltage output in the range from 0.1 V to 3.0 V for DA0, and 0.6 V to 3.6 V for DA1. These ranges can be specified with the constants PWM_MIN, PWM_MAX0, and PWM_MAX1. In other words, setting channel DA0 to the value PWM_MIN will output 0.1 V, and setting it to PWM_MAX0 will output 3.0 V. Similarly, setting DA1 to PWM_MIN will output 0.6 V, and setting it to PWM_MAX1 will output 3.6 V. Values below PWM_MIN will be rounded down to 0, and values above PWM_MAX0 (PWM_MAX1 for DA1) will be rounded up to 1024.
The output channels can also be set in an "always on" or "always off" mode, which does not require CPU cycles. The "always on" mode is set by requesting an output value of 1024, and will provide about 3.4 V on channel DA0, and 3.6 V on DA1. The "always off" mode is selected by asking for a value of 0, and provides an output of around 0.1 V on DA0 and 0.0 V on DA1.
See Table 3 below for a summary of the possible analog output voltages corresponding to values given in the anaOut function.
Table 3. Typical Analog Output Voltages Corresponding
to Values in anaOut FunctionDA0 0.08 V 0.08 V 2.875 V 3.4 V DA1 0.004 V 0.63 V 3.6 V 3.6 V The output value is set using the following function.
void anaOut(int channel, int value)
- sets the state of an analog output channel.
- jrioInit must be called first.
- channel is the output channel number (0 or 1 on the Jackrabbit).
- value is an integer from 0-1024 that corresponds to an output voltage as shown in Table 3.
NOTE See the sample program JRIOTEST.C for examples of using the anaOut function. Effect of Interrupts on Analog I/O
The stability of the voltage output (and hence the voltage input determination as well) depends on the ability of the driver to respond quickly to interrupt requests. Dynamic C debugging, use of the printf function, or any serial communications can disrupt the pulse-width modulation utilized by the driver and cause fluctuations in the voltage outputs. Avoid using serial communications or printf statements during portions of your program where the voltage must remain steady. Also be aware that debugging and running Dynamic C in polling mode will cause fluctuations. Finally, be certain to disable the PWM drivers by setting the output values to 0 or 1024 when you are done using them to free up the CPU.
Calibration of Values to Voltages
The analog output channels on the Jackrabbit board can be more accurately calibrated for each individual Jackrabbit board in the following manner (calibration of DA0 is assumed in this example, calibration of DA1 would proceed similarly):
- Set desired channel output to PWM_MIN.
- Measure voltage Vmin on DA0.
- Set desired channel output to PWM_MAX0.
- Measure voltage Vmax on DA0.
- A linear relation between input value and voltage can now be calculated:
4.2.4 Analog Input
The analog input channel on the Jackrabbit (AD0 on header J5) works by varying analog output channel DA0 until its voltage matches the input voltage on AD0. DA0 obviously cannot be used while an input voltage is being measured, although channel DA0 is still available. The value returned corresponds to the value that DA0 required to match the input voltage (you would call anaOut(0,value) for DA0 to provide that same voltage). If the value returned is negative, then the function considers the value suspect for some reason (most likely a failure of the DA0 voltage to settle quickly). The value can be taken as is, or another measurement can be done.
void anaIn(int channel, int *value)
- Analog input for the Jackrabbit analog input channel (AD0).
- jrioInit must be called first.
- channel is the input channel number (0 only on the Jackrabbit).
An integer between 0 and 1024 will be returned in value, corresponding to a voltage obtained if output channel DA0 was set to that value. If a value is found, but the voltage has not appeared to fully settle, the value will be negative (but equal in magnitude to the found voltage) to allow remeasurement if desired.
NOTE See sample program JRIOTEST.C for an example of the use of anaIn. Two versions of the analog input function are available: the standard function, listed above, that does not return until the measurement has been made, and a cofunction version that can be called from within a costatement. This cofunction version allows other tasks to be performed while the voltage match is being made. The voltage measurement will take ten calls of the cofunction version to make a measurement.
void cof_anaIn(int channel, int *value)
- The parameters are identical to those described above for anaIn.
NOTE See sample program JRIO_COF.C for an example of the use of cof_anaIn. 4.3 Serial Communication Drivers
The interface to the Rabbit serial library, RSERIAL.LIB, is designed to provide users with a set of functions that send and receive entire blocks of data without yielding to other tasks, a set of single user cofunctions that send and receive data but yield to other tasks, and a set of circular buffer functions.
The naming convention is serXfn:
- ser - serial
- X - the port being used: A, B, C, or D
- fn - the function being implemented
For example, serBgetc() is the serial port B function getc(), which returns a character.
The Rabbit serial functions are listed in the following groups.
- Open and Close Functions
- Non-Cofunction Blocking Input Functions
- Non-Cofunction Blocking Output Functions
- Single-User Cofunction Input Functions
- Single-User Cofunction Output Functions
- Circular Buffer Functions
4.3.1 Open and Close Functions
The open and close functions enable and disable serial communication over the specified port.
int serXopen (long baud);
- Currently only 8N1 transmission (8 data bits, no parity, 1 stop bit) is supported. The open function sets up the interrupt service routine vector.
Parameters
- baud--desired baud rate in bits per second
Return Value
- 1--The baud rate set on the Rabbit is the same as the input baud rate.
- 0--The baud rate set on the rabbit does not match the input baud rate.
int serXclose ( );
- Disables the serial port interrupt service routine.
Parameters
- None.
Return Value
- 1
4.3.2 Non-Cofunction Blocking Input Functions
These are simple functions that do not use Dynamic C costatements. If no input data are available when called, they return immediately with appropriate status information in their return value. Once they begin to receive characters, they do not yield to other tasks until they complete their operation or until a character-to-character timeout period elapses.
int serXgetc ( );
- Gets a single character. Always returns immediately, either with the next available input byte, or with -1 if none is available.
Parameters
- None
Return Value
- An integer with return character in the low byte. No character is represented by a return of -1.
int serXread (void *data, int length, unsigned long tmout);
- Reads a block of characters. Returns the number of bytes read from an input serial stream. The stream is considered to be ended when all length bytes have been read or when the timeout period elapses waiting for data to appear in the input buffer.
Parameters
- data--Destination data structure. The user must ensure data is allocated for at least length bytes.
- length--The number of bytes to read.
- tmout--The number of milliseconds to wait for receipt of each byte before timing out.
Return Value
- The number of bytes read into data until timed out or until all length bytes have been read.
4.3.3 Non-Cofunction Blocking Output Functions
These are simple functions that do not use Dynamic C costatements. They immediately begin to perform their task, not yielding to other tasks until all characters have been written.
int serXputc (char c);
- Writes a character to the serial port.
Parameters
- c--Character to write
Return Value
- 1 for success, 0 if the character could not be written to the port.
int serXputs (char *s);
- Calls serXwrite (s, strlen (s)).
Parameters
- s--Null-terminated character string source to write to the serial port.
Return Value
- The number of characters written.
int serXwrite (void *data, int length);
- Writes a block of length bytes to the serial port.
Parameters
- data--Destination data structure. The user must ensure data is allocated for at least length bytes.
- length--The number of bytes to read.
Return Value
- The number of bytes written to the serial port.
4.3.4 Single-User Cofunction Input Functions
These are Dynamic C cofunctions. If the input buffer they use is locked or becomes full during the course of their operation, they yield to other tasks, but do not return to execute the next statement within their own costatement block until they have completed their operation.
scofunc int cof_serXgetc ( );
- Reads a single character from the serial port, yielding when not successful, and only returning when a character is successfully read.
Parameters
- None
Return Value
- An integer with the character read in the low byte.
scofunc int cof_serXgets(char *s, int length, unsigned long tmout);
- Reads a null-terminated string, completes its execution when a carriage return is read, length number of characters are read, or the character to character timeout period elapses after the first character is read. It yields to other tasks while the input buffer is locked or becomes empty during its execution, and only returns control to the following statement in its own costatement block when it completes.
Parameters
- data--Destination data structure. The user must ensure data is allocated for at least length bytes.
- length--The number of bytes to read.
- tmout--The number of milliseconds to wait for each character after the first character is read.
Return Value
- 1--CR or length bytes read into s.
- 0--Function times out before reading CR or length bytes.
scofunc int cof_serXread(void *data, int length, unsigned long tmout);
- Reads a block of characters, completes its execution when length number of characters are read, or the character-to-character timeout period elapses after the first character is read. It yields to other tasks while the input buffer is locked or becomes empty during its execution and only returns control to the following statement in its own costatement block when it completes.
Parameters
- data--Destination data structure. The user must ensure data is allocated for at least length bytes.
- length--The number of bytes to read.
- tmout--The number of milliseconds to wait for each character after the first.
Return Value
- The number of bytes read.
4.3.5 Single-User Cofunction Output Functions
These are Dynamic C cofunctions. If the output buffer they use is locked or becomes empty during the course of their operation, they yield to other tasks, but do not return to execute the next statement within their own costatement block until they have completed their operation.
scofunc void cof_serXputc (char c);
- Writes a single character to the serial port, yielding to other tasks when unsuccessful, and returning only when the character is successfully written.
Parameters
- c--Character to write to the serial port.
Return Value
- None
scofunc void cof_serXputs(char *s);
- Writes a null-terminated character string to the serial port, yielding to other tasks when unsuccessful or whenever the buffer is full, returning only when the string is successfully written.
Parameters
- s--Null-terminated character string written to the serial port.
Return Value
- None
scofunc void cof_serXwrite (void *data, int length);
- Writes a block of characters to the serial port, yielding to other tasks when unsuccessful or whenever the buffer is full, returning only when all the data is successfully written.
Parameters
- data--Source data structure to write to the serial port.
- length--Number of characters in data to write.
Return Value
- None
4.3.6 Circular Buffer Functions
These functions act on or report status of the circular transmit/receive buffers.
Macro definitions are used to establish the buffer sizes:
- xINBUFSIZE--read buffer size, where x is A, B, C, or D
- xOUTBUFSIZE--write buffer size where x is A, B, C, or D
The user must define each buffer size for each port being used to be a power of 2 minus 1 with a macro. The size of 2^n - 1 enables masking for fast rollover calculations. If no value or an illegal value is defined, a default size of 31 will be used and a compiler warning will be given. When using cofunctions, smaller buffer sizes can yield more frequently to other tasks, but have the risk of a large input data stream overrunning the buffer and losing data if the other task executes for too long relative to the baud rate.
int serXpeek ( );
- Returns the first character in the receive buffer, if any are available, without removing it from the buffer.
Parameters
- None
Return Value
- An integer with return character in the low byte. No character is represented by a return of -1.
void serXrdFlush ( );
- Flushes the serial port receive buffer.
Parameters
- None
Return Value
- None
void serXwrFlush ( );
- Flushes the serial port transmit buffer.
Parameters
- None
Return Value
- None
int serXrdFree ( );
- Calculates the free space in the serial port receive buffer.
Parameters
- None
Return Value
- The number of characters the serial port receive buffer can accept before becoming full.
int serXwrFree ( );
- Calculates the free space in the serial port transmit buffer.
Parameters
- None
Return Value
- The number of characters the serial port transmit buffer can accept before becoming full.
int serXrdUsed ( );
- Calculates the number of characters ready to read from the serial port receive buffer.
Parameters
- None
Return Value
- The number of characters currently in the serial port receive buffer.
| Z-World http://www.zworld.com Voice: (530) 757-3737 FAX: (530) 753-5141 sales@zworld.com |