├── MANIFEST.in ├── piupdue ├── __init__.py ├── Logger.py ├── ArduinoFlashHardValues.py ├── ArduinoFlashSerial.py ├── ArduinoFlashEefc.py ├── ArduinoFlashXmodem.py └── piupdue.py ├── TODO.md ├── .gitignore ├── setup.py ├── LICENSE ├── README.md └── README.rst /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.rst -------------------------------------------------------------------------------- /piupdue/__init__.py: -------------------------------------------------------------------------------- 1 | from piupdue import Upload, GetConnectedDeviceList -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # To Do 2 | 3 | * Increase speed of upload. 4 | * Add testing. 5 | * Check if runs from Windows & MAC. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled python modules. 2 | *.pyc 3 | 4 | # Setuptools distribution folder. 5 | /dist/ 6 | 7 | # Python egg metadata, regenerated from source files by setuptools. 8 | /*.egg-info -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | import os 3 | 4 | def readme(): 5 | with open('README.rst') as f: 6 | return f.read() 7 | 8 | setup( 9 | name='piupdue', 10 | version='1.0.1', 11 | description='Upload code to Arduino Due from Python.', 12 | url='https://github.com/johngrantuk/piupdue', 13 | author='John Grant', 14 | author_email='johngrantuk@googlemail.com', 15 | license='MIT', 16 | packages=find_packages(), 17 | 18 | long_description=readme(), 19 | 20 | ) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 johngrantuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /piupdue/Logger.py: -------------------------------------------------------------------------------- 1 | import time, logging, logging.handlers 2 | from datetime import datetime 3 | import os.path 4 | 5 | class Logger: 6 | saveToLog = False 7 | display = True 8 | my_logger = False 9 | sockJs = False 10 | 11 | def __init__(self, SaveToLog, FilePath="\piupdue.log", Display=True, SockJs=False): 12 | 13 | if SaveToLog: 14 | self.saveToLog = SaveToLog 15 | self.filePath = FilePath 16 | self.display = Display 17 | self.sockJs = SockJs 18 | self.my_logger = logging.getLogger(FilePath) 19 | self.my_logger.setLevel(logging.DEBUG) 20 | 21 | handler = logging.handlers.RotatingFileHandler(FilePath, maxBytes='2000000', backupCount=5) # Add the log message handler to the logger 22 | self.my_logger.addHandler(handler) 23 | 24 | def Log(self, Message): 25 | """ Saves message and timestamp to logfile.""" 26 | Message = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S:%f')[:-3] + ", " + Message 27 | 28 | if self.sockJs: 29 | self.sockJs.broadcast(self.sockJs._connected, Message) 30 | 31 | if self.display: 32 | print Message 33 | 34 | if self.saveToLog: 35 | if not os.path.isfile(self.filePath): 36 | raise Exception(self.filePath + " Log File Broken!!") 37 | 38 | self.my_logger.debug(Message) -------------------------------------------------------------------------------- /piupdue/ArduinoFlashHardValues.py: -------------------------------------------------------------------------------- 1 | """ Hard coded values and settings.""" 2 | import ctypes 3 | 4 | arduinoPort = '/dev/ttyACM1' 5 | isNativePort = True 6 | logFile = '/var/log/ScotSat/ArduinoFlash.log' 7 | sketchFile = "/var/www/Testing/TestSketch1.cpp.bin" 8 | 9 | LiveWrite = True 10 | 11 | # Set by flashFactory when EefcFlash is first called. FlashFactory.cpp LN192, flash = new EefcFlash(samba, "ATSAM3X8", 0x80000, 2048, 256, 2, 32, 0x20001000, 0x20010000, 0x400e0a00, false); 12 | words = ctypes.c_uint32(0x00000030).value 13 | stack = ctypes.c_uint32(0x00000020).value 14 | 15 | eraseAuto = False # set false on LN66 flasher.cpp when flash is erased. 16 | 17 | planes = 2 18 | pages = 2048 19 | addr = ctypes.c_uint32(0x80000).value 20 | user = ctypes.c_uint32(0x20001000).value 21 | regs = ctypes.c_uint32(0x400e0a00).value # FlashFactory.cpp LN192 22 | size = 256 23 | 24 | dstAddr = 0x00000028 # WordCopyArm.cpp 25 | srcAddr = 0x0000002c 26 | 27 | reset = user + 0x00000024 # WordCopyApplet - addr + applet.reset 28 | start = user + 0x00000000 # WordCopyApplet - addr + applet.start 29 | 30 | pageBufferA = user + 0x34 # _wordCopy.size() 31 | pageBufferB = pageBufferA + size 32 | 33 | EEFC0_FMR = regs + 0x00 # EefcFlash.cpp 34 | EEFC1_FMR = regs + 0x200 35 | EEFC0_FSR = regs + 0x08 36 | EEFC1_FSR = regs + 0x208 37 | EEFC_KEY = 0x5a 38 | EEFC_FCMD_EA = 0x5 39 | EEFC0_FCR = regs + 0x04 40 | EEFC1_FCR = regs + 0x204 41 | EEFC_FCMD_EWP = 0x3 42 | EEFC_FCMD_WP = 0x1 43 | 44 | EEFC_FCMD_SGPB = 0xb 45 | EEFC_FCMD_CGPB = 0xc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # piupdue 2 | Python package that enables a compiled Ardunio Sketch to be uploaded to an Arduino Due from a RaspberryPI (connected by USB). 3 | 4 | Based on the [Arduino BOSSA C++ source code.](https://github.com/shumatech/BOSSA/tree/arduino/src) 5 | 6 | Install using: $ pip install piupdue 7 | 8 | Sketch file must be saved locally on PI and be of type ".cpp.bin". 9 | 10 | # Run from cmd line 11 | 12 | usage: piupdue.py [-h] -f SKETCHFILE [-p PORT] [-l LOGFILE] 13 | 14 | optional arguments: 15 | 16 | -h, --help show this help message and exit 17 | 18 | -f SKETCHFILE, --file SKETCHFILE Sketch file to upload. Including path. (/path/File.cpp.bin) 19 | 20 | -p PORT, --port PORT Port Due is connected on. Leave blank for auto selection. 21 | 22 | -l LOGFILE, --log LOGFILE Save output to log file. 23 | 24 | # Use in Python Program 25 | 26 | Use the Upload function found in piupdue.py, Ex: 27 | 28 | import piupdue 29 | 30 | piupdue.Upload('/usr/update/FastSketch.cpp.bin', '/dev/ttyACM1', '/var/log/piupdue.log') 31 | 32 | # Some background 33 | 34 | The Arduino Due is a microcontroller board based on the Atmel SAM3X8E ARM Cortex-M3 CPU. It is the first Arduino board based on a 32-bit ARM core microcontroller instead of the more common AVR. 35 | The different mcu means the performance is better but also means the booting process is different from the AVR, Ardunio has designed the board such that flashing firmware is easier than what the 36 | stock SAM3X has offered, [this link](http://playground.arduino.cc/Bootloader/DueBootloaderExplained) explains the booting process and the tricks that Arduiro implemented. 37 | 38 | The "avrdude" program is used to upload code to the AVR based Arduinos and there are quite a few examples of how to do this from the RaspberryPI. BOSSAC is used by Arduino to upload code to the ARM, 39 | it's the command line variation of [BOSSA](http://www.shumatech.com/web/products/bossa) which is a simple and open source flash programming utility for Atmel's SAM family of flash-based ARM microcontrollers 40 | designed to replace Atmel's SAM-BA software. 41 | 42 | I required the ability to upload new code from a RaspberryPI to a Due. I couldn't find any info on getting BOSSAC to run on the PI so I have written this package in Python to replicate the fucntionality. 43 | 44 | 45 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | piupdue 2 | ======= 3 | 4 | Python package that enables a compiled Ardunio Sketch to be uploaded to 5 | an Arduino Due from a RaspberryPI (connected by USB). 6 | 7 | Based on the `Arduino BOSSA C++ source 8 | code. `__ 9 | 10 | Install using: $ pip install piupdue 11 | 12 | Sketch file must be saved locally on PI and be of type ".cpp.bin". 13 | 14 | Run from cmd line 15 | ================= 16 | 17 | usage: piupdue.py [-h] -f SKETCHFILE [-p PORT] [-l LOGFILE] 18 | 19 | optional arguments: -h, --help show this help message and exit -f 20 | SKETCHFILE, --file SKETCHFILE Sketch file to upload. Including path. 21 | (/path/File.cpp.bin) -p PORT, --port PORT Port Due is connected on. 22 | Leave blank for auto selection. -l LOGFILE, --log LOGFILE Save output to 23 | log file. # Use in Python Program 24 | 25 | Use the Upload function found in piupdue.py, Ex: 26 | 27 | import piupdue 28 | 29 | piupdue.Upload('/usr/update/FastSketch.cpp.bin', '/dev/ttyACM1', 30 | '/var/log/piupdue.log') 31 | 32 | Some background 33 | =============== 34 | 35 | The Arduino Due is a microcontroller board based on the Atmel SAM3X8E 36 | ARM Cortex-M3 CPU. It is the first Arduino board based on a 32-bit ARM 37 | core microcontroller instead of the more common AVR. The different mcu 38 | means the performance is better but also means the booting process is 39 | different from the AVR, Ardunio has designed the board such that 40 | flashing firmware is easier than what the stock SAM3X has offered, `this 41 | link `__ 42 | explains the booting process and the tricks that Arduiro implemented. 43 | 44 | The "avrdude" program is used to upload code to the AVR based Arduinos 45 | and there are quite a few examples of how to do this from the 46 | RaspberryPI. BOSSAC is used by Arduino to upload code to the ARM, it's 47 | the command line variation of 48 | `BOSSA `__ which is a 49 | simple and open source flash programming utility for Atmel's SAM family 50 | of flash-based ARM microcontrollers designed to replace Atmel's SAM-BA 51 | software. 52 | 53 | I required the ability to upload new code from a RaspberryPI to a Due. I 54 | couldn't find any info on getting BOSSAC to run on the PI so I have 55 | written this package in Python to replicate the fucntionality. 56 | -------------------------------------------------------------------------------- /piupdue/ArduinoFlashSerial.py: -------------------------------------------------------------------------------- 1 | """ 2 | Dealing with serial commands. 3 | ReadWord(SerialPort, WriteAddress, Log) - Writes the address command and return the value in a 32 bit number. 4 | ReadSerialByte(ser, Log) - Reads one byte of data from serial port. 5 | ReadSerial(ser, Log) - return any data in serial port. 6 | WriteWord(SerialPort, Addr, Value, Log) - Converts addr and value into message of format: W{addr},{value}# WXXXXXXXX,XXXXXXXX# and writes to serial port. 7 | Write(SerialPort, Log, Addr, Data, DataSize) - Converts addr and value into message of format: S{addr},{value}# SXXXXXXXX,XXXXXXXX# and writes to serial port. Then uses WriteXmodem to transfer data. 8 | Go(SerialPort, Log, Addr) - Converts addr into message of format: G{addr}# GXXXXXXXX# and writes to serial port. 9 | """ 10 | import time, binascii, sys 11 | import ArduinoFlashHardValues, ArduinoFlashXmodem 12 | 13 | def ReadWord(SerialPort, WriteAddress, Log): 14 | """ Writes to address and flips the received bits and stores in a 32 bit variable. """ 15 | Log.Log("ReadWord(), Writing: " + WriteAddress) 16 | 17 | SerialPort.write(WriteAddress) 18 | 19 | data = ReadSerial(SerialPort, Log) 20 | 21 | value = (ord(data[3]) << 24 | ord(data[2]) << 16 | ord(data[1]) << 8 | ord(data[0]) << 0) # ord() gives value of byte. Incase where data = {1,2,3,4}, value = 00000100 00000011 00000010 00000001, ie 4,3,2,1 22 | 23 | Log.Log("Value: " + str(value) + ", " + hex(value)) 24 | 25 | return value 26 | 27 | def ReadSerialByte(ser, Log): 28 | """ Reads one byte of data from serial port. """ 29 | 30 | toBeRead = ser.inWaiting() 31 | 32 | if toBeRead > 0: 33 | data = ser.read(1) 34 | 35 | Log.Log("Read data: " + data + ", " + binascii.hexlify(data)) 36 | 37 | return data 38 | else: 39 | #Log.Log("No Data To Be Read") 40 | return "" 41 | 42 | def ReadSerial(ser, Log): 43 | """ Reads any data in serial port. """ 44 | time.sleep(2) 45 | while 1: 46 | 47 | toBeRead = ser.inWaiting() 48 | Log.Log("ReadSerial(), " + str(toBeRead) + " bytes in buffer.") 49 | 50 | if toBeRead > 0: 51 | data = ser.read(toBeRead) 52 | 53 | hexData = ":".join("{:02x}".format(ord(c)) for c in data) # Just for display purposes. 54 | 55 | Log.Log("Read data: " + data + "\nIn hex: " + hexData) 56 | 57 | return data 58 | else: 59 | Log.Log("No Data To Be Read") 60 | break 61 | 62 | 63 | def WriteWord(SerialPort, Addr, Value, Log): 64 | """ Converts addr and value into message of format: W{addr},{value}# WXXXXXXXX,XXXXXXXX# and writes to serial port.""" 65 | addr = '{0:08X}'.format(Addr) 66 | value = '{0:08X}'.format(Value) 67 | 68 | output = "W" + addr + "," + value + '#' # W20001020,20010000# 69 | Log.Log("Writing Word: " + output) 70 | 71 | if ArduinoFlashHardValues.LiveWrite: 72 | SerialPort.write(output) 73 | 74 | def Write(SerialPort, Log, Addr, Data, DataSize, IsNativePort): 75 | """ 76 | Converts addr and value into message of format: S{addr},{value}# SXXXXXXXX,XXXXXXXX# and writes to serial port. 77 | Then uses WriteXmodem to transfer data. 78 | """ 79 | addr = '{0:08X}'.format(Addr) 80 | size = '{0:08X}'.format(DataSize) 81 | 82 | output = "S" + addr + "," + size + '#' 83 | Log.Log("Writing: " + output) 84 | 85 | if ArduinoFlashHardValues.LiveWrite: 86 | SerialPort.write(output) 87 | 88 | if IsNativePort: 89 | ArduinoFlashXmodem.WriteBinary(SerialPort, Log, Data, len(Data)) 90 | else: 91 | ArduinoFlashXmodem.WriteXmodem(SerialPort, Log, Data, DataSize) 92 | 93 | def Go(SerialPort, Log, Addr): 94 | """ Converts addr into message of format: G{addr}# GXXXXXXXX# and writes to serial port.""" 95 | addr = '{0:08X}'.format(Addr) 96 | 97 | output = "G" + addr + "#" #snprintf((char*) cmd, sizeof(cmd), "G%08X#", addr); G20001020# 98 | 99 | Log.Log("Serial.Go(): " + output) 100 | 101 | if ArduinoFlashHardValues.LiveWrite: 102 | SerialPort.write(output) -------------------------------------------------------------------------------- /piupdue/ArduinoFlashEefc.py: -------------------------------------------------------------------------------- 1 | """ Handles main processor operations. 2 | WriteFileToFlash() 3 | LoadBuffer() 4 | WritePage() 5 | EraseFlash() 6 | SetBootFlash() 7 | Reset() 8 | 9 | Not sure what all are doing but tests have worked. 10 | """ 11 | import ArduinoFlashSerial, ArduinoFlashHardValues 12 | import ctypes, time, os 13 | 14 | def WriteFileToFlash(SerialPort, Log, File, IsNativePort): 15 | """ 16 | Writes File to processors flash in blocks pageSize long. 17 | """ 18 | Log.Log("Writing file to flash: " + File) 19 | 20 | pageSize = ArduinoFlashHardValues.size # Size of data blocks to be written. 21 | pageNum = 0 22 | offset = 0 # -- Flash.h LN99 => 0 23 | numPages = 0 24 | onBufferA = True # LN52 Flash.cpp 25 | 26 | fileSizeBytes = os.path.getsize(File) # Find file size. 27 | 28 | numPages = (fileSizeBytes + pageSize - 1) / pageSize # 47 pages for blink. 29 | if numPages > ArduinoFlashHardValues.pages: 30 | raise Exception("WriteFlash()-File Size Error. numPages: " + str(numPages)) 31 | 32 | Log.Log("Writing " + str(fileSizeBytes) + "bytes to flash in " + str(numPages) + " pages.") 33 | 34 | f = open(File, 'rb') 35 | 36 | while True: 37 | piece = f.read(pageSize) # Reads a block of data from file. 38 | 39 | if not piece: 40 | Log.Log("End of file??") 41 | break 42 | 43 | readBytes = len(piece) 44 | 45 | Log.Log("Read: " + str(readBytes) + "bytes from file. onBufferA: " + str(onBufferA) + ", PageNum: " + str(pageNum)) 46 | 47 | dataJ = [] 48 | 49 | for i in range(0, readBytes): 50 | dataJ.append(ord(piece[i])) 51 | 52 | LoadBuffer(SerialPort, Log, onBufferA, dataJ, IsNativePort) 53 | 54 | page = offset + pageNum 55 | onBufferA = WritePage(page, onBufferA, SerialPort, Log) 56 | 57 | pageNum += 1 58 | 59 | if pageNum == numPages or readBytes != pageSize: 60 | Log.Log("End of file...") 61 | break 62 | 63 | f.close() 64 | Log.Log("End of WriteFlash()\n") 65 | 66 | def EraseFlash(SerialPort, Log): 67 | """ Erases processor flash. """ 68 | Log.Log("EraseFlash():") 69 | 70 | WaitFSR(SerialPort, Log) 71 | 72 | WriteFCR0(ArduinoFlashHardValues.EEFC_FCMD_EA, 0, SerialPort, Log) 73 | 74 | WaitFSR(SerialPort, Log) 75 | 76 | WriteFCR1(ArduinoFlashHardValues.EEFC_FCMD_EA, 0, SerialPort, Log) 77 | 78 | Log.Log("Flash Erased.") 79 | 80 | def LoadBuffer(SerialPort, Log, OnBufferA, Data, IsNativePort): 81 | """ 82 | Writes SXXXXXXXX,XXXXXXXX# command then Xmodem. 83 | """ 84 | Log.Log("LoadBuffer():") 85 | ArduinoFlashSerial.Write(SerialPort, Log, ArduinoFlashHardValues.pageBufferA if OnBufferA else ArduinoFlashHardValues.pageBufferB, Data, ArduinoFlashHardValues.size, IsNativePort) 86 | Log.Log("End of LoadBuffer()\n") 87 | 88 | 89 | def WritePage(Page, OnBufferA, SerialPort, Log): 90 | """ LN256 EefcFlash """ 91 | Log.Log("Write Page(), Page: " + str(Page) + ", OnBufferA: " + str(OnBufferA)) 92 | 93 | SetDstAddr(ArduinoFlashHardValues.addr + Page * ArduinoFlashHardValues.size, SerialPort, Log) 94 | 95 | SetSrcAddr(ArduinoFlashHardValues.pageBufferA if OnBufferA else ArduinoFlashHardValues.pageBufferB, SerialPort, Log) 96 | 97 | OnBufferA = not OnBufferA 98 | 99 | WaitFSR(SerialPort, Log) 100 | 101 | ArduinoFlashSerial.WriteWord(SerialPort, ArduinoFlashHardValues.reset, ArduinoFlashHardValues.start + 1, Log) # _wordCopy.runv(); 102 | 103 | ArduinoFlashSerial.Go(SerialPort, Log, ArduinoFlashHardValues.stack + ArduinoFlashHardValues.user) # _wordCopy.runv(); 104 | 105 | if ArduinoFlashHardValues.planes == 2 and Page >= ArduinoFlashHardValues.pages / 2: 106 | WriteFCR1(ArduinoFlashHardValues.EEFC_FCMD_EWP if ArduinoFlashHardValues.eraseAuto else ArduinoFlashHardValues.EEFC_FCMD_WP, Page - ArduinoFlashHardValues.pages / 2, SerialPort, Log) 107 | else: 108 | WriteFCR0(ArduinoFlashHardValues.EEFC_FCMD_EWP if ArduinoFlashHardValues.eraseAuto else ArduinoFlashHardValues.EEFC_FCMD_WP, Page, SerialPort, Log) 109 | 110 | Log.Log("End of Write Page()\n") 111 | return OnBufferA 112 | 113 | def SetBootFlash(SerialPort, Log, Enable): 114 | """ Sets boot flash. """ 115 | Log.Log("SetBootFlash():") 116 | WaitFSR(SerialPort, Log) 117 | WriteFCR0(ArduinoFlashHardValues.EEFC_FCMD_SGPB if Enable else ArduinoFlashHardValues.EEFC_FCMD_CGPB, 1, SerialPort, Log) 118 | WaitFSR(SerialPort, Log) 119 | time.sleep(1) 120 | Log.Log("End of SetBootFlash.") 121 | 122 | def Reset(SerialPort, Log): 123 | """ Resets processor. """ 124 | Log.Log("Reset()...") 125 | ArduinoFlashSerial.WriteWord(SerialPort, 0x400E1A00, 0xA500000D, Log) 126 | Log.Log("Reset done...") 127 | time.sleep(1) 128 | 129 | def WaitFSR(SerialPort, Log): 130 | """ Not sure what it does. """ 131 | Log.Log("WaitFSR():") 132 | tries = 0 133 | fsr1 = ctypes.c_uint32(0x1).value 134 | 135 | while tries <= 500: 136 | 137 | addr = "w" + '{0:08X}'.format(ArduinoFlashHardValues.EEFC0_FSR) + ",4#" 138 | Log.Log("Sending EEFC0_FSR: " + addr) 139 | 140 | if ArduinoFlashHardValues.LiveWrite: 141 | fsr0 = ArduinoFlashSerial.ReadWord(SerialPort, addr, Log) 142 | 143 | if fsr0 & (1 << 2): 144 | Log.Log("WaitFSR() Error. fsr0") 145 | 146 | addr = "w" + '{0:08X}'.format(ArduinoFlashHardValues.EEFC1_FSR) + ",4#" 147 | Log.Log("Sending EFC1_FSR: " + addr) 148 | 149 | if ArduinoFlashHardValues.LiveWrite: 150 | fsr1 = ArduinoFlashSerial.ReadWord(SerialPort, addr, Log) 151 | 152 | if fsr1 & (1 << 2): 153 | Log.Log("WaitFSR() Error. fsr1") 154 | 155 | if fsr0 & fsr1 & 0x1: 156 | Log.Log("Breaking.") 157 | break 158 | 159 | time.sleep(1) ##########??????? 160 | else: 161 | break 162 | 163 | tries += 1 164 | 165 | if tries > 500: 166 | Log.Log("WaitFSR() Error. Tried and failed!!") 167 | 168 | def WriteFCR0(cmd, arg, SerialPort, Log): 169 | """ 170 | writeFCR0(uint8_t cmd, uint32_t arg) 171 | writeFCR0(EEFC_FCMD_EA, 0); 172 | EefcFlash.cpp LN314 _samba.writeWord(EEFC0_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd); 173 | """ 174 | Log.Log("WriteFCR0()") 175 | value = (ArduinoFlashHardValues.EEFC_KEY << 24) | (arg << 8) | cmd 176 | 177 | ArduinoFlashSerial.WriteWord(SerialPort, ArduinoFlashHardValues.EEFC0_FCR, value, Log) 178 | 179 | def WriteFCR1(cmd, arg, SerialPort, Log): 180 | """ 181 | EefcFlash::writeFCR1(uint8_t cmd, uint32_t arg) 182 | _samba.writeWord(EEFC1_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd); 183 | """ 184 | Log.Log("WriteFCR1()") 185 | value = (ArduinoFlashHardValues.EEFC_KEY << 24) | (arg << 8) | cmd 186 | 187 | ArduinoFlashSerial.WriteWord(SerialPort, ArduinoFlashHardValues.EEFC1_FCR, value, Log) 188 | 189 | def SetDstAddr(DstAddr, SerialPort, Log): 190 | """ Unsure """ 191 | Log.Log("SetDstAddr()") 192 | ArduinoFlashSerial.WriteWord(SerialPort, ArduinoFlashHardValues.user + ArduinoFlashHardValues.dstAddr, DstAddr, Log) # WordCopyApplet (0x20001000 + 0x00000028), DstAddr 193 | 194 | def SetSrcAddr(SrcAddr, SerialPort, Log): 195 | """ Unsure """ 196 | Log.Log("SetSrcAddr()") 197 | ArduinoFlashSerial.WriteWord(SerialPort, ArduinoFlashHardValues.user + ArduinoFlashHardValues.srcAddr, SrcAddr, Log) # WordCopyApplet (0x20001000 + 0x00000028), DstAddr -------------------------------------------------------------------------------- /piupdue/ArduinoFlashXmodem.py: -------------------------------------------------------------------------------- 1 | """ FlashXmodem Implementation.""" 2 | import ctypes, time 3 | import ArduinoFlashHardValues, ArduinoFlashSerial 4 | 5 | BLK_SIZE = 128 6 | MAX_RETRIES = 20 7 | code = [0x09, 0x48, 0x0a, 0x49, 0x0a, 0x4a, 0x02, 0xe0, 0x08, 0xc9, 0x08, 0xc0, 0x01, 0x3a, 0x00, 0x2a,0xfa, 0xd1, 0x04, 0x48, 0x00, 0x28, 0x01, 0xd1, 0x01, 0x48, 0x85, 0x46, 0x70, 0x47, 0xc0, 0x46,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00] 8 | 9 | 10 | def crc16Calc(Data, StartElement, Len): 11 | """ Calculates 2 Byte CRC """ 12 | 13 | crc16Table = [0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,\ 14 | 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,\ 15 | 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,\ 16 | 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,\ 17 | 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,\ 18 | 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,\ 19 | 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,\ 20 | 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,\ 21 | 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,\ 22 | 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,\ 23 | 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,\ 24 | 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,\ 25 | 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,\ 26 | 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,\ 27 | 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,\ 28 | 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,\ 29 | 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,\ 30 | 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,\ 31 | 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,\ 32 | 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,\ 33 | 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,\ 34 | 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,\ 35 | 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,\ 36 | 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,\ 37 | 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,\ 38 | 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,\ 39 | 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,\ 40 | 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,\ 41 | 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,\ 42 | 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,\ 43 | 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,\ 44 | 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0] 45 | 46 | crc16 = ctypes.c_uint16(0).value 47 | 48 | for x in range(StartElement, Len + StartElement): 49 | crc16 = (crc16 << 8) ^ ctypes.c_uint16(crc16Table[((crc16 >> 8) ^ ctypes.c_uint8(Data[x]).value) & 0xff]).value 50 | 51 | crc16 = ctypes.c_uint16(crc16).value 52 | 53 | return crc16 54 | 55 | def Crc16Add(Data): 56 | """ Calculates two byte CRC and adds to end of Data array.""" 57 | 58 | crc16 = ctypes.c_uint16(crc16Calc(Data, 3, BLK_SIZE)).value 59 | 60 | Data[BLK_SIZE + 3] = (crc16 >> 8) & 0xff 61 | Data[BLK_SIZE + 4] = crc16 & 0xff 62 | 63 | def WriteBinary(SerialPort, Log, Data, Size): 64 | """ Writes all data to serial port. _port->write(buffer, size) != size""" 65 | Log.Log("WriteBinary()...") 66 | Log.Log("Writing bytes: " + str(Size)) 67 | 68 | blkStr = "" 69 | for e in Data: 70 | blkStr = blkStr + chr(e) 71 | 72 | if ArduinoFlashHardValues.LiveWrite: 73 | bytesWritten = SerialPort.write(blkStr) 74 | Log.Log("Bytes written: " + str(bytesWritten)) 75 | 76 | if bytesWritten != Size: 77 | raise Exception("WriteBinary() Exception.") 78 | 79 | 80 | def WriteXmodem(SerialPort, log, Data, Size): 81 | """ Main implementation of Xmodem(). See Samba.cpp LN392 """ 82 | log.Log("\n\nWriteXmodem():") 83 | 84 | blkNum = 1 # Block numbers haven't been implemented yet. 85 | blk = [ctypes.c_uint8(0).value] * (BLK_SIZE + 5) # Initial decleration of blk array. 86 | 87 | for retries in range(0, MAX_RETRIES): 88 | log.Log("Waiting for start char, C.") 89 | 90 | if ArduinoFlashHardValues.LiveWrite: 91 | receivedMsg = ArduinoFlashSerial.ReadSerialByte(SerialPort, log) 92 | else: 93 | receivedMsg = 'C' 94 | 95 | if receivedMsg == 'C': 96 | break 97 | 98 | if retries == MAX_RETRIES - 1: 99 | raise Exception("WriteXmodem() Waited Max For Start Char.") 100 | 101 | codeNo = 0 102 | bytesWritten = 0 103 | while Size > 0: 104 | 105 | blk[0] = ctypes.c_uint8(0x01).value # First three bytes are pre-filled. 106 | blk[1] = ctypes.c_uint8(blkNum & 0xff).value 107 | blk[2] = ctypes.c_uint8(~(blkNum & 0xff)).value 108 | 109 | log.Log("len(Data): " + str(len(Data)) + ", min: " + str(min(Size, BLK_SIZE))) 110 | log.Log("!. Code No: " + str(codeNo)) 111 | 112 | if codeNo < len(Data): 113 | for x in range(3, min(len(Data), BLK_SIZE) + 3): # Fills blk array (starting from 3rd element) with Data bytes. 114 | blk[x] = Data[codeNo] 115 | codeNo = codeNo + 1 116 | 117 | log.Log("2. Code No: " + str(codeNo)) 118 | 119 | if Size < BLK_SIZE: # Fills any unwritten elements with 0 BLK_SIZE=128. 120 | log.Log("Filling in 0s.") 121 | for x in range(3 + len(Data), BLK_SIZE): 122 | blk[x] = 0x00 123 | 124 | Crc16Add(blk) # Calculates two byte CRC and adds to end of blk. 125 | 126 | i = 0 # For display purpose. 127 | 128 | log.Log("Converting Xmodem CRC Code into string for serial transfer.") 129 | blkStr = "" 130 | for e in blk: 131 | blkStr = blkStr + chr(e) 132 | 133 | line = 0 134 | i = 0 # For display purpose. 135 | dataStr = "Writing Data: \n0. " 136 | for e in blk: 137 | dataStr = dataStr + hex(e) + " " 138 | 139 | if (i + 1)%16 == 0: 140 | line += 1 141 | dataStr = dataStr + "\n" + str(line) + ". " 142 | 143 | i += 1 144 | 145 | log.Log(dataStr) 146 | 147 | for retries in range(0, MAX_RETRIES): 148 | log.Log("WriteXmodem(), writing Xmodem CRC Code data...") 149 | if ArduinoFlashHardValues.LiveWrite: 150 | bytesWritten = SerialPort.write(blkStr) 151 | # Write to the SAM-BA 152 | log.Log("WriteXmodem(), xModem CRC Code data written. " + str(bytesWritten)) 153 | log.Log("WriteXmodem(), checking for ACK...") 154 | time.sleep(1) 155 | 156 | if ArduinoFlashHardValues.LiveWrite: 157 | receivedMsg = ArduinoFlashSerial.ReadSerialByte(SerialPort, log) 158 | else: 159 | receivedMsg = '\x06' 160 | 161 | if receivedMsg == '\x06': 162 | break 163 | 164 | time.sleep(3) 165 | 166 | if retries == MAX_RETRIES - 1: 167 | raise Exception("WriteXmodem() Waited While Writing Blk.") 168 | 169 | log.Log("Size: " + str(Size)) 170 | Size = Size - BLK_SIZE 171 | blkNum = blkNum + 1 172 | log.Log("Size: " + str(Size)) 173 | 174 | for retries in range(0, MAX_RETRIES): 175 | 176 | log.Log("ACK receive, writing EOT...") 177 | SerialPort.write('\x04') # 0x04 = EOT 178 | 179 | log.Log("Waiting for ACK.") 180 | time.sleep(1) 181 | 182 | if ArduinoFlashHardValues.LiveWrite: 183 | receivedMsg = ArduinoFlashSerial.ReadSerialByte(SerialPort, log) 184 | else: 185 | receivedMsg = '\x06' 186 | 187 | if receivedMsg == '\x06': 188 | log.Log("ACK received.") 189 | log.Log("WriteXmodem() Complete.") 190 | break 191 | 192 | time.sleep(3) 193 | 194 | if retries == MAX_RETRIES - 1: 195 | raise Exception("WriteXmodem() Waited While Writing EOT.") 196 | 197 | log.Log("WriteXmodem() Complete.\n") -------------------------------------------------------------------------------- /piupdue/piupdue.py: -------------------------------------------------------------------------------- 1 | """ Main program functions.""" 2 | import ArduinoFlashXmodem, Logger, ArduinoFlashSerial, ArduinoFlashEefc, ArduinoFlashHardValues 3 | import time, serial, os, sys 4 | import traceback 5 | import ctypes 6 | import argparse 7 | import signal 8 | 9 | ser = 0 10 | log = 0 11 | 12 | import subprocess 13 | import glob 14 | from os import listdir 15 | from os.path import isfile, join 16 | 17 | def GetConnectedDeviceList(): 18 | 19 | portList = [] 20 | #(ttyS|ttyUSB|ttyACM|ttyAMA|rfcomm|ttyO)[0-9]{1,3}"); 21 | for port in glob.glob('/dev/ttyACM*[0-9]'): 22 | GetPortInfo(port, portList) 23 | 24 | for port in glob.glob('/dev/ttyAMA*[0-9]'): 25 | GetPortInfo(port, portList) 26 | 27 | for ports in portList: 28 | print ports[0] + ", " + ports[1] 29 | 30 | return portList 31 | 32 | def GetPortInfo(Port, PortList): 33 | 34 | p = subprocess.Popen(["sudo udevadm info -q path -n " + Port], stdout=subprocess.PIPE, shell=True) 35 | (output, err) = p.communicate() 36 | 37 | p = subprocess.Popen(["sudo udevadm info --query=property -p " + output], stdout=subprocess.PIPE, shell=True) 38 | (output, err) = p.communicate() 39 | 40 | infoStrs = output.split('\n') 41 | 42 | for info in infoStrs: 43 | if "ID_VENDOR=Teensyduino" in info: 44 | PortList.append([Port, "Teensy"]) 45 | elif "ID_MODEL_ID=003e" in info: 46 | PortList.append([Port, "Due"]) 47 | elif "ID_MODEL_FROM_DATABASE=at91sam SAMBA bootloader" in info: 48 | PortList.append([Port, "Due-SAMBA Mode"]) 49 | 50 | def SetSamBA(DueSerialPort): 51 | """ 52 | Initial triggering of chip into SAM-BA mode. 53 | On the Programming Port there is an ATMEGA16U2 chip, acting as a USB bridge to expose the SAM UART as USB. 54 | If the host is connected to the programming port at baud rate 1200, the ATMEGA16U2 will assert the Erase pin and Reset pin of the SAM3X, forcing it to the SAM-BA bootloader mode. 55 | The port remains the same number but to access SAM-BA Baud rate must be changed to 115200. 56 | """ 57 | log.Log("Setting into SAM-BA..." + DueSerialPort) 58 | 59 | ser = serial.Serial(port=DueSerialPort,\ 60 | baudrate=1200,\ 61 | parity=serial.PARITY_NONE,\ 62 | stopbits=serial.STOPBITS_ONE,\ 63 | bytesize=serial.EIGHTBITS,\ 64 | timeout=2000) 65 | 66 | ser.write("\n") 67 | time.sleep(3) 68 | ser.close() 69 | 70 | log.Log("SAM-BA Set.") 71 | 72 | def ConnectSamBA(): 73 | """ 74 | Connects to a processor that has been set into SAM-BA bootloader mode. (115200 Baud) 75 | Does some initialisation then checks Chip ID confirming correct processor. 76 | """ 77 | log.Log("ConnectSamBA()...") 78 | 79 | ser = serial.Serial(port=ArduinoFlashHardValues.arduinoPort,\ 80 | baudrate=115200,\ 81 | parity=serial.PARITY_NONE,\ 82 | stopbits=serial.STOPBITS_ONE,\ 83 | bytesize=serial.EIGHTBITS,\ 84 | xonxoff=False,\ 85 | timeout=None) 86 | 87 | log.Log("Openining at 115200...\n") 88 | 89 | time.sleep(5) 90 | 91 | ser.flushInput() 92 | 93 | log.Log("Writing 0x80...\n") 94 | ser.write('\x80') 95 | ArduinoFlashSerial.ReadSerial(ser, log) 96 | 97 | log.Log("Writing 0x80...\n") 98 | ser.write('\x80') 99 | ArduinoFlashSerial.ReadSerial(ser, log) 100 | 101 | log.Log("Writing #...\n") 102 | ser.write("\x23") 103 | ArduinoFlashSerial.ReadSerial(ser, log) 104 | 105 | log.Log("Setting into Binary mode (N#)...\n") 106 | ser.write("\x4E\x23") 107 | ArduinoFlashSerial.ReadSerial(ser, log) 108 | 109 | log.Log("Reading Chip ID...\n") 110 | 111 | chipId = ArduinoFlashSerial.ReadWord(ser, "\x77\x34\x30\x30\x45\x30\x39\x34\x30\x2C\x34\x23", log) 112 | 113 | log.Log("Chip ID: " + str(chipId) + ", " + hex(chipId)) 114 | 115 | eproc = (chipId >> 5) & 0x7 116 | arch = (chipId >> 20) & 0xff 117 | 118 | log.Log("eproc: " + str(eproc) + ", " + hex(eproc)) 119 | log.Log("arch: " + str(arch) + ", " + hex(arch)) 120 | 121 | if eproc == 3: 122 | if arch >= 0x80 and arch <= 0x8a: # Check for SAM3 architecture 123 | log.Log("Supported SAM3 processor.") 124 | return ser 125 | if arch >= 0x93 and arch <= 0x9a: 126 | log.Log("Supported SAM3 processor.") 127 | return ser 128 | 129 | log.Log("Unsupported Cortex-M3 architecture.") 130 | return False 131 | else: 132 | log.Log("Unsupported processor") 133 | return False 134 | 135 | def ConnectSamBANative(DueSerialPort): 136 | """ 137 | Connects to a processor that has been set into SAM-BA bootloader mode. (115200 Baud) 138 | Does some initialisation then checks Chip ID confirming correct processor. 139 | """ 140 | log.Log("ConnectSamBA()...") 141 | 142 | ser = serial.Serial(port=DueSerialPort,\ 143 | baudrate=921600,\ 144 | parity=serial.PARITY_NONE,\ 145 | stopbits=serial.STOPBITS_ONE,\ 146 | bytesize=serial.EIGHTBITS,\ 147 | xonxoff=False,\ 148 | timeout=None) 149 | 150 | log.Log("Openining at 921600...\n") 151 | 152 | time.sleep(5) 153 | 154 | ser.flushInput() 155 | 156 | log.Log("Setting into Binary mode (N#)...\n") 157 | ser.write("\x4E\x23") 158 | ArduinoFlashSerial.ReadSerial(ser, log) 159 | 160 | log.Log("Check for USER Address...\n") 161 | 162 | userAdd = ArduinoFlashSerial.ReadWord(ser, "w00000000,4#", log) 163 | log.Log("User addr: " + str(userAdd) + ", " + hex(userAdd)) 164 | 165 | log.Log("Reading Chip ID...\n") 166 | 167 | chipId = ArduinoFlashSerial.ReadWord(ser, "\x77\x34\x30\x30\x45\x30\x39\x34\x30\x2C\x34\x23", log) # w400e0940,4# 168 | 169 | log.Log("Chip ID: " + str(chipId) + ", " + hex(chipId)) 170 | 171 | eproc = (chipId >> 5) & 0x7 172 | arch = (chipId >> 20) & 0xff 173 | 174 | log.Log("eproc: " + str(eproc) + ", " + hex(eproc)) 175 | log.Log("arch: " + str(arch) + ", " + hex(arch)) 176 | 177 | if eproc == 3: 178 | if arch >= 0x80 and arch <= 0x8a: # Check for SAM3 architecture 179 | log.Log("Supported SAM3 processor.") 180 | return ser 181 | if arch >= 0x93 and arch <= 0x9a: 182 | log.Log("Supported SAM3 processor.") 183 | return ser 184 | 185 | log.Log("Unsupported Cortex-M3 architecture.") 186 | return False 187 | else: 188 | log.Log("Unsupported processor") 189 | return False 190 | 191 | def ArduinoFlashLoad(SketchFile, DueSerialPort, IsNativePort): 192 | """ 193 | Loads a new sketch to Arduino Due. 194 | Sets into SAM-BA mode. 195 | Erases flash. 196 | Uploads new hex file. 197 | Sets boot flash. 198 | Resets processor. 199 | """ 200 | 201 | log.Log("ArduinoFlashLoad()...") 202 | 203 | serialPort = ConnectSamBANative(DueSerialPort) # Connects to SAM-BA mode and confirms correct processor. 204 | if not serialPort: 205 | return 206 | 207 | length = ctypes.c_uint32(len(ArduinoFlashXmodem.code)).value 208 | ArduinoFlashSerial.Write(serialPort, log, ArduinoFlashHardValues.user, ArduinoFlashXmodem.code, length, IsNativePort) # Writes the Xmodem hard code. Applet.cpp 209 | 210 | ArduinoFlashSerial.WriteWord(serialPort, ArduinoFlashHardValues.user + ArduinoFlashHardValues.words, ArduinoFlashHardValues.size / 4, log) # 4 comes from sizeof(uint32_t) ie 4 bytes 211 | 212 | ArduinoFlashSerial.WriteWord(serialPort, ArduinoFlashHardValues.user + ArduinoFlashHardValues.stack, ArduinoFlashHardValues.user, log) # Set stack? 213 | 214 | ArduinoFlashSerial.WriteWord(serialPort, ArduinoFlashHardValues.EEFC0_FMR, (0x6 << 8), log) # EefcFlash?? 215 | 216 | ArduinoFlashSerial.WriteWord(serialPort, ArduinoFlashHardValues.EEFC1_FMR, (0x6 << 8), log) 217 | 218 | ArduinoFlashEefc.EraseFlash(serialPort, log) # Erase Flash 219 | 220 | ArduinoFlashEefc.WriteFileToFlash(serialPort, log, SketchFile, IsNativePort) # Write new file 221 | 222 | ArduinoFlashEefc.SetBootFlash(serialPort, log, True) # Sets boot flash. 223 | 224 | ArduinoFlashEefc.Reset(serialPort, log) # Resets processor. 225 | 226 | log.Log("Flash Loaded.") 227 | 228 | def Checks(Port, SketchFile): 229 | """ Does basic checks that sketch file exists and port is connected.""" 230 | if not os.path.isfile(SketchFile): 231 | log.Log("Sketch File Does Not Exist: " + SketchFile) 232 | sys.exit() 233 | 234 | try: 235 | ser = serial.Serial(port=Port,\ 236 | baudrate=1200,\ 237 | parity=serial.PARITY_NONE,\ 238 | stopbits=serial.STOPBITS_ONE,\ 239 | bytesize=serial.EIGHTBITS,\ 240 | timeout=2000) 241 | 242 | except serial.SerialException: 243 | log.Log("Problem with selected Port. Double check it is correct.") 244 | sys.exit() 245 | except Exception: 246 | raise Exception("Unexpected excetion in Checks(): " + traceback.format_exc()) 247 | 248 | def Upload(sketchFile, port, logFile=False, sockJs=False): 249 | try: 250 | global log 251 | 252 | if not logFile: 253 | log = Logger.Logger(False) # Doesn't save to Log, just prints. 254 | else: 255 | log = Logger.Logger(True, logFile, True, sockJs) # Saves to Log file. 256 | 257 | log.Log("Starting ArduinoFlashLog.py") 258 | log.Log(sketchFile) 259 | log.Log(port) 260 | 261 | Checks(port, sketchFile) 262 | 263 | portDetail = [] 264 | GetPortInfo(port, portDetail) # Gets the details for the specified port. 265 | 266 | #log.Log(str(portDetail)) 267 | #log.Log(portDetail[0][1]) 268 | 269 | if len(portDetail) < 1: 270 | log.Log("Port not connected to a supported device.") 271 | elif portDetail[0][1] == "Due-SAMBA Mode": # Checks if port is already in SAM-BA mode. If it is then Flash file. 272 | log.Log("Already in SAM-BA Mode.") 273 | ArduinoFlashLoad(sketchFile, port, ArduinoFlashHardValues.isNativePort) 274 | elif portDetail[0][1] == "Due": # Checks if port is in Due mode. If so then set to SAM-BA then Flash file. 275 | log.Log("Setting into SAM-BA Mode.") 276 | SetSamBA(port) # Sets processor into SAM-BA mode. 277 | time.sleep(2) 278 | portList = GetConnectedDeviceList() # Gets list of all connected serials. 279 | 280 | for port in portList: # Check each port for a connect SAM-BA mode and assume it is correct one. 281 | log.Log("Port: " + str(port)) 282 | log.Log(str(port[1])) 283 | 284 | if port[1] == "Due-SAMBA Mode": 285 | log.Log("New port: " + port[0]) 286 | ArduinoFlashLoad(sketchFile, port[0], ArduinoFlashHardValues.isNativePort) 287 | break 288 | else: 289 | log.Log("Not a supported device.") 290 | 291 | if ser: 292 | ser.close() 293 | 294 | log.Log("Exiting ArduinoFlashLog.py") 295 | except Exception, e: 296 | log.Log("Main Exception:") 297 | log.Log(traceback.format_exc()) 298 | 299 | if __name__ == "__main__": 300 | """ Main entry for program. """ 301 | 302 | parser = argparse.ArgumentParser(description='Upload Arduino Sketch to Arduino Due via Pi.') 303 | 304 | parser.add_argument("-f", "--file", dest="sketchFile", required=True, help="Sketch file to upload. Including path. (/path/File.cpp.bin)") 305 | parser.add_argument("-p", "--port", dest="port", default=False, help="Port Due is connected on. Leave blank for auto selection.") 306 | parser.add_argument("-l", "--log", dest="logFile", default=False, help="Save output to log file.") 307 | 308 | args = parser.parse_args() 309 | 310 | sketchFile = args.sketchFile 311 | port = args.port 312 | logFile = args.logFile 313 | 314 | try: 315 | if not port: 316 | print "Attempting to find first connected Device." 317 | portList = GetConnectedDeviceList() # Gets list of all connected serials. 318 | for portDevice in portList: # Check each port for a connect SAM-BA mode and assume it is correct one. 319 | if portDevice[1] == "Due-SAMBA Mode": 320 | port = portDevice[0] 321 | break 322 | elif portDevice[1] == "Due": 323 | port = portDevice[0] 324 | break 325 | 326 | if not port: 327 | print "Couldn't find a connected Device to upload to." 328 | sys.exit() 329 | 330 | print "Uploading to Port: " + port 331 | Upload(sketchFile, port, logFile) 332 | except Exception, e: 333 | print "Main Exception:" 334 | print traceback.format_exc() --------------------------------------------------------------------------------