發布成功
贊賞金額:
支付金額:5元
支付方式:
贊賞成功!
你的贊賞是對作者最大的肯定~?
【編者按 】關于BlueNRG系列如何使用靜態協議棧 - Copy,適用范圍:BlueNRG-LP 軟件, BlueNRG-1/2的也可以參考此方法,本文主要描述使用BlueNRG-LP SDK進行開發時,如何搭建使用靜態協議棧環境。
在使用BlueNRG-LP調試的時候,有時遇到Flash空間不夠的問題,如果應用還需要包含OTA,如果OTA中又包含協議棧,為了解決Flash空間不夠這個問題,我推薦使用靜態協議棧的方式,節省空間,加速OTA的升級過程。
下文描述具體的操作,我默認你已經知曉ST 官方的BlueNRG-xx 基本開發環境搭建和OTA基本知識,ST官方提供比較多類型的OTA方式,詳細請自行看官方文檔《AN4869 Application note The BlueNRG-1, BlueNRG-2 BLE OTA (over-the-air) firmware upgrade.pdf》 或者《AN5463 Application note The BlueNRG-LP (over-the-air) firmware upgrade.pdf》。
溫馨提示:請使用最新版本SDK進行開發
ST官方SDK中已經提供了靜態協議棧的Demo:
? C:\Users\Lucien\ST\BlueNRG-LP DK 1.0.0\Projects\BLE_Examples\BLE_StaticStack
– Release
? OTA_BTL_ResetManager
? C:\Users\Lucien\ST\BlueNRG-LP DK 1.0.0\Projects\BLE_Examples\BLE_SensorDemo_StaticStack
– Release
? LowerApp_OTA
? HigherApp_OTA
其中,一個工程負責生成協議棧,另一個工程負責應用,那么這里BLE_StaticStack中的Release與OTA_BTL_ResetManager怎么和Release,LowerApp_OTA和HigherApp_OTA組合呢?
? BLE_StaticStack中的Release + BLE_SensorDemo_StaticStack中的Release //不帶OTA的使用固定協議棧的方法
? BLE_StaticStack中的OTA_BTL_ResetManager + BLE_SensorDemo_StaticStack中的 LowerApp_OTA or HigherApp_OTA //帶OTA的使用固定協議棧的方法
如果你的應用工程移植起來不繁瑣或者還沒有開發應用并且ST官方SDK中已經提供了靜態協議棧的Demo滿足你的基本要求,你可以直接使用它。如果不是,那可能就需要直接在你目標的工程上改為靜態協議棧,并且可能需要裁剪協議棧。下面我介紹一個比較復雜些的使用靜態協議棧的修改方法。我們先通過了解Flash分布來知曉接下來這個實驗的整個框架。
Flash區域 | 說明 |
NVM | 4KB |
APP | 客戶應用程序,暫定92KB |
Boot + BLE_OTA_ServiceManager | 應用OTA,12kb |
BLE Stack | 協議棧,暫定138KB,可以裁剪 |
2.4G OTA (10KB 升級協議棧) | 占10KB 升級協議棧和應用代碼 |
BlueNRG-355 的Flash空間是256kB,實現的基本思路是:由于協議棧的升級幾率比較低,這里又不太想占用太多的代碼空間,所以協議棧的升級改用走2.4G私有協議進行升級,如果是非安全性要求很高很高的應用(一般的應用)我個人認為不需要升級協議棧。這里對協議棧的空中升級只是留一手,萬一需要升級,又不想通過串口或者SW口升級。
? 2.4G OTA 使用的工程是RADIO_OTA_ResetManager中的Client,
? 如果對協議棧和應用一起升級的工程是RADIO_OTA_ResetManager中的Server_FixedImage。
? BLE full Stack 的工程是 BLE_StaticStack
? Boot + BLE_OTA_ServiceManager 的工程是BLE_OTA_ServiceManager ,主要實現不備份方式的OTA(即OTA服務程序和應用不捆綁在一起)
? APP 客戶應用程序,這塊可使用的大小可以根據實際使用BLE Stack size進行調整,后面會描述調整的方法
下面我們一步一步,一個工程一個工程調試,從“基本的協議棧+app”到“支持應用OTA的協議棧+app”再到“支持協議棧OTA和支持應用OTA的靜態協議棧Demo".我主要給出基于Keil 優化分析過程,IAR的操作類似,相對更簡單一些,可以同樣類比過去。
1. 編譯生成靜態協議棧: BlueNRG-LP DK 1.0.0\Projects\BLE_Examples\BLE_StaticStack 編譯成功后,會在目錄BlueNRG-LP DK 1.0.0\Middlewares\ST\Bluetooth_LE\library\static_stack下生成libbluenrg_lp_static_stack.a文件,這里Keil 和IAR都一樣,但想要成功編譯并且生成static_stack下生成libbluenrg_lp_static_stack.a 需要使用安裝arm-none-eabi工具鏈,none表示不帶操作系統(普通的RTOS不算在這類操作系統中,這里主要是稍微大型一些的如Linux操作系統)。工具鏈請自行到GNU官網上下載,安裝好后,然后設置環境變量.
安裝工具鏈和測試可以參考文檔:BlueNRG-LP DK 1.0.0\Projects\BLE_Examples\BLE_StaticStack\README.txt
這里主要是keil或者IAR編譯后,運行腳本: "..........\Utility\create_sym_lib.exe --symbols ....\sym_export.txt --rename BLE_STACK_Init=BLE_STACK_Init_nocallbacks Release\Objects\BLE_StaticStack.axf ..........\Middlewares\ST\Bluetooth_LE\Library\static_stack\libbluenrg_lp_static_stack.a" 主要作用是把文件sym_export.txt中的列表中的函數,從編譯生成的*.axf文件中找出對應的地址信息,然后通過create_sym_lib.exe生成.a庫, 這個*.a文件就是應用于協議棧的橋梁,應用層是在協議棧之上的,這個是接口,就算將來升級協議棧,接口一般都是不允許改動的,這樣不會影響應用。
1. 修改BLE_MultipleConnections調用靜態協議棧
默認BLE_MultipleConnections工程,使用的不是固定協議棧的方式。我們需要更換為調用上一步驟生成的*.a文件 此過程可以參考官方文件: BlueNRG-LP DK 1.0.0\Projects\BLE_Examples\BLE_SensorDemo_StaticStack\README.txt
操作步驟如下:
– 移除或者禁止加入編譯老的libbluenrg_lp_stack.a和stack_user_cfg.c
? Keil平臺禁止加入編譯可以右擊該文件,然后選擇Option for File xxx ... 接著把Include target build 去掉,最后點擊OK,可以看到文件前面有個紅色的禁止圖標
– IAR平臺禁止加入編譯可以右擊該文件,然后選擇Options,接著勾選左上角的Exclude form build,最后點擊OK,可以看到文件圖標顏色變灰色。
– 禁止整個文件夾加入編譯也是如是操作,后續不再啰嗦。
– 移除或者禁止整個NVM文件夾,Middlewares/Profiles文件夾和bluenrg_lp_hal_vtimer.c bluenrg_lp_ll_radio.c, 這兩部分已經在協議棧中包含了,如果不禁止掉會重復包含重新定義。
– 添加文件libbluenrg_lp_static_stack.a和bluenrg_lp_stack_init_if.c到工程,文件路徑:Middlewares\ST\Bluetooth_LE\Library\static_stack
? Keil 平臺添加*.a庫后,需要將其文件類型手動選擇為庫文件類型。 //右擊*.a文件,Options for file *.a ,然后選擇File type 下拉框選擇Library file。
– 定義宏MEMORY_FLASH_APP_OFFSET,這個宏定義的值能決定生成文件的絕對地址,由于Flash的擦除必須是每次一整頁(2KB),所以加入協議棧的bin文件占用地址0x1A438 Byte(105.05KB) 則應用偏移為0x1A800(106KB)
? Keil 平臺MEMORY_FLASH_APP_OFFSET這個宏定義需要定義在Options for target -> linker->Misc controls中,格式可以參考BLE_SensorDemo_StaticStack工程。
– IAR 平臺MEMORY_FLASH_APP_OFFSET這個宏定義需要定義在Options->linker->config->configuration file symbol definitions中,格式也可以參考BLE_SensorDemo_StaticStack工程。
– 定義MEMORY_RAM_APP_OFFSET宏,因為靜態協議棧這種方式,變量在兩個不同的工程中,所以協議棧的變量和應用的變量得區分開來,這個宏需要根據協議棧變量占用RAM的大小來決定,查看默認的工程,可以看到BLE_StaticStack.map文件中變量存放的最后一行是:
Base Addr | Size | Type | Attr | Idx | E Section Name | Object |
0x200007ec | 0x00000024 | Zero | RW | 4255 | .bss | libbluenrg_lp_stack.a(mem_alloc.o) |
? RAM的起始地址為0x20000000, 可以算出協議棧占用的內存總數為0x7EC+ 0x24 = 0x810, IAR平臺下這個數值很可能是不一樣(0x7AC),IAR的編譯效率一般會更高一些,這里如果擔心算得不準,也可以設置稍微偏大一點點。
– 還有一點需要注意的是協議棧中定義的宏BLE_STACK_FULL_CONF 需要和應用中保持一致,如果不一致可能有有些問題。
– 協議棧中代碼裁剪可以精確到函數,除了選擇合適的協議棧配置宏定義外,可以通過是否注釋bluenrg_lp_cmd_if.c中cmd_call_table[]數組中的函數,用來決定是否將該函數編譯進協議棧。(這種方式相當靈活,暫時沒有看到過可以做到這樣的其他藍牙芯片廠家)
– 編譯成功后,分別通過下載BLE_StaticStack.hex 和 BLE_MultipleConnections_MasterSlave.hex, 可以使用Keil 或者IAR直接download,也可以使用Flash utility下載。實際測試發現,如果在線調試,可能會有些錯誤,應該是平臺工具的問題,RAM變量的銜接問題,建議使用靜態協議棧后就不要用在線debug單步調試了,如果想用單步調試則先不要改成靜態協議棧這種方式。
? 如果下載bin文件,可以合稱后直接下載,也可以分別下載,但需要設定下載地址,操作和合成細節在這就先不說。
– 小結: 這個階段我們將一個普通使用非靜態協議棧工程改成了使用靜態協議棧的方式,將協議棧占用的Flash和RAM 區分開來,然后通過不同的協議棧宏配置和注釋cmd_call_table[]數組中的函數,可以實現對協議棧的裁剪
固件 | MEMORY_FLASH_APP_SIZE [Linker] | MEMORY_FLASH_APP_OFFSET[Linker] | MEMORY_RAM_APP_OFFSET[Linker] | RESET_MANAGER_SIZE[PreDefine] | |||
BLE_StaticStack | 0x22800 | none(default 0) | none(default 0) | 0x22800 | |||
BLE_MultipleConnections | none | 0x22800 | 0x810 | none | |||
? 測試: 成功更改后,應該可以通過串口日志和使用BLE測試工具成功看到應用程序跑起來
Flash分布:
Flash | 說明 |
NVM | 4KB |
APP | 114KB |
BLE Stack | 138KB |
? 將BLE_OTA_ServiceManager更改為支持靜態協議棧版本比較簡單,和上述步驟很類似,我就不一一描述了,下面我只描述一些細節,供參考。
? 更改OTA處代碼OTA_btl.h中將
#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))
更改為:
#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))
? 注意修改BLE_OTA_ServiceManager中協議棧配置宏和靜態協議棧保持一致(我這里是BLE_STACK_FULL_CONF)
? BLE_MultipleConnections做如下修改:
– 在linker中增加宏定義(注意Keil格式和IAR格式稍微有點不一樣):
CONFIG_OTA_USE_SERVICE_MANAGER=1 // 修改鏈接文件使按照CONFIG_OTA_USE_SERVICE_MANAGER格式劃分
MEMORY_FLASH_APP_OFFSET=0x25800 // 應用其實偏移地址修改為: BLE_StaticStack+BLE_OTA_ServiceManager
MEMORY_RAM_APP_OFFSET=0x0810 // 內存不能占用到協議棧使用那部分的
+ 增加 修改鏈接腳本文件: BlueNRG_LP.sct or BlueNRG_LP.icf
Keil: // #ifdef CONFIG_OTA_USE_SERVICE_MANAGER分支下
#define SERVICE_MANAGER_SIZE (0x16800)
#define MEMORY_FLASH_APP_SIZE (_MEMORY_FLASH_SIZE_ - SERVICE_MANAGER_SIZE - FLASH_NVM_DATASIZE)
#define MEMORY_FLASH_APP_OFFSET (SERVICE_MANAGER_SIZE)
更改為:
#ifndef SERVICE_MANAGER_SIZE
#define SERVICE_MANAGER_SIZE (0x16800)
#endif
#ifndef MEMORY_FLASH_APP_OFFSET
#define MEMORY_FLASH_APP_OFFSET (SERVICE_MANAGER_SIZE)
#endif
#define MEMORY_FLASH_APP_SIZE (_MEMORY_FLASH_SIZE_ - MEMORY_FLASH_APP_OFFSET - FLASH_NVM_DATASIZE)
IAR: // CONFIG_OTA_USE_SERVICE_MANAGER分支下
同樣類比更改,這里不再復述
固件 | MEMORY FLASH APP SIZE [Linker] | MEMORY FLASH APP OFFSET [Linker] | MEMORY RAM APP OFFSET [Linker] | RESET MANAGER SIZE [PreDefine] | SERVICE MANAGER SIZE [PreDefine] | SERVICE MANAGER OFFSET [PreDefine] | |
BLE_StaticStack | 0x22800 | none(default 0) | none(default 0) | 0 | none | none | |
BLE_OTA_ServiceManager | 0x3000 | 0x22800 | 0x810 | none | 0x25800 | 0x22800 | |
BLE_MultipleConnections | none | 0x25800 | 0x810 | none | none | none | |
? Flash分布如下圖
Flash | 說明 |
NVM | 4KB |
APP | 102KB |
BLE_OTA_ServiceManager | 12KB |
BLE Stack | 138KB |
? 這里協議棧的升級由于空間不夠,這里就采用2.4G 升級方式。工程路徑: BlueNRG-LP DK 1.0.0\Projects\Peripheral_Examples\Examples_MIX\RADIO\RADIO_OTA_ResetManager-->Client
? 主要修改配置宏,前面描述比較詳細,這里我就不一一描述了。主要羅列一些不同工程的linker配置和宏配置。
– RADIO_OTA_ResetManager:
linker:
MEMORY_FLASH_APP_SIZE=0x2800
MEMORY_RAM_APP_OFFSET=0x0810
Preprocessor Defined symbols:
SERVICE_MANAGER_SIZE=0x2800
? BLE_StaticStack:
linker:
MEMORY_FLASH_APP_SIZE=0x22800
MEMORY_FLASH_APP_OFFSET=0x2800
Preprocessor Defined symbols:
RESET_MANAGER_SIZE=0x25000
BLE_STACK_FULL_CONF
? BLE_OTA_ServiceManager:
linker:
MEMORY_FLASH_APP_SIZE=0x3000
MEMORY_FLASH_APP_OFFSET=0x25000
MEMORY_RAM_APP_OFFSET=0x0810
Preprocessor Defined symbols:
BLE_STACK_FULL_CONF
SERVICE_MANAGER_OFFSET=0x25000
SERVICE_MANAGER_SIZE=0x3000
? BLE_OTA_ServiceManager:
linker:
CONFIG_OTA_USE_SERVICE_MANAGER=1
MEMORY_FLASH_APP_OFFSET=0x28000
MEMORY_RAM_APP_OFFSET=0x0810
Preprocessor Defined symbols:
BLE_STACK_FULL_CONF
Flash | 說明 |
NVM | 4KB |
APP | 92KB |
BLE_OTA_ServiceManager | 12KB |
BLE Stack | 138KB |
2.4G_OTA_ServiceManager | 10KB |
通過上述一步一步的優化,我們完成了將普通工程改成使用靜態協議棧的方式,并且支持OTA。
實際應用可能有各種不同的應用需求,用戶可以根據同樣原理去優化適配合適你們的工程。
作者:LucienKUANG, 多年BLE 和Mesh相關開發和支持經驗,先后開發過,空氣波壓力治療儀系統,共享單車鎖,自拍桿,點讀筆電子價簽系統等等嵌入式軟件產品的嵌入式軟件開發。支持過ST,Dialog等大廠BLE相關產品的開發。在我愛方案網的個人店鋪為“路恩”,有類似的項目開發需求者歡迎聯系。