Does not work yet but getting closer?

This commit is contained in:
rusefi 2020-06-27 19:53:14 -04:00
parent 32d17463fc
commit 00ff85c536
10 changed files with 138 additions and 43 deletions

View File

@ -8,11 +8,7 @@ public enum DfuCommmand {
CLRSTATUS(4),
GETSTATE(5),
ABORT(6),
/**
* http://dfu-util.sourceforge.net/dfuse.html
*/
SE_SET_ADDRESS(0x21);
;
private final byte value;

View File

@ -1,16 +1,38 @@
package com.rusefi.dfu;
import com.rusefi.dfu.commands.DfuCommandGetStatus;
import com.rusefi.dfu.usb4java.USBDfuConnection;
import java.nio.ByteBuffer;
public interface DfuConnection {
int SECOND = 1000;
int DFU_TIMEOUT = 10 * DfuConnection.SECOND;
static void waitStatus(USBDfuConnection device) {
DfuCommandGetStatus.State state = DfuCommandGetStatus.read(device);
System.out.println(" state " + state);
while (state == DfuCommandGetStatus.State.DFU_DOWNLOAD_BUSY || state == DfuCommandGetStatus.State.DFU_ERROR) {
sleep(106);
state = DfuCommandGetStatus.read(device);
System.out.println(" state " + state);
}
}
static void sleep(int millis) {
System.out.println("Sleep " + millis);
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
FlashRange getFlashRange();
int getTransferSize();
int receiveData(DfuCommmand command, short value, ByteBuffer data);
int receiveData(DfuCommmand command, short wValue, ByteBuffer data);
int sendData(DfuCommmand command, short value, ByteBuffer data);
int sendData(DfuCommmand command, short wValue, ByteBuffer data);
}

View File

@ -0,0 +1,13 @@
package com.rusefi.dfu;
public class DfuSeCommand {
public static final short W_SPECIAL = 0;
public static final short W_DNLOAD = 2;
/**
* http://dfu-util.sourceforge.net/dfuse.html
*/
public static byte SE_SET_ADDRESS = 0x21;
public static byte SE_ERASE_PAGE = 0x41;
}

View File

@ -11,6 +11,8 @@ public class DfuCommandGetStatus {
public static State read(USBDfuConnection session) {
ByteBuffer buffer = ByteBuffer.allocateDirect(PACKET_SIZE);
int count = session.receiveData(DfuCommmand.GETSTATUS, (short) 0, buffer);
if (count == 0)
return State.DFU_ERROR;
if (count != PACKET_SIZE)
throw new IllegalStateException("Got " + count);
buffer.rewind();

View File

@ -0,0 +1,21 @@
package com.rusefi.dfu.commands;
import com.rusefi.dfu.DfuCommmand;
import com.rusefi.dfu.DfuConnection;
import com.rusefi.dfu.DfuSeCommand;
import com.rusefi.dfu.usb4java.LogUtil;
import com.rusefi.dfu.usb4java.USBDfuConnection;
import org.apache.commons.logging.Log;
import java.nio.ByteBuffer;
public class DfuSeCommandErasePage {
private static final Log log = LogUtil.getLog(DfuSeCommandErasePage.class);
public static void execute(USBDfuConnection session, int address) {
log.info(String.format("SetAddress %x", address));
ByteBuffer buffer = DfuSeCommandSetAddress.createSpecialCommandBuffer(DfuSeCommand.SE_ERASE_PAGE, address);
session.sendData(DfuCommmand.DNLOAD, DfuSeCommand.W_SPECIAL, buffer);
DfuConnection.waitStatus(session);
}
}

View File

@ -1,14 +1,35 @@
package com.rusefi.dfu.commands;
import com.rusefi.dfu.DfuCommmand;
import com.rusefi.dfu.DfuSeCommand;
import com.rusefi.dfu.usb4java.LogUtil;
import com.rusefi.dfu.usb4java.USBDfuConnection;
import org.apache.commons.logging.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class DfuSeCommandSetAddress {
private static final Log log = LogUtil.getLog(DfuSeCommandSetAddress.class);
public static void execute(USBDfuConnection session, int address) {
ByteBuffer buffer = ByteBuffer.allocateDirect(4);
log.info(String.format("SetAddress %x", address));
ByteBuffer buffer = createSpecialCommandBuffer(DfuSeCommand.SE_SET_ADDRESS, address);
buffer.putInt(address);
session.sendData(DfuCommmand.CLRSTATUS, (short) 0, buffer);
session.sendData(DfuCommmand.DNLOAD, DfuSeCommand.W_SPECIAL, buffer);
}
protected static ByteBuffer createSpecialCommandBuffer(byte command, int address) {
ByteBuffer buffer = createBuffer(5);
buffer.put(command);
// buffer.rewind();
// byte[] t = new byte[4];
// buffer.get(t);
buffer.putInt(address);
return buffer;
}
protected static ByteBuffer createBuffer(int capacity) {
return ByteBuffer.allocateDirect(capacity).order(ByteOrder.LITTLE_ENDIAN);
}
}

View File

@ -34,21 +34,21 @@ public class USBDfuConnection implements DfuConnection {
}
@Override
public int receiveData(DfuCommmand command, short value, ByteBuffer data) {
return transfer(command, value, data, LibUsb.ENDPOINT_IN);
public int receiveData(DfuCommmand command, short wValue, ByteBuffer data) {
return transfer(command, wValue, data, LibUsb.ENDPOINT_IN);
}
@Override
public int sendData(DfuCommmand command, short value, ByteBuffer data) {
return transfer(command, value, data, LibUsb.ENDPOINT_OUT);
public int sendData(DfuCommmand command, short wValue, ByteBuffer data) {
return transfer(command, wValue, data, LibUsb.ENDPOINT_OUT);
}
private int transfer(DfuCommmand command, short value, ByteBuffer data, byte mode) {
private int transfer(DfuCommmand command, short wValue, ByteBuffer data, byte mode) {
return LibUsb.controlTransfer(
deviceHandle,
(byte) (mode | LibUsb.REQUEST_TYPE_CLASS | LibUsb.RECIPIENT_INTERFACE),
command.getValue(),
value,
wValue,
interfaceNumber,
data,
DFU_TIMEOUT);

View File

@ -10,11 +10,15 @@ import java.util.concurrent.atomic.AtomicInteger;
public class HexImage extends AtomicInteger {
private final byte[] image;
private final FlashRange range;
private final int totalBytes;
private final int maxOffset;
public HexImage(byte[] image, int totalBytes) {
public HexImage(byte[] image, FlashRange range, int totalBytes, int maxOffset) {
this.image = image;
this.range = range;
this.totalBytes = totalBytes;
this.maxOffset = maxOffset;
}
static HexImage loadHexToBuffer(InputStream is, FlashRange range) throws IntelHexException, IOException {
@ -24,6 +28,8 @@ public class HexImage extends AtomicInteger {
Parser ihp = new Parser(is);
AtomicInteger totalBytesReceived = new AtomicInteger();
AtomicInteger maxOffset = new AtomicInteger();
// register parser listener
ihp.setDataListener(new DataListener() {
@Override
@ -31,6 +37,8 @@ public class HexImage extends AtomicInteger {
// System.out.printf("Address %x size %x\n", address, data.length);
totalBytesReceived.addAndGet(data.length);
maxOffset.set((int) Math.max(maxOffset.get(), address + data.length));
if (address < range.getBaseAddress() || address + data.length > range.getBaseAddress() + range.getTotalLength())
throw new IllegalStateException(String.format("Image data out of range: %x@%x not withiin %s",
data.length,
@ -46,7 +54,9 @@ public class HexImage extends AtomicInteger {
});
ihp.parse();
return new HexImage(image, totalBytesReceived.get());
maxOffset.set(range.getBaseAddress() + 16 * 1024);
return new HexImage(image, range, totalBytesReceived.get(), maxOffset.get());
}
public byte[] getImage() {
@ -56,4 +66,22 @@ public class HexImage extends AtomicInteger {
public int getTotalBytes() {
return totalBytes;
}
public int getMaxOffset() {
return maxOffset;
}
public FlashRange getRange() {
return range;
}
@Override
public String toString() {
return "HexImage{" +
"image=" + image.length +
", range=" + range +
", totalBytes=" + totalBytes +
", maxOffset=" + maxOffset +
'}';
}
}

View File

@ -12,7 +12,7 @@ public class HexReaderSandbox {
HexImage image = HexImage.loadHexToBuffer(new FileInputStream("rusefi.hex"), range);
System.out.println("Total received " + image.getTotalBytes());
System.out.println("Total received " + image);
}
}

View File

@ -1,6 +1,6 @@
package com.rusefi.dfu;
import com.rusefi.dfu.commands.DfuCommandGetStatus;
import com.rusefi.dfu.commands.DfuSeCommandErasePage;
import com.rusefi.dfu.commands.DfuSeCommandSetAddress;
import com.rusefi.dfu.usb4java.DfuDeviceLocator;
import com.rusefi.dfu.usb4java.LogUtil;
@ -26,37 +26,29 @@ public class Sandbox {
HexImage image = HexImage.loadHexToBuffer(new FileInputStream("rusefi.hex"), device.getFlashRange());
for (int offset = 0; offset < device.getFlashRange().getTotalLength(); offset += device.getTransferSize()) {
System.out.println("Handing offset " + offset);
DfuSeCommandErasePage.execute(device, 0x08000000);
DfuSeCommandErasePage.execute(device, 0x08004000);
DfuSeCommandErasePage.execute(device, 0x08008000);
DfuSeCommandErasePage.execute(device, 0x0800C000);
DfuSeCommandErasePage.execute(device, 0x08010000);
DfuSeCommandErasePage.execute(device, 0x08020000);
DfuSeCommandErasePage.execute(device, 0x08040000);
for (int offset = 0; offset < image.getMaxOffset() - image.getRange().getBaseAddress(); offset += device.getTransferSize()) {
System.out.println("Handling offset " + offset);
DfuSeCommandSetAddress.execute(device, device.getFlashRange().getBaseAddress() + offset);
waitStatus(device);
DfuConnection.waitStatus(device);
ByteBuffer buffer = ByteBuffer.allocateDirect(device.getTransferSize());
buffer.put(image.getImage(), offset, device.getTransferSize());
device.sendData(DfuCommmand.DNLOAD, (short) 2, buffer);
waitStatus(device);
device.sendData(DfuCommmand.DNLOAD, DfuSeCommand.W_DNLOAD, buffer);
// AN3156 USB DFU protocol used in the STM32 bootloader
// "The Write memory operation is effectively executed only when a DFU_GETSTATUS request is issued by the host. "
DfuConnection.waitStatus(device);
}
log.info("STM32 DFU " + device);
}
private static void waitStatus(USBDfuConnection device) {
DfuCommandGetStatus.State state = DfuCommandGetStatus.read(device);
System.out.println(" state " + state);
while (state == DfuCommandGetStatus.State.DFU_DOWNLOAD_BUSY) {
sleep(106);
state = DfuCommandGetStatus.read(device);
System.out.println(" state " + state);
}
}
private static void sleep(int millis) {
System.out.println("Sleep " + millis);
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}