diff options
Diffstat (limited to 'book/ru/src/migration')
| -rw-r--r-- | book/ru/src/migration/migration_v5.md | 289 |
1 files changed, 223 insertions, 66 deletions
diff --git a/book/ru/src/migration/migration_v5.md b/book/ru/src/migration/migration_v5.md index 04aedc5..870c20f 100644 --- a/book/ru/src/migration/migration_v5.md +++ b/book/ru/src/migration/migration_v5.md @@ -30,7 +30,46 @@ mod app { Так как теперь используется обычный модуль Rust, это значит, что можно использовать обычный пользовательский код в этом модуле. -Также жто значит, что `use`-выражения для ресурсов (и т.п.) могут понадобиться. +Также это значит, что `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. @@ -63,137 +102,255 @@ mod app { Это работает и для ОЗУ-функций, см. examples/ramfunc.rs -## Init всегда возвращает поздние ресурсы +## Структуры ресурсов - `#[shared]`, `#[local]` -С целью сделать API более симметричным задача #[init] всегда возвращает поздние ресурсы. +Ранее ресурсы RTIC должны были размещаться в структуре с именем "Resources": -С этого: +``` rust +struct Resources { + // Ресурсы определяются здесь +} +``` + +Начиная с RTIC v0.6.0 структуры ресурсов аннотируются подобно +`#[task]`, `#[init]`, `#[idle]`: аттрибутами `#[shared]` и `#[local]` ``` rust -#[rtic::app(device = lm3s6965)] -mod app { - #[init] - fn init(_: init::Context) { - rtic::pend(Interrupt::UART0); - } +#[shared] +struct MySharedResources { + // Разделяемые задачами ресурсы определены здесь +} - // [еще код] +#[local] +struct MyLocalResources { + // Ресурсы, определенные здесь нельзя передавать между задачами; каждый из них локальный для единственной задачи } ``` -на это: +Эти структуры разработчик может называть по своему желанию. + +## `shared` и `local` аргументы в `#[task]`'ах + +В v0.6.0 ресурсы разделены на `shared` ресурсы и `local` ресурсы. +`#[task]`, `#[init]` и `#[idle]` больше не имеют аргумента `resources`; +они должны использовать аргументы `shared` и `local`. + +В v0.5.x: ``` rust -#[rtic::app(device = lm3s6965)] -mod app { - #[init] - fn init(_: init::Context) -> init::LateResources { - rtic::pend(Interrupt::UART0); +struct Resources { + local_to_b: i64, + shared_by_a_and_b: i64, +} - init::LateResources {} - } +#[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) {} +``` + +В v0.6.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) {} ``` -## Структура Resources - `#[resources]` +## Симметричные блокировки -Ранее ресурсы RTIC должны были располагаться в структуре с именем "Resources": +Теперь RTIC использует симметричные блокировки, это значит, что метод `lock` нужно использовать для +всех доступов к `shared` ресурсам. Поскольку высокоприоритетные задачи имеют эксклюзивный доступ к ресурсу, +в старом коде можно было следующее: ``` rust -struct Resources { - // Ресурсы определены здесь +#[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 = /* ... */); } ``` -В RTIC v0.6.0 структура ресурсов аннотируется также, как и -`#[task]`, `#[init]`, `#[idle]`: атрибутом `#[resources]` +С симметричными блокировками нужно вызывать `lock` для обоих задач: ``` rust -#[resources] -struct Resources { - // Ресурсы определены здесь +#[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 -#[resources] -struct Whateveryouwant { - // Ресурсы определены здесь +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; } ``` -будет работать так же хороршо. +v0.6 код: -## Вызов/планирование откуда угодно +``` 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 -#[task(spawn = [bar])] -fn foo(cx: foo::Context) { - cx.spawn.bar().unwrap(); +#[init] +fn init(_: init::Context) { + static mut BUFFER: [u8; 1024] = [0; 1024]; + let buffer: &'static mut [u8; 1024] = BUFFER; } +``` -#[task(schedule = [bar])] -fn bar(cx: bar::Context) { - cx.schedule.foo(/* ... */).unwrap(); +v0.6.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 -#[task] -fn foo(_c: foo::Context) { - bar::spawn().unwrap(); +#[rtic::app(device = lm3s6965)] +mod app { + #[init] + fn init(_: init::Context) { + rtic::pend(Interrupt::UART0); + } + + // [еще код] } +``` -#[task] -fn bar(_c: bar::Context) { - foo::schedule(/* ... */).unwrap(); +на это: + + +``` 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] } ``` -Заметьте, что атрибуты `spawn` и `schedule` больше не нужны. +## Вызов/планирование откуда угодно -## Симметричные блокировки +С этой новой возвожностью, старый код, такой как: -Теперь RTIC использует симметричные блокировки, это значит, что метод `lock` нужно использовать для -всех доступов к ресурсам. Поскольку высокоприоритетные задачи имеют эксклюзивный доступ к ресурсу, -в старом коде можно было следующее: ``` rust -#[task(priority = 2, resources = [r])] +#[task(spawn = [bar])] fn foo(cx: foo::Context) { - cx.resources.r = /* ... */; + cx.spawn.bar().unwrap(); } -#[task(resources = [r])] +#[task(schedule = [bar])] fn bar(cx: bar::Context) { - cx.resources.r.lock(|r| r = /* ... */); + cx.schedule.foo(/* ... */).unwrap(); } ``` -С симметричными блокировками нужно вызывать `lock` для обоих задач: +Теперь будет выглядеть так: ``` rust -#[task(priority = 2, resources = [r])] -fn foo(cx: foo::Context) { - cx.resources.r.lock(|r| r = /* ... */); +#[task] +fn foo(_c: foo::Context) { + bar::spawn().unwrap(); } -#[task(resources = [r])] -fn bar(cx: bar::Context) { - cx.resources.r.lock(|r| r = /* ... */); +#[task] +fn bar(_c: bar::Context) { + foo::schedule(/* ... */).unwrap(); } ``` -Заметьте, что скорость работы не изменяется благодаря оптимизациям LLVM, которые убирают ненужные блокировки. +Заметьте, что атрибуты `spawn` и `schedule` больше не нужны. --- |
