nrf51822-添加DFU服务
以?ble_app_uart例子為基礎,在其上添加dfu服務。
Sdk中的bootloader提供了兩個方式來進入升級模式,一種是按鍵,另一種是手機點擊升級。?
在bootloader代碼相關代碼如下
如果是手機app通過點擊圖標直接升級,那么在app跳轉到bootloader進行升級前就會設置? NRF_POWER->GPREGRET?這個寄存器的值。所以bootloader代碼中開始就是判斷這個寄存器中的值來判斷是不是手機觸發的進入DFU模式。
下面的代碼會判斷是否有 設備上的按鍵按下,如果在上電過程中按下按鍵也會進入DFU模式。
?
PS:無論是通過手機上的?DFU圖標進入升級模式,還是通過設備上的按鍵進入升級模式都是需要?bootloader的, 兩種方式只是進入升級模式 的方式不同而已。
首先打開ble_app_uart工程在keil中添加如下所需模塊
然后添加一些DFU相關的處理代碼
Main.c中添加
?
#ifdef BLE_DFU_APP_SUPPORT
#include "ble_dfu.h"
#include "dfu_app_handler.h"
#endif
?
修改IS_SRVC_CHANGED_CHARACT_PRESENT?宏為1
????
Main.c中添加如下宏
Main.c中添加如下靜態變量
#ifdef BLE_DFU_APP_SUPPORT???
static ble_dfu_t???????????????????????? m_dfus;???????????????????????????????????
#endif
Main.c中添加如下3個函數
點擊(此處)折疊或打開
以上代碼都用??BLE_DFU_APP_SUPPORT?這個宏來包含了,所以添加這些代碼后需要在工程設置中添加一下這個宏的定義。
PS:官方的?hrs例子中 存在帶dfu的工程,打開那個工程直接全局搜這個宏就能找到上面這個和?dfu相關的代碼了。這里的代碼就是從那里拷貝過來的。
?
Main.c中的services_init函數的最后添加 創建dfu?服務的代碼
?
static void services_init(void)
{
???????? ………………………
???????? ……………………….
#ifdef BLE_DFU_APP_SUPPORT
??? /** @snippet [DFU BLE Service initialization] */
??? ble_dfu_init_t?? dfus_init;
?
??? // Initialize the Device Firmware Update Service.
??? memset(&dfus_init, 0, sizeof(dfus_init));
?
??
?dfus_init.evt_handler?? = dfu_app_on_dfu_evt;
??? dfus_init.error_handler = NULL;
??? dfus_init.evt_handler?? = dfu_app_on_dfu_evt;
??? dfus_init.revision????? = DFU_REVISION;
?
??? err_code = ble_dfu_init(&m_dfus, &dfus_init);
??? APP_ERROR_CHECK(err_code);
?
??? dfu_app_reset_prepare_set(reset_prepare);
??? dfu_app_dm_appl_instance_set(m_app_handle);
???????? #endif // BLE_DFU_APP_SUPPORT
}
事件派發函數中 添加?dfu的事件處理函數以及?device_manage模塊的事件處理函數
Main.c中再添加如下函數和代碼
這時候編譯下載程序后使用nordic?官方軟件?nrf master control panel軟件 連接設備后可以看到右上角有一個DFU的小圖標。點擊那個就可以升級了。
PS:別忘了需要燒寫bootloader
那么點擊這個dfu圖標后是如何跳轉bootloader進入升級模式的呢。
前面我們在service_init?中添加了dfu服務的創建。
函數中設置了一個回調函數?dfu_app_on_dfu_evt
當點擊?DFU?圖標后就會發送一條啟動指令,dfu_app_on_dfu_evt函數中會處理這條指令
Bootloader_start函數就是做一些設置然后跳轉到bootloader中去
上面的?sd_power_gpregret_set函數就是設置一個標記,表明從是從app?中啟動進入bootloader的。
和前面說的bootloader代碼中開頭的判斷所對應
Sdk中的bootloader例子是基于32Kram的51422,如果使用16kram的51822需要修改如下地址
?
另外,一旦燒錄bootloader后設備上電啟動順序不再是 協議棧->app
而是 協議棧->bootloader->app
在bootloader中會對app是否有效做判斷,sdk中的實現是只有通過DFU模式升級的app才會被認為有效的,應為DFU模式升級后會設置一些相關標志。?DFU判斷app是不是有效就是判斷這些標志, 所以如果你用燒錄軟件燒寫app,因為沒有設置一些標志,所以bootloader會認為?app無效,從而不會啟動app。
不過可以通過修改一下變量來實現,即使通過燒錄軟件燒錄app,bootloader也可以正常啟動app。
打開bootlaoder工程中的bootloader_settings.c文件,修改如下變量就可以了。
如果應用程序中使用了看門狗那么dfu中也需要喂狗,51822的看門狗打開后就會一直運行。
看門狗最好設置成 睡眠時看門狗也停止,這樣方便處理,只要在 喚醒后喂狗就行了,睡眠多久無所謂,因為睡眠時看門狗不會計數
直接將下面兩個值設置為0。
bootloader代碼中添加喂狗代碼
PS:如果使用的SDK是高版本,并且程序中本身已經 有 自定義基準UUID的話,這個時候添加DFU代碼需要修改 ?基準UUID允許添加的個數,因為默認是1,本身服務已經添加了, 而DFU服務也是使用自定義 基準UUID的,這個時候?ble_dfu_init??初始化函數里面調用?sd_ble_uuid_vs_add 函數時就會出錯了。所以修改允許設置的自定義UUID個數。 如下修改:
總結
以上是生活随笔為你收集整理的nrf51822-添加DFU服务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BLE-NRF51822教程6-创建一个
- 下一篇: nrf51822-使用16位自定义UUI