From b875d3a1781ee0d82690ed7a350efdf43a81c42f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 23 Jan 2023 15:08:52 +0100 Subject: [PATCH 01/14] examples: update adc internal channels to support STM32C0xx Signed-off-by: Frederic Pillon --- .../ADC/Internal_channels/Internal_channels.ino | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino index 7abcec3..ee43ee6 100644 --- a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino +++ b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino @@ -20,13 +20,22 @@ #include "stm32yyxx_ll_adc.h" /* Values available in datasheet */ +#if defined(STM32C0xx) +#define CALX_TEMP 30 +#else #define CALX_TEMP 25 -#if defined(STM32F1xx) -#define V25 1430 +#endif + +#if defined(STM32C0xx) +#define VTEMP 760 +#define AVG_SLOPE 2530 +#define VREFINT 1212 +#elif defined(STM32F1xx) +#define VTEMP 1430 #define AVG_SLOPE 4300 #define VREFINT 1200 #elif defined(STM32F2xx) || defined(STM32F4xx) -#define V25 760 +#define VTEMP 760 #define AVG_SLOPE 2500 #define VREFINT 1210 #endif @@ -66,7 +75,7 @@ static int32_t readTempSensor(int32_t VRef) return (__LL_ADC_CALC_TEMPERATURE(VRef, analogRead(ATEMP), LL_ADC_RESOLUTION)); #endif #elif defined(__LL_ADC_CALC_TEMPERATURE_TYP_PARAMS) - return (__LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(AVG_SLOPE, V25, CALX_TEMP, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION)); + return (__LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(AVG_SLOPE, VTEMP, CALX_TEMP, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION)); #else return 0; #endif From ff8640fee27e9bca4805cf289cf0069f64c1b89e Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 24 May 2023 17:28:14 +0200 Subject: [PATCH 02/14] examples(ADC internal): disable ICACHE if enabled For some series, calibration values are stored in FLASH read-only area and required to disable ICACHE before access them. Signed-off-by: Frederic Pillon --- .../Internal_channels/Internal_channels.ino | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino index ee43ee6..373e8d9 100644 --- a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino +++ b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino @@ -93,6 +93,16 @@ static int32_t readVoltage(int32_t VRef, uint32_t pin) // The loop routine runs over and over again forever: void loop() { +#if defined(ICACHE) && defined (HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) + bool icache_enabled = false; + if (HAL_ICACHE_IsEnabled() == 1) { + icache_enabled = true; + /* Disable instruction cache prior to internal cacheable memory update */ + if (HAL_ICACHE_Disable() != HAL_OK) { + Error_Handler(); + } + } +#endif /* ICACHE && HAL_ICACHE_MODULE_ENABLED && !HAL_ICACHE_MODULE_DISABLED */ // Print out the value read int32_t VRef = readVref(); Serial.printf("VRef(mv)= %i", VRef); @@ -104,4 +114,13 @@ void loop() { #endif Serial.printf("\tA0(mv)= %i\n", readVoltage(VRef, A0)); delay(200); +#if defined(ICACHE) && defined (HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) + if (icache_enabled) + { + /* Re-enable instruction cache */ + if (HAL_ICACHE_Enable() != HAL_OK) { + Error_Handler(); + } + } +#endif /* ICACHE && HAL_ICACHE_MODULE_ENABLED && !HAL_ICACHE_MODULE_DISABLED */ } \ No newline at end of file From 2e82ca1523b3c8b6ec5b1a9eca01e857d02ba1c4 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 24 May 2023 17:29:42 +0200 Subject: [PATCH 03/14] Update library.properties Signed-off-by: Frederic Pillon --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 3c18ed3..d6ddf7f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino Examples -version=1.2.2 +version=1.2.3 author=several maintainer=stm32duino sentence=Provides several examples for the Arduino core for STM32 MCUs. From d43dcec8b82e81796ee7256a8b98111865fa2e3e Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 26 Aug 2024 11:18:13 +0200 Subject: [PATCH 04/14] fix(u0): VREFINT_CAL value is not programmed during production Signed-off-by: Frederic Pillon --- .../ADC/Internal_channels/Internal_channels.ino | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino index 373e8d9..35644dc 100644 --- a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino +++ b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino @@ -54,6 +54,13 @@ void setup() { static int32_t readVref() { +#ifdef STM32U0xx + /* On some devices Internal voltage reference calibration value not programmed + during production and return 0xFFFF. See errata sheet. */ + if ((uint32_t)(*VREFINT_CAL_ADDR) == 0xFFFF) { + return 3300U; + } +#endif #ifdef __LL_ADC_CALC_VREFANALOG_VOLTAGE #ifdef STM32U5xx return (__LL_ADC_CALC_VREFANALOG_VOLTAGE(ADC1, analogRead(AVREF), LL_ADC_RESOLUTION)); From f7e428614500faecdcd7134b08fe8ecf0419155b Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 5 Sep 2024 14:56:41 +0200 Subject: [PATCH 05/14] fix(spi): update examples after SPI rework Signed-off-by: Frederic Pillon --- examples/NonReg/SPI_loop/SPI_loop.ino | 48 +++++++++++++++++---------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/examples/NonReg/SPI_loop/SPI_loop.ino b/examples/NonReg/SPI_loop/SPI_loop.ino index 7feab8b..ae77e68 100644 --- a/examples/NonReg/SPI_loop/SPI_loop.ino +++ b/examples/NonReg/SPI_loop/SPI_loop.ino @@ -24,34 +24,46 @@ #warning "LED_BUILTIN is not defined." #endif -#define MOSI_PIN PIN_SPI_MOSI -#define MISO_PIN PIN_SPI_MISO -#define SCK_PIN PIN_SPI_SCK -#define CS_PIN PIN_SPI_SS +/* Set to 1 if CS have to be managed by the hardware */ +#define CS_HARDWARE_CONTROL 0 + +#define MOSI_PIN PIN_SPI_MOSI +#define MISO_PIN PIN_SPI_MISO +#define SCK_PIN PIN_SPI_SCK +#define CS_PIN PIN_SPI_SS uint8_t buffer_tx[] = "Thequickbrownfoxjumpsoverthelazydog\0"; -#define BUF_SIZE sizeof(buffer_tx) +#define BUF_SIZE sizeof(buffer_tx) uint8_t buffer_rx[BUF_SIZE] = {}; /* SPI transfer loop nb */ #define TEST_LOOP_NB 9 void setup() { - uint8_t tested_ok = 0; // test result + uint8_t tested_ok = 0; // test result SPI.setMOSI(MOSI_PIN); SPI.setMISO(MISO_PIN); SPI.setSCLK(SCK_PIN); - // Don't set CS_PIN to have Software ChipSelect management - // Instead, CS_PIN is passed as argument to SPI.transfer(CS_PIN) - // SPI.setSSEL(CS_PIN); +#if CS_HARDWARE_CONTROL == 1 + SPI.setSSEL(CS_PIN); +#endif +#if CS_HARDWARE_CONTROL == 0 + pinMode(CS_PIN, OUTPUT); + digitalWrite(CS_PIN, HIGH); +#endif /* the SPI pin configuration is done by the SPI.begin */ - SPI.begin(CS_PIN); + SPI.begin(); for (uint8_t received = 0; received < TEST_LOOP_NB; received++) { - SPI.transfer(CS_PIN, buffer_tx, buffer_rx, BUF_SIZE, SPI_LAST); - +#if CS_HARDWARE_CONTROL == 0 + digitalWrite(CS_PIN, LOW); +#endif + SPI.transfer(buffer_tx, buffer_rx, BUF_SIZE); +#if CS_HARDWARE_CONTROL == 0 + digitalWrite(CS_PIN, HIGH); +#endif /* compare what is received to what was sent */ if (!memcmp(buffer_tx, buffer_rx, BUF_SIZE)) { /* this transfer passed */ @@ -60,14 +72,14 @@ void setup() { memset(buffer_rx, 0, BUF_SIZE); } /* display test result */ - pinMode(LED_BUILTIN, OUTPUT); // Configure LED pin, for test result - digitalWrite(LED_BUILTIN, LOW); // start with led off + pinMode(LED_BUILTIN, OUTPUT); // Configure LED pin, for test result + digitalWrite(LED_BUILTIN, LOW); // start with led off if (tested_ok == TEST_LOOP_NB) { - /* success */ - digitalWrite(LED_BUILTIN, HIGH); + /* success */ + digitalWrite(LED_BUILTIN, HIGH); } else { - /* error. Please verify MISO is externally connected to MOSI */ - digitalWrite(LED_BUILTIN, LOW); + /* error. Please verify MISO is externally connected to MOSI */ + digitalWrite(LED_BUILTIN, LOW); } } From a841002c8b472f12e7f7357e30323da981609a1f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 5 Sep 2024 15:03:33 +0200 Subject: [PATCH 06/14] chore: bump library version to 1.2.4 Signed-off-by: Frederic Pillon --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index d6ddf7f..9fdcaf3 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino Examples -version=1.2.3 +version=1.2.4 author=several maintainer=stm32duino sentence=Provides several examples for the Arduino core for STM32 MCUs. From a55074a6a4c4b279ccf875111d20082cdc18fc8c Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 21 Nov 2024 17:11:12 +0100 Subject: [PATCH 07/14] chore(hardwaretimer): update definition TIMER_DISABLED replaced by TIMER_OUTPUT_DISABLED See https://github.com/stm32duino/Arduino_Core_STM32/pull/2572 Signed-off-by: Frederic Pillon --- .../HardwareTimer_OutputInput_test.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/NonReg/HardwareTimer/HardwareTimer_OutputInput_test/HardwareTimer_OutputInput_test.ino b/examples/NonReg/HardwareTimer/HardwareTimer_OutputInput_test/HardwareTimer_OutputInput_test.ino index 12a499b..1dc20d3 100644 --- a/examples/NonReg/HardwareTimer/HardwareTimer_OutputInput_test/HardwareTimer_OutputInput_test.ino +++ b/examples/NonReg/HardwareTimer/HardwareTimer_OutputInput_test/HardwareTimer_OutputInput_test.ino @@ -453,7 +453,7 @@ void loop() test_step++; MyTim_output->pauseChannel(Output1_channel); - MyTim_output->setMode(Output1_channel, TIMER_DISABLED); + MyTim_output->setMode(Output1_channel, TIMER_OUTPUT_DISABLED); MyTim_output->resumeChannel(Output1_channel); Verify_output(1, 0, 0); // in PWM2, output is the complementary of PW1 Verify_output(2, OUTPUT_FREQUENCY, OUTPUT_DUTY2); From 33f94a16b712c74ba2f8a9666c43bf1d6be28b7b Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 22 Nov 2024 14:45:38 +0100 Subject: [PATCH 08/14] chore: update version Signed-off-by: Frederic Pillon --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 9fdcaf3..a70baf0 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino Examples -version=1.2.4 +version=1.2.5 author=several maintainer=stm32duino sentence=Provides several examples for the Arduino core for STM32 MCUs. From 523b71e95a3198d2845771132e9441e54a7f6b1c Mon Sep 17 00:00:00 2001 From: George Popa Date: Fri, 6 Jun 2025 15:54:27 +0100 Subject: [PATCH 09/14] 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 6d861cea16f6934a8d5ece8e41a253e54c7869ce Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 10 Jul 2025 14:10:17 +0200 Subject: [PATCH 10/14] chore: add STM32WB0 support to internal channel examples Signed-off-by: Frederic Pillon --- .../Internal_channels/Internal_channels.ino | 73 ++++++++++++------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino index 35644dc..73df14a 100644 --- a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino +++ b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino @@ -27,70 +27,82 @@ #endif #if defined(STM32C0xx) -#define VTEMP 760 +#define VTEMP 760 #define AVG_SLOPE 2530 -#define VREFINT 1212 +#define VREFINT 1212 #elif defined(STM32F1xx) -#define VTEMP 1430 +#define VTEMP 1430 #define AVG_SLOPE 4300 -#define VREFINT 1200 +#define VREFINT 1200 #elif defined(STM32F2xx) || defined(STM32F4xx) -#define VTEMP 760 +#define VTEMP 760 #define AVG_SLOPE 2500 -#define VREFINT 1210 +#define VREFINT 1210 #endif /* Analog read resolution */ +#if defined(LL_ADC_RESOLUTION_12B) #define LL_ADC_RESOLUTION LL_ADC_RESOLUTION_12B +#elif defined(LL_ADC_DS_DATA_WIDTH_12_BIT) +#define LL_ADC_RESOLUTION LL_ADC_DS_DATA_WIDTH_12_BIT +#else +#error "ADC resolution could not be defined!" +#endif #define ADC_RANGE 4096 // the setup routine runs once when you press reset: void setup() { // initialize serial communication at 9600 bits per second: Serial.begin(9600); - while (!Serial); + while (!Serial) + ; analogReadResolution(12); } -static int32_t readVref() -{ +#ifdef AVREF +static uint32_t readVref() { + uint32_t Vref = 3300; #ifdef STM32U0xx /* On some devices Internal voltage reference calibration value not programmed during production and return 0xFFFF. See errata sheet. */ - if ((uint32_t)(*VREFINT_CAL_ADDR) == 0xFFFF) { - return 3300U; - } + if ((uint32_t)(*VREFINT_CAL_ADDR) != 0xFFFF) { #endif #ifdef __LL_ADC_CALC_VREFANALOG_VOLTAGE #ifdef STM32U5xx - return (__LL_ADC_CALC_VREFANALOG_VOLTAGE(ADC1, analogRead(AVREF), LL_ADC_RESOLUTION)); + Vref = __LL_ADC_CALC_VREFANALOG_VOLTAGE(ADC1, analogRead(AVREF), LL_ADC_RESOLUTION); #else - return (__LL_ADC_CALC_VREFANALOG_VOLTAGE(analogRead(AVREF), LL_ADC_RESOLUTION)); + Vref = __LL_ADC_CALC_VREFANALOG_VOLTAGE(analogRead(AVREF), LL_ADC_RESOLUTION); #endif #else - return (VREFINT * ADC_RANGE / analogRead(AVREF)); // ADC sample to mV + Vref = VREFINT * ADC_RANGE / analogRead(AVREF); // ADC sample to mV +#endif +#ifdef STM32U0xx + } #endif + return Vref; } +#endif #ifdef ATEMP -static int32_t readTempSensor(int32_t VRef) -{ +static int32_t readTempSensor(int32_t VRef) { + uint32_t temp = 0; #ifdef __LL_ADC_CALC_TEMPERATURE #ifdef STM32U5xx - return (__LL_ADC_CALC_TEMPERATURE(ADC1, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION)); + temp = __LL_ADC_CALC_TEMPERATURE(ADC1, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION); +#elif defined(STM32WB0x) + (void)VRef; + temp = __LL_ADC_CALC_TEMPERATURE(analogRead(ATEMP), LL_ADC_DS_DATA_WIDTH_12_BIT); #else - return (__LL_ADC_CALC_TEMPERATURE(VRef, analogRead(ATEMP), LL_ADC_RESOLUTION)); + temp = __LL_ADC_CALC_TEMPERATURE(VRef, analogRead(ATEMP), LL_ADC_RESOLUTION); #endif #elif defined(__LL_ADC_CALC_TEMPERATURE_TYP_PARAMS) - return (__LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(AVG_SLOPE, VTEMP, CALX_TEMP, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION)); -#else - return 0; + temp = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(AVG_SLOPE, VTEMP, CALX_TEMP, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION); #endif + return temp; } #endif -static int32_t readVoltage(int32_t VRef, uint32_t pin) -{ +static int32_t readVoltage(int32_t VRef, uint32_t pin) { #ifdef STM32U5xx return (__LL_ADC_CALC_DATA_TO_VOLTAGE(ADC1, VRef, analogRead(pin), LL_ADC_RESOLUTION)); #else @@ -100,7 +112,7 @@ static int32_t readVoltage(int32_t VRef, uint32_t pin) // The loop routine runs over and over again forever: void loop() { -#if defined(ICACHE) && defined (HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) +#if defined(ICACHE) && defined(HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) bool icache_enabled = false; if (HAL_ICACHE_IsEnabled() == 1) { icache_enabled = true; @@ -110,9 +122,15 @@ void loop() { } } #endif /* ICACHE && HAL_ICACHE_MODULE_ENABLED && !HAL_ICACHE_MODULE_DISABLED */ + // Print out the value read +#ifdef AVREF int32_t VRef = readVref(); Serial.printf("VRef(mv)= %i", VRef); +#else + // No Vref fro STM32WB0xx + int32_t VRef = LL_ADC_VIN_RANGE_3V6; +#endif #ifdef ATEMP Serial.printf("\tTemp(°C)= %i", readTempSensor(VRef)); #endif @@ -121,9 +139,8 @@ void loop() { #endif Serial.printf("\tA0(mv)= %i\n", readVoltage(VRef, A0)); delay(200); -#if defined(ICACHE) && defined (HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) - if (icache_enabled) - { +#if defined(ICACHE) && defined(HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) + if (icache_enabled) { /* Re-enable instruction cache */ if (HAL_ICACHE_Enable() != HAL_OK) { Error_Handler(); From 91528def07f91008d8a83731ed9fc74e37ec9d7f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 10 Jul 2025 14:22:42 +0200 Subject: [PATCH 11/14] chore: bump version Signed-off-by: Frederic Pillon --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index a70baf0..8d175d9 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino Examples -version=1.2.5 +version=1.2.6 author=several maintainer=stm32duino sentence=Provides several examples for the Arduino core for STM32 MCUs. From 3ca29079fb4b3d8f3b7559a64b29973e3cd16668 Mon Sep 17 00:00:00 2001 From: George Popa Date: Thu, 31 Jul 2025 13:57:28 +0100 Subject: [PATCH 12/14] fix: some mistakes/typos and added 2 more flags Signed-off-by: George Popa Co-authored-by: Frederic Pillon --- .../Registers/Reset_reason/Reset_reason.ino | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino b/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino index a268188..c6e9356 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,15 +25,17 @@ 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(); @@ -69,9 +74,26 @@ void setup() { #ifdef RCC_CSR_PORRSTF if (LL_RCC_IsActiveFlag_PORRST()) last_reset_reason = (reset_reason)(last_reset_reason | POWER_ON_DOWN); #endif +#if defined(PWR_CSR_SBF) || defined(PWR_SR_SBF) || defined(PWR_SR1_SBF) || defined(PWR_CSR1_SBF) || defined(PWR_PMSR_SBF) + if (LL_PWR_IsActiveFlag_SB()) last_reset_reason = (reset_reason)(last_reset_reason | STANDBY); +#endif +#if defined(PWR_CSR_WUF) + if (LL_PWR_IsActiveFlag_WU()) last_reset_reason = (reset_reason)(last_reset_reason | WAKEUP); +#endif + // Clear reset flags LL_RCC_ClearResetFlags(); +#if defined(PWR_SCR_CSBF) || defined(PWR_CR1_CSBF) || defined(PWR_PMCR_CSSF) || defined(PWR_SR_CSSF) +#if defined(STM32U0xx) + LL_PWR_ClearFlag_CSB(); +#else + LL_PWR_ClearFlag_SB(); +#endif +#endif +#if defined(PWR_CSR_WUF) + LL_PWR_ClearFlag_WU(); +#endif } void loop() { @@ -83,10 +105,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) { From 75a8c0b3a4cfb9940e5e931fb89ad57b7fadc6bf Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 3 Sep 2025 15:51:55 +0200 Subject: [PATCH 13/14] chore: bump version Signed-off-by: Frederic Pillon --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 8d175d9..be51ffb 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino Examples -version=1.2.6 +version=1.2.7 author=several maintainer=stm32duino sentence=Provides several examples for the Arduino core for STM32 MCUs. From 9dcda4e99769b9068e93dd2f55f0a8a666260e7f Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 4 Sep 2025 11:33:22 +0100 Subject: [PATCH 14/14] Minor changes (#67) Signed-off-by: George Popa Co-authored-by: Frederic Pillon * fix: commented out potential non-included library * Update examples/Peripherals/Registers/Reset_reason/Reset_reason.ino Co-authored-by: Frederic Pillon Signed-off-by: Alex * Update examples/Peripherals/Registers/Reset_reason/Reset_reason.ino Co-authored-by: Frederic Pillon Signed-off-by: Alex * Update examples/Peripherals/Registers/Reset_reason/Reset_reason.ino Co-authored-by: Frederic Pillon Signed-off-by: Alex * Update examples/Peripherals/Registers/Reset_reason/Reset_reason.ino Co-authored-by: Frederic Pillon Signed-off-by: Alex * Update examples/Peripherals/Registers/Reset_reason/Reset_reason.ino Co-authored-by: Frederic Pillon Signed-off-by: Alex * Update examples/Peripherals/Registers/Reset_reason/Reset_reason.ino Co-authored-by: Frederic Pillon Signed-off-by: Alex --------- Signed-off-by: George Popa Signed-off-by: Alex Co-authored-by: Frederic Pillon --- .../Peripherals/Registers/Reset_reason/Reset_reason.ino | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino b/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino index c6e9356..15179d0 100644 --- a/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino +++ b/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino @@ -1,6 +1,3 @@ -#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 @@ -12,6 +9,7 @@ #include "stm32yyxx_ll_rcc.h" #include "IWatchdog.h" +// #include "STM32LowPower.h" #define USER_BTN_PIN USER_BTN // Adjust this for your board @@ -36,6 +34,9 @@ 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 WakeUp reset condition (needs STM32LowPower.h library) + // LowPower.shutdown(1000); + // Below is the Software reset condition // NVIC_SystemReset(); @@ -82,7 +83,7 @@ void setup() { #endif - // Clear reset flags + // Clear internal reset flags after they were captured LL_RCC_ClearResetFlags(); #if defined(PWR_SCR_CSBF) || defined(PWR_CR1_CSBF) || defined(PWR_PMCR_CSSF) || defined(PWR_SR_CSSF) #if defined(STM32U0xx)