Модуль IWDG MCAL
Підтримувані родини STM32: H5
Не підтримуються: G4, H7, L4, U5
Цей репозиторій містить драйвер MCAL (Microcontroller Abstraction Layer) для незалежного сторожового таймера (Independent Watchdog) (IWDG) у мікроконтролерах STM32.
Він пропонує простий і безпечний інтерфейс для запуску, налаштування та оновлення (refresh) сторожового таймера без роботи з дільниками, значеннями перезавантаження чи прапорцями оновлення регістрів.
Кожна родина STM32 підтримується в окремій гілці цього репозиторію:
STM32G4STM32U5STM32L4STM32H5- та інші за потреби.
📘 Огляд
Драйвер IWDG MCAL абстрагує незалежний сторожовий таймер STM32 до інтерфейсу, заснованого на часі.
Користувач налаштовує сторожовий таймер у мілісекундах, а решту робить модуль:
- Обчислення дільника (4 - 1024) і значення перезавантаження за потрібним тайм-аутом та частотою LSI
- Опційне вікно (window) - оновлення дозволене лише в останній частині тайм-ауту
- Опційне переривання раннього пробудження (early wakeup) - користувацький callback викликається до того, як сторожовий таймер скине MCU
- Автоматичне оновлення з
Iwdg_Task()або ручне оновлення черезIwdg_Set_Refresh() - Зчитування стану сторожового таймера та досягнутого тайм-ауту
Доступ на запис до регістрів (ключовий регістр), прапорці оновлення регістрів і перевірка зворотним зчитуванням кожного запису конфігурації обробляються всередині модуля.
✅ Користувачеві не потрібно підключати чи використовувати жодні додаткові модулі, як-от драйвери RCC або NVIC.
Частота LSI зчитується з модуля RCC, а переривання раннього пробудження налаштовується через модуль NVIC всередині.
⚠️ Після запуску сторожовий таймер неможливо зупинити (апаратне обмеження). Його зупиняє лише системне скидання, якщо тільки в option bytes не вибрано апаратний режим сторожового таймера.
Iwdg_Deinit()лише вимикає переривання та автоматичне оновлення - застосунок має продовжувати оновлювати сторожовий таймер.
🧩 Архітектура
Архітектура відповідає стандартній багаторівневій структурі MCAL, що використовується в усіх репозиторіях STM32 MCAL:
┌────────────────────────────┐
│ Application │
└────────────┬───────────────┘
│
┌────────────▼───────────────┐
│ HAL │
│(Hardware Abstraction Layer)│
└────────────┬───────────────┘
┌────────────▼───────────────┐
│ MCAL - Iwdg │
│ ├── Iwdg_Port.h │
│ ├── Iwdg_Types.h │
│ └── Iwdg.c/.h │
└────────────┬───────────────┘
│
┌────────────▼───────────────┐
│ RAL │
│(Register Abstraction Layer)│
└────────────────────────────┘
🧠 Рекомендації щодо використання
Користувач має взаємодіяти лише з такими двома публічними заголовками:
| Файл | Призначення |
|---|---|
Iwdg_Port.h | Містить усі функції публічного API (ініціалізація, оновлення, зчитування стану та тайм-ауту, конфігурація за замовчуванням) |
Iwdg_Types.h | Містить визначення типів, що використовуються в API (структура конфігурації, тип часу, тип callback-а, стани запиту) |
Усе інше — таблиці дільників, допоміжні функції, обробник переривання — є внутрішнім і не повинно використовуватися напряму.
Публічний API
| Функція | Опис |
|---|---|
Iwdg_Get_ModuleVersion() | Повертає версію ПЗ модуля |
Iwdg_Init( config ) | Обчислює конфігурацію, запускає та налаштовує сторожовий таймер |
Iwdg_Deinit() | Вимикає переривання раннього пробудження та автоматичне оновлення (сторожовий таймер продовжує працювати) |
Iwdg_Task() | Автоматично оновлює сторожовий таймер (лише коли вікно не використовується) |
Iwdg_Get_DefaultConfig( config ) | Заповнює конфігурацію за замовчуванням: тайм-аут 1 с, без вікна, без переривання раннього пробудження |
Iwdg_Get_State( state ) | Повертає IWDG_FUNCTION_ACTIVE, якщо сторожовий таймер працює |
Iwdg_Get_Timeout( timeout ) | Повертає досягнутий тайм-аут у мс, обчислений за регістрами |
Iwdg_Set_Refresh() | Оновлює (перезавантажує) лічильник сторожового таймера |
Конфігурація
| Елемент | Опис |
|---|---|
Timeout | Потрібний тайм-аут у мс. З LSI 32 кГц діапазон приблизно 1 мс - 131 с. |
Window | Тривалість вікна перед тайм-аутом у мс, коли оновлення дозволене. IWDG_TIME_UNUSED вимикає вікно. Має бути коротшою за Timeout. |
EarlyWakeup | Час до тайм-ауту в мс, коли спрацьовує переривання раннього пробудження. IWDG_TIME_UNUSED вимикає переривання. Має бути коротшим за Timeout. |
EarlyWakeupIsr | Користувацький callback переривання раннього пробудження, може бути NULL |
IrqPriority | Пріоритет переривання раннього пробудження (0 - найвищий) |
Некоректна конфігурація (тайм-аут поза діапазоном, вікно або раннє пробудження не коротші за тайм-аут) відхиляється функцією Iwdg_Init() до запису в будь-який регістр.
Примітки
- Режим вікна - оновлення до початку вікна негайно скидає MCU (апаратна поведінка), програмно про це повідомити неможливо.
Iwdg_Task()не виконує оновлення в режимі вікна, застосунок має викликатиIwdg_Set_Refresh()всередині вікна. - Апаратний режим сторожового таймера - якщо
Iwdg_Get_State()повертаєIWDG_FUNCTION_ACTIVEдоIwdg_Init()після скидання, сторожовий таймер було запущено через option bytes. - Причина скидання - скидання від IWDG можна виявити після запуску за допомогою
Rcc_Get_ResetSource( RCC_RESET_SRC_IWDG, &flag )і очистити за допомогоюRcc_Set_ResetSourceClear()у модулі RCC. - Точність тайм-ауту - частота LSI змінюється залежно від температури та напруги (дивіться datasheet), тож реальний тайм-аут відрізняється від обчисленого.
⚙️ Типовий приклад використання
#include "Iwdg_Port.h"
static void App_WatchdogWarning( void )
{
// Last chance to store diagnostic data before the watchdog reset
}
int main(void)
{
iwdg_Config_t iwdgConfig;
iwdg_Time_ms_t achievedTimeout = 0u;
iwdg_RequestState_t iwdgState = IWDG_REQUEST_ERROR;
iwdgState = Iwdg_Get_DefaultConfig( &iwdgConfig );
iwdgConfig.Timeout = 500u; // Reset after 500 ms without refresh
iwdgConfig.EarlyWakeup = 50u; // Callback 50 ms before reset
iwdgConfig.EarlyWakeupIsr = App_WatchdogWarning;
iwdgConfig.IrqPriority = 0u;
if( IWDG_REQUEST_OK == iwdgState )
{
iwdgState = Iwdg_Init( &iwdgConfig );
}
if( IWDG_REQUEST_OK == iwdgState )
{
iwdgState = Iwdg_Get_Timeout( &achievedTimeout );
}
while (1)
{
// Refreshes the watchdog automatically (no window configured)
Iwdg_Task();
}
}
🧾 Стратегія гілкування
Кожна родина STM32 має власну гілку:
| Гілка | Опис |
|---|---|
STM32G4 | Драйвер MCAL для родини STM32G4 |
STM32U5 | Драйвер MCAL для родини STM32U5 |
STM32L4 | Драйвер MCAL для родини STM32L4 |
STM32H5 | Драйвер MCAL для родини STM32H5 |
Ці гілки містять специфічні для родини визначення регістрів, діапазони дільників і прив'язки до RCC/NVIC, зберігаючи спільний інтерфейс.
🧩 Залежності
- Rcc_Lib – частота тактування LSI (
RCC_PERIPH_IWDG) - Nvic_Lib – обробка переривання раннього пробудження
- RAL (Register Abstraction Layer) – використовується всередині для доступу до низькорівневих регістрів
Усі обов'язкові конфігурації RCC і NVIC обробляються всередині.
🧱 Приклад структури каталогів
Iwdg/
├── Iwdg_Port.h
├── Iwdg_Types.h
├── Iwdg.c
├── Iwdg.h
├── CMakeLists.txt
├── LICENSE.md
└── README.md
🛠 Інтеграція з CMake
- Додайте
Iwdg_Libдо вашої CMake-бібліотеки. - Підключіть
Iwdg_Port.hу вашому проєкті. - Злінкуйте з файлами реалізації модуля Iwdg.
- Налаштуйте модуль відповідно до вашого апаратного забезпечення.
Ліцензія
Цей проєкт ліцензовано за Creative Commons Attribution–NonCommercial 4.0 International (CC BY-NC 4.0).
Ви вільні використовувати, змінювати та поширювати цю роботу в некомерційних цілях за умови належного зазначення авторства.
Повні умови дивіться у LICENSE.md або на creativecommons.org/licenses/by-nc/4.0.
Автори
- Mr.Nobody — embedbits.com
Внески вітаються! Будь ласка, відкрийте pull request.