3550|5

95

帖子

0

资源

一粒金砂(中级)

【沁恒CH582】蓝牙协议栈的结构分析 [复制链接]

蓝牙协议栈的结构

在CH583芯片中内置了一个低功耗蓝牙模块(BLE)虽然在上一节我们已经稀里糊涂使用过一次了,但是对于这个功能实现的细节没有更加深入的分析。本节,我将就芯片开源的部分和芯片中能够获取到的信息对芯片的BLE模块展开初步分析。

BLE部分

虽然没有言明(也可能是我没有找到重点),可以得知在芯片中实现的物理层是BLE5.0的硬件层。使用GFSK调制和2.4GHz的频道。

CH582M芯片的协议栈是不开源的,所以目前留给我们的突破口就仅有面向用户接口部分了。配置和应用程序的实现基于的协议是GAP和GATT。

GAP是通用访问协议,是BLE设备内部功能对外的配置接口,主要用于设置GAP的角色,工作模式,安全特性。主要负责蓝牙设备的广播、连接和设备绑定。

GAP角色 描述 对应配置文件
广播者 不可以直接连接的持续广播设备 Broadcaster role
观察者 可以扫描广播设备但是不能发起建立连接的设备 Observer role
从机 可以被连接的广播设备,可以在单个链路连接中作为从机 Peripheral role
主机 可以扫描广播设备并发起连接,在单个链路或多个链路中作为主机 Central role

接下来我们观察一下Peripheral程序中的main的实现。

在完成基础部分的初始化之后,系统调用函数CH57X_BLEInit()初始化BLE外设。这一段函数的实现,给出了具体的实现。

整个库中执行做的核心任务就是在初始化bleConfig_t结构体。下面给出了这个结构体的详细信息:

 /* BLE library config struct */
 typedef struct tag_ble_config
 {
     uint32_t MEMAddr;               // library memory start address
     uint16_t MEMLen;                // library memory size
     uint32_t SNVAddr;               // SNV flash start address,must be data-flash area or NULL(bonding information will not be saved)
     uint16_t SNVBlock;              // SNV flash block size ( default 512 )
     uint8_t SNVNum;                 // SNV flash block number ( default 1 )
     uint8_t BufMaxLen;              // The Controller supported the maximum length of the payload,Range 27-251,ATT_MTU = BufMaxLen-4 ( default 27 )
     uint8_t BufNumber;              // Maximum number of sent and received packages cached by the controller( default 5 )
                                     // Must be greater than the number of connections.
     uint8_t TxNumEvent;             // Maximum number of TX data in a connection event ( default 1 )
     uint8_t TxPower;                // Maximum transmit power level( default LL_TX_POWEER_0_DBM(0dBm) )
     uint8_t WakeUpTime;             // Wake up time value in one RTC count ( default 45 )
     uint8_t SelRTCClock;            // RTC clock select LSE,LSI(32768Hz or 32000Hz)( default:0 LSE,1: LSI(32000Hz),2:LSI(32768Hz))
                                     // bit7: select connect timer.0:RTC timer 1:system clock timer(must disable sleep)
     uint8_t RxNumEvent;             // Maximum number of RX data in a connection event ( default equal to BufNumber )
     uint8_t MacAddr[6];             // MAC address,little-endian( factory default )
     uint8_t ConnectNumber;          // Connect number,lower two bits are peripheral number,followed by central number
     uint8_t WindowWidening;         // Wait rf start window
     uint8_t WaitWindow;             // Wait event arrive window
     pfnSrandCB srandCB;             // Register a program that generate a random seed
     pfnSleepCB sleepCB;             // Register a program that set idle mode
     pfnTempSampleCB tsCB;           // Register a program that read the current temperature,determine whether calibration is need
     pfnLSECalibrationCB rcCB;       // Register a program that RC32K clock calibration
     pfnLibStatusErrorCB staCB;      // Register a program that library status callback
     pfnFlashReadCB readFlashCB;     // Register a program that read flash
     pfnFlashWriteCB writeFlashCB;   // Register a program that write flash
 } bleConfig_t; // Library initialization call BLE_LibInit function

其中最为用户需要关心的就是设备的MAC地址,在此处指定设备MAC地址之后将会将会绑定到BLE模块。并且之后调用BLE_LibInit()闭源函数执行蓝牙初始化。设备的固定MAC地址可以通过函数GetMACAddress()得到。这个MAC地址是烧录在芯片FLASH中的,可以通过FLASH直接读出。FLASH的读取函数也是闭源的,具体读出的细节并不重要。

但是深究整个结构体,我们可以推测到BLE将会在初始化过程中校对系统时间,这个信息在实时通信过程中是非常关键的。

接下来在HAL_Init()函数中注册了一个任务,并获取了其任务的ID。

 halTaskID = TMOS_ProcessEventRegister( HAL_ProcessEvent );

执行这个任务的主函数声明如下。这个函数的具体内容就是执行HAL层的各种消息响应。

 tmosEvents HAL_ProcessEvent( tmosTaskID task_id, tmosEvents events );

这一部分的内容我们下一节详细聊,我们先回到主线,观察BLE的初始化过程。

接下来执行的任务是初始化GAP协议的相关内容,系统根据不同的角色提供了针对不同BLE所处角色的GAP初始化函数。在Peripheral例程中使用的是作为从机角色的初始化函数GAPRole_PeripheralInit();。这个函数的具体实现随协议栈仍然是闭源的。

接下来到了初始化BLE的最关键部分,void Peripheral_Init()这个函数中给出了作为从机的BLE外设启动的全过程。接下来详细分析一下其中的步骤:

首先使用函数GAPRole_SetParameter()设定GAP模块的参数,完成GAP模块的功能。其中支持的功能包括如下的这些:

 #define GAPROLE_PROFILEROLE                     0x300  //!< Reading this parameter will return GAP Role type. Read Only. Size is uint8_t.
 #define GAPROLE_IRK                             0x301  //!< Identity Resolving Key. Read/Write. Size is uint8_t[KEYLEN]. Default is all 0, which means that the IRK will be randomly generated.
 #define GAPROLE_SRK                             0x302  //!< Signature Resolving Key. Read/Write. Size is uint8_t[KEYLEN]. Default is all 0, which means that the SRK will be randomly generated.
 #define GAPROLE_SIGNCOUNTER                     0x303  //!< Sign Counter. Read/Write. Size is uint32_t. Default is 0.
 #define GAPROLE_BD_ADDR                         0x304  //!< Device's Address. Read Only. Size is uint8_t[B_ADDR_LEN]. This item is read from the controller.
 #define GAPROLE_ADVERT_ENABLED                  0x305  //!< Enable/Disable Advertising. Read/Write. Size is uint8_t. Default is TRUE=Enabled.
 #define GAPROLE_ADVERT_DATA                     0x306  //!< Advertisement Data. Read/Write. Max size is B_MAX_ADV_EXT_LEN. Default to all 0.
 #define GAPROLE_SCAN_RSP_DATA                   0x307  //!< Scan Response Data. Read/Write. Max size is B_MAX_ADV_EXT_LEN. Defaults to all 0.
 #define GAPROLE_ADV_EVENT_TYPE                  0x308  //!< Advertisement Type. Read/Write. Size is uint8_t.  Default is GAP_ADTYPE_ADV_IND.
 #define GAPROLE_ADV_DIRECT_TYPE                 0x309  //!< Direct Advertisement Address Type. Read/Write. Size is uint8_t. Default is ADDRTYPE_PUBLIC.
 #define GAPROLE_ADV_DIRECT_ADDR                 0x30A  //!< Direct Advertisement Address. Read/Write. Size is uint8_t[B_ADDR_LEN]. Default is NULL.
 #define GAPROLE_ADV_CHANNEL_MAP                 0x30B  //!< Which channels to advertise on. Read/Write Size is uint8_t. Default is GAP_ADVCHAN_ALL
 #define GAPROLE_ADV_FILTER_POLICY               0x30C  //!< Filter Policy. Ignored when directed advertising is used. Read/Write. Size is uint8_t. Default is GAP_FILTER_POLICY_ALL.
 #define GAPROLE_STATE                           0x30D  //!< Reading this parameter will return GAP Peripheral Role State. Read Only. Size is uint8_t.
 #define GAPROLE_MAX_SCAN_RES                    0x30E  //!< Maximum number of discover scan results to receive. Default is 0 = unlimited.
 #define GAPROLE_MIN_CONN_INTERVAL               0x311  //!< Minimum Connection Interval to allow (n * 1.25ms).  Range: 7.5 msec to 4 seconds (0x0006 to 0x0C80). Read/Write. Size is uint16_t. Default is 7.5 milliseconds (0x0006).
 #define GAPROLE_MAX_CONN_INTERVAL               0x312  //!< Maximum Connection Interval to allow (n * 1.25ms).  Range: 7.5 msec to 4 seconds (0x0006 to 0x0C80). Read/Write. Size is uint16_t. Default is 4 seconds (0x0C80).
 // v5.x
 #define GAPROLE_PHY_TX_SUPPORTED                0x313  //!< The transmitter PHYs that the Host prefers the Controller to use.Default is GAP_PHY_BIT_ALL
 #define GAPROLE_PHY_RX_SUPPORTED                0x314  //!< The receiver PHYs that the Host prefers the Controller to use.Default is GAP_PHY_BIT_ALL
 #define GAPROLE_PERIODIC_ADVERT_DATA            0x315  //!< Periodic advertisement Data. Read/Write. Max size is B_MAX_ADV_PERIODIC_LEN. Default to all 0.
 #define GAPROLE_PERIODIC_ADVERT_ENABLED         0x316  //!< bit0:Enable/Disable Periodic Advertising. Read/Write. Size is uint8_t. Default is FALSE=Disable.

接下来要设置GAP GATT Server的参数,在标准库中仅仅给出了设置设备名的参数,这个设备名将会被广播以方便连接。另外支持设置的参数如下:

 #define GGS_DEVICE_NAME_ATT                     0   // RW  uint8_t[GAP_DEVICE_NAME_LEN]
 #define GGS_APPEARANCE_ATT                      1   // RW  uint16_t
 #define GGS_PERI_PRIVACY_FLAG_ATT               2   // RW  uint8_t
 #define GGS_RECONNCT_ADDR_ATT                   3   // RW  uint8_t[B_ADDR_LEN]
 #define GGS_PERI_CONN_PARAM_ATT                 4   // RW  sizeof(gapPeriConnectParams_t)
 #define GGS_PERI_PRIVACY_FLAG_PROPS             5   // RW  uint8_t
 #define GGS_W_PERMIT_DEVICE_NAME_ATT            6   // W   uint8_t
 #define GGS_W_PERMIT_APPEARANCE_ATT             7   // W   uint8_t
 #define GGS_W_PERMIT_PRIVACY_FLAG_ATT           8   // W   uint8_t
 #define GGS_CENT_ADDR_RES_ATT                   9   // RW  uint8_t

接下来是使用函数GAP_SetParamValue,设定GAP的时间相关参数,具体支持设定的参数包括:

 // GAP_PARAMETER_ID_DEFINES GAP Parameter IDs
 // Timers
 #define TGAP_GEN_DISC_ADV_MIN                   0   //!< Minimum time to remain advertising, when in Discoverable mode.Default 0-turns off the timeout. (n * 0.625 mSec).
 #define TGAP_LIM_ADV_TIMEOUT                    1   //!< Maximum time to remain advertising, when in Limited Discoverable mode.Default 180 seconds. (n * 1 seconds)
 #define TGAP_DISC_SCAN                          2   //!< Minimum time to perform scanning,Setting this parameter to 0 turns off the timeout.Default 10.24seconds. (n * 0.625 mSec)
 ​
 // when in General Discovery process
 #define TGAP_DISC_ADV_INT_MIN                   3   //!< Minimum advertising interval.Default 160. (n * 0.625 mSec)
 #define TGAP_DISC_ADV_INT_MAX                   4   //!< Maximum advertising interval.Default 160. (n * 0.625 mSec)
 #define TGAP_DISC_SCAN_INT                      5   //!< Scan interval used during Link Layer Scanning state.Default 16. (n * 0.625 mSec)
 #define TGAP_DISC_SCAN_WIND                     6   //!< Scan window used during Link Layer Scanning state.Default 16. (n * 0.625 mSec)
 ​
 // when in Connection Establishment process(1M PHY)
 #define TGAP_CONN_EST_INT_MIN                   7   //!< Minimum Link Layer connection interval.Default 80. (n * 1.25 mSec)
 #define TGAP_CONN_EST_INT_MAX                   8   //!< Maximum Link Layer connection interval.Default 80. (n * 1.25 mSec)
 #define TGAP_CONN_EST_SCAN_INT                  9   //!< Scan interval used during Link Layer Initiating state.Default 16. (n * 0.625 mSec)
 #define TGAP_CONN_EST_SCAN_WIND                 10  //!< Scan window used during Link Layer Initiating state.Default 16. (n * 0.625 mSec)
 #define TGAP_CONN_EST_HIGH_SCAN_INT             11  //!< Scan interval used during Link Layer Initiating state, high duty scan cycle scan parameters (n * 0.625 mSec)
 #define TGAP_CONN_EST_HIGH_SCAN_WIND            12  //!< Scan window used during Link Layer Initiating state, high duty scan cycle scan parameters (n * 0.625 mSec)
 #define TGAP_CONN_EST_SUPERV_TIMEOUT            13  //!< Link Layer connection supervision timeout.Default 2000. (n * 10 mSec)
 #define TGAP_CONN_EST_LATENCY                   14  //!< Link Layer connection slave latency.Default 0. (in number of connection events)
 #define TGAP_CONN_EST_MIN_CE_LEN                15  //!< Local informational parameter about minimum length of connection needed.Default 0. (n * 0.625 mSec)
 #define TGAP_CONN_EST_MAX_CE_LEN                16  //!< Local informational parameter about maximum length of connection needed.Default 0. (n * 0.625 mSec)
 ​
 // Proprietary
 #define TGAP_PRIVATE_ADDR_INT                   17  //!< Minimum Time Interval between private (resolvable) address changes.Default 15. (n * 1 minute)
 #define TGAP_SM_TIMEOUT                         18  //!< SM Message Timeout (milliseconds). Default 30 seconds.
 #define TGAP_SM_MIN_KEY_LEN                     19  //!< SM Minimum Key Length supported. Default 7.
 #define TGAP_SM_MAX_KEY_LEN                     20  //!< SM Maximum Key Length supported. Default 16.
 #define TGAP_FILTER_ADV_REPORTS                 21  //!< Filter duplicate advertising reports. Default TRUE.
 #define TGAP_SCAN_RSP_RSSI_MIN                  22  //!< Minimum RSSI required for scan responses to be reported to the app. Default -127.
 #define TGAP_REJECT_CONN_PARAMS                 23  //!< Whether or not to reject Connection Parameter Update Request received on Central device. Default FALSE.
 #define TGAP_AUTH_TASK_ID                       24  //!< Task ID override for Task Authentication control (for stack internal use only)
 ​
 // v5.x
 #define TGAP_ADV_TX_POWER                       25  //!< Indicates the maximum power level Range: -127 ≤ N ≤ +126 Units: dBm.Default 127(Host has no preference).
 #define TGAP_ADV_PRIMARY_PHY                    26  //!< Indicates the PHY on which the advertising packets are transmitted on the primary advertising channel.LE 1M/LE Coded.Default GAP_PHY_VAL_LE_1M.
 #define TGAP_ADV_SECONDARY_PHY                  27  //!< LE 1M/LE 2M/LE Coded. Default GAP_PHY_VAL_LE_1M.
 #define TGAP_ADV_SECONDARY_MAX_SKIP             28  //!< Maximum advertising events the Controller can skip before sending the AUX_ADV_IND packets on the secondary advertising channel. Default 0.
 #define TGAP_ADV_ADVERTISING_SID                29  //!< Value of the Advertising SID subfield in the ADI field of the PDU Range:0-15. Default 0.
 #define TGAP_ADV_SCAN_REQ_NOTIFY                30  //!< Scan request notifications enabled.Default 0-disabled.
 #define TGAP_ADV_ADVERTISING_DURATION           31  //!< Advertising duration Range: 0x0001 – 0xFFFF Time = N * 10 ms. Default 0-No advertising duration.
 #define TGAP_ADV_MAX_EVENTS                     32  //!< indicates the maximum number of extended advertising events. Default 0.
 ​
 // when in General Discovery process
 #define TGAP_DISC_SCAN_PHY                      33  //!< LE 1M/LE Coded. Default GAP_PHY_BIT_LE_1M.
 #define TGAP_DISC_SCAN_CODED_INT                34  //!< Scan interval used during Link Layer coded Scanning state, when in General Discovery process (n * 0.625 mSec)
 #define TGAP_DISC_SCAN_CODED_WIND               35  //!< Scan window used during Link Layer coded Scanning state, when in General Discovery process (n * 0.625 mSec)
 #define TGAP_DISC_SCAN_DURATION                 36  //!< Scan duration Range: 0x0001 – 0xFFFF Time = N * 10 ms. Default 0-Scan continuously until explicitly disable.
 #define TGAP_DISC_SCAN_PERIOD                   37  //!< Time interval from when the Controller started its last Scan_Duration until it begins the subsequent Scan_Duration.
                                                     //!< Default 0 Periodic scanning disabled.
 ​
 // when in Connection Establishment process(2M PHY)
 #define TGAP_CONN_EST_INT_PHY                   38  //!< LE 1M/LE Coded. Default GAP_PHY_BIT_LE_1M.
 #define TGAP_CONN_EST_2M_INT_MIN                39  //!< Minimum Link Layer connection interval.Default 80. (n * 1.25 mSec)
 #define TGAP_CONN_EST_2M_INT_MAX                40  //!< Maximum Link Layer connection interval.Default 80. (n * 1.25 mSec)
 #define TGAP_CONN_EST_2M_SUPERV_TIMEOUT         41  //!< Link Layer connection supervision timeout.Default 2000. (n * 10 mSec)
 #define TGAP_CONN_EST_2M_LATENCY                42  //!< Link Layer connection slave latency.Default 0. (in number of connection events)
 #define TGAP_CONN_EST_2M_MIN_CE_LEN             43  //!< Local informational parameter about minimum length of connection needed.Default 0. (n * 0.625 mSec)
 #define TGAP_CONN_EST_2M_MAX_CE_LEN             44  //!< Local informational parameter about maximum length of connection needed.Default 0. (n * 0.625 mSec)
 ​
 // when in Connection Establishment process(Coded PHY)
 #define TGAP_CONN_EST_CODED_INT_MIN             45  //!< Minimum Link Layer connection interval.Default 80. (n * 1.25 mSec)
 #define TGAP_CONN_EST_CODED_INT_MAX             46  //!< Maximum Link Layer connection interval.Default 80. (n * 1.25 mSec)
 #define TGAP_CONN_EST_CODED_SCAN_INT            47  //!< Scan interval used during Link Layer Initiating state.Default 16. (n * 0.625 mSec)
 #define TGAP_CONN_EST_CODED_SCAN_WIND           48  //!< Scan window used during Link Layer Initiating state.Default 16. (n * 0.625 mSec)
 #define TGAP_CONN_EST_CODED_HIGH_SCAN_INT       49  //!< Scan interval used during Link Layer Initiating state, high duty scan cycle scan parameters (n * 0.625 mSec)
 #define TGAP_CONN_EST_CODED_HIGH_SCAN_WIND      50  //!< Scan window used during Link Layer Initiating state, high duty scan cycle scan parameters (n * 0.625 mSec)
 #define TGAP_CONN_EST_CODED_SUPERV_TIMEOUT      51  //!< Link Layer connection supervision timeout.Default 2000. (n * 10 mSec)
 #define TGAP_CONN_EST_CODED_LATENCY             52  //!< Link Layer connection slave latency.Default 0. (in number of connection events)
 #define TGAP_CONN_EST_CODED_MIN_CE_LEN          53  //!< Local informational parameter about minimum length of connection needed.Default 0. (n * 0.625 mSec)
 #define TGAP_CONN_EST_CODED_MAX_CE_LEN          54  //!< Local informational parameter about maximum length of connection needed.Default 0. (n * 0.625 mSec)
 ​
 // periodic advertising
 #define TGAP_PERIODIC_ADV_INT_MIN               55  //!< Minimum periodic advertising interval.Range: 0x0006 to 0xFFFF.Default 160. (n * 1.25 mSec)
 #define TGAP_PERIODIC_ADV_INT_MAX               56  //!< Maximum periodic advertising interval.Range: 0x0006 to 0xFFFF.Default 160. (n * 1.25 mSec)
 #define TGAP_PERIODIC_ADV_PROPERTIES            57  //!< Include TxPower in the periodic advertising PDU.
 ​
 #define TGAP_PARAMID_MAX                        58  //!< ID MAX-valid Parameter ID

之后使用GAPBondMgr_SetParameter设置连接关系,用于描述来凝结相关的信息。

 // GAPBOND_PROFILE_PARAMETERS GAP Bond Manager Parameters
 #define GAPBOND_PERI_PAIRING_MODE               0x400  //!< Pairing Mode: @ref GAPBOND_PAIRING_MODE_DEFINES. Read/Write. Size is uint8_t. Default is GAPBOND_PAIRING_MODE_WAIT_FOR_REQ.
 #define GAPBOND_PERI_MITM_PROTECTION            0x401  //!< Man-In-The-Middle (MITM) basically turns on Passkey protection in the pairing algorithm. Read/Write. Size is uint8_t. Default is 0(disabled).
 #define GAPBOND_PERI_IO_CAPABILITIES            0x402  //!< I/O capabilities.  Read/Write. Size is uint8_t. Default is GAPBOND_IO_CAP_DISPLAY_ONLY @ref GAPBOND_IO_CAP_DEFINES.
 #define GAPBOND_PERI_OOB_ENABLED                0x403  //!< OOB data available for pairing algorithm. Read/Write. Size is uint8_t. Default is 0(disabled).
 #define GAPBOND_PERI_OOB_DATA                   0x404  //!< OOB Data. Read/Write. size uint8_t[16]. Default is all 0's.
 #define GAPBOND_PERI_BONDING_ENABLED            0x405  //!< Request Bonding during the pairing process if enabled.  Read/Write. Size is uint8_t. Default is 0(disabled).
 #define GAPBOND_PERI_KEY_DIST_LIST              0x406  //!< The key distribution list for bonding.  size is uint8_t.  @ref GAPBOND_KEY_DIST_DEFINES. Default is sEncKey, sIdKey, mIdKey, mSign enabled.
 #define GAPBOND_PERI_DEFAULT_PASSCODE           0x407  //!< The default passcode for MITM protection. size is uint32_t. Range is 0 - 999,999. Default is 0.
 #define GAPBOND_CENT_PAIRING_MODE               0x408  //!< Pairing Mode: @ref  GAPBOND_PAIRING_MODE_DEFINES. Read/Write. Size is uint8_t. Default is GAPBOND_PAIRING_MODE_WAIT_FOR_REQ.
 #define GAPBOND_CENT_MITM_PROTECTION            0x409  //!< Man-In-The-Middle (MITM) basically turns on Passkey protection in the pairing algorithm. Read/Write. Size is uint8_t. Default is 0(disabled).
 #define GAPBOND_CENT_IO_CAPABILITIES            0x40A  //!< I/O capabilities.  Read/Write. Size is uint8_t. Default is GAPBOND_IO_CAP_DISPLAY_ONLY @ref GAPBOND_IO_CAP_DEFINES.
 #define GAPBOND_CENT_OOB_ENABLED                0x40B  //!< OOB data available for pairing algorithm. Read/Write. Size is uint8_t. Default is 0(disabled).
 #define GAPBOND_CENT_OOB_DATA                   0x40C  //!< OOB Data. Read/Write. size uint8_t[16]. Default is all 0's.
 #define GAPBOND_CENT_BONDING_ENABLED            0x40D  //!< Request Bonding during the pairing process if enabled.  Read/Write. Size is uint8_t. Default is 0(disabled).
 #define GAPBOND_CENT_KEY_DIST_LIST              0x40E  //!< The key distribution list for bonding.  size is uint8_t.  @ref GAPBOND_KEY_DIST_DEFINES. Default is sEncKey, sIdKey, mIdKey, mSign enabled.
 #define GAPBOND_CENT_DEFAULT_PASSCODE           0x40F  //!< The default passcode for MITM protection. size is uint32_t. Range is 0 - 999,999. Default is 0.
 #define GAPBOND_ERASE_ALLBONDS                  0x410  //!< Erase all of the bonded devices. Write Only. No Size.
 #define GAPBOND_AUTO_FAIL_PAIRING               0x411  //!< TEST MODE (DO NOT USE) to automatically send a Pairing Fail when a Pairing Request is received. Read/Write. size is uint8_t. Default is 0 (disabled).
 #define GAPBOND_AUTO_FAIL_REASON                0x412  //!< TEST MODE (DO NOT USE) Pairing Fail reason when auto failing. Read/Write. size is uint8_t. Default is 0x05 (SMP_PAIRING_FAILED_NOT_SUPPORTED).
 #define GAPBOND_KEYSIZE                         0x413  //!< Key Size used in pairing. Read/Write. size is uint8_t. Default is 16.
 #define GAPBOND_AUTO_SYNC_WL                    0x414  //!< Clears the White List adds to it each unique address stored by bonds in NV. Read/Write. Size is uint8_t. Default is FALSE.
 #define GAPBOND_BOND_COUNT                      0x415  //!< Gets the total number of bonds stored in NV. Read Only. Size is uint8_t. Default is 0 (no bonds).
 #define GAPBOND_BOND_FAIL_ACTION                0x416  //!< Possible actions Central may take upon an unsuccessful bonding. Write Only. Size is uint8_t. Default is 0x02 (Terminate link upon unsuccessful bonding).
 #define GAPBOND_ERASE_SINGLEBOND                0x417  //!< Erase a single bonded device. Write only. Must provide address type followed by device address.
 #define GAPBOND_BOND_AUTO                       0x418  //!< Auto save bonds into FLASH. Write Only. size is uint8_t. Default is 1(enabled).
 #define GAPBOND_BOND_UPDATE                     0x419  //!< Save current bonds into FLASH. Write Only. No Size.
 #define GAPBOND_DISABLE_SINGLEBOND              0x41A  //!< Disable a single bonded device. Write only. Must provide address type followed by device address.
 #define GAPBOND_ENABLE_SINGLEBOND               0x41B  //!< Ensable a single bonded device. Write only. Must provide address type followed by device address.
 #define GAPBOND_DISABLE_ALLBONDS                0x41C  //!< Disable all of the bonded devices. Write Only. No Size.
 #define GAPBOND_ENABLE_ALLBONDS                 0x41D  //!< Ensable all of the bonded devices. Write Only. No Size.
 #define GAPBOND_ERASE_AUTO                      0x41E  //!< Auto erase all of the bonded devices when the maximum number is reached.Size is uint8_t. Default is 1(enabled).
 #define GAPBOND_AUTO_SYNC_RL                    0x41F  //!< Clears the Resolving List adds to it each unique address stored by bonds in NV. Read/Write. Size is uint8_t. Default is FALSE.

接下来的代码就是注册一个GATT的服务,并注册相关回调响应函数。

最终进入主循环,将系统的权限交由TMOS操作系统。

我们可以在回调函数中找到响应的处理代码段,比如在BLE_UART例程中的函数:

 static bStatus_t ble_uart_ReadAttrCB( 
     uint16 connHandle, 
     gattAttribute_t *pAttr,
     uint8 *pValue, uint16 *pLen, 
     uint16 offset, 
     uint16 maxLen,
     uint8 method );

这个函数将有实时嵌入式系统进行调用,最终支持整个逻辑层功能的实现。

操作系统层TMOS

在这套程序中提供了一个基础但是强大的操作系统。其基本的使用框架就是注册响应函数,发布消息,响应消息。TMOS的执行方式就是在主循环中按照特定的优先级执行相关的响应例程。从数据手册中描述上应该是通过队列的方式实现,是不是有可能用极左树(笑)。

接下来罗列一下最关键的几项函数:

 // 创建一个任务:
 extern tmosTaskID TMOS_ProcessEventRegister( pTaskEventHandlerFn eventCb );
 // 回调函数原型;
 typedef tmosEvents (*pTaskEventHandlerFn)( tmosTaskID taskID, tmosEvents event );
 tmosEvents EventController( tmosTaskID task_id, tmosEvents events);
 // 发送一个消息(执行一个时事件)
 extern bStatus_t tmos_start_task( tmosTaskID taskID, tmosEvents event, tmosTimer time );

在回调函数中可以按照下面的模板进行任务的响应:

 tmosEvents HAL_ProcessEvent( tmosTaskID task_id, tmosEvents events )
 {
     // 初始化局部变量
      uint8 * msgPtr;
     
     // 从HAL层扒一点示例过来,有一个直观感受
     // 处理HAL层消息,调用tmos_msg_receive读取消息,处理完成后删除消息。
     if ( events & SYS_EVENT_MSG )
     {   
          // 样例
         msgPtr = tmos_msg_receive( task_id );
         if ( msgPtr )
         {
             /* De-allocate */
             tmos_msg_deallocate( msgPtr );
         }
         return events ^ SYS_EVENT_MSG;
     }
     
     // 这里是消息响应的框架
      if ( events & TASK1 )
      {}
     if(events & TASK2)
     {}
     return 0;
 }    

除此之外,系统也提供了堆管理的功能提供了堆的申请、释放和内存基础操作。

 extern uint32_t tmos_rand( void ); // pseudo-random number
 extern BOOL tmos_memcmp( const void *src1, const void *src2, uint32_t len ); // TRUE - same, FALSE - different
 extern BOOL tmos_isbufset( uint8_t *buf, uint8_t val, uint32_t len ); // TRUE if all "val",FALSE otherwise
 extern uint32_t tmos_strlen( char *pString );
 extern void tmos_memset( void * pDst, uint8_t Value, uint32_t len );
 extern void tmos_memcpy( void *dst, const void *src, uint32_t len ); // Generic memory copy.

由于这样的任务并非抢占式,因此,我们在书写每一个event时应当尽量保证其中的内容尽可能精练。


回复

2601

帖子

3

资源

版主

分析这个确实需要耐心跟时间,我也就用什么看什么,但是这个任务系统要处理复杂的程序还是不是很合适。

回复

5274

帖子

236

资源

管理员

代码你用编辑器的代码插入功能会清晰些

点评

是这样的,我是markdown直接编辑好贴过来的,其实还好  详情 回复 发表于 2022-4-28 09:22

回复

95

帖子

0

资源

一粒金砂(中级)

nmg 发表于 2022-4-27 17:37 代码你用编辑器的代码插入功能会清晰些

是这样的,我是markdown直接编辑好贴过来的,其实还好


回复

4

帖子

0

资源

一粒金砂(初级)

很不错


回复

3

帖子

0

资源

一粒金砂(初级)

感觉挺nb的,要是能硬件pin对pin,软件完全兼容一些现有的方案就太棒了!


回复
您需要登录后才可以回帖 登录 | 注册

相关帖子
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
    推荐帖子
    简单高效的零点采集电路

    从业多年一直都有用到零点采集功能,一直的做法都是低要求的直接将交流信号限流引入IO;要求高点的就用三极管;要求再高的用运发 ...

    软件工程师说不会用GPIO来模拟I2C,是不是个菜鸡?

    本帖最后由 lingking 于 2019-6-26 00:06 编辑 今天遇到一件烦心的事。公司里面一个搞软件的说我设计的电路I2C有问题。说是 ...

    【急聘!】信步科技Layout工程师

    【急聘!】信步科技Layout工程师 此内容由EEWORLD论坛网友seavo原创,如需转载或用于商业用途需征得作者同意并注明出处 ...

    【SAMR21新玩法】汇总

    本帖最后由 dcexpert 于 2019-10-18 11:36 编辑 436737 与传统开发方法不同的用法,不需要IDE和编译器,使用python和图形 ...

    智能相机结构设计--实物装配

    经过各种细节微调,打样了一版光固化3D,及用加工中心CNC了一版铝合金; 装配好后的样子: 571704 571705 57170 ...

    颁奖:ADI应用之旅——电池管理及智慧储能篇

    ADI应用之旅——电池管理及智慧储能篇活动颁奖啦!名单详见下方列表。请获奖者务必在2021年12月10日23:59前,按照下方 ...

    关闭
    站长推荐上一条 1/7 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表