diff options
Diffstat (limited to 'book/ru/src/migration')
| -rw-r--r-- | book/ru/src/migration/migration_rtic.md | 48 | ||||
| -rw-r--r-- | book/ru/src/migration/migration_v4.md | 230 | ||||
| -rw-r--r-- | book/ru/src/migration/migration_v5.md | 365 |
3 files changed, 0 insertions, 643 deletions
diff --git a/book/ru/src/migration/migration_rtic.md b/book/ru/src/migration/migration_rtic.md deleted file mode 100644 index 28813fe..0000000 --- a/book/ru/src/migration/migration_rtic.md +++ /dev/null @@ -1,48 +0,0 @@ -# Миграция с 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 deleted file mode 100644 index 0ff8039..0000000 --- a/book/ru/src/migration/migration_v4.md +++ /dev/null @@ -1,230 +0,0 @@ -# Миграция с 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 deleted file mode 100644 index 84bd9fb..0000000 --- a/book/ru/src/migration/migration_v5.md +++ /dev/null @@ -1,365 +0,0 @@ -# Миграция с v0.5.x на v1.0.0 - -Этот раздел описывает как обновиться с версии v0.5.x на v1.0.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`-выражения для ресурсов, используемые -в пользовательском коде должны быть перемещены внутрь `mod app`, -либо на них можно сослаться с помощью `super`. Например, измените: - -```rust -use some_crate::some_func; - -#[rtic::app(/* .. */)] -const APP: () = { - fn func() { - some_crate::some_func(); - } -}; -``` - -на - -```rust -#[rtic::app(/* .. */)] -mod app { - use some_crate::some_func; - - fn func() { - some_crate::some_func(); - } -} -``` - -или - -```rust -use some_crate::some_func; - -#[rtic::app(/* .. */)] -mod app { - fn func() { - super::some_crate::some_func(); - } -} -``` - -## Перенос диспетчеров из `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 - - -## Структуры ресурсов - `#[shared]`, `#[local]` - -Ранее ресурсы RTIC должны были размещаться в структуре с именем "Resources": - -``` rust -struct Resources { - // Ресурсы определяются здесь -} -``` - -Начиная с RTIC v1.0.0 структуры ресурсов аннотируются подобно -`#[task]`, `#[init]`, `#[idle]`: аттрибутами `#[shared]` и `#[local]` - -``` rust -#[shared] -struct MySharedResources { - // Разделяемые задачами ресурсы определены здесь -} - -#[local] -struct MyLocalResources { - // Ресурсы, определенные здесь нельзя передавать между задачами; каждый из них локальный для единственной задачи -} -``` - -Эти структуры разработчик может называть по своему желанию. - -## `shared` и `local` аргументы в `#[task]`'ах - -В v1.0.0 ресурсы разделены на `shared` ресурсы и `local` ресурсы. -`#[task]`, `#[init]` и `#[idle]` больше не имеют аргумента `resources`; -они должны использовать аргументы `shared` и `local`. - -В v0.5.x: - -``` rust -struct Resources { - local_to_b: i64, - shared_by_a_and_b: i64, -} - -#[task(resources = [shared_by_a_and_b])] -fn a(_: a::Context) {} - -#[task(resources = [shared_by_a_and_b, local_to_b])] -fn b(_: b::Context) {} -``` - -В v1.0.0: - -``` rust -#[shared] -struct Shared { - shared_by_a_and_b: i64, -} - -#[local] -struct Local { - local_to_b: i64, -} - -#[task(shared = [shared_by_a_and_b])] -fn a(_: a::Context) {} - -#[task(shared = [shared_by_a_and_b], local = [local_to_b])] -fn b(_: b::Context) {} -``` - -## Симметричные блокировки - -Теперь RTIC использует симметричные блокировки, это значит, что метод `lock` нужно использовать для -всех доступов к `shared` ресурсам. Поскольку высокоприоритетные задачи имеют эксклюзивный доступ к ресурсу, -в старом коде можно было следующее: - -``` 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, shared = [r])] -fn foo(cx: foo::Context) { - cx.shared.r.lock(|r| r = /* ... */); -} - -#[task(shared = [r])] -fn bar(cx: bar::Context) { - cx.shared.r.lock(|r| r = /* ... */); -} -``` - -Заметьте, что скорость работы не изменяется благодаря оптимизациям LLVM, которые убирают ненужные блокировки. - -## Неблокирующий доступ к ресурсам - -В RTIC 0.5 к ресурсам разделяемым задачами, запускаемыми с одинаковым -приоритетом, можно получить доступ *без* `lock` API. -Это все еще возможно в 0.6: ресурс `#[shared]` должен быть аннотирован -аттрибутом поля `#[lock_free]`. - -v0.5 код: - -``` rust -struct Resources { - counter: u64, -} - -#[task(resources = [counter])] -fn a(cx: a::Context) { - *cx.resources.counter += 1; -} - -#[task(resources = [counter])] -fn b(cx: b::Context) { - *cx.resources.counter += 1; -} -``` - -v1.0 код: - -``` rust -#[shared] -struct Shared { - #[lock_free] - counter: u64, -} - -#[task(shared = [counter])] -fn a(cx: a::Context) { - *cx.shared.counter += 1; -} - -#[task(shared = [counter])] -fn b(cx: b::Context) { - *cx.shared.counter += 1; -} -``` - -## нет преобразования `static mut` - -`static mut` переменные больше не преобразуются в безопасные `&'static mut` ссылки. -Вместо этого синтаксиса используйте аргумент `local` в `#[init]`. - -v0.5.x code: - -``` rust -#[init] -fn init(_: init::Context) { - static mut BUFFER: [u8; 1024] = [0; 1024]; - let buffer: &'static mut [u8; 1024] = BUFFER; -} -``` - -v1.0.0 code: - -``` rust -#[init(local = [ - buffer: [u8; 1024] = [0; 1024] -// type ^^^^^^^^^^^^ ^^^^^^^^^ initial value -])] -fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - let buffer: &'static mut [u8; 1024] = cx.local.buffer; - - (Shared {}, Local {}, init::Monotonics()) -} -``` - -## 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 { - #[shared] - struct MySharedResources {} - - #[local] - struct MyLocalResources {} - - #[init] - fn init(_: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { - rtic::pend(Interrupt::UART0); - - (MySharedResources, MyLocalResources, init::Monotonics()) - } - - // [more code] -} -``` - -## Вызов/планирование откуда угодно - -С этой новой возвожностью, старый код, такой как: - - -``` 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` больше не нужны. - ---- - -## Дополнительно - -### Внешние задачи - -Как программные, так и аппаратные задачи теперь можно определять вне модуля `mod app`. -Ранее это было возможно только путем реализации обертки, вызывающей реализацию задачи. - -Смотреть примеры `examples/extern_binds.rs` и `examples/extern_spawn.rs`. - |
