Tackling the queued serial peripheral interface
Jack is a freelance programmer and contributing editor to Embedded Systems Programming magazine. He can be contacted at either P.O. Box 51, Golden, CO 80402, [email protected]., or by fax at 303-277-9497.
Among Motorola's 300-bus microcontrollers, the 68332 is probably the most applicable to embedded-systems programming. The 68332 offers a slightly abbreviated 68020 instruction set along with a few added instructions. The 68332's time-processing unit (TPU) allows 16 digital I/O lines to be employed in a variety of timer-event functions. A third functional block of the 68332, the queued serial module (QSM), processes serial transactions on two channels: The first is the serial communications interface (SCI), which is an on-chip UART; the second is the queued serial peripheral interface (QSPI), a 4-wire synchronous serial bidirectional transfer mechanism.
Synchronous serial protocols are simultaneous, bidirectional clockings of bits between two stations. Synchronous serial data communications effect a design trade-off between data-transfer speed on one hand, and economy on the other. While a synchronous serial exchange between a CPU and a peripheral is slower than parallel bus communication, the smaller pin package of the synchronous serial periphal demands fewer printed wires and less board space. Another advantage of the synchronous serial peripheral is that the circuit designer, once having become familiar with such a peripheral device, is able to employ it in various designs without regard to the host microcontroller. In programmer's parlance, the synchronous serial peripheral is more portable than the bus peripheral.
Among the popular synchronous serial protocols for which off-the-shelf silicon devices are available are Philips/
Signetics' I2C, National Semiconductor's Microwire, and Motorola's SPI. While the I2C is attractive because it provides synchronous, full-duplex communications and determinate arbitration of multiple masters using two wires, the other two protocols (which require four wires and depend upon single-mastering via chip selects and station addresses) are useful, inexpensive, and available.
Not Just SPI
The queued serial peripheral interface (QSPI) submodule of the 68332 QSM is highly programmable, enough so that it can be used not only with the various and sometimes divergent implementations of Motorola SPI, but also with National Semiconductor Microwire devices.
In discussing the 68332, I'll refer to Vesta Technology's SBC332, a stand-alone, 68332-based, single-board computer. The SBC332 is a Motorola BCC pin-alike/work-alike with socketed memory and certain other features intended to make the SBC332 more generally useful than its ancestor, the BCC.
The SBC332 has been used to control an LCD/beeper/keypad (LBK) daughterboard via SPI, using the QSPI on the 332 side and two Harris CDP68HC68P1 8-bit SPI parallel ports on the LBK itself. If you're a data-sheet junkie and don't have the Harris book handy, note that the CDP68HC68P1 is a part acquired from GE/Intersil and appears in the latter organization's last few annual catalogs also.
In certain applications we've made good use of the 93(C)46, a second-sourced Microwire EEPROM which offers 64 16-bit words of readable/writable storage with a life cycle ranging from 100,000 writes per cell to over 400,000 writes per cell, depending on the manufacturer's specification. Larger devices ranging up to 11-bit address space that are essentially code-compatible with the smaller part are available in this family.
Communication with these two parts, the CDP68HC68P1 and the 9346, is the subject of the code examples presented here.
Queued Serial
The QSPI queue has 16 entries for commands and synchronous replies that travel on this bidirectional facility. The commands are written to command RAM, and the replies returned in receive RAM.
Once the desired setup is achieved by programming the appropriate QSM registers (for instance, by setting up the baud, master/slave relationship, appropriate clock edge for data latching and desired chip-select levels as in the accompanying source-code examples), conducting one or more QSPI transactions is a matter of:
- Writing commands to command RAM.
- Setting the new queue pointer (NEWQP) and end queue pointer (ENDQP) to point to the first and last command of a series of commands which are to be transmitted. This is done after establishing whether the commands between NEWQP and ENDQP should loop or execute in sequence once only by our settings of serial peripheral control register 2 (SPCR2).
- Sending a "go" message to the QSPI by setting the serial peripheral enable bit (SPE) high in serial peripheral control register 1 (SPCR1).
The Code
The source code presented here is written for Vesta Forth Standard Edition (VFSE), a fully orthogonal, 32-bit, subroutine-threaded, ROM-resident Forth, optimized for generation of embedded-control applications.
LBK332.F (Listing One, page 106) illustrates the use of the QSPI to control the Vesta LBK LCD/beeper/keypad board. While notable as a model of setting up the various registers and activating queued operations, once they are initialized the LBK's CD68HC68P1 ports are typical SPI protocol parts and require no especially neat programming tricks, other than appropriate delays for the controlled peripherals to react to commands. When I wrote the code, it wasn't clear to me why the serial peripheral finished flag always seemed to come True before the receive RAM that contains the response from the addressed SPI peripheral becomes valid. It turns out that the SPF flag doesn't self-reset; software must do this at the commencement of every queue launching. Well, I'll be! I therefore resorted to long loops (see the word LBK332! in the listing) between the instant QSPI asserts that a transaction is finished by setting the serial peripheral interface finished (SPIF) bit in the serial peripheral status register (SPSR) and the time I actually read the receive RAM. Sounds silly, but it worked at the time.
QSM332.F (Listing Two page 108) provides the generalized constructs for programming the registers of the QSM. All the registers concerned with QSM control are defined, along with their relevant bits. Where multiple-bit mask fields appear in the programming model, both the field and the shift required to move a right-justified mask into the proper position for writing to the register are defined.
Also defined are words to manipulate QSM interrupt structure, processor mode of access, activity, and status during 68332 BACKGROUND mode.
In 9346_332.F (available electronically), the requirements for emulating Microwire are more demanding. While it is easy enough to program data transitions on the correct clock edge as suited to Microwire by setting the CPOL and CPHA bits in serial peripheral control register 0 (SPCR0), the problem of message length is not as tractable.
The 68332 QSPI is designed for multiple transactions of the same data width. While that data width is programmable, it is difficult to reprogram on the fly, but that is precisely what is required to interface a Microwire device to the QSPI.
Certain operations upon the 9346 take one start bit, a 3-bit command, a 6-bit address, and a 16-bit data value. This 10-bit+16-bit bidirectional data exchange isn't native to QSPI: The bit-width of an SPI transaction is not part of the command RAM entry. Instead, it's a bit mask in SPCR0. Therefore, a transaction must be completed before this setting is switched from 10-bit to 16-bit transactions (the maximum) for the second portion of the Microwire message.
The problem is that when the transaction is suspended after the preliminary 10-bit start+command+address is transmitted to the 9346, QSPI lets the chip-select for the device go inactive, terminating (from the point of view of the 9346) the transaction.
The trick is that the program must explicitly assert the chip-select for the desired device by writing the appropriate mask to QPDR prior to activating the SPI. If the chip select is asserted explicitly, SPI doesn't de-assert it upon completing the single preliminary 10-bit transaction. Then the bit-width field in SPCR0 can be changed quickly and the second portion of the transaction sent on its way. The 9346 doesn't care that the serial clocking is thus a little longer between the 10th and 11th bit than at other times, since transaction clocking is the responsibility of the host processor. At the termination of the complete transaction, the chip-select is explicitly de-asserted.
Conclusion
"Sixers" who've watched in frustration as the 68K family has been relegated upwards to VME can relax now that Motorola has finally provided a part suitable for control applications, the bread and butter of embedded-systems programming. Just as 68332 on-chip discrete I/O and TPU help justify the cost of the part, 68332 QSPI alleviates, in part, the often-difficult task of selecting appropriate peripheral devices for a 68K-based embedded system.
[LISTING ONE] DOWNLOAD \ Filename: lbk332.f \ Author: jack j. woehr [email protected] JAX on GEnie SYSOP, RCFB (303) 278-0364 \ Copyright (c) 1991, Vesta Technology, Inc. ALL RIGHTS RESERVED. \ Platform: SBC332 w/ VFSE Purpose: Primitives & exercise LBK332 board. \ Dependencies: Platform; W@ W! (16-bit ops) \ TRUE FALSE 0<> from Core Extensions \ YREG332.F and QSM332.F must be loaded \ Some code meant to execute only in Supervisor mode. \ References: MC68332 USER'S MANUAL [MC68332UM/AD] Motorola, 1990 \ GE Solid State Data Book SSD-260C Printed 12-87 [GE-SSD] BASE @ HEX \ ** Utilities -- Kludgy delays, may have to be adjusted when PAUSE is \ implemented. Reason for this delay: 1) Receive RAM doesn't seem to be written \ yet even when SPI says it's done in the SPSR.SPIF register, and \ 2) This stuff seems to be too fast for the LCD display. : 20-MS ( --) 2000 0 DO ( PAUSE) LOOP ; : 100-MS ( --) 10000 0 DO ( PAUSE) LOOP ; \ ** Setting up for QSPI for the LBK332 \ These routines can serve as models for other types of QSPI setup, though \ actual values, e.g., baud, int vects & int levels might be different in a \ different application. These are specific to CDP68HC68P1 used on the LBK332. \ [MC68332UM/AD] 5.4.3.1 Write first to set output state. Specifically, we had \ better make sure that the LBK332 Chip Select is not active (low) (PCS0/_SS). : QPDR-SETUP ( --) QPDR.PCS0/_SS QPDR TRUE SET-YREG ; \ [MC68332UM/AD] 5.4.3.3 \ Then configure direction bits MISO input, PCS0 MOSI output : QDDR-SETUP ( --) QDDR.MISO QDDR FALSE SET-YREG QDDR.PCS0/_SS QDDR.SCK OR QDDR.MOSI OR QDDR TRUE SET-YREG ; \ [MC68332UM/AD] 5.5.4.6 \ Init RAM : QSPI-RAM-INIT ( --) ; \ [MC68332UM/AD] 5.4.3 : QPAR-BITS ( chip-sel-mask --) [ QPAR.PCS0/_SS QPAR.PCS1 OR QPAR.PCS2 OR QPAR.PCS2 OR ] LITERAL DUP ROT AND \ constrain chip select mask SWAP INVERT QPAR W@ AND \ NAND off CS bits in current reg mask OR \ OR in new chip select mask QPAR.MOSI QPAR.MISO OR OR \ OR in these bits QPAR W! \ store new mask ; \ [MC68332UM/AD] 5.5.4.1 .. Set up as master of 8 bit xfers, 2.1MHz, \ Data changes on leading edge, sampled on falling edge. : SPCR0-SETUP ( --) SPCR0.MSTR \ SBC332 is master 8 >SPCR0.BITS LSHIFT OR \ CDP68HC68P1 is 8 bit xfers SPCR0.CPHA OR \ [GE-SSD] pg. 537 Fig. 3 FF OR \ SPCR0.SPBR 33 KHz frequency (Table 5-9) SPCR0 TRUE SET-YREG \ install mask register ; \ [MC68332UM/AD] 5.5.4.2 .. Set up but don't start up : SPCR1-SETUP ( --) SPCR1.DSCKL >SPCR1.DSCKL LSHIFT SPCR1.DTL OR SPCR1.SPE OR SPCR1 FALSE SET-YREG ; \ [MC68332UM/AD] 5.5.4.3 .. Reads to this register get actual reg contents, \ not necessarily last-written which latter is buffered during serial xfer, \ taking effect next xfer. We setup here for no interrupts, no wraparound, etc. \ Of course, application will change this ... this is just init, \ and is powerup default. : SPCR2-SETUP ( --) 0 SPCR2 W! ; \ [MC68332UM/AD] 5.5.4.4 .. We don't need any of this stuff. : SPCR3-SETUP ( --) 0 SPCR3 W! ; \ ** Setup of QSM in order prescribed by [MC68332UM/AD] 5.4.1 : QSM-SETUP ( --) FALSE QSM-SUPERVISOR 1 QSM-IARB! FALSE QSM-STOP FALSE QSM-FREEZE 40 QIVR W! 1 1 QSM-INT-LEVEL QPDR-SETUP QDDR-SETUP QSPI-RAM-INIT QPAR.PCS0/_SS QPAR-BITS SPCR0-SETUP SPCR1-SETUP SPCR2-SETUP SPCR3-SETUP ; \ Set QSPI a-runnin' : QSPI-START ( --) SPCR1.SPE SPCR1 TRUE SET-YREG ; \ Orderly QSPI shutdown : QSPI-SHUTDOWN ( --) SPCR3.HALT SPCR3 TRUE SET-YREG BEGIN ( PAUSE) SPSR W@ SPSR.HALTA AND 0<> UNTIL SPCR1.SPE SPCR1 FALSE SET-YREG ; \ Clear a HALT condition : UNHALT ( --) SPCR3.HALT SPCR3 FALSE SET-YREG ; \ Return indicates of QSPI was inactive and thus able to conduct one two-byte \ transaction. Presumes only PCS0/_SS from among chip selects is assigned to \ QSPI; otherwise, command masks should contain states for other chip selects. : LBK332! ( u1 u2 -- flag) SPCR1 W@ SPCR1.SPE AND 0= IF TRAN-RAM 2 + W! TRAN-RAM W! COMD-RAM.CONT COMD-RAM C! \ PCS0/_SS low 0 COMD-RAM 1+ C! \ ditto SPCR2.NEWQP FALSE SPCR2 SET-YREG [ 1 >SPCR2.ENDQP LSHIFT SPCR2.ENDQP AND ] LITERAL SPCR2 TRUE SET-YREG QSPI-START TRUE 20-MS \ kludge delay for Receive RAM to get written ELSE 2DROP FALSE THEN ; : QSPI-DONE? ( -- flag) SPSR W@ SPSR.SPIF AND 0<> ; : QSPI-READY? ( -- flag) SPCR1 W@ SPCR1.SPE AND 0= ; : WAIT-QSPI-DONE ( --) BEGIN ( PAUSE) QSPI-DONE? UNTIL ; : WAIT-QSPI-READY ( --) BEGIN ( PAUSE) QSPI-READY? UNTIL ; \ Constants for controlling the two CDP68HC68P1 chips, addressed \ 0 and 1. Port 0 is all outputs, except for KEY*. Port 1 is an output to \ write to the LCD, and an input to read the keypad. [GE-SSD] pp. 537-539 00 CONSTANT PORT0 40 CONSTANT PORT1 00 CONSTANT DATA-REG 20 CONSTANT DIR-REG 00 CONSTANT READ 10 CONSTANT WRITE 00 CONSTANT WRITE-BITS 08 CONSTANT RESET-BITS 0C CONSTANT SET-BITS \ These only need to be set if you want to read the compare flag 00 CONSTANT ONE-NON-MATCH 01 CONSTANT ALL-MATCH 02 CONSTANT ALL-NON-MATCH 03 CONSTANT ONE-MATCH : PORT0-SETUP ( --) [ PORT0 DIR-REG WRITE WRITE-BITS OR OR OR ] LITERAL 7F LBK332! DROP \ port 0 all output except KEY* ; : PORT1-IN ( --) [ PORT1 DIR-REG WRITE WRITE-BITS OR OR OR ] LITERAL 00 LBK332! DROP ; : PORT1-OUT ( --) [ PORT1 DIR-REG WRITE WRITE-BITS OR OR OR ] LITERAL FF LBK332! DROP ; : LBK332-CONFIG ( --) PORT0-SETUP PORT1-IN \ must be changed to write LCD ; \ ** IO Port Control \ Bits from Port 0 01 CONSTANT R/W* \ Read/Write for LCD Port 02 CONSTANT ENLCD0 \ LCD 0 Enable 04 CONSTANT ENLCD1 \ LCD 1 Enable 08 CONSTANT ENKEY* \ CS for the 74HC541 which reads keypad 10 CONSTANT ENBEEP* \ Beeper enable 20 CONSTANT TONE0/RS \ RS for LCD .. D0 of Beeper pitch 40 CONSTANT TONE1 \ n/a for LCD .. D1 of Beeper pitch 80 CONSTANT KEY* \ Active low when there is a keypress 05 CONSTANT TONE-SHIFT \ Shift for pitch bitmask \ Only reads data, discards compare mask. : PORT0@ ( -- u) WAIT-QSPI-READY [ PORT0 DATA-REG READ OR OR ] LITERAL DUP LBK332! DROP WAIT-QSPI-DONE REC-RAM 2 + W@ ; \ Writes data : PORT0! ( u --) WAIT-QSPI-READY [ PORT0 DATA-REG WRITE WRITE-BITS OR OR OR ] LITERAL SWAP LBK332! DROP ; \ sets data : PORT0-SET! ( u --) WAIT-QSPI-READY [ PORT0 DATA-REG WRITE SET-BITS OR OR OR ] LITERAL SWAP LBK332! DROP ; \ resets data : PORT0-RESET! ( u --) WAIT-QSPI-READY [ PORT0 DATA-REG WRITE RESET-BITS OR OR OR ] LITERAL SWAP LBK332! DROP ; \ Only reads data, discards compare mask. : PORT1@ ( -- u) WAIT-QSPI-READY [ PORT1 DATA-REG READ OR OR ] LITERAL DUP LBK332! DROP WAIT-QSPI-DONE REC-RAM 2 + W@ ; \ Writes data : PORT1! ( u --) WAIT-QSPI-READY [ PORT1 DATA-REG WRITE WRITE-BITS OR OR OR ] LITERAL SWAP LBK332! DROP ; \ ** Keypad Control -- Enable, disable keypad reader. Necessary so that keypad \ data doesn't trash LCD writes. : KEYPAD-ENABLE ( --) ENKEY* PORT0-RESET! ; : KEYPAD-DISABLE ( --) ENKEY* PORT0-SET! ; \ Is a key currently pressed? : PKEY? ( -- flag) PORT0@ KEY* AND 0= ; \ @PKEY returns a mask in which D0-D2 are octal row and D3-D5 are octal column. \ The mask is only valid if KEY* is currently reading HI : @PKEY ( -- mask) PORT1-IN KEYPAD-ENABLE PORT1@ KEYPAD-DISABLE ; \ ** LCD Control -- Delays may have to be written into these LCD words \ depending upon serial clock rate. : LCD0-CMD! ( u --) KEYPAD-DISABLE PORT1-OUT PORT1! R/W* PORT0-RESET! TONE0/RS PORT0-RESET! ENLCD0 PORT0-SET! ENLCD0 PORT0-RESET! 100-MS \ kludge delay for slow LCD ; : LCD0-DATA! ( u --) KEYPAD-DISABLE PORT1-OUT PORT1! R/W* PORT0-RESET! TONE0/RS PORT0-SET! ENLCD0 PORT0-SET! ENLCD0 PORT0-RESET! 100-MS \ kludge delay for slow LCD ; : LCD1-CMD! ( u --) KEYPAD-DISABLE PORT1-OUT PORT1! R/W* PORT0-RESET! TONE0/RS PORT0-RESET! ENLCD1 PORT0-SET! ENLCD1 PORT0-RESET! 100-MS \ kludge delay for slow LCD ; : LCD1-DATA! ( u --) KEYPAD-DISABLE PORT1-OUT PORT1! R/W* PORT0-RESET! TONE0/RS PORT0-SET! ENLCD1 PORT0-SET! ENLCD1 PORT0-RESET! 100-MS \ kludge delay for slow LCD ; \ ** Generic LCD0 Stuph ... RTFM if this doesn't work : LCD0-HOME ( --) 02 LCD0-CMD! ; : LCD0-CLEAR ( --) 01 LCD0-CMD! ; : LCD0-INIT ( --) 38 LCD0-CMD! 0F LCD0-CMD! LCD0-HOME LCD0-CLEAR ; : LCD0-TYPE ( c-addr u --) OVER + SWAP ?DO I C@ LCD0-DATA! LOOP ; \ ** Beeper \ Deactivate the #@$!* beeper : UNBEEP ( --) PORT0@ ENBEEP* OR PORT0! ; \ Beep at pitches 0 - 3 : BEEP ( u --) 4 MOD TONE-SHIFT LSHIFT PORT0@ [ TONE0/RS TONE1 OR ] LITERAL INVERT AND OR ENBEEP* INVERT AND PORT0! ; \ ** Initialize : LBK332-SETUP ( --) QSM-SETUP PORT0-SETUP ; \ ** Quicky Test : TEST-LBK332 ( --) LBK332-SETUP LCD0-INIT BEGIN BEGIN UNBEEP PKEY? EKEY? OR UNTIL PKEY? IF LCD0-HOME LCD0-CLEAR @PKEY 1F AND DUP 3 RSHIFT DUP 4 MOD BEEP S" Row: " LCD0-TYPE 30 OR LCD0-DATA! 7 AND 30 OR DUP 4 MOD BEEP S" Column: " LCD0-TYPE LCD0-DATA! BEGIN PKEY? 0= EKEY? OR UNTIL ELSE KEY DROP UNBEEP EXIT THEN AGAIN ; BASE ! END-DOWNLOAD
[LISTING TWO]
DOWNLOAD \ Filename: qsm332.f \ Author: jack j. woehr [email protected] JAX on GEnie SYSOP, RCFB (303) 278-0364 \ Copyright (c) 1991, Vesta Technology, Inc. ALL RIGHTS RESERVED. \ Platform: SBC332 w/ VFSE \ Purpose: Defines and primitives for SBC332 Queued Serial Modul (QSM) \ Dependencies: Platform board; VFSE-332 operators W! W@ (16-bit ops). \ Needs: YREG332.F \ References: MC68332 USER'S MANUAL [MC68332UM/AD] Motorola, 1990 \ $Log: V:/vestasrc/forth/68332/tpuqsm/vcs/qsm332.f_v $ \ Rev 1.1 14 Jul 1992 11:26:26 jax \ cleanup edits \ Rev 1.0 17 Jun 1992 10:09:26 jax \ Initial revision. \ ** QSM registers and bits from MC68332UM/AD Tables 5-1 and 5-2. BASE @ HEX FFC00 YREG QMCR 8000 CONSTANT QMCR.STOP 4000 CONSTANT QMCR.FRZ1 2000 CONSTANT QMCR.FRZ0 80 CONSTANT QMCR.SUPV 0F CONSTANT QMCR.IARB \ field, not bit mask \ FFC02 YREG QTEST \ Not used in VFSE-332 \ 08 CONSTANT QTEST.TSBD \ 04 CONSTANT QTEST.SYNC \ 02 CONSTANT QTEST.TQSM \ 01 CONSTANT QTEST.TMM FFC04 YREG QILR \ 8 msbs \ FFC05 YREG QILR \ byte address, but SET-YREG uses W@ W! 3800 CONSTANT QILR.ILQSPI \ field 0B CONSTANT >QILR.ILQSPI \ bit shift 700 CONSTANT QILR.ILSCI \ field 08 CONSTANT >QILR.ILSCI \ bit shift FFC04 YREG QIVR \ 8 lsbs FF CONSTANT QIVR.INTV \ number \ FFC06 YREG RESERVED FFC08 YREG SCCR0 1FFF CONSTANT SCCR0.SCBR \ field FFC0A YREG SCCR1 4000 CONSTANT SCCR1.LOOPS 2000 CONSTANT SCCR1.WOMS 1000 CONSTANT SCCR1.ILT 800 CONSTANT SCCR1.PT 400 CONSTANT SCCR1.PE 200 CONSTANT SCCR1.M 100 CONSTANT SCCR1.WAKE 80 CONSTANT SCCR1.TIE 40 CONSTANT SCCR1.TCIE 20 CONSTANT SCCR1.RIE 10 CONSTANT SCCR1.ILIE 8 CONSTANT SCCR1.TE 4 CONSTANT SCCR1.RE 2 CONSTANT SCCR1.RWU 1 CONSTANT SCCR1.SBK FFC0C YREG SCSR 100 CONSTANT SCSR.TDRE 80 CONSTANT SCSR.TC 40 CONSTANT SCSR.RDRF 20 CONSTANT SCSR.RAF 10 CONSTANT SCSR.IDLE 8 CONSTANT SCSR.OR 4 CONSTANT SCSR.NF 2 CONSTANT SCSR.FE 1 CONSTANT SCSR.PF FFC0E YREG SCDR 100 CONSTANT SCDR.R8/T8 80 CONSTANT SCDR.R7/T7 40 CONSTANT SCDR.R6/T6 20 CONSTANT SCDR.R5/T5 10 CONSTANT SCDR.R4/T4 8 CONSTANT SCDR.R3/T3 4 CONSTANT SCDR.R2/T2 2 CONSTANT SCDR.R1/T1 1 CONSTANT SCDR.R0/T0 \ FFC10 YREG RESERVED \ FFC12 YREG RESERVED FFC14 YREG QPDR \ 8 lsbs only .. 8 msbs reserved 80 CONSTANT QPDR.TXD 40 CONSTANT QPDR.PCS3 20 CONSTANT QPDR.PCS2 10 CONSTANT QPDR.PCS1 8 CONSTANT QPDR.PCS0/_SS 4 CONSTANT QPDR.SCK 2 CONSTANT QPDR.MOSI 1 CONSTANT QPDR.MISO FFC16 YREG QPAR \ 8 msbs \ FFC17 YREG QPAR \ byte address, but SET-YREG uses W@ W! 4000 CONSTANT QPAR.PCS3 2000 CONSTANT QPAR.PCS2 1000 CONSTANT QPAR.PCS1 800 CONSTANT QPAR.PCS0/_SS 200 CONSTANT QPAR.MOSI 100 CONSTANT QPAR.MISO FFC16 YREG QDDR \ 8 lsbs 80 CONSTANT QDDR.TXD 40 CONSTANT QDDR.PCS3 20 CONSTANT QDDR.PCS2 10 CONSTANT QDDR.PCS1 8 CONSTANT QDDR.PCS0/_SS 4 CONSTANT QDDR.SCK 2 CONSTANT QDDR.MOSI 1 CONSTANT QDDR.MISO FFC18 YREG SPCR0 8000 CONSTANT SPCR0.MSTR 4000 CONSTANT SPCR0.WOMQ 3C00 CONSTANT SPCR0.BITS \ field 0A CONSTANT >SPCR0.BITS \ shift 200 CONSTANT SPCR0.CPOL 100 CONSTANT SPCR0.CPHA FF CONSTANT SPCR0.SPBR \ field FFC1A YREG SPCR1 8000 CONSTANT SPCR1.SPE 7F00 CONSTANT SPCR1.DSCKL \ field 08 CONSTANT >SPCR1.DSCKL \ shift FF CONSTANT SPCR1.DTL \ field FFC1C YREG SPCR2 8000 CONSTANT SPCR2.SPIFIE 4000 CONSTANT SPCR2.WREN 2000 CONSTANT SPCR2.WRTO F00 CONSTANT SPCR2.ENDQP \ field 08 CONSTANT >SPCR2.ENDQP \ shift 0F CONSTANT SPCR2.NEWQP \ field 00 CONSTANT >SPCR2.NEWQP \ shift FFC1E YREG SPCR3 \ 8 msbs \ FFC1F YREG SPCR3 \ byte address, but SET-YREG uses W@ W! 400 CONSTANT SPCR3.LOOPQ 200 CONSTANT SPCR3.HMIE 100 CONSTANT SPCR3.HALT FFC1E YREG SPSR \ 8 lsbs 80 CONSTANT SPSR.SPIF 40 CONSTANT SPSR.MODF 20 CONSTANT SPSR.HALTA 0F CONSTANT SPSR.CPTQP \ field \ FFC20 YREG RESERVED \ YFFC20 - YFFCFF FFD00 YREG REC-RAM \ YFFD00 - YFFD1F FFD20 YREG TRAN-RAM \ YFFD20 - YFFD3F FFD40 YREG COMD-RAM \ YFFD40 - YFFD4F 80 CONSTANT COMD-RAM.CONT 40 CONSTANT COMD-RAM.BITSE 20 CONSTANT COMD-RAM.DT 10 CONSTANT COMD-RAM.DSCK 08 CONSTANT COMD-RAM.PCS3 04 CONSTANT COMD-RAM.PCS2 02 CONSTANT COMD-RAM.PCS1 01 CONSTANT COMD-RAM.PCS0/_SS \ ** QSM Functionality \ *** [MC68332UM/AD 5.4.2.1] \ TRUE stops, FALSE enables QSM. Supervisor mode only. : QSM-STOP ( flag --) QMCR.STOP QMCR ROT SET-YREG ; \ To avoid complications at restart & prevent data corruption, first disable \ all submodules: SCI rx/tx should be disabled, and operation completion \ verified before asserting STOP. QSPI submodule should be stopped by asserting \ SPCR3.HALT and asserting STOP after HALTA flag set. TRUE causes QSM to HALT \ on transfer boundary when FREEZE asserted on IMB, FALSE causes QSM to ignore \ said signal. FREEZE is asserted when 332 enters the background mode. : QSM-FREEZE ( flag --) QMCR.FRZ1 QMCR ROT SET-YREG ; \ TRUE sets QSM supervisor-only access, FALSE (from supervisor mode, \ of course, resets to QSM user access permitted. : QSM-SUPERVISOR ( flag --) QMCR.SUPV QMCR ROT SET-YREG ; \ 0 causes 332 to view QSM int as spurious, 1 (lo) to 15 (hi) are \ interrupt arbitration priority levels. : QSM-IARB! ( 0-15 --) QMCR.IARB AND \ acceptable values 0 - 15 QMCR W@ \ fetch reg contents QMCR.IARB INVERT AND \ mask off IARB bits OR \ OR in desired mask QMCR W! \ store reg ; \ *** [MC68332UM/AD 5.4.2.2] is for when MCU is in test mode. \ Not used in Vesta Forth Standard Edition \ *** [MC68332UM/AD 5.4.2.3] \ Int levels 0-7; if same, QSPI given priority. : QSM-INT-LEVEL ( QSPI-level SCI-level --) >QILR.ILSCI LSHIFT QILR.ILSCI AND \ shift 0-7 mask and constrain SWAP >QILR.ILQSPI LSHIFT QILR.ILQSPI AND \ ditto OR \ form combination desired mask QILR W@ \ get register QILR.ILQSPI QILR.ILSCI OR INVERT AND \ mask off IL fields from reg OR \ OR in desired mask QILR W! \ store reg ; \ *** [MC68332UM/AD 5.4.2.4] \ Int vectors for QSPI/SCI are adjacent; bit D0 of int vect is 0 for SCI \ and 1 for QSPI. : QSM-INT-VECTOR ( vector --) QIVR.INTV AND QIVR W! ; \ *** [MC68332UM/AD 5.4.3] \ In general, bit assignments can be handled directly by the application \ using SET-YREG from YREGS322.F BASE ! END-DOWNLOAD End Listings
Copyright © 1993, Dr. Dobb's Journal