# Миграция с 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`.