Compare commits

..

No commits in common. "master" and "fix-stc15f104w" have entirely different histories.

29 changed files with 1416 additions and 3050 deletions

View File

@ -1,6 +1,6 @@
name: Python package
on: [push, pull_request]
on: [push]
jobs:
test:
@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8]
python-version: [3.5, 3.7, 3.8]
steps:
- uses: actions/checkout@v2
@ -47,4 +47,4 @@ jobs:
pip3 install --upgrade coveralls
coveralls --finish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,68 +0,0 @@
文档说明 Explanation
-------------------
此文档翻译自README.MD
This document was translated from README.MD
最后修改时间2020年6月8日
Last modified time: June 8, 2020
stcgal - 用于STC MCU的ISP闪存工具
===============================
stcgal是用于[STC MCU Ltd]的命令行闪存编程工具。
兼容8051微控制器。
STC微控制器具有基于UART / USB的引导加载程序BSL
它采用系统内编程即基于数据包的协议通过串行链路刷新代码存储器和IAP存储器。
BSL还用于配置各种设备选项。
不幸的是该协议没有公开记录STC仅提供粗略的Windows GUI应用程序进行编程
stcgal是STC的Windows软件的功能全面的开源替代品。
它支持多种MCU非常便携适合自动下载。
特点
--------
* 支持STC 89/90/10/11/12/15/8/32系列
* UART和USB BSL支持
* 显示信息
* 确定工作频率
* 程序闪存
* 程序IAP / EEPROM
* 设置设备选项
* 读取唯一的设备IDSTC 10/11/12/15/8
* 设置RC振荡器频率STC 15/8
* 自动电源使用DTR切换或自定义Shell命令循环
* 自动UART协议检测
快速开始
----------
安装stcgal可能需要root /管理员权限):
pip3 install stcgal
呼叫stcgal并显示的用法
stcgal -h
更多的信息
-------------------
[安装方法](doc/zh_CN/INSTALL.md)
[如何取使用](doc/zh_CN/USAGE.md)
[常见问题](doc/zh_CN/FAQ.md)
[支持的MCU型号](doc/zh_CN/MODELS.md)
执照
-------
stcgal是根据MIT许可发布的。

View File

@ -22,7 +22,7 @@ suitable for automation.
Features
--------
* Support for STC 89/90/10/11/12/15/8/32 series
* Support for STC 89/90/10/11/12/15/8 series
* UART and USB BSL support
* Display part info
* Determine operating frequency

30
debian/changelog vendored Normal file
View File

@ -0,0 +1,30 @@
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
-- Grigori <greg@chown.ath.cx> Tue, 19 Sep 2017 17:57:11 +0200
stcgal (1.3) unstable; urgency=low
* Update to 1.3
-- Grigori Goronzy <greg@chown.ath.cx> Sat, 10 Jun 2017 10:01:07 +0200
stcgal (1.2) unstable; urgency=low
* Update to 1.2
* Add optional python3-usb dependency
-- Grigori Goronzy <greg@chown.ath.cx> Fri, 20 May 2016 03:21:25 +0200
stcgal (1.0git) unstable; urgency=low
* Initial Debianized Release
-- Andrew 'Necromant' Andrianov <andrew@ncrmnt.org> Wed, 25 Nov 2015 13:07:03 +0300

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

27
debian/control vendored Normal file
View File

@ -0,0 +1,27 @@
Source: stcgal
Section: electronics
Priority: optional
Maintainer: Andrew Andrianov <andrew@ncrmnt.org>
Build-Depends: debhelper (>= 9), python3, python3-setuptools, dh-python, python3-serial, python3-tqdm, python3-yaml
Standards-Version: 3.9.5
Homepage: https://github.com/grigorig/stcgal
X-Python3-Version: >= 3.2
Package: stcgal
Architecture: all
Depends: ${misc:Depends}, python3, python3-serial, python3-tqdm
Recommends: python3-usb (>= 1.0.0~b2)
Description: STC MCU ISP flash tool
stcgal is a command line flash programming tool for STC MCU Ltd.
8051 compatible microcontrollers. The name was inspired by avrdude.
.
STC microcontrollers have an UART/USB based boot strap loader (BSL). It
utilizes a packet-based protocol to flash the code memory and IAP
memory over a serial link. This is referred to as in-system programming
(ISP). The BSL is also used to configure various (fuse-like) device
options. Unfortunately, this protocol is not publicly documented and
STC only provide a (crude) Windows GUI application for programming.
.
stcgal is a full-featured Open Source replacement for STC's Windows
software; it supports a wide range of MCUs, it is very portable and
suitable for automation.

32
debian/copyright vendored Normal file
View File

@ -0,0 +1,32 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: stcgal
Upstream-Contact: Grigori Goronzy <greg@kinoho.net>
Source: https://github.com/grigorig/stcgal
Files: *
Copyright: 2013-2015 Grigori Goronzy <greg@kinoho.net>
License: MIT
Files: debian/*
Copyright: 2015 Andrew 'Necromant' Andrianov <andrew@ncrmnt.org>
2015 Grigori Goronzy <greg@kinoho.net>
License: MIT
License: MIT
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.

4
debian/docs vendored Normal file
View File

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

7
debian/rules vendored Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/make -f
export PYBUILD_NAME=stcgal
%:
dh $@ --with python3 --buildsystem=pybuild

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (native)

View File

@ -1,30 +1,22 @@
Supported MCU models
====================
stcgal should fully support STC 89/90/10/11/12/15/8/32 series MCUs.
stcgal should fully support STC 89/90/10/11/12/15/8 series MCUs.
So far, stcgal was tested with the following MCU models:
STC89/90 series
* STC89C52RC (BSL version: 4.3C/6.6C)
* STC89C54RD+ (BSL version: 4.3C)
* STC90C52RC (BSL version: 4.3C)
* STC90C58RD+ (BSL version: 4.3C)
STC10/11 series
* STC10F04XE (BSL version: 6.5J)
* STC11F02E (BSL version: 6.5K)
* STC11F08XE (BSL version: 6.5M)
STC12 series
* STC89C54RD+ (BSL version: 4.3C)
* STC12C2052 (BSL version: 5.8D)
* STC12C2052AD (BSL version: 5.8D)
* STC12C5608AD (BSL version: 6.0G)
* STC12C5A16S2 (BSL version: 6.2I)
* STC12C5A60S2 (BSL version: 6.2I/7.1I)
* STC11F02E (BSL version: 6.5K)
* STC10F04XE (BSL version: 6.5J)
* STC11F08XE (BSL version: 6.5M)
* STC12C5204AD (BSL version: 6.6H)
STC15 series
* STC15F104E (BSL version: 6.7Q)
* STC15F204EA (BSL version: 6.7R)
* STC15L104W (BSL version: 7.1.4Q)
@ -32,25 +24,9 @@ STC15 series
* IAP15F2K61S2 (BSL version: 7.1.4S)
* STC15L2K16S2 (BSL version: 7.2.4S)
* IAP15L2K61S2 (BSL version: 7.2.5S)
* STC15W408AS (BSL version: 7.2.4T and 7.2.5T)
* STC15W4K56S4 (BSL version: 7.3.4T and 7.3.7T, UART and USB mode)
STC8 series
* STC8A8K64S4A12 (BSL version: 7.3.9U and 7.3.12U)
* STC15W408AS (BSL version: 7.2.4T)
* STC15W4K56S4 (BSL version: 7.3.4T, UART and USB mode)
* STC8A8K64S4A12 (BSL version: 7.3.9U)
* STC8F2K08S2 (BSL version: 7.3.10U)
* STC8A8K64D4 (BSL version: 7.4.2U)
* STC8G1K08A-8PIN (BSL version: 7.3.12U)
* STC8G1K08-20/16PIN (BSL version: 7.3.12U)
* STC8G1K17-20/16PIN (BSL version: 7.3.12U)
* STC8G2K64S4 (BSL version: 7.3.11U)
* STC8H1K08 (BSL version: 7.3.12U)
* STC8H1K17T (BSL version: 7.4.5U)
* STC8H3K64S2 (BSL version: 7.4.1U)
* STC8H3K64S4 (BSL version: 7.4.1U)
* STC8H4K64TL (BSL version: 7.4.3U)
* STC8H8K64U (BSL version: 7.4.4U)
STC32 series
* STC32G12K128-Beta (BSL version: 7.4.4U)
Compatibility reports, both negative and positive, are welcome.

View File

@ -4,13 +4,13 @@ Usage
Call stcgal with ```-h``` for usage information.
```
usage: stcgal [-h] [-e] [-a] [-A {dtr,rts}] [-r RESETCMD]
[-P {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,stc8d,stc8g,usb15,auto}]
[-p PORT] [-b BAUD] [-l HANDSHAKE] [-o OPTION] [-t TRIM] [-D]
[-V]
[code_image] [eeprom_image]
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.7 - an STC MCU ISP flash tool
stcgal 1.5 - an STC MCU ISP flash tool
(C) 2014-2018 Grigori Goronzy and others
https://github.com/grigorig/stcgal
@ -18,19 +18,16 @@ positional arguments:
code_image code segment file to flash (BIN/HEX)
eeprom_image eeprom segment file to flash (BIN/HEX)
options:
optional arguments:
-h, --help show this help message and exit
-e, --erase only erase flash memory
-a, --autoreset cycle power automatically by asserting DTR
-A {dtr,rts,dtr_inverted,rts_inverted}, --resetpin {dtr,rts,dtr_inverted,rts_inverted}
pin to hold down when using --autoreset (default: DTR)
-r RESETCMD, --resetcmd RESETCMD
shell command for board power-cycling (instead of DTR
assertion)
-P {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,stc8d,stc8g,usb15,auto}, --protocol {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,stc8d,stc8g,usb15,auto}
-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: 115200)
-b BAUD, --baud BAUD transfer baud rate (default: 19200)
-l HANDSHAKE, --handshake HANDSHAKE
handshake baud rate (default: 2400)
-o OPTION, --option OPTION
@ -43,12 +40,6 @@ options:
Most importantly, ```-p``` sets the serial port to be used for programming.
### Transfer baud rate
The default value of 115200 Baud is supported by all MCU starting with
the STC15 family, and at least the STC12C5A56S2 before that. For older
MCU, you might have to use ```-b 19200``` for correct operation.
### Protocols
STC MCUs use a variety of related but incompatible protocols for the
@ -58,15 +49,12 @@ and MCU series is as follows:
* ```auto``` Automatic detection of UART based protocols (default)
* ```stc89``` STC89/90 series
* ```stc89a``` STC89/90 series (BSL 7.2.5C)
* ```stc12a``` STC12x052 series and possibly others
* ```stc12b``` STC12x52 series, STC12x56 series and possibly others
* ```stc12``` Most STC10/11/12 series
* ```stc15a``` STC15x104E and STC15x204E(A) series
* ```stc15``` Most STC15 series
* ```stc8``` STC8A8K64S4A12 and STC8F series
* ```stc8d``` All STC8 and STC32 series
* ```stc8g``` STC8G1 and STC8H1 series
* ```stc8``` STC8 series
* ```usb15``` USB support on STC15W4 series
The text files in the doc/reverse-engineering subdirectory provide an
@ -254,4 +242,4 @@ STC15W4 series have an USB-based BSL that can be optionally
used. USB support in stcgal is experimental and might change in the
future. USB mode is enabled by using the ```usb15``` protocol. The
port (```-p```) flag as well as the baudrate options are ignored for
the USB protocol. RC frequency trimming is not supported.
the USB protocol. RC frequency trimming is not supported.

View File

@ -1,484 +0,0 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Vincent DEFERT. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This program automates the procedure explained below and generates
* on the standard output the content of the 'models' list of models.py.
*
* It takes the name of the stc-isp executable as argument.
*/
/**
* Manual procedure to read MCU definitions from a new STC-ISP executable
* ========================================================================
*
* We want to extract 2 tables from the executable, one with MCU names and
* the other with their characteristics, let's call them "Name Table" and
* "Info Table" respectively.
*
* The Info Table appears first in the executable and contains references
* to the MCU name in the Name Table. Each entry in the Name Table is 16
* bytes long, 32 for the Info Table. New entries are prepended to the
* Info Table, and appended to the Name Table. Of course, both have the
* same number of entries.
*
* This means that the Name Table is very easy to locate, as well as the
* end of the Info Table, but not its beginning, which must be calculated.
*
* Finally, the field of an Info Table entry that references the MCU name
* is expressed as a memory address, not a file position, so we'll need to
* determine the base memory address of the name table.
*
* 1. Dump the content of the executable in a text file.
*
* hexdump -C stc-isp-v6.89G.exe > stc-isp-v6.89G.txt
*
* 2. Locate the first entry of the Name Table.
*
* Search for the following byte sequence:
* 53 54 43 39 30 4c 45 35 31 36 41 44 00 00 00 00
* (i.e. nul-terminated "STC90LE516AD" string).
*
* Let's call this file position NTS (Name Table Start).
*
* 3. Locate the end of the Name Table.
*
* Search for the following byte sequence:
* 55 4e 4b 4e 4f 57 4e 00 25 30 36 58 00 00 00 00
* (i.e. nul-terminated "UNKNOWN" and "%06X" strings).
*
* Let's call this file position NTE (Name Table End).
*
* 4. Find the end of the Info Table.
*
* Search for the following byte sequence (fixed last entry):
* 05 46 01 00 xx xx xx xx 90 f1 00 00 00 f8 00 00
* 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
*
* Bytes marked as 'xx' must be ignored while searching
*
* [Note: searching for '90 f1 00 00 00 f8 00 00' is sufficient.]
*
* It should be followed by 32 zeroed bytes. Let's call the file position
* of the first zeroed byte ITE (Info Table End).
*
* 5. Find the beginning of the Info Table.
*
* The Info Table start with a block of 32 zeroed bytes except bytes
* 4-7 which point at NTE, i.e. an info block pointing at the 'UNKNOWN'
* MCU name. It's the only reliable way to determine the location of
* the Info Table.
*
* Our first valid info block will thus be the offset of the Unknown
* block + 32. Let's call this file position ITS (Info Table Start).
*
* 6. Calculate the number of MCU definitions (i.e. Info Table entries).
*
* NB_MCU = (ITE - ITS) / 32
*
* 7. Determine the base memory address of the name table.
*
* Let's suppose 'xx xx xx xx' is '9c f7 4a 00'. As it belongs to the Info
* Table entry describing the first item of the Name Table, we directly
* have what we're looking for, i.e. 0x004af79c.
*
* NTBA = littleEndianOf32bitUnsignedInt('xx xx xx xx')
*
* The index in the Name Table corresponding to a given Info Table item
* is thus:
*
* NAME_IDX = (nameAddressFieldOfInfoTableItem - NTBA) / 0x10
*
* NOTE: for some reason, the Info Table entries of the STC08XE-3V and
* STC08XE-5V each have 2 distinct mcuId, which gives 1115 Info Table
* entries for 1113 strings in the Name Table.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Must be updated with the "UNKNOWN" name offset before use.
static uint8_t infoTableStartSignature[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
// 0x90, 0xf1 is the magic number of the STC90LE516AD
// We test only the last 24 byte of its 32-byte entry, as they are
// sufficiently discriminating and do not depend on a particular
// executable release.
static const uint8_t infoTableEndSignature[] = {
0x90, 0xf1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// NUL-terminated "STC90LE516AD" followed by 3 NUL bytes
static const uint8_t nameTableStartSignature[] = {
0x53, 0x54, 0x43, 0x39, 0x30, 0x4c, 0x45, 0x35,
0x31, 0x36, 0x41, 0x44, 0x00, 0x00, 0x00, 0x00,
};
// NUL-terminated "UNKNOWN" and "%06X" followed by 3 NUL bytes
static const uint8_t nameTableEndSignature[] = {
0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x00,
0x25, 0x30, 0x36, 0x58, 0x00, 0x00, 0x00, 0x00,
};
typedef struct {
uint32_t flags;
uint32_t nameAddr;
uint32_t mcuId;
uint32_t flashSize;
uint32_t eepromSize;
uint32_t eepromStartAddr; // STC89 & STC90 only. 0 means IAP.
uint32_t totalSize;
uint32_t unknown2;
} MCUInfo;
// Bit 1 is 1 for MCU which can accept 5V power supply voltage, be it
// exclusively or not, and 0 for low-voltage only MCU (around 3.3V).
#define FLAG_ACCEPT_5V_SUPPLY_VOLTAGE 0x00000002
// Bit 3 is 1 for so-called "IAP" MCU, meaning the start address of the
// flash portion used for EEPROM emulation can be configured.
#define FLAG_CONFIGURABLE_EEPROM_SIZE 0x00000008
// Bit 7 is 1 for MCU with an adjustable internal RC oscillator, i.e.
// that supports calibration. When bits 7 and 8 are both 0, the MCU has
// no IRCO at all (external crystal only).
#define FLAG_CONFIGURABLE_IRCO_FREQ 0x00000080
// Bit 8 is 1 for MCU with a fixed-frequency internal RC oscillator
// (the old IRC* models).
#define FLAG_FIXED_FREQUENCY_IRCO 0x00000100
// Bit 12 is 1 for MCS-251 MCU, i.e. with a flash size that can be
// larger than 64KB.
#define FLAG_IS_MCS251_MCU 0x00001000
#define SEARCH_BUFFER_LEN 8192
#define MCU_NAME_LEN 16
#define NO_MATCH -1
#define FOUND -2
// May help to guess the meaning of new flags as they are added.
static void toBits(uint32_t n, char *result) {
*result = '\0';
int pos = 0;
for (uint32_t mask = 0x80000000; mask; mask >>= 1, pos++) {
if (pos) {
strcat(result, ",");
}
if (n & mask) {
strcat(result, "1");
} else {
strcat(result, "0");
}
}
}
static void printCSVHeader(FILE *csvFile) {
if (csvFile != NULL) {
fprintf(csvFile, "name,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,flags (hex),mcuId,flashSize,eepromSize,eepromStartAddr,totalSize,unknown2\n");
}
}
static void printCSVRow(FILE *csvFile, const MCUInfo *info, const char *name) {
char flags[64];
if (csvFile != NULL) {
toBits(info->flags, flags);
fprintf(
csvFile,
"%s,%s,0x%08x,0x%04x,%u,%u,0x%08x,%u,0x%08x\n",
name,
flags,
info->flags,
(uint16_t) info->mcuId,
info->flashSize,
info->eepromSize,
info->eepromStartAddr,
info->totalSize,
info->unknown2
);
}
}
static const char *toBool(uint32_t flags, uint32_t mask) {
return (flags & mask) ? "True" : "False";
}
static void printMCUModel(const MCUInfo *info, const char *name) {
printf(
" MCUModel(name='%s', magic=0x%04x, total=%u, code=%u, eeprom=%u, iap=%s, calibrate=%s, mcs251=%s),\n",
name,
(uint16_t) info->mcuId,
info->totalSize,
info->flashSize,
info->eepromSize,
toBool(info->flags, FLAG_CONFIGURABLE_EEPROM_SIZE),
toBool(info->flags, FLAG_CONFIGURABLE_IRCO_FREQ),
toBool(info->flags, FLAG_IS_MCS251_MCU)
);
}
static void printUsage(const char *pgmName) {
printf("Usage: %s <STC-ISP_executable> [<CSV_output_file>]\n", pgmName);
printf("\n");
printf("- STC-ISP_executable is the file from which MCU models must be extracted.\n");
printf("Their list will be printed on the standard output.\n");
printf("\n");
printf("- The optional CSV_output_file will receive the MCU flags detail of each model\n");
printf("to facilitate reverse engineering efforts.\n");
printf("\n");
printf("Example: %s stc-isp-v6.91Q.exe MCUFlags.csv > MCUModels.txt\n", pgmName);
}
int main(int argc, const char **argv) {
int rc = 1;
MCUInfo *infoTable = NULL;
char *nameTable = NULL;
int mcuCount = 0;
uint32_t infoTableStartOffset = 0;
uint32_t infoTableEndOffset = 0;
uint32_t nameTableStartOffset = 0;
uint32_t nameTableEndOffset = 0;
uint32_t baseAddr = 0;
int nameTableSize = 0;
if (argc < 2) {
fprintf(stderr, "ERROR: missing argument\n");
printUsage(argv[0]);
exit(1);
}
FILE *exeFile = fopen(argv[1], "rb");
FILE *csvFile = NULL;
if (exeFile != NULL) {
if (argc > 2) {
csvFile = fopen(argv[2], "wt");
}
rc = 2;
uint8_t *buffer = (uint8_t *) malloc(SEARCH_BUFFER_LEN);
if (buffer != NULL) {
rc = 3;
int infoTableEndMatch = NO_MATCH;
int nameTableStartMatch = NO_MATCH;
int nameTableEndMatch = NO_MATCH;
uint32_t fileOffset = 0;
int bytesRead = 0;
while ((bytesRead = fread(buffer, 1, SEARCH_BUFFER_LEN, exeFile)) != 0) {
for (int curByte = 0; curByte < SEARCH_BUFFER_LEN; curByte++) {
int noMatch = 1;
if (infoTableEndMatch > NO_MATCH) {
if (infoTableEndSignature[infoTableEndMatch + 1] == buffer[curByte]) {
infoTableEndMatch++;
noMatch = 0;
if (infoTableEndMatch == (sizeof(infoTableEndSignature) -1)) {
infoTableEndMatch = FOUND;
break;
}
} else {
infoTableEndMatch = NO_MATCH;
}
}
if (nameTableStartMatch > NO_MATCH) {
if (nameTableStartSignature[nameTableStartMatch + 1] == buffer[curByte]) {
nameTableStartMatch++;
noMatch = 0;
if (nameTableStartMatch == (sizeof(nameTableStartSignature) -1)) {
nameTableStartMatch = FOUND;
break;
}
} else {
nameTableStartMatch = NO_MATCH;
}
}
if (nameTableEndMatch > NO_MATCH) {
if (nameTableEndSignature[nameTableEndMatch + 1] == buffer[curByte]) {
nameTableEndMatch++;
noMatch = 0;
if (nameTableEndMatch == (sizeof(nameTableEndSignature) - 1)) {
nameTableEndMatch = FOUND;
break;
}
} else {
nameTableEndMatch = NO_MATCH;
}
}
if (noMatch) {
if (infoTableEndMatch == NO_MATCH && infoTableEndSignature[0] == buffer[curByte]) {
infoTableEndMatch = 0;
infoTableEndOffset = fileOffset + curByte;
} else if (nameTableStartMatch == NO_MATCH && nameTableStartSignature[0] == buffer[curByte]) {
nameTableStartMatch = 0;
nameTableStartOffset = fileOffset + curByte;
} else if (nameTableEndMatch == NO_MATCH && nameTableEndSignature[0] == buffer[curByte]) {
nameTableEndMatch = 0;
nameTableEndOffset = fileOffset + curByte;
}
}
}
if (infoTableEndMatch == FOUND && nameTableStartMatch == FOUND && nameTableEndMatch == FOUND) {
rc = 0;
break;
}
fileOffset += SEARCH_BUFFER_LEN;
}
if (rc == 0) {
// Point to the byte immediately following the table's last entry.
infoTableEndOffset += sizeof(infoTableEndSignature);
// Read last item of Info Table
fseek(exeFile, infoTableEndOffset - sizeof(MCUInfo), SEEK_SET);
MCUInfo lastItem;
fread(&lastItem, sizeof(MCUInfo), 1, exeFile);
// We need it now in order to calculate the memory address
// corresponding to the UNKNOWN name.
// We'll also need baseAddr later, anyway.
baseAddr = lastItem.nameAddr;
rc = 4;
int infoTableStartMatch = NO_MATCH;
uint32_t fileOffset = 0;
int bytesRead = 0;
*((uint32_t *)(infoTableStartSignature)) = (baseAddr - nameTableStartOffset) + nameTableEndOffset;
fseek(exeFile, 0, SEEK_SET);
while ((bytesRead = fread(buffer, 1, SEARCH_BUFFER_LEN, exeFile)) != 0) {
for (int curByte = 0; curByte < SEARCH_BUFFER_LEN; curByte++) {
if (infoTableStartMatch > NO_MATCH) {
if (infoTableStartSignature[infoTableStartMatch + 1] == buffer[curByte]) {
infoTableStartMatch++;
if (infoTableStartMatch == (sizeof(infoTableStartSignature) - 1)) {
infoTableStartMatch = FOUND;
break;
}
} else {
infoTableStartMatch = NO_MATCH;
}
}
if (infoTableStartMatch == NO_MATCH && infoTableStartSignature[0] == buffer[curByte]) {
infoTableStartMatch = 0;
infoTableStartOffset = fileOffset + curByte;
}
}
if (infoTableStartMatch == FOUND) {
// Point to the first entry following the Unknown one.
infoTableStartOffset += sizeof(MCUInfo) - 4;
// Calculate number of entries while we're at it
mcuCount = (infoTableEndOffset - infoTableStartOffset) / sizeof(MCUInfo);
rc = 0;
break;
}
fileOffset += SEARCH_BUFFER_LEN;
}
}
free(buffer);
if (rc == 0) {
nameTableSize = nameTableEndOffset - nameTableStartOffset;
nameTable = (char *) malloc(nameTableSize);
if (nameTable == NULL) {
rc = 5;
}
}
if (rc == 0) {
fseek(exeFile, nameTableStartOffset, SEEK_SET);
fread(nameTable, nameTableSize, 1, exeFile);
infoTable = (MCUInfo *) malloc(infoTableEndOffset - infoTableStartOffset);
if (infoTable != NULL) {
fseek(exeFile, infoTableStartOffset, SEEK_SET);
fread(infoTable, infoTableEndOffset - infoTableStartOffset, 1, exeFile);
} else {
rc = 6;
free(nameTable);
}
}
}
fclose(exeFile);
}
if (rc == 0) {
printCSVHeader(csvFile);
for (int mcu = 0; mcu < mcuCount; mcu++) {
const char *mcuName = &nameTable[infoTable[mcu].nameAddr - baseAddr];
if (strncmp(mcuName, "STC12C54", 8) == 0 || strncmp(mcuName, "STC12LE54", 9) == 0) {
// STC12x54xx always have 12KB EEPROM
infoTable[mcu].eepromSize = 12 * 1024;
}
printCSVRow(csvFile, &infoTable[mcu], mcuName);
printMCUModel(&infoTable[mcu], mcuName);
}
free(infoTable);
free(nameTable);
}
if (csvFile != NULL) {
fclose(csvFile);
}
return rc;
}

View File

@ -0,0 +1,40 @@
#!/usr/bin/env python3
# This curious script dumps all model info from STC-ISP.
# Data is directly read from the binary.
# Offsets are for stc-isp-15xx-v6.86O.exe, sha1sum f70e317d758ef8c942613a8b0540147d7170589b
MCU_TABLE_OFFSET = 0x0006ac80
MCU_TABLE_SIZE = 984
MCU_RECORD_SIZE = 32
MCU_NAMES_OFFSET = 0x00087810
MCU_NAMES_PTR_OFFSET = 0x00487810
import struct
import sys
inp = open(sys.argv[1], "rb")
for i in range(MCU_TABLE_SIZE):
mcu_record_offset = MCU_TABLE_OFFSET + MCU_RECORD_SIZE * i
inp.seek(mcu_record_offset)
mcu_record = inp.read(MCU_RECORD_SIZE)
flags, name_ptr, mcu_id, code_size, ee_size, _, total_size, _ = struct.unpack("<8I", mcu_record)
mcu_id &= 0xffff
mcu_name_offset = MCU_NAMES_OFFSET + (name_ptr - MCU_NAMES_PTR_OFFSET)
inp.seek(mcu_name_offset)
name_str = inp.read(16).split(b'\00')[0].decode("ascii")
# TODO: With some MCUs, the amount of available EEPROM depends on the BSL version.
# Generally, newer BSLs free up a KB of additional EEPROM. Currently, always the
# maximum amount (with newer BSL) is reported.
# STC12x54xx always have 12 KB eeprom
if name_str.startswith("STC12C54") or name_str.startswith("STC12LE54"):
ee_size = 12 * 1024
print("MCUModel(name='%s', magic=0x%02x%02x, total=%d, code=%d, eeprom=%d)," %
(name_str, mcu_id >> 8, mcu_id & 0xff, total_size, code_size, ee_size))
inp.close()

View File

@ -1,80 +0,0 @@
001046: Read (UP): 2021-01-09 15:37:44.9125552 +0.0085328
46 b9 68 00 29 50 fd 84 1e 11 4d 05 8e 96 27 7c F.h.)P....M...'|
^
cpu_6t
04 47 01 7f 40 81 72 43 00 f0 51 05 80 00 ff ff .G..@.rC..Q.....
^ ^ ^ ^
freq_counte | | |
bl_version |
bl_stepping |
bl_minor
ff ff 38 20 20 02 19 60 0d a0 16 ..8 ..`...
001057: Write (DOWN): 2021-01-09 15:37:44.9814096 +0.0129872
46 b9 6a 00 0a 01 ff fd 82 02 f3 16 F.j.........
^
handshake
001072: Read (UP): 2021-01-09 15:37:45.0836096 +0.0115168
46 b9 68 00 07 01 00 70 16 F.h....p.
001113: Write (DOWN): 2021-01-09 15:37:45.1352048 +0.0171904
46 b9 6a 00 0b 05 00 00 46 b9 01 79 16 F.j.....F..y.
^
ping-pong
001116: Read (UP): 2021-01-09 15:37:45.1392768 +0.0017200
46 b9 68 00 07 05 00 74 16 F.h....t.
001127: Write (DOWN): 2021-01-09 15:37:45.1502464 +0.0109472
46 b9 6a 00 0b 03 00 00 46 b9 01 77 16 F.j.....F..w.
^
erase_flash ?
001170: Read (UP): 2021-01-09 15:37:45.4729040 +0.0099696
46 b9 68 00 0e 03 f0 51 c5 f2 06 7c 14 04 07 16 F.h....Q...|....
^
mcu id
001181: Write (DOWN): 2021-01-09 15:37:45.4791856 +0.0062576
46 b9 6a 00 8b 32 00 00 46 b9 02 00 08 12 00 3f F.j..2..F......?
^ ^
write address
write data
80 fe 75 81 07 12 00 4c e5 82 60 03 02 00 03 e4 ..u....L..`.....
78 ff f6 d8 fd 02 00 03 ae 82 af 83 8e 04 8f 05 x...............
1e be ff 01 1f ec 4d 60 0f 7c 90 7d 01 1c bc ff ......M`.|.}....
01 1d ec 4d 70 f7 80 e4 22 90 03 e8 12 00 1e e5 ...Mp...".......
80 f4 f5 80 80 f3 75 82 00 22 ff ff ff ff ff ff ......u.."......
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
ff ff ff ff ff ff ff ff ff ff 52 f9 16 ..........R..
001188: Read (UP): 2021-01-09 15:37:45.5301744 +0.0047088
46 b9 68 00 08 02 54 00 c6 16 F.h...T...
^
write done
001199: Write (DOWN): 2021-01-09 15:37:45.5575264 +0.0273248
46 b9 6a 00 0c 04 00 00 46 b9 fd 02 76 16 F.j.....F...v.
^
write msr
001202: Read (UP): 2021-01-09 15:37:45.5625296 +0.0018304
46 b9 68 00 08 04 54 00 c8 16 F.h...T...
unknown
001213: Write (DOWN): 2021-01-09 15:37:45.5712992 +0.0087472
46 b9 6a 00 07 ff 01 70 16 F.j....p.
unknown

View File

@ -1,84 +0,0 @@
文档说明 Explanation
------------------------
此文档翻译自FAQ.md
This document was translated from FAQ.md
最后修改时间2020年6月8日
Last modified time: June 8, 2020
常见问题
======================================
### 问题1是否可以从芯片中读取代码或EEPROM存储器
从设计上讲这是STC的引导加载程序协议无法实现的。 STC将此视为安全功能。目前没有已知的解决方法。有关更多详细信息和讨论请参见问题7。
### 问题2哪些串行接口已通过stcgal测试过
stcgal应该可以与波特率为16550的UART兼容。
但是如今基于USB模拟的UART是典型的情况。
以下是已通过stcgal成功测试的USB模拟UART接口芯片
* FT232系列操作系统LinuxWindows
* CH340 / CH341操作系统WindowsLinux需要内核4.10
* PL2303操作系统WindowsLinux
* CP2102操作系统WindowsLinuxmacOS
已知不起作用的接口:
* Raspberry Pi Mini UART缺少奇偶校验支持请启用PL011 UART
### 问题3stcgal 启动失败同时显示 `module 'serial' has no attribute 'PARITY_NONE'` 等类似信息
PyPI软件包“ serial”数据序列库和PyPI软件包“ pyserial”stcgal所需的串行端口访问库之间存在模块名称冲突。
您必须卸载'serial'软件包(`pip3 uninstall serial`)并重新安装'pyserial'`pip3 install --force-reinstall pyserial`)才能解决此问题。
目前没有其他已知的解决方案。
### 问题4stcgal无法识别MCU并停留在“Waiting for MCU”中
有许多问题可能导致此症状:
* 电气问题和错误连接。确保正确连接了RX / TXGND和VCC。
如果您不使用自动复位功能还应确保仅在stcgal启动后才接通电源因为引导加载程序仅在上电复位时被调用。
* 通过I / O引脚供电。
即使未连接VCC也可以通过I / O引脚例如RX / TX为MCU供电。
在这种情况下,上电复位逻辑不起作用。请参阅下一个问题。
* erial接口不兼容。由于各种原因一些基于USB的UART与STC MCU的兼容性很差。
您可以尝试使用选项`-l 1200`将握手波特率从标准2400波特降低到1200波特在某些情况下可以解决这些问题。
### 问题5如何避免MCU从I/O引脚供电
可以采取各种补救措施来避免MCU从I/O引脚供电。
* 您可以尝试在MCU VCC和GND之间连接一个电阻<1k以使注入的电源短路并希望将电压降至欠压值以下
* 另一种选择是在可能注入功率的I / O线上插入串联电阻。例如在RX / TX线上尝试一个类似1k的值。
* 还有另一种可能性是切换GND而不是VCC。
在大多数情况下,这应该是一个相当可靠的解决方案。
### 问题6RC频率调整失败
首先请确保指定的频率使用正确的单位。频率以kHz为单位指定安全范围约为5000 kHz-30000 kHz。
此外频率调整使用UART时钟作为时钟参考因此UART不兼容或时钟不准确也会导致频率调整问题。如果可能的话
尝试另一个UART芯片。
### 问题7波特率切换失败或闪存编程失败
特别是在高编程波特率,例如, 115200波特。尝试降低波特率或使用默认的19200波特率。
某些USB UART也会由于时序不正确而引起问题这可能会导致各种问题。
### 问题8如何使用自动重置功能
标准自动重置功能的工作原理与Arduino类似。 DTR是低电平有效信号在stcgal启动时置位500 ms然后在其余的编程序列中置为无效。
在标准USB UART上这将导致500 ms的低脉冲然后是高相位。 stcgal作者推荐以下电路
```
VCC --o o-- MCU GND
| |
.-. |
| | 1k |
| | |
'_' |
| |
| ||-+
DTR --o --||<- BS170/BSS138
||-| (N-CH MOSFET)
|
|
GND ---------o
```
该电路使用一个N沟道MOSFET作为开关来切换MCU的GND。 VCC直接连接。这避免了寄生供电问题。上拉电阻可确保在DTR输入悬空时接通MCU。

View File

@ -1,24 +0,0 @@
文档说明 Explanation
------------------------
此文档翻译自INSTALL.md
This document was translated from INSTALL.md
最后修改时间2020年6月8日
Last modified time: June 8, 2020
安装说明
============
stcgal需要Python 3.2或更高版本pyserial 3.0或更高版本以及TQDM 4.0.0或更高版本。
USB支持是可选的并且需要pyusb 1.0.0b2或更高版本。如果已经安装了依赖项,则可以使用包含的
```stcgal.py``` 脚本直接运行stcgal。
永久安装有几种选择:
* 使用Python3和```pip```。运行```pip3 install stcgal```
在系统上全局安装最新版本的stcgal。
这可能需要管理员/ root用户权限才能进行写到系统目录。
* 使用setuptools。运行`./setup.py build`来构建,并运行'sudo ./setup.py install`'来安装stcgal。

View File

@ -1,65 +0,0 @@
文档说明 Explanation
------------------------
此文档翻译自MODELS.md
This document was translated from MODELS.md
最后修改时间2020年6月8日
Last modified time: June 8, 2020
支持的MCU型号
====================
stcgal理论上完全支持STC 89/90/10/11/12/15/8/32系列MCU。
到目前为止stcgal已使用以下MCU模型进行了测试
89/90系列
* STC89C52RC (BSL 版本: 4.3C/6.6C)
* STC89C54RD+ (BSL 版本: 4.3C)
* STC90C52RC (BSL 版本: 4.3C)
* STC90C58RD+ (BSL 版本: 4.3C)
STC12C系列
* STC12C2052 (BSL 版本: 5.8D)
* STC12C2052AD (BSL 版本: 5.8D)
* STC12C5608AD (BSL 版本: 6.0G)
* STC12C5A16S2 (BSL 版本: 6.2I)
* STC12C5A60S2 (BSL 版本: 6.2I/7.1I)
* STC12C5204AD (BSL 版本: 6.6H)
10/11系列价格
* STC10F04XE (BSL 版本: 6.5J)
* STC11F02E (BSL 版本: 6.5K)
* STC11F08XE (BSL 版本: 6.5M)
STC15系列
* STC15F104E (BSL 版本: 6.7Q)
* STC15F204EA (BSL 版本: 6.7R)
* STC15L104W (BSL 版本: 7.1.4Q)
* STC15F104W (BSL 版本: 7.1.4Q)
* IAP15F2K61S2 (BSL 版本: 7.1.4S)
* STC15L2K16S2 (BSL 版本: 7.2.4S)
* IAP15L2K61S2 (BSL 版本: 7.2.5S)
* STC15W408AS (BSL 版本: 7.2.4T 和 7.2.5T)
* STC15W4K56S4 (BSL 版本: 7.3.4T 和 7.3.7T, UART and USB mode)
STC8系列
* STC8A8K64S4A12 (BSL 版本: 7.3.9U 和 7.3.12U)
* STC8F2K08S2 (BSL 版本: 7.3.10U)
* STC8A8K64D4 (BSL 版本: 7.4.2U)
* STC8G1K08A-8PIN (BSL 版本: 7.3.12U)
* STC8G1K08-20/16PIN (BSL 版本: 7.3.12U)
* STC8G1K17-20/16PIN (BSL 版本: 7.3.12U)
* STC8G2K64S4 (BSL 版本: 7.3.11U)
* STC8H1K08 (BSL 版本: 7.3.12U)
* STC8H3K64S2 (BSL 版本: 7.4.1U)
* STC8H3K64S4 (BSL 版本: 7.4.1U)
* STC8H4K64TL (BSL 版本: 7.4.3U)
* STC8H8K64U (BSL 版本: 7.4.4U)
STC32系列
* STC32G12K128-Beta (BSL 版本: 7.4.4U)
欢迎提供兼容性报告,无论是负面的还是正面的。

View File

@ -1,22 +0,0 @@
文档说明 Explanation
------------------------
此文档翻译自PyPI.md
This document was translated from PyPI.md
最后修改时间2020年6月8日
Last modified time: June 8, 2020
stcgal - 用于STC MCU的ISP闪存工具
===============================
stcgal是用于[STC MCU Ltd](http://stcmcu.com/)的命令行闪存编程工具。 兼容8051微控制器。
STC微控制器具有基于UART / USB的引导加载程序BSL
它采用系统内编程即基于数据包的协议通过串行链路刷新代码存储器和IAP存储器。
BSL还用于配置各种设备选项。 不幸的是该协议没有公开记录STC仅提供粗略的Windows GUI应用程序进行编程
stcgal是STC的Windows软件的功能全面的开源替代品。 它支持多种MCU非常便携适合自动下载。
[有关更多信息请参见GitHub页面。](https://github.com/grigorig/stcgal).

View File

@ -1,248 +0,0 @@
文档说明 Explanation
------------------------
此文档翻译自USAGE.md
This document was translated from USAGE.md
最后修改时间2020年6月8日
Last modified time: June 8, 2020
使用方法
=====
使用 ```-h``` 调用stcgal以获取使用信息。'//'后面是翻译,实际使用过程中没有后面内容)
```
usage: stcgal [-h] [-e] [-a] [-A {dtr,rts}] [-r RESETCMD]
[-P {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,stc8d,stc8g,usb15,auto}]
[-p PORT] [-b BAUD] [-l HANDSHAKE] [-o OPTION] [-t TRIM] [-D]
[-V]
[code_image] [eeprom_image]
stcgal 1.7 - an STC MCU ISP flash tool
(C) 2014-2018 Grigori Goronzy and others
https://github.com/grigorig/stcgal
positional arguments:
code_image code segment file to flash (BIN/HEX) //代码段文件刷新
eeprom_image eeprom segment file to flash (BIN/HEX) //EEPROM段文件刷新
optional arguments:
-h, --help show this help message and exit //显示此帮助消息并退出
-a, --autoreset cycle power automatically by asserting DTR//断言DTR自动重启电源
-A {dtr,rts}, --resetpin {dtr,rts}
pin to hold down when using --autoreset (default: DTR)
-r RESETCMD, --resetcmd RESETCMD
shell command for board power-cycling (instead of DTR //用于板上电重启的shell命令而不是DTR断言
assertion)
-P {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,stc8d,stc8g,usb15,auto}, --protocol {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,stc8d,stc8g,usb15,auto}
protocol version (default: auto) //协议版本芯片系列在默认状态为auto
-p PORT, --port PORT serial port device //串口设备
-b BAUD, --baud BAUD transfer baud rate (default: 115200) //传输波特率默认值115200
-l HANDSHAKE, --handshake HANDSHAKE
handshake baud rate (default: 2400) //握手波特率默认值2400
-o OPTION, --option OPTION
set option (can be used multiple times, see//设置选项(可以多次使用,请参阅文档)
documentation)
-t TRIM, --trim TRIM RC oscillator frequency in kHz (STC15+ series only)//RC振荡器频率kHz仅STC15 +系列)
-D, --debug enable debug output //启用调试输出
-V, --version print version info and exit //打印版本信息并退出
```
最重要的是, ```-p``` 设置用于编程的串行端口。
### 传输波特率
所有从 STC15 系列开始的 MCU 都支持默认值 115200 波特,至少是之前的 STC12C5A56S2。
对于较旧的 MCU您可能必须使用 ```-b 19200``` 才能正确操作。
### 通讯协议与规定
STC MCU对BSL使用各种相关但不兼容的协议。协议可以用```-P``` 标志来指定。
默认情况下使用UART协议自动检测。协议与MCU系列的对应关系如下
* ```auto``` 自动检测基于UART的协议默认
* ```stc89``` STC89/90 系列
* ```stc89a``` STC89/90 系列BSL 7.2.5C
* ```stc12a``` STC12x052 系列和其他类似系列
* ```stc12b``` STC12x52 系列, STC12x56 系列和其他类似系列
* ```stc12``` 多数 STC10/11/12 系列
* ```stc15a``` STC15x104E 和 STC15x204E(A) 系列
* ```stc15``` 多数 STC15 系列
* ```stc8``` STC8A8K64S4A12 和 STC8F 系列
* ```stc8d``` 所有 STC8 和 STC32 系列
* ```stc8g``` STC8G1 和 STC8H1 系列
* ```usb15``` 支持USB的STC15W4系列
doc / reverse-engineering子目录中的文本文件提供了BSL使用的反向工程协议的概述。
有关更多详细信息,请阅读源代码。
### 获取MCU信息
调用stcgal而不编写任何文件。它将转储有关MCU的信息例如'//'后面是翻译,实际使用过程中没有后面内容)
```
$ ./stcgal.py -P stc15
Waiting for MCU, please cycle power: done //等待MCU请重启电源
Target model:
Name: IAP15F2K61S2
Magic: F449
Code flash: 61.0 KB
EEPROM flash: 0.0 KB
Target frequency: 10.046 MHz //单片机频率
Target BSL version: 7.1S //单片机BSL版本
Target wakeup frequency: 34.771 KHz //单片机唤醒频率
Target options:
reset_pin_enabled=False //复位引脚启用状态
clock_source=internal //时钟来源
clock_gain=high
watchdog_por_enabled=False //看门狗状态
watchdog_stop_idle=True
watchdog_prescale=256 //看门狗预分频系数
low_voltage_reset=True //低电压复位
low_voltage_threshold=3
eeprom_lvd_inhibit=True
eeprom_erase_enabled=False
bsl_pindetect_enabled=False
por_reset_delay=long
rstout_por_state=high
uart2_passthrough=False //串口2直通
uart2_pin_mode=normal //串口2引脚模式
Disconnected!
```
如果识别失败,阅读[FAQ(chinese)](FAQ.md)
### 编程Flash闪存
stcgal支持Intel十六进制编码文件以及二进制文件。
Intel HEX通过文件扩展名(. hex,. ihx 或者. ihex ) 自动测试。
像前面一样调用 stcgal但提供代码映像的路径
```
$ ./stcgal.py -P stc15 hello.hex
Waiting for MCU, please cycle power: done
Target model:
Name: IAP15F2K61S2
Magic: F449
Code flash: 61.0 KB
EEPROM flash: 0.0 KB
Target frequency: 10.046 MHz //单片机频率
Target BSL version: 7.1S //单片机BSL版本
Target wakeup frequency: 34.771 KHz //单片机唤醒频率
Target options:
reset_pin_enabled=False //复位引脚启用状态
clock_source=internal //时钟来源
clock_gain=high
watchdog_por_enabled=False //看门狗状态
watchdog_stop_idle=True
watchdog_prescale=256 //看门狗预分频系数
low_voltage_reset=True //低电压复位
low_voltage_threshold=3
eeprom_lvd_inhibit=True
eeprom_erase_enabled=False
bsl_pindetect_enabled=False
por_reset_delay=long
rstout_por_state=high
uart2_passthrough=False //串口2直通
uart2_pin_mode=normal //串口2模式
Loading flash: 80 bytes (Intel HEX)
Trimming frequency: 10.046 MHz
Switching to 19200 baud: done
Erasing flash: done
Writing 256 bytes: .... done
Setting options: done
Target UID: 0D000021022632
Disconnected!
```
还可以编程存储器的EEPROM部分。 将 Flash 图像路径添加到命令行后添加EEPROM图像路径。
stcgal默认使用 19200 bps的保守波特率。 可以通过标志```-b```选择更快的波特率来加快编程速度。
### 设备选项
stcgal转储了许多目标选项。 也可以修改这些。 在命令行上提供一个( 或者更多) `-o` 标志,后面跟一个 key-value 对来调整这些设置。
例如你可以将外部晶体启用为时钟源:
```
$ ./stcgal.py -P stc15 -o clock_source=external hello.bin
```
请注意,设备选项只能在 Flash 内存被编程时设置
#### 命令行选项键
并非所有部件都支持所有选项。 描述中列出了支持每个选项的协议或者部分。
选项密钥 | 可能的值 | 协议/模型 | 描述
------------------------------|-------------------|---------------------|------------
```cpu_6t_enabled``` | true/false | 仅STC89 | 6T快速模式
```bsl_pindetect_enabled``` | true/false | 全部 | BSL仅在 p3。2/p3。3 或者 p1.0/p1.1 ( 取决于模型) 低时启用
```eeprom_erase_enabled``` | true/false | 全部 | 使用下一个编程周期擦除 EEPROM
```clock_gain``` | low/high | 所有带XTAL引脚 | 外部晶体的时钟增益
```ale_enabled``` | true/false | 仅STC89 | 如果 true正常 GPIO如果 false则启用ALE引脚
```xram_enabled``` | true/false | 仅STC89 | 使用内部 XRAM ( 仅适用于 STC89 )
```watchdog_por_enabled``` | true/false | 全部 | 复位复位后的看门狗状态( POR )
```low_voltage_reset``` | low/high | STC12A/STC12 | 低电压复位级别( 低:~3.3V, 高: ~3.7V)
```low_voltage_reset``` | true/false | STC12 | 启用RESET2引脚低压检测
```low_voltage_reset``` | true/false | STC15A | 启用低电压复位( brownout )
```clock_source``` | internal/external | 带XTAL的STC12A+ | 使用内部( RC ) 或者外部( 晶体) 时钟
```watchdog_stop_idle``` | true/false | STC12A+ | 在空闲模式停止看门狗
```watchdog_prescale``` | 2,4,8,...,256 | STC12A+ | 看门狗定时器预分频器,必须是两个电源。
```reset_pin_enabled``` | true/false | STC12+ | 如果 true正常 GPIO如果 false则复位引脚
```oscillator_stable_delay``` | 4096,...,32768 | 仅STC11F系列 | 时钟中的晶体稳定延迟。 一定是 two。
```por_reset_delay``` | short/long | STC12+ | 复位复位( POR ) 延迟
```low_voltage_threshold``` | 0...7 | STC15A+ | 低电压检测阈值。型号特定
```eeprom_lvd_inhibit``` | true/false | STC15A+ | 在低电压情况下忽略EEPROM写入
```rstout_por_state``` | low/high | STC15+ | 上电复位后的RSTOUT / RSTSV引脚状态
```uart1_remap``` | true/false | STC8 | 通过UART1到UART2引脚( 用于单导线UART模式)
```uart2_passthrough``` | true/false | STC15+ | 直通UART1至UART2引脚用于单线UART模式
```uart2_pin_mode``` | push-pull/normal | STC15+ | UART2 TX引脚的输出模式
```cpu_core_voltage``` | low/mid/high | STC15W+ | CPU核心电压( 低:~2.7V, mid: ~3.3V, 高:~3.6V)
```epwm_open_drain``` | true/false | STC8 | 上电复位后对EPWM引脚使用漏极开路引脚模式
```program_eeprom_split``` | 512 - 65024 | STC8A8 w/ 64 KB | 选择代码闪存和EEPROM闪存之间的划分以512字节块为单位
### 频率微调
如果使用内部RC振荡器 (```clock_source=internal```),
stcgal可以执行修整过程以将其调整为给定值。 仅在STC15系列及更高版本中受支持。
调整值与设备选项一起存储。 使用 ```-t``` 标志请求对某个值进行修剪。
通常可以实现4000到30000 kHz之间的频率。 如果修剪失败stcgal将中止。
### 自动功率循环
STC的微控制器需要上电复位才能调用引导加载程序这可能很不方便。
stcgal可以使用串行接口的DTR控制信号来自动执行此操作。
当通过```-a```用自动复位功能时DTR信号有效约500 ms。
这需要外部电路来实际切换电源。
在某些情况下当微控制器仅消耗很少的功率时就有可能直接从DTR信号提供功率。
作为DTR的替代方法可以使用定制的shell命令或外部脚本通过-r选项来重置设备。
您应将命令与```-a```选项一起指定。不要忘了引号
例如:
```
$ ./stcgal.py -P stc15 -a -r "echo 1 > /sys/class/gpio/gpio666/value"
```
或者
```
$ ./stcgal.py -P stc15 -a -r "./powercycle.sh"
```
### 退出状态
如果在执行stcgal时没有发生错误则退出状态为 0.。
任何错误( 如协议错误或者 I/O 错误) 都会导致退出状态 1。
如果用户按ctrl键中止 stcgal则会导致退出状态为 2.
### USB支持
STC15W4系列具有一个基于USB的BSL可以选择性的使用它。
stcgal中的USB支持是实验性的将来可能会改变。
USB模式是通过使用“ usb15”协议启用的。
USB协议会忽略端口```-p```标志以及波特率选项。同时不支持RC频率调整。

View File

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

View File

@ -26,7 +26,6 @@ import stcgal
import serial
from stcgal.utils import BaudType
from stcgal.protocols import Stc89Protocol
from stcgal.protocols import Stc89AProtocol
from stcgal.protocols import Stc12AProtocol
from stcgal.protocols import Stc12BProtocol
from stcgal.protocols import Stc12Protocol
@ -34,8 +33,6 @@ from stcgal.protocols import Stc15Protocol
from stcgal.protocols import Stc15AProtocol
from stcgal.protocols import StcUsb15Protocol
from stcgal.protocols import Stc8Protocol
from stcgal.protocols import Stc8dProtocol
from stcgal.protocols import Stc8gProtocol
from stcgal.protocols import StcAutoProtocol
from stcgal.protocols import StcProtocolException
from stcgal.protocols import StcFramingException
@ -46,15 +43,12 @@ class StcGal:
def __init__(self, opts):
self.opts = opts
self.hexFileType = 8
self.initialize_protocol(opts)
def initialize_protocol(self, opts):
"""Initialize protocol backend"""
if opts.protocol == "stc89":
self.protocol = Stc89Protocol(opts.port, opts.handshake, opts.baud)
elif opts.protocol == "stc89a":
self.protocol = Stc89AProtocol(opts.port, opts.handshake, opts.baud)
elif opts.protocol == "stc12a":
self.protocol = Stc12AProtocol(opts.port, opts.handshake, opts.baud)
elif opts.protocol == "stc12b":
@ -62,19 +56,14 @@ class StcGal:
elif opts.protocol == "stc12":
self.protocol = Stc12Protocol(opts.port, opts.handshake, opts.baud)
elif opts.protocol == "stc15a":
self.protocol = Stc15AProtocol(opts.port, opts.handshake, opts.baud, round(opts.trim * 1000))
self.protocol = Stc15AProtocol(opts.port, opts.handshake, opts.baud,
round(opts.trim * 1000))
elif opts.protocol == "stc15":
self.protocol = Stc15Protocol(opts.port, opts.handshake, opts.baud, round(opts.trim * 1000))
self.protocol = Stc15Protocol(opts.port, opts.handshake, opts.baud,
round(opts.trim * 1000))
elif opts.protocol == "stc8":
self.protocol = Stc8Protocol(opts.port, opts.handshake, opts.baud, round(opts.trim * 1000))
elif opts.protocol == "stc8d":
self.protocol = Stc8dProtocol(opts.port, opts.handshake, opts.baud, round(opts.trim * 1000))
elif opts.protocol == "stc8g":
"""FIXME Ugly hack, but works until I fully implement the STC8G protocol"""
if opts.trim < 27360:
self.protocol = Stc8dProtocol(opts.port, opts.handshake, opts.baud, round(opts.trim * 1000))
else:
self.protocol = Stc8gProtocol(opts.port, opts.handshake, opts.baud, round(opts.trim * 1000))
self.protocol = Stc8Protocol(opts.port, opts.handshake, opts.baud,
round(opts.trim * 1000))
elif opts.protocol == "usb15":
self.protocol = StcUsb15Protocol()
else:
@ -101,7 +90,6 @@ class StcGal:
fname.endswith(".ihex")):
try:
hexfile = IHex.read(fileobj)
self.hexFileType = hexfile.get_mode()
binary = hexfile.extract_data()
print("%d bytes (Intel HEX)" %len(binary))
return binary
@ -115,55 +103,45 @@ class StcGal:
def program_mcu(self):
"""Execute the standard programming flow."""
if self.opts.option: self.emit_options(self.opts.option)
if self.protocol.split_code and self.protocol.model.iap:
code_size = self.protocol.split_code
ee_size = self.protocol.split_eeprom
else:
code_size = self.protocol.model.code
ee_size = self.protocol.model.eeprom
code_size = self.protocol.model.code
ee_size = self.protocol.model.eeprom
print("Loading flash: ", end="")
sys.stdout.flush()
bindata = self.load_file_auto(self.opts.code_image)
if self.protocol.model.mcs251 and self.hexFileType != 32:
print("Invalid input file. MCU is an MCS-251, input file MUST specify a linear", file=sys.stderr)
print("base address, i.e. contain a type 04 record. More information at:", file=sys.stderr)
print("https://en.wikipedia.org/wiki/Intel_HEX", file=sys.stderr)
else:
# warn if it overflows
if len(bindata) > code_size:
print("WARNING: code_image overflows into eeprom segment!", file=sys.stderr)
if len(bindata) > (code_size + ee_size):
print("WARNING: code_image truncated!", file=sys.stderr)
bindata = bindata[0:code_size + ee_size]
# add eeprom data if supplied
if self.opts.eeprom_image:
print("Loading EEPROM: ", end="")
sys.stdout.flush()
eedata = self.load_file_auto(self.opts.eeprom_image)
if len(eedata) > ee_size:
print("WARNING: eeprom_image truncated!", file=sys.stderr)
eedata = eedata[0:ee_size]
if len(bindata) < code_size:
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]
bindata += eedata
# warn if it overflows
if len(bindata) > code_size:
print("WARNING: code_image overflows into eeprom segment!", file=sys.stderr)
if len(bindata) > (code_size + ee_size):
print("WARNING: code_image truncated!", file=sys.stderr)
bindata = bindata[0:code_size + ee_size]
# pad to 512 byte boundary
if len(bindata) % 512:
bindata += b'\xff' * (512 - len(bindata) % 512)
# add eeprom data if supplied
if self.opts.eeprom_image:
print("Loading EEPROM: ", end="")
sys.stdout.flush()
eedata = self.load_file_auto(self.opts.eeprom_image)
if len(eedata) > ee_size:
print("WARNING: eeprom_image truncated!", file=sys.stderr)
eedata = eedata[0:ee_size]
if len(bindata) < code_size:
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]
bindata += eedata
self.protocol.handshake()
self.protocol.erase_flash(len(bindata), code_size)
self.protocol.program_flash(bindata)
self.protocol.program_options()
# pad to 512 byte boundary
if len(bindata) % 512:
bindata += b'\xff' * (512 - len(bindata) % 512)
if self.opts.option: self.emit_options(self.opts.option)
self.protocol.handshake()
self.protocol.erase_flash(len(bindata), code_size)
self.protocol.program_flash(bindata)
self.protocol.program_options()
self.protocol.disconnect()
def erase_mcu(self):
@ -183,7 +161,7 @@ class StcGal:
return 0
try:
self.protocol.connect(autoreset=self.opts.autoreset, resetcmd=self.opts.resetcmd, resetpin=self.opts.resetpin)
self.protocol.connect(autoreset=self.opts.autoreset, resetcmd=self.opts.resetcmd)
if isinstance(self.protocol, StcAutoProtocol):
if not self.protocol.protocol_name:
raise StcProtocolException("cannot detect protocol")
@ -203,8 +181,7 @@ class StcGal:
except (StcFramingException, StcProtocolException) as ex:
sys.stdout.flush()
print("Protocol error: %s" % ex, file=sys.stderr)
if not isinstance(self.protocol, StcAutoProtocol):
self.protocol.disconnect()
self.protocol.disconnect()
return 1
except serial.SerialException as ex:
sys.stdout.flush()
@ -262,13 +239,11 @@ def cli():
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("-A", "--resetpin", help="pin to hold down when using --autoreset (default: DTR)",
choices=["dtr", "rts", "dtr_inverted", "rts_inverted"], default="dtr")
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", "stc89a", "stc12a", "stc12b", "stc12", "stc15a", "stc15", "stc8", "stc8d", "stc8g", "usb15", "auto"], 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: 115200)", type=BaudType(), default=115200)
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, see documentation)", action="append")
parser.add_argument("-t", "--trim", help="RC oscillator frequency in kHz (STC15+ series only)", type=float, default=0.0)

View File

@ -14,6 +14,7 @@ class IHex:
"""Read Intel HEX data from string or lines"""
ihex = cls()
segbase = 0
for line in lines:
line = line.strip()
if not line:
@ -21,14 +22,14 @@ class IHex:
t, a, d = ihex.parse_line(line)
if t == 0x00:
ihex.insert_data(a, d)
ihex.insert_data(segbase + a, d)
elif t == 0x01:
break # Should we check for garbage after this?
elif t == 0x02:
ihex.set_mode(16)
ihex.linearBaseAddress = struct.unpack(">H", d[0:2])[0] << 4
segbase = struct.unpack(">H", d[0:2])[0] << 4
elif t == 0x03:
ihex.set_mode(16)
@ -38,7 +39,7 @@ class IHex:
elif t == 0x04:
ihex.set_mode(32)
ihex.linearBaseAddress = struct.unpack(">H", d[0:2])[0] << 16
segbase = struct.unpack(">H", d[0:2])[0] << 16
elif t == 0x05:
ihex.set_mode(32)
@ -62,7 +63,6 @@ class IHex:
self.start = None
self.mode = 8
self.row_bytes = 16
self.linearBaseAddress = 0
def set_row_bytes(self, row_bytes):
"""Set output hex file row width (bytes represented per row)."""
@ -105,12 +105,6 @@ class IHex:
def set_mode(self, mode):
self.mode = mode
def get_mode(self):
return self.mode
def get_linearBaseAddress(self):
return self.linearBaseAddress
def get_area(self, addr):
for start, data in self.areas.items():
end = start + len(data)
@ -199,7 +193,6 @@ class IHex:
output += self.make_line(
0x04, 0, struct.pack(">H", newsegbase))
segbase = newsegbase
segbase = newsegbase
output += self.make_line(0x00, addr, chunk)

File diff suppressed because it is too large Load Diff

View File

@ -788,4 +788,4 @@ class Stc8Option(BaseOption):
num_val = Utils.to_int(val)
if num_val < 512 or num_val > 65024 or (num_val % 512) != 0:
raise ValueError("must be between 512 and 65024 bytes and a multiple of 512 bytes")
self.msr[4] = num_val // 256
self.msr[4] = num_val // 256

File diff suppressed because it is too large Load Diff

View File

@ -99,7 +99,7 @@ class TestProgramFuzzed(unittest.TestCase):
def single_fuzz(self, yml, serial_mock, fuzzer, read_mock, err, out, sleep_mock, write_mock):
"""Test a single programming cycle with fuzzing"""
with open(yml) as test_file:
test_data = yaml.load(test_file.read(), Loader=yaml.SafeLoader)
test_data = yaml.load(test_file.read())
for _ in range(1000):
with self.subTest():
opts = get_default_opts()