Оптимізована система команд мікроконтролерів

Трохи більше року тому була опублікована стаття «Мікропроцесор «з гаража»» і, можливо, зараз настав непоганий момент для того, щоб знову нагадати про проект.

Мабуть, головна новина це розширення системи команд, назване «Версія 1.1». Її відмінність від попередньої це розширені можливості адресації. Але про все по порядку. Щоб уявити, про що йде мова, погляньте на мапу системи команд (картинка кликабельна):

image

Насамперед саме її хотілося винести на ваш суд. При проектуванні системи команд були визначені дві основні вимоги — хороша розширюваність і висока щільність коду. Жовтим кольором на малюнку позначені зарезервовані коди операцій. Як видно з картинки, виконати вимоги розширюваності нам вдалося. Втім, жовті «клітини» це не єдина можливість для розширення — деякий резерв закладений в невикористаних бітах у многобайтовых кодів операцій. Крім цього, два префікса (NOTCH і KOL) можуть розширювати семантику кодів операцій. Як видно з картинки, кількість однобайтових префіксів може бути безболісно збільшено. Ось ці фактори дозволяють заявити про видатних можливостях розширення. Але це ще не все. В даний час максимальна довжина інструкції обмежена пятья байтами — цей розмір був вибраний виходячи з можливостей нашої недорогий ПЛІС. Уявіть, наскільки можна розширити систему команд, якщо призначити коди операцій в діапазоні з 0xf0 за 0xff для більш довгих інструкцій — шість байтів, сім… довжина інструкції може бути обмежена лише здоровим глуздом. Отже, я сподіваюся, що сумнівів у можливості розширення системи команд не виникло ні в кого, якщо вони все ж є — милості прошу обговорити їх у коментарях.

А що ж з щільністю коду? Так, Хабр суворий і не любить вигаданих даних. За суб'єктивними оцінками, поточна щільність коду може конкурувати по щільності коду з першими версіями процесорів з архітектурою RISC. Наприклад, якщо розглядати самі перші версії ARM і MIPS, то, схоже, що версія 1.1 перевершує їх по цьому параметру. Що стосується x86 і сучасних RISC, то дякую багатства команд цих архітектур, щільність коду на них вище. Однак, якщо правильно експлуатувати закладені можливості розширення, то за праметру «Щільність коду» можна перевершити сучасні популярні архітектури.

Я впевнений, що багатьом програмістам, які мають досвід написання на асемблері x86, побіжного погляду на таблицю з інструкціями достатньо, щоб заявити «Я вмію писати на цьому асемблері». Не знаю, наскільки назви ассемблерних мненмоник захищені патентами, але вони обрані збігаються з x86. Окремо хотілося б сказати про інструкціях з дапазона 0xd0-0xd7. Це четырехбайтовые інструкції, другий байт визначає регістри загального призначення, а третій і четвертий служать для розширеної адресації.

image

Біт S/D визначає, який з аргументів (четырехбитные коди регістрів у другому байті) є покажчиком — перший або другий регістр. Три біта зарезервовані для подальших розширень і повинні бути встановлені в 0, решта біти визначають беззнакове число, прибавляемое до покажчика при непрямої адресації. Дані операції з'явилися для спрощення роботи зі структурованими даними. Почитати про це можна, наприклад, ось тут — everest.l4os.ua/aliases_for_registers/

Що характерно, спочатку код розроблявся як позиційно повністю незалежний і в системі команд ви не знайдете жодної інструкції переходу за абсолютною адресою — умовного, ні безумовного. Усі адреси переходів представлені як зміщення относительнос лічильника команд. Навіщо? Це зроблено щоб на рівні архітектури реалізувати 100% позиційно незалежний машинний код. Потрібна константа? Вибирайте її зміщення відносно лічильника команд. Потрібна статична змінна, адресуйте щодо лічильника команд. Втім, деталі реалізації різних режимів адресації надійно сховані за діями асемблера. Відповідь на питання, як без абсолютної адресації викликати системні функції — далі за текстом.

Власне, все вищесказане відноситься до системи команд. Ймовірно, ви оцінили її, можливо з чимось навіть погодилися, але… вона запізнилася років на 20. Основні області застосування мікропроцесорів вже поділені між архітектурою x86, arm, mips і простими микроконтоллерами. Розширюваність і щільність коду це самі останні речі, на які подивиться розробник пристрою при виборі мікропроцесора. Що ж дає надію, на те, що проект виявиться цікавим розробникам? Раз вже мова йде про систему команд, то придивіться до однобайтовым інструкцій IDLE, TASK_ID, SEND, RECV, LOCK, FREE.

Фішка процесора в тому, що всередині нього захована невелика частина операційної системи, що управляє завданнями і саме поняття завдання «зашитий» в мікропроцесорі. Нові інструкції якраз і служать для підтримки багатозадачності. Інструкція IDLE виконує безумовний вхід в планувальник. Фактично непотрібна інструкція, корисна лише для налагодження самого планувальника. Інструкція TASK_ID поверне ідентифікатор активної задачі і кількість тактів до наступної планової операції розподілу часу. Парні інструкції LOCK і FREE служать для захоплення і звільнення буфера повідомлення. В даному випадку, незважаючи на збіг назва інструкції LOCK з інструкцією x86, вона виконує зовсім інші функції. Оскільки процесор оперує поняттям завдання, то потрібні кошти для взаємодії завдань. За допомогою інструкції LOCK завдання захоплює буфер повідомлення, а за допомогою інструкції FREE освободжает його. Буфер повідомлення це 64 регістру, обмін з якими відбувається за допомогою інструкцій SET_MR (запис регістра повідомлень значенням з РОН) і GET_MR і (читання регістра повідомлень РОН).

Звичайно ж найважливіші інструкції, заради яких і затівався весь проект, це інструкції SEND і RECV — інструкції передачі і прийому повідомлень. Ці інструкції мають два аргументи — номер завдання для взаємодії і таймаут операції (задаються в регістрах). Найпростіший спосіб віддати завдання системи або реалізувати затримку, це послати повідомлення самому собі або чекати повідомлення від себе — планувальник просто не буде передавати управління блокованої задачі раніше закінчення таймауту повідомлення.

Операції SEND і RECV синхронні — щоб відбувся процес передачі повідомлення між завданнями, одне із завдань повинна виконати RECV, а інша SEND. У більшості випадків це означає, що перше завдання, виконала одну з цих інструкцій, заблокується в очікуванні готовності іншого завдання. Якщо з якоїсь причини блокування небажана, то встановлюється нульовий таймаут і в разі неготовності однієї із сторін, замість блокування завдання отримує статус, що сигналізує про таймауте.

В момент передачі повідомлення буфер повідомлення, який раніше був захоплений інструкцією LOCK, комутується завдання приймаючої повідомлення. Завдання, що прийняла повідомлення, після роботи з буфером повинна його звільнити. Наприклад, виклик бібліотечної функції puts міг би виглядати так:

LOCK; Захоплення буфера повідомлення
SET_MR MR0, R2; установка ідентифікатор повідомлення
SET_MR MR1, R3; установка аргументу повідомлення
SEND; передача повідомлення
RECV; очікування відповіді на повідомлення
GET_MR R0, MR0; читання коду повернення
FREE; звільнення буфера повідомлення

Цей код максимально спрощений для простоти розуміння. У цьому прикладі інструкція FREE звільняє буфер повідомлень, отриманий інструкцією RECV, оскільки буфер, захоплений інструкцією LOCK, делегований завдання-приймача при передачі повідомлення.

Незважаючи на гадану складність і незвичайність рішення, з погляду прикладного програміста нічого не змінюється — бібліотечні функції ретельно приховують деталі реалізації. А ось системним програмістам і розробникам бібліотек доведеться постаратися — почати доведеться з того, що будь-яка взаємодія програм необхідно описати у вигляді протоколу, що описує формат запитів і відповідей — складний програмний комплекс описується як набір взаємодіючих суб'єктів, які через взаємодію вирішують певні завдання.

Всі експерименти проводяться ось з цим дивом — платою Марсоход2:

image

Дякую за увагу. Перш за все хотілося б обговорити систему команд, оскільки вона вже працює в залозі. Що стосується апаратних розширень для багатозадачності, то вони ще не готові — інформація про підтримку багатозадачності надана в ознайомлювальних цілях, а фактична реалізація може не відповідати матеріалу в статті.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.