Juggernaut 发表于 2024-4-4 11:21

《原子嵌入式Linux驱动开发详解与实战》阅读体验5- 驱动分离和pinctrl

<div class='showpostmsg'><p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>驱动分离是指把硬件相关的部分(驱动层)从纯软件部分(事件处理层)剥离出来,使硬件厂家只需要关注硬件相关部分代码的编写。</strong>具体来说就是在驱动层中使用platform机制(将所有设备挂接到一个虚拟的总线上,方便sysfs节点和设备电源的管理,使得驱动代码,具有更好的扩展性和跨平台性,就不会因为新的平台而再次编写驱动)把硬件相关的代码(固定的,如板子的网卡、中断地址)和驱动(会根据程序作变动,如点哪一个LED)分离开来,即要编写两个文件:dev.c和drv.c(platform设备和platform驱动)。</span></p>

<div style="text-align: center;"></div>

<p><span style="font-size:16px;">要使用pinctrl子系统,需要在设备树里面设置PIN的配置信息,由pinctrl子系统根据你提供的信息来配置PIN功能,在设备树里面创建一个节点来描述PIN的配置信息。</span></p>

<pre>
<code>1814      pinctrl: pin-controller@50002000 {
1815            #address-cells = &lt;1&gt;;
1816            #size-cells = &lt;1&gt;;
1817            compatible = "st,stm32mp157-pinctrl";
1818            ranges = &lt;0 0x50002000 0xa400&gt;;
1819            interrupt-parent = &lt;&amp;exti&gt;;
1820            st,syscfg = &lt;&amp;exti 0x60 0xff&gt;;
1821            hwlocks = &lt;&amp;hsem 0 1&gt;;
1822            pins-are-numbered;
......
1968      };</code></pre>

<p><span style="font-size:16px;">然后向pinctrl节点追加数据,不同的外设使用的PIN不同、其配置也不同,因此一个萝卜一个坑,将某个外设所使用的所有PIN都组织在一个子节点里面。每个pincrtl节点必须至少包含一个子节点来存放pincrtl相关信息,也就是pinctrl集,这个集合里面存放当前外设用到哪些引脚(PIN)、这些引脚应该怎么配置、复用相关的配置、上下拉、默认输出高电平还是低电平。</span></p>

<pre>
<code>1   &amp;pinctrl {
......
534   m_can1_pins_a: m-can1-0 {
535         pins1 {
536             pinmux = &lt;STM32_PINMUX('H', 13, AF9)&gt;;         /* CAN1_TX */
537             slew-rate = &lt;1&gt;;
538             drive-push-pull;
539             bias-disable;
540         };
541         pins2 {
542             pinmux = &lt;STM32_PINMUX('I', 9, AF9)&gt;;         /* CAN1_RX */
543             bias-disable;
544         };
545   };
......
554   pwm1_pins_a: pwm1-0 {
555         pins {
556             pinmux = &lt;STM32_PINMUX('E', 9, AF1)&gt;, /* TIM1_CH1 */
557                  &lt;STM32_PINMUX('E', 11, AF1)&gt;,                 /* TIM1_CH2 */
558                  &lt;STM32_PINMUX('E', 14, AF1)&gt;;                 /* TIM1_CH4 */
559             bias-pull-down;
560             drive-push-pull;
561             slew-rate = &lt;0&gt;;
562         };
563   };
......
1411};</code></pre>

<p><span style="font-size:16px;">pinctrl其他的电气特征设置不再详细介绍,《原子嵌入式Linux驱动开发详解与实战》讲的很详细了。</span></p>

<p><strong><span style="font-size:16px;">PIN驱动</span></strong></p>

<p><span style="font-size:16px;">所有的东西都已经准备好了,包括寄存器地址和寄存器值,Linux内核相应的驱动文件就会根据这些值来做相应的初始化。</span></p>

<pre>
<code class="language-cpp">2323    static struct stm32_pinctrl_match_data stm32mp157_match_data = {
2324      .pins = stm32mp157_pins,
2325      .npins = ARRAY_SIZE(stm32mp157_pins),
2326    };
2327
2328    static struct stm32_pinctrl_match_data stm32mp157_z_match_data = {
2329      .pins = stm32mp157_z_pins,
2330      .npins = ARRAY_SIZE(stm32mp157_z_pins),
2331      .pin_base_shift = STM32MP157_Z_BASE_SHIFT,
2332    };
2333
2334    static const struct of_device_id stm32mp157_pctrl_match[] = {
2335      {
2336            .compatible = "st,stm32mp157-pinctrl",
2337            .data = &amp;stm32mp157_match_data,
2338      },
2339      {
2340            .compatible = "st,stm32mp157-z-pinctrl",
2341            .data = &amp;stm32mp157_z_match_data,
2342      },
2343      { }
2344    };
2345
2346    static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = {
2347         SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume)
2348    };
2349
2350    static struct platform_driver stm32mp157_pinctrl_driver = {
2351      .probe = stm32_pctl_probe,
2352      .driver = {
2353            .name = "stm32mp157-pinctrl",
2354            .of_match_table = stm32mp157_pctrl_match,
2355            .pm = &amp;stm32_pinctrl_dev_pm_ops,
2356      },
2357    };
2358
2359    static int __init stm32mp157_pinctrl_init(void)
2360    {
2361      return platform_driver_register(&amp;stm32mp157_pinctrl_driver);
2362    }
2363    arch_initcall(stm32mp157_pinctrl_init);</code></pre>

<p>&nbsp;</p>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

2609 发表于 2024-4-7 14:08

<p>驱动的分离,是的,越读越感觉到操作系统是一种思想</p>

Nubility 发表于 2024-9-26 11:48

<p>&ldquo;每个pincrtl节点必须至少包含一个子节点来存放pincrtl相关信息&rdquo;, 是所有芯片的设备树都这样要求的吗, 如果不包含子节点,会有什么后果</p>
页: [1]
查看完整版本: 《原子嵌入式Linux驱动开发详解与实战》阅读体验5- 驱动分离和pinctrl