aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/settings.json5
-rw-r--r--embassy-mspm0/Cargo.toml125
-rw-r--r--embassy-mspm0/build.rs616
-rw-r--r--embassy-mspm0/build_common.rs94
-rw-r--r--embassy-mspm0/src/fmt.rs270
-rw-r--r--embassy-mspm0/src/gpio.rs1070
-rw-r--r--embassy-mspm0/src/int_group/c110x.rs25
-rw-r--r--embassy-mspm0/src/int_group/g350x.rs51
-rw-r--r--embassy-mspm0/src/int_group/g351x.rs52
-rw-r--r--embassy-mspm0/src/int_group/l130x.rs46
-rw-r--r--embassy-mspm0/src/int_group/l222x.rs49
-rw-r--r--embassy-mspm0/src/lib.rs112
-rw-r--r--embassy-mspm0/src/time_driver.rs437
-rw-r--r--embassy-mspm0/src/timer.rs48
-rw-r--r--examples/mspm0c1104/.cargo/config.toml11
-rw-r--r--examples/mspm0c1104/Cargo.toml32
-rw-r--r--examples/mspm0c1104/README.md27
-rw-r--r--examples/mspm0c1104/build.rs35
-rw-r--r--examples/mspm0c1104/memory.x5
-rw-r--r--examples/mspm0c1104/src/bin/blinky.rs27
-rw-r--r--examples/mspm0c1104/src/bin/button.rs35
-rw-r--r--examples/mspm0g3507/.cargo/config.toml9
-rw-r--r--examples/mspm0g3507/Cargo.toml21
-rw-r--r--examples/mspm0g3507/README.md27
-rw-r--r--examples/mspm0g3507/build.rs35
-rw-r--r--examples/mspm0g3507/memory.x6
-rw-r--r--examples/mspm0g3507/src/bin/blinky.rs27
-rw-r--r--examples/mspm0g3507/src/bin/button.rs35
-rw-r--r--examples/mspm0g3519/.cargo/config.toml10
-rw-r--r--examples/mspm0g3519/Cargo.toml21
-rw-r--r--examples/mspm0g3519/MSPM0GX51X_Series.yaml424
-rw-r--r--examples/mspm0g3519/README.md27
-rw-r--r--examples/mspm0g3519/build.rs35
-rw-r--r--examples/mspm0g3519/memory.x6
-rw-r--r--examples/mspm0g3519/src/bin/blinky.rs27
-rw-r--r--examples/mspm0g3519/src/bin/button.rs35
-rw-r--r--examples/mspm0l1306/.cargo/config.toml9
-rw-r--r--examples/mspm0l1306/Cargo.toml21
-rw-r--r--examples/mspm0l1306/README.md27
-rw-r--r--examples/mspm0l1306/build.rs35
-rw-r--r--examples/mspm0l1306/memory.x5
-rw-r--r--examples/mspm0l1306/src/bin/blinky.rs27
-rw-r--r--examples/mspm0l1306/src/bin/button.rs35
-rw-r--r--examples/mspm0l2228/.cargo/config.toml10
-rw-r--r--examples/mspm0l2228/Cargo.toml21
-rw-r--r--examples/mspm0l2228/MSPM0L122X_L222X_Series.yaml239
-rw-r--r--examples/mspm0l2228/README.md27
-rw-r--r--examples/mspm0l2228/build.rs35
-rw-r--r--examples/mspm0l2228/memory.x6
-rw-r--r--examples/mspm0l2228/src/bin/blinky.rs27
-rw-r--r--examples/mspm0l2228/src/bin/button.rs35
51 files changed, 4476 insertions, 0 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 48d0957e6..e4814ff27 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -28,6 +28,11 @@
28 // To work on the examples, comment the line above and all of the cargo.features lines, 28 // To work on the examples, comment the line above and all of the cargo.features lines,
29 // then uncomment ONE line below to select the chip you want to work on. 29 // then uncomment ONE line below to select the chip you want to work on.
30 // This makes rust-analyzer work on the example crate and all its dependencies. 30 // This makes rust-analyzer work on the example crate and all its dependencies.
31 // "examples/mspm0c1104/Cargo.toml",
32 // "examples/mspm0g3507/Cargo.toml",
33 // "examples/mspm0g3519/Cargo.toml",
34 // "examples/mspm0l1306/Cargo.toml",
35 // "examples/mspm0l2228/Cargo.toml",
31 // "examples/nrf52840-rtic/Cargo.toml", 36 // "examples/nrf52840-rtic/Cargo.toml",
32 // "examples/nrf5340/Cargo.toml", 37 // "examples/nrf5340/Cargo.toml",
33 // "examples/nrf-rtos-trace/Cargo.toml", 38 // "examples/nrf-rtos-trace/Cargo.toml",
diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml
new file mode 100644
index 000000000..0f4092d8a
--- /dev/null
+++ b/embassy-mspm0/Cargo.toml
@@ -0,0 +1,125 @@
1[package]
2name = "embassy-mspm0"
3version = "0.1.0"
4edition = "2021"
5license = "MIT OR Apache-2.0"
6description = "Embassy Hardware Abstraction Layer (HAL) for Texas Instruments MSPM0 series microcontrollers"
7keywords = ["embedded", "async", "mspm0", "hal", "embedded-hal"]
8categories = ["embedded", "hardware-support", "no-std", "asynchronous"]
9repository = "https://github.com/embassy-rs/embassy"
10documentation = "https://docs.embassy.dev/embassy-mspm0"
11
12[package.metadata.docs.rs]
13features = ["defmt", "unstable-pac", "time-driver-any", "time", "mspm0g3507"]
14rustdoc-args = ["--cfg", "docsrs"]
15
16[dependencies]
17embassy-sync = { version = "0.6.2", path = "../embassy-sync" }
18embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true }
19# TODO: Support other tick rates
20embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true, features = ["tick-hz-32_768"] }
21embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true }
22embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
23embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] }
24embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false }
25embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true }
26
27embedded-hal = { version = "1.0" }
28embedded-hal-async = { version = "1.0" }
29
30defmt = { version = "0.3", optional = true }
31log = { version = "0.4.14", optional = true }
32cortex-m-rt = ">=0.6.15,<0.8"
33cortex-m = "0.7.6"
34critical-section = "1.2.0"
35
36# mspm0-metapac = { version = "" }
37mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-9faa5239a8eab04946086158f2a7fdff5a6a179d" }
38
39[build-dependencies]
40proc-macro2 = "1.0.94"
41quote = "1.0.40"
42
43# mspm0-metapac = { version = "", default-features = false, features = ["metadata"] }
44mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-9faa5239a8eab04946086158f2a7fdff5a6a179d", default-features = false, features = ["metadata"] }
45
46[features]
47default = ["rt"]
48
49## Enable `mspm0-metapac`'s `rt` feature
50rt = ["mspm0-metapac/rt"]
51
52## Use [`defmt`](https://docs.rs/defmt/latest/defmt/) for logging
53defmt = [
54 "dep:defmt",
55 "embassy-sync/defmt",
56 "embassy-embedded-hal/defmt",
57 "embassy-hal-internal/defmt",
58 "embassy-time?/defmt",
59]
60
61## Re-export mspm0-metapac at `mspm0::pac`.
62## This is unstable because semver-minor (non-breaking) releases of embassy-mspm0 may major-bump (breaking) the mspm0-metapac version.
63## If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC.
64## There are no plans to make this stable.
65unstable-pac = []
66
67#! ## Time
68
69# Features starting with `_` are for internal use only. They're not intended
70# to be enabled by other crates, and are not covered by semver guarantees.
71_time-driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"]
72
73# Use any time driver
74time-driver-any = ["_time-driver"]
75## Use TIMG0 as time driver
76time-driver-timg0 = ["_time-driver"]
77## Use TIMG1 as time driver
78time-driver-timg1 = ["_time-driver"]
79## Use TIMG2 as time driver
80time-driver-timg2 = ["_time-driver"]
81## Use TIMG3 as time driver
82time-driver-timg3 = ["_time-driver"]
83## Use TIMG4 as time driver
84time-driver-timg4 = ["_time-driver"]
85## Use TIMG5 as time driver
86time-driver-timg5 = ["_time-driver"]
87## Use TIMG6 as time driver
88time-driver-timg6 = ["_time-driver"]
89## Use TIMG7 as time driver
90time-driver-timg7 = ["_time-driver"]
91## Use TIMG8 as time driver
92time-driver-timg8 = ["_time-driver"]
93## Use TIMG9 as time driver
94time-driver-timg9 = ["_time-driver"]
95## Use TIMG10 as time driver
96time-driver-timg10 = ["_time-driver"]
97## Use TIMG11 as time driver
98time-driver-timg11 = ["_time-driver"]
99# TODO: Support TIMG12 and TIMG13
100## Use TIMG14 as time driver
101time-driver-timg14 = ["_time-driver"]
102## Use TIMA0 as time driver
103time-driver-tima0 = ["_time-driver"]
104## Use TIMA1 as time driver
105time-driver-tima1 = ["_time-driver"]
106
107#! ## Chip-selection features
108#! Select your chip by specifying the model as a feature, e.g. `mspm0g3507`.
109#! Check the `Cargo.toml` for the latest list of supported chips.
110#!
111#! **Important:** Do not forget to adapt the target chip in your toolchain,
112#! e.g. in `.cargo/config.toml`.
113
114mspm0c110x = [ "mspm0-metapac/mspm0c110x" ]
115mspm0g110x = [ "mspm0-metapac/mspm0g110x" ]
116mspm0g150x = [ "mspm0-metapac/mspm0g150x" ]
117mspm0g151x = [ "mspm0-metapac/mspm0g151x" ]
118mspm0g310x = [ "mspm0-metapac/mspm0g310x" ]
119mspm0g350x = [ "mspm0-metapac/mspm0g350x" ]
120mspm0g351x = [ "mspm0-metapac/mspm0g351x" ]
121mspm0l110x = [ "mspm0-metapac/mspm0l110x" ]
122mspm0l122x = [ "mspm0-metapac/mspm0l122x" ]
123mspm0l130x = [ "mspm0-metapac/mspm0l130x" ]
124mspm0l134x = [ "mspm0-metapac/mspm0l134x" ]
125mspm0l222x = [ "mspm0-metapac/mspm0l222x" ]
diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs
new file mode 100644
index 000000000..ffbe15c56
--- /dev/null
+++ b/embassy-mspm0/build.rs
@@ -0,0 +1,616 @@
1use std::collections::HashMap;
2use std::io::Write;
3use std::path::{Path, PathBuf};
4use std::process::Command;
5use std::sync::LazyLock;
6use std::{env, fs};
7
8use common::CfgSet;
9use mspm0_metapac::metadata::METADATA;
10use proc_macro2::{Ident, Literal, Span, TokenStream};
11use quote::{format_ident, quote};
12
13#[path = "./build_common.rs"]
14mod common;
15
16fn main() {
17 generate_code();
18}
19
20fn generate_code() {
21 let mut cfgs = common::CfgSet::new();
22 common::set_target_cfgs(&mut cfgs);
23
24 cfgs.declare_all(&["gpio_pb", "gpio_pc", "int_group1"]);
25
26 let mut singletons = Vec::new();
27
28 // Generate singletons for GPIO pins. To only consider pins available on a family, use the name of
29 // the pins from the pincm mappings.
30 for pincm_mapping in METADATA.pincm_mappings.iter() {
31 singletons.push(pincm_mapping.pin.to_string());
32 }
33
34 for peri in METADATA.peripherals {
35 match peri.kind {
36 // Specially generated.
37 "gpio" => match peri.name {
38 "GPIOB" => cfgs.enable("gpio_pb"),
39 "GPIOC" => cfgs.enable("gpio_pc"),
40 _ => (),
41 },
42
43 // These peripherals are managed internally by the hal.
44 "iomux" | "cpuss" => {}
45
46 _ => singletons.push(peri.name.to_string()),
47 }
48 }
49
50 time_driver(&singletons, &mut cfgs);
51
52 // ========
53 // Write singletons
54 let mut g = TokenStream::new();
55
56 let singleton_tokens: Vec<_> = singletons.iter().map(|s| format_ident!("{}", s)).collect();
57
58 g.extend(quote! {
59 embassy_hal_internal::peripherals_definition!(#(#singleton_tokens),*);
60 });
61
62 g.extend(quote! {
63 embassy_hal_internal::peripherals_struct!(#(#singleton_tokens),*);
64 });
65
66 // ========
67 // Generate GPIO pincm lookup tables.
68 let pincms = METADATA.pincm_mappings.iter().map(|mapping| {
69 let port_letter = mapping.pin.strip_prefix("P").unwrap();
70 let port_base = (port_letter.chars().next().unwrap() as u8 - b'A') * 32;
71 // This assumes all ports are single letter length.
72 // This is fine unless TI releases a part with 833+ GPIO pins.
73 let pin_number = mapping.pin[2..].parse::<u8>().unwrap();
74
75 let num = port_base + pin_number;
76
77 // But subtract 1 since pincm indices start from 0, not 1.
78 let pincm = Literal::u8_unsuffixed(mapping.pincm - 1);
79 quote! {
80 #num => #pincm
81 }
82 });
83
84 g.extend(quote! {
85 #[doc = "Get the mapping from GPIO pin port to IOMUX PINCM index. This is required since the mapping from IO to PINCM index is not consistent across parts."]
86 pub(crate) fn gpio_pincm(pin_port: u8) -> u8 {
87 match pin_port {
88 #(#pincms),*,
89 _ => unreachable!(),
90 }
91 }
92 });
93
94 for pincm_mapping in METADATA.pincm_mappings.iter() {
95 let name = Ident::new(&pincm_mapping.pin, Span::call_site());
96 let port_letter = pincm_mapping.pin.strip_prefix("P").unwrap();
97 let port_letter = port_letter.chars().next().unwrap();
98 let pin_number = Literal::u8_unsuffixed(pincm_mapping.pin[2..].parse::<u8>().unwrap());
99
100 let port = Ident::new(&format!("Port{}", port_letter), Span::call_site());
101
102 // TODO: Feature gate pins that can be used as NRST
103
104 g.extend(quote! {
105 impl_pin!(#name, crate::gpio::Port::#port, #pin_number);
106 });
107 }
108
109 // Generate timers
110 for peripheral in METADATA
111 .peripherals
112 .iter()
113 .filter(|p| p.name.starts_with("TIM"))
114 {
115 let name = Ident::new(&peripheral.name, Span::call_site());
116 let timers = &*TIMERS;
117
118 let timer = timers.get(peripheral.name).expect("Timer does not exist");
119 assert!(timer.bits == 16 || timer.bits == 32);
120 let bits = if timer.bits == 16 {
121 quote! { Bits16 }
122 } else {
123 quote! { Bits32 }
124 };
125
126 g.extend(quote! {
127 impl_timer!(#name, #bits);
128 });
129 }
130
131 // Generate interrupt module
132 let interrupts: Vec<Ident> = METADATA
133 .interrupts
134 .iter()
135 .map(|interrupt| Ident::new(interrupt.name, Span::call_site()))
136 .collect();
137
138 g.extend(quote! {
139 embassy_hal_internal::interrupt_mod! {
140 #(#interrupts),*
141 }
142 });
143
144 let group_interrupt_enables = METADATA
145 .interrupts
146 .iter()
147 .filter(|interrupt| interrupt.name.contains("GROUP"))
148 .map(|interrupt| {
149 let name = Ident::new(interrupt.name, Span::call_site());
150
151 quote! {
152 crate::interrupt::typelevel::#name::enable();
153 }
154 });
155
156 // Generate interrupt enables for groups
157 g.extend(quote! {
158 pub fn enable_group_interrupts(_cs: critical_section::CriticalSection) {
159 use crate::interrupt::typelevel::Interrupt;
160
161 unsafe {
162 #(#group_interrupt_enables)*
163 }
164 }
165 });
166
167 let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
168 let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string();
169 fs::write(&out_file, g.to_string()).unwrap();
170 rustfmt(&out_file);
171}
172
173fn time_driver(singletons: &[String], cfgs: &mut CfgSet) {
174 // Timer features
175 for (timer, desc) in TIMERS.iter() {
176 if desc.bits != 16 {
177 continue;
178 }
179
180 let name = timer.to_lowercase();
181 cfgs.declare(&format!("time_driver_{}", name));
182 }
183
184 let time_driver = match env::vars()
185 .map(|(a, _)| a)
186 .filter(|x| x.starts_with("CARGO_FEATURE_TIME_DRIVER_"))
187 .get_one()
188 {
189 Ok(x) => Some(
190 x.strip_prefix("CARGO_FEATURE_TIME_DRIVER_")
191 .unwrap()
192 .to_ascii_lowercase(),
193 ),
194 Err(GetOneError::None) => None,
195 Err(GetOneError::Multiple) => panic!("Multiple time-driver-xxx Cargo features enabled"),
196 };
197
198 // Verify the selected timer is available
199 let singleton = match time_driver.as_ref().map(|x| x.as_ref()) {
200 None => "",
201 Some("timg0") => "TIMG0",
202 Some("timg1") => "TIMG1",
203 Some("timg2") => "TIMG2",
204 Some("timg3") => "TIMG3",
205 Some("timg4") => "TIMG4",
206 Some("timg5") => "TIMG5",
207 Some("timg6") => "TIMG6",
208 Some("timg7") => "TIMG7",
209 Some("timg8") => "TIMG8",
210 Some("timg9") => "TIMG9",
211 Some("timg10") => "TIMG10",
212 Some("timg11") => "TIMG11",
213 Some("timg14") => "TIMG14",
214 Some("tima0") => "TIMA0",
215 Some("tima1") => "TIMA1",
216 Some("any") => {
217 // Order of timer candidates:
218 // 1. 16-bit, 2 channel
219 // 2. 16-bit, 2 channel with shadow registers
220 // 3. 16-bit, 4 channel
221 // 4. 16-bit with QEI
222 // 5. Advanced timers
223 //
224 // TODO: Select RTC first if available
225 // TODO: 32-bit timers are not considered yet
226 [
227 // 16-bit, 2 channel
228 "TIMG0", "TIMG1", "TIMG2", "TIMG3",
229 // 16-bit, 2 channel with shadow registers
230 "TIMG4", "TIMG5", "TIMG6", "TIMG7", // 16-bit, 4 channel
231 "TIMG14", // 16-bit with QEI
232 "TIMG8", "TIMG9", "TIMG10", "TIMG11", // Advanced timers
233 "TIMA0", "TIMA1",
234 ]
235 .iter()
236 .find(|tim| singletons.contains(&tim.to_string()))
237 .expect("Could not find any timer")
238 }
239 _ => panic!("unknown time_driver {:?}", time_driver),
240 };
241
242 if !singleton.is_empty() {
243 cfgs.enable(format!("time_driver_{}", singleton.to_lowercase()));
244 }
245}
246
247/// rustfmt a given path.
248/// Failures are logged to stderr and ignored.
249fn rustfmt(path: impl AsRef<Path>) {
250 let path = path.as_ref();
251 match Command::new("rustfmt").args([path]).output() {
252 Err(e) => {
253 eprintln!("failed to exec rustfmt {:?}: {:?}", path, e);
254 }
255 Ok(out) => {
256 if !out.status.success() {
257 eprintln!("rustfmt {:?} failed:", path);
258 eprintln!("=== STDOUT:");
259 std::io::stderr().write_all(&out.stdout).unwrap();
260 eprintln!("=== STDERR:");
261 std::io::stderr().write_all(&out.stderr).unwrap();
262 }
263 }
264 }
265}
266
267#[allow(dead_code)]
268struct TimerDesc {
269 bits: u8,
270 /// Is there an 8-bit prescaler
271 prescaler: bool,
272 /// Is there a repeat counter
273 repeat_counter: bool,
274 ccp_channels_internal: u8,
275 ccp_channels_external: u8,
276 external_pwm_channels: u8,
277 phase_load: bool,
278 shadow_load: bool,
279 shadow_ccs: bool,
280 deadband: bool,
281 fault_handler: bool,
282 qei_hall: bool,
283}
284
285/// Description of all timer instances.
286const TIMERS: LazyLock<HashMap<String, TimerDesc>> = LazyLock::new(|| {
287 let mut map = HashMap::new();
288 map.insert(
289 "TIMG0".into(),
290 TimerDesc {
291 bits: 16,
292 prescaler: true,
293 repeat_counter: false,
294 ccp_channels_internal: 2,
295 ccp_channels_external: 2,
296 external_pwm_channels: 2,
297 phase_load: false,
298 shadow_load: false,
299 shadow_ccs: false,
300 deadband: false,
301 fault_handler: false,
302 qei_hall: false,
303 },
304 );
305
306 map.insert(
307 "TIMG1".into(),
308 TimerDesc {
309 bits: 16,
310 prescaler: true,
311 repeat_counter: false,
312 ccp_channels_internal: 2,
313 ccp_channels_external: 2,
314 external_pwm_channels: 2,
315 phase_load: false,
316 shadow_load: false,
317 shadow_ccs: false,
318 deadband: false,
319 fault_handler: false,
320 qei_hall: false,
321 },
322 );
323
324 map.insert(
325 "TIMG2".into(),
326 TimerDesc {
327 bits: 16,
328 prescaler: true,
329 repeat_counter: false,
330 ccp_channels_internal: 2,
331 ccp_channels_external: 2,
332 external_pwm_channels: 2,
333 phase_load: false,
334 shadow_load: false,
335 shadow_ccs: false,
336 deadband: false,
337 fault_handler: false,
338 qei_hall: false,
339 },
340 );
341
342 map.insert(
343 "TIMG3".into(),
344 TimerDesc {
345 bits: 16,
346 prescaler: true,
347 repeat_counter: false,
348 ccp_channels_internal: 2,
349 ccp_channels_external: 2,
350 external_pwm_channels: 2,
351 phase_load: false,
352 shadow_load: false,
353 shadow_ccs: false,
354 deadband: false,
355 fault_handler: false,
356 qei_hall: false,
357 },
358 );
359
360 map.insert(
361 "TIMG4".into(),
362 TimerDesc {
363 bits: 16,
364 prescaler: true,
365 repeat_counter: false,
366 ccp_channels_internal: 2,
367 ccp_channels_external: 2,
368 external_pwm_channels: 2,
369 phase_load: false,
370 shadow_load: true,
371 shadow_ccs: true,
372 deadband: false,
373 fault_handler: false,
374 qei_hall: false,
375 },
376 );
377
378 map.insert(
379 "TIMG5".into(),
380 TimerDesc {
381 bits: 16,
382 prescaler: true,
383 repeat_counter: false,
384 ccp_channels_internal: 2,
385 ccp_channels_external: 2,
386 external_pwm_channels: 2,
387 phase_load: false,
388 shadow_load: true,
389 shadow_ccs: true,
390 deadband: false,
391 fault_handler: false,
392 qei_hall: false,
393 },
394 );
395
396 map.insert(
397 "TIMG6".into(),
398 TimerDesc {
399 bits: 16,
400 prescaler: true,
401 repeat_counter: false,
402 ccp_channels_internal: 2,
403 ccp_channels_external: 2,
404 external_pwm_channels: 2,
405 phase_load: false,
406 shadow_load: true,
407 shadow_ccs: true,
408 deadband: false,
409 fault_handler: false,
410 qei_hall: false,
411 },
412 );
413
414 map.insert(
415 "TIMG7".into(),
416 TimerDesc {
417 bits: 16,
418 prescaler: true,
419 repeat_counter: false,
420 ccp_channels_internal: 2,
421 ccp_channels_external: 2,
422 external_pwm_channels: 2,
423 phase_load: false,
424 shadow_load: true,
425 shadow_ccs: true,
426 deadband: false,
427 fault_handler: false,
428 qei_hall: false,
429 },
430 );
431
432 map.insert(
433 "TIMG8".into(),
434 TimerDesc {
435 bits: 16,
436 prescaler: true,
437 repeat_counter: false,
438 ccp_channels_internal: 2,
439 ccp_channels_external: 2,
440 external_pwm_channels: 2,
441 phase_load: false,
442 shadow_load: false,
443 shadow_ccs: false,
444 deadband: false,
445 fault_handler: false,
446 qei_hall: true,
447 },
448 );
449
450 map.insert(
451 "TIMG9".into(),
452 TimerDesc {
453 bits: 16,
454 prescaler: true,
455 repeat_counter: false,
456 ccp_channels_internal: 2,
457 ccp_channels_external: 2,
458 external_pwm_channels: 2,
459 phase_load: false,
460 shadow_load: false,
461 shadow_ccs: false,
462 deadband: false,
463 fault_handler: false,
464 qei_hall: true,
465 },
466 );
467
468 map.insert(
469 "TIMG10".into(),
470 TimerDesc {
471 bits: 16,
472 prescaler: true,
473 repeat_counter: false,
474 ccp_channels_internal: 2,
475 ccp_channels_external: 2,
476 external_pwm_channels: 2,
477 phase_load: false,
478 shadow_load: false,
479 shadow_ccs: false,
480 deadband: false,
481 fault_handler: false,
482 qei_hall: true,
483 },
484 );
485
486 map.insert(
487 "TIMG11".into(),
488 TimerDesc {
489 bits: 16,
490 prescaler: true,
491 repeat_counter: false,
492 ccp_channels_internal: 2,
493 ccp_channels_external: 2,
494 external_pwm_channels: 2,
495 phase_load: false,
496 shadow_load: false,
497 shadow_ccs: false,
498 deadband: false,
499 fault_handler: false,
500 qei_hall: true,
501 },
502 );
503
504 map.insert(
505 "TIMG12".into(),
506 TimerDesc {
507 bits: 32,
508 prescaler: false,
509 repeat_counter: false,
510 ccp_channels_internal: 2,
511 ccp_channels_external: 2,
512 external_pwm_channels: 2,
513 phase_load: false,
514 shadow_load: false,
515 shadow_ccs: true,
516 deadband: false,
517 fault_handler: false,
518 qei_hall: false,
519 },
520 );
521
522 map.insert(
523 "TIMG13".into(),
524 TimerDesc {
525 bits: 32,
526 prescaler: false,
527 repeat_counter: false,
528 ccp_channels_internal: 2,
529 ccp_channels_external: 2,
530 external_pwm_channels: 2,
531 phase_load: false,
532 shadow_load: false,
533 shadow_ccs: true,
534 deadband: false,
535 fault_handler: false,
536 qei_hall: false,
537 },
538 );
539
540 map.insert(
541 "TIMG14".into(),
542 TimerDesc {
543 bits: 16,
544 prescaler: true,
545 repeat_counter: false,
546 ccp_channels_internal: 4,
547 ccp_channels_external: 4,
548 external_pwm_channels: 4,
549 phase_load: false,
550 shadow_load: false,
551 shadow_ccs: false,
552 deadband: false,
553 fault_handler: false,
554 qei_hall: false,
555 },
556 );
557
558 map.insert(
559 "TIMA0".into(),
560 TimerDesc {
561 bits: 16,
562 prescaler: true,
563 repeat_counter: true,
564 ccp_channels_internal: 4,
565 ccp_channels_external: 2,
566 external_pwm_channels: 8,
567 phase_load: true,
568 shadow_load: true,
569 shadow_ccs: true,
570 deadband: true,
571 fault_handler: true,
572 qei_hall: false,
573 },
574 );
575
576 map.insert(
577 "TIMA1".into(),
578 TimerDesc {
579 bits: 16,
580 prescaler: true,
581 repeat_counter: true,
582 ccp_channels_internal: 2,
583 ccp_channels_external: 2,
584 external_pwm_channels: 4,
585 phase_load: true,
586 shadow_load: true,
587 shadow_ccs: true,
588 deadband: true,
589 fault_handler: true,
590 qei_hall: false,
591 },
592 );
593
594 map
595});
596
597enum GetOneError {
598 None,
599 Multiple,
600}
601
602trait IteratorExt: Iterator {
603 fn get_one(self) -> Result<Self::Item, GetOneError>;
604}
605
606impl<T: Iterator> IteratorExt for T {
607 fn get_one(mut self) -> Result<Self::Item, GetOneError> {
608 match self.next() {
609 None => Err(GetOneError::None),
610 Some(res) => match self.next() {
611 Some(_) => Err(GetOneError::Multiple),
612 None => Ok(res),
613 },
614 }
615 }
616}
diff --git a/embassy-mspm0/build_common.rs b/embassy-mspm0/build_common.rs
new file mode 100644
index 000000000..4f24e6d37
--- /dev/null
+++ b/embassy-mspm0/build_common.rs
@@ -0,0 +1,94 @@
1// NOTE: this file is copy-pasted between several Embassy crates, because there is no
2// straightforward way to share this code:
3// - it cannot be placed into the root of the repo and linked from each build.rs using `#[path =
4// "../build_common.rs"]`, because `cargo publish` requires that all files published with a crate
5// reside in the crate's directory,
6// - it cannot be symlinked from `embassy-xxx/build_common.rs` to `../build_common.rs`, because
7// symlinks don't work on Windows.
8
9use std::collections::HashSet;
10use std::env;
11
12/// Helper for emitting cargo instruction for enabling configs (`cargo:rustc-cfg=X`) and declaring
13/// them (`cargo:rust-check-cfg=cfg(X)`).
14#[derive(Debug)]
15pub struct CfgSet {
16 enabled: HashSet<String>,
17 declared: HashSet<String>,
18}
19
20impl CfgSet {
21 pub fn new() -> Self {
22 Self {
23 enabled: HashSet::new(),
24 declared: HashSet::new(),
25 }
26 }
27
28 /// Enable a config, which can then be used in `#[cfg(...)]` for conditional compilation.
29 ///
30 /// All configs that can potentially be enabled should be unconditionally declared using
31 /// [`Self::declare()`].
32 pub fn enable(&mut self, cfg: impl AsRef<str>) {
33 if self.enabled.insert(cfg.as_ref().to_owned()) {
34 println!("cargo:rustc-cfg={}", cfg.as_ref());
35 }
36 }
37
38 pub fn enable_all(&mut self, cfgs: &[impl AsRef<str>]) {
39 for cfg in cfgs.iter() {
40 self.enable(cfg.as_ref());
41 }
42 }
43
44 /// Declare a valid config for conditional compilation, without enabling it.
45 ///
46 /// This enables rustc to check that the configs in `#[cfg(...)]` attributes are valid.
47 pub fn declare(&mut self, cfg: impl AsRef<str>) {
48 if self.declared.insert(cfg.as_ref().to_owned()) {
49 println!("cargo:rustc-check-cfg=cfg({})", cfg.as_ref());
50 }
51 }
52
53 pub fn declare_all(&mut self, cfgs: &[impl AsRef<str>]) {
54 for cfg in cfgs.iter() {
55 self.declare(cfg.as_ref());
56 }
57 }
58
59 pub fn set(&mut self, cfg: impl Into<String>, enable: bool) {
60 let cfg = cfg.into();
61 if enable {
62 self.enable(cfg.clone());
63 }
64 self.declare(cfg);
65 }
66}
67
68/// Sets configs that describe the target platform.
69pub fn set_target_cfgs(cfgs: &mut CfgSet) {
70 let target = env::var("TARGET").unwrap();
71
72 if target.starts_with("thumbv6m-") {
73 cfgs.enable_all(&["cortex_m", "armv6m"]);
74 } else if target.starts_with("thumbv7m-") {
75 cfgs.enable_all(&["cortex_m", "armv7m"]);
76 } else if target.starts_with("thumbv7em-") {
77 cfgs.enable_all(&["cortex_m", "armv7m", "armv7em"]);
78 } else if target.starts_with("thumbv8m.base") {
79 cfgs.enable_all(&["cortex_m", "armv8m", "armv8m_base"]);
80 } else if target.starts_with("thumbv8m.main") {
81 cfgs.enable_all(&["cortex_m", "armv8m", "armv8m_main"]);
82 }
83 cfgs.declare_all(&[
84 "cortex_m",
85 "armv6m",
86 "armv7m",
87 "armv7em",
88 "armv8m",
89 "armv8m_base",
90 "armv8m_main",
91 ]);
92
93 cfgs.set("has_fpu", target.ends_with("-eabihf"));
94}
diff --git a/embassy-mspm0/src/fmt.rs b/embassy-mspm0/src/fmt.rs
new file mode 100644
index 000000000..8ca61bc39
--- /dev/null
+++ b/embassy-mspm0/src/fmt.rs
@@ -0,0 +1,270 @@
1#![macro_use]
2#![allow(unused)]
3
4use core::fmt::{Debug, Display, LowerHex};
5
6#[cfg(all(feature = "defmt", feature = "log"))]
7compile_error!("You may not enable both `defmt` and `log` features.");
8
9#[collapse_debuginfo(yes)]
10macro_rules! assert {
11 ($($x:tt)*) => {
12 {
13 #[cfg(not(feature = "defmt"))]
14 ::core::assert!($($x)*);
15 #[cfg(feature = "defmt")]
16 ::defmt::assert!($($x)*);
17 }
18 };
19}
20
21#[collapse_debuginfo(yes)]
22macro_rules! assert_eq {
23 ($($x:tt)*) => {
24 {
25 #[cfg(not(feature = "defmt"))]
26 ::core::assert_eq!($($x)*);
27 #[cfg(feature = "defmt")]
28 ::defmt::assert_eq!($($x)*);
29 }
30 };
31}
32
33#[collapse_debuginfo(yes)]
34macro_rules! assert_ne {
35 ($($x:tt)*) => {
36 {
37 #[cfg(not(feature = "defmt"))]
38 ::core::assert_ne!($($x)*);
39 #[cfg(feature = "defmt")]
40 ::defmt::assert_ne!($($x)*);
41 }
42 };
43}
44
45#[collapse_debuginfo(yes)]
46macro_rules! debug_assert {
47 ($($x:tt)*) => {
48 {
49 #[cfg(not(feature = "defmt"))]
50 ::core::debug_assert!($($x)*);
51 #[cfg(feature = "defmt")]
52 ::defmt::debug_assert!($($x)*);
53 }
54 };
55}
56
57#[collapse_debuginfo(yes)]
58macro_rules! debug_assert_eq {
59 ($($x:tt)*) => {
60 {
61 #[cfg(not(feature = "defmt"))]
62 ::core::debug_assert_eq!($($x)*);
63 #[cfg(feature = "defmt")]
64 ::defmt::debug_assert_eq!($($x)*);
65 }
66 };
67}
68
69#[collapse_debuginfo(yes)]
70macro_rules! debug_assert_ne {
71 ($($x:tt)*) => {
72 {
73 #[cfg(not(feature = "defmt"))]
74 ::core::debug_assert_ne!($($x)*);
75 #[cfg(feature = "defmt")]
76 ::defmt::debug_assert_ne!($($x)*);
77 }
78 };
79}
80
81#[collapse_debuginfo(yes)]
82macro_rules! todo {
83 ($($x:tt)*) => {
84 {
85 #[cfg(not(feature = "defmt"))]
86 ::core::todo!($($x)*);
87 #[cfg(feature = "defmt")]
88 ::defmt::todo!($($x)*);
89 }
90 };
91}
92
93#[collapse_debuginfo(yes)]
94macro_rules! unreachable {
95 ($($x:tt)*) => {
96 {
97 #[cfg(not(feature = "defmt"))]
98 ::core::unreachable!($($x)*);
99 #[cfg(feature = "defmt")]
100 ::defmt::unreachable!($($x)*);
101 }
102 };
103}
104
105#[collapse_debuginfo(yes)]
106macro_rules! panic {
107 ($($x:tt)*) => {
108 {
109 #[cfg(not(feature = "defmt"))]
110 ::core::panic!($($x)*);
111 #[cfg(feature = "defmt")]
112 ::defmt::panic!($($x)*);
113 }
114 };
115}
116
117#[collapse_debuginfo(yes)]
118macro_rules! trace {
119 ($s:literal $(, $x:expr)* $(,)?) => {
120 {
121 #[cfg(feature = "log")]
122 ::log::trace!($s $(, $x)*);
123 #[cfg(feature = "defmt")]
124 ::defmt::trace!($s $(, $x)*);
125 #[cfg(not(any(feature = "log", feature="defmt")))]
126 let _ = ($( & $x ),*);
127 }
128 };
129}
130
131#[collapse_debuginfo(yes)]
132macro_rules! debug {
133 ($s:literal $(, $x:expr)* $(,)?) => {
134 {
135 #[cfg(feature = "log")]
136 ::log::debug!($s $(, $x)*);
137 #[cfg(feature = "defmt")]
138 ::defmt::debug!($s $(, $x)*);
139 #[cfg(not(any(feature = "log", feature="defmt")))]
140 let _ = ($( & $x ),*);
141 }
142 };
143}
144
145#[collapse_debuginfo(yes)]
146macro_rules! info {
147 ($s:literal $(, $x:expr)* $(,)?) => {
148 {
149 #[cfg(feature = "log")]
150 ::log::info!($s $(, $x)*);
151 #[cfg(feature = "defmt")]
152 ::defmt::info!($s $(, $x)*);
153 #[cfg(not(any(feature = "log", feature="defmt")))]
154 let _ = ($( & $x ),*);
155 }
156 };
157}
158
159#[collapse_debuginfo(yes)]
160macro_rules! warn {
161 ($s:literal $(, $x:expr)* $(,)?) => {
162 {
163 #[cfg(feature = "log")]
164 ::log::warn!($s $(, $x)*);
165 #[cfg(feature = "defmt")]
166 ::defmt::warn!($s $(, $x)*);
167 #[cfg(not(any(feature = "log", feature="defmt")))]
168 let _ = ($( & $x ),*);
169 }
170 };
171}
172
173#[collapse_debuginfo(yes)]
174macro_rules! error {
175 ($s:literal $(, $x:expr)* $(,)?) => {
176 {
177 #[cfg(feature = "log")]
178 ::log::error!($s $(, $x)*);
179 #[cfg(feature = "defmt")]
180 ::defmt::error!($s $(, $x)*);
181 #[cfg(not(any(feature = "log", feature="defmt")))]
182 let _ = ($( & $x ),*);
183 }
184 };
185}
186
187#[cfg(feature = "defmt")]
188#[collapse_debuginfo(yes)]
189macro_rules! unwrap {
190 ($($x:tt)*) => {
191 ::defmt::unwrap!($($x)*)
192 };
193}
194
195#[cfg(not(feature = "defmt"))]
196#[collapse_debuginfo(yes)]
197macro_rules! unwrap {
198 ($arg:expr) => {
199 match $crate::fmt::Try::into_result($arg) {
200 ::core::result::Result::Ok(t) => t,
201 ::core::result::Result::Err(e) => {
202 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
203 }
204 }
205 };
206 ($arg:expr, $($msg:expr),+ $(,)? ) => {
207 match $crate::fmt::Try::into_result($arg) {
208 ::core::result::Result::Ok(t) => t,
209 ::core::result::Result::Err(e) => {
210 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
211 }
212 }
213 }
214}
215
216#[derive(Debug, Copy, Clone, Eq, PartialEq)]
217pub struct NoneError;
218
219pub trait Try {
220 type Ok;
221 type Error;
222 fn into_result(self) -> Result<Self::Ok, Self::Error>;
223}
224
225impl<T> Try for Option<T> {
226 type Ok = T;
227 type Error = NoneError;
228
229 #[inline]
230 fn into_result(self) -> Result<T, NoneError> {
231 self.ok_or(NoneError)
232 }
233}
234
235impl<T, E> Try for Result<T, E> {
236 type Ok = T;
237 type Error = E;
238
239 #[inline]
240 fn into_result(self) -> Self {
241 self
242 }
243}
244
245pub(crate) struct Bytes<'a>(pub &'a [u8]);
246
247impl<'a> Debug for Bytes<'a> {
248 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
249 write!(f, "{:#02x?}", self.0)
250 }
251}
252
253impl<'a> Display for Bytes<'a> {
254 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
255 write!(f, "{:#02x?}", self.0)
256 }
257}
258
259impl<'a> LowerHex for Bytes<'a> {
260 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
261 write!(f, "{:#02x?}", self.0)
262 }
263}
264
265#[cfg(feature = "defmt")]
266impl<'a> defmt::Format for Bytes<'a> {
267 fn format(&self, fmt: defmt::Formatter) {
268 defmt::write!(fmt, "{:02x}", self.0)
269 }
270}
diff --git a/embassy-mspm0/src/gpio.rs b/embassy-mspm0/src/gpio.rs
new file mode 100644
index 000000000..fd4dc55ab
--- /dev/null
+++ b/embassy-mspm0/src/gpio.rs
@@ -0,0 +1,1070 @@
1#![macro_use]
2
3use core::convert::Infallible;
4use core::future::Future;
5use core::pin::Pin as FuturePin;
6use core::task::{Context, Poll};
7
8use embassy_hal_internal::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker;
10#[cfg(all(feature = "rt", feature = "mspm0c110x"))]
11use crate::pac::interrupt;
12
13use crate::pac::{
14 self,
15 gpio::{self, vals::*},
16};
17
18/// Represents a digital input or output level.
19#[derive(Debug, Eq, PartialEq, Clone, Copy)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub enum Level {
22 /// Logical low.
23 Low,
24 /// Logical high.
25 High,
26}
27
28impl From<bool> for Level {
29 fn from(val: bool) -> Self {
30 match val {
31 true => Self::High,
32 false => Self::Low,
33 }
34 }
35}
36
37impl From<Level> for bool {
38 fn from(level: Level) -> bool {
39 match level {
40 Level::Low => false,
41 Level::High => true,
42 }
43 }
44}
45
46/// Represents a pull setting for an input.
47#[derive(Debug, Clone, Copy, Eq, PartialEq)]
48pub enum Pull {
49 /// No pull.
50 None,
51 /// Internal pull-up resistor.
52 Up,
53 /// Internal pull-down resistor.
54 Down,
55}
56
57/// A GPIO bank with up to 32 pins.
58#[derive(Debug, Clone, Copy, Eq, PartialEq)]
59pub enum Port {
60 /// Port A.
61 PortA = 0,
62
63 /// Port B.
64 #[cfg(gpio_pb)]
65 PortB = 1,
66
67 /// Port C.
68 #[cfg(gpio_pc)]
69 PortC = 2,
70}
71
72/// GPIO flexible pin.
73///
74/// This pin can either be a disconnected, input, or output pin, or both. The level register bit will remain
75/// set while not in output mode, so the pin's level will be 'remembered' when it is not in output
76/// mode.
77pub struct Flex<'d> {
78 pin: PeripheralRef<'d, AnyPin>,
79}
80
81impl<'d> Flex<'d> {
82 /// Wrap the pin in a `Flex`.
83 ///
84 /// The pin remains disconnected. The initial output level is unspecified, but can be changed
85 /// before the pin is put into output mode.
86 #[inline]
87 pub fn new(pin: impl Peripheral<P = impl Pin> + 'd) -> Self {
88 into_ref!(pin);
89
90 // Pin will be in disconnected state.
91 Self {
92 pin: pin.map_into(),
93 }
94 }
95
96 /// Set the pin's pull.
97 #[inline]
98 pub fn set_pull(&mut self, pull: Pull) {
99 let pincm = pac::IOMUX.pincm(self.pin.pin_cm() as usize);
100
101 pincm.modify(|w| {
102 w.set_pipd(matches!(pull, Pull::Down));
103 w.set_pipu(matches!(pull, Pull::Up));
104 });
105 }
106
107 /// Put the pin into input mode.
108 ///
109 /// The pull setting is left unchanged.
110 #[inline]
111 pub fn set_as_input(&mut self) {
112 let pincm = pac::IOMUX.pincm(self.pin.pin_cm() as usize);
113
114 pincm.modify(|w| {
115 w.set_pf(GPIO_PF);
116 w.set_hiz1(false);
117 w.set_pc(true);
118 w.set_inena(true);
119 });
120
121 self.pin.block().doeclr31_0().write(|w| {
122 w.set_dio(self.pin.bit_index(), true);
123 });
124 }
125
126 /// Put the pin into output mode.
127 ///
128 /// The pin level will be whatever was set before (or low by default). If you want it to begin
129 /// at a specific level, call `set_high`/`set_low` on the pin first.
130 #[inline]
131 pub fn set_as_output(&mut self) {
132 let pincm = pac::IOMUX.pincm(self.pin.pin_cm() as usize);
133
134 pincm.modify(|w| {
135 w.set_pf(GPIO_PF);
136 w.set_hiz1(false);
137 w.set_pc(true);
138 w.set_inena(false);
139 });
140
141 self.pin.block().doeset31_0().write(|w| {
142 w.set_dio(self.pin.bit_index(), true);
143 });
144 }
145
146 /// Put the pin into input + open-drain output mode.
147 ///
148 /// The hardware will drive the line low if you set it to low, and will leave it floating if you set
149 /// it to high, in which case you can read the input to figure out whether another device
150 /// is driving the line low.
151 ///
152 /// The pin level will be whatever was set before (or low by default). If you want it to begin
153 /// at a specific level, call `set_high`/`set_low` on the pin first.
154 ///
155 /// The internal weak pull-up and pull-down resistors will be disabled.
156 #[inline]
157 pub fn set_as_input_output(&mut self) {
158 let pincm = pac::IOMUX.pincm(self.pin.pin_cm() as usize);
159
160 pincm.modify(|w| {
161 w.set_pf(GPIO_PF);
162 w.set_hiz1(true);
163 w.set_pc(true);
164 w.set_inena(false);
165 });
166
167 self.set_pull(Pull::None);
168 }
169
170 /// Set the pin as "disconnected", ie doing nothing and consuming the lowest
171 /// amount of power possible.
172 ///
173 /// This is currently the same as [`Self::set_as_analog()`] but is semantically different
174 /// really. Drivers should `set_as_disconnected()` pins when dropped.
175 ///
176 /// Note that this also disables the internal weak pull-up and pull-down resistors.
177 #[inline]
178 pub fn set_as_disconnected(&mut self) {
179 let pincm = pac::IOMUX.pincm(self.pin.pin_cm() as usize);
180
181 pincm.modify(|w| {
182 w.set_pf(DISCONNECT_PF);
183 w.set_hiz1(false);
184 w.set_pc(false);
185 w.set_inena(false);
186 });
187
188 self.set_pull(Pull::None);
189 self.set_inversion(false);
190 }
191
192 /// Configure the logic inversion of this pin.
193 ///
194 /// Logic inversion applies to both the input and output path of this pin.
195 #[inline]
196 pub fn set_inversion(&mut self, invert: bool) {
197 let pincm = pac::IOMUX.pincm(self.pin.pin_cm() as usize);
198
199 pincm.modify(|w| {
200 w.set_inv(invert);
201 });
202 }
203
204 // TODO: drive strength, hysteresis, wakeup enable, wakeup compare
205
206 /// Put the pin into the PF mode, unchecked.
207 ///
208 /// This puts the pin into the PF mode, with the request number. This is completely unchecked,
209 /// it can attach the pin to literally any peripheral, so use with care. In addition the pin
210 /// peripheral is connected in the iomux.
211 ///
212 /// The peripheral attached to the pin depends on the part in use. Consult the datasheet
213 /// or technical reference manual for additional details.
214 #[inline]
215 pub fn set_pf_unchecked(&mut self, pf: u8) {
216 // Per SLAU893, PF is only 5 bits
217 assert!((pf & 0x3F) != 0, "PF is out of range");
218
219 let pincm = pac::IOMUX.pincm(self.pin.pin_cm() as usize);
220
221 pincm.modify(|w| {
222 w.set_pf(pf);
223 // If the PF is manually set, connect the pin
224 w.set_pc(true);
225 });
226 }
227
228 /// Get whether the pin input level is high.
229 #[inline]
230 pub fn is_high(&self) -> bool {
231 !self.is_low()
232 }
233
234 /// Get whether the pin input level is low.
235 #[inline]
236 pub fn is_low(&self) -> bool {
237 self.pin.block().din31_0().read().dio(self.pin.bit_index())
238 }
239
240 /// Returns current pin level
241 #[inline]
242 pub fn get_level(&self) -> Level {
243 self.is_high().into()
244 }
245
246 /// Set the output as high.
247 #[inline]
248 pub fn set_high(&mut self) {
249 self.pin.block().doutset31_0().write(|w| {
250 w.set_dio(self.pin.bit_index() as usize, true);
251 });
252 }
253
254 /// Set the output as low.
255 #[inline]
256 pub fn set_low(&mut self) {
257 self.pin.block().doutclr31_0().write(|w| {
258 w.set_dio(self.pin.bit_index(), true);
259 });
260 }
261
262 /// Toggle pin output
263 #[inline]
264 pub fn toggle(&mut self) {
265 self.pin.block().douttgl31_0().write(|w| {
266 w.set_dio(self.pin.bit_index(), true);
267 })
268 }
269
270 /// Set the output level.
271 #[inline]
272 pub fn set_level(&mut self, level: Level) {
273 match level {
274 Level::Low => self.set_low(),
275 Level::High => self.set_high(),
276 }
277 }
278
279 /// Get the current pin input level.
280 #[inline]
281 pub fn get_output_level(&self) -> Level {
282 self.is_high().into()
283 }
284
285 /// Is the output level high?
286 #[inline]
287 pub fn is_set_high(&self) -> bool {
288 !self.is_set_low()
289 }
290
291 /// Is the output level low?
292 #[inline]
293 pub fn is_set_low(&self) -> bool {
294 (self.pin.block().dout31_0().read().0 & self.pin.bit_index() as u32) == 0
295 }
296
297 /// Wait until the pin is high. If it is already high, return immediately.
298 #[inline]
299 pub async fn wait_for_high(&mut self) {
300 if self.is_high() {
301 return;
302 }
303
304 self.wait_for_rising_edge().await
305 }
306
307 /// Wait until the pin is low. If it is already low, return immediately.
308 #[inline]
309 pub async fn wait_for_low(&mut self) {
310 if self.is_low() {
311 return;
312 }
313
314 self.wait_for_falling_edge().await
315 }
316
317 /// Wait for the pin to undergo a transition from low to high.
318 #[inline]
319 pub async fn wait_for_rising_edge(&mut self) {
320 InputFuture::new(self.pin.reborrow(), Polarity::RISE).await
321 }
322
323 /// Wait for the pin to undergo a transition from high to low.
324 #[inline]
325 pub async fn wait_for_falling_edge(&mut self) {
326 InputFuture::new(self.pin.reborrow(), Polarity::FALL).await
327 }
328
329 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
330 #[inline]
331 pub async fn wait_for_any_edge(&mut self) {
332 InputFuture::new(self.pin.reborrow(), Polarity::RISE_FALL).await
333 }
334}
335
336impl<'d> Drop for Flex<'d> {
337 #[inline]
338 fn drop(&mut self) {
339 self.set_as_disconnected();
340 }
341}
342
343/// GPIO input driver.
344pub struct Input<'d> {
345 pin: Flex<'d>,
346}
347
348impl<'d> Input<'d> {
349 /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
350 #[inline]
351 pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, pull: Pull) -> Self {
352 let mut pin = Flex::new(pin);
353 pin.set_as_input();
354 pin.set_pull(pull);
355 Self { pin }
356 }
357
358 /// Get whether the pin input level is high.
359 #[inline]
360 pub fn is_high(&self) -> bool {
361 self.pin.is_high()
362 }
363
364 /// Get whether the pin input level is low.
365 #[inline]
366 pub fn is_low(&self) -> bool {
367 self.pin.is_low()
368 }
369
370 /// Get the current pin input level.
371 #[inline]
372 pub fn get_level(&self) -> Level {
373 self.pin.get_level()
374 }
375
376 /// Configure the logic inversion of this pin.
377 ///
378 /// Logic inversion applies to the input path of this pin.
379 #[inline]
380 pub fn set_inversion(&mut self, invert: bool) {
381 self.pin.set_inversion(invert)
382 }
383
384 /// Wait until the pin is high. If it is already high, return immediately.
385 #[inline]
386 pub async fn wait_for_high(&mut self) {
387 self.pin.wait_for_high().await
388 }
389
390 /// Wait until the pin is low. If it is already low, return immediately.
391 #[inline]
392 pub async fn wait_for_low(&mut self) {
393 self.pin.wait_for_low().await
394 }
395
396 /// Wait for the pin to undergo a transition from low to high.
397 #[inline]
398 pub async fn wait_for_rising_edge(&mut self) {
399 self.pin.wait_for_rising_edge().await
400 }
401
402 /// Wait for the pin to undergo a transition from high to low.
403 #[inline]
404 pub async fn wait_for_falling_edge(&mut self) {
405 self.pin.wait_for_falling_edge().await
406 }
407
408 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
409 #[inline]
410 pub async fn wait_for_any_edge(&mut self) {
411 self.pin.wait_for_any_edge().await
412 }
413}
414
415/// GPIO output driver.
416///
417/// Note that pins will **return to their floating state** when `Output` is dropped.
418/// If pins should retain their state indefinitely, either keep ownership of the
419/// `Output`, or pass it to [`core::mem::forget`].
420pub struct Output<'d> {
421 pin: Flex<'d>,
422}
423
424impl<'d> Output<'d> {
425 /// Create GPIO output driver for a [Pin] with the provided [Level] configuration.
426 #[inline]
427 pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level) -> Self {
428 let mut pin = Flex::new(pin);
429 pin.set_as_output();
430 pin.set_level(initial_output);
431 Self { pin }
432 }
433
434 /// Set the output as high.
435 #[inline]
436 pub fn set_high(&mut self) {
437 self.pin.set_high();
438 }
439
440 /// Set the output as low.
441 #[inline]
442 pub fn set_low(&mut self) {
443 self.pin.set_low();
444 }
445
446 /// Set the output level.
447 #[inline]
448 pub fn set_level(&mut self, level: Level) {
449 self.pin.set_level(level)
450 }
451
452 /// Is the output pin set as high?
453 #[inline]
454 pub fn is_set_high(&self) -> bool {
455 self.pin.is_set_high()
456 }
457
458 /// Is the output pin set as low?
459 #[inline]
460 pub fn is_set_low(&self) -> bool {
461 self.pin.is_set_low()
462 }
463
464 /// What level output is set to
465 #[inline]
466 pub fn get_output_level(&self) -> Level {
467 self.pin.get_output_level()
468 }
469
470 /// Toggle pin output
471 #[inline]
472 pub fn toggle(&mut self) {
473 self.pin.toggle();
474 }
475
476 /// Configure the logic inversion of this pin.
477 ///
478 /// Logic inversion applies to the input path of this pin.
479 #[inline]
480 pub fn set_inversion(&mut self, invert: bool) {
481 self.pin.set_inversion(invert)
482 }
483}
484
485/// GPIO output open-drain driver.
486///
487/// Note that pins will **return to their floating state** when `OutputOpenDrain` is dropped.
488/// If pins should retain their state indefinitely, either keep ownership of the
489/// `OutputOpenDrain`, or pass it to [`core::mem::forget`].
490pub struct OutputOpenDrain<'d> {
491 pin: Flex<'d>,
492}
493
494impl<'d> OutputOpenDrain<'d> {
495 /// Create a new GPIO open drain output driver for a [Pin] with the provided [Level].
496 #[inline]
497 pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level) -> Self {
498 let mut pin = Flex::new(pin);
499 pin.set_level(initial_output);
500 pin.set_as_input_output();
501 Self { pin }
502 }
503
504 /// Get whether the pin input level is high.
505 #[inline]
506 pub fn is_high(&self) -> bool {
507 !self.pin.is_low()
508 }
509
510 /// Get whether the pin input level is low.
511 #[inline]
512 pub fn is_low(&self) -> bool {
513 self.pin.is_low()
514 }
515
516 /// Get the current pin input level.
517 #[inline]
518 pub fn get_level(&self) -> Level {
519 self.pin.get_level()
520 }
521
522 /// Set the output as high.
523 #[inline]
524 pub fn set_high(&mut self) {
525 self.pin.set_high();
526 }
527
528 /// Set the output as low.
529 #[inline]
530 pub fn set_low(&mut self) {
531 self.pin.set_low();
532 }
533
534 /// Set the output level.
535 #[inline]
536 pub fn set_level(&mut self, level: Level) {
537 self.pin.set_level(level);
538 }
539
540 /// Get whether the output level is set to high.
541 #[inline]
542 pub fn is_set_high(&self) -> bool {
543 self.pin.is_set_high()
544 }
545
546 /// Get whether the output level is set to low.
547 #[inline]
548 pub fn is_set_low(&self) -> bool {
549 self.pin.is_set_low()
550 }
551
552 /// Get the current output level.
553 #[inline]
554 pub fn get_output_level(&self) -> Level {
555 self.pin.get_output_level()
556 }
557
558 /// Toggle pin output
559 #[inline]
560 pub fn toggle(&mut self) {
561 self.pin.toggle()
562 }
563
564 /// Configure the logic inversion of this pin.
565 ///
566 /// Logic inversion applies to the input path of this pin.
567 #[inline]
568 pub fn set_inversion(&mut self, invert: bool) {
569 self.pin.set_inversion(invert)
570 }
571
572 /// Wait until the pin is high. If it is already high, return immediately.
573 #[inline]
574 pub async fn wait_for_high(&mut self) {
575 self.pin.wait_for_high().await
576 }
577
578 /// Wait until the pin is low. If it is already low, return immediately.
579 #[inline]
580 pub async fn wait_for_low(&mut self) {
581 self.pin.wait_for_low().await
582 }
583
584 /// Wait for the pin to undergo a transition from low to high.
585 #[inline]
586 pub async fn wait_for_rising_edge(&mut self) {
587 self.pin.wait_for_rising_edge().await
588 }
589
590 /// Wait for the pin to undergo a transition from high to low.
591 #[inline]
592 pub async fn wait_for_falling_edge(&mut self) {
593 self.pin.wait_for_falling_edge().await
594 }
595
596 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
597 #[inline]
598 pub async fn wait_for_any_edge(&mut self) {
599 self.pin.wait_for_any_edge().await
600 }
601}
602
603/// Type-erased GPIO pin
604pub struct AnyPin {
605 pin_port: u8,
606}
607
608impl AnyPin {
609 /// Create an [AnyPin] for a specific pin.
610 ///
611 /// # Safety
612 /// - `pin_port` should not in use by another driver.
613 #[inline]
614 pub unsafe fn steal(pin_port: u8) -> Self {
615 Self { pin_port }
616 }
617}
618
619impl_peripheral!(AnyPin);
620
621impl Pin for AnyPin {}
622impl SealedPin for AnyPin {
623 #[inline]
624 fn pin_port(&self) -> u8 {
625 self.pin_port
626 }
627}
628
629/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an [AnyPin].
630#[allow(private_bounds)]
631pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + SealedPin + Sized + 'static {
632 fn degrade(self) -> AnyPin {
633 AnyPin {
634 pin_port: self.pin_port(),
635 }
636 }
637
638 /// The index of this pin in PINCM (pin control management) registers.
639 #[inline]
640 fn pin_cm(&self) -> u8 {
641 self._pin_cm()
642 }
643}
644
645impl<'d> embedded_hal::digital::ErrorType for Flex<'d> {
646 type Error = Infallible;
647}
648
649impl<'d> embedded_hal::digital::InputPin for Flex<'d> {
650 #[inline]
651 fn is_high(&mut self) -> Result<bool, Self::Error> {
652 Ok((*self).is_high())
653 }
654
655 #[inline]
656 fn is_low(&mut self) -> Result<bool, Self::Error> {
657 Ok((*self).is_low())
658 }
659}
660
661impl<'d> embedded_hal::digital::OutputPin for Flex<'d> {
662 #[inline]
663 fn set_low(&mut self) -> Result<(), Self::Error> {
664 Ok(self.set_low())
665 }
666
667 #[inline]
668 fn set_high(&mut self) -> Result<(), Self::Error> {
669 Ok(self.set_high())
670 }
671}
672
673impl<'d> embedded_hal::digital::StatefulOutputPin for Flex<'d> {
674 #[inline]
675 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
676 Ok((*self).is_set_high())
677 }
678
679 #[inline]
680 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
681 Ok((*self).is_set_low())
682 }
683}
684
685impl<'d> embedded_hal_async::digital::Wait for Flex<'d> {
686 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
687 self.wait_for_high().await;
688 Ok(())
689 }
690
691 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
692 self.wait_for_low().await;
693 Ok(())
694 }
695
696 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
697 self.wait_for_rising_edge().await;
698 Ok(())
699 }
700
701 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
702 self.wait_for_falling_edge().await;
703 Ok(())
704 }
705
706 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
707 self.wait_for_any_edge().await;
708 Ok(())
709 }
710}
711
712impl<'d> embedded_hal::digital::ErrorType for Input<'d> {
713 type Error = Infallible;
714}
715
716impl<'d> embedded_hal::digital::InputPin for Input<'d> {
717 #[inline]
718 fn is_high(&mut self) -> Result<bool, Self::Error> {
719 Ok((*self).is_high())
720 }
721
722 #[inline]
723 fn is_low(&mut self) -> Result<bool, Self::Error> {
724 Ok((*self).is_low())
725 }
726}
727
728impl<'d> embedded_hal_async::digital::Wait for Input<'d> {
729 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
730 self.wait_for_high().await;
731 Ok(())
732 }
733
734 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
735 self.wait_for_low().await;
736 Ok(())
737 }
738
739 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
740 self.wait_for_rising_edge().await;
741 Ok(())
742 }
743
744 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
745 self.wait_for_falling_edge().await;
746 Ok(())
747 }
748
749 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
750 self.wait_for_any_edge().await;
751 Ok(())
752 }
753}
754
755impl<'d> embedded_hal::digital::ErrorType for Output<'d> {
756 type Error = Infallible;
757}
758
759impl<'d> embedded_hal::digital::OutputPin for Output<'d> {
760 #[inline]
761 fn set_low(&mut self) -> Result<(), Self::Error> {
762 Ok(self.set_low())
763 }
764
765 #[inline]
766 fn set_high(&mut self) -> Result<(), Self::Error> {
767 Ok(self.set_high())
768 }
769}
770
771impl<'d> embedded_hal::digital::StatefulOutputPin for Output<'d> {
772 #[inline]
773 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
774 Ok((*self).is_set_high())
775 }
776
777 #[inline]
778 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
779 Ok((*self).is_set_low())
780 }
781}
782
783impl<'d> embedded_hal::digital::ErrorType for OutputOpenDrain<'d> {
784 type Error = Infallible;
785}
786
787impl<'d> embedded_hal::digital::InputPin for OutputOpenDrain<'d> {
788 #[inline]
789 fn is_high(&mut self) -> Result<bool, Self::Error> {
790 Ok((*self).is_high())
791 }
792
793 #[inline]
794 fn is_low(&mut self) -> Result<bool, Self::Error> {
795 Ok((*self).is_low())
796 }
797}
798
799impl<'d> embedded_hal::digital::OutputPin for OutputOpenDrain<'d> {
800 #[inline]
801 fn set_low(&mut self) -> Result<(), Self::Error> {
802 Ok(self.set_low())
803 }
804
805 #[inline]
806 fn set_high(&mut self) -> Result<(), Self::Error> {
807 Ok(self.set_high())
808 }
809}
810
811impl<'d> embedded_hal::digital::StatefulOutputPin for OutputOpenDrain<'d> {
812 #[inline]
813 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
814 Ok((*self).is_set_high())
815 }
816
817 #[inline]
818 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
819 Ok((*self).is_set_low())
820 }
821}
822
823impl<'d> embedded_hal_async::digital::Wait for OutputOpenDrain<'d> {
824 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
825 self.wait_for_high().await;
826 Ok(())
827 }
828
829 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
830 self.wait_for_low().await;
831 Ok(())
832 }
833
834 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
835 self.wait_for_rising_edge().await;
836 Ok(())
837 }
838
839 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
840 self.wait_for_falling_edge().await;
841 Ok(())
842 }
843
844 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
845 self.wait_for_any_edge().await;
846 Ok(())
847 }
848}
849
850/// The pin function to disconnect peripherals from the pin.
851///
852/// This is also the pin function used to connect to analog peripherals, such as an ADC.
853const DISCONNECT_PF: u8 = 0;
854
855/// The pin function for the GPIO peripheral.
856///
857/// This is fixed to `1` for every part.
858const GPIO_PF: u8 = 1;
859
860macro_rules! impl_pin {
861 ($name: ident, $port: expr, $pin_num: expr) => {
862 impl crate::gpio::Pin for crate::peripherals::$name {}
863 impl crate::gpio::SealedPin for crate::peripherals::$name {
864 #[inline]
865 fn pin_port(&self) -> u8 {
866 ($port as u8) * 32 + $pin_num
867 }
868 }
869
870 impl From<crate::peripherals::$name> for crate::gpio::AnyPin {
871 fn from(val: crate::peripherals::$name) -> Self {
872 crate::gpio::Pin::degrade(val)
873 }
874 }
875 };
876}
877
878// TODO: Possible micro-op for C110X, not every pin is instantiated even on the 20 pin parts.
879// This would mean cfg guarding to just cfg guarding every pin instance.
880static PORTA_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32];
881#[cfg(gpio_pb)]
882static PORTB_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32];
883#[cfg(gpio_pc)]
884static PORTC_WAKERS: [AtomicWaker; 32] = [const { AtomicWaker::new() }; 32];
885
886pub(crate) trait SealedPin {
887 fn pin_port(&self) -> u8;
888
889 fn port(&self) -> Port {
890 match self.pin_port() / 32 {
891 0 => Port::PortA,
892 #[cfg(gpio_pb)]
893 1 => Port::PortB,
894 #[cfg(gpio_pc)]
895 2 => Port::PortC,
896 _ => unreachable!(),
897 }
898 }
899
900 fn waker(&self) -> &AtomicWaker {
901 match self.port() {
902 Port::PortA => &PORTA_WAKERS[self.bit_index()],
903 #[cfg(gpio_pb)]
904 Port::PortB => &PORTB_WAKERS[self.bit_index()],
905 #[cfg(gpio_pc)]
906 Port::PortC => &PORTC_WAKERS[self.bit_index()],
907 }
908 }
909
910 fn _pin_cm(&self) -> u8 {
911 // Some parts like the MSPM0L222x have pincm mappings all over the place.
912 crate::gpio_pincm(self.pin_port())
913 }
914
915 fn bit_index(&self) -> usize {
916 (self.pin_port() % 32) as usize
917 }
918
919 #[inline]
920 fn block(&self) -> gpio::Gpio {
921 match self.pin_port() / 32 {
922 0 => pac::GPIOA,
923 #[cfg(gpio_pb)]
924 1 => pac::GPIOB,
925 #[cfg(gpio_pc)]
926 2 => pac::GPIOC,
927 _ => unreachable!(),
928 }
929 }
930}
931
932#[must_use = "futures do nothing unless you `.await` or poll them"]
933struct InputFuture<'d> {
934 pin: PeripheralRef<'d, AnyPin>,
935}
936
937impl<'d> InputFuture<'d> {
938 fn new(pin: PeripheralRef<'d, AnyPin>, polarity: Polarity) -> Self {
939 let block = pin.block();
940
941 // First clear the bit for this event. Otherwise previous edge events may be recorded.
942 block.cpu_int().iclr().write(|w| {
943 w.set_dio(pin.bit_index(), true);
944 });
945
946 // Selecting which polarity events happens is a RMW operation.
947 //
948 // Guard with a critical section in case two different threads try to select events at the
949 // same time.
950 critical_section::with(|_cs| {
951 // Tell the hardware which pin event we want to receive.
952 if pin.bit_index() >= 16 {
953 block.polarity31_16().modify(|w| {
954 w.set_dio(pin.bit_index() - 16, polarity);
955 });
956 } else {
957 block.polarity15_0().modify(|w| {
958 w.set_dio(pin.bit_index(), polarity);
959 });
960 };
961 });
962
963 Self { pin }
964 }
965}
966
967impl<'d> Future for InputFuture<'d> {
968 type Output = ();
969
970 fn poll(self: FuturePin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
971 // We need to register/re-register the waker for each poll because any
972 // calls to wake will deregister the waker.
973 let waker = self.pin.waker();
974 waker.register(cx.waker());
975
976 // The interrupt handler will mask the interrupt if the event has occurred.
977 if self
978 .pin
979 .block()
980 .cpu_int()
981 .ris()
982 .read()
983 .dio(self.pin.bit_index())
984 {
985 return Poll::Ready(());
986 }
987
988 // Unmasking the interrupt is a RMW operation.
989 //
990 // Guard with a critical section in case two different threads try to unmask at the same time.
991 critical_section::with(|_cs| {
992 self.pin.block().cpu_int().imask().modify(|w| {
993 w.set_dio(self.pin.bit_index(), true);
994 });
995 });
996
997 Poll::Pending
998 }
999}
1000
1001pub(crate) fn init(gpio: gpio::Gpio) {
1002 gpio.gprcm().rstctl().write(|w| {
1003 w.set_resetstkyclr(true);
1004 w.set_resetassert(true);
1005 w.set_key(ResetKey::KEY);
1006 });
1007
1008 gpio.gprcm().pwren().write(|w| {
1009 w.set_enable(true);
1010 w.set_key(PwrenKey::KEY);
1011 });
1012
1013 gpio.evt_mode().modify(|w| {
1014 // The CPU will clear it's own interrupts
1015 w.set_cpu_cfg(EvtCfg::SOFTWARE);
1016 });
1017}
1018
1019#[cfg(feature = "rt")]
1020fn irq_handler(gpio: gpio::Gpio, wakers: &[AtomicWaker; 32]) {
1021 // Only consider pins which have interrupts unmasked.
1022 let bits = gpio.cpu_int().mis().read().0;
1023
1024 for i in BitIter(bits) {
1025 wakers[i as usize].wake();
1026
1027 // Notify the future that an edge event has occurred by masking the interrupt for this pin.
1028 gpio.cpu_int().imask().modify(|w| {
1029 w.set_dio(i as usize, false);
1030 });
1031 }
1032}
1033
1034struct BitIter(u32);
1035
1036impl Iterator for BitIter {
1037 type Item = u32;
1038
1039 fn next(&mut self) -> Option<Self::Item> {
1040 match self.0.trailing_zeros() {
1041 32 => None,
1042 b => {
1043 self.0 &= !(1 << b);
1044 Some(b)
1045 }
1046 }
1047 }
1048}
1049
1050// C110x has a dedicated interrupt just for GPIOA, as it does not have a GROUP1 interrupt.
1051#[cfg(all(feature = "rt", feature = "mspm0c110x"))]
1052#[interrupt]
1053fn GPIOA() {
1054 gpioa_interrupt();
1055}
1056
1057#[cfg(feature = "rt")]
1058pub(crate) fn gpioa_interrupt() {
1059 irq_handler(pac::GPIOA, &PORTA_WAKERS);
1060}
1061
1062#[cfg(all(feature = "rt", gpio_pb))]
1063pub(crate) fn gpiob_interrupt() {
1064 irq_handler(pac::GPIOB, &PORTB_WAKERS);
1065}
1066
1067#[cfg(all(feature = "rt", gpio_pc))]
1068pub(crate) fn gpioc_interrupt() {
1069 irq_handler(pac::GPIOC, &PORTC_WAKERS);
1070}
diff --git a/embassy-mspm0/src/int_group/c110x.rs b/embassy-mspm0/src/int_group/c110x.rs
new file mode 100644
index 000000000..c503af631
--- /dev/null
+++ b/embassy-mspm0/src/int_group/c110x.rs
@@ -0,0 +1,25 @@
1use crate::pac;
2use crate::pac::interrupt;
3
4#[cfg(feature = "rt")]
5#[interrupt]
6fn GROUP0() {
7 use mspm0_metapac::Group0;
8
9 let group = pac::CPUSS.int_group(1);
10
11 // TODO: Decompose to direct u8
12 let iidx = group.iidx().read().stat().to_bits();
13
14 let Ok(group) = pac::Group0::try_from(iidx as u8) else {
15 debug!("Invalid IIDX for group 0: {}", iidx);
16 return;
17 };
18
19 match group {
20 Group0::WWDT0 => todo!("implement WWDT0"),
21 Group0::DEBUGSS => todo!("implement DEBUGSS"),
22 Group0::FLASHCTL => todo!("implement FLASHCTL"),
23 Group0::SYSCTL => todo!("implement SYSCTL"),
24 }
25}
diff --git a/embassy-mspm0/src/int_group/g350x.rs b/embassy-mspm0/src/int_group/g350x.rs
new file mode 100644
index 000000000..818dd6e1e
--- /dev/null
+++ b/embassy-mspm0/src/int_group/g350x.rs
@@ -0,0 +1,51 @@
1use crate::pac;
2use crate::pac::interrupt;
3
4#[cfg(feature = "rt")]
5#[interrupt]
6fn GROUP0() {
7 use mspm0_metapac::Group0;
8
9 let group = pac::CPUSS.int_group(1);
10
11 // Must subtract by 1 since NO_INTR is value 0
12 let iidx = group.iidx().read().stat().to_bits() - 1;
13
14 let Ok(group) = pac::Group0::try_from(iidx as u8) else {
15 debug!("Invalid IIDX for group 0: {}", iidx);
16 return;
17 };
18
19 match group {
20 Group0::WWDT0 => todo!("implement WWDT0"),
21 Group0::WWDT1 => todo!("implement WWDT1"),
22 Group0::DEBUGSS => todo!("implement DEBUGSS"),
23 Group0::FLASHCTL => todo!("implement FLASHCTL"),
24 Group0::SYSCTL => todo!("implement SYSCTL"),
25 }
26}
27
28#[cfg(feature = "rt")]
29#[interrupt]
30fn GROUP1() {
31 use mspm0_metapac::Group1;
32
33 let group = pac::CPUSS.int_group(1);
34
35 // Must subtract by 1 since NO_INTR is value 0
36 let iidx = group.iidx().read().stat().to_bits() - 1;
37
38 let Ok(group) = pac::Group1::try_from(iidx as u8) else {
39 debug!("Invalid IIDX for group 1: {}", iidx);
40 return;
41 };
42
43 match group {
44 Group1::GPIOA => crate::gpio::gpioa_interrupt(),
45 Group1::GPIOB => crate::gpio::gpiob_interrupt(),
46 Group1::COMP0 => todo!("implement COMP0"),
47 Group1::COMP1 => todo!("implement COMP1"),
48 Group1::COMP2 => todo!("implement COMP2"),
49 Group1::TRNG => todo!("implement TRNG"),
50 }
51}
diff --git a/embassy-mspm0/src/int_group/g351x.rs b/embassy-mspm0/src/int_group/g351x.rs
new file mode 100644
index 000000000..b43e0a9db
--- /dev/null
+++ b/embassy-mspm0/src/int_group/g351x.rs
@@ -0,0 +1,52 @@
1use crate::pac;
2use crate::pac::interrupt;
3
4#[cfg(feature = "rt")]
5#[interrupt]
6fn GROUP0() {
7 use mspm0_metapac::Group0;
8
9 let group = pac::CPUSS.int_group(1);
10
11 // Must subtract by 1 since NO_INTR is value 0
12 let iidx = group.iidx().read().stat().to_bits() - 1;
13
14 let Ok(group) = pac::Group0::try_from(iidx as u8) else {
15 debug!("Invalid IIDX for group 0: {}", iidx);
16 return;
17 };
18
19 match group {
20 Group0::WWDT0 => todo!("implement WWDT0"),
21 Group0::WWDT1 => todo!("implement WWDT1"),
22 Group0::DEBUGSS => todo!("implement DEBUGSS"),
23 Group0::FLASHCTL => todo!("implement FLASHCTL"),
24 Group0::SYSCTL => todo!("implement SYSCTL"),
25 }
26}
27
28#[cfg(feature = "rt")]
29#[interrupt]
30fn GROUP1() {
31 use mspm0_metapac::Group1;
32
33 let group = pac::CPUSS.int_group(1);
34
35 // Must subtract by 1 since NO_INTR is value 0
36 let iidx = group.iidx().read().stat().to_bits() - 1;
37
38 let Ok(group) = pac::Group1::try_from(iidx as u8) else {
39 debug!("Invalid IIDX for group 1: {}", iidx);
40 return;
41 };
42
43 match group {
44 Group1::GPIOA => crate::gpio::gpioa_interrupt(),
45 Group1::GPIOB => crate::gpio::gpiob_interrupt(),
46 Group1::COMP0 => todo!("implement COMP0"),
47 Group1::COMP1 => todo!("implement COMP1"),
48 Group1::COMP2 => todo!("implement COMP2"),
49 Group1::TRNG => todo!("implement TRNG"),
50 Group1::GPIOC => crate::gpio::gpioc_interrupt(),
51 }
52}
diff --git a/embassy-mspm0/src/int_group/l130x.rs b/embassy-mspm0/src/int_group/l130x.rs
new file mode 100644
index 000000000..6d033cc56
--- /dev/null
+++ b/embassy-mspm0/src/int_group/l130x.rs
@@ -0,0 +1,46 @@
1use crate::pac;
2use crate::pac::interrupt;
3
4#[cfg(feature = "rt")]
5#[interrupt]
6fn GROUP0() {
7 use mspm0_metapac::Group0;
8
9 let group = pac::CPUSS.int_group(1);
10
11 // Must subtract by 1 since NO_INTR is value 0
12 let iidx = group.iidx().read().stat().to_bits() - 1;
13
14 let Ok(group) = pac::Group0::try_from(iidx as u8) else {
15 debug!("Invalid IIDX for group 0: {}", iidx);
16 return;
17 };
18
19 match group {
20 Group0::WWDT0 => todo!("implement WWDT0"),
21 Group0::DEBUGSS => todo!("implement DEBUGSS"),
22 Group0::FLASHCTL => todo!("implement FLASHCTL"),
23 Group0::SYSCTL => todo!("implement SYSCTL"),
24 }
25}
26
27#[cfg(feature = "rt")]
28#[interrupt]
29fn GROUP1() {
30 use mspm0_metapac::Group1;
31
32 let group = pac::CPUSS.int_group(1);
33
34 // Must subtract by 1 since NO_INTR is value 0
35 let iidx = group.iidx().read().stat().to_bits() - 1;
36
37 let Ok(group) = pac::Group1::try_from(iidx as u8) else {
38 debug!("Invalid IIDX for group 1: {}", iidx);
39 return;
40 };
41
42 match group {
43 Group1::GPIOA => crate::gpio::gpioa_interrupt(),
44 Group1::COMP0 => todo!("implement COMP0"),
45 }
46}
diff --git a/embassy-mspm0/src/int_group/l222x.rs b/embassy-mspm0/src/int_group/l222x.rs
new file mode 100644
index 000000000..703e16e78
--- /dev/null
+++ b/embassy-mspm0/src/int_group/l222x.rs
@@ -0,0 +1,49 @@
1use crate::pac;
2use crate::pac::interrupt;
3
4#[cfg(feature = "rt")]
5#[interrupt]
6fn GROUP0() {
7 use mspm0_metapac::Group0;
8
9 let group = pac::CPUSS.int_group(1);
10
11 // Must subtract by 1 since NO_INTR is value 0
12 let iidx = group.iidx().read().stat().to_bits() - 1;
13
14 let Ok(group) = pac::Group0::try_from(iidx as u8) else {
15 debug!("Invalid IIDX for group 0: {}", iidx);
16 return;
17 };
18
19 match group {
20 Group0::WWDT0 => todo!("implement WWDT0"),
21 Group0::DEBUGSS => todo!("implement DEBUGSS"),
22 Group0::FLASHCTL => todo!("implement FLASHCTL"),
23 Group0::SYSCTL => todo!("implement SYSCTL"),
24 }
25}
26
27#[cfg(feature = "rt")]
28#[interrupt]
29fn GROUP1() {
30 use mspm0_metapac::Group1;
31
32 let group = pac::CPUSS.int_group(1);
33
34 // Must subtract by 1 since NO_INTR is value 0
35 let iidx = group.iidx().read().stat().to_bits() - 1;
36
37 let Ok(group) = pac::Group1::try_from(iidx as u8) else {
38 debug!("Invalid IIDX for group 1: {}", iidx);
39 return;
40 };
41
42 match group {
43 Group1::GPIOA => crate::gpio::gpioa_interrupt(),
44 Group1::GPIOB => crate::gpio::gpiob_interrupt(),
45 Group1::COMP0 => todo!("implement COMP0"),
46 Group1::TRNG => todo!("implement TRNG"),
47 Group1::GPIOC => crate::gpio::gpioc_interrupt(),
48 }
49}
diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs
new file mode 100644
index 000000000..ee629f063
--- /dev/null
+++ b/embassy-mspm0/src/lib.rs
@@ -0,0 +1,112 @@
1#![no_std]
2// Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc
3#![cfg_attr(
4 docsrs,
5 feature(doc_auto_cfg, doc_cfg_hide),
6 doc(cfg_hide(doc, docsrs))
7)]
8
9// This mod MUST go first, so that the others see its macros.
10pub(crate) mod fmt;
11
12pub mod gpio;
13pub mod timer;
14
15#[cfg(feature = "_time-driver")]
16mod time_driver;
17
18// Interrupt group handlers.
19#[cfg_attr(feature = "mspm0c110x", path = "int_group/c110x.rs")]
20#[cfg_attr(feature = "mspm0g110x", path = "int_group/g110x.rs")]
21#[cfg_attr(feature = "mspm0g150x", path = "int_group/g150x.rs")]
22#[cfg_attr(feature = "mspm0g151x", path = "int_group/g151x.rs")]
23#[cfg_attr(feature = "mspm0g310x", path = "int_group/g310x.rs")]
24#[cfg_attr(feature = "mspm0g350x", path = "int_group/g350x.rs")]
25#[cfg_attr(feature = "mspm0g351x", path = "int_group/g351x.rs")]
26#[cfg_attr(feature = "mspm0l110x", path = "int_group/l110x.rs")]
27#[cfg_attr(feature = "mspm0l122x", path = "int_group/l122x.rs")]
28#[cfg_attr(feature = "mspm0l130x", path = "int_group/l130x.rs")]
29#[cfg_attr(feature = "mspm0l134x", path = "int_group/l134x.rs")]
30#[cfg_attr(feature = "mspm0l222x", path = "int_group/l222x.rs")]
31mod int_group;
32
33pub(crate) mod _generated {
34 #![allow(dead_code)]
35 #![allow(unused_imports)]
36 #![allow(non_snake_case)]
37 #![allow(missing_docs)]
38
39 include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
40}
41
42// Reexports
43pub use _generated::{peripherals, Peripherals};
44pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
45#[cfg(feature = "unstable-pac")]
46pub use mspm0_metapac as pac;
47#[cfg(not(feature = "unstable-pac"))]
48pub(crate) use mspm0_metapac as pac;
49
50pub use crate::_generated::interrupt;
51pub(crate) use _generated::gpio_pincm;
52
53
54/// `embassy-mspm0` global configuration.
55#[non_exhaustive]
56#[derive(Clone, Copy)]
57pub struct Config {
58 // TODO
59}
60
61impl Default for Config {
62 fn default() -> Self {
63 Self {
64 // TODO
65 }
66 }
67}
68
69pub fn init(_config: Config) -> Peripherals {
70 critical_section::with(|cs| {
71 let peripherals = Peripherals::take_with_cs(cs);
72
73 // TODO: Further clock configuration
74
75 pac::SYSCTL.mclkcfg().modify(|w| {
76 // Enable MFCLK
77 w.set_usemftick(true);
78 // MDIV must be disabled if MFCLK is enabled.
79 w.set_mdiv(0);
80 });
81
82 // Enable MFCLK for peripheral use
83 //
84 // TODO: Optional?
85 pac::SYSCTL.genclken().modify(|w| {
86 w.set_mfpclken(true);
87 });
88
89 pac::SYSCTL.borthreshold().modify(|w| {
90 w.set_level(0);
91 });
92
93 gpio::init(pac::GPIOA);
94 #[cfg(gpio_pb)]
95 gpio::init(pac::GPIOB);
96 #[cfg(gpio_pc)]
97 gpio::init(pac::GPIOC);
98
99 _generated::enable_group_interrupts(cs);
100
101 #[cfg(feature = "mspm0c110x")]
102 unsafe {
103 use crate::_generated::interrupt::typelevel::Interrupt;
104 crate::interrupt::typelevel::GPIOA::enable();
105 }
106
107 #[cfg(feature = "_time-driver")]
108 time_driver::init(cs);
109
110 peripherals
111 })
112}
diff --git a/embassy-mspm0/src/time_driver.rs b/embassy-mspm0/src/time_driver.rs
new file mode 100644
index 000000000..3af7a5edb
--- /dev/null
+++ b/embassy-mspm0/src/time_driver.rs
@@ -0,0 +1,437 @@
1use core::{
2 cell::{Cell, RefCell},
3 sync::atomic::{compiler_fence, AtomicU32, Ordering},
4 task::Waker,
5};
6
7use critical_section::{CriticalSection, Mutex};
8use embassy_time_driver::Driver;
9use embassy_time_queue_utils::Queue;
10use mspm0_metapac::{
11 interrupt,
12 tim::{
13 vals::{Cm, Cvae, CxC, EvtCfg, PwrenKey, Ratio, Repeat, ResetKey},
14 Counterregs16, Tim,
15 },
16};
17
18use crate::peripherals;
19use crate::timer::SealedTimer;
20
21// Currently TIMG12 and TIMG13 are excluded because those are 32-bit timers.
22#[cfg(time_driver_timg0)]
23type T = peripherals::TIMG0;
24#[cfg(time_driver_timg1)]
25type T = peripherals::TIMG1;
26#[cfg(time_driver_timg2)]
27type T = peripherals::TIMG2;
28#[cfg(time_driver_timg3)]
29type T = peripherals::TIMG3;
30#[cfg(time_driver_timg4)]
31type T = peripherals::TIMG4;
32#[cfg(time_driver_timg5)]
33type T = peripherals::TIMG5;
34#[cfg(time_driver_timg6)]
35type T = peripherals::TIMG6;
36#[cfg(time_driver_timg7)]
37type T = peripherals::TIMG7;
38#[cfg(time_driver_timg8)]
39type T = peripherals::TIMG8;
40#[cfg(time_driver_timg9)]
41type T = peripherals::TIMG9;
42#[cfg(time_driver_timg10)]
43type T = peripherals::TIMG10;
44#[cfg(time_driver_timg11)]
45type T = peripherals::TIMG11;
46#[cfg(time_driver_timg14)]
47type T = peripherals::TIMG14;
48#[cfg(time_driver_tima0)]
49type T = peripherals::TIMA0;
50#[cfg(time_driver_tima1)]
51type T = peripherals::TIMA1;
52
53// TODO: RTC
54
55fn regs() -> Tim {
56 unsafe { Tim::from_ptr(T::regs()) }
57}
58
59fn regs_counter(tim: Tim) -> Counterregs16 {
60 unsafe { Counterregs16::from_ptr(tim.counterregs(0).as_ptr()) }
61}
62
63/// Clock timekeeping works with something we call "periods", which are time intervals
64/// of 2^15 ticks. The Clock counter value is 16 bits, so one "overflow cycle" is 2 periods.
65fn calc_now(period: u32, counter: u16) -> u64 {
66 ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64)
67}
68
69/// The TIMx driver uses one of the `TIMG` or `TIMA` timer instances to implement a timer with a 32.768 kHz
70/// tick rate. (TODO: Allow setting the tick rate)
71///
72/// This driver defines a period to be 2^15 ticks. 16-bit timers of course count to 2^16 ticks.
73///
74/// To generate a period every 2^15 ticks, the CC0 value is set to 2^15 and the load value set to 2^16.
75/// Incrementing the period on a CCU0 and load results in the a period of 2^15 ticks.
76///
77/// For a specific timestamp, load the lower 16 bits into the CC1 value. When the period where the timestamp
78/// should be enabled is reached, then the CCU1 (CC1 up) interrupt runs to actually wake the timer.
79///
80/// TODO: Compensate for per part variance. This can supposedly be done with the FCC system.
81/// TODO: Allow using 32-bit timers (TIMG12 and TIMG13).
82struct TimxDriver {
83 /// Number of 2^15 periods elapsed since boot.
84 period: AtomicU32,
85 /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled.
86 alarm: Mutex<Cell<u64>>,
87 queue: Mutex<RefCell<Queue>>,
88}
89
90impl TimxDriver {
91 #[inline(never)]
92 fn init(&'static self, _cs: CriticalSection) {
93 // Clock config
94 // TODO: Configurable tick rate up to 4 MHz (32 kHz for now)
95 let regs = regs();
96
97 // Reset timer
98 regs.gprcm(0).rstctl().write(|w| {
99 w.set_resetassert(true);
100 w.set_key(ResetKey::KEY);
101 w.set_resetstkyclr(true);
102 });
103
104 // Power up timer
105 regs.gprcm(0).pwren().write(|w| {
106 w.set_enable(true);
107 w.set_key(PwrenKey::KEY);
108 });
109
110 // Following the instructions according to SLAU847D 23.2.1: TIMCLK Configuration
111
112 // 1. Select TIMCLK source
113 regs.clksel().modify(|w| {
114 // Use LFCLK for a 32.768kHz tick rate
115 w.set_lfclk_sel(true);
116 // TODO: Allow MFCLK for configurable tick rate up to 4 MHz
117 // w.set_mfclk_sel(ClkSel::ENABLE);
118 });
119
120 // 2. Divide by TIMCLK, we don't need to divide further for the 32kHz tick rate
121 regs.clkdiv().modify(|w| {
122 w.set_ratio(Ratio::DIV_BY_1);
123 });
124
125 // 3. To be generic across timer instances, we do not use the prescaler.
126 // TODO: mspm0-sdk always sets this, regardless of timer width?
127 regs.commonregs(0).cps().modify(|w| {
128 w.set_pcnt(0);
129 });
130
131 regs.pdbgctl().modify(|w| {
132 w.set_free(true);
133 });
134
135 // 4. Enable the TIMCLK.
136 regs.commonregs(0).cclkctl().modify(|w| {
137 w.set_clken(true);
138 });
139
140 regs.counterregs(0).ctrctl().modify(|w| {
141 // allow counting during debug
142 w.set_repeat(Repeat::REPEAT_3);
143 w.set_cvae(Cvae::ZEROVAL);
144 w.set_cm(Cm::UP);
145
146 // Must explicitly set CZC, CAC and CLC to 0 in order for all the timers to count.
147 //
148 // The reset value of these registers is 0x07, which is a reserved value.
149 //
150 // Looking at a bit representation of the reset value, this appears to be an AND
151 // of 2-input QEI mode and CCCTL_3 ACOND. Given that TIMG14 and TIMA0 have no QEI
152 // and 4 capture and compare channels, this works by accident for those timer units.
153 w.set_czc(CxC::CCTL0);
154 w.set_cac(CxC::CCTL0);
155 w.set_clc(CxC::CCTL0);
156 });
157
158 // Setup the period
159 let ctr = regs_counter(regs);
160
161 // Middle
162 ctr.cc(0).modify(|w| {
163 w.set_ccval(0x7FFF);
164 });
165
166 ctr.load().modify(|w| {
167 w.set_ld(u16::MAX);
168 });
169
170 // Enable the period interrupts
171 //
172 // This does not appear to ever be set for CPU_INT in the TI SDK and is not technically needed.
173 regs.evt_mode().modify(|w| {
174 w.set_evt_cfg(0, EvtCfg::SOFTWARE);
175 });
176
177 regs.int_event(0).imask().modify(|w| {
178 w.set_l(true);
179 w.set_ccu0(true);
180 });
181
182 unsafe { T::enable_interrupt() };
183
184 // Allow the counter to start counting.
185 regs.counterregs(0).ctrctl().modify(|w| {
186 w.set_en(true);
187 });
188 }
189
190 #[inline(never)]
191 fn next_period(&self) {
192 let r = regs();
193
194 // We only modify the period from the timer interrupt, so we know this can't race.
195 let period = self.period.load(Ordering::Relaxed) + 1;
196 self.period.store(period, Ordering::Relaxed);
197 let t = (period as u64) << 15;
198
199 critical_section::with(move |cs| {
200 r.int_event(0).imask().modify(move |w| {
201 let alarm = self.alarm.borrow(cs);
202 let at = alarm.get();
203
204 if at < t + 0xC000 {
205 // just enable it. `set_alarm` has already set the correct CC1 val.
206 w.set_ccu1(true);
207 }
208 })
209 });
210 }
211
212 #[inline(never)]
213 fn on_interrupt(&self) {
214 let r = regs();
215
216 critical_section::with(|cs| {
217 let mis = r.int_event(0).mis().read();
218
219 // Advance to next period if overflowed
220 if mis.l() {
221 self.next_period();
222
223 r.int_event(0).iclr().write(|w| {
224 w.set_l(true);
225 });
226 }
227
228 if mis.ccu0() {
229 self.next_period();
230
231 r.int_event(0).iclr().write(|w| {
232 w.set_ccu0(true);
233 });
234 }
235
236 if mis.ccu1() {
237 r.int_event(0).iclr().write(|w| {
238 w.set_ccu1(true);
239 });
240
241 self.trigger_alarm(cs);
242 }
243 });
244 }
245
246 fn trigger_alarm(&self, cs: CriticalSection) {
247 let mut next = self
248 .queue
249 .borrow(cs)
250 .borrow_mut()
251 .next_expiration(self.now());
252
253 while !self.set_alarm(cs, next) {
254 next = self
255 .queue
256 .borrow(cs)
257 .borrow_mut()
258 .next_expiration(self.now());
259 }
260 }
261
262 fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {
263 let r = regs();
264 let ctr = regs_counter(r);
265
266 self.alarm.borrow(cs).set(timestamp);
267
268 let t = self.now();
269
270 if timestamp <= t {
271 // If alarm timestamp has passed the alarm will not fire.
272 // Disarm the alarm and return `false` to indicate that.
273 r.int_event(0).imask().modify(|w| w.set_ccu1(false));
274
275 self.alarm.borrow(cs).set(u64::MAX);
276
277 return false;
278 }
279
280 // Write the CC1 value regardless of whether we're going to enable it now or not.
281 // This way, when we enable it later, the right value is already set.
282 ctr.cc(1).write(|w| {
283 w.set_ccval(timestamp as u16);
284 });
285
286 // Enable it if it'll happen soon. Otherwise, `next_period` will enable it.
287 let diff = timestamp - t;
288 r.int_event(0).imask().modify(|w| w.set_ccu1(diff < 0xC000));
289
290 // Reevaluate if the alarm timestamp is still in the future
291 let t = self.now();
292 if timestamp <= t {
293 // If alarm timestamp has passed since we set it, we have a race condition and
294 // the alarm may or may not have fired.
295 // Disarm the alarm and return `false` to indicate that.
296 // It is the caller's responsibility to handle this ambiguity.
297 r.int_event(0).imask().modify(|w| w.set_ccu1(false));
298
299 self.alarm.borrow(cs).set(u64::MAX);
300
301 return false;
302 }
303
304 // We're confident the alarm will ring in the future.
305 true
306 }
307}
308
309impl Driver for TimxDriver {
310 fn now(&self) -> u64 {
311 let regs = regs();
312
313 let period = self.period.load(Ordering::Relaxed);
314 // Ensure the compiler does not read the counter before the period.
315 compiler_fence(Ordering::Acquire);
316
317 let counter = regs_counter(regs).ctr().read().cctr() as u16;
318
319 calc_now(period, counter)
320 }
321
322 fn schedule_wake(&self, at: u64, waker: &Waker) {
323 critical_section::with(|cs| {
324 let mut queue = self.queue.borrow(cs).borrow_mut();
325
326 if queue.schedule_wake(at, waker) {
327 let mut next = queue.next_expiration(self.now());
328
329 while !self.set_alarm(cs, next) {
330 next = queue.next_expiration(self.now());
331 }
332 }
333 });
334 }
335}
336
337embassy_time_driver::time_driver_impl!(static DRIVER: TimxDriver = TimxDriver {
338 period: AtomicU32::new(0),
339 alarm: Mutex::new(Cell::new(u64::MAX)),
340 queue: Mutex::new(RefCell::new(Queue::new()))
341});
342
343pub(crate) fn init(cs: CriticalSection) {
344 DRIVER.init(cs);
345}
346
347#[cfg(time_driver_timg0)]
348#[interrupt]
349fn TIMG0() {
350 DRIVER.on_interrupt();
351}
352
353#[cfg(time_driver_timg1)]
354#[interrupt]
355fn TIMG1() {
356 DRIVER.on_interrupt();
357}
358
359#[cfg(time_driver_timg2)]
360#[interrupt]
361fn TIMG2() {
362 DRIVER.on_interrupt();
363}
364
365#[cfg(time_driver_timg3)]
366#[interrupt]
367fn TIMG3() {
368 DRIVER.on_interrupt();
369}
370
371#[cfg(time_driver_timg4)]
372#[interrupt]
373fn TIMG4() {
374 DRIVER.on_interrupt();
375}
376
377#[cfg(time_driver_timg5)]
378#[interrupt]
379fn TIMG5() {
380 DRIVER.on_interrupt();
381}
382
383#[cfg(time_driver_timg6)]
384#[interrupt]
385fn TIMG6() {
386 DRIVER.on_interrupt();
387}
388
389#[cfg(time_driver_timg7)]
390#[interrupt]
391fn TIMG7() {
392 DRIVER.on_interrupt();
393}
394
395#[cfg(time_driver_timg8)]
396#[interrupt]
397fn TIMG8() {
398 DRIVER.on_interrupt();
399}
400
401#[cfg(time_driver_timg9)]
402#[interrupt]
403fn TIMG9() {
404 DRIVER.on_interrupt();
405}
406
407#[cfg(time_driver_timg10)]
408#[interrupt]
409fn TIMG10() {
410 DRIVER.on_interrupt();
411}
412
413#[cfg(time_driver_timg11)]
414#[interrupt]
415fn TIMG11() {
416 DRIVER.on_interrupt();
417}
418
419// TODO: TIMG12 and TIMG13
420
421#[cfg(time_driver_timg14)]
422#[interrupt]
423fn TIMG14() {
424 DRIVER.on_interrupt();
425}
426
427#[cfg(time_driver_tima0)]
428#[interrupt]
429fn TIMA0() {
430 DRIVER.on_interrupt();
431}
432
433#[cfg(time_driver_tima1)]
434#[interrupt]
435fn TIMA1() {
436 DRIVER.on_interrupt();
437}
diff --git a/embassy-mspm0/src/timer.rs b/embassy-mspm0/src/timer.rs
new file mode 100644
index 000000000..4441e5640
--- /dev/null
+++ b/embassy-mspm0/src/timer.rs
@@ -0,0 +1,48 @@
1#![macro_use]
2
3/// Amount of bits of a timer.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6pub enum TimerBits {
7 /// 16 bits.
8 Bits16,
9 /// 32 bits.
10 Bits32,
11}
12
13#[allow(private_bounds)]
14pub trait Timer: SealedTimer + 'static {
15 /// Amount of bits this timer has.
16 const BITS: TimerBits;
17}
18
19pub(crate) trait SealedTimer {
20 /// Registers for this timer.
21 ///
22 /// This is a raw pointer to the register block. The actual register block layout varies depending on the
23 /// timer type.
24 fn regs() -> *mut ();
25
26 /// Enable the interrupt corresponding to this timer.
27 unsafe fn enable_interrupt();
28}
29
30macro_rules! impl_timer {
31 ($name: ident, $bits: ident) => {
32 impl crate::timer::SealedTimer for crate::peripherals::$name {
33 fn regs() -> *mut () {
34 crate::pac::$name.as_ptr()
35 }
36
37 unsafe fn enable_interrupt() {
38 use embassy_hal_internal::interrupt::InterruptExt;
39 crate::interrupt::$name.unpend();
40 crate::interrupt::$name.enable();
41 }
42 }
43
44 impl crate::timer::Timer for crate::peripherals::$name {
45 const BITS: crate::timer::TimerBits = crate::timer::TimerBits::$bits;
46 }
47 };
48}
diff --git a/examples/mspm0c1104/.cargo/config.toml b/examples/mspm0c1104/.cargo/config.toml
new file mode 100644
index 000000000..204a56b1c
--- /dev/null
+++ b/examples/mspm0c1104/.cargo/config.toml
@@ -0,0 +1,11 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace MSPM0C1104 with your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --chip MSPM0C1104 --protocol=swd"
4
5[build]
6target = "thumbv6m-none-eabi"
7
8[env]
9DEFMT_LOG = "debug"
10# defmt's buffer needs to be shrunk since the MSPM0C1104 only has 1KB of ram.
11DEFMT_RTT_BUFFER_SIZE = "72"
diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml
new file mode 100644
index 000000000..35c9b1358
--- /dev/null
+++ b/examples/mspm0c1104/Cargo.toml
@@ -0,0 +1,32 @@
1[package]
2edition = "2021"
3name = "embassy-mspm0-c1104-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6
7[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c110x", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["task-arena-size-128", "arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3"
16defmt-rtt = "0.4"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] }
18panic-semihosting = "0.6.0"
19
20# The chip only has 1KB of ram, so we must optimize binaries regardless
21[profile.dev]
22debug = 2
23opt-level = "z"
24lto = true
25codegen-units = 1
26# strip = true
27
28[profile.release]
29debug = 2
30opt-level = "z"
31lto = true
32codegen-units = 1
diff --git a/examples/mspm0c1104/README.md b/examples/mspm0c1104/README.md
new file mode 100644
index 000000000..e5c9f961d
--- /dev/null
+++ b/examples/mspm0c1104/README.md
@@ -0,0 +1,27 @@
1# Examples for MSPM0C110x family
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-MSPM0C1104](https://www.ti.com/tool/LP-MSPM0C1104) 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 C1104 it should be `probe-rs run --chip MSPM0C1104`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for C1104 it should be `mspm0c1104`. 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/mspm0c1104/build.rs b/examples/mspm0c1104/build.rs
new file mode 100644
index 000000000..30691aa97
--- /dev/null
+++ b/examples/mspm0c1104/build.rs
@@ -0,0 +1,35 @@
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}
diff --git a/examples/mspm0c1104/memory.x b/examples/mspm0c1104/memory.x
new file mode 100644
index 000000000..a9108835a
--- /dev/null
+++ b/examples/mspm0c1104/memory.x
@@ -0,0 +1,5 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 16K
4 RAM : ORIGIN = 0x20000000, LENGTH = 1K
5}
diff --git a/examples/mspm0c1104/src/bin/blinky.rs b/examples/mspm0c1104/src/bin/blinky.rs
new file mode 100644
index 000000000..264ea3eb5
--- /dev/null
+++ b/examples/mspm0c1104/src/bin/blinky.rs
@@ -0,0 +1,27 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Level, Output},
8 Config,
9};
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_halt as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) -> ! {
15 info!("Hello world!");
16 let p = embassy_mspm0::init(Config::default());
17
18 let mut led1 = Output::new(p.PA22, Level::Low);
19 led1.set_inversion(true);
20
21 loop {
22 Timer::after_millis(400).await;
23
24 info!("Toggle");
25 led1.toggle();
26 }
27}
diff --git a/examples/mspm0c1104/src/bin/button.rs b/examples/mspm0c1104/src/bin/button.rs
new file mode 100644
index 000000000..988170ef9
--- /dev/null
+++ b/examples/mspm0c1104/src/bin/button.rs
@@ -0,0 +1,35 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Input, Level, Output, Pull},
8 Config,
9};
10use {defmt_rtt as _, panic_halt as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) -> ! {
14 info!("Hello world!");
15
16 let p = embassy_mspm0::init(Config::default());
17
18 let led1 = p.PA22;
19 let s2 = p.PA16;
20
21 let mut led1 = Output::new(led1, Level::Low);
22
23 let mut s2 = Input::new(s2, Pull::Up);
24
25 // led1 is active low
26 led1.set_high();
27
28 loop {
29 s2.wait_for_falling_edge().await;
30
31 info!("Switch 2 was pressed");
32
33 led1.toggle();
34 }
35}
diff --git a/examples/mspm0g3507/.cargo/config.toml b/examples/mspm0g3507/.cargo/config.toml
new file mode 100644
index 000000000..34c720cdd
--- /dev/null
+++ b/examples/mspm0g3507/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace MSPM0G3507 with your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --chip MSPM0G3507 --protocol=swd"
4
5[build]
6target = "thumbv6m-none-eabi"
7
8[env]
9DEFMT_LOG = "debug"
diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml
new file mode 100644
index 000000000..c1f304174
--- /dev/null
+++ b/examples/mspm0g3507/Cargo.toml
@@ -0,0 +1,21 @@
1[package]
2edition = "2021"
3name = "embassy-mspm0-g3507-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6
7[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g350x", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3"
16defmt-rtt = "0.4"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] }
18panic-semihosting = "0.6.0"
19
20[profile.release]
21debug = 2
diff --git a/examples/mspm0g3507/README.md b/examples/mspm0g3507/README.md
new file mode 100644
index 000000000..5e8a83212
--- /dev/null
+++ b/examples/mspm0g3507/README.md
@@ -0,0 +1,27 @@
1# Examples for MSPM0C350x family
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-MSPM0G3507](https://www.ti.com/tool/LP-MSPM0G3507) 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 G3507 it should be `probe-rs run --chip MSPM0G3507`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for G3507 it should be `mspm0g3507`. 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/mspm0g3507/build.rs b/examples/mspm0g3507/build.rs
new file mode 100644
index 000000000..30691aa97
--- /dev/null
+++ b/examples/mspm0g3507/build.rs
@@ -0,0 +1,35 @@
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}
diff --git a/examples/mspm0g3507/memory.x b/examples/mspm0g3507/memory.x
new file mode 100644
index 000000000..37e381fbd
--- /dev/null
+++ b/examples/mspm0g3507/memory.x
@@ -0,0 +1,6 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 128K
4 /* Select non-parity range of SRAM due to SRAM_ERR_01 errata in SLAZ758 */
5 RAM : ORIGIN = 0x20200000, LENGTH = 32K
6}
diff --git a/examples/mspm0g3507/src/bin/blinky.rs b/examples/mspm0g3507/src/bin/blinky.rs
new file mode 100644
index 000000000..11eee2d80
--- /dev/null
+++ b/examples/mspm0g3507/src/bin/blinky.rs
@@ -0,0 +1,27 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Level, Output},
8 Config,
9};
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_halt as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) -> ! {
15 info!("Hello world!");
16 let p = embassy_mspm0::init(Config::default());
17
18 let mut led1 = Output::new(p.PA0, Level::Low);
19 led1.set_inversion(true);
20
21 loop {
22 Timer::after_millis(400).await;
23
24 info!("Toggle");
25 led1.toggle();
26 }
27}
diff --git a/examples/mspm0g3507/src/bin/button.rs b/examples/mspm0g3507/src/bin/button.rs
new file mode 100644
index 000000000..1d9a37c5c
--- /dev/null
+++ b/examples/mspm0g3507/src/bin/button.rs
@@ -0,0 +1,35 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Input, Level, Output, Pull},
8 Config,
9};
10use {defmt_rtt as _, panic_halt as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) -> ! {
14 info!("Hello world!");
15
16 let p = embassy_mspm0::init(Config::default());
17
18 let led1 = p.PA0;
19 let s2 = p.PB21;
20
21 let mut led1 = Output::new(led1, Level::Low);
22
23 let mut s2 = Input::new(s2, Pull::Up);
24
25 // led1 is active low
26 led1.set_high();
27
28 loop {
29 s2.wait_for_falling_edge().await;
30
31 info!("Switch 2 was pressed");
32
33 led1.toggle();
34 }
35}
diff --git a/examples/mspm0g3519/.cargo/config.toml b/examples/mspm0g3519/.cargo/config.toml
new file mode 100644
index 000000000..1a4768682
--- /dev/null
+++ b/examples/mspm0g3519/.cargo/config.toml
@@ -0,0 +1,10 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace MSPM0G3519 with your chip as listed in `probe-rs chip list`
3# TODO: Remove description path after new chiptool release
4runner = "probe-rs run --restore-unwritten --verify --chip MSPM0G3519 --protocol=swd --chip-description-path ./MSPM0GX51X_Series.yaml"
5
6[build]
7target = "thumbv6m-none-eabi"
8
9[env]
10DEFMT_LOG = "trace"
diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml
new file mode 100644
index 000000000..fc6f0e31b
--- /dev/null
+++ b/examples/mspm0g3519/Cargo.toml
@@ -0,0 +1,21 @@
1[package]
2edition = "2021"
3name = "embassy-mspm0-g3519-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6
7[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g351x", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["task-arena-size-16384", "arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3"
16defmt-rtt = "0.4"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] }
18panic-semihosting = "0.6.0"
19
20[profile.release]
21debug = 2
diff --git a/examples/mspm0g3519/MSPM0GX51X_Series.yaml b/examples/mspm0g3519/MSPM0GX51X_Series.yaml
new file mode 100644
index 000000000..375623b94
--- /dev/null
+++ b/examples/mspm0g3519/MSPM0GX51X_Series.yaml
@@ -0,0 +1,424 @@
1name: MSPM0GX51X Series
2manufacturer:
3 id: 0x17
4 cc: 0x0
5generated_from_pack: true
6pack_file_release: 1.0.0
7variants:
8- name: MSPM0G1518
9 cores:
10 - name: main
11 type: armv6m
12 core_access_options: !Arm
13 ap: 0
14 memory_map:
15 - !Nvm
16 name: IROM1
17 range:
18 start: 0x0
19 end: 0x40000
20 cores:
21 - main
22 access:
23 write: false
24 boot: true
25 - !Generic
26 name: IROM2
27 range:
28 start: 0x400000
29 end: 0x440000
30 cores:
31 - main
32 access:
33 write: false
34 - !Generic
35 name: IRAM1
36 range:
37 start: 0x20000000
38 end: 0x20010000
39 cores:
40 - main
41 - !Generic
42 name: IRAM_Parity
43 range:
44 start: 0x20100000
45 end: 0x20110000
46 cores:
47 - main
48 - !Ram
49 name: IRAM_No_Parity
50 range:
51 start: 0x20200000
52 end: 0x20220000
53 cores:
54 - main
55 - !Generic
56 name: IRAM_Parity_Code
57 range:
58 start: 0x20300000
59 end: 0x20310000
60 cores:
61 - main
62 - !Generic
63 name: NonMain_ECC
64 range:
65 start: 0x41c00000
66 end: 0x41c00800
67 cores:
68 - main
69 access:
70 write: false
71 execute: false
72 - !Generic
73 name: Factory_ECC
74 range:
75 start: 0x41c40000
76 end: 0x41c40200
77 cores:
78 - main
79 access:
80 write: false
81 execute: false
82 - !Generic
83 name: Data
84 range:
85 start: 0x41d00000
86 end: 0x41d04000
87 cores:
88 - main
89 access:
90 write: false
91 execute: false
92 flash_algorithms:
93 - mspm0gx51x_main_512kb
94 - mspm0gx51x_nonmain
95 - mspm0gx51x_data_16kb
96- name: MSPM0G1519
97 cores:
98 - name: main
99 type: armv6m
100 core_access_options: !Arm
101 ap: 0
102 memory_map:
103 - !Nvm
104 name: IROM1
105 range:
106 start: 0x0
107 end: 0x80000
108 cores:
109 - main
110 access:
111 write: false
112 boot: true
113 - !Generic
114 name: IROM2
115 range:
116 start: 0x400000
117 end: 0x480000
118 cores:
119 - main
120 access:
121 write: false
122 - !Generic
123 name: IRAM1
124 range:
125 start: 0x20000000
126 end: 0x20010000
127 cores:
128 - main
129 - !Generic
130 name: IRAM_Parity
131 range:
132 start: 0x20100000
133 end: 0x20110000
134 cores:
135 - main
136 - !Ram
137 name: IRAM_No_Parity
138 range:
139 start: 0x20200000
140 end: 0x20220000
141 cores:
142 - main
143 - !Generic
144 name: IRAM_Parity_Code
145 range:
146 start: 0x20300000
147 end: 0x20310000
148 cores:
149 - main
150 - !Generic
151 name: NonMain_ECC
152 range:
153 start: 0x41c00000
154 end: 0x41c00800
155 cores:
156 - main
157 access:
158 write: false
159 execute: false
160 - !Generic
161 name: Factory_ECC
162 range:
163 start: 0x41c40000
164 end: 0x41c40200
165 cores:
166 - main
167 access:
168 write: false
169 execute: false
170 - !Generic
171 name: Data
172 range:
173 start: 0x41d00000
174 end: 0x41d04000
175 cores:
176 - main
177 access:
178 write: false
179 execute: false
180 flash_algorithms:
181 - mspm0gx51x_main_512kb
182 - mspm0gx51x_nonmain
183 - mspm0gx51x_data_16kb
184- name: MSPM0G3518
185 cores:
186 - name: main
187 type: armv6m
188 core_access_options: !Arm
189 ap: 0
190 memory_map:
191 - !Nvm
192 name: IROM1
193 range:
194 start: 0x0
195 end: 0x40000
196 cores:
197 - main
198 access:
199 write: false
200 boot: true
201 - !Generic
202 name: IROM2
203 range:
204 start: 0x400000
205 end: 0x440000
206 cores:
207 - main
208 access:
209 write: false
210 - !Generic
211 name: IRAM1
212 range:
213 start: 0x20000000
214 end: 0x20010000
215 cores:
216 - main
217 - !Generic
218 name: IRAM_Parity
219 range:
220 start: 0x20100000
221 end: 0x20110000
222 cores:
223 - main
224 - !Ram
225 name: IRAM_No_Parity
226 range:
227 start: 0x20200000
228 end: 0x20220000
229 cores:
230 - main
231 - !Generic
232 name: IRAM_Parity_Code
233 range:
234 start: 0x20300000
235 end: 0x20310000
236 cores:
237 - main
238 - !Generic
239 name: NonMain_ECC
240 range:
241 start: 0x41c00000
242 end: 0x41c00800
243 cores:
244 - main
245 access:
246 write: false
247 execute: false
248 - !Generic
249 name: Factory_ECC
250 range:
251 start: 0x41c40000
252 end: 0x41c40200
253 cores:
254 - main
255 access:
256 write: false
257 execute: false
258 - !Generic
259 name: Data
260 range:
261 start: 0x41d00000
262 end: 0x41d04000
263 cores:
264 - main
265 access:
266 write: false
267 execute: false
268 flash_algorithms:
269 - mspm0gx51x_main_512kb
270 - mspm0gx51x_nonmain
271 - mspm0gx51x_data_16kb
272- name: MSPM0G3519
273 cores:
274 - name: main
275 type: armv6m
276 core_access_options: !Arm
277 ap: 0
278 memory_map:
279 - !Nvm
280 name: IROM1
281 range:
282 start: 0x0
283 end: 0x80000
284 cores:
285 - main
286 access:
287 write: false
288 boot: true
289 - !Generic
290 name: IROM2
291 range:
292 start: 0x400000
293 end: 0x480000
294 cores:
295 - main
296 access:
297 write: false
298 - !Generic
299 name: IRAM1
300 range:
301 start: 0x20000000
302 end: 0x20010000
303 cores:
304 - main
305 - !Generic
306 name: IRAM_Parity
307 range:
308 start: 0x20100000
309 end: 0x20110000
310 cores:
311 - main
312 - !Ram
313 name: IRAM_No_Parity
314 range:
315 start: 0x20200000
316 end: 0x20220000
317 cores:
318 - main
319 - !Generic
320 name: IRAM_Parity_Code
321 range:
322 start: 0x20300000
323 end: 0x20310000
324 cores:
325 - main
326 - !Generic
327 name: NonMain_ECC
328 range:
329 start: 0x41c00000
330 end: 0x41c00800
331 cores:
332 - main
333 access:
334 write: false
335 execute: false
336 - !Generic
337 name: Factory_ECC
338 range:
339 start: 0x41c40000
340 end: 0x41c40200
341 cores:
342 - main
343 access:
344 write: false
345 execute: false
346 - !Generic
347 name: Data
348 range:
349 start: 0x41d00000
350 end: 0x41d04000
351 cores:
352 - main
353 access:
354 write: false
355 execute: false
356 flash_algorithms:
357 - mspm0gx51x_main_512kb
358 - mspm0gx51x_nonmain
359 - mspm0gx51x_data_16kb
360flash_algorithms:
361- name: mspm0gx51x_main_512kb
362 description: MSPM0GX51X MAIN 512KB
363 default: true
364 instructions: ESEJAgEiQlADSUEYCmgHIBBABCj60HBH0BMAABC1FEgBaAcikUMBYBJMYWggaAMikEMgYBEgAAQIQAEhCgWQQgXQCQSIQgTRAfC2+QHgAfCL+WBoDyGIQ2BgAfCF+QZIAWgEIpFDAWAA8Aj4ACAQvQATQEAAAQtAEO0A4ARIBSFBYAEhAWADSAFoSQf81HBHAOEMQNDjDEAAIHBHcLUEIMZDACQITeAHB9EALgXQKEYA8Oj5BEZ2HPXnASBEQARA//fc/yBGcL0A0AxA+LUERm1GKUYA8Cj4AUYBICp4ACoB0IUCAOBFAgApGtAEIMdDACAMTsEHEdEALw/Q//e+/zBGIUYqRgDwp/xAIjBGIUYA8ND4fxwA8Cn46+cBIUhACED4vQDQDEAQtQxKE2gFJBRgByQcQApLG2gUYIIKCUgQQAlKGkCQQgHSACMLcJBCAdMAIBC9ASAQvcBGABNAQBgAxEH/7z8A/w8AAIGwCkgBaAciCkAAkgCZybIDKQPQAJnJsgEp89EAmMCywR5IQkhBAbBwR8BG0OMMQP61FEYNRgZGAqn/97//ASEAKCjQAC0m0AcgKEAj0QKoAXgBIAApAdCBAgDgQQIBkQ9PACEALRbQwAcU0P/3UP8KSDFGAZoA8Dn8OGhAB/zUBkgxRiJGAPAf+wg2CDQIPf/3tv/l5whG/r3ARgDQDEDQ4wxAELUFTAFRABkAKwPQAspBYFse+eeAaBC9BBEAABC1BUwBUQAZmkIC2ALKQWD654BoEL3ARgQRAAC8tQpMBBkAlACcIYAISUEYACsG0BSIAZEBnSyAkhxbHvbnBElAWICyvL3ARgQRAAAIEQAADBEAALy1CUwEGQCUAJwhgAdJQRiaQgXYFIgBkQGdLICSHPfnA0lAWICyvL0EEQAACBEAAAwRAAAQtQIjE0MRIhIChBhjYCFiASGBUBC9wEaAtQIjE0MDSoNQghjRYf/3kf6AvQQRAAAQtQRGEUgAISFQIBhBYIFgykMCZBEgAAIiGFIjU2ARYgEhIVAgRgDwKfgJSQpoBSMLYAcjE0AHShJoC2CRDgTQACgC0CBGAPAx+BC90BEAAAATQEAYAMRBA0kAIkJQQBhCYIJgcEfARtARAAAAIclDAUqBUHBHwEYQEgAAgbAKSUAYAWgHIgpAAJIAmcmyAykD0ACZybIBKfPRAJjAssEeSEJIQQGwcEfQEwAA/rUYSxloBSIaYAciCkAWSQloGmARIhICApCAGAGQjw4STQEgAp7/sv83+bK5QhXQwQcT0DBGAPD5+AEkYgIwRilGAPBB+0IgAZlIYA1iDGCgAi0YMEb/97v/5OcBIQhA/r3ARgATQEAYAMRBAADQQRC1BEYQSAAhIVAgGEFggWDKQwJkDUhSIiJQIBjBYSBG//fu/QpJCmgFIwtgByMTQAhKEmgLYJEOBNABKALQIEYA8Ar4EL3ARtARAAAEEQAAABNAQBgAxEGAtQdJACJCUEEYSmCKYAVJUiJCUEEYBErKYf/3xf2AvdARAAAEEQAAAADQQfC1h7AERgDwhfgFRjpIAWgFIgJgByIKQDhJCWgCYDhIIBgCkBEgAAIElCYYNUgIQClGAfBf+CpGgAIBkGgIBpAQIAWQACcBJD1GIEYDkgCUlUJJ0sEHR9AGmIVCAdIAIQDgASEoSABoQAUgRgDVCEYpBokOBdH5FTtGJKd5Wh9GBZEAKCBGKtAEnCBGAPBU+AEgAQSyaApDsmAfIQkBBZoKQLNoi0OZGLFgDyFJArJoikNBAlEYsWAAIQKaEWBRYJFgyUMRZFIhcWApRgGaUUMxYjBgIEYAnP/3AP8DmgEhCQZ/GG0cs+cBIQoEs2iTQ7NgCEAHsPC9ABNAQBgAxEHQEQAA/w8AAEggC0AQACAAQACAAAZIAWgFIgJgByIKQARJCWgCYIgEgA9AHHBHwEYAE0BAGADEQREhCQJCGAUjU2ABIkJQAkgBaEkH/NRwR9DjDEAQtQRG//eC/gAoENAJSCAYESEJAmEYACICYEIgSGAGSAhiASAIYCBG//eu/hC9ACAQvcBGEBIAAAAAwEEBSQAiQlBwRxASAAAQtQRG//fs/gMoDNEGSCAYBklhGAAiCmBCIQFgBEnBYSBG//fd/BC9BBEAABASAAAAAMBBELUERv/3FP8AKBDQCUggGBEhCQJhGAAiAmBCIEhgBkgIYgEgCGAgRv/3cP4QvQAgEL3ARhASAAAAAMBBsLURIxsCxBgBJWVgZWIhYhF4IWPFULC9ELUFSwEkxFDDGBxi2WEReNli//eh/BC9BBEAAHC1ESMbAsQYASVlYAMmZmIhYhGIIWPFUHC9wEYQtQZLASTEUMMYAyQcYtlhEYjZYv/3hPwQvcBGBBEAAHC1ESMbAsQYASVlYA8mZmIhYhFoIWPFUHC9wEYQtQZLASTEUMMYDyQcYtlhEWjZYv/3ZvwQvcBGBBEAAHC1ESMbAsQYASVlYP8mZmIhYhFoIWNRaGFjxVBwvcBGELUHSwEkxFDDGP8kHGLZYRFo2WJRaBlj//dE/BC9wEYEEQAAcLURIxsCxBgBJWVg/yYCNmZiIWIReCFjxVBwvRC1BksBJMRQwxj/JAI0HGLZYRF42WL/9yX8EL0EEQAAcLURIxsCxBgBJWVg/yYENmZiIWIRiCFjxVBwvRC1BksBJMRQwxj/JAQ0HGLZYRGI2WL/9wf8EL0EEQAAcLURIxsCxBgBJWVg/yYQNmZiIWIRaCFjxVBwvRC1BksBJMRQwxj/JBA0HGLZYRFo2WL/9+n7EL0EEQAAcLURIxsCxBgBJWVgBE5mYiFiEWghY1FoYWPFUHC9wEb/AQAAELUHSwEkxFDDGAZMHGLZYRFo2WJRaBlj//fG+xC9wEYEEQAA/wEAAPC1ESQkAgUZASZuYP8nAjdvYiliEXgpYxl4AkqBUAZR8L3ARrARAACwtQhMASUFUQQZ/yUCNSVi4WEReOFiGXgDSoFQ//ec+7C9wEYEEQAAsBEAAPC1ESQkAgUZASZuYP8nBDdvYiliEYgpYxl4AkqBUAZR8L3ARrARAACwtQhMASUFUQQZ/yUENSVi4WERiOFiGXgDSoFQ//dy+7C9wEYEEQAAsBEAAPC1ESQkAgUZASZuYP8nEDdvYiliEWgpYxl4AkqBUAZR8L3ARrARAACwtQhMASUFUQQZ/yUQNSVi4WERaOFiGXgDSoFQ//dI+7C9wEYEEQAAsBEAAPC1ESQkAgUZASZuYAVPb2IpYhFoKWNRaGljGXgCSoFQBlHwvf8BAACwEQAAsLUITAElBVEEGQdNJWLhYRFo4WJRaCFjGXgESoFQ//cb+7C9BBEAAP8BAACwEQAA8LWHsB9GBpIFkQRGASEYRgSRCEBBQkFBWh4YRpBBCEARIQkCA5RhGAKRDJkBkQOdAC8f0MEHHdAoRv/30/0oRgWcIUYBmgDwG/gEmQKaUWAKSFBiFGIGnjBoEGNwaFBjEWAINAWUvx4oRv/3jfwINgaW3ecEmQhAB7Dwvf8BAABwtRVGDEYLSUYYIEYA8D75ASGKApVCBNBKApVCCNHACALgPDZgBMAOgUAwaIhDMGBwvcBG1BEAAPi1HEYVRg5GB0YBIdgHAdAIRgDgBCAALADRCEYGmQCRACwQ0MGyASkN0DhGMUYAmv/3yv84RjFGKkb/98X+CDYINaQe7OfAsvi9wEbwtYewBpMEkgORA0YBIQyfOEYCkQhAQUJBQXoeOEaQQQhAGElZGAGRESEJAgWTXBgNmQCRAC8h0MEHH9AFmAOdKUYAmv/3mv8CmmJgDkhgYiViBJ4waCBjcGhgYwaZCHgBmxhgImAINQOVSRwGkb8eBZj/9wf8CDYEltvnApkIQAew8L2wEQAA/wEAAP61ApMVRg5GAZAInwEh+AcB0AhGAOAEIAAvANEIRgmZAJEALxXQwbIBKRLQAZwgRjFGAJr/91z/IEYxRipGApwjRv/3/f4INmQcApQINb8e5+fAsv69/rUfRhRGDUYCRlkeGEaIQREhCQICklYYCJkBkQAvJdDBByPQApgpRgGa//c2/wEgcGABLwvQ/yFxYjViIWgxY2FocWMwYL8eCCECIAfgDyFxYjViIWgxYzBgACcEIW0YgAAkGAKY//ec+9fnASEIQP69+LUfRhRGDUYGRgArAdAEIADgASAGmQCRAC8b0MGyASkY0DBGKUYAmv/3/v4wRilGIkYBLwXQ//d5/b8eCCECIgTg//dT/QAnBCEBIm0YkQBkGOHnwLL4vQNJACJCUEAYQmCCYHBHwEbQEQAAACHJQwJKgVCAGEFggWBwR9ARAAAESQAiQlBAGEJggmACZEJkgmRwR9ARAAAAIclDBEqBUIAYQWCBYAFkQWSBZHBHwEbQEQAAELUERv/3VvwBRgtKEGgFIxNgByMDQAlIAGgTYKQKAikI0wdKEEAA8DX8AUYgRgDwMfwMRiBGEL0AE0BAGADEQf8PAABwtRVGDEYLSUYYIEb/99b/ASGKApVCBNBKApVCCNHACALgPDZgBMAOgUAwaAhDMGBwvcBG1BEAALC1ESMbAsQYAyVlYCFiASFhYhJ4ImPBULC9sLURIxsCxBgDJWVgIWJlYhGIIWMBIcFQsL2wtREjGwLEGAMlZWAhYg8hYWIRaCFjASHBULC9sLURIxsCxBgDJWVgIWL/IWFiEWghY1FoYWMBIcFQsL0QtQZLAyTEUMMYASQcYtlhEXjZYv/3DPkQvcBGBBEAABC1BUsDJMRQwxgcYtlhEYjZYv/3/fgQvQQRAAAQtQZLAyTEUMMYDyQcYtlhEWjZYv/37vgQvcBGBBEAABC1B0sDJMRQwxj/JBxi2WERaNliUWgZY//33PgQvcBGBBEAABC1BksDJMRQwxj/JAI0HGLZYRF42WL/98v4EL0EEQAAELUGSwMkxFDDGP8kBDQcYtlhEYjZYv/3u/gQvQQRAAAQtQZLAyTEUMMY/yQQNBxi2WERaNli//er+BC9BBEAABC1B0sDJMRQwxgGTBxi2WERaNliUWgZY//3mvgQvcBGBBEAAP8BAACwtQhMAyUFUQQZ/yUCNSVi4WEReOFiGXgDSoFQ//eE+LC9wEYEEQAAsBEAALC1CEwDJQVRBBn/JQQ1JWLhYRGI4WIZeANKgVD/9274sL3ARgQRAACwEQAAsLUITAMlBVEEGf8lEDUlYuFhEWjhYhl4A0qBUP/3WPiwvcBGBBEAALARAACwtQhMAyUFUQQZB00lYuFhEWjhYlFoIWMZeARKgVD/90H4sL0EEQAA/wEAALARAACwtREjGwLEGAMlZWAhYv8hAjFhYhF4IWMBIcFQsL2wtREjGwLEGAMlZWAhYv8hBDFhYhGIIWMBIcFQsL2wtREjGwLEGAMlZWAhYv8hEDFhYhFoIWMBIcFQsL3ARrC1ESMbAsQYAyVlYCFiBElhYhFoIWNRaGFjASHBULC9/wEAAHC1ESQkAgUZAyZuYCli/yECMWliEXgpYxl4AkqBUAEhAVFwvbARAABwtREkJAIFGQMmbmApYv8hBDFpYhGIKWMZeAJKgVABIQFRcL2wEQAAcLURJCQCBRkDJm5gKWL/IRAxaWIRaCljGXgCSoFQASEBUXC9sBEAAHC1ESQkAgUZAyZuYCliBklpYhFoKWNRaGljGXgDSoFQASEBUXC9wEb/AQAAsBEAABC1ESISAoMYBiRcYBliASGBUBC9gLUESgYjg1CCGNFh/veU/4C9wEYEEQAAELUTRgRGBEoA8Aj4ESAAAgEhIVAQvcBG//8AALC1B0wRJQVRABkCYsFhGWjBYlloAWOZaEFj2WiBY7C9BBEAABC1E0YERgRK//fo/xEgAAIBISFQEL3ARv//AQCwtR1GE0YERgZK//fZ/yh4BUlgUGAYaXhBYBEgAAIBISFQsL3//wEAsBEAAPC1hbAfRhRGDUYCRhEgAQIAKwHQAy8B2AAgAOABIASSVhgKmQOR/yEQMQKRAZYALzrQwQc40ASYKUYDmv/3WPwBLxDQAy8a2AEgcGACmfAxcWI1YiFoMWNhaHFjMGC/HgghAiIJ4AEicmACmHBiNWIhaDFjMmAAJwQhBJgO4C5GJUYEnCBGMUYqRv/3lf8gRixGNUYBnj8fECEEIm0YkQBkGP/3qfjC5wEhCEAFsPC9/7UBJCICKksZaAOSkUMZYChJDWhtBPzVRX4lQJ5ppkN0GZxhICQEXQMlLEDeaa5DNBncYSBMJWgFJiZgRmo3aB9idmheYgcmLkAmYMRpfyUtAt5prkNkBmQMNBncYQdoRWiCaACSxmgCaQGSQmkCkpppEkwUQDoHEgstA62yqhgyQwCdLQctDRVDAZoVQwKaFUMAfihDCkoCQBAZmGEYaAOaEEMYYAhogAX81f+9wEYIAQtABAILQAATQECNAPD/cv8PALC1/yIEMg5JC2iTQ4J4AyQUQAJ4EgISGRpDCmAJSgpLE2AKTCVobQX81UB4ACgD0AhoECQEQwxgWBwQYLC9wEYUAQtAFAMLQAEAAJEEAgtADEkKaAAoA9ABIIACAkMG4AMggkMKYAEggAIKaIJDCmABIAAFSmgCQ0pgA0gBaIkD/NVwRwABC0AEAgtAASCBAgZKE2iLQxNgAAVRaIFDUWADSAFoiQP81HBHwEYAAQtABAILQAdJiGAHSAJokgL81QEiEgQLaBNDC2ABaMkG/NVwR8BGBAELQAQCC0ABIAAEBEkKaIJDCmADSAFoyQb81HBHwEYEAQtABAILQBC1D0kLaAEik0MLYAMjGwMYQIxonEMgGIhgiGgIIwND9yCDQ4tgCGgQQwhgEAeKaAJDimADSAFoyQX81RC9wEYIAQtABAILQHC1EUsdaAEkpUMdYAMlLQMoQJ5orkMwGJhgmGj/JahDybJAGJhgGGggQxhgmGghBwAqBtAIQ5hgBEgBaMkF/NVwvYhDmGBwvQgBC0AEAgtAsLU/IxsEBEwlaJ1DCEMQQxhAKBggYLC9OAELQAlIAGhABwjUCEhBaMkCBtQAaIAFBdUDIHBHACBwRwIgcEcBIHBHwEYQ7QDgAAELQApJCmwAIAAqANBwRwhKEmhSB/rVCGjABQTUCGiABQPVAyBwRwIgcEcBIHBHAAELQBDtAOAHScprACABKgfRBkoSaFIHA9UIaIACAdUCIHBHASBwRwQBC0AQ7QDgELUISxxrASIiQAjRBkwgQBhgIUBZYNhqBEkBQ9liUEJQQRC9GCALQMD/PwAQAAB2ELUIS5xqASIiQAjRBkwgQBhgIUAZYFhqBEkBQ1liUEJQQRC9ICALQMD/PwBAAAB2ACIDCYtCLNMDCotCEdMAI5xGTuADRgtDPNQAIkMIi0Ix0wMJi0Ic0wMKi0IB05RGP+DDCYtCAdPLAcAaUkGDCYtCAdOLAcAaUkFDCYtCAdNLAcAaUkEDCYtCAdMLAcAaUkHDCItCAdPLAMAaUkGDCItCAdOLAMAaUkFDCItCAdNLAMAaUkFBGgDSAUZSQRBGcEdd4MoPANBJQgMQANNAQlNAnEYAIgMJi0It0wMKi0IS04kB/CISugMKi0IM04kBkhGLQgjTiQGSEYtCBNOJATrQkhEA4IkJwwmLQgHTywHAGlJBgwmLQgHTiwHAGlJBQwmLQgHTSwHAGlJBAwmLQgHTCwHAGlJBwwiLQgHTywDAGlJBgwiLQgHTiwDAGlJB2dJDCItCAdNLAMAaUkFBGgDSAUZSQRBGY0ZbEAHTQEIAKwDVSUJwR2NGWxAA00BCAbUFSQAoAtxJHAhAAOAIRsBGwEYCvQC/////fwAAAAA=
365 load_address: 0x20200008
366 pc_init: 0x1d
367 pc_uninit: 0x99
368 pc_program_page: 0x19d
369 pc_erase_sector: 0xcd
370 pc_erase_all: 0x9d
371 data_section_offset: 0x16e4
372 flash_properties:
373 address_range:
374 start: 0x0
375 end: 0x80000
376 page_size: 0x400
377 erased_byte_value: 0xff
378 program_page_timeout: 500
379 erase_sector_timeout: 3000
380 sectors:
381 - size: 0x400
382 address: 0x0
383- name: mspm0gx51x_nonmain
384 description: MSPM0GX51X NON-MAIN
385 instructions: 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AAELQApJCmwAIAAqANBwRwhKEmhSB/rVCGjABQTUCGiABQPVAyBwRwIgcEcBIHBHAAELQBDtAOAHScprACABKgfRBkoSaFIHA9UIaIACAdUCIHBHASBwRwQBC0AQ7QDgELUISxxrASIiQAjRBkwgQBhgIUBZYNhqBEkBQ9liUEJQQRC9GCALQMD/PwAQAAB2ELUIS5xqASIiQAjRBkwgQBhgIUAZYFhqBEkBQ1liUEJQQRC9ICALQMD/PwBAAAB2ACIDCYtCLNMDCotCEdMAI5xGTuADRgtDPNQAIkMIi0Ix0wMJi0Ic0wMKi0IB05RGP+DDCYtCAdPLAcAaUkGDCYtCAdOLAcAaUkFDCYtCAdNLAcAaUkEDCYtCAdMLAcAaUkHDCItCAdPLAMAaUkGDCItCAdOLAMAaUkFDCItCAdNLAMAaUkFBGgDSAUZSQRBGcEdd4MoPANBJQgMQANNAQlNAnEYAIgMJi0It0wMKi0IS04kB/CISugMKi0IM04kBkhGLQgjTiQGSEYtCBNOJATrQkhEA4IkJwwmLQgHTywHAGlJBgwmLQgHTiwHAGlJBQwmLQgHTSwHAGlJBAwmLQgHTCwHAGlJBwwiLQgHTywDAGlJBgwiLQgHTiwDAGlJB2dJDCItCAdNLAMAaUkFBGgDSAUZSQRBGY0ZbEAHTQEIAKwDVSUJwR2NGWxAA00BCAbUFSQAoAtxJHAhAAOAIRsBGwEYCvQC/////fwAAAAS7qruqu6q7qv//////////u6q7qruqu6r//7uqu6q7qv///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9B/+hoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEFgIVAgEDAgOoEv//r5YTdg9yY1+9tEpaCmPDnxKvMPlQpu5clxvhiOicQFH/////////////////////////////////////////////SADJWPEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
386 load_address: 0x20200008
387 pc_init: 0x1d
388 pc_uninit: 0xb5
389 pc_program_page: 0x1a9
390 pc_erase_sector: 0x159
391 pc_erase_all: 0x211
392 data_section_offset: 0x1b84
393 flash_properties:
394 address_range:
395 start: 0x41c00000
396 end: 0x41c00400
397 page_size: 0x40
398 erased_byte_value: 0xff
399 program_page_timeout: 500
400 erase_sector_timeout: 3000
401 sectors:
402 - size: 0x400
403 address: 0x0
404- name: mspm0gx51x_data_16kb
405 description: MSPM0GX51X DATA 16KB
406 instructions: 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
407 load_address: 0x20200008
408 pc_init: 0x1d
409 pc_uninit: 0x99
410 pc_program_page: 0x19d
411 pc_erase_sector: 0xcd
412 pc_erase_all: 0x9d
413 data_section_offset: 0x16e4
414 flash_properties:
415 address_range:
416 start: 0x0
417 end: 0x4000
418 page_size: 0x400
419 erased_byte_value: 0xff
420 program_page_timeout: 500
421 erase_sector_timeout: 3000
422 sectors:
423 - size: 0x400
424 address: 0x0
diff --git a/examples/mspm0g3519/README.md b/examples/mspm0g3519/README.md
new file mode 100644
index 000000000..5034b1913
--- /dev/null
+++ b/examples/mspm0g3519/README.md
@@ -0,0 +1,27 @@
1# Examples for MSPM0G351x family
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-MSPM0G3519](https://www.ti.com/tool/LP-MSPM0G3519) 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 G3519 it should be `probe-rs run --chip MSPM0G3519`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for G3519 it should be `mspm0g3519`. 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/mspm0g3519/build.rs b/examples/mspm0g3519/build.rs
new file mode 100644
index 000000000..30691aa97
--- /dev/null
+++ b/examples/mspm0g3519/build.rs
@@ -0,0 +1,35 @@
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}
diff --git a/examples/mspm0g3519/memory.x b/examples/mspm0g3519/memory.x
new file mode 100644
index 000000000..e6e0ec9e9
--- /dev/null
+++ b/examples/mspm0g3519/memory.x
@@ -0,0 +1,6 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 512K
4 /* Select non-parity range of SRAM due to SRAM_ERR_01 errata in SLAZ758 */
5 RAM : ORIGIN = 0x20200000, LENGTH = 128K
6}
diff --git a/examples/mspm0g3519/src/bin/blinky.rs b/examples/mspm0g3519/src/bin/blinky.rs
new file mode 100644
index 000000000..11eee2d80
--- /dev/null
+++ b/examples/mspm0g3519/src/bin/blinky.rs
@@ -0,0 +1,27 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Level, Output},
8 Config,
9};
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_halt as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) -> ! {
15 info!("Hello world!");
16 let p = embassy_mspm0::init(Config::default());
17
18 let mut led1 = Output::new(p.PA0, Level::Low);
19 led1.set_inversion(true);
20
21 loop {
22 Timer::after_millis(400).await;
23
24 info!("Toggle");
25 led1.toggle();
26 }
27}
diff --git a/examples/mspm0g3519/src/bin/button.rs b/examples/mspm0g3519/src/bin/button.rs
new file mode 100644
index 000000000..2bdb2bcb1
--- /dev/null
+++ b/examples/mspm0g3519/src/bin/button.rs
@@ -0,0 +1,35 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Input, Level, Output, Pull},
8 Config,
9};
10use {defmt_rtt as _, panic_halt as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) -> ! {
14 info!("Hello world!");
15
16 let p = embassy_mspm0::init(Config::default());
17
18 let led1 = p.PA0;
19 let s2 = p.PB3;
20
21 let mut led1 = Output::new(led1, Level::Low);
22
23 let mut s2 = Input::new(s2, Pull::Up);
24
25 // led1 is active low
26 led1.set_high();
27
28 loop {
29 s2.wait_for_falling_edge().await;
30
31 info!("Switch 2 was pressed");
32
33 led1.toggle();
34 }
35}
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..6b87916b8
--- /dev/null
+++ b/examples/mspm0l1306/Cargo.toml
@@ -0,0 +1,21 @@
1[package]
2edition = "2021"
3name = "embassy-mspm0-l1306-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6
7[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l130x", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["task-arena-size-1024", "arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3"
16defmt-rtt = "0.4"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] }
18panic-semihosting = "0.6.0"
19
20[profile.release]
21debug = 2
diff --git a/examples/mspm0l1306/README.md b/examples/mspm0l1306/README.md
new file mode 100644
index 000000000..5a55d721e
--- /dev/null
+++ b/examples/mspm0l1306/README.md
@@ -0,0 +1,27 @@
1# Examples for MSPM0L130x family
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 example for L1306 it should be `mspm0l1306`. 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..30691aa97
--- /dev/null
+++ b/examples/mspm0l1306/build.rs
@@ -0,0 +1,35 @@
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}
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/blinky.rs b/examples/mspm0l1306/src/bin/blinky.rs
new file mode 100644
index 000000000..11eee2d80
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/blinky.rs
@@ -0,0 +1,27 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Level, Output},
8 Config,
9};
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_halt as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) -> ! {
15 info!("Hello world!");
16 let p = embassy_mspm0::init(Config::default());
17
18 let mut led1 = Output::new(p.PA0, Level::Low);
19 led1.set_inversion(true);
20
21 loop {
22 Timer::after_millis(400).await;
23
24 info!("Toggle");
25 led1.toggle();
26 }
27}
diff --git a/examples/mspm0l1306/src/bin/button.rs b/examples/mspm0l1306/src/bin/button.rs
new file mode 100644
index 000000000..2813518c2
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/button.rs
@@ -0,0 +1,35 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Input, Level, Output, Pull},
8 Config,
9};
10use {defmt_rtt as _, panic_halt as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) -> ! {
14 info!("Hello world!");
15
16 let p = embassy_mspm0::init(Config::default());
17
18 let led1 = p.PA0;
19 let s2 = p.PA14;
20
21 let mut led1 = Output::new(led1, Level::Low);
22
23 let mut s2 = Input::new(s2, Pull::Up);
24
25 // led1 is active low
26 led1.set_high();
27
28 loop {
29 s2.wait_for_falling_edge().await;
30
31 info!("Switch 2 was pressed");
32
33 led1.toggle();
34 }
35}
diff --git a/examples/mspm0l2228/.cargo/config.toml b/examples/mspm0l2228/.cargo/config.toml
new file mode 100644
index 000000000..4284749e9
--- /dev/null
+++ b/examples/mspm0l2228/.cargo/config.toml
@@ -0,0 +1,10 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace MSPM0L2228 with your chip as listed in `probe-rs chip list`
3# TODO: Remove description path after new chiptool release
4runner = "probe-rs run --restore-unwritten --verify --chip MSPM0L2228 --protocol=swd --chip-description-path ./MSPM0L122X_L222X_Series.yaml"
5
6[build]
7target = "thumbv6m-none-eabi"
8
9[env]
10DEFMT_LOG = "trace"
diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml
new file mode 100644
index 000000000..9474c2ced
--- /dev/null
+++ b/examples/mspm0l2228/Cargo.toml
@@ -0,0 +1,21 @@
1[package]
2edition = "2021"
3name = "embassy-mspm0-l2228-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6
7[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l222x", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["task-arena-size-1024", "arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3"
16defmt-rtt = "0.4"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] }
18panic-semihosting = "0.6.0"
19
20[profile.release]
21debug = 2
diff --git a/examples/mspm0l2228/MSPM0L122X_L222X_Series.yaml b/examples/mspm0l2228/MSPM0L122X_L222X_Series.yaml
new file mode 100644
index 000000000..ac52fda2e
--- /dev/null
+++ b/examples/mspm0l2228/MSPM0L122X_L222X_Series.yaml
@@ -0,0 +1,239 @@
1name: MSPM0L122X_L222X Series
2manufacturer:
3 id: 0x17
4 cc: 0x0
5generated_from_pack: true
6pack_file_release: 1.1.1
7variants:
8- name: MSPM0L1227
9 cores:
10 - name: main
11 type: armv6m
12 core_access_options: !Arm
13 ap: 0
14 memory_map:
15 - !Nvm
16 name: IROM1
17 range:
18 start: 0x0
19 end: 0x20000
20 cores:
21 - main
22 access:
23 write: false
24 boot: true
25 - !Ram
26 name: IRAM1
27 range:
28 start: 0x20200000
29 end: 0x20208000
30 cores:
31 - main
32 - !Generic
33 name: NonMain
34 range:
35 start: 0x41c00000
36 end: 0x41c00200
37 cores:
38 - main
39 access:
40 write: false
41 execute: false
42 - !Generic
43 name: Factory
44 range:
45 start: 0x41c40000
46 end: 0x41c40080
47 cores:
48 - main
49 access:
50 write: false
51 execute: false
52 flash_algorithms:
53 - mspm0l122x_l222x_main_256kb
54 - mspm0l122x_l222x_nonmain
55- name: MSPM0L1228
56 cores:
57 - name: main
58 type: armv6m
59 core_access_options: !Arm
60 ap: 0
61 memory_map:
62 - !Nvm
63 name: IROM1
64 range:
65 start: 0x0
66 end: 0x40000
67 cores:
68 - main
69 access:
70 write: false
71 boot: true
72 - !Ram
73 name: IRAM1
74 range:
75 start: 0x20200000
76 end: 0x20208000
77 cores:
78 - main
79 - !Generic
80 name: NonMain
81 range:
82 start: 0x41c00000
83 end: 0x41c00200
84 cores:
85 - main
86 access:
87 write: false
88 execute: false
89 - !Generic
90 name: Factory
91 range:
92 start: 0x41c40000
93 end: 0x41c40080
94 cores:
95 - main
96 access:
97 write: false
98 execute: false
99 flash_algorithms:
100 - mspm0l122x_l222x_main_256kb
101 - mspm0l122x_l222x_nonmain
102- name: MSPM0L2227
103 cores:
104 - name: main
105 type: armv6m
106 core_access_options: !Arm
107 ap: 0
108 memory_map:
109 - !Nvm
110 name: IROM1
111 range:
112 start: 0x0
113 end: 0x20000
114 cores:
115 - main
116 access:
117 write: false
118 boot: true
119 - !Ram
120 name: IRAM1
121 range:
122 start: 0x20200000
123 end: 0x20208000
124 cores:
125 - main
126 - !Generic
127 name: NonMain
128 range:
129 start: 0x41c00000
130 end: 0x41c00200
131 cores:
132 - main
133 access:
134 write: false
135 execute: false
136 - !Generic
137 name: Factory
138 range:
139 start: 0x41c40000
140 end: 0x41c40080
141 cores:
142 - main
143 access:
144 write: false
145 execute: false
146 flash_algorithms:
147 - mspm0l122x_l222x_main_256kb
148 - mspm0l122x_l222x_nonmain
149- name: MSPM0L2228
150 cores:
151 - name: main
152 type: armv6m
153 core_access_options: !Arm
154 ap: 0
155 memory_map:
156 - !Nvm
157 name: IROM1
158 range:
159 start: 0x0
160 end: 0x40000
161 cores:
162 - main
163 access:
164 write: false
165 boot: true
166 - !Ram
167 name: IRAM1
168 range:
169 start: 0x20200000
170 end: 0x20208000
171 cores:
172 - main
173 - !Generic
174 name: NonMain
175 range:
176 start: 0x41c00000
177 end: 0x41c00200
178 cores:
179 - main
180 access:
181 write: false
182 execute: false
183 - !Generic
184 name: Factory
185 range:
186 start: 0x41c40000
187 end: 0x41c40080
188 cores:
189 - main
190 access:
191 write: false
192 execute: false
193 flash_algorithms:
194 - mspm0l122x_l222x_main_256kb
195 - mspm0l122x_l222x_nonmain
196flash_algorithms:
197- name: mspm0l122x_l222x_main_256kb
198 description: MSPM0L122X_222X MAIN 256KB
199 default: true
200 instructions: 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
201 load_address: 0x20200008
202 pc_init: 0x1d
203 pc_uninit: 0x5d
204 pc_program_page: 0x145
205 pc_erase_sector: 0x61
206 pc_erase_all: 0x131
207 data_section_offset: 0x12dc
208 flash_properties:
209 address_range:
210 start: 0x0
211 end: 0x40000
212 page_size: 0x400
213 erased_byte_value: 0xff
214 program_page_timeout: 500
215 erase_sector_timeout: 3000
216 sectors:
217 - size: 0x400
218 address: 0x0
219- name: mspm0l122x_l222x_nonmain
220 description: MSPM0L122X_222X NON-MAIN
221 instructions: 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A0gBaIkD/NRwR8BGAAELQAQCC0ABIAAEBEkKaIJDCmADSAFoyQb81HBHwEYEAQtABAILQAAiAwmLQizTAwqLQhHTACOcRk7gA0YLQzzUACJDCItCMdMDCYtCHNMDCotCAdOURj/gwwmLQgHTywHAGlJBgwmLQgHTiwHAGlJBQwmLQgHTSwHAGlJBAwmLQgHTCwHAGlJBwwiLQgHTywDAGlJBgwiLQgHTiwDAGlJBQwiLQgHTSwDAGlJBQRoA0gFGUkEQRnBHXeDKDwDQSUIDEADTQEJTQJxGACIDCYtCLdMDCotCEtOJAfwiEroDCotCDNOJAZIRi0II04kBkhGLQgTTiQE60JIRAOCJCcMJi0IB08sBwBpSQYMJi0IB04sBwBpSQUMJi0IB00sBwBpSQQMJi0IB0wsBwBpSQcMIi0IB08sAwBpSQYMIi0IB04sAwBpSQdnSQwiLQgHTSwDAGlJBQRoA0gFGUkEQRmNGWxAB00BCACsA1UlCcEdjRlsQANNAQgG1BUkAKALcSRwIQADgCEbARsBGAr0Av////38CAAABu6q7qruqu6r//////////7uqu6q7qruq//+7qruqu6r///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+yIGk/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAABoCGQIBAwIDshL//6+WE3YPcmNfvbRKWgpjw58SrzD5UKbuXJcb4YjonEBR/////////////////////////////////////////////0gA0UsBbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
222 load_address: 0x20200008
223 pc_init: 0x1d
224 pc_uninit: 0x7d
225 pc_program_page: 0x18d
226 pc_erase_sector: 0x121
227 pc_erase_all: 0x79
228 data_section_offset: 0x1774
229 flash_properties:
230 address_range:
231 start: 0x41c00000
232 end: 0x41c00200
233 page_size: 0x40
234 erased_byte_value: 0xff
235 program_page_timeout: 500
236 erase_sector_timeout: 3000
237 sectors:
238 - size: 0x200
239 address: 0x0
diff --git a/examples/mspm0l2228/README.md b/examples/mspm0l2228/README.md
new file mode 100644
index 000000000..c73fa13b6
--- /dev/null
+++ b/examples/mspm0l2228/README.md
@@ -0,0 +1,27 @@
1# Examples for MSPM0L222x family
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-MSPM0L2228](https://www.ti.com/tool/LP-MSPM0L2228) 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 L2228 it should be `probe-rs run --chip MSPM0L2228`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for L2228 it should be `mspm0l2228`. 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/mspm0l2228/build.rs b/examples/mspm0l2228/build.rs
new file mode 100644
index 000000000..30691aa97
--- /dev/null
+++ b/examples/mspm0l2228/build.rs
@@ -0,0 +1,35 @@
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}
diff --git a/examples/mspm0l2228/memory.x b/examples/mspm0l2228/memory.x
new file mode 100644
index 000000000..aba414a88
--- /dev/null
+++ b/examples/mspm0l2228/memory.x
@@ -0,0 +1,6 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 256K
4 /* Select non-parity range of SRAM due to SRAM_ERR_01 errata in SLAZ758 */
5 RAM : ORIGIN = 0x20200000, LENGTH = 32K
6}
diff --git a/examples/mspm0l2228/src/bin/blinky.rs b/examples/mspm0l2228/src/bin/blinky.rs
new file mode 100644
index 000000000..11eee2d80
--- /dev/null
+++ b/examples/mspm0l2228/src/bin/blinky.rs
@@ -0,0 +1,27 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Level, Output},
8 Config,
9};
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_halt as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) -> ! {
15 info!("Hello world!");
16 let p = embassy_mspm0::init(Config::default());
17
18 let mut led1 = Output::new(p.PA0, Level::Low);
19 led1.set_inversion(true);
20
21 loop {
22 Timer::after_millis(400).await;
23
24 info!("Toggle");
25 led1.toggle();
26 }
27}
diff --git a/examples/mspm0l2228/src/bin/button.rs b/examples/mspm0l2228/src/bin/button.rs
new file mode 100644
index 000000000..f26929dde
--- /dev/null
+++ b/examples/mspm0l2228/src/bin/button.rs
@@ -0,0 +1,35 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::{
7 gpio::{Input, Level, Output, Pull},
8 Config,
9};
10use {defmt_rtt as _, panic_halt as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) -> ! {
14 info!("Hello world!");
15
16 let p = embassy_mspm0::init(Config::default());
17
18 let led1 = p.PA0;
19 let s2 = p.PB8;
20
21 let mut led1 = Output::new(led1, Level::Low);
22
23 let mut s2 = Input::new(s2, Pull::Up);
24
25 // led1 is active low
26 led1.set_high();
27
28 loop {
29 s2.wait_for_falling_edge().await;
30
31 info!("Switch 2 was pressed");
32
33 led1.toggle();
34 }
35}