Skip to content

Commit 2344ca2

Browse files
committed
cortex-m-pac crate
1 parent 6a324a8 commit 2344ca2

File tree

6 files changed

+395
-0
lines changed

6 files changed

+395
-0
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
resolver = "2"
33
members = [
44
"cortex-m",
5+
"cortex-m-pac",
56
"cortex-m-rt",
67
"cortex-m-semihosting",
78
"panic-itm",

cortex-m-pac/CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Change Log
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
6+
and this project adheres to [Semantic Versioning](http://semver.org/).
7+
8+
## [Unreleased]

cortex-m-pac/Cargo.toml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[package]
2+
name = "cortex-m-pac"
3+
version = "0.1.0"
4+
edition = "2021"
5+
rust-version = "1.60"
6+
repository = "https://github.com/rust-embedded/cortex-m"
7+
authors = ["The Cortex-M Team <[email protected]>",]
8+
categories = ["embedded", "hardware-support", "no-std"]
9+
description = "Low level access to Cortex-M processors"
10+
documentation = "https://docs.rs/cortex-m-pac"
11+
keywords = ["arm", "cortex-m", "register", "peripheral"]
12+
license = "MIT OR Apache-2.0"
13+
readme = "README.md"
14+
15+
[package.metadata.docs.rs]
16+
targets = [
17+
"thumbv8m.main-none-eabihf",
18+
"thumbv6m-none-eabi",
19+
"thumbv7em-none-eabi",
20+
"thumbv7em-none-eabihf",
21+
"thumbv7m-none-eabi",
22+
"thumbv8m.base-none-eabi",
23+
"thumbv8m.main-none-eabi"
24+
]

cortex-m-pac/README.md

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
[![crates.io](https://img.shields.io/crates/d/cortex-m-pac.svg)](https://crates.io/crates/cortex-m-pac)
2+
[![crates.io](https://img.shields.io/crates/v/cortex-m-pac.svg)](https://crates.io/crates/cortex-m-pac)
3+
4+
# `cortex-m-pac`
5+
6+
> Target-specific traits to be implemented by PACs
7+
8+
This project is developed and maintained by the [Cortex-M team][team].
9+
10+
## [Documentation](https://docs.rs/crate/cortex-m-pac)
11+
12+
## Minimum Supported Rust Version (MSRV)
13+
14+
This crate is guaranteed to compile on stable Rust 1.60 and up. It *might*
15+
compile with older versions but that may change in any new patch release.
16+
17+
## License
18+
19+
Copyright 2024 [Cortex-M team][team]
20+
21+
Permission to use, copy, modify, and/or distribute this software for any purpose
22+
with or without fee is hereby granted, provided that the above copyright notice
23+
and this permission notice appear in all copies.
24+
25+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
26+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
27+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
28+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
29+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
30+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
31+
THIS SOFTWARE.
32+
33+
## Code of Conduct
34+
35+
Contribution to this crate is organized under the terms of the [Rust Code of
36+
Conduct][CoC], the maintainer of this crate, the [Cortex-M team][team], promises
37+
to intervene to uphold that code of conduct.
38+
39+
[CoC]: CODE_OF_CONDUCT.md
40+
[team]: https://github.com/rust-embedded/wg#the-cortex-m-team

cortex-m-pac/src/lib.rs

+264
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
#![no_std]
2+
3+
pub mod result;
4+
5+
use result::Result;
6+
7+
/// Trait for enums of target-specific exception numbers.
8+
///
9+
/// This trait should be implemented by a peripheral access crate (PAC) on its enum of available
10+
/// exceptions for a specific device. Alternatively, the `cortex-m` crate provides a default
11+
/// implementation. Each variant must convert to a `usize` of its exception number.
12+
///
13+
/// # Safety
14+
///
15+
/// * This trait must only be implemented on the `cortex-m` crate or on a PAC of a Cortex-M target.
16+
/// * This trait must only be implemented on enums of exceptions.
17+
/// * Each enum variant must represent a distinct value (no duplicates are permitted),
18+
/// * Each enum variant must always return the same value (do not change at runtime).
19+
/// * All the exception numbers must be less than or equal to `MAX_EXCEPTION_NUMBER`.
20+
/// * `MAX_EXCEPTION_NUMBER` must coincide with the highest allowed exception number.
21+
pub unsafe trait ExceptionNumber: Copy {
22+
/// Highest number assigned to an exception.
23+
const MAX_EXCEPTION_NUMBER: usize;
24+
25+
/// Converts an exception to its corresponding number.
26+
fn number(self) -> usize;
27+
28+
/// Tries to convert a number to a valid exception.
29+
fn from_number(value: usize) -> Result<Self>;
30+
}
31+
32+
/// Trait for enums of target-specific interrupt numbers.
33+
///
34+
/// This trait should be implemented by a peripheral access crate (PAC) on its enum of available
35+
/// interrupts for a specific device. Each variant must convert to a `usize` of its interrupt number.
36+
///
37+
/// # Safety
38+
///
39+
/// * This trait must only be implemented on a PAC of a Cortex-M target.
40+
/// * This trait must only be implemented on enums of interrupts.
41+
/// * Each enum variant must represent a distinct value (no duplicates are permitted),
42+
/// * Each enum variant must always return the same value (do not change at runtime).
43+
/// * All the interrupt numbers must be less than or equal to `MAX_INTERRUPT_NUMBER`.
44+
/// * `MAX_INTERRUPT_NUMBER` must coincide with the highest allowed interrupt number.
45+
pub unsafe trait InterruptNumber: Copy {
46+
/// Highest number assigned to an interrupt source.
47+
const MAX_INTERRUPT_NUMBER: usize;
48+
49+
/// Converts an interrupt source to its corresponding number.
50+
fn number(self) -> usize;
51+
52+
/// Tries to convert a number to a valid interrupt.
53+
fn from_number(value: usize) -> Result<Self>;
54+
}
55+
56+
/// Trait for enums of priority levels.
57+
///
58+
/// This trait should be implemented by a peripheral access crate (PAC) on its enum of available
59+
/// priority numbers for a specific device. Each variant must convert to a `usize` of its priority level.
60+
///
61+
/// # Safety
62+
///
63+
/// * This trait must only be implemented on a PAC of a Cortex-M target.
64+
/// * This trait must only be implemented on enums of priority levels.
65+
/// * Each enum variant must represent a distinct value (no duplicates are permitted).
66+
/// * Each enum variant must always return the same value (do not change at runtime).
67+
/// * All the priority level numbers must be less than or equal to `MAX_PRIORITY_NUMBER`.
68+
/// * `MAX_PRIORITY_NUMBER` must coincide with the highest allowed priority number.
69+
pub unsafe trait PriorityNumber: Copy {
70+
/// Number assigned to the highest priority level.
71+
const MAX_PRIORITY_NUMBER: usize;
72+
73+
/// Converts a priority level to its corresponding number.
74+
fn number(self) -> usize;
75+
76+
/// Tries to convert a number to a valid priority level.
77+
fn from_number(value: usize) -> Result<Self>;
78+
}
79+
80+
/// Trait for enums of core identifiers.
81+
///
82+
/// This trait should be implemented by a peripheral access crate (PAC) on its enum of available
83+
/// cores for a specific device. Each variant must convert to a `usize` of its core ID number.
84+
///
85+
/// # Safety
86+
///
87+
/// * This trait must only be implemented on a PAC of a Cortex-M target.
88+
/// * This trait must only be implemented on enums of core IDs.
89+
/// * Each enum variant must represent a distinct value (no duplicates are permitted),
90+
/// * Each anum variant must always return the same value (do not change at runtime).
91+
/// * All the core ID numbers must be less than or equal to `MAX_CORE_ID_NUMBER`.
92+
/// * `MAX_CORE_ID_NUMBER` must coincide with the highest allowed core ID number.
93+
pub unsafe trait CoreIdNumber: Copy {
94+
/// Highest number assigned to a core.
95+
const MAX_CORE_ID_NUMBER: usize;
96+
97+
/// Converts a Core ID to its corresponding number.
98+
fn number(self) -> usize;
99+
100+
/// Tries to convert a number to a valid Core ID.
101+
fn from_number(value: usize) -> Result<Self>;
102+
}
103+
104+
#[cfg(test)]
105+
mod test {
106+
use super::*;
107+
use crate::result::Error;
108+
109+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
110+
enum Exception {
111+
E1 = 1,
112+
E3 = 3,
113+
}
114+
115+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
116+
enum Interrupt {
117+
I1 = 1,
118+
I2 = 2,
119+
I4 = 4,
120+
}
121+
122+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
123+
enum Priority {
124+
P0 = 0,
125+
P1 = 1,
126+
P2 = 2,
127+
P3 = 3,
128+
}
129+
130+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
131+
enum CoreId {
132+
H0 = 0,
133+
H1 = 1,
134+
H2 = 2,
135+
}
136+
137+
unsafe impl ExceptionNumber for Exception {
138+
const MAX_EXCEPTION_NUMBER: usize = Self::E3 as usize;
139+
140+
#[inline]
141+
fn number(self) -> usize {
142+
self as _
143+
}
144+
145+
#[inline]
146+
fn from_number(number: usize) -> Result<Self> {
147+
match number {
148+
1 => Ok(Exception::E1),
149+
3 => Ok(Exception::E3),
150+
_ => Err(Error::InvalidVariant(number)),
151+
}
152+
}
153+
}
154+
155+
unsafe impl InterruptNumber for Interrupt {
156+
const MAX_INTERRUPT_NUMBER: usize = Self::I4 as usize;
157+
158+
#[inline]
159+
fn number(self) -> usize {
160+
self as _
161+
}
162+
163+
#[inline]
164+
fn from_number(number: usize) -> Result<Self> {
165+
match number {
166+
1 => Ok(Interrupt::I1),
167+
2 => Ok(Interrupt::I2),
168+
4 => Ok(Interrupt::I4),
169+
_ => Err(Error::InvalidVariant(number)),
170+
}
171+
}
172+
}
173+
174+
unsafe impl PriorityNumber for Priority {
175+
const MAX_PRIORITY_NUMBER: usize = Self::P3 as usize;
176+
177+
#[inline]
178+
fn number(self) -> usize {
179+
self as _
180+
}
181+
182+
#[inline]
183+
fn from_number(number: usize) -> Result<Self> {
184+
match number {
185+
0 => Ok(Priority::P0),
186+
1 => Ok(Priority::P1),
187+
2 => Ok(Priority::P2),
188+
3 => Ok(Priority::P3),
189+
_ => Err(Error::InvalidVariant(number)),
190+
}
191+
}
192+
}
193+
194+
unsafe impl CoreIdNumber for CoreId {
195+
const MAX_CORE_ID_NUMBER: usize = Self::H2 as usize;
196+
197+
#[inline]
198+
fn number(self) -> usize {
199+
self as _
200+
}
201+
202+
#[inline]
203+
fn from_number(number: usize) -> Result<Self> {
204+
match number {
205+
0 => Ok(CoreId::H0),
206+
1 => Ok(CoreId::H1),
207+
2 => Ok(CoreId::H2),
208+
_ => Err(Error::InvalidVariant(number)),
209+
}
210+
}
211+
}
212+
213+
#[test]
214+
fn check_exception_enum() {
215+
assert_eq!(Exception::E1.number(), 1);
216+
assert_eq!(Exception::E3.number(), 3);
217+
218+
assert_eq!(Exception::from_number(0), Err(Error::InvalidVariant(0)));
219+
assert_eq!(Exception::from_number(1), Ok(Exception::E1));
220+
assert_eq!(Exception::from_number(2), Err(Error::InvalidVariant(2)));
221+
assert_eq!(Exception::from_number(3), Ok(Exception::E3));
222+
assert_eq!(Exception::from_number(4), Err(Error::InvalidVariant(4)));
223+
}
224+
225+
#[test]
226+
fn check_interrupt_enum() {
227+
assert_eq!(Interrupt::I1.number(), 1);
228+
assert_eq!(Interrupt::I2.number(), 2);
229+
assert_eq!(Interrupt::I4.number(), 4);
230+
231+
assert_eq!(Interrupt::from_number(0), Err(Error::InvalidVariant(0)));
232+
assert_eq!(Interrupt::from_number(1), Ok(Interrupt::I1));
233+
assert_eq!(Interrupt::from_number(2), Ok(Interrupt::I2));
234+
assert_eq!(Interrupt::from_number(3), Err(Error::InvalidVariant(3)));
235+
assert_eq!(Interrupt::from_number(4), Ok(Interrupt::I4));
236+
assert_eq!(Interrupt::from_number(5), Err(Error::InvalidVariant(5)));
237+
}
238+
239+
#[test]
240+
fn check_priority_enum() {
241+
assert_eq!(Priority::P0.number(), 0);
242+
assert_eq!(Priority::P1.number(), 1);
243+
assert_eq!(Priority::P2.number(), 2);
244+
assert_eq!(Priority::P3.number(), 3);
245+
246+
assert_eq!(Priority::from_number(0), Ok(Priority::P0));
247+
assert_eq!(Priority::from_number(1), Ok(Priority::P1));
248+
assert_eq!(Priority::from_number(2), Ok(Priority::P2));
249+
assert_eq!(Priority::from_number(3), Ok(Priority::P3));
250+
assert_eq!(Priority::from_number(4), Err(Error::InvalidVariant(4)));
251+
}
252+
253+
#[test]
254+
fn check_core_id_enum() {
255+
assert_eq!(CoreId::H0.number(), 0);
256+
assert_eq!(CoreId::H1.number(), 1);
257+
assert_eq!(CoreId::H2.number(), 2);
258+
259+
assert_eq!(CoreId::from_number(0), Ok(CoreId::H0));
260+
assert_eq!(CoreId::from_number(1), Ok(CoreId::H1));
261+
assert_eq!(CoreId::from_number(2), Ok(CoreId::H2));
262+
assert_eq!(CoreId::from_number(3), Err(Error::InvalidVariant(3)));
263+
}
264+
}

0 commit comments

Comments
 (0)