Skip to content

Enable IWDG module for Nucleo-64 F446RE board. #234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
245e5be
Enable IWDG module for Nucleo-64 F446RE board. Not sure why it was not
ghent360 Apr 2, 2018
f5ca1bc
Revert the HAL modification.
ghent360 Apr 4, 2018
ac814fe
Add Watchdog library to expose the IWDG component.
ghent360 Apr 4, 2018
0b67ea7
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Apr 10, 2018
5e89c28
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Apr 20, 2018
0e3471a
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Apr 25, 2018
4e1e865
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Apr 27, 2018
c337725
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 May 3, 2018
446c9d4
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 May 8, 2018
fa7b449
[DISCO_F746NG] Use HSE instead of HSE ByPass
fpistm May 11, 2018
a71ed8d
[CM7] Enable I-Cache and D-Cache
fpistm May 11, 2018
1ff1e3e
[RTC] Make some arguments optional (part 2)
fpistm May 11, 2018
fb628c3
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 May 12, 2018
fa0dbfa
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 May 13, 2018
28c63c3
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 May 20, 2018
cd7bdc9
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 May 22, 2018
e84adb3
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 May 26, 2018
4d40743
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 May 29, 2018
f61f749
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 May 31, 2018
7d30e34
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Jun 4, 2018
826a7f9
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Jun 13, 2018
11a2c44
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Jun 16, 2018
b50097b
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Jul 5, 2018
c044cf4
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Jul 18, 2018
d85964a
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Jul 26, 2018
011c80c
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Jul 30, 2018
00c3dbe
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Aug 1, 2018
8e02dd9
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Aug 2, 2018
32ad156
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Aug 5, 2018
fd648e3
Merge branch 'master' of https://github.com/stm32duino/Arduino_Core_S…
ghent360 Aug 7, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions cores/arduino/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,10 @@ void initVariant() { }
#ifdef NVIC_PRIORITYGROUP_4
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
#endif
#if (__CORTEX_M == 0x07U)
#if (__CORTEX_M == 0x07U) && !defined(UNUSED_ID_CACHE)
// Defined in CMSIS core_cm7.h
#ifndef I_CACHE_DISABLED
SCB_EnableICache();
#endif
#ifndef D_CACHE_DISABLED
SCB_EnableDCache();
#endif
#endif

init();
Expand Down
2 changes: 1 addition & 1 deletion cores/arduino/stm32/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
return;
break;
}
obj->irqHandleOC(obj, channel);
obj->irqHandleOC(obj, channel);
}
}

Expand Down
81 changes: 81 additions & 0 deletions libraries/Watchdog/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
## **Watchdog Library V1.0** for Arduino

**Written by:** _Venelin Efremov_.

### **What is the Watchdog library.**

Th Watchdog library provides an interface to the independent watchdog module (IWDG) inside STM32 chips.
The IWDG module is used in production systems to generate a reset signal to the CPU in case some
catastrophic event in causes the software to become "stuck" or unresponsive.

The IWDG module contains a count-down timer. The module would generate a reset condition when the timer reaches zero. In normal operation mode the software running on the CPU would reload the timer periodically to
prevent the reset condition from happening. However if a software bug or other error causes the CPU to execute a different code path for too long, the reload would not happen and the IWDG module would reset the CPU.

### **How to use it**
The Watchdog library is included with the STM32 core download. To add its functionality to your sketch you'll need to reference the library header file. You do this by adding an include directive to the top of your sketch.

```Arduino
#include <Watchdog.h>

void setup() {
...
// Initialize the IWDG with 4 seconds timeout.
// This would cause a CPU reset if the IWDG timer
// is not reloaded in approximately 4 seconds.
watchdog_init(4000);
}

void loop() {
...your code here...
// make sure the code in this loop is executed in
// less than 2 seconds to leave 50% headroom for
// the timer reload.
watchdog_reset();
}

```

### **Library functions**

#### **`watchdog_init(uint16_t timeout_ms)`**

The `watchdog_init()` function would initialize the IWDG hardware block.

The timeout_ms parameter would set the timer reset timeout. When the
timer reaches zero the hardware block would generate a reset signal
for the CPU.

When specifying timeout value plan to refresh the timer at least twice
as often. The `watchdog_reset()` operation is not expensive.

The downside of slecting a very large timeout value is that your system
may be left in a "stuck" state for too long, before the reset is
generated.

Valid timeout values are between 1ms and 32,768ms (~32.8 seconds). For
values above 4095 the timeout paramater starts to loose precision:

| timeout value range | timeout value precision |
| ------------------- |:-----------------------:|
| 1 - 4096 | 1ms
| 4097 - 8192 | 2ms
| 8193 - 16384 | 4ms
| 16385 - 32768 | 8ms

Calling the `watchdog_init()` method with value outside of the valid range
would return without initializing the watchdog timer.

**WARNING:**
*Once started the watchdog timer can not be stopped. If you are
planning to debug the live system, the watchdog timer may cause the
system to be reset while you are stopped in the debugger. Also consider
the watchdog timer implications if you are designing a system which puts
the CPU in sleep mode.*

#### **`watchdog_reset()`**

The `watchdog_reset()` function would reset the watchdog timer.

Once you have initialized the watchdog you **HAVE** to call `watchdog_reset()`
periodically to prevent the CPU being reset.

34 changes: 34 additions & 0 deletions libraries/Watchdog/Watchdog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "Watchdog.h"

static IWDG_HandleTypeDef hiwdg;

void watchdog_init(uint16_t timeout_ms) {
if (timeout_ms == 0 || timeout_ms > 32768) {
return;
}
hiwdg.Instance = IWDG;
// Compute the prescaler value. Start with 32 which gives 1ms precision.
hiwdg.Init.Prescaler = IWDG_PRESCALER_32;
timeout_ms--;
if (timeout_ms > 4095) {
// 2ms precision
hiwdg.Init.Prescaler = IWDG_PRESCALER_64;
timeout_ms >>= 1;
}
if (timeout_ms > 4095) {
// 4ms precision
hiwdg.Init.Prescaler = IWDG_PRESCALER_128;
timeout_ms >>= 1;
}
if (timeout_ms > 4095) {
// 8ms precision
hiwdg.Init.Prescaler = IWDG_PRESCALER_256;
timeout_ms >>= 1;
}
hiwdg.Init.Reload = timeout_ms;
HAL_IWDG_Init(&hiwdg);
}

void watchdog_reset() {
HAL_IWDG_Refresh(&hiwdg);
}
66 changes: 66 additions & 0 deletions libraries/Watchdog/Watchdog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#ifndef __WATCHDOG_STM32_H__
#define __WATCHDOG_STM32_H__

#include "Arduino.h"
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
* To enable the IWDG HAL component used by this library you must add a
* file named build_opt.h to your sketch with the following content:
*
* -DHAL_IWDG_MODULE_ENABLED
*
* Include the dash (-) in front of DHAL_IWDG_MODULE_ENABLED
*/

/*
* The watchdog_init function would initialize the IWDG hardware block.
*
* The timeout_ms parameter would set the timer reset timeout. When the
* timer reaches zero the hardware block would generate a reset signal
* for the CPU.
*
* When specifying timeout value plan to refresh the timer at least twice
* as often. The reset operation is not very expensive.
*
* The downside of slecting a very large timeout value is that your system
* may be left in a "stuck" state for too long, before the reset is
* generated.
*
* Valid timeout values are between 1ms and 32,768ms (~32.8 seconds). For
* values above 4095 the timeout paramater starts to loose precision:
*
* timeout value range | timeout value precision
* 00001-04096 | 1ms
* 04097-08192 | 2ms
* 08193-16384 | 4ms
* 16385-32768 | 8ms
*
* Calling the watchdog_init method with value outside of the valid range
* would return without initializing the watchdog timer.
*
* WARNING: Once started the watchdog timer can not be stopped. If you are
* planning to debug the live system, the watchdog timer may cause the
* system to be reset while you are stopped in the debugger. Also consider
* the watchdog timer implications if you are designing a system which puts
* the CPU in sleep mode.
*
*/
void watchdog_init(uint16_t timeout_ms);

/*
* The watchdog_reset() function would reset the watchdog timer. Once you
* have initialized the watchdog you HAVE to call watchdog_reset()
* periodically to prevent the CPU being reset.
*/
void watchdog_reset();

#ifdef __cplusplus
}
#endif

#endif // __WATCHDOG_STM32_H__
55 changes: 55 additions & 0 deletions libraries/Watchdog/examples/Button/Button.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Watchdog + Button

This example code is in the public domain.

The code demonstrates the use of a watchdog timer. The watchdog timer is
initialized with timeout of 10 seconds. Every time the button is pressed,
the watchdog timer is reset. If left unattended the system would reset
itself about every 10 seconds.

You would have to keep pressing the button frequently (< 10 seoncds apart)
to prevent the system from reseting itself.

You would recongnize the reset condition when the LED blinks rapidly a
few times.

This is not a practical example, in real code you would reset the watchdog
timer in the main loop without requiring user input.

The code is modified version of the code from:
http://www.arduino.cc/en/Tutorial/Button
*/

#include <Watchdog.h>

const int buttonPin = USER_BTN;
const int ledPin = LED_BUILTIN;

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);

// Blink the LED to indicate reset.
for(uint8_t idx = 0; idx < 5; idx++) {
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
delay(100);
}
// Init the watchdog timer with 10 seconds timeout
watchdog_init(10000);
}

void loop() {
// read the state of the pushbutton value:
int buttonState = digitalRead(buttonPin);

if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
// Reset the watchdog only when the button is pressed.
watchdog_reset();
}
}
1 change: 1 addition & 0 deletions libraries/Watchdog/examples/Button/build_opt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-DHAL_IWDG_MODULE_ENABLED
20 changes: 20 additions & 0 deletions libraries/Watchdog/keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#######################################
# Syntax Coloring Map For Watchdog
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################


#######################################
# Methods and Functions (KEYWORD2)
#######################################

watchdog_init KEYWORD2
watchdog_reset KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################

9 changes: 9 additions & 0 deletions libraries/Watchdog/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=Watchdog
version=1.0
author=Arduino, Venelin Efremov
maintainer=stm32duino
sentence=Enables support for independent watchdog hardware on STM32 processors.
paragraph=Independent watchdog (IWDG) is a hardware timer on the chip which would generate a reset condition if the times is not reloaded withing the specified time. It is genrally used in production systems to reset the system if the CPU becomes "stuck".
category=Timing
url=
architectures=stm32
8 changes: 4 additions & 4 deletions variants/DISCO_F746NG/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,14 @@ WEAK void SystemClock_Config(void)

PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC|RCC_PERIPHCLK_USART1
|RCC_PERIPHCLK_CLK48;
PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
PeriphClkInitStruct.PLLSAI.PLLSAIR = 5;
PeriphClkInitStruct.PLLSAI.PLLSAIN = 100;
PeriphClkInitStruct.PLLSAI.PLLSAIR = 2;
PeriphClkInitStruct.PLLSAI.PLLSAIQ = 2;
PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV4;
PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV2;
PeriphClkInitStruct.PLLSAIDivQ = 1;
PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_4;
PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48SOURCE_PLLSAIP;
PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48SOURCE_PLL;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
Expand Down