<?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>SCPfirmware 源码分析 on 夜云泊</title>
    <link>https://lifeislife.cn/categories/scpfirmware-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/</link>
    <description>feedId:57980998056508425+userId:73222296380546048 Recent content in SCPfirmware 源码分析 on 夜云泊</description>
    <generator>Hugo -- 0.160.1</generator>
    <language>zh</language>
    <lastBuildDate>Thu, 15 Aug 2024 15:42:13 +0800</lastBuildDate>
    <atom:link href="https://lifeislife.cn/categories/scpfirmware-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>SCP-firmware 源码分析-module 间 api 调用分析</title>
      <link>https://lifeislife.cn/posts/scp-firmware%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-module%E9%97%B4api%E8%B0%83%E7%94%A8%E5%88%86%E6%9E%90/</link>
      <pubDate>Thu, 15 Aug 2024 15:42:13 +0800</pubDate>
      <guid>https://lifeislife.cn/posts/scp-firmware%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-module%E9%97%B4api%E8%B0%83%E7%94%A8%E5%88%86%E6%9E%90/</guid>
      <description>&lt;p&gt;想了解如何提供 API，我们先看看 CMN 模块是如何使用 API 的，在文件&lt;code&gt;module/cmn700/src/mod_cmn700.c&lt;/code&gt;我们可以看到如下代码：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// module/cmn700/src/mod_cmn700.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mod_system_info_get_info_api&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;system_info_api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cmn700_start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;system_info_api&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;get_system_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;system_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FWK_SUCCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;chip_id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;system_info&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;chip_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;multi_chip_mode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;system_info&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;multi_chip_mode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;他调用了&lt;code&gt;system_info_api-&amp;gt;get_system_info&lt;/code&gt;这个函数，实际这就是 mod_system_info 暴露给 mod_cmn700 的一个 API。用于获取系统信息。&lt;/p&gt;
&lt;p&gt;为何这个静态变量&lt;code&gt;system_info_api&lt;/code&gt;就能调用到&lt;code&gt;mod_system_info&lt;/code&gt;的函数呢？我们继续搜索代码，可以看到如下代码：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// module/cmn700/src/mod_cmn700.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cmn700_bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;round&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;fwk_id_is_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FWK_ID_TYPE_MODULE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;cm&#34;&gt;/* Bind to system info module to obtain multi-chip info */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fwk_module_bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nf&#34;&gt;FWK_ID_MODULE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_SYSTEM_INFO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nf&#34;&gt;FWK_ID_API&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_SYSTEM_INFO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MOD_SYSTEM_INFO_GET_API_IDX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;system_info_api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在&lt;code&gt;cmn700_bind&lt;/code&gt;函数中，调用了&lt;code&gt;fwk_module_bind&lt;/code&gt;函数，这个函数的作用是绑定一个模块的 API，这样就可以通过这个 API 调用模块的函数。&lt;code&gt;fwk_module_bind&lt;/code&gt;函数的第一个参数是提供 API 的模块的 ID，比如当前是模块&lt;code&gt;system_info&lt;/code&gt;的 ID，如果是要用 USB 的 API，那么就是 USB 模块的 ID。第二个参数是 API 的 ID，这个 ID 是在模块的头文件中定义的，比如&lt;code&gt;mod_system_info.h&lt;/code&gt;中定义了&lt;code&gt;MOD_SYSTEM_INFO_GET_API_IDX&lt;/code&gt;，这个宏定义的值就是 API 的 ID。第三个参数是 API 的指针，这个指针就是开头提到的静态变量的地址，它是定义在使用 API 的模块中的。这样就可以通过 API 的指针调用模块的函数。对于 USB 模块，我们就需要在使用到 USB 的模块中定义一个静态变量。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fwk_module_bind&lt;/code&gt;做了什么呢？进入该函数，可以看到它回调了&lt;code&gt;mod_system_info&lt;/code&gt;的&lt;code&gt;process_bind_request&lt;/code&gt;函数，也就是&lt;code&gt;system_info_process_bind_request&lt;/code&gt;函数。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// framework/src/fwk_module.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fwk_module_bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;api_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_mod_ctx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;process_bind_request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;fwk_module_ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bind_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;api_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;system_info_process_bind_request&lt;/code&gt;函数的作用是根据 API 的 ID 返回 API 的指针。它把&lt;code&gt;get_system_info_api&lt;/code&gt;的地址赋值给了&lt;code&gt;api&lt;/code&gt;。这就实现了 API 的暴露。经过这个函数，&lt;code&gt;system_info_api&lt;/code&gt;就指向了&lt;code&gt;get_system_info_api&lt;/code&gt;。实际就是我们在&lt;code&gt;cmn700_bind&lt;/code&gt;函数中使用&lt;code&gt;system_info_api&lt;/code&gt;就是在调用&lt;code&gt;get_system_info_api&lt;/code&gt;。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// module/system_info/src/mod_system_info.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;system_info_process_bind_request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;requester_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;targer_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;api_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;switch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;fwk_id_get_api_idx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;MOD_SYSTEM_INFO_GET_API_IDX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_system_info_api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FWK_E_PARAM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FWK_SUCCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;解释完这个 bind 函数，它是在哪被调用的？它在框架初始化时就会被调用，分析&lt;code&gt;fwk_arch_init&lt;/code&gt;函数，可以看到在&lt;code&gt;fwk_module_start&lt;/code&gt;函数中会对每一个模块调用&lt;code&gt;bind&lt;/code&gt;函数。函数调用流程参考图片文件。在此就不再赘述了。&lt;/p&gt;
&lt;p&gt;经过以上分析，提供 API 的模块需要做的事情就是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;在模块的头文件中定义 API 的 ID，它有一定的格式，具体可以参考 MSCP 文档&lt;code&gt;doc/framework.md&lt;/code&gt;的&lt;code&gt;APIs&lt;/code&gt;章节。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mod_modulename_api&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;MOD_MODULENAME_API_A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;MOD_MODULENAME_API_B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在模块的源文件中定义 API 结构体，用于在其他模块中使用。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mod_system_info_get_info_api&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_system_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mod_system_info&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在模块原文件中提供&lt;code&gt;process_bind_request&lt;/code&gt;函数，用于根据 API 的 ID 返回 API 的指针。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;system_info_process_bind_request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;requester_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;targer_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;api_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;switch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;fwk_id_get_api_idx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;MOD_SYSTEM_INFO_GET_API_IDX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;api&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_system_info_api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FWK_E_PARAM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FWK_SUCCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在模块的源文件中定义 API 的指针，用于提供 API 的地址。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mod_system_info_get_info_api&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_system_info_api&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_system_info&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;system_info_get_system_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;实现需要提供的 API 函数。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;system_info_get_system_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mod_system_info&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys_info&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;system_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FWK_SUCCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以上就是大致的移植流程了。&lt;/p&gt;
&lt;p&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&#34;en&#34;&gt;
&lt;head&gt;
    &lt;meta charset=&#34;UTF-8&#34;&gt;
    &lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;&gt;
    &lt;title&gt;Responsive Image&lt;/title&gt;
    &lt;style&gt;
        .post-img-view {
            text-align: center;
        }
        .responsive-image {
            display: block;
            margin: 0 auto;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    
    &lt;div class=&#34;post-img-view&#34;&gt;
        &lt;a data-fancybox=&#34;gallery&#34; href=&#34;https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img//2024/08/10/5b3d6d12e4e9e9b2b7aa5cc5fc6c8738.png&#34;&gt;
            &lt;img class=&#34;responsive-image&#34; src=&#34;https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img//2024/08/10/5b3d6d12e4e9e9b2b7aa5cc5fc6c8738.png&#34; alt=&#34;&#34;  style=&#34;margin: 0 auto;&#34;/&gt;
        &lt;/a&gt;
    &lt;/div&gt;
    

    &lt;script&gt;
        document.addEventListener(&#34;DOMContentLoaded&#34;, function() {
            var images = document.querySelectorAll(&#34;.responsive-image&#34;);
            var maxHeight = window.innerHeight / 3;
            images.forEach(function(image) {
                image.style.maxHeight = maxHeight + &#34;px&#34;;
            });
        });
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;&lt;/p&gt;
</description>
      <content:encoded><![CDATA[<p>想了解如何提供 API，我们先看看 CMN 模块是如何使用 API 的，在文件<code>module/cmn700/src/mod_cmn700.c</code>我们可以看到如下代码：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// module/cmn700/src/mod_cmn700.c
</span></span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">mod_system_info_get_info_api</span> <span class="o">*</span><span class="n">system_info_api</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">cmn700_start</span><span class="p">(</span><span class="kt">fwk_id_t</span> <span class="n">id</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="p">...</span>
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">system_info_api</span><span class="o">-&gt;</span><span class="nf">get_system_info</span><span class="p">(</span><span class="o">&amp;</span><span class="n">system_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">status</span> <span class="o">==</span> <span class="n">FWK_SUCCESS</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">chip_id</span> <span class="o">=</span> <span class="n">system_info</span><span class="o">-&gt;</span><span class="n">chip_id</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">multi_chip_mode</span> <span class="o">=</span> <span class="n">system_info</span><span class="o">-&gt;</span><span class="n">multi_chip_mode</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="p">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>他调用了<code>system_info_api-&gt;get_system_info</code>这个函数，实际这就是 mod_system_info 暴露给 mod_cmn700 的一个 API。用于获取系统信息。</p>
<p>为何这个静态变量<code>system_info_api</code>就能调用到<code>mod_system_info</code>的函数呢？我们继续搜索代码，可以看到如下代码：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// module/cmn700/src/mod_cmn700.c
</span></span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">cmn700_bind</span><span class="p">(</span><span class="kt">fwk_id_t</span> <span class="n">id</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">round</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="p">...</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">fwk_id_is_type</span><span class="p">(</span><span class="n">id</span><span class="p">,</span> <span class="n">FWK_ID_TYPE_MODULE</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="cm">/* Bind to system info module to obtain multi-chip info */</span>
</span></span><span class="line"><span class="cl">        <span class="n">status</span> <span class="o">=</span> <span class="nf">fwk_module_bind</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="nf">FWK_ID_MODULE</span><span class="p">(</span><span class="n">FWK_MODULE_IDX_SYSTEM_INFO</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="nf">FWK_ID_API</span><span class="p">(</span><span class="n">FWK_MODULE_IDX_SYSTEM_INFO</span><span class="p">,</span> <span class="n">MOD_SYSTEM_INFO_GET_API_IDX</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="o">&amp;</span><span class="n">system_info_api</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">status</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="p">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>在<code>cmn700_bind</code>函数中，调用了<code>fwk_module_bind</code>函数，这个函数的作用是绑定一个模块的 API，这样就可以通过这个 API 调用模块的函数。<code>fwk_module_bind</code>函数的第一个参数是提供 API 的模块的 ID，比如当前是模块<code>system_info</code>的 ID，如果是要用 USB 的 API，那么就是 USB 模块的 ID。第二个参数是 API 的 ID，这个 ID 是在模块的头文件中定义的，比如<code>mod_system_info.h</code>中定义了<code>MOD_SYSTEM_INFO_GET_API_IDX</code>，这个宏定义的值就是 API 的 ID。第三个参数是 API 的指针，这个指针就是开头提到的静态变量的地址，它是定义在使用 API 的模块中的。这样就可以通过 API 的指针调用模块的函数。对于 USB 模块，我们就需要在使用到 USB 的模块中定义一个静态变量。</p>
<p><code>fwk_module_bind</code>做了什么呢？进入该函数，可以看到它回调了<code>mod_system_info</code>的<code>process_bind_request</code>函数，也就是<code>system_info_process_bind_request</code>函数。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// framework/src/fwk_module.c
</span></span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">fwk_module_bind</span><span class="p">(</span><span class="kt">fwk_id_t</span> <span class="n">target_id</span><span class="p">,</span> <span class="kt">fwk_id_t</span> <span class="n">api_id</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">api</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="p">...</span>
</span></span><span class="line"><span class="cl">    <span class="n">status</span> <span class="o">=</span> <span class="n">fwk_mod_ctx</span><span class="o">-&gt;</span><span class="n">desc</span><span class="o">-&gt;</span><span class="nf">process_bind_request</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">fwk_module_ctx</span><span class="p">.</span><span class="n">bind_id</span><span class="p">,</span> <span class="n">target_id</span><span class="p">,</span> <span class="n">api_id</span><span class="p">,</span> <span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">api</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="p">}</span>
</span></span></code></pre></div><p><code>system_info_process_bind_request</code>函数的作用是根据 API 的 ID 返回 API 的指针。它把<code>get_system_info_api</code>的地址赋值给了<code>api</code>。这就实现了 API 的暴露。经过这个函数，<code>system_info_api</code>就指向了<code>get_system_info_api</code>。实际就是我们在<code>cmn700_bind</code>函数中使用<code>system_info_api</code>就是在调用<code>get_system_info_api</code>。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// module/system_info/src/mod_system_info.c
</span></span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">system_info_process_bind_request</span><span class="p">(</span><span class="kt">fwk_id_t</span> <span class="n">requester_id</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="kt">fwk_id_t</span> <span class="n">targer_id</span><span class="p">,</span> <span class="kt">fwk_id_t</span> <span class="n">api_id</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">**</span><span class="n">api</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="k">switch</span> <span class="p">(</span><span class="nf">fwk_id_get_api_idx</span><span class="p">(</span><span class="n">api_id</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nl">MOD_SYSTEM_INFO_GET_API_IDX</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="o">*</span><span class="n">api</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">get_system_info_api</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">default</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">FWK_E_PARAM</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="k">return</span> <span class="n">FWK_SUCCESS</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>解释完这个 bind 函数，它是在哪被调用的？它在框架初始化时就会被调用，分析<code>fwk_arch_init</code>函数，可以看到在<code>fwk_module_start</code>函数中会对每一个模块调用<code>bind</code>函数。函数调用流程参考图片文件。在此就不再赘述了。</p>
<p>经过以上分析，提供 API 的模块需要做的事情就是：</p>
<ol>
<li>
<p>在模块的头文件中定义 API 的 ID，它有一定的格式，具体可以参考 MSCP 文档<code>doc/framework.md</code>的<code>APIs</code>章节。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">enum</span> <span class="n">mod_modulename_api</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">MOD_MODULENAME_API_A</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">MOD_MODULENAME_API_B</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div></li>
<li>
<p>在模块的源文件中定义 API 结构体，用于在其他模块中使用。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">mod_system_info_get_info_api</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">get_system_info</span><span class="p">)(</span><span class="k">const</span> <span class="k">struct</span> <span class="n">mod_system_info</span> <span class="o">**</span><span class="n">sys_info</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div></li>
<li>
<p>在模块原文件中提供<code>process_bind_request</code>函数，用于根据 API 的 ID 返回 API 的指针。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">system_info_process_bind_request</span><span class="p">(</span><span class="kt">fwk_id_t</span> <span class="n">requester_id</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="kt">fwk_id_t</span> <span class="n">targer_id</span><span class="p">,</span> <span class="kt">fwk_id_t</span> <span class="n">api_id</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">**</span><span class="n">api</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="k">switch</span> <span class="p">(</span><span class="nf">fwk_id_get_api_idx</span><span class="p">(</span><span class="n">api_id</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nl">MOD_SYSTEM_INFO_GET_API_IDX</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="o">*</span><span class="n">api</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">get_system_info_api</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">default</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">FWK_E_PARAM</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="k">return</span> <span class="n">FWK_SUCCESS</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></li>
<li>
<p>在模块的源文件中定义 API 的指针，用于提供 API 的地址。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">mod_system_info_get_info_api</span> <span class="n">get_system_info_api</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="n">get_system_info</span> <span class="o">=</span> <span class="n">system_info_get_system_info</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div></li>
<li>
<p>实现需要提供的 API 函数。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">system_info_get_system_info</span><span class="p">(</span><span class="k">const</span> <span class="k">struct</span> <span class="n">mod_system_info</span> <span class="o">**</span><span class="n">sys_info</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="o">*</span><span class="n">sys_info</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">system_info</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">FWK_SUCCESS</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></li>
</ol>
<p>以上就是大致的移植流程了。</p>
<p>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Responsive Image</title>
    <style>
        .post-img-view {
            text-align: center;
        }
        .responsive-image {
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    
    <div class="post-img-view">
        <a data-fancybox="gallery" href="https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img//2024/08/10/5b3d6d12e4e9e9b2b7aa5cc5fc6c8738.png">
            <img class="responsive-image" src="https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img//2024/08/10/5b3d6d12e4e9e9b2b7aa5cc5fc6c8738.png" alt=""  style="margin: 0 auto;"/>
        </a>
    </div>
    

    <script>
        document.addEventListener("DOMContentLoaded", function() {
            var images = document.querySelectorAll(".responsive-image");
            var maxHeight = window.innerHeight / 3;
            images.forEach(function(image) {
                image.style.maxHeight = maxHeight + "px";
            });
        });
    </script>
</body>
</html></p>
]]></content:encoded>
    </item>
    <item>
      <title>SCP-firmware 源码分析 - 源码编译以及模块初始化流程</title>
      <link>https://lifeislife.cn/posts/scp-firmware%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E4%BB%A5%E5%8F%8A%E6%A8%A1%E5%9D%97%E5%88%9D%E5%A7%8B%E5%8C%96%E6%B5%81%E7%A8%8B/</link>
      <pubDate>Sat, 10 Aug 2024 15:42:13 +0800</pubDate>
      <guid>https://lifeislife.cn/posts/scp-firmware%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E4%BB%A5%E5%8F%8A%E6%A8%A1%E5%9D%97%E5%88%9D%E5%A7%8B%E5%8C%96%E6%B5%81%E7%A8%8B/</guid>
      <description>&lt;h2 id=&#34;编译源码&#34;&gt;编译源码&lt;/h2&gt;
&lt;h3 id=&#34;下载配置工具链&#34;&gt;下载配置工具链&lt;/h3&gt;
&lt;p&gt;访问&lt;a href=&#34;https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads&#34;&gt;ARM 官网下载工具链&lt;/a&gt;下载自己系统的版本的工具链。如果你也是 x86_64 的 Linux 系统，直接点击&lt;a href=&#34;https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz&#34;&gt;该链接下载 arm-gnu-toolchain-13.3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;解压工具链：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;xz -d arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tar -xvf arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;将工具链路径添加到环境变量中。&lt;/p&gt;
&lt;h3 id=&#34;编译源码-1&#34;&gt;编译源码&lt;/h3&gt;
&lt;p&gt;源码使用 CMake 进行编译，CMake 版本需要 3.18.4 以上。如果你是 Ubuntu 20.04，直接安装即可。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install cmake
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果你是 Ubuntu 18.04，需要升级 CMAKE。可以通过下面的方式下载源码编译安装 CMAKE。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wget https://github.com/Kitware/CMake/releases/download/v3.22.0/cmake-3.22.0-linux-x86_64.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tar -zxvf cmake-3.22.0-linux-x86_64.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mv cmake-3.22.0-linux-x86_64 /usr/local/cmake
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr/local/cmake/bin:&lt;span class=&#34;nv&#34;&gt;$PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;源码编译：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make -f Makefile.cmake &lt;span class=&#34;nv&#34;&gt;PRODUCT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;totalcompute/tc2 &lt;span class=&#34;nv&#34;&gt;MODE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;debug firmware-scp_ramfw
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;源码编译成功后，会在&lt;code&gt;build/tc2/GNU/debug/firmware-scp_ramfw/bin&lt;/code&gt;目录下生成二进制文件。具体编译参数，可以参考源码根目录下的&lt;code&gt;user_guide&lt;/code&gt;文档。&lt;/p&gt;
&lt;h2 id=&#34;初始化流程分析&#34;&gt;初始化流程分析&lt;/h2&gt;
&lt;p&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&#34;en&#34;&gt;
&lt;head&gt;
    &lt;meta charset=&#34;UTF-8&#34;&gt;
    &lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;&gt;
    &lt;title&gt;Responsive Image&lt;/title&gt;
    &lt;style&gt;
        .post-img-view {
            text-align: center;
        }
        .responsive-image {
            display: block;
            margin: 0 auto;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    
    &lt;div class=&#34;post-img-view&#34;&gt;
        &lt;a data-fancybox=&#34;gallery&#34; href=&#34;https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img//2024/08/15/9489caa086aadd2299d862a9267ff947.png&#34;&gt;
            &lt;img class=&#34;responsive-image&#34; src=&#34;https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img//2024/08/15/9489caa086aadd2299d862a9267ff947.png&#34; alt=&#34;&#34;  style=&#34;margin: 0 auto;&#34;/&gt;
        &lt;/a&gt;
    &lt;/div&gt;
    

    &lt;script&gt;
        document.addEventListener(&#34;DOMContentLoaded&#34;, function() {
            var images = document.querySelectorAll(&#34;.responsive-image&#34;);
            var maxHeight = window.innerHeight / 3;
            images.forEach(function(image) {
                image.style.maxHeight = maxHeight + &#34;px&#34;;
            });
        });
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;&lt;/p&gt;
&lt;h3 id=&#34;fwk_module_init-初始时module_config_table-是在什么时候被初始化的&#34;&gt;fwk_module_init 初始时，module_config_table 是在什么时候被初始化的？&lt;/h3&gt;
&lt;p&gt;module_config_table 无法在源码中直接搜索到，因为它是在编译过程中生成的，当你编译一次后，就会在 output/build/mpw/GNU/debug/firmware-scp_romfw/framework/src/fwk_module_list.c 找到这个变量。具体它是如何生成的，注意通过 &lt;code&gt;framework/CMakeLists.txt&lt;/code&gt; 文件中的这段代码完成，我们逐行分析这段代码。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;LENGTH&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_IDX_MAX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;获取模块列表的长度，保存在 &lt;code&gt;SCP_MODULE_IDX_MAX&lt;/code&gt; 变量中。在每个 &lt;code&gt;Firmware.cmake&lt;/code&gt; 文件中，都会有一个 &lt;code&gt;SCP_MODULES&lt;/code&gt; 变量，这个变量保存了该产品所包含的模块。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# product/juno/scp_romfw/Firmware.cmake
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;test&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;uart&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;当前我们加入了两个模块，所以 &lt;code&gt;SCP_MODULE_IDX_MAX&lt;/code&gt; 的值为 2。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;foreach&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;idx&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;RANGE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;SCP_MODULE_IDX_MAX&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;idx&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;EQUAL&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_IDX_MAX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_IDX_GEN&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;    FWK_MODULE_IDX_COUNT = ${idx},\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;endif&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;遍历模块列表，生成模块索引的定义，如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module_idx&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_COUNT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;GET&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;idx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;将 &lt;code&gt;SCP_MODULES&lt;/code&gt; 列表中索引为 &lt;code&gt;idx&lt;/code&gt; 的元素赋值给变量 &lt;code&gt;SCP_MODULE&lt;/code&gt;，以便在后续的代码中使用。当前 &lt;code&gt;idx&lt;/code&gt; 为 0，所以 &lt;code&gt;SCP_MODULE&lt;/code&gt; 为 &lt;code&gt;test&lt;/code&gt;。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;MAKE_C_IDENTIFIER&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;SCP_MODULE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;TOUPPER&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;SCP_MODULE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_UPPER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;将 &lt;code&gt;SCP_MODULE&lt;/code&gt; 转换为 C 标识符。将 &lt;code&gt;SCP_MODULE&lt;/code&gt; 转为大写并保存在 &lt;code&gt;SCP_MODULE_UPPER&lt;/code&gt; 中，即 &lt;code&gt;SCP_MODULE_UPPER=&amp;quot;TEST&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_IDX_GEN&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;    FWK_MODULE_IDX_${SCP_MODULE_UPPER} = ${idx},\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_ID_INIT_GEN&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;#define FWK_MODULE_ID_${SCP_MODULE_UPPER}_INIT FWK_ID_MODULE_INIT(FWK_MODULE_IDX_${SCP_MODULE_UPPER})\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_ID_GEN&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;#define FWK_MODULE_ID_${SCP_MODULE_UPPER} FWK_ID_MODULE(FWK_MODULE_IDX_${SCP_MODULE_UPPER})\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_ID_CONST_GEN&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;static const fwk_id_t fwk_module_id_${SCP_MODULE} = FWK_MODULE_ID_${SCP_MODULE_UPPER}_INIT;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_EXTERN_GEN&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;extern const struct fwk_module module_${SCP_MODULE};\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_EXTERN_CONFIG_GEN&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;extern const struct fwk_module_config config_${SCP_MODULE};\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_GEN&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;    &amp;amp;module_${SCP_MODULE},\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULE_CONFIG_GEN&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;    &amp;amp;config_${SCP_MODULE},\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;进行一些宏替换，替换后的结果如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SCP_MODULE_IDX_GEN: &amp;#34;   FWK_MODULE_IDX_TEST = 0,&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SCP_MODULE_ID_INIT_GEN: &amp;#34;#define FWK_MODULE_ID_TEST_INIT FWK_ID_MODULE_INIT(FWK_MODULE_IDX_TEST)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SCP_MODULE_ID_GEN: &amp;#34;#define FWK_MODULE_ID_TEST FWK_ID_MODULE(FWK_MODULE_IDX_TEST)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SCP_MODULE_ID_CONST_GEN: &amp;#34;static const fwk_id_t fwk_module_id_test = FWK_MODULE_ID_TEST_INIT;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SCP_MODULE_EXTERN_GEN: &amp;#34;extern const struct fwk_module module_test;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SCP_MODULE_EXTERN_CONFIG_GEN: &amp;#34;extern const struct fwk_module_config config_test;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SCP_MODULE_GEN: &amp;#34;&amp;amp;module_test,&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SCP_MODULE_CONFIG_GEN: &amp;#34;&amp;amp;config_test,&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;target_compile_definitions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;framework&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                               &lt;span class=&#34;s&#34;&gt;PUBLIC&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;BUILD_HAS_MOD_${SCP_MODULE_UPPER}=1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;将 &lt;code&gt;BUILD_HAS_MOD_TEST&lt;/code&gt; 定义为 1，以便在后续的代码中使用。&lt;/p&gt;
&lt;p&gt;在源码文件中有两个模板文件，分别为 &lt;code&gt;fwk_module_list.c.in&lt;/code&gt; 和 &lt;code&gt;fwk_module_idx.h.in&lt;/code&gt;，这两个文件中包含了一些宏定义，这些宏定义在编译过程中会被替换为上面生成的宏定义。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stddef.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCP_MODULE_EXTERN_GEN&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module_table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCP_MODULE_GEN&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCP_MODULE_EXTERN_CONFIG_GEN&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module_config&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module_config_table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCP_MODULE_CONFIG_GEN&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;fwk_id.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCP_MODULE_ID_INIT_GEN&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCP_MODULE_ID_GEN&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module_idx&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCP_MODULE_IDX_GEN&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCP_MODULE_ID_CONST_GEN&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在编译过程中就会生成下面两个文件，当使用&lt;code&gt;module_config_table&lt;/code&gt;时，就会引用这两个文件，找到对应的配置。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// build/mpw/GNU/debug/firmware-scp_romfw/framework/include/fwk_module_idx.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define FWK_MODULE_ID_TEST_INIT FWK_ID_MODULE_INIT(FWK_MODULE_IDX_TEST)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define FWK_MODULE_ID_UART_INIT FWK_ID_MODULE_INIT(FWK_MODULE_IDX_UART)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define FWK_MODULE_ID_TEST FWK_ID_MODULE(FWK_MODULE_IDX_TEST)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define FWK_MODULE_ID_UART FWK_ID_MODULE(FWK_MODULE_IDX_UART)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module_idx&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_TEST&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_UART&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_COUNT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module_id_test&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FWK_MODULE_ID_TEST_INIT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;fwk_id_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module_id_uart&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FWK_MODULE_ID_UART_INIT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// build/mpw/GNU/debug/firmware-scp_romfw/framework/src/fwk_module_list.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;extern&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;module_test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;extern&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;module_uart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module_table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module_test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module_uart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;extern&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module_config&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;config_test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;extern&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module_config&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;config_uart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fwk_module_config&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module_config_table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FWK_MODULE_IDX_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;config_test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;config_uart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;如何确定各个模块在初始化过程中的执行顺序&#34;&gt;如何确定各个模块在初始化过程中的执行顺序？&lt;/h3&gt;
&lt;p&gt;在每个产品目录 mscp/product/juno/scp_romfw/Firmware.cmake 中，都会有一个 Firmware.cmake 文件，这个文件中会包含该产品所包含的模块：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;juno-ppu&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;juno-rom&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;gtimer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;sds&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;bootloader&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;APPEND&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;SCP_MODULES&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;juno-soc-clock&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;编译后会在 output 文件夹中生成&lt;code&gt;fwk_module_idx.h&lt;/code&gt;文件，这个文件中会包含所有模块的索引，如下：&lt;/p&gt;
&lt;p&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&#34;en&#34;&gt;
&lt;head&gt;
    &lt;meta charset=&#34;UTF-8&#34;&gt;
    &lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;&gt;
    &lt;title&gt;Responsive Image&lt;/title&gt;
    &lt;style&gt;
        .post-img-view {
            text-align: center;
        }
        .responsive-image {
            display: block;
            margin: 0 auto;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    
    &lt;div class=&#34;post-img-view&#34;&gt;
        &lt;a data-fancybox=&#34;gallery&#34; href=&#34;https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img/14-48-59-f81a00af1d7e54bd428cf18f77a3465e-20240729144858-cdaa85.png&#34;&gt;
            &lt;img class=&#34;responsive-image&#34; src=&#34;https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img/14-48-59-f81a00af1d7e54bd428cf18f77a3465e-20240729144858-cdaa85.png&#34; alt=&#34;&#34;  style=&#34;margin: 0 auto;&#34;/&gt;
        &lt;/a&gt;
    &lt;/div&gt;
    

    &lt;script&gt;
        document.addEventListener(&#34;DOMContentLoaded&#34;, function() {
            var images = document.querySelectorAll(&#34;.responsive-image&#34;);
            var maxHeight = window.innerHeight / 3;
            images.forEach(function(image) {
                image.style.maxHeight = maxHeight + &#34;px&#34;;
            });
        });
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;&lt;/p&gt;
</description>
      <content:encoded><![CDATA[<h2 id="编译源码">编译源码</h2>
<h3 id="下载配置工具链">下载配置工具链</h3>
<p>访问<a href="https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads">ARM 官网下载工具链</a>下载自己系统的版本的工具链。如果你也是 x86_64 的 Linux 系统，直接点击<a href="https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz">该链接下载 arm-gnu-toolchain-13.3</a></p>
<p>解压工具链：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">xz -d arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz
</span></span><span class="line"><span class="cl">tar -xvf arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar
</span></span></code></pre></div><p>将工具链路径添加到环境变量中。</p>
<h3 id="编译源码-1">编译源码</h3>
<p>源码使用 CMake 进行编译，CMake 版本需要 3.18.4 以上。如果你是 Ubuntu 20.04，直接安装即可。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo apt install cmake
</span></span></code></pre></div><p>如果你是 Ubuntu 18.04，需要升级 CMAKE。可以通过下面的方式下载源码编译安装 CMAKE。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">wget https://github.com/Kitware/CMake/releases/download/v3.22.0/cmake-3.22.0-linux-x86_64.tar.gz
</span></span><span class="line"><span class="cl">tar -zxvf cmake-3.22.0-linux-x86_64.tar.gz
</span></span><span class="line"><span class="cl">mv cmake-3.22.0-linux-x86_64 /usr/local/cmake
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">PATH</span><span class="o">=</span>/usr/local/cmake/bin:<span class="nv">$PATH</span>
</span></span></code></pre></div><p>源码编译：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">make -f Makefile.cmake <span class="nv">PRODUCT</span><span class="o">=</span>totalcompute/tc2 <span class="nv">MODE</span><span class="o">=</span>debug firmware-scp_ramfw
</span></span></code></pre></div><p>源码编译成功后，会在<code>build/tc2/GNU/debug/firmware-scp_ramfw/bin</code>目录下生成二进制文件。具体编译参数，可以参考源码根目录下的<code>user_guide</code>文档。</p>
<h2 id="初始化流程分析">初始化流程分析</h2>
<p>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Responsive Image</title>
    <style>
        .post-img-view {
            text-align: center;
        }
        .responsive-image {
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    
    <div class="post-img-view">
        <a data-fancybox="gallery" href="https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img//2024/08/15/9489caa086aadd2299d862a9267ff947.png">
            <img class="responsive-image" src="https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img//2024/08/15/9489caa086aadd2299d862a9267ff947.png" alt=""  style="margin: 0 auto;"/>
        </a>
    </div>
    

    <script>
        document.addEventListener("DOMContentLoaded", function() {
            var images = document.querySelectorAll(".responsive-image");
            var maxHeight = window.innerHeight / 3;
            images.forEach(function(image) {
                image.style.maxHeight = maxHeight + "px";
            });
        });
    </script>
</body>
</html></p>
<h3 id="fwk_module_init-初始时module_config_table-是在什么时候被初始化的">fwk_module_init 初始时，module_config_table 是在什么时候被初始化的？</h3>
<p>module_config_table 无法在源码中直接搜索到，因为它是在编译过程中生成的，当你编译一次后，就会在 output/build/mpw/GNU/debug/firmware-scp_romfw/framework/src/fwk_module_list.c 找到这个变量。具体它是如何生成的，注意通过 <code>framework/CMakeLists.txt</code> 文件中的这段代码完成，我们逐行分析这段代码。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="s">LENGTH</span> <span class="s">SCP_MODULES</span> <span class="s">SCP_MODULE_IDX_MAX</span><span class="p">)</span><span class="err">
</span></span></span></code></pre></div><p>获取模块列表的长度，保存在 <code>SCP_MODULE_IDX_MAX</code> 变量中。在每个 <code>Firmware.cmake</code> 文件中，都会有一个 <code>SCP_MODULES</code> 变量，这个变量保存了该产品所包含的模块。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl"><span class="c"># product/juno/scp_romfw/Firmware.cmake
</span></span></span><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULES</span> <span class="s2">&#34;test&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULES</span> <span class="s2">&#34;uart&#34;</span><span class="p">)</span><span class="err">
</span></span></span></code></pre></div><p>当前我们加入了两个模块，所以 <code>SCP_MODULE_IDX_MAX</code> 的值为 2。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl"><span class="nb">foreach</span><span class="p">(</span><span class="s">idx</span> <span class="s">RANGE</span> <span class="o">${</span><span class="nv">SCP_MODULE_IDX_MAX</span><span class="o">}</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">if</span><span class="p">(</span><span class="s">idx</span> <span class="s">EQUAL</span> <span class="s">SCP_MODULE_IDX_MAX</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">        <span class="nb">string</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULE_IDX_GEN</span> <span class="s2">&#34;    FWK_MODULE_IDX_COUNT = ${idx},\n&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="cl">        <span class="nb">break</span><span class="p">()</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">endif</span><span class="p">()</span><span class="err">
</span></span></span></code></pre></div><p>遍历模块列表，生成模块索引的定义，如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">enum</span> <span class="n">fwk_module_idx</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">FWK_MODULE_IDX_COUNT</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl">    <span class="nb">list</span><span class="p">(</span><span class="s">GET</span> <span class="s">SCP_MODULES</span> <span class="o">${</span><span class="nv">idx</span><span class="o">}</span> <span class="s">SCP_MODULE</span><span class="p">)</span><span class="err">
</span></span></span></code></pre></div><p>将 <code>SCP_MODULES</code> 列表中索引为 <code>idx</code> 的元素赋值给变量 <code>SCP_MODULE</code>，以便在后续的代码中使用。当前 <code>idx</code> 为 0，所以 <code>SCP_MODULE</code> 为 <code>test</code>。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">MAKE_C_IDENTIFIER</span> <span class="o">${</span><span class="nv">SCP_MODULE</span><span class="o">}</span> <span class="s">SCP_MODULE</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">TOUPPER</span> <span class="o">${</span><span class="nv">SCP_MODULE</span><span class="o">}</span> <span class="s">SCP_MODULE_UPPER</span><span class="p">)</span><span class="err">
</span></span></span></code></pre></div><p>将 <code>SCP_MODULE</code> 转换为 C 标识符。将 <code>SCP_MODULE</code> 转为大写并保存在 <code>SCP_MODULE_UPPER</code> 中，即 <code>SCP_MODULE_UPPER=&quot;TEST&quot;</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULE_IDX_GEN</span> <span class="s2">&#34;    FWK_MODULE_IDX_${SCP_MODULE_UPPER} = ${idx},\n&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULE_ID_INIT_GEN</span> <span class="s2">&#34;#define FWK_MODULE_ID_${SCP_MODULE_UPPER}_INIT FWK_ID_MODULE_INIT(FWK_MODULE_IDX_${SCP_MODULE_UPPER})\n&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULE_ID_GEN</span> <span class="s2">&#34;#define FWK_MODULE_ID_${SCP_MODULE_UPPER} FWK_ID_MODULE(FWK_MODULE_IDX_${SCP_MODULE_UPPER})\n&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULE_ID_CONST_GEN</span> <span class="s2">&#34;static const fwk_id_t fwk_module_id_${SCP_MODULE} = FWK_MODULE_ID_${SCP_MODULE_UPPER}_INIT;\n&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULE_EXTERN_GEN</span> <span class="s2">&#34;extern const struct fwk_module module_${SCP_MODULE};\n&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULE_EXTERN_CONFIG_GEN</span> <span class="s2">&#34;extern const struct fwk_module_config config_${SCP_MODULE};\n&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULE_GEN</span> <span class="s2">&#34;    &amp;module_${SCP_MODULE},\n&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl">    <span class="nb">string</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULE_CONFIG_GEN</span> <span class="s2">&#34;    &amp;config_${SCP_MODULE},\n&#34;</span><span class="p">)</span><span class="err">
</span></span></span></code></pre></div><p>进行一些宏替换，替换后的结果如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl">SCP_MODULE_IDX_GEN: &#34;   FWK_MODULE_IDX_TEST = 0,&#34;
</span></span><span class="line"><span class="cl">SCP_MODULE_ID_INIT_GEN: &#34;#define FWK_MODULE_ID_TEST_INIT FWK_ID_MODULE_INIT(FWK_MODULE_IDX_TEST)&#34;
</span></span><span class="line"><span class="cl">SCP_MODULE_ID_GEN: &#34;#define FWK_MODULE_ID_TEST FWK_ID_MODULE(FWK_MODULE_IDX_TEST)&#34;
</span></span><span class="line"><span class="cl">SCP_MODULE_ID_CONST_GEN: &#34;static const fwk_id_t fwk_module_id_test = FWK_MODULE_ID_TEST_INIT;&#34;
</span></span><span class="line"><span class="cl">SCP_MODULE_EXTERN_GEN: &#34;extern const struct fwk_module module_test;&#34;
</span></span><span class="line"><span class="cl">SCP_MODULE_EXTERN_CONFIG_GEN: &#34;extern const struct fwk_module_config config_test;&#34;
</span></span><span class="line"><span class="cl">SCP_MODULE_GEN: &#34;&amp;module_test,&#34;
</span></span><span class="line"><span class="cl">SCP_MODULE_CONFIG_GEN: &#34;&amp;config_test,&#34;
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl">    <span class="nb">target_compile_definitions</span><span class="p">(</span><span class="s">framework</span>
</span></span><span class="line"><span class="cl">                               <span class="s">PUBLIC</span> <span class="s2">&#34;BUILD_HAS_MOD_${SCP_MODULE_UPPER}=1&#34;</span><span class="p">)</span><span class="err">
</span></span></span></code></pre></div><p>将 <code>BUILD_HAS_MOD_TEST</code> 定义为 1，以便在后续的代码中使用。</p>
<p>在源码文件中有两个模板文件，分别为 <code>fwk_module_list.c.in</code> 和 <code>fwk_module_idx.h.in</code>，这两个文件中包含了一些宏定义，这些宏定义在编译过程中会被替换为上面生成的宏定义。</p>
<div class="highlight"><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;stddef.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">SCP_MODULE_EXTERN_GEN</span><span class="err">@</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="k">struct</span> <span class="n">fwk_module</span> <span class="o">*</span><span class="n">module_table</span><span class="p">[</span><span class="n">FWK_MODULE_IDX_COUNT</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">SCP_MODULE_GEN</span><span class="err">@</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">SCP_MODULE_EXTERN_CONFIG_GEN</span><span class="err">@</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="k">struct</span> <span class="n">fwk_module_config</span> <span class="o">*</span><span class="n">module_config_table</span><span class="p">[</span><span class="n">FWK_MODULE_IDX_COUNT</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">SCP_MODULE_CONFIG_GEN</span><span class="err">@</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><div class="highlight"><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;fwk_id.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">SCP_MODULE_ID_INIT_GEN</span><span class="err">@</span>
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">SCP_MODULE_ID_GEN</span><span class="err">@</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">enum</span> <span class="n">fwk_module_idx</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">SCP_MODULE_IDX_GEN</span><span class="err">@</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">@</span><span class="n">SCP_MODULE_ID_CONST_GEN</span><span class="err">@</span>
</span></span></code></pre></div><p>在编译过程中就会生成下面两个文件，当使用<code>module_config_table</code>时，就会引用这两个文件，找到对应的配置。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// build/mpw/GNU/debug/firmware-scp_romfw/framework/include/fwk_module_idx.h
</span></span></span><span class="line"><span class="cl"><span class="cp">#define FWK_MODULE_ID_TEST_INIT FWK_ID_MODULE_INIT(FWK_MODULE_IDX_TEST)
</span></span></span><span class="line"><span class="cl"><span class="cp">#define FWK_MODULE_ID_UART_INIT FWK_ID_MODULE_INIT(FWK_MODULE_IDX_UART)
</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="cp">#define FWK_MODULE_ID_TEST FWK_ID_MODULE(FWK_MODULE_IDX_TEST)
</span></span></span><span class="line"><span class="cl"><span class="cp">#define FWK_MODULE_ID_UART FWK_ID_MODULE(FWK_MODULE_IDX_UART)
</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="k">enum</span> <span class="n">fwk_module_idx</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">FWK_MODULE_IDX_TEST</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">FWK_MODULE_IDX_UART</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">FWK_MODULE_IDX_COUNT</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">fwk_id_t</span> <span class="n">fwk_module_id_test</span> <span class="o">=</span> <span class="n">FWK_MODULE_ID_TEST_INIT</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">fwk_id_t</span> <span class="n">fwk_module_id_uart</span> <span class="o">=</span> <span class="n">FWK_MODULE_ID_UART_INIT</span><span class="p">;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// build/mpw/GNU/debug/firmware-scp_romfw/framework/src/fwk_module_list.c
</span></span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">fwk_module</span> <span class="n">module_test</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">fwk_module</span> <span class="n">module_uart</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="k">const</span> <span class="k">struct</span> <span class="n">fwk_module</span> <span class="o">*</span><span class="n">module_table</span><span class="p">[</span><span class="n">FWK_MODULE_IDX_COUNT</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="o">&amp;</span><span class="n">module_test</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="o">&amp;</span><span class="n">module_uart</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">fwk_module_config</span> <span class="n">config_test</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">fwk_module_config</span> <span class="n">config_uart</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="k">const</span> <span class="k">struct</span> <span class="n">fwk_module_config</span> <span class="o">*</span><span class="n">module_config_table</span><span class="p">[</span><span class="n">FWK_MODULE_IDX_COUNT</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="o">&amp;</span><span class="n">config_test</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="o">&amp;</span><span class="n">config_uart</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><h3 id="如何确定各个模块在初始化过程中的执行顺序">如何确定各个模块在初始化过程中的执行顺序？</h3>
<p>在每个产品目录 mscp/product/juno/scp_romfw/Firmware.cmake 中，都会有一个 Firmware.cmake 文件，这个文件中会包含该产品所包含的模块：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULES</span> <span class="s2">&#34;juno-ppu&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULES</span> <span class="s2">&#34;juno-rom&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULES</span> <span class="s2">&#34;gtimer&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULES</span> <span class="s2">&#34;sds&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULES</span> <span class="s2">&#34;bootloader&#34;</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="nb">list</span><span class="p">(</span><span class="s">APPEND</span> <span class="s">SCP_MODULES</span> <span class="s2">&#34;juno-soc-clock&#34;</span><span class="p">)</span><span class="err">
</span></span></span></code></pre></div><p>编译后会在 output 文件夹中生成<code>fwk_module_idx.h</code>文件，这个文件中会包含所有模块的索引，如下：</p>
<p>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Responsive Image</title>
    <style>
        .post-img-view {
            text-align: center;
        }
        .responsive-image {
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    
    <div class="post-img-view">
        <a data-fancybox="gallery" href="https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img/14-48-59-f81a00af1d7e54bd428cf18f77a3465e-20240729144858-cdaa85.png">
            <img class="responsive-image" src="https://picbed-1311007548.cos.ap-shanghai.myqcloud.com/markdown_picbed/img/14-48-59-f81a00af1d7e54bd428cf18f77a3465e-20240729144858-cdaa85.png" alt=""  style="margin: 0 auto;"/>
        </a>
    </div>
    

    <script>
        document.addEventListener("DOMContentLoaded", function() {
            var images = document.querySelectorAll(".responsive-image");
            var maxHeight = window.innerHeight / 3;
            images.forEach(function(image) {
                image.style.maxHeight = maxHeight + "px";
            });
        });
    </script>
</body>
</html></p>
]]></content:encoded>
    </item>
  </channel>
</rss>
