Silicon EFR32BG22低功耗蓝牙开发入门篇

一 环境搭建

开发环境使用官方提供的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 > 0
  pconfig->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收到数据之后,这里默认回复一个abcd123
			if(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 空中升级过程

在这里插入图片描述

user app Gecko Boot appLoader OTA Cmd reply user 1. 断开连接 2. 设置OTA标志 3. 重启系统 重启系统之后进入Gecko Boot 检测到OTA被设置,进入appLoader 将新的固件gbl文件发送给appLoader,appLoader覆盖原来的app空间 固件包 ....... 固件包 烧录完成之后,清空OTA标志,重启系统 未检测到OTA标志,进入app user app Gecko Boot appLoader
  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下载地址

  • 11
    点赞
  • 89
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值