Implementing DFU over I2C, only ACK byte received
Hi,
I am implementing DFU over I2C to an STM32L476, trying to follow AN4221 and AN2606.
For now I am focused on just getting some DFU command to work successfully over I2C, and I started with "Get Version" to get the bootloader version. I am able to get the ACK byte back (0x79), but not the rest of the data.
I first tried to write the command (and the following for the checksum), and then try to receive the 3 bytes that are specified. ACK, $version, ACK. In pseudo code:
beginTransmission(0x43); // slave address, 7bit
write(0x01); // cmd = GetVersion
write(0xFE); // complimentary of cmd, for XOR checksumming
endTransmission(STOP);
data = read(3, STOP);
In this case I get an error indicating that less than 3 bytes was received.
Is it not correct to expect the protocol to be able to work like this?
Since the documentation flowcharts indicates for host to "wait for ACK" (although the device flowchart does not mention it). I also tried to first read 1 byte for the ACK, check it, and then wait for the remaining 2 bytes. In this case I get the ACK byte successfully, but then nothing for. I have tried to omit the STOP condition.
beginTransmission(0x43); // slave address, 7bit
write(0x01); // cmd = GetVersion
write(0xFE); // complimentary of cmd, for XOR checksumming
endTransmission(STOP);
ack = read(1, STOP); // or NOSTOP, no change
if ack == 0x79
data = read(2, STOP);
At this point I am unsure what else to try in terms of protocol changes. Any tips and tricks welcomed.
Is there any reference implementation of this available?
More details:
The device is put into the sytem bootloader using the BOOT0/RESET pins. I always do this, then wait 1 second, before attempt I2C communication. The ACK byte is reliably transmitted, 5/5 times per each test-run.
The host board, which will do the programming, is a Particle P1 (STM32F2xx I think). There are other I2C devices on the bus, like a screen and I/O expander, etc. I have check and there should be no conflict for the address.
The Arduino-style `Wire` I2C library provided by Particle is used for communication (it uses STM32 HAL underneath, implementation can be found here https://github.com/particle-iot/device-os/blob/develop/hal/src/stm32f2xx/i2c_hal.c). This is used successfully with the other pheripherals, is in production for several years now.
I have also tested to program the slave board over I2C using the stm32flash utility from an Embedded Linux machine, and that worked OK.
