1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-29 22:24:26 +00:00

add watchdog

This commit is contained in:
Tomasz Duda
2024-01-14 17:56:51 +01:00
parent c40d07d377
commit 89121938ad
4 changed files with 209 additions and 2 deletions

View File

@@ -84,3 +84,6 @@ async def to_code(config):
cg.add_platformio_option("board_upload.use_1200bps_touch", "true")
cg.add_platformio_option("board_upload.require_upload_port", "true")
cg.add_platformio_option("board_upload.wait_for_upload_port", "true")
cg.add_build_flag("-DNRFX_WDT_ENABLED=1")
cg.add_build_flag("-DNRFX_WDT0_ENABLED=1")
cg.add_build_flag("-DNRFX_WDT_CONFIG_NO_IRQ=1")

View File

@@ -2,6 +2,7 @@
#include <Arduino.h>
#include "Adafruit_nRFCrypto.h"
#include "nrfx_wdt.h"
namespace esphome {
@@ -10,8 +11,24 @@ uint32_t millis() { return ::millis(); }
void delay(uint32_t ms) { ::delay(ms); }
uint32_t micros() { return ::micros(); }
struct nrf5x_wdt_obj
{
nrfx_wdt_t wdt;
nrfx_wdt_channel_id ch;
};
static nrfx_wdt_config_t nrf5x_wdt_cfg = NRFX_WDT_DEFAULT_CONFIG;
static struct nrf5x_wdt_obj nrf5x_wdt = {
.wdt = NRFX_WDT_INSTANCE(0),
};
void arch_init() {
nRFCrypto.begin();
//Configure WDT.
nrfx_wdt_init(&nrf5x_wdt.wdt, &nrf5x_wdt_cfg, nullptr);
nrfx_wdt_channel_alloc(&nrf5x_wdt.wdt, &nrf5x_wdt.ch);
nrfx_wdt_enable(&nrf5x_wdt.wdt);
nRFCrypto.begin();
// Init random seed
union seedParts {
uint32_t seed32;
@@ -21,7 +38,9 @@ void arch_init() {
randomSeed(seed.seed32);
}
void arch_feed_wdt() { /* TODO */ }
void arch_feed_wdt() {
nrfx_wdt_feed(&nrf5x_wdt.wdt);
}
void arch_restart() { /* TODO */ }

View File

@@ -1,3 +1,7 @@
#pragma once
namespace esphome {
void nrf52GetMacAddr(uint8_t *mac);
}

View File

@@ -0,0 +1,181 @@
/*
* Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <nrfx.h>
#if NRFX_CHECK(NRFX_WDT_ENABLED)
#if !(NRFX_CHECK(NRFX_WDT0_ENABLED) || NRFX_CHECK(NRFX_WDT1_ENABLED))
#error "No enabled WDT instances. Check <nrfx_config.h>."
#endif
#include <nrfx_wdt.h>
#define NRFX_LOG_MODULE WDT
#include <nrfx_log.h>
// Control block - driver instance local data.
typedef struct
{
nrfx_drv_state_t state;
uint8_t alloc_index;
#if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
nrfx_wdt_event_handler_t wdt_event_handler;
#endif
} wdt_control_block_t;
static wdt_control_block_t m_cb[NRFX_WDT_ENABLED_COUNT];
nrfx_err_t nrfx_wdt_init(nrfx_wdt_t const * p_instance,
nrfx_wdt_config_t const * p_config,
nrfx_wdt_event_handler_t wdt_event_handler)
{
NRFX_ASSERT(p_config);
nrfx_err_t err_code;
wdt_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
#if NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
(void)wdt_event_handler;
#else
p_cb->wdt_event_handler = wdt_event_handler;
#endif
if (p_cb->state == NRFX_DRV_STATE_UNINITIALIZED)
{
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
}
else
{
err_code = NRFX_ERROR_INVALID_STATE;
NRFX_LOG_WARNING("Function: %s, error code: %s.",
__func__,
NRFX_LOG_ERROR_STRING_GET(err_code));
return err_code;
}
nrf_wdt_behaviour_set(p_instance->p_reg, p_config->behaviour);
uint64_t ticks = (p_config->reload_value * 32768ULL) / 1000;
NRFX_ASSERT(ticks <= UINT32_MAX);
nrf_wdt_reload_value_set(p_instance->p_reg, (uint32_t) ticks);
#if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
if (wdt_event_handler)
{
nrf_wdt_int_enable(p_instance->p_reg, NRF_WDT_INT_TIMEOUT_MASK);
NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg), p_config->interrupt_priority);
NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
}
#endif
err_code = NRFX_SUCCESS;
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
return err_code;
}
void nrfx_wdt_enable(nrfx_wdt_t const * p_instance)
{
wdt_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
NRFX_ASSERT(p_cb->alloc_index != 0);
NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
nrf_wdt_task_trigger(p_instance->p_reg, NRF_WDT_TASK_START);
p_cb->state = NRFX_DRV_STATE_POWERED_ON;
NRFX_LOG_INFO("Enabled.");
}
void nrfx_wdt_feed(nrfx_wdt_t const * p_instance)
{
wdt_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
for (uint8_t i = 0; i < p_cb->alloc_index; i++)
{
nrf_wdt_reload_request_set(p_instance->p_reg, (nrf_wdt_rr_register_t)(NRF_WDT_RR0 + i));
}
}
nrfx_err_t nrfx_wdt_channel_alloc(nrfx_wdt_t const * p_instance, nrfx_wdt_channel_id * p_channel_id)
{
nrfx_err_t result;
wdt_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
NRFX_ASSERT(p_channel_id);
NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
NRFX_CRITICAL_SECTION_ENTER();
if (p_cb->alloc_index < NRF_WDT_CHANNEL_NUMBER)
{
*p_channel_id = (nrfx_wdt_channel_id)(NRF_WDT_RR0 + p_cb->alloc_index);
p_cb->alloc_index++;
nrf_wdt_reload_request_enable(p_instance->p_reg, *p_channel_id);
result = NRFX_SUCCESS;
}
else
{
result = NRFX_ERROR_NO_MEM;
}
NRFX_CRITICAL_SECTION_EXIT();
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(result));
return result;
}
void nrfx_wdt_channel_feed(nrfx_wdt_t const * p_instance, nrfx_wdt_channel_id channel_id)
{
NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_POWERED_ON);
nrf_wdt_reload_request_set(p_instance->p_reg, channel_id);
}
#if NRFX_CHECK(NRFX_WDT0_ENABLED) && !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
void nrfx_wdt_0_irq_handler(void)
{
if (nrf_wdt_event_check(NRF_WDT0, NRF_WDT_EVENT_TIMEOUT))
{
m_cb[NRFX_WDT0_INST_IDX].wdt_event_handler();
nrf_wdt_event_clear(NRF_WDT0, NRF_WDT_EVENT_TIMEOUT);
}
}
#endif
#if NRFX_CHECK(NRFX_WDT1_ENABLED) && !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
void nrfx_wdt_1_irq_handler(void)
{
if (nrf_wdt_event_check(NRF_WDT1, NRF_WDT_EVENT_TIMEOUT))
{
m_cb[NRFX_WDT1_INST_IDX].wdt_event_handler();
nrf_wdt_event_clear(NRF_WDT1, NRF_WDT_EVENT_TIMEOUT);
}
}
#endif
#endif // NRFX_CHECK(NRFX_WDT_ENABLED)