mirror of
https://github.com/oliverschmidt/contiki.git
synced 2024-11-19 03:05:14 +00:00
Merge pull request #25 from eduble/master
Set of fixes related to stm32w boards.
This commit is contained in:
commit
8eeae7689e
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@
|
||||
*.log
|
||||
*.elf
|
||||
*.ihex
|
||||
*.pyc
|
||||
obj_*
|
||||
symbols.*
|
||||
Makefile.target
|
||||
|
@ -168,7 +168,7 @@ endif
|
||||
|
||||
|
||||
|
||||
FLASHER = sudo $(CONTIKI)/tools/stm32w/stm32w_flasher/stm32w_flasher
|
||||
FLASHER = sudo $(CONTIKI)/tools/stm32w/stm32w_flasher/py_files/stm32w_flasher.py
|
||||
|
||||
# Check if we are running under Windows
|
||||
ifeq ($(HOST_OS),Windows)
|
||||
@ -257,9 +257,7 @@ endif #IAR
|
||||
|
||||
MOTELIST = $(CONTIKI)/tools/stm32w/motelist-linux
|
||||
|
||||
MOTES = $(shell $(MOTELIST) 2>&- | grep USB | \
|
||||
cut -f 4 -d \ | \
|
||||
perl -ne 'print $$1 . " " if(m-(/dev/\w+)-);')
|
||||
MOTES = $(shell $(MOTELIST) 2>&- | awk '{print $$2}' | grep '\/')
|
||||
|
||||
motelist: stm-motelist
|
||||
|
||||
|
@ -22,7 +22,3 @@ ifeq ($(HOST_OS),Windows)
|
||||
SERIALDUMP = $(CONTIKI)/tools/stm32w/serialdump-windows
|
||||
endif
|
||||
|
||||
|
||||
|
||||
login:
|
||||
$(SERIALDUMP) -b115200 -d10000 $(PORT)
|
||||
|
@ -24,7 +24,9 @@ my %Opt = (
|
||||
usb => 0,
|
||||
method => "auto",
|
||||
kernel => "auto",
|
||||
dev_prefix => [ "/dev/usb/tts/", "/dev/ttyUSB", "/dev/tts/USB" ],
|
||||
usb_dev_prefix => [ "/dev/usb/tts/", "/dev/ttyUSB", "/dev/tts/USB" ],
|
||||
acm_dev_prefix => [ "/dev/ttyACM" ],
|
||||
dev_prefix => undef,
|
||||
usbserial => "sudo cat /proc/tty/driver/usbserial |",
|
||||
);
|
||||
|
||||
@ -61,7 +63,8 @@ sub scan_sysfs {
|
||||
|
||||
# Scan /sys/bus/usb/drivers/usb for FTDI devices
|
||||
my @ftdidevs =
|
||||
grep { ($_->{UsbVendor}||"") eq "0403" && ($_->{UsbProduct}||"") eq "6001" && ($_->{UsbBcdDevice}||"") eq "0600"}
|
||||
grep { (($_->{UsbVendor}||"") eq "0403" && ($_->{UsbProduct}||"") eq "6001" && ($_->{UsbBcdDevice}||"") eq "0600") ||
|
||||
(($_->{UsbVendor}||"") eq "0483" && ($_->{UsbProduct}||"") eq "5741")}
|
||||
map { {
|
||||
SysPath => $_,
|
||||
UsbVendor => snarf("$_/idVendor",1),
|
||||
@ -90,9 +93,19 @@ sub scan_sysfs {
|
||||
|
||||
my $port = "$syspath/$f->{SysDev}:1.0";
|
||||
($f->{DriverName} = readlink("$port/driver")) =~ s{^.*/}{} if -l "$port/driver";
|
||||
($f->{SerialDevName} = (glob("$port/tty*"),undef)[0]) =~ s{^.*/}{};
|
||||
($f->{SerialDevName} = (glob("$port/tty/tty* $port/tty*"),undef)[0]) =~ s{^.*/}{};
|
||||
$f->{SerialDevNum} = $1 if $f->{SerialDevName} =~ /(\d+)/;
|
||||
$f->{SerialDevName} = getSerialDevName( $f->{SerialDevNum} ) || " (none)";
|
||||
my $dev_prefix = $Opt{dev_prefix};
|
||||
if (not defined $dev_prefix)
|
||||
{
|
||||
if ( $f->{SerialDevName} =~ ".*ACM.*" ) {
|
||||
$dev_prefix = $Opt{acm_dev_prefix}
|
||||
}
|
||||
else {
|
||||
$dev_prefix = $Opt{usb_dev_prefix}
|
||||
}
|
||||
}
|
||||
$f->{SerialDevName} = getSerialDevName($dev_prefix, $f->{SerialDevNum} ) || " (none)";
|
||||
}
|
||||
|
||||
return @ftdidevs;
|
||||
@ -115,6 +128,12 @@ sub scan_procfs {
|
||||
$usbtree{usbkey($tts->{path})}{usbserial} = $tts if defined $tts->{path};
|
||||
}
|
||||
|
||||
my $dev_prefix = $Opt{dev_prefix};
|
||||
if (not defined $dev_prefix)
|
||||
{
|
||||
$dev_prefix = $Opt{usb_dev_prefix}
|
||||
}
|
||||
|
||||
my @ftdidevs = map { {
|
||||
UsbVendor => $_->{Vendor},
|
||||
UsbProduct => $_->{ProdID},
|
||||
@ -127,7 +146,7 @@ sub scan_procfs {
|
||||
UsbPath => (($Opt{kernel} eq "2.4") ? $_->{usbserial}{path} : $_->{usbpath}),
|
||||
DriverName => $_->{driver},
|
||||
SerialDevNum => $_->{usbserial}{tts},
|
||||
SerialDevName => getSerialDevName($_->{usbserial}{tts}) || " (none)",
|
||||
SerialDevName => getSerialDevName($dev_prefix, $_->{usbserial}{tts}) || " (none)",
|
||||
} }
|
||||
grep { ($_->{Vendor}||"") eq "0403" && ($_->{ProdID}||"") eq "6001" && ($_->{BcdDevice}||"") eq "0600"}
|
||||
values %usbtree;
|
||||
@ -194,17 +213,18 @@ sub usbkey {
|
||||
# first one that actually exists.
|
||||
#
|
||||
sub getSerialDevName {
|
||||
my $dev_prefix = shift;
|
||||
my $devnum = shift;
|
||||
my $devname = undef;
|
||||
if( defined $devnum ) {
|
||||
if( ref($Opt{dev_prefix}) eq "ARRAY" ) {
|
||||
if( ref($dev_prefix) eq "ARRAY" ) {
|
||||
$devname = $devnum;
|
||||
for my $prefix (@{$Opt{dev_prefix}}) {
|
||||
for my $prefix (@{$dev_prefix}) {
|
||||
my $file = $prefix . $devnum;
|
||||
if( -e $file ) { $devname = $file; last; }
|
||||
}
|
||||
} else {
|
||||
$devname = $Opt{dev_prefix} . $devnum;
|
||||
$devname = $dev_prefix . $devnum;
|
||||
}
|
||||
}
|
||||
return $devname;
|
||||
|
83
tools/stm32w/stm32w_flasher/py_files/file_utils.py
Normal file
83
tools/stm32w/stm32w_flasher/py_files/file_utils.py
Normal file
@ -0,0 +1,83 @@
|
||||
|
||||
# See comment in stm32w_flasher.py.
|
||||
# Extraction and little adaptation performed by E.Duble (CNRS, LIG).
|
||||
|
||||
import struct
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
"""Base class for exceptions in this module."""
|
||||
args = None
|
||||
message = None
|
||||
|
||||
class FileFormatError(Error):
|
||||
"""
|
||||
Exception raised for errors in the file format
|
||||
|
||||
Attributes:
|
||||
filename -- filename with unknown format
|
||||
message -- format error message
|
||||
|
||||
"""
|
||||
args = None
|
||||
message = None
|
||||
def __init__(self, filename, message):
|
||||
self.filename = filename
|
||||
self.message = message
|
||||
|
||||
|
||||
class fileFormatReader(object):
|
||||
def __init__(self, filename, startAddress=None):
|
||||
self.filename = filename
|
||||
self.startAddress = startAddress
|
||||
|
||||
def getRawBinary(self):
|
||||
fileContent = None
|
||||
bytes = None
|
||||
f = open(self.filename, 'rb')
|
||||
if self.filename[-4:] == '.bin':
|
||||
bytesRaw = f.read()
|
||||
bytes = []
|
||||
bytes.extend(struct.unpack(('B' * len(bytesRaw)), bytesRaw))
|
||||
f.close()
|
||||
else:
|
||||
if self.filename[-4:] == '.s37':
|
||||
fillChar = 255
|
||||
fileContent = f.readlines()
|
||||
f.close()
|
||||
startAddress = None
|
||||
currentAddress = None
|
||||
bytes = []
|
||||
for line in fileContent:
|
||||
if line[:2] == 'S3':
|
||||
count = int(line[2:4], 16)
|
||||
if startAddress is None:
|
||||
startAddress = int(line[4:12], 16)
|
||||
currentAddress = startAddress
|
||||
address = int(line[4:12], 16)
|
||||
if currentAddress < address:
|
||||
bytes = (bytes + ([fillChar] * (address - currentAddress)))
|
||||
currentAddress = address
|
||||
else:
|
||||
if currentAddress > address:
|
||||
raise FileFormatError(self.filename, 'S37, Non progressing addresses detected')
|
||||
for i in range((count - 5)):
|
||||
bytes = (bytes + [int(line[(12 + (i * 2)):((12 + (i * 2)) + 2)], 16)])
|
||||
continue
|
||||
currentAddress = (currentAddress + (count - 5))
|
||||
continue
|
||||
else:
|
||||
if line[:2] == 'S0':
|
||||
continue
|
||||
else:
|
||||
if line[:2] == 'S7':
|
||||
break
|
||||
else:
|
||||
raise FileFormatError(self.filename, 'S37: unknown field type')
|
||||
self.startAddress = startAddress
|
||||
else:
|
||||
raise FileFormatError(self.filename, 'Unknown extension')
|
||||
return (self.startAddress, bytes)
|
||||
|
||||
|
||||
|
25
tools/stm32w/stm32w_flasher/py_files/messages.py
Normal file
25
tools/stm32w/stm32w_flasher/py_files/messages.py
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
# See comment in stm32w_flasher.py.
|
||||
# Extraction and little adaptation performed by E.Duble (CNRS, LIG).
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
def errorMessage(msg, header=True):
|
||||
if header:
|
||||
sys.stderr.write('ERROR: ')
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.flush()
|
||||
|
||||
def infoMessage(msg, header=True):
|
||||
if header:
|
||||
sys.stdout.write('INFO: ')
|
||||
sys.stdout.write(msg)
|
||||
sys.stdout.flush()
|
||||
|
||||
def warningMessage(msg, header=True):
|
||||
if header:
|
||||
sys.stderr.write('WARNING: ')
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.flush()
|
||||
|
287
tools/stm32w/stm32w_flasher/py_files/prodeng.py
Normal file
287
tools/stm32w/stm32w_flasher/py_files/prodeng.py
Normal file
File diff suppressed because one or more lines are too long
1058
tools/stm32w/stm32w_flasher/py_files/rs232_interface.py
Normal file
1058
tools/stm32w/stm32w_flasher/py_files/rs232_interface.py
Normal file
File diff suppressed because it is too large
Load Diff
279
tools/stm32w/stm32w_flasher/py_files/stm32w_flasher.py
Executable file
279
tools/stm32w/stm32w_flasher/py_files/stm32w_flasher.py
Executable file
@ -0,0 +1,279 @@
|
||||
#!/usr/bin/env python
|
||||
import optparse, os, sys, time
|
||||
|
||||
# The binary file at [contiki]/tools/stm32w/stm32w_flasher/stm32w_flasher
|
||||
# contained python code.
|
||||
# This binary file did not work anymore on Ubuntu 12.04, so
|
||||
# it was replaced by this extracted python code, as discussed
|
||||
# with people at ST Crolles (France).
|
||||
#
|
||||
# Extraction and little adaptation performed by E.Duble (CNRS, LIG).
|
||||
|
||||
try:
|
||||
import serial
|
||||
import ftdi
|
||||
except:
|
||||
print 'Python modules serial and ftdi could not be loaded.'
|
||||
print 'Please install these dependencies:'
|
||||
print '(On Ubuntu) $ sudo apt-get install python-serial python-ftdi'
|
||||
sys.exit(-1)
|
||||
|
||||
from messages import infoMessage, errorMessage
|
||||
from rs232_interface import rs232Interface, getFirstAvailableSerialPort
|
||||
|
||||
versionMajor = 2
|
||||
versionMinor = 0
|
||||
versionPatch = 1
|
||||
versionQualifier = "b2"
|
||||
version = "%d.%d.%d%s"%(versionMajor, versionMinor, versionPatch, versionQualifier)
|
||||
|
||||
commandTable = [
|
||||
['-i', '--interface', 'store', "<rs232 | rf > specify flasher interface (default rs232)",None],
|
||||
['-p', '--port', 'store', "</dev/ttyXXX | auto>: specify rs232 port or auto mode (only relevant if interface selected is rs232 or rf)", None],
|
||||
['-f', '--flash-image', 'store_true', "program flash"],
|
||||
['-a', '--address', 'store', "0xHHHHHHHH specify baseaddress (only relevat for .bin images)", "0x08000000"],
|
||||
['-v', '--verify', 'store_true', "verify flash content against file", False],
|
||||
#['-d', '--device-info', 'store_true', 'print information about the STM32W device', False],
|
||||
['-r', '--reset', 'store_true', 'Reset device', False],
|
||||
['-s', '--start', 'store_true', 'Start application', False],
|
||||
['-m', '--masserase', 'store_true', 'Erase user flash (masserase)', False],
|
||||
['-b', '--bootloader-mode', 'store_true', 'Device is already in bootloader mode.(Only relevant for rs232 interface)', False],
|
||||
['-e', '--eui64', 'store', "0xHHHHHHHHHHHHHHHH specify EUI64 (only relevat for rf interface)", "0xFFFFFFFFFFFFFFFF"],
|
||||
['', '--enable-readout-protection', 'store', "<0|1> Disable or enable readout protection", None],
|
||||
['', '--set-write-protection', 'store', "0xHHHHHHHH Set write protection to hex value (each bit set to zero is protecting 4K)" , "0xFFFFFFFF"],
|
||||
]
|
||||
|
||||
def initCommandLineParser():
|
||||
"""Create a command-line parser and return it.
|
||||
"""
|
||||
USAGE = '%prog [option...] [filename{.s37|.bin}] ...'
|
||||
DESCR = """ Flash programming utility for STM32W108 device """
|
||||
|
||||
parser = optparse.OptionParser(usage=USAGE, description=DESCR,
|
||||
version='%%prog %s' % version)
|
||||
|
||||
for item in commandTable:
|
||||
if len(item) > 4:
|
||||
default = item[4]
|
||||
else:
|
||||
default = None
|
||||
parser.add_option(item[0], item[1], action=item[2], help=item[3], default=default)
|
||||
|
||||
return parser
|
||||
|
||||
def getFileVersionDate(fname):
|
||||
returnValue = ""
|
||||
return returnValue
|
||||
|
||||
def initInterface (interface, port, noReset=False, rfMode=False, eui64=0):
|
||||
returnValue = rs232Interface(port, noReset, rfMode, eui64)
|
||||
if returnValue.init():
|
||||
returnValue = None
|
||||
return returnValue
|
||||
|
||||
def terminateInterface(interface):
|
||||
if (isinstance(interface, rs232Interface)):
|
||||
interface.terminate()
|
||||
|
||||
def flashImage (interface, inputFile, startAddress, doErase=True):
|
||||
def progressReport(size, fileSize):
|
||||
infoMessage ("Programming %05d/%05d\r"%(size,fileSize))
|
||||
infoMessage ("Programming user flash\n")
|
||||
if not interface.programUserFlash(inputFile, startAddress, progressReport, doErase):
|
||||
infoMessage("Failed \n")
|
||||
else:
|
||||
infoMessage("Done \n")
|
||||
|
||||
def verifyFlashImage (interface, inputFile, startAddress):
|
||||
def progressReport(size, fileSize):
|
||||
infoMessage ("Verifying %05d/%05d\r"%(size,fileSize))
|
||||
|
||||
infoMessage ("Verifying user flash\n")
|
||||
if not interface.verifyFlash(inputFile, startAddress, progressReport):
|
||||
infoMessage("Failed \n")
|
||||
else:
|
||||
infoMessage("Done \n")
|
||||
|
||||
def resetDevice (interface):
|
||||
infoMessage ("Resetting device\n")
|
||||
|
||||
returnValue = not interface.startApplication(0)
|
||||
|
||||
if (returnValue):
|
||||
infoMessage("Failed \n")
|
||||
else:
|
||||
infoMessage("Done \n")
|
||||
|
||||
def startApplication (interface, startAddress):
|
||||
infoMessage ("Starting application from address: %08x\n"%startAddress)
|
||||
if not interface.startApplication(startAddress):
|
||||
infoMessage("Failed \n")
|
||||
else:
|
||||
infoMessage("Done \n")
|
||||
|
||||
def eraseUserFlash (interface):
|
||||
infoMessage ("Erasing user flash (mass erase)\n")
|
||||
if not interface.eraseUserFlash():
|
||||
infoMessage("Failed \n")
|
||||
else:
|
||||
infoMessage("Done \n")
|
||||
|
||||
def printBanner():
|
||||
infoMessage ("STM32W flasher utility version %s\n"%version)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
absolutePath = os.path.abspath(sys.argv[0])
|
||||
if "frozen" in dir(sys):
|
||||
version += " " + getFileVersionDate(sys.executable)
|
||||
else:
|
||||
version += "-" + time.strftime("%Y%m%d",time.localtime(os.stat(absolutePath).st_ctime))
|
||||
|
||||
version += " for Linux"
|
||||
|
||||
interfaceHandle = None
|
||||
printBanner()
|
||||
|
||||
parser = initCommandLineParser()
|
||||
(options, args) = parser.parse_args()
|
||||
rfMode = False
|
||||
|
||||
# Check command line option
|
||||
if (len(args) == 1):
|
||||
if (len(sys.argv) == 2):
|
||||
# No option means flashing by default
|
||||
options.flash_image = True
|
||||
options.image = args[0]
|
||||
|
||||
if (len(args) > 1):
|
||||
parser.print_help()
|
||||
sys.exit(-1)
|
||||
|
||||
if (len(sys.argv) == 1):
|
||||
parser.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
if (options.interface is None):
|
||||
# Set defualt for interface
|
||||
if (options.port is None):
|
||||
options.interface = "rs232"
|
||||
options.port = "auto"
|
||||
else:
|
||||
options.interface = "rs232"
|
||||
elif (options.interface == "rf"):
|
||||
rfMode = True
|
||||
options.address = "0x08003000"
|
||||
options.interface = "rs232"
|
||||
options.bootloader_mode = True
|
||||
|
||||
options.interface = options.interface.lower()
|
||||
|
||||
if ((options.interface == "rs232") and (options.port == None)):
|
||||
parser.print_help()
|
||||
sys.exit(-1)
|
||||
|
||||
if (options.interface != "rs232" and options.interface != "jlink"):
|
||||
parser.print_help()
|
||||
sys.exit(-1)
|
||||
|
||||
startAddress = int(options.address,16)
|
||||
|
||||
if (options.interface == "rs232"):
|
||||
optionArg = options.port.upper()
|
||||
if (optionArg == "AUTO"):
|
||||
port = getFirstAvailableSerialPort()
|
||||
if port is None:
|
||||
errorMessage ("Unable to find serial port in auto mode: no STM32W boards detected\n")
|
||||
sys.exit(-1)
|
||||
infoMessage ("Auto mode selected serial port: %s\n"%port)
|
||||
elif (options.port[:4] == "/dev"): ## For Linux
|
||||
port = options.port
|
||||
else:
|
||||
try:
|
||||
port = int(optionArg)
|
||||
except ValueError:
|
||||
errorMessage("Invalid port: %s\n"%options.port)
|
||||
sys.exit(-1)
|
||||
else:
|
||||
port = None
|
||||
|
||||
if (options.interface == "jlink"):
|
||||
errorMessage("JLink not yet supported.\n")
|
||||
sys.exit(-1)
|
||||
|
||||
if (options.start and options.reset):
|
||||
errorMessage ("Only one option between -s (--start) and -r (--reset) may be specified")
|
||||
sys.exit(-1)
|
||||
|
||||
interfaceHandle = initInterface(options.interface, port, options.bootloader_mode, rfMode, int(options.eui64, 16))
|
||||
|
||||
if interfaceHandle is None:
|
||||
errorMessage("Error while initiliazing interface\n")
|
||||
sys.exit(-1)
|
||||
|
||||
readoutProtection = interfaceHandle.isReadProtectionActive()
|
||||
|
||||
if readoutProtection:
|
||||
infoMessage("!Warning: Readout protection is active\n")
|
||||
|
||||
options.device_info = False
|
||||
|
||||
if (options.masserase):
|
||||
eraseUserFlash(interfaceHandle)
|
||||
|
||||
if (options.enable_readout_protection is not None):
|
||||
if (options.enable_readout_protection == "1"):
|
||||
if not readoutProtection:
|
||||
infoMessage("Enabling readout protection\n")
|
||||
interfaceHandle.enableReadProtection(True)
|
||||
infoMessage("Done\n")
|
||||
else:
|
||||
infoMessage("Readout protection already enabled, no action\n")
|
||||
|
||||
elif (options.enable_readout_protection == "0"):
|
||||
if readoutProtection:
|
||||
infoMessage("Disabling readout protection (this will clear user flash and CIB)\n")
|
||||
interfaceHandle.enableReadProtection(False)
|
||||
infoMessage("Done\n")
|
||||
else:
|
||||
infoMessage("Readout protection already disaabled, no action\n")
|
||||
else:
|
||||
errorMessage("Invalid value for --enable-readout-protection\n")
|
||||
terminateInterface(interfaceHandle)
|
||||
sys.exit(-1)
|
||||
|
||||
if options.flash_image:
|
||||
flashImage(interfaceHandle, options.image, startAddress, not options.masserase)
|
||||
|
||||
if options.verify and not readoutProtection:
|
||||
verifyFlashImage(interfaceHandle, options.image, startAddress)
|
||||
|
||||
|
||||
if (options.start):
|
||||
startApplication(interfaceHandle, startAddress)
|
||||
|
||||
if (options.reset):
|
||||
resetDevice(interfaceHandle)
|
||||
|
||||
terminateInterface(interfaceHandle)
|
||||
|
||||
sys.exit (0)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
infoMessage ("User break\n")
|
||||
terminateInterface(interfaceHandle)
|
||||
sys.exit(-1)
|
||||
|
||||
except Exception, inst:
|
||||
if not ("frozen" in dir(sys)):
|
||||
raise
|
||||
else:
|
||||
errorMessage("Internal error\n")
|
||||
errorMessage("%s\n"%repr(type(inst))) # the exception instance
|
||||
errorMessage("%s\n"%repr(inst.args)) # arguments stored in .args
|
||||
if interfaceHandle:
|
||||
terminateInterface(interfaceHandle)
|
||||
sys.exit(-1)
|
||||
|
||||
|
241
tools/stm32w/stm32w_flasher/py_files/ymodem.py
Normal file
241
tools/stm32w/stm32w_flasher/py_files/ymodem.py
Normal file
@ -0,0 +1,241 @@
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user