7
7
Фреймворк дает пользователю полный контроль за тем, какой контекст может
8
8
получить доступ к какому ресурсу.
9
9
10
- Все ресурсы определены в одной структуре внутри модуля ` #[app] ` .
11
- Каждое поле структуры соответствует отдельному ресурсу.
12
- ` struct ` -ура должна быть аннотирована следующим атрибутом: ` #[resources] ` .
13
-
14
- Ресурсам могут быть опционально даны начальные значения с помощью атрибута ` #[init] ` .
15
- Ресурсы, которым не передано начально значение, называются
16
- * поздними* ресурсами, более детально они описаны в одном из разделов на этой странице.
10
+ Все ресурсы определены в * двух* структурах внутри модуля ` #[app] ` .
11
+ Каждое поле этих структур соответствует отдельному ресурсу.
12
+ Одна ` struct ` -ура должна быть аннотирована атрибутом ` #[local] ` .
13
+ Другая ` struct ` -ура должна быть аннотирована атрибутом ` #[shared] ` .
14
+ Разница между этими двумя множествами ресурсов будет описана познее.
17
15
18
16
Каждый контекс (задача-обработчик, ` init ` или ` idle ` ) должен указать ресурсы, к которым
19
17
он намерен обращаться, в соответсятвующем ему атрибуте с метаданными, используя
20
- аргумент ` resources ` . Этот аргумент принимает список имен ресурсов в качестве значения.
21
- Перечисленные ресурсы становятся доступны в контексте через поле ` resources ` структуры ` Context ` .
18
+ либо аргумент ` local ` , либо ` shared ` . Этот аргумент принимает список имен ресурсов в качестве значения.
19
+ Перечисленные ресурсы становятся доступны в контексте через поля ` local ` и ` shared ` структуры ` Context ` .
20
+
21
+ Во время выполнения при выходе из функции ` #[init] ` все ресурсы инициализированы.
22
+ Функция ` #[init] ` должна возвращать начальные значения для всех ресурсов;
23
+ отсюда следует, что тип возвращаемого ею значения включает типы
24
+ структур ` #[shared] ` и ` #[local] ` .
25
+ Поскольку ресурсы инициализированы в ходе функции ` #[init] ` , к ним нельзя
26
+ получить доступ внетри функции ` #[init] ` .
22
27
23
- Пример программы, показанной ниже содержит два обработчика прерывания, которые разделяют
24
- доступ к ресурсу под названием ` shared ` .
28
+ Пример программы, показанной ниже содержит два обработчика прерывания.
29
+ Каждый обработчик имеет доступ к его собственному ` #[local] ` ресурсу .
25
30
26
31
``` rust
27
32
{{#include .. / .. / .. / .. / examples / resource . rs}}
@@ -32,15 +37,17 @@ $ cargo run --example resource
32
37
{{#include ../../../../ci/expected/resource.run}}
33
38
```
34
39
35
- Заметьте, что к ресурсу ` shared ` нельзя получить доступ из ` idle ` . Попытка сделать это
36
- приведет к ошибке компиляции.
40
+ К ресурсу ` #[local] ` нельзя получить доступ извне задачи к которой он
41
+ привязан атрибутом ` #[task] ` .
42
+ Попытка обращения к одному и тому же ресурсу ` #[local] ` из более чем одной
43
+ задачи - ошибка компиляции.
37
44
38
45
## ` lock `
39
46
40
- Критические секции необходимы для разделения изменяемых данных таким образом,
47
+ Критические секции необходимы для доступа к ресурсам ` #[shared] ` таким образом,
41
48
чтобы избежать гонок данных.
42
49
43
- Поле ` resources ` , передаваемого ` Context ` реализует трейт [ ` Mutex ` ] для каждого разделяемого
50
+ Поле ` shared ` , передаваемого ` Context ` реализует трейт [ ` Mutex ` ] для каждого разделяемого
44
51
ресурса, доступного задаче.
45
52
46
53
Единственный метод этого трейта, [ ` lock ` ] , запускает свой аргумент-замыкание в критической секции.
@@ -81,33 +88,7 @@ $ cargo run --example lock
81
88
{{#include .. / .. / .. / .. / examples / multilock . rs}}
82
89
```
83
90
84
- ## Поздние ресурсы
85
-
86
- Поздние ресурсы - такие ресурсы, которым не передано начальное значение во время компиляции
87
- с помощью атрибута ` #[init] ` , но которые вместо этого инициализируются во время выполнения
88
- с помощью значений из структуры ` init::LateResources ` , возвращаемой функцией ` init ` .
89
-
90
- Поздние ресурсы полезны, например, для * move* (передача владения) периферии,
91
- инициализированной в ` init ` , в задачи.
92
-
93
- Пример ниже использует поздние ресурсы, чтобы установить неблокируемый односторонний канал
94
- между обработчиком прерывания ` UART0 ` и задачей ` idle ` . Для канала использована очередь типа
95
- один производитель-один потребитель [ ` Queue ` ] . Структура очереди разделяется на потребителя
96
- и производителя в ` init ` , а затем каждая из частей располагается в отдельном ресурсу;
97
- ` UART0 ` владеет ресурсом производителя, а ` idle ` владеет ресурсом потребителя.
98
-
99
- [ `Queue` ] : ../../../api/heapless/spsc/struct.Queue.html
100
-
101
- ``` rust
102
- {{#include .. / .. / .. / .. / examples / late . rs}}
103
- ```
104
-
105
- ``` console
106
- $ cargo run --example late
107
- {{#include ../../../../ci/expected/late.run}}
108
- ```
109
-
110
- ## Только разделяемый доступ
91
+ ## Только разделяемый (` &- ` ) доступ
111
92
112
93
По-умолчанию фреймворк предполагает, что все задачи требуют эксклюзивный доступ (` &mut- ` ) к ресурсам,
113
94
но возможно указать, что задаче достаточен разделяемый доступ (` &- ` ) к ресурсы с помощью синтакисиса
@@ -139,11 +120,21 @@ $ cargo run --example only-shared-access
139
120
140
121
## Неблокируемый доступ к изменяемым ресурсам
141
122
142
- Есть две других возможности доступа к ресурсам
123
+ Критическая секция * не* требуется для доступа к ресурсу ` #[shared] ` ,
124
+ к которому обращаются только из задач с * одинаковым* приоритетом.
125
+ В этом случае вы можете избежать ` lock ` API, добавив атрибут поля ` #[lock_free] ` при объявдении ресурса (смотреть пример ниже).
126
+ Заметьте, что это лишь для удобства: даже если вы используете ` lock ` API,
127
+ во время выполнения фреймворк * не* создаст критическую секцию.
128
+ Еще одно ценное замечание: использование ` #[lock_free] ` на ресурсах,
129
+ разделяемых задачами, запускаемыми с разными приоритетами
130
+ приведет к ошибке * компиляции* -- не импользование ` lock ` API может
131
+ привести к гонке данных в этом случае.
143
132
144
- * ` #[lock_free] ` : могут быть несколько задач с одинаковым приоритетом,
145
- получающие доступ к ресурсу без критических секций. Так как задачи с
146
- одинаковым приоритетом никогда не могут вытеснить друг друга, это безопасно.
147
- * ` #[task_local] ` : в этом случае должна быть только одна задача, использующая
148
- этот ресурс, так же как локальный ` static mut ` ресурс задачи, но (опционально) устанавливаемая с в init.
133
+ ``` rust
134
+ {{#include .. / .. / .. / .. / examples / lock - free . rs}}
135
+ ```
149
136
137
+ ``` console
138
+ $ cargo run --example lock-free
139
+ {{#include ../../../../ci/expected/lock-free.run}}
140
+ ```
0 commit comments