From: ian Date: Thu, 17 Nov 2005 18:50:15 +0000 (+0000) Subject: seriallib interface draft X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=a37c2f7e723fd5cb02f0ece356af4577bf242911;p=trains.git seriallib interface draft --- diff --git a/detpic/seriallib.inc b/detpic/seriallib.inc new file mode 100644 index 0000000..af77a34 --- /dev/null +++ b/detpic/seriallib.inc @@ -0,0 +1,211 @@ +;###################################################################### +; seriallib.inc - SERIAL LIBRARY - DECLARATIONS AND DOCUMENTATION +; +;============================================================ +; GENERAL INFORMATION + +; Purpose: +; -------- +; +; This library allows the PIC to communicate with the host via the +; PIC's UART, configured for RS232 at 9600 8N1. It implements +; unidirectional flow control: the host may ask the PIC not to +; transmit, but not vice versa. + +; Naming scheme: +; -------------- +; +; serial_... are for use by the rest of the program and +; are the entrypoints which enable use of the serial port +; serialu_... must be defined in the rest of the program +; with the functionality and behaviour described. + +; At all times following serial_init, the serial hardware in the PIC is +; completely reserved to the routines defined in seriallib.asm. Nothing +; else is allowed to read or modify the PIC UART state. + +; Use of PORTB, RBIF etc.: +; ------------------------ +; +; The seriallib makes use of the PORTB `interrupt on change' feature, +; and expects at all times after serial_init to have exclusive use of +; that feature, including the RBIF flag. Only seriallib is allowed to +; make reads of PORTB directly; the main program must call +; serial_portb_read instead. The main program may freely write to +; LATB. +; +; If any of RB5, RB6 or RB7 is an output which would be electrically +; floating if left in tristate (Z state by the PIC) then before +; calling serial_init the main program must have configured the +; appropriate TRISB bit(s) as outputs - presumably, after having +; configured the corresponding LATB bit(s). This will avoid excessive +; interrupts resulting from floating values. +; +; Registers and calling conventions: +; ---------------------------------- +; +; Unless otherwise stated, all routines accept any value in, and may +; trash, W and the flags. All other registers and locations not +; specifically mentioned here will be preserved by the +; serial_... routines (and are therefore reserved for the rest of the +; program). In all cases, routines are called with CALL or RCALL or +; the equivalent, and routines are allowed to have subroutines (ie, to +; use the call/return address stack). + +; serial_... routines except serial_interrupt will never _directly_ call +; any serialu_... routine; when we say `causes' this means that the +; relevant serialu_... routine will be called at some later point from +; serial_interrupt. serialu_... routines are allowed to call appropriate +; serial_... routines (except serial_interrupt) directly if the context +; and Tx State allows. + +; All routines except serial_init and serial_write_please +; must be called only: +; * During a low-priority interrupt; +; * From the main loop with low-priority interrupts disabled; or +; * From within an serialu_... routine (which are always called +; from within serial_interrupt). +; This is to avoid having one serial_... routine running in an interrupt +; which interrupted the middle of another serial_... routine. + +; Some time between calling serial_init and waiting for the first event, +; the main program should of course enable interrupts. + +;============================================================ +; COMMON ROUTINES and RECEPTION + +;-------------------- + extern serial_init +; +; Initialises the serial port and library state appropriately. Must +; be called exactly once, which must be before any other +; serial_... function. +; +; At call On return +; serial controller any for use by seriallib +; PORTB any for use by seriallib +; serial interrupt config any enabled, low priority +; Port B interrupt-on-change any enabled, low priority +; TRISB<5:7> any outputs configured unchanged +; TRISB<4> any configured for input +; TRISB<0:2> any unchanged +; LATB any outputs configured unchanged, use freely +; global interrupt enable disabled unchanged +; Tx State Not-in-use Must-Notify +; +; Note that as soon as the interrupts are enabled, the serial port +; will generate an interrupt, so that we go from Tx State Must-Notify +; to Idle via call to serialu_writeable. (See the Transmission +; section below.) + +;-------------------- + extern serial_portb_read +; At call On return +; W any value from PORTB +; +; Provided to allow the main program to read any bits in PORTB which +; it is using as inputs. See the notes above about PORTB. + +;-------------------- + extern serial_interrupt +; +; Must be called by the main program's low priority interrupt handler. +; The main program's interrupt handler is responsible for saving W and +; the flags register and other interrupt-related administrivia. If +; there is a serial interrupt, this routine will service it, taking any +; necessary action including calling appropriate serialu_... routines, +; and clear the interrupt flag[*]. +; +; At call On return +; Tx State any except Not-in-use may change +; serial interrupt state any cleared[*] +; +; [*] The interrupt event on entry, if any, will be dealt with. If +; interrupt processing takes a long time, another interrupt will occur +; and this may result in the serial interrupt flag being set on return +; from serial_inerrupt. + +;-------------------- + extern serialu_receive +; +; Called to notify the main program that a byte has been recieved from +; the host. The byte value is supplied. There is no way for the PIC +; to signal flow control to the host, to stop the host from sending +; data. It is up to the main program to do _something_ with the +; received data (or to panic or to discard it). +; +; Beforehand At call +; W data byte from host + +;====================================================================== +; TRANSMISSION +; +; States: +; [Not-in-use] +; | +; |init +; V +; ,------------->+<-------------. +; | | | +; | [Must-Notify] | +; | | | +; | write_ready| | +; | | | +; | V | +; | [Idle] | +; | | `-----------' +; | write_byte| write_please +; | | +; | V +; | [Busy]<----------. +; | | `-----------' +; `--------------' write_please + +; The seriallib will handle the host's requests for flow control. + +;-------------------- + extern serialu_write_ready +; +; Called to notify the main program that the serial port is now ready +; to transmit a byte. The main program should call serial_write_byte, +; or serial_write_please, either immediately or at some later point. +; +; Beforehand At call +; Tx State Must-Notify Idle + +;-------------------- + extern serial_write_byte +; +; Provides a byte to be written to the serial port. +; +; At call On return +; Tx State Idle Busy +; W byte for host any + +;-------------------- + extern serial_write_please +; +; Asks to be re-notified if the serial port is ready for transmission. +; This will regenerate the call to serialu_write_ready if applicable. +; +; At call On return +; Tx State Idle Must-Notify +; Tx State Busy Busy +; +; serialu_write_ready will *not* be called directly from +; serial_write_please, but only from serial_interrupt (as discussed +; above). +; +; Exceptionally, serial_write_please is fully reentrant. It need not +; be called from interrupt context and need not be called with +; interrupts disabled. It is permissible for serial_write_please to +; be interrupted by an invocation of serial_interrupt or vice versa. +; +; For example, if the main program has a buffer of characters for +; transmission, serialu_write_ready would call serial_write_byte if +; the buffer had something in it. If it didn't then it would simply +; return. When something is put in the buffer, the main program would +; call serial_write_please unconditionally, which would ensure that +; serialu_write_ready will be called soon. + +;======================================================================