aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/rp/src/bin/gpio_multicore.rs12
-rw-r--r--tests/rp/src/bin/i2c.rs12
-rw-r--r--tests/rp/src/bin/multicore.rs12
-rw-r--r--tests/rp/src/bin/pwm.rs14
-rw-r--r--tests/stm32/Cargo.toml8
-rw-r--r--tests/stm32/src/bin/can.rs67
-rw-r--r--tests/stm32/src/bin/can_common.rs112
-rw-r--r--tests/stm32/src/bin/cryp.rs30
-rw-r--r--tests/stm32/src/bin/fdcan.rs172
-rw-r--r--tests/stm32/src/bin/ucpd.rs120
-rw-r--r--tests/stm32/src/common.rs8
11 files changed, 363 insertions, 204 deletions
diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs
index 8aed9b80c..e9c6f3122 100644
--- a/tests/rp/src/bin/gpio_multicore.rs
+++ b/tests/rp/src/bin/gpio_multicore.rs
@@ -21,10 +21,14 @@ static CHANNEL1: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
21#[cortex_m_rt::entry] 21#[cortex_m_rt::entry]
22fn main() -> ! { 22fn main() -> ! {
23 let p = embassy_rp::init(Default::default()); 23 let p = embassy_rp::init(Default::default());
24 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { 24 spawn_core1(
25 let executor1 = EXECUTOR1.init(Executor::new()); 25 p.CORE1,
26 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1)))); 26 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
27 }); 27 move || {
28 let executor1 = EXECUTOR1.init(Executor::new());
29 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1))));
30 },
31 );
28 let executor0 = EXECUTOR0.init(Executor::new()); 32 let executor0 = EXECUTOR0.init(Executor::new());
29 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0)))); 33 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0))));
30} 34}
diff --git a/tests/rp/src/bin/i2c.rs b/tests/rp/src/bin/i2c.rs
index 153b37999..9615007bd 100644
--- a/tests/rp/src/bin/i2c.rs
+++ b/tests/rp/src/bin/i2c.rs
@@ -210,10 +210,14 @@ async fn controller_task(con: &mut i2c::I2c<'static, I2C0, i2c::Async>) {
210 config.addr = DEV_ADDR as u16; 210 config.addr = DEV_ADDR as u16;
211 let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); 211 let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config);
212 212
213 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { 213 spawn_core1(
214 let executor1 = EXECUTOR1.init(Executor::new()); 214 p.CORE1,
215 executor1.run(|spawner| unwrap!(spawner.spawn(device_task(device)))); 215 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
216 }); 216 move || {
217 let executor1 = EXECUTOR1.init(Executor::new());
218 executor1.run(|spawner| unwrap!(spawner.spawn(device_task(device))));
219 },
220 );
217 221
218 let c_sda = p.PIN_21; 222 let c_sda = p.PIN_21;
219 let c_scl = p.PIN_20; 223 let c_scl = p.PIN_20;
diff --git a/tests/rp/src/bin/multicore.rs b/tests/rp/src/bin/multicore.rs
index 60d9f85ec..783ea0f27 100644
--- a/tests/rp/src/bin/multicore.rs
+++ b/tests/rp/src/bin/multicore.rs
@@ -19,10 +19,14 @@ static CHANNEL1: Channel<CriticalSectionRawMutex, bool, 1> = Channel::new();
19#[cortex_m_rt::entry] 19#[cortex_m_rt::entry]
20fn main() -> ! { 20fn main() -> ! {
21 let p = embassy_rp::init(Default::default()); 21 let p = embassy_rp::init(Default::default());
22 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { 22 spawn_core1(
23 let executor1 = EXECUTOR1.init(Executor::new()); 23 p.CORE1,
24 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task()))); 24 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
25 }); 25 move || {
26 let executor1 = EXECUTOR1.init(Executor::new());
27 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task())));
28 },
29 );
26 let executor0 = EXECUTOR0.init(Executor::new()); 30 let executor0 = EXECUTOR0.init(Executor::new());
27 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); 31 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task())));
28} 32}
diff --git a/tests/rp/src/bin/pwm.rs b/tests/rp/src/bin/pwm.rs
index e71d9e610..4b02e5bab 100644
--- a/tests/rp/src/bin/pwm.rs
+++ b/tests/rp/src/bin/pwm.rs
@@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) {
28 28
29 // Test free-running clock 29 // Test free-running clock
30 { 30 {
31 let pwm = Pwm::new_free(&mut p.PWM_CH3, cfg.clone()); 31 let pwm = Pwm::new_free(&mut p.PWM_SLICE3, cfg.clone());
32 cortex_m::asm::delay(125); 32 cortex_m::asm::delay(125);
33 let ctr = pwm.counter(); 33 let ctr = pwm.counter();
34 assert!(ctr > 0); 34 assert!(ctr > 0);
@@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) {
46 // Test output from A 46 // Test output from A
47 { 47 {
48 let pin1 = Input::new(&mut p9, Pull::None); 48 let pin1 = Input::new(&mut p9, Pull::None);
49 let _pwm = Pwm::new_output_a(&mut p.PWM_CH3, &mut p6, cfg.clone()); 49 let _pwm = Pwm::new_output_a(&mut p.PWM_SLICE3, &mut p6, cfg.clone());
50 Timer::after_millis(1).await; 50 Timer::after_millis(1).await;
51 assert_eq!(pin1.is_low(), invert_a); 51 assert_eq!(pin1.is_low(), invert_a);
52 Timer::after_millis(5).await; 52 Timer::after_millis(5).await;
@@ -60,7 +60,7 @@ async fn main(_spawner: Spawner) {
60 // Test output from B 60 // Test output from B
61 { 61 {
62 let pin2 = Input::new(&mut p11, Pull::None); 62 let pin2 = Input::new(&mut p11, Pull::None);
63 let _pwm = Pwm::new_output_b(&mut p.PWM_CH3, &mut p7, cfg.clone()); 63 let _pwm = Pwm::new_output_b(&mut p.PWM_SLICE3, &mut p7, cfg.clone());
64 Timer::after_millis(1).await; 64 Timer::after_millis(1).await;
65 assert_ne!(pin2.is_low(), invert_a); 65 assert_ne!(pin2.is_low(), invert_a);
66 Timer::after_millis(5).await; 66 Timer::after_millis(5).await;
@@ -75,7 +75,7 @@ async fn main(_spawner: Spawner) {
75 { 75 {
76 let pin1 = Input::new(&mut p9, Pull::None); 76 let pin1 = Input::new(&mut p9, Pull::None);
77 let pin2 = Input::new(&mut p11, Pull::None); 77 let pin2 = Input::new(&mut p11, Pull::None);
78 let _pwm = Pwm::new_output_ab(&mut p.PWM_CH3, &mut p6, &mut p7, cfg.clone()); 78 let _pwm = Pwm::new_output_ab(&mut p.PWM_SLICE3, &mut p6, &mut p7, cfg.clone());
79 Timer::after_millis(1).await; 79 Timer::after_millis(1).await;
80 assert_eq!(pin1.is_low(), invert_a); 80 assert_eq!(pin1.is_low(), invert_a);
81 assert_ne!(pin2.is_low(), invert_a); 81 assert_ne!(pin2.is_low(), invert_a);
@@ -94,7 +94,7 @@ async fn main(_spawner: Spawner) {
94 // Test level-gated 94 // Test level-gated
95 { 95 {
96 let mut pin2 = Output::new(&mut p11, Level::Low); 96 let mut pin2 = Output::new(&mut p11, Level::Low);
97 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::Level, cfg.clone()); 97 let pwm = Pwm::new_input(&mut p.PWM_SLICE3, &mut p7, InputMode::Level, cfg.clone());
98 assert_eq!(pwm.counter(), 0); 98 assert_eq!(pwm.counter(), 0);
99 Timer::after_millis(5).await; 99 Timer::after_millis(5).await;
100 assert_eq!(pwm.counter(), 0); 100 assert_eq!(pwm.counter(), 0);
@@ -110,7 +110,7 @@ async fn main(_spawner: Spawner) {
110 // Test rising-gated 110 // Test rising-gated
111 { 111 {
112 let mut pin2 = Output::new(&mut p11, Level::Low); 112 let mut pin2 = Output::new(&mut p11, Level::Low);
113 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::RisingEdge, cfg.clone()); 113 let pwm = Pwm::new_input(&mut p.PWM_SLICE3, &mut p7, InputMode::RisingEdge, cfg.clone());
114 assert_eq!(pwm.counter(), 0); 114 assert_eq!(pwm.counter(), 0);
115 Timer::after_millis(5).await; 115 Timer::after_millis(5).await;
116 assert_eq!(pwm.counter(), 0); 116 assert_eq!(pwm.counter(), 0);
@@ -125,7 +125,7 @@ async fn main(_spawner: Spawner) {
125 // Test falling-gated 125 // Test falling-gated
126 { 126 {
127 let mut pin2 = Output::new(&mut p11, Level::High); 127 let mut pin2 = Output::new(&mut p11, Level::High);
128 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::FallingEdge, cfg.clone()); 128 let pwm = Pwm::new_input(&mut p.PWM_SLICE3, &mut p7, InputMode::FallingEdge, cfg.clone());
129 assert_eq!(pwm.counter(), 0); 129 assert_eq!(pwm.counter(), 0);
130 Timer::after_millis(5).await; 130 Timer::after_millis(5).await;
131 assert_eq!(pwm.counter(), 0); 131 assert_eq!(pwm.counter(), 0);
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index bfe003a11..e42470004 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -13,7 +13,7 @@ stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"]
13stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac", "rng"] 13stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac", "rng"]
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"] 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"]
18stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "hash"] 18stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "hash"]
19stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"] 19stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"]
@@ -47,6 +47,7 @@ mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"]
47embassy-stm32-wpan = [] 47embassy-stm32-wpan = []
48not-gpdma = [] 48not-gpdma = []
49dac = [] 49dac = []
50ucpd = []
50 51
51cm0 = ["portable-atomic/unsafe-assume-single-core"] 52cm0 = ["portable-atomic/unsafe-assume-single-core"]
52 53
@@ -161,6 +162,11 @@ path = "src/bin/timer.rs"
161required-features = [] 162required-features = []
162 163
163[[bin]] 164[[bin]]
165name = "ucpd"
166path = "src/bin/ucpd.rs"
167required-features = [ "ucpd",]
168
169[[bin]]
164name = "usart" 170name = "usart"
165path = "src/bin/usart.rs" 171path = "src/bin/usart.rs"
166required-features = [] 172required-features = []
diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs
index f4effa244..551764458 100644
--- a/tests/stm32/src/bin/can.rs
+++ b/tests/stm32/src/bin/can.rs
@@ -6,17 +6,20 @@
6#[path = "../common.rs"] 6#[path = "../common.rs"]
7mod common; 7mod common;
8use common::*; 8use common::*;
9use defmt::assert;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
11use embassy_stm32::bind_interrupts; 10use embassy_stm32::bind_interrupts;
12use embassy_stm32::can::bxcan::filter::Mask32; 11use embassy_stm32::can::filter::Mask32;
13use embassy_stm32::can::bxcan::{Fifo, Frame, StandardId}; 12use embassy_stm32::can::{
14use embassy_stm32::can::{Can, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler}; 13 Can, Fifo, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler,
14};
15use embassy_stm32::gpio::{Input, Pull}; 15use embassy_stm32::gpio::{Input, Pull};
16use embassy_stm32::peripherals::CAN1; 16use embassy_stm32::peripherals::CAN1;
17use embassy_time::{Duration, Instant}; 17use embassy_time::Duration;
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19 19
20mod can_common;
21use can_common::*;
22
20bind_interrupts!(struct Irqs { 23bind_interrupts!(struct Irqs {
21 CAN1_RX0 => Rx0InterruptHandler<CAN1>; 24 CAN1_RX0 => Rx0InterruptHandler<CAN1>;
22 CAN1_RX1 => Rx1InterruptHandler<CAN1>; 25 CAN1_RX1 => Rx1InterruptHandler<CAN1>;
@@ -29,6 +32,11 @@ async fn main(_spawner: Spawner) {
29 let p = embassy_stm32::init(config()); 32 let p = embassy_stm32::init(config());
30 info!("Hello World!"); 33 info!("Hello World!");
31 34
35 let options = TestOptions {
36 max_latency: Duration::from_micros(1200),
37 max_buffered: 2,
38 };
39
32 let can = peri!(p, CAN); 40 let can = peri!(p, CAN);
33 let tx = peri!(p, CAN_TX); 41 let tx = peri!(p, CAN_TX);
34 let mut rx = peri!(p, CAN_RX); 42 let mut rx = peri!(p, CAN_RX);
@@ -44,54 +52,25 @@ async fn main(_spawner: Spawner) {
44 52
45 info!("Configuring can..."); 53 info!("Configuring can...");
46 54
47 can.as_mut() 55 can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
48 .modify_filters()
49 .enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
50 56
51 can.set_bitrate(1_000_000); 57 can.modify_config()
52 can.as_mut()
53 .modify_config()
54 .set_loopback(true) // Receive own frames 58 .set_loopback(true) // Receive own frames
55 .set_silent(true) 59 .set_silent(true)
56 // .set_bit_timing(0x001c0003) 60 // .set_bit_timing(0x001c0003)
57 .enable(); 61 .set_bitrate(1_000_000);
58
59 info!("Can configured");
60
61 let mut i: u8 = 0;
62 loop {
63 let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), [i]);
64 62
65 info!("Transmitting frame..."); 63 can.enable().await;
66 let tx_ts = Instant::now();
67 can.write(&tx_frame).await;
68 64
69 let envelope = can.read().await.unwrap(); 65 info!("Can configured");
70 info!("Frame received!");
71
72 info!("loopback time {}", envelope.ts);
73 info!("loopback frame {=u8}", envelope.frame.data().unwrap()[0]);
74
75 let latency = envelope.ts.saturating_duration_since(tx_ts);
76 info!("loopback latency {} us", latency.as_micros());
77 66
78 // Theoretical minimum latency is 55us, actual is usually ~80us 67 run_can_tests(&mut can, &options).await;
79 const MIN_LATENCY: Duration = Duration::from_micros(50);
80 const MAX_LATENCY: Duration = Duration::from_micros(150);
81 assert!(
82 MIN_LATENCY <= latency && latency <= MAX_LATENCY,
83 "{} <= {} <= {}",
84 MIN_LATENCY,
85 latency,
86 MAX_LATENCY
87 );
88 68
89 i += 1; 69 // Test again with a split
90 if i > 10 { 70 let (mut tx, mut rx) = can.split();
91 break; 71 run_split_can_tests(&mut tx, &mut rx, &options).await;
92 }
93 }
94 72
95 info!("Test OK"); 73 info!("Test OK");
74
96 cortex_m::asm::bkpt(); 75 cortex_m::asm::bkpt();
97} 76}
diff --git a/tests/stm32/src/bin/can_common.rs b/tests/stm32/src/bin/can_common.rs
new file mode 100644
index 000000000..4b39269cc
--- /dev/null
+++ b/tests/stm32/src/bin/can_common.rs
@@ -0,0 +1,112 @@
1use defmt::{assert, *};
2use embassy_stm32::can;
3use embassy_time::{Duration, Instant};
4
5#[derive(Clone, Copy, Debug)]
6pub struct TestOptions {
7 pub max_latency: Duration,
8 pub max_buffered: u8,
9}
10
11pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, options: &TestOptions) {
12 let mut i: u8 = 0;
13 loop {
14 //let tx_frame = can::frame::Frame::new_standard(0x123, &[i, 0x12 as u8, 0x34 as u8, 0x56 as u8, 0x78 as u8, 0x9A as u8, 0xBC as u8 ]).unwrap();
15 let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap();
16
17 //info!("Transmitting frame...");
18 let tx_ts = Instant::now();
19 can.write(&tx_frame).await;
20
21 let (frame, timestamp) = can.read().await.unwrap().parts();
22 //info!("Frame received!");
23
24 // Check data.
25 assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]);
26
27 //info!("loopback time {}", timestamp);
28 //info!("loopback frame {=u8}", frame.data()[0]);
29 let latency = timestamp.saturating_duration_since(tx_ts);
30 info!("loopback latency {} us", latency.as_micros());
31
32 // Theoretical minimum latency is 55us, actual is usually ~80us
33 const MIN_LATENCY: Duration = Duration::from_micros(50);
34 // Was failing at 150 but we are not getting a real time stamp. I'm not
35 // sure if there are other delays
36 assert!(
37 MIN_LATENCY <= latency && latency <= options.max_latency,
38 "{} <= {} <= {}",
39 MIN_LATENCY,
40 latency,
41 options.max_latency
42 );
43
44 i += 1;
45 if i > 5 {
46 break;
47 }
48 }
49
50 // Below here, check that we can receive from both FIFO0 and FIFO1
51 // Above we configured FIFO1 for extended ID packets. There are only 3 slots
52 // in each FIFO so make sure we write enough to fill them both up before reading.
53 for i in 0..options.max_buffered {
54 // Try filling up the RX FIFO0 buffers
55 //let tx_frame = if 0 != (i & 0x01) {
56 let tx_frame = if i < options.max_buffered / 2 {
57 info!("Transmitting standard frame {}", i);
58 can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap()
59 } else {
60 info!("Transmitting extended frame {}", i);
61 can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap()
62 };
63 can.write(&tx_frame).await;
64 }
65
66 // Try and receive all 6 packets
67 for _i in 0..options.max_buffered {
68 let (frame, _ts) = can.read().await.unwrap().parts();
69 match frame.id() {
70 embedded_can::Id::Extended(_id) => {
71 info!("Extended received! {}", frame.data()[0]);
72 //info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
73 }
74 embedded_can::Id::Standard(_id) => {
75 info!("Standard received! {}", frame.data()[0]);
76 //info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
77 }
78 }
79 }
80}
81
82pub async fn run_split_can_tests<'d, T: can::Instance>(
83 tx: &mut can::CanTx<'d, T>,
84 rx: &mut can::CanRx<'d, T>,
85 options: &TestOptions,
86) {
87 for i in 0..options.max_buffered {
88 // Try filling up the RX FIFO0 buffers
89 //let tx_frame = if 0 != (i & 0x01) {
90 let tx_frame = if i < options.max_buffered / 2 {
91 info!("Transmitting standard frame {}", i);
92 can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap()
93 } else {
94 info!("Transmitting extended frame {}", i);
95 can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap()
96 };
97 tx.write(&tx_frame).await;
98 }
99
100 // Try and receive all 6 packets
101 for _i in 0..options.max_buffered {
102 let (frame, _ts) = rx.read().await.unwrap().parts();
103 match frame.id() {
104 embedded_can::Id::Extended(_id) => {
105 info!("Extended received! {}", frame.data()[0]);
106 }
107 embedded_can::Id::Standard(_id) => {
108 info!("Standard received! {}", frame.data()[0]);
109 }
110 }
111 }
112}
diff --git a/tests/stm32/src/bin/cryp.rs b/tests/stm32/src/bin/cryp.rs
index f105abf26..60778bdaa 100644
--- a/tests/stm32/src/bin/cryp.rs
+++ b/tests/stm32/src/bin/cryp.rs
@@ -10,9 +10,14 @@ use aes_gcm::aead::{AeadInPlace, KeyInit};
10use aes_gcm::Aes128Gcm; 10use aes_gcm::Aes128Gcm;
11use common::*; 11use common::*;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::cryp::*; 13use embassy_stm32::cryp::{self, *};
14use embassy_stm32::{bind_interrupts, peripherals};
14use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
15 16
17bind_interrupts!(struct Irqs {
18 CRYP => cryp::InterruptHandler<peripherals::CRYP>;
19});
20
16#[embassy_executor::main] 21#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 22async fn main(_spawner: Spawner) {
18 let p: embassy_stm32::Peripherals = embassy_stm32::init(config()); 23 let p: embassy_stm32::Peripherals = embassy_stm32::init(config());
@@ -22,27 +27,32 @@ async fn main(_spawner: Spawner) {
22 const AAD1: &[u8] = b"additional data 1 stdargadrhaethaethjatjatjaetjartjstrjsfkk;'jopofyuisrteytweTASTUIKFUKIXTRDTEREharhaeryhaterjartjarthaethjrtjarthaetrhartjatejatrjsrtjartjyt1"; 27 const AAD1: &[u8] = b"additional data 1 stdargadrhaethaethjatjatjaetjartjstrjsfkk;'jopofyuisrteytweTASTUIKFUKIXTRDTEREharhaeryhaterjartjarthaethjrtjarthaetrhartjatejatrjsrtjartjyt1";
23 const AAD2: &[u8] = b"additional data 2 stdhthsthsthsrthsrthsrtjdykjdukdyuldadfhsdghsdghsdghsadghjk'hioethjrtjarthaetrhartjatecfgjhzdfhgzdfhzdfghzdfhzdfhzfhjatrjsrtjartjytjfytjfyg"; 28 const AAD2: &[u8] = b"additional data 2 stdhthsthsthsrthsrthsrtjdykjdukdyuldadfhsdghsdghsdghsadghjk'hioethjrtjarthaetrhartjatecfgjhzdfhgzdfhzdfghzdfhzdfhzfhjatrjsrtjartjytjfytjfyg";
24 29
25 let hw_cryp = Cryp::new(p.CRYP); 30 let in_dma = peri!(p, CRYP_IN_DMA);
31 let out_dma = peri!(p, CRYP_OUT_DMA);
32
33 let mut hw_cryp = Cryp::new(p.CRYP, in_dma, out_dma, Irqs);
26 let key: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; 34 let key: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
27 let mut ciphertext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; 35 let mut ciphertext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()];
28 let mut plaintext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; 36 let mut plaintext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()];
29 let iv: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; 37 let iv: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
30 38
31 // Encrypt in hardware using AES-GCM 128-bit 39 // Encrypt in hardware using AES-GCM 128-bit in blocking mode.
32 let aes_gcm = AesGcm::new(&key, &iv); 40 let aes_gcm = AesGcm::new(&key, &iv);
33 let mut gcm_encrypt = hw_cryp.start(&aes_gcm, Direction::Encrypt); 41 let mut gcm_encrypt = hw_cryp.start_blocking(&aes_gcm, Direction::Encrypt);
34 hw_cryp.aad_blocking(&mut gcm_encrypt, AAD1, false); 42 hw_cryp.aad_blocking(&mut gcm_encrypt, AAD1, false);
35 hw_cryp.aad_blocking(&mut gcm_encrypt, AAD2, true); 43 hw_cryp.aad_blocking(&mut gcm_encrypt, AAD2, true);
36 hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD1, &mut ciphertext[..PAYLOAD1.len()], false); 44 hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD1, &mut ciphertext[..PAYLOAD1.len()], false);
37 hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD2, &mut ciphertext[PAYLOAD1.len()..], true); 45 hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD2, &mut ciphertext[PAYLOAD1.len()..], true);
38 let encrypt_tag = hw_cryp.finish_blocking(gcm_encrypt); 46 let encrypt_tag = hw_cryp.finish_blocking(gcm_encrypt);
39 47
40 // Decrypt in hardware using AES-GCM 128-bit 48 // Decrypt in hardware using AES-GCM 128-bit in async (DMA) mode.
41 let mut gcm_decrypt = hw_cryp.start(&aes_gcm, Direction::Decrypt); 49 let mut gcm_decrypt = hw_cryp.start(&aes_gcm, Direction::Decrypt).await;
42 hw_cryp.aad_blocking(&mut gcm_decrypt, AAD1, false); 50 hw_cryp.aad(&mut gcm_decrypt, AAD1, false).await;
43 hw_cryp.aad_blocking(&mut gcm_decrypt, AAD2, true); 51 hw_cryp.aad(&mut gcm_decrypt, AAD2, true).await;
44 hw_cryp.payload_blocking(&mut gcm_decrypt, &ciphertext, &mut plaintext, true); 52 hw_cryp
45 let decrypt_tag = hw_cryp.finish_blocking(gcm_decrypt); 53 .payload(&mut gcm_decrypt, &ciphertext, &mut plaintext, true)
54 .await;
55 let decrypt_tag = hw_cryp.finish(gcm_decrypt).await;
46 56
47 info!("AES-GCM Ciphertext: {:?}", ciphertext); 57 info!("AES-GCM Ciphertext: {:?}", ciphertext);
48 info!("AES-GCM Plaintext: {:?}", plaintext); 58 info!("AES-GCM Plaintext: {:?}", plaintext);
diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs
index dd78d7fb3..27bdd038a 100644
--- a/tests/stm32/src/bin/fdcan.rs
+++ b/tests/stm32/src/bin/fdcan.rs
@@ -6,26 +6,26 @@
6#[path = "../common.rs"] 6#[path = "../common.rs"]
7mod common; 7mod common;
8use common::*; 8use common::*;
9use defmt::assert;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
11use embassy_stm32::peripherals::*; 10use embassy_stm32::peripherals::*;
12use embassy_stm32::{bind_interrupts, can, Config}; 11use embassy_stm32::{bind_interrupts, can, Config};
13use embassy_time::{Duration, Instant}; 12use embassy_time::Duration;
14use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
15 14
16bind_interrupts!(struct Irqs { 15mod can_common;
16use can_common::*;
17
18bind_interrupts!(struct Irqs2 {
19 FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>;
20 FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>;
21});
22bind_interrupts!(struct Irqs1 {
17 FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>; 23 FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
18 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>; 24 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
19}); 25});
20 26
21struct TestOptions {
22 config: Config,
23 max_latency: Duration,
24 second_fifo_working: bool,
25}
26
27#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))] 27#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))]
28fn options() -> TestOptions { 28fn options() -> (Config, TestOptions) {
29 use embassy_stm32::rcc; 29 use embassy_stm32::rcc;
30 info!("H75 config"); 30 info!("H75 config");
31 let mut c = config(); 31 let mut c = config();
@@ -34,15 +34,17 @@ fn options() -> TestOptions {
34 mode: rcc::HseMode::Oscillator, 34 mode: rcc::HseMode::Oscillator,
35 }); 35 });
36 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; 36 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
37 TestOptions { 37 (
38 config: c, 38 c,
39 max_latency: Duration::from_micros(1200), 39 TestOptions {
40 second_fifo_working: false, 40 max_latency: Duration::from_micros(1200),
41 } 41 max_buffered: 3,
42 },
43 )
42} 44}
43 45
44#[cfg(any(feature = "stm32h7a3zi"))] 46#[cfg(any(feature = "stm32h7a3zi"))]
45fn options() -> TestOptions { 47fn options() -> (Config, TestOptions) {
46 use embassy_stm32::rcc; 48 use embassy_stm32::rcc;
47 info!("H7a config"); 49 info!("H7a config");
48 let mut c = config(); 50 let mut c = config();
@@ -51,139 +53,63 @@ fn options() -> TestOptions {
51 mode: rcc::HseMode::Oscillator, 53 mode: rcc::HseMode::Oscillator,
52 }); 54 });
53 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; 55 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
54 TestOptions { 56 (
55 config: c, 57 c,
56 max_latency: Duration::from_micros(1200), 58 TestOptions {
57 second_fifo_working: false, 59 max_latency: Duration::from_micros(1200),
58 } 60 max_buffered: 3,
61 },
62 )
59} 63}
60 64
61#[cfg(any(feature = "stm32g491re", feature = "stm32g431cb"))] 65#[cfg(any(feature = "stm32g491re", feature = "stm32g431cb"))]
62fn options() -> TestOptions { 66fn options() -> (Config, TestOptions) {
63 info!("G4 config"); 67 info!("G4 config");
64 TestOptions { 68 (
65 config: config(), 69 config(),
66 max_latency: Duration::from_micros(500), 70 TestOptions {
67 second_fifo_working: true, 71 max_latency: Duration::from_micros(500),
68 } 72 max_buffered: 6,
73 },
74 )
69} 75}
70 76
71#[embassy_executor::main] 77#[embassy_executor::main]
72async fn main(_spawner: Spawner) { 78async fn main(_spawner: Spawner) {
73 //let peripherals = embassy_stm32::init(config()); 79 //let peripherals = embassy_stm32::init(config());
74 80
75 let options = options(); 81 let (config, options) = options();
76 let peripherals = embassy_stm32::init(options.config); 82 let peripherals = embassy_stm32::init(config);
77 83
78 let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs); 84 let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs1);
85 let mut can2 = can::CanConfigurator::new(peripherals.FDCAN2, peripherals.PB12, peripherals.PB13, Irqs2);
79 86
80 // 250k bps 87 // 250k bps
81 can.set_bitrate(250_000); 88 can.set_bitrate(250_000);
89 can2.set_bitrate(250_000);
82 90
83 can.set_extended_filter( 91 can.set_extended_filter(
84 can::filter::ExtendedFilterSlot::_0, 92 can::filter::ExtendedFilterSlot::_0,
85 can::filter::ExtendedFilter::accept_all_into_fifo1(), 93 can::filter::ExtendedFilter::accept_all_into_fifo1(),
86 ); 94 );
95 can2.set_extended_filter(
96 can::filter::ExtendedFilterSlot::_0,
97 can::filter::ExtendedFilter::accept_all_into_fifo1(),
98 );
87 99
88 let mut can = can.into_internal_loopback_mode(); 100 let mut can = can.into_internal_loopback_mode();
101 let mut can2 = can2.into_internal_loopback_mode();
89 102
90 info!("CAN Configured"); 103 run_can_tests(&mut can, &options).await;
104 run_can_tests(&mut can2, &options).await;
91 105
92 let mut i: u8 = 0; 106 info!("CAN Configured");
93 loop {
94 let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap();
95
96 info!("Transmitting frame...");
97 let tx_ts = Instant::now();
98 can.write(&tx_frame).await;
99
100 let (frame, timestamp) = can.read().await.unwrap();
101 info!("Frame received!");
102
103 // Check data.
104 assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]);
105
106 info!("loopback time {}", timestamp);
107 info!("loopback frame {=u8}", frame.data()[0]);
108 let latency = timestamp.saturating_duration_since(tx_ts);
109 info!("loopback latency {} us", latency.as_micros());
110
111 // Theoretical minimum latency is 55us, actual is usually ~80us
112 const MIN_LATENCY: Duration = Duration::from_micros(50);
113 // Was failing at 150 but we are not getting a real time stamp. I'm not
114 // sure if there are other delays
115 assert!(
116 MIN_LATENCY <= latency && latency <= options.max_latency,
117 "{} <= {} <= {}",
118 MIN_LATENCY,
119 latency,
120 options.max_latency
121 );
122
123 i += 1;
124 if i > 10 {
125 break;
126 }
127 }
128
129 let max_buffered = if options.second_fifo_working { 6 } else { 3 };
130
131 // Below here, check that we can receive from both FIFO0 and FIFO0
132 // Above we configured FIFO1 for extended ID packets. There are only 3 slots
133 // in each FIFO so make sure we write enough to fill them both up before reading.
134 for i in 0..3 {
135 // Try filling up the RX FIFO0 buffers with standard packets
136 let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap();
137 info!("Transmitting frame {}", i);
138 can.write(&tx_frame).await;
139 }
140 for i in 3..max_buffered {
141 // Try filling up the RX FIFO0 buffers with extended packets
142 let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap();
143 info!("Transmitting frame {}", i);
144 can.write(&tx_frame).await;
145 }
146
147 // Try and receive all 6 packets
148 for i in 0..max_buffered {
149 let (frame, _ts) = can.read().await.unwrap();
150 match frame.id() {
151 embedded_can::Id::Extended(id) => {
152 info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
153 }
154 embedded_can::Id::Standard(id) => {
155 info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
156 }
157 }
158 }
159 107
160 // Test again with a split 108 // Test again with a split
161 let (mut tx, mut rx) = can.split(); 109 let (mut tx, mut rx) = can.split();
162 for i in 0..3 { 110 let (mut tx2, mut rx2) = can2.split();
163 // Try filling up the RX FIFO0 buffers with standard packets 111 run_split_can_tests(&mut tx, &mut rx, &options).await;
164 let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap(); 112 run_split_can_tests(&mut tx2, &mut rx2, &options).await;
165 info!("Transmitting frame {}", i);
166 tx.write(&tx_frame).await;
167 }
168 for i in 3..max_buffered {
169 // Try filling up the RX FIFO0 buffers with extended packets
170 let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap();
171 info!("Transmitting frame {}", i);
172 tx.write(&tx_frame).await;
173 }
174
175 // Try and receive all 6 packets
176 for i in 0..max_buffered {
177 let (frame, _ts) = rx.read().await.unwrap();
178 match frame.id() {
179 embedded_can::Id::Extended(id) => {
180 info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
181 }
182 embedded_can::Id::Standard(id) => {
183 info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
184 }
185 }
186 }
187 113
188 info!("Test OK"); 114 info!("Test OK");
189 cortex_m::asm::bkpt(); 115 cortex_m::asm::bkpt();
diff --git a/tests/stm32/src/bin/ucpd.rs b/tests/stm32/src/bin/ucpd.rs
new file mode 100644
index 000000000..c09334ec8
--- /dev/null
+++ b/tests/stm32/src/bin/ucpd.rs
@@ -0,0 +1,120 @@
1// required-features: ucpd
2#![no_std]
3#![no_main]
4#[path = "../common.rs"]
5mod common;
6
7use common::*;
8use defmt::{assert, assert_eq};
9use embassy_executor::Spawner;
10use embassy_futures::join::join;
11use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, RxError, Ucpd};
12use embassy_stm32::{bind_interrupts, peripherals};
13use embassy_time::Timer;
14
15bind_interrupts!(struct Irqs {
16 UCPD1_2 => ucpd::InterruptHandler<peripherals::UCPD1>, ucpd::InterruptHandler<peripherals::UCPD2>;
17});
18
19static SRC_TO_SNK: [u8; 6] = [0, 1, 2, 3, 4, 5];
20static SNK_TO_SRC: [u8; 4] = [9, 8, 7, 6];
21
22async fn wait_for_vstate<T: ucpd::Instance>(cc_phy: &mut CcPhy<'_, T>, vstate: CcVState) {
23 let (mut cc1, mut _cc2) = cc_phy.vstate();
24 while cc1 != vstate {
25 (cc1, _cc2) = cc_phy.wait_for_vstate_change().await;
26 }
27}
28
29async fn source(
30 mut ucpd: Ucpd<'static, peripherals::UCPD1>,
31 rx_dma: peripherals::DMA1_CH1,
32 tx_dma: peripherals::DMA1_CH2,
33) {
34 debug!("source: setting default current pull-up");
35 ucpd.cc_phy().set_pull(CcPull::SourceDefaultUsb);
36
37 // Wait for default sink.
38 debug!("source: wait for sink");
39 wait_for_vstate(ucpd.cc_phy(), CcVState::LOW).await;
40
41 // Advertise a higher current by changing the pull-up resistor.
42 debug!("source: sink detected, setting 3.0A current pull-up");
43 ucpd.cc_phy().set_pull(CcPull::Source3_0A);
44
45 let (_, mut pd_phy) = ucpd.split_pd_phy(rx_dma, tx_dma, CcSel::CC1);
46
47 // Listen for an incoming message
48 debug!("source: wait for message from sink");
49 let mut snk_to_src_buf = [0_u8; 30];
50 let n = unwrap!(pd_phy.receive(snk_to_src_buf.as_mut()).await);
51 assert_eq!(n, SNK_TO_SRC.len());
52 assert_eq!(&snk_to_src_buf[..n], SNK_TO_SRC.as_slice());
53
54 // Send message
55 debug!("source: message received, sending message");
56 unwrap!(pd_phy.transmit(SRC_TO_SNK.as_slice()).await);
57
58 // Wait for hard-reset
59 debug!("source: message sent, waiting for hard-reset");
60 assert!(matches!(
61 pd_phy.receive(snk_to_src_buf.as_mut()).await,
62 Err(RxError::HardReset)
63 ));
64}
65
66async fn sink(
67 mut ucpd: Ucpd<'static, peripherals::UCPD2>,
68 rx_dma: peripherals::DMA1_CH3,
69 tx_dma: peripherals::DMA1_CH4,
70) {
71 debug!("sink: setting pull down");
72 ucpd.cc_phy().set_pull(CcPull::Sink);
73
74 // Wait for default source.
75 debug!("sink: waiting for default vstate");
76 wait_for_vstate(ucpd.cc_phy(), CcVState::LOW).await;
77
78 // Wait higher current pull-up.
79 //debug!("sink: source default vstate detected, waiting for 3.0A vstate");
80 //wait_for_vstate(ucpd.cc_phy(), CcVState::HIGHEST).await;
81 //debug!("sink: source 3.0A vstate detected");
82 // TODO: not working yet, why? no idea, replace with timer for now
83 Timer::after_millis(100).await;
84
85 let (_, mut pd_phy) = ucpd.split_pd_phy(rx_dma, tx_dma, CcSel::CC1);
86
87 // Send message
88 debug!("sink: sending message");
89 unwrap!(pd_phy.transmit(SNK_TO_SRC.as_slice()).await);
90
91 // Listen for an incoming message
92 debug!("sink: message sent, waiting for message from source");
93 let mut src_to_snk_buf = [0_u8; 30];
94 let n = unwrap!(pd_phy.receive(src_to_snk_buf.as_mut()).await);
95 assert_eq!(n, SRC_TO_SNK.len());
96 assert_eq!(&src_to_snk_buf[..n], SRC_TO_SNK.as_slice());
97
98 // Send hard reset
99 debug!("sink: message received, sending hard-reset");
100 unwrap!(pd_phy.transmit_hardreset().await);
101}
102
103#[embassy_executor::main]
104async fn main(_spawner: Spawner) {
105 let p = embassy_stm32::init(config());
106 info!("Hello World!");
107
108 // Wire between PD0 and PA8
109 let ucpd1 = Ucpd::new(p.UCPD1, Irqs {}, p.PA8, p.PB15);
110 let ucpd2 = Ucpd::new(p.UCPD2, Irqs {}, p.PD0, p.PD2);
111
112 join(
113 source(ucpd1, p.DMA1_CH1, p.DMA1_CH2),
114 sink(ucpd2, p.DMA1_CH3, p.DMA1_CH4),
115 )
116 .await;
117
118 info!("Test OK");
119 cortex_m::asm::bkpt();
120}
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 3297ea7e2..0e555efc8 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -140,6 +140,7 @@ define_peris!(
140); 140);
141#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))] 141#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))]
142define_peris!( 142define_peris!(
143 CRYP_IN_DMA = DMA1_CH0, CRYP_OUT_DMA = DMA1_CH1,
143 UART = USART1, UART_TX = PB6, UART_RX = PB7, UART_TX_DMA = DMA1_CH0, UART_RX_DMA = DMA1_CH1, 144 UART = USART1, UART_TX = PB6, UART_RX = PB7, UART_TX_DMA = DMA1_CH0, UART_RX_DMA = DMA1_CH1,
144 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PB5, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH0, SPI_RX_DMA = DMA1_CH1, 145 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PB5, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH0, SPI_RX_DMA = DMA1_CH1,
145 ADC = ADC1, DAC = DAC1, DAC_PIN = PA4, 146 ADC = ADC1, DAC = DAC1, DAC_PIN = PA4,
@@ -250,13 +251,6 @@ define_peris!(
250); 251);
251 252
252pub fn config() -> Config { 253pub fn config() -> Config {
253 // Setting this bit is mandatory to use PG[15:2].
254 #[cfg(feature = "stm32u5a5zj")]
255 embassy_stm32::pac::PWR.svmcr().modify(|w| {
256 w.set_io2sv(true);
257 w.set_io2vmen(true);
258 });
259
260 #[allow(unused_mut)] 254 #[allow(unused_mut)]
261 let mut config = Config::default(); 255 let mut config = Config::default();
262 256