osd-contiki/tools/stm32w/stm32w_flasher/py_files/ymodem.py

242 lines
6.7 KiB
Python
Raw Normal View History

# See comment in stm32w_flasher.py.
# Extraction and little adaptation performed by E.Duble (CNRS, LIG).
import os
import serial
import struct
import time
from messages import errorMessage
from messages import infoMessage
class Ymodem():
ABORT1 = 65
ABORT2 = 97
ACK = 6
CA = 24
CRC16 = 67
EOT = 4
NAK = 21
PACKET_1K_SIZE = 1024
PACKET_HEADER = 3
PACKET_OVERHEAD = 5
PACKET_SIZE = 128
PACKET_TRAILER = 2
SOH = 1
STATE_DONE = 6
STATE_READY = 2
STATE_SEND_EOT = 3
STATE_SEND_SESSION_DONE = 4
STATE_START_APPLICATION = 5
STATE_WAITING_ACK = 1
STATE_WAITING_CRC16 = 0
STX = 2
YMODEM_RX_TO_TX = 2
YMODEM_TX_TO_RX = 0
YMODEM_TX_TO_RX2 = 1
def Crc16X(self, packet, count):
j = 0
crc = 0
for j in range(count):
crc = (crc ^ ((packet[j]) << 8))
for i in range(8):
if (crc & 32768):
crc = ((crc << 1) ^ 4129)
continue
else:
crc = (crc << 1)
continue
continue
return crc
def __init__(self, serialPort, port, updateAction=None):
self.serialPort = serialPort
self.updateAction = updateAction
self.port = port
return None
def bootloaderInit(self):
returnValue = False
systemRestartPacket = [170, 1, 7, 85]
self.serialPort.write(struct.pack(('B' * len(systemRestartPacket)), *systemRestartPacket))
self.serialPort.close()
time.sleep(5)
self.serialPort = serial.Serial(port, 10, timeout=4)
self.serialPort.flushInput()
systemRestartPacket = [170, 1, 5, 85]
self.serialPort.write(struct.pack(('B' * len(systemRestartPacket)), *systemRestartPacket))
self.serialPort.read(4)
for i in range(10):
startTime = time.time()
while (time.time() - startTime) < 0.5:
if self.serialPort.inWaiting() > 0:
c = self.serialPort.read(1)
c = (struct.unpack('B', c)[0])
if c == ord('C'):
returnValue = True
break
time.sleep(0.01)
continue
continue
return returnValue
def getByte(self):
data = None
if self.serialPort.inWaiting() > 0:
data = (struct.unpack('B', self.serialPort.read(1))[0])
if data:
pass
return data
def loadFile(self, name):
returnValue = True
state = self.STATE_WAITING_CRC16
filename = os.path.basename(name)
startTime = time.time()
try:
f = open(name, 'rb')
infoMessage((('File ' + name) + ' opened\n'))
f.seek(0, 2)
file_size = f.tell()
f.seek(0, 0)
packet_number = 0
loop_counter = 1
size = file_size
retry = 0
packet = []
prevState = self.STATE_READY
while True:
newState = state
if state == self.STATE_WAITING_CRC16:
if self.updateAction:
self.updateAction((file_size - max(size, 0)), file_size)
data = self.getByte()
if data == self.CRC16:
newState = self.STATE_READY
else:
if state == self.STATE_WAITING_ACK:
if self.updateAction:
self.updateAction((file_size - max(size, 0)), file_size)
data = self.getByte()
if data is not None:
if data == self.ACK:
if prevState == self.STATE_READY:
retry = 0
if loop_counter > 1:
size = (size - packet_size)
packet_number = ((packet_number + 1) % 256)
loop_counter = (loop_counter + 1)
packet_done = True
if self.updateAction:
self.updateAction((file_size - max(size, 0)), file_size)
else:
infoMessage(('Sent %05d/%05d\r' % ((file_size - max(size, 0)), file_size)))
newState = self.STATE_READY
else:
if prevState == self.STATE_SEND_EOT:
newState = self.STATE_SEND_SESSION_DONE
else:
if prevState == self.STATE_SEND_SESSION_DONE:
newState = self.STATE_START_APPLICATION
else:
if data == self.CA:
errorMessage('Transaction aborted by client\n')
newState = self.STATE_DONE
else:
if data == self.CRC16:
pass
else:
if prevState == self.STATE_READY:
infoMessage('Retrying\n')
retry = (retry + 1)
if retry > 3:
errorMessage('Too many retry exiting\n')
newState = self.STATE_DONE
else:
newState = self.STATE_READY
else:
if state == self.STATE_READY:
if size <= 0:
newState = self.STATE_SEND_EOT
else:
if retry == 0:
packet = []
if loop_counter == 1:
packet.extend(struct.unpack(('%uB' % len(filename)), filename))
packet = (packet + [0])
size_string = ('%d ' % file_size)
packet.extend(struct.unpack(('%uB' % len(size_string)), size_string))
packet_size = self.PACKET_SIZE
else:
packet_size = self.PACKET_1K_SIZE
packet_string = f.read(packet_size)
packet.extend(struct.unpack(('%uB' % len(packet_string)), packet_string))
packet = (packet + ([0] * (packet_size - len(packet))))
if self.sendYModemPacket(packet, packet_number):
newState = self.STATE_DONE
else:
newState = self.STATE_WAITING_ACK
else:
if state == self.STATE_SEND_EOT:
if self.updateAction:
self.updateAction((file_size - max(size, 0)), file_size)
else:
infoMessage(('Sent %05d/%05d\r' % ((file_size - max(size, 0)), file_size)))
self.sendByte(self.EOT)
newState = self.STATE_WAITING_ACK
else:
if state == self.STATE_SEND_SESSION_DONE:
self.sendYModemPacket(([0] * 128), 0)
newState = self.STATE_WAITING_ACK
else:
if state == self.STATE_START_APPLICATION:
self.startApplication()
newState = self.STATE_DONE
else:
if state == self.STATE_DONE:
returnValue = False
endTime = time.time()
infoMessage('\nDone\n')
break
else:
errorMessage(('Unknonw state = %d' % state))
newState = self.STATE_DONE
if state != newState:
prevState = state
state = newState
continue
else:
continue
return returnValue
except:
errorMessage((('File ' + name) + ' open failed\n'))
if self.updateAction:
self.updateAction(0, 0)
return returnValue
def sendByte(self, byte):
self.serialPort.write(struct.pack('B', byte))
return None
def sendYModemPacket(self, myPacket, packet_number):
returnValue = 0
packet = myPacket[:]
packet_crc = self.Crc16X(packet, len(packet))
packet.append(((packet_crc >> 8) & 255))
packet.append((packet_crc & 255))
packet.insert(0, (255 - packet_number))
packet.insert(0, packet_number)
if len(myPacket) == self.PACKET_SIZE:
packet.insert(0, self.SOH)
else:
packet.insert(0, self.STX)
self.serialPort.write(struct.pack(('B' * len(packet)), *packet))
return returnValue
def startApplication(self):
return None