日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

nrf51822-添加DFU服务

發布時間:2025/3/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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個函數

點擊(此處)折疊或打開

  • #ifdef BLE_DFU_APP_SUPPORT
  • /**@brief?Function?for?stopping advertising.
  • ?*/
  • static void advertising_stop(void)
  • {
  • ????uint32_t err_code;

  • ????err_code?=?sd_ble_gap_adv_stop();
  • ????APP_ERROR_CHECK(err_code);

  • ????err_code?=?bsp_indication_set(BSP_INDICATE_IDLE);
  • ????APP_ERROR_CHECK(err_code);
  • }


  • /**@brief?Function?for?loading application-specific context after establishing a secure connection.
  • ?*
  • ?*?@details This?function?will load the application context?and?check?if?the ATT table?is?marked as?
  • ?*?changed.?If?the ATT table?is?marked as changed,?a Service Changed Indication
  • ?*?is?sent?to?the peer?if?the Service Changed CCCD?is?set?to?indicate.
  • ?*
  • ?*?@param[in]?p_handle The Device Manager handle that identifies the connection?for?which the context?
  • ?*?should be loaded.
  • ?*/
  • static void app_context_load(dm_handle_t?const?*?p_handle)
  • {
  • ????uint32_t err_code;
  • ????static uint32_t context_data;
  • ????dm_application_context_t context;

  • ????context.len?=?sizeof(context_data);
  • ????context.p_data?=?(uint8_t?*)&context_data;

  • ????err_code?=?dm_application_context_get(p_handle,?&context);
  • ????if?(err_code?==?NRF_SUCCESS)
  • ????{
  • ????????//?Send Service Changed Indication?if?ATT table has changed.
  • ????????if?((context_data?&?(DFU_APP_ATT_TABLE_CHANGED?<<?DFU_APP_ATT_TABLE_POS))?!=?0)
  • ????????{
  • ????????????err_code?=?sd_ble_gatts_service_changed(m_conn_handle,?APP_SERVICE_HANDLE_START,?BLE_HANDLE_MAX);
  • ????????????if?((err_code?!=?NRF_SUCCESS)?&&
  • ????????????????(err_code?!=?BLE_ERROR_INVALID_CONN_HANDLE)?&&
  • ????????????????(err_code?!=?NRF_ERROR_INVALID_STATE)?&&
  • ????????????????(err_code?!=?BLE_ERROR_NO_TX_BUFFERS)?&&
  • ????????????????(err_code?!=?NRF_ERROR_BUSY)?&&
  • ????????????????(err_code?!=?BLE_ERROR_GATTS_SYS_ATTR_MISSING))
  • ????????????{
  • ????????????????APP_ERROR_HANDLER(err_code);
  • ????????????}
  • ????????}

  • ????????err_code?=?dm_application_context_delete(p_handle);
  • ????????APP_ERROR_CHECK(err_code);
  • ????}
  • ????else?if?(err_code?==?DM_NO_APP_CONTEXT)
  • ????{
  • ????????//?No context available.?Ignore.
  • ????}
  • ????else
  • ????{
  • ????????APP_ERROR_HANDLER(err_code);
  • ????}
  • }


  • /**?@snippet?[DFU BLE Reset prepare]?*/
  • /**@brief?Function?for?preparing?for?system reset.
  • ?*
  • ?*?@details This?function?implements @ref dfu_app_reset_prepare_t.?It will be called by?
  • ?*?@ref dfu_app_handler.c before entering the bootloader/DFU.
  • ?*?This allows the current running application?to?shut down gracefully.
  • ?*/
  • static void reset_prepare(void)
  • {
  • ????uint32_t err_code;

  • ????if?(m_conn_handle?!=?BLE_CONN_HANDLE_INVALID)
  • ????{
  • ????????//?Disconnect from peer.
  • ????????err_code?=?sd_ble_gap_disconnect(m_conn_handle,?BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
  • ????????APP_ERROR_CHECK(err_code);
  • ????????err_code?=?bsp_indication_set(BSP_INDICATE_IDLE);
  • ????????APP_ERROR_CHECK(err_code);
  • ????}
  • ????else
  • ????{
  • ????????//?If?not?connected,?the device will be advertising.?Hence stop the advertising.
  • ????????advertising_stop();
  • ????}

  • ????err_code?=?ble_conn_params_stop();
  • ????APP_ERROR_CHECK(err_code);

  • ????nrf_delay_ms(500);
  • }
  • /**?@snippet?[DFU BLE Reset prepare]?*/
  • #endif?//?BLE_DFU_APP_SUPPORT

  • 以上代碼都用??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服务的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 又黄又高潮的视频 | 天天射天天爽 | 污片免费看| 午夜视频在线免费观看 | 中文字幕久久综合 | 华人色| 99精品在线观看 | 97公开免费视频 | 欧美性生活一区 | 一级爱爱免费视频 | 91激情影院 | 亚洲乱人伦 | 成人精品在线 | 污污内射久久一区二区欧美日韩 | 久久都是精品 | 人妻熟女一区二区三区 | 久久中文字幕av | 又黄又骚又爽 | 三级精品在线观看 | 爱情岛论坛亚洲品质自拍 | 动漫女生光屁股 | 91视频网址 | 超碰加勒比 | 国产男女啪啪 | 一本色道久久亚洲综合精品蜜桃 | 午夜av免费观看 | 亚洲人屁股眼子交1 | 乳孔很大能进去的av番号 | 中文字幕二区三区 | 日韩免费福利视频 | 天天干女人 | 丰满少妇被猛烈进入一区二区 | 亚洲网址 | 日本久久久久久 | 色黄啪啪网 | 草莓视频一区二区三区 | 日日夜夜操操操 | 亚洲欧美综合一区 | 狠狠操天天操夜夜操 | 中文字幕日韩精品在线 | 黑人与日本少妇 | 国产69xx| 美女又爽又黄又免费 | 亚洲精品一区二区三区区别 | 中文字幕在线播放第一页 | 韩日av | 欧美美女一级片 | 国产主播在线播放 | 亚洲AV无码国产精品 | 免费av在线电影 | 国产欧美另类 | 夜夜夜撸 | 日韩精品一区二区不卡 | 成人短视频在线 | aaaaa黄色片 天堂网在线观看 | 不卡的毛片 | 色图av | 欧美黄网在线观看 | 国产精品久久久久久中文字 | 91丨九色丨蝌蚪丨丝袜 | 99re这里只有精品首页 | 欧美一区二区视频免费观看 | 黄色片视频在线观看 | 欧美 日韩 视频 | a毛片在线免费观看 | 西西人体44www大胆无码 | 亚洲女人初尝黑人巨大 | 一区二区三区日本视频 | 欧美日韩资源 | 91精品国产91久久久久久久久久久久 | 久久视频精品在线 | 亚洲国产精品区 | 成人区精品一区二区婷婷 | 亚洲精品在线电影 | 国产精品久久久久影院老司 | 国产一区二区三区四区五区美女 | 欧美男人亚洲天堂 | 免费网站91 | 无人在线观看高清视频 单曲 | 精品一区二区三区在线观看 | 午夜爽爽视频 | 国产男男gay体育生白袜 | 国产亚洲色婷婷久久 | 精品白浆| 三级无遮挡 | 日韩色| 永久久久久久 | 欧美日韩亚洲国产另类 | 国产成人在线免费观看 | xxx日本少妇 | 亚洲欧美一区在线 | 粉嫩一区二区三区 | 在线看片不卡 | 色图一区 | 懂色av一区| 午夜伦伦电影理论片费看 | 毛片无遮挡高清免费观看 | 中文字幕免费在线观看视频 | 在线日韩成人 |