From f9753f3d314ca00fb36103fa39b0911d3e3047ba Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Mon, 21 Jul 2025 14:22:32 +0200 Subject: mspm0: Add I2C Controller examples for mspm0l1306, mspm0g3507 MCUs - mspm0l1306 examples: add I2C blocking & async examples - mspm0l1306 examples: add -O2 optimization due to Flash limitations - mspm0g3507 examples: add I2C blocking & async examples --- examples/mspm0l1306/src/bin/i2c.rs | 37 +++++++++++++++++++++++++++ examples/mspm0l1306/src/bin/i2c_async.rs | 43 ++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 examples/mspm0l1306/src/bin/i2c.rs create mode 100644 examples/mspm0l1306/src/bin/i2c_async.rs (limited to 'examples/mspm0l1306/src/bin') diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs new file mode 100644 index 000000000..02c0ee740 --- /dev/null +++ b/examples/mspm0l1306/src/bin/i2c.rs @@ -0,0 +1,37 @@ +//! Example of using blocking I2C +//! +//! This uses the virtual COM port provided on the LP-MSPM0L1306 board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c}; +use {defmt_rtt as _, panic_halt as _}; + +const ADDRESS: u8 = 0x6a; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_mspm0::init(Default::default()); + + let instance = p.I2C0; + let scl = p.PA1; + let sda = p.PA0; + + let mut config = Config::default(); + config.clock_source = ClockSel::BusClk; + config.bus_speed = BusSpeed::FastMode; + let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, config)); + + let mut to_read = [0u8; 1]; + let to_write: u8 = 0x0F; + + match i2c.blocking_write_read(ADDRESS, &[to_write], &mut to_read) { + Ok(()) => info!("Register {}: {}", to_write, to_read[0]), + Err(e) => error!("I2c Error: {:?}", e), + } + + loop {} +} diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs new file mode 100644 index 000000000..34e2c64e7 --- /dev/null +++ b/examples/mspm0l1306/src/bin/i2c_async.rs @@ -0,0 +1,43 @@ +//! Example of using async I2C +//! +//! This uses the virtual COM port provided on the LP-MSPM0L1306 board. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::bind_interrupts; +use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c, InterruptHandler}; +use embassy_mspm0::peripherals::I2C0; +use {defmt_rtt as _, panic_halt as _}; + +const ADDRESS: u8 = 0x6a; + +bind_interrupts!(struct Irqs { + I2C0 => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let p = embassy_mspm0::init(Default::default()); + + let instance = p.I2C0; + let scl = p.PA1; + let sda = p.PA0; + + let mut config = Config::default(); + config.clock_source = ClockSel::BusClk; + config.bus_speed = BusSpeed::FastMode; + let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, config)); + + let mut to_read = [0u8; 1]; + let to_write: u8 = 0x0F; + + match i2c.async_write_read(ADDRESS, &[to_write], &mut to_read).await { + Ok(()) => info!("Register {}: {}", to_write, to_read[0]), + Err(e) => error!("I2c Error: {:?}", e), + } + + loop {} +} -- cgit From 917a509c1a899d7054f1a9cf2a21369dc143f46b Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Wed, 23 Jul 2025 17:00:10 +0200 Subject: mspm0-I2C: automate source clock definition - i2c-config: automatically defines clock source based on input I2C rate - i2c: proper config functions naming - i2c-examples: adapt to changed API - i2c: save initialization pf cctr register --- examples/mspm0l1306/src/bin/i2c.rs | 7 ++----- examples/mspm0l1306/src/bin/i2c_async.rs | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'examples/mspm0l1306/src/bin') diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs index 02c0ee740..cf65206b2 100644 --- a/examples/mspm0l1306/src/bin/i2c.rs +++ b/examples/mspm0l1306/src/bin/i2c.rs @@ -7,7 +7,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c}; +use embassy_mspm0::i2c::{Config, I2c}; use {defmt_rtt as _, panic_halt as _}; const ADDRESS: u8 = 0x6a; @@ -20,10 +20,7 @@ async fn main(_spawner: Spawner) -> ! { let scl = p.PA1; let sda = p.PA0; - let mut config = Config::default(); - config.clock_source = ClockSel::BusClk; - config.bus_speed = BusSpeed::FastMode; - let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, config)); + let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default())); let mut to_read = [0u8; 1]; let to_write: u8 = 0x0F; diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs index 34e2c64e7..a54beebe5 100644 --- a/examples/mspm0l1306/src/bin/i2c_async.rs +++ b/examples/mspm0l1306/src/bin/i2c_async.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::bind_interrupts; -use embassy_mspm0::i2c::{BusSpeed, ClockSel, Config, I2c, InterruptHandler}; +use embassy_mspm0::i2c::{Config, I2c, InterruptHandler}; use embassy_mspm0::peripherals::I2C0; use {defmt_rtt as _, panic_halt as _}; @@ -26,10 +26,7 @@ async fn main(_spawner: Spawner) -> ! { let scl = p.PA1; let sda = p.PA0; - let mut config = Config::default(); - config.clock_source = ClockSel::BusClk; - config.bus_speed = BusSpeed::FastMode; - let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, config)); + let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); let mut to_read = [0u8; 1]; let to_write: u8 = 0x0F; -- cgit From d6a87b411432d9c6eedd48aa30b72cda069bd86c Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Tue, 29 Jul 2025 15:26:34 +0200 Subject: mspm0-I2C: mention blocking API's restrictions - blocking API for transfering max 8 bytes - async API has no such limitations --- examples/mspm0l1306/src/bin/i2c.rs | 3 ++- examples/mspm0l1306/src/bin/i2c_async.rs | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'examples/mspm0l1306/src/bin') diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs index cf65206b2..51327dff5 100644 --- a/examples/mspm0l1306/src/bin/i2c.rs +++ b/examples/mspm0l1306/src/bin/i2c.rs @@ -1,4 +1,5 @@ -//! Example of using blocking I2C +//! This example uses FIFO with polling, and the maximum FIFO size is 8. +//! Refer to async example to handle larger packets. //! //! This uses the virtual COM port provided on the LP-MSPM0L1306 board. diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs index a54beebe5..74826bcc4 100644 --- a/examples/mspm0l1306/src/bin/i2c_async.rs +++ b/examples/mspm0l1306/src/bin/i2c_async.rs @@ -1,4 +1,4 @@ -//! Example of using async I2C +//! The example uses FIFO and interrupts, wrapped in async API. //! //! This uses the virtual COM port provided on the LP-MSPM0L1306 board. @@ -28,10 +28,10 @@ async fn main(_spawner: Spawner) -> ! { let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); - let mut to_read = [0u8; 1]; - let to_write: u8 = 0x0F; + let mut to_read = [1u8; 17]; + let to_write = [0u8; 17]; - match i2c.async_write_read(ADDRESS, &[to_write], &mut to_read).await { + match i2c.async_write_read(ADDRESS, &to_write, &mut to_read).await { Ok(()) => info!("Register {}: {}", to_write, to_read[0]), Err(e) => error!("I2c Error: {:?}", e), } -- cgit From e78959ed67f8c89f2adc78f5e4580c62d3c66081 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Mon, 4 Aug 2025 13:10:39 +0200 Subject: mspm0-I2C: replace examples for mspm0l1306 & mspm0g3507 with AD5171 --- examples/mspm0l1306/src/bin/i2c.rs | 28 +++++++++++++++++++--------- examples/mspm0l1306/src/bin/i2c_async.rs | 26 ++++++++++++++++++-------- 2 files changed, 37 insertions(+), 17 deletions(-) (limited to 'examples/mspm0l1306/src/bin') diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs index 51327dff5..e8801c485 100644 --- a/examples/mspm0l1306/src/bin/i2c.rs +++ b/examples/mspm0l1306/src/bin/i2c.rs @@ -1,7 +1,7 @@ //! This example uses FIFO with polling, and the maximum FIFO size is 8. //! Refer to async example to handle larger packets. //! -//! This uses the virtual COM port provided on the LP-MSPM0L1306 board. +//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board. #![no_std] #![no_main] @@ -9,9 +9,10 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::i2c::{Config, I2c}; +use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; -const ADDRESS: u8 = 0x6a; +const ADDRESS: u8 = 0x2c; #[embassy_executor::main] async fn main(_spawner: Spawner) -> ! { @@ -23,13 +24,22 @@ async fn main(_spawner: Spawner) -> ! { let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default())); - let mut to_read = [0u8; 1]; - let to_write: u8 = 0x0F; + let mut pot_value: u8 = 0; - match i2c.blocking_write_read(ADDRESS, &[to_write], &mut to_read) { - Ok(()) => info!("Register {}: {}", to_write, to_read[0]), - Err(e) => error!("I2c Error: {:?}", e), - } + loop { + let to_write = [0u8, pot_value]; + + match i2c.blocking_write(ADDRESS, &to_write) { + Ok(()) => info!("New potentioemter value: {}", pot_value), + Err(e) => error!("I2c Error: {:?}", e), + } - loop {} + pot_value += 1; + // if reached 64th position (max) + // start over from lowest value + if pot_value == 64 { + pot_value = 0; + } + Timer::after_millis(500).await; + } } diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs index 74826bcc4..c4a6938ff 100644 --- a/examples/mspm0l1306/src/bin/i2c_async.rs +++ b/examples/mspm0l1306/src/bin/i2c_async.rs @@ -1,6 +1,6 @@ //! The example uses FIFO and interrupts, wrapped in async API. //! -//! This uses the virtual COM port provided on the LP-MSPM0L1306 board. +//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board. #![no_std] #![no_main] @@ -10,6 +10,7 @@ use embassy_executor::Spawner; use embassy_mspm0::bind_interrupts; use embassy_mspm0::i2c::{Config, I2c, InterruptHandler}; use embassy_mspm0::peripherals::I2C0; +use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; const ADDRESS: u8 = 0x6a; @@ -28,13 +29,22 @@ async fn main(_spawner: Spawner) -> ! { let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default())); - let mut to_read = [1u8; 17]; - let to_write = [0u8; 17]; + let mut pot_value: u8 = 0; - match i2c.async_write_read(ADDRESS, &to_write, &mut to_read).await { - Ok(()) => info!("Register {}: {}", to_write, to_read[0]), - Err(e) => error!("I2c Error: {:?}", e), - } + loop { + let to_write = [0u8, pot_value]; + + match i2c.async_write(ADDRESS, &to_write).await { + Ok(()) => info!("New potentioemter value: {}", pot_value), + Err(e) => error!("I2c Error: {:?}", e), + } - loop {} + pot_value += 1; + // if reached 64th position (max) + // start over from lowest value + if pot_value == 64 { + pot_value = 0; + } + Timer::after_millis(500).await; + } } -- cgit From 93ba2c9c95721f1fe16269f09c219b161b2969cb Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 21 Aug 2025 09:32:05 +0200 Subject: mspm0-watchdog: add watchdog examples for all chips --- examples/mspm0l1306/src/bin/wwdt.rs | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 examples/mspm0l1306/src/bin/wwdt.rs (limited to 'examples/mspm0l1306/src/bin') diff --git a/examples/mspm0l1306/src/bin/wwdt.rs b/examples/mspm0l1306/src/bin/wwdt.rs new file mode 100644 index 000000000..f2bbe5701 --- /dev/null +++ b/examples/mspm0l1306/src/bin/wwdt.rs @@ -0,0 +1,54 @@ +//! Example of using window watchdog timer in the MSPM0L1306 chip. +//! +//! It tests the use case when watchdog timer is expired and when watchdog is pet too early. + +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_mspm0::gpio::{Level, Output}; +use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_halt as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + info!("Hello world!"); + + let p = embassy_mspm0::init(Default::default()); + let mut conf = Config::default(); + conf.timeout = Timeout::Sec1; + + // watchdog also resets the system if the pet comes too early, + // less than 250 msec == 25% from 1 sec + conf.closed_window = ClosedWindowPercentage::TwentyFive; + let mut wdt = Watchdog::new(p.WWDT0, conf); + info!("Started the watchdog timer"); + + let mut led1 = Output::new(p.PA0, Level::High); + led1.set_inversion(true); + Timer::after_millis(900).await; + + for _ in 1..=5 { + info!("pet watchdog"); + led1.toggle(); + wdt.pet(); + Timer::after_millis(500).await; + } + + // watchdog timeout test + info!("Stopped the pet command, device will reset in less than 1 second"); + loop { + led1.toggle(); + Timer::after_millis(500).await; + } + + // watchdog "too early" test + // info!("Device will reset when the pet comes too early"); + // loop { + // led1.toggle(); + // wdt.pet(); + // Timer::after_millis(200).await; + // } +} -- cgit From 2eb643bac66844dccddc11065c3debbaef468595 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Tue, 26 Aug 2025 08:19:12 +0200 Subject: mspm0-watchdog: rename mod watchdog to wwdt --- examples/mspm0l1306/src/bin/wwdt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/mspm0l1306/src/bin') diff --git a/examples/mspm0l1306/src/bin/wwdt.rs b/examples/mspm0l1306/src/bin/wwdt.rs index f2bbe5701..b8fb1a1cd 100644 --- a/examples/mspm0l1306/src/bin/wwdt.rs +++ b/examples/mspm0l1306/src/bin/wwdt.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_mspm0::gpio::{Level, Output}; -use embassy_mspm0::watchdog::{ClosedWindowPercentage, Config, Timeout, Watchdog}; +use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog}; use embassy_time::Timer; use {defmt_rtt as _, panic_halt as _}; -- cgit