From 0dd2807f3b06ad35c493028008d353148edd5ef3 Mon Sep 17 00:00:00 2001 From: Quy Tran Date: Fri, 25 Jul 2025 03:18:48 +0000 Subject: [PATCH 1/4] manifest: hal: renesas: Update commit ID for hal_renesas Update commit ID to add LVD HAL support for LVD Signed-off-by: Quy Tran --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 60cd188d65129..240c6e0803beb 100644 --- a/west.yml +++ b/west.yml @@ -226,7 +226,7 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: 0769fe1520f6c14e6301188588da758a609f181d + revision: pull/122/head groups: - hal - name: hal_rpi_pico From 93401c0a237e15ef6282bd877e81ae3b95d5d852 Mon Sep 17 00:00:00 2001 From: Quy Tran Date: Wed, 5 Feb 2025 13:28:58 +0700 Subject: [PATCH 2/4] drivers: misc: lvd: Add support for LVD driver for RX130 series Add the low-voltage detection driver support for RX130 series which run on LVDAb modules. The target is to monitor the voltage level input to Vcc/CMPA2 pin using a program Signed-off-by: Quy Tran --- drivers/misc/CMakeLists.txt | 1 + drivers/misc/Kconfig | 1 + drivers/misc/renesas_rx_lvd/CMakeLists.txt | 5 + drivers/misc/renesas_rx_lvd/Kconfig | 19 ++ drivers/misc/renesas_rx_lvd/renesas_rx_lvd.c | 206 ++++++++++++++++++ dts/bindings/misc/renesas,rx-lvd.yaml | 82 +++++++ .../misc/renesas_rx_lvd/renesas_rx_lvd.h | 67 ++++++ .../dt-bindings/pinctrl/renesas/pinctrl-rx.h | 1 + modules/Kconfig.renesas | 5 + 9 files changed, 387 insertions(+) create mode 100644 drivers/misc/renesas_rx_lvd/CMakeLists.txt create mode 100644 drivers/misc/renesas_rx_lvd/Kconfig create mode 100644 drivers/misc/renesas_rx_lvd/renesas_rx_lvd.c create mode 100644 dts/bindings/misc/renesas,rx-lvd.yaml create mode 100644 include/zephyr/drivers/misc/renesas_rx_lvd/renesas_rx_lvd.h diff --git a/drivers/misc/CMakeLists.txt b/drivers/misc/CMakeLists.txt index 437bd124247a6..6670a68864375 100644 --- a/drivers/misc/CMakeLists.txt +++ b/drivers/misc/CMakeLists.txt @@ -12,6 +12,7 @@ add_subdirectory_ifdef(CONFIG_NORDIC_VPR_LAUNCHER nordic_vpr_launcher) add_subdirectory_ifdef(CONFIG_MCUX_FLEXIO mcux_flexio) add_subdirectory_ifdef(CONFIG_RENESAS_RA_EXTERNAL_INTERRUPT renesas_ra_external_interrupt) add_subdirectory_ifdef(CONFIG_RENESAS_RX_EXTERNAL_INTERRUPT renesas_rx_external_interrupt) +add_subdirectory_ifdef(CONFIG_RENESAS_RX_LVD renesas_rx_lvd) add_subdirectory_ifdef(CONFIG_NXP_RTXXX_DSP_CTRL nxp_rtxxx_dsp_ctrl) add_subdirectory_ifdef(CONFIG_STM32N6_AXISRAM stm32n6_axisram) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 2fd046e2430cd..c64f36ea4204c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -19,6 +19,7 @@ source "drivers/misc/coresight/Kconfig" source "drivers/misc/interconn/Kconfig" source "drivers/misc/renesas_ra_external_interrupt/Kconfig" source "drivers/misc/renesas_rx_external_interrupt/Kconfig" +source "drivers/misc/renesas_rx_lvd/Kconfig" source "drivers/misc/nxp_rtxxx_dsp_ctrl/Kconfig" source "drivers/misc/stm32n6_axisram/Kconfig" diff --git a/drivers/misc/renesas_rx_lvd/CMakeLists.txt b/drivers/misc/renesas_rx_lvd/CMakeLists.txt new file mode 100644 index 0000000000000..d611a2b332d99 --- /dev/null +++ b/drivers/misc/renesas_rx_lvd/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_RENESAS_RX_LVD renesas_rx_lvd.c) diff --git a/drivers/misc/renesas_rx_lvd/Kconfig b/drivers/misc/renesas_rx_lvd/Kconfig new file mode 100644 index 0000000000000..ee723206b8e0c --- /dev/null +++ b/drivers/misc/renesas_rx_lvd/Kconfig @@ -0,0 +1,19 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Renesas RX Voltage Detection Circuit + +config RENESAS_RX_LVD + bool "Renesas RX Low-Voltage Detection Driver" + depends on DT_HAS_RENESAS_RX_LVD_ENABLED + default y + select USE_RX_RDP_LVD + select PINCTRL + help + Enable Renesas RX low voltage detection driver + +config RENESAS_RX_LVD_INIT_PRIORITY + int "RX LVD initialization priority" + default KERNEL_INIT_PRIORITY_DEVICE + help + System initialization priority for RX LVD driver. diff --git a/drivers/misc/renesas_rx_lvd/renesas_rx_lvd.c b/drivers/misc/renesas_rx_lvd/renesas_rx_lvd.c new file mode 100644 index 0000000000000..d7c53eddc820c --- /dev/null +++ b/drivers/misc/renesas_rx_lvd/renesas_rx_lvd.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rx_lvd + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(renesas_rx_lvd, CONFIG_SOC_LOG_LEVEL); + +#define LVD0_NODE DT_NODELABEL(lvd0) +#define LVD1_NODE DT_NODELABEL(lvd1) +#define LVD_NO_FUNC ((void (*)(void *))NULL) + +/* + * The extern functions below are implemented in the r_lvd_rx_hw.c source file. + * For more information, please refer to r_lvd_rx_hw.c in HAL Renesas + */ +extern void lvd_ch1_isr(void); +extern void lvd_ch2_isr(void); + +struct rx_lvd_data { + void (*callback)(void *args); + void (*user_callback)(void *user_data); + void *user_data; +}; + +struct rx_lvd_config { + lvd_channel_t channel; + lvd_config_t lvd_config; + uint8_t vdet_target; + uint8_t lvd_action; + bool lvd_support_cpma2; +}; + +int renesas_rx_pin_set_cmpa2(const struct device *dev) +{ + const struct rx_lvd_config *config = dev->config; + const struct pinctrl_dev_config *pcfg; + + if (config->channel == 0) { + if (DT_NODE_HAS_PROP(LVD0_NODE, pinctrl_0)) { + PINCTRL_DT_DEFINE(LVD0_NODE); + pcfg = PINCTRL_DT_DEV_CONFIG_GET(LVD0_NODE); + } else { + LOG_ERR("No pinctrl-0 property found in the device tree"); + return -EINVAL; + } + } else { + if (DT_NODE_HAS_PROP(LVD1_NODE, pinctrl_0)) { + PINCTRL_DT_DEFINE(LVD1_NODE); + pcfg = PINCTRL_DT_DEV_CONFIG_GET(LVD1_NODE); + } else { + LOG_ERR("No pinctrl_0 property found in the device tree"); + return -EINVAL; + } + } + + /* In the case of monitoring the CMPA2 pin, set the CMPA2 pin. */ + /* This only applicable to channel 1 with the LVDb driver */ + int ret = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); + + if (ret < 0) { + LOG_ERR("Failed to apply pinctrl state: %d\n", ret); + return -EINVAL; + } + + return 0; +} + +int renesas_rx_lvd_get_status(const struct device *dev, lvd_status_position_t *status_position, + lvd_status_cross_t *status_cross) +{ + const struct rx_lvd_config *config = dev->config; + int ret; + + ret = R_LVD_GetStatus(config->channel, status_position, status_cross); + if (ret != 0) { + LOG_ERR("Failed to get LVD status"); + return -EINVAL; + } + + return ret; +} + +int renesas_rx_lvd_clear_status(const struct device *dev) +{ + const struct rx_lvd_config *config = dev->config; + int ret; + + ret = R_LVD_ClearStatus(config->channel); + if (ret != 0) { + LOG_ERR("Failed to clear LVD status"); + return -EINVAL; + } + + return ret; +} + +int renesas_rx_lvd_register_callback(const struct device *dev, void (*callback)(void *), + void *user_data) +{ + struct rx_lvd_data *data = dev->data; + + data->user_callback = callback; + data->user_data = user_data; + + return 0; +} + +#define LVD_IRQ_CONNECT() \ + do { \ + IF_ENABLED(DT_NODE_HAS_STATUS_OKAY(LVD0_NODE), ( \ + IRQ_CONNECT(DT_IRQN(LVD0_NODE), \ + DT_IRQ(LVD0_NODE, priority), \ + lvd_ch1_isr, \ + DEVICE_DT_GET(LVD0_NODE), \ + 0); \ + irq_enable(DT_IRQN(LVD0_NODE)); \ + )) \ + IF_ENABLED(DT_NODE_HAS_STATUS_OKAY(LVD1_NODE), ( \ + IRQ_CONNECT(DT_IRQN(LVD1_NODE), \ + DT_IRQ(LVD1_NODE, priority), \ + lvd_ch2_isr, \ + DEVICE_DT_GET(LVD1_NODE), \ + 0); \ + irq_enable(DT_IRQN(LVD1_NODE)); \ + )) \ + } while (0) + +static int renesas_rx_lvd_init(const struct device *dev) +{ + lvd_err_t ret; + + LVD_IRQ_CONNECT(); + + const struct rx_lvd_config *config = dev->config; + const struct rx_lvd_data *data = dev->data; + + /* In reset or no-action when LVD is detected, callback will not be triggered. */ + ret = R_LVD_Open(config->channel, &config->lvd_config, data->callback); + if (ret != 0) { + LOG_ERR("Failed to initialize LVD channel %d", config->channel); + return -EIO; + } + + /* Set the CMPA2 pin if the target is CMPA2 */ + /* NOTE: For the RX130 series, CMPA2 is only used on channel 2. */ + if ((config->lvd_support_cpma2) && (config->vdet_target == 1)) { + return renesas_rx_pin_set_cmpa2(dev); + } + + return 0; +} + +#define RENESAS_RX_LVD_INIT(index) \ + \ + static const struct rx_lvd_config rx_lvd_config_##index = { \ + .channel = DT_INST_PROP(index, channel), \ + .lvd_config = \ + { \ + .trigger = DT_INST_PROP(index, lvd_trigger), \ + }, \ + .lvd_action = DT_INST_PROP(index, lvd_action), \ + .vdet_target = DT_INST_PROP(index, vdet_target), \ + .lvd_support_cpma2 = DT_INST_PROP(index, renesas_lvd_external_target), \ + }; \ + \ + void rx_lvd_callback_##index(void *args) \ + { \ + ARG_UNUSED(args); \ + const struct device *dev = DEVICE_DT_GET(DT_INST(index, renesas_rx_lvd)); \ + struct rx_lvd_data *data = dev->data; \ + \ + /* Call the user's callback function*/ \ + if (data->user_callback) { \ + data->user_callback(data->user_data); \ + } \ + }; \ + \ + static struct rx_lvd_data rx_lvd_data_##index = { \ + .callback = rx_lvd_callback_##index, \ + }; \ + \ + static int renesas_rx_lvd_init_##index(const struct device *dev) \ + { \ + int err = renesas_rx_lvd_init(dev); \ + if (err != 0) { \ + return err; \ + } \ + return 0; \ + } \ + \ + DEVICE_DT_INST_DEFINE(index, renesas_rx_lvd_init_##index, NULL, &rx_lvd_data_##index, \ + &rx_lvd_config_##index, PRE_KERNEL_1, \ + CONFIG_RENESAS_RX_LVD_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(RENESAS_RX_LVD_INIT) diff --git a/dts/bindings/misc/renesas,rx-lvd.yaml b/dts/bindings/misc/renesas,rx-lvd.yaml new file mode 100644 index 0000000000000..4fb5f127b5e3a --- /dev/null +++ b/dts/bindings/misc/renesas,rx-lvd.yaml @@ -0,0 +1,82 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RX LVD driver + +compatible: "renesas,rx-lvd" + +include: [base.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + channel: + type: int + description: RX LVD channel + + lvd-action: + required: true + type: int + enum: [0, 1, 2, 3] + description: | + Choose the action to be taken when the LVD is detected. + - 0: Reset + - 1: Non-maskable interrupt + - 2: Maskable interrupt + - 3: No action + + voltage-level: + required: true + type: int + description: | + Specifies the voltage detection level for each channel, set an integer + value which expresses the number up to two decimal places. + Example: + - To set the voltage detection level to 3.00 V, specify '300'. + - To set the voltage detection level to default value, specify '0xFFFF' + For specific voltage detection support levels of each RX MCU series, + please refer to the HWM. + + renesas,lvd-external-target: + type: boolean + description: | + Specifies whether the RX LVD driver supports CMPA2 pin as target. + Note: For RX130 series, CMPA2 pin is available only for channel 1. + + vdet-target: + required: true + type: int + enum: [0, 1] + description: | + Specifies the target to be monitored for each channel. + Note: For RX130 series, CMPA2 pin is available only for channel 1. + - 0: VCC + - 1: CMPA2 pin + + lvd-trigger: + required: true + type: int + enum: [0, 1, 2] + description: | + Specifies the voltage detection conditions and influences interrupt conditions + - 0: LVD_TRIGGER_RISE + - 1: LVD_TRIGGER_FALL + - 2: LVD_TRIGGER_BOTH + + lvd-stabilization: + type: int + enum: [0, 1] + description: | + Specifies the reset negation timing for each channel, with reset selected as processing. + - 0: After a LVD reset, negation occurs when a certain period elapses after the + monitored voltage goes above the voltage detection level. + - 1: Negation occurs when a certain period elapses after the LVD reset assertion. + Note: "a certain period" here means a wait time after a voltage monitoring reset. + Refer to the User's Manual: Hardware for details. + + pinctrl-0: + description: Pin control for LVD when using CMPA2 pin as target + + pinctrl-names: + description: Pin control names for LVD when using CMPA2 pin as target diff --git a/include/zephyr/drivers/misc/renesas_rx_lvd/renesas_rx_lvd.h b/include/zephyr/drivers/misc/renesas_rx_lvd/renesas_rx_lvd.h new file mode 100644 index 0000000000000..41aeaf02befcb --- /dev/null +++ b/include/zephyr/drivers/misc/renesas_rx_lvd/renesas_rx_lvd.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_MISC_RENESAS_RX_LVD_H_ +#define ZEPHYR_DRIVERS_MISC_RENESAS_RX_LVD_H_ + +#include "r_lvd_rx_if.h" + +/** + * @brief Get the current status of the LVD (Low Voltage Detection) circuit. + * + * This function retrieves the current voltage status from the LVD module, + * including the position of the voltage level relative to the threshold, + * and whether the voltage has crossed the threshold. + * @param[in] dev LVD device instance. + * @param[out] status_position Pointer to store the LVD status position. + * @param[out] status_cross Pointer to store the LVD status cross. + * + * @retval 0 On success. + * @retval -EINVAL On failure. + */ +int renesas_rx_lvd_get_status(const struct device *dev, lvd_status_position_t *status_position, + lvd_status_cross_t *status_cross); + +/** + * @brief Clear the current status of the LVD (Low Voltage Detection) circuit. + * + * This function clears the current voltage status from the LVD module. + * @param[in] dev LVD device instance. + * + * @retval 0 On success. + * @retval -EINVAL On failure. + */ +int renesas_rx_lvd_clear_status(const struct device *dev); + +/** + * @brief Register a callback function for LVD status changes. + * + * This function registers a callback function that will be called when the + * LVD status changes. This applicable only if the LVD action is set to + * trigger an interrupt on status change. + * @param[in] dev LVD device instance. + * @param[in] callback Pointer to the callback function. + * @param[in] user_data Pointer to user data that will be passed to the callback. + * + * @retval 0 On success. + * @retval -EINVAL On failure. + */ +int renesas_rx_lvd_register_callback(const struct device *dev, void (*callback)(void *), + void *user_data); + +/** + * @brief Set pin for CMPA2 if the target is CMPA2. + * + * This function sets the pin configuration for CMPA2 if the target + * device is CMPA2. + * @param[in] dev LVD device instance. + * + * @retval 0 On success. + * @retval -EINVAL On failure. + */ +int renesas_rx_pin_set_cmpa2(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_MISC_RENESAS_RX_LVD_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-rx.h b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-rx.h index 35547c608f6e4..17abf0520ceee 100644 --- a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-rx.h +++ b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-rx.h @@ -20,6 +20,7 @@ #define RX_PSEL_SCI_6 0xB #define RX_PSEL_TMR 0x5 #define RX_PSEL_POE 0x7 +#define RX_PSEL_LVD 0x0 /* P0nPFS */ #define RX_PSEL_P0nPFS_HIZ 0x0 diff --git a/modules/Kconfig.renesas b/modules/Kconfig.renesas index 12a898e2d8e8c..e8a9149207494 100644 --- a/modules/Kconfig.renesas +++ b/modules/Kconfig.renesas @@ -304,4 +304,9 @@ config USE_RX_RDP_I2C help Enable RX RDP I2C driver +config USE_RX_RDP_LVD + bool + help + Enable RX RDP LVD driver + endif # HAS_RENESAS_RX_RDP From 260602b941ede4d34677f2333eca9195bd55016b Mon Sep 17 00:00:00 2001 From: Quy Tran Date: Wed, 5 Feb 2025 13:36:33 +0700 Subject: [PATCH 3/4] dts: renesas: rx: Add dts property node for lvd Add lvd dts node for channel 1 and 2 of LVD driver Signed-off-by: Quy Tran --- dts/rx/renesas/rx130-common.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dts/rx/renesas/rx130-common.dtsi b/dts/rx/renesas/rx130-common.dtsi index cfba992cde784..89178138bbb91 100644 --- a/dts/rx/renesas/rx130-common.dtsi +++ b/dts/rx/renesas/rx130-common.dtsi @@ -811,6 +811,25 @@ status = "disabled"; }; + lvd0: lvd@800e0 { + compatible = "renesas,rx-lvd"; + reg = <0x000800E0 0x02>; + channel = <0>; + interrupts = <88 1>; + interrupt-names = "lvd"; + status = "disabled"; + }; + + lvd1: lvd@800e2 { + compatible = "renesas,rx-lvd"; + reg = <0x000800E2 0x02>; + channel = <1>; + interrupts = <89 1>; + interrupt-names = "lvd"; + renesas,lvd-external-target; + status = "disabled"; + }; + ofsm: ofsm@ffffff80 { compatible = "zephyr,memory-region"; reg = <0xFFFFFF80 0x0F>; From c11e903105880260003ac3ce21ef3ea941ca29b8 Mon Sep 17 00:00:00 2001 From: Quy Tran Date: Thu, 6 Feb 2025 13:59:04 +0700 Subject: [PATCH 4/4] samples: boards: renesas: Add sample for RX LVD driver Add a simple sample for LVD driver on RSK-RX130-512kb Signed-off-by: Quy Tran --- samples/boards/renesas/lvd/CMakeLists.txt | 10 ++ samples/boards/renesas/lvd/README.rst | 69 +++++++++ .../lvd/boards/rsk_rx130_512kb.overlay | 26 ++++ samples/boards/renesas/lvd/prj.conf | 1 + samples/boards/renesas/lvd/sample.yaml | 8 ++ samples/boards/renesas/lvd/src/main.c | 136 ++++++++++++++++++ 6 files changed, 250 insertions(+) create mode 100644 samples/boards/renesas/lvd/CMakeLists.txt create mode 100644 samples/boards/renesas/lvd/README.rst create mode 100644 samples/boards/renesas/lvd/boards/rsk_rx130_512kb.overlay create mode 100644 samples/boards/renesas/lvd/prj.conf create mode 100644 samples/boards/renesas/lvd/sample.yaml create mode 100644 samples/boards/renesas/lvd/src/main.c diff --git a/samples/boards/renesas/lvd/CMakeLists.txt b/samples/boards/renesas/lvd/CMakeLists.txt new file mode 100644 index 0000000000000..d867843a7a0b4 --- /dev/null +++ b/samples/boards/renesas/lvd/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(lvd) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/renesas/lvd/README.rst b/samples/boards/renesas/lvd/README.rst new file mode 100644 index 0000000000000..dcdf854f2f0a8 --- /dev/null +++ b/samples/boards/renesas/lvd/README.rst @@ -0,0 +1,69 @@ +.. zephyr:code-sample:: renesas-lvd + :name: Renesas Low-voltage Detection Sample + + Demonstrates monitoring and reacting to voltage levels. + +Overview +******** + +This sample application shows how to use the Renesas Low-voltage Detection (LVD) +driver in Zephyr to monitor supply voltage and indicate status via LEDs. +The app reads the voltage status, handles LVD interrupts, and updates +LEDs based on whether the voltage is above or below a configured threshold. + +Features +******** + +- Reads voltage status from the LVD peripheral. +- Handles LVD interrupts (if enabled in device tree/config). +- Indicates voltage status using two LEDs: + - LED_ABOVE: On when voltage is above threshold. + - LED_BELOW: On when voltage is below threshold. +- Prints status messages to the console. + +Hardware Setup +************** + +- Ensure that the monitored target pin is supplied with power. + +Building and Running +******************** + +To build and flash the sample on a supported Renesas RX board: + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/renesas/lvd + :board: rsk_rx130@512kb + :goals: build flash + :compact: + +Usage +***** + +- On startup, the app prints the configured voltage threshold. +- The app continuously monitors the voltage: + - If voltage is **above** the threshold, LED_ABOVE is turned on, LED_BELOW is off. + - If voltage is **below** the threshold, LED_BELOW is turned on, LED_ABOVE is off. +- If LVD interrupt is enabled, voltage changes will trigger an interrupt and update the + status immediately. + +Customization +************* + +- You can change the voltage threshold and LVD action via device tree properties. +- LED pins can be reassigned by modifying the ``led0`` and ``led1`` aliases in your + board's DTS. + +Example Output +************** + +:: + + =========================================================== + LVD Voltage Monitoring Sample Started + Threshold Voltage Level : 384 mV + =========================================================== + [LVD Init] Voltage is ABOVE threshold (384 mV) + [LVD] Interrupt: Voltage level crossing detected! + [WARNING] Voltage instability detected! Check power supply. + [LVD] Voltage is BELOW threshold (384 mV) diff --git a/samples/boards/renesas/lvd/boards/rsk_rx130_512kb.overlay b/samples/boards/renesas/lvd/boards/rsk_rx130_512kb.overlay new file mode 100644 index 0000000000000..aa23eeecd1d0b --- /dev/null +++ b/samples/boards/renesas/lvd/boards/rsk_rx130_512kb.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + lvd1_default: lvd1_default { + group1 { + /* CMPA2 */ + psels = ; + renesas,analog-enable; + input-enable; + }; + }; +}; + +&lvd1 { + pinctrl-0 = <&lvd1_default>; + pinctrl-names = "default"; + lvd-action = <2>; + voltage-level = <384>; + vdet-target = <1>; /* CMPA2 */ + lvd-trigger = <2>; /* LVD_TRIGGER_BOTH */ + lvd-stabilization = <0>; + status = "okay"; +}; diff --git a/samples/boards/renesas/lvd/prj.conf b/samples/boards/renesas/lvd/prj.conf new file mode 100644 index 0000000000000..1e935e973c761 --- /dev/null +++ b/samples/boards/renesas/lvd/prj.conf @@ -0,0 +1 @@ +CONFIG_LOG=y diff --git a/samples/boards/renesas/lvd/sample.yaml b/samples/boards/renesas/lvd/sample.yaml new file mode 100644 index 0000000000000..0ec46240e8c3d --- /dev/null +++ b/samples/boards/renesas/lvd/sample.yaml @@ -0,0 +1,8 @@ +sample: + name: Low Voltage Detector (LVD) +tests: + sample.boards.renesas.lvd: + build_only: true + platform_allow: + - rsk_rx130@512kb + tags: lvd diff --git a/samples/boards/renesas/lvd/src/main.c b/samples/boards/renesas/lvd/src/main.c new file mode 100644 index 0000000000000..a404b7e1d7092 --- /dev/null +++ b/samples/boards/renesas/lvd/src/main.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Local Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* LVD node & config from Device Tree */ +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rx_lvd) +#define LVD_NODE DT_INST(0, renesas_rx_lvd) +#endif + +#define LVD_ACTION DT_PROP(LVD_NODE, lvd_action) +#define VOLTAGE_THRESHOLD DT_PROP(LVD_NODE, voltage_level) + +/* GPIO LEDs */ +#define LED_BELOW_NODE DT_ALIAS(led0) +#define LED_ABOVE_NODE DT_ALIAS(led1) + +static const struct gpio_dt_spec led_below = GPIO_DT_SPEC_GET(LED_BELOW_NODE, gpios); +static const struct gpio_dt_spec led_above = GPIO_DT_SPEC_GET(LED_ABOVE_NODE, gpios); + +/* Semaphore for LVD interrupt */ +static struct k_sem lvd_sem; + +#if LVD_ACTION == 2 +#define LVD_INT 1 +#else +#define LVD_INT 0 +#endif + +#if LVD_INT +void user_callback(void *user_data) +{ + ARG_UNUSED(user_data); + printk("[LVD] Interrupt: Voltage level crossing detected!\n"); + printk("[WARNING] Voltage instability detected! Check power supply.\n"); + k_sem_give(&lvd_sem); +} +#endif + +/* Handle voltage status: get, print, update LEDs */ +static void handle_voltage_status(const struct device *lvd_dev, const char *tag) +{ + int ret; + lvd_status_position_t position; + lvd_status_cross_t cross; + + ret = renesas_rx_lvd_get_status(lvd_dev, &position, &cross); + if (ret != 0) { + printk("[%s] Error: Failed to get LVD status.\n", tag); + return; + } + + switch (position) { + case LVD_STATUS_POSITION_ABOVE: + printk("[%s] Voltage is ABOVE threshold (%d mV)\n", tag, VOLTAGE_THRESHOLD); + gpio_pin_set_dt(&led_above, 1); + gpio_pin_set_dt(&led_below, 0); + break; + case LVD_STATUS_POSITION_BELOW: + printk("[%s] Voltage is BELOW threshold (%d mV)\n", tag, VOLTAGE_THRESHOLD); + gpio_pin_set_dt(&led_below, 1); + gpio_pin_set_dt(&led_above, 0); + break; + default: + printk("[%s] Unknown voltage position\n", tag); + break; + } + + ret = renesas_rx_lvd_clear_status(lvd_dev); + if (ret != 0) { + printk("[%s] Warning: Failed to clear LVD status\n", tag); + } +} + +int main(void) +{ + int ret; + const struct device *const lvd_dev = DEVICE_DT_GET(LVD_NODE); + + k_sem_init(&lvd_sem, 0, 1); + + if (!device_is_ready(lvd_dev)) { + printk("[LVD] Error: LVD device not ready.\n"); + return -EINVAL; + } + +#if LVD_INT + ret = renesas_rx_lvd_register_callback(lvd_dev, user_callback, NULL); + if (ret != 0) { + printk("[LVD] Error: Failed to register callback.\n"); + return -EINVAL; + } +#endif + + if (!gpio_is_ready_dt(&led_below) || !gpio_is_ready_dt(&led_above)) { + printk("[GPIO] Error: LED GPIOs not ready.\n"); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&led_below, GPIO_OUTPUT_ACTIVE); + if (ret < 0) { + return ret; + } + + ret = gpio_pin_configure_dt(&led_above, GPIO_OUTPUT_ACTIVE); + if (ret < 0) { + return ret; + } + + printk("===========================================================\n"); + printk("LVD Voltage Monitoring Sample Started\n"); + printk("Threshold Voltage Level : %d mV\n", VOLTAGE_THRESHOLD); + printk("===========================================================\n"); + + handle_voltage_status(lvd_dev, "LVD Init"); + + while (1) { + k_sem_take(&lvd_sem, K_FOREVER); + handle_voltage_status(lvd_dev, "LVD"); + } + + return 0; +}