mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-10 04:43:33 +00:00
lp-i2c: Added support for LP I2C peripheral to LP core
This commit adds support for the LP I2C peripheral driver to be used by the LP core. An example is also added to demonstrate the usage of the LP I2C peripheral from the LP core.
This commit is contained in:
@@ -90,6 +90,10 @@ examples/system/light_sleep:
|
||||
temporary: true
|
||||
reason: target(s) not supported yet
|
||||
|
||||
examples/system/lp_core/lp_i2c:
|
||||
enable:
|
||||
- if: SOC_LP_I2C_SUPPORTED == 1
|
||||
|
||||
examples/system/ota/advanced_https_ota:
|
||||
disable:
|
||||
- if: IDF_TARGET == "esp32h2"
|
||||
|
7
examples/system/lp_core/lp_i2c/CMakeLists.txt
Normal file
7
examples/system/lp_core/lp_i2c/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
list(APPEND SDKCONFIG_DEFAULTS "sdkconfig.defaults")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(lp_i2c_example)
|
63
examples/system/lp_core/lp_i2c/README.md
Normal file
63
examples/system/lp_core/lp_i2c/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
| Supported Targets | ESP32-C6 |
|
||||
| ----------------- | -------- |
|
||||
|
||||
# LP I2C Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## Overview
|
||||
|
||||
This example demonstrates basic usage of the LP I2C driver from the LP core by reading to and writing from a sensor connected over I2C.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
To run this example, you should have a ESP32-C6 based development board as well as a BH1750 sensor. BH1750 is an ambient light sensor. More information about it can be found in the [BH1750 datasheet](https://www.mouser.com/datasheet/2/348/bh1750fvi-e-186247.pdf).
|
||||
|
||||
#### Pin Assignment:
|
||||
|
||||
**Note:** The following pin assignments are used by default.
|
||||
|
||||
| | SDA | SCL |
|
||||
| ----------------------- | ------| ------|
|
||||
| ESP32-C6 LP I2C Master | GPIO6 | GPIO7 |
|
||||
| BH1750 Sensor | SDA | SCL |
|
||||
|
||||
**Note:** There's no need to add an external pull-up resistors for SDA/SCL pin, because the driver enables the internal pull-up resistors.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Enter `idf.py -p PORT flash monitor` to build, flash and monitor the project.
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
The log output should indicate that the LP core and the LP I2C peripheral have been successfully initialized. The main CPU would then enter deep sleep mode. The LP Core should wakeup the main CPU if the Light Intensity Value breaches the set thresholds.
|
||||
|
||||
```bash
|
||||
Not an LP core wakeup. Cause = 0
|
||||
Initializing...
|
||||
LP core loaded with firmware successfully
|
||||
LP I2C initialized successfully
|
||||
Entering deep sleep...
|
||||
|
||||
(When the BH1750 sensor is shielded from a light source, the Lux value should be smaller and the LP core should wakeup the main CPU)
|
||||
|
||||
LP core woke up the main CPU
|
||||
Lux = 3
|
||||
Entering deep sleep...
|
||||
|
||||
(When the BH1750 sensor is exposed to a direct light source, the Lux value should be larger and the LP core should wakup the main CPU)
|
||||
|
||||
LP core woke up the main CPU
|
||||
Lux = 1222
|
||||
Entering deep sleep...
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.)
|
25
examples/system/lp_core/lp_i2c/main/CMakeLists.txt
Normal file
25
examples/system/lp_core/lp_i2c/main/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
# Register the component
|
||||
idf_component_register(SRCS "lp_i2c_main.c"
|
||||
INCLUDE_DIRS ""
|
||||
REQUIRES ulp)
|
||||
|
||||
#
|
||||
# ULP support additions to component CMakeLists.txt.
|
||||
#
|
||||
# 1. The LP Core app name must be unique (if multiple components use LP Core).
|
||||
set(ulp_app_name lp_core_${COMPONENT_NAME})
|
||||
#
|
||||
# 2. Specify all C files.
|
||||
# Files should be placed into a separate directory (in this case, lp_core/),
|
||||
# which should not be added to COMPONENT_SRCS.
|
||||
set(ulp_lp_core_sources "lp_core/main.c")
|
||||
|
||||
#
|
||||
# 3. List all the component source files which include automatically
|
||||
# generated LP Core export file, ${ulp_app_name}.h:
|
||||
set(ulp_exp_dep_srcs "lp_i2c_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_lp_core_sources}" "${ulp_exp_dep_srcs}")
|
23
examples/system/lp_core/lp_i2c/main/bh1750_defs.h
Normal file
23
examples/system/lp_core/lp_i2c/main/bh1750_defs.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/***************************************************
|
||||
* BH1750 Register Addresses
|
||||
***************************************************/
|
||||
#define BH1750_I2C_ADDR 0x23
|
||||
#define BH1750_POWER_ON 0x01
|
||||
#define BH1750_CONTINUOUS_H_RES_MODE 0x10
|
||||
#define BH1750_CONTINUOUS_H_RES_MODE2 0x11
|
||||
#define BH1750_CONTINUOUS_L_RES_MODE 0x13
|
||||
#define BH1750_ONE_TIME_H_RES_MODE 0x20
|
||||
#define BH1750_ONE_TIME_H_RES_MODE2 0x21
|
||||
#define BH1750_ONE_TIME_L_RES_MODE 0x23
|
||||
|
||||
/***************************************************
|
||||
* Example configurations
|
||||
***************************************************/
|
||||
#define EXAMPLE_RES_MODE BH1750_CONTINUOUS_H_RES_MODE
|
75
examples/system/lp_core/lp_i2c/main/lp_core/main.c
Normal file
75
examples/system/lp_core/lp_i2c/main/lp_core/main.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "ulp_lp_core_i2c.h"
|
||||
#include "ulp_lp_core_utils.h"
|
||||
#include "../bh1750_defs.h"
|
||||
|
||||
#define LP_I2C_TRANS_TIMEOUT_CYCLES 5000
|
||||
#define LP_I2C_TRANS_WAIT_FOREVER -1
|
||||
|
||||
#define LUX_THRESHOLD_LOW 5
|
||||
#define LUX_THRESHOLD_HIGH 1000
|
||||
|
||||
static uint32_t sensor_on = 0;
|
||||
static uint32_t res_update_done = 0;
|
||||
volatile uint32_t lux = 0;
|
||||
|
||||
static void bh1750_read()
|
||||
{
|
||||
uint8_t data_rd[2];
|
||||
esp_err_t ret = lp_core_i2c_master_read_from_device(LP_I2C_NUM_0, BH1750_I2C_ADDR, data_rd, sizeof(data_rd), LP_I2C_TRANS_TIMEOUT_CYCLES);
|
||||
if (ret != ESP_OK) {
|
||||
// Skip this round of calculation and return
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate light intensity value */
|
||||
uint16_t level = ((data_rd[0] << 8) | data_rd[1]);
|
||||
lux = (level * 10) / 12;
|
||||
|
||||
/* Wakeup main CPU if the Lux breaches the thresholds */
|
||||
if (lux < LUX_THRESHOLD_LOW || lux > LUX_THRESHOLD_HIGH) {
|
||||
ulp_lp_core_wakeup_main_processor();
|
||||
}
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
uint8_t data_wr = 0;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
while (1) {
|
||||
if (!sensor_on) {
|
||||
/* Power ON the sensor */
|
||||
data_wr = BH1750_POWER_ON;
|
||||
ret = lp_core_i2c_master_write_to_device(LP_I2C_NUM_0, BH1750_I2C_ADDR, &data_wr, sizeof(data_wr), LP_I2C_TRANS_WAIT_FOREVER);
|
||||
if (ret != ESP_OK) {
|
||||
// Bail and try again
|
||||
continue;
|
||||
}
|
||||
sensor_on = 1;
|
||||
}
|
||||
|
||||
if (!res_update_done) {
|
||||
data_wr = EXAMPLE_RES_MODE;
|
||||
ret = lp_core_i2c_master_write_to_device(LP_I2C_NUM_0, BH1750_I2C_ADDR, &data_wr, sizeof(data_wr), LP_I2C_TRANS_WAIT_FOREVER);
|
||||
if (ret != ESP_OK) {
|
||||
// Bail and try again
|
||||
continue;
|
||||
}
|
||||
res_update_done = 1;
|
||||
}
|
||||
|
||||
/* Read BH1750 sensor data */
|
||||
bh1750_read();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
77
examples/system/lp_core/lp_i2c/main/lp_i2c_main.c
Normal file
77
examples/system/lp_core/lp_i2c/main/lp_i2c_main.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "esp_sleep.h"
|
||||
#include "lp_core_main.h"
|
||||
#include "ulp_lp_core.h"
|
||||
#include "lp_core_i2c.h"
|
||||
|
||||
extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_main_bin_start");
|
||||
extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_main_bin_end");
|
||||
|
||||
static void lp_core_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ulp_lp_core_cfg_t cfg = {
|
||||
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU,
|
||||
};
|
||||
|
||||
ret = ulp_lp_core_load_binary(lp_core_main_bin_start, (lp_core_main_bin_end - lp_core_main_bin_start));
|
||||
if (ret != ESP_OK) {
|
||||
printf("LP Core load failed\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
ret = ulp_lp_core_run(&cfg);
|
||||
if (ret != ESP_OK) {
|
||||
printf("LP Core run failed\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
printf("LP core loaded with firmware successfully\n");
|
||||
}
|
||||
|
||||
static void lp_i2c_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
/* Initialize LP I2C with default configuration */
|
||||
const lp_core_i2c_cfg_t i2c_cfg = LP_CORE_I2C_DEFAULT_CONFIG();
|
||||
ret = lp_core_i2c_master_init(LP_I2C_NUM_0, &i2c_cfg);
|
||||
if (ret != ESP_OK) {
|
||||
printf("LP I2C init failed\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
printf("LP I2C initialized successfully\n");
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||
if (cause != ESP_SLEEP_WAKEUP_ULP) {
|
||||
printf("Not an LP core wakeup. Cause = %d\n", cause);
|
||||
printf("Initializing...\n");
|
||||
|
||||
/* Initialize LP_I2C from the main processor */
|
||||
lp_i2c_init();
|
||||
|
||||
/* Load LP Core binary and start the coprocessor */
|
||||
lp_core_init();
|
||||
} else if (cause == ESP_SLEEP_WAKEUP_ULP) {
|
||||
printf("LP core woke up the main CPU\n");
|
||||
printf("Lux = %ld\n", ulp_lux);
|
||||
}
|
||||
|
||||
/* Setup wakeup triggers */
|
||||
ESP_ERROR_CHECK(esp_sleep_enable_ulp_wakeup());
|
||||
|
||||
/* Enter Deep Sleep */
|
||||
printf("Entering deep sleep...\n");
|
||||
esp_deep_sleep_start();
|
||||
}
|
10
examples/system/lp_core/lp_i2c/sdkconfig.defaults
Normal file
10
examples/system/lp_core/lp_i2c/sdkconfig.defaults
Normal file
@@ -0,0 +1,10 @@
|
||||
# Enable LP Core
|
||||
CONFIG_ULP_COPROC_ENABLED=y
|
||||
CONFIG_ULP_COPROC_TYPE_LP_CORE=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
|
Reference in New Issue
Block a user