SE 746-NT Embedded Software Systems Development

607 views
522 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
607
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
11
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

SE 746-NT Embedded Software Systems Development

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

×