• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdio.h>
17 #include <errno.h>
18 #include "duet_cm4.h"
19 #include "duet.h"
20 #include "duet_wdg.h"
21 #ifdef ALIOS_SUPPORT
22 #include "lega_rhino.h"
23 #else
24 #include "lega_rtos.h"
25 #endif
26 // WDG APB CLOCK 0-15 BIT 4-7
27 #define APB_DIV_1   0
28 #define APB_DIV_2   1
29 #define APB_DIV_3   2
30 #define APB_DIV_4   3
31 #define APB_DIV_5   4
32 #define APB_DIV_6   5
33 #define APB_DIV_7   6
34 #define APB_DIV_8   7
35 #define APB_DIV_9   8
36 #define APB_DIV_10  9
37 #define APB_DIV_11  10
38 #define APB_DIV_12  11
39 #define APB_DIV_13  12
40 #define APB_DIV_14  13
41 #define APB_DIV_15  14
42 #define APB_DIV_16  15
43 #define WDG_APB_DIV APB_DIV_1
44 #define WDG_APB_DIV_REG 0X40000854
45 
hw_watchdog_unlock(void)46 void hw_watchdog_unlock(void)
47 {
48     WATCHDOG->LOCK = WDG_LOCK_TOKEN;
49 }
50 
hw_watchdog_lock(void)51 void hw_watchdog_lock(void)
52 {
53     WATCHDOG->LOCK = ~(WDG_LOCK_TOKEN);
54 }
55 
hw_watchdog_disable(void)56 void hw_watchdog_disable(void)
57 {
58     hw_watchdog_unlock();
59     WATCHDOG->CONTROL = 0x0;
60     WATCHDOG->LOAD = 0xffffffff;
61     hw_watchdog_lock();
62 }
63 
hw_watchdog_isr(unsigned int delay)64 void hw_watchdog_isr(unsigned int delay)
65 {
66     hw_watchdog_unlock();
67     WATCHDOG->CONTROL = WDG_INTEN;
68     WATCHDOG->LOAD = delay;
69     hw_watchdog_lock();
70 }
71 
hw_watchdog_reset(unsigned int delay)72 void hw_watchdog_reset(unsigned int delay)
73 {
74     hw_watchdog_unlock();
75     WATCHDOG->CONTROL = WDG_RESEN | WDG_INTEN;
76     WATCHDOG->LOAD = delay;
77     hw_watchdog_lock();
78 }
79 
hw_watchdog_isr_clr(void)80 void hw_watchdog_isr_clr(void)
81 {
82     hw_watchdog_unlock();
83     WATCHDOG->INTCLR = 0x1;
84     hw_watchdog_lock();
85 }
86 
WDG_IRQHandler(void)87 void WDG_IRQHandler(void)
88 {
89     duet_intrpt_enter();
90     NVIC_DisableIRQ(WDG_IRQn);
91     duet_intrpt_exit();
92 }
93 
94 /**
95  * This function will initialize the on board CPU hardware watch dog
96  *
97  * @param[in]  wdg  the watch dog device
98  *
99  * @return  0 : on success, EIO : if an error occurred with any step
100  */
duet_wdg_init(duet_wdg_dev_t * wdg)101 int32_t duet_wdg_init(duet_wdg_dev_t *wdg)
102 {
103     uint32_t reg_value;
104     if (NULL == wdg) {
105         return EIO;
106     }
107     if (0 == wdg->port) {
108         // OPEN WDG CLOCK
109         reg_value = REG_RD(PERI_CLK_EN_REG1) & (~WDG_BUS_CLK_BIT);
110         REG_WR(PERI_CLK_EN_REG1, (reg_value | (WDG_BUS_CLK_BIT)));
111         // WDG CLOCK DIV SET
112         reg_value = REG_RD(WDG_APB_DIV_REG);
113         REG_WR(WDG_APB_DIV_REG, (reg_value | (WDG_APB_DIV << 4)));
114         hw_watchdog_reset(wdg->config.timeout * (SYSTEM_CLOCK / (WDG_APB_DIV + 1) / 1000 /
115                           2)); // 1000 for ms, 2 for watchdog feature
116         // ENABLE WDG IRQ
117         reg_value = REG_RD(DUTE_IRQ_EN_REG) & (~WDG_IRQ_BIT);
118         REG_WR(DUTE_IRQ_EN_REG, (reg_value | (WDG_IRQ_BIT)));
119         NVIC_EnableIRQ(WDG_IRQn);
120         return 0;
121     } else {
122         return EIO;
123     }
124 }
125 
126 /**
127  * Reload watchdog counter.
128  *
129  * @param[in]  wdg  the watch dog device
130  */
duet_wdg_reload(duet_wdg_dev_t * wdg)131 void duet_wdg_reload(duet_wdg_dev_t *wdg)
132 {
133     if (NULL == wdg) {
134         return;
135     }
136     if (0 == wdg->port) {
137         lega_rtos_declare_critical();
138         lega_rtos_enter_critical();
139         hw_watchdog_isr_clr();
140         NVIC_ClearPendingIRQ(WDG_IRQn);
141         NVIC_EnableIRQ(WDG_IRQn);
142         lega_rtos_exit_critical();
143     }
144 }
145 
146 /**
147  * This function performs any platform-specific cleanup needed for hardware watch dog.
148  *
149  * @param[in]  wdg  the watch dog device
150  *
151  * @return  0 : on success, EIO : if an error occurred with any step
152  */
duet_wdg_finalize(duet_wdg_dev_t * wdg)153 int32_t duet_wdg_finalize(duet_wdg_dev_t *wdg)
154 {
155     uint32_t reg_value;
156     if (NULL == wdg) {
157         return EIO;
158     }
159     if (0 == wdg->port) {
160         // DIS WDG IRQ
161         reg_value = REG_RD(DUTE_IRQ_DIS_REG) & (~WDG_IRQ_BIT);
162         REG_WR(DUTE_IRQ_DIS_REG, (reg_value | (WDG_IRQ_BIT)));
163         NVIC_DisableIRQ(WDG_IRQn);
164         hw_watchdog_disable();
165         // Set WDG Clock Disable
166         reg_value = REG_RD(PERI_CLK_DIS_REG1) & (~WDG_BUS_CLK_BIT);
167         REG_WR(PERI_CLK_DIS_REG1, (reg_value | (WDG_BUS_CLK_BIT)));
168         return 0;
169     } else {
170         return EIO;
171     }
172 }
173 
174