add README.md
This commit is contained in:
2
Makefile
2
Makefile
@@ -40,7 +40,7 @@ CFLAGS += --stack-auto --noinduction --use-non-free
|
|||||||
## Disable lospre (workaround for bug 2673)
|
## Disable lospre (workaround for bug 2673)
|
||||||
#CFLAGS += --nolospre
|
#CFLAGS += --nolospre
|
||||||
LDFLAGS = -m$(ARCH) -l$(ARCH) --out-fmt-ihx
|
LDFLAGS = -m$(ARCH) -l$(ARCH) --out-fmt-ihx
|
||||||
OPTFLAGS = -Wl-bOPTION=0x4800 -Wl-bOPTION_BOOT=0x481C
|
OPTFLAGS = -Wl-bOPTION=0x4800 -Wl-bOPTION_BOOT=0x4812
|
||||||
|
|
||||||
# Conditionally add ENABLE_OPTION_BOOTLOADER macro
|
# Conditionally add ENABLE_OPTION_BOOTLOADER macro
|
||||||
ifneq ($(ENABLE_OPTION_BOOTLOADER),0)
|
ifneq ($(ENABLE_OPTION_BOOTLOADER),0)
|
||||||
|
|||||||
183
README.txt
183
README.txt
@@ -1,15 +1,170 @@
|
|||||||
This example toggles an LED on PD4 every 250 milliseconds.
|
# STM8 Bootloader Template Project
|
||||||
|
|
||||||
--------------------
|
## Overview
|
||||||
| |
|
|
||||||
| | 270 Ohm
|
This project provides a flexible bootloader implementation for STM8 microcontrollers using the SDCC compiler. The bootloader resides in the option bytes reserved area and enables in-application programming (IAP) capabilities via UART communication.
|
||||||
| PD4 |------\/\/\-----
|
|
||||||
| | |
|
Note: The bootloader implementation is based on and inspired by the [STM8uLoader](https://github.com/ovsp/STM8uLoader) project, with significant modifications and enhancements for integration into this template structure.
|
||||||
| | __|__
|
|
||||||
| <STM8> | \ / LED
|
## Features
|
||||||
| | _\_/_
|
|
||||||
| | |
|
- **Dual-stage Bootloader**:
|
||||||
| | _|_
|
- Boot1: Minimal bootloader stored in option bytes (0x4812-0x483F)
|
||||||
| | [GND]
|
- Boot2: Full-featured bootloader loaded via serial communication
|
||||||
| |
|
|
||||||
--------------------
|
- **Flexible Configuration**:
|
||||||
|
- Enable/disable bootloader via `ENABLE_OPTION_BOOTLOADER` Makefile macro
|
||||||
|
- Configurable communication parameters
|
||||||
|
|
||||||
|
- **Complete Toolchain**:
|
||||||
|
- PC-side programming utility for firmware updates
|
||||||
|
- Support for read, write, verify, and reset operations
|
||||||
|
|
||||||
|
- **Safe Operation**:
|
||||||
|
- Bootloader integrity protected in option bytes
|
||||||
|
- Fallback to application on timeout or communication failure
|
||||||
|
|
||||||
|
## Bootloader Reference
|
||||||
|
|
||||||
|
This project's bootloader implementation is derived from the excellent STM8uLoader project by ovsp. Key adaptations include:
|
||||||
|
|
||||||
|
- Integration into a modular template project structure
|
||||||
|
- Dual-stage bootloader approach (Boot1 in option bytes, Boot2 loaded dynamically)
|
||||||
|
- Enhanced Makefile system with configuration macros
|
||||||
|
- Extended command set and error handling
|
||||||
|
|
||||||
|
## Bootloader Operation Flow
|
||||||
|
|
||||||
|
1. **Power-on/Reset**:
|
||||||
|
- MCU starts execution at reset vector
|
||||||
|
- Control transfers to `bootloader_enter()` in `bsp/init0.c`
|
||||||
|
|
||||||
|
2. **Stage 1 (Boot1)**:
|
||||||
|
- Copies Boot1 from option bytes (0x4812-0x483F) to RAM and Run
|
||||||
|
- Sends synchronization sequence `0x00 0x0D` via UART
|
||||||
|
- Waits for PC to send Boot2 code
|
||||||
|
|
||||||
|
3. **Stage 2 (Boot2)**:
|
||||||
|
- Receives and validates Boot2 code from PC
|
||||||
|
- Executes Boot2 which provides full command interface
|
||||||
|
- Processes PC commands for programming, reading, and device control
|
||||||
|
|
||||||
|
4. **Application Start**:
|
||||||
|
- On successful programming or timeout, jumps to main application
|
||||||
|
- Option to stay in bootloader mode for debugging
|
||||||
|
|
||||||
|
## Building the Project
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
- SDCC (Small Device C Compiler) installed
|
||||||
|
- stm8flash or similar programming tool
|
||||||
|
- Python 3.x (for PC tools)
|
||||||
|
|
||||||
|
### Compilation Options
|
||||||
|
|
||||||
|
Enable bootloader support:
|
||||||
|
```bash
|
||||||
|
make ENABLE_OPTION_BOOTLOADER=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Disable bootloader (direct application execution):
|
||||||
|
```bash
|
||||||
|
make ENABLE_OPTION_BOOTLOADER=0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Targets
|
||||||
|
```bash
|
||||||
|
# Build both application and bootloader option
|
||||||
|
make all
|
||||||
|
|
||||||
|
# Program device (requires stm8flash)
|
||||||
|
make flash
|
||||||
|
```
|
||||||
|
|
||||||
|
## Option Bytes Configuration
|
||||||
|
|
||||||
|
The bootloader uses the reserved option byte area (0x4812-0x483F) for storage:
|
||||||
|
|
||||||
|
| Address Range | Content | Size |
|
||||||
|
|---------------|--------------------------|-------|
|
||||||
|
| 0x4800-0x480A | Device option bytes | 11 bytes |
|
||||||
|
| 0x4812-0x483F | Boot1 code | 46 bytes |
|
||||||
|
|
||||||
|
**Important**: These addresses are specific to STM8S103/003. Adjust for other STM8 variants.
|
||||||
|
|
||||||
|
## PC Communication Protocol
|
||||||
|
|
||||||
|
### Connection Parameters
|
||||||
|
- **Baud Rate**: 128000 bps
|
||||||
|
- **Data Bits**: 8
|
||||||
|
- **Parity**: None
|
||||||
|
- **Stop Bits**: 1
|
||||||
|
|
||||||
|
### Command Set
|
||||||
|
| Command | Opcode | Description |
|
||||||
|
|---------|--------|--------------------------------------|
|
||||||
|
| READ | 0xF1 | Read memory from device |
|
||||||
|
| WRITE | 0xF2 | Write memory to device |
|
||||||
|
| ERASE | 0xF3 | Erase flash sectors |
|
||||||
|
| RESET | 0xF4 | Reset to application |
|
||||||
|
|
||||||
|
### Communication Sequence
|
||||||
|
1. Boot1 sends sync bytes: `0x00 0x0D`
|
||||||
|
2. PC responds with Boot2 code length
|
||||||
|
3. Boot1 acknowledges and receives Boot2
|
||||||
|
4. Boot2 executes and presents command prompt
|
||||||
|
5. PC sends commands with appropriate parameters
|
||||||
|
|
||||||
|
## Usage Example
|
||||||
|
|
||||||
|
### Programming New Firmware
|
||||||
|
```bash
|
||||||
|
# 1. Build the application
|
||||||
|
make ENABLE_OPTION_BOOTLOADER=1
|
||||||
|
|
||||||
|
# 2. Connect to device
|
||||||
|
python scripts/stm8isp.py --port /dev/ttyUSB0
|
||||||
|
|
||||||
|
# 3. Follow interactive prompts to program
|
||||||
|
# or use command line:
|
||||||
|
python scripts/stm8isp.py --port /dev/ttyUSB0 --write firmware.ihx
|
||||||
|
```
|
||||||
|
|
||||||
|
## Supported Devices
|
||||||
|
|
||||||
|
Currently tested with:
|
||||||
|
- STM8S103/003 (default configuration)
|
||||||
|
|
||||||
|
**Important**: To port to other STM8 variants need verify peripheral register definitions
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **No response from device**:
|
||||||
|
- Verify baud rate settings
|
||||||
|
- Check UART pin connections (TX/RX swapped?)
|
||||||
|
- Ensure option bytes are correctly programmed
|
||||||
|
|
||||||
|
2. **Bootloader not starting**:
|
||||||
|
- Verify `ENABLE_OPTION_BOOTLOADER` is set during compilation
|
||||||
|
- Check reset vector points to `bootloader_enter`
|
||||||
|
- Confirm option bytes are protected from erasure
|
||||||
|
|
||||||
|
## Safety Considerations
|
||||||
|
|
||||||
|
1. **Power Stability**: Ensure stable power supply during programming
|
||||||
|
2. **Watchdog Timer**: Disable or properly handle watchdog in bootloader
|
||||||
|
3. **Interrupts**: Save/restore interrupt context during bootloader operations
|
||||||
|
4. **Memory Protection**: Never overwrite bootloader area in option bytes
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [STM8uLoader](https://github.com/ovsp/STM8uLoader)
|
||||||
|
- [STM8S Reference Manual](https://www.st.com/resource/en/reference_manual/cd00190271-stm8s-series-and-stm8af-series-8bit-microcontrollers-stmicroelectronics.pdf)
|
||||||
|
- [SDCC User Guide](http://sdcc.sourceforge.net/doc/sdccman.pdf)
|
||||||
|
- [STM8 Bootloader AN2659](https://www.st.com/resource/en/application_note/cd00173937-stm8-swim-communication-protocol-and-debug-module-stmicroelectronics.pdf)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Note**: This implementation is for educational and development purposes. Always verify bootloader behavior in your specific application context before deployment.
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
;; M Code
|
;; M Code
|
||||||
;; option O0 O1 N1 O2 N2 O3 N3 O4 N4 O5 N5
|
;; option O0 O1 N1 O2 N2 O3 N3 O4 N4 O5 N5
|
||||||
;; 4800 00 00 ff 00 ff 00 ff 00 ff 00 ff -- -- -- -- --
|
;; 4800 00 00 ff 00 ff 00 ff 00 ff 00 ff -- -- -- -- --
|
||||||
;; 03D0|4810 -- -- -- -- -- -- -- -- -- -- -- -- 00 03 df a6
|
;; 03D0|4810 -- -- 00 03 d5 a6 0d c7 52 32 c7 52 35 c7 52 31
|
||||||
;; 03E0|4820 0d c7 52 32 c7 52 35 c7 52 31 5f 5c 27 0c 72 0b
|
;; 03E0|4820 a6 80 5f 5c 27 14 72 0b 52 30 f8 3b 52 31 4c 26
|
||||||
;; 03F0|4830 52 30 f8 3b 52 31 4c 26 f1 81 72 cc 48 3e 80 04
|
;; 03F0|4830 f1 96 5c 5c 5c 13 01 26 e7 81 72 cc 48 3e 80 04
|
||||||
|
|
||||||
;; UART1 register address definitions
|
;; UART1 register address definitions
|
||||||
UART1_SR = 0x5230 ; Status register
|
UART1_SR = 0x5230 ; Status register
|
||||||
@@ -11,49 +11,58 @@ UART1_DR = 0x5231 ; Data register
|
|||||||
UART1_BRR1 = 0x5232 ; Baud rate register 1
|
UART1_BRR1 = 0x5232 ; Baud rate register 1
|
||||||
UART1_CR2 = 0x5235 ; Control register 2
|
UART1_CR2 = 0x5235 ; Control register 2
|
||||||
|
|
||||||
RAM_SIZE = 0x0400 ; Ram size (end of address)
|
RAM_SIZE = 0x0400 ; Ram size (end of bootloader address)
|
||||||
|
|
||||||
;; Bootloader body (located in OPT reserved area 0x481C-0x483F)
|
;; Bootloader body (located in OPT reserved area 0x481C-0x483F)
|
||||||
.area OPTION_BOOT
|
.area OPTION_BOOT
|
||||||
|
|
||||||
_bootO_start_data:
|
_boot_start_data:
|
||||||
;; Termination flag (copy process stops when encountering 0)
|
;; Termination flag (copy process stops when encountering 0)
|
||||||
.db 0x00 ; [00] Termination byte
|
.db 0x00 ; [00] Termination byte
|
||||||
|
|
||||||
;; [03 DF] RAM address for ret execution
|
;; [03 D5] RAM address for ret execution
|
||||||
.db (RAM_SIZE-(_bootO_go_adr-_bootO_start+2))>>8
|
.db (RAM_SIZE-(_boot_go_adr-_boot_start+2))>>8
|
||||||
.db (RAM_SIZE-(_bootO_go_adr-_bootO_start+2))&0xFF
|
.db (RAM_SIZE-(_boot_go_adr-_boot_start+2))&0xFF
|
||||||
|
|
||||||
_bootO_start:
|
_boot_start:
|
||||||
;; Initialize UART 9600 8N1
|
;; Initialize UART 9600 8N1
|
||||||
ld A, #0x0D ; [A6 0D] A = 0x0D (version number + UART configuration)
|
ld A, #0x0D ; [A6 0D] A = 0x0D (version number + UART configuration)
|
||||||
ld UART1_BRR1, A ; [C7 52 32] Set baud rate
|
ld UART1_BRR1, A ; [C7 52 32] Set baud rate
|
||||||
ld UART1_CR2, A ; [C7 52 35] Enable UART transmit/receive
|
ld UART1_CR2, A ; [C7 52 35] Enable UART transmit/receive
|
||||||
|
|
||||||
;; Send BREAK signal and version number $0D
|
;; Send BREAK signal and version number $0D
|
||||||
ld UART1_DR, A ; [C7 52 31] Send version number 0x0D
|
ld UART1_DR, A ; [C7 52 31] Send version number 0x0D
|
||||||
|
|
||||||
;; Receive maximum 243-byte data block and push onto stack
|
;; Receive 128-byte data block and push onto stack
|
||||||
_bootO_rx_byte:
|
_boot_rx_block:
|
||||||
clrw X ; [5F] Reset X (for timeout detection)
|
ld A, #0x80 ; [A6 80]
|
||||||
_bootO_rx_wait:
|
_boot_rx_byte:
|
||||||
incw X ; [5C] Increment X, check for overflow (timeout detection)
|
clrw X ; [5F] Reset X (for timeout detection)
|
||||||
jreq _bootO_exit ; [27 0C] If X overflows (receive timeout), exit
|
_boot_rx_wait:
|
||||||
|
incw X ; [5C] Increment X, check for overflow (timeout detection)
|
||||||
|
jreq _boot_exit ; [27 14] If X overflows (receive timeout), exit
|
||||||
|
|
||||||
;; Wait for data reception
|
;; Wait for data reception
|
||||||
btjf UART1_SR, #5, _bootO_rx_wait;[72 0B 52 30 F8]
|
btjf UART1_SR, #5, _boot_rx_wait ;[72 0B 52 30 F8]
|
||||||
|
|
||||||
;; Data received, push onto stack
|
;; Data received, push onto stack
|
||||||
push UART1_DR ; [3B 52 31]
|
push UART1_DR ; [3B 52 31]
|
||||||
inc A ; [4C] Increment A, used as receive counter
|
inc A ; [4C] Increment A, used as receive counter
|
||||||
jrne _bootO_rx_byte ; [26 F1] If A is not 0, continue receiving
|
jrne _boot_rx_byte ; [26 F1] If A is not 0, continue receiving
|
||||||
|
|
||||||
|
;; Check address
|
||||||
|
ldw X, SP ; [96]
|
||||||
|
incw X ; [5c]
|
||||||
|
incw X ; [5c]
|
||||||
|
incw X ; [5c]
|
||||||
|
cpw X, (1, SP) ; [13 01]
|
||||||
|
jrne _boot_rx_block ; [26 E7]
|
||||||
;; Reception complete, jump to received code
|
;; Reception complete, jump to received code
|
||||||
ret ; [81] Jump to address at top of stack via ret instruction
|
ret ; [81] Jump to address at top of stack via ret instruction
|
||||||
|
|
||||||
_bootO_exit:
|
_boot_exit:
|
||||||
;; Timeout exit, jump to user program
|
;; Timeout exit, jump to user program
|
||||||
jp [_bootO_go_adr] ; [72 CC 48 3E] Indirect jump
|
jp [_boot_go_adr] ; [72 CC 48 3E] Indirect jump
|
||||||
|
|
||||||
_bootO_go_adr:
|
_boot_go_adr:
|
||||||
.db 0x80, 0x04 ; [80 04] User program address: 0x8004
|
.db 0x80, 0x04 ; [80 04] User program address: 0x8004
|
||||||
|
|||||||
Reference in New Issue
Block a user