女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

針對app開發過程中對OAD功能做一個流程和代碼解讀

電子設計 ? 來源:網友電子設計發布 ? 作者:網友電子設計發布 ? 2021-12-29 14:45 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

CC2640 R2是一款面向 Bluetooth Smart 應用的低功耗無線 MCU。該芯片運行TI的BLE協議棧,并支持OAD(Over the Air Download)空中固件升級功能,此空中固件升級功能就是利用Android或者iOS的產品對應app通過BLE對CC2640R2的產品進行固件升級。同時,TI其實提供了Anroid和iOS的源碼對其支持:http://www.ti.com/tool/SENSORTAG-SW?keyMatch=sensortag&tisearch=Search-EN-Everything。這部分的源碼是基于TI的SensorTag硬件進行開發的,包含了很多內容,對于客戶來說,基本上不適合直接拿去使用,但是其中的OAD部分代碼,卻是可以通用的。但是對于客戶的iOS或者Android app工程師來說,往往對BLE協議不熟,那就更不用說TI的OAD協議了,所以即使提供了源碼,客戶在這一部分開發起來還是很困難。本文就針對這一點,針對app開發過程中對OAD功能做一個流程和代碼解讀,用以幫助客戶更方便完成此功能開發。

首先,第一步是從上面的鏈接下載到最新的android和iOS源碼,上述鏈接最終會指引到github的下載地址。

有了源碼之后,我們就可以解讀了。

從app的角度上來看TI的OAD協議,大致是這樣的:

App連接上設備之后,就能發現OAD的service和characteristics(服務和特征值):

服務的UUID:0xFFC0,對應的128bit UUID:

F000FFC0-0451-4000-B000-000000000000

服務下面有兩個主要特征值:(其他特征值可以暫且忽略)

OAD Image Identify,UUID:0xFFC1;OAD Image Block,UUID:0xFFC2,對應的128bit UUID:

– OAD Image Identify F000FFC1-0451-4000-B000-000000000000,用于交互確認固件版本信息。

– OAD Image Block F000FFC2-0451-4000-B000-000000000000,用于傳送新的固件。

固件更新的所有操作都是對上面這兩個特征值進行操作。

用TI的SensorTag app可以看到:

用第三方app比如light blue也能看到,安卓手機的情況也是一樣。

在TI提供的示例代碼中,在Android中,客戶唯一要用到的文件其實就是FwUpdateActivity_CC26xx.java,所有的OAD流程基本全部都在這里。另外有一個相關的文件BluetoothLeService.java,這個是TI的SensorTag App封裝的BLE相關API接口集合,主要用于一些特征值的操作,比如write,read等,OAD用到的主要就是write,通過write來神奇地實現各種流程。在iOS源碼中,流程相關的主要是BLETIOAD2Profile.m(注意,另外一個BLETIOADProfile.m,這是針對舊版的CC254x的,和CC26xx略有不同,這里不做討論,有興趣可以自己去看),基本就在這里,另外對應也有一個BLE相關接口集合BLEUtility.m。

第一步

從app來講,開始OAD的第一步就是先使能上面兩個特征值的notification功能。

簡單來說就是調用android或者iOS提供的現有API,分分鐘完成。(藍牙協議上來說就是往這兩個特征值的CCC句柄上寫01:00,我們這里盡量不討論具體藍牙協議,從簡考慮,有興趣的人可以自己去研究一下)。

對應到代碼里,

Android在FwUpdateActivity_CC26xx.java中,新的固件文件裝載到手機內存后:public void onLoad(View v)中調用:

mLeService.setCharacteristicNotification(mCharIdentify, true);

mLeService.setCharacteristicNotification(mCharBlock, true);

實際上可以根據客戶真實代碼在適當位置加上面兩個函數就行,這樣第一步其實就完成了。

*更多說明:

上面兩個函數,其實就是BluetoothLeService.java中的API,最終追蹤下去的話是調用Android SDK 的BLE API來使能notification:

mBluetoothGatt.setCharacteristicNotification(request.characteristic, request.notifyenable)

其實我們也可以直接調用這個來實現上面的功能。

iOS在BLETIOAD2Profile.m里的-(void) configureProfile 函數里調用:

CBUUID *sUUID = [CBUUID UUIDWithString:TI_OAD_SERVICE];

CBUUID *cUUID = [CBUUID UUIDWithString:TI_OAD_IMAGE_NOTIFY];

[BLEUtility setNotificationForCharacteristic:self.d.p sCBUUID:sUUID cCBUUID:cUUID enable:YES];

cUUID = [CBUUID UUIDWithString:TI_OAD_IMAGE_BLOCK_REQUEST];

if (self.notifications)[BLEUtility setNotificationForCharacteristic:self.d.p sCBUUID:sUUID cCBUUID:cUUID enable:YES];

注意,iOS代碼里面OAD Image Identify和OAD Image Block對應的是TI_OAD_IMAGE_NOTIFY和TI_OAD_IMAGE_BLOCK_REQUEST。同樣,在iOS里適當位置調用這個函數就行。

*更多說明:

對于iOS TI給出的源碼,是BLEUtility.m中封裝了Apple的BLE API來使能notification:

- (void)setNotifyValue:(BOOL)enabled forCharacteristic:(CBCharacteristic *)characteristic;

一樣,我們也可以直接調用這個來實現上面的功能。

空中sniffer抓包看的話,就能看到這兩個使能notification的流程:

第二步

從app角度來講,第二步就是要把新固件的版本信息從手機傳送到外設上,讓外設進行判斷是否要升級。

這一步就要用到OAD Image Identify,這個特征值在整個OAD過程中只會用到一次,就是在這里。

App這邊先從獲得到的新固件里把固件的image header (16個字節) 讀出來,image header就是固件的二進制文件的開始16個字節,很容易獲取到。

體現在代碼里,

Android:還是在FwUpdateActivity_CC26xx.java中,在打開新固件文件的時候:

private boolean loadFile(String filepath, boolean isAsset) {

順便創建要發送的16個字節image header結構:

mFileImgHdr = new ImgHdr(mFileBuffer,readLen);

這個構造函數就會把image header部分給組織好放到16字節的一個buffer中去,用以接下來發送給設備。這個類的定義也在FwUpdateActivity_CC26xx.java中:

private class ImgHdr {

……

ImgHdr(byte[] buf, int fileLen) {

this.len = (fileLen / (16 / 4));

this.ver = 0;

this.uid[0] = this.uid[1] = this.uid[2] = this.uid[3] = ‘E’;

this.addr = 0;

this.imgType = 1; //EFL_OAD_IMG_TYPE_APP

this.crc0 = calcImageCRC((int)0,buf);

crc1 = (short)0xFFFF;

……

}

可以看到構造函數里面,雖然有讀取到的實際固件文件的image header作為輸入參數,但我們實際的代碼里面為了演示,只是寫死了一些內容。這里可以根據實際情況修改一下,根據前面提到的16字節header的順序來就行,比如:

private class ImgHdr {

……

ImgHdr(byte[] buf, int fileLen) {

this.len = (fileLen / (16 / 4));

this.ver = buf[5];

this.ver = (this.ver 《《 8) | buf[4];

this.uid[0] = buf[8];this.uid[1] = buf[9];

this.uid[2] = buf[10]; this.uid[3] = buf[11];

this.addr = buf[13];

this.addr = (this.addr 《《 8) | buf[12];

this.imgType = buf[14];//EFL_OAD_IMG_TYPE_APP

this.crc0 = calcImageCRC((int)0,buf);

crc1 = (short)0xFFFF;

……

}

這樣就基本能拿到實際的真實數據了。

iOS:就很簡單了,直接把新固件文件開始的16字節header復制到代碼里就可以了,還是在BLETIOAD2Profile.m里,在-(void) uploadImage 函數中:

img_hdr_t2 imgHeader;

uint32_t pages = ((uint32_t)self.imageFile.length / 4096);

//做個CRC校驗,放到image header中去,同時把image header的16字節內容補完整。

[self calcImageInfo:0 pages:pages imageHeader:&imgHeader buf:imageFileData];

memcpy(requestData, &imgHeader, 16);

需要注意的是iOS給的源碼里面,image header內容的補充是在crc校驗函數里面一并完成的:-(void) calcImageInfo里:

imageHeader buf:(uint8_t *)buf {

imageHeader-》len = (pages * FLASH_PAGE_SIZE) / (OAD_BLOCK_SIZE / FLASH_WORD_SIZE);

imageHeader-》ver = 0;

imageHeader-》uid[0] = imageHeader-》uid[1] = imageHeader-》uid[2] = imageHeader-》uid[3] = ‘E’;

imageHeader-》addr = (firstpage * FLASH_PAGE_SIZE) / (OAD_BLOCK_SIZE / FLASH_WORD_SIZE);

imageHeader-》imgType = EFL_OAD_IMG_TYPE_APP;

imageHeader-》res[0] = 0xff;

imageHeader-》crc0 = [self calcImageCRC:firstpage imageHeader:imageHeader buf:buf];

imageHeader-》crc1 = 0xffff;

}

這樣iOS這里也得到完整的image header信息了。

接下來app將通過OAD Image Identify這個特征值首先把前面得到的新的固件的版本信息發送給設備(CC2640R2),這個版本信息包含在前面得到的image header的16個字節buffer里,把這個發出去給設備就行了。

體現在代碼里,

Android,還是在FwUpdateActivity_CC26xx.java中,開始流程函數:

private void startProgramming() {

獲取image identify(其實就是image header):

mCharIdentify.setValue(mFileImgHdr.getRequest());

并通過BLE的write characteristic動作從app發送到設備端:

mLeService.writeCharacteristic(mCharIdentify);

*更多說明:

上面write characteristic函數其實就是BluetoothLeService.java中的API,最終追蹤下去的話是調用Android SDK 的BLE API來進行BLE的write command操作:

mBluetoothGatt.writeCharacteristic(request.characteristic);

其實我們也可以直接調用這個來實現上面的功能。

iOS代碼中,在BLETIOAD2Profile.m里,還是在-(void) uploadImage 函數里:

CBUUID *cUUID = [CBUUID UUIDWithString:TI_OAD_IMAGE_NOTIFY];

[BLEUtility writeNoResponseCharacteristic:self.d.p sCBUUID:sUUID cCBUUID:cUUID data:[NSData dataWithBytes:requestData length:16]];

通過 write characteristic來把image header發送到設備端。

*更多說明:

這個的write函數,其實也是在BLEUtility.m里面封裝了Apple的BLE標準API:

- (void)writeValue:(NSData *)data forCharacteristic:(CBCharacteristic *)characteristic type:(CBCharacteristicWriteType)type;

我們也可以直接調用這個來實現上面的功能。

空中sniffer抓包能看到write command發送image header:

最后,設備收到image header之后,會進行和自己本身的固件版本號進行比較。如果發現image header中的版本號沒有自己的版本號新,那么就直接以notification (這里notification是在前面第一步使能)的形式在OAD Image Identify上回復自己的版本號給手機,表示拒絕此次固件升級,此次升級就此結束。

空中sniffer抓包,其中標黃的部分就是設備回復自身版本號,表示拒絕此次固件升級:

如果發現image header中的版本號確實比自己本身的固件版本號要新,那么就同意這次固件更新,會在OAD Image Block這個特征值的notification (這里notification是在前面第一步使能)上回復0x0000,表示準備接受序列號第0個固件內容包。注意實在OAD Image Block這個特征值上,不是OAD Image Identify這個特征值上,OAD Image Identify這個特征值的使命在前面已經完成,后面不會再使用。

從sniffer看就會看到0x0000從外設發回手機:

總結下來第二步,就是app要在OAD Image Identify特征值上發送新固件的image header到設備端,然后設備端進行判斷是否要接收新的固件進行升級,如果要升級,則在OAD Image Block特征值上向手機回復0x0000,不然回復自己目前的固件版本號表示拒絕更新。總結起來就是下面的兩個流程圖:

第三步

這一步從app來講就是按照順序發送固件內容了。

手機在OAD Image Block特征值上收到0x0000之后就代表設備端愿意接收新固件,并且意思是對方準備好接收第0個固件包。每個固件包的內容長度是16個字節,并且需要在頭部放上兩個字節的序列號,序列號從0x0000開始累加,一直到最后一個固件包。

*注意這個序列號是小端在前的,所以后面是0x0100,0x0200,0x0300,0x0400,…,0xFF00,0x0001,0x0101,0x0201,…這樣累加上去。

從空中sniffer上看,很容易就能看到整個流程的交互:

首先是手機發送第0包的固件內容,通過BLE的Write方式在OAD Image Block特征值上發送,固件block內容是16個字節,注意下圖標黃的頭兩個字節,是固件包序列號,第0包是0x0000,所以包的總長是16+2=18個字節。

那么設備收到APP發送過去的第0包固件后,回復請求下一個固件包,通過Notification的方式在OAD Image Block特征值上回復0x0100:

APP收到設備發回的0x0100,就知道對方已經等待接收下一包固件,于是就發送下一包0x0100的固件包,以此類推,一直到固件發送結束。

具體到代碼里,

在Android中,就是在programBlock()函數里,這里我們只關注核心部分:

private void programBlock() {

省略前面邏輯相關代碼,工程里面很容易看懂。

// Prepare block

首先自然是包序列號,buffer的頭兩個字節:

mOadBuffer[0] = Conversion.loUint16(mProgInfo.iBlocks);

mOadBuffer[1] = Conversion.hiUint16(mProgInfo.iBlocks);

然后是16個字節的固件block包內容:

System.arraycopy(mFileBuffer, mProgInfo.iBytes, mOadBuffer, 2, OAD_BLOCK_SIZE);

// Send block

接著把這18個字節通過write方式在OAD Image Block特征值上發送:

mCharBlock.setValue(mOadBuffer);

boolean success = mLeService.writeCharacteristicNonBlock(mCharBlock);

如果發送成功,那么就順移相關的包序列號還有固件文件中的位移標志:

if (success) {

// Update stats

packetsSent++;

mProgInfo.iBlocks++;

mProgInfo.iBytes += OAD_BLOCK_SIZE;

mProgressBar.setProgress((mProgInfo.iBlocks * 100) / mProgInfo.nBlocks);

如果最后一個固件block成功完成,那么就恭喜,OAD順利成功!

if (mProgInfo.iBlocks == mProgInfo.nBlocks) {

b.setTitle(“Programming finished”);

b.setPositiveButton(“OK”,null);

AlertDialog d = b.create();

d.show();

mProgramming = false;

mLog.append(“Programming finished at block ” + (mProgInfo.iBlocks + 1) + “\n”);

}

} else {

mProgramming = false;

msg = “GATT writeCharacteristic failed\n”;

}

}

*更多說明:

上面boolean success = mLeService.writeCharacteristicNonBlock(mCharBlock);這個函數,其實就是BluetoothLeService.java中的API,最終追蹤下去的話是調用Android SDK 的BLE API來實現的:mBluetoothGatt.writeCharacteristic(request.characteristic);

iOS的代碼里,體現在BLETIOAD2Profile.m里的-(void) sendOnePacket 函數,只看核心部分,和Android很像的,因為流程一樣:

-(void) sendOnePacket {

//Prepare Block

首先自然是包序列號,buffer的頭兩個字節:

uint8_t requestData[2 + OAD_BLOCK_SIZE];

requestData[0] = LO_UINT16(self.iBlocks);

requestData[1] = HI_UINT16(self.iBlocks);

然后是16個字節的固件block包內容:

memcpy(&requestData[2] , &imageFileData[self.iBytes], OAD_BLOCK_SIZE);

CBUUID *sUUID = [CBUUID UUIDWithString:TI_OAD_SERVICE];

CBUUID *cUUID = [CBUUID UUIDWithString:TI_OAD_IMAGE_BLOCK_REQUEST];

接著把這18個字節通過write方式在OAD Image Block特征值上發送:

[BLEUtility writeNoResponseCharacteristic:self.d.p sCBUUID:sUUID cCBUUID:cUUID data:[NSData dataWithBytes:requestData length:2 + OAD_BLOCK_SIZE]];

如果發送成功,那么就順移相關的包序列號還有固件文件中的位移標志:

dataWithBytes:requestData length:2 + OAD_BLOCK_SIZE]);

self.sndDataCount ++;

self.iBlocks++;

self.iBytes += OAD_BLOCK_SIZE;

self.sentPackets++;

如果最后一個固件block成功完成,那么就恭喜,OAD順利成功!

if(self.iBlocks == self.nBlocks) {

self.inProgramming = NO;

[self.oadDelegate didFinishUploading];

return;

}

流程和Android完全一樣,我連注釋都直接復制過來了J。

這樣就是完整的OAD流程了。總結就是分三步走:使能OAD Image Identify和OAD Image Block 的notification,在OAD Image Identify上發送新固件版本(image header)進行確認,最后在OAD Image Block上按順序把固件發送完,結束。

審核編輯:何安

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式處理
    +關注

    關注

    0

    文章

    341

    瀏覽量

    10299
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    HarmonyOS實戰: 城市選擇功能的快速實現

    最近在日常開發過程中,需要實現城市選擇功能,同時支持模糊搜索。看似簡單的功能動手實現起來卻有很多難點。本篇文章詳細記錄開發過程中遇到的問題和對應的解決方法,希望能夠幫助你,建議點贊收藏
    的頭像 發表于 06-24 17:07 ?114次閱讀

    HarmonyOS 代碼工坊的指尖開發,讓 APP 開發所見即所得

    沙盤被直接搬入了移動設備本身。眼尖的開發者應該已經發現,最近華為應用市場“應用嘗鮮”專區里,上架了款名為“HarmonyOS 代碼工坊”的新應用,下載量持續攀升。 開發者只需要下載“
    的頭像 發表于 06-24 12:08 ?161次閱讀
    HarmonyOS <b class='flag-5'>代碼</b>工坊的指尖<b class='flag-5'>開發</b>,讓 <b class='flag-5'>APP</b> <b class='flag-5'>開發</b>所見即所得

    HarmonyOS實戰:高德地圖自定義定位圖標展示

    前言 地圖定位功能基本上已經成了日常應用程序的必備功能,在日常開發地圖定位的功能的時候難免會遇到很多意想不到的問題,本篇文章記錄日常
    的頭像 發表于 06-09 14:59 ?223次閱讀
    HarmonyOS實戰:高德地圖自定義定位圖標展示

    使用CY7C65213開發過程中,應該用哪個interface進行uart通信?

    在使用CY7C65213開發過程中,我想用CyUartRead讀數據,但是好像沒有接口的deviceType是CY_TYPE_UART,想請問我應該用哪個interface進行uart通信? 是否有相關指導文件,或描述符指導?
    發表于 06-03 07:04

    DevEco Studio AI輔助開發工具兩大升級功能 鴻蒙應用開發效率再提升

    帶來了前所未有的智能問答體驗。 RAG增強型與傳統生成式AI的關鍵差異: 圖2:DeepSeek模型增強RAG能力前后效果對比圖 升級點2:新增代碼解釋功能,提升初學者開發效率 針對開發過程中
    發表于 04-18 14:43

    半導體制造過程中的三主要階段

    前段工藝(Front-End)、中段工藝(Middle-End)和后段工藝(Back-End)是半導體制造過程中的三主要階段,它們在制造過程中扮演著不同的角色。
    的頭像 發表于 03-28 09:47 ?2583次閱讀
    半導體制造<b class='flag-5'>過程中</b>的三<b class='flag-5'>個</b>主要階段

    鴻蒙海報編輯器APP,分享端云一體化開發的經驗!

    前言 在我工作的日常,經常會用些畫圖編輯器,簡單設計些頁面原型。而在去年低代碼很火的時候,我在公司就開發
    的頭像 發表于 03-16 16:09 ?382次閱讀
    鴻蒙海報編輯器<b class='flag-5'>APP</b>,分享端云<b class='flag-5'>一體化開發</b>的經驗!

    芯科科技Web-BasedFlash工具助力優化Matter開發流程

    Silicon Labs(芯科科技)獨家提供Matter開發流程(Matter Developer Journey)設計資源,以作為其不斷努力提升開發者體驗,并簡化該協議開發過程
    的頭像 發表于 02-20 09:52 ?485次閱讀

    在linux下開發過程中, DLP4500 GUI無法連接光機怎么解決?

    在linux下開發過程中, DLP4500 GUI 無法連接光機,出現錯誤提示如下: open device_handle error: Is a directory opening path
    發表于 02-20 08:41

    DevEco Studio構建分析工具Build Analyzer 為原生鴻蒙應用開發提速

    。值得提的是,某頭部短視頻公司還基于Build Analyzer的能力,針對其自身工程特點,構建了內部開發效率檢測平臺,用于支撐該公司內部各應用開發過程中的構建性能分析和優化,大幅提
    發表于 02-17 18:06

    如何在日常開發過程中提高代碼質量

    。 提高代碼質量是系統工程,本文主要介紹開發人員如何在日常開發過程中提高代碼質量。 01 什
    的頭像 發表于 01-23 09:09 ?543次閱讀
    如何在日常<b class='flag-5'>開發過程中</b>提高<b class='flag-5'>代碼</b>質量

    充分考慮設備的體驗性易用性 藍鵬設計部將這理念貫穿于整個研發過程

    設計部還充分考慮了設備的易用性。他們深知,易于使用的設備能夠降低用戶的學習成本,提高用戶的使用效率。因此,在研發過程中,設計部注重從以下幾個方面提升設備的易用性: 1.簡化操作流程
    發表于 12-24 14:07

    MCU開發流程的注意事項

    微控制器單元(MCU)是現代電子系統不可或缺的核心組件,廣泛應用于各種嵌入式系統和物聯網設備。MCU開發流程涉及多個階段,從需求分析到最終產品的測試和部署。在這個
    的頭像 發表于 11-01 13:52 ?845次閱讀

    自己做的TAS5825板子軟件開發過程中怎么接到PPC3上去調試呢?

    我們打算做一個TAS5825的板子,PPC3軟件已經申請下來了,有問題是我們自己做的TAS5825板子軟件開發過程中怎么接到PPC3上去調試呢?
    發表于 10-15 08:15

    康謀分享 | 在基于場景的AD/ADAS驗證過程中,識別挑戰性場景!

    基于場景的驗證是AD/ADAS系統開發過程中的重要步驟,然而面對海量駕駛記錄數據時,如何實現自動且高效地識別、分類和提取駕駛記錄的挑戰性場景?本文康謀為您介紹IVEX軟件識別挑戰性場景并進行數據分析的強大功能
    的頭像 發表于 08-28 10:16 ?1420次閱讀
    康謀分享 | 在基于場景的AD/ADAS驗證<b class='flag-5'>過程中</b>,識別挑戰性場景!