From d5332d90905f9daa4a455521b82d73c167dafbd7 Mon Sep 17 00:00:00 2001 From: George Popa Date: Fri, 6 Jun 2025 15:54:27 +0100 Subject: [PATCH 1/2] feat: add 2 interesting examples Signed-off-by: George Popa Co-authored-by: Frederic Pillon --- .../Registers/Reset_reason/Reset_reason.ino | 99 +++++++++++++++++++ .../Registers/UID_Retrieve/UID_Retrieve.ino | 53 ++++++++++ 2 files changed, 152 insertions(+) create mode 100644 examples/Peripherals/Registers/Reset_reason/Reset_reason.ino create mode 100644 examples/Peripherals/Registers/UID_Retrieve/UID_Retrieve.ino diff --git a/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino b/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino new file mode 100644 index 0000000..a268188 --- /dev/null +++ b/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino @@ -0,0 +1,99 @@ +/* Last Reset Reason Sketch +* This sketch will determine what caused the last reset on the STM32 MCU. Most microcontrollers +* have a register dedicated to storing the last reason of the chip, weather being from a +* low power condition, software caused brown-out. Test it by resetting the MCU via the USER button +* which triggers the Reset_my_MCU() function or unplug the USB cable and repluggit back. Adjust your +* UART, USER Button pin and registers accordingly. Use the MCU's datasheet and/or stm32yyyxxx.h for reference. +* The code is provided "as is" with no liability. +*/ + +#include "stm32yyxx_ll_rcc.h" +#include "IWatchdog.h" + +#define USER_BTN_PIN USER_BTN // Adjust this for your board + +// Enumerator for combining reset flag bits into one byte then display them +enum reset_reason { + UNKNOWN_RESET = 0, + BROWN_OUT = 1 << 0, + NRST_PIN = 1 << 1, + SOFTWARE_RST = 1 << 2, + INDEPENDENT_WDG = 1 << 3, + WINDOW_WDG = 1 << 4, + LOW_POWER = 1 << 5, + OPTION_BYTE_LOADER = 1 << 6, + POWER_ON_DOWN = 1 << 7 +}; + +reset_reason last_reset_reason = UNKNOWN_RESET; +static int default_button_state = LOW; + +void Reset_My_MCU() { + // There are a few reset conditions. + // Keep the one you wish to use and comment out the others. + // Below is the Software reset condition + // NVIC_SystemReset(); + + // Below is the Watchdog Timer reset condition + IWatchdog.begin(1000); //1ms tick then reset + while (1) + ; // Wait for reset +} + +void setup() { + pinMode(USER_BTN_PIN, INPUT); + default_button_state = digitalRead(USER_BTN_PIN); + Serial.begin(115200); + while (!Serial) + ; // Wait for Serial + +#ifdef RCC_CSR_BORRSTF + if (LL_RCC_IsActiveFlag_BORRST()) last_reset_reason = (reset_reason)(last_reset_reason | BROWN_OUT); +#endif + if (LL_RCC_IsActiveFlag_PINRST()) last_reset_reason = (reset_reason)(last_reset_reason | NRST_PIN); + if (LL_RCC_IsActiveFlag_SFTRST()) last_reset_reason = (reset_reason)(last_reset_reason | SOFTWARE_RST); +#if defined(RCC_RSR_IWDG1RSTF) + if (LL_RCC_IsActiveFlag_IWDG1RST()) last_reset_reason = (reset_reason)(last_reset_reason | INDEPENDENT_WDG); +#else + if (LL_RCC_IsActiveFlag_IWDGRST()) last_reset_reason = (reset_reason)(last_reset_reason | INDEPENDENT_WDG); +#endif +#if defined(RCC_RSR_WWDG1RSTF) + if (LL_RCC_IsActiveFlag_WWDG1RST()) last_reset_reason = (reset_reason)(last_reset_reason | WINDOW_WDG); +#else + if (LL_RCC_IsActiveFlag_WWDGRST()) last_reset_reason = (reset_reason)(last_reset_reason | WINDOW_WDG); +#endif + if (LL_RCC_IsActiveFlag_LPWRRST()) last_reset_reason = (reset_reason)(last_reset_reason | LOW_POWER); +#if defined(RCC_CSR_OBLRSTF) || defined(RCC_CSR2_OBLRSTF) + if (LL_RCC_IsActiveFlag_OBLRST()) last_reset_reason = (reset_reason)(last_reset_reason | OPTION_BYTE_LOADER); +#endif +#ifdef RCC_CSR_PORRSTF + if (LL_RCC_IsActiveFlag_PORRST()) last_reset_reason = (reset_reason)(last_reset_reason | POWER_ON_DOWN); +#endif + + // Clear reset flags + LL_RCC_ClearResetFlags(); +} + +void loop() { + Serial.println("Last reset reason:"); + + if (last_reset_reason & BROWN_OUT) Serial.println(" - Brown-out reset"); + if (last_reset_reason & SOFTWARE_RST) Serial.println(" - Software reset"); + if (last_reset_reason & INDEPENDENT_WDG) Serial.println(" - Independent Watchdog reset"); + if (last_reset_reason & WINDOW_WDG) Serial.println(" - Window Watchdog reset"); + if (last_reset_reason & LOW_POWER) Serial.println(" - Low-power reset"); + if (last_reset_reason & OPTION_BYTE_LOADER) Serial.println(" - Option byte loader reset"); + if (last_reset_reason & NRST_PIN) Serial.println(" - Pin reset (NRST or software)"); //last case so the rest take precedence before issuing NRST + if (last_reset_reason & POWER_ON_DOWN) Serial.println(" - Power on or power down reset"); + if (last_reset_reason == UNKNOWN_RESET) Serial.println(" - Unknown or no flags set"); + last_reset_reason = UNKNOWN_RESET; + + // Trigger software reset on button press + if (digitalRead(USER_BTN_PIN) != default_button_state) { + Serial.println("Button pressed → Triggering reset..."); + delay(300); // Debounce + Reset_My_MCU(); + } + + delay(1000); +} diff --git a/examples/Peripherals/Registers/UID_Retrieve/UID_Retrieve.ino b/examples/Peripherals/Registers/UID_Retrieve/UID_Retrieve.ino new file mode 100644 index 0000000..605502a --- /dev/null +++ b/examples/Peripherals/Registers/UID_Retrieve/UID_Retrieve.ino @@ -0,0 +1,53 @@ +/* UID Retrieve sketch +* UID (Universal Identifier) is a ID that's etched to each MCU at factory release +* so it's uniquely identifiable. This can help traceability and addressing devices +* without having to craft a database yourself. This sketch retrieves UID, MAC, Device +* and Revision ID of each MCU. Refer to the relevant datasheet to know where are these +* values are stored in the registers. +* The code is provided "as is" with no liability. +*/ + +void setup() { + Serial.begin(115200); + while (!Serial) + ; // Wait for Serial to be ready + + Serial.printf("%s Device Identifiers:\n", BOARD_NAME); + + // Unique Device ID (96 bits / 12 bytes) + uint32_t uid0 = HAL_GetUIDw0(); + uint32_t uid1 = HAL_GetUIDw1(); + uint32_t uid2 = HAL_GetUIDw2(); + + Serial.print("UID: "); + Serial.print(uid2, HEX); + Serial.print("-"); + Serial.print(uid1, HEX); + Serial.print("-"); + Serial.println(uid0, HEX); + + // MAC Address: typically stored in UID for STM32U series + // Use the lower 6 bytes of the 96-bit UID (commonly used) + uint8_t mac[6] = { + (uint8_t)(uid0 >> 0), + (uint8_t)(uid0 >> 8), + (uint8_t)(uid0 >> 16), + (uint8_t)(uid1 >> 0), + (uint8_t)(uid1 >> 8), + (uint8_t)(uid1 >> 16) + }; + + Serial.print("MAC Address: "); + for (int i = 0; i < 6; i++) { + if (mac[i] < 0x10) Serial.print("0"); + Serial.print(mac[i], HEX); + if (i < 5) Serial.print(":"); + } + Serial.println(); + Serial.printf("Device ID: 0x%x\n", HAL_GetDEVID()); + Serial.printf("Revision ID: 0x%x\n", HAL_GetREVID()); +} + +void loop() { + // Nothing here +} From d8b16d504cab8e8d23229f047bb0f3995aed5289 Mon Sep 17 00:00:00 2001 From: George Popa Date: Thu, 31 Jul 2025 13:57:28 +0100 Subject: [PATCH 2/2] fixed some mistakes, typos and added 2 more flags --- .../Registers/Reset_reason/Reset_reason.ino | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino b/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino index a268188..62352fa 100644 --- a/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino +++ b/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino @@ -1,7 +1,10 @@ +#include +#include + /* Last Reset Reason Sketch * This sketch will determine what caused the last reset on the STM32 MCU. Most microcontrollers * have a register dedicated to storing the last reason of the chip, weather being from a -* low power condition, software caused brown-out. Test it by resetting the MCU via the USER button +* low power condition, software caused or brown-out. Test it by resetting the MCU via holding the USER button, * which triggers the Reset_my_MCU() function or unplug the USB cable and repluggit back. Adjust your * UART, USER Button pin and registers accordingly. Use the MCU's datasheet and/or stm32yyyxxx.h for reference. * The code is provided "as is" with no liability. @@ -22,22 +25,25 @@ enum reset_reason { WINDOW_WDG = 1 << 4, LOW_POWER = 1 << 5, OPTION_BYTE_LOADER = 1 << 6, - POWER_ON_DOWN = 1 << 7 + POWER_ON_DOWN = 1 << 7, + STANDBY = 1 << 8, + WAKEUP = 1 << 9 }; -reset_reason last_reset_reason = UNKNOWN_RESET; +reset_reason last_reset_reason = UNKNOWN_RESET; //is initially 0 or unknown static int default_button_state = LOW; void Reset_My_MCU() { - // There are a few reset conditions. - // Keep the one you wish to use and comment out the others. + // There are a few reset conditions. Keep the one you wish to use and comment out the others. + // Below is the Software reset condition // NVIC_SystemReset(); // Below is the Watchdog Timer reset condition IWatchdog.begin(1000); //1ms tick then reset while (1) - ; // Wait for reset + ; // Wait for reset + } void setup() { @@ -69,9 +75,18 @@ void setup() { #ifdef RCC_CSR_PORRSTF if (LL_RCC_IsActiveFlag_PORRST()) last_reset_reason = (reset_reason)(last_reset_reason | POWER_ON_DOWN); #endif +#ifdef RCC_CSR_SBF + if (LL_PWR_IsActiveFlag_SB()) last_reset_reason = (reset_reason)(last_reset_reason | STANDBY); +#endif +#ifdef RCC_CSR_WUF + if (LL_PWR_IsActiveFlag_WU()) last_reset_reason = (reset_reason)(last_reset_reason | WAKEUP); +#endif + // Clear reset flags LL_RCC_ClearResetFlags(); + LL_PWR_ClearFlag_SB(); + LL_PWR_ClearFlag_WU(); } void loop() { @@ -83,10 +98,11 @@ void loop() { if (last_reset_reason & WINDOW_WDG) Serial.println(" - Window Watchdog reset"); if (last_reset_reason & LOW_POWER) Serial.println(" - Low-power reset"); if (last_reset_reason & OPTION_BYTE_LOADER) Serial.println(" - Option byte loader reset"); - if (last_reset_reason & NRST_PIN) Serial.println(" - Pin reset (NRST or software)"); //last case so the rest take precedence before issuing NRST + if (last_reset_reason & STANDBY) Serial.println(" - Standby mode reset"); + if (last_reset_reason & WAKEUP) Serial.println(" - WakeUp flag reset (Pin or RTC)"); if (last_reset_reason & POWER_ON_DOWN) Serial.println(" - Power on or power down reset"); + if (last_reset_reason & NRST_PIN) Serial.println(" - Pin reset (NRST or software)"); //last case so the rest take precedence before issuing NRST if (last_reset_reason == UNKNOWN_RESET) Serial.println(" - Unknown or no flags set"); - last_reset_reason = UNKNOWN_RESET; // Trigger software reset on button press if (digitalRead(USER_BTN_PIN) != default_button_state) {