Michael Barr - Programming Embedded Systems in C and C++

Здесь есть возможность читать онлайн «Michael Barr - Programming Embedded Systems in C and C++» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 1999, ISBN: 1999, Издательство: O'Reilly, Жанр: Программирование, Компьютерное железо, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Programming Embedded Systems in C and C++: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Programming Embedded Systems in C and C++»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

This book introduces embedded systems to C and C++ programmers. Topics include testing memory devices, writing and erasing Flash memory, verifying nonvolatile memory contents, controlling on-chip peripherals, device driver design and implementation, optimizing embedded code for size and speed, and making the most of C++ without a performance penalty.

Programming Embedded Systems in C and C++ — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Programming Embedded Systems in C and C++», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

An example of such a data structure is shown below. This structure describes the registers in one of the on-chip timer/counter units within the 80188EB processor. The device has three registers, arranged as shown in the TimerCounter data structure below. each register is 16 bits wide and should be treated as an unsigned integer, although one of them, the control register, is actually a collection of individually significant bits.

struct TimerCounter {

unsigned short count; // Current Count, offset 0x00

unsigned short maxCountA; // Maximum Count, offset 0x02

unsigned short _reserved; // Unused Space, offset 0x04

unsigned short control; // Control Bits, offset 0x06

};

To make the bits within the control register easier to read and write individually, we might also define the following 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?

2. A set of variables to track the current state of the hardware and device driver

The second step in the driver development process is to figure out what variables you will need to track the state of the hardware and device driver. For example, in the case of the timer/counter unit described earlier we'll probably need to know if the hardware has been initialized. And if it has been, we might also want to know the length of the running countdown.

Some device drivers create more than one software device. This is a purely logical device that is implemented over the top of the basic peripheral hardware. For example, it is easy to imagine that more than one software timer could be created from a single timer/counter unit. The timer/counter unit would be configured to generate a periodic clock tick, and the device driver would then manage a set of software timers of various lengths by maintaining state information for each.

3. A routine to initialize the hardware to a known state

Once you know how you'll track the state of the physical and logical devices, it's time to start writing the functions that actually interact with and control the device. It is probably best to begin with the hardware initialization routine. You'll need that one first anyway, and it's a good way to get familiar with the device interaction.

4. A set of routines that, taken together, provide an API for users of the device driver

After you've successfully initialized the device, you can start adding other functionality to the driver. Hopefully, you've already settled on the names and purposes of the various routines, as well as their respective parameters and return values. All that's left to do now is implement and test each one. We'll see examples of such routines in the next section.

5. One or more interrupt service routines

It's best to design, implement, and test most of the device driver routines before enabling interrupts for the first time. Locating the source of interrupt-related problems can be quite challenging. And, if you add possible bugs in the other driver modules to the mix, it could even approach impossible. It's far better to use polling to get the guts of the driver working. That way you'll know how the device works (and that it is indeed working) when you start looking for the source of your interrupt problems. And there will almost certainly be some of those.

7.3 A Simple Timer Driver

The device driver example that we're about to discuss is designed to control one of the timer/counter units contained within the 80188EB processor. I have chosen to implement this driver — and all of the remaining examples in the book — in C++. Although C++ offers no additional assistance over C in accessing hardware registers, there are many good reasons to use it for this type of abstraction. Most notably, C++ classes allow us to hide the actual hardware interface more completely than any C features or programming techniques. For example, a constructor can be included to automatically configure the hardware each time a new timer object is declared. This eliminates the need for an explicit call from the application software to the driver initialization routine. In addition, it is possible to hide the data structure that corresponds to the device registers within the private part of the associated class. This helps to prevent the application programmer from accidentally reading or writing the device registers from some other part of the program.

The definition of the Timer class is as follows:

enum TimerState { Idle, Active, Done };

enum TimerType { OneShot, Periodic };

class Timer {

public:

Timer();

~Timer();

int start(unsigned int nMilliseconds, TimerType = OneShot);

int waitfor();

void cancel();

TimerState state;

TimerType type;

unsigned int length;

unsigned int count;

Timer * pNext;

private:

static void interrupt Interrupt();

};

Before discussing the implementation of this class, let's examine the previous declaration and consider the device driver's overall structure. The first thing we see are two enumerated types, TimerState and TimerType . The main purpose of these types is to make the rest of the code more readable. From them we learn that each software timer has a current state — Idle , Active , or Done — and a type — OneShot or Periodic . The timer's type tells the driver what to do with the timer when it expires; a Periodic timer is to be restarted then.

The constructor for the Timer class is also the device driver's initialization routine. It ensures that the timer/counter hardware is actively generating a clock tick every 1 millisecond. The other public methods of the class — start , waitfor , and cancel — provide an API for an easy-to-use software timer. These methods allow application programmers to start one-shot and periodic timers, wait for them to expire, and cancel running timers, respectively. This is a much simpler and more generic interface than that provided by the timer/counter hardware within the 80188EB chip. For one thing, the timer hardware does not know about human units of time, like milliseconds. But because the timer driver hides the specifics of this particular hardware, the application programmer need never even know about that.

The data members of the class should also help give you some insight into the device driver implementation. The first three items are variables that answer the following questions about this software timer:

• What is the timer's current state (idle, active, or done)?

• What type of a timer is it (one-shot or periodic)?

• What is the total length of the timer (in units called ticks)?

Following those are two more data members, both of which contain information that is specific to this implementation of the timer driver. The values of count and pNext have meaning only within the context of a linked list of active software timers. This linked list is ordered by the number of ticks remaining for each timer. So count contains information about the number of ticks remaining before this software timer is set to expire, [18] Specifically, it represents the number of clock ticks remaining after all of the timers ahead of it in the list have expired. and pNext is a pointer to the software timer that will expire the soonest after this one.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Programming Embedded Systems in C and C++»

Представляем Вашему вниманию похожие книги на «Programming Embedded Systems in C and C++» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Programming Embedded Systems in C and C++»

Обсуждение, отзывы о книге «Programming Embedded Systems in C and C++» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x