Upload
flashdomain
View
462
Download
1
Embed Size (px)
Citation preview
SE 746-NTEmbedded Software Systems Development
Robert Oshana
Lecture #7
For more information, please contact:NTU Tape Orders:NTU Media Services: (970) 495-6455
Lecture 7
Peripherals
www.embedded.com
Peripherals
• Devices useful in a wide variety of systems
• Included within the same chip or processor– Internal or on-chip
• Software required to control• Another difficult issue for embedded
developers
Control and status registers
• The basic interface between the processor and the peripheral is a set of control and status registers
• Part of the peripheral– Meanings are peripheral dependent
• Usually located in the memory or I/O space– Usually both– Memory mapped are easier to work with as
well as more popular
Control and status registers
• Memory mapped control and status registers can be made to look like ordinary variables– Declare a pointer to the register (or
block of registers)– Set the value of the pointer explicitly– Use it like any other pointer
Control and status registers
Unsigned short * pP2LTCH = (unsigned short *) 0x7200005E;
voidtoggleLed(void){
*pP2LTCH ^= LED_GREEN; /* read, xor, and modify */
} /* toggleLed() */
Pointer to an unsigned short is a 16 bit register
Control and status registers
• The contents of a device register can change without the knowledge or intervention of your program– Can be modified by peripheral hardware
• Contents of a variable will not change unless the program modifies them explicitly
• Contents of device registers are volatile (can change without notice)
Control and status registers
• C/C++ keyword volatile should be used when declaring pointers to device registers
• Warns the compiler not to make any assumptions about the data stored at that address– One write followed by another write to a
register cannot be assumed to be redundant
Control and status registers
• Volatile keyword instructs the optimization phase of the compiler to treat that variable as though its behavior cannot be predicted at compile time
Volatile unsigned short * pP2LTCH = (unsigned short *) 0x7200005E;
Control and status registers
• Value of the variable pP2LTCH will remain 0x7200005E for the duration of the program (unless changed somewhere else!)– Data pointed to is subject to change
without notice
• Location of the register is fixed – contents may not be
Control and status registers
• Disadvantage of I/O mapped register is there is no standard way to access them using C/C++
• Must use special machine language instructions
• Must use special library routines or inline assembly
Device driver philosophy
• Philosophy; hide the hardware completely
• Goal is to have the device driver module to be the only piece of software in the system that reads/writes control/status registers
• ISR that responds to device should be part of device driver
Device driver philosophy
• Attempting to hide H/W complexity can be difficult
• Interface must reflect broad features of the device
• The API should be general enough to not change if underlying device does– Flash memory all have the concept of
sectors, but varies by device
Device driver philosophy
– Erase operation is based on sectors although sector size can vary
• Device drivers for embedded systems different than workstations– Device drivers for workstations
concerned with satisfying the OS• Interface between OS and network card• Device driver for network card must
conform to this software interface
Device driver philosophy
– Application programmers that want to use the network card forced to use API provided by OS
– No direct access to the card– Goal of hiding hardware complexity met
• Application software for embedded system can easily access hardware
• All S/W linked into single binary image– Little distinction between app s/w, OS, and
device driver
Device driver philosophy
• Enforcement of access restrictions is responsibility of the S/W developer
• Design decisions that the developers must make consciously
Device driver philosophy
• Benefits of good device driver design– 1. Structure is easier to understand
because of modularization– 2. Only one module ever interacts with
peripherals registers• State of H/W can be more accurately tracked
– 3. S/W changes that result from H/W changes are localized to the device driver
Components of device driver design
• 1. A data structure that overlays the memory mapped control and status registers of the device– C-style struct that looks like the
memory mapped registers of the device– Information from the data book– Use dummy variables for unused or
reserved locations
Components of device driver design
Struct TimerCounter{
unsigned short count; // current count, offset 0x00unsigned short maxCountA; // current count, offset 0x00unsigned short _reserved; // current count, offset 0x00unsigned short control; // current count, offset 0x00
};
Structure for on-chip timer/counter unit on the 80188EBprocessor
Components of device driver design
• Make the bits within the control register easier to read and write individually, define bitmasks
#define TIMER_ENABLE 0xC000 // enable the timer#define TIMER_DISABLE 0x4000 // disable the timer#define TIMER_INTERRUPT 0x2000 // enable timer interrupts#define TIMER_MAXCOUNT 0x0020 // timer complete?#define TIMER_PERIODIC 0x0001 // periodic timer ?
Components of device driver design
• 2. A set of variables to track the current state of the hardware and device driver– Determine what variables to track the state
of the hardware and device driver• Has hardware been initialized?• Length of running countdown?
– Some device drivers create more than one software device
• Logical device implemented on top of the basic peripheral hardware
Components of device driver design
– Example; more than one software timer unit created from single timer/counter unit
• Timer/counter unit configured to generate a periodic clock tick
• Device driver manages a set of software timers of various lengths by maintaining state information for each
Components of device driver design
• 3. A routine to initialize the hardware to a known state– Start writing functions that actually
interact with the device (using information interface already developed)
– First one should probably be the hardware initialization routine
Components of device driver design
• 4. A set of routines that provide an API for users of the device driver– After device has been initialized, start
adding other routines– Names and functions should be well
thought out• Parameters• Return values• Implement and test
Components of device driver design
• 5. One or more interrupt service routines– Design, implement, and test before
enabling interrupts– Locating the source of interrupts can be
challenging– Use polling to get the guts of the driver
working– Then start looking at interrupts
Simple timer driver
• C++ can hide details more completely than C
• C++ classes can hide H/W interface• Constructor can be included to
automatically configure the hardware each time a new timer object is declared– Eliminates explicit call from app s/w to driver
initialization routine– Hide data structure in private to prevent
accidental writing/reading
enum TimerState { Idle, Active, Done };enum TimerType { OneShot, Periodic };
Class Timer{
public:Timer(); ~Timer();
int start(unsigned int nMilliseconds, TimerType = Oneshot);int waitfor();void canel();
TimerState state;TImerType type;unsigned int length;
unsigned int count;Timer * pNext;
Private:
static void interrupt Interrupt();
};
Simple timer example
• Two enumerated types (TimerState, TimerType)– Makes the rest of the code more readable– Describes timer states and types– For example a Periodic timer should be
restarted
• Constructor is device drivers inti routine– Ensures timer is actively generating clock
ticks
Simple timer example
• Public methods (start, waitfor, cancel)– APIs for easy use– Simple and generic– H/W doesn’t understand human units
like milliseconds but the app developer does not have to know this
Simple timer example
• Private method interrupt– ISR– Declared static to prevent manipulation of
data members of the individual software timers
• For example, cannot modify the state of a timer• Static keyword automatically enforced by the
compiler
– Each timer has own private data store• Can easily create multiple copies
#include “i8018xEB.h”#include “timer.h”
#define CYCLES_PER_TICK (25000/4) // # clock cycles per tick
/********************************************************************************Method: Timer()•*•* Description: Constructor for the timer class•*•* Note:•*•* Returns: none defined•*•********************************************************************************•Timer::Timer(void)•{
•static int bInitialized = 0;
•//•// initialize the new software timer•//
Only initialize once
•//•// initialize the new software timer•//•state = Idle;•type = OneShot;•length = 0;•count = 0;•pNext = NULL:
•//•// initialize the timer hardware, if not previously done•//•If (!bInitialized)•{
•//•// install the interrupt handler and enable timer interrupts•//•gProcessor.installHandler(TIMER2_INT, Timer::Interrupt);•gProcessor.pPCB->intControl.timerControl &=
•~(TIMER_MASK | TIMER_PRIORITY);
•//•// install the hardware device (use timer 2)•//•gProcessor.pPCB->timer[2].count = 0;•gProcessor.pPCB->timer[2].maxCountA = CYCLES_PER_TICK;•gProcessor.pPCB->timer[2].control = TIMER_ENABLE• | TIMER_INTERRUPT
• | TIMER_PERIODIC;
•//•// mark the timer hardware initialized•//•bInitialized = 1;
•}•} /* Timer() */
Global variable declared in header file, represents 80188EBprocessor
Start a 1 ms periodic timer that generated an interruptat the end of each cycle – will act as clock tick neededto create software timers of arbitrary length
Embedded software components
Application software
System software
DSP Timers DMAI/O
peripheralsMemory
Chip support
Target board
DSP
CSLRTOS Kernel/
SchedulerOther
libraries
codec
Timer, DMA,etc
Application
Hardware abstraction
User code
Hardware Abstraction Layer
Service Layer
SE 746-NTEmbedded Software Systems Development
Robert Oshana
10 minute break
For more information, please contact:NTU Tape Orders:NTU Media Services: (970) 495-6455