1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
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`.
|