1

我有一个嵌入式系统,我正在编写一个用户应用程序。用户应用程序需要获取固件映像并将其拆分为适合发送到嵌入式系统进行编程的块。我从 S-record 文件开始,并使用 Xmodem 进行文件传输(这意味着每个主要的“文件”传输都需要以 EOF 结束),所以对我来说最简单的事情是将图像文件拆分为一组完整的 s 记录文件,不大于(单线程)嵌入式系统的接收缓冲区大小。我的用户应用程序是用 python 编写的,我有一个 C 程序可以将固件映像拆分为适当大小的文件,但我认为可能有一种更“pythonic”的方式来解决这个问题,也许是通过使用自定义流处理程序。

有什么想法吗?

编辑:为了加入讨论,我可以将输入文件输入缓冲区。我如何使用范围来设置进入文件大小或完整 S 记录行('S' 分隔的 ASCII 文本)的缓冲区的硬限制?

4

2 回答 2

0

如果你已经有一个 C 程序,那么你很幸运。Python 就像是基于 C 的脚本语言,具有大多数相同的功能。有关所有熟悉的 CI/O 功能,请参阅使用流的核心工具。然后,您可以通过将方法滚动到中并使用Python Slice Notation 之类的东西来使您的程序更加 Pythonic 。

于 2013-06-11T14:45:40.107 回答
0

我认为这是一个有趣的问题,而且 S-record 格式并不太复杂,所以我编写了一个 S-record 编码器,在我有限的测试中似乎可以工作。

import struct

def s_record_encode(fileobj, recordtype, address, buflen):
    """S-Record encode bytes from file.

    fileobj      file-like object to read data (if any)
    recordtype   'S0' to 'S9'
    address      integer address
    buflen       maximum output buffer size
    """
    # S-type to (address_len, has_data)
    record_address_bytes = {
        'S0':(2, True), 'S1':(2, True), 'S2':(3, True), 'S3':(4, True),
        'S5':(2, False), 'S7':(4, False), 'S8':(3, False), 'S9':(2, False)
    }

    # params for this record type
    address_len, has_data = record_address_bytes[recordtype]

    # big-endian address as string, trimmed to length
    address = struct.pack('>L', address)[-address_len:]

    # read data up to 255 bytes minus address and checksum len
    if has_data:
        data = fileobj.read(0xff - len(address) - 1)
        if not data:
            return '', 0
    else:
        data = ''

    # byte count is address + data + checksum
    count = len(address) + len(data) + 1
    count = struct.pack('B', count)

    # checksum count + address + data
    checksummed_record = count + address + data
    checksum = struct.pack('B', sum(ord(d) for d in checksummed_record) & 0xff ^ 0xff)

    # glue record type to hex encoded buffer
    record = recordtype + (checksummed_record + checksum).encode('hex').upper()

    # return buffer and how much data we read from the file
    return record, len(data)



def s_record_test():
    from cStringIO import StringIO

    # from an example, this should encode to given string
    fake_file = StringIO("\x0A\x0A\x0D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
    encode_to = "S1137AF00A0A0D0000000000000000000000000061"
    fake_file.seek(0)
    record, buflen = s_record_encode(fake_file, 'S1', 0x7af0, 80)
    print 'record', record
    print 'encode_to', encode_to
    assert record == encode_to

    fake_file = StringIO()
    for i in xrange(1000):
        fake_file.write(struct.pack('>L', i))
    fake_file.seek(0)

    address = 0

    while True:
        buf, datalen = s_record_encode(fake_file, 'S2', address, 100)
        if not buf:
            break
        print address, datalen, buf
        address += datalen
于 2013-06-12T14:44:14.727 回答