Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/rx/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ zephyr_library_sources(
isr_exit.S
fatal.c
reboot.c
nmi.c
)

zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c)
113 changes: 113 additions & 0 deletions arch/rx/core/nmi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2025 Renesas Electronics Corporation
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/sw_isr_table.h>
#include <zephyr/irq.h>
#include <kswap.h>
#include <zephyr/tracing/tracing.h>
#include <zephyr/arch/rx/sw_nmi_table.h>

#define NMI_NMIST_MASK 0x01
#define NMI_OSTST_MASK 0x02
#define NMI_IWDTST_MASK 0x08
#define NMI_LVD1ST_MASK 0x10
#define NMI_LVD2ST_MASK 0x20

#define NMIER_BASE_ADDRESS DT_REG_ADDR_BY_NAME(DT_NODELABEL(icu), NMIER)
#define NMISR_BASE_ADDRESS DT_REG_ADDR_BY_NAME(DT_NODELABEL(icu), NMISR)
#define NMICLR_BASE_ADDRESS DT_REG_ADDR_BY_NAME(DT_NODELABEL(icu), NMICLR)
#define REG(addr) *((uint8_t *)(addr))

struct nmi_vector_entry _nmi_vector_table[NMI_TABLE_SIZE] = {
{(nmi_callback_t)0xFFFFFFFFU, (void *)0xFFFFFFFFU}, /* NMI Pin Interrupt */
{(nmi_callback_t)0xFFFFFFFFU,
(void *)0xFFFFFFFFU}, /* Oscillation Stop Detection Interrupt */
{(nmi_callback_t)0xFFFFFFFFU, (void *)0xFFFFFFFFU}, /* IWDT Underflow/Refresh Error */
{(nmi_callback_t)0xFFFFFFFFU, (void *)0xFFFFFFFFU}, /* Voltage Monitoring 1 Interrupt */
{(nmi_callback_t)0xFFFFFFFFU, (void *)0xFFFFFFFFU}, /* Voltage Monitoring 2 Interrupt */
};

void nmi_enable(uint8_t nmi_vector, nmi_callback_t callback, void *arg)
{
if (nmi_vector >= NMI_TABLE_SIZE) {
return;
}

_nmi_vector_table[nmi_vector].callback = callback;
_nmi_vector_table[nmi_vector].arg = arg;

switch (nmi_vector) {
/* NMI Pin Interrupt */
case 0:
REG(NMIER_BASE_ADDRESS) |= (1 << 0);
break;
/* Oscillation Stop Detection Interrupt */
case 1:
REG(NMIER_BASE_ADDRESS) |= (1 << 1);
break;
/* IWDT Underflow/Refresh Error */
case 2:
REG(NMIER_BASE_ADDRESS) |= (1 << 3);
break;
/* Voltage Monitoring 1 Interrupt */
case 3:
REG(NMIER_BASE_ADDRESS) |= (1 << 4);
break;
/* Voltage Monitoring 2 Interrupt */
case 4:
REG(NMIER_BASE_ADDRESS) |= (1 << 5);
break;
default:
break;
}
}

int get_nmi_request(void)
{
uint8_t nmi_status = REG(NMISR_BASE_ADDRESS);

if (nmi_status & NMI_NMIST_MASK) {
return 0;
} else if (nmi_status & NMI_OSTST_MASK) {
return 1;
} else if (nmi_status & NMI_IWDTST_MASK) {
return 2;
} else if (nmi_status & NMI_LVD1ST_MASK) {
return 3;
} else if (nmi_status & NMI_LVD2ST_MASK) {
return 4;
}

return NMI_TABLE_SIZE;
}

void handle_nmi(uint8_t nmi_vector)
{
if (nmi_vector >= NMI_TABLE_SIZE) {
return;
}

_nmi_vector_table[nmi_vector].callback(_nmi_vector_table[nmi_vector].arg);

switch (nmi_vector) {
case 0:
REG(NMICLR_BASE_ADDRESS) |= (1 << 0);
break;
case 1:
REG(NMICLR_BASE_ADDRESS) |= (1 << 1);
break;
case 2:
REG(NMICLR_BASE_ADDRESS) |= (1 << 3);
break;
case 3:
REG(NMICLR_BASE_ADDRESS) |= (1 << 4);
break;
case 4:
REG(NMICLR_BASE_ADDRESS) |= (1 << 5);
break;
default:
break;
}
}
43 changes: 23 additions & 20 deletions arch/rx/core/vects.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
#include <zephyr/irq.h>
#include <kswap.h>
#include <zephyr/tracing/tracing.h>
#include <zephyr/drivers/clock_control/renesas_rx_cgc.h>
#include <zephyr/arch/rx/sw_nmi_table.h>
#ifndef CONFIG_SOC_SERIES_RX62N
#include <ofsm.h>
#endif

typedef void (*fp)(void);
extern void _start(void);
Expand All @@ -19,20 +22,22 @@ extern void z_rx_irq_exit(void);
#define CONFIG_GEN_IRQ_START_VECTOR 0
#endif

#ifndef SOC_RX_MDE
#define SOC_RX_MDE (0xFFFFFFFFUL)
#endif
#ifndef SOC_RX_OFS0
#define SOC_RX_OFS0 (0xFFFFFFFFUL)
#endif
#ifndef SOC_RX_OFS1
#define SOC_RX_OFS1 (0xFFFFFFFFUL)
#endif

#define EXVECT_SECT __attribute__((section(".exvectors")))
#define RVECT_SECT __attribute__((section(".rvectors")))
#define FVECT_SECT __attribute__((section(".fvectors")))

#define __ISR__ __attribute__((interrupt, naked))

#define SET_OFS1_HOCO_BITS(reg, freq) \
((reg) & ~(0b11 << 12)) | ((((freq) == 24000000 ? 0b10 \
: (freq) == 32000000 ? 0b11 \
: (freq) == 48000000 ? 0b01 \
: (freq) == 64000000 ? 0b00 \
: 0b11) \
<< 12))

static ALWAYS_INLINE void REGISTER_SAVE(void)
{
__asm volatile(
Expand Down Expand Up @@ -106,9 +111,9 @@ static void __ISR__ INT_Excep_FloatingPoint(void)
static void __ISR__ INT_NonMaskableInterrupt(void)
{
REGISTER_SAVE();
ISR_DIRECT_HEADER();
z_fatal_error(K_ERR_CPU_EXCEPTION, NULL);
ISR_DIRECT_FOOTER(1);
int nmi_vector = get_nmi_request();

handle_nmi(nmi_vector);
REGISTER_RESTORE_EXIT();
}

Expand Down Expand Up @@ -430,12 +435,10 @@ INT_DEMUX(255);
const void *FixedVectors[] FVECT_SECT = {
/* 0x00-0x4c: Reserved, must be 0xff (according to e2 studio example) */
/* Reserved for OFSM */
(fp)SOC_RX_MDE,
(fp)0xFFFFFFFF,
(fp)0xFFFFFFFF,
(fp)(SET_OFS1_HOCO_BITS(
0xFFFFFFFF,
(RX_CGC_PROP_HAS_STATUS_OKAY_OR(DT_NODELABEL(hoco), clock_frequency, 32000000)))),
(fp)0xFFFFFFFF,
(fp)SOC_RX_OFS1,
(fp)SOC_RX_OFS0,
/* Reserved area */
(fp)0xFFFFFFFF,
(fp)0xFFFFFFFF,
Expand Down Expand Up @@ -490,10 +493,10 @@ const FVECT_SECT void *resetVector = _start;
*/
const void *ExceptVectors[] EXVECT_SECT = {
/* 0x00-0x4c: Reserved, must be 0xff (according to e2 studio example) */
(fp)SOC_RX_MDE,
(fp)0xFFFFFFFF,
(fp)0xFFFFFFFF,
(fp)0xFFFFFFFF,
(fp)0xFFFFFFFF,
(fp)SOC_RX_OFS1,
(fp)SOC_RX_OFS0,
(fp)0xFFFFFFFF,
(fp)0xFFFFFFFF,
(fp)0xFFFFFFFF,
Expand Down
11 changes: 11 additions & 0 deletions boards/renesas/rsk_rx130/rsk_rx130.dts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
led0 = &led1;
led1 = &led3;
sw0 = &sw1;
watchdog0 = &iwdt;
};
};

Expand All @@ -72,6 +73,10 @@
status = "okay";
};

&iwdtlsclk {
status = "okay";
};

&cmt {
clock-frequency = <4000000>;
status = "okay";
Expand Down Expand Up @@ -145,3 +150,9 @@
pinctrl-names = "default";
status = "okay";
};

&iwdt {
window-start = <0x3000>;
window-end = <0x0300>;
status = "okay";
};
1 change: 1 addition & 0 deletions drivers/watchdog/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_ANDES_ATCWDT200 wdt_andes_atcwdt200.c)
zephyr_library_sources_ifdef(CONFIG_WDT_NXP_FS26 wdt_nxp_fs26.c)
zephyr_library_sources_ifdef(CONFIG_WDT_SHELL wdt_shell.c)
zephyr_library_sources_ifdef(CONFIG_WDT_RENESAS_RA wdt_renesas_ra.c)
zephyr_library_sources_ifdef(CONFIG_WDT_RENESAS_RX_IWDT wdt_renesas_rx_iwdt.c)
zephyr_library_sources_ifdef(CONFIG_WDT_NXP_EWM wdt_nxp_ewm.c)

zephyr_library_sources_ifdef(CONFIG_WDT_TI_RTI wdt_ti_rti.c)
Expand Down
2 changes: 2 additions & 0 deletions drivers/watchdog/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ source "drivers/watchdog/Kconfig.rts5912"

source "drivers/watchdog/Kconfig.renesas_ra"

source "drivers/watchdog/Kconfig.renesas_rx"

source "drivers/watchdog/Kconfig.wch"

source "drivers/watchdog/Kconfig.nxp_ewm"
Expand Down
41 changes: 41 additions & 0 deletions drivers/watchdog/Kconfig.renesas_rx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Renesas RX Watchdog configuration

# Copyright (c) 2025 Renesas Electronics Corporation
# SPDX-License-Identifier: Apache-2.0

config WDT_RENESAS_RX_IWDT
bool "Renesas RX Series Independent Watchdog Driver"
default y
depends on DT_HAS_RENESAS_RX_IWDT_ENABLED
select HAS_WDT_DISABLE_AT_BOOT if WDT_RENESAS_RX_IWDT_REGISTER_START_MODE
select USE_RX_RDP_IWDT
help
Enable Renesas RX series watchdog driver.

if WDT_RENESAS_RX_IWDT

config WDT_RENESAS_RX_IWDT_USE_NMI
bool "Non-maskable interrupt for IWDT"
default y
help
Enable NMI for IWDT.

choice
prompt "IWDT Start Mode"
default WDT_RENESAS_RX_IWDT_REGISTER_START_MODE
help
Select the IWDT start mode.
- WDT_RENESAS_RX_IWDT_AUTO_START_MODE: Counting automatically starts after a reset
(auto-start mode), controlled by option function select register 0 (OFS0).
- WDT_RENESAS_RX_IWDT_REGISTER_START_MODE: Counting is started by refreshing the counter.
(controlled by the IWDT registers)

config WDT_RENESAS_RX_IWDT_AUTO_START_MODE
bool "Start IWDT automatically on reset"

config WDT_RENESAS_RX_IWDT_REGISTER_START_MODE
bool "IWDT Start Mode Select"

endchoice

endif # WDT_RENESAS_RX_IWDT
Loading