# STM32 Bootloader (Beta)

## Описание
Этот бутлоадер для STM32 реализован как **машина состояний (state machine)**.  
Его задача — управлять обновлением прошивки по UART или CAN, а также обеспечивать безопасный переход между приложением и бутлоадером.

---

## Общение с бутлоадером
В [гите](https://git.arktika.cyou/Razvalyaev/boot_terminal) есть терминалка на C# для общения с бутом через SlCan (uart там не сделан).
А вообще реализованы следующие команды
- `0x01` — стирание прошивки во Flash — (`CMD_ERASE`)  
- `0x02` — запуск процедуры приёма страницы — (`CMD_START_RECEIVE`)  
- `0x03` — запись блока прошивки — (`CMD_WRITE`)  
- `0x04` — переход в приложение — (`CMD_GOTOAPP`)  
- `0x05` — сброс микроконтроллера — (`CMD_RESET`)  
- `0x06` — принудительный переход в бутлоадер — (`CMD_GOTOBOOT`)  
- `0xAA` — проверка связи (ping) — (`CMD_PING`)  


Бутлоадер уже содержит каркас для работы как с **CAN** (и некоторые наработки для **UART**, но не проверенные).  
Для расширения функционала и поддержки новых протоколов нужно доопределить следующие функции.

- Приём команды:
  ```c
  BootloaderCommand_t Bootloader_UART_Receive(Bootloader_t *bl); //boot_uart.c
  BootloaderCommand_t Bootloader_CAN_Receive(Bootloader_t *bl); //boot_can.c
  ```
  - Читает 1 байт команды и возвращает её (`CMD_ERASE`, `CMD_WRITE`, и т.п.) или, если нет команды, `NO_CMD`.
- Приём страницы прошивки:
  ```c
  void Bootloader_UART_Receive_Page(Bootloader_t *bl); //boot_uart.c
  void Bootloader_CAN_Receive_Page(Bootloader_t *bl); //boot_can.c
  ```
  - Принимает блок данных длиной `PAGE_SIZE` байт.
  - Принимает CRC32 (4 байта).
  - Заполняет поля `bl->fw_buffer`, `bl->fw_len`, `bl->fw_crc`.

---

## Как работает бутлоадер
1. После сброса бутлоадер проверяет сохранённые ошибки и "ключ" прошивки.  
   - Если приложение корректное — выполняется переход в него.  
   - Если приложение повреждено или нет ключа — остаётся в бутлоадере.  
2. В состоянии `IDLE` бутлоадер слушает команды.  
3. Прошивка отправляется страницами, каждая страница проверяется по CRC32.  
4. По завершению записи устанавливается "ключ приложения", и возможен переход в основное приложение.  
5. При ошибках — возврат в состояние `ERROR`, уведомление хоста и мигание LED. Для сброса ошибок надо перезапустить МК.


---
## Основные особенности бута
- Реализован как конечный автомат со следующими состояниями:
  - `INIT` — проверка ключа, и далее переход в приложение или инициализация бута
  - `IDLE` — ожидание команды
  - `RECEIVE_UART` / `RECEIVE_CAN` — приём страницы прошивки
  - `WRITE` — запись принятой страницы во Flash
  - `ERASE` — стирание приложения
  - `JUMP_TO_APP` — переход к основному приложению
  - `JUMP_TO_BOOT` — возврат в бутлоадер
  - `RESET` — программный сброс
  - `ERROR` — обработка ошибок
- Проверка целостности прошивки с помощью **CRC32**
- Учёт ошибок (hardfault, memmanage, watchdog и т.п.)
- Индикация состояния через LED:
  - мигает раз в 500 мс при ошибке
  - включается при приеме комады и выключается, когда команда выполнена

---

## Интеграция в проект
Здесь бутлоадер и основное приложение реализованы как отдельные таргеты:

- **Таргет приложения**  
  Исключает `main()` бутлоадера и компилирует только само приложение.  
  Адрес загрузки приложения: `0x0800C000`.

- **Таргет бутлоадера**  
  Исключает код приложения и компилирует только бутлоадер.  
  Адрес загрузки бутлоадера: `0x08000000`.
  
Чтобы в основном приложении можно было управлять бутлоадером:
1. Подключить `boot_jump.h` и `boot_jump.c` для взаимодействия с бутлоадером:
```c  
#include "boot_jump.h"  
```
2. В начале `main()` вызвать `App_Init()`, чтобы установить VTOR на
начало приложения:
```c  
App_Init();             
```
3. Для перехода в бутлоадер (например, при ошибке или обновлении):
```c  
JumpToBootloader();     
```
