一 环境搭建
开发环境使用官方提供的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等待工程创建完成即可。
这个平台对开发者其实是很友好的,工程创建完之后,平台已经为我们做了大量的工作,用户只需要关心自己的业务逻辑部分即可。
三 目录结构
工程的文件结构如下图所示:
- app
主要定义一些基础的宏定义,比如MAX和MIN
- hardware
关于硬件的一些设置和宏定义。
- platform
平台的主要功能。提供一些库、硬件驱动等。
- protocol
这里主要是指BLE协议。
- soc-empty_2.isc
蓝牙配置文件。silicon平台使用该文件来对蓝牙进行可视化的配置,降低了开发的难度。
- gatt.xml/gatt_db.c/gatt_db.h
该文件是根据soc-empty_2.isc自动生成的。
- efr32bg22c224f512im40.ld
整个工程的链接指导文件,设置Flash和RAM的起始地址及大小,设置堆栈大小等。
四 代码架构
1 添加自定义服务
工程创建完成之后,平台默认给我们添加了3个服务
- GeneGeneric Access
- Device Information
- Silicon Labs OTA
下面我们来添加一个串口透传服务。
选中 Custom BLE GATT,点击右边新建按钮,new server
这里我们可以修改该服务的Name以及UUID,并将Advertise Service勾选上表示在广播的时候将该服务广播出去。
给服务添加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权限,参数选择默认即可。
- 给服务添加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
- app收到OTA指令之后,断开当前连接并调用gecko_cmd_system_reset(2); 设置OTA标志并重启系统。
- Gecko Boot检测到OTA标志,进入appLoader。进入appLoader之后开始通过蓝牙接收用户发送过来的新固件。
- appLoader将收到的新固件直接覆盖原来的app区域。
- 升级完之后,appLoader清除OTA标志并重启系统。
- Gecko Boot没有检测到OTA标志,则进入app开始执行。
可以使用EFR Connect进行升级。
文中的demo和apk下载地址
Silicon EFR32BG22低功耗蓝牙开发入门篇相关推荐
- 低功耗蓝牙开发入门概念科普
一.概述 1.缘起 低功耗蓝牙起源于Bluetooth4.0版本,至今已发展到5.3 4.0 bluetooth low enerngy 这个阶段低功耗蓝牙的基础框架已经稳定成型,后面版本主要退出新特 ...
- 安卓基于BLE的蓝牙开发入门
BLE蓝牙开发简单入门 BLE背景介绍 引言 BLE简介 Gatt协议以及必备知识 蓝牙开发涉及的API介绍 BLE实战准备 真机调试 权限准备 写两个简单的页面 扫描设备主界面 扫描设备信息界面 实 ...
- ble 低功耗蓝牙开发学习 嵌入式交流学习
ble 低功耗蓝牙开发学习 嵌入式交流学习 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 这篇文章教你学会低功耗蓝牙开发,从0到深入,适合自学的学生.初级工程师 前言 随着疫情爆发 ...
- 安卓模拟ibeacon_【首发】联接真实与虚拟世界:Estimote Beacons Developer Kit 低功耗蓝牙开发套件...
[首发]联接真实与虚拟世界:Estimote Beacons Developer Kit 低功耗蓝牙开发套件 2014-03-24 11:18:43 58点赞 229收藏 105评论 小编注:此篇文章 ...
- Android 低功耗蓝牙开发(数据交互)
Android 低功耗蓝牙开发(数据交互) 前言 正文 一.BluetoothGattCallback 1. onPhyUpdate 2. onPhyRead 3. onServicesDiscove ...
- Android 8.0 BLE 低功耗蓝牙开发记录
Android 8.0 BLE 低功耗蓝牙开发记录(1-3)--------------(权限申请篇未完待续) 目的:开源博客,希望大家一起修改博客错误地方,共同完善并会鸣谢提供意见的朋友.为大家提供 ...
- Android 蓝牙开发(三) -- 低功耗蓝牙开发
Android 蓝牙开发(一) – 传统蓝牙聊天室 Android 蓝牙开发(三) – 低功耗蓝牙开发 项目工程BluetoothDemo 前面已经学习了经典蓝牙开发,学习了蓝牙的配对连接和通信,又通 ...
- 《低功耗蓝牙开发权威指南》——第2章基本概念
本节书摘来自华章社区<低功耗蓝牙开发权威指南>一书中的第2章基本概念,作者 (英)Robin Heydon,更多章节内容可以访问云栖社区"华章社区"公众号查看 第2章 ...
- 《低功耗蓝牙开发权威指南》——第3章低功耗蓝牙的体系结构
本节书摘来自华章社区<低功耗蓝牙开发权威指南>一书中的第3章低功耗蓝牙的体系结构,作者 (英)Robin Heydon,更多章节内容可以访问云栖社区"华章社区"公众号查 ...
最新文章
- android 权限自动授权,Android判断是否某个权限是否授权
- Spring Cloud 参考文档(Spring Cloud Context:应用程序上下文服务)
- Bootstrap 模态框插件Modal 的事件
- 深入浅出Shell编程: Shell 变量【ZT】
- Hibernate初始化创建SessionFactory,Session,关闭SessonFactory,session
- Resources$NotFoundException
- MySQL的存储过程优缺点
- 【机器人】关于驱动器与控制器的工作机制
- C++ std::lock_guard 自动加锁、释放锁 原理
- 关于一个正弦波程序表格生成器
- 关键路径算法——AOE网
- [阿里云] 域名解析设置
- java和Js中的类型转换_graalvm js 与java 类型转换的一些方法
- vue实现结算淘宝购物车效果
- 走马灯如何实现图片自适应
- 《程序员2013精华本》
- ###岁月静好###
- AI 模型社区“魔搭”亮相,平头哥又上新,端云一体生态再升级
- thinkphp5 ajax分页
- 【深度优先遍历】经典岛屿问题汇总
热门文章
- 怀孕后可使用计算机吗,怀孕可以用电脑工作吗?使用须适当
- 计算机开关键是什么符号,按钮开关符号知识大盘点 【图文】
- leJOS EV3 Eclipse Mac 总结
- 计算机关系差 并 交,计算机三个关系投影 交 并 差是什么意思
- 裁判文书网爬虫Docid解密思路
- [poj3889]Fractal Streets
- 计算机教师格言座右铭,教师教育格言座右铭
- cgb2109-day02
- Java回炉学习(七)
- Selenium库实现推特爬虫