<?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>BES on 栈外随记</title>
    <link>https://btio.cn/categories/bes/</link>
    <description>Recent content in BES on 栈外随记</description>
    <image>
      <title>栈外随记</title>
      <url>https://btio.cn/images/logo-arong.svg</url>
      <link>https://btio.cn/images/logo-arong.svg</link>
    </image>
    <generator>Hugo</generator>
    <language>zh-CN</language><lastBuildDate>Fri, 23 Oct 2026 00:00:00 +0800</lastBuildDate>
    <atom:link href="https://btio.cn/categories/bes/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>【BES】编译配置（03）：Make 变量怎样变成 C 宏</title>
      <link>https://btio.cn/posts/2026/10/23/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE03make-%E5%8F%98%E9%87%8F%E6%80%8E%E6%A0%B7%E5%8F%98%E6%88%90-c-%E5%AE%8F/</link>
      <pubDate>Fri, 23 Oct 2026 00:00:00 +0800</pubDate>
      <guid>https://btio.cn/posts/2026/10/23/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE03make-%E5%8F%98%E9%87%8F%E6%80%8E%E6%A0%B7%E5%8F%98%E6%88%90-c-%E5%AE%8F/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://btio.cn/posts/2026/10/22/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE02%E6%9E%84%E5%BB%BA%E7%9B%AE%E6%A0%87%E4%B8%8E%E9%85%8D%E7%BD%AE%E8%A6%86%E7%9B%96/&#34;&gt;前一篇&lt;/a&gt;
讨论了 Make 变量从哪里来、怎样覆盖。接下来还要弄清楚：配置文件中的开关，怎样影响 C 源码里的 &lt;code&gt;#ifdef&lt;/code&gt;？&lt;/p&gt;
&lt;h2 id=&#34;一从变量到宏的传递过程&#34;&gt;一、从变量到宏的传递过程&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;程序&lt;/th&gt;
					&lt;th&gt;主要读取什么&lt;/th&gt;
					&lt;th&gt;在构建中负责什么&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Make&lt;/td&gt;
					&lt;td&gt;Makefile、&lt;code&gt;.mk&lt;/code&gt; 文件&lt;/td&gt;
					&lt;td&gt;根据配置安排构建，并组织传给编译器的参数&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;C 编译器&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;.c&lt;/code&gt;、&lt;code&gt;.h&lt;/code&gt; 等源码文件&lt;/td&gt;
					&lt;td&gt;根据宏和源码内容，生成目标文件&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;写在 &lt;code&gt;.mk&lt;/code&gt; 文件中的变量，是给 Make 使用的。C 编译器不会自动读取这些变量。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;先用一个简单的 &lt;code&gt;MY_FEATURE&lt;/code&gt; 开关说明。&lt;/p&gt;
&lt;h3 id=&#34;11-定义-make-变量&#34;&gt;1.1 定义 Make 变量&lt;/h3&gt;
&lt;p&gt;假设 &lt;code&gt;.mk&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-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;MY_FEATURE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;MY_FEATURE&lt;/code&gt; 是 Make 变量，Make 用 &lt;code&gt;$(MY_FEATURE)&lt;/code&gt; 取值。例如，判断这个开关是否等于 &lt;code&gt;1&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-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;ifeq&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;MY_FEATURE&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;,1)&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;c&#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;endif&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;12-export传递给子-make&#34;&gt;1.2 &lt;code&gt;export&lt;/code&gt;：传递给子 Make&lt;/h3&gt;
&lt;p&gt;如果顶层 Make 另外启动子 Make 来构建模块，后面的子 Make 也可能需要这个开关。这时可以前面加 &lt;code&gt;export&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-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;export &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;MY_FEATURE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;export&lt;/code&gt; 会把变量带给后续子进程，子 Make 因而也能读取 &lt;code&gt;MY_FEATURE&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;这里说的子 Make，是另外启动的 Make 进程。如果是同一个 Make， 通过 &lt;code&gt;include&lt;/code&gt; 读入多个配置文件时，变量可以在该进程内使用，无需为了 &lt;code&gt;include&lt;/code&gt; 单独加 &lt;code&gt;export&lt;/code&gt;。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【BES】编译配置（04）：源码怎样编译成固件</title>
      <link>https://btio.cn/posts/2026/10/23/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE04%E6%BA%90%E7%A0%81%E6%80%8E%E6%A0%B7%E7%BC%96%E8%AF%91%E6%88%90%E5%9B%BA%E4%BB%B6/</link>
      <pubDate>Fri, 23 Oct 2026 00:00:00 +0800</pubDate>
      <guid>https://btio.cn/posts/2026/10/23/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE04%E6%BA%90%E7%A0%81%E6%80%8E%E6%A0%B7%E7%BC%96%E8%AF%91%E6%88%90%E5%9B%BA%E4%BB%B6/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://btio.cn/posts/2026/10/23/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE03make-%E5%8F%98%E9%87%8F%E6%80%8E%E6%A0%B7%E5%8F%98%E6%88%90-c-%E5%AE%8F/&#34;&gt;前一篇&lt;/a&gt;
说明了配置怎样变成编译参数。除了参数，构建系统还需要知道哪些目录、哪些源文件参与构建。这里继续借助本地 BES SDK，从源码清单查到编译命令，再看目标文件怎样链接成固件。&lt;/p&gt;
&lt;h2 id=&#34;一源码选择与编译&#34;&gt;一、源码选择与编译&lt;/h2&gt;
&lt;h3 id=&#34;11-core-y选择顶层目录&#34;&gt;1.1 &lt;code&gt;core-y&lt;/code&gt;：选择顶层目录&lt;/h3&gt;
&lt;p&gt;要选择参与构建的源码，先要确定它们所在的目录。这份 SDK 在 &lt;code&gt;target.mk&lt;/code&gt; 中通过 &lt;code&gt;core-y&lt;/code&gt; 列出顶层构建目录：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/71c4332f-e353-4fb1-a7fb-be5bbd0cc556.png&#34;&gt;
&lt;em&gt;图 1：&lt;code&gt;target.mk&lt;/code&gt; 用 &lt;code&gt;core-y&lt;/code&gt; 指定顶层构建目录&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;当前面没有指定 &lt;code&gt;EXT_SRC_DIR&lt;/code&gt; 时，会把 &lt;code&gt;apps/&lt;/code&gt; 和 &lt;code&gt;services/&lt;/code&gt; 加入这部分构建列表。后续再进入这些目录，读取各自的 Makefile。&lt;/p&gt;
&lt;h3 id=&#34;12-obj-y列出子目录和目标文件&#34;&gt;1.2 &lt;code&gt;obj-y&lt;/code&gt;：列出子目录和目标文件&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;core-y&lt;/code&gt; 加入 &lt;code&gt;services/&lt;/code&gt; 后，构建系统会读取 &lt;code&gt;services/Makefile&lt;/code&gt;。里面的 &lt;code&gt;obj-y&lt;/code&gt; 再决定这个目录下哪些内容参与构建。&lt;/p&gt;
&lt;p&gt;在这套构建系统里，&lt;code&gt;obj-y&lt;/code&gt; 是当前目录的构建清单，里面既可以写子目录，也可以写目标文件。清单的名称和处理方式由 SDK 的构建脚本约定，Make 本身不会因为变量叫 &lt;code&gt;obj-y&lt;/code&gt; 就自动编译它。&lt;/p&gt;
&lt;h4 id=&#34;1子目录条目&#34;&gt;（1）子目录条目&lt;/h4&gt;
&lt;p&gt;在 &lt;code&gt;services/Makefile&lt;/code&gt; 的 &lt;code&gt;obj-y&lt;/code&gt; 列表中，可以找到：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/2cd1527f-f90e-4558-8d91-4f5b94644d5b.png&#34;&gt;
&lt;em&gt;图 2：&lt;code&gt;services/Makefile&lt;/code&gt; 用 &lt;code&gt;obj-y&lt;/code&gt; 列出子目录&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;audio_process/&lt;/code&gt; 末尾带 &lt;code&gt;/&lt;/code&gt;，表示还要进入这个子目录，继续读取 &lt;code&gt;services/audio_process/Makefile&lt;/code&gt;。&lt;/p&gt;
&lt;h4 id=&#34;2目标文件条目&#34;&gt;（2）目标文件条目&lt;/h4&gt;
&lt;p&gt;进入 &lt;code&gt;services/audio_process/&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;audio_process.c
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;audio_process_vol.c
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;audio_spectrum.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这些源码需要经过编译，生成对应的 &lt;code&gt;.o&lt;/code&gt; 文件。例如，&lt;code&gt;audio_process.c&lt;/code&gt; 编译后生成 &lt;code&gt;audio_process.o&lt;/code&gt;。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【BES】外设适配（01）：触摸输入从采样到事件</title>
      <link>https://btio.cn/posts/2026/10/23/bes%E5%A4%96%E8%AE%BE%E9%80%82%E9%85%8D01%E8%A7%A6%E6%91%B8%E8%BE%93%E5%85%A5%E4%BB%8E%E9%87%87%E6%A0%B7%E5%88%B0%E4%BA%8B%E4%BB%B6/</link>
      <pubDate>Fri, 23 Oct 2026 00:00:00 +0800</pubDate>
      <guid>https://btio.cn/posts/2026/10/23/bes%E5%A4%96%E8%AE%BE%E9%80%82%E9%85%8D01%E8%A7%A6%E6%91%B8%E8%BE%93%E5%85%A5%E4%BB%8E%E9%87%87%E6%A0%B7%E5%88%B0%E4%BA%8B%E4%BB%B6/</guid>
      <description>&lt;h2 id=&#34;一tws-按键交互背景&#34;&gt;一、TWS 按键交互背景&lt;/h2&gt;
&lt;p&gt;耳机可以通过电容触摸、压力感应、实体按键或敲击检测等方式接收用户操作。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/d818f1bd-4b8b-44c6-859a-2e64d98ab0ce.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;我接触的这份 BES 项目使用 CAPSENSOR 电容感应方案。
以“双击暂停音乐”为例，先要完成触摸检测，得到“某个事件”，应用才能继续执行对应功能。&lt;/p&gt;
&lt;h2 id=&#34;二触摸检测的基本流程&#34;&gt;二、触摸检测的基本流程&lt;/h2&gt;
&lt;p&gt;手指接近或接触感应区域，会引起电容变化。硬件按一定节奏测量，将结果转换成程序能读取的数值，这个过程叫作&lt;strong&gt;采样&lt;/strong&gt;。软件再结合数据随时间的变化，识别单击、双击或长按。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/e4093ded-3ee8-48a1-8d76-e21d216407ec.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;采样数据是测量结果，触摸事件是识别结果。&lt;/strong&gt; 在实际开发中，重点先确认检测能启动、事件能产生，再将事件接入业务。&lt;/p&gt;
&lt;h2 id=&#34;三开机后从应用初始化到触摸初始化&#34;&gt;三、开机后，从应用初始化到触摸初始化&lt;/h2&gt;
&lt;p&gt;先看开机时这条主线&lt;/p&gt;
&lt;div class=&#34;mermaid-diagram&#34; role=&#34;group&#34; aria-label=&#34;流程图&#34;&gt;
  &lt;pre class=&#34;mermaid&#34;&gt;%%{init: {&amp;#34;flowchart&amp;#34;: {&amp;#34;htmlLabels&amp;#34;: true, &amp;#34;wrappingWidth&amp;#34;: 1000, &amp;#34;rankSpacing&amp;#34;: 30}, &amp;#34;themeVariables&amp;#34;: {&amp;#34;lineColor&amp;#34;: &amp;#34;#71829a&amp;#34;}, &amp;#34;themeCSS&amp;#34;: &amp;#34;.nodeLabel { white-space: nowrap; } .nodeLabel p { margin: 0; }&amp;#34;}}%%
flowchart TB
    subgraph INIT[&amp;#34;① 应用初始化&amp;#34;]
        direction LR
        A[&amp;#34;应用入口&amp;lt;br/&amp;gt;app_init()&amp;#34;]
        B[&amp;#34;初始化触摸模块&amp;lt;br/&amp;gt;app_mcu_core_capsensor_init()&amp;#34;]
        C[&amp;#34;准备时钟和模拟电路&amp;lt;br/&amp;gt;capsensor_driver_init()&amp;#34;]
        D[&amp;#34;创建检测线程&amp;lt;br/&amp;gt;cap_sensor_core_thread_init()&amp;#34;]
        A --&amp;gt; B --&amp;gt; C --&amp;gt; D
    end

    subgraph TASK[&amp;#34;② 检测线程&amp;#34;]
        direction LR
        E[&amp;#34;线程开始执行&amp;lt;br/&amp;gt;capsensor_thread()&amp;#34;]
        F[&amp;#34;配置并启动采样&amp;lt;br/&amp;gt;capsensor_drv_start()&amp;#34;]
        G[&amp;#34;设置采样中断&amp;lt;br/&amp;gt;cap_sensor_irqinit()&amp;#34;]
        E --&amp;gt; F --&amp;gt; G
    end

    INIT -..-&amp;gt;|&amp;#34;创建线程后，由 RTOS 调度运行&amp;#34;| TASK

    classDef initPhase fill:#e8f2ff,stroke:#7ba4d8,color:#23456b,stroke-width:1.5px;
    classDef taskPhase fill:#e7f4ec,stroke:#78aa8b,color:#24563a,stroke-width:1.5px;
    class A,B,C,D initPhase;
    class E,F,G taskPhase;
    style INIT fill:#f1f6fd,stroke:#b8cfe8,color:#23456b
    style TASK fill:#f0f8f3,stroke:#b9d7c4,color:#24563a&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&#34;31-从应用入口进入检测初始化&#34;&gt;3.1 从应用入口进入检测初始化&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;app_init()&lt;/code&gt; 在 &lt;code&gt;CAPSENSOR_ENABLE&lt;/code&gt; 开启时，调用 &lt;code&gt;app_mcu_core_capsensor_init()&lt;/code&gt;。图中前一个函数用于恢复佩戴检测的校准参数，这里继续沿第二个函数看触摸初始化。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【BES】外设适配（02）：触摸事件怎样交给应用</title>
      <link>https://btio.cn/posts/2026/10/23/bes%E5%A4%96%E8%AE%BE%E9%80%82%E9%85%8D02%E8%A7%A6%E6%91%B8%E4%BA%8B%E4%BB%B6%E6%80%8E%E6%A0%B7%E4%BA%A4%E7%BB%99%E5%BA%94%E7%94%A8/</link>
      <pubDate>Fri, 23 Oct 2026 00:00:00 +0800</pubDate>
      <guid>https://btio.cn/posts/2026/10/23/bes%E5%A4%96%E8%AE%BE%E9%80%82%E9%85%8D02%E8%A7%A6%E6%91%B8%E4%BA%8B%E4%BB%B6%E6%80%8E%E6%A0%B7%E4%BA%A4%E7%BB%99%E5%BA%94%E7%94%A8/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://btio.cn/posts/2026/10/23/bes%E5%A4%96%E8%AE%BE%E9%80%82%E9%85%8D01%E8%A7%A6%E6%91%B8%E8%BE%93%E5%85%A5%E4%BB%8E%E9%87%87%E6%A0%B7%E5%88%B0%E4%BA%8B%E4%BB%B6/&#34;&gt;上一篇&lt;/a&gt;
讲到检测线程得到单击、双击等事件。这篇接着看：事件怎样进入应用，最后找到对应业务。&lt;/p&gt;
&lt;p&gt;本项目的 MCU 处理路径如下：&lt;/p&gt;
&lt;div class=&#34;mermaid-diagram&#34; role=&#34;group&#34; aria-label=&#34;流程图&#34;&gt;
  &lt;pre class=&#34;mermaid&#34;&gt;%%{init: {&amp;#34;flowchart&amp;#34;: {&amp;#34;htmlLabels&amp;#34;: true, &amp;#34;wrappingWidth&amp;#34;: 1000, &amp;#34;rankSpacing&amp;#34;: 30}, &amp;#34;themeVariables&amp;#34;: {&amp;#34;lineColor&amp;#34;: &amp;#34;#71829a&amp;#34;}}}%%
flowchart TB
    subgraph R0[&amp;#34;① 检测线程：调用接收函数&amp;#34;]
        direction LR
        R0N0[&amp;#34;得到检测事件&amp;lt;br/&amp;gt;status.event&amp;#34;]
        R0N1[&amp;#34;转换为应用按键事件&amp;lt;br/&amp;gt;app_capsensor_click_event()&amp;#34;]
        R0N2[&amp;#34;放入应用邮箱&amp;lt;br/&amp;gt;capsensor_key_event_process()&amp;#34;]
        R0N0 --&amp;gt; R0N1 --&amp;gt; R0N2
    end
    class R0N0,R0N1,R0N2 blue;
    style R0 fill:#f1f6fd,stroke:#b8cfe8,color:#23456b
    subgraph R1[&amp;#34;② 应用线程：取消息并分发&amp;#34;]
        direction LR
        R1N0[&amp;#34;还原按键消息&amp;lt;br/&amp;gt;app_key_handle_process()&amp;#34;]
        R1N1[&amp;#34;进入产品处理&amp;lt;br/&amp;gt;app_ibrt_user_key()&amp;#34;]
        R1N2[&amp;#34;按产品状态、左右耳和事件类型&amp;lt;br/&amp;gt;分发到对应业务函数&amp;#34;]
        R1N0 --&amp;gt; R1N1 --&amp;gt; R1N2
    end
    class R1N0,R1N1,R1N2 green;
    style R1 fill:#f0f8f3,stroke:#b9d7c4,color:#24563a
    R0 -..-&amp;gt;|&amp;#34;通过邮箱交给应用线程&amp;#34;| R1
    classDef blue fill:#e8f2ff,stroke:#7ba4d8,color:#23456b,stroke-width:1.5px;
    classDef green fill:#e7f4ec,stroke:#78aa8b,color:#24563a,stroke-width:1.5px;
    classDef amber fill:#fff3df,stroke:#d5a25b,color:#72501e,stroke-width:1.5px;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&#34;一初始化时登记事件接收函数&#34;&gt;一、初始化时，登记事件接收函数&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;app_mcu_core_capsensor_init()&lt;/code&gt; 中有一行：&lt;/p&gt;</description>
    </item>
    <item>
      <title>【BES】编译配置（01）：编译命令与构建脚本</title>
      <link>https://btio.cn/posts/2026/10/22/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE01%E7%BC%96%E8%AF%91%E5%91%BD%E4%BB%A4%E4%B8%8E%E6%9E%84%E5%BB%BA%E8%84%9A%E6%9C%AC/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0800</pubDate>
      <guid>https://btio.cn/posts/2026/10/22/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE01%E7%BC%96%E8%AF%91%E5%91%BD%E4%BB%A4%E4%B8%8E%E6%9E%84%E5%BB%BA%E8%84%9A%E6%9C%AC/</guid>
      <description>&lt;p&gt;在&lt;a href=&#34;https://btio.cn/posts/2026/10/20/bes%E7%B3%BB%E7%BB%9F%E6%80%BB%E8%A7%8801%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE%E5%A6%82%E4%BD%95%E5%86%B3%E5%AE%9A%E5%9B%BA%E4%BB%B6%E5%8A%9F%E8%83%BD/&#34;&gt;《系统总览（01）：编译配置如何决定固件功能》&lt;/a&gt;
中，用 ANC 介绍了配置对源码的影响。实际构建项目时，还要先弄清楚该执行什么命令、得到什么文件，以及是否需要后续处理。&lt;/p&gt;
&lt;p&gt;这里通过我在实际项目开发中所使用的BES  2700这款芯片的SDK 所用的构建命令进行介绍。包含构建目标、输出路径和 CRC 处理方式。&lt;/p&gt;
&lt;h2 id=&#34;一执行编译命令&#34;&gt;一、执行编译命令&lt;/h2&gt;
&lt;p&gt;编译bes工程，可以在工程根目录打开终端，输入：&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-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make &lt;span class=&#34;nv&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;best1306p -j
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make 会读取工程里的 Makefile，并按其中的规则完成构建。这条命令中，&lt;code&gt;T=best1306p&lt;/code&gt; 是用于选择这份工程的构建配置，&lt;code&gt;-j&lt;/code&gt; 用于并行构建。&lt;/p&gt;
&lt;p&gt;平时修改的 &lt;code&gt;.c&lt;/code&gt;、&lt;code&gt;.cpp&lt;/code&gt; 源码。经过编译、链接，源码会变成芯片能够执行的程序，并与相关数据一起组成固件。本例生成的固件文件路径是 &lt;code&gt;out/best1306p/best1306p.bin&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;二为固件补充校验信息&#34;&gt;二、为固件补充校验信息&lt;/h2&gt;
&lt;h3 id=&#34;21-crc-后处理&#34;&gt;2.1 CRC 后处理&lt;/h3&gt;
&lt;p&gt;编译生成固件后，有些项目还需要为后续升级补充校验信息。例如，接收方要检查收到的数据是否与准备好的固件一致，就需要一个用于比较的校验值。这里以 CRC32 为例。&lt;/p&gt;
&lt;p&gt;CRC 的中文名称是“循环冗余校验”。电脑先算好一个值，接收方拿到数据后，再按相同范围、相同算法算一次，与保存的值比较：&lt;/p&gt;
&lt;div class=&#34;mermaid-diagram&#34; role=&#34;group&#34; aria-label=&#34;流程图&#34;&gt;
  &lt;pre class=&#34;mermaid&#34;&gt;%%{init: {&amp;#34;flowchart&amp;#34;: {&amp;#34;htmlLabels&amp;#34;: true, &amp;#34;wrappingWidth&amp;#34;: 1000, &amp;#34;rankSpacing&amp;#34;: 30}, &amp;#34;themeVariables&amp;#34;: {&amp;#34;lineColor&amp;#34;: &amp;#34;#71829a&amp;#34;}}}%%
flowchart TB
    subgraph R0[&amp;#34;① 电脑上准备固件时&amp;#34;]
        direction LR
        R0N0[&amp;#34;生成固件&amp;#34;]
        R0N1[&amp;#34;计算 CRC&amp;#34;]
        R0N2[&amp;#34;将校验值填入固件&amp;#34;]
        R0N0 --&amp;gt; R0N1 --&amp;gt; R0N2
    end
    class R0N0,R0N1,R0N2 blue;
    style R0 fill:#f1f6fd,stroke:#b8cfe8,color:#23456b
    subgraph R1[&amp;#34;② 后续设备接收后&amp;#34;]
        direction LR
        R1N0[&amp;#34;读取收到的固件数据&amp;#34;]
        R1N1[&amp;#34;耳机重新计算 CRC&amp;#34;]
        R1N2[&amp;#34;与固件中保存的 CRC 比较&amp;#34;]
        R1N0 --&amp;gt; R1N1 --&amp;gt; R1N2
    end
    class R1N0,R1N1,R1N2 green;
    style R1 fill:#f0f8f3,stroke:#b9d7c4,color:#24563a
    R0 -..-&amp;gt;|&amp;#34;后续设备收到文件&amp;#34;| R1
    classDef blue fill:#e8f2ff,stroke:#7ba4d8,color:#23456b,stroke-width:1.5px;
    classDef green fill:#e7f4ec,stroke:#78aa8b,color:#24563a,stroke-width:1.5px;
    classDef amber fill:#fff3df,stroke:#d5a25b,color:#72501e,stroke-width:1.5px;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;对比结果不同，说明数据在传输中发生了变化；结果相同，表示通过校验，数据传输正常。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【BES】编译配置（02）：构建目标与配置覆盖</title>
      <link>https://btio.cn/posts/2026/10/22/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE02%E6%9E%84%E5%BB%BA%E7%9B%AE%E6%A0%87%E4%B8%8E%E9%85%8D%E7%BD%AE%E8%A6%86%E7%9B%96/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0800</pubDate>
      <guid>https://btio.cn/posts/2026/10/22/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE02%E6%9E%84%E5%BB%BA%E7%9B%AE%E6%A0%87%E4%B8%8E%E9%85%8D%E7%BD%AE%E8%A6%86%E7%9B%96/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://btio.cn/posts/2026/10/22/bes%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE01%E7%BC%96%E8%AF%91%E5%91%BD%E4%BB%A4%E4%B8%8E%E6%9E%84%E5%BB%BA%E8%84%9A%E6%9C%AC/&#34;&gt;前一篇&lt;/a&gt;
介绍了如何执行构建命令。这篇看配置怎样被选中和加载。&lt;/p&gt;
&lt;h2 id=&#34;一构建目标与配置加载&#34;&gt;一、构建目标与配置加载&lt;/h2&gt;
&lt;h3 id=&#34;11-t选择构建目标&#34;&gt;1.1 &lt;code&gt;T&lt;/code&gt;：选择构建目标&lt;/h3&gt;
&lt;p&gt;要知道本次构建用了哪套配置，可以先查构建命令传入了哪些变量、Makefile 怎样使用它们。&lt;/p&gt;
&lt;p&gt;这份 SDK 用 &lt;code&gt;T&lt;/code&gt; 选择构建目标，顶层 &lt;code&gt;Makefile&lt;/code&gt; 根据T的值，拼出配置文件路径。传入 &lt;code&gt;T=best1306p&lt;/code&gt;，选中的就是 &lt;code&gt;config/best1306p/target.mk&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/a4529f52-b717-46a8-aa9e-b7499d57cbee.png&#34;&gt;
&lt;em&gt;图 1：顶层 &lt;code&gt;Makefile&lt;/code&gt; 根据 &lt;code&gt;T&lt;/code&gt; 拼出配置路径&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;默认的构建输出目录如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/ce61f938-c97f-4f36-b850-ba3bf3375d4f.png&#34;&gt;
&lt;em&gt;图 2：顶层 &lt;code&gt;Makefile&lt;/code&gt; 中的输出目录设置与目标检查&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Makefile 还会检查这个文件是否存在。不存在时，会报 &lt;code&gt;Invalid target&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;修改配置前先看构建命令里的 &lt;code&gt;T&lt;/code&gt;，再去找对应目录，避免改了另一套配置。&lt;/p&gt;
&lt;h3 id=&#34;12-chip指定芯片平台&#34;&gt;1.2 &lt;code&gt;CHIP&lt;/code&gt;：指定芯片平台&lt;/h3&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-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CHIP&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?=&lt;/span&gt; best1306p
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里用的也是 &lt;code&gt;best1306p&lt;/code&gt; 作为默认值。&lt;/p&gt;
&lt;p&gt;两个变量的用途分别是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;T&lt;/code&gt;&lt;/strong&gt;：选择哪套产品或构建配置。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;CHIP&lt;/code&gt;&lt;/strong&gt;：指定这套配置使用的芯片平台。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这次两者恰好都叫 &lt;code&gt;best1306p&lt;/code&gt;。换成产品目标时，它们可能不同。&lt;/p&gt;
&lt;h3 id=&#34;13-配置文件的加载顺序&#34;&gt;1.3 配置文件的加载顺序&lt;/h3&gt;
&lt;p&gt;配置拆在多个文件中时，Make 可以用 &lt;code&gt;include&lt;/code&gt; 读入其他文件。因此，查配置除了找赋值，还要沿着 &lt;code&gt;include&lt;/code&gt; 看它们的加载顺序。&lt;/p&gt;
&lt;p&gt;这份工程的顶层 &lt;code&gt;Makefile&lt;/code&gt; 先读入下面两个文件：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/7309d56c-162d-47de-b7ca-7618c2b455a3.png&#34;&gt;
&lt;em&gt;图 3：先读取目标配置，再读取公共配置&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;srctree&lt;/code&gt; 表示源码根目录。这里先读取 &lt;code&gt;target.mk&lt;/code&gt;，再读取 &lt;code&gt;common.mk&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;target.mk&lt;/code&gt; 里面还有其他 &lt;code&gt;include&lt;/code&gt;。Make 读到这里，会先处理被包含的文件，再回来接着读后面的配置。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【BES】系统总览（02）：开机初始化到应用模块</title>
      <link>https://btio.cn/posts/2026/10/21/bes%E7%B3%BB%E7%BB%9F%E6%80%BB%E8%A7%8802%E5%BC%80%E6%9C%BA%E5%88%9D%E5%A7%8B%E5%8C%96%E5%88%B0%E5%BA%94%E7%94%A8%E6%A8%A1%E5%9D%97/</link>
      <pubDate>Wed, 21 Oct 2026 00:00:00 +0800</pubDate>
      <guid>https://btio.cn/posts/2026/10/21/bes%E7%B3%BB%E7%BB%9F%E6%80%BB%E8%A7%8802%E5%BC%80%E6%9C%BA%E5%88%9D%E5%A7%8B%E5%8C%96%E5%88%B0%E5%BA%94%E7%94%A8%E6%A8%A1%E5%9D%97/</guid>
      <description>&lt;p&gt;耳机开机后，应用层需要先准备好运行环境：读取配置数据、创建消息处理机制、初始化各业务模块，之后才能处理按键、连接、音乐播放等事件。&lt;/p&gt;
&lt;h2 id=&#34;一应用层从哪里开始&#34;&gt;一、应用层从哪里开始&lt;/h2&gt;
&lt;p&gt;正常启动时，&lt;code&gt;main()&lt;/code&gt; 完成平台侧准备，然后调用 &lt;code&gt;app_init()&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/30cdfc02-8d91-4454-a25d-e36f7f48da40.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;app_init()&lt;/code&gt; 是应用层初始化的主要入口。看这个函数，可以了解 SDK 开机时启用了哪些模块，以及模块之间的初始化顺序和条件。&lt;/p&gt;
&lt;h2 id=&#34;二app_init-初始化系统和模块&#34;&gt;二、&lt;code&gt;app_init()&lt;/code&gt; 初始化系统和模块&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;app_init()&lt;/code&gt; 下，关键的初始化函数有：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;nv_record_init()&lt;/code&gt;：准备 NV 数据、工厂参数&lt;/li&gt;
&lt;li&gt;&lt;code&gt;app_os_init()&lt;/code&gt;：创建 app 邮箱和线程&lt;/li&gt;
&lt;li&gt;&lt;code&gt;app_battery_open()&lt;/code&gt;：检查电池、充电状态，确定启动分支&lt;/li&gt;
&lt;li&gt;&lt;code&gt;app_key_open()&lt;/code&gt;：按键检测及开机按键处理&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bt_app_init()&lt;/code&gt;：蓝牙模块&lt;/li&gt;
&lt;li&gt;&lt;code&gt;app_audio_open()&lt;/code&gt;：音频模块&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这里的初始化，是为了让模块具备处理业务的条件。例如，音频模块初始化完成，并不代表已经开始播放音乐，后面还需要播放事件触发。&lt;/p&gt;
&lt;h2 id=&#34;三建立应用线程和邮箱&#34;&gt;三、建立应用线程和邮箱&lt;/h2&gt;
&lt;p&gt;在 &lt;code&gt;app_init()&lt;/code&gt; 中，会调用 &lt;code&gt;app_os_init()&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/9e87eacd-d73b-489b-8afb-56a30c4396a4.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;这个函数主要完成两件事：先创建 app 邮箱，再创建 app 线程。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;正文配图&#34; loading=&#34;lazy&#34; src=&#34;https://picgocloud.com/m/16f47e13-f664-487e-8a8c-c7b7463f2820.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;邮箱用于保存待处理的应用消息，&lt;code&gt;app_thread&lt;/code&gt; 负责取出消息，并根据模块编号交给对应的处理函数。所以，这里的消息链路大致为：&lt;/p&gt;
&lt;div class=&#34;mermaid-diagram&#34; role=&#34;group&#34; aria-label=&#34;流程图&#34;&gt;
  &lt;pre class=&#34;mermaid&#34;&gt;%%{init: {&amp;#34;flowchart&amp;#34;: {&amp;#34;htmlLabels&amp;#34;: true, &amp;#34;wrappingWidth&amp;#34;: 1000, &amp;#34;rankSpacing&amp;#34;: 30}, &amp;#34;themeVariables&amp;#34;: {&amp;#34;lineColor&amp;#34;: &amp;#34;#71829a&amp;#34;}}}%%
flowchart TB
    subgraph R0[&amp;#34;① 消息投递&amp;#34;]
        direction LR
        R0N0[&amp;#34;模块产生消息&amp;#34;]
        R0N1[&amp;#34;放入 app 邮箱&amp;#34;]
        R0N0 --&amp;gt; R0N1
    end
    class R0N0,R0N1 blue;
    style R0 fill:#f1f6fd,stroke:#b8cfe8,color:#23456b
    subgraph R1[&amp;#34;② 应用线程处理&amp;#34;]
        direction LR
        R1N0[&amp;#34;app_thread 取出消息&amp;#34;]
        R1N1[&amp;#34;调用对应模块的处理函数&amp;#34;]
        R1N0 --&amp;gt; R1N1
    end
    class R1N0,R1N1 green;
    style R1 fill:#f0f8f3,stroke:#b9d7c4,color:#24563a
    R0 -..-&amp;gt;|&amp;#34;通过邮箱交接&amp;#34;| R1
    classDef blue fill:#e8f2ff,stroke:#7ba4d8,color:#23456b,stroke-width:1.5px;
    classDef green fill:#e7f4ec,stroke:#78aa8b,color:#24563a,stroke-width:1.5px;
    classDef amber fill:#fff3df,stroke:#d5a25b,color:#72501e,stroke-width:1.5px;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;这是 app 线程的处理方式。蓝牙和音频等子系统也有各自的线程或回调，整个 SDK 由这些任务协作运行。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【BES】系统总览（03）：事件如何触发业务处理</title>
      <link>https://btio.cn/posts/2026/10/21/bes%E7%B3%BB%E7%BB%9F%E6%80%BB%E8%A7%8803%E4%BA%8B%E4%BB%B6%E5%A6%82%E4%BD%95%E8%A7%A6%E5%8F%91%E4%B8%9A%E5%8A%A1%E5%A4%84%E7%90%86/</link>
      <pubDate>Wed, 21 Oct 2026 00:00:00 +0800</pubDate>
      <guid>https://btio.cn/posts/2026/10/21/bes%E7%B3%BB%E7%BB%9F%E6%80%BB%E8%A7%8803%E4%BA%8B%E4%BB%B6%E5%A6%82%E4%BD%95%E8%A7%A6%E5%8F%91%E4%B8%9A%E5%8A%A1%E5%A4%84%E7%90%86/</guid>
      <description>&lt;h1 id=&#34;bes系统总览03事件如何触发业务处理&#34;&gt;【BES】系统总览（03）：事件如何触发业务处理&lt;/h1&gt;
&lt;p&gt;上一篇介绍了开机初始化：创建线程、邮箱，初始化按键、蓝牙、音频等模块。&lt;/p&gt;
&lt;p&gt;初始化完成后，耳机就可以响应各种变化。例如，用户双击耳机、手机连接成功、App 切换降噪模式，都会触发相应的处理。&lt;/p&gt;
&lt;p&gt;这一篇主要介绍：&lt;strong&gt;一个事件发生后，是怎样进入业务代码的。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;一事件与业务的区别&#34;&gt;一、事件与业务的区别&lt;/h2&gt;
&lt;p&gt;事件描述“发生了什么”，业务决定“接下来做什么”。&lt;/p&gt;
&lt;p&gt;例如，用户双击左耳：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;事件&lt;/strong&gt;：左耳发生双击。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;业务&lt;/strong&gt;：根据当前状态，执行播放、暂停或者接听电话等操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;同一个操作，在不同状态下可能执行不同功能。&lt;/p&gt;
&lt;p&gt;整体流程可以这样理解：&lt;/p&gt;
&lt;div class=&#34;mermaid-diagram&#34; role=&#34;group&#34; aria-label=&#34;流程图&#34;&gt;
  &lt;pre class=&#34;mermaid&#34;&gt;%%{init: {&amp;#34;flowchart&amp;#34;: {&amp;#34;htmlLabels&amp;#34;: true, &amp;#34;wrappingWidth&amp;#34;: 1000, &amp;#34;rankSpacing&amp;#34;: 30}, &amp;#34;themeVariables&amp;#34;: {&amp;#34;lineColor&amp;#34;: &amp;#34;#71829a&amp;#34;}}}%%
flowchart TB
    subgraph R0[&amp;#34;① 事件传递&amp;#34;]
        direction LR
        R0N0[&amp;#34;检测到变化&amp;#34;]
        R0N1[&amp;#34;传递事件&amp;#34;]
        R0N2[&amp;#34;找到处理函数&amp;#34;]
        R0N0 --&amp;gt; R0N1 --&amp;gt; R0N2
    end
    class R0N0,R0N1,R0N2 blue;
    style R0 fill:#f1f6fd,stroke:#b8cfe8,color:#23456b
    subgraph R1[&amp;#34;② 业务处理&amp;#34;]
        direction LR
        R1N0[&amp;#34;判断当前状态&amp;#34;]
        R1N1[&amp;#34;执行具体操作&amp;#34;]
        R1N0 --&amp;gt; R1N1
    end
    class R1N0,R1N1 green;
    style R1 fill:#f0f8f3,stroke:#b9d7c4,color:#24563a
    R0 --&amp;gt; R1
    classDef blue fill:#e8f2ff,stroke:#7ba4d8,color:#23456b,stroke-width:1.5px;
    classDef green fill:#e7f4ec,stroke:#78aa8b,color:#24563a,stroke-width:1.5px;
    classDef amber fill:#fff3df,stroke:#d5a25b,color:#72501e,stroke-width:1.5px;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;下面结合 BES 的触摸链路来看。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【BES】系统总览（01）：编译配置如何决定固件功能</title>
      <link>https://btio.cn/posts/2026/10/20/bes%E7%B3%BB%E7%BB%9F%E6%80%BB%E8%A7%8801%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE%E5%A6%82%E4%BD%95%E5%86%B3%E5%AE%9A%E5%9B%BA%E4%BB%B6%E5%8A%9F%E8%83%BD/</link>
      <pubDate>Tue, 20 Oct 2026 00:00:00 +0800</pubDate>
      <guid>https://btio.cn/posts/2026/10/20/bes%E7%B3%BB%E7%BB%9F%E6%80%BB%E8%A7%8801%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE%E5%A6%82%E4%BD%95%E5%86%B3%E5%AE%9A%E5%9B%BA%E4%BB%B6%E5%8A%9F%E8%83%BD/</guid>
      <description>&lt;h2 id=&#34;一编译配置是什么&#34;&gt;一、编译配置是什么&lt;/h2&gt;
&lt;p&gt;配置主要由 &lt;code&gt;.mk&lt;/code&gt; 文件决定。看这些文件，可以了解当前选择了什么平台、加入了哪些模块，以及使用了哪些配置。&lt;/p&gt;
&lt;p&gt;编译配置发生在电脑生成固件时。耳机上电后，运行的是已经编译好的固件。&lt;/p&gt;
&lt;p&gt;整体流程如下：&lt;/p&gt;
&lt;div class=&#34;mermaid-diagram&#34; role=&#34;group&#34; aria-label=&#34;流程图&#34;&gt;
  &lt;pre class=&#34;mermaid&#34;&gt;%%{init: {&amp;#34;flowchart&amp;#34;: {&amp;#34;htmlLabels&amp;#34;: true, &amp;#34;wrappingWidth&amp;#34;: 1000, &amp;#34;rankSpacing&amp;#34;: 30}, &amp;#34;themeVariables&amp;#34;: {&amp;#34;lineColor&amp;#34;: &amp;#34;#71829a&amp;#34;}}}%%
flowchart TB
    subgraph R0[&amp;#34;① 电脑上构建&amp;#34;]
        direction LR
        R0N0[&amp;#34;读取配置&amp;#34;]
        R0N1[&amp;#34;编译、链接&amp;#34;]
        R0N2[&amp;#34;生成固件&amp;#34;]
        R0N0 --&amp;gt; R0N1 --&amp;gt; R0N2
    end
    class R0N0,R0N1,R0N2 blue;
    style R0 fill:#f1f6fd,stroke:#b8cfe8,color:#23456b
    subgraph R1[&amp;#34;② 耳机上运行&amp;#34;]
        direction LR
        R1N0[&amp;#34;烧录固件&amp;#34;]
        R1N1[&amp;#34;上电启动&amp;#34;]
        R1N2[&amp;#34;运行固件中的代码&amp;#34;]
        R1N0 --&amp;gt; R1N1 --&amp;gt; R1N2
    end
    class R1N0,R1N1,R1N2 green;
    style R1 fill:#f0f8f3,stroke:#b9d7c4,color:#24563a
    R0 --&amp;gt; R1
    classDef blue fill:#e8f2ff,stroke:#7ba4d8,color:#23456b,stroke-width:1.5px;
    classDef green fill:#e7f4ec,stroke:#78aa8b,color:#24563a,stroke-width:1.5px;
    classDef amber fill:#fff3df,stroke:#d5a25b,color:#72501e,stroke-width:1.5px;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&#34;二anc-配置如何影响源码&#34;&gt;二、ANC 配置如何影响源码&lt;/h2&gt;
&lt;h3 id=&#34;1-判断是否加载-anc-配置&#34;&gt;1. 判断是否加载 ANC 配置&lt;/h3&gt;
&lt;p&gt;下面是 &lt;code&gt;target.mk&lt;/code&gt; 中的判断：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
