ulp: Added support for RTC I2C driver for ULP RISC-V on esp32s2 and esp32s3

This commit adds support for using the RTC I2C peripheral on the ULP
RISC-V core for esp32s2 and esp32s3. It also adds an example to demonstrate the
usage of the RTC I2C peripheral.

This commit also modifies the rtc_i2c register structure files to enable
the use of bitfields in the ULP RISC-V RTC I2C driver.
This commit is contained in:
Sudeep Mohanty
2022-08-09 15:46:14 +02:00
parent 6193e4c8e8
commit 4fde033a5f
21 changed files with 1559 additions and 302 deletions
+4
View File
@@ -194,6 +194,10 @@ examples/system/ulp_riscv/gpio_interrupt:
temporary: true
reason: the other targets are not tested yet
examples/system/ulp_riscv/i2c:
enable:
- if: SOC_RISCV_COPROC_SUPPORTED == 1
examples/system/ulp_riscv/uart_print:
enable:
- if: SOC_RISCV_COPROC_SUPPORTED == 1
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ulp-riscv-rtc-i2c-example)
+76
View File
@@ -0,0 +1,76 @@
| Supported Targets | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | -------- |
# ULP RISC-V I2C Example
This example demonstrates how to use the RTC I2C peripheral from the ULP RISC-V coprocessor in deep sleep.
The ULP program is based on the BMP180 Temperature and Pressure sensor (https://cz.mouser.com/datasheet/2/783/BST-BMP180-DS000-1509579.pdf) which has an I2C interface. The main CPU initializes the RTC I2C peripheral, the BMP180 sensor and loads the ULP program. It then goes into deep sleep.
The ULP program periodically measures the temperature and pressure values from the BMP180 sensor and wakesup the main CPU when the values are above a certain thershold.
### Hardware Required
* A development board with a SOC which has a RISC-V ULP coprocessor (e.g., ESP32-S2 Saola)
* A BMP180 sensor module
* A USB cable for power supply and programming
## Example output
Below is the output from this example.
```
Not a ULP-RISC V wakeup (cause = 0)
Initializing RTC I2C ...
RTC_I2C_STATUS_REG = 0x00000000
Reading calibration data from BMP180 ...
ac1 = 7819
ac2 = -1152
ac3 = -14317
ac4 = 34252
ac5 = 25122
ac6 = 14289
b1 = 6515
b2 = 44
mb = -32768
mc = -11786
md = 2746
Reading initial uncompensated temperature and pressure data ...
Uncompensated Temperature = 22865
Uncompensated Pressure = 41768
Real Temperature = 24.900000 deg celcius
Real Pressure = 990.640000 hPa
Entering in deep sleep
ESP-ROM:esp32s2-rc4-20191025
Build:Oct 25 2019
rst:0x5 (DSLEEP),boot:0x9 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3ffe6108,len:0x1298
load:0x4004c000,len:0x92c
load:0x40050000,len:0x2f04
entry 0x4004c154
W (76) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
ULP RISC-V woke up the main CPU
Uncompensated Temperature = 22865
Uncompensated Pressure = 41765
Reading calibration data from BMP180 ...
ac1 = 7819
ac2 = -1152
ac3 = -14317
ac4 = 34252
ac5 = 25122
ac6 = 14289
b1 = 6515
b2 = 44
mb = -32768
mc = -11786
md = 2746
New Real Temperature = 24.900000 deg celcius
New Real Pressure = 990.550000 hPa
Entering in deep sleep
```
@@ -0,0 +1,25 @@
idf_component_register(SRCS "ulp_riscv_rtc_i2c_example_main.c"
INCLUDE_DIRS ""
REQUIRES soc ulp)
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
#
# ULP support additions to component CMakeLists.txt.
#
# 1. The ULP app name must be unique (if multiple components use ULP).
set(ulp_app_name ulp_${COMPONENT_NAME})
#
# 2. Specify all C and Assembly source files.
# Files should be placed into a separate directory (in this case, ulp/),
# which should not be added to COMPONENT_SRCS.
set(ulp_riscv_sources "ulp/main.c")
#
# 3. List all the component source files which include automatically
# generated ULP export file, ${ulp_app_name}.h:
set(ulp_exp_dep_srcs "ulp_riscv_rtc_i2c_example_main.c")
#
# 4. Call function to build ULP binary and embed in project using the argument
# values above.
ulp_embed_binary(${ulp_app_name} "${ulp_riscv_sources}" "${ulp_exp_dep_srcs}")
@@ -0,0 +1,110 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once
/***************************************************
* BMP180 Register Addresses
***************************************************/
#define BMP180_SENSOR_I2C_ADDR 0x77
#define BMP180_SENSOR_REG_ADDR_WHO_AM_I 0xD0
#define BMP180_SENSOR_REG_ADDR_SOFT_RESET 0xE0
#define BMP180_SENSOR_REG_ADDR_AC1_MSB 0xAA
#define BMP180_SENSOR_REG_ADDR_AC1_LSB 0xAB
#define BMP180_SENSOR_REG_ADDR_AC2_MSB 0xAC
#define BMP180_SENSOR_REG_ADDR_AC2_LSB 0xAD
#define BMP180_SENSOR_REG_ADDR_AC3_MSB 0xAE
#define BMP180_SENSOR_REG_ADDR_AC3_LSB 0xAF
#define BMP180_SENSOR_REG_ADDR_AC4_MSB 0xB0
#define BMP180_SENSOR_REG_ADDR_AC4_LSB 0xB1
#define BMP180_SENSOR_REG_ADDR_AC5_MSB 0xB2
#define BMP180_SENSOR_REG_ADDR_AC5_LSB 0xB3
#define BMP180_SENSOR_REG_ADDR_AC6_MSB 0xB4
#define BMP180_SENSOR_REG_ADDR_AC6_LSB 0xB5
#define BMP180_SENSOR_REG_ADDR_B1_MSB 0xB6
#define BMP180_SENSOR_REG_ADDR_B1_LSB 0xB7
#define BMP180_SENSOR_REG_ADDR_B2_MSB 0xB8
#define BMP180_SENSOR_REG_ADDR_B2_LSB 0xB9
#define BMP180_SENSOR_REG_ADDR_MB_MSB 0xBA
#define BMP180_SENSOR_REG_ADDR_MB_LSB 0xBB
#define BMP180_SENSOR_REG_ADDR_MC_MSB 0xBC
#define BMP180_SENSOR_REG_ADDR_MC_LSB 0xBD
#define BMP180_SENSOR_REG_ADDR_MD_MSB 0xBE
#define BMP180_SENSOR_REG_ADDR_MD_LSB 0xBF
#define BMP180_SENSOR_REG_ADDR_CTRL_REG 0xF4
#define BMP180_SENSOR_REG_ADDR_SENSOR_DATA_MSB 0xF6
#define BMP180_SENSOR_REG_ADDR_SENSOR_DATA_LSB 0xF7
#define BMP180_SENSOR_REG_ADDR_SENSOR_DATA_XLSB 0xF8
/***************************************************
* BMP180 Control Commands
***************************************************/
#define BMP180_SENSOR_CMD_READ_TEMPERATURE 0x2E
#define BMP180_SENSOR_CMD_READ_PRESSURE_OSS_0 0x34
#define BMP180_SENSOR_CMD_READ_PRESSURE_OSS_1 0x74
#define BMP180_SENSOR_CMD_READ_PRESSURE_OSS_2 0xB4
#define BMP180_SENSOR_CMD_READ_PRESSURE_OSS_3 0xF4
#define BMP180_SENSOR_CMD_SOFT_RESET 0xB6
/***************************************************
* BMP180 Chip ID
***************************************************/
#define BMP180_SENSOR_CHIP_ID 0x55
/***************************************************
* BMP180 Calibration Data
***************************************************/
typedef struct {
int16_t ac1;
int16_t ac2;
int16_t ac3;
uint16_t ac4;
uint16_t ac5;
uint16_t ac6;
int16_t b1;
int16_t b2;
int16_t mb;
int16_t mc;
int16_t md;
} bmp180_cal_data_t;
bmp180_cal_data_t bmp180_cal_data;
/***************************************************
* BMP180 Oversampling setting to measure pressure
***************************************************/
typedef enum {
OSS_0 = 0, // Ultra low power
OSS_1 = 1, // Standard
OSS_2 = 2, // High resolution
OSS_3 = 3 // Ultra high resolution
} oss_mode_t;
/***************************************************
* BMP180 Interaction APIs
***************************************************/
static void bmp180_read_cal_data(void); // Read cal data
static void bmp180_read_ut_data(int16_t *ut_data); // Read uncompensated temperature
static void bmp180_read_up_data(int32_t *up_data, oss_mode_t oss_mode); // Read uncompensated pressure
/************************************************
* BMP180 Utility APIs
************************************************/
static void bmp180_read16(uint16_t *data_out, uint32_t reg_msb, uint32_t reg_lsb);
static int32_t bmp180_calculate_real_temp(int32_t ut_data);
static int32_t bmp180_calculate_real_pressure(int32_t up_data, int32_t ut_data, oss_mode_t oss_mode);
/************************************************
* Pressure measurement mode
************************************************/
#define EXAMPLE_OSS_MODE OSS_0
/************************************************
* Temperature and Pressure thresholds (uncompensated) to wake up Main CPU
* The threshold values have been selected for demp purposes and may not
* represent real world use case.
************************************************/
#define EXAMPLE_UT_THRESHOLD 20000
#define EXAMPLE_UP_THRESHOLD 40000
@@ -0,0 +1,126 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* ULP RISC-V RTC I2C example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
This code runs on ULP RISC-V coprocessor
*/
#include <stdint.h>
#include "ulp_riscv.h"
#include "ulp_riscv_utils.h"
#include "ulp_riscv_i2c_ulp_core.h"
#include "../bmp180_defs.h"
/************************************************
* Shared data between main CPU and ULP
************************************************/
int16_t ut_data = 0;
int32_t up_data = 0;
int32_t ut_threshold = EXAMPLE_UT_THRESHOLD;
int32_t up_threshold = EXAMPLE_UP_THRESHOLD;
oss_mode_t oss_mode = EXAMPLE_OSS_MODE;
int main (void)
{
/* Read uncompensated temperature */
bmp180_read_ut_data(&ut_data);
/* Read uncompensated pressure */
bmp180_read_up_data(&up_data, oss_mode);
/* Wakeup the main CPU if either the uncompensated temperature or uncompensated pressure values
* are more than their respective threshold values.
*/
if ((ut_data > ut_threshold) || (up_data > up_threshold)) {
ulp_riscv_wakeup_main_processor();
}
return 0;
}
static void bmp180_read16(uint16_t *data_out, uint32_t reg_msb, uint32_t reg_lsb)
{
uint8_t data_rd = 0;
*data_out = 0;
ulp_riscv_i2c_master_set_slave_reg_addr(reg_msb);
ulp_riscv_i2c_master_read_from_device(&data_rd, 1);
*data_out |= (uint16_t)(data_rd << 8);
ulp_riscv_i2c_master_set_slave_reg_addr(reg_lsb);
data_rd = 0;
ulp_riscv_i2c_master_read_from_device(&data_rd, 1);
*data_out |= (uint16_t)(data_rd);
}
static void bmp180_read_ut_data(int16_t *ut_data)
{
/* Set slave register address to the control register */
ulp_riscv_i2c_master_set_slave_reg_addr(BMP180_SENSOR_REG_ADDR_CTRL_REG);
/* Setup control register to read temperature */
uint8_t cmd = BMP180_SENSOR_CMD_READ_TEMPERATURE;
ulp_riscv_i2c_master_write_to_device(&cmd, 1);
/* Wait at least 4.5 milliseconds for the sensor to complete the reading */
ulp_riscv_delay_cycles(5 * ULP_RISCV_CYCLES_PER_US * 1000);
/* Read uncompensated temperature data */
bmp180_read16((uint16_t *)ut_data, BMP180_SENSOR_REG_ADDR_SENSOR_DATA_MSB, BMP180_SENSOR_REG_ADDR_SENSOR_DATA_LSB);
}
static void bmp180_read_up_data(int32_t *up_data, oss_mode_t oss_mode)
{
uint16_t press_high;
uint8_t press_low;
/* Set slave register address to the control register */
ulp_riscv_i2c_master_set_slave_reg_addr(BMP180_SENSOR_REG_ADDR_CTRL_REG);
/* Setup control register to read pressure */
uint8_t cmd = 0;
uint8_t wait = 0;
switch(oss_mode)
{
case OSS_0:
cmd = BMP180_SENSOR_CMD_READ_PRESSURE_OSS_0;
wait = 5; // Wait atleast 4.5 msec
break;
case OSS_1:
cmd = BMP180_SENSOR_CMD_READ_PRESSURE_OSS_1;
wait = 8; // Wait atleast 7.5 msec
break;
case OSS_2:
cmd = BMP180_SENSOR_CMD_READ_PRESSURE_OSS_2;
wait = 14; // Wait atleast 13.5 msec
break;
case OSS_3:
cmd = BMP180_SENSOR_CMD_READ_PRESSURE_OSS_3;
wait = 26; // Wait atleast 25.5 msec
break;
}
ulp_riscv_i2c_master_write_to_device(&cmd, 1);
/* Wait for the required amount of time for the sensor to complete the reading */
ulp_riscv_delay_cycles(wait * ULP_RISCV_CYCLES_PER_US * 1000);
/* Read uncompensated temperature data */
/* Read MSB + LSB */
bmp180_read16(&press_high, BMP180_SENSOR_REG_ADDR_SENSOR_DATA_MSB, BMP180_SENSOR_REG_ADDR_SENSOR_DATA_LSB);
/* Read XLSB */
ulp_riscv_i2c_master_set_slave_reg_addr(BMP180_SENSOR_REG_ADDR_SENSOR_DATA_XLSB);
ulp_riscv_i2c_master_read_from_device(&press_low, 1);
*up_data = (((uint32_t)press_high << 8) + (uint32_t)press_low) >> (8 - oss_mode);
}
@@ -0,0 +1,351 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* ULP RISC-V RTC I2C example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <math.h>
#include "esp_sleep.h"
#include "ulp_riscv.h"
#include "ulp_riscv_i2c.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ulp_main.h"
#include "bmp180_defs.h"
extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
/************************************************
* ULP utility APIs
************************************************/
static void init_ulp_program(void);
/************************************************
* RTC I2C utility APIs
************************************************/
static void init_i2c(void);
void app_main(void)
{
uint8_t data_rd = 0;
int16_t ut_data = 0;
int32_t up_data = 0;
int32_t temperature = 0;
int32_t pressure = 0;
oss_mode_t oss_mode;
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
/* Not a wakeup from ULP
* Initialize RTC I2C
* Setup BMP180 sensor
* Store current temperature and pressure values
* Load the ULP firmware
* Go to deep sleep
*/
if (cause != ESP_SLEEP_WAKEUP_ULP) {
printf("Not a ULP-RISC V wakeup (cause = %d)\n", cause);
/* Initialize RTC I2C */
init_i2c();
/* Configure I2C slave address */
ulp_riscv_i2c_master_set_slave_addr(BMP180_SENSOR_I2C_ADDR);
/* Reset the BMP180 sensor*/
ulp_riscv_i2c_master_set_slave_reg_addr(BMP180_SENSOR_REG_ADDR_SOFT_RESET);
uint8_t data_wr = BMP180_SENSOR_CMD_SOFT_RESET;
ulp_riscv_i2c_master_write_to_device(&data_wr, 1);
/* Confirm that the sensor is alive
* The BMP180 returns the chip id 0x55 on quering reg addr 0xD0
*/
ulp_riscv_i2c_master_set_slave_reg_addr(BMP180_SENSOR_REG_ADDR_WHO_AM_I);
ulp_riscv_i2c_master_read_from_device(&data_rd, 1);
if (data_rd != BMP180_SENSOR_CHIP_ID) {
printf("ERROR: Cannot communicate with I2C sensor\n");
abort();
}
/* Read the calibration data */
printf("Reading calibration data from BMP180 ...\n");
bmp180_read_cal_data();
printf("\n");
/* Read uncompensated temperature and pressure */
printf("Reading initial uncompensated temperature and pressure data ...\n");
ut_data = 0;
up_data = 0;
oss_mode = EXAMPLE_OSS_MODE;
bmp180_read_ut_data(&ut_data);
bmp180_read_up_data(&up_data, oss_mode);
printf("Uncompensated Temperature = %d\n", ut_data);
printf("Uncompensated Pressure = %d\n", up_data);
printf("\n");
/* Calculate real temperature value */
temperature = bmp180_calculate_real_temp((int32_t)ut_data);
printf("Real Temperature = %f deg celcius\n", (float)(temperature/10.0));
/* Calculate real pressure value */
pressure = bmp180_calculate_real_pressure(up_data, (int32_t)ut_data, oss_mode);
printf("Real Pressure = %f hPa\n", pressure / 100.0);
printf("\n");
/* Load ULP firmware
*
* The ULP is responsible of monitoring the temperature and pressure values
* periodically. It will wakeup the main CPU if the temperature and pressure
* values are above a certain threshold.
*/
init_ulp_program();
}
/* ULP RISC-V read and detected a temperature or pressure above the limit */
if (cause == ESP_SLEEP_WAKEUP_ULP) {
printf("ULP RISC-V woke up the main CPU\n");
/* Pause ULP while we are using the RTC I2C from the main CPU */
ulp_timer_stop();
ulp_riscv_halt();
printf("Uncompensated Temperature = %d\n", ulp_ut_data);
printf("Uncompensated Pressure = %d\n", ulp_up_data);
/* Read the calibration data again */
printf("Reading calibration data from BMP180 ...\n");
bmp180_read_cal_data();
printf("\n");
/* Calculate real temperature and pressure again */
temperature = 0;
temperature = bmp180_calculate_real_temp((int32_t)ulp_ut_data);
printf("New Real Temperature = %f deg celcius\n", (float)(temperature/10.0));
/* Calculate real pressure value */
pressure = 0;
pressure = bmp180_calculate_real_pressure(ulp_up_data, (int32_t)ulp_ut_data, oss_mode);
printf("New Real Pressure = %f hPa\n", pressure / 100.0);
/* Resume ULP and go to deep sleep again */
ulp_timer_resume();
}
/* Add a delay for everything to the printed before heading in to light sleep */
vTaskDelay(100);
/* Go back to sleep, only the ULP RISC-V will run */
printf("Entering deep sleep\n\n");
/* RTC peripheral power domain needs to be kept on to keep RTC I2C related configs during sleep */
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
ESP_ERROR_CHECK(esp_sleep_enable_ulp_wakeup());
esp_deep_sleep_start();
}
static void init_i2c(void)
{
/* Configure RTC I2C */
printf("Initializing RTC I2C ...\n");
ulp_riscv_i2c_cfg_t i2c_cfg = ULP_RISCV_I2C_DEFAULT_CONFIG();
ulp_riscv_i2c_master_init(&i2c_cfg);
}
static void bmp180_read16(uint16_t *data_out, uint32_t reg_msb, uint32_t reg_lsb)
{
uint8_t data_rd = 0;
*data_out = 0;
ulp_riscv_i2c_master_set_slave_reg_addr(reg_msb);
ulp_riscv_i2c_master_read_from_device(&data_rd, 1);
*data_out |= (uint16_t)(data_rd << 8);
ulp_riscv_i2c_master_set_slave_reg_addr(reg_lsb);
data_rd = 0;
ulp_riscv_i2c_master_read_from_device(&data_rd, 1);
*data_out |= (uint16_t)(data_rd);
}
static void bmp180_read_cal_data(void)
{
/* AC1 */
bmp180_read16((uint16_t *)&bmp180_cal_data.ac1, BMP180_SENSOR_REG_ADDR_AC1_MSB, BMP180_SENSOR_REG_ADDR_AC1_LSB);
printf("ac1 = %d\n", bmp180_cal_data.ac1);
/* AC2 */
bmp180_read16((uint16_t *)&bmp180_cal_data.ac2, BMP180_SENSOR_REG_ADDR_AC2_MSB, BMP180_SENSOR_REG_ADDR_AC2_LSB);
printf("ac2 = %d\n", bmp180_cal_data.ac2);
/* AC3 */
bmp180_read16((uint16_t *)&bmp180_cal_data.ac3, BMP180_SENSOR_REG_ADDR_AC3_MSB, BMP180_SENSOR_REG_ADDR_AC3_LSB);
printf("ac3 = %d\n", bmp180_cal_data.ac3);
/* AC4 */
bmp180_read16(&bmp180_cal_data.ac4, BMP180_SENSOR_REG_ADDR_AC4_MSB, BMP180_SENSOR_REG_ADDR_AC4_LSB);
printf("ac4 = %u\n", bmp180_cal_data.ac4);
/* AC5 */
bmp180_read16(&bmp180_cal_data.ac5, BMP180_SENSOR_REG_ADDR_AC5_MSB, BMP180_SENSOR_REG_ADDR_AC5_LSB);
printf("ac5 = %u\n", bmp180_cal_data.ac5);
/* AC6 */
bmp180_read16(&bmp180_cal_data.ac6, BMP180_SENSOR_REG_ADDR_AC6_MSB, BMP180_SENSOR_REG_ADDR_AC6_LSB);
printf("ac6 = %u\n", bmp180_cal_data.ac6);
/* B1 */
bmp180_read16((uint16_t *)&bmp180_cal_data.b1, BMP180_SENSOR_REG_ADDR_B1_MSB, BMP180_SENSOR_REG_ADDR_B1_LSB);
printf("b1 = %d\n", bmp180_cal_data.b1);
/* B2 */
bmp180_read16((uint16_t *)&bmp180_cal_data.b2, BMP180_SENSOR_REG_ADDR_B2_MSB, BMP180_SENSOR_REG_ADDR_B2_LSB);
printf("b2 = %d\n", bmp180_cal_data.b2);
/* MB */
bmp180_read16((uint16_t *)&bmp180_cal_data.mb, BMP180_SENSOR_REG_ADDR_MB_MSB, BMP180_SENSOR_REG_ADDR_MB_LSB);
printf("mb = %d\n", bmp180_cal_data.mb);
/* MC */
bmp180_read16((uint16_t *)&bmp180_cal_data.mc, BMP180_SENSOR_REG_ADDR_MC_MSB, BMP180_SENSOR_REG_ADDR_MC_LSB);
printf("mc = %d\n", bmp180_cal_data.mc);
/* MD */
bmp180_read16((uint16_t *)&bmp180_cal_data.md, BMP180_SENSOR_REG_ADDR_MD_MSB, BMP180_SENSOR_REG_ADDR_MD_LSB);
printf("md = %d\n", bmp180_cal_data.md);
}
static void bmp180_read_ut_data(int16_t *ut_data)
{
/* Set slave register address to the control register */
ulp_riscv_i2c_master_set_slave_reg_addr(BMP180_SENSOR_REG_ADDR_CTRL_REG);
/* Setup control register to read temperature */
uint8_t cmd = BMP180_SENSOR_CMD_READ_TEMPERATURE;
ulp_riscv_i2c_master_write_to_device(&cmd, 1);
/* Wait at least 4.5 milliseconds for the sensor to complete the reading */
vTaskDelay(pdMS_TO_TICKS(5));
/* Read uncompensated temperature data */
bmp180_read16((uint16_t *)ut_data, BMP180_SENSOR_REG_ADDR_SENSOR_DATA_MSB, BMP180_SENSOR_REG_ADDR_SENSOR_DATA_LSB);
}
static int32_t computeb5(int32_t ut_data)
{
int32_t x1 = (ut_data - (int32_t)bmp180_cal_data.ac6) * ((int32_t)bmp180_cal_data.ac5) >> 15;
int32_t x2 = ((int32_t)bmp180_cal_data.mc << 11) / (x1 + (int32_t)bmp180_cal_data.md);
return x1 + x2;
}
static int32_t bmp180_calculate_real_temp(int32_t ut_data)
{
int32_t b5 = computeb5(ut_data);
int32_t t = (b5 + 8) >> 4;
return t;
}
static void bmp180_read_up_data(int32_t *up_data, oss_mode_t oss_mode)
{
uint16_t press_high;
uint8_t press_low;
/* Set slave register address to the control register */
ulp_riscv_i2c_master_set_slave_reg_addr(BMP180_SENSOR_REG_ADDR_CTRL_REG);
/* Setup control register to read pressure */
uint8_t cmd = 0;
uint8_t wait = 0;
switch(oss_mode)
{
case OSS_0:
cmd = BMP180_SENSOR_CMD_READ_PRESSURE_OSS_0;
wait = 5; // Wait atleast 4.5 msec
break;
case OSS_1:
cmd = BMP180_SENSOR_CMD_READ_PRESSURE_OSS_1;
wait = 8; // Wait atleast 7.5 msec
break;
case OSS_2:
cmd = BMP180_SENSOR_CMD_READ_PRESSURE_OSS_2;
wait = 14; // Wait atleast 13.5 msec
break;
case OSS_3:
cmd = BMP180_SENSOR_CMD_READ_PRESSURE_OSS_3;
wait = 26; // Wait atleast 25.5 msec
break;
}
ulp_riscv_i2c_master_write_to_device(&cmd, 1);
/* Wait for the required amount of time for the sensor to complete the reading */
vTaskDelay(pdMS_TO_TICKS(wait));
/* Read uncompensated temperature data */
/* Read MSB + LSB */
bmp180_read16(&press_high, BMP180_SENSOR_REG_ADDR_SENSOR_DATA_MSB, BMP180_SENSOR_REG_ADDR_SENSOR_DATA_LSB);
/* Read XLSB */
ulp_riscv_i2c_master_set_slave_reg_addr(BMP180_SENSOR_REG_ADDR_SENSOR_DATA_XLSB);
ulp_riscv_i2c_master_read_from_device(&press_low, 1);
*up_data = (((uint32_t)press_high << 8) + (uint32_t)press_low) >> (8 - oss_mode);
}
static int32_t bmp180_calculate_real_pressure(int32_t up_data, int32_t ut_data, oss_mode_t oss_mode)
{
int32_t p, x1, x2, x3, b3, b5, b6;
uint32_t b4, b7;
b5 = computeb5(ut_data);
b6 = b5 - 4000;
x1 = (bmp180_cal_data.b2 * ((b6 * b6) >> 12)) >> 11;
x2 = (bmp180_cal_data.ac2 * b6) >> 11;
x3 = x1 + x2;
b3 = (((((int32_t) bmp180_cal_data.ac1) * 4 + x3) << oss_mode) + 2) >> 2;
x1 = (bmp180_cal_data.ac3 * b6) >> 13;
x2 = (bmp180_cal_data.b1 * ((b6 * b6) >> 12)) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (bmp180_cal_data.ac4 * (uint32_t) (x3 + 32768)) >> 15;
b7 = ((uint32_t) (up_data - b3) * (50000 >> oss_mode));
if (b7 < 0x80000000) {
p = (b7 << 1) / b4;
} else {
p = (b7 / b4) << 1;
}
x1 = (p >> 8) * (p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
p = p + ((x1 + x2 + 3791) >> 4);
return p;
}
static void init_ulp_program(void)
{
esp_err_t err = ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start));
ESP_ERROR_CHECK(err);
/* The first argument is the period index, which is not used by the ULP-RISC-V timer
* The second argument is the period in microseconds, which gives a wakeup time period of: 20ms
*/
ulp_set_wakeup_period(0, 20000);
/* Start the program */
err = ulp_riscv_run();
ESP_ERROR_CHECK(err);
}
@@ -0,0 +1,9 @@
# Enable ULP
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_RISCV=y
CONFIG_ULP_COPROC_RESERVE_MEM=4096
# Set log level to Warning to produce clean output
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
CONFIG_BOOTLOADER_LOG_LEVEL=2
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
CONFIG_LOG_DEFAULT_LEVEL=2