.github/copilot-instructions.md
@@ -1,54 +1,36 @@
## Repo overview (quick)
# Quick instructions for AI coding agents
- This is an STM32H7 firmware project for a lawnmower MCU. Key folders:
  - `Core/` — HAL/RTOS entry (Cube-generated code; see `Core/Src/main.c`).
  - `Drivers/` — STM32 HAL driver sources.
  - `APL/` — high-level application config and app entry (`APL/app.c`, `APL/AppConfig.h`).
  - `FML/` — feature modules (GPS, Internet, Bluetooth, UDPClient, etc.). Example: `FML/GPS.c` parses NMEA and uploads via `UDPClient`.
  - `HIDOLibrary/Include` — shared utility types and helpers (HIDO_* API and types used everywhere).
  - `MDK-ARM/` — Keil project files (`STM32H743.uvprojx`, `.uvoptx`) and build artifacts.
Overview
- STM32H743 (FreeRTOS) firmware for an autonomous lawnmower. Mix of CubeMX HAL, platform glue (HIDO_*), FML functional modules, and APL tasks.
## What matters for edits
What to read first
- Entry: `STM32H743/Core/Src/main.c` (MX_* init, `app_main()`, osKernelStart)
- App: `STM32H743/APL/app.c` (`app_task()` initializes modules and polls with a binary semaphore)
- Modules: `STM32H743/FML/*` (GPS, SBUS, Motion, Internet, UDP/TCP)
- Utilities: `STM32H743/HIDOLibrary/Include/` (HIDO_* helpers)
- Entry flow: `Core/Src/main.c` initializes HAL, registers UARTs and starts the RTOS. It calls `app_main()` (implemented in `APL/app.c`) before `osKernelStart()`.
- Main app loop runs in `APL/app_task` which polls subsystems after being awakened by a binary semaphore. ISR-to-main wake uses `app_trigger_from_isr()` (gives the same semaphore).
- Use existing registration patterns: `Uart_Register(...)` for UART endpoints, `GPS_PinRegister(...)` for GPIO pins, and module init functions e.g. `GPS_Init()`, `Internet_Init()`, `UDPClient_Init()`.
- Preserve Cube-generated sections: keep code inside/near `/* USER CODE BEGIN */` / `/* USER CODE END */` unchanged when modifying generated files.
Core rules and patterns
- Do not change CubeMX generated code outside `/* USER CODE BEGIN/END */` blocks. If you must regenerate, move logic to `FML/`/`APL/`.
- Init & Poll pattern: implement `Module_Init()` and `Module_Poll()`; call Init in `app_task()` and Poll during app loop.
- UARTs: register HAL handles with `Uart_Register(UART_ID_*, &huartX)` after `MX_USARTX_UART_Init()`; `Uart_Init()` config may require DMA buffers.
- ISR wake: signal `app_task` using `app_trigger_from_isr()`; avoid direct task notification unless you match existing pattern.
- Naming & API: follow `HIDO_*` typedefs and `HIDO_OK/HIDO_ERR` return conventions; use `HIDO_*` timers, queues, and helpers.
## Build & debug notes (concrete)
Build & debug
- Two build modes: CubeMX + STM32CubeIDE (edit `.ioc`) or Keil MDK-uVision (`MDK-ARM/STM32H743.uvprojx`).
- Use J-Link to flash; default debug UART: `USART1` (921600). Python telemetry/telemetry tool uses `UART5` (921600).
- DMA/coherency: avoid enabling D-cache while using DMA unless buffer cache maintenance is implemented.
- Two supported project entry points are present: STM32Cube `.ioc` (STM32H743/STM32H743.ioc) and Keil MDK `.uvprojx` (MDK-ARM/STM32H743.uvprojx). Developers typically:
  - Open the `.ioc` in STM32CubeIDE and generate code, or
  - Open the `.uvprojx` in Keil uVision (MDK) to build and flash.
- Debug/log serial: `USART1` is used as debug (`huart1`) at 921600 (see `MX_USART1_UART_Init` in `main.c`). GPS is on `USART2` (115200 default).
- UARTs use DMA for RX/TX in many places — be careful when changing buffer sizes or switching to interrupt-based I/O.
Safe changes and examples
- Add a new UART-based sensor:
  1) Configure UART in CubeMX / MX_USARTX_UART_Init() in `main.c` (USER CODE blocks)
  2) `Uart_Register(UART_ID_NEW, &huartX)` in `main.c` after init
  3) Add `FML/NewModule_Init()` and `FML/NewModule_Poll()` and call from `app_task()`
- Tuning: adjust motion PID and constants in `STM32H743/FML/motion_config.h` and `APL/global_param.h`. Persist via `save_com_map_to_flash()`.
## Project-specific conventions & patterns
Notes for AI agents
- Only change generated code inside USER blocks. Prefer to add files in `FML/`/`APL/` and follow `HIDO_` conventions.
- Minimize blocking work in `MotionControl_Task` and `app_task()`; keep real-time paths deterministic.
- For deeper module rules and examples, consult `STM32H743/.github/copilot-instructions.md` and `docs/`.
- Types and helpers use the `HIDO_` prefix (e.g. `HIDO_UINT32`, `HIDO_Util*`, `HIDO_Debug`). Search `HIDOLibrary/Include` for helper APIs.
- Polling model: many subsystems expose `*_Init()` and `*_Poll()` (e.g. `GPS_Poll()`, `Internet_Poll()`). Work is driven by the `app_task` loop.
- ISR -> application wake uses the global semaphore from `app_trigger_from_isr()` — prefer this pattern rather than direct task notifications in new code for consistency.
- Generated HAL code pattern: keep peripheral init in `MX_*_Init()` functions within `main.c` and put higher-level logic in `APL/` or `FML/`.
## Examples for common changes
- Add a new UART-based sensor: call `Uart_Register(UART_ID_X, &huartX)` in `main.c` after the corresponding `MX_USARTX_UART_Init()`, then create `Sensor_Init()`/`Sensor_Poll()` in `FML/` and call from `app_task`.
- Change debug log speed: edit `MX_USART1_UART_Init` in `Core/Src/main.c` and adjust callers that assume 921600.
- Add a periodic job: use the existing `HIDO_Timer` utilities and the app semaphore wake flow; follow `app_task`'s pattern to poll on wake.
## Where to look (quick file list)
- Entry & init: `Core/Src/main.c`
- App startup & scheduler task: `APL/app.c`, `Core/Src/freertos.c`
- Feature modules: `FML/GPS.c`, `FML/Internet/*.c`, `FML/UDPClient.c`
- Utilities and shared types: `HIDOLibrary/Include/*` (HIDO_* APIs)
- Project files: `STM32H743/STM32H743.ioc`, `MDK-ARM/STM32H743.uvprojx`
## Short guidelines for AI agents
- Only change generated files inside USER CODE blocks unless you also regenerate the Cube project (.ioc); prefer adding new modules under `FML/` or `APL/`.
- Follow existing naming and type conventions: use `HIDO_` helpers and typedefs for cross-module compatibility.
- When modifying peripheral config, update `MX_*_Init()` in `main.c` and check related registration calls (`Uart_Register`, `GPIO` pin registers).
- Use the semaphore-based `app_trigger_from_isr()` to wake the main loop from ISRs.
If you'd like, I can convert this into a shorter or longer version, or merge any existing instructions you have. Any areas you want me to expand or examples to add?
If any section should include deeper examples (UART template, module skeletons, or unit test patterns), tell me which piece to expand.