aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ru/src/README_RU.md104
-rw-r--r--ru/src/SUMMARY.md15
-rw-r--r--ru/src/by-example.md16
-rw-r--r--ru/src/by-example/app.md101
-rw-r--r--ru/src/by-example/new.md67
-rw-r--r--ru/src/by-example/resources.md122
-rw-r--r--ru/src/by-example/singletons.md26
-rw-r--r--ru/src/by-example/tasks.md63
-rw-r--r--ru/src/by-example/timer-queue.md90
-rw-r--r--ru/src/by-example/tips.md63
-rw-r--r--ru/src/by-example/types-send-sync.md59
-rw-r--r--ru/src/chapter_1.md1
-rw-r--r--ru/src/internals.md7
-rw-r--r--ru/src/internals/ceilings.md3
-rw-r--r--ru/src/internals/tasks.md3
-rw-r--r--ru/src/internals/timer-queue.md3
-rw-r--r--ru/src/preface.md12
17 files changed, 753 insertions, 2 deletions
diff --git a/ru/src/README_RU.md b/ru/src/README_RU.md
new file mode 100644
index 00000000..b17685ac
--- /dev/null
+++ b/ru/src/README_RU.md
@@ -0,0 +1,104 @@
+# Real Time For the Masses
+
+Конкурентный фреймворк для создания систем реального времени.
+
+**ВАЖНО** Эта библиотека в настоящее время в состоянии пре-релиза (бета).
+Мы зарезервировали право делать ломающие синтакс изменения или патчить дыры
+в безопасности памяти до релиза v0.4.0, который запланирован на 2018-12-07.
+Когда выйдет v0.4.0, *все пре-релизы будут убраны*. Если при запуске Вы
+получите сообщение о панике или бесполезное сообщение об ошибке
+(вводящее в заблуждение), или что-то будет работать не так, как Вы ожидаете,
+пожалуйста, сообщите о [проблеме]!
+
+[проблеме]: https://github.com/japaric/cortex-m-rtfm/issues
+
+## Возможности
+
+- **Задачи** - единица конкуренции [^1]. Задачи могут *запускаться по событию*
+ (в ответ на асинхронный стимул) или вызываться программно по желанию.
+
+- **Передача сообщений** между задачами. А именно, сообщения можно передавать
+ программным задачам в момент вызова.
+
+- **Очередь таймера** [^2]. Программные задачи можно планировать на запуск в
+ определенный момент в будущем. Это свойство можно использовать, чтобы
+ реализовывать периодические задачи.
+
+- Поддержка приоритетов задач, и таким образом, **вытесняющей многозадачности**.
+
+- **Эффективное, свободное от гонок данных разделение памяти** через хорошо
+ разграниченные критические секции на *основе приоритетов* [^1].
+
+- **Выполнение без взаимной блокировки задач**, гарантированное на этапе
+ компиляции. Это более сильная гарантия, чем предоставляемая
+ [стандартной абстракцией `Mutex`][std-mutex].
+
+[std-mutex]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
+
+- **Минимальные затраты на диспетчеризацию**. Диспетчер задач имеет
+ минимальный след; основная часть работы по диспетчеризации делается аппаратно.
+
+- **Высокоэффективное использование памяти**: Все задачи используют общий стек
+ вызовов и нет сильной зависимости от динамического распределителя памяти.
+
+- **Все устройства Cortex-M полностью поддерживаются**.
+
+- Эта модель задач поддается известному анализу методом WCET (наихудшего
+ времени исполнения) и техникам анализа диспетчеризации. (Хотя мы еще не
+ разработали для дружественных инструментов для этого).
+
+## Требования
+
+- Rust 1.31.0+
+
+- Программы нужно писать используя 2018 edition.
+
+## [User documentation](https://japaric.github.io/cortex-m-rtfm/book)
+
+## [API reference](https://japaric.github.io/cortex-m-rtfm/api/rtfm/index.html)
+
+## Благодарности
+
+Эта библиотека основана на [языке RTFM][rtfm-lang], созданном Embedded
+Systems group в [Техническом Университете Luleå][ltu], под рук.
+[Prof. Per Lindgren][per].
+
+[rtfm-lang]: http://www.rtfm-lang.org/
+[ltu]: https://www.ltu.se/?l=en
+[per]: https://www.ltu.se/staff/p/pln-1.11258?l=en
+
+## Ссылки
+
+[^1]: Eriksson, J., Häggström, F., Aittamaa, S., Kruglyak, A., & Lindgren, P.
+ (2013, June). Real-time for the masses, step 1: Programming API and static
+ priority SRP kernel primitives. In Industrial Embedded Systems (SIES), 2013
+ 8th IEEE International Symposium on (pp. 110-113). IEEE.
+
+[^2]: Lindgren, P., Fresk, E., Lindner, M., Lindner, A., Pereira, D., & Pinho,
+ L. M. (2016). Abstract timers and their implementation onto the arm cortex-m
+ family of mcus. ACM SIGBED Review, 13(1), 48-53.
+
+## Лицензия
+
+Все исходные тексты (включая примеры кода) лицензированы либо под:
+
+- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) или
+ [https://www.apache.org/licenses/LICENSE-2.0][L1])
+- MIT license ([LICENSE-MIT](LICENSE-MIT) or
+ [https://opensource.org/licenses/MIT][L2])
+
+[L1]: https://www.apache.org/licenses/LICENSE-2.0
+[L2]: https://opensource.org/licenses/MIT
+
+на Ваше усмотрение.
+
+Текст книги лицензирован по условиям лицензий
+Creative Commons CC-BY-SA v4.0 ([LICENSE-CC-BY-SA](LICENSE-CC-BY-SA) или
+[https://creativecommons.org/licenses/by-sa/4.0/legalcode][L3]).
+
+[L3]: https://creativecommons.org/licenses/by-sa/4.0/legalcode
+
+### Contribution
+
+Если вы явно не заявляете иначе, любой взнос, преднамеренно представленный
+для включения в эту работу, как определено в лицензии Apache-2.0, лицензируется, как указано выше, без каких-либо дополнительных условий.
diff --git a/ru/src/SUMMARY.md b/ru/src/SUMMARY.md
index 7390c828..d57ee4c0 100644
--- a/ru/src/SUMMARY.md
+++ b/ru/src/SUMMARY.md
@@ -1,3 +1,16 @@
# Summary
-- [Chapter 1](./chapter_1.md)
+[Введение](./preface.md)
+- [RTFM в примерах](./by-example.md)
+ - [Атрибут `app](./by-example/app.md)
+ - [Ресурсы](./by-example/resources.md)
+ - [Задачи](./by-example/tasks.md)
+ - [Очередь таймера](./by-example/timer-queue.md)
+ - [Одиночки](./by-example/singletons.md)
+ - [Типы, Send и Sync](./by-example/types-send-sync.md)
+ - [Создание нового проекта](./by-example/new.md)
+ - [Советы и хитрости](./by-example/tips.md)
+- [Под капотом](./internals.md)
+ - [Ceiling analysis](./internals/ceilings.md)
+ - [Диспетчер задач](./internals/tasks.md)
+ - [Очередь таймера](./internals/timer-queue.md)
diff --git a/ru/src/by-example.md b/ru/src/by-example.md
new file mode 100644
index 00000000..6955f8ef
--- /dev/null
+++ b/ru/src/by-example.md
@@ -0,0 +1,16 @@
+# RTFM в примерах
+
+Эта часть книги представляет фреймворк Real Time For the Masses (RTFM)
+новым пользователям через примеры с растущей сложностью.
+
+Все примеры в этой книге можно найти в [репозитории] проекта на GitHub,
+и большинство примеров можно запустить на эмуляторе QEMU, поэтому никакого
+специальног оборудования не требуется to follow along.
+
+[репозитории]: https://github.com/japaric/cortex-m-rtfm
+
+Чтобы запустить примеры на Вашем ноутбуке / PC, Вам нужна программа
+`qemu-system-arm`. Посмотрите [the embedded Rust book] на предмет инструкций
+как настроить окружение для разработки встраиваемых устройств, в том числе QEMU.
+
+[the embedded Rust book]: https://rust-embedded.github.io/book/intro/install.html
diff --git a/ru/src/by-example/app.md b/ru/src/by-example/app.md
new file mode 100644
index 00000000..bcd778da
--- /dev/null
+++ b/ru/src/by-example/app.md
@@ -0,0 +1,101 @@
+# The `app` attribute
+
+Это наименьшая возможная программа на RTFM:
+
+``` rust
+{{#include ../../../examples/smallest.rs}}
+```
+
+Все программы на RTFM используют атрибут [`app`] (`#[app(..)]`). Этот атрибут
+нужно применять к `const`-элементам, содержащим элементы. Атрибут `app` имеет
+обязательный аргумент `device`, в качестве значения которому передается *путь*.
+Этот путь должен указывать на библиотеку *устройства*, сгенерированную с помощью
+[`svd2rust`] **v0.14.x**. Атрибут `app` развернется в удобную точку входа,
+поэтому нет необходимости использовать атрибут [`cortex_m_rt::entry`].
+
+[`app`]: ../../api/cortex_m_rtfm_macros/attr.app.html
+[`svd2rust`]: https://crates.io/crates/svd2rust
+[`cortex_m_rt::entry`]: ../../api/cortex_m_rt_macros/attr.entry.html
+
+> **ОТСТУПЛЕНИЕ**: Некоторые из вас удивятся, почему мы используем ключевое слово `const` как
+> модуль, а не правильное `mod`. Причина в том, что использование атрибутов на
+> модулях требует feature gate, который требует ночную сборку. Чтобы заставить
+> RTFM работать на стабильной сборке, мы используем вместо него слово `const`.
+> Когда большая часть макросов 1.2 стабилизируются, мы прейдем от `const` к `mod` и в конце концов в атрибуту уровне приложения (`#![app]`).
+
+## `init`
+
+Внутри псевдо-модуля атрибут `app` ожидает найти функцию инициализации, обозначенную
+атрибутом `init`. Эта функция должна иметь сигнатуру `[unsafe] fn()`.
+
+Эта функция инициализации будет первой частью запускаемого приложения.
+Функция `init` запустится *с отключенными прерываниями* и будет иметь эксклюзивный
+доступ к периферии Cortex-M и специфичной для устройства периферии через переменные
+`core` and `device`, которые внедряются в область видимости `init` атрибутом `app`.
+Не вся периферия Cortex-M доступна в `core`, потому что рантайм RTFM принимает владение
+частью из неё -- более подробно см. структуру [`rtfm::Peripherals`].
+
+Переменные `static mut`, определённые в начале `init` будут преобразованы
+в ссылки `&'static mut` с безопасным доступом.
+
+[`rtfm::Peripherals`]: ../../api/rtfm/struct.Peripherals.html
+
+Пример ниже показывает типы переменных `core` и `device` и
+демонстрирует безопасный доступ к переменной `static mut`.
+
+``` rust
+{{#include ../../../examples/init.rs}}
+```
+
+Запуск примера напечатает `init` в консоли и завершит процесс QEMU.
+
+``` console
+$ cargo run --example init
+{{#include ../../../ci/expected/init.run}}```
+
+## `idle`
+
+Функция, помеченная атрибутом `idle` может присутствовать в псевдо-модуле
+опционально. Эта функция используется как специальная *задача ожидания* и должна иметь
+сигнатуру `[unsafe] fn() - > !`.
+
+Когда она присутствует, рантайм запустит задачу `idle` после `init`. В отличие от
+`init`, `idle` запустится *с включенными прерываниями* и не может завершиться,
+поэтому будет работать бесконечно.
+
+Когда функция `idle` определена, рантайм устанавливает бит [SLEEPONEXIT], после чего
+отправляет микроконтроллер в состояние сна после выполнения `init`.
+
+[SLEEPONEXIT]: https://developer.arm.com/products/architecture/cpu-architecture/m-profile/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit
+
+Как и в `init`, переменные `static mut`будут преобразованы в ссылки `&'static mut`
+с безопасным доступом.
+
+В примере ниже показан запуск `idle` после `init`.
+
+``` rust
+{{#include ../../../examples/idle.rs}}
+```
+
+``` console
+$ cargo run --example idle
+{{#include ../../../ci/expected/idle.run}}```
+
+## `interrupt` / `exception`
+
+Как Вы бы сделали с помощью библиотеки `cortex-m-rt`, Вы можете использовать атрибуты
+`interrupt` и `exception` внутри псевдо-модуля `app`, чтобы определить обработчики
+прерываний и исключений. В RTFM, мы называем обработчики прерываний и исключений
+*аппаратными* задачами.
+
+``` rust
+{{#include ../../../examples/interrupt.rs}}
+```
+
+``` console
+$ cargo run --example interrupt
+{{#include ../../../ci/expected/interrupt.run}}```
+
+До сих пор программы RTFM, которые мы видели не отличались от программ, которые
+можно написать, используя только библиотеку `cortex-m-rt`. В следующем разделе
+мы начнем знакомиться с функционалом, присущим только RTFM.
diff --git a/ru/src/by-example/new.md b/ru/src/by-example/new.md
new file mode 100644
index 00000000..f3aa4551
--- /dev/null
+++ b/ru/src/by-example/new.md
@@ -0,0 +1,67 @@
+# Создание нового проекта
+
+Теперь, когда Вы изучили основные возможности фреймворка RTFM, Вы можете
+попробовать его использовать на Вашем оборудовании следуя этим инструкциям.
+
+1. Создайте экземпляр из шаблона [`cortex-m-quickstart`].
+
+[`cortex-m-quickstart`]: https://github.com/rust-embedded/cortex-m-quickstart#cortex-m-quickstart
+
+``` console
+$ # например используя `cargo-generate`
+$ cargo generate \
+ --git https://github.com/rust-embedded/cortex-m-quickstart \
+ --name app
+
+$ # следуйте остальным инструкциям
+```
+
+2. Добавьте крейт устройства, сгенерированный с помощью [`svd2rust`] **v0.14.x**,
+или библиотеку отладочной платы, у которой в зависимостях одно из устройств.
+ Убедитесь, что опция `rt` крейта включена.
+
+[`svd2rust`]: https://crates.io/crates/svd2rust
+
+В этом примере я покажу использование крейта устройства [`lm3s6965`].
+Эта библиотека не имеет Cargo-опции `rt`; эта опция всегда включена.
+
+[`lm3s6965`]: https://crates.io/crates/lm3s6965
+
+Этот крейт устройства предоставляет линковочный скрипт с макетом памяти
+целевого устройства, поэтому `memory.x` и `build.rs` не нужно удалять.
+
+``` console
+$ cargo add lm3s6965 --vers 0.1.3
+
+$ rm memory.x build.rs
+```
+
+3. Добавьте библиотеку `cortex-m-rtfm` как зависимость, и если необходимо,
+включите опцию `timer-queue`.
+
+``` console
+$ cargo add cortex-m-rtfm --allow-prerelease --upgrade=none
+```
+
+4. Напишите программу RTFM.
+
+Здесь я буду использовать пример `init` из библиотеки `cortex-m-rtfm`.
+
+``` console
+$ curl \
+ -L https://github.com/japaric/cortex-m-rtfm/raw/v0.4.0-beta.1/examples/init.rs \
+ > src/main.rs
+```
+
+Этот пример зависит от библиотеки `panic-semihosting`:
+
+``` console
+$ cargo add panic-semihosting
+```
+
+5. Соберите его, загрузите в микроконтроллер и запустите.
+
+``` console
+$ # ПРИМЕЧАНИЕ: Я раскомментировал опцию `runner` в `.cargo/config`
+$ cargo run
+{{#include ../../../ci/expected/init.run}}```
diff --git a/ru/src/by-example/resources.md b/ru/src/by-example/resources.md
new file mode 100644
index 00000000..a117e6ad
--- /dev/null
+++ b/ru/src/by-example/resources.md
@@ -0,0 +1,122 @@
+## Ресурсы
+
+Одно из ограничений атрибутов, предоставляемых библиотекой `cortex-m-rt` является
+то, что совместное использование данных (или периферии) между прерываниями,
+или прерыванием и функцией `init`, требуют `cortex_m::interrupt::Mutex`, который
+*всегда* требует отключения *всех* прерываний для доступа к данным. Отключение всех
+прерываний не всегда необходимо для безопасности памяти, но компилятор не имеет
+достаточно информации, чтобы оптимизировать доступ к разделяемым данным.
+
+Атрибут `app` имеет полную картину приложения, поэтому может оптимизировать доступ к
+`static`-переменным. В RTFM мы обращаемся к `static`-переменным, объявленным внутри
+псевдо-модуля `app` как к *ресурсам*. Чтобы получить доступ к ресурсу, контекст
+(`init`, `idle`, `interrupt` или `exception`) должен сначала определить
+аргумент `resources` в соответствующем атрибуте.
+
+В примере ниже два обработчика прерываний имеют доступ к одному и тому же ресурсу.
+Никакого `Mutex` в этом случае не требуется, потому что оба обработчика запускаются
+с обним приоритетом и никакого вытеснения быть не может.
+К ресурсу `SHARED` можно получить доступ только из этих двух прерываний.
+
+``` rust
+{{#include ../../../examples/resource.rs}}
+```
+
+``` console
+$ cargo run --example resource
+{{#include ../../../ci/expected/resource.run}}
+```
+
+## Приоритеты
+
+Приоритет каждого прерывания можно определить в атрибутах `interrupt` и `exception`.
+Невозможно установить приоритет любым другим способом, потому что рантайм
+забирает владение прерыванием `NVIC`; также невозможно изменить приоритет
+обработчика / задачи в рантайме. Благодаря этому ограничению у фреймворка
+есть знание о *статических* приоритетах всех обработчиков прерываний и исключений.
+
+Прерывания и исключения могут иметь приоритеты в интервале `1..=(1 << NVIC_PRIO_BITS)`,
+где `NVIC_PRIO_BITS` - константа, определённая в библиотеке `device`.
+Задача `idle` имеет приоритет `0`, наименьший.
+
+Ресурсы, совместно используемые обработчиками, работающими на разных приоритетах,
+требуют критических секций для безопасности памяти. Фреймворк проверяет, что
+критические секции используются, но *только где необходимы*: например,
+критические секции не нужны для обработчика с наивысшим приоритетом, имеющим
+доступ к ресурсу.
+
+API критической секции, предоставляемое фреймворком RTFM (см. [`Mutex`]),
+основано на динамических приоритетах вместо отключения прерываний. Из этого следует,
+что критические секции не будут допускать *запуск некоторых* обработчиков,
+включая все соперничающие за ресурс, но будут позволять запуск обработчиков с
+большим приоритетом не соперничащих за ресурс.
+
+[`Mutex`]: ../../api/rtfm/trait.Mutex.html
+
+В примере ниже у нас есть 3 обработчика прерываний с приоритетами от одного
+до трех. Два обработчика с низким приоритетом соперничают за ресурс `SHARED`.
+Обработчик с низшим приоритетом должен заблокировать ([`lock`]) ресурс
+`SHARED`, чтобы получить доступ к его данным, в то время как обработчик со
+средним приоритетом может напрямую получать доступ к его данным. Обработчик
+с наивысшим приоритетом может свободно вытеснять критическую секцию,
+созданную обработчиком с низшим приоритетом.
+
+[`lock`]: ../../api/rtfm/trait.Mutex.html#method.lock
+
+``` rust
+{{#include ../../../examples/lock.rs}}
+```
+
+``` console
+$ cargo run --example lock
+{{#include ../../../ci/expected/lock.run}}```
+
+## Поздние ресурсы
+
+В отличие от обычных `static`-переменных, к которым должно быть присвоено
+начальное значение, ресурсы можно инициализировать в рантайме.
+Мы называем ресурсы, инициализируемые в рантайме *поздними*. Поздние ресурсы
+полезны для *переноса* (как при передаче владения) периферии из `init` в
+обработчики прерываний и исключений.
+
+Поздние ресурсы определяются как обычные ресурсы, но им присваивается начальное
+значение `()` (the unit value). Поздние ресурсы необходимо инициализировать в конце
+функции `init` используя обычное присвоение (например `FOO = 1`).
+
+В примере ниже использованы поздние ресурсы, чтобы установить неблокированный,
+односторонний канал между обработчиком прерывания `UART0` и функцией `idle`.
+Очередь типа один производитель-один потребитель [`Queue`] использована как канал.
+Очередь разделена на элементы потребителя и поизводителя в `init` и каждый элемент
+расположен в отдельном ресурсе; `UART0` владеет ресурсом произодителя, а `idle`
+владеет ресурсом потребителя.
+
+[`Queue`]: ../../api/heapless/spsc/struct.Queue.html
+
+``` rust
+{{#include ../../../examples/late.rs}}
+```
+
+``` console
+$ cargo run --example late
+{{#include ../../../ci/expected/late.run}}```
+
+## `static`-ресурсы
+
+Переменные типа `static` также можно использовать в качестве ресурсов. Задачи
+могут получать только (разделяемые) `&` ссылки на ресурсы, но блокировки не
+нужны для доступа к данным. Вы можете думать о `static`-ресурсах как о простых
+`static`-переменных, которые можно инициализировать в рантайме и иметь лучшие
+правила видимости: Вы можете контролировать, какие задачи получают доступ к
+переменной, чтобы переменная не была видна всем фунциям в область видимости,
+где она была объявлена.
+
+В примере ниже ключ загружен (или создан) в рантайме, а затем использован в двух
+задачах, запущенных на разных приоритетах.
+
+``` rust
+{{#include ../../../examples/static.rs}}
+```
+
+``` console
+$ cargo run --example static
+{{#include ../../../ci/expected/static.run}}```
diff --git a/ru/src/by-example/singletons.md b/ru/src/by-example/singletons.md
new file mode 100644
index 00000000..b7131e63
--- /dev/null
+++ b/ru/src/by-example/singletons.md
@@ -0,0 +1,26 @@
+# Одиночки
+
+Атрибут `app` знает о библиотеке [`owned-singleton`] и её атрибуте [`Singleton`].
+Когда этот атрибут применяется к одному из ресурсов, рантайм производит для Вас
+`unsafe` инициализацию одиночки, проверяя, что только один экземпляр одиночки
+когда-либо создан.
+
+[`owned-singleton`]: ../../api/owned_singleton/index.html
+[`Singleton`]: ../../api/owned_singleton_macros/attr.Singleton.html
+
+Заметьте, что когда Вы используете атрибут `Singleton`, Вым нужно иметь
+`owned_singleton` в зависимостях.
+
+Ниже, в примере, использован атрибут `Singleton` на куске памяти, а затем
+использован экземпляр одиночки как фиксированный по размеру пул памяти,
+используя одну из абстракций [`alloc-singleton`].
+
+[`alloc-singleton`]: https://crates.io/crates/alloc-singleton
+
+``` rust
+{{#include ../../../examples/singleton.rs}}
+```
+
+``` console
+$ cargo run --example singleton
+{{#include ../../../ci/expected/singleton.run}}```
diff --git a/ru/src/by-example/tasks.md b/ru/src/by-example/tasks.md
new file mode 100644
index 00000000..d958d571
--- /dev/null
+++ b/ru/src/by-example/tasks.md
@@ -0,0 +1,63 @@
+# Программные задачи
+
+RTFM обрабатывает прерывания и исключения как *аппаратные* задачи. Аппаратные
+задачи могут вызываться устройством в ответ на события, такие как нажатие кнопки.
+RTFM также поддерживает *программные* задачи, порождаемые программой из любого
+контекста выполнения.
+
+Программным задачам также можно назначать приоритет и диспетчеризовать из
+обработчиков прерываний. RTFM требует определения свободных прерываний в блоке
+`extern`, когда используются программные задачи; эти свободные прерывания будут использованы, чтобы диспетчеризовать программные задачи. Преимущество программных
+задач перед аппаратными в том, что на один обработчик прерывания можно назначить
+множество задач.
+
+Программные задачи определяются заданием функциям атрибута `task`. Чтобы было
+возможно вызывать программные задачи, имя задачи нужно передать в аргументе
+`spawn` контекста атрибута (`init`, `idle`, `interrupt`, etc.).
+
+В примере ниже продемонстрированы три программных задачи, запускаемые на 2-х
+разных приоритетах. Трем задачам назначены 2 обработчика прерываний.
+
+``` rust
+{{#include ../../../examples/task.rs}}
+```
+
+``` console
+$ cargo run --example task
+{{#include ../../../ci/expected/task.run}}```
+
+## Передача сообщений
+
+Другое преимущество программных задач - возможность передавать сообщения задачам
+во время их вызова. Тип полезной нагрузки сообщения должен быть определен в
+сигнатуре обработчика задачи.
+
+Пример ниже демонстрирует три задачи, две из которых ожидают сообщения.
+
+``` rust
+{{#include ../../../examples/message.rs}}
+```
+
+``` console
+$ cargo run --example message
+{{#include ../../../ci/expected/message.run}}```
+
+## Ёмкость
+
+Диспетчеры задач *не* используют динамическое выделение памяти. Память
+необходимая для размещения сообщений, резервируется статически. Фреймворк
+зарезервирует достаточно памяти для каждого контекста, чтобы можно было вызвать
+каждую задачу как минимум единожды. Это разумно по умолчанию, но
+"внутреннюю" ёмкость каждой задачи можно контролировать используя аргумент
+`capacicy` атрибута `task`.
+
+В примере ниже установлена ёмкость программной задачи `foo` на 4. Если ёмкость
+не определена, тогда второй вызов `spawn.foo` в `UART0` вызовет ошибку.
+
+``` rust
+{{#include ../../../examples/capacity.rs}}
+```
+
+``` console
+$ cargo run --example capacity
+{{#include ../../../ci/expected/capacity.run}}```
diff --git a/ru/src/by-example/timer-queue.md b/ru/src/by-example/timer-queue.md
new file mode 100644
index 00000000..939192fa
--- /dev/null
+++ b/ru/src/by-example/timer-queue.md
@@ -0,0 +1,90 @@
+# Очередь таймера
+
+Когда включена опция `timer-queue`, фреймворк RTFM включает
+*глобальную очередь таймера*, которую приложения могут использовать, чтобы
+*планировать* программные задачи на запуск через некоторое время в будущем.
+
+Чтобы была возможность планировать программную задачу, имя задачи должно
+присутствовать в аргументе `schedule` контекста атрибута. Когда задача
+планируется, момент ([`Instant`]), в который задачу нужно запустить, нужно передать
+как первый аргумент вызова `schedule`.
+
+[`Instant`]: ../../api/rtfm/struct.Instant.html
+
+Рантайм RTFM включает монотонный, растущий только вверх, 32-битный таймер,
+значение которого можно запросить конструктором `Instant::now`. Время ([`Duration`])
+можно передать в `Instant::now()`, чтобы получить `Instant` в будущем. Монотонный
+таймер отключен пока запущен `init`, поэтому `Instant::now()` всегда возвращает
+значение `Instant(0 /* циклов тактовой частоты */)`; таймер включается сразу перед
+включением прерываний и запуском `idle`.
+
+[`Duration`]: ../../api/rtfm/struct.Duration.html
+
+В примере ниже две задачи планируются из `init`: `foo` и `bar`. `foo` -
+запланирована на запуск через 8 миллионов тактов в будущем. Кроме того, `bar`
+запланирован на запуск через 4 миллиона тактов в будущем. `bar` запустится раньше
+`foo`, т.к. он запланирован на запуск первым.
+
+> **ВАЖНО**: Примеры, использующие API `schedule` или абстракцию `Instant`
+> **не** будут правильно работать на QEMU, потому что функциональность счетчика
+> тактов Cortex-M не реализована в `qemu-system-arm`.
+
+``` rust
+{{#include ../../../examples/schedule.rs}}
+```
+
+Запуск программы на реальном оборудовании производит следующий вывод в консоли:
+
+``` text
+{{#include ../../../ci/expected/schedule.run}}
+```
+
+## Периодические задачи
+
+Программные задачи имеют доступ к `Instant` в момент, когда были запланированы
+на запуск через переменную `scheduled`. Эта информация и API `schedule` могут
+быть использованы для реализации периодических задач, как показано в примере ниже.
+
+``` rust
+{{#include ../../../examples/periodic.rs}}
+```
+
+Это вывод, произведенный примером. Заметьте, что есть смещение / колебание нуля
+даже если `schedule.foo` была вызвана в *конце* `foo`. Использование
+`Instant::now` вместо `scheduled` имело бы влияние на смещение / колебание.
+
+``` text
+{{#include ../../../ci/expected/periodic.run}}
+```
+
+## Базовое время
+
+Для задач, планируемых из `init` мы имеем точную информацию о их планируемом
+(`scheduled`) времени. Для аппаратных задач нет `scheduled` времени, потому
+что эти задачи асинхронны по природе. Для аппаратных задач рантайм предоставляет
+время старта (`start`), которе отражает время, в которое обработчик прерывания
+был запущен.
+
+Заметьте, что `start` **не** равен времени возникновения события, вызвавшего
+задачу. В зависимости от приоритета задачи и загрузки системы время
+`start` может быть сильно отдалено от времени возникновения события.
+
+Какое по Вашему мнению будет значение `scheduled` для программных задач которые
+*вызываются*, вместо того чтобы планироваться? Ответ в том, что вызываемые
+задачи наследуют *базовое* время контекста, в котором вызваны. Бызовым для
+аппаратных задач является `start`, базовым для программных задач - `scheduled`
+и базовым для `init` - `start = Instant(0)`. `idle` на сомом деле не имеет
+базового времени но задачи, вызванные из него будут использовать `Instant::now()`
+как их базовое время.
+
+Пример ниже демонстрирует разное значение *базового времени*.
+
+``` rust
+{{#include ../../../examples/baseline.rs}}
+```
+
+Запуск программы на реальном оборудовании произведет следующий вывод в консоли:
+
+``` text
+{{#include ../../../ci/expected/baseline.run}}
+```
diff --git a/ru/src/by-example/tips.md b/ru/src/by-example/tips.md
new file mode 100644
index 00000000..3608dc2f
--- /dev/null
+++ b/ru/src/by-example/tips.md
@@ -0,0 +1,63 @@
+# Советы и хитрости
+
+## Generics
+
+Ресурсы, совместно используемые двумя или более задачами реализуют трейт `Mutex`
+во *всех* контекстах, даже в тех, где для доступа к данным не требуются
+критические секции. Это позволяет легко писать обобщенный код оперирующий
+ресурсами, который можно вызывать из различных задач. Вот такой пример:
+
+``` rust
+{{#include ../../../examples/generics.rs}}
+```
+
+``` console
+$ cargo run --example generics
+{{#include ../../../ci/expected/generics.run}}```
+
+Это также позволяет Вам изменять статические приоритеты задач без
+переписывания кода. Если Вы единообразно используете `lock`-и для доступа
+к данным в разделяемых ресурсах, тогда Ваш код продолжит компилироваться,
+когда Вы измените приоритет задач.
+
+## Запуск задач из RAM
+
+Главной целью переноса описания программы на RTFM в атрибуты в
+RTFM v0.4.x была возможность взаимодействия с другими атрибутами.
+Напримерe, атрибут `link_section` можно применять к задачам, чтобы разместить
+из в RAM; это может улучшить производительность в некоторых случаях.
+
+> **ВАЖНО**: Обычно атрибуты `link_section`, `export_name` и `no_mangle`
+> очень мощные, но их легко использовать неправильно. Неверное использование
+> любого из этих атрибутов может вызвать неопределенное поведение;
+> Вам следует всегда предпочитать использование безопасных, высокоуровневых
+> атрибутов вокруг них, таких как атрибуты `interrupt` и `exception`
+> из `cortex-m-rt`.
+>
+> В особых случаях функций RAM нет безопасной абстракции в `cortex-m-rt`
+> v0.6.5 но создано [RFC] для добавления атрибута `ramfunc` в будущем релизе.
+
+[RFC]: https://github.com/rust-embedded/cortex-m-rt/pull/100
+
+В примере ниже показано как разместить высокоприоритетную задачу `bar` в RAM.
+
+``` rust
+{{#include ../../../examples/ramfunc.rs}}
+```
+
+Запуск этой программы произведет ожидаемый вывод.
+
+``` console
+$ cargo run --example ramfunc
+{{#include ../../../ci/expected/ramfunc.run}}```
+
+Можно посмотреть на вывод `cargo-nm`, чтобы убедиться, что `bar` расположен в RAM
+(`0x2000_0000`), тогда как `foo` расположен во Flash (`0x0000_0000`).
+
+``` console
+$ cargo nm --example ramfunc --release | grep ' foo::'
+{{#include ../../../ci/expected/ramfunc.grep.foo}}```
+
+``` console
+$ cargo nm --example ramfunc --release | grep ' bar::'
+{{#include ../../../ci/expected/ramfunc.grep.bar}}```
diff --git a/ru/src/by-example/types-send-sync.md b/ru/src/by-example/types-send-sync.md
new file mode 100644
index 00000000..5b3857ca
--- /dev/null
+++ b/ru/src/by-example/types-send-sync.md
@@ -0,0 +1,59 @@
+# Типы, Send и Sync
+
+Атрибут `app` вводит контекст, коллекцию переменных в каждую из функций.
+Все эти переменные имеют предсказуемые, неанонимные типы, поэтому Вы можете
+писать простые функции, получающие их как аргументы.
+
+Описание API определяет как эти типы эти типы генерируются из входных данных.
+Вы можете также сгенерировать документацию для Вашей бинарной библиотеки
+(`cargo doc --bin <name>`); в документации Вы найдете структуры `Context`
+(например `init::Context` и `idle::Context`), чьи поля представляют переменные
+включенные в каждую функцию.
+
+В примере ниже сгенерированы разные типы с помощью атрибута `app`.
+
+``` rust
+{{#include ../../../examples/types.rs}}
+```
+
+## `Send`
+
+[`Send`] - маркерный трейт для "типов, которые можно передавать через границы
+потоков", как это определено в `core`. В контексте RTFM трейт `Send` необходим
+только там, где возможна передача значения между задачами, запускаемыми на
+*разных* приоритетах. Это возникает в нескольких случаях: при передаче сообщений,
+в совместно используемых `static mut` ресурсах и инициализации поздних ресурсов.
+
+[`Send`]: https://doc.rust-lang.org/core/marker/trait.Send.html
+
+Атрибут `app` проверит, что `Send` реализован, где необходимо, поэтому Вам не
+стоит волноваться об этом. Более важно знать, где Вам *не* нужен трейт `Send`:
+в типах, передаваемых между задачами с *одинаковым* приоритетом. Это возникает
+в двух случаях: при передаче сообщений и в совместно используемых `static mut`
+ресурсах.
+
+В примере ниже показано, где можно использовать типы, не реализующие `Send`.
+
+``` rust
+{{#include ../../../examples/not-send.rs}}
+```
+
+## `Sync`
+
+Похожая ситуация, [`Sync`] - маркерный трейт для "типов, на которых можно
+ссылаться в разных потоках", как это определено в `core`. В контексте RTFM
+трейт `Sync` необходим только там, где возможны две или более задачи,
+запускаемые на разных приоритетах, чтобы захватить разделяемую ссылку на
+ресурс. Это возникает только совместно используемых `static`-ресурсах.
+
+[`Sync`]: https://doc.rust-lang.org/core/marker/trait.Sync.html
+
+Атрибут `app` проверит, что `Sync` реализован, где необходимо, но важно знать,
+где ограничение `Sync` не требуется: в `static`-ресурсах, разделяемых между
+задачами с *одинаковым* приоритетом.
+
+В примере ниже показано, где можно использовать типы, не реализующие `Sync`.
+
+``` rust
+{{#include ../../../examples/not-sync.rs}}
+```
diff --git a/ru/src/chapter_1.md b/ru/src/chapter_1.md
deleted file mode 100644
index b743fda3..00000000
--- a/ru/src/chapter_1.md
+++ /dev/null
@@ -1 +0,0 @@
-# Chapter 1
diff --git a/ru/src/internals.md b/ru/src/internals.md
new file mode 100644
index 00000000..4a47e775
--- /dev/null
+++ b/ru/src/internals.md
@@ -0,0 +1,7 @@
+# Под капотом
+
+В этом разделе описывабтся внутренности фркймворка на *высоком уровне*.
+Низкоуровневые тонкости, такие как парсинг и кодогенерация производимые
+процедурным макросом (`#[app]`) здесь объясняться не будут. Мы сосредоточимся
+на анализе пользовательской спецификации и структурах данных, используемых
+рантаймом.
diff --git a/ru/src/internals/ceilings.md b/ru/src/internals/ceilings.md
new file mode 100644
index 00000000..2c645a4d
--- /dev/null
+++ b/ru/src/internals/ceilings.md
@@ -0,0 +1,3 @@
+# Ceiling analysis
+
+**TODO**
diff --git a/ru/src/internals/tasks.md b/ru/src/internals/tasks.md
new file mode 100644
index 00000000..85f783fb
--- /dev/null
+++ b/ru/src/internals/tasks.md
@@ -0,0 +1,3 @@
+# Task dispatcher
+
+**TODO**
diff --git a/ru/src/internals/timer-queue.md b/ru/src/internals/timer-queue.md
new file mode 100644
index 00000000..70592852
--- /dev/null
+++ b/ru/src/internals/timer-queue.md
@@ -0,0 +1,3 @@
+# Timer queue
+
+**TODO**
diff --git a/ru/src/preface.md b/ru/src/preface.md
new file mode 100644
index 00000000..8aa53ad7
--- /dev/null
+++ b/ru/src/preface.md
@@ -0,0 +1,12 @@
+<h1 align="center">Real Time For the Masses</h1>
+
+<p align="center">Конкурентный фреймворк для создания систем реального времени</p>
+
+# Введение
+
+Эта книга содержит документацию уровня пользователя фреймворком Real Time For the Masses
+(RTFM). Описание API можно найти [здесь](../api/rtfm/index.html).
+
+{{#include README_RU.md:5:54}}
+
+{{#include README_RU.md:60:}}