IAR Aug 2000
Device Driver Development - Portability and Tools
While application developers often have access to good software tools, the task of
designing and implementing device drivers have continued to be time-consuming and
prone to errors, largely due to a lack of adequate tools.
Developing device drivers for a highly integrated microcontroller can be daunting, partly
due to the sheer complexity of the device, but also due to some other difficulties. This
article will give an overview of device driver design and traditional development
techniques, and then discuss portability and the options available using modern tools,
such as IAR MakeAppÔ.
Chip Initialization
When a new electronic board is available, software must be written to handle system
start-up. This is usually done by responding to a reset interrupt or jumping to a fixed start
address. Basic initialization of stack pointer, compiler environment and bus controller
settings are done during this phase. The CPU will most often not interface to external
hardware unless some low-level configurations are made:
·
Bus interface (address and data buses, chip-select signals).
·
Memory configuration (DRAM refresh, wait-states, handshaking).
·
Interrupt system (IRQs, interrupt priorities and masks).
Once low-level configuration has been performed, execution normally continues in the
application programs main() function. At this point, the application logic and device
drivers can start execution.
Peripheral module device drivers
Device drivers provide a software interface for accessing hardware from software. The
application developer now needs a driver library that can be used by the application
program to access hardware services in peripheral modules (UARTs, Timers, A/D or D/A
converters, CAN or DMA controllers etc).
Peripheral module device drivers take care of:
·
Initialization (e.g. setting up baud rate or timer periods)
·
Run-time control (e.g. sending character strings or starting DMA transfers)
·
Interrupt handling (responding to hardware events)
Driver logic is normally implemented by modifying or testing special function register
(SFR) control and status bits in a suitable order. A modern high-end microcontroller can
have several thousand SFR bits, each of which must be carefully initialized and
manipulated at run-time in proper sequence.