<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>结构体 on Hacper&#39;s Blog</title>
    <link>https://hacperme.com/tags/%E7%BB%93%E6%9E%84%E4%BD%93/</link>
    <description>Recent content in 结构体 on Hacper&#39;s Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh</language>
    <lastBuildDate>Wed, 19 Jul 2023 00:05:17 +0800</lastBuildDate>
    <atom:link href="https://hacperme.com/tags/%E7%BB%93%E6%9E%84%E4%BD%93/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>C 的结构体成员在内存中的存储顺序以及对硬件的描述能力</title>
      <link>https://hacperme.com/posts/notes/20230719_c_struct_memory/</link>
      <pubDate>Wed, 19 Jul 2023 00:05:17 +0800</pubDate>
      <guid>https://hacperme.com/posts/notes/20230719_c_struct_memory/</guid>
      <description>介绍 c 语言是如何通过指针、结构体、联合体、位域等这些语法来描述硬件的。</description>
      <content:encoded><![CDATA[<h2 id="c-语言结构体成员和位域在内存中的存储方式">c 语言结构体成员和位域在内存中的存储方式</h2>
<p>在小端存储的机器上，C编译器对结构体的成员按它们的声明顺序从低到高的地址进行存储，先定义的成员存储在内存的低地址，使用位域的时候也是类似，先定义的成员先占用低比特位。</p>
<h2 id="c-语言怎么描述硬件寄存器">c 语言怎么描述硬件寄存器？</h2>
<p>通常硬件寄存器会映射到一段特定的内存地址，我们可以通过指针来访问和修改寄存器的内容。每个寄存器的功能不一定相同，需要根据硬件手册来具体定义。下面以某个芯片平台的 pwm 控制寄存器为例，说明如何使用 c 语言描述硬件寄存器。</p>
<p><img loading="lazy" src="https://github.com/hacperme/picx_hosting/raw/master/20210507/image-20230719011111212.5buks5rpf3c0.webp" alt=""  />
</p>
<p>这个平台有 4 个 pwm 外设，控制寄存器的基址分别是 0xD401A000，0xD401A400，0xD401A800 ，0xD401AC00，然后每个 pwm 有三个 32 位 的寄存器，分别是 PWM_CRx，PWM_DCR，PWM_PCR。在这三个寄存器里面，不同的 bit 范围之间又控制着不同的功能。在 c 语言里面，可通过联合体、结构体和位域来定义这些寄存器的功能。</p>
<p>三个 pwm 控制寄存器的基地址:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#define  PWM0_BASE (0xD401A000)
</span></span></span><span class="line"><span class="cl"><span class="cp">#define  PWM1_BASE (0xD401A400)
</span></span></span><span class="line"><span class="cl"><span class="cp">#define  PWM2_BASE (0xD401A800)
</span></span></span><span class="line"><span class="cl"><span class="cp">#define  PWM3_BASE (0xD401AC00)
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>每个 pwm 有三个寄存器， PWM_CRx，PWM_DCR，PWM_PCR，与偏移地址对应，4字节递增:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">typedef</span> <span class="k">volatile</span> <span class="k">struct</span> 
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">PWM_CRx</span><span class="p">;</span>   <span class="cm">/*Offset: 0x00*/</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">PWM_DCR</span> <span class="p">;</span>  <span class="cm">/*Offset: 0x04*/</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">PWM_PCR</span> <span class="p">;</span>  <span class="cm">/*Offset: 0x08*/</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="n">PWM_HW_T</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>将 pwm 寄存器地址转换为 PWM_HW_T * 类型的指针，方便通过指针对数据进行读写:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#define HW_PWM0 ((PWM_HW_T *)(PWM0_BASE))
</span></span></span><span class="line"><span class="cl"><span class="cp">#define HW_PWM1 ((PWM_HW_T *)(PWM1_BASE))
</span></span></span><span class="line"><span class="cl"><span class="cp">#define HW_PWM2 ((PWM_HW_T *)(PWM2_BASE))
</span></span></span><span class="line"><span class="cl"><span class="cp">#define HW_PWM3 ((PWM_HW_T *)(PWM3_BASE))
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>每个寄存器的功能定义:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// PWM_CRx 寄存器定义
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">typedef</span> <span class="k">union</span> 
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">v</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> 
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">uint32_t</span> <span class="nl">PRESCALE</span> <span class="p">:</span> <span class="mi">6</span><span class="p">;</span>  <span class="c1">//[5:0]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">uint32_t</span> <span class="nl">SD</span> <span class="p">:</span> <span class="mi">1</span><span class="p">;</span>        <span class="c1">//[6]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">uint32_t</span> <span class="nl">Reserved</span> <span class="p">:</span><span class="mi">25</span><span class="p">;</span>  <span class="c1">//[31:7]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span><span class="n">d</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="n">REG_PWM_CRx_T</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// PWM_DCR 寄存器定义
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">typedef</span> <span class="k">union</span> 
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">v</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> 
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">uint32_t</span> <span class="nl">DCYCLE</span> <span class="p">:</span> <span class="mi">10</span><span class="p">;</span>   <span class="c1">//[9:0]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">uint32_t</span> <span class="nl">FD</span> <span class="p">:</span><span class="mi">1</span><span class="p">;</span>         <span class="c1">//[10]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">uint32_t</span> <span class="nl">Reserved</span> <span class="p">:</span><span class="mi">21</span><span class="p">;</span>  <span class="c1">//[31:11]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span><span class="n">d</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="n">REG_PWM_DCR_T</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// PWM_PCR 寄存器定义
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">typedef</span> <span class="k">union</span> 
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">v</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> 
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">uint32_t</span> <span class="nl">PV</span> <span class="p">:</span> <span class="mi">10</span><span class="p">;</span>     	<span class="c1">//[9:0]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">uint32_t</span> <span class="nl">Reserved</span> <span class="p">:</span><span class="mi">22</span><span class="p">;</span>  <span class="c1">//[31:10]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span><span class="n">d</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="n">REG_PWM_PCR_T</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>操作 pwm 寄存器示例，读和写寄存器都可以通过指针操作实现:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">PWM0_Init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">PWM_HW_T</span> <span class="o">*</span><span class="n">PWM</span> <span class="o">=</span> <span class="n">HW_PWM0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">REG_PWM_CRx_T</span> <span class="n">PWM_CRx</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">REG_PWM_DCR_T</span> <span class="n">PWM_DCR</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">REG_PWM_PCR_T</span> <span class="n">PWM_PCR</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">PWM_CRx</span><span class="p">.</span><span class="n">d</span><span class="p">.</span><span class="n">PRESCALE</span> <span class="o">=</span> <span class="mh">0x3F</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">PWM_CRx</span><span class="p">.</span><span class="n">d</span><span class="p">.</span><span class="n">SD</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">PWM_CRx</span><span class="p">.</span><span class="n">d</span><span class="p">.</span><span class="n">Reserved</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 写  pwm0 的 PWM_CRx 寄存器
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">PWM</span><span class="o">-&gt;</span><span class="n">PWM_CRx</span> <span class="o">=</span> <span class="n">PWM_CRx</span><span class="p">.</span><span class="n">v</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	
</span></span><span class="line"><span class="cl">    <span class="c1">// 读 pwm0 的 PWM_DCR 寄存器
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">PWM_DCR</span><span class="p">.</span><span class="n">v</span> <span class="o">=</span> <span class="n">PWM</span><span class="o">-&gt;</span><span class="n">PWM_DCR</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">PWM_PCR</span><span class="p">.</span><span class="n">d</span><span class="p">.</span><span class="n">PV</span> <span class="o">=</span> <span class="mh">0x3FF</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">PWM_PCR</span><span class="p">.</span><span class="n">d</span><span class="p">.</span><span class="n">Reserved</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">PWM</span><span class="o">-&gt;</span><span class="n">PWM_PCR</span> <span class="o">=</span> <span class="n">PWM_PCR</span><span class="p">.</span><span class="n">v</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div>]]></content:encoded>
    </item>
  </channel>
</rss>
