spresense: update SDK to 2.3.0

This commit is contained in:
Kamil Tomaszewski 2021-09-03 09:25:22 +02:00
parent cf5c32be3b
commit a0d960f2a1
10 changed files with 45 additions and 898 deletions

View File

@ -128,7 +128,6 @@ OPTIMIZATION_FLAGS ?= -O2 -fno-inline-functions
# option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk # option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
CFLAGS += $(OPTIMIZATION_FLAGS) CFLAGS += $(OPTIMIZATION_FLAGS)
LIBM = "${shell "$(CC)" $(CFLAGS) -print-file-name=libm.a}" LIBM = "${shell "$(CC)" $(CFLAGS) -print-file-name=libm.a}"
LIBGCC = "${shell "$(CC)" $(CFLAGS) -print-libgcc-file-name}" LIBGCC = "${shell "$(CC)" $(CFLAGS) -print-libgcc-file-name}"
@ -146,7 +145,15 @@ LDFLAGS = \
-u board_timerhook \ -u board_timerhook \
$(BUILD)/libmpy.a \ $(BUILD)/libmpy.a \
$(SPRESENSE_SDK)/nuttx/libs/libapps.a \ $(SPRESENSE_SDK)/nuttx/libs/libapps.a \
$(SPRESENSE_SDK)/nuttx/libs/libnuttx.a \ $(SPRESENSE_SDK)/nuttx/libs/libarch.a \
$(SPRESENSE_SDK)/nuttx/libs/libbinfmt.a \
$(SPRESENSE_SDK)/nuttx/libs/libboard.a \
$(SPRESENSE_SDK)/nuttx/libs/libboards.a \
$(SPRESENSE_SDK)/nuttx/libs/libc.a \
$(SPRESENSE_SDK)/nuttx/libs/libdrivers.a \
$(SPRESENSE_SDK)/nuttx/libs/libfs.a \
$(SPRESENSE_SDK)/nuttx/libs/libmm.a \
$(SPRESENSE_SDK)/nuttx/libs/libsched.a \
$(LIBM) \ $(LIBM) \
$(LIBGCC) \ $(LIBGCC) \
--end-group \ --end-group \

View File

@ -75,7 +75,7 @@ Bootloader information:
* You have to accept the End User License Agreement to be able to download and use the Spresense bootloader binary. * You have to accept the End User License Agreement to be able to download and use the Spresense bootloader binary.
Download the spresense binaries zip archive from: [Spresense firmware v2-0-002](https://developer.sony.com/file/download/download-spresense-firmware-v2-0-002) Download the spresense binaries zip archive from: [Spresense firmware v2-3-000](https://developer.sony.com/file/download/download-spresense-firmware-v2-3-000)
Extract spresense binaries in your PC to ports/spresense/spresense-exported-sdk/firmware/ Extract spresense binaries in your PC to ports/spresense/spresense-exported-sdk/firmware/

View File

@ -24,6 +24,8 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <string.h>
#include <arch/chip/pin.h> #include <arch/chip/pin.h>
#include <cxd56_spi.h> #include <cxd56_spi.h>
#include <cxd56_pinconfig.h> #include <cxd56_pinconfig.h>

View File

@ -38,7 +38,7 @@ static uint16_t pulse_index = 0;
static uint16_t pulse_length; static uint16_t pulse_length;
static int pulse_fd = -1; static int pulse_fd = -1;
static bool pulseout_timer_handler(unsigned int *next_interval_us, void *arg) { static bool pulseout_timer_handler(uint32_t *next_interval_us, void *arg) {
uint8_t pwm_num = (uint8_t)(int)arg; uint8_t pwm_num = (uint8_t)(int)arg;
pulse_index++; pulse_index++;
@ -46,7 +46,7 @@ static bool pulseout_timer_handler(unsigned int *next_interval_us, void *arg) {
return false; return false;
} }
*next_interval_us = pulse_buffer[pulse_index] * 1000; *next_interval_us = pulse_buffer[pulse_index];
if (pulse_index % 2 == 0) { if (pulse_index % 2 == 0) {
pwmout_start(pwm_num); pwmout_start(pwm_num);
@ -108,7 +108,7 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t *self, uint16_t *pu
pulse_index = 0; pulse_index = 0;
pulse_length = len; pulse_length = len;
unsigned long timeout = pulse_buffer[0] * 1000; unsigned long timeout = pulse_buffer[0];
ioctl(pulse_fd, TCIOC_SETTIMEOUT, timeout); ioctl(pulse_fd, TCIOC_SETTIMEOUT, timeout);

View File

@ -130,7 +130,6 @@ int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t sta
check_whole_block(bufinfo); check_whole_block(bufinfo);
return self->inode->u.i_bops->write(self->inode, bufinfo->buf, start_block, bufinfo->len / 512); return self->inode->u.i_bops->write(self->inode, bufinfo->buf, start_block, bufinfo->len / 512);
;
} }
void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) { void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) {

View File

@ -12,8 +12,8 @@
# CONFIG_MMCSD_MMCSUPPORT is not set # CONFIG_MMCSD_MMCSUPPORT is not set
# CONFIG_MMCSD_SPI is not set # CONFIG_MMCSD_SPI is not set
# CONFIG_MTD_SMART_WEAR_LEVEL is not set # CONFIG_MTD_SMART_WEAR_LEVEL is not set
# CONFIG_NET_IPv4 is not set
# CONFIG_NXFONTS_PACKEDMSFIRST is not set # CONFIG_NXFONTS_PACKEDMSFIRST is not set
# CONFIG_READLINE_ECHO is not set
# CONFIG_STANDARD_SERIAL is not set # CONFIG_STANDARD_SERIAL is not set
CONFIG_ARCH="arm" CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="spresense" CONFIG_ARCH_BOARD="spresense"
@ -21,16 +21,8 @@ CONFIG_ARCH_BOARD_SPRESENSE=y
CONFIG_ARCH_CHIP="cxd56xx" CONFIG_ARCH_CHIP="cxd56xx"
CONFIG_ARCH_CHIP_CXD56XX=y CONFIG_ARCH_CHIP_CXD56XX=y
CONFIG_ARCH_INTERRUPTSTACK=2048 CONFIG_ARCH_INTERRUPTSTACK=2048
CONFIG_ARCH_MATH_H=y
CONFIG_ARCH_STACKDUMP=y CONFIG_ARCH_STACKDUMP=y
CONFIG_ARMV7M_USEBASEPRI=y CONFIG_ARMV7M_USEBASEPRI=y
CONFIG_ASMP=y
CONFIG_AUDIO=y
CONFIG_AUDIOUTILS_DSP_MOUNTPT="/mnt/sd0/BIN"
CONFIG_AUDIOUTILS_MANAGER=y
CONFIG_AUDIOUTILS_PLAYER=y
CONFIG_AUDIOUTILS_PLAYLIST=y
CONFIG_AUDIOUTILS_RECORDER=y
CONFIG_BOARDCTL_IOCTL=y CONFIG_BOARDCTL_IOCTL=y
CONFIG_BOARDCTL_POWEROFF=y CONFIG_BOARDCTL_POWEROFF=y
CONFIG_BOARDCTL_RESET=y CONFIG_BOARDCTL_RESET=y
@ -41,13 +33,13 @@ CONFIG_BOARD_CRASHDUMP=y
CONFIG_BOARD_LATE_INITIALIZE=y CONFIG_BOARD_LATE_INITIALIZE=y
CONFIG_BOARD_LOOPSPERMSEC=5434 CONFIG_BOARD_LOOPSPERMSEC=5434
CONFIG_BOOT_RUNFROMISRAM=y CONFIG_BOOT_RUNFROMISRAM=y
CONFIG_BUILTIN=y
CONFIG_CLOCK_MONOTONIC=y CONFIG_CLOCK_MONOTONIC=y
CONFIG_CXD56_ADC=y CONFIG_CXD56_ADC=y
CONFIG_CXD56_AUDIO=y
CONFIG_CXD56_BINARY=y CONFIG_CXD56_BINARY=y
CONFIG_CXD56_CHARGER=y CONFIG_CXD56_CHARGER=y
CONFIG_CXD56_CISIF=y CONFIG_CXD56_CISIF=y
CONFIG_CXD56_DMAC_SPI4_RX=y
CONFIG_CXD56_DMAC_SPI4_TX=y
CONFIG_CXD56_GAUGE=y CONFIG_CXD56_GAUGE=y
CONFIG_CXD56_GNSS=y CONFIG_CXD56_GNSS=y
CONFIG_CXD56_HPADC0=y CONFIG_CXD56_HPADC0=y
@ -65,33 +57,13 @@ CONFIG_CXD56_PWM3=y
CONFIG_CXD56_PWM=y CONFIG_CXD56_PWM=y
CONFIG_CXD56_SDIO=y CONFIG_CXD56_SDIO=y
CONFIG_CXD56_SPI3=y CONFIG_CXD56_SPI3=y
CONFIG_CXD56_SPI4=y
CONFIG_CXD56_SPI5=y CONFIG_CXD56_SPI5=y
CONFIG_CXD56_SPI=y CONFIG_CXD56_SPI=y
CONFIG_CXD56_UART2=y CONFIG_CXD56_UART2=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DNN_RT=y
CONFIG_DNN_RT_MP=y
CONFIG_DRIVERS_VIDEO=y CONFIG_DRIVERS_VIDEO=y
CONFIG_EXTERNALS_CMSIS=y
CONFIG_FAT_LCNAMES=y
CONFIG_FAT_LFN=y
CONFIG_FAT_MAXFNAME=64
CONFIG_FS_FAT=y CONFIG_FS_FAT=y
CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_REGISTER=y
CONFIG_FS_ROMFS=y
CONFIG_FS_SMARTFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_LCD=y
CONFIG_LCD_NOGETRUN=y
CONFIG_LIBC_FLOATINGPOINT=y CONFIG_LIBC_FLOATINGPOINT=y
CONFIG_LIBC_IPv4_ADDRCONV=y
CONFIG_LIBC_IPv6_ADDRCONV=y
CONFIG_LIB_KBDCODEC=y
CONFIG_MAX_WDOGPARMS=2
CONFIG_MEMUTILS=y
CONFIG_MMCSD=y CONFIG_MMCSD=y
CONFIG_MMCSD_SDIO=y CONFIG_MMCSD_SDIO=y
CONFIG_MTD=y CONFIG_MTD=y
@ -101,32 +73,12 @@ CONFIG_MTD_SMART_ENABLE_CRC=y
CONFIG_MTD_SMART_FSCK=y CONFIG_MTD_SMART_FSCK=y
CONFIG_MTD_SMART_SECTOR_SIZE=4096 CONFIG_MTD_SMART_SECTOR_SIZE=4096
CONFIG_NAME_MAX=64 CONFIG_NAME_MAX=64
CONFIG_NET=y
CONFIG_NETDEVICES=y
CONFIG_NETDEV_LATEINIT=y
CONFIG_NET_SOCKOPTS=y
CONFIG_NET_TCP_NO_STACK=y
CONFIG_NET_UDP_NO_STACK=y
CONFIG_NET_USRSOCK=y
CONFIG_NET_USRSOCK_TCP=y
CONFIG_NET_USRSOCK_UDP=y
CONFIG_NFILE_STREAMS=8
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_DISABLE_LOSMART=y
CONFIG_NSH_LINELEN=160
CONFIG_NSH_MAXARGUMENTS=14
CONFIG_NSH_READLINE=y CONFIG_NSH_READLINE=y
CONFIG_PIPES=y CONFIG_PIPES=y
CONFIG_PREALLOC_MQ_MSGS=4
CONFIG_PREALLOC_TIMERS=4 CONFIG_PREALLOC_TIMERS=4
CONFIG_PREALLOC_WDOGS=16
CONFIG_PWM=y CONFIG_PWM=y
CONFIG_RAM_SIZE=1572864 CONFIG_RAM_SIZE=1572864
CONFIG_RAM_START=0x0d000000 CONFIG_RAM_START=0x0d000000
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_READLINE_CMD_HISTORY_LINELEN=160
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_RR_INTERVAL=200 CONFIG_RR_INTERVAL=200
CONFIG_RTC=y CONFIG_RTC=y
CONFIG_RTC_ALARM=y CONFIG_RTC_ALARM=y
@ -141,21 +93,14 @@ CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_WAITPID=y CONFIG_SCHED_WAITPID=y
CONFIG_SDCLONE_DISABLE=y CONFIG_SDCLONE_DISABLE=y
CONFIG_SDIO_MUXBUS=y CONFIG_SDIO_MUXBUS=y
CONFIG_SDK_AUDIO=y
CONFIG_SERIAL_TERMIOS=y CONFIG_SERIAL_TERMIOS=y
CONFIG_SMARTFS_ALIGNED_ACCESS=y
CONFIG_SMARTFS_MAXNAMLEN=30
CONFIG_SMARTFS_MULTI_ROOT_DIRS=y
CONFIG_SPECIFIC_DRIVERS=y
CONFIG_SPI=y CONFIG_SPI=y
CONFIG_SPRESENSE_EXTENSION=y CONFIG_SPRESENSE_EXTENSION=y
CONFIG_START_DAY=6 CONFIG_START_DAY=6
CONFIG_START_MONTH=12 CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011 CONFIG_START_YEAR=2011
CONFIG_SYSTEMTICK_HOOK=y CONFIG_SYSTEMTICK_HOOK=y
CONFIG_SYSTEM_CLE=y
CONFIG_SYSTEM_NSH=y CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_CXXINITIALIZE=y
CONFIG_UART1_RXBUFSIZE=1024 CONFIG_UART1_RXBUFSIZE=1024
CONFIG_UART1_SERIAL_CONSOLE=y CONFIG_UART1_SERIAL_CONSOLE=y
CONFIG_UART1_TXBUFSIZE=1024 CONFIG_UART1_TXBUFSIZE=1024

@ -1 +1 @@
Subproject commit b575f1c48afb5acca27a1281a9036287cf3d2868 Subproject commit 6a148be8497704d4afb5d14c175a12a592813fac

View File

@ -30,23 +30,20 @@
# POSSIBILITY OF SUCH DAMAGE. # POSSIBILITY OF SUCH DAMAGE.
# #
import time
import sys
import os
import struct
import glob
import fnmatch
import errno
import telnetlib
import argparse import argparse
import shutil import errno
import subprocess import os
import re import re
import subprocess
import sys
import telnetlib
import time
import xmodem import xmodem
import_serial_module = True import_serial_module = True
# When SDK release, plase set SDK_RELEASE as True. # When SDK release, please set SDK_RELEASE as True.
SDK_RELEASE = False SDK_RELEASE = False
if SDK_RELEASE: if SDK_RELEASE:
@ -58,7 +55,7 @@ else:
try: try:
import serial import serial
except: except ImportError:
import_serial_module = False import_serial_module = False
# supported environment various # supported environment various
@ -71,6 +68,7 @@ PROTOCOL_TELNET = 1
MAX_DOT_COUNT = 70 MAX_DOT_COUNT = 70
# configure parameters and default value # configure parameters and default value
class ConfigArgs: class ConfigArgs:
PROTOCOL_TYPE = None PROTOCOL_TYPE = None
@ -173,7 +171,10 @@ class ConfigArgsLoader:
group = self.parser.add_argument_group() group = self.parser.add_argument_group()
group.add_argument("-c", "--serial-port", dest="serial_port", help="the serial port") group.add_argument("-c", "--serial-port", dest="serial_port", help="the serial port")
group.add_argument( group.add_argument(
"-b", "--xmodem-baudrate", dest="xmodem_baud", help="Use the faster baudrate in xmodem" "-b",
"--xmodem-baudrate",
dest="xmodem_baud",
help="Use the faster baudrate in xmodem",
) )
mutually_group = self.parser.add_mutually_exclusive_group() mutually_group = self.parser.add_mutually_exclusive_group()
@ -223,12 +224,12 @@ class ConfigArgsLoader:
ConfigArgs.PKGUPD_NAME = args.pkgupd_name ConfigArgs.PKGUPD_NAME = args.pkgupd_name
# Get serial port or telnet server ip etc # Get serial port or telnet server ip etc
if args.serial_protocol == True: if args.serial_protocol is True:
ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL
elif args.telnet_protocol == True: elif args.telnet_protocol is True:
ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET
if ConfigArgs.PROTOCOL_TYPE == None: if ConfigArgs.PROTOCOL_TYPE is None:
proto = os.environ.get("CXD56_PROTOCOL") proto = os.environ.get("CXD56_PROTOCOL")
if proto is not None: if proto is not None:
if "s" in proto: if "s" in proto:
@ -236,7 +237,7 @@ class ConfigArgsLoader:
elif "t" in proto: elif "t" in proto:
ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET
if ConfigArgs.PROTOCOL_TYPE == None: if ConfigArgs.PROTOCOL_TYPE is None:
ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL
if ConfigArgs.PROTOCOL_TYPE == PROTOCOL_SERIAL: if ConfigArgs.PROTOCOL_TYPE == PROTOCOL_SERIAL:
@ -358,8 +359,7 @@ class TelnetDev:
if MAX_DOT_COUNT < cur_count: if MAX_DOT_COUNT < cur_count:
cur_count = MAX_DOT_COUNT cur_count = MAX_DOT_COUNT
for idx in range(cur_count - self.count): for idx in range(cur_count - self.count):
print("#", end="") print("#", end="", flush=True)
sys.stdout.flush()
self.count = cur_count self.count = cur_count
if self.count == MAX_DOT_COUNT: if self.count == MAX_DOT_COUNT:
print("\n") print("\n")
@ -584,7 +584,7 @@ def main():
try: try:
config_loader = ConfigArgsLoader() config_loader = ConfigArgsLoader()
config_loader.update_config() config_loader.update_config()
except: except Exception:
return errno.EINVAL return errno.EINVAL
# Wait to reset the board # Wait to reset the board
@ -593,7 +593,7 @@ def main():
do_wait_reset = True do_wait_reset = True
if ConfigArgs.AUTO_RESET: if ConfigArgs.AUTO_RESET:
if subprocess.call("cd " + sys.path[0] + "; ./reset_board.sh", shell=True) == 0: if subprocess.call("cd " + sys.path[0] + "; ./reset_board.sh", shell=True) == 0:
print("auto reset board sucess!!") print("auto reset board success!!")
do_wait_reset = False do_wait_reset = False
bootrom_msg = writer.cancel_autoboot() bootrom_msg = writer.cancel_autoboot()
@ -601,7 +601,7 @@ def main():
do_wait_reset = False do_wait_reset = False
bootrom_msg = writer.cancel_autoboot() bootrom_msg = writer.cancel_autoboot()
if ConfigArgs.WAIT_RESET == False and do_wait_reset == True: if ConfigArgs.WAIT_RESET is False and do_wait_reset is True:
rx = writer.recv() rx = writer.recv()
time.sleep(1) time.sleep(1)
for i in range(3): for i in range(3):
@ -621,7 +621,7 @@ def main():
# Remove files # Remove files
if ConfigArgs.ERASE_NAME: if ConfigArgs.ERASE_NAME:
print(">>> Remove exisiting files ...") print(">>> Remove existing files ...")
writer.delete_files(ConfigArgs.ERASE_NAME) writer.delete_files(ConfigArgs.ERASE_NAME)
# Install files # Install files

View File

@ -0,0 +1,2 @@
pyserial>=2.7
xmodem>=0.3.2

View File

@ -1,808 +0,0 @@
"""
===============================
XMODEM file transfer protocol
===============================
.. $Id$
This is a literal implementation of XMODEM.TXT_, XMODEM1K.TXT_ and
XMODMCRC.TXT_, support for YMODEM and ZMODEM is pending. YMODEM should
be fairly easy to implement as it is a hack on top of the XMODEM
protocol using sequence bytes ``0x00`` for sending file names (and some
meta data).
.. _XMODEM.TXT: doc/XMODEM.TXT
.. _XMODEM1K.TXT: doc/XMODEM1K.TXT
.. _XMODMCRC.TXT: doc/XMODMCRC.TXT
Data flow example including error recovery
==========================================
Here is a sample of the data flow, sending a 3-block message.
It includes the two most common line hits - a garbaged block,
and an ``ACK`` reply getting garbaged. ``CRC`` or ``CSUM`` represents
the checksum bytes.
XMODEM 128 byte blocks
----------------------
::
SENDER RECEIVER
<-- NAK
SOH 01 FE Data[128] CSUM -->
<-- ACK
SOH 02 FD Data[128] CSUM -->
<-- ACK
SOH 03 FC Data[128] CSUM -->
<-- ACK
SOH 04 FB Data[128] CSUM -->
<-- ACK
SOH 05 FA Data[100] CPMEOF[28] CSUM -->
<-- ACK
EOT -->
<-- ACK
XMODEM-1k blocks, CRC mode
--------------------------
::
SENDER RECEIVER
<-- C
STX 01 FE Data[1024] CRC CRC -->
<-- ACK
STX 02 FD Data[1024] CRC CRC -->
<-- ACK
STX 03 FC Data[1000] CPMEOF[24] CRC CRC -->
<-- ACK
EOT -->
<-- ACK
Mixed 1024 and 128 byte Blocks
------------------------------
::
SENDER RECEIVER
<-- C
STX 01 FE Data[1024] CRC CRC -->
<-- ACK
STX 02 FD Data[1024] CRC CRC -->
<-- ACK
SOH 03 FC Data[128] CRC CRC -->
<-- ACK
SOH 04 FB Data[100] CPMEOF[28] CRC CRC -->
<-- ACK
EOT -->
<-- ACK
YMODEM Batch Transmission Session (1 file)
------------------------------------------
::
SENDER RECEIVER
<-- C (command:rb)
SOH 00 FF foo.c NUL[123] CRC CRC -->
<-- ACK
<-- C
SOH 01 FE Data[128] CRC CRC -->
<-- ACK
SOH 02 FC Data[128] CRC CRC -->
<-- ACK
SOH 03 FB Data[100] CPMEOF[28] CRC CRC -->
<-- ACK
EOT -->
<-- NAK
EOT -->
<-- ACK
<-- C
SOH 00 FF NUL[128] CRC CRC -->
<-- ACK
"""
__author__ = "Wijnand Modderman <maze@pyth0n.org>"
__copyright__ = ["Copyright (c) 2010 Wijnand Modderman", "Copyright (c) 1981 Chuck Forsberg"]
__license__ = "MIT"
__version__ = "0.3.2"
import logging
import time
import sys
from functools import partial
import collections
# Loggerr
log = logging.getLogger("xmodem")
# Protocol bytes
SOH = bytes([0x01])
STX = bytes([0x02])
EOT = bytes([0x04])
ACK = bytes([0x06])
DLE = bytes([0x10])
NAK = bytes([0x15])
CAN = bytes([0x18])
CRC = bytes([0x43]) # C
class XMODEM(object):
"""
XMODEM Protocol handler, expects an object to read from and an object to
write to.
>>> def getc(size, timeout=1):
... return data or None
...
>>> def putc(data, timeout=1):
... return size or None
...
>>> modem = XMODEM(getc, putc)
:param getc: Function to retreive bytes from a stream
:type getc: callable
:param putc: Function to transmit bytes to a stream
:type putc: callable
:param mode: XMODEM protocol mode
:type mode: string
:param pad: Padding character to make the packets match the packet size
:type pad: char
"""
# crctab calculated by Mark G. Mendel, Network Systems Corporation
crctable = [
0x0000,
0x1021,
0x2042,
0x3063,
0x4084,
0x50A5,
0x60C6,
0x70E7,
0x8108,
0x9129,
0xA14A,
0xB16B,
0xC18C,
0xD1AD,
0xE1CE,
0xF1EF,
0x1231,
0x0210,
0x3273,
0x2252,
0x52B5,
0x4294,
0x72F7,
0x62D6,
0x9339,
0x8318,
0xB37B,
0xA35A,
0xD3BD,
0xC39C,
0xF3FF,
0xE3DE,
0x2462,
0x3443,
0x0420,
0x1401,
0x64E6,
0x74C7,
0x44A4,
0x5485,
0xA56A,
0xB54B,
0x8528,
0x9509,
0xE5EE,
0xF5CF,
0xC5AC,
0xD58D,
0x3653,
0x2672,
0x1611,
0x0630,
0x76D7,
0x66F6,
0x5695,
0x46B4,
0xB75B,
0xA77A,
0x9719,
0x8738,
0xF7DF,
0xE7FE,
0xD79D,
0xC7BC,
0x48C4,
0x58E5,
0x6886,
0x78A7,
0x0840,
0x1861,
0x2802,
0x3823,
0xC9CC,
0xD9ED,
0xE98E,
0xF9AF,
0x8948,
0x9969,
0xA90A,
0xB92B,
0x5AF5,
0x4AD4,
0x7AB7,
0x6A96,
0x1A71,
0x0A50,
0x3A33,
0x2A12,
0xDBFD,
0xCBDC,
0xFBBF,
0xEB9E,
0x9B79,
0x8B58,
0xBB3B,
0xAB1A,
0x6CA6,
0x7C87,
0x4CE4,
0x5CC5,
0x2C22,
0x3C03,
0x0C60,
0x1C41,
0xEDAE,
0xFD8F,
0xCDEC,
0xDDCD,
0xAD2A,
0xBD0B,
0x8D68,
0x9D49,
0x7E97,
0x6EB6,
0x5ED5,
0x4EF4,
0x3E13,
0x2E32,
0x1E51,
0x0E70,
0xFF9F,
0xEFBE,
0xDFDD,
0xCFFC,
0xBF1B,
0xAF3A,
0x9F59,
0x8F78,
0x9188,
0x81A9,
0xB1CA,
0xA1EB,
0xD10C,
0xC12D,
0xF14E,
0xE16F,
0x1080,
0x00A1,
0x30C2,
0x20E3,
0x5004,
0x4025,
0x7046,
0x6067,
0x83B9,
0x9398,
0xA3FB,
0xB3DA,
0xC33D,
0xD31C,
0xE37F,
0xF35E,
0x02B1,
0x1290,
0x22F3,
0x32D2,
0x4235,
0x5214,
0x6277,
0x7256,
0xB5EA,
0xA5CB,
0x95A8,
0x8589,
0xF56E,
0xE54F,
0xD52C,
0xC50D,
0x34E2,
0x24C3,
0x14A0,
0x0481,
0x7466,
0x6447,
0x5424,
0x4405,
0xA7DB,
0xB7FA,
0x8799,
0x97B8,
0xE75F,
0xF77E,
0xC71D,
0xD73C,
0x26D3,
0x36F2,
0x0691,
0x16B0,
0x6657,
0x7676,
0x4615,
0x5634,
0xD94C,
0xC96D,
0xF90E,
0xE92F,
0x99C8,
0x89E9,
0xB98A,
0xA9AB,
0x5844,
0x4865,
0x7806,
0x6827,
0x18C0,
0x08E1,
0x3882,
0x28A3,
0xCB7D,
0xDB5C,
0xEB3F,
0xFB1E,
0x8BF9,
0x9BD8,
0xABBB,
0xBB9A,
0x4A75,
0x5A54,
0x6A37,
0x7A16,
0x0AF1,
0x1AD0,
0x2AB3,
0x3A92,
0xFD2E,
0xED0F,
0xDD6C,
0xCD4D,
0xBDAA,
0xAD8B,
0x9DE8,
0x8DC9,
0x7C26,
0x6C07,
0x5C64,
0x4C45,
0x3CA2,
0x2C83,
0x1CE0,
0x0CC1,
0xEF1F,
0xFF3E,
0xCF5D,
0xDF7C,
0xAF9B,
0xBFBA,
0x8FD9,
0x9FF8,
0x6E17,
0x7E36,
0x4E55,
0x5E74,
0x2E93,
0x3EB2,
0x0ED1,
0x1EF0,
]
def __init__(self, getc, putc, mode="xmodem", pad=b"\x1a"):
self.getc = getc
self.putc = putc
self.mode = mode
self.pad = pad
def abort(self, count=2, timeout=60):
"""
Send an abort sequence using CAN bytes.
"""
for counter in range(0, count):
self.putc(CAN, timeout)
def send(self, stream, retry=32, timeout=360, quiet=0, callback=None):
"""
Send a stream via the XMODEM protocol.
>>> stream = file('/etc/issue', 'rb')
>>> print modem.send(stream)
True
Returns ``True`` upon succesful transmission or ``False`` in case of
failure.
:param stream: The stream object to send data from.
:type stream: stream (file, etc.)
:param retry: The maximum number of times to try to resend a failed
packet before failing.
:type retry: int
:param timeout: The number of seconds to wait for a response before
timing out.
:type timeout: int
:param quiet: If 0, it prints info to stderr. If 1, it does not print any info.
:type quiet: int
:param callback: Reference to a callback function that has the
following signature. This is useful for
getting status updates while a xmodem
transfer is underway.
Expected callback signature:
def callback(total_packets, success_count, error_count)
:type callback: callable
"""
# initialize protocol
try:
packet_size = dict(xmodem=128, xmodem1k=1024)[self.mode]
except AttributeError:
raise ValueError("An invalid mode was supplied")
error_count = 0
crc_mode = 0
cancel = 0
while True:
char = self.getc(1)
if char:
if char == NAK:
crc_mode = 0
break
elif char == CRC:
crc_mode = 1
break
elif char == CAN:
if not quiet:
print("received CAN", file=sys.stderr)
if cancel:
return False
else:
cancel = 1
else:
log.error("send ERROR expected NAK/CRC, got %s" % (ord(char),))
error_count += 1
if error_count >= retry:
self.abort(timeout=timeout)
return False
# send data
error_count = 0
success_count = 0
total_packets = 0
sequence = 1
while True:
data = stream.read(packet_size)
if not data:
log.info("sending EOT")
# end of stream
break
total_packets += 1
data = data.ljust(packet_size, self.pad)
if crc_mode:
crc = self.calc_crc(data)
else:
crc = self.calc_checksum(data)
# emit packet
while True:
if packet_size == 128:
self.putc(SOH)
else: # packet_size == 1024
self.putc(STX)
self.putc(bytes([sequence]))
self.putc(bytes([0xFF - sequence]))
self.putc(data)
if crc_mode:
self.putc(bytes([crc >> 8]))
self.putc(bytes([crc & 0xFF]))
else:
self.putc(bytes([crc]))
char = self.getc(1, timeout)
if char == ACK:
success_count += 1
if isinstance(callback, collections.Callable):
callback(total_packets, success_count, error_count)
break
if char == NAK:
error_count += 1
if isinstance(callback, collections.Callable):
callback(total_packets, success_count, error_count)
if error_count >= retry:
# excessive amounts of retransmissions requested,
# abort transfer
self.abort(timeout=timeout)
log.warning("excessive NAKs, transfer aborted")
return False
# return to loop and resend
continue
else:
log.error("Not ACK, Not NAK")
error_count += 1
if isinstance(callback, collections.Callable):
callback(total_packets, success_count, error_count)
if error_count >= retry:
# excessive amounts of retransmissions requested,
# abort transfer
self.abort(timeout=timeout)
log.warning("excessive protocol errors, transfer aborted")
return False
# return to loop and resend
continue
# protocol error
self.abort(timeout=timeout)
log.error("protocol error")
return False
# keep track of sequence
sequence = (sequence + 1) % 0x100
while True:
# end of transmission
self.putc(EOT)
# An ACK should be returned
char = self.getc(1, timeout)
if char == ACK:
break
else:
error_count += 1
if error_count >= retry:
self.abort(timeout=timeout)
log.warning("EOT was not ACKd, transfer aborted")
return False
return True
def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0):
"""
Receive a stream via the XMODEM protocol.
>>> stream = file('/etc/issue', 'wb')
>>> print modem.recv(stream)
2342
Returns the number of bytes received on success or ``None`` in case of
failure.
"""
# initiate protocol
error_count = 0
char = 0
cancel = 0
while True:
# first try CRC mode, if this fails,
# fall back to checksum mode
if error_count >= retry:
self.abort(timeout=timeout)
return None
elif crc_mode and error_count < (retry / 2):
if not self.putc(CRC):
time.sleep(delay)
error_count += 1
else:
crc_mode = 0
if not self.putc(NAK):
time.sleep(delay)
error_count += 1
char = self.getc(1, timeout)
if not char:
error_count += 1
continue
elif char == SOH:
# crc_mode = 0
break
elif char == STX:
break
elif char == CAN:
if cancel:
return None
else:
cancel = 1
else:
error_count += 1
# read data
error_count = 0
income_size = 0
packet_size = 128
sequence = 1
cancel = 0
while True:
while True:
if char == SOH:
packet_size = 128
break
elif char == STX:
packet_size = 1024
break
elif char == EOT:
# We received an EOT, so send an ACK and return the received
# data length
self.putc(ACK)
return income_size
elif char == CAN:
# cancel at two consecutive cancels
if cancel:
return None
else:
cancel = 1
else:
if not quiet:
print("recv ERROR expected SOH/EOT, got", ord(char), file=sys.stderr)
error_count += 1
if error_count >= retry:
self.abort()
return None
# read sequence
error_count = 0
cancel = 0
seq1 = ord(self.getc(1))
seq2 = 0xFF - ord(self.getc(1))
if seq1 == sequence and seq2 == sequence:
# sequence is ok, read packet
# packet_size + checksum
data = self.getc(packet_size + 1 + crc_mode, timeout)
if crc_mode:
csum = (ord(data[-2]) << 8) + ord(data[-1])
data = data[:-2]
log.debug("CRC (%04x <> %04x)" % (csum, self.calc_crc(data)))
valid = csum == self.calc_crc(data)
else:
csum = data[-1]
data = data[:-1]
log.debug(
"checksum (checksum(%02x <> %02x)" % (ord(csum), self.calc_checksum(data))
)
valid = ord(csum) == self.calc_checksum(data)
# valid data, append chunk
if valid:
income_size += len(data)
stream.write(data)
self.putc(ACK)
sequence = (sequence + 1) % 0x100
char = self.getc(1, timeout)
continue
else:
# consume data
self.getc(packet_size + 1 + crc_mode)
self.debug("expecting sequence %d, got %d/%d" % (sequence, seq1, seq2))
# something went wrong, request retransmission
self.putc(NAK)
def calc_checksum(self, data, checksum=0):
"""
Calculate the checksum for a given block of data, can also be used to
update a checksum.
>>> csum = modem.calc_checksum('hello')
>>> csum = modem.calc_checksum('world', csum)
>>> hex(csum)
'0x3c'
"""
return (sum(map(ord, data)) + checksum) % 256
def calc_crc(self, data, crc=0):
"""
Calculate the Cyclic Redundancy Check for a given block of data, can
also be used to update a CRC.
>>> crc = modem.calc_crc('hello')
>>> crc = modem.calc_crc('world', crc)
>>> hex(crc)
'0xd5e3'
"""
for char in data:
crc = (crc << 8) ^ self.crctable[((crc >> 8) ^ int(char)) & 0xFF]
return crc & 0xFFFF
XMODEM1k = partial(XMODEM, mode="xmodem1k")
def run():
import optparse
import subprocess
parser = optparse.OptionParser(usage="%prog [<options>] <send|recv> filename filename")
parser.add_option("-m", "--mode", default="xmodem", help="XMODEM mode (xmodem, xmodem1k)")
options, args = parser.parse_args()
if len(args) != 3:
parser.error("invalid arguments")
return 1
elif args[0] not in ("send", "recv"):
parser.error("invalid mode")
return 1
def _func(so, si):
import select
import subprocess
print("si", si)
print("so", so)
def getc(size, timeout=3):
w, t, f = select.select([so], [], [], timeout)
if w:
data = so.read(size)
else:
data = None
print("getc(", repr(data), ")")
return data
def putc(data, timeout=3):
w, t, f = select.select([], [si], [], timeout)
if t:
si.write(data)
si.flush()
size = len(data)
else:
size = None
print("putc(", repr(data), repr(size), ")")
return size
return getc, putc
def _pipe(*command):
pipe = subprocess.Popen(command, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
return pipe.stdout, pipe.stdin
if args[0] == "recv":
import io
getc, putc = _func(*_pipe("sz", "--xmodem", args[2]))
stream = open(args[1], "wb")
xmodem = XMODEM(getc, putc, mode=options.mode)
status = xmodem.recv(stream, retry=8)
stream.close()
elif args[0] == "send":
getc, putc = _func(*_pipe("rz", "--xmodem", args[2]))
stream = open(args[1], "rb")
xmodem = XMODEM(getc, putc, mode=options.mode)
status = xmodem.send(stream, retry=8)
stream.close()
if __name__ == "__main__":
sys.exit(run())