mirror of https://github.com/rusefi/dfu_java.git
logger & leaveDFU
This commit is contained in:
parent
ce9ac815ec
commit
3ca7c5513e
|
@ -3,18 +3,19 @@ package com.rusefi.dfu;
|
|||
import com.rusefi.dfu.commands.DfuCommandGetStatus;
|
||||
|
||||
public class DfuConnectionUtil {
|
||||
public static void waitStatus(DfuConnection device) {
|
||||
DfuCommandGetStatus.State state = DfuCommandGetStatus.read(device);
|
||||
public static void waitStatus(DfuLogic.Logger logger, DfuConnection device) {
|
||||
DfuCommandGetStatus.State state = DfuCommandGetStatus.read(logger, device);
|
||||
System.out.println(" state " + state);
|
||||
while (state == DfuCommandGetStatus.State.DFU_DOWNLOAD_BUSY || state == DfuCommandGetStatus.State.DFU_ERROR) {
|
||||
sleep(106);
|
||||
state = DfuCommandGetStatus.read(device);
|
||||
state = DfuCommandGetStatus.read(logger, device);
|
||||
System.out.println(" state " + state);
|
||||
}
|
||||
}
|
||||
|
||||
public static void sleep(int millis) {
|
||||
System.out.println("Sleep " + millis);
|
||||
public static void sleep(DfuLogic.Logger logger, int millis) {
|
||||
if (millis == 0)
|
||||
return;
|
||||
logger.info("Sleep " + millis);
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.rusefi.dfu;
|
||||
|
||||
import com.rusefi.dfu.commands.DfuSeCommandErasePage;
|
||||
import com.rusefi.dfu.commands.DfuSeCommandSetAddress;
|
||||
import com.rusefi.dfu.commands.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
@ -14,19 +13,19 @@ public class DfuLogic {
|
|||
public static final byte USB_DT_DFU = 0x21;
|
||||
public static final String FLASH_TAG = "Flash";
|
||||
|
||||
public static void uploadImage(DfuConnection device, BinaryImage image, FlashRange range) {
|
||||
public static void uploadImage(Logger logger, DfuConnection device, BinaryImage image, FlashRange range) {
|
||||
List<Integer> erasePages = range.pagesForSize(image.getImageSize());
|
||||
// todo: smarted start address logic
|
||||
int eraseAddress = 0x08000000;
|
||||
for (Integer erasePage : erasePages) {
|
||||
DfuSeCommandErasePage.execute(device, eraseAddress);
|
||||
DfuSeCommandErasePage.execute(logger, device, eraseAddress);
|
||||
eraseAddress += erasePage;
|
||||
}
|
||||
System.out.println(String.format("Erased up to %x", eraseAddress));
|
||||
logger.info(String.format("Erased up to %x", eraseAddress));
|
||||
|
||||
for (int offset = 0; offset < image.getImage().length; offset += device.getTransferSize()) {
|
||||
DfuSeCommandSetAddress.execute(device, device.getFlashRange().getBaseAddress() + offset);
|
||||
DfuConnectionUtil.waitStatus(device);
|
||||
DfuSeCommandSetAddress.execute(logger, device, device.getFlashRange().getBaseAddress() + offset);
|
||||
DfuConnectionUtil.waitStatus(logger, device);
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(device.getTransferSize());
|
||||
// last transfer would usually be smaller than transfer size
|
||||
|
@ -35,7 +34,49 @@ public class DfuLogic {
|
|||
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. "
|
||||
DfuConnectionUtil.waitStatus(device);
|
||||
DfuConnectionUtil.waitStatus(logger, device);
|
||||
}
|
||||
}
|
||||
|
||||
public static void leaveDFU(Logger logger, DfuConnection device) {
|
||||
device.sendData(DfuCommmand.DNLOAD, DfuSeCommand.W_DNLOAD, ByteBuffer.allocateDirect(0));
|
||||
// The DFU Leave operation is effectively executed only when a DFU_GETSTATUS request is
|
||||
// issued by the host.
|
||||
DfuConnectionUtil.waitStatus(logger, device);
|
||||
}
|
||||
|
||||
public static void startup(Logger logger, DfuConnection device) {
|
||||
DfuCommandGetStatus.State state = DfuCommandGetStatus.read(logger, device);
|
||||
logger.info("DFU state: " + state);
|
||||
switch (state) {
|
||||
case DFU_IDLE:
|
||||
// best status
|
||||
break;
|
||||
case DFU_ERROR:
|
||||
DfuCommandClearStatus.execute(device);
|
||||
break;
|
||||
case DFU_DOWNLOAD_SYNC:
|
||||
case DFU_DOWNLOAD_IDLE:
|
||||
case DFU_UPLOAD_IDLE:
|
||||
case DFU_MANIFEST_SYNC:
|
||||
case DFU_DOWNLOAD_BUSY:
|
||||
case DFU_MANIFEST:
|
||||
DfuCommandAbort.execute(device);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected state " + state);
|
||||
}
|
||||
state = DfuCommandGetStatus.read(logger, device);
|
||||
if (state != DfuCommandGetStatus.State.DFU_IDLE)
|
||||
throw new IllegalStateException("Not idle on start-up");
|
||||
}
|
||||
|
||||
public interface Logger {
|
||||
Logger VOID = message -> {
|
||||
};
|
||||
|
||||
Logger CONSOLE = System.out::println;
|
||||
|
||||
void info(String message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ import android.hardware.usb.*;
|
|||
import com.rusefi.dfu.DfuLogic;
|
||||
import com.rusefi.dfu.DfuSeFlashDescriptor;
|
||||
import com.rusefi.dfu.FlashRange;
|
||||
//import com.rusefi.dfu.LogUtil;
|
||||
//import org.apache.commons.logging.Log;
|
||||
|
||||
public class DfuDeviceLocator {
|
||||
// private static final Log log = LogUtil.getLog(DfuDeviceLocator.class);
|
||||
|
|
|
@ -2,28 +2,64 @@ package com.rusefi.dfu.commands;
|
|||
|
||||
import com.rusefi.dfu.DfuCommmand;
|
||||
import com.rusefi.dfu.DfuConnection;
|
||||
import com.rusefi.dfu.DfuConnectionUtil;
|
||||
import com.rusefi.dfu.DfuLogic;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class DfuCommandGetStatus {
|
||||
private static final int PACKET_SIZE = 6;
|
||||
|
||||
public static State read(DfuConnection session) {
|
||||
public static State read(DfuLogic.Logger logger, DfuConnection 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);
|
||||
return State.DFU_ERROR;
|
||||
buffer.rewind();
|
||||
buffer.get(); // status
|
||||
buffer.get(); // timeout
|
||||
buffer.get(); // timeout
|
||||
buffer.get(); // timeout
|
||||
Status status = Status.valueOf(buffer.get()); // status
|
||||
int timeout = buffer.get();
|
||||
timeout = timeout | (buffer.get() << 8);
|
||||
timeout = timeout | (buffer.get() << 8);
|
||||
System.out.println("During " + status + " timeout=" + timeout);
|
||||
byte state = buffer.get();
|
||||
DfuConnectionUtil.sleep(logger, timeout);
|
||||
return State.valueOf(state);
|
||||
}
|
||||
|
||||
public enum Status {
|
||||
OK(0x00),
|
||||
ERROR_TARGET(0x01),
|
||||
ERROR_FILE(0x02),
|
||||
ERROR_WRITE(0x03),
|
||||
ERROR_ERASE(0x04),
|
||||
ERROR_CHECK_ERASED(0x05),
|
||||
ERROR_PROG(0x06),
|
||||
ERROR_VERIFY(0x07),
|
||||
ERROR_ADDRESS(0x08),
|
||||
ERROR_NOTDONE(0x09),
|
||||
ERROR_FIRMWARE(0x0a),
|
||||
ERROR_VENDOR(0x0b),
|
||||
ERROR_USBR(0x0c),
|
||||
ERROR_POR(0x0d),
|
||||
ERROR_UNKNOWN(0x0e),
|
||||
ERROR_STALLEDPKT(0x0f);
|
||||
|
||||
private final byte value;
|
||||
|
||||
Status(int value) {
|
||||
this.value = (byte) value;
|
||||
}
|
||||
|
||||
public static Status valueOf(byte value) {
|
||||
for (Status s : Status.values()) {
|
||||
if (s.value == value) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum State {
|
||||
APP_IDLE(0x00),
|
||||
APP_DETACH(0x01),
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
package com.rusefi.dfu.commands;
|
||||
|
||||
import com.rusefi.dfu.*;
|
||||
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(DfuConnection session, int address) {
|
||||
log.info(String.format("SetAddress %x", address));
|
||||
public static void execute(DfuLogic.Logger logger, DfuConnection session, int address) {
|
||||
logger.info(String.format("SetAddress %x", address));
|
||||
ByteBuffer buffer = DfuSeCommandSetAddress.createSpecialCommandBuffer(DfuSeCommand.SE_ERASE_PAGE, address);
|
||||
session.sendData(DfuCommmand.DNLOAD, DfuSeCommand.W_SPECIAL, buffer);
|
||||
DfuConnectionUtil.waitStatus(session);
|
||||
DfuConnectionUtil.waitStatus(logger, session);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,15 @@ package com.rusefi.dfu.commands;
|
|||
|
||||
import com.rusefi.dfu.DfuCommmand;
|
||||
import com.rusefi.dfu.DfuConnection;
|
||||
import com.rusefi.dfu.DfuLogic;
|
||||
import com.rusefi.dfu.DfuSeCommand;
|
||||
import com.rusefi.dfu.LogUtil;
|
||||
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(DfuConnection session, int address) {
|
||||
log.info(String.format("SetAddress %x", address));
|
||||
public static void execute(DfuLogic.Logger logger, DfuConnection session, int address) {
|
||||
logger.info(String.format("SetAddress %x", address));
|
||||
ByteBuffer buffer = createSpecialCommandBuffer(DfuSeCommand.SE_SET_ADDRESS, address);
|
||||
session.sendData(DfuCommmand.DNLOAD, DfuSeCommand.W_SPECIAL, buffer);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
package com.rusefi.dfu.usb4java;
|
||||
|
||||
import com.rusefi.dfu.DfuLogic;
|
||||
import com.rusefi.dfu.DfuSeFlashDescriptor;
|
||||
import com.rusefi.dfu.FlashRange;
|
||||
import com.rusefi.dfu.LogUtil;
|
||||
import com.rusefi.dfu.commands.DfuCommandAbort;
|
||||
import com.rusefi.dfu.commands.DfuCommandClearStatus;
|
||||
import com.rusefi.dfu.commands.DfuCommandGetStatus;
|
||||
import com.rusefi.dfu.*;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.usb4java.*;
|
||||
|
||||
|
@ -27,11 +21,11 @@ public class DfuDeviceLocator {
|
|||
return context;
|
||||
}
|
||||
|
||||
public static USBDfuConnection findDevice() {
|
||||
return findDevice(openContext(), DfuLogic.ST_VENDOR, (short) DfuLogic.ST_DFU_PRODUCT);
|
||||
public static USBDfuConnection findDevice(DfuLogic.Logger logger) {
|
||||
return findDevice(logger, openContext(), DfuLogic.ST_VENDOR, (short) DfuLogic.ST_DFU_PRODUCT);
|
||||
}
|
||||
|
||||
private static USBDfuConnection findDevice(Context context, short vendorId, short productId) {
|
||||
private static USBDfuConnection findDevice(DfuLogic.Logger logger, Context context, short vendorId, short productId) {
|
||||
// Read the USB device list
|
||||
DeviceList list = new DeviceList();
|
||||
int result = LibUsb.getDeviceList(context, list);
|
||||
|
@ -48,7 +42,7 @@ public class DfuDeviceLocator {
|
|||
if (result != LibUsb.SUCCESS)
|
||||
throw new LibUsbException("getDeviceDescriptor", result);
|
||||
if (descriptor.idVendor() == vendorId && descriptor.idProduct() == productId) {
|
||||
return findDfuInterface(device, descriptor);
|
||||
return findDfuInterface(logger, device, descriptor);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -64,7 +58,7 @@ public class DfuDeviceLocator {
|
|||
return (((x & 0xff) << 8) | ((x >> 8) & 0xff));
|
||||
}
|
||||
|
||||
public static USBDfuConnection findDfuInterface(Device device, DeviceDescriptor deviceDescriptor) {
|
||||
public static USBDfuConnection findDfuInterface(DfuLogic.Logger logger, Device device, DeviceDescriptor deviceDescriptor) {
|
||||
byte numConfigurations = deviceDescriptor.bNumConfigurations();
|
||||
|
||||
appendInfo(numConfigurations + " configuration(s)");
|
||||
|
@ -154,29 +148,7 @@ public class DfuDeviceLocator {
|
|||
|
||||
USBDfuConnection session = new USBDfuConnection(deviceHandle, interfaceNumber, transferSize, flashRange);
|
||||
|
||||
DfuCommandGetStatus.State state = DfuCommandGetStatus.read(session);
|
||||
log.info("DFU state: " + state);
|
||||
switch (state) {
|
||||
case DFU_IDLE:
|
||||
// best status
|
||||
break;
|
||||
case DFU_ERROR:
|
||||
DfuCommandClearStatus.execute(session);
|
||||
break;
|
||||
case DFU_DOWNLOAD_SYNC:
|
||||
case DFU_DOWNLOAD_IDLE:
|
||||
case DFU_UPLOAD_IDLE:
|
||||
case DFU_MANIFEST_SYNC:
|
||||
case DFU_DOWNLOAD_BUSY:
|
||||
case DFU_MANIFEST:
|
||||
DfuCommandAbort.execute(session);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected state " + state);
|
||||
}
|
||||
state = DfuCommandGetStatus.read(session);
|
||||
if (state != DfuCommandGetStatus.State.DFU_IDLE)
|
||||
throw new IllegalStateException("Not idle");
|
||||
DfuLogic.startup(logger, session);
|
||||
|
||||
|
||||
System.out.printf("info:\n" + usbInfo);
|
||||
|
|
|
@ -48,7 +48,7 @@ public class DfuLogicTest {
|
|||
|
||||
|
||||
|
||||
DfuLogic.uploadImage(device, image, range);
|
||||
DfuLogic.uploadImage(DfuLogic.Logger.VOID, device, image, range);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ public class Sandbox {
|
|||
public static void main(String[] args) throws IOException, IntelHexException {
|
||||
log.info("Hello sandbox");
|
||||
|
||||
USBDfuConnection device = DfuDeviceLocator.findDevice();
|
||||
DfuLogic.Logger logger = DfuLogic.Logger.CONSOLE;
|
||||
USBDfuConnection device = DfuDeviceLocator.findDevice(logger);
|
||||
if (device == null) {
|
||||
System.err.println("No DFU devices found");
|
||||
return;
|
||||
|
@ -22,7 +23,8 @@ public class Sandbox {
|
|||
|
||||
HexImage image = HexImage.loadHexToBuffer(new FileInputStream("rusefi.hex"), device.getFlashRange());
|
||||
|
||||
DfuLogic.uploadImage(device, image, device.getFlashRange());
|
||||
DfuLogic.uploadImage(logger, device, image, device.getFlashRange());
|
||||
DfuLogic.leaveDFU(logger, device);
|
||||
|
||||
log.info("STM32 DFU " + device);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue