aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/stm32/Cargo.toml15
-rw-r--r--tests/stm32/gen_test.py2
-rw-r--r--tests/stm32/src/bin/cordic.rs135
3 files changed, 147 insertions, 5 deletions
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index e42470004..e09083111 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -14,8 +14,8 @@ stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not
14stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"] 14stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"]
15stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"] 15stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"]
16stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac", "ucpd"] 16stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac", "ucpd"]
17stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan"] 17stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan", "cordic"]
18stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "hash"] 18stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "hash", "cordic"]
19stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"] 19stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"]
20stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan", "hash", "cryp"] 20stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan", "hash", "cryp"]
21stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng", "fdcan"] 21stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng", "fdcan"]
@@ -25,8 +25,8 @@ stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma", "rng"]
25stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma", "rng", "hash"] 25stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma", "rng", "hash"]
26stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma", "rng"] 26stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma", "rng"]
27stm32l552ze = ["embassy-stm32/stm32l552ze", "not-gpdma", "rng", "hash"] 27stm32l552ze = ["embassy-stm32/stm32l552ze", "not-gpdma", "rng", "hash"]
28stm32u585ai = ["embassy-stm32/stm32u585ai", "chrono", "rng", "hash"] 28stm32u585ai = ["embassy-stm32/stm32u585ai", "chrono", "rng", "hash", "cordic"]
29stm32u5a5zj = ["embassy-stm32/stm32u5a5zj", "chrono", "rng", "hash"] 29stm32u5a5zj = ["embassy-stm32/stm32u5a5zj", "chrono", "rng", "hash"] # FIXME: cordic test cause it crash
30stm32wb55rg = ["embassy-stm32/stm32wb55rg", "chrono", "not-gpdma", "ble", "mac" , "rng"] 30stm32wb55rg = ["embassy-stm32/stm32wb55rg", "chrono", "not-gpdma", "ble", "mac" , "rng"]
31stm32wba52cg = ["embassy-stm32/stm32wba52cg", "chrono", "rng", "hash"] 31stm32wba52cg = ["embassy-stm32/stm32wba52cg", "chrono", "rng", "hash"]
32stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"] 32stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"]
@@ -48,6 +48,7 @@ embassy-stm32-wpan = []
48not-gpdma = [] 48not-gpdma = []
49dac = [] 49dac = []
50ucpd = [] 50ucpd = []
51cordic = ["dep:num-traits"]
51 52
52cm0 = ["portable-atomic/unsafe-assume-single-core"] 53cm0 = ["portable-atomic/unsafe-assume-single-core"]
53 54
@@ -83,6 +84,7 @@ chrono = { version = "^0.4", default-features = false, optional = true}
83sha2 = { version = "0.10.8", default-features = false } 84sha2 = { version = "0.10.8", default-features = false }
84hmac = "0.12.1" 85hmac = "0.12.1"
85aes-gcm = {version = "0.10.3", default-features = false, features = ["aes", "heapless"] } 86aes-gcm = {version = "0.10.3", default-features = false, features = ["aes", "heapless"] }
87num-traits = {version="0.2", default-features = false,features = ["libm"], optional = true}
86 88
87# BEGIN TESTS 89# BEGIN TESTS
88# Generated by gen_test.py. DO NOT EDIT. 90# Generated by gen_test.py. DO NOT EDIT.
@@ -92,6 +94,11 @@ path = "src/bin/can.rs"
92required-features = [ "can",] 94required-features = [ "can",]
93 95
94[[bin]] 96[[bin]]
97name = "cordic"
98path = "src/bin/cordic.rs"
99required-features = [ "rng", "cordic",]
100
101[[bin]]
95name = "cryp" 102name = "cryp"
96path = "src/bin/cryp.rs" 103path = "src/bin/cryp.rs"
97required-features = [ "cryp",] 104required-features = [ "cryp",]
diff --git a/tests/stm32/gen_test.py b/tests/stm32/gen_test.py
index 8ff156c0e..daf714376 100644
--- a/tests/stm32/gen_test.py
+++ b/tests/stm32/gen_test.py
@@ -14,7 +14,7 @@ for f in sorted(glob('./src/bin/*.rs')):
14 with open(f, 'r') as f: 14 with open(f, 'r') as f:
15 for line in f: 15 for line in f:
16 if line.startswith('// required-features:'): 16 if line.startswith('// required-features:'):
17 features = line.split(':', 2)[1].strip().split(',') 17 features = [feature.strip() for feature in line.split(':', 2)[1].strip().split(',')]
18 18
19 tests[name] = features 19 tests[name] = features
20 20
diff --git a/tests/stm32/src/bin/cordic.rs b/tests/stm32/src/bin/cordic.rs
new file mode 100644
index 000000000..400e10207
--- /dev/null
+++ b/tests/stm32/src/bin/cordic.rs
@@ -0,0 +1,135 @@
1// required-features: rng, cordic
2
3// Test Cordic driver, with Q1.31 format, Sin function, at 24 iterations (aka PRECISION = 6), using DMA transfer
4
5#![no_std]
6#![no_main]
7
8#[path = "../common.rs"]
9mod common;
10use common::*;
11use embassy_executor::Spawner;
12use embassy_stm32::cordic::utils;
13use embassy_stm32::{bind_interrupts, cordic, peripherals, rng};
14use num_traits::Float;
15use {defmt_rtt as _, panic_probe as _};
16
17bind_interrupts!(struct Irqs {
18 RNG => rng::InterruptHandler<peripherals::RNG>;
19});
20
21/* input value control, can be changed */
22
23const INPUT_U32_COUNT: usize = 9;
24const INPUT_U8_COUNT: usize = 4 * INPUT_U32_COUNT;
25
26// Assume first calculation needs 2 arguments, the reset needs 1 argument.
27// And all calculation generate 2 results.
28const OUTPUT_LENGTH: usize = (INPUT_U32_COUNT - 1) * 2;
29
30#[embassy_executor::main]
31async fn main(_spawner: Spawner) {
32 let dp = embassy_stm32::init(config());
33
34 //
35 // use RNG generate random Q1.31 value
36 //
37 // we don't generate floating-point value, since not all binary value are valid floating-point value,
38 // and Q1.31 only accept a fixed range of value.
39
40 let mut rng = rng::Rng::new(dp.RNG, Irqs);
41
42 let mut input_buf_u8 = [0u8; INPUT_U8_COUNT];
43 defmt::unwrap!(rng.async_fill_bytes(&mut input_buf_u8).await);
44
45 // convert every [u8; 4] to a u32, for a Q1.31 value
46 let mut input_q1_31 = unsafe { core::mem::transmute::<[u8; INPUT_U8_COUNT], [u32; INPUT_U32_COUNT]>(input_buf_u8) };
47
48 // ARG2 for Sin function should be inside [0, 1], set MSB to 0 of a Q1.31 value, will make sure it's no less than 0.
49 input_q1_31[1] &= !(1u32 << 31);
50
51 //
52 // CORDIC calculation
53 //
54
55 let mut output_q1_31 = [0u32; OUTPUT_LENGTH];
56
57 // setup Cordic driver
58 let mut cordic = cordic::Cordic::new(
59 dp.CORDIC,
60 defmt::unwrap!(cordic::Config::new(
61 cordic::Function::Sin,
62 Default::default(),
63 Default::default(),
64 )),
65 );
66
67 #[cfg(feature = "stm32g491re")]
68 let (mut write_dma, mut read_dma) = (dp.DMA1_CH4, dp.DMA1_CH5);
69
70 #[cfg(any(feature = "stm32h563zi", feature = "stm32u585ai", feature = "stm32u5a5zj"))]
71 let (mut write_dma, mut read_dma) = (dp.GPDMA1_CH0, dp.GPDMA1_CH1);
72
73 // calculate first result using blocking mode
74 let cnt0 = defmt::unwrap!(cordic.blocking_calc_32bit(&input_q1_31[..2], &mut output_q1_31, false, false));
75
76 // calculate rest results using async mode
77 let cnt1 = defmt::unwrap!(
78 cordic
79 .async_calc_32bit(
80 &mut write_dma,
81 &mut read_dma,
82 &input_q1_31[2..],
83 &mut output_q1_31[cnt0..],
84 true,
85 false,
86 )
87 .await
88 );
89
90 // all output value length should be the same as our output buffer size
91 defmt::assert_eq!(cnt0 + cnt1, output_q1_31.len());
92
93 let mut cordic_result_f64 = [0.0f64; OUTPUT_LENGTH];
94
95 for (f64_val, u32_val) in cordic_result_f64.iter_mut().zip(output_q1_31) {
96 *f64_val = utils::q1_31_to_f64(u32_val);
97 }
98
99 //
100 // software calculation
101 //
102
103 let mut software_result_f64 = [0.0f64; OUTPUT_LENGTH];
104
105 let arg2 = utils::q1_31_to_f64(input_q1_31[1]);
106
107 for (&arg1, res) in input_q1_31
108 .iter()
109 .enumerate()
110 .filter_map(|(idx, val)| if idx != 1 { Some(val) } else { None })
111 .zip(software_result_f64.chunks_mut(2))
112 {
113 let arg1 = utils::q1_31_to_f64(arg1);
114
115 let (raw_res1, raw_res2) = (arg1 * core::f64::consts::PI).sin_cos();
116 (res[0], res[1]) = (raw_res1 * arg2, raw_res2 * arg2);
117 }
118
119 //
120 // check result are the same
121 //
122
123 for (cordic_res, software_res) in cordic_result_f64[..cnt0 + cnt1]
124 .chunks(2)
125 .zip(software_result_f64.chunks(2))
126 {
127 for (cord_res, soft_res) in cordic_res.iter().zip(software_res.iter()) {
128 // 2.0.powi(-19) is the max residual error for Sin function, in q1.31 format, with 24 iterations (aka PRECISION = 6)
129 defmt::assert!((cord_res - soft_res).abs() <= 2.0.powi(-19));
130 }
131 }
132
133 info!("Test OK");
134 cortex_m::asm::bkpt();
135}