46 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
51ac52d3a3 Fix build status badge
Use GitHub Actions badge.
2021-01-02 18:13:29 +01:00
43dbb2ef64 README: fix coverage badge branch 2021-01-02 18:07:21 +01:00
d7ed8bd530 Fix coveralls integration 2021-01-02 18:06:19 +01:00
6b83017de9 Raise minimal Python version to 3.5
Newer PyYAML versions require Python 3.5.

Python 3.4 is EOL for some time and even 3.5 reached EOL recently. So
just switch to that as minimum version.
2021-01-02 17:24:44 +01:00
2d7ccf8b3d Fix PyYAML warning
Use SafeLoader to get rid of warning.
2021-01-02 17:22:15 +01:00
77b3f0e1b7 Replace Travis CI with GitHub Actions 2021-01-02 15:24:46 +01:00
5d3214060b Merge branch 'coveralls' 2018-11-13 03:18:07 +01:00
7e413b09ec CI: disable PyPy3
There are some test-related issues with it, so disable it for now.
2018-11-13 03:16:52 +01:00
3aa08b67c0 CI: prefer pip to Debian packages
According to Travis CI docs, pip should be preferred.
2018-11-13 03:07:06 +01:00
42f93bc481 Add coveralls badge to README 2018-11-13 02:59:32 +01:00
dbfc1b3f50 CI: Add coveralls support 2018-11-13 02:52:46 +01:00
9d47588ad2 Add PyPI badge to README 2018-11-13 02:20:42 +01:00
217e5fb17e CI: try to fix and simplify apt setup
Run apt update to update the package cache, as this seems to be needed by
Travis now. Also reduce the package set - we don't build any deb or rpm
packages anymore. This should hopefully fix the CI build.
2018-11-09 01:14:41 +01:00
3875b1f415 Note serial module name conflict in FAQ
See #35 for discussion.
2018-11-09 01:02:01 +01:00
8e31765cba Add Quickstart documentation 2018-09-24 23:29:45 +02:00
75db655419 Update version to 1.6
Update version to 1.6 for both the Python package and the Debian package
metadata (untested).
2018-09-24 23:01:13 +02:00
1c062ed0c7 Update documentation
Minor updates and improvements to the documentation.
2018-09-24 22:51:57 +02:00
4fe0a30072 Add test for untrimmed MCUs
Add a test that verifies that programming untrimmed MCUs results in
an error.
2018-09-24 22:15:43 +02:00
7d9f512b6d Fix programing tests
The options mock object needs to have the "version" property, otherwise
tests always pass (they just end up calling the version info).
2018-09-24 22:14:29 +02:00
6544699a84 Minor FAQ rewording 2018-09-24 21:41:36 +02:00
f5089af93a Remove note about stc8 support maturity
It's not experimental anymore.
2018-09-24 21:41:19 +02:00
bc829ce54c frontend: catch unknown errors
Catch unknown error types in the first stage (connect/initialize).
Sometimes we unfortunately see unexpected exceptions, for instance
pyserial might throw termios.error. See #39 for more details.
2018-09-24 00:43:27 +02:00
97d0d1123b frontend: add -V/--version flag
Add a new CLI flag to print version info and exit, like it is common.
2018-09-23 23:41:44 +02:00
5032b631bf Drop documentation file installation
This doesn't work as I want it to work, after all. Don't install any
documentation for now.
2018-09-23 22:47:50 +02:00
9ae334ec25 Update installation instructions
Mention TQDM dependency and switch to official PyPI repositories.
2018-09-23 22:47:50 +02:00
05984a6c49 CI: drop deploy step
RPM/DEB packages are discontinued (they're unlikely to come back). Users
are encouraged to use PyPI instead.
2018-09-23 22:47:39 +02:00
22 changed files with 483 additions and 85 deletions

50
.github/workflows/python.yml vendored Normal file
View 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 }}

3
.gitignore vendored
View File

@ -10,3 +10,6 @@ __pycache__/
/debian/stcgal*
/debian/files
/.vscode
.coverage
coverage.xml
htmlcov/

View File

@ -1,33 +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
before_deploy:
- deactivate
- python3 setup.py bdist_rpm
- dpkg-buildpackage -uc -us
- cp ../*.deb dist/
deploy:
provider: releases
api_key: $GH_TOKEN
file_glob: true
file:
- dist/stcgal*_all.deb
- dist/stcgal*.noarch.rpm
skip_cleanup: true
on:
tags: true
python: "3.4"

View File

@ -1,4 +1,6 @@
[![Build Status](https://travis-ci.org/grigorig/stcgal.svg)](https://travis-ci.org/grigorig/stcgal)
[![Build Status](https://github.com/grigorig/stcgal/workflows/Python%20package/badge.svg?branch=master)](https://github.com/grigorig/stcgal/actions?query=workflow%3A%22Python+package%22)
[![Coverage Status](https://coveralls.io/repos/github/grigorig/stcgal/badge.svg?branch=master)](https://coveralls.io/github/grigorig/stcgal?branch=master)
[![PyPI version](https://badge.fury.io/py/stcgal.svg)](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
-------------------

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
stcgal (1.6) unstable; urgency=low
* Update to 1.6
-- Grigori Goronzy <greg@chown.ath.cx> Mon, 24 Sep 2018 22:56:31 +0200
stcgal (1.4) unstable; urgency=low
* Update to 1.4

4
debian/docs vendored
View File

@ -1,2 +1,4 @@
README.md
TODO.md
doc/USAGE.md
doc/MODELS.md
doc/FAQ.md

View File

@ -3,11 +3,13 @@ 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?
The following USB-based UART interface chips have been successfully tested with stcgal:
stcgal should work fine with common 16550 compatible UARTs that are traditionally available on many platforms. However, nowadays, USB-based UARTs are the typical case. The following USB-based UART interface chips have been successfully tested with stcgal:
* FT232 family (OS: Linux, Windows)
* CH340/CH341 (OS: Windows, Linux requires Kernel 4.10)
@ -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?
@ -40,7 +47,7 @@ Various remedies are possible to avoid parasitic powering.
First, make sure that the frequency specified uses the correct unit. The frequency is specified in kHz and the safe range is approximately 5000 kHz - 30000 kHz. Furthermore, frequency trimming uses the UART clock as the clock reference, so UART incompatibilities or clock inaccuracies can also result in issues with frequency trimming. If possible, try another UART chip.
### Baud rate switching fails
### Baud rate switching fails or flash programming fails
This can especially happen at high programming baud rates, e.g. 115200 baud. Try a lower baudrate, or stick to the default of 19200 baud. Some USB UARTs are known to cause problems due to inaccurate timing as well, which can lead to various issues.

View File

@ -1,16 +1,15 @@
Installation
============
stcgal requires Python 3.2 (or later) and pySerial. 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.
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.
There are several options for permanent installation:
* Use Python3 and ```pip```. Run
```pip3 install git+https://github.com/grigorig/stcgal.git```
to install the latest version of stcgal globally on your system.
* Use Python3 and ```pip```. Run ```pip3 install stcgal``` to
install the latest release of stcgal globally on your system.
This may require administrator/root permissions for write access
to system directories.

View File

@ -1,7 +1,7 @@
Supported MCU models
====================
stcgal should fully support STC 89/90/10/11/12/15 series MCUs. Support for STC8 series MCUs is work in progress.
stcgal should fully support STC 89/90/10/11/12/15/8 series MCUs.
So far, stcgal was tested with the following MCU models:
@ -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

@ -4,12 +4,14 @@ Usage
Call stcgal with ```-h``` for usage information.
```
usage: stcgal.py [-h] [-a] [-P {stc89,stc12a,stc12,stc15a,stc15,auto}]
usage: stcgal.py [-h] [-a] [-r RESETCMD]
[-P {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,usb15,auto}]
[-p PORT] [-b BAUD] [-l HANDSHAKE] [-o OPTION] [-t TRIM] [-D]
[-V]
[code_image] [eeprom_image]
stcgal 1.0 - an STC MCU ISP flash tool
(C) 2014-2015 Grigori Goronzy
stcgal 1.5 - an STC MCU ISP flash tool
(C) 2014-2018 Grigori Goronzy and others
https://github.com/grigorig/stcgal
positional arguments:
@ -20,18 +22,20 @@ optional arguments:
-h, --help show this help message and exit
-a, --autoreset cycle power automatically by asserting DTR
-r RESETCMD, --resetcmd RESETCMD
Use this shell command for board power-cycling
(instead of DTR assertion)
-P {stc89,stc12a,stc12,stc15a,stc15,auto}, --protocol {stc89,stc12a,stc12,stc15a,stc15,auto}
protocol version
shell command for board power-cycling (instead of DTR
assertion)
-P {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,usb15,auto}, --protocol {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,usb15,auto}
protocol version (default: auto)
-p PORT, --port PORT serial port device
-b BAUD, --baud BAUD transfer baud rate (default: 19200)
-l HANDSHAKE, --handshake HANDSHAKE
handshake baud rate (default: 2400)
-o OPTION, --option OPTION
set option (can be used multiple times)
-t TRIM, --trim TRIM RC oscillator frequency in kHz (STC15 series only)
set option (can be used multiple times, see
documentation)
-t TRIM, --trim TRIM RC oscillator frequency in kHz (STC15+ series only)
-D, --debug enable debug output
-V, --version print version info and exit
```
Most importantly, ```-p``` sets the serial port to be used for programming.
@ -43,6 +47,7 @@ BSL. The protocol can be specified with the ```-P``` flag. By default
UART protocol autodetection is used. The mapping between protocols
and MCU series is as follows:
* ```auto``` Automatic detection of UART based protocols (default)
* ```stc89``` STC89/90 series
* ```stc12a``` STC12x052 series and possibly others
* ```stc12b``` STC12x52 series, STC12x56 series and possibly others
@ -51,11 +56,10 @@ and MCU series is as follows:
* ```stc15``` Most STC15 series
* ```stc8``` STC8 series
* ```usb15``` USB support on STC15W4 series
* ```auto``` Automatic detection of UART based protocols (default)
The text files in the doc/ subdirectory provide an overview over
the reverse engineered protocols used by the BSLs. For more details,
please read the source code.
The text files in the doc/reverse-engineering subdirectory provide an
overview over the reverse engineered protocols used by the BSLs. For
more details, please read the source code.
### Getting MCU information
@ -92,6 +96,8 @@ Target options:
Disconnected!
```
If the identification fails, see the [FAQ](FAQ.md) for troubleshooting.
### Program the flash memory
stcgal supports Intel HEX encoded files as well as binary files. Intel
@ -195,8 +201,8 @@ If the internal RC oscillator is used (```clock_source=internal```),
stcgal can execute a trim procedure to adjust it to a given value. This
is only supported by STC15 series and newer. The trim values are stored
with device options. Use the ```-t``` flag to request trimming to a certain
value. Generally, frequencies between 4 and 35 MHz can be achieved. If
trimming fails, stcgal will abort.
value. Generally, frequencies between 4000 and 30000 kHz can be achieved.
If trimming fails, stcgal will abort.
### Automatic power-cycling

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

@ -31,7 +31,6 @@ setup(
name = "stcgal",
version = stcgal.__version__,
packages = find_packages(exclude=["doc", "tests"]),
data_files = [("doc", ["README.md", "doc/FAQ.md", "doc/MODELS.md", "doc/USAGE.md"])],
install_requires = ["pyserial>=3.0", "tqdm>=4.0.0"],
extras_require = {
"usb": ["pyusb>=1.0.0"]
@ -59,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",

View File

@ -1 +1 @@
__version__ = "1.5"
__version__ = "1.6"

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,9 +144,22 @@ 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."""
if self.opts.version:
print("stcgal {}".format(stcgal.__version__))
return 0
try:
self.protocol.connect(autoreset=self.opts.autoreset, resetcmd=self.opts.resetcmd)
if isinstance(self.protocol, StcAutoProtocol):
@ -178,11 +191,17 @@ class StcGal:
sys.stdout.flush()
print("I/O error: %s" % ex, file=sys.stderr)
return 1
except Exception as ex:
sys.stdout.flush()
print("Unexpected error: %s" % ex, file=sys.stderr)
return 1
try:
if self.opts.code_image:
self.program_mcu()
return 0
elif self.opts.erase:
self.erase_mcu()
else:
self.protocol.disconnect()
return 0
except NameError as ex:
@ -215,18 +234,21 @@ 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="Use this shell command for board power-cycling (instead of DTR assertion)", action="store")
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)",
choices=["stc89", "stc12a", "stc12b", "stc12", "stc15a", "stc15", "stc8", "usb15", "auto"], default="auto")
parser.add_argument("-p", "--port", help="serial port device", default="/dev/ttyUSB0")
parser.add_argument("-b", "--baud", help="transfer baud rate (default: 19200)", type=BaudType(), default=19200)
parser.add_argument("-l", "--handshake", help="handshake baud rate (default: 2400)", type=BaudType(), default=2400)
parser.add_argument("-o", "--option", help="set option (can be used multiple times)", action="append")
parser.add_argument("-t", "--trim", help="RC oscillator frequency in kHz (STC15 series only)", type=float, default=0.0)
parser.add_argument("-o", "--option", help="set option (can be used multiple times, see documentation)", action="append")
parser.add_argument("-t", "--trim", help="RC oscillator frequency in kHz (STC15+ series only)", type=float, default=0.0)
parser.add_argument("-D", "--debug", help="enable debug output", action="store_true")
parser.add_argument("-V", "--version", help="print version info and exit", action="store_true")
opts = parser.parse_args()
# run programmer

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])

View File

@ -0,0 +1,5 @@
name: STC8F2K08S2 untrimmed programming test
protocol: stc8
code_data: [49, 50, 51, 52, 53, 54, 55, 56, 57]
responses:
- [0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x00, 0x04, 0xFF, 0xFF, 0x8B, 0xFD, 0xFF, 0x27, 0x38, 0xF5, 0x73, 0x73, 0x55, 0x00, 0xF6, 0x41, 0x0A, 0x88, 0x86, 0x6F, 0x8F, 0x08, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x20, 0x05, 0x3C, 0x18, 0x05, 0x22, 0x32, 0xFF]

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)

View File

@ -27,6 +27,7 @@ from unittest.mock import patch
import yaml
import stcgal.frontend
import stcgal.protocols
from stcgal.protocols import StcProtocolException
def convert_to_bytes(list_of_lists):
"""Convert lists of integer lists to list of byte lists"""
@ -43,6 +44,7 @@ def get_default_opts():
opts.trim = 22118
opts.eeprom_image = None
opts.debug = False
opts.version = False
opts.code_image.name = "test.bin"
opts.code_image.read.return_value = b"123456789"
return opts
@ -127,6 +129,24 @@ class ProgramTests(unittest.TestCase):
"""Test a programming cycle with STC15 protocol, L1 series"""
self._program_yml("./tests/stc15l104w.yml", serial_mock, read_mock)
@patch("stcgal.protocols.StcBaseProtocol.read_packet")
@patch("stcgal.protocols.Stc89Protocol.write_packet")
@patch("stcgal.protocols.serial.Serial", autospec=True)
@patch("stcgal.protocols.time.sleep")
@patch("sys.stdout")
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(), Loader=yaml.SafeLoader)
opts = get_default_opts()
opts.trim = 0.0
opts.protocol = test_data["protocol"]
opts.code_image.read.return_value = bytes(test_data["code_data"])
serial_mock.return_value.inWaiting.return_value = 1
read_mock.side_effect = convert_to_bytes(test_data["responses"])
gal = stcgal.frontend.StcGal(opts)
self.assertEqual(gal.run(), 1)
def test_program_stc15w4_usb(self):
"""Test a programming cycle with STC15W4 USB protocol"""
self.skipTest("USB not supported yet, trace missing")
@ -134,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"])