Introduction | - | - | UART drivers are modules which contain all the hardware level driver code
for hardware which performs Universal Asynchronous Receiver Transmitter functions - or in
lay-man's terms, serial input and output. Common UARTs include the 16550 and antique 8250. Both at a minimal level allow the input and output of characters across a serial line. However, debuggers may require the use of the only serial port on some hardware, and so hence a UART driver module may indirect console i/o through the debugger. Also, hardware like an ethernet controller or a parallel port can function as a UART, so these driver modules are not restricted to merely serial hardware. You could even drive an LCD panel or VGA display as a UART. Furthermore, as there may be more than one UART controller of the same type in your hardware (often there are two serial controllers in development hardware), the driver keeps its internal data within a context block. This allows the same code to drive multiple controllers of the same type easily. |
|||||||||||||||||||||||||
Callability |
|
|||||||||||||||||||||||||||
HALError |
The first four letters of the module name should be some four letter mnemonic representing the chosen name of the driver. |
|||||||||||||||||||||||||||
Portability | API is portable Code is portable |
|||||||||||||||||||||||||||
Constituents | Usually written in ANSI C for portability | |||||||||||||||||||||||||||
Porting notes | All non-portable information will be in the common.h file held in the specific port directory. Some problems may occur with the packing of items within structures or bit orientation of the host processor | |||||||||||||||||||||||||||
Other Notes | None | |||||||||||||||||||||||||||
General use | Because each UART driver is different, there are different prefixes
before each call provided by the module. However, the postfixes and function of each call
are the same across every UART driver. Prefixes can be anything you want, but it is good form to maintain some sort of convention. We suggest <acronym>UARTDriver_<API postfix> eg; 16550UARTDriver_Initialise. It is expected that most UART driver modules will be written entirely in C to aid portability (hence one can change the processor but retain the remainder of the hardware). However, if the module is written in C, calls may only be made when the C run-time system is operational (ie; main memory and C library working and initialised). Hence, one may wish to write the driver partly or wholly in assembler to prevent these limitations - this can be especially relevent when debugging early boot code. Interrupt driven i/o is not expected to be implemented within the NedHAL API framework, but DMA driven i/o is permitted and encouraged. This is because interrupt driven i/o requires substantial support from other areas of NedHAL which are non-portable, and hence the UART code would become unportable. You can by all means add your own API's to do interrupt driven i/o to the same module source, or else have an internal switch to interrupt driven i/o after the operating system is ready to handle it - but the driver module must start up in a fashion which does not require interrupt support. Remember that debug i/o is best done in a polled fashion in case the operating system is too screwed up to do it via interrupts. To initialise and finalise the operation of this module, the usual calls <name>_Initialise and <name>_Finalise are provided. The API <name>_Set sets the future operation of the UART. The API's <name>_WriteN and <name>_ReadN perform output and input to the UART. The optional API <name>_GetIOStatus returns the current buffer status of the UART. |
Purpose | - | - | Initialises the UART driver module for subsequent use | |
Prototype | HALError *<name>_Initialise(HALUARTBlk *contextblk, void *hardwareaddr, int uartid) | |||
Exit | Null if no error occurred, pointer to valid HALError structure otherwise | |||
Interrupts | IRQ is unchanged FIQ is unchanged |
|||
Processor Mode | Unchanged | |||
Staticity | Not static | |||
Use | This call initialises the HALUARTBlk pointed to by contextblk
with appropriate data to drive the UART hardware at base address hardwareaddr.
You may assign a driver-dependent identification number in uartid
- this may be necessary for internal driver purposes. You will need to keep the context block set up by this call valid at all times until you have finalised its operation as DMA driven i/o may need to use the block to perform its task. |
|||
Notes | None |
Purpose | Deinitialises the UART driver module | |||
Prototype | HALError *<name>_Finalise(HALUARTBlk *contextblk) | |||
Exit | Null if no error occurred, pointer to valid HALError structure otherwise | |||
Interrupts | IRQ is unchanged FIQ is unchanged |
|||
Processor Mode | Unchanged | |||
Staticity | Not static | |||
Use | This call deinitialises the hardware specified by contextblk. You may dispose of contextblk after this call returns. | |||
Notes | None |
Purpose | Reconfigures the UART driver | |||
Prototype | HALError *<name>_Set(HALUARTBlk *contextblk, u32 baud, u8 bits, u8 parity, u8 stopbits) | |||
Exit | Null if no error occurred, pointer to valid HALError structure otherwise | |||
Interrupts | IRQ is unchanged FIQ is unchanged |
|||
Processor Mode | Unchanged | |||
Staticity | Not static | |||
Use | This call changes the settings of the hardware specified by contextblk
to run at baud bits per second, to use bits
bits per byte and to use stopbits stop bits per byte sent. The only parameter which should need further explanation is parity. This can take one of the following values:
|
|||
Notes | None |
Purpose | Writes a a certain number of characters to the UART driver | |||
Prototype | HALError *<name>_WriteN(HALUARTBlk *contextblk, char *buffer, int length) | |||
Exit | Null if no error occurred, pointer to valid HALError structure otherwise | |||
Interrupts | IRQ is unchanged FIQ is unchanged |
|||
Processor Mode | Unchanged | |||
Staticity | Not static | |||
Use | This call writes length characters from the
character array pointed to by buffer to the hardware specified by contextblk. Note that this call may or may not return before all or part of the actual write takes place. Use <name>_GetIOStatus to determine current input and output status. If the write does take place asynchronously, the buffer passed to this call is copied to an internal buffer and hence you may dispose of the local buffer upon return of this call. |
|||
Notes | None |
Purpose | Reads a a certain number of characters from the UART driver | |||
Prototype | HALError *<name>_ReadN(HALUARTBlk *contextblk, char *buffer, int length) | |||
Exit | Null if no error occurred, pointer to valid HALError structure otherwise | |||
Interrupts | IRQ is unchanged FIQ is unchanged |
|||
Processor Mode | Unchanged | |||
Staticity | Not static | |||
Use | This call reads length characters into the
character array pointed to by buffer from the hardware specified
by contextblk. This call will always wait until all the characters have been read. Use <name>_GetIOStatus to determine how many characters are awaiting to be read. |
|||
Notes | None |
Purpose | Returns the current input and output status' of the UART driver | |||
Prototype | HALError *<name>_GetIOStatus(HALUARTBlk *contextblk, s32 *txsize, s32 *rxsize) | |||
Exit | Null if no error occurred, pointer to valid HALError structure otherwise | |||
Interrupts | IRQ is unchanged FIQ is unchanged |
|||
Processor Mode | Unchanged | |||
Staticity | Not static | |||
Use | This call sets the s32's pointed to by txsize and
rxsize to the characters remaining in output buffer and the input
buffer respectively of the hardware specified by contextblk. If either the pointer's txsize or rxsize are null on entry, those values are not set. If the values returned are -1, this indicates a value which is not zero (ie; the driver does not know how many bytes there are but it does know that it isn't none). |
|||
Notes | This call may not be provided by some UART driver modules |