MPSL Assert 107,291 and 107,301

Hello,

I'm developing my custom sensor application. It's a matter over thread device. Before final product I'm working on a NRF52840 DK PCA 100056 v3.0.1 and NCS 3.02. It has uart1 in async mode for a sensor and I2c for another sensor and a gpio input. The sensor using uart is async. Other sensor whic is using I2c doesn't have an interrupt. Added both classes. The error log is below. I'm 107,291 one sometimes. 107,301 happens when using mutex in a thread on the call to

k_mutex_lock(&g_sensor_data_mutex, K_FOREVER);
Can you tell me what is the reason for this MPSL assert 107.291 and 107,301?

/* Copyright (c) 2021 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

/ {
	/*
	 * In some default configurations within the nRF Connect SDK,
	 * e.g. on nRF52840, the chosen zephyr,entropy node is &cryptocell.
	 * This devicetree overlay ensures that default is overridden wherever it
	 * is set, as this application uses the RNG node for entropy exclusively.
	 */
	chosen {
		zephyr,entropy = &rng;
        nordic,pm-ext-flash = &mx25r64;
        zephyr,console = &uart0;
	};

	aliases {
        ld2410-uart = &uart1;
        // Alias for Button 4 (SW4) for commissioning
        // Alias for the BH1750 sensor
        bh1750-sensor = &bh1750;
        // New: Alias for the LD2410C OUT pin, now referencing the new node
        //sw0 = &button0;
    };

    buttons {
            compatible = "gpio-keys";
            button4: button_4 {
                label = "LD2410_Presence_OUT"; // Add a label for clarity and debugging

                // Reference the GPIO controller (&gpio0) explicitly, followed by pin number and flags.
                // P0.28 is pin 28 on port 0.
                // GPIO_INPUT (0x01) | GPIO_PULL_UP (0x08) = 0x09
                gpios = <&gpio1 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
                zephyr,code = <INPUT_KEY_4>;
            }; 
    };

    // New: Define the LD2410C OUT pin as a direct GPIO input with pull-up
    // Moved outside of &gpio0 to enable correct DT_ALIAS and GPIO_DT_SPEC_GET usage.
    // Use 'gpio-keys' compatible for generic digital inputs for robust parsing.
    // ld2410_presence_gpio_node: ld2410_presence_gpio_node {
    //     compatible = "gpio-keys"; // Using gpio-keys to define a generic input
    //     status = "okay";
    //     label = "LD2410_Presence_OUT"; // Add a label for clarity and debugging

    //     // Reference the GPIO controller (&gpio0) explicitly, followed by pin number and flags.
    //     // P0.28 is pin 28 on port 0.
    //     // GPIO_INPUT (0x01) | GPIO_PULL_UP (0x08) = 0x09
    //     gpios = <&gpio0 28 (GPIO_PULL_UP)>;
    // };
};

// Configure UART1 for LD2410C using pinctrl
// IMPORTANT: These pin numbers (P1.10 and P1.11) are examples.
// Consult nRF52840 DK schematics and nRF52840 datasheet to choose
// available and appropriate pins for UART1 on your board.
&uart1 {
	compatible = "nordic,nrf-uarte";
	current-speed = <230400>;
	status = "okay";
	pinctrl-0 = <&uart1_default>;
	pinctrl-1 = <&uart1_sleep>;
	pinctrl-names = "default", "sleep";
};

// Configure I2C0 bus for BH1750 sensor using pinctrl
// IMPORTANT: Replace with your actual SDA/SCL pins for I2C0.
// Common choices include P0.26 (SCL) and P0.27 (SDA) on nRF52840 DK.
&i2c0 {
	status = "okay";
	clock-frequency = <I2C_BITRATE_FAST>; // Fast mode (400kHz)
	pinctrl-0 = <&i2c0_default>; // Reference to the pinctrl configuration for I2C0

	// BH1750 sensor node
	bh1750: bh1750@23 { // Default I2C address for BH1750 (0x23 or 0x5C)
		compatible = "rohm,bh1750";
		reg = <0x23>; // Verify this I2C address with your specific BH1750 module
		label = "BH1750 Illuminance Sensor";
		// Optionally add measurement interval if the driver supports it
		// measurement-interval-ms = <1000>;
	};
};

// Define the commissioning button directly under &gpio0
// 'label' property removed as it's not supported by nrf-gpio.yaml binding for direct GPIO nodes.
//&gpio0 {
/* 	button_commissioning: button_commissioning {
		// (GPIO_INPUT | GPIO_PULL_UP) typically results in 0x01 | 0x08 = 0x09
		// When a node is a child of the GPIO controller, 'gpios' property
		// should directly specify the pin number and flags, without the controller phandle.
		gpios = <25 0x09>; // P0.25 for SW4, with INPUT and PULL_UP
		// label = "Commissioning Button"; // Removed
		status = "okay"; // Explicitly enable the node
		gpio-hog; // Correct: Just add the property name for a boolean type
	}; */

    // New: Define the LD2410C OUT pin as a direct GPIO input with pull-up
    // Assuming LD2410C OUT is connected to P0.28 (adjust pin number as needed)
    // ld2410_presence_out_gpio: ld2410_presence_out_gpio {
    //     // (GPIO_INPUT | GPIO_PULL_UP) = 0x01 |
    //     // 0x08 = 0x09
    //     gpios = <28 0x09>;
    //     // P0.28 for LD2410C OUT, with INPUT and PULL_UP
    //     status = "okay";
    //     gpio-hog;
    //     // Mark as hogged by this node if binding requires it for direct GPIO inputs
    // };
//};

// Define pinctrl nodes for UART1 and I2C0
// These nodes specify the exact pin numbers and their configurations for peripherals.
// NRF_PSEL(peripheral_function, port_number, pin_number)
// 'bias-pull-up' property is used for enabling internal pull-ups for the group.
// For P0.xx pins, use port 0. For P1.xx pins, use port 1.
&pinctrl {

	uart1_default: uart1_default {
		group1 {
			// P1.10 for UART RX
			psels = <NRF_PSEL(UART_RX, 1, 10)>;
			bias-pull-up;
		};
		group2 {
			// P1.11 for UART TX
			psels = <NRF_PSEL(UART_TX, 1, 11)>;
		};
	};

	uart1_sleep: uart1_sleep {
		group1 {
			psels = <NRF_PSEL(UART_RX, 1, 10)>,
				<NRF_PSEL(UART_TX, 1, 11)>;
			low-power-enable;
		};
	};

	i2c0_default: i2c0_default {
		group1 {
			// I2C0 SCL pin (P0.26) = Function 0x13 (TWIM_SCL), Port 0, Pin 26 -> PSEL = (0x13 << 8) | (0 << 5) | 26 = 0x131A
			// I2C0 SDA pin (P0.27) = Function 0x14 (TWIM_SDA), Port 0, Pin 27 -> PSEL = (0x14 << 8) | (0 << 5) | 27 = 0x141B
			// 'bias-pull-up' property enables internal pull-ups for these pins in this group.
			psels = <NRF_PSEL(TWIM_SCL, 0, 26)>,
				<NRF_PSEL(TWIM_SDA, 0, 27)>;
			bias-pull-up; // Enable internal pull-ups for these pins
		};
	};
};

/* Disable unused peripherals to reduce power consumption */
&gpio1 {
	status = "okay";
};

&adc {
	status = "disabled";
};

&i2c1 {
	status = "disabled";
};
&pwm0 {
	status = "disabled";
};
&spi1 {
	status = "disabled";
};
&spi3 {
	status = "disabled";
};
&usbd {
	status = "disabled";
};

#
# Copyright (c) 2021 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

# This sample uses Kconfig.defaults to set options common for all
# samples. This file should contain only options specific for this sample
# or overrides of default values.

# Enable CHIP
CONFIG_CHIP=y
CONFIG_CHIP_PROJECT_CONFIG="src/chip_project_config.h"
# 32768 == 0x8000 (example Product ID added temporaly,
# but it must be changed with proper PID from the list:
# https://github.com/project-chip/connectedhomeip/blob/482e6fd03196a6de45465a90003947ef4b86e0b1/docs/examples/discussion/PID_allocation_for_example_apps.md)
CONFIG_CHIP_DEVICE_PRODUCT_ID=32768
CONFIG_STD_CPP17=y

# Enable Matter pairing automatically on application start.
CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y

# Enable Matter extended announcement and increase duration to 1 hour.
CONFIG_CHIP_BLE_EXT_ADVERTISING=y
CONFIG_CHIP_BLE_ADVERTISING_DURATION=60

# Add support for LEDs and buttons on Nordic development kits
CONFIG_DK_LIBRARY=y

# Bluetooth Low Energy configuration
CONFIG_BT_DEVICE_NAME="MatterTemplate"

# Other settings
CONFIG_THREAD_NAME=y
CONFIG_MPU_STACK_GUARD=y
CONFIG_RESET_ON_FATAL_ERROR=n
CONFIG_CHIP_LIB_SHELL=y
CONFIG_NCS_SAMPLE_MATTER_TEST_SHELL=y

# Disable NFC commissioning
CONFIG_CHIP_NFC_COMMISSIONING=n

# Reduce application size
CONFIG_USE_SEGGER_RTT=n


CONFIG_CHIP_OCCUPANCY_SENSING_SERVER=y
CONFIG_CHIP_ILLUMINANCE_MEASUREMENT_SERVER=y

# Enable Factory Data feature
CONFIG_CHIP_FACTORY_DATA=y
CONFIG_CHIP_FACTORY_DATA_BUILD=y


CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_0_INTERRUPT_DRIVEN=y
CONFIG_UART_1_INTERRUPT_DRIVEN=n
CONFIG_NRFX_UARTE1=y
CONFIG_UART_1_ASYNC=y
CONFIG_LOG=y
CONFIG_LOG_MODE_IMMEDIATE=y
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_MODE_MINIMAL=n
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
#CONFIG_UART_USE_RUNTIME_CONFIGURE=y
CONFIG_HEAP_MEM_POOL_SIZE=8192
CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y

CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_BH1750=y

CONFIG_GPIO=y

# Custom Thread Stack Sizes (defined in your custom Kconfig file)
CONFIG_LD2410_UART_THREAD_STACK_SIZE=2048
CONFIG_BH1750_I2C_THREAD_STACK_SIZE=2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_BT_RX_STACK_SIZE=2048
CONFIG_MAIN_STACK_SIZE=4096
# CONFIG_THREAD_ANALYZER=y
# CONFIG_THREAD_ANALYZER_USE_PRINTK=y
# CONFIG_THREAD_ANALYZER_AUTO=y
# CONFIG_THREAD_ANALYZER_AUTO_INTERVAL=5

#include "ld2410_driver.h"
#include "sensor_data_common.h" // Access to shared sensor data

#include <zephyr/logging/log.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/gpio.h>
#include <string.h> // For memcpy, memcmp
#include <zephyr/sys_clock.h> // For K_FOREVER

LOG_MODULE_REGISTER(ld2410_driver, 4);

// K_THREAD_STACK_DEFINE and struct k_thread declaration MUST be at global scope
K_THREAD_STACK_DEFINE(ld2410_uart_thread_stack, CONFIG_LD2410_UART_THREAD_STACK_SIZE);
struct k_thread ld2410_uart_thread_data;

#define UART_RX_BUF_SIZE 256
//#define LD2410_PRESENCE ld2410-presence-out
#define LD2410_BUTTON	DT_NODELABEL(button4)
static uint8_t uart_rx_buf[UART_RX_BUF_SIZE];
static K_FIFO_DEFINE(uart_rx_fifo); // FIFO to pass received data from callback to thread

// Get a reference to the LD2410 UART device as defined in the device tree overlay
static const struct device *ld2410_uart_dev = DEVICE_DT_GET(DT_ALIAS(ld2410_uart));
static const struct gpio_dt_spec ld2410_out_gpio = GPIO_DT_SPEC_GET(LD2410_BUTTON, gpios);
static struct gpio_callback ld2410_presence_cb_data;


void ld2410_presence_isr(const struct device *port, struct gpio_callback *cb, uint32_t pins)
{
    // This ISR should be kept as short and fast as possible.
    // Avoid heavy processing, mutexes, or blocking calls here.
    // Instead, signal a dedicated thread to do the heavy lifting.

    // Get the current state of the pin (optional, if you only care about changes)
    bool current_pin_state = gpio_pin_get_dt(&ld2410_out_gpio);

    // Update the atomic variable directly. This is ISR-safe.
    if (current_pin_state) {
        atomic_set(&g_current_sensor_data.presence_detected, 1); // Set to 1 for true
    } else {
        atomic_set(&g_current_sensor_data.presence_detected, 0); // Set to 0 for false
    }

    LOG_INF("LD2410 Presence changed! Pin %d state: %s", ld2410_out_gpio.pin, current_pin_state ? "HIGH" : "LOW");

    // Signal your main LD2410 processing thread or a dedicated workqueue
    // if you need to do more complex debouncing or processing here.
    // For example: k_sem_give(&my_ld2410_event_sem); or k_msgq_put(&my_ld2410_msgq, &current_state, K_NO_WAIT);
}

int ld2410_presence_interrupt_init(void)
{
    int ret;

    // Check if the GPIO device is ready
    if (!gpio_is_ready_dt(&ld2410_out_gpio)) {
        LOG_ERR("LD2410 Presence GPIO device is not ready!");
        return -ENODEV;
    }

    // Configure the pin as a GPIO input (even if already in DTS, good to explicitly configure)
    ret = gpio_pin_configure_dt(&ld2410_out_gpio, GPIO_INPUT | GPIO_PULL_DOWN);
    if (ret < 0) {
        LOG_ERR("Could not configure LD2410 Presence GPIO pin %d (error: %d)", ld2410_out_gpio.pin, ret);
        return ret;
    }

    // Configure the interrupt trigger:
    // GPIO_INT_EDGE_BOTH: Triggers on both rising and falling edges (HIGH to LOW, LOW to HIGH)
    // GPIO_INT_EDGE_RISING: Triggers only on rising edge (LOW to HIGH)
    // GPIO_INT_EDGE_FALLING: Triggers only on falling edge (HIGH to LOW)
    // Use GPIO_INT_EDGE_BOTH to detect any change in the presence state.
    ret = gpio_pin_interrupt_configure_dt(&ld2410_out_gpio, GPIO_INT_EDGE_BOTH);
    if (ret < 0) {
        LOG_ERR("Could not configure LD2410 Presence GPIO interrupt (error: %d)", ret);
        return ret;
    }   

    // Initialize the GPIO callback structure:
    // - first argument is the callback struct itself
    // - second argument is the function to call (our ISR)
    // - third argument is a bitmask of the pins that this callback applies to
    gpio_init_callback(&ld2410_presence_cb_data, ld2410_presence_isr, BIT(ld2410_out_gpio.pin));

    // Add the callback to the GPIO device
    ret = gpio_add_callback(ld2410_out_gpio.port, &ld2410_presence_cb_data);
    if (ret < 0) {
        LOG_ERR("Could not add LD2410 Presence GPIO callback (error: %d)", ret);
        return ret;
    }

    LOG_INF("LD2410 Presence GPIO interrupt initialized pin %d.", ld2410_out_gpio.pin);
    return 0;
}

/**
 * @brief UART callback function.
 *
 * This function is called by the UART driver when new data is received or
 * a transmission is complete. It pushes received data to a FIFO.
 */
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
    ARG_UNUSED(dev);
    ARG_UNUSED(user_data);

    switch (evt->type) {
    case UART_RX_RDY: {
        LOG_DBG("LD2410 UART RX RDY (test)"); // This simple log

        if (evt->data.rx.len > 0) {
            LOG_DBG("LD2410 UART RX RDY (test): %d bytes (offset %d)", evt->data.rx.len, evt->data.rx.offset); // This simple log
            uint8_t *buf_chunk = k_malloc(evt->data.rx.len + sizeof(size_t));
            if (buf_chunk) {
                *(size_t *)buf_chunk = evt->data.rx.len;
                memcpy(buf_chunk + sizeof(size_t), evt->data.rx.buf + evt->data.rx.offset, evt->data.rx.len);
                k_fifo_put(&uart_rx_fifo, buf_chunk);
                LOG_DBG("LD2410 UART RX RDY: %d bytes (offset %d)", evt->data.rx.len, evt->data.rx.offset);
            } else {
                LOG_ERR("LD2410: Failed to allocate memory for UART RX data.");
            }
        }
        break;
    }
    case UART_RX_DISABLED:
        // Use 0 for non-blocking timeout.
        uart_rx_enable(ld2410_uart_dev, uart_rx_buf, sizeof(uart_rx_buf), 0);
        LOG_DBG("LD2410 UART RX Disabled, re-enabling.");
        break;
    case UART_TX_DONE:
        LOG_DBG("LD2410 UART TX Done.");
        break;
    case UART_TX_ABORTED:
        LOG_WRN("LD2410 UART TX Aborted.");
        break;
    case UART_RX_STOPPED:
        LOG_WRN("LD2410 UART RX Stopped. Reason: %d", evt->data.rx_stop.reason);
        break;
    case UART_RX_BUF_REQUEST:
    case UART_RX_BUF_RELEASED:
    default:
        break;
    }
}

/**
 * @brief Parses raw data received from the LD2410C sensor based on PDF.
 *
 * This function parses "Target basic information data" (Data type 0x02)
 * as described in "Protocolo_comunicacion_serial_LD2410C.pdf",
 * sections 2.3.1 (Table 9, Table 10) and 2.3.2 (Table 12).
 *
 * @param buffer Pointer to the raw data buffer.
 * @param len Length of the data in the buffer.
 */
static void parse_ld2410_data(const uint8_t *buffer, size_t len)
{
    // Frame Header: F4 F3 F2 F1 (4 bytes)
    const uint8_t HEADER[] = {0xF4, 0xF3, 0xF2, 0xF1};
    // End of Frame: F8 F7 F6 F5 (4 bytes)
    const uint8_t FOOTER[] = {0xF8, 0xF7, 0xF6, 0xF5};

    // "Intra-frame data" length for "Target basic information data" (Data Type 0x02)
    const uint16_t EXPECTED_INTRA_FRAME_DATA_LEN = 13; // 0x0D 0x00

    // Total expected frame length: Header (4) + Length (2) + Intra-frame Data (13) + Footer (4) = 23 bytes
    const size_t EXPECTED_TOTAL_FRAME_LEN = sizeof(HEADER) + 2 + EXPECTED_INTRA_FRAME_DATA_LEN + sizeof(FOOTER);

    // Iterate through the received chunk to find frames.
    for (size_t i = 0; i <= len - EXPECTED_TOTAL_FRAME_LEN; ++i) {
        if (memcmp(&buffer[i], HEADER, sizeof(HEADER)) == 0) {
            uint16_t received_intra_frame_len = (uint16_t)buffer[i + 4] | ((uint16_t)buffer[i + 5] << 8);

            if (received_intra_frame_len != EXPECTED_INTRA_FRAME_DATA_LEN) {
                LOG_DBG("LD2410: Invalid intra-frame data length (expected %u, got %u).",
                        EXPECTED_INTRA_FRAME_DATA_LEN, received_intra_frame_len);
                continue;
            }

            if (memcmp(&buffer[i + EXPECTED_TOTAL_FRAME_LEN - sizeof(FOOTER)], FOOTER, sizeof(FOOTER)) == 0) {
                const size_t DATA_TYPE_OFFSET = i + 6;
                const size_t HEAD_OFFSET = i + 7;
                const size_t TARGET_STATUS_OFFSET = i + 8;
                const size_t MOV_DIST_LSB_OFFSET = i + 9;
                const size_t STILL_DIST_LSB_OFFSET = i + 12;
                const size_t TAIL_OFFSET = i + 17;
                const size_t CALIBRATION_OFFSET = i + 18;


                if (buffer[DATA_TYPE_OFFSET] != 0x02 || buffer[HEAD_OFFSET] != 0xAA ||
                    buffer[TAIL_OFFSET] != 0x55 || buffer[CALIBRATION_OFFSET] != 0x00) {
                    LOG_DBG("LD2410: Frame content mismatch (type/head/tail/calibration).");
                    continue;
                }

                bool new_presence = (buffer[TARGET_STATUS_OFFSET] != 0x00);
                uint16_t new_moving_dist = (uint16_t)buffer[MOV_DIST_LSB_OFFSET] |
                                           ((uint16_t)buffer[MOV_DIST_LSB_OFFSET + 1] << 8);
                uint16_t new_still_dist = (uint16_t)buffer[STILL_DIST_LSB_OFFSET] |
                                          ((uint16_t)buffer[STILL_DIST_LSB_OFFSET + 1] << 8);

                k_mutex_lock(&g_sensor_data_mutex, K_FOREVER);
                g_current_sensor_data.presence_detected = new_presence;
                g_current_sensor_data.moving_distance = new_moving_dist;
                g_current_sensor_data.still_distance = new_still_dist;
                k_mutex_unlock(&g_sensor_data_mutex);

                LOG_INF("LD2410 Data: Presence=%s, Moving=%ucm, Still=%ucm",
                        new_presence ? "YES" : "NO", new_moving_dist, new_still_dist);

                return;
            }
        }
    }
    LOG_DBG("LD2410: No complete and valid frame found in this chunk.");
}

// Function to be called from main.cpp for initialization
int ld2410_uart_init(void)
{
    if (!device_is_ready(ld2410_uart_dev)) {
        LOG_ERR("LD2410 UART device not ready!");
        return -ENODEV; // Return error code
    }

    // struct uart_config uart_cfg = {
    //     .baudrate = 230400,
    //     .parity = UART_CFG_PARITY_NONE,
    //     .stop_bits = UART_CFG_STOP_BITS_1,
    //     .data_bits = UART_CFG_DATA_BITS_8,
    //     .flow_ctrl = UART_CFG_FLOW_CTRL_NONE
    // };

    // int ret = uart_configure(ld2410_uart_dev, &uart_cfg); // Call uart_configure here
    // if (ret) {
    //     LOG_ERR("Failed to configure LD2410 UART (error %d)!", ret);
    //     return ret;
    // }

    int ret = uart_callback_set(ld2410_uart_dev, uart_cb, NULL);
    if (ret) {
        LOG_ERR("Failed to set UART callback (error %d)!", ret);
        return ret;
    }

    ret = uart_rx_enable(ld2410_uart_dev, uart_rx_buf, sizeof(uart_rx_buf), SYS_FOREVER_US); // Use K_NO_WAIT for async
    if (ret) {
        LOG_ERR("Failed to enable UART RX (error %d)!", ret);
        return ret;
    }

    LOG_INF("LD2410 UART initialized and RX enabled.");
    return 0; // Success
}


/**
 * @brief Entry point for the LD2410 UART reader thread.
 */
void ld2410_uart_reader_entry_point(void *p1, void *p2, void *p3)
{
    LOG_INF("LD2410 UART reader thread started. Waiting for data...");

    while (true) {
        // Blocks until data is available in the FIFO
        // FIX: Use K_FOREVER directly as k_timeout_t for k_fifo_get
        uint8_t *rx_data_chunk_with_len = k_fifo_get(&uart_rx_fifo, K_FOREVER);
        if (rx_data_chunk_with_len) {
            size_t chunk_len = *(size_t *)rx_data_chunk_with_len; // Retrieve length
            uint8_t *rx_data_chunk = rx_data_chunk_with_len + sizeof(size_t); // Pointer to actual data

            parse_ld2410_data(rx_data_chunk, chunk_len);

            k_free(rx_data_chunk_with_len); // Free the allocated buffer
        }
    }
}

#include "bh1750_driver.h"
#include "sensor_data_common.h" // Access to shared sensor data

#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor.h> // Zephyr's generic sensor API

LOG_MODULE_REGISTER(bh1750_driver, CONFIG_LOG_DEFAULT_LEVEL);

// Get a reference to the BH1750 sensor device as defined in the device tree overlay
static const struct device *bh1750_dev = DEVICE_DT_GET(DT_ALIAS(bh1750_sensor));

// Thread stack and data for the BH1750 I2C reader thread
K_THREAD_STACK_DEFINE(bh1750_i2c_thread_stack, CONFIG_BH1750_I2C_THREAD_STACK_SIZE);
struct k_thread bh1750_i2c_thread_data;

/**
 * @brief Entry point for the BH1750 I2C reader thread.
 *
 * This thread periodically reads illuminance data from the BH1750 sensor
 * and updates a shared data structure.
 */
void bh1750_i2c_reader_entry_point(void *p1, void *p2, void *p3)
{
    ARG_UNUSED(p1);
    ARG_UNUSED(p2);
    ARG_UNUSED(p3);

    if (!device_is_ready(bh1750_dev)) {
        LOG_ERR("BH1750 sensor device not ready! Check device tree overlay and connections.");
        return;
    }

    LOG_INF("BH1750 I2C reader thread started. Reading illuminance...");

    struct sensor_value lux_value;
    int ret;

    while (true) {
        // Trigger sensor measurement
        ret = sensor_sample_fetch(bh1750_dev);
        if (ret < 0) {
            LOG_ERR("BH1750: Sensor sample fetch failed: %d", ret);
            k_sleep(K_SECONDS(5)); // Longer sleep on error
            continue;
        }

        // Get the illuminance value
        ret = sensor_channel_get(bh1750_dev, SENSOR_CHAN_LIGHT, &lux_value);
        if (ret < 0) {
            LOG_ERR("BH1750: Cannot get illuminance channel data: %d", ret);
            k_sleep(K_SECONDS(5)); // Longer sleep on error
            continue;
        }

        // Convert to Lux (assuming val1 is integer lux, val2 is micro lux)
        uint32_t current_lux = lux_value.val1;
        // If you need more precision, you can use lux_value.val2 (micro lux)
        // current_lux = (lux_value.val1 * 1000000 + lux_value.val2) / 1000000;

        // Acquire mutex before updating shared data
        k_mutex_lock(&g_sensor_data_mutex, K_FOREVER);
        g_current_sensor_data.illuminance_lux = current_lux;
        k_mutex_unlock(&g_sensor_data_mutex);

        LOG_INF("BH1750 Illuminance: %u Lux", current_lux);

        // Sleep for a period before the next reading
        k_sleep(K_SECONDS(2)); // Read every 2 seconds
    }
}

[09:28:34.707,275] <dbg> ld2410_driver: uart_cb: LD2410 UART RX Disabled, re-enabling.
uart:~$ :28:34.707,031] <inf> ld2410_driver: LD2410 Data[09:28:34.908,538] <err> mpsl_init: MPSL ASSERT: 107, 291
[09:28:34.908,538] <err> mpsl_init: MPSL ASSERT: 107, 291
uart:~$ [09:28:34.920,989] <err> os: ***** HARD FAULT *****
[09:28:34.920,989] <err> os: ***** HARD FAULT *****
uart:~$ [09:28:34.932,464] <err> os:   Fault escalation (see below)
[09:28:34.932,464] <err> os:   Fault escalation (see below)
uart:~$ [09:28:34.945,343] <err> os: ARCH_EXCEPT with reason 3

[09:28:34.945,343] <err> os: ARCH_EXCEPT with reason 3

uart:~$ [09:28:34.957,519] <err> os: r0/a1:  0x00000003  r1/a2:  0x00000000  r2/a3:  0x00000000
[09:28:34.957,519] <err> os: r0/a1:  0x00000003  r1/a2:  0x00000000  r2/a3:  0x00000000
uart:~$ [09:28:34.975,219] <err> os: r3/a4:  0x00000003 r12/ip:  0x00000000 r14/lr:  0x0007ffbb
[09:28:34.975,219] <err> os: r3/a4:  0x00000003 r12/ip:  0x00000000 r14/lr:  0x0007ffbb
uart:~$ [09:28:34.992,919] <err> os:  xpsr:  0x0100001b
[09:28:34.992,919] <err> os:  xpsr:  0x0100001b
uart:~$ [09:28:35.003,723] <err> os: Faulting instruction address (r15/pc): 0x0003af06
[09:28:35.003,723] <err> os: Faulting instruction address (r15/pc): 0x0003af06
uart:~$ [09:28:35.019,866] <err> os: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0
[09:28:35.019,866] <err> os: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0
uart:~$ [09:28:35.035,491] <err> os: Fault during interrupt handling

[09:28:35.035,491] <err> os: Fault during interrupt handling

uart:~$ [09:28:35.048,706] <err> os: Current thread: 0x20003318 (unknown)
[09:28:35.048,706] <err> os: Current thread: 0x20003318 (unknown)
uart:~$ [09:28:35.062,591] <err> os: Halting system
[09:28:35.062,591] <err> os: Halting system

[00:00:15.386,810] <dbg> chip: LogV: [IN]TransportMgr initialized
uart:~$ [00:02:07.777,893] <err> mpsl_init: MPSL ASSERT: 107, 301
[00:02:07.777,893] <err> mpsl_init: MPSL ASSERT: 107, 301
uart:~$ [00:02:07.790,374] <err> os: ***** HARD FAULT *****
[00:02:07.790,374] <err> os: ***** HARD FAULT *****
uart:~$ [00:02:07.801,849] <err> os:   Fault escalation (see below)
[00:02:07.801,849] <err> os:   Fault escalation (see below)
uart:~$ [00:02:07.814,697] <err> os: ARCH_EXCEPT with reason 3

[00:02:07.814,697] <err> os: ARCH_EXCEPT with reason 3

uart:~$ [00:02:07.826,873] <err> os: r0/a1:  0x00000003  r1/a2:  0x00000000  r2/a3:  0x00000000
[00:02:07.826,873] <err> os: r0/a1:  0x00000003  r1/a2:  0x00000000  r2/a3:  0x00000000
uart:~$ [00:02:07.844,604] <err> os: r3/a4:  0x00000003 r12/ip:  0x00000000 r14/lr:  0x0007ff71
[00:02:07.844,604] <err> os: r3/a4:  0x00000003 r12/ip:  0x00000000 r14/lr:  0x0007ff71
uart:~$ [00:02:07.862,304] <err> os:  xpsr:  0x0100001b
[00:02:07.862,304] <err> os:  xpsr:  0x0100001b
uart:~$ [00:02:07.873,077] <err> os: Faulting instruction address (r15/pc): 0x0003af5a
[00:02:07.873,077] <err> os: Faulting instruction address (r15/pc): 0x0003af5a
uart:~$ [00:02:07.889,251] <err> os: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0
[00:02:07.889,251] <err> os: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0
uart:~$ [00:02:07.904,876] <err> os: Fault during interrupt handling

[00:02:07.904,876] <err> os: Fault during interrupt handling

uart:~$ [00:02:07.918,060] <err> os: Current thread: 0x20003278 (unknown)
[00:02:07.918,060] <err> os: Current thread: 0x20003278 (unknown)
uart:~$ [00:02:07.931,976] <err> os: Halting system
[00:02:07.931,976] <err> os: Halting system

Related