Skip to content

Commit c7fc4c3

Browse files
committed
generic safe/unsafe W::bits
1 parent eea8296 commit c7fc4c3

File tree

4 files changed

+47
-39
lines changed

4 files changed

+47
-39
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
77

88
## [Unreleased]
99

10+
- generic unsafe `W::bits` + safe `W::set`
1011
- Add `svd::Device` validation after parsing by `serde`
1112
- Add `skip-crate-attributes` config flag
1213
- Better display parsing errors

src/generate/generic.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ pub trait Readable: RegisterSpec {}
6767
///
6868
/// Registers marked with `Readable` can be also be `modify`'ed.
6969
pub trait Writable: RegisterSpec {
70+
// `Safe` or `Unsafe` writting raw bits
71+
type Safety;
72+
7073
/// Specifies the register bits that are not changed if you pass `1` and are changed if you pass `0`
7174
const ZERO_TO_MODIFY_FIELDS_BITMAP: Self::Ux;
7275

@@ -390,6 +393,31 @@ where
390393
/// Used as an argument to the closures in the `write` and `modify` methods of the register.
391394
pub type W<REG> = raw::W<REG>;
392395

396+
impl<REG: Writable> W<REG> {
397+
/// Writes raw bits to the register.
398+
///
399+
/// # Safety
400+
///
401+
/// Passing incorrect value can cause undefined behaviour. See reference manual
402+
#[inline(always)]
403+
pub unsafe fn bits(&mut self, bits: REG::Ux) -> &mut Self {
404+
self.bits = bits;
405+
self
406+
}
407+
}
408+
impl<REG> W<REG> where REG: Writable<Safety = Safe> {
409+
/// Writes raw bits to the register.
410+
///
411+
/// # Safety
412+
///
413+
/// Passing incorrect value can cause undefined behaviour. See reference manual
414+
#[inline(always)]
415+
pub fn set(&mut self, bits: REG::Ux) -> &mut Self {
416+
self.bits = bits;
417+
self
418+
}
419+
}
420+
393421
/// Field reader.
394422
///
395423
/// Result of the `read` methods of fields.

src/generate/register.rs

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -333,44 +333,6 @@ pub fn render_register_mod(
333333

334334
mod_items.extend(w_impl_items);
335335

336-
// the writer can be safe if:
337-
// * there is a single field that covers the entire register
338-
// * that field can represent all values
339-
// * the write constraints of the register allow full range of values
340-
let can_write_safe = !unsafety(
341-
register
342-
.fields
343-
.as_ref()
344-
.and_then(|fields| fields.first())
345-
.and_then(|field| field.write_constraint)
346-
.as_ref(),
347-
rsize,
348-
) || !unsafety(register.write_constraint.as_ref(), rsize);
349-
350-
if can_write_safe {
351-
mod_items.extend(quote! {
352-
#[doc = "Writes raw bits to the register."]
353-
#[inline(always)]
354-
pub fn bits(&mut self, bits: #rty) -> &mut Self {
355-
self.bits = bits;
356-
self
357-
}
358-
});
359-
} else {
360-
mod_items.extend(quote! {
361-
/// Writes raw bits to the register.
362-
///
363-
/// # Safety
364-
///
365-
/// Passing incorrect value can cause undefined behaviour. See reference manual
366-
#[inline(always)]
367-
pub unsafe fn bits(&mut self, bits: #rty) -> &mut Self {
368-
self.bits = bits;
369-
self
370-
}
371-
});
372-
}
373-
374336
close.to_tokens(&mut mod_items);
375337
}
376338

@@ -403,6 +365,22 @@ pub fn render_register_mod(
403365
});
404366
}
405367
if can_write {
368+
// the writer can be safe if:
369+
// * there is a single field that covers the entire register
370+
// * that field can represent all values
371+
// * the write constraints of the register allow full range of values
372+
let can_write_safe = !unsafety(
373+
register
374+
.fields
375+
.as_ref()
376+
.and_then(|fields| fields.first())
377+
.and_then(|field| field.write_constraint)
378+
.as_ref(),
379+
rsize,
380+
) || !unsafety(register.write_constraint.as_ref(), rsize);
381+
let safe_ty = if can_write_safe { "Safe" } else { "Unsafe" };
382+
let safe_ty = Ident::new(safe_ty, span);
383+
406384
let doc =
407385
format!("`write(|w| ..)` method takes [`{name_snake_case}::W`](W) writer structure",);
408386

@@ -412,6 +390,7 @@ pub fn render_register_mod(
412390
mod_items.extend(quote! {
413391
#[doc = #doc]
414392
impl crate::Writable for #regspec_ident {
393+
type Safety = crate::#safe_ty;
415394
const ZERO_TO_MODIFY_FIELDS_BITMAP: Self::Ux = #zero_to_modify_fields_bitmap;
416395
const ONE_TO_MODIFY_FIELDS_BITMAP: Self::Ux = #one_to_modify_fields_bitmap;
417396
}

src/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ impl ToSanitizedCase for str {
106106
}
107107
}
108108
fn to_sanitized_not_keyword_snake_case(&self) -> Cow<str> {
109-
const INTERNALS: [&str; 4] = ["set_bit", "clear_bit", "bit", "bits"];
109+
const INTERNALS: [&str; 5] = ["set_bit", "clear_bit", "bit", "bits", "set"];
110110

111111
let s = Case::Snake.sanitize(self);
112112
if s.as_bytes().first().unwrap_or(&0).is_ascii_digit() {

0 commit comments

Comments
 (0)