aboutsummaryrefslogtreecommitdiff
path: root/examples/mspm0l1306
diff options
context:
space:
mode:
Diffstat (limited to 'examples/mspm0l1306')
-rw-r--r--examples/mspm0l1306/.cargo/config.toml9
-rw-r--r--examples/mspm0l1306/Cargo.toml31
-rw-r--r--examples/mspm0l1306/README.md27
-rw-r--r--examples/mspm0l1306/build.rs37
-rw-r--r--examples/mspm0l1306/memory.x5
-rw-r--r--examples/mspm0l1306/src/bin/adc.rs39
-rw-r--r--examples/mspm0l1306/src/bin/blinky.rs25
-rw-r--r--examples/mspm0l1306/src/bin/button.rs33
-rw-r--r--examples/mspm0l1306/src/bin/i2c.rs45
-rw-r--r--examples/mspm0l1306/src/bin/i2c_async.rs50
-rw-r--r--examples/mspm0l1306/src/bin/i2c_target.rs63
-rw-r--r--examples/mspm0l1306/src/bin/uart.rs35
-rw-r--r--examples/mspm0l1306/src/bin/wwdt.rs54
13 files changed, 453 insertions, 0 deletions
diff --git a/examples/mspm0l1306/.cargo/config.toml b/examples/mspm0l1306/.cargo/config.toml
new file mode 100644
index 000000000..93f148a71
--- /dev/null
+++ b/examples/mspm0l1306/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace MSPM0L1306 with your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --chip MSPM0L1306 --protocol=swd"
4
5[build]
6target = "thumbv6m-none-eabi"
7
8[env]
9DEFMT_LOG = "trace"
diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml
new file mode 100644
index 000000000..d5b5e9d3e
--- /dev/null
+++ b/examples/mspm0l1306/Cargo.toml
@@ -0,0 +1,31 @@
1[package]
2edition = "2024"
3name = "embassy-mspm0-l1306-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l1306rhb", "defmt", "rt", "time-driver-any"] }
10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] }
13panic-halt = "1.0.0"
14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
15cortex-m-rt = { version = "0.7.0"}
16defmt = "1.0.1"
17defmt-rtt = "1.0.0"
18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
19panic-semihosting = "0.6.0"
20
21[profile.release]
22debug = 2
23
24[profile.dev]
25debug = 2
26opt-level = 2
27
28[package.metadata.embassy]
29build = [
30 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0l1306" }
31]
diff --git a/examples/mspm0l1306/README.md b/examples/mspm0l1306/README.md
new file mode 100644
index 000000000..4d698e0fa
--- /dev/null
+++ b/examples/mspm0l1306/README.md
@@ -0,0 +1,27 @@
1# Examples for MSPM0L1306
2
3Run individual examples with
4```
5cargo run --bin <module-name>
6```
7for example
8```
9cargo run --bin blinky
10```
11
12## Checklist before running examples
13A large number of the examples are written for the [LP-MSPM0L1306](https://www.ti.com/tool/LP-MSPM0L1306) board.
14
15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
16
17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L1306 it should be `probe-rs run --chip MSPM0L1306`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0L1306 it should be `mspm0l1306rhb`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip.
19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
21
22If you are unsure, please drop by the Embassy Matrix chat for support, and let us know:
23
24* Which example you are trying to run
25* Which chip and board you are using
26
27Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org
diff --git a/examples/mspm0l1306/build.rs b/examples/mspm0l1306/build.rs
new file mode 100644
index 000000000..2d777c2d3
--- /dev/null
+++ b/examples/mspm0l1306/build.rs
@@ -0,0 +1,37 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
16fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31
32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35 // You must tell cargo to link interrupt groups if the rt feature is enabled.
36 println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x");
37}
diff --git a/examples/mspm0l1306/memory.x b/examples/mspm0l1306/memory.x
new file mode 100644
index 000000000..d93b61f44
--- /dev/null
+++ b/examples/mspm0l1306/memory.x
@@ -0,0 +1,5 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 64K
4 RAM : ORIGIN = 0x20000000, LENGTH = 4K
5}
diff --git a/examples/mspm0l1306/src/bin/adc.rs b/examples/mspm0l1306/src/bin/adc.rs
new file mode 100644
index 000000000..235396b8a
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/adc.rs
@@ -0,0 +1,39 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::adc::{self, Adc, Vrsel};
7use embassy_mspm0::{Config, bind_interrupts, peripherals};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _};
10
11bind_interrupts!(struct Irqs {
12 ADC0 => adc::InterruptHandler<peripherals::ADC0>;
13});
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) -> ! {
17 info!("Hello world!");
18 let p = embassy_mspm0::init(Config::default());
19
20 // Configure adc with sequence 0 to 1
21 let mut adc = Adc::new_async(p.ADC0, Default::default(), Irqs);
22 let sequence = [(&p.PA22.into(), Vrsel::VddaVssa), (&p.PA20.into(), Vrsel::VddaVssa)];
23 let mut readings = [0u16; 2];
24
25 loop {
26 let r = adc.read_channel(&p.PA27).await;
27 info!("Raw adc PA27: {}", r);
28 // With a voltage range of 0-3.3V and a resolution of 12 bits, the raw value can be
29 // approximated to voltage (~0.0008 per step).
30 let mut x = r as u32;
31 x = x * 8;
32 info!("Adc voltage PA27: {},{:#04}", x / 10_000, x % 10_000);
33 // Read a sequence of channels
34 adc.read_sequence(sequence.into_iter(), &mut readings).await;
35 info!("Raw adc sequence: {}", readings);
36
37 Timer::after_millis(400).await;
38 }
39}
diff --git a/examples/mspm0l1306/src/bin/blinky.rs b/examples/mspm0l1306/src/bin/blinky.rs
new file mode 100644
index 000000000..47eaf1535
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/blinky.rs
@@ -0,0 +1,25 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Level, Output};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) -> ! {
13 info!("Hello world!");
14 let p = embassy_mspm0::init(Config::default());
15
16 let mut led1 = Output::new(p.PA0, Level::Low);
17 led1.set_inversion(true);
18
19 loop {
20 Timer::after_millis(400).await;
21
22 info!("Toggle");
23 led1.toggle();
24 }
25}
diff --git a/examples/mspm0l1306/src/bin/button.rs b/examples/mspm0l1306/src/bin/button.rs
new file mode 100644
index 000000000..33e682272
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/button.rs
@@ -0,0 +1,33 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Input, Level, Output, Pull};
8use {defmt_rtt as _, panic_halt as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) -> ! {
12 info!("Hello world!");
13
14 let p = embassy_mspm0::init(Config::default());
15
16 let led1 = p.PA0;
17 let s2 = p.PA14;
18
19 let mut led1 = Output::new(led1, Level::Low);
20
21 let mut s2 = Input::new(s2, Pull::Up);
22
23 // led1 is active low
24 led1.set_high();
25
26 loop {
27 s2.wait_for_falling_edge().await;
28
29 info!("Switch 2 was pressed");
30
31 led1.toggle();
32 }
33}
diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs
new file mode 100644
index 000000000..e8801c485
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/i2c.rs
@@ -0,0 +1,45 @@
1//! This example uses FIFO with polling, and the maximum FIFO size is 8.
2//! Refer to async example to handle larger packets.
3//!
4//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board.
5
6#![no_std]
7#![no_main]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_mspm0::i2c::{Config, I2c};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15const ADDRESS: u8 = 0x2c;
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) -> ! {
19 let p = embassy_mspm0::init(Default::default());
20
21 let instance = p.I2C0;
22 let scl = p.PA1;
23 let sda = p.PA0;
24
25 let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default()));
26
27 let mut pot_value: u8 = 0;
28
29 loop {
30 let to_write = [0u8, pot_value];
31
32 match i2c.blocking_write(ADDRESS, &to_write) {
33 Ok(()) => info!("New potentioemter value: {}", pot_value),
34 Err(e) => error!("I2c Error: {:?}", e),
35 }
36
37 pot_value += 1;
38 // if reached 64th position (max)
39 // start over from lowest value
40 if pot_value == 64 {
41 pot_value = 0;
42 }
43 Timer::after_millis(500).await;
44 }
45}
diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs
new file mode 100644
index 000000000..c4a6938ff
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/i2c_async.rs
@@ -0,0 +1,50 @@
1//! The example uses FIFO and interrupts, wrapped in async API.
2//!
3//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::bind_interrupts;
11use embassy_mspm0::i2c::{Config, I2c, InterruptHandler};
12use embassy_mspm0::peripherals::I2C0;
13use embassy_time::Timer;
14use {defmt_rtt as _, panic_halt as _};
15
16const ADDRESS: u8 = 0x6a;
17
18bind_interrupts!(struct Irqs {
19 I2C0 => InterruptHandler<I2C0>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) -> ! {
24 let p = embassy_mspm0::init(Default::default());
25
26 let instance = p.I2C0;
27 let scl = p.PA1;
28 let sda = p.PA0;
29
30 let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default()));
31
32 let mut pot_value: u8 = 0;
33
34 loop {
35 let to_write = [0u8, pot_value];
36
37 match i2c.async_write(ADDRESS, &to_write).await {
38 Ok(()) => info!("New potentioemter value: {}", pot_value),
39 Err(e) => error!("I2c Error: {:?}", e),
40 }
41
42 pot_value += 1;
43 // if reached 64th position (max)
44 // start over from lowest value
45 if pot_value == 64 {
46 pot_value = 0;
47 }
48 Timer::after_millis(500).await;
49 }
50}
diff --git a/examples/mspm0l1306/src/bin/i2c_target.rs b/examples/mspm0l1306/src/bin/i2c_target.rs
new file mode 100644
index 000000000..4d147d08b
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/i2c_target.rs
@@ -0,0 +1,63 @@
1//! Example of using async I2C target
2//!
3//! This uses the virtual COM port provided on the LP-MSPM0L1306 board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::i2c::Config;
11use embassy_mspm0::i2c_target::{Command, Config as TargetConfig, I2cTarget, ReadStatus};
12use embassy_mspm0::peripherals::I2C0;
13use embassy_mspm0::{bind_interrupts, i2c};
14use {defmt_rtt as _, panic_halt as _};
15
16bind_interrupts!(struct Irqs {
17 I2C0 => i2c::InterruptHandler<I2C0>;
18});
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) -> ! {
22 let p = embassy_mspm0::init(Default::default());
23
24 let instance = p.I2C0;
25 let scl = p.PA1;
26 let sda = p.PA0;
27
28 let config = Config::default();
29 let mut target_config = TargetConfig::default();
30 target_config.target_addr = 0x48;
31 target_config.general_call = true;
32 let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config, target_config).unwrap();
33
34 let mut read = [0u8; 8];
35 let data = [8u8; 2];
36 let data_wr = [9u8; 2];
37
38 loop {
39 match i2c.listen(&mut read).await {
40 Ok(Command::GeneralCall(_)) => info!("General call received"),
41 Ok(Command::Read) => {
42 info!("Read command received");
43 match i2c.respond_to_read(&data).await.unwrap() {
44 ReadStatus::Done => info!("Finished reading"),
45 ReadStatus::NeedMoreBytes => {
46 info!("Read needs more bytes - will reset");
47 i2c.reset().unwrap();
48 }
49 ReadStatus::LeftoverBytes(_) => {
50 info!("Leftover bytes received");
51 i2c.flush_tx_fifo();
52 }
53 }
54 }
55 Ok(Command::Write(_)) => info!("Write command received"),
56 Ok(Command::WriteRead(_)) => {
57 info!("Write-Read command received");
58 i2c.respond_and_fill(&data_wr, 0xFE).await.unwrap();
59 }
60 Err(e) => info!("Got error {}", e),
61 }
62 }
63}
diff --git a/examples/mspm0l1306/src/bin/uart.rs b/examples/mspm0l1306/src/bin/uart.rs
new file mode 100644
index 000000000..95c56fdd3
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/uart.rs
@@ -0,0 +1,35 @@
1//! Example of using blocking uart
2//!
3//! This uses the virtual COM port provided on the LP-MSPM0L1306 board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::uart::{Config, Uart};
11use {defmt_rtt as _, panic_halt as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) -> ! {
15 info!("Hello world!");
16
17 let p = embassy_mspm0::init(Default::default());
18
19 let instance = p.UART0;
20 let tx = p.PA8;
21 let rx = p.PA9;
22
23 let config = Config::default();
24 let mut uart = unwrap!(Uart::new_blocking(instance, rx, tx, config));
25
26 unwrap!(uart.blocking_write(b"Hello Embassy World!\r\n"));
27 info!("wrote Hello, starting echo");
28
29 let mut buf = [0u8; 1];
30
31 loop {
32 unwrap!(uart.blocking_read(&mut buf));
33 unwrap!(uart.blocking_write(&buf));
34 }
35}
diff --git a/examples/mspm0l1306/src/bin/wwdt.rs b/examples/mspm0l1306/src/bin/wwdt.rs
new file mode 100644
index 000000000..b8fb1a1cd
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/wwdt.rs
@@ -0,0 +1,54 @@
1//! Example of using window watchdog timer in the MSPM0L1306 chip.
2//!
3//! It tests the use case when watchdog timer is expired and when watchdog is pet too early.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::gpio::{Level, Output};
11use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) -> ! {
17 info!("Hello world!");
18
19 let p = embassy_mspm0::init(Default::default());
20 let mut conf = Config::default();
21 conf.timeout = Timeout::Sec1;
22
23 // watchdog also resets the system if the pet comes too early,
24 // less than 250 msec == 25% from 1 sec
25 conf.closed_window = ClosedWindowPercentage::TwentyFive;
26 let mut wdt = Watchdog::new(p.WWDT0, conf);
27 info!("Started the watchdog timer");
28
29 let mut led1 = Output::new(p.PA0, Level::High);
30 led1.set_inversion(true);
31 Timer::after_millis(900).await;
32
33 for _ in 1..=5 {
34 info!("pet watchdog");
35 led1.toggle();
36 wdt.pet();
37 Timer::after_millis(500).await;
38 }
39
40 // watchdog timeout test
41 info!("Stopped the pet command, device will reset in less than 1 second");
42 loop {
43 led1.toggle();
44 Timer::after_millis(500).await;
45 }
46
47 // watchdog "too early" test
48 // info!("Device will reset when the pet comes too early");
49 // loop {
50 // led1.toggle();
51 // wdt.pet();
52 // Timer::after_millis(200).await;
53 // }
54}