aboutsummaryrefslogtreecommitdiff
path: root/book/ru/src/by-example
diff options
context:
space:
mode:
Diffstat (limited to 'book/ru/src/by-example')
-rw-r--r--book/ru/src/by-example/app.md161
-rw-r--r--book/ru/src/by-example/new.md84
-rw-r--r--book/ru/src/by-example/resources.md140
-rw-r--r--book/ru/src/by-example/tasks.md116
-rw-r--r--book/ru/src/by-example/timer-queue.md108
-rw-r--r--book/ru/src/by-example/tips.md175
-rw-r--r--book/ru/src/by-example/types-send-sync.md49
7 files changed, 0 insertions, 833 deletions
diff --git a/book/ru/src/by-example/app.md b/book/ru/src/by-example/app.md
deleted file mode 100644
index 5259bfa..0000000
--- a/book/ru/src/by-example/app.md
+++ /dev/null
@@ -1,161 +0,0 @@
-# Атрибут `app`
-
-Это простейшая из возможных программ на RTIC:
-
-``` rust
-{{#include ../../../../examples/smallest.rs}}
-```
-
-Все программы на RTIC используют атрибут [`app`] (`#[app(..)]`). Этот атрибут
-должен применяться к элементу `mod`. Атрибут `app` имеет обязательный аргумент `device`,
-который принимает *путь* как значение. Это должен быть полный путь, указывающий на
-*крейт доступа к периферии* (PAC), сгенерированный с помощью [`svd2rust`] версии **v0.14.x**
-или новее. Более подробно в разделе [Создание нового проекта](./new.md).
-
-Атрибут `app` будет раскрыт в подходящую точку входа программы, поэтому
-атрибут [`cortex_m_rt::entry`] не нужен.
-
-[`app`]: ../../../api/cortex_m_rtic_macros/attr.app.html
-[`svd2rust`]: https://crates.io/crates/svd2rust
-[`cortex_m_rt::entry`]: ../../../api/cortex_m_rt_macros/attr.entry.html
-
-## `init`
-
-Внутри модуля `app` атрибут ожидает найти функцию инициализации, помеченную
-атрибутом `init`. Эта функция должна иметь сигнатуру
-`fn(init::Context) (-> init::LateResources, init::Monotonics)`.
-
-Эта функция инициализации будет первой частью программы, выполняемой при запуске.
-Функция `init` будет запущена *с отключенными прерываниями* и будет иметь эксклюзивный доступ
-к Cortex-M, в котором токен `bare_metal::CriticalSection` доступен как `cs`.
-Опционально, устройство-специфичные периферия доступна через поля `core` и `device` структуры
-`init::Context`.
-
-`static mut` переменные, определенные в начале `init` будут преобразованы в
-`&'static mut` ссылки, безопасные для доступа. Обратите внимание, данная возможность может
-быть удалена в следующем релизе, см. `task_local` ресурсы.
-
-[`rtic::Peripherals`]: ../../api/rtic/struct.Peripherals.html
-
-Пример ниже показывает типы полей `core`, `device` и `cs`, и демонстрирует
-безопасный доступ к `static mut` переменной. Поле `device` доступно только
-когда аргумент `peripherals` установлен в `true` (по умолчанию).
-В редких случаях, когда вы захотите создать приложение с минимальным потреблением ресурсов,
-можно явно установить `peripherals` в `false`.
-
-``` rust
-{{#include ../../../../examples/init.rs}}
-```
-
-Запуск примера напечатате `init` в консоли, а затем завершит процесс QEMU.
-
-``` console
-$ cargo run --example init
-{{#include ../../../../ci/expected/init.run}}
-```
-
-> **ПРИМЕЧАНИЕ**: Не забывайте указывать выбранное вами целевое устройство, передавая параметр target
-> в cargo (например `cargo run --example init --target thumbv7m-none-eabi`) или
-> настроив устройство, используемое по умолчанию для сборки примеров в `.cargo/config.toml`.
-> В нашем случае используется Cortex M3, эмулируемый с помощью QEMU, поэтому пишем `thumbv7m-none-eabi`.
-> Смотрите [`Создание нового проекта`](./new.md) для большей информации.
-
-## `idle`
-
-Функцию, помеченную атрибутом `idle` может опционально добавить в модуль.
-Эта функция используется как специальная *задача ожидания* и должна иметь сигнатуру
-`fn(idle::Context) - > !`.
-
-Если она присутствует, задача `idle` будет запущена после `init`. В отличие от
-`init`, `idle` будет запущена *с включенными прерываниями* и она не может вернуть результат,
-а значит должна работать вечно.
-
-Как и в `init`, `static mut` переменные будут трансформированы в `&'static mut` ссылки,
-безопасные для доступа. Обратите внимание, данная возможность может
-быть удалена в следующем релизе, см. `task_local` ресурсы.
-
-Пример ниже показывает, что `idle` запускается после `init`.
-
-**Примечание:** Цикл `loop {}` в функци ожидания не может быть пустым, так как это сломает
-микроконтроллер, из-за того, что LLVM компилирует пустые циклы в инструкцию `UDF` в release mode.
-Чтобы избежать неопределенного поведения, цикл должен включать "side-effect"
-путем вставки ассемблерной инструкции (например, `WFI`) или ключевого слова `continue`.
-
-``` rust
-{{#include ../../../../examples/idle.rs}}
-```
-
-``` console
-$ cargo run --example idle
-{{#include ../../../../ci/expected/idle.run}}
-```
-
-## Аппаратные задачи
-
-Чтобы объявить обработчик прерывания, фреймворк предоставляет атрибут `#[task]`,
-который можно применять к функциям. Этот атрибут берет аргумент `binds`, чье значение -
-это имя прерывания, которому будет назначен обработчик;
-функция, декорированная этим атрибутом становится обработчиком прерывания.
-В фреймворке такие типы задач именуются *аппаратными*, потому что они начинают
-выполняться в ответ на аппаратное событие.
-
-Пример ниже демонстрирует использование атрибута `#[task]`, чтобы объявить
-обработчик прерывания. Как и в случае с `#[init]` и `#[idle]` локальные `static
-mut` переменные безопасны для использования с аппаратной задачей.
-
-``` rust
-{{#include ../../../../examples/hardware.rs}}
-```
-
-``` console
-$ cargo run --example hardware
-{{#include ../../../../ci/expected/hardware.run}}
-```
-
-До сих пор все программы на RTIC, которые мы видели, не отличались от программ,
-которые можно написать, используя лишь крейт `cortex-m-rt`. С этого момента мы
-начинаем представлять возможности, уникальные для RTIC.
-
-## Приоритеты
-
-Статический приоритет каждого обработчика можно оределить в атрибуте `task`, используя
-аргумент `priority`. Задачи могут иметь приоритет в диапазоне `1..=(1 << NVIC_PRIO_BITS)`,
-где `NVIC_PRIO_BITS` - это константа, определенная в крейте `устройства`.
-Когда аргумент `priority` не указан, предполагается, что приоритет равен `1`.
-Задача `idle` имеет ненастраиваемый приоритет `0`, наименьший из возможных.
-
-> Более высокое значение означает более высокий приоритет в RTIC, что противоположно тому,
-> что указано в периферии NVIC Cortex-M.
-> Точнее, это значит, что число `10` обозначает приоритет **выше**, чем число `9`.
-
-Когда несколько задач готовы к запуску, задача с самым большим статическим
-приоритетом будет запущена первой. Приоритезацию задач можно рассматривать по
-такому сценарию: сигнал прерывания приходит во время выполнения задачи с низким приоритетом;
-сигнал переключает задачу с высоким приоритетом в режим ожидания.
-Разница в приоритетах приводи к тому, что задача с высоким приоритетом вытесняет задачу с низким:
-выполнение задачи с низким приоритетом замораживается и задача с высоким приоритетом выполняется,
-пока не будет завершена. Как только задача с высоким приоритетом будет остановлена,
-продолжится выполнение задачи с низким приоритетом.
-
-Следующий пример демонстрирует диспетчеризацию на основе приоритетов задач.
-
-``` rust
-{{#include ../../../../examples/preempt.rs}}
-```
-
-``` console
-$ cargo run --example preempt
-{{#include ../../../../ci/expected/preempt.run}}
-```
-
-Заметьте, что задача `gpiob` *не* вытесняет задачу `gpioc`, потому что ее приоритет
-*такой же*, как и у `gpioc`. Однако, как только `gpioc` возвращает результат,
-выполненяется задача `gpiob`, как более приоритетная по сравнению с `gpioa`.
-Выполнение `gpioa` возобновляется только после выхода из `gpiob`.
-
-Еще одно замечание по поводу приоритетов: выбор приоритета большего, чем поддерживает устройство
-(а именно `1 << NVIC_PRIO_BITS`) приведет к ошибке компиляции.
-Из-за ограничений языка, сообщение об ошибке далеко от понимания:
-вам скажут что-то похожее на "evaluation of constant value failed", а указатель на ошибку
-*не* покажет на проблемное значение прерывания --
-мы извиняемся за это!
diff --git a/book/ru/src/by-example/new.md b/book/ru/src/by-example/new.md
deleted file mode 100644
index 0ff8d98..0000000
--- a/book/ru/src/by-example/new.md
+++ /dev/null
@@ -1,84 +0,0 @@
-# Создание нового проекта
-
-Теперь, когда Вы изучили основные возможности фреймворка RTIC, Вы можете
-попробовать его использовать на Вашем оборудовании следуя этим инструкциям.
-
-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. Добавьте крейт доступа к периферии (PAC), сгенерированный с помощью[`svd2rust`]
- **v0.14.x**, или крейт отладочной платы, у которой в зависимостях один из таких PAC'ов.
- Убедитесь, что опция `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-rtic` как зависимость.
-
-``` console
-$ cargo add cortex-m-rtic --allow-prerelease
-```
-
-4. Напишите свою RTIC программу.
-
-Здесь я буду использовать пример `init` из крейта `cortex-m-rtic`.
-
-Примеры находтся в папке `examples`, а содержание `init.rs` показано здесь:
-
-``` console
-{{#include ../../../../examples/init.rs}}
-```
-
-Пример `init` использует устройство `lm3s6965`. Не забудьте настроить аргумент `device`
-в атрибуте макроса app так, чтобы он соответствовал пути к PAC-крейту, если он отличается,
-а также добавить перифериб и другие аргументы если необходимо.
-Несмотря на то, что в программе могут использоваться псевдонимы типов,
-здесь необходимо указать полный путь (из корня крейта). Для многих устройств,
-есть общий подход в крейтах реализации HAL (с псевдонимом `hal`) и крейтах поддержки
-отладочных плат реекспортиорвать PAC как `pac`, что приводит нас к образцу, аналогичному
-приведенному ниже:
-
-```rust
-use abcd123_hal as hal;
-//...
-
-#[rtic::app(device = crate::hal::pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
-mod app { /*...*/ }
-```
-
-Пример `init` также зависит от крейта `panic-semihosting`:
-
-``` console
-$ cargo add panic-semihosting
-```
-
-5. Соберите его, загрузите в микроконтроллер и запустите.
-
-``` console
-$ # ПРИМЕЧАНИЕ: Я раскомментировал опцию `runner` в `.cargo/config.toml`
-$ cargo run
-{{#include ../../../../ci/expected/init.run}}
-```
diff --git a/book/ru/src/by-example/resources.md b/book/ru/src/by-example/resources.md
deleted file mode 100644
index ed8904b..0000000
--- a/book/ru/src/by-example/resources.md
+++ /dev/null
@@ -1,140 +0,0 @@
-# Ресурсы
-
-Фреймворк предоставляет абстракцию для разделения данных между любыми контекстами,
-с которыми мы встречались в предыдущей главе (задачами-обработчиками, `init` и `idle`): ресурсы.
-
-Ресурсы - это данные, видимые только функциями, определенными внутри модуля `#[app]`.
-Фреймворк дает пользователю полный контроль за тем, какой контекст может
-получить доступ к какому ресурсу.
-
-Все ресурсы определены в *двух* структурах внутри модуля `#[app]`.
-Каждое поле этих структур соответствует отдельному ресурсу.
-Одна `struct`-ура должна быть аннотирована атрибутом `#[local]`.
-Другая `struct`-ура должна быть аннотирована атрибутом `#[shared]`.
-Разница между этими двумя множествами ресурсов будет описана познее.
-
-Каждый контекс (задача-обработчик, `init` или `idle`) должен указать ресурсы, к которым
-он намерен обращаться, в соответсятвующем ему атрибуте с метаданными, используя
-либо аргумент `local`, либо `shared`. Этот аргумент принимает список имен ресурсов в качестве значения.
-Перечисленные ресурсы становятся доступны в контексте через поля `local` и `shared` структуры `Context`.
-
-Во время выполнения при выходе из функции `#[init]` все ресурсы инициализированы.
-Функция `#[init]` должна возвращать начальные значения для всех ресурсов;
-отсюда следует, что тип возвращаемого ею значения включает типы
-структур `#[shared]` и `#[local]`.
-Поскольку ресурсы инициализированы в ходе функции `#[init]`, к ним нельзя
-получить доступ внетри функции `#[init]`.
-
-Пример программы, показанной ниже содержит два обработчика прерывания.
-Каждый обработчик имеет доступ к его собственному `#[local]` ресурсу.
-
-``` rust
-{{#include ../../../../examples/resource.rs}}
-```
-
-``` console
-$ cargo run --example resource
-{{#include ../../../../ci/expected/resource.run}}
-```
-
-К ресурсу `#[local]` нельзя получить доступ извне задачи к которой он
-привязан атрибутом `#[task]`.
-Попытка обращения к одному и тому же ресурсу `#[local]` из более чем одной
-задачи - ошибка компиляции.
-
-## `lock`
-
-Критические секции необходимы для доступа к ресурсам `#[shared]` таким образом,
-чтобы избежать гонок данных.
-
-Поле `shared`, передаваемого `Context` реализует трейт [`Mutex`] для каждого разделяемого
-ресурса, доступного задаче.
-
-Единственный метод этого трейта, [`lock`], запускает свой аргумент-замыкание в критической секции.
-
-[`Mutex`]: ../../../api/rtic/trait.Mutex.html
-[`lock`]: ../../../api/rtic/trait.Mutex.html#method.lock
-
-Критическая секция, создаваемая интерфейсом `lock` основана на динамических приоритетах:
-она временно повышает динамический приоритет контекста до *максимального* приоритета,
-что не дает другим задачам возможности вытеснить критическую секцию.
-Этот протокол синхронизации известен как [Протокол немедленного максимального приоритета
-(ICPP)][icpp], и компилируется диспетчером RTIC с [Политикой ресурсов стека(SRP)][srp].
-
-[icpp]: https://en.wikipedia.org/wiki/Priority_ceiling_protocol
-[srp]: https://en.wikipedia.org/wiki/Stack_Resource_Policy
-
-В примере ниже у нас есть три обработчика прерываний с приоритетами от одного до трех.
-Два из обработчиков с более низким приоритетом соревнуются за ресурс `shared`,
-поэтому должны блокировать доступа к данным ресурса.
-Обработчик с наивысшим приоритетом, который не имеет доступа к ресурсу `shared`,
-может свободно вытеснять критическую секцию, созданную обработчиком с низким приоритетом.
-
-``` rust
-{{#include ../../../../examples/lock.rs}}
-```
-
-``` console
-$ cargo run --example lock
-{{#include ../../../../ci/expected/lock.run}}
-```
-
-## Множественное блокировка
-
-Это расширение к `lock`, чтобы уменьшить количесво отступов, блокируемые ресурсы можно объединять в кортежи.
-Следующий пример это демонстрирует:
-
-``` rust
-{{#include ../../../../examples/multilock.rs}}
-```
-
-## Только разделяемый (`&-`) доступ
-
-По-умолчанию фреймворк предполагает, что все задачи требуют эксклюзивный доступ (`&mut-`) к ресурсам,
-но возможно указать, что задаче достаточен разделяемый доступ (`&-`) к ресурсы с помощью синтакисиса
-`&resource_name` в списке `resources`.
-
-Преимущество указания разделяемого досупа (`&-`) к ресурсу в том, что для доступа к ресурсу
-не нужна блокировка, даже если за ресурс соревнуются несколько задач, запускаемые с
-разными приоритетами. Недостаток в том, что задача получает только разделяемую ссылку (`&-`)
-на ресурс, и ограничена операциями, возможными с ней, но там, где разделяемой ссылки достаточно,
-такой подход уменьшает количесво требуемых блокировок.
-В дополнение к простым неизменяемым данным, такой разделяемый доступ может быть полезен для
-ресурсов, безопасно реализующих внутреннюю мутабельность с самоблокировкой или атомарными операциями.
-
-Заметьте, что в этом релизе RTIC невозможно запросить и эксклюзивный доступ (`&mut-`)
-и разделяемый (`&-`) для *одного и того же* ресурса из различных задач.
-Попытка это сделать приведет к ошибке компиляции.
-
-В примере ниже ключ (например криптографический ключ) загружается (или создается) во время выполнения,
-а затем используется двумя задачами, запускаемымы с различным приоритетом без каких-либо блокировок.
-
-``` rust
-{{#include ../../../../examples/only-shared-access.rs}}
-```
-
-``` console
-$ cargo run --example only-shared-access
-{{#include ../../../../ci/expected/only-shared-access.run}}
-```
-
-## Неблокируемый доступ к изменяемым ресурсам
-
-Критическая секция *не* требуется для доступа к ресурсу `#[shared]`,
-к которому обращаются только из задач с *одинаковым* приоритетом.
-В этом случае вы можете избежать `lock` API, добавив атрибут поля `#[lock_free]` при объявдении ресурса (смотреть пример ниже).
-Заметьте, что это лишь для удобства: даже если вы используете `lock` API,
-во время выполнения фреймворк *не* создаст критическую секцию.
-Еще одно ценное замечание: использование `#[lock_free]` на ресурсах,
-разделяемых задачами, запускаемыми с разными приоритетами
-приведет к ошибке *компиляции* -- не импользование `lock` API может
-привести к гонке данных в этом случае.
-
-``` rust
-{{#include ../../../../examples/lock-free.rs}}
-```
-
-``` console
-$ cargo run --example lock-free
-{{#include ../../../../ci/expected/lock-free.run}}
-``` \ No newline at end of file
diff --git a/book/ru/src/by-example/tasks.md b/book/ru/src/by-example/tasks.md
deleted file mode 100644
index 3c99d00..0000000
--- a/book/ru/src/by-example/tasks.md
+++ /dev/null
@@ -1,116 +0,0 @@
-# Программные задачи
-
-В дополнение к аппаратным задачам, вызываемым в ответ на аппаратные события,
-RTIC также поддерживает *программные* задачи, которые могут порождаться
-приложением из любого контекста выполнения.
-
-Программным задачам можно также назначать приоритет и, под капотом, они
-диспетчеризуются обработчиками прерываний. RTIC требует, чтобы свободные
-прерывания, были указаны в аргументе `dispatchers` модуля `app`, если используются
-программные задачи; часть из этих свободных прерываний будут использованы для
-управления программными задачами. Преимущество программных задач над аппаратными
-в том, что множество задач можно назначить на один обработчик прерывания.
-
-Программные задачи также определяются атрибутом `task`, но аргумент `binds` опускается.
-
-Пример ниже демонстрирует три программные задачи, запускаемых 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}}
-```
-
-## Вместимость
-
-RTIC *не* производит никакого рода аллокаций памяти в куче.
-Память, необходимая для размещения сообщения резервируется статически.
-По-умолчанию фреймворк минимизирует выделение памяти программой таким образом,
-что каждая задача имеет "вместимость" для сообщения равную 1:
-это значит, что не более одного сообщения можно передать задаче перед тем, как
-у нее появится возможность к запуску. Это значение по-умолчанию можно
-изменить для каждой задачи, используя аргумент `capacity`.
-Этот аргумент принимает положительное целое, которое определяет как много
-сообщений буфер сообщений задачи может хранить.
-
-Пример ниже устанавливает вместимость программной задачи `foo` равной 4.
-Если вместимость не установить, второй вызов `spawn.foo` в `UART0` приведет к ошибке (панике).
-
-``` rust
-{{#include ../../../../examples/capacity.rs}}
-```
-
-``` console
-$ cargo run --example capacity
-{{#include ../../../../ci/expected/capacity.run}}
-```
-
-## Обработка ошибок
-
-Интерфейс `spawn` возвращает вариант `Err`, если для размещения сообщения нет места.
-В большинстве сценариев возникающие ошибки обрабатываются одним из двух способов:
-
-- Паника, с помощью `unwrap`, `expect`, и т.п. Этот метод используется, чтобы обнаружить
- ошибку программиста (например bug) выбора вместительности, которая оказалась недостаточна.
- Когда эта паника встречается во время тестирования, выбирается большая вместительность,
- и перекомпиляция программы может решить проблему, но иногда достаточно окунуться глубже
- и провести анализ времени выполнения программы, чтобы выяснить, может ли платформа
- обрабатывать пиковые нагрузки, или процессор необходимо заменить на более быстрый.
-
-- Игнорирование результата. В программах реального времени, как и в обычных, может быть
- нормальным иногда терять данные, или не получать ответ на некоторые события в пиковых ситуациях.
- В таких сценариях может быть допустимо игнорирование ошибки вызова `spawn`.
-
-Следует отметить, что повторная попытка вызова `spawn` обычно неверный подход, поскольку
-такая операция на практике вероятно никогда не завершится успешно.
-Так как у нас есть только переключения контекста на задачи с *более высоким* приоритетом,
-повторение вызова `spawn` на задаче с низким приоритом никогда не позволит планировщику
-вызвать задачу, что значит, что буфер никогда не будет очищен. Такая ситуация отражена в
-следующем наброске:
-
-``` rust
-#[rtic::app(..)]
-mod app {
- #[init(spawn = [foo, bar])]
- fn init(cx: init::Context) {
- cx.spawn.foo().unwrap();
- cx.spawn.bar().unwrap();
- }
-
- #[task(priority = 2, spawn = [bar])]
- fn foo(cx: foo::Context) {
- // ..
-
- // программа зависнет здесь
- while cx.spawn.bar(payload).is_err() {
- // повтор попытки вызова spawn, если произошла ошибка
- }
- }
-
- #[task(priority = 1)]
- fn bar(cx: bar::Context, payload: i32) {
- // ..
- }
-}
-```
diff --git a/book/ru/src/by-example/timer-queue.md b/book/ru/src/by-example/timer-queue.md
deleted file mode 100644
index c8818d7..0000000
--- a/book/ru/src/by-example/timer-queue.md
+++ /dev/null
@@ -1,108 +0,0 @@
-# Очередь таймера
-
-В отличие от интерфейса `spawn`, который немедленно передает программную задачу
-планировщику для немедленного запуска, интерфейс `schedule` можно использовать
-для планирования задачи к запуске через какое-то время в будущем.
-
-Чтобы использовать интерфейс `schedule`, предварительно должен быть определен
-монотонный таймер с помощью аргумента `monotonic` атрибута `#[app]`.
-Этот аргумент принимает путь к типу, реализующему трейт [`Monotonic`].
-Ассоциированный тип, `Instant`, этого трейта представляет метку времени в соответствущих
-единицах измерения и широко используется в интерфейсе `schedule` -- предлагается смоделировать
-этот тип позднее [один из таких есть в стандартной библиотеке][std-instant].
-
-Хотя это не отражено в определении трейта (из-за ограничений системы типов / трейтов),
-разница двух `Instant`ов должна возвращать какой-то тип `Duration` (см. [`core::time::Duration`])
-и этот `Duration` должен реализовывать трейт `TryInto<u32>`.
-Реализация этого трейта должна конвертировать значение `Duration`, которое
-использует какую-то определенную единицу измерения времени, в единицы измерения "тактов системного таймера
-(SYST)". Результат преобразований должен быть 32-битным целым.
-Если результат не соответствует 32-битному целому, тогда операция должна возвращать ошибку любого типа.
-
-[`Monotonic`]: ../../../api/rtic/trait.Monotonic.html
-[std-instant]: https://doc.rust-lang.org/std/time/struct.Instant.html
-[`core::time::Duration`]: https://doc.rust-lang.org/core/time/struct.Duration.html
-
-Для целевых платформ ARMv7+ крейт `rtic` предоставляет реализацию `Monotonic`, основанную на
-встроенном CYCle CouNTer (CYCCNT). Заметьте, что это 32-битный таймер, работающий на
-частоте центрального процессора, и поэтому не подходит для отслеживания интервалов времени в секундах.
-
-Когда планируется задача, (определенный пользователем) `Instant`, в который задача должна быть
-выполнена, должен передаваться в качестве первого аргумента вызова `schedule`.
-
-К тому же, выбранный `monotonic` таймер, необходимо сконфигурировать и инициализировать в
-фазе работы `#[init]`. Заметьте, что *также* касается случая использования `CYCCNT`,
-предоставляемого крейтом `cortex-m-rtic`.
-
-Пример ниже планирует к выполнению две задачи из `init`: `foo` и `bar`. `foo` запланирована
-к запуску через 8 миллионов циклов в будущем. Далее, `bar` запланировано запустить через
-4 миллиона циклов в будущем. Таким образом, `bar` запустится до `foo`, так как и запланировано.
-
-> **DF:YJ**: Примеры, использующие интерфейс `schedule` или абстракцию `Instant`
-> **не будут** правильно работать на эмуляторе QEMU, поскольку счетчик циклов Cortex-M
-> функционально не был реализован в `qemu-system-arm`.
-
-``` rust
-{{#include ../../../../examples/schedule.rs}}
-```
-
-Запусе программы на реальном оборудовании создает следующий вывод в консоли:
-
-``` text
-{{#include ../../../../ci/expected/schedule.run}}
-```
-
-Когда интерфейс `schedule` используется, среда исполнения использует внутри
-обработчик прерываний `SysTick` и периферию системного таймера (`SYST`), поэтому ни
-тот ни другой нельзя использовать в программе. Это гарантируется изменением типа
-`init::Context.core` с `cortex_m::Peripherals` на `rtic::Peripherals`.
-Последняя структура содержит все поля из предыдущей кроме `SYST`.
-
-## Периодические задачи
-
-Программные задачи имеют доступ к моменту времени `Instant`, в который они были запланированы
-на выполнение переменной `scheduled`. Эта информация и интерфейс `schedule` можно использовать,
-чтобы реализовать периодические задачи, как показано ниже.
-
-``` rust
-{{#include ../../../../examples/periodic.rs}}
-```
-
-Это вывод, создаваемый примером. Заметьте, что здесь пристствует небольшой дрейф / колебания
-даже несмотря на то, что `schedule.foo` была вызвана в *конце* `foo`. Использование
-`Instant::now` вместо `scheduled` вызвало бы дрейф / колебания.
-
-``` text
-{{#include ../../../../ci/expected/periodic.run}}
-```
-
-## Базовое время
-
-Для задач, вызываемых из `init` мы имеем точную информацию о их `scheduled` времени.
-Для аппаратных задач такого времени нет, поскольку они асинхронны по природе.
-Для аппаратных задач среда исполнения предоставляет время запуска (`start`), которое отражает
-время, в которое обработчик прерывания будет запущен.
-
-Заметьте, что `start` **не** равно времени прихода события, которое вызывает задачу.
-В зависимости от приоритета задачи и загрузки системы, время `start` может сильно отдалиться от
-времени прихода события.
-
-Какое по вашему мнению будет значение `scheduled` для программных задач, которые вызываются через
-`spawn` вместо планирования? Ответ в том, что вызываемые задачи наследуют
-*базовое* время того контекста, который их вызывает. Базовое время аппаратных задач -
-это их время `start`, базовое время программных задач - их время `scheduled`, а
-базовое время `init` - время старта системы, или нулевое
-(`Instant::zero()`). `idle` на самом деле не имеет базового времени, но задачи вызываемые из нее,
-используют `Instant::now()` в качестве базового.
-
-Пример ниже демонстрирует разные смыслы *базового времени*.
-
-``` rust
-{{#include ../../../../examples/baseline.rs}}
-```
-
-Запуск программы на реальном оборудовании приведет к следующему выводу в консоли:
-
-``` text
-{{#include ../../../../ci/expected/baseline.run}}
-```
diff --git a/book/ru/src/by-example/tips.md b/book/ru/src/by-example/tips.md
deleted file mode 100644
index 7d4fc2f..0000000
--- a/book/ru/src/by-example/tips.md
+++ /dev/null
@@ -1,175 +0,0 @@
-# Советы и хитрости
-
-Полные примеры для RTIC смотрите в репозитарии [rtic-examples][rtic-examples].
-
-[rtic-examples]: https://github.com/rtic-rs/rtic-examples
-
-## Обобщенное программирование (Generics)
-
-Все объекты, предоставляющие ресурысы реализуют трейт `rtic::Mutex`.
-Если ресурс не реализует его, можно обернуть его в новый тип [`rtic::Exclusive`],
-который реализует трейт `Mutex`. С помощью этого нового типа
-можно написать обобщенную функцию, которая работает с обобщенным ресурсом и
-вызывать его из различных задач, чтобы производить однотипные операции над
-похожим множеством ресурсов.
-Вот один такой пример:
-
-[`rtic::Exclusive`]: ../../../api/rtic/struct.Exclusive.html
-
-``` rust
-{{#include ../../../../examples/generics.rs}}
-```
-
-``` console
-$ cargo run --example generics
-{{#include ../../../../ci/expected/generics.run}}
-```
-
-## Условная компиляция
-
-Вы можете использовать условную компиляцию (`#[cfg]`) на ресурсах (полях структуры
-`#[resources] struct Resources`) и задачах (элементах `fn`).
-Эффект использования атрибутов `#[cfg]` в том, что ресурс/ задача
-будут *не* доступны в соответствующих структурах `Context` если условие не выполняется.
-
-В примере ниже выводится сообщение каждый раз, когда вызывается задача `foo`, но только
-если программы скомпилирова с профилем `dev`.
-
-``` rust
-{{#include ../../../../examples/cfg.rs}}
-```
-
-``` console
-$ cargo run --example cfg --release
-
-$ cargo run --example cfg
-{{#include ../../../../ci/expected/cfg.run}}
-```
-
-## Запуск задач из ОЗУ
-
-Главной целью переноса описания программы на RTIC в атрибуты в
-RTIC v0.4.x была возможность взаимодействия с другими атрибутами.
-Напримерe, атрибут `link_section` можно применять к задачам, чтобы разместить
-их в ОЗУ; это может улучшить производительность в некоторых случаях.
-
-> **ВАЖНО**: Обычно атрибуты `link_section`, `export_name` и `no_mangle`
-> очень мощные, но их легко использовать неправильно. Неверное использование
-> любого из этих атрибутов может вызвать неопределенное поведение;
-> Вам следует всегда предпочитать использование безопасных, высокоуровневых
-> атрибутов вместо них, таких как атрибуты `interrupt` и `exception`
-> из `cortex-m-rt`.
->
-> В особых функций, размещаемых в ОЗУ нет безопасной абстракции в `cortex-m-rt`
-> v0.6.5 но создано [RFC] для добавления атрибута `ramfunc` в будущем релизе.
-
-[RFC]: https://github.com/rust-embedded/cortex-m-rt/pull/100
-
-В примере ниже показано как разместить высокоприоритетную задачу `bar` в ОЗУ.
-
-``` rust
-{{#include ../../../../examples/ramfunc.rs}}
-```
-
-Запуск этой программы создаст ожидаемый вывод.
-
-``` console
-$ cargo run --example ramfunc
-{{#include ../../../../ci/expected/ramfunc.run}}
-```
-
-Можно посмотреть на вывод `cargo-nm`, чтобы убедиться, что `bar` расположен в ОЗУ
-(`0x2000_0000`), тогда как `foo` расположен во Flash (`0x0000_0000`).
-
-``` console
-$ cargo nm --example ramfunc --release | grep ' foo::'
-{{#include ../../../../ci/expected/ramfunc.run.grep.foo}}
-```
-
-``` console
-$ cargo nm --example ramfunc --release | grep ' bar::'
-{{#include ../../../../ci/expected/ramfunc.run.grep.bar}}
-```
-
-## Обходной путь для быстрой передачи сообщений
-
-Передача сообщений всегда вызывает копирование от отправителя в
-статическую переменную, а затем из статической переменной получателю.
-Таким образом, при передаче большого буфера, например `[u8; 128]`, передача сообщения
-вызывает два дорогих вызова `memcpy`. Чтобы минимизировать накладные расходы на передачу
-сообщения, можно использовать обходной путь: вместо передачи буфера по значению,
-можно передавать владеющий указатель на буфер.
-
-Можно использовать глобальный аллокатор, чтобы реализовать данный трюк (`alloc::Box`,
-`alloc::Rc`, и т.п.), либо использовать статически аллоцируемый пул памяти, например [`heapless::Pool`].
-
-[`heapless::Pool`]: https://docs.rs/heapless/0.5.0/heapless/pool/index.html
-
-Здесь приведен пример использования `heapless::Pool` для "упаковки" буфера из 128 байт.
-
-``` rust
-{{#include ../../../../examples/pool.rs}}
-```
-
-``` console
-$ cargo run --example pool
-{{#include ../../../../ci/expected/pool.run}}
-```
-
-## Инспектирование раскрываемого кода
-
-`#[rtic::app]` - это процедурный макрос, который создает код.
-Если по какой-то причине вам нужно увидеть код, сгенерированный этим макросом,
-у вас есть два пути:
-
-Вы можете изучить файл `rtic-expansion.rs` внутри папки `target`. Этот файл
-содержит элемент `#[rtic::app]` в раскрытом виде (не всю вашу программу!)
-из *последней сборки* (с помощью `cargo build` или `cargo check`) RTIC программы.
-Раскрытый код не отформатирован по-умолчанию, но вы можете запустить `rustfmt`
-на нем перед тем, как читать.
-
-``` console
-$ cargo build --example foo
-
-$ rustfmt target/rtic-expansion.rs
-
-$ tail target/rtic-expansion.rs
-```
-
-``` rust
-#[doc = r" Implementation details"]
-mod app {
- #[doc = r" Always include the device crate which contains the vector table"]
- use lm3s6965 as _;
- #[no_mangle]
- unsafe extern "C" fn main() -> ! {
- rtic::export::interrupt::disable();
- let mut core: rtic::export::Peripherals = core::mem::transmute(());
- core.SCB.scr.modify(|r| r | 1 << 1);
- rtic::export::interrupt::enable();
- loop {
- rtic::export::wfi()
- }
- }
-}
-```
-
-Или, вы можете использовать подкоманду [`cargo-expand`]. Она раскроет
-*все* макросы, включая атрибут `#[rtic::app]`, и модули в вашем крейте и
-напечатает вывод в консоль.
-
-[`cargo-expand`]: https://crates.io/crates/cargo-expand
-
-``` console
-$ # создаст такой же вывод, как выше
-$ cargo expand --example smallest | tail
-```
-
-## Деструктуризация ресурса
-
-Если задача требует нескольких ресурсов, разбиение структуры ресурсов
-может улучшить читабельность. Вот два примера того, как это можно сделать:
-
-``` rust
-{{#include ../../../../examples/destructure.rs}}
-```
diff --git a/book/ru/src/by-example/types-send-sync.md b/book/ru/src/by-example/types-send-sync.md
deleted file mode 100644
index 755a379..0000000
--- a/book/ru/src/by-example/types-send-sync.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# Типы, Send и Sync
-
-Каждая функция в модуле `app` принимает структуру `Context` в качесте первого параметра.
-Все поля этих структур имеют предсказуемые, неанонимные типы,
-поэтому вы можете написать обычные функции, принимающие их как аргументы.
-
-Справочник по API определяет как эти типы генерируются на основе входных данных.
-Вы можете также сгенерировать документацию к вашему крейту программы (`cargo doc --bin <name>`);
-в документации вы найдете структуры `Context` (например `init::Context` и
-`idle::Context`).
-
-Пример ниже показывает различные типы, сгенерированные атрибутом `app`.
-
-``` rust
-{{#include ../../../../examples/types.rs}}
-```
-
-## `Send`
-
-[`Send`] - это маркерный трейт для "типов, которые можно передавать через границы
-потоков", как это определено в `core`. В контексте RTIC трейт `Send` необходим
-только там, где возможна передача значения между задачами, запускаемыми на
-*разных* приоритетах. Это возникает в нескольких случаях: при передаче сообщений,
-в разделяемых `static mut` ресурсах и при инициализации поздних ресурсов.
-
-[`Send`]: https://doc.rust-lang.org/core/marker/trait.Send.html
-
-Атрибут `app` проверит, что `Send` реализован, где необходимо, поэтому вам не
-стоит волноваться об этом. В настоящий момент все передаваемые типы в RTIC должны быть `Send`, но
-это ограничение возможно будет ослаблено в будущем.
-
-## `Sync`
-
-Аналогично, [`Sync`] - маркерный трейт для "типов, на которые можно безопасно разделять между потоками",
-как это определено в `core`. В контексте RTIC типаж `Sync` необходим только там,
-где возможно для двух или более задач, запускаемых на разных приоритетах получить разделяемую ссылку (`&-`) на
-ресурс. Это возникает только (`&-`) ресурсах с разделяемым доступом.
-
-[`Sync`]: https://doc.rust-lang.org/core/marker/trait.Sync.html
-
-Атрибут `app` проверит, что `Sync` реализован, где необходимо, но важно знать,
-где ограничение `Sync` не требуется: в (`&-`) ресурсах с разделяемым доступом, за которые
-соперничают задачи с *одинаковым* приоритетом.
-
-В примере ниже показано, где можно использовать типы, не реализующие `Sync`.
-
-``` rust
-{{#include ../../../../examples/not-sync.rs}}
-```