2012-02-16 19 views
3

これは数日間私を悩ませています。私は私のユーティリティLScreamerをWindows 7に移行しようとしていますが、協力しているようではありません。Python - LinuxからWindowsへのプログラムの移行は、Windowsでは動作しません。

このユーティリティは、atmegaで実行されているブートローダにAtmegaファームウェアファイルを送信します。 Linuxの場合、このユーティリティを実行すると、必要な再送信を行うだけでファイル全体を送信することができます。 Windowsでは、他のすべての送信は再送信であり、ほとんどの場合、プロセッサは完全なファームウェアを取得しません。

私はPythonとpyserialを理解することは、それらがOS間で移植可能でなければならないということです。しかし、私はPythonの使用経験がないので、おそらく私は何か変なことをしています。

以下に添付されているLScreamerユーティリティに観察可能なエラーはありますか?ご協力いただきありがとうございます!

#! /usr/bin/env python 
""" This program is a port of Screamer V2.0 produced on Sparkfun.com which is 
    useful for wirelessly downloading code to an arduino. 
    The problem with the original code was that it was written for Windows, 
    whereas there may be many Linux users that would like to use the program. 
    Currently this port only supports ATmega168 and ATmega1280, but it has 
    been written to easily add more processors. Questions and contributions 
    can be submitted back to the developer at [email protected] 

    This has been updated to work on Windows as well, but it will still be 
    called LScreamer. 

    Here is the sparkfun page: http://www.sparkfun.com/tutorials/122#Step2 

Usage: python LScreamer.py [options] [input file] 

Options: 
    -h, --help   show this help 
    -v, --verbose  show additional information 
    -p     Processor, 
         available arguments 'ATMEGA168', 'ATMEGA328' or 'ATMEGA1280' 
         default: ATMEGA168 
    -i, --interface Specify serial interface to broadcast 
         firmware file over, default /dev/ttyUSB0 

Examples: 
    LScreamer.py -p ATMEGA168 -v -i /dev/ttyUSB0 ~/file.hex 
      Wirelessly downloads file.hex to an ATMEGA168 processor 
    LScreamer.py -p ATMEGA328 -v -i COM1 C:/Project/file.hex 
      Wirelessly downloads file.hex to an ATMEGA328 processor 
    LScreamer.py 
      Lists this information as well as the available ports on the system. 
      This could be ran before inserting serial device, and after, to 
      determine which port it has been connected to. 

    """ 

import serial 
import glob 
import sys 
import getopt 
import platform 
from time import sleep 

def scan(): 
    """scan for available ports. return a list of device names.""" 
    if is_windows: 
     # scan for available ports. return a list of tuples (num, name) 
     available = [] 
     for i in range(256): 
      try: 
       s = serial.Serial(i) 
       available.append((i, s.portstr)) 
       s.close() 
      except serial.SerialException: 
       pass 
     return available 
    else: 
     return glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') 

def usage(): 
    print __doc__ 

class FileProc: 
    "File processing utilities" 

    def __init__(self, fileloc): 
     """Main processing occurs within the FileProc class""" 
     #define global variables modified in this def 

     self.setArc() 
     pfile = self.parse(fileloc) 
     if _parsed_file == 0: 
      print "Problem parsing hex file, please check file again" 
      sys.exit() 

     #file parsed successfully, initiate remote reset 
     print "Waiting for target IC to boot into bootloader" 
     if _verbose == 1: print "Open port " + _iface + ' with baud rate = 19200, 8 data bits, 1 stop bit, 1 sign bit with a 1 second timeout' 

     ser = serial.Serial(_iface, 19200, timeout=1) 

     #toggle RTS line to restart remote device 
     ser.setRTS(1)    #set RTS 
     ser.setRTS(0)    #Clear RTS 
     ser.setRTS(1)    #set RTS 
     ser.setRTS(0)    #Clear RTS 

     #sleep(1)    #wait for 1 seconds with RTS set 
     print " To quit waiting, do Cnrl + C" 
     if _verbose == 1: 
      print " If target IC does not boot into bootloader and start outputting a 5, not '5', then the target should be checked" 
     while ser.read(1) != '\x05': 
      pass 

     #target is in bootloader, send 6, not '6', to start firmware transmission 
     ser.write('\x06') 
     print "Target has successfully booted into bootloader, starting transmission of firmware" 

     current_memory_address = 0 
     while current_memory_address < _lastmem: 
      #wait until target IC sends confirmation 
      while (ser.inWaiting() == 0): 
       pass 

      target_status = ser.read() 
      if target_status == 'T': 
       #everything working correctly 
       pass 
      elif target_status == '\x07': 
       #need to resend line 
       print "resending last line" 
       current_memory_address -= _pagesize 
      else: 
       print target_status 
       print "incorrect response from target IC, will now exit" 
       sys.exit() 

      #show progress in terminal 
      print str(current_memory_address) + " of " + str(_lastmem) 

      #start processing hex file for output 
      #convert 16 bit current_memory_address into two 8-bit characters 
      memory_address_high = current_memory_address/256 
      memory_address_low = current_memory_address % 256 

      #calculate checksum of this line 
      checksum = 0 
      checksum = checksum + _pagesize 
      checksum += memory_address_high 
      checksum += memory_address_low 

      for x in range(_pagesize): 
       checksum += pfile[current_memory_address + x] 

      #reduce checksum so that it is only 8 bits 
      while checksum > 256: 
       checksum -= 256 

      #take two's compliment of checksum 
      checksum = 256 - checksum 

      #start sending current line to target ic 
      #start character 
      ser.write(":") 

      #record length 
      if _pagesize < 256: 
       ser.write(chr(_pagesize)) 
      else: #split up into high and low byte 
       ser.write(chr(_pagesize >> 8)) 
       ser.write(chr(_pagesize % 256)) 

      #send this block's address 
      ser.write(chr(memory_address_low)) 
      ser.write(chr(memory_address_high)) 

      #send this blocks checksum 
      ser.write(chr(checksum)) 

      #now send the block 
      for x in range(_pagesize): 
       ser.write(chr(pfile[current_memory_address + x])) 

      #update current memory address 
      current_memory_address += _pagesize 

     #we have completed transmitting, tell target ic. Multiple S's for redundancy 
     ser.write(":") 
     ser.write("S") 
     ser.write("S") 
     ser.write("S") 
     ftemp.write(":SSS") 
     ftemp.close() 
     #tell user that transmission completed successfully 
     print "LScreamer has successfully sent " + str(_lastmem) + " bytes to the target " + _type 

     #close serial port 
     ser.close() 

     #exit gracefully 




    def setArc(self): 
     global _memsize 
     global _pagesize 
     global _parsed_file 
     global _maxsize 
     global _lastmem 
     global _type 
     _parsed_file = 0 
     if _type == 'ATMEGA168': 
      _memsize = 16384 
      _pagesize = 128 #words 
      _maxsize = _memsize - 1 
     elif _type == 'ATMEGA1280': 
      _memsize = 131072 
      _pagesize = 256 #words 
      _maxsize = _memsize - 1 
    elif _type == 'ATMEGA328': 
      _memsize = 32768 
      _pagesize = 128 #words 
      _maxsize = _memsize - 1 



    def parse(self, fileloc): 
     """remove formatting and checksums, sort into rows of 128 bytes""" 
     #define global variables modified in this def 
     global _lastmem 
     global _parsed_file 
     try: 
      fhex = open(fileloc,"r") 
     except IOError: 
      print "File could not be opened" 
      sys.exit() 
     """file is open, enter loop reading in hex lines""" 
     li=[] #initialize list, so can start adding elements by extending it 
     if _verbose == 1: print "reading input file '" + fileloc + "' now." 
     while 1: 
      lines = fhex.readlines(100000) 
      if not lines: 
       break 
      for line in lines: 
       #remove colon and new line 
       if(line[0]!=':'): #if line has no : then ignore 
        continue 
       s = line.split(":") 
       s = s[1].split("\r\n") 
       if(s[7:9]=='04'): 
        continue 
       if(len(s[0])!=0): #remove empty lines 
        li.extend([s[0]]) 
     #Hex file is cleaned up now, stored in list li 
     #prefill hex_array with 0xFF 
     hex_array=[] 
     hex_array = [255 for i in range(_memsize)] 

     if _verbose == 1: print " processing hex file..." 

     #step through cleaned file and load into hex array 
     for line in li: 
      record_length = int(line[0:2], 16) # int('A',16) returns 10 

      #find memory address to store this line 
      memory_address_high = int(line[2:4], 16) 
      memory_address_low = int(line[4:6], 16) 
      memory_address = memory_address_high * 256 + memory_address_low 

      #check for end of file tag 
      if int(line[6:8], 16) == 1: 
       break 

      #save last memory location 
      _lastmem = memory_address + record_length 

      for x in range(record_length): #Save values to 
       lower_byte = 8+x*2 
       upper_byte = 10+x*2 
       #print "lower %d upper %d x %d" % (lower_byte, upper_byte, x) 
       hex_array[memory_address + x]= int(line[lower_byte:upper_byte], 16) 
       #print "int(line[lb:ub},16 = %d" % (int(line[lower_byte:upper_byte], 16)) 
       #print hex_array 
       #sleep(1) 

     #file was successfully parsed 
     fhex.close() 
     _parsed_file = 1 
     return hex_array 




def main(argv): 
    #determine OS 
    global is_windows 
    is_windows = (platform.system().lower().find("win") > -1) 

    try: 
     #To test this in python, do args = '-hvp ATMEGA168 /home/test'.split() 
     #then do getopt.getopt(argv, "hvp:", ["help", "--verbose"]) 
     opts, args = getopt.getopt(argv, 'hvp:i:', ['help', 'verbose', 'interface']) 
     #detect if no inputs are given 
     if len(args) == 0: 
      usage() 
      print "\nThe available interfaces are: " + str(scan()) + "\n" 
      sys.exit(2) 
    except getopt.GetoptError: 
     usage() 
     sys.exit(2) 
    #setup global variables 
    global _verbose ; _verbose = 0 
    global _iface ; _iface = '/dev/ttyUSB0' 
    global _type ; _type = 'ATMEGA168' 

    for opt, arg in opts: 
     if opt in ("-h", "--help"): 
      usage() 
      sys.exit() 
     if opt in ('-v', '--verbose'): 
      _verbose = 1 
     if opt in ('-p'): 
      _type = arg 
     if opt in ('-i', '--interface'): 
      _iface = arg 
    hex = "".join(args) 

    FileProc(hex) 


if __name__=='__main__': 
    main(sys.argv[1:]) 
""" 
* This program is free software; you can redistribute it and/or modify it  * 
* under the terms of the GNU General Public License as published by the Free * 
* Software Foundation; either version 3 of the License, or (at your option) * 
* any later version.               * 
*                    * 
* This program is distributed in the hope that it will be useful, but WITHOUT * 
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or  * 
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * 
* more details.                * 
*                    * 
* You should have received a copy of the GNU General Public License along  * 
* with this program; if not, see <http://www.gnu.org/licenses/>.    *""" 
+0

USBからシリアルアダプタ、またはネイティブCOMポートを使用していますか? –

+0

私はXBee、XBee、XBeeを使用しています。 Linuxでは接続がうまくいくので、XBeeの問題ではないと思います(でもそうかもしれません)。 –

+0

Windows上のネイティブCOMポートでテストできますか?それはドライバーの問題かもしれません。 –

答えて

2

IをMAX3232を接続し、XBeeがドロップしていることを発見しましたパケットのため、私はそれのためのより良いドライバを得るために調査するつもりです。 MCUがシリアルケーブルを介してコンピュータに接続されると、プログラムは正常にダウンロードされます。だから、xbeeのように見えますが、Pythonの問題ではありません。ご協力いただきありがとうございます!

+0

[このブログの投稿](http://psychoul.com/electronics/xbee-dropping-bytes-my-solution)は潜在的な修正ですか?作成者は、宛先アドレスを割り当てることで、ドロップされたパケットの問題を修正すると言います。指示は '+++'を送り、 'OK'を待ってから、' ATDN 'を送ります。 –

1

あなたはユニバーサル改行をサポートしてHEXファイルを開いてみてください:

fhex = open(fileloc, "rU") 

また、あなたのチェックサムが間違っています。それは次のようになります。また

while checksum >= 256: 
    checksum -= 256 

#take two's complement of checksum 
checksum = 255 - checksum 

、代わりに:

hex_array = [255] * _memsize 

をし、ビジー待機中にスリープを置く:

hex_array = [255 for i in range(_memsize)] 

あなたが使用することができ

while ser.read(1) != '\x05': 
    time.sleep(0.1) 
+0

普遍的な改行サポートでファイルを開こうとしましたが、動作しませんでした。 'チェックサムの場合 –

+0

私の古い返信を修正できないようです。基本的にはすべて試してみましたが、役に立たなかった:/ XBeeモジュール用のドライバもロールバックしましたが、まだ同じ方法で動作しています(多くの再試行、終了時にプロセッサは起動しません) 私はAvrdudeを使ってフラッシュを読むことを検討しなければならないので、それが何を得ているか見ることができます。ありがとう! –

関連する問題