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. */ 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 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 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 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 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 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