littleshrimp 发表于 2021-8-28 17:34

BlueNRG系列如何使用静态协议栈

本帖最后由 littleshrimp 于 2021-8-28 17:33 编辑

<h1>前言</h1>

<blockquote>
<p>适用范围:BlueNRG-LP 软件, BlueNRG-1/2的也可以参考此方法 下文主要描述使用BlueNRG-LP SDK进行开发时,如何搭建使用静态协议栈环境。</p>

<p>如果你对BlueNRG-x系列的存储分布还不是那么熟悉,建议您阅读&nbsp;<a href="https://gitee.com/lucienkuang/BlueNRG-x-documentation/blob/master/Application/BlueNRG%E7%B3%BB%E5%88%97%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E9%9D%99%E6%80%81%E5%8D%8F%E8%AE%AE%E6%A0%88/BlueNRG%E7%B3%BB%E5%88%97%E5%AD%98%E5%82%A8%E5%88%86%E6%9E%90(Flash_and_RAM).md">BlueNRG系列存储分析(Flash_and_RAM)</a></p>
</blockquote>

<p>BlueNRG-1/2使用静态协议栈参考Demo:</p>

<p><a href="https://github.com/wallekuang/BlueNRG-1-2_Static_Static" rel="nofollow">https://github.com/wallekuang/BlueNRG-1-2_Static_Static</a></p>

<p>BlueNRG-LP使用静态协议栈参考Demo:</p>

<p><a href="https://gitee.com/lucienkuang/BlueNRG-LP_Static_Stack.git">https://gitee.com/lucienkuang/BlueNRG-LP_Static_Stack.git</a></p>

<p><strong>静态协议栈分多个工程,如果您只想简单使用,不做其他定制化的修改,并不想深入了解,可以直接复用上述给出的工程,然后只需要适配您自己的应用工程即可。</strong></p>

<h1>背景</h1>

<blockquote>
<p>在使用BlueNRG-LP调试的时候,有时遇到Flash空间不够的问题,可能应用还需要包含OTA,可能OTA中又包含协议栈。为了解决Flash空间不够这个问题,推荐使用静态协议栈的方式,节省空间,加速OTA的升级过程。</p>
</blockquote>

<h1>知识背景须知</h1>

<blockquote>
<p>下文描述具体的操作,默认您已经知晓ST 官方的BlueNRG-x 基本开发环境搭建和知晓OTA基本知识,ST官方提供比较多类型的OTA方式,详细请自行看官方文档&nbsp;<a href="https://www.st.com/resource/en/application_note/dm00293821.pdf" rel="nofollow">BLE Over Ther Air Firmware Upgrade (AN4869)&nbsp;</a>或者<a href="https://www.st.com/resource/en/application_note/dm00691320-the-bluenrglp-ota-overtheair-firmware-upgrade-stmicroelectronics.pdf" rel="nofollow">Bluetooth LE Over Ther Air Firmware Upgrade (AN5463)&nbsp;</a>。</p>
</blockquote>

<blockquote>
<p>温馨提示:<strong>请使用最新版本SDK进行开发</strong></p>
</blockquote>

<p>编译静态协议栈工程需要使用到GNU工具链,如果您没有安装,可以参考此文档进行安装&nbsp;<a href="https://gitee.com/lucienkuang/BlueNRG-x-documentation/blob/master/FAQ/%E5%AE%89%E8%A3%85GNU%E5%B7%A5%E5%85%B7%E9%93%BE/%E5%A6%82%E4%BD%95%E5%AE%89%E8%A3%85GNU%E5%B7%A5%E5%85%B7%E9%93%BE.md">如何安装GNU工具链</a></p>

<h1>参考使用官方静态协议栈Demo</h1>

<p>官方默认提供的静态协议栈工程的参考介绍:&nbsp;<a href="https://gitee.com/lucienkuang/BlueNRG-x-documentation/blob/master/Application/BlueNRG%E7%B3%BB%E5%88%97%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E9%9D%99%E6%80%81%E5%8D%8F%E8%AE%AE%E6%A0%88/%E9%9D%99%E6%80%81%E5%8D%8F%E8%AE%AE%E6%A0%88%E5%B7%A5%E7%A8%8B%E7%9A%844%E7%A7%8D%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE.md">静态协议栈工程的4种默认配置</a></p>

<h1>参考使用已有的自定义配置静态协议栈工程。</h1>

<p>如果您对配置过程不感兴趣,或者觉得比较繁琐,可以直接使用ST官方SDK中已经提供了静态协议栈的Demo,或者使用这个</p>

<h1>配置BlueNRG-LP工程为静态协议栈</h1>

<h2>自定义配置静态协议栈1(OTA使用BLE_OTA_ServiceManager)</h2>

<p><strong>如果你的应用工程移植起来不繁琐或者还没有开发应用并且ST官方SDK中已经提供了静态协议栈的Demo满足你的基本要求,你可以直接使用它。如果不是,那可能就需要直接在你目标的工程上改为静态协议栈,并且可能需要裁剪协议栈。下面我介绍一个比较常用用静态协议栈的修改方法。我们先通过了解Flash分布来知晓接下来这个实验的整个框架。应用程序APP这块,我们选择比较常用的BLE_SerialPort 工程;OTA 这里选择不备份的,单独的一个程序;协议栈选择Basic配置</strong></p>

<h3>Flash分布(此表格很重要,后续调试可以在此翻看):</h3>

<p>不同编辑工具,编译代码的效率不一样,个人实测,IAR的编辑的效率要比Keil 的高,有时有可能差别2KB以上。为了省事后续IAR 也采用和Keil 一致的参数。</p>

<ul>
        <li><strong>后续调试IAR 平台和Keil 平台实际 Flash分布</strong></li>
</ul>

<table>
        <thead>
                <tr>
                        <th>Flash区域</th>
                        <th align="left">占据空间</th>
                        <th>说明</th>
                </tr>
        </thead>
        <tbody>
                <tr>
                        <td>NVM</td>
                        <td align="left"><strong>[0x1007F000,0x10080000)【127页~128页】[0x3F000,0x4000)</strong></td>
                        <td>4KB=0x1000 ,协议栈存储GATT属性表和配对密钥等使用。</td>
                </tr>
                <tr>
                        <td>APP(BLE_SerialPort)</td>
                        <td align="left"><strong>[0x1005E000,0x1007F000)【60页~126页】[0x1E000,0x3F000)</strong></td>
                        <td>客户应用程序(132KB=0x21000可用空间)</td>
                </tr>
                <tr>
                        <td>BLE_OTA_ServiceManager</td>
                        <td align="left"><strong>[0x1005B000,0x1005E000)【54页~59页】 [0x1B000,0x1E000)</strong></td>
                        <td>应用OTA(12KB=0x3000)</td>
                </tr>
                <tr>
                        <td>BLE Stack(Basic)</td>
                        <td align="left"><strong>[0x10040000,0x1005B000) 【0页~53页】[0x00000,0x1B000)</strong></td>
                        <td>协议栈(108KB=0x1B000,BLE_STACK_SLAVE_DLE_CONF, 并且使能CONTROLLER_MASTER_ENABLED),协议栈可以裁剪和增加.如果是只作为从机只需要0x18000(96KB)。</td>
                </tr>
        </tbody>
</table>

<ul>
        <li>BLE Stack 的工程使用的是Basic配置,但将宏配置为BLE_STACK_SLAVE_DLE_CONF,考虑到BLE_SerialPort工程中有Master部分的,我们这里代码中Mater部分的也编译进去,因此使能CONTROLLER_MASTER_ENABLED。(stack_user_cfg.h中BLE_STACK_SLAVE_DLE_CONF下使能 CONTROLLER_MASTER_ENABLED = 1)
        <ul>
                <li>这里协议栈的配置选择和配置比较简单,主要是使用了哪些功能就使能对应的宏。更多精细的协议栈优化可以到具体的函数,如果没有使用到,就将bluenrg_lp_cmd_if.c 中对应的函数注释,这里先不涉及复杂的操作。</li>
                <li>配置好后编译生成固件,&nbsp;<strong>libbluenrg_lp_static_stack_basic.a</strong>,生成的固件将给BLE_OTA_ServiceManager工程和BLE_SerialPort工程使用。</li>
        </ul>
        </li>
        <li>BLE_OTA_ServiceManager 的工程是BLE_OTA_ServiceManager ,主要实现不备份方式的OTA(即OTA服务程序和应用不捆绑在一起)</li>
        <li>APP 客户应用程序,这块可使用的大小可以根据实际使用BLE Stack size进行调整,后面会描述调整的方法</li>
        <li>关于占据空间这块,第一部分是绝对地址,第二部分是Flash的页数,第三部分是相对地址。如果您对具体数值怎么得来有疑问,关于这点得通过下面的实操步骤往复调试,查看map,计算才能得来,这里是先给出结果。</li>
</ul>

<p>我们将根据这个Flash的分布,从Flash的底部,往上一个一个工程调试配置,</p>

<p>即从 BLE Stack&mdash;&mdash;》BLE_OTA_ServiceManager&mdash;&mdash;》BLE_SerialPort</p>

<p>不同的应用工程配置,需要协议栈提供不同的特性支持,协议栈的配置和应用使用协议栈的配置需要保持一致。为了方便,这里BLE_SerialPort中做主机和从机的配置都选用同一种协议栈的配置,考虑到BLE_SerialPort中有做主机(CONTROLLER_MASTER_ENABLED),以及BLE_OTA_ServiceManager使用了CONFIG_SW_OTA_DATA_LENGTH_EXT特性,因此所有工程。</p>

<h3><strong>BLE Stack(Basic)工程的更改点如下:</strong></h3>

<ul>
        <li>在工程配置Preprocessor中将RESET_MANAGER_SIZE=0x18000更改为:RESET_MANAGER_SIZE=0x1B000
        <ul>
                <li>因为更改了宏定义,使能了CONTROLLER_MASTER_ENABLED,需要占据更多的空间</li>
        </ul>
        </li>
        <li>在工程配置Preprocessor中将BLE_STACK_BASIC_CONF改为BLE_STACK_SLAVE_DLE_CONF
        <ul>
                <li>因为所有工程宏定义最好保持一致,只使用一个协议栈。</li>
        </ul>
        </li>
        <li>在工程配置Preprocessor中增加CONFIG_NUM_MAX_LINKS=1
        <ul>
                <li>这里需要根据实际应用来,如果此数值协议栈与其他工程不一致,有可能报RAM错误。</li>
        </ul>
        </li>
        <li>在工程配置Linker中将MEMORY_FLASH_APP_SIZE=0x18000更改为MEMORY_FLASH_APP_SIZE=0x1B000
        <ul>
                <li>需要更多的code区域,需要的大小可以通过生成的map文件查看得知。</li>
        </ul>
        </li>
        <li>在bluenrg_lp_cmd_if.c 中增加头文件包含 #include &ldquo;stack_user_cfg.h&rdquo; (如果没有包含该头文件的话)</li>
</ul>

<p>如果您对MEMORY_FLASH_APP_SIZE,MEMORY_RAM_APP_OFFSET等链接脚本中的宏定义表示的意义不是那么清楚的话,建议您查看阅读<a href="https://gitee.com/lucienkuang/BlueNRG-x-documentation/blob/master/Application/BlueNRG%E7%B3%BB%E5%88%97%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E9%9D%99%E6%80%81%E5%8D%8F%E8%AE%AE%E6%A0%88/BlueNRG%E7%B3%BB%E5%88%97%E5%AD%98%E5%82%A8%E5%88%86%E6%9E%90(Flash_and_RAM).md">BlueNRG系列存储分析(Flash_and_RAM)</a></p>

<h3>配置BLE_OTA_ServiceManager为静态协议栈版本</h3>

<ul>
        <li>
        <p>建议参考 BlueNRG-LP_DK_1_1_0\Projects\BLE_Examples\BLE_SensorDemo_StaticStack\README.txt</p>
        </li>
        <li>
        <p>为了不影响老的配置,这里新建一个配置</p>

        <ul>
                <li>IAR:Project&mdash;&mdash;》Edit configurations. ---&gt; 命名为StaticStackRlease</li>
                <li>Keil: File Extensions,Bolcks and Environment(Manage Project Items)</li>
        </ul>
        </li>
        <li>
        <p>从工程文件中禁用libbluenrg_lp_stack.a 和stack_user_cfg.c .</p>
        </li>
        <li>
        <p>在您的项目中包含 bluenrg_lp_stack_init_if.c 和 libbluenrg_lp_static_stack.a(来自 Middlewares\ST\Bluetooth_LE\Library\static_stack)。</p>

        <blockquote>
        <p>其中Keil 平台添加.a文件需要如下图所示,手动选择文件为lib 文件。</p>
        </blockquote>

        <blockquote>
        <p></p>
        </blockquote>
        </li>
        <li>
        <p>禁用所有包含在静态堆栈中的外部模块和驱动程序(它们的 符号被导出并可被应用程序使用):</p>

        <ul>
                <li>AES</li>
                <li>BLECNTR</li>
                <li>Cryptolib</li>
                <li>NVM</li>
                <li>PKA</li>
                <li>RNG</li>
                <li>GAP and GATT profiles</li>
                <li>HAL_VTimer</li>
                <li>rf_driver_hal_vtimer.c rf_driver_ll_radio_2g4.c rf_driver_ll_timer.c</li>
        </ul>
        </li>
        <li>
        <p>根据 BlueNRG 静态堆栈映像占用的 Flash 大小为链接器定义 MEMORY_FLASH_APP_OFFSET。 例如。 如果静态堆栈映像使用 Flash 直到地址 0x1005 A8F0,则偏移量必须大于等于 0x1B000,这是与页面开头对齐的第一个可用 Flash 位置的偏移量。</p>
        </li>
        <li>
        <p>为链接器定义 MEMORY_RAM_APP_OFFSET,以便在空闲 RAM 空间中分配变量,其中静态堆栈库没有分配其他变量。请参阅 BLE_SensorDemo_Static_Stack 项目中使用的 MEMORY_RAM_APP_OFFSET 以了解在使用静态堆栈时您的应用程序必须使用哪个 RAM 偏移 BlueNRG-LP DK 中包含的二进制文件。</p>
        </li>
        <li>
        <blockquote>
        <p>// 总结Linker 中的宏定义</p>

        <p>MEMORY_FLASH_APP_SIZE=0x3000 MEMORY_FLASH_APP_OFFSET=0x1B000 MEMORY_RAM_APP_OFFSET=0x06A0</p>

        <p>Keil 中格式和IAR稍微有点不一样,根据葫芦画瓢可得</p>

        <p>--predefine=&quot;-DMEMORY_FLASH_APP_SIZE=0x3000 -DMEMORY_FLASH_APP_OFFSET=0x1B000 -DMEMORY_RAM_APP_OFFSET=0x06A0&quot;</p>
        </blockquote>
        </li>
        <li>
        <p>使用与静态堆栈相同的模块化配置(例如,如果静态堆栈已使用 BLE_STACK_FULL_CONF 构建,则使用 BLE_STACK_FULL_CONF,如果静态堆栈已使用 BLE_STACK_BASIC_CONF 构建,则使用 BLE_STACK_BASIC_CONF)。</p>
        </li>
        <li>
        <blockquote>
        <p>// 总结Preprocessor中的定义</p>

        <p>SERVICE_MANAGER_OFFSET=0x1B000 SERVICE_MANAGER_SIZE=0x3000</p>

        <p>BLE_STACK_SLAVE_DLE_CONF</p>
        </blockquote>

        <ul>
                <li>更改OTA处代码OTA_btl.h中将</li>
        </ul>
        </li>
</ul>

<pre>
#define SERVICE_MANAGER_OFFSET   (0x0)
#ifdef CONFIG_DEVICE_BLUENRG_LP
    #define SERVICE_MANAGER_SIZE       PAGE_SIZE_ROUND(90* 1024) /* BlueNRG-LP, BLE stack v3.x with modular approach TBR*/
#endif

#define SM_APP_SIZE                PAGE_SIZE_TRUNC((_MEMORY_FLASH_SIZE_-SERVICE_MANAGER_SIZE-NVM_SIZE))</pre>

<pre>
更改为:</pre>

<pre>
#ifndef SERVICE_MANAGER_OFFSET
    #define SERVICE_MANAGER_OFFSET   (0)
#endif
#ifndef SERVICE_MANAGER_SIZE
    #define SERVICE_MANAGER_SIZE       PAGE_SIZE_ROUND(90* 1024) /* BlueNRG-LP, BLE stack v3.x with modular approach TBR*/
#endif   

#define SM_APP_SIZE                PAGE_SIZE_TRUNC((_MEMORY_FLASH_SIZE_-SERVICE_MANAGER_SIZE-NVM_SIZE-SERVICE_MANAGER_OFFSET))</pre>

<ul>
        <li>修改完后,编译固件查看其地址,确认无误后下载运行,使用BLE测试工具测试(如果使用Keil工具,BLE_OTA_ServiceManager的偏移地址应该是0x1005B000)。</li>
</ul>

<p></p>

<h3>配置BLE_SerialPort为静态协议栈版本</h3>

<ul>
        <li>
        <p>建议参考 BlueNRG-LP_DK_1_1_0\Projects\BLE_Examples\BLE_SensorDemo_StaticStack\README.txt</p>
        </li>
        <li>
        <p>这里举例子配置 Serial Port 的Service配置</p>
        </li>
        <li>
        <p>为了不影响老的配置,这里新建一个配置</p>

        <ul>
                <li>IAR:Project&mdash;&mdash;》Edit configurations. ---&gt; 命名为StaticStackService</li>
                <li>Keil: File Extensions,Bolcks and Environment(Manage Project Items)</li>
        </ul>

        <ul>
                <li>
                <p>从工程文件中禁用libbluenrg_lp_stack.a 和stack_user_cfg.c .</p>
                </li>
                <li>
                <p>禁用所有包含在静态堆栈中的外部模块和驱动程序(它们的 符号被导出并可被应用程序使用):</p>

                <ul>
                        <li>AES</li>
                        <li>BLECNTR</li>
                        <li>Cryptolib</li>
                        <li>NVM</li>
                        <li>PKA</li>
                        <li>RNG</li>
                        <li>GAP and GATT profiles</li>
                        <li>HAL_VTimer</li>
                        <li>rf_driver_hal_vtimer.c rf_driver_ll_radio_2g4.c</li>
                </ul>
                </li>
        </ul>
        </li>
        <li>
        <p>根据 BlueNRG 静态堆栈映像占用的 Flash 大小 ,加上BLE_OTA_ServiceManager区域所占的大小(12KB), 为链接器定义 MEMORY_FLASH_APP_OFFSET + BLE_OTA_ServiceManager size。 例如。 如果静态堆栈映像使用 Flash 直到地址 0x1005 9B20,则偏移量必须大于等于 0x1B000 + 0x3000,这是与页面开头对齐的第一个可用 Flash 位置的偏移量。</p>
        </li>
        <li>
        <p>为Linker定义 MEMORY_RAM_APP_OFFSET,以便在空闲 RAM 空间中分配变量,其中静态堆栈库没有分配其他变量。请参阅 BLE_SensorDemo_Static_Stack 项目中使用的 MEMORY_RAM_APP_OFFSET 以了解在使用静态堆栈时您的应用程序必须使用哪个 RAM 偏移 BlueNRG-LP DK 中包含的二进制文件。</p>
        </li>
        <li>
        <blockquote>
        <p>// 总结Linker 中的宏定义</p>

        <p>CONFIG_OTA_USE_SERVICE_MANAGER=1 MEMORY_FLASH_APP_SIZE=0x21000 MEMORY_RAM_APP_OFFSET=0x06A0 MEMORY_FLASH_APP_OFFSET=0x1E000</p>

        <p>Keil 中格式和IAR稍微有点不一样,根据葫芦画瓢可得</p>

        <p>--predefine=&quot;-DCONFIG_OTA_USE_SERVICE_MANAGER=1 -DMEMORY_FLASH_APP_SIZE=0x21000 -DMEMORY_RAM_APP_OFFSET=0x06A0 -DMEMORY_FLASH_APP_OFFSET=0x1E000 &quot;</p>
        </blockquote>
        </li>
        <li>
        <p>增加 修改链接脚本文件: BlueNRG_LP.sct or BlueNRG_LP.icf</p>

        <blockquote>
        <p>// IAR左边 Keil 右边 主要增加&ldquo;#Ifndef endif&rdquo;</p>

        <p></p>
        </blockquote>
        </li>
        <li>
        <p>测试:</p>

        <ul>
                <li>检查是否通过编译</li>
                <li>使用JFlash检查生成的Hex文件偏移地址</li>
                <li>下载程序</li>
                <li>检查串口日志和使用BLE 测试工具扫描广播</li>
        </ul>
        </li>
</ul>

<h2>自定义配置静态协议栈2(OTA服务在应用BLE_SerialPort中,备份应用程序)</h2>

<h3>Flash分布</h3>

<table>
        <thead>
                <tr>
                        <th>Flash区域</th>
                        <th align="left">占据空间</th>
                        <th>说明</th>
                </tr>
        </thead>
        <tbody>
                <tr>
                        <td>NVM</td>
                        <td align="left"><strong>[0x1007F000,0x10080000)【127页~128页】[0x3F000,0x4000)</strong></td>
                        <td>4KB=0x1000 ,协议栈存储GATT属性表和配对密钥等使用。</td>
                </tr>
                <tr>
                        <td>HigherAPP(BLE_SerialPort)</td>
                        <td align="left"><strong>[0x1006D000,0x1007F000)【60页~126页】[0x2D000,0x3F000)</strong></td>
                        <td>客户应用程序高地址区域(72KB=0x12000可用空间)</td>
                </tr>
                <tr>
                        <td>LowerAPP(BLE_SerialPort)</td>
                        <td align="left"><strong>[0x1005B000,0x1006D000)【60页~126页】[0x1B000,0x2D000)</strong></td>
                        <td>客户应用程序低地址区域(72KB=0x12000可用空间)</td>
                </tr>
                <tr>
                        <td>BLE Stack(Basic)</td>
                        <td align="left"><strong>[0x10040000,0x1005B000) 【0页~53页】[0x00000,0x1B000)</strong></td>
                        <td>协议栈(108KB=0x1B000,BLE_STACK_SLAVE_DLE_CONF, 并且使能CONTROLLER_MASTER_ENABLED),协议栈可以裁剪和增加.如果是只作为从机只需要0x18000(96KB)。</td>
                </tr>
        </tbody>
</table>

<h3>小结</h3>

<pre>
通过上述一步一步的优化,我们完成了将普通工程改成使用静态协议栈的方式,并且支持OTA。
实际应用可能有各种不同的应用需求,用户可以根据同样原理去优化适配合适你们的工程。
如果希望协议栈页可以通过空中升级,查看下文。</pre>

<h2>进阶:配置支持协议栈的升级(待完善。。。)</h2>

<ul>
        <li>这里协议栈的升级由于空间不够,这里就采用2.4G 升级方式。工程路径: BlueNRG-LP DK 1.0.0\Projects\Peripheral_Examples\Examples_MIX\RADIO\RADIO_OTA_ResetManager--&gt;Client</li>
        <li>主要修改配置宏,前面描述比较详细,这里我就不一一描述了。主要罗列一些不同工程的linker配置和宏配置。</li>
</ul>

<p>更多内容请参考lucienkuang的帖子《BlueNRG系列的教程_文档_培训资料与常见问题等汇总介绍》</p>

<p><a href="https://bbs.eeworld.com.cn/thread-1162870-1-1.html">https://bbs.eeworld.com.cn/thread-1162870-1-1.html</a></p>

Jacktang 发表于 2021-8-30 08:47

<p>BlueNRG系列教程级总结,收藏</p>
页: [1]
查看完整版本: BlueNRG系列如何使用静态协议栈