20 Commits

Author SHA1 Message Date
9202399a84 Add STC15F104W variant to compatibility list 2021-01-09 01:58:32 +01:00
3cf2cb38e7 stc15: reduce sleep after baudrate switch
We just sleep 200 ms, but apparently that's already too much with some
handshake baudrates. Cut it in half to fix
failures with "-l 9600" in some cases.

Addresses #17.
2021-01-09 01:18:56 +01:00
384471f765 stc15: fix fuzzing test failure 2021-01-06 20:08:26 +01:00
df2fbc23cd stc15: fix baudrate switching
Baudrate switching fixes for both HW and SW UART devices:

* Program secondary SW UART timing parameter correctly. Supposedly this
  controls the sampling position when receiving data.
* Swap around trim range/adjust parameter for HW UART devices (as
  determind by older traces)
* Use correct constant for timing calculations

This should fix some STC15x10xW series MCUs. Compatibility to other
devices might be improved as well.

Addresses #17.
2021-01-06 19:56:46 +01:00
77df068efd docs: note that you can actually read back EEPROM 2021-01-03 20:31:07 +01:00
2fb96d6236 docs: note autodetection incompatibilities 2021-01-03 20:30:41 +01:00
c2fd3ab710 Add -e/--erase option
Erases the flash memory without any programming. Mutually exclusive with
providing a file to flash.
2021-01-03 19:57:50 +01:00
0d5e8e645f Revert "protocols: fix off-by-one in payload extraction"
This reverts commit 0e020f2aa4.

Nothing needed fixing here. This strips off one byte too many.
2021-01-03 18:40:27 +01:00
1ec855e6a1 Revert "Add "stc89a" protocol"
This reverts commit c5d509d1fa.
2021-01-03 18:36:05 +01:00
d708a00e9e Revert "docs: add stc89a to protocol information"
This reverts commit 5c2950f084.
2021-01-03 18:35:55 +01:00
5c2950f084 docs: add stc89a to protocol information 2021-01-03 16:52:44 +01:00
c5d509d1fa Add "stc89a" protocol
This protocol variant is designed for newer STC89 series chips with BSL
version 7.x.x. The new firmware uses framing
with 16-bit checksum.

This protocol variant is currently untested because I don't have any
hardware at hand.

Addresses #50, #40.
2021-01-03 16:41:05 +01:00
0e020f2aa4 protocols: fix off-by-one in payload extraction
Drop all of the checksum bytes. This didn't take the end-of-frame marker
into account.
2021-01-03 16:10:05 +01:00
b46d81a184 Add ihex tests
Add basic ihex module tests for reading and writing.
2021-01-03 15:53:38 +01:00
ad5a532ab9 ihex: fix writer str/bytes confusion
The HEX writer was never tested/used before and didn't work. Some
leftovers from the Python 2 conversion are the culprit.
2021-01-03 15:51:48 +01:00
b3741af045 gitignore: add coverage report outputs 2021-01-03 14:11:52 +01:00
1e78d62f5d Update installation instructions
Python 3.5 is required now.
2021-01-03 14:10:25 +01:00
d0597578de Add additional reverse-engineering notes 2021-01-03 14:09:50 +01:00
eaeab65044 frontend: fix flash/eeprom padding
Fill space with 0xFF instead of 0x00.  Addresses #58.
2021-01-02 18:26:21 +01:00
a19fc406a3 Merge branch 'github-actions' 2021-01-02 18:14:57 +01:00
12 changed files with 338 additions and 19 deletions

5
.gitignore vendored
View File

@ -9,4 +9,7 @@ __pycache__/
/deb_dist
/debian/stcgal*
/debian/files
/.vscode
/.vscode
.coverage
coverage.xml
htmlcov/

View File

@ -3,7 +3,9 @@ Frequently Asked Questions
### Is it possible to read code (or EEPROM) memory out of a chip?
By design, this is not possible with STC's bootloader protocols. This is considered a security feature by STC. There is no known workaround at this time. See issue #7 for more details and discussion.
By design, it is not possible to read back code flash memory with STC's bootloader protocols. This is considered a security feature by STC. There is no known workaround at this time. See issue #7 for more details and discussion.
On some STC MCUs, you can erase code flash memory without erasing EEPROM. That means you can create a program to dump the EEPROM. stcgal does not have any native support to do that at this time.
### Which serial interfaces have been tested with stcgal?
@ -30,7 +32,8 @@ There are a number of issues that can result in this symptom:
* Electrical issues and wrong connections. Make sure that RX/TX, GND and VCC are connected correctly. If you do not use the autoreset feature, also make sure to connect power only after stcgal starts, as the bootloader is only invoked on power-on reset.
* Parasitic powering through I/O pins. The MCU can be powered through I/O pins (such as RX/TX) even if VCC is not connected. In this case, the power-on reset logic does not work. See next question.
* Serial interface incompatibilities. Some USB-based UARTs have bad compatibility with STC MCUs for various reasons. You can try to lower the handshake baudrate from the standard 2400 baud to 1200 baud with the option `-l 1200`, which works around these issues in some cases.
* Serial interface compatibility issues with protocol autodetection (for instance with some fake FTDI USB UART chips). Try to explicitly provide the protocol variant with the option ```-P```.
* Other serial interface incompatibilities. Some USB-based UARTs have bad compatibility with STC MCUs for various reasons. You can try to lower the handshake baudrate from the standard 2400 baud to 1200 baud with the option `-l 1200`, which works around these issues in some cases.
### How can I avoid parasitic powering?

View File

@ -1,7 +1,7 @@
Installation
============
stcgal requires Python 3.2 (or later), pyserial 3.0 or later and
stcgal requires Python 3.5 (or later), pyserial 3.0 or later and
TQDM 4.0.0 or later. USB support is optional and requires pyusb
1.0.0b2 or later. You can run stcgal directly with the included
```stcgal.py``` script if the dependencies are already installed.

View File

@ -20,7 +20,7 @@ So far, stcgal was tested with the following MCU models:
* STC15F104E (BSL version: 6.7Q)
* STC15F204EA (BSL version: 6.7R)
* STC15L104W (BSL version: 7.1.4Q)
* STC15F104W (BSL version: 7.1.4Q)
* STC15F104W (BSL version: 7.1.4Q and 7.2.5Q)
* IAP15F2K61S2 (BSL version: 7.1.4S)
* STC15L2K16S2 (BSL version: 7.2.4S)
* IAP15L2K61S2 (BSL version: 7.2.5S)

View File

@ -0,0 +1,57 @@
STC15F103
00064F50 63 C3 08 00 2C FC 47 00 9B F2 00 00 00 0C 00 00 c...,.G.........
00064F60 00 08 00 00 00 00 00 00 00 20 00 00 07 03 00 00 ......... ......
STC15L103
00065110 61 C3 08 00 90 FB 47 00 DB F2 00 00 00 0C 00 00 a.....G.........
00065120 00 08 00 00 00 00 00 00 00 20 00 00 07 03 00 00 ......... ......
STC15F104E
00065190 E3 02 08 00 AC B1 47 00 94 F2 00 00 00 10 00 00 ......G.........
000651A0 00 04 00 00 00 00 00 00 00 20 00 00 07 00 00 00 ......... ......
STC15L104W
X Y Z
00065050 E1 C3 08 00 B8 B1 47 00 D4 F2 00 00 00 10 00 00 ......G.........
00065060 00 04 00 00 00 00 00 00 00 20 00 00 07 03 00 00 ......... ......
STC15L104E
000651B0 E1 02 08 00 94 B1 47 00 D4 F2 00 00 00 10 00 00 ......G.........
000651C0 00 04 00 00 00 00 00 00 00 20 00 00 07 00 00 00 ......... ......
byte X bit 1: F vs L? low => L part, high => F part
byte Z: protocol/model generation number?
IAP15F2K61S2
00063750 AF 0B 09 00 08 06 48 00 49 F4 00 00 00 F4 00 00 ......H.I.......
00063760 00 00 00 00 00 00 00 00 00 00 01 00 07 00 00 00 ................
STC15F2K08S2
00063650 A3 0B 09 00 78 06 48 00 01 F4 00 00 00 20 00 00 ....x.H...... ..
00063660 00 D4 00 00 00 00 00 00 00 00 01 00 07 00 00 00 ................
STC15F2K32S2
000636B0 A3 0B 09 00 48 06 48 00 04 F4 00 00 00 80 00 00 ....H.H.........
000636C0 00 74 00 00 00 00 00 00 00 00 01 00 07 00 00 00 .t..............
STC15F2K60S2
00063730 A3 0B 09 00 64 B2 47 00 08 F4 00 00 00 F0 00 00 ....d.G.........
00063740 00 04 00 00 00 00 00 00 00 00 01 00 07 00 00 00 ................
IRC15F2K63S2
00063770 BF 0C 09 00 F8 05 48 00 4A F4 00 00 00 FE 00 00 ......H.J.......
00063780 00 00 00 00 00 00 00 00 00 00 01 00 07 00 00 00 ................
IRC15F1K63S
00064470 BE 8C 09 00 20 00 48 00 20 F4 00 00 00 FE 00 00 .... .H. .......
00064480 00 00 00 00 00 00 00 00 00 00 01 00 07 00 00 00 ................
IRC15W207S
000648B0 B7 CC 0A 00 AC FE 47 00 56 F5 00 00 00 1E 00 00 ......G.V.......
000648C0 00 00 00 00 00 00 00 00 00 20 00 00 07 00 00 00 ......... ......
STC15H4K56S4
00063610 AF 8B 0E 00 98 06 48 00 07 F6 00 00 00 E0 00 00 ......H.........
00063620 00 00 00 00 00 00 00 00 00 00 01 00 07 00 00 00 ................

View File

@ -0,0 +1,108 @@
fresh chip, RC frequency untuned, caught with stcgal
2015-12-10 23:39:46.886233: PC
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
7F 7F 7F 7F 7F 7F 7F 7F 7F 7F 7F
2015-12-10 23:39:50.989044: MCU
46 B9 68 00 34 50 8D FF 73 96 F5 7B 9F FF FF FF
FF FF 25 EF 00 00 73 54 00 F5 28 04 06 70 96 02
15 19 1C 1E 23 00 EC E0 04 D7 F8 73 BF FF FF 15
09 25 60 16 92 16
2015-12-10 23:39:51.231028: PC
46 B9 6A 00 07 82 00 F3 16
Checking target MCU ...
MCU type: STC15W4K56S4
F/W version: 7.3.4T
Current H/W Option:
. Current system clock source is internal IRC oscillator
. IRC is unadjusted
. Oscillator gain is HIGH
. Wakeup Timer frequency: 36.351KHz
. Do not detect the level of P3.2 and P3.3 next download
. Power-on reset, use the extra power-on delay
. RESET pin behaves as I/O pin
. Interrupt while detect a Low-Voltage
. Thresh voltage level of the built-in LVD : 2.78 V
. Permit EEPROM operation under Low-Voltag
. CPU-Core supply level : 3.38 V
. Hardware do not enable Watch-Dog-Timer
. Watch-Dog-Timer pre-scalar : 64
. Watch-Dog-Timer stop count in idle mode
. Program can modify the Watch-Dog-Timer scalar
. Erase user EEPROM area at next download
. Do not control 485 at next download
. Do not check user password next download
. TXD is independent IO
. TXD pin as quasi-bidirectional mode after reset
. P2.0 output HIGH level after reset
. MCU type: STC15W4K56S4
F/W version: 7.3.4T
Complete !
Waiting for MCU, please cycle power: done
Target model:
Name: STC15W4K56S4
Magic: F528
Code flash: 56.0 KB
EEPROM flash: 3.0 KB
Target frequency: 0.000 MHz
Target BSL version: 7.3.4T
Target wakeup frequency: 36.351 KHz
Target options:
reset_pin_enabled=False
clock_source=internal
clock_gain=high
watchdog_por_enabled=False
watchdog_stop_idle=True
watchdog_prescale=64
low_voltage_reset=False
low_voltage_threshold=3
eeprom_lvd_inhibit=False
eeprom_erase_enabled=True
bsl_pindetect_enabled=False
por_reset_delay=long
rstout_por_state=high
uart2_passthrough=False
uart2_pin_mode=normal
Disconnected!
cpu core supply level
2.68v
46 B9 68 00 34 50 8D FF 73 96 F7 BC 9F 00 5B 7A C0 FD 27 ED 00 00 73 54 00 F5 28 04 06 70 96 02 15 19 1C 1E 23 00 EC E0 04 D7 EA 92 FF FF FF 15 09 25 60 14 BD 16
3.33v
46 B9 68 00 34 50 8D FF 73 96 F7 BC 9F 00 5B 92 30 FD 25 EA 00 FC 73 54 00 F5 28 04 06 70 96 02 15 19 1C 1E 23 00 EC E0 04 D7 F7 92 FF FF FF 15 09 25 60 15 49 16
3.63v
46 B9 68 00 34 50 8D FF 73 96 F7 BC 9F 00 5B 7A C0 FD 25 EF 00 00 73 54 00 F5 28 04 06 70 96 02 15 19 1C 1E 23 00 EC E0 04 D7 FD 92 FF FF FF 15 09 25 60 14 D0 16
3.73v
46 B9 68 00 34 50 8D FF 73 96 F7 BC 9F 00 5B 92 30 FD 25 EA 00 00 73 54 00 F5 28 04 06 70 96 02 15 19 1C 1E 23 00 EC E0 04 D7 FF 92 FF FF FF 15 09 25 60 14 55 16
^^
core voltage
voltage: ff -> 3.73v
fd -> 3.63v
f7 -> 3.33v
ea -> 2.68v

View File

@ -0,0 +1,32 @@
Cycling power: done
Waiting for MCU: <- Packet data: 46 B9 68 00 30 50 FF FF FF FF 8F 00 04 FF FF 8B FD FF 27 3E F5 73 73 55 00 F6 41 0A 88 86 6F 8F 08 20 20 20 01 00 00 20 05 3C 18 05 22 32 FF 12 18 16
-> Packet data: 46 B9 6A 00 07 FF 01 70 16
done
Target model:
Name: STC8F2K08S2
Magic: F641
Code flash: 8.0 KB
EEPROM flash: 56.0 KB
Target frequency: 0.000 MHz
Target BSL version: 7.3.10U
Target wakeup frequency: 34.950 KHz
Target ref. voltage: 1340 mV
Target mfg. date: 2018-05-22
Target options:
reset_pin_enabled=False
clock_gain=high
watchdog_por_enabled=False
watchdog_stop_idle=True
watchdog_prescale=64
low_voltage_reset=False
low_voltage_threshold=2
eeprom_erase_enabled=True
bsl_pindetect_enabled=False
por_reset_delay=long
rstout_por_state=high
uart1_remap=False
uart2_passthrough=False
uart2_pin_mode=normal
epwm_open_drain=False
program_eeprom_split=29440
Disconnected!

View File

@ -0,0 +1,35 @@
Cycling power: done
Waiting for MCU: done
Protocol detected: stc8
Target model:
Name: STC8F2K08S2
Magic: F641
Code flash: 8.0 KB
EEPROM flash: 56.0 KB
Target frequency: 0.000 MHz
Target BSL version: 7.3.10U
Target wakeup frequency: 34.950 KHz
Target ref. voltage: 1340 mV
Target mfg. date: 2018-05-22
Target options:
reset_pin_enabled=False
clock_gain=high
watchdog_por_enabled=False
watchdog_stop_idle=True
watchdog_prescale=64
low_voltage_reset=False
low_voltage_threshold=2
eeprom_erase_enabled=True
bsl_pindetect_enabled=False
por_reset_delay=long
rstout_por_state=high
uart1_remap=False
uart2_passthrough=False
uart2_pin_mode=normal
epwm_open_drain=False
program_eeprom_split=29440
Loading flash: 80 bytes (Intel HEX)
<- Packet data: 46 B9 68 00 30 50 FF FF FF FF 8F 00 04 FF FF 8B FD FF 27 38 F5 73 73 55 00 F6 41 0A 88 86 6F 8F 08 20 20 20 01 00 00 20 05 3C 18 05 22 32 FF 12 12 16
Protocol error: uncalibrated, please provide a trim value
-> Packet data: 46 B9 6A 00 07 FF 01 70 16
Disconnected!

View File

@ -126,7 +126,7 @@ class StcGal:
print("WARNING: eeprom_image truncated!", file=sys.stderr)
eedata = eedata[0:ee_size]
if len(bindata) < code_size:
bindata += bytes(code_size - len(bindata))
bindata += bytes([0xff] * (code_size - len(bindata)))
elif len(bindata) > code_size:
print("WARNING: eeprom_image overlaps code_image!", file=sys.stderr)
bindata = bindata[0:code_size]
@ -144,6 +144,15 @@ class StcGal:
self.protocol.program_options()
self.protocol.disconnect()
def erase_mcu(self):
"""Erase MCU without programming"""
code_size = self.protocol.model.code
self.protocol.handshake()
self.protocol.erase_flash(code_size, code_size)
self.protocol.disconnect()
def run(self):
"""Run programmer, main entry point."""
@ -190,8 +199,10 @@ class StcGal:
try:
if self.opts.code_image:
self.program_mcu()
return 0
self.protocol.disconnect()
elif self.opts.erase:
self.erase_mcu()
else:
self.protocol.disconnect()
return 0
except NameError as ex:
sys.stdout.flush()
@ -223,8 +234,10 @@ def cli():
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
description="stcgal {} - an STC MCU ISP flash tool\n".format(stcgal.__version__) +
"(C) 2014-2018 Grigori Goronzy and others\nhttps://github.com/grigorig/stcgal")
parser.add_argument("code_image", help="code segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
exclusives = parser.add_mutually_exclusive_group()
exclusives.add_argument("code_image", help="code segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
parser.add_argument("eeprom_image", help="eeprom segment file to flash (BIN/HEX)", type=argparse.FileType("rb"), nargs='?')
exclusives.add_argument("-e", "--erase", help="only erase flash memory", action="store_true")
parser.add_argument("-a", "--autoreset", help="cycle power automatically by asserting DTR", action="store_true")
parser.add_argument("-r", "--resetcmd", help="shell command for board power-cycling (instead of DTR assertion)", action="store")
parser.add_argument("-P", "--protocol", help="protocol version (default: auto)",

View File

@ -155,8 +155,8 @@ class IHex:
def make_line(self, line_type, addr, data):
line = struct.pack(">BHB", len(data), addr, line_type)
line += data
line += chr(self.calc_checksum(line))
return ":" + line.encode("hex").upper() + "\r\n"
line += bytes([self.calc_checksum(line)])
return ":" + line.hex().upper() + "\r\n"
def write(self):
"""Write Intel HEX data to string"""
@ -207,7 +207,7 @@ class IHex:
output += self.make_line(
0x05, 0, struct.pack(">I", self.start))
output += self.make_line(0x01, 0, "")
output += self.make_line(0x01, 0, b"")
return output
def write_file(self, fname):

View File

@ -1394,16 +1394,19 @@ class Stc15Protocol(Stc15AProtocol):
# hardware UART. Only one family of models seems to lack a hardware
# UART, and we can isolate those with a check on the magic.
# This is a bit of a hack, but it works.
bauds = self.baud_transfer if (self.mcu_magic >> 8) == 0xf2 else self.baud_transfer * 4
packet += struct.pack(">H", int(65535 - program_speed / bauds))
packet += bytes(user_trim)
if (self.mcu_magic >> 8) == 0xf2:
packet += struct.pack(">H", int(65536 - program_speed / self.baud_transfer))
packet += struct.pack(">H", int(65536 - program_speed / 2 * 3 / self.baud_transfer))
else:
packet += struct.pack(">H", int(65536 - program_speed / (self.baud_transfer * 4)))
packet += bytes(reversed(user_trim))
iap_wait = self.get_iap_delay(program_speed)
packet += bytes([iap_wait])
self.write_packet(packet)
response = self.read_packet()
if len(response) < 1 or response[0] != 0x01:
raise StcProtocolException("incorrect magic in handshake packet")
time.sleep(0.2)
time.sleep(0.1)
self.ser.baudrate = self.baud_transfer
def switch_baud_ext(self):
@ -1413,14 +1416,17 @@ class Stc15Protocol(Stc15AProtocol):
sys.stdout.flush()
packet = bytes([0x01])
packet += bytes([self.freq_count_24, 0x40])
packet += struct.pack(">H", int(65535 - self.mcu_clock_hz / self.baud_transfer / 4))
bauds = int(65536 - self.mcu_clock_hz / self.baud_transfer / 4)
if bauds >= 65536:
raise StcProtocolException("baudrate adjustment failed")
packet += struct.pack(">H", bauds)
iap_wait = self.get_iap_delay(self.mcu_clock_hz)
packet += bytes([0x00, 0x00, iap_wait])
self.write_packet(packet)
response = self.read_packet()
if len(response) < 1 or response[0] != 0x01:
raise StcProtocolException("incorrect magic in handshake packet")
time.sleep(0.2)
time.sleep(0.1)
self.ser.baudrate = self.baud_transfer
# for switching back to RC, program factory values
@ -1664,7 +1670,7 @@ class Stc8Protocol(Stc15Protocol):
sys.stdout.flush()
packet = bytes([0x01, 0x00, 0x00])
bauds = self.baud_transfer * 4
packet += struct.pack(">H", round(65535 - 24E6 / bauds))
packet += struct.pack(">H", round(65536 - 24E6 / bauds))
packet += bytes([user_trim[1], user_trim[0]])
iap_wait = self.get_iap_delay(24E6)
packet += bytes([iap_wait])

62
tests/test_ihex.py Normal file
View File

@ -0,0 +1,62 @@
#
# Copyright (c) 2021 Grigori Goronzy <greg@chown.ath.cx>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
import unittest
import stcgal.ihex
class IHEXTests(unittest.TestCase):
"""Tests for IHEX reader"""
def test_simple(self):
"""Test reading a basic, valid file"""
lines = [
b":0B00000068656C6C6F5F776F726C645A",
b":00000001FF"
]
bindata = stcgal.ihex.IHex.read(lines).extract_data()
self.assertEqual(bindata, b"hello_world")
def test_empty(self):
"""Test reading an empty file"""
lines = []
bindata = stcgal.ihex.IHex.read(lines).extract_data()
self.assertEqual(bindata, b"")
def test_invalid(self):
"""Test invalid encoded data"""
lines = [
":abc"
]
with self.assertRaises(ValueError):
stcgal.ihex.IHex.read(lines)
def test_roundtrip(self):
"""Test round-trip through encoder/decoder"""
bindata = b"12345678"
for mode in (8, 16, 32):
with self.subTest(mode):
hexer = stcgal.ihex.IHex()
hexer.set_mode(mode)
hexer.insert_data(0, bindata)
encoded = hexer.write().encode("ASCII").splitlines()
decoded = stcgal.ihex.IHex.read(encoded).extract_data()
self.assertEqual(decoded, bindata)