aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-12-08 20:49:45 +0100
committerGitHub <[email protected]>2023-12-08 20:49:45 +0100
commit4e7b855b2d2e934c4af9e30f55cead1f0478432d (patch)
tree701a3fdac56b07b9a708152406001074af5864e4 /docs
parent3f30e87cb579a21afa57efcd50e279070994265d (diff)
parentc05149e5e4110bed416e8a8568cf446e9db8774d (diff)
Merge pull request #2265 from JuliDi/docs-best-practices
[Docs] Add best practices page
Diffstat (limited to 'docs')
-rw-r--r--docs/modules/ROOT/nav.adoc5
-rw-r--r--docs/modules/ROOT/pages/best_practices.adoc53
2 files changed, 56 insertions, 2 deletions
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 2154799f3..fabb80e31 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -2,6 +2,7 @@
2** xref:basic_application.adoc[Basic application] 2** xref:basic_application.adoc[Basic application]
3** xref:project_structure.adoc[Project Structure] 3** xref:project_structure.adoc[Project Structure]
4** xref:new_project.adoc[Starting a new Embassy project] 4** xref:new_project.adoc[Starting a new Embassy project]
5** xref:best_practices.adoc[Best Practices]
5* xref:layer_by_layer.adoc[Bare metal to async] 6* xref:layer_by_layer.adoc[Bare metal to async]
6* xref:runtime.adoc[Executor] 7* xref:runtime.adoc[Executor]
7* xref:delaying_a_task.adoc[Delaying a Task] 8* xref:delaying_a_task.adoc[Delaying a Task]
@@ -11,7 +12,7 @@
11* xref:bootloader.adoc[Bootloader] 12* xref:bootloader.adoc[Bootloader]
12 13
13* xref:examples.adoc[Examples] 14* xref:examples.adoc[Examples]
14* xref:developer.adoc[Developer] 15* xref:developer.adoc[Developer Docs]
15** xref:developer_stm32.adoc[Developer: STM32] 16** xref:developer_stm32.adoc[Developer Docs: STM32]
16* xref:embassy_in_the_wild.adoc[Embassy in the wild] 17* xref:embassy_in_the_wild.adoc[Embassy in the wild]
17* xref:faq.adoc[Frequently Asked Questions] 18* xref:faq.adoc[Frequently Asked Questions]
diff --git a/docs/modules/ROOT/pages/best_practices.adoc b/docs/modules/ROOT/pages/best_practices.adoc
new file mode 100644
index 000000000..1e02f9ba9
--- /dev/null
+++ b/docs/modules/ROOT/pages/best_practices.adoc
@@ -0,0 +1,53 @@
1= Best Practices
2
3Over time, a couple of best practices have emerged. The following list should serve as a guideline for developers writing embedded software in _Rust_, especially in the context of the _Embassy_ framework.
4
5== Passing Buffers by Reference
6It may be tempting to pass arrays or wrappers, like link:https://docs.rs/heapless/latest/heapless/[`heapless::Vec`], to a function or return one just like you would with a `std::Vec`. However, in most embedded applications you don't want to spend ressources on an allocator and end up placing buffers on the stack.
7This, however, can easily blow up your stack if you are not careful.
8
9Consider the following example:
10[,rust]
11----
12fn process_buffer(mut buf: [u8; 1024]) -> [u8; 1024] {
13 // do stuff and return new buffer
14 for elem in buf.iter_mut() {
15 *elem = 0;
16 }
17 buf
18}
19
20pub fn main() -> () {
21 let buf = [1u8; 1024];
22 let buf_new = process_buffer(buf);
23 // do stuff with buf_new
24 ()
25}
26----
27When calling `process_buffer` in your program, a copy of the buffer you pass to the function will be created,
28consuming another 1024 bytes.
29After the processing, another 1024 byte buffer will be placed on the stack to be returned to the caller.
30(You can check the assembly, there will be two memcopy operations, e.g., `bl __aeabi_memcpy` when compiling for a Cortex-M processor.)
31
32*Possible Solution:*
33
34Pass the data by reference and not by value on both, the way in and the way out.
35For example, you could return a slice of the input buffer as the output.
36Requiring the lifetime of the input slice and the output slice to be the same, the memory safetly of this procedure will be enforced by the compiler.
37
38[,rust]
39----
40fn process_buffer<'a>(buf: &'a mut [u8]) -> &'a mut[u8] {
41 for elem in buf.iter_mut() {
42 *elem = 0;
43 }
44 buf
45}
46
47pub fn main() -> () {
48 let mut buf = [1u8; 1024];
49 let buf_new = process_buffer(&mut buf);
50 // do stuff with buf_new
51 ()
52}
53----