esp32[s2|s3]: Add UORB support for internal temperature sensor

This commit is contained in:
Eren Terzioglu 2024-10-04 18:56:36 +03:00 committed by Xiang Xiao
parent 929f9ccfa2
commit 4060f6ba80
4 changed files with 326 additions and 27 deletions

View file

@ -31,10 +31,23 @@ config ESPRESSIF_SPIFLASH
menu "Internal Temperature Sensor Configuration"
depends on ESPRESSIF_TEMP
config ESPRESSIF_TEMP_UORB
bool "Internal Temperature Sensor UORB Interface"
default n
---help---
Enables work with the UORB or Character Device interface.
If not set, the Character Device is used by default.
config ESPRESSIF_TEMP_PATH
string "Internal Temperature Sensor Path"
depends on !ESPRESSIF_TEMP_UORB
default "dev/temp"
config ESPRESSIF_TEMP_PATH_DEVNO
int "Internal Temperature Sensor Path Device Number"
depends on ESPRESSIF_TEMP_UORB
default 0
endmenu # ESPRESSIF_TEMP
config ESPRESSIF_HAVE_OTA_PARTITION

View file

@ -23,6 +23,7 @@
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/nuttx.h>
#ifdef CONFIG_ESPRESSIF_TEMP
#include <stdio.h>
@ -42,6 +43,9 @@
#include <nuttx/can/can.h>
#include <nuttx/signal.h>
#include <nuttx/arch.h>
#ifdef CONFIG_ESPRESSIF_TEMP_UORB
#include <nuttx/sensors/sensor.h>
#endif
#include "xtensa.h"
#include "espressif/esp_temperature_sensor.h"
@ -62,6 +66,8 @@
* Pre-processor Definitions
****************************************************************************/
#define ESP_TEMP_MIN_INTERVAL 30000
/****************************************************************************
* Private Types
****************************************************************************/
@ -78,14 +84,19 @@ enum esp_tempstate_e
struct esp_temp_priv_s
{
#ifndef CONFIG_ESPRESSIF_TEMP_UORB
const struct file_operations *ops; /* Standard file operations */
#endif
const temperature_sensor_attribute_t *tsens_attribute; /* Attribute struct of the common layer */
struct esp_temp_sensor_config_t cfg; /* Configuration struct of the common layer */
temperature_sensor_clk_src_t clk_src; /* Clock source to use */
int module; /* Peripheral module */
int refs; /* Reference count */
mutex_t lock; /* Mutual exclusion mutex */
#ifdef CONFIG_ESPRESSIF_TEMP_UORB
struct sensor_lowerhalf_s lower; /* Lower half sensor driver. */
uint32_t interval; /* Sensor acquisition interval. */
#endif
/* Temperature sensor work state (see enum esp_tempstate_e) */
volatile enum esp_tempstate_e tempstate;
@ -109,9 +120,25 @@ static void esp_temp_sensor_register(struct esp_temp_priv_s *priv);
static int esp_temperature_sensor_install(struct esp_temp_priv_s *priv,
struct esp_temp_sensor_config_t cfg);
static void esp_temperature_sensor_uninstall(struct esp_temp_priv_s *priv);
static int esp_temperature_sensor_get_celsius(struct file *filep,
char *buffer,
size_t buflen);
static int esp_temperature_sensor_get_celsius(struct esp_temp_priv_s *priv,
int *buffer);
#ifdef CONFIG_ESPRESSIF_TEMP_UORB
static int esp_temperature_sensor_set_interval(
struct sensor_lowerhalf_s *lower,
struct file *filep,
uint32_t *period_us);
static int esp_temperature_sensor_activate(
struct sensor_lowerhalf_s *lower,
struct file *filep,
bool enable);
static int esp_temperature_sensor_fetch(struct sensor_lowerhalf_s *lower,
struct file *filep,
char *buffer, size_t buflen);
#else
static int esp_temperature_sensor_read(struct file *filep,
char *buffer,
size_t buflen);
#endif /* CONFIG_ESPRESSIF_TEMP_UORB */
/****************************************************************************
* Private Data
@ -119,17 +146,28 @@ static int esp_temperature_sensor_get_celsius(struct file *filep,
static float g_delta_t = NAN;
#ifndef CONFIG_ESPRESSIF_TEMP_UORB
static const struct file_operations g_esp_temp_sensor_fops =
{
NULL, /* open */
NULL, /* close */
esp_temperature_sensor_get_celsius, /* read */
esp_temperature_sensor_read, /* read */
NULL, /* write */
};
#else
static const struct sensor_ops_s g_esp_temp_sensor_sops =
{
.activate = esp_temperature_sensor_activate, /* Enable/disable sensor. */
.fetch = esp_temperature_sensor_fetch,
.set_interval = esp_temperature_sensor_set_interval, /* Set output data period. */
};
#endif /* CONFIG_ESPRESSIF_TEMP_UORB */
struct esp_temp_priv_s esp_temp_priv =
{
#ifndef CONFIG_ESPRESSIF_TEMP_UORB
.ops = &g_esp_temp_sensor_fops,
#endif
.tsens_attribute = NULL,
.cfg =
{
@ -139,6 +177,13 @@ struct esp_temp_priv_s esp_temp_priv =
.module = PERIPH_TEMPSENSOR_MODULE,
.refs = 0,
.lock = NXMUTEX_INITIALIZER,
#ifdef CONFIG_ESPRESSIF_TEMP_UORB
.lower =
{
0
},
.interval = ESP_TEMP_MIN_INTERVAL,
#endif
.tempstate = 0,
};
@ -229,7 +274,7 @@ static int temperature_sensor_choose_best_range(struct esp_temp_priv_s *priv)
if (priv->tsens_attribute == NULL)
{
syslog(LOG_ERR, "Out of testing range");
snerr("Out of testing range");
return ERROR;
}
@ -255,12 +300,12 @@ static int temperature_sensor_read_delta_t(void)
{
if (esp_efuse_rtc_calib_get_tsens_val(&g_delta_t) != OK)
{
syslog(LOG_WARNING, "Calibration failed");
snwarn("Calibration failed");
g_delta_t = 0;
return ERROR;
}
syslog(LOG_INFO, "delta_T = %f", g_delta_t);
sninfo("delta_T = %f", g_delta_t);
return OK;
}
@ -339,8 +384,7 @@ static void esp_temperature_sensor_disable(struct esp_temp_priv_s *priv)
* Name: esp_temp_sensor_register
*
* Description:
* This function registers the internal temperature sensor to
* /dev/temp driver.
* This function registers the internal temperature sensor.
*
* Input Parameters:
* priv - Pointer to the internal driver state structure.
@ -352,8 +396,12 @@ static void esp_temperature_sensor_disable(struct esp_temp_priv_s *priv)
static void esp_temp_sensor_register(struct esp_temp_priv_s *priv)
{
#ifndef CONFIG_ESPRESSIF_TEMP_UORB
register_driver(CONFIG_ESPRESSIF_TEMP_PATH, &g_esp_temp_sensor_fops,
0666, priv);
#else
sensor_register(&priv->lower, CONFIG_ESPRESSIF_TEMP_PATH_DEVNO);
#endif /* CONFIG_ESPRESSIF_TEMP_UORB */
}
/****************************************************************************
@ -381,7 +429,7 @@ static int esp_temperature_sensor_install(struct esp_temp_priv_s *priv,
ret = temperature_sensor_attribute_table_sort();
if (ret < 0)
{
syslog(LOG_ERR, "Table sort failed");
snerr("Table sort failed");
goto err;
}
@ -390,7 +438,7 @@ static int esp_temperature_sensor_install(struct esp_temp_priv_s *priv,
ret = temperature_sensor_choose_best_range(priv);
if (ret < 0)
{
syslog(LOG_ERR, "Cannot select the correct range");
snerr("Cannot select the correct range");
goto err;
}
@ -434,40 +482,36 @@ static void esp_temperature_sensor_uninstall(struct esp_temp_priv_s *priv)
* Read temperature sensor data that is converted to degrees Celsius.
*
* Input Parameters:
* filep - The pointer of file, represents each user using the sensor
* priv - Pointer to the internal driver state structure.
* buffer - Buffer to save temperature sensor value in degrees Celsius
* buflen - Length of the buffer
*
* Returned Value:
* Returns OK on success; a negated errno value on failure
*
****************************************************************************/
static int esp_temperature_sensor_get_celsius(struct file *filep,
char *buffer,
size_t buflen)
static int esp_temperature_sensor_get_celsius(struct esp_temp_priv_s *priv,
int *buffer)
{
uint32_t tsens_out;
struct inode *inode = filep->f_inode;
struct esp_temp_priv_s *priv = inode->i_private;
int *out = (int *)buffer;
float *out = (float *)buffer;
nxmutex_lock(&priv->lock);
if (priv == NULL)
{
syslog(LOG_WARNING, "Temperature sensor has not been installed");
snwarn("Temperature sensor has not been installed");
goto err;
}
esp_temperature_sensor_enable(priv);
if (priv->tempstate != TEMP_SENSOR_ENABLE)
{
syslog(LOG_WARNING, "Temperature sensor not enabled");
snwarn("Temperature sensor not enabled");
goto err;
}
tsens_out = temperature_sensor_ll_get_raw_value();
syslog(LOG_INFO, "Temperature sensor raw value: %d", tsens_out);
sninfo("Temperature sensor raw value: %ld", (long int)tsens_out);
*out = temperature_sensor_parse_raw_value(tsens_out,
priv->tsens_attribute->offset);
@ -476,7 +520,7 @@ static int esp_temperature_sensor_get_celsius(struct file *filep,
if (*out < priv->tsens_attribute->range_min ||
*out > priv->tsens_attribute->range_max)
{
syslog(LOG_WARNING, "Temperature sensor value is out of range");
snwarn("Temperature sensor value is out of range");
goto err;
}
@ -488,6 +532,142 @@ err:
return ERROR;
}
#ifndef CONFIG_ESPRESSIF_TEMP_UORB
/****************************************************************************
* Name: esp_temperature_sensor_read
*
* Description:
* Read temperature sensor data that is converted to degrees Celsius.
*
* Input Parameters:
* filep - The pointer of file, represents each user using the sensor
* buffer - Buffer to save temperature sensor value in degrees Celsius
* buflen - Length of the buffer
*
* Returned Value:
* Returns OK on success; a negated errno value on failure
*
****************************************************************************/
static int esp_temperature_sensor_read(struct file *filep,
char *buffer,
size_t buflen)
{
struct inode *inode = filep->f_inode;
struct esp_temp_priv_s *priv = inode->i_private;
return esp_temperature_sensor_get_celsius(priv, (int *)buffer);
}
#else
static int esp_temperature_sensor_fetch(struct sensor_lowerhalf_s *lower,
struct file *filep,
char *buffer, size_t buflen)
{
struct esp_temp_priv_s *priv =
container_of (lower, struct esp_temp_priv_s, lower);
int ret;
struct sensor_temp temp;
float val = 0.0;
if (buflen != sizeof(temp))
{
return -EINVAL;
}
esp_temperature_sensor_get_celsius(priv, (int *)&val);
sninfo("temp = %d\n", (int)val);
temp.timestamp = sensor_get_timestamp();
temp.temperature = (int)val;
memcpy(buffer, &temp, sizeof(temp));
return buflen;
}
/****************************************************************************
* Name: esp_temperature_sensor_set_interval
*
* Description:
* Set the sensor output data period in microseconds for a given sensor.
* If *period_us < min_delay it will be replaced by min_delay.
*
* Input Parameters:
* lower - The instance of lower half sensor driver.
* filep - The pointer of file, represents each user using the sensor.
* period_us - The time between report data, in us. It may by overwrite
* by lower half driver.
*
* Returned Value:
* Return OK(0) if the driver was success; A negated errno
* value is returned on any failure.
*
****************************************************************************/
static int esp_temperature_sensor_set_interval(
struct sensor_lowerhalf_s *lower,
struct file *filep,
uint32_t *period_us)
{
struct esp_temp_priv_s *priv = (struct esp_temp_priv_s *)lower;
if (*period_us < ESP_TEMP_MIN_INTERVAL)
{
priv->interval = ESP_TEMP_MIN_INTERVAL;
*period_us = priv->interval;
}
else
{
priv->interval = *period_us;
}
return OK;
}
/****************************************************************************
* Name: esp_temperature_sensor_activate
*
* Description:
* Enable or disable sensor device. when enable sensor, sensor will
* work in current mode(if not set, use default mode). when disable
* sensor, it will disable sense path and stop convert.
*
* Input Parameters:
* lower - The instance of lower half sensor driver.
* filep - The pointer of file, represents each user using the sensor.
* enable - true(enable) and false(disable).
*
* Returned Value:
* Return OK(0) if the driver was success; A negated errno
* value is returned on any failure.
*
****************************************************************************/
static int esp_temperature_sensor_activate(
struct sensor_lowerhalf_s *lower,
struct file *filep,
bool enable)
{
struct esp_temp_priv_s *priv = (struct esp_temp_priv_s *)lower;
/* Set accel output data rate. */
if (enable)
{
esp_temperature_sensor_enable(priv);
}
else
{
/* Set suspend mode to sensors. */
esp_temperature_sensor_disable(priv);
}
return OK;
}
#endif /* CONFIG_ESPRESSIF_TEMP_UORB */
/****************************************************************************
* Public Functions
****************************************************************************/
@ -517,7 +697,7 @@ int esp_temperature_sensor_initialize(struct esp_temp_sensor_config_t cfg)
if (priv->refs++ != 0)
{
nxmutex_unlock(&priv->lock);
syslog(LOG_INFO, "Temperature sensor previously initialized."
sninfo("Temperature sensor previously initialized."
"Handler: %p\n", priv);
}
else
@ -525,16 +705,22 @@ int esp_temperature_sensor_initialize(struct esp_temp_sensor_config_t cfg)
ret = esp_temperature_sensor_install(priv, cfg);
if (ret != OK)
{
syslog(LOG_ERR, "Temperature sensor initialization failed!");
snerr("Temperature sensor initialization failed!");
nxmutex_unlock(&priv->lock);
return ret;
}
}
#ifdef CONFIG_ESPRESSIF_TEMP_UORB
priv->lower.ops = &g_esp_temp_sensor_sops;
priv->lower.type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
priv->interval = ESP_TEMP_MIN_INTERVAL;
#endif
esp_temp_sensor_register(priv);
nxmutex_unlock(&priv->lock);
syslog(LOG_INFO, "Temperature sensor initialized! Handler: %p\n", priv);
sninfo("Temperature sensor initialized! Handler: %p\n", priv);
return OK;
}

View file

@ -0,0 +1,49 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_ARCH_LEDS is not set
# CONFIG_NSH_ARGCAT is not set
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
CONFIG_ARCH="xtensa"
CONFIG_ARCH_BOARD="esp32s2-saola-1"
CONFIG_ARCH_BOARD_COMMON=y
CONFIG_ARCH_BOARD_ESP32S2_SAOLA_1=y
CONFIG_ARCH_CHIP="esp32s2"
CONFIG_ARCH_CHIP_ESP32S2=y
CONFIG_ARCH_CHIP_ESP32S2WROVER=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_XTENSA=y
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BUILTIN=y
CONFIG_ESP32S2_UART0=y
CONFIG_ESPRESSIF_TEMP=y
CONFIG_ESPRESSIF_TEMP_UORB=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_IDLETHREAD_STACKSIZE=3072
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INIT_STACKSIZE=3072
CONFIG_INTELHEX_BINARY=y
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_LINELEN=64
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_SENSORS=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_SYSLOG_BUFFER=y
CONFIG_SYSTEM_NSH=y
CONFIG_TESTING_SENSORTEST=y
CONFIG_UART0_SERIAL_CONSOLE=y

View file

@ -0,0 +1,51 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_ARCH_LEDS is not set
# CONFIG_NSH_ARGCAT is not set
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
CONFIG_ARCH="xtensa"
CONFIG_ARCH_BOARD="esp32s3-devkit"
CONFIG_ARCH_BOARD_COMMON=y
CONFIG_ARCH_BOARD_ESP32S3_DEVKIT=y
CONFIG_ARCH_CHIP="esp32s3"
CONFIG_ARCH_CHIP_ESP32S3=y
CONFIG_ARCH_CHIP_ESP32S3WROOM1N4=y
CONFIG_ARCH_INTERRUPTSTACK=2048
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_XTENSA=y
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BUILTIN=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_ESP32S3_UART0=y
CONFIG_ESPRESSIF_TEMP=y
CONFIG_ESPRESSIF_TEMP_UORB=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_IDLETHREAD_STACKSIZE=3072
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INTELHEX_BINARY=y
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_LINELEN=64
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_SENSORS=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_SYSLOG_BUFFER=y
CONFIG_SYSTEM_NSH=y
CONFIG_TESTING_SENSORTEST=y
CONFIG_UART0_SERIAL_CONSOLE=y