- 进入函数 fn + F12
- 回到前一个光标点 control + -
- 查看函数引用 fn + shift + F12, 每多按一次这个组合就跳转一次到引用该函数的地方
nimble advertising
今天顺利将美人鱼(Mermaid)插件装上,整理一张时序图:
sequenceDiagram NPL->>HCI:BLE_HCI_OCF_LE_SET_ADV_ENABLE HCI->>HCI:ble_ll_hci_cmd_proc() HCI->>ADV: ble_ll_hci_adv_set_enable() note over ADV: ble_ll_adv_sm_start() ADV->>Scheduler: ble_ll_sched_adv_new() Scheduler->>Scheduler: ble_ll_sched_run() note over Scheduler: ble_ll_sched_execute_item() Scheduler->>ADV: ble_ll_adv_tx_start_cb() ADV->>PHY: ble_phy_tx() PHY->>ADV: ble_ll_adv_tx_done() ADV->>NPL: adv_txdone_ev NPL->>ADV: ble_ll_adv_event_done() note over ADV: ble_ll_adv_done() note over ADV: ble_ll_adv_reschedule_event() ADV-->>Scheduler: ble_ll_sched_adv_reschedule() RADIO->>PHY: RADIO_IRQn note over PHY: ble_phy_isr() note over PHY: ble_phy_rx_start_isr() PHY->>ADV: ble_ll_adv_rx_isr_start() note over PHY: ble_phy_rx_end_isr() PHY->>ADV: ble_ll_adv_rx_isr_end() note over ADV: ble_ll_adv_rx_req() ADV->>PHY:ble_phy_tx(ble_ll_adv_scan_rsp_legacy_pdu_make) NPL->>LL: ble_ll_event_rx_pkt() LL->>LL: ble_ll_rx_pkt_in() LL->>ADV: ble_ll_adv_rx_pkt_in() note over ADV: ble_ll_adv_conn_req_rxd() ADV->>CONN: ble_ll_conn_slave_start() note over ADV: ble_ll_adv_sm_stop() note over CONN: ble_ll_conn_created() CONN->>Scheduler:ble_ll_sched_slave_new() note over CONN: ble_ll_conn_next_event()
将本地文件夹push到github
进入文件夹,git init 把这个目录变成git可以管理的仓库
1
git init
把文件添加到版本库中,使用命令 git add . 添加到暂存区里面去,不要忘记后面的小数点“.”,意为添加文件夹下的所有文件
1
git add .
用命令 git commit告诉Git,把文件提交到仓库。引号内为提交说明
1
git commit -m 'first version'
关联到远程库
1
git remote add origin https://github.com/reponame.git
把本地库的内容推送到远程,使用 git push命令,实际上是把当前分支master推送到远程。执行此命令后会要求输入用户名、密码,验证通过后即开始上传。
1
git push -u origin master
舞曲
几段喜欢的音乐,如有侵权,请随时通知。
-
“哦嘛哩嘛嘞,邦邦”
简单欢快,不知道是哪个国家舞蹈。 -
快板、慢板、快板三段,中间慢板最美,柔中带刚,刚中带柔,有一种飘来飘去的感觉。
一直没搞清楚奔腾的到底是骏马?还是套马的汉子? -
也算是一个拉丁舞种。
-
改编自腾格尔的歌曲,刘福洋和万玛尖措表演,表达两兄弟来开草原时恋恋不舍的内心。
-
探戈。
作为一个节奏控,跑步必须有鼓点,要不就跑不起来。下面几个蒙古神曲,伴我每天跑过5km
Nimble scheduler
Nimble controller 的Scheduler是由一个32K的timer来驱动的,一个tick是30.52us,完全执行在timer的isr里,所以timer callback里要做的事情不能太耗时(超过一个tick),否则scheduler就不准确了,如下为scheduler的主函数:1
2/* Initialize cputimer for the scheduler */
os_cputime_timer_init(&g_ble_ll_sched_timer, ble_ll_sched_run, NULL);
时间单位
- Tick:由clock决定,对于32K clock来说,一个tick就是 1000000us/(32*1024) = 30.52us.
- Slot:1250个毫秒
- Period:N * Slot,N是可配置的
- Epoch:M * Period,M是可配置的
Scheduler在调度的时候,有时要将Connection event放在Period的边界,scanning/initiating/advertising是尽可能发生在没有被用到的Period内。1
2
3/* Time per BLE scheduler slot */
#define BLE_LL_SCHED_USECS_PER_SLOT (1250)
#define BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT (41) /* 1 tick = 30.517 usecs */
调度单位
每一个可被调度的单位叫做Sched item, 这些item放在FIFO的List中,每当timer到期后Scheduler就从List里拉一个出来做执行。
每一个item有如下几个属性:
- schedule type,类型
- enquened,是否入Q,入Q就代表是Ready,等待被执行
- remainder,剩余的执行时间
- start_time, 开始执行时间
- end_time, 结束执行时间
- cb_args, item执行函数的参数
- sched_cb, item被调度到的时候的执行函数
如下是相关的code segment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 struct ble_ll_sched_item
{
uint8_t sched_type;
uint8_t enqueued;
uint8_t remainder;
uint32_t start_time;
uint32_t end_time;
void *cb_arg;
sched_cb_func sched_cb;
TAILQ_ENTRY(ble_ll_sched_item) link;
};
/* Types of scheduler events */
#define BLE_LL_SCHED_TYPE_ADV (1)
#define BLE_LL_SCHED_TYPE_SCAN (2)
#define BLE_LL_SCHED_TYPE_CONN (3)
#define BLE_LL_SCHED_TYPE_AUX_SCAN (4)
#define BLE_LL_SCHED_TYPE_DTM (5)
#define BLE_LL_SCHED_TYPE_PERIODIC (6)
#define BLE_LL_SCHED_TYPE_SYNC (7)
调度原则
- Sched item之间没有优先级的关系,完全按照Sched item的start_time为序,一个一个的执行。
- 调度到某个item时就直接执行这个item的sched_cb,并将这个item从调度列表上删掉,callback执行完后,再起timer,等待下一个item的start_time到期。
- item在插入到调度列表的时候就已经排好序了。
- 在插入新的Adv Sched item的时候,新的Adv要避开每一个跟他有overlap的item,直到找到一个完全跟它没有overlap的位置,这意味着在有同样的start time的情况下,先入list的优先级高。
- 以插入一个Adv Schedule为例,假如Scheduler的ReadyList里有4个item,它们的排列如下。那么下图中绿色的item就是可以直接插入的item,而红色的item则需要一直往后移动,一直移到一个能插入>的地方,也许到list最后才能有它的一席之地。
- 在一个adv event执行完成后,需要再计算下一个adv event起来的时间,请参考下图。
Item中的Delay(0~10ms)指的是这个adv event最大允许delay的时间。
- 以插入一个Adv Schedule为例,假如Scheduler的ReadyList里有4个item,它们的排列如下。那么下图中绿色的item就是可以直接插入的item,而红色的item则需要一直往后移动,一直移到一个能插入>的地方,也许到list最后才能有它的一席之地。
- 但是对于type为CONN的Sched是有点优先级的
- 正在execute的type为CONN的Sched的优先级最高,要新建立的conn的sched (ble_ll_sched_slave_new())如果刚好跟正在execute的conn overlap,那直接就取消新的这个conn。
1
2
3
4
5/* The schedule item must occur after current running item (if any) */
if (ble_ll_sched_overlaps_current(sch)) {
OS_EXIT_CRITICAL(sr);
return rc;
}
- 正在execute的type为CONN的Sched的优先级最高,要新建立的conn的sched (ble_ll_sched_slave_new())如果刚好跟正在execute的conn overlap,那直接就取消新的这个conn。
- 在收到CONN_IND的时候,为了能尽快在windowOffset到达时发包出去回应对方,会将跟他overlap的type为CONN的sched 给盖掉
- 但这包如果type是其他的type,则会继续往后shift找合适的位置,但如果是回应CONN_IND的第一包的话,不在规定时间发包出去,link就建立不起来,这里还是有点问题。
1
2
3
4
5
6 if (ble_ll_sched_is_overlap(sch, entry)) {
/* If we overlap with a connection, we re-schedule */
if (ble_ll_sched_conn_overlap(entry)) {
break;
}
}
更正 #4
感谢jaydenh215的指导,上图中关于Adv reschedule的图例欠妥,正确的符合code行为的插入Sched的示意图如下。
如果超过了max_delay,那插入也是失败的,如下图,虽然在#3的前面有位置给sch插入,但是因为overdue了,所以插入会失败。
Periodic Advertising Sync Transfer (PAST)[未完结]
Periodic Advertising Sync Transfer 是BT 5.1的一个新feature,SIG官网上有一篇文章介绍的还不错What You Need to Know About Periodic Advertising Sync Transfer。这里就做一个简单的总结。
这个新概念的引入,本质上是为了省电。对于Legacy的advertising,Advertiser在interval附近会加一个Delay(0~10ms),那么Scanner就需要多开窗来抓到adverting 数据包,增加耗电,而PAST概念就是为了在某个场景下可以解决这个问题。
先看下几种Advertising的概念
1.Legacy Advertising
Legacy Advertising只在37/38/39三个Channel上打,为了避免adv event刚好跟Scannner的scan window完美错过,在Adv的Interval上会加一个随机值advDalay,让Anchor点随机shift一点点,增加与Scanner的scan window碰撞的几率,示意图如下:
下图为Legacy Adv的PDU的格式:
2.Extended Advertising
Legacy Advertising能发送的Adv data有限,所以后来又衍生出了 extended adv:在Data channel里也可以打Adv data,如下图。
而Extended Advertising引入的概念就比较多了,比如:
- Advertising Handle,
- Advertising Set
- Advertising Data ID
- …
当收到的Adv的type是 ADV_EXT_IND 时,Adv的Payload的数据格式如下:
3.Periodic Advertising
在Extended Advertising的基础上,在发送大量数据的时候又引入了Periodic Advertising。
Periodic Advertising 流程的建立有两种方式:
3.1 正常的Scanner 和 Advertiser的交互
如下图中AoD Transmitter 与 Smartphone的Sync。
3.2 已经有Periodic Advertising Synchronization infomation的一方,将该data通过 LE-C 转发给另外一个跟它连线的设备,就是PAST。
如下图右图中Smartphone 与Wearable Device之间的关系,Wearable device在前期不需要开Scan去抓ADV_EXT_IND就知道后续要到哪里去收AUX_SYNC_IND包,从而节约了电能。
4. 关于PAST的细节:
下图是Spec中关于Periodic Advertising的一个Sequence flow。
message 流程图如下:
下面三图中A是Scanner,B是Advertiser,A和B中有一个与C有BLE连线,那么会有三种情况: