Skip to content

Commit

Permalink
add serial, few fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Puech committed Nov 19, 2015
1 parent af6aa3e commit c104c61
Show file tree
Hide file tree
Showing 31 changed files with 7,394 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ ORIGINAL_BIN = $(RESOURCES)/original_firmware.bin
include stmlib/makefile.inc

flasher: bin
pyinstaller -y "flasher/XAOC Firmware Update Tool.spec"
cd flasher; pyinstaller -y "XAOC Firmware Update Tool.spec"

# Rule for uploading the original firmware
upload_original_serial:
Expand Down
3 changes: 3 additions & 0 deletions flasher/XAOC Firmware Update Tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@
# GUI Flash utility for STM32 projects, based on stm32loader

import sys
import os
import os.path
import glob

import sys

from Tkinter import *
import tkMessageBox
import tkFileDialog
Expand Down
10 changes: 5 additions & 5 deletions flasher/XAOC Firmware Update Tool.spec
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ block_cipher = None


a = Analysis(['XAOC Firmware Update Tool.py'],
pathex=['flasher/'],
pathex=[''],
binaries=None,
datas=None,
hiddenimports=[],
datas=[('logo.gif', '.')],
hiddenimports=['serial'],
hookspath=None,
runtime_hooks=None,
excludes=None,
Expand All @@ -25,8 +25,8 @@ exe = EXE(pyz,
debug=False,
strip=None,
upx=True,
console=False , icon='flasher/icon.icns')
console=False , icon='../batumi/flasher/icon.icns')
app = BUNDLE(exe,
name='XAOC Firmware Update Tool.app',
icon='flasher/icon.icns',
icon='../batumi/flasher/icon.icns',
bundle_identifier=None)
86 changes: 86 additions & 0 deletions flasher/serial/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env python
#
# portable serial port access with python
# this is a wrapper module for different platform implementations
#
# (C) 2001-2015 Chris Liechti <[email protected]>
#
# SPDX-License-Identifier: BSD-3-Clause

import importlib
import sys

from serial.serialutil import *
#~ SerialBase, SerialException, to_bytes, iterbytes

VERSION = '3.0b1'

if sys.platform == 'cli':
from serial.serialcli import Serial
else:
import os
# chose an implementation, depending on os
if os.name == 'nt': # sys.platform == 'win32':
from serial.serialwin32 import Serial
elif os.name == 'posix':
from serial.serialposix import Serial, PosixPollSerial, VTIMESerial
elif os.name == 'java':
from serial.serialjava import Serial
else:
raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))


protocol_handler_packages = [
'serial.urlhandler',
]


def serial_for_url(url, *args, **kwargs):
"""\
Get an instance of the Serial class, depending on port/url. The port is not
opened when the keyword parameter 'do_not_open' is true, by default it
is. All other parameters are directly passed to the __init__ method when
the port is instantiated.
The list of package names that is searched for protocol handlers is kept in
``protocol_handler_packages``.
e.g. we want to support a URL ``foobar://``. A module
``my_handlers.protocol_foobar`` is provided by the user. Then
``protocol_handler_packages.append("my_handlers")`` would extend the search
path so that ``serial_for_url("foobar://"))`` would work.
"""
# check and remove extra parameter to not confuse the Serial class
do_open = not kwargs.pop('do_not_open', False)
# the default is to use the native implementation
klass = Serial
try:
url_lowercase = url.lower()
except AttributeError:
# it's not a string, use default
pass
else:
# if it is an URL, try to import the handler module from the list of possible packages
if '://' in url_lowercase:
protocol = url_lowercase.split('://', 1)[0]
module_name = '.protocol_%s' % (protocol,)
for package_name in protocol_handler_packages:
try:
package = importlib.import_module(package_name)
handler_module = importlib.import_module(module_name, package_name)
except ImportError:
continue
else:
if hasattr(handler_module, 'serial_class_for_url'):
url, klass = handler_module.serial_class_for_url(url)
else:
klass = handler_module.Serial
break
else:
raise ValueError('invalid URL, protocol %r not known' % (protocol,))
# instantiate and open when desired
instance = klass(None, *args, **kwargs)
instance.port = url
if do_open:
instance.open()
return instance
115 changes: 115 additions & 0 deletions flasher/serial/aio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/usr/bin/env python3
#
# Python Serial Port Extension for Win32, Linux, BSD, Jython
# module for serial IO for POSIX compatible systems, like Linux
# see __init__.py
#
# (C) 2015 Chris Liechti <[email protected]>
#
# SPDX-License-Identifier: BSD-3-Clause
"""\
Support asyncio with serial ports. EXPERIMENTAL
Posix platforms only, Python 3.4+ only.
Windows event loops can not wait for serial ports with the current
implementation. It should be possible to get that working though.
"""
import asyncio
import serial
import logger


class SerialTransport(asyncio.Transport):
def __init__(self, loop, protocol, serial_instance):
self._loop = loop
self._protocol = protocol
self.serial = serial_instance
self._closing = False
self._paused = False
# XXX how to support url handlers too
self.serial.timeout = 0
self.serial.nonblocking()
loop.call_soon(protocol.connection_made, self)
# only start reading when connection_made() has been called
loop.call_soon(loop.add_reader, self.serial.fd, self._read_ready)

def __repr__(self):
return '{self.__class__.__name__}({self._loop}, {self._protocol}, {self.serial})'.format(self=self)

def close(self):
if self._closing:
return
self._closing = True
self._loop.remove_reader(self.serial.fd)
self.serial.close()
self._loop.call_soon(self._protocol.connection_lost, None)

def _read_ready(self):
data = self.serial.read(1024)
if data:
self._protocol.data_received(data)

def write(self, data):
self.serial.write(data)

def can_write_eof(self):
return False

def pause_reading(self):
if self._closing:
raise RuntimeError('Cannot pause_reading() when closing')
if self._paused:
raise RuntimeError('Already paused')
self._paused = True
self._loop.remove_reader(self._sock_fd)
if self._loop.get_debug():
logger.debug("%r pauses reading", self)

def resume_reading(self):
if not self._paused:
raise RuntimeError('Not paused')
self._paused = False
if self._closing:
return
self._loop.add_reader(self._sock_fd, self._read_ready)
if self._loop.get_debug():
logger.debug("%r resumes reading", self)

#~ def set_write_buffer_limits(self, high=None, low=None):
#~ def get_write_buffer_size(self):
#~ def writelines(self, list_of_data):
#~ def write_eof(self):
#~ def abort(self):


@asyncio.coroutine
def create_serial_connection(loop, protocol_factory, *args, **kwargs):
ser = serial.Serial(*args, **kwargs)
protocol = protocol_factory()
transport = SerialTransport(loop, protocol, ser)
return (transport, protocol)

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# test
if __name__ == '__main__':
class Output(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
print('port opened', transport)
transport.serial.rts = False
transport.write(b'hello world\n')

def data_received(self, data):
print('data received', repr(data))
self.transport.close()

def connection_lost(self, exc):
print('port closed')
asyncio.get_event_loop().stop()

loop = asyncio.get_event_loop()
coro = create_serial_connection(loop, Output, '/dev/ttyUSB0', baudrate=115200)
loop.run_until_complete(coro)
loop.run_forever()
loop.close()
Loading

0 comments on commit c104c61

Please sign in to comment.