aboutsummaryrefslogtreecommitdiff
path: root/book/ru/src/migration
diff options
context:
space:
mode:
Diffstat (limited to 'book/ru/src/migration')
-rw-r--r--book/ru/src/migration/migration_rtic.md48
-rw-r--r--book/ru/src/migration/migration_v4.md230
-rw-r--r--book/ru/src/migration/migration_v5.md208
3 files changed, 486 insertions, 0 deletions
diff --git a/book/ru/src/migration/migration_rtic.md b/book/ru/src/migration/migration_rtic.md
new file mode 100644
index 0000000..28813fe
--- /dev/null
+++ b/book/ru/src/migration/migration_rtic.md
@@ -0,0 +1,48 @@
+# Миграция с RTFM на RTIC
+
+В этом разделе описано, как обновить приложение, написанное на RTFM v0.5.x на RTIC той же версии.
+Это необходимо из-за переименования фреймворка в соответствии с [RFC #33].
+
+**Примечание:** Между RTFM v0.5.3 и RTIC v0.5.3 нет разниц в коде, это исключительно изменение имен.
+
+[RFC #33]: https://github.com/rtic-rs/rfcs/pull/33
+
+## `Cargo.toml`
+
+Во-первых, зависимость `cortex-m-rtfm` должна быть изменена на `cortex-m-rtic`.
+
+``` toml
+[dependencies]
+# измените это
+cortex-m-rtfm = "0.5.3"
+
+# на это
+cortex-m-rtic = "0.5.3"
+```
+
+## Изменения в коде
+
+Единственное изменение в коде, которое нужно сделать - поменять все ссылки на `rtfm`,
+чтобы они указывали на `rtic`:
+
+``` rust
+//
+// Измените это
+//
+
+#[rtfm::app(/* .. */, monotonic = rtfm::cyccnt::CYCCNT)]
+const APP: () = {
+ // ...
+
+};
+
+//
+// На это
+//
+
+#[rtic::app(/* .. */, monotonic = rtic::cyccnt::CYCCNT)]
+const APP: () = {
+ // ...
+
+};
+```
diff --git a/book/ru/src/migration/migration_v4.md b/book/ru/src/migration/migration_v4.md
new file mode 100644
index 0000000..0ff8039
--- /dev/null
+++ b/book/ru/src/migration/migration_v4.md
@@ -0,0 +1,230 @@
+# Миграция с v0.4.x на v0.5.0
+
+Этот раздел описывает как обновить программы, написанные на RTIC v0.4.x
+на версию v0.5.0 фреймворка.
+
+## `Cargo.toml`
+
+Во-первых, нужно обновить версию зависимости `cortex-m-rtic` до
+`"0.5.0"`. Опцию `timer-queue` нужно удалить.
+
+``` toml
+[dependencies.cortex-m-rtic]
+# изменить это
+version = "0.4.3"
+
+# на это
+version = "0.5.0"
+
+# и удалить Cargo feature
+features = ["timer-queue"]
+# ^^^^^^^^^^^^^
+```
+
+## Аргумент `Context`
+
+Все функции внутри элемента `#[rtic::app]` должны принимать первым аргументом
+структуру `Context`. Этот тип `Context` будет содержать переменные, которые были магически
+инъецированы в область видимости функции версией v0.4.x фреймворка:
+`resources`, `spawn`, `schedule` -- эти переменные станут полями структуры `Context`.
+Каждая функция элемента `#[rtic::app]` получит отдельный тип `Context`.
+
+``` rust
+#[rtic::app(/* .. */)]
+const APP: () = {
+ // change this
+ #[task(resources = [x], spawn = [a], schedule = [b])]
+ fn foo() {
+ resources.x.lock(|x| /* .. */);
+ spawn.a(message);
+ schedule.b(baseline);
+ }
+
+ // into this
+ #[task(resources = [x], spawn = [a], schedule = [b])]
+ fn foo(mut cx: foo::Context) {
+ // ^^^^^^^^^^^^^^^^^^^^
+
+ cx.resources.x.lock(|x| /* .. */);
+ // ^^^
+
+ cx.spawn.a(message);
+ // ^^^
+
+ cx.schedule.b(message, baseline);
+ // ^^^
+ }
+
+ // change this
+ #[init]
+ fn init() {
+ // ..
+ }
+
+ // into this
+ #[init]
+ fn init(cx: init::Context) {
+ // ^^^^^^^^^^^^^^^^^
+ // ..
+ }
+
+ // ..
+};
+```
+
+## Ресурсы
+
+Синтаксис, используемый, для определения ресурсов был изменен с переменных `static mut`
+на структуру `Resources`.
+
+``` rust
+#[rtic::app(/* .. */)]
+const APP: () = {
+ // измените это
+ static mut X: u32 = 0;
+ static mut Y: u32 = (); // поздний ресурс
+
+ // на это
+ struct Resources {
+ #[init(0)] // <- начальное значение
+ X: u32, // ПРИМЕЧАНИЕ: мы предлагаем изменить стиль именования на `snake_case`
+
+ Y: u32, // поздний ресурс
+ }
+
+ // ..
+};
+```
+
+## Периферия устройства
+
+Если ваша программа получала доступ к периферии в `#[init]` через
+переменну `device`, вам нужно будет добавить `peripherals = true` в атрибут
+`#[rtic::app]`, чтобы и дальше получать доступ к периферии через поле `device` структуры `init::Context`.
+
+Измените это:
+
+``` rust
+#[rtic::app(/* .. */)]
+const APP: () = {
+ #[init]
+ fn init() {
+ device.SOME_PERIPHERAL.write(something);
+ }
+
+ // ..
+};
+```
+
+На это:
+
+``` rust
+#[rtic::app(/* .. */, peripherals = true)]
+// ^^^^^^^^^^^^^^^^^^
+const APP: () = {
+ #[init]
+ fn init(cx: init::Context) {
+ // ^^^^^^^^^^^^^^^^^
+ cx.device.SOME_PERIPHERAL.write(something);
+ // ^^^
+ }
+
+ // ..
+};
+```
+
+## `#[interrupt]` и `#[exception]`
+
+Атрибуты `#[interrupt]` и `#[exception]` были удалены. Чтобы определять аппаратные задачи в v0.5.x
+используте атрибут `#[task]` с аргументом `binds`.
+
+Измените это:
+
+``` rust
+#[rtic::app(/* .. */)]
+const APP: () = {
+ // аппаратные задачи
+ #[exception]
+ fn SVCall() { /* .. */ }
+
+ #[interrupt]
+ fn UART0() { /* .. */ }
+
+ // программные задачи
+ #[task]
+ fn foo() { /* .. */ }
+
+ // ..
+};
+```
+
+На это:
+
+``` rust
+#[rtic::app(/* .. */)]
+const APP: () = {
+ #[task(binds = SVCall)]
+ // ^^^^^^^^^^^^^^
+ fn svcall(cx: svcall::Context) { /* .. */ }
+ // ^^^^^^ мы предлагаем использовать `snake_case` имя здесь
+
+ #[task(binds = UART0)]
+ // ^^^^^^^^^^^^^
+ fn uart0(cx: uart0::Context) { /* .. */ }
+
+ #[task]
+ fn foo(cx: foo::Context) { /* .. */ }
+
+ // ..
+};
+```
+
+## `schedule`
+
+Интерфейс `schedule` больше не требует cargo опции `timer-queue`, которая была удалена.
+Чтобы использовать интерфес `schedule`, нужно сначала определить
+монотонный тамер, который будет использоваьт среды выполнения, с помощью аргумента `monotonic`
+атрибута `#[rtic::app]`. Чтобы продолжить использовать счетчик циклов
+(CYCCNT) в качестве монотонного таймера, как было в версии v0.4.x, добавьте
+аргумент `monotonic = rtic::cyccnt::CYCCNT` в атрибут `#[rtic::app]`.
+
+Также были добавлены типы `Duration` и `Instant`, а трейт `U32Ext` был перемещен в модуль `rtic::cyccnt`.
+Этот модуль доступен только на устройствах ARMv7-M+.
+Удаление `timer-queue` также возвращает периферию `DWT` в структуру периферии ядра,
+включить ее в работу можно внутри `init`.
+
+Измените это:
+
+``` rust
+use rtic::{Duration, Instant, U32Ext};
+
+#[rtic::app(/* .. */)]
+const APP: () = {
+ #[task(schedule = [b])]
+ fn a() {
+ // ..
+ }
+};
+```
+
+На это:
+
+``` rust
+use rtic::cyccnt::{Duration, Instant, U32Ext};
+// ^^^^^^^^
+
+#[rtic::app(/* .. */, monotonic = rtic::cyccnt::CYCCNT)]
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+const APP: () = {
+ #[init]
+ fn init(cx: init::Context) {
+ cx.core.DWT.enable_cycle_counter();
+ // опционально, настройка запуска DWT без подключенного отладчика
+ cx.core.DCB.enable_trace();
+ }
+ #[task(schedule = [b])]
+ fn a(cx: a::Context) {
+ // ..
+ }
+};
+```
diff --git a/book/ru/src/migration/migration_v5.md b/book/ru/src/migration/migration_v5.md
new file mode 100644
index 0000000..04aedc5
--- /dev/null
+++ b/book/ru/src/migration/migration_v5.md
@@ -0,0 +1,208 @@
+# Миграция с v0.5.x на v0.6.0
+
+Этот раздел описывает как обновиться с версии v0.5.x на v0.6.0 фреймворка RTIC.
+
+## `Cargo.toml` - увеличьте версию
+
+Измените версию `cortex-m-rtic` на `"0.6.0"`.
+
+## `mod` вместо `const`
+
+С поддержкой атрибутов над модулями трюк с `const APP` теперь не нужен.
+
+Измените
+
+``` rust
+#[rtic::app(/* .. */)]
+const APP: () = {
+ [код здесь]
+};
+```
+
+на
+
+``` rust
+#[rtic::app(/* .. */)]
+mod app {
+ [код здесь]
+}
+```
+
+Так как теперь используется обычный модуль Rust, это значит, что можно использовать
+обычный пользовательский код в этом модуле.
+Также жто значит, что `use`-выражения для ресурсов (и т.п.) могут понадобиться.
+
+## Перенос диспетчеров из `extern "C"` в аргументы app.
+
+Измените
+
+``` rust
+#[rtic::app(/* .. */)]
+const APP: () = {
+ [код здесь]
+
+ // RTIC требует, чтобы неиспользуемые прерывания были задекларированы в блоке extern, когда
+ // используются программные задачи; эти свободные прерывания будут использованы для управления
+ // программными задачами.
+ extern "C" {
+ fn SSI0();
+ fn QEI0();
+ }
+};
+```
+
+на
+
+``` rust
+#[rtic::app(/* .. */, dispatchers = [SSI0, QEI0])]
+mod app {
+ [код здесь]
+}
+```
+
+Это работает и для ОЗУ-функций, см. examples/ramfunc.rs
+
+
+## Init всегда возвращает поздние ресурсы
+
+С целью сделать API более симметричным задача #[init] всегда возвращает поздние ресурсы.
+
+С этого:
+
+``` rust
+#[rtic::app(device = lm3s6965)]
+mod app {
+ #[init]
+ fn init(_: init::Context) {
+ rtic::pend(Interrupt::UART0);
+ }
+
+ // [еще код]
+}
+```
+
+на это:
+
+``` rust
+#[rtic::app(device = lm3s6965)]
+mod app {
+ #[init]
+ fn init(_: init::Context) -> init::LateResources {
+ rtic::pend(Interrupt::UART0);
+
+ init::LateResources {}
+ }
+
+ // [еще код]
+}
+```
+
+## Структура Resources - `#[resources]`
+
+Ранее ресурсы RTIC должны были располагаться в структуре с именем "Resources":
+
+``` rust
+struct Resources {
+ // Ресурсы определены здесь
+}
+```
+
+В RTIC v0.6.0 структура ресурсов аннотируется также, как и
+`#[task]`, `#[init]`, `#[idle]`: атрибутом `#[resources]`
+
+``` rust
+#[resources]
+struct Resources {
+ // Ресурсы определены здесь
+}
+```
+
+На самом деле, имя структуры предоставлено на усмотрение разработчика:
+
+``` rust
+#[resources]
+struct Whateveryouwant {
+ // Ресурсы определены здесь
+}
+```
+
+будет работать так же хороршо.
+
+## Вызов/планирование откуда угодно
+
+С этой новой возвожностью, старый код, такой как:
+
+
+``` rust
+#[task(spawn = [bar])]
+fn foo(cx: foo::Context) {
+ cx.spawn.bar().unwrap();
+}
+
+#[task(schedule = [bar])]
+fn bar(cx: bar::Context) {
+ cx.schedule.foo(/* ... */).unwrap();
+}
+```
+
+Теперь будет выглядеть так:
+
+``` rust
+#[task]
+fn foo(_c: foo::Context) {
+ bar::spawn().unwrap();
+}
+
+#[task]
+fn bar(_c: bar::Context) {
+ foo::schedule(/* ... */).unwrap();
+}
+```
+
+Заметьте, что атрибуты `spawn` и `schedule` больше не нужны.
+
+## Симметричные блокировки
+
+Теперь RTIC использует симметричные блокировки, это значит, что метод `lock` нужно использовать для
+всех доступов к ресурсам. Поскольку высокоприоритетные задачи имеют эксклюзивный доступ к ресурсу,
+в старом коде можно было следующее:
+
+``` rust
+#[task(priority = 2, resources = [r])]
+fn foo(cx: foo::Context) {
+ cx.resources.r = /* ... */;
+}
+
+#[task(resources = [r])]
+fn bar(cx: bar::Context) {
+ cx.resources.r.lock(|r| r = /* ... */);
+}
+```
+
+С симметричными блокировками нужно вызывать `lock` для обоих задач:
+
+``` rust
+#[task(priority = 2, resources = [r])]
+fn foo(cx: foo::Context) {
+ cx.resources.r.lock(|r| r = /* ... */);
+}
+
+#[task(resources = [r])]
+fn bar(cx: bar::Context) {
+ cx.resources.r.lock(|r| r = /* ... */);
+}
+```
+
+Заметьте, что скорость работы не изменяется благодаря оптимизациям LLVM, которые убирают ненужные блокировки.
+
+---
+
+## Дополнительно
+
+### Внешние задачи
+
+Как программные, так и аппаратные задачи теперь можно определять вне модуля `mod app`.
+Ранее это было возможно только путем реализации обертки, вызывающей реализацию задачи.
+
+Смотреть примеры `examples/extern_binds.rs` и `examples/extern_spawn.rs`.
+