Merge pull request #4435 from bespsm/mspm0-i2c

MSPM0: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs)
This commit is contained in:
i509VCB 2025-08-14 20:36:40 +00:00 committed by GitHub
commit 32f142d585
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 1421 additions and 2 deletions

View File

@ -0,0 +1,10 @@
# Changelog for embassy-mspm0
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased - ReleaseDate
- feat: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs) (#4435)

View File

@ -35,6 +35,7 @@ embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", fe
embassy-embedded-hal = { version = "0.4.0", path = "../embassy-embedded-hal", default-features = false }
embassy-executor = { version = "0.8.0", path = "../embassy-executor", optional = true }
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
embedded-hal = { version = "1.0" }
embedded-hal-nb = { version = "1.0" }
embedded-hal-async = { version = "1.0" }
@ -49,7 +50,7 @@ cortex-m = "0.7.6"
critical-section = "1.2.0"
# mspm0-metapac = { version = "" }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-235158ac2865d8aac3a1eceb2d62026eb12bf38f" }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-df572e257eabf06e6e0ae6c9077e0a2fec1fb5e1" }
[build-dependencies]
proc-macro2 = "1.0.94"
@ -57,7 +58,7 @@ quote = "1.0.40"
cfg_aliases = "0.2.1"
# mspm0-metapac = { version = "", default-features = false, features = ["metadata"] }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-235158ac2865d8aac3a1eceb2d62026eb12bf38f", default-features = false, features = ["metadata"] }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-df572e257eabf06e6e0ae6c9077e0a2fec1fb5e1", default-features = false, features = ["metadata"] }
[features]
default = ["rt"]

View File

@ -549,9 +549,11 @@ fn generate_peripheral_instances() -> TokenStream {
for peripheral in METADATA.peripherals {
let peri = format_ident!("{}", peripheral.name);
let fifo_size = peripheral.sys_fentries;
let tokens = match peripheral.kind {
"uart" => Some(quote! { impl_uart_instance!(#peri); }),
"i2c" => Some(quote! { impl_i2c_instance!(#peri, #fifo_size); }),
_ => None,
};
@ -598,6 +600,9 @@ fn generate_pin_trait_impls() -> TokenStream {
("uart", "RX") => Some(quote! { impl_uart_rx_pin!(#peri, #pin_name, #pf); }),
("uart", "CTS") => Some(quote! { impl_uart_cts_pin!(#peri, #pin_name, #pf); }),
("uart", "RTS") => Some(quote! { impl_uart_rts_pin!(#peri, #pin_name, #pf); }),
("i2c", "SDA") => Some(quote! { impl_i2c_sda_pin!(#peri, #pin_name, #pf); }),
("i2c", "SCL") => Some(quote! { impl_i2c_scl_pin!(#peri, #pin_name, #pf); }),
_ => None,
};

1208
embassy-mspm0/src/i2c.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@ mod macros;
pub mod dma;
pub mod gpio;
pub mod i2c;
pub mod timer;
pub mod uart;

View File

@ -0,0 +1,45 @@
//! This example uses FIFO with polling, and the maximum FIFO size is 8.
//! Refer to async example to handle larger packets.
//!
//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0G3507 board.
#![no_std]
#![no_main]
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;
#[embassy_executor::main]
async fn main(_spawner: Spawner) -> ! {
let p = embassy_mspm0::init(Default::default());
let instance = p.I2C1;
let scl = p.PB2;
let sda = p.PB3;
let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default()));
let mut pot_value: u8 = 0;
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),
}
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;
}
}

View File

@ -0,0 +1,50 @@
//! The example uses FIFO and interrupts, wrapped in async API.
//!
//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0G3507 board.
#![no_std]
#![no_main]
use defmt::*;
use embassy_executor::Spawner;
use embassy_mspm0::bind_interrupts;
use embassy_mspm0::i2c::{Config, I2c, InterruptHandler};
use embassy_mspm0::peripherals::I2C1;
use embassy_time::Timer;
use {defmt_rtt as _, panic_halt as _};
const ADDRESS: u8 = 0x6a;
bind_interrupts!(struct Irqs {
I2C1 => InterruptHandler<I2C1>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) -> ! {
let p = embassy_mspm0::init(Default::default());
let instance = p.I2C1;
let scl = p.PB2;
let sda = p.PB3;
let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default()));
let mut pot_value: u8 = 0;
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),
}
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;
}
}

View File

@ -19,3 +19,7 @@ panic-semihosting = "0.6.0"
[profile.release]
debug = 2
[profile.dev]
debug = 2
opt-level = 2

View File

@ -0,0 +1,45 @@
//! This example uses FIFO with polling, and the maximum FIFO size is 8.
//! Refer to async example to handle larger packets.
//!
//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board.
#![no_std]
#![no_main]
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 = 0x2c;
#[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 i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default()));
let mut pot_value: u8 = 0;
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),
}
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;
}
}

View File

@ -0,0 +1,50 @@
//! The example uses FIFO and interrupts, wrapped in async API.
//!
//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board.
#![no_std]
#![no_main]
use defmt::*;
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;
bind_interrupts!(struct Irqs {
I2C0 => InterruptHandler<I2C0>;
});
#[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 i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default()));
let mut pot_value: u8 = 0;
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),
}
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;
}
}