logger & leaveDFU

This commit is contained in:
rusefi 2020-07-05 17:17:13 -04:00
parent ce9ac815ec
commit 3ca7c5513e
9 changed files with 118 additions and 74 deletions

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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),

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -48,7 +48,7 @@ public class DfuLogicTest {
DfuLogic.uploadImage(device, image, range);
DfuLogic.uploadImage(DfuLogic.Logger.VOID, device, image, range);
}
}

View File

@ -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);
}