Compare commits
35 Commits
v1.6
...
fix-stc15f
Author | SHA1 | Date | |
---|---|---|---|
9202399a84 | |||
3cf2cb38e7 | |||
384471f765 | |||
df2fbc23cd | |||
77df068efd | |||
2fb96d6236 | |||
c2fd3ab710 | |||
0d5e8e645f | |||
1ec855e6a1 | |||
d708a00e9e | |||
5c2950f084 | |||
c5d509d1fa | |||
0e020f2aa4 | |||
b46d81a184 | |||
ad5a532ab9 | |||
b3741af045 | |||
1e78d62f5d | |||
d0597578de | |||
eaeab65044 | |||
a19fc406a3 | |||
51ac52d3a3 | |||
43dbb2ef64 | |||
d7ed8bd530 | |||
6b83017de9 | |||
2d7ccf8b3d | |||
77b3f0e1b7 | |||
5d3214060b | |||
7e413b09ec | |||
3aa08b67c0 | |||
42f93bc481 | |||
dbfc1b3f50 | |||
9d47588ad2 | |||
217e5fb17e | |||
3875b1f415 | |||
8e31765cba |
50
.github/workflows/python.yml
vendored
Normal file
50
.github/workflows/python.yml
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
name: Python package
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: [3.5, 3.7, 3.8]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install pyusb coverage coveralls pyserial PyYAML tqdm
|
||||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||
- name: Build package
|
||||
run: |
|
||||
python setup.py build
|
||||
- name: Test with unittest
|
||||
run: |
|
||||
coverage run --source=stcgal setup.py test
|
||||
- name: Coveralls
|
||||
run: |
|
||||
coveralls
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COVERALLS_FLAG_NAME: ${{ matrix.python-version }}
|
||||
COVERALLS_PARALLEL: true
|
||||
|
||||
coveralls:
|
||||
name: Finish Coveralls
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
container: python:3-slim
|
||||
steps:
|
||||
- name: Finished
|
||||
run: |
|
||||
pip3 install --upgrade coveralls
|
||||
coveralls --finish
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -9,4 +9,7 @@ __pycache__/
|
||||
/deb_dist
|
||||
/debian/stcgal*
|
||||
/debian/files
|
||||
/.vscode
|
||||
/.vscode
|
||||
.coverage
|
||||
coverage.xml
|
||||
htmlcov/
|
17
.travis.yml
17
.travis.yml
@ -1,17 +0,0 @@
|
||||
sudo: required
|
||||
dist: trusty
|
||||
language: python
|
||||
cache:
|
||||
- pip
|
||||
python:
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
- "pypy3"
|
||||
before_install:
|
||||
- sudo apt install rpm dpkg-dev debhelper dh-python python3-setuptools fakeroot python3-serial python3-yaml
|
||||
install:
|
||||
- pip install pyusb
|
||||
script:
|
||||
- python setup.py build
|
||||
- python setup.py test
|
15
README.md
15
README.md
@ -1,4 +1,6 @@
|
||||
[](https://travis-ci.org/grigorig/stcgal)
|
||||
[](https://github.com/grigorig/stcgal/actions?query=workflow%3A%22Python+package%22)
|
||||
[](https://coveralls.io/github/grigorig/stcgal?branch=master)
|
||||
[](https://badge.fury.io/py/stcgal)
|
||||
|
||||
stcgal - STC MCU ISP flash tool
|
||||
===============================
|
||||
@ -32,6 +34,17 @@ Features
|
||||
* Automatic power-cycling with DTR toggle or a custom shell command
|
||||
* Automatic UART protocol detection
|
||||
|
||||
Quickstart
|
||||
----------
|
||||
|
||||
Install stcgal (might need root/administrator privileges):
|
||||
|
||||
pip3 install stcgal
|
||||
|
||||
Call stcgal and show usage:
|
||||
|
||||
stcgal -h
|
||||
|
||||
Further information
|
||||
-------------------
|
||||
|
||||
|
11
doc/FAQ.md
11
doc/FAQ.md
@ -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?
|
||||
|
||||
@ -20,13 +22,18 @@ Interfaces that are known to not work:
|
||||
|
||||
In general, stcgal requires accurate baud rate timings and parity support.
|
||||
|
||||
### stcgal fails to start with the error `module 'serial' has no attribute 'PARITY_NONE'` or similar
|
||||
|
||||
There is a module name conflict between the PyPI package 'serial' (a data serialization library) and the PyPI package 'pyserial' (the serial port access library needed by stcgal). You have to uninstall the 'serial' package (`pip3 uninstall serial`) and reinstall 'pyserial' (`pip3 install --force-reinstall pyserial`) to fix this. There is no other known solution at the moment.
|
||||
|
||||
### stcgal fails to recognize the MCU and is stuck at "Waiting for MCU"
|
||||
|
||||
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?
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
57
doc/reverse-engineering/mcudb_flags.txt
Normal file
57
doc/reverse-engineering/mcudb_flags.txt
Normal 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 ................
|
||||
|
108
doc/reverse-engineering/stc15w4.txt
Normal file
108
doc/reverse-engineering/stc15w4.txt
Normal 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
|
||||
|
32
doc/reverse-engineering/stc8-new.txt
Normal file
32
doc/reverse-engineering/stc8-new.txt
Normal 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!
|
35
doc/reverse-engineering/untrimmed.txt
Normal file
35
doc/reverse-engineering/untrimmed.txt
Normal 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!
|
1
setup.py
1
setup.py
@ -58,7 +58,6 @@ setup(
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: MacOS",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Topic :: Software Development :: Embedded Systems",
|
||||
|
@ -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)",
|
||||
|
@ -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):
|
||||
|
@ -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
62
tests/test_ihex.py
Normal 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)
|
@ -137,7 +137,7 @@ class ProgramTests(unittest.TestCase):
|
||||
def test_program_stc8_untrimmed(self, out, sleep_mock, serial_mock, write_mock, read_mock):
|
||||
"""Test error with untrimmed MCU"""
|
||||
with open("./tests/stc8f2k08s2-untrimmed.yml") as test_file:
|
||||
test_data = yaml.load(test_file.read())
|
||||
test_data = yaml.load(test_file.read(), Loader=yaml.SafeLoader)
|
||||
opts = get_default_opts()
|
||||
opts.trim = 0.0
|
||||
opts.protocol = test_data["protocol"]
|
||||
@ -154,7 +154,7 @@ class ProgramTests(unittest.TestCase):
|
||||
def _program_yml(self, yml, serial_mock, read_mock):
|
||||
"""Program MCU with data from YAML file"""
|
||||
with open(yml) as test_file:
|
||||
test_data = yaml.load(test_file.read())
|
||||
test_data = yaml.load(test_file.read(), Loader=yaml.SafeLoader)
|
||||
opts = get_default_opts()
|
||||
opts.protocol = test_data["protocol"]
|
||||
opts.code_image.read.return_value = bytes(test_data["code_data"])
|
||||
|
Reference in New Issue
Block a user