216 lines
6.9 KiB
Python
216 lines
6.9 KiB
Python
|
'''
|
|||
|
Copyright 2020 Blue Liang, liangkangnan@163.com
|
|||
|
|
|||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|||
|
you may not use this file except in compliance with the License.
|
|||
|
You may obtain a copy of the License at
|
|||
|
|
|||
|
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|
|||
|
Unless required by applicable law or agreed to in writing, software
|
|||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
|
See the License for the specific language governing permissions and
|
|||
|
limitations under the License.
|
|||
|
'''
|
|||
|
|
|||
|
import os
|
|||
|
import sys
|
|||
|
|
|||
|
import serial
|
|||
|
#import serial.tools.list_ports
|
|||
|
|
|||
|
'''
|
|||
|
通过串口下载固件到FPGA开发板,FPGA收到数据后将数据烧写到ROM(Flash)。
|
|||
|
有两种包类型:包0和其他包。包0用来传输文件名和文件大小,其他包用来传输文件内容。
|
|||
|
每个包的大小固定为131个字节(1字节包号+128字节数据+2字节CRC)。
|
|||
|
'''
|
|||
|
|
|||
|
# 包0格式
|
|||
|
# number:0,包序号
|
|||
|
# data[0] ~ data[59]:文件名
|
|||
|
# data[60] ~ data[63]:文件大小(字节),其中data[60]为MSB
|
|||
|
# crc[0]:crc低字节,crc[1]:crc高字节
|
|||
|
'''
|
|||
|
0 1 2 ... 128 129 130
|
|||
|
|-------------------------------------------------------------------|
|
|||
|
| number | data[0] | data[1] | ... | data[127] | crc[0] | crc[1] |
|
|||
|
|-------------------------------------------------------------------|
|
|||
|
'''
|
|||
|
|
|||
|
# 包1 ~ n格式
|
|||
|
# number:包序号
|
|||
|
# data[0]~data[127]:文件内容
|
|||
|
# crc[0]:crc低字节,crc[1]:crc高字节
|
|||
|
'''
|
|||
|
0 1 2 ... 128 129 130
|
|||
|
|-------------------------------------------------------------------|
|
|||
|
| number | data[0] | data[1] | ... | data[127] | crc[0] | crc[1] |
|
|||
|
|-------------------------------------------------------------------|
|
|||
|
'''
|
|||
|
|
|||
|
|
|||
|
ACK = bytes([0x6])
|
|||
|
FIRST_PACKET_LEN = 131
|
|||
|
FILE_NAME_INDEX = 1
|
|||
|
FILE_SIZE_INDEX = 61
|
|||
|
FIRST_PACKET_CRC0_INDEX = 129
|
|||
|
FIRST_PACKET_CRC1_INDEX = 130
|
|||
|
OTHER_PACKET_LEN = 131
|
|||
|
|
|||
|
|
|||
|
serial_com = serial.Serial()
|
|||
|
|
|||
|
|
|||
|
# 串口初始化
|
|||
|
# 串口参数:115200, 8 N 1
|
|||
|
def serial_init():
|
|||
|
serial_com.port = sys.argv[1]
|
|||
|
serial_com.baudrate = 115200
|
|||
|
serial_com.bytesize = serial.EIGHTBITS
|
|||
|
serial_com.parity = serial.PARITY_NONE
|
|||
|
serial_com.stopbits = serial.STOPBITS_ONE
|
|||
|
serial_com.xonxoff = False
|
|||
|
serial_com.rtscts = False
|
|||
|
serial_com.dsrdtr = False
|
|||
|
|
|||
|
if serial_com.is_open == False:
|
|||
|
serial_com.open()
|
|||
|
if serial_com.is_open:
|
|||
|
return 0
|
|||
|
else:
|
|||
|
return -1
|
|||
|
|
|||
|
def serial_deinit():
|
|||
|
if serial_com.is_open == True:
|
|||
|
serial_com.close()
|
|||
|
|
|||
|
# 串口写数据
|
|||
|
def serial_write(b):
|
|||
|
if serial_com.is_open == True:
|
|||
|
serial_com.write(b)
|
|||
|
return len(b)
|
|||
|
else:
|
|||
|
return 0
|
|||
|
|
|||
|
# 串口读数据
|
|||
|
def serial_read(length, timeout):
|
|||
|
if (timeout > 0):
|
|||
|
serial_com.timeout = timeout
|
|||
|
|
|||
|
if serial_com.is_open == True:
|
|||
|
data = serial_com.read(length)
|
|||
|
if len(data) > 0:
|
|||
|
return data
|
|||
|
else:
|
|||
|
return -1
|
|||
|
else:
|
|||
|
return -1
|
|||
|
|
|||
|
# CRC计算
|
|||
|
def calc_crc16(data):
|
|||
|
crc = 0xFFFF
|
|||
|
for pos in data:
|
|||
|
crc ^= pos
|
|||
|
for i in range(8):
|
|||
|
if ((crc & 1) != 0):
|
|||
|
crc >>= 1
|
|||
|
crc ^= 0xA001
|
|||
|
else:
|
|||
|
crc >>= 1
|
|||
|
return crc
|
|||
|
|
|||
|
# 主函数
|
|||
|
def main():
|
|||
|
if serial_init() == 0:
|
|||
|
bin_file_size = os.path.getsize(sys.argv[2])
|
|||
|
print('bin file size: %d bytes' % bin_file_size)
|
|||
|
bin_file_name = os.path.basename(sys.argv[2])
|
|||
|
print('bin file name: ' + bin_file_name)
|
|||
|
print('Total %d packets to be sent' % (int(bin_file_size / 128) + 1))
|
|||
|
|
|||
|
############### 第一个包 ###############
|
|||
|
print('send #0 packet')
|
|||
|
packet = [0] * FIRST_PACKET_LEN
|
|||
|
# 1.包号
|
|||
|
packet[0] = 0
|
|||
|
i = FILE_NAME_INDEX
|
|||
|
# 2.文件名
|
|||
|
for c in bin_file_name:
|
|||
|
packet[i] = ord(c)
|
|||
|
i = i + 1
|
|||
|
# 3.文件大小
|
|||
|
packet[FILE_SIZE_INDEX] = (bin_file_size >> 24) & 0xff
|
|||
|
packet[FILE_SIZE_INDEX + 1] = (bin_file_size >> 16) & 0xff
|
|||
|
packet[FILE_SIZE_INDEX + 2] = (bin_file_size >> 8) & 0xff
|
|||
|
packet[FILE_SIZE_INDEX + 3] = (bin_file_size >> 0) & 0xff
|
|||
|
crc = calc_crc16(packet[1:129])
|
|||
|
# 4.CRC
|
|||
|
packet[FIRST_PACKET_CRC0_INDEX] = (crc >> 0) & 0xff
|
|||
|
packet[FIRST_PACKET_CRC1_INDEX] = (crc >> 8) & 0xff
|
|||
|
|
|||
|
#print(packet)
|
|||
|
# 5.发送
|
|||
|
serial_write(bytes(packet))
|
|||
|
# 6.读应答
|
|||
|
ack = serial_read(1, 3)
|
|||
|
if (ack != ACK):
|
|||
|
print('packet0 NACK from slave')
|
|||
|
return
|
|||
|
|
|||
|
############### 剩余包 ###############
|
|||
|
bin_file = open(sys.argv[2], 'rb')
|
|||
|
data = bin_file.read(bin_file_size)
|
|||
|
remain_data_len = bin_file_size
|
|||
|
remain_data_index = 0
|
|||
|
# 文件有多少个128字节
|
|||
|
for i in range(int(bin_file_size / 128) + 1):
|
|||
|
print('send #%d packet' % (i + 1))
|
|||
|
packet = [0] * OTHER_PACKET_LEN
|
|||
|
packet[0] = i + 1
|
|||
|
j = 1
|
|||
|
k = remain_data_index
|
|||
|
if (remain_data_len >= 128):
|
|||
|
for r in range(128):
|
|||
|
packet[j] = data[k]
|
|||
|
j = j + 1
|
|||
|
k = k + 1
|
|||
|
crc = calc_crc16(packet[1:129])
|
|||
|
packet[FIRST_PACKET_CRC0_INDEX] = (crc >> 0) & 0xff
|
|||
|
packet[FIRST_PACKET_CRC1_INDEX] = (crc >> 8) & 0xff
|
|||
|
serial_write(bytes(packet))
|
|||
|
ack = serial_read(1, 3)
|
|||
|
if (ack != ACK):
|
|||
|
print('NACK1 from slave')
|
|||
|
return
|
|||
|
remain_data_len = remain_data_len - 128
|
|||
|
remain_data_index = remain_data_index + 128
|
|||
|
else:
|
|||
|
for r in range(remain_data_len):
|
|||
|
packet[j] = data[k]
|
|||
|
j = j + 1
|
|||
|
k = k + 1
|
|||
|
crc = calc_crc16(packet[1:129])
|
|||
|
packet[FIRST_PACKET_CRC0_INDEX] = (crc >> 0) & 0xff
|
|||
|
packet[FIRST_PACKET_CRC1_INDEX] = (crc >> 8) & 0xff
|
|||
|
serial_write(bytes(packet))
|
|||
|
ack = serial_read(1, 3)
|
|||
|
if (ack != ACK):
|
|||
|
print('NACK2 from slave')
|
|||
|
return
|
|||
|
|
|||
|
bin_file.close()
|
|||
|
|
|||
|
print('Send successfully...')
|
|||
|
else:
|
|||
|
print('!!! serial init failed !!!')
|
|||
|
|
|||
|
serial_deinit()
|
|||
|
|
|||
|
# 程序入口
|
|||
|
if __name__ == "__main__":
|
|||
|
if (len(sys.argv) != 3):
|
|||
|
print('Usage: python ' + sys.argv[0] + ' COMx ' + 'bin_file')
|
|||
|
else:
|
|||
|
main()
|