tinyriscv/tools/tinyriscv_fw_downloader.py

216 lines
6.9 KiB
Python
Raw Normal View History

'''
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格式
# number0包序号
# 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()