| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <plat/pwr.h> |
| #include <plat/wdt.h> |
| #include <plat/cmsis.h> |
| |
| struct StmDbgmcu { |
| volatile uint32_t IDCODE; |
| volatile uint32_t CR; |
| volatile uint32_t APB1FZ; |
| volatile uint32_t APB2FZ; |
| }; |
| |
| struct StmWwdg { |
| volatile uint16_t CR; |
| uint8_t unused0[2]; |
| volatile uint16_t CFR; |
| uint8_t unused1[2]; |
| volatile uint16_t SR; |
| uint8_t unused2[2]; |
| }; |
| |
| #define DBGMCU ((struct StmDbgmcu*)DBGMCU_BASE) |
| #define WWDG ((struct StmWwdg*)WWDG_BASE) |
| |
| /* DBGMCU bit definitions */ |
| #define DBG_WWDG_STOP 0x00000800U |
| |
| /* WWDG bit definitions */ |
| #define WWDG_CR_ENABLE 0x80 |
| |
| #define WWDG_TCNT_HIGH 0x40 |
| #define WWDG_TCNT_MASK 0x3F |
| |
| #define WWDG_CFR_DIV2 0x0080 |
| #define WWDG_CFR_DIV4 0x0100 |
| #define WWDG_CFR_DIV8 0x0180 |
| #define WWDG_CFR_EWI 0x0200 |
| |
| /* WWDG parameters */ |
| #define WWDG_WINDOW_SIZE 0x3F // 0 < x <= 0x3F |
| |
| void WWDG_IRQHandler(void); |
| void __attribute__((naked)) WWDG_IRQHandler(void) |
| { |
| asm volatile( |
| "mov r0, #2 \n" |
| "b cpuCommonFaultCode \n" |
| ); |
| } |
| |
| void wdtEnableClk() |
| { |
| pwrUnitClock(PERIPH_BUS_APB1, PERIPH_APB1_WWDG, true); |
| } |
| |
| void wdtEnableIrq() |
| { |
| NVIC_EnableIRQ(WWDG_IRQn); |
| } |
| |
| void wdtDisableClk() |
| { |
| pwrUnitClock(PERIPH_BUS_APB1, PERIPH_APB1_WWDG, false); |
| } |
| |
| void wdtDisableIrq() |
| { |
| NVIC_DisableIRQ(WWDG_IRQn); |
| } |
| |
| void wdtInit() |
| { |
| #if defined(DEBUG) && defined(DEBUG_SWD) |
| // Disable WWDG if core is halted |
| DBGMCU->APB1FZ |= DBG_WWDG_STOP; |
| #endif |
| |
| wdtEnableClk(); |
| WWDG->CFR = WWDG_CFR_EWI | WWDG_CFR_DIV8 | WWDG_TCNT_HIGH | (WWDG_WINDOW_SIZE & WWDG_TCNT_MASK); |
| WWDG->CR = WWDG_CR_ENABLE | WWDG_TCNT_HIGH | (WWDG_WINDOW_SIZE & WWDG_TCNT_MASK); |
| // with 16Mhz APB1 clock, this is 256*DIV = 2,048 uS per WWDG tick with DIV=8, max 131,072 uS WWDG window |
| wdtEnableIrq(); |
| } |
| |
| void wdtPing() |
| { |
| WWDG->CR = (WWDG->CR & ~WWDG_TCNT_MASK) | WWDG_TCNT_HIGH | (WWDG_WINDOW_SIZE & WWDG_TCNT_MASK); |
| } |