1 /*
2 * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <nrfx.h>
33
34 #if NRFX_CHECK(NRFX_WDT_ENABLED)
35 #include <nrfx_wdt.h>
36
37 #define NRFX_LOG_MODULE WDT
38 #include <nrfx_log.h>
39
40 /**@brief WDT state. */
41 static nrfx_drv_state_t m_state;
42
43 /**@brief WDT alloc table. */
44 static uint8_t m_alloc_index;
45
46 #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
47 /**@brief WDT event handler. */
48 static nrfx_wdt_event_handler_t m_wdt_event_handler;
49
50 /**@brief WDT interrupt handler. */
nrfx_wdt_irq_handler(void)51 void nrfx_wdt_irq_handler(void)
52 {
53 if (nrf_wdt_event_check(NRF_WDT_EVENT_TIMEOUT))
54 {
55 m_wdt_event_handler();
56 nrf_wdt_event_clear(NRF_WDT_EVENT_TIMEOUT);
57 }
58 }
59 #endif
60
61
nrfx_wdt_init(nrfx_wdt_config_t const * p_config,nrfx_wdt_event_handler_t wdt_event_handler)62 nrfx_err_t nrfx_wdt_init(nrfx_wdt_config_t const * p_config,
63 nrfx_wdt_event_handler_t wdt_event_handler)
64 {
65 NRFX_ASSERT(p_config);
66 nrfx_err_t err_code;
67
68 #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
69 NRFX_ASSERT(wdt_event_handler != NULL);
70 m_wdt_event_handler = wdt_event_handler;
71 #else
72 NRFX_ASSERT(wdt_event_handler == NULL);
73 (void)wdt_event_handler;
74 #endif
75 if (m_state == NRFX_DRV_STATE_UNINITIALIZED)
76 {
77 m_state = NRFX_DRV_STATE_INITIALIZED;
78 }
79 else
80 {
81 err_code = NRFX_ERROR_INVALID_STATE;
82 NRFX_LOG_WARNING("Function: %s, error code: %s.",
83 __func__,
84 NRFX_LOG_ERROR_STRING_GET(err_code));
85 return err_code;
86 }
87
88 nrf_wdt_behaviour_set(p_config->behaviour);
89
90 nrf_wdt_reload_value_set((p_config->reload_value * 32768) / 1000);
91
92 #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
93 NRFX_IRQ_PRIORITY_SET(WDT_IRQn, p_config->interrupt_priority);
94 NRFX_IRQ_ENABLE(WDT_IRQn);
95 #endif
96
97 err_code = NRFX_SUCCESS;
98 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
99 return err_code;
100 }
101
102
nrfx_wdt_enable(void)103 void nrfx_wdt_enable(void)
104 {
105 NRFX_ASSERT(m_alloc_index != 0);
106 NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
107 #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
108 nrf_wdt_int_enable(NRF_WDT_INT_TIMEOUT_MASK);
109 #endif
110 nrf_wdt_task_trigger(NRF_WDT_TASK_START);
111 m_state = NRFX_DRV_STATE_POWERED_ON;
112 NRFX_LOG_INFO("Enabled.");
113 }
114
115
nrfx_wdt_feed(void)116 void nrfx_wdt_feed(void)
117 {
118 NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
119 for (uint8_t i = 0; i < m_alloc_index; i++)
120 {
121 nrf_wdt_reload_request_set((nrf_wdt_rr_register_t)(NRF_WDT_RR0 + i));
122 }
123 }
124
nrfx_wdt_channel_alloc(nrfx_wdt_channel_id * p_channel_id)125 nrfx_err_t nrfx_wdt_channel_alloc(nrfx_wdt_channel_id * p_channel_id)
126 {
127 nrfx_err_t result;
128 NRFX_ASSERT(p_channel_id);
129 NRFX_ASSERT(m_state == NRFX_DRV_STATE_INITIALIZED);
130
131 NRFX_CRITICAL_SECTION_ENTER();
132 if (m_alloc_index < NRF_WDT_CHANNEL_NUMBER)
133 {
134 *p_channel_id = (nrfx_wdt_channel_id)(NRF_WDT_RR0 + m_alloc_index);
135 m_alloc_index++;
136 nrf_wdt_reload_request_enable(*p_channel_id);
137 result = NRFX_SUCCESS;
138 }
139 else
140 {
141 result = NRFX_ERROR_NO_MEM;
142 }
143 NRFX_CRITICAL_SECTION_EXIT();
144 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(result));
145 return result;
146 }
147
nrfx_wdt_channel_feed(nrfx_wdt_channel_id channel_id)148 void nrfx_wdt_channel_feed(nrfx_wdt_channel_id channel_id)
149 {
150 NRFX_ASSERT(m_state == NRFX_DRV_STATE_POWERED_ON);
151 nrf_wdt_reload_request_set(channel_id);
152 }
153
154 #endif // NRFX_CHECK(NRFX_WDT_ENABLED)
155