Bug fixed: initial execute of data when offset % size == 0

This commit is contained in:
Aleksander Nowakowski 2016-06-22 14:29:26 +02:00
parent eef6f798b8
commit 841a3abda4
3 changed files with 29 additions and 32 deletions

View File

@ -118,7 +118,7 @@ import android.support.annotation.NonNull;
public float getSpeed() { public float getSpeed() {
final long now = SystemClock.elapsedRealtime(); final long now = SystemClock.elapsedRealtime();
final float speed = now - timeStart != 0 ? (float) (bytesSent - lastBytesSent - initalBytesSent) / (float) (now - lastProgressTime) : 0.0f; final float speed = now - timeStart != 0 ? (float) (bytesSent - lastBytesSent) / (float) (now - lastProgressTime) : 0.0f;
lastProgressTime = now; lastProgressTime = now;
lastBytesSent = bytesSent; lastBytesSent = bytesSent;
return speed; return speed;

View File

@ -258,7 +258,7 @@ import no.nordicsemi.android.error.SecureDfuError;
* <li>If offset == init file size - it will send Execute command to execute the Init file, as it may have not been executed before.</li> * <li>If offset == init file size - it will send Execute command to execute the Init file, as it may have not been executed before.</li>
* </ul> * </ul>
* </li> * </li>
* <li>If the CRCs don't match, or the received offset is greater then init file size, it creates the Command Object and sends the whole * <li>If the CRC don't match, or the received offset is greater then init file size, it creates the Command Object and sends the whole
* Init file as the previous one was different.</li> * Init file as the previous one was different.</li>
* </ol> * </ol>
* Sending of the Init packet is done without using PRNs (Packet Receipt Notifications), so they are disabled prior to sending the data. * Sending of the Init packet is done without using PRNs (Packet Receipt Notifications), so they are disabled prior to sending the data.
@ -302,7 +302,7 @@ import no.nordicsemi.android.error.SecureDfuError;
// There is no need to send it again. We may try to resume sending data. // There is no need to send it again. We may try to resume sending data.
logi("-> Whole Init packet was sent before"); logi("-> Whole Init packet was sent before");
skipSendingInitPacket = true; skipSendingInitPacket = true;
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Command object match Init packet"); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Received CRC match Init packet");
} else { } else {
logi("-> " + info.offset + " bytes of Init packet were sent before"); logi("-> " + info.offset + " bytes of Init packet were sent before");
resumeSendingInitPacket = true; resumeSendingInitPacket = true;
@ -360,8 +360,8 @@ import no.nordicsemi.android.error.SecureDfuError;
} else { } else {
if (attempt < MAX_ATTEMPTS) { if (attempt < MAX_ATTEMPTS) {
attempt++; attempt++;
logi("CRC32 does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")"); logi("CRC does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_WARNING, "CRC32 does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")"); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_WARNING, "CRC does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")");
try { try {
// Go back to the beginning, we will send the whole Init packet again // Go back to the beginning, we will send the whole Init packet again
resumeSendingInitPacket = false; resumeSendingInitPacket = false;
@ -375,8 +375,8 @@ import no.nordicsemi.android.error.SecureDfuError;
return; return;
} }
} else { } else {
loge("CRC32 does not match!"); loge("CRC does not match!");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_ERROR, "CRC32 does not match!"); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_ERROR, "CRC does not match!");
mService.terminateConnection(gatt, DfuBaseService.ERROR_CRC_ERROR); mService.terminateConnection(gatt, DfuBaseService.ERROR_CRC_ERROR);
return; return;
} }
@ -436,6 +436,12 @@ import no.nordicsemi.android.error.SecureDfuError;
int bytesSentAndExecuted = info.maxSize * currentChunk; int bytesSentAndExecuted = info.maxSize * currentChunk;
int bytesSentNotExecuted = info.offset - bytesSentAndExecuted; int bytesSentNotExecuted = info.offset - bytesSentAndExecuted;
// If the offset is dividable by maxSize, assume that the last page was not executed
if (bytesSentNotExecuted == 0) {
bytesSentAndExecuted -= info.maxSize;
bytesSentNotExecuted = info.maxSize;
}
// Read the same number of bytes from the current init packet to calculate local CRC32 // Read the same number of bytes from the current init packet to calculate local CRC32
if (bytesSentAndExecuted > 0) { if (bytesSentAndExecuted > 0) {
mFirmwareStream.read(new byte[bytesSentAndExecuted]); // Read executed bytes mFirmwareStream.read(new byte[bytesSentAndExecuted]); // Read executed bytes
@ -452,15 +458,18 @@ import no.nordicsemi.android.error.SecureDfuError;
if (crc == info.CRC32) { if (crc == info.CRC32) {
mProgressInfo.setBytesSent(info.offset); mProgressInfo.setBytesSent(info.offset);
mProgressInfo.setBytesReceived(info.offset); mProgressInfo.setBytesReceived(info.offset);
resumeSendingData = true; mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, info.offset + " bytes of data sent before, CRC match");
// If the whole page was sent and CRC match, we have to make sure it was executed
if (bytesSentNotExecuted == info.maxSize && info.offset < mImageSizeInBytes) {
logi("Executing data object (Op Code = 4)");
writeExecute();
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Data object executed");
} else { } else {
if (bytesSentNotExecuted == 0) { resumeSendingData = true;
// Looks like the whole last chunk was invalid and not executed. We have to rewind last maxSize bytes as we don't have any mark there.
bytesSentAndExecuted -= info.maxSize;
bytesSentNotExecuted = info.maxSize;
((ArchiveInputStream) mFirmwareStream).rewind(info.maxSize);
mFirmwareStream.mark(info.maxSize);
} }
} else {
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_WARNING, info.offset + " bytes sent before, CRC does not match");
// The CRC of the current object is not correct. If there was another Data object sent before, its CRC must have been correct, // The CRC of the current object is not correct. If there was another Data object sent before, its CRC must have been correct,
// as it has been executed. Either way, we have to create the current object again. // as it has been executed. Either way, we have to create the current object again.
mProgressInfo.setBytesSent(bytesSentAndExecuted); mProgressInfo.setBytesSent(bytesSentAndExecuted);
@ -468,6 +477,7 @@ import no.nordicsemi.android.error.SecureDfuError;
info.offset -= bytesSentNotExecuted; info.offset -= bytesSentNotExecuted;
info.CRC32 = 0; // invalidate info.CRC32 = 0; // invalidate
mFirmwareStream.reset(); mFirmwareStream.reset();
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Resuming from byte " + info.offset + "...");
} }
} catch (final IOException e) { } catch (final IOException e) {
loge("Error while reading firmware stream", e); loge("Error while reading firmware stream", e);
@ -525,8 +535,8 @@ import no.nordicsemi.android.error.SecureDfuError;
} else { } else {
if (attempt < MAX_ATTEMPTS) { if (attempt < MAX_ATTEMPTS) {
attempt++; attempt++;
logi("CRC32 does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")"); logi("CRC does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_WARNING, "CRC32 does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")"); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_WARNING, "CRC does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")");
try { try {
mFirmwareStream.reset(); mFirmwareStream.reset();
mProgressInfo.setBytesSent(checksum.offset - info.maxSize); mProgressInfo.setBytesSent(checksum.offset - info.maxSize);
@ -536,8 +546,8 @@ import no.nordicsemi.android.error.SecureDfuError;
return; return;
} }
} else { } else {
loge("CRC32 does not match!"); loge("CRC does not match!");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_ERROR, "CRC32 does not match!"); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_ERROR, "CRC does not match!");
mService.terminateConnection(gatt, DfuBaseService.ERROR_CRC_ERROR); mService.terminateConnection(gatt, DfuBaseService.ERROR_CRC_ERROR);
return; return;
} }

View File

@ -350,19 +350,6 @@ public class ArchiveInputStream extends ZipInputStream {
bytesReadFromMarkedSource = bytesReadFromCurrentSource; bytesReadFromMarkedSource = bytesReadFromCurrentSource;
} }
public void rewind(final int offset) {
if (applicationBytes != null && (softDeviceBytes != null || bootloaderBytes != null || softDeviceAndBootloaderBytes != null))
throw new UnsupportedOperationException("Application must be sent in a separate connection.");
bytesRead = Math.max(bytesRead - offset, 0);
if (currentSource == bootloaderBytes && softDeviceBytes != null && bytesReadFromCurrentSource - offset < 0) {
currentSource = softDeviceBytes;
bytesReadFromCurrentSource = Math.max(softDeviceSize - (offset - bytesReadFromCurrentSource), 0);
} else {
bytesReadFromCurrentSource -= Math.max(bytesReadFromCurrentSource - offset, 0);
}
}
@Override @Override
public void reset() throws IOException { public void reset() throws IOException {
if (applicationBytes != null && (softDeviceBytes != null || bootloaderBytes != null || softDeviceAndBootloaderBytes != null)) if (applicationBytes != null && (softDeviceBytes != null || bootloaderBytes != null || softDeviceAndBootloaderBytes != null))