rust-embedded / rust-embedded/svd2rust

Alignment padding in generated structs is incorrectly accounted for.

Open
#522 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
857
Forks
164
PR merge metrics
No merged PRs in 30d

Description

svd2rust accounts for alignment padding incorrectly.

E.g., in the attached example, struct ALIGNME has 6 bytes of data and 2 bytes of alignment padding, a total of 8 bytes. The following field next32 at offset 8 therefore needs no explicit padding added before it.

But svd2rust has not counted the alignment padding and ends up inserting 2 bytes of incorrect padding. After further alignment, this appears to leave next32 at offset 12 instead of the correct 8.

.svd and part of the output .rs inline below. Github wouldn't let me add them as attachments.....

#[repr(C)]
pub struct RegisterBlock {
    #[doc = "0x00 - u32+u16"]
    pub alignme: ALIGNME,
    _reserved1: [u8; 2usize],
    #[doc = "0x08 - Following 32 bit field"]
    pub next32: crate::Reg<next32::NEXT32_SPEC>,
}
#[repr(C)]
pub struct ALIGNME {
    #[doc = "0x00 - Thirty two and serious"]
    pub reg32: crate::Reg<self::alignme::reg32::REG32_SPEC>,
    #[doc = "0x04 - 16 bit reigster"]
    pub reg16: crate::Reg<self::alignme::reg16::REG16_SPEC>,
}

and the SVD

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator version: 1.6.0.225 -->
<device schemaVersion="1.3" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd">
  <vendor>Testing 123</vendor>
  <vendorID>NotReal</vendorID>
  <name>dummy</name>
  <series>dumb</series>
  <version>1.0</version>
  <description>dummy</description>
  <licenseText>Made up example license.</licenseText>
  <cpu>
    <name>CM4</name>
    <revision>r0p1</revision>
    <endian>little</endian>
    <mpuPresent>true</mpuPresent>
    <fpuPresent>true</fpuPresent>
    <vtorPresent>1</vtorPresent>
    <nvicPrioBits>3</nvicPrioBits>
    <vendorSystickConfig>0</vendorSystickConfig>
  </cpu>
  <addressUnitBits>8</addressUnitBits>
  <width>32</width>
  <resetValue>0x00000000</resetValue>
  <resetMask>0xFFFFFFFF</resetMask>
  <peripherals>
    <peripheral>
      <name>PERI</name>
      <description>A peripheral</description>
      <baseAddress>0x40000000</baseAddress>
      <addressBlock>
        <offset>0</offset>
        <size>4096</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <cluster>
          <name>alignme</name>
          <description>u32+u16</description>
          <addressOffset>0x00000000</addressOffset>
          <register>
            <name>REG32</name>
            <description>Thirty two and serious</description>
            <addressOffset>0x0</addressOffset>
            <size>32</size>
            <access>read-write</access>
            <resetValue>0x0</resetValue>
            <resetMask>0x0</resetMask>
            <fields>
              <field>
                <name>F32</name>
                <description>A 32 bit field.</description>
                <bitRange>[31:0]</bitRange>
                <access>read-write</access>
              </field>
            </fields>
          </register>
          <register>
            <name>REG16</name>
            <description>16 bit reigster</description>
            <addressOffset>0x4</addressOffset>
            <size>16</size>
            <access>read-write</access>
            <resetValue>0x0</resetValue>
            <resetMask>0x0</resetMask>
            <fields>
              <field>
                <name>F16</name>
                <description>A 16 bit field.  Sweet 16.</description>
                <bitRange>[15:0]</bitRange>
                <access>read-write</access>
              </field>
            </fields>
          </register>
        </cluster>
        <register>
          <name>NEXT32</name>
          <description>Following 32 bit field</description>
          <addressOffset>8</addressOffset>
          <size>32</size>
          <access>read-write</access>
          <resetValue>0</resetValue>
          <resetMask>0</resetMask>
          <fields>
            <field>
              <name>F32</name>
              <description>32 bits again</description>
              <bitRange>[31:0]</bitRange>
              <access>read-write</access>
            </field>
          </fields>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>


Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue using the supplied SVD and compare the generated Rust RegisterBlock and ALIGNME definitions. Trace the generator logic that accounts for cluster alignment and padding, then verify that next32 is generated at offset 8 without redundant padding.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
embedded-iot, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.