Closed gksrb4 closed 4 years ago
Hi, Can you provide logs? FYI: I'll release an update to DFU Library on both Android and iOS today, and it may improve the speed on newer phones. If you'll find there "XXX bytes were lost" on the DFU performed from Note 10, the update should help. If not, I need more information.
Hi, I'm waiting to release next version! but, It's still not released officially.
I saw usage
implementation 'no.nordicsemi.android:dfu:1.9.1'
so I tried.
but, this version doesn't work even in starting dfu.
So. I share 1.9.0 version dfu log.
... 2019-11-29 13:29:46.667 W/DfuImpl: 1040 bytes were lost! ...
2019-11-29 13:32:27.039 I/DfuImpl: Transfer of 78824 bytes has taken 162752 ms --> almost 3 minutes!
1.9.1 version crash log
--------- beginning of crash
2019-11-29 13:47:59.177 E/AndroidRuntime: FATAL EXCEPTION: IntentService[DfuBaseService]
Process: my-package-name, PID: 10230
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/gson/Gson;
at no.nordicsemi.android.dfu.internal.ArchiveInputStream.parseZip(ArchiveInputStream.java:329)
at no.nordicsemi.android.dfu.internal.ArchiveInputStream.<init>(ArchiveInputStream.java:139)
at no.nordicsemi.android.dfu.DfuBaseService.openInputStream(DfuBaseService.java:1439)
at no.nordicsemi.android.dfu.DfuBaseService.onHandleIntent(DfuBaseService.java:1158)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:76)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:216)
at android.os.HandlerThread.run(HandlerThread.java:65)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.gson.Gson" on path: DexPathList[[zip file "/data/app/my-package-name-b-mP7oEYzNmnSqGusx_dvg==/base.apk"],nativeLibraryDirectories=[/data/app/my-package-name-b-mP7oEYzNmnSqGusx_dvg==/lib/arm64, /system/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at no.nordicsemi.android.dfu.internal.ArchiveInputStream.parseZip(ArchiveInputStream.java:329)
at no.nordicsemi.android.dfu.internal.ArchiveInputStream.<init>(ArchiveInputStream.java:139)
at no.nordicsemi.android.dfu.DfuBaseService.openInputStream(DfuBaseService.java:1439)
at no.nordicsemi.android.dfu.DfuBaseService.onHandleIntent(DfuBaseService.java:1158)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:76)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:216)
at android.os.HandlerThread.run(HandlerThread.java:65)
This looks like R8 configuration or missing dependency to gson. Try adding the library as a module, not from jcenter. Clone it and follow the instructions in Readme.
adding
implementation 'no.nordicsemi.android:dfu:1.9.1'
implementation 'com.google.code.gson:gson:2.8.6'
and -keep class no.nordicsemi.android.dfu.** { *; }
to proguard rule.
so, It doesn't occur the crash. but It's still slow.
2019-12-02 09:32:39.306 W/DfuImpl: 1280 bytes were lost!
..
2019-12-02 09:35:30.279 I/DfuImpl: Transfer of 78824 bytes has taken 172737 ms
So here's why it's slow. As you are using the latest version, which contains a fix for the issue we found when doing DFU on devices with DFU bootloader from recent SDKs, the library waits 400 ms before sending bytes of the first data object. You have excluded all debug messages from the log, but it can be seen in the timings here:
2019-12-02 09:32:37.142 I/DfuImpl: Creating Data object (Op Code = 1, Type = 2, Size = 4096) (1/20)
2019-12-02 09:32:37.586 I/DfuImpl: Uploading firmware...
The Uploading firmware... message is sent 400+ ms after the first message is printed. For comparison, creating the second object took 37 ms:
2019-12-02 09:32:38.427 I/DfuImpl: Creating Data object (Op Code = 1, Type = 2, Size = 4096) (2/20)
2019-12-02 09:32:38.464 I/DfuImpl: Uploading firmware..
During our tests we found that those 400 ms delay is required and enough. Without it, the error you get on the 3rd object was coming immediately during sending the first one and no matter how many retries the lib did, some packets were lost, the CRC didn't match and DFU was stopped with an error. With the initial delay it seems to be stable. However, from time to time we also observe that bytes get lost in a later stage. At that time we try to minimize the risk of failure, so the library sets the PRN (Packet Receipt Notifications) to 1:
2019-12-02 09:32:39.305 I/DfuImpl: Checksum received (Offset = 6912, CRC = 044F3C7B)
2019-12-02 09:32:39.306 W/DfuImpl: 1280 bytes were lost!
2019-12-02 09:32:39.324 I/DfuImpl: Sending the number of packets before notifications (Op Code = 2, Value = 1) <- here
2019-12-02 09:32:39.375 I/DfuImpl: CRC does not match! Expected 28531180 but found 044F3C7B. Retrying...(2/3)
so that each packet sent is ack by the DFU target. This means that instead of sending packets as fast as possible, most probably many packets per connection interval, the library now switches to "safe" mode, where it sends one packet in one connection interval, then waits for a PRN in the next interval, etc, so effectively sends 1 packet per 2 connection intervals. You may observe, that sending the 1st took 809 ms:
2019-12-02 09:32:37.586 I/DfuImpl: Uploading firmware...
2019-12-02 09:32:38.030 I/DfuImpl: Sending Calculate Checksum command (Op Code = 3)
2019-12-02 09:32:38.395 I/DfuImpl: Checksum received (Offset = 4096, CRC = 587F0D7E)
but after setting PRN to 1 each next packet took ~9 seconds:
2019-12-02 09:32:39.445 I/DfuImpl: Uploading firmware...
2019-12-02 09:32:48.718 I/DfuImpl: Sending Calculate Checksum command (Op Code = 3)
2019-12-02 09:32:48.755 I/DfuImpl: Checksum received (Offset = 8192, CRC = E273DD66)
What you may do, is to import the DFU library as a module (check how) and modify this part: https://github.com/NordicSemiconductor/Android-DFU-Library/blob/58bd4c2aec66b85e779d8be7d6e05ca8a47cb1ed/dfu/src/main/java/no/nordicsemi/android/dfu/SecureDfuImpl.java#L596-L599 so it does this 400 ms delay for every packet, not only for the first one. 400 ms delay is better than 9 sec. You may also try other values for the delay.
Hi, thanks to analyze the log! I have understood meaning of the log.
However, from time to time we also observe that bytes get lost in a later stage.
--> Why this happen in galaxy 10 note only not galaxy note 4? As I understood, this is a ultimate reason for different speed.
What you may do, is to import the DFU library as a module (check how) and modify this part:
delete condition and only
mService.waitFor(initialDelay);
like this?
Why this happen in galaxy 10 note only not galaxy note 4? As I understood, this is a ultimate reason for different speed.
Yes, I think it's that the newest phones can send data faster than the target can handle. The connection parameters on the peripheral should not allow such situation, but thy do so we have to "slow down" is a bit on the phone side. I don't know what could be some other reason.
like this?
Yes, that should be ok. Please, let me know if it improved the speed and no bytes were lost after that.
I have tired to add module. but the some trouble occur.
ERROR: Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve project :dfu.
What I did was.
delete
//implementation 'no.nordicsemi.android:dfu:1.9.1'
in dependency. replace implementation project(':dfu')
and clone and copy to my project dir as DFULibrary.
In settings.gradle add
include ':dfu'
project(':dfu').projectDir = file('../DFULibrary/dfu')
In the settings.gradle you have to provide the correct path to the dfu folder. By default it is cloned to Android-DFU-Library folder, so if you have it there, replace the DFULibrary with the correct path.
include ':dfu'
project(':dfu').projectDir = file('../Android-DFU-Library/dfu')
I already tried this name. however, It was not working. so I changed directory name Android-DFU-Library to DFULibrary.
Just make sure the path is correct.
device: nRF51822 sdk13.3.0 In galaxy note 4, Dfu takes 40~50 sec. but, In galaxy note 10, It takes almost 3 min. It is obviously slow.
I have used following code.
Does I miss something?