Skip to content

Commit

Permalink
Merge pull request #362 from Qyriad/features/chipcon-support-ihex
Browse files Browse the repository at this point in the history
host: chipcon command: support reading from Intel hex
  • Loading branch information
ktemkin authored Jan 6, 2021
2 parents bb2ed2d + b00c7d2 commit 53b2056
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 12 deletions.
25 changes: 21 additions & 4 deletions host/greatfet/commands/greatfet_chipcon.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

from __future__ import print_function

import ast
import io
import argparse

from intelhex import IntelHex

from greatfet.utils import GreatFETArgumentParser, log_silent, log_verbose


Expand Down Expand Up @@ -42,6 +44,8 @@ def main():
parser.add_argument('-E', '--mass-erase', action='store_true', help="Erase the entire flash memory")
parser.add_argument('-w', '--write', metavar='<filename>', type=argparse.FileType('rb'),
help="Write data from file")
parser.add_argument("--bin", action='store_true', default=False,
help="Disable Intel hex detection and flash as-is.")

args = parser.parse_args()

Expand All @@ -65,7 +69,7 @@ def main():
mass_erase_flash(chipcon, log_function)

if args.write:
program_flash(chipcon, args.write, args.address, args.erase, args.verify, log_function)
program_flash(chipcon, args.write, args.address, args.erase, args.verify, args.bin, log_function)


def chip_id(programmer):
Expand All @@ -83,9 +87,22 @@ def mass_erase_flash(programmer, log_function):
programmer.mass_erase_flash()


def program_flash(programmer, in_file, start_address, erase, verify, log_function):
log_function("Writing data to flash...")
def program_flash(programmer, in_file, start_address, erase, verify, force_bin, log_function):
image_array = in_file.read()

if image_array.startswith(b':') and not force_bin:

print("File type detected as Intel Hex -- converting to binary before flashing...")
print("To force flashing as-is, pass --bin.")

# HACK: The IntelHex class expects a filename or file-like object, but...we've already read the file.
# So let's wrap it in a file-like object. Normally, we'd use io.BytesIO,
# except IntelHex wants strings, not bytes objects. So...
intel_hex = IntelHex(io.StringIO(image_array.decode('ascii')))
image_array = intel_hex.tobinstr()


log_function("Writing data to flash...")
programmer.program_flash(image_array, erase=erase, verify=verify, start=start_address)


Expand Down
15 changes: 8 additions & 7 deletions host/greatfet/programmers/chipcon.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def write_flash_page(self, linear_address, input_data, erase_page=True):
# should only be included in the routine when the erase_page_1 = 1.
# The pseudo-code does not refer to this parameter!
routine_part1 = [
0x75, 0xAD, ((linear_address >> 8) // FLASH_WORD_SIZE) & 0x7E, # MOV FADDRH, #imm
0x75, 0xAD, ((linear_address >> 8) // FLASH_WORD_SIZE) & 0x7E, # MOV FADDRH, #imm
0x75, 0xAC, 0x00, # MOV FADDRL, #00
]
routine_erase = [
Expand Down Expand Up @@ -253,7 +253,7 @@ def write_flash_page(self, linear_address, input_data, erase_page=True):
else:
routine = routine_part1 + routine_part2

self.write_xdata_memory(0xF000, input_data)
self.write_xdata_memory(0xF000, input_data[:FLASH_PAGE_SIZE])
self.write_xdata_memory(0xF000 + FLASH_PAGE_SIZE, routine)
self.run_instruction(0x75, 0xC7, 0x51) # MOV MEMCRT, (bank * 16) + 1
self.set_pc(0xF000 + FLASH_PAGE_SIZE)
Expand All @@ -276,12 +276,12 @@ def read_flash_page(self, linear_address):
return self.read_code_memory(linear_address & 0xFFFF, FLASH_PAGE_SIZE)


def read_flash(self, *, start_address=0, length=0):
def read_flash(self, *, start_address=0, length):
""" Read a chunk of flash memory.
Parameters:
length -- The length (in bytes) of the amount of flash memory that you want to read.
start_address -- The address in flash memory you want to begin reading data from.
length -- The length (in bytes) of the amount of flash memory that you want to read.
"""
flash_data = bytearray()
for i in range(start_address, length, FLASH_PAGE_SIZE):
Expand All @@ -308,23 +308,24 @@ def program_flash(self, image_array, *, erase=True, verify=True, start=0):
Parameters:
image_array -- The data to be written to the flash.
erase -- Used to specify whether or not the flash needs to be erased before programming.
verify - Used to specify whether or not the data was flashed correctly.
verify -- Used to specify whether or not the data was flashed correctly.
start -- The address to begin writing data to the flash.
"""

if erase:
self.mass_erase_flash()

data = bytearray(image_array)
address = 0
address = start

while data:
time.sleep(0.1)
# Grab a page...
page = data[:FLASH_PAGE_SIZE]
del data[:FLASH_PAGE_SIZE]

# ... and write it to flash.
self.write_flash_page(address, page, False)
self.write_flash_page(address - start, page, False)
address += FLASH_PAGE_SIZE

time.sleep(0.1)
Expand Down
3 changes: 2 additions & 1 deletion host/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ def read(fname):
'tqdm',
'cmsis_svd',
'tabulate',
'prompt_toolkit<3.1.0'
'prompt_toolkit<3.1.0',
'intelhex',
],
description='Python library for hardware hacking with the GreatFET',
long_description=read('README.md'),
Expand Down

0 comments on commit 53b2056

Please sign in to comment.