stm32l: add watchdog support

Use the Independant WatchDog.
The Window WatchDog would provide a nice early warning interrupt before
actually rebooting but the max period (128 ms) is probably too short for
our purpose.

The full GPIO support and the reboot cause detection will be implemented
in later steps.

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>

BUG=None
TEST=on Discovery board, do blocking waits of 500ms and 1500ms, and
check the latter reboots the platform and the former does not.

Change-Id: I26e4d8b26b733269b7811cc3b3a09daf98ea364a
This commit is contained in:
Vincent Palatin
2012-02-02 17:00:53 +00:00
parent a0d1a9e80e
commit f771cca719
5 changed files with 92 additions and 0 deletions

View File

@@ -20,6 +20,9 @@ void configure_board(void)
(0x7 << 12) | (0x7 << 8);
STM32L_GPIO_MODER(B) = (STM32L_GPIO_MODER(B) & ~0x00F00000) |
0x00A00000;
/* Green and blue LEDs : configure port 6 and 7 as output */
STM32L_GPIO_MODER(B) |= (1 << (7 * 2)) | (1 << (6 * 2));
}
/**
@@ -28,6 +31,9 @@ void configure_board(void)
*/
int jtag_pre_init(void)
{
/* stop TIM2, TIM3 and watchdogs when the JTAG stops the CPU */
STM32L_DBGMCU_APB1FZ |= 0x00001803;
return EC_SUCCESS;
}

View File

@@ -14,4 +14,5 @@
* 'd' in an opaque parameter passed to the routine at startup
*/
#define CONFIG_TASK_LIST \
TASK(WATCHDOG, watchdog_task, NULL) \
TASK(CONSOLE, console_task, NULL)

View File

@@ -9,3 +9,4 @@
CORE:=cortex-m
chip-y=uart.o clock.o hwtimer.o system.o
chip-$(CONFIG_TASK_WATCHDOG)+=watchdog.o

View File

@@ -221,6 +221,15 @@
#define STM32L_RTC_TAFCR REG32(STM32L_RTC_BASE + 0x40)
#define STM32L_RTC_BACKUP(n) REG32(STM32L_RTC_BASE + 0x50 + 4 * (n))
/* --- Debug --- */
#define STM32L_DBGMCU_BASE 0xE0042000
#define STM32L_DBGMCU_IDCODE REG32(STM32L_DBGMCU_BASE + 0x00)
#define STM32L_DBGMCU_CR REG32(STM32L_DBGMCU_BASE + 0x04)
#define STM32L_DBGMCU_APB1FZ REG32(STM32L_DBGMCU_BASE + 0x08)
#define STM32L_DBGMCU_APB2FZ REG32(STM32L_DBGMCU_BASE + 0x0C)
/* --- MISC --- */
#define STM32L_RI_BASE 0x40007C04

75
chip/stm32l/watchdog.c Normal file
View File

@@ -0,0 +1,75 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Watchdog driver */
#include <stdint.h>
#include "board.h"
#include "common.h"
#include "config.h"
#include "registers.h"
#include "gpio.h"
#include "task.h"
#include "timer.h"
#include "uart.h"
#include "util.h"
/* LSI oscillator frequency is typically 38 kHz
* but might vary from 28 to 56kHz.
* So let's pick 56kHz to ensure we reload
* early enough.
*/
#define LSI_CLOCK 56000
/* Prescaler divider = /256 */
#define IWDG_PRESCALER 6
#define IWDG_PRESCALER_DIV (1 << ((IWDG_PRESCALER) + 2))
void watchdog_reload(void)
{
/* Reload the watchdog */
STM32L_IWDG_KR = 0xaaaa;
}
int watchdog_init(int period_ms)
{
uint32_t watchdog_period;
/* set the time-out period */
watchdog_period = period_ms * (LSI_CLOCK / IWDG_PRESCALER_DIV) / 1000;
/* Unlock watchdog registers */
STM32L_IWDG_KR = 0x5555;
/* Set the prescaler between the LSI clock and the watchdog counter */
STM32L_IWDG_PR = IWDG_PRESCALER & 7;
/* Set the reload value of the watchdog counter */
STM32L_IWDG_RLR = watchdog_period & 0x7FF ;
/* Start the watchdog (and re-lock registers) */
STM32L_IWDG_KR = 0xcccc;
return EC_SUCCESS;
}
/* Low priority task to reload the watchdog */
void watchdog_task(void)
{
while (1) {
#ifdef BOARD_discovery
/* TODO use GPIO API: gpio_set_level(GPIO_GREEN_LED, 1); */
STM32L_GPIO_ODR(B) |= (1 << 7) ;
#endif
usleep(500000);
watchdog_reload();
#ifdef BOARD_discovery
/* TODO use GPIO API: gpio_set_level(GPIO_GREEN_LED, 0); */
STM32L_GPIO_ODR(B) &= ~(1 << 7) ;
#endif
usleep(500000);
watchdog_reload();
}
}