- •«Пермский национальный исследовательский политехнический университет»
- •«Встроенные микропроцессорные системы»
- •Составитель о.В. Гончаровский
- •Оглавление
- •2. Программное обеспечение встроенных систем ……….
- •Введение
- •Аппаратные средства встроенных систем
- •Организация аппаратных средств встроенных
- •1.2. Элементы архитектуры процессоров встроенных систем
- •1.2.1. Множество команд
- •1.2.3.1. Адресное пространство
- •1.2.3.2. Порядок байт
- •1. 2.3.3. Когерентность памяти
- •1. 2.3.4. Защита памяти
- •1. 2. 4. Модель прерываний
- •1.2. 5.Модель управления памятью
- •1.2.5.1. Страничная организация памяти
- •1.2.5.2. Сегментация памяти
- •1.3. Типы процессоров
- •1.4. Формы параллелизма в процессорах
- •1.4.1. Конвейеризация
- •1.4.2. Параллелизм уровня команд
- •1.5.Технологии памяти
- •1.5.1. Оперативная память
- •1.5.1. 1. Статическое озу
- •1.5.2. Постоянное запоминающее устройство (rom)
- •1.6. Иерархия памяти
- •1.6.1. Распределение или карта памяти
- •1.6.2. Блокнотная и кэш память
- •1.6.2.2. Ассоциативная по множеству кэш-память
- •1.6.2.3. Обновление кэш-памяти.
- •1.6.2.4. Протокол когерентности кэширования с обратной записью
- •1.7. Магистраль микропроцессорной системы
- •1.8. Базовые устройства ввода-вывода встроенных систем
- •1.8.1. Порты ввода-вывода общего назначения
- •1.7.2. Таймер-счетчик
- •1.8.3. Импульсно-кодовая модуляция.
- •1.8.4. Многоканальный аналого-цифровой преобразователь
- •1.9. Базовые последовательные интерфейсы ввода-вывода
- •1.9.2. Последовательный интерфейс spi
- •1.9.4.1. Введение в usb
- •1.9.4.2. Интерфейс Open Host Controller для usb
- •Вопросы для самопроверки
- •Модуль 2
- •1.10. Язык проектирования аппаратуры vhdl
- •1.10.2. Введение в vhdl
- •1.10.2.1. Программирование на vhdl для моделирования и синтеза [22]
- •1.10.2.3. Операторы присваивание и process [22]
- •1.10.2.4. Цикл моделирования vhdl
- •1.10.2.5. Многозначная логика и стандарт ieee 1164
- •1.11. Проектирование устройств ввода-вывода и контроллеров
- •1.12. Интегрированная среда разработки аппаратных средств
- •Вопросы для самопроверки
- •Модуль 3
- •2. Программное обеспечение встроенных систем
- •2.1 Модель вычислений
- •2.2 Автомат с конечным числом состояний
- •2.3. Асинхронный язык проектирования sdl
- •2.4. Синхронный язык проектирования Lustre
- •2.5. Многозадачность.
- •2.5.1. Язык программирования Си
- •2.5.2. Потоки
- •2.5.2.1. Реализация потоков
- •2.5.2.2. Взаимное исключение
- •2.5.2.3. Взаимная блокировка
- •2.5.2.4. Модели непротиворечивости памяти
- •2.5.2.5. Проблемы с потоками
- •2.5.3. Процессы и передача сообщений
- •2.6. Интегрированная среда разработки прикладного программного
- •2.6.2. Комплект программ Telelogic Tau sdl Suite
- •2.6.3. Средства разработки программного обеспечения
- •2.7.1. Моделирование, эмуляция и макетирование
- •2.7.2. Формальная верификация
- •2.7.3. Оценка производительности
- •2.7.3.1. Оценка wcet
- •2.7.3.2. Исчисление реального времени
- •2.7.4. Модели энергии и мощности
- •2.7.5. Тепловая модель
- •Задания
- •1. Конвейеризация
- •2. Иерархия памяти
- •3. Базовые устройства ввода-вывода встроенных систем
- •5. Многозадачность
- •6. Валидация и оценка проекта
- •Заключение
- •Библиографический список
- •Встроенные микропроцессорные системы
2.5.2. Потоки
Потоки (thread или тред) – императивные программы, которые выполняются одновременно и разделяют (совместно используют) адресное пространство. Одновременность выполнения опирается на механизм прерываний, имеющийся во всех микропроцессорах.
Большинство ОС обеспечивают высокоуровневый механизм противоположно прерываниям для императивных программ с разделяемой памятью. Механизм выступает в форме коллекции процедур, которые программист может использовать. Такие процедуры обычно соответствуют стандартизованным API (application program interface), которые дают возможность писать переносимые программы (работают на различных процессорах и ОС).
Таким API, например, является Pthreads (или POSIX threads), интегрированным во многие современные ОС. Pthreads определяют множество Си-типов, функций и констант. Они стандартизованы IEEE в 1988 для унификации вариантов ОС Unix. В Pthreads поток определяется Си-функцией и создается вызовом функции создания потока.
На рис. 75 показана простая многопоточная Си-программа, использующая Pthreads. printN (строки 3 – 9) – функция, которую поток начинает выполнять при старте, называют стартовой подпрограммой. Стартовая
10
int
main(void)
{ 11
pthread_t threadID1, threadID2; 12
void*
exitStatus; 13
int
x1
= 1, x2 = 2; 14
pthread_create(&threadID1, NULL, printN, &x1); 15
pthread_create(&threadID2, NULL, printN, &x2); 16
printf("Started threads.\n"); 17
pthread_join(threadID1, &exitStatus); 18
pthread_join(threadID2, &exitStatus); 19
return
0; 20
}
1
#include
<pthread.h> 2
#include
<stdio.h> 3
void*
printN(void*
arg) { 4
int
i; 5
for
(i
= 0; i < 10; i++) { 6
printf("My ID: %d\n", *(int*)arg); 7
} 8
return
NULL; 9
}
Рис. 75. Простая многопоточная Си-программа, использующая Pthreads
подпрограмма печатает передаваемый аргумент 10 раз и завершается. Функция main создает два потока (строки 14, 15), каждый из которых будет выполнять стартовую подпрограмму. Первый создаваемый поток будет печатать значение 1, а второй – 2 . Когда запускаются эта программы, значения 1 и 2 в некотором чередующемся порядке, зависящим от планировщика задач. Обычно повторное выполнение вызовет отличный чередующийся порядок 1 и 2.
Функция pthread_create создает поток и сразу завершается. Стартовая
подпрограмма может не начать выполняться перед выходом из pthread_create. Строки 17 и 18 используют функцию pthread_join для того чтобы главная программа main не завершилась перед завершением работы потоков. Без этих строк запущенная программа не сможет произвести требуемые результаты всеми потоками.
Во встроенных приложениях широко распространено объявление стартовой подпрограммы как бесконечного цикла, т.е из нее невозможно выйти. Например, стартовая подпрограмма может «вечно» выполняться, периодически выполняя вывод информации на дисплей. Если стартовая подпрограмма не возвращается, тогда некоторый другой поток, который вызывает
для нее pthread_join, будет навсегда заблокирован.
Как показано на рис.75 стартовая подпрограмма может иметь аргумент и возвращать значение. Четвертый аргумент pthread_create является адресом аргумента, который передается в стартовую подпрограмму. Важно понимать модель памяти Си, иначе возможны очень тонкие ошибки. Предположим, создается поток внутри следующей функции:
1
pthread_t createThread(int
x)
{ 2
pthread_t ID; 3
pthread_create(&ID, NULL, printN, &x); 4
return
ID; 5
}
Этот код является некорректным, так как аргумент стартовой подпрограммы задается указателем на переменную в стеке. Во время когда поток обращается к оговоренному адресу памяти, функция createThread с вероятностью может завершиться и адрес памяти может быть перезаписан кем-нибудь следующим, попавшим в эту область стека.