diff --git a/Makefile b/Makefile index 173031b..614b55f 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ CFLAGS += --stack-auto --noinduction --use-non-free ## Disable lospre (workaround for bug 2673) #CFLAGS += --nolospre 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 ifneq ($(ENABLE_OPTION_BOOTLOADER),0) diff --git a/README.txt b/README.txt index d1fbc13..08e9807 100644 --- a/README.txt +++ b/README.txt @@ -1,15 +1,170 @@ -This example toggles an LED on PD4 every 250 milliseconds. +# STM8 Bootloader Template Project - -------------------- -| | -| | 270 Ohm -| PD4 |------\/\/\----- -| | | -| | __|__ -| | \ / LED -| | _\_/_ -| | | -| | _|_ -| | [GND] -| | - -------------------- +## Overview + +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. + +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. + +## Features + +- **Dual-stage Bootloader**: + - Boot1: Minimal bootloader stored in option bytes (0x4812-0x483F) + - 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. diff --git a/scripts/bootloader.opt b/scripts/bootloader.opt index 20d6729..c853e2f 100644 --- a/scripts/bootloader.opt +++ b/scripts/bootloader.opt @@ -1,9 +1,9 @@ ;; M Code ;; option O0 O1 N1 O2 N2 O3 N3 O4 N4 O5 N5 ;; 4800 00 00 ff 00 ff 00 ff 00 ff 00 ff -- -- -- -- -- -;; 03D0|4810 -- -- -- -- -- -- -- -- -- -- -- -- 00 03 df a6 -;; 03E0|4820 0d c7 52 32 c7 52 35 c7 52 31 5f 5c 27 0c 72 0b -;; 03F0|4830 52 30 f8 3b 52 31 4c 26 f1 81 72 cc 48 3e 80 04 +;; 03D0|4810 -- -- 00 03 d5 a6 0d c7 52 32 c7 52 35 c7 52 31 +;; 03E0|4820 a6 80 5f 5c 27 14 72 0b 52 30 f8 3b 52 31 4c 26 +;; 03F0|4830 f1 96 5c 5c 5c 13 01 26 e7 81 72 cc 48 3e 80 04 ;; UART1 register address definitions UART1_SR = 0x5230 ; Status register @@ -11,49 +11,58 @@ UART1_DR = 0x5231 ; Data register UART1_BRR1 = 0x5232 ; Baud rate register 1 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) .area OPTION_BOOT -_bootO_start_data: +_boot_start_data: ;; Termination flag (copy process stops when encountering 0) .db 0x00 ; [00] Termination byte - ;; [03 DF] RAM address for ret execution - .db (RAM_SIZE-(_bootO_go_adr-_bootO_start+2))>>8 - .db (RAM_SIZE-(_bootO_go_adr-_bootO_start+2))&0xFF + ;; [03 D5] RAM address for ret execution + .db (RAM_SIZE-(_boot_go_adr-_boot_start+2))>>8 + .db (RAM_SIZE-(_boot_go_adr-_boot_start+2))&0xFF -_bootO_start: +_boot_start: ;; Initialize UART 9600 8N1 - ld A, #0x0D ; [A6 0D] A = 0x0D (version number + UART configuration) - ld UART1_BRR1, A ; [C7 52 32] Set baud rate - ld UART1_CR2, A ; [C7 52 35] Enable UART transmit/receive + ld A, #0x0D ; [A6 0D] A = 0x0D (version number + UART configuration) + ld UART1_BRR1, A ; [C7 52 32] Set baud rate + ld UART1_CR2, A ; [C7 52 35] Enable UART transmit/receive ;; 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 -_bootO_rx_byte: - clrw X ; [5F] Reset X (for timeout detection) -_bootO_rx_wait: - incw X ; [5C] Increment X, check for overflow (timeout detection) - jreq _bootO_exit ; [27 0C] If X overflows (receive timeout), exit + ;; Receive 128-byte data block and push onto stack +_boot_rx_block: + ld A, #0x80 ; [A6 80] +_boot_rx_byte: + clrw X ; [5F] Reset X (for timeout detection) +_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 - 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 - push UART1_DR ; [3B 52 31] - inc A ; [4C] Increment A, used as receive counter - jrne _bootO_rx_byte ; [26 F1] If A is not 0, continue receiving + push UART1_DR ; [3B 52 31] + inc A ; [4C] Increment A, used as receive counter + 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 - 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 - jp [_bootO_go_adr] ; [72 CC 48 3E] Indirect jump + jp [_boot_go_adr] ; [72 CC 48 3E] Indirect jump -_bootO_go_adr: - .db 0x80, 0x04 ; [80 04] User program address: 0x8004 +_boot_go_adr: + .db 0x80, 0x04 ; [80 04] User program address: 0x8004