一 环境搭建

开发环境使用官方提供的Simplicity Studio,在官网即可下载到。silicon 官网:https://www.silabs.com/

该平台的SDK以及文档全部都可以通过Simplicity Studio下载得到,因此下载安装Simplicity Studio是第一步。

1 安装SDK

  • Simplicity Studio安装完之后,你的界面就如下图所示。这个工具需要进行简单的注册,注册是免费的。点击下载按钮,下载安装sdk。

  • 选择Install by Product Group

  • 选择Bluetooth,这里只关心Bluetooth,因此只需要勾选Bluetooth即可。点击下一步。

    这里会列出来,你有权限下载的内容。点击下一步。

  • 勾选需要下载的内容。点击Finish,等待安装完成。我的环境已经安装过了Bluetooth sdk,因此这里没有这个选项。

2 环境设置

外观设置
Windows, Preferences, General, Appearance, Colors and Fonts设置自己喜欢的字体

设置SDK
Windows, Preferences, Simplicity Studio, SDKs

3 参考手册

在一切就绪之后,发现在主界面还是什么都没有。

这里需要先建一个product,选择一个板子和芯片。我这里以Thunderboard EFR32BG22(SLTB010A)为例。



添加完板子之后,就可以在主界面看到大量的文档和demo了。做为刚接触silicon平台的开发者来说从QSG139: Bluetooth® SDK v2.x Quick Start Guide这个文档入手是个不错的选择。

二 新建工程

  • 点击 New Project,选择Bluetooth SDK
  • 选择一个工程做为模板,官方建议选择SOC - Empty做为模板。
  • 设置工程名字,选择工程存放目录。
  • 使用GNU ARM 编译链。点击finish等待工程创建完成即可。

    这个平台对开发者其实是很友好的,工程创建完之后,平台已经为我们做了大量的工作,用户只需要关心自己的业务逻辑部分即可。

三 目录结构

工程的文件结构如下图所示:

  1. app
    主要定义一些基础的宏定义,比如MAX和MIN
  2. hardware
    关于硬件的一些设置和宏定义。
  3. platform
    平台的主要功能。提供一些库、硬件驱动等。
  4. protocol
    这里主要是指BLE协议。
  5. soc-empty_2.isc
    蓝牙配置文件。silicon平台使用该文件来对蓝牙进行可视化的配置,降低了开发的难度。
  6. gatt.xml/gatt_db.c/gatt_db.h
    该文件是根据soc-empty_2.isc自动生成的。
  7. efr32bg22c224f512im40.ld
    整个工程的链接指导文件,设置Flash和RAM的起始地址及大小,设置堆栈大小等。

四 代码架构

1 添加自定义服务

工程创建完成之后,平台默认给我们添加了3个服务

  • GeneGeneric Access
  • Device Information
  • Silicon Labs OTA

    下面我们来添加一个串口透传服务。
  1. 选中 Custom BLE GATT,点击右边新建按钮,new server

    这里我们可以修改该服务的Name以及UUID,并将Advertise Service勾选上表示在广播的时候将该服务广播出去。

  2. 给服务添加TX特征
    选中服务uart,点击右边的新建按钮,选择 new characteristic

  • Name 设置该特征的名字,可自定义

  • UUID 设置该特征的UUID,可自定义

  • Value Type 该设置决定了可以向特征写入什么类型的数据,这里选择utf-8

  • Length 可以向TX写入的最长数据

  • 设置特征的权限,这里的权限指的是用户可以对这个特征进行的操作。

    我们这里给TX特性添加一个Notify的权限,表示当前设备会主动的向用户端发送数据。根据蓝牙核心卷的规定,具有Notify权限必须要添加一个描述(Descriptors): Client Characteristic Configuration, 该描述是方便用户是否决定接收设备主动发来的数据。

    Client Characteristic Configuration可以直接从左侧的Descriptors栏里面直接拖拽到TX下面,给这个Descriptors添加Read和Write权限,参数选择默认即可。

  1. 给服务添加RX特性

添加RX特性的过程和TX一样,这里给RX的权限有 Write 和 Write without Response

一切就绪之后,点击Generate自动生成配置文件。


编译通过之后会在 \GNU ARM v7.2.1 - Default 目录下生成可执行文件。烧录到板子之后,使用EFR Connect连接,可以看到我们刚才设置的效果。

2 代码分析

main.c

static gecko_configuration_t config = {.config_flags = 0,                                   /* Check flag options from UG136 */
#if defined(FEATURE_LFXO) || defined(PLFRCO_PRESENT).sleep.flags = SLEEP_FLAGS_DEEP_SLEEP_ENABLE,        /* Sleep is enabled */
#else.sleep.flags = 0,
#endif.bluetooth.max_connections = MAX_CONNECTIONS,        /* Maximum number of simultaneous connections */.bluetooth.max_advertisers = MAX_ADVERTISERS,        /* Maximum number of advertisement sets */.bluetooth.heap = bluetooth_stack_heap,              /* Bluetooth stack memory for connection management */.bluetooth.heap_size = sizeof(bluetooth_stack_heap), /* Bluetooth stack memory for connection management */
#if defined(FEATURE_LFXO).bluetooth.sleep_clock_accuracy = 100,               /* Accuracy of the Low Frequency Crystal Oscillator in ppm. ** Do not modify if you are using a module                  */
#elif defined(PLFRCO_PRESENT).bluetooth.sleep_clock_accuracy = 500,               /* In case of internal RCO the sleep clock accuracy is 500 ppm */
#endif.gattdb = &bg_gattdb_data,                           /* Pointer to GATT database */.ota.flags = 0,                                      /* Check flag options from UG136 */.ota.device_name_len = 3,                            /* Length of the device name in OTA DFU mode */.ota.device_name_ptr = "OTA",                        /* Device name in OTA DFU mode */.ota.antenna_defined = APP_RF_CONFIG_ANTENNA,.ota.antenna = APP_RF_ANTENNA,.pa.config_enable = 1,                               /* Set this to be a valid PA config */
#if defined(FEATURE_PA_INPUT_FROM_VBAT).pa.input = GECKO_RADIO_PA_INPUT_VBAT,               /* Configure PA input to VBAT */
#else.pa.input = GECKO_RADIO_PA_INPUT_DCDC,               /* Configure PA input to DCDC */
#endif // defined(FEATURE_PA_INPUT_FROM_VBAT).rf.flags = APP_RF_CONFIG_ANTENNA,                 /* Enable antenna configuration. */.rf.antenna = APP_RF_ANTENNA,                      /* Select antenna path! */
};

config 是整个系统的主要配置文件,生成的代码只是部分配置,如果需要其它设置可以参考相关的文档说明。
比如我们在软件里面需要开启软件定时器,只需要添加max_timers 字段。

int main(void)
{/* 初始化MCU,设置MCU时钟频率,设置用到的其它模块的时钟频率 */initMcu();/* 初始化跟板子相关的一些外设 */initBoard();/* Initialize application */initApp();initVcomEnable();/* 可以在这里添加用户自定义的初始化代码 *///....../* 主要逻辑在这里*/appMain(&config);
}

app.h

//RX和TX的值,需要根据gatt_db.c来进行修改
#define RX_ATTRIBUTE    (0x000b)
#define TX_ATTRIBUTE    (0x000d)

app.c

#define MAX_BLE_DATA_LEN    21
#define REPLY_LEN   MAX_BLE_DATA_LEN
uint8_t reply[21];
char* test_replay = "abcd123";
/* 主循环 */
void appMain(gecko_configuration_t *pconfig)
{#if DISABLE_SLEEP > 0pconfig->sleep.flags = 0;
#endif/* Initialize debug prints. Note: debug prints are off by default. See DEBUG_LEVEL in app.h */initLog();/* 根据 main.c 中的config 文件来初始化协议栈,当初始化完成之后会生成一个gecko_evt_system_boot_id事件在该事件产生之前不能对蓝牙做其他操作 */gecko_init(pconfig);while (1) {/* Event pointer for handling events */struct gecko_cmd_packet* evt;/* if there are no events pending then the next call to gecko_wait_event() may cause* device go to deep sleep. Make sure that debug prints are flushed before going to sleep */if (!gecko_event_pending()) {flushLog();}/* 等待一个事件,这个函数会阻塞调用。 详细说明参考文档 UG136. */evt = gecko_wait_event();/* Handle events */switch (BGLIB_MSG_ID(evt->header)) {/* This boot event is generated when the system boots up after reset.* Do not call any stack commands before receiving the boot event.* Here the system is set to start advertising immediately after boot procedure. */case gecko_evt_system_boot_id:bootMessage(&(evt->data.evt_system_boot));printLog("boot event - starting advertising\r\n");/* Set advertising parameters. 100ms advertisement interval.* The first parameter is advertising set handle* The next two parameters are minimum and maximum advertising interval, both in* units of (milliseconds * 1.6).* The last two parameters are duration and maxevents left as default. */gecko_cmd_le_gap_set_advertise_timing(0, 160, 160, 0, 0);/* 开始广播 */gecko_cmd_le_gap_start_advertising(0, le_gap_general_discoverable, le_gap_connectable_scannable);break;case gecko_evt_le_connection_opened_id:printLog("connection opened\r\n");break;case gecko_evt_le_connection_closed_id:printLog("connection closed, reason: 0x%2.2x\r\n", evt->data.evt_le_connection_closed.reason);/* 如果OTA标志被设置,则重启系统,并标记OTA类型*/if (boot_to_dfu) {/* 传入的值为2表示通过蓝牙进行空中升级 */gecko_cmd_system_reset(2);} else {/* Restart advertising after client has disconnected */gecko_cmd_le_gap_start_advertising(0, le_gap_general_discoverable, le_gap_connectable_scannable);}break;/* Events related to OTA upgrading----------------------------------------------------------------------------- *//* Check if the user-type OTA Control Characteristic was written.* If ota_control was written, boot the device into Device Firmware Upgrade (DFU) mode. */case gecko_evt_gatt_server_user_write_request_id://收到OTA命令if (evt->data.evt_gatt_server_user_write_request.characteristic == gattdb_ota_control) {/* 设置OTA标志*/boot_to_dfu = 1;/* 回复用户 */gecko_cmd_gatt_server_send_user_write_response(evt->data.evt_gatt_server_user_write_request.connection,gattdb_ota_control,bg_err_success);/* 断开连接准备进入OTA模式 */gecko_cmd_le_connection_close(evt->data.evt_gatt_server_user_write_request.connection);}break;/* 根据应用的需要添加其他的事件,该平台所支持的事件都可以在 native_gecko.h 中找到 */case gecko_evt_gatt_server_attribute_value_id:{struct gecko_msg_gatt_server_attribute_value_evt_t* att = &evt->data.evt_gatt_server_attribute_value;//当Rx收到数据之后,这里默认回复一个abcd123if(att->attribute == RX_ATTRIBUTE){uint8 connection = att->connection;gecko_cmd_gatt_server_send_characteristic_notification(connection, TX_ATTRIBUTE, strlen(test_replay), test_replay);}}break;default:break;}}
}

3 空中升级

空中升级对于开发者,可以说是非常的友好。
详细的信息可以参看文档:ug266-gecko-bootloader-user-guide.pdf 和 an1086-gecko-bootloader-bluetooth.pdf
这些文档在silicon的官网都可以搜到。

3.1 制作升级文件

当应用程序编译完成之后,只要执行根目录下的create_bl_files.bat批处理文件,平台就会自动帮我们生成可用来升级的.gbl文件。
第一次使用该文件的时候需要添加两个用户变量:


在执行该批处理的时候可能会遇到这样的问题:

应该是当前系统要求命令路径不能带空格,因此修改这个批处理文件中的命令,PATH_SCMD 和 OBJCOPY都加上双引号即可。
比如将

%OBJCOPY% -O srec -j .text_apploader* "%PATH_OUT%" "%PATH_GBL%\%OTA_APPLO_NAME%.srec"

修改成

"%OBJCOPY%" -O srec -j .text_apploader* "%PATH_OUT%" "%PATH_GBL%\%OTA_APPLO_NAME%.srec"

执行成功之后会在根目录下生成一个 output_gbl 文件夹里面有升级需要的gbl文件。

我们这里选择application.gbl,不带crc,只更新应用部分。

3.2 flash分布


在0地址处存放的是Gecko BootLoader,这部分代码需要另外一个工程进行生成。
silicon把appLoader以可执行文件的形式提供给用户,当我们的app编译完成之后appLoader会被自动的添加到我们的bin文件中。
因此我们生成的bin文件包含appLoader、协议栈、应用。

3.3 空中升级过程

#mermaid-svg-dxpeXWAcXroAKatz .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-dxpeXWAcXroAKatz .label text{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz .node rect,#mermaid-svg-dxpeXWAcXroAKatz .node circle,#mermaid-svg-dxpeXWAcXroAKatz .node ellipse,#mermaid-svg-dxpeXWAcXroAKatz .node polygon,#mermaid-svg-dxpeXWAcXroAKatz .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-dxpeXWAcXroAKatz .node .label{text-align:center;fill:#333}#mermaid-svg-dxpeXWAcXroAKatz .node.clickable{cursor:pointer}#mermaid-svg-dxpeXWAcXroAKatz .arrowheadPath{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-dxpeXWAcXroAKatz .flowchart-link{stroke:#333;fill:none}#mermaid-svg-dxpeXWAcXroAKatz .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-dxpeXWAcXroAKatz .edgeLabel rect{opacity:0.9}#mermaid-svg-dxpeXWAcXroAKatz .edgeLabel span{color:#333}#mermaid-svg-dxpeXWAcXroAKatz .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-dxpeXWAcXroAKatz .cluster text{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-dxpeXWAcXroAKatz .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-dxpeXWAcXroAKatz text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-dxpeXWAcXroAKatz .actor-line{stroke:grey}#mermaid-svg-dxpeXWAcXroAKatz .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-dxpeXWAcXroAKatz .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-dxpeXWAcXroAKatz #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-dxpeXWAcXroAKatz .sequenceNumber{fill:#fff}#mermaid-svg-dxpeXWAcXroAKatz #sequencenumber{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz #crosshead path{fill:#333;stroke:#333}#mermaid-svg-dxpeXWAcXroAKatz .messageText{fill:#333;stroke:#333}#mermaid-svg-dxpeXWAcXroAKatz .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-dxpeXWAcXroAKatz .labelText,#mermaid-svg-dxpeXWAcXroAKatz .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-dxpeXWAcXroAKatz .loopText,#mermaid-svg-dxpeXWAcXroAKatz .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-dxpeXWAcXroAKatz .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-dxpeXWAcXroAKatz .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-dxpeXWAcXroAKatz .noteText,#mermaid-svg-dxpeXWAcXroAKatz .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-dxpeXWAcXroAKatz .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-dxpeXWAcXroAKatz .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-dxpeXWAcXroAKatz .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-dxpeXWAcXroAKatz .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz .section{stroke:none;opacity:0.2}#mermaid-svg-dxpeXWAcXroAKatz .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-dxpeXWAcXroAKatz .section2{fill:#fff400}#mermaid-svg-dxpeXWAcXroAKatz .section1,#mermaid-svg-dxpeXWAcXroAKatz .section3{fill:#fff;opacity:0.2}#mermaid-svg-dxpeXWAcXroAKatz .sectionTitle0{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz .sectionTitle1{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz .sectionTitle2{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz .sectionTitle3{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-dxpeXWAcXroAKatz .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz .grid path{stroke-width:0}#mermaid-svg-dxpeXWAcXroAKatz .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-dxpeXWAcXroAKatz .task{stroke-width:2}#mermaid-svg-dxpeXWAcXroAKatz .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz .taskText:not([font-size]){font-size:11px}#mermaid-svg-dxpeXWAcXroAKatz .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-dxpeXWAcXroAKatz .task.clickable{cursor:pointer}#mermaid-svg-dxpeXWAcXroAKatz .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-dxpeXWAcXroAKatz .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-dxpeXWAcXroAKatz .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-dxpeXWAcXroAKatz .taskText0,#mermaid-svg-dxpeXWAcXroAKatz .taskText1,#mermaid-svg-dxpeXWAcXroAKatz .taskText2,#mermaid-svg-dxpeXWAcXroAKatz .taskText3{fill:#fff}#mermaid-svg-dxpeXWAcXroAKatz .task0,#mermaid-svg-dxpeXWAcXroAKatz .task1,#mermaid-svg-dxpeXWAcXroAKatz .task2,#mermaid-svg-dxpeXWAcXroAKatz .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-dxpeXWAcXroAKatz .taskTextOutside0,#mermaid-svg-dxpeXWAcXroAKatz .taskTextOutside2{fill:#000}#mermaid-svg-dxpeXWAcXroAKatz .taskTextOutside1,#mermaid-svg-dxpeXWAcXroAKatz .taskTextOutside3{fill:#000}#mermaid-svg-dxpeXWAcXroAKatz .active0,#mermaid-svg-dxpeXWAcXroAKatz .active1,#mermaid-svg-dxpeXWAcXroAKatz .active2,#mermaid-svg-dxpeXWAcXroAKatz .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-dxpeXWAcXroAKatz .activeText0,#mermaid-svg-dxpeXWAcXroAKatz .activeText1,#mermaid-svg-dxpeXWAcXroAKatz .activeText2,#mermaid-svg-dxpeXWAcXroAKatz .activeText3{fill:#000 !important}#mermaid-svg-dxpeXWAcXroAKatz .done0,#mermaid-svg-dxpeXWAcXroAKatz .done1,#mermaid-svg-dxpeXWAcXroAKatz .done2,#mermaid-svg-dxpeXWAcXroAKatz .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-dxpeXWAcXroAKatz .doneText0,#mermaid-svg-dxpeXWAcXroAKatz .doneText1,#mermaid-svg-dxpeXWAcXroAKatz .doneText2,#mermaid-svg-dxpeXWAcXroAKatz .doneText3{fill:#000 !important}#mermaid-svg-dxpeXWAcXroAKatz .crit0,#mermaid-svg-dxpeXWAcXroAKatz .crit1,#mermaid-svg-dxpeXWAcXroAKatz .crit2,#mermaid-svg-dxpeXWAcXroAKatz .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-dxpeXWAcXroAKatz .activeCrit0,#mermaid-svg-dxpeXWAcXroAKatz .activeCrit1,#mermaid-svg-dxpeXWAcXroAKatz .activeCrit2,#mermaid-svg-dxpeXWAcXroAKatz .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-dxpeXWAcXroAKatz .doneCrit0,#mermaid-svg-dxpeXWAcXroAKatz .doneCrit1,#mermaid-svg-dxpeXWAcXroAKatz .doneCrit2,#mermaid-svg-dxpeXWAcXroAKatz .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-dxpeXWAcXroAKatz .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-dxpeXWAcXroAKatz .milestoneText{font-style:italic}#mermaid-svg-dxpeXWAcXroAKatz .doneCritText0,#mermaid-svg-dxpeXWAcXroAKatz .doneCritText1,#mermaid-svg-dxpeXWAcXroAKatz .doneCritText2,#mermaid-svg-dxpeXWAcXroAKatz .doneCritText3{fill:#000 !important}#mermaid-svg-dxpeXWAcXroAKatz .activeCritText0,#mermaid-svg-dxpeXWAcXroAKatz .activeCritText1,#mermaid-svg-dxpeXWAcXroAKatz .activeCritText2,#mermaid-svg-dxpeXWAcXroAKatz .activeCritText3{fill:#000 !important}#mermaid-svg-dxpeXWAcXroAKatz .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-dxpeXWAcXroAKatz g.classGroup text .title{font-weight:bolder}#mermaid-svg-dxpeXWAcXroAKatz g.clickable{cursor:pointer}#mermaid-svg-dxpeXWAcXroAKatz g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-dxpeXWAcXroAKatz g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-dxpeXWAcXroAKatz .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-dxpeXWAcXroAKatz .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-dxpeXWAcXroAKatz .dashed-line{stroke-dasharray:3}#mermaid-svg-dxpeXWAcXroAKatz #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz .commit-id,#mermaid-svg-dxpeXWAcXroAKatz .commit-msg,#mermaid-svg-dxpeXWAcXroAKatz .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-dxpeXWAcXroAKatz g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-dxpeXWAcXroAKatz g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-dxpeXWAcXroAKatz g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-dxpeXWAcXroAKatz .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-dxpeXWAcXroAKatz .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-dxpeXWAcXroAKatz .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-dxpeXWAcXroAKatz .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-dxpeXWAcXroAKatz .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-dxpeXWAcXroAKatz .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-dxpeXWAcXroAKatz .edgeLabel text{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-dxpeXWAcXroAKatz .node circle.state-start{fill:black;stroke:black}#mermaid-svg-dxpeXWAcXroAKatz .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-dxpeXWAcXroAKatz #statediagram-barbEnd{fill:#9370db}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-state .divider{stroke:#9370db}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-dxpeXWAcXroAKatz .note-edge{stroke-dasharray:5}#mermaid-svg-dxpeXWAcXroAKatz .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-dxpeXWAcXroAKatz .error-icon{fill:#522}#mermaid-svg-dxpeXWAcXroAKatz .error-text{fill:#522;stroke:#522}#mermaid-svg-dxpeXWAcXroAKatz .edge-thickness-normal{stroke-width:2px}#mermaid-svg-dxpeXWAcXroAKatz .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-dxpeXWAcXroAKatz .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-dxpeXWAcXroAKatz .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-dxpeXWAcXroAKatz .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-dxpeXWAcXroAKatz .marker{fill:#333}#mermaid-svg-dxpeXWAcXroAKatz .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-dxpeXWAcXroAKatz {color: rgba(0, 0, 0, 0.75);font: ;}userappGecko BootappLoaderOTA Cmdreply user1. 断开连接2. 设置OTA标志3. 重启系统重启系统之后进入Gecko Boot检测到OTA被设置,进入appLoader将新的固件gbl文件发送给appLoader,appLoader覆盖原来的app空间固件包.......固件包烧录完成之后,清空OTA标志,重启系统未检测到OTA标志,进入appuserappGecko BootappLoader
  1. app收到OTA指令之后,断开当前连接并调用gecko_cmd_system_reset(2); 设置OTA标志并重启系统。
  2. Gecko Boot检测到OTA标志,进入appLoader。进入appLoader之后开始通过蓝牙接收用户发送过来的新固件。
  3. appLoader将收到的新固件直接覆盖原来的app区域。
  4. 升级完之后,appLoader清除OTA标志并重启系统。
  5. Gecko Boot没有检测到OTA标志,则进入app开始执行。

可以使用EFR Connect进行升级。

文中的demo和apk下载地址

Silicon EFR32BG22低功耗蓝牙开发入门篇相关推荐

  1. 低功耗蓝牙开发入门概念科普

    一.概述 1.缘起 低功耗蓝牙起源于Bluetooth4.0版本,至今已发展到5.3 4.0 bluetooth low enerngy 这个阶段低功耗蓝牙的基础框架已经稳定成型,后面版本主要退出新特 ...

  2. 安卓基于BLE的蓝牙开发入门

    BLE蓝牙开发简单入门 BLE背景介绍 引言 BLE简介 Gatt协议以及必备知识 蓝牙开发涉及的API介绍 BLE实战准备 真机调试 权限准备 写两个简单的页面 扫描设备主界面 扫描设备信息界面 实 ...

  3. ble 低功耗蓝牙开发学习 嵌入式交流学习

    ble 低功耗蓝牙开发学习 嵌入式交流学习 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 这篇文章教你学会低功耗蓝牙开发,从0到深入,适合自学的学生.初级工程师 前言 随着疫情爆发 ...

  4. 安卓模拟ibeacon_【首发】联接真实与虚拟世界:Estimote Beacons Developer Kit 低功耗蓝牙开发套件...

    [首发]联接真实与虚拟世界:Estimote Beacons Developer Kit 低功耗蓝牙开发套件 2014-03-24 11:18:43 58点赞 229收藏 105评论 小编注:此篇文章 ...

  5. Android 低功耗蓝牙开发(数据交互)

    Android 低功耗蓝牙开发(数据交互) 前言 正文 一.BluetoothGattCallback 1. onPhyUpdate 2. onPhyRead 3. onServicesDiscove ...

  6. Android 8.0 BLE 低功耗蓝牙开发记录

    Android 8.0 BLE 低功耗蓝牙开发记录(1-3)--------------(权限申请篇未完待续) 目的:开源博客,希望大家一起修改博客错误地方,共同完善并会鸣谢提供意见的朋友.为大家提供 ...

  7. Android 蓝牙开发(三) -- 低功耗蓝牙开发

    Android 蓝牙开发(一) – 传统蓝牙聊天室 Android 蓝牙开发(三) – 低功耗蓝牙开发 项目工程BluetoothDemo 前面已经学习了经典蓝牙开发,学习了蓝牙的配对连接和通信,又通 ...

  8. 《低功耗蓝牙开发权威指南》——第2章基本概念

    本节书摘来自华章社区<低功耗蓝牙开发权威指南>一书中的第2章基本概念,作者 (英)Robin Heydon,更多章节内容可以访问云栖社区"华章社区"公众号查看 第2章 ...

  9. 《低功耗蓝牙开发权威指南》——第3章低功耗蓝牙的体系结构

    本节书摘来自华章社区<低功耗蓝牙开发权威指南>一书中的第3章低功耗蓝牙的体系结构,作者 (英)Robin Heydon,更多章节内容可以访问云栖社区"华章社区"公众号查 ...

最新文章

  1. android 权限自动授权,Android判断是否某个权限是否授权
  2. Spring Cloud 参考文档(Spring Cloud Context:应用程序上下文服务)
  3. Bootstrap 模态框插件Modal 的事件
  4. 深入浅出Shell编程: Shell 变量【ZT】
  5. Hibernate初始化创建SessionFactory,Session,关闭SessonFactory,session
  6. Resources$NotFoundException
  7. MySQL的存储过程优缺点
  8. 【机器人】关于驱动器与控制器的工作机制
  9. C++ std::lock_guard 自动加锁、释放锁 原理
  10. 关于一个正弦波程序表格生成器
  11. 关键路径算法——AOE网
  12. [阿里云] 域名解析设置
  13. java和Js中的类型转换_graalvm js 与java 类型转换的一些方法
  14. vue实现结算淘宝购物车效果
  15. 走马灯如何实现图片自适应
  16. 《程序员2013精华本》
  17. ###岁月静好###
  18. AI 模型社区“魔搭”亮相,平头哥又上新,端云一体生态再升级
  19. thinkphp5 ajax分页
  20. 【深度优先遍历】经典岛屿问题汇总

热门文章

  1. 怀孕后可使用计算机吗,怀孕可以用电脑工作吗?使用须适当
  2. 计算机开关键是什么符号,按钮开关符号知识大盘点 【图文】
  3. leJOS EV3 Eclipse Mac 总结
  4. 计算机关系差 并 交,计算机三个关系投影 交 并 差是什么意思
  5. 裁判文书网爬虫Docid解密思路
  6. [poj3889]Fractal Streets
  7. 计算机教师格言座右铭,教师教育格言座右铭
  8. cgb2109-day02
  9. Java回炉学习(七)
  10. Selenium库实现推特爬虫