mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-05 13:44:32 +02:00
RISCV-ULP: Add DS18B20 1wire RISCV-ULP example
This commit is contained in:
@@ -32,12 +32,14 @@
|
|||||||
esp_err_t ulp_riscv_run(void)
|
esp_err_t ulp_riscv_run(void)
|
||||||
{
|
{
|
||||||
/* Reset COCPU when power on. */
|
/* Reset COCPU when power on. */
|
||||||
SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_CLK_FO);
|
|
||||||
SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN);
|
SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN);
|
||||||
esp_rom_delay_us(20);
|
esp_rom_delay_us(20);
|
||||||
CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_CLK_FO);
|
|
||||||
CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN);
|
CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN);
|
||||||
|
|
||||||
|
/* The coprocessor cpu trap signal doesnt have a stable reset value,
|
||||||
|
force ULP-RISC-V clock on to stop RTC_COCPU_TRAP_TRIG_EN from waking the CPU*/
|
||||||
|
SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_CLK_FO);
|
||||||
|
|
||||||
/* Disable ULP timer */
|
/* Disable ULP timer */
|
||||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);
|
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);
|
||||||
/* wait for at least 1 RTC_SLOW_CLK cycle */
|
/* wait for at least 1 RTC_SLOW_CLK cycle */
|
||||||
|
@@ -20,6 +20,8 @@ extern "C" {
|
|||||||
|
|
||||||
#include "ulp_riscv/ulp_riscv.h"
|
#include "ulp_riscv/ulp_riscv.h"
|
||||||
#include "soc/rtc_io_reg.h"
|
#include "soc/rtc_io_reg.h"
|
||||||
|
#include "soc/sens_reg.h"
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GPIO_NUM_0 = 0, /*!< GPIO0, input and output */
|
GPIO_NUM_0 = 0, /*!< GPIO0, input and output */
|
||||||
@@ -51,38 +53,39 @@ typedef enum {
|
|||||||
RTCIO_MODE_OUTPUT_OD = 1,
|
RTCIO_MODE_OUTPUT_OD = 1,
|
||||||
} rtc_io_out_mode_t;
|
} rtc_io_out_mode_t;
|
||||||
|
|
||||||
static inline void example_ulp_gpio_init(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_init(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
|
SET_PERI_REG_MASK(SENS_SAR_IO_MUX_CONF_REG, SENS_IOMUX_CLK_GATE_EN_M);
|
||||||
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_MUX_SEL);
|
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_MUX_SEL);
|
||||||
REG_SET_FIELD(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_SEL, 0);
|
REG_SET_FIELD(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_SEL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_deinit(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_deinit(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_MUX_SEL);
|
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_MUX_SEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_output_enable(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_output_enable(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
REG_SET_FIELD(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS, BIT(gpio_num));
|
REG_SET_FIELD(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS, BIT(gpio_num));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_output_disable(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_output_disable(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
REG_SET_FIELD(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC, BIT(gpio_num));
|
REG_SET_FIELD(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC, BIT(gpio_num));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_input_enable(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_input_enable(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_IE);
|
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_IE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_input_disable(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_input_disable(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_IE);
|
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_IE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_output_level(gpio_num_t gpio_num, uint8_t level)
|
static inline void ulp_riscv_gpio_output_level(gpio_num_t gpio_num, uint8_t level)
|
||||||
{
|
{
|
||||||
if (level) {
|
if (level) {
|
||||||
REG_SET_FIELD(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS, BIT(gpio_num));
|
REG_SET_FIELD(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS, BIT(gpio_num));
|
||||||
@@ -91,32 +94,32 @@ static inline void example_ulp_gpio_output_level(gpio_num_t gpio_num, uint8_t le
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint8_t example_ulp_gpio_get_level(gpio_num_t gpio_num)
|
static inline uint8_t ulp_riscv_gpio_get_level(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
return (uint8_t)((REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & BIT(gpio_num)) ? 1 : 0);
|
return (uint8_t)((REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & BIT(gpio_num)) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_set_output_mode(gpio_num_t gpio_num, rtc_io_out_mode_t mode)
|
static inline void ulp_riscv_gpio_set_output_mode(gpio_num_t gpio_num, rtc_io_out_mode_t mode)
|
||||||
{
|
{
|
||||||
REG_SET_FIELD(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_DRV, mode);
|
REG_SET_FIELD(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_DRV, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_pullup(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_pullup(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RUE);
|
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_pullup_disable(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_pullup_disable(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RUE);
|
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_pulldown(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_pulldown(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RDE);
|
SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void example_ulp_gpio_pulldown_disable(gpio_num_t gpio_num)
|
static inline void ulp_riscv_gpio_pulldown_disable(gpio_num_t gpio_num)
|
||||||
{
|
{
|
||||||
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RDE);
|
CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_RDE);
|
||||||
}
|
}
|
@@ -58,6 +58,24 @@ void ulp_riscv_rescue_from_monitor(void);
|
|||||||
*/
|
*/
|
||||||
void __attribute__((noreturn)) ulp_riscv_shutdown(void);
|
void __attribute__((noreturn)) ulp_riscv_shutdown(void);
|
||||||
|
|
||||||
|
#define ULP_RISCV_GET_CCOUNT() ({ int __ccount; \
|
||||||
|
asm volatile("rdcycle %0;" : "=r"(__ccount)); \
|
||||||
|
__ccount; })
|
||||||
|
|
||||||
|
|
||||||
|
/* These are only approximate default numbers, the default frequency
|
||||||
|
of the 8M oscillator is 8.5MHz +/- 5%, at the default DCAP setting
|
||||||
|
*/
|
||||||
|
#define ULP_RISCV_CYCLES_PER_US 8.5
|
||||||
|
#define ULP_RISCV_CYCLES_PER_MS ULP_RISCV_CYCLES_PER_US*1000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Makes the co-processor busy wait for a certain number of cycles
|
||||||
|
*
|
||||||
|
* @param cycles Number of cycles to busy wait
|
||||||
|
*/
|
||||||
|
void ulp_riscv_delay_cycles(uint32_t cycles);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -39,3 +39,12 @@ void ulp_riscv_shutdown(void)
|
|||||||
|
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ulp_riscv_delay_cycles(uint32_t cycles)
|
||||||
|
{
|
||||||
|
uint32_t start = ULP_RISCV_GET_CCOUNT();
|
||||||
|
|
||||||
|
while ((ULP_RISCV_GET_CCOUNT() - start) < cycles) {
|
||||||
|
/* Wait */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -10,7 +10,7 @@ from tiny_test_fw import Utility
|
|||||||
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32'])
|
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32'])
|
||||||
def test_examples_ulp(env, extra_data):
|
def test_examples_ulp(env, extra_data):
|
||||||
|
|
||||||
dut = env.get_dut('ulp', 'examples/system/ulp')
|
dut = env.get_dut('ulp', 'examples/system/ulp_fsm/ulp')
|
||||||
dut.start_app()
|
dut.start_app()
|
||||||
|
|
||||||
dut.expect_all('Not ULP wakeup, initializing ULP',
|
dut.expect_all('Not ULP wakeup, initializing ULP',
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
@@ -9,7 +9,7 @@ from tiny_test_fw import Utility
|
|||||||
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32'])
|
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32'])
|
||||||
def test_examples_ulp_adc(env, extra_data):
|
def test_examples_ulp_adc(env, extra_data):
|
||||||
|
|
||||||
dut = env.get_dut('ulp_adc', 'examples/system/ulp_adc')
|
dut = env.get_dut('ulp_adc', 'examples/system/ulp_fsm/ulp_adc')
|
||||||
dut.start_app()
|
dut.start_app()
|
||||||
|
|
||||||
dut.expect_all('Not ULP wakeup',
|
dut.expect_all('Not ULP wakeup',
|
6
examples/system/ulp_riscv/ds18b20_onewire/CMakeLists.txt
Normal file
6
examples/system/ulp_riscv/ds18b20_onewire/CMakeLists.txt
Normal file
@@ -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.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(ulp-riscv-ds18b20-example)
|
42
examples/system/ulp_riscv/ds18b20_onewire/README.md
Normal file
42
examples/system/ulp_riscv/ds18b20_onewire/README.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
| Supported Targets | ESP32-S2 |
|
||||||
|
| ----------------- | -------- |
|
||||||
|
|
||||||
|
# ULP-RISC-V DS18B20 Temperature Sensor OneWire Communication
|
||||||
|
|
||||||
|
This example demonstrates how to program the ULP-RISC-V co-processor to read temperature from a [DS18B20](https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf) temperature sensor over 1-Wire.
|
||||||
|
When the measurement exceeds the limit set(32.5 degrees) the co-processor will wake up the main CPU from deep-sleep and the main CPU will print the temperature measurement.
|
||||||
|
|
||||||
|
### Hardware Required
|
||||||
|
|
||||||
|
* A development board with a SOC which has a RISC-V ULP coprocessor (e.g., ESP32-S2 Saola)
|
||||||
|
* A USB cable for power supply and programming
|
||||||
|
* A DS18B20 temperature sensor
|
||||||
|
|
||||||
|
Example connection :
|
||||||
|
|
||||||
|
| ESP Dev-kit | DS18B20 |
|
||||||
|
| ------------ | ------- |
|
||||||
|
| GPIO4 | DQ |
|
||||||
|
| VCC 3.3V | VDD |
|
||||||
|
| GND | GND |
|
||||||
|
|
||||||
|
|
||||||
|
## Example output
|
||||||
|
|
||||||
|
```
|
||||||
|
Not a ULP wakeup, initializing it!
|
||||||
|
Entering in deep sleep
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
ULP-RISC-V woke up the main CPU, temperature is above set limit!
|
||||||
|
ULP-RISC-V read temperature is 32.562500
|
||||||
|
Entering in deep sleep
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
ULP-RISC-V woke up the main CPU, temperature is above set limit!
|
||||||
|
ULP-RISC-V read temperature is 33.000000
|
||||||
|
Entering in deep sleep
|
||||||
|
|
||||||
|
```
|
@@ -0,0 +1,27 @@
|
|||||||
|
# Set usual component variables
|
||||||
|
set(COMPONENT_SRCS "ulp_riscv_ds18b20_example_main.c")
|
||||||
|
set(COMPONENT_ADD_INCLUDEDIRS "")
|
||||||
|
set(COMPONENT_REQUIRES soc nvs_flash ulp driver)
|
||||||
|
|
||||||
|
register_component()
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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_ds18b20_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}")
|
156
examples/system/ulp_riscv/ds18b20_onewire/main/ulp/main.c
Normal file
156
examples/system/ulp_riscv/ds18b20_onewire/main/ulp/main.c
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
/* ULP-RISC-V 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 <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "ulp_riscv/ulp_riscv.h"
|
||||||
|
#include "ulp_riscv/ulp_riscv_utils.h"
|
||||||
|
#include "ulp_riscv/ulp_riscv_gpio.h"
|
||||||
|
|
||||||
|
#define EXAMPLE_1WIRE_GPIO GPIO_NUM_4
|
||||||
|
|
||||||
|
#define WAKEUP_TEMP_C 32.5
|
||||||
|
#define TEMP_ALARM_LIMIT ( (int)(WAKEUP_TEMP_C*16) )
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SENSOR_CONVERSION_INIT,
|
||||||
|
SENSOR_CONVERSION_READ,
|
||||||
|
} sensor_state_t;
|
||||||
|
|
||||||
|
sensor_state_t state = SENSOR_CONVERSION_INIT;
|
||||||
|
int32_t temp_reg_val = INT32_MIN;
|
||||||
|
|
||||||
|
static void ds18b20_write_bit(bool bit)
|
||||||
|
{
|
||||||
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0);
|
||||||
|
if (bit) {
|
||||||
|
/* Must pull high within 15 us, without delay this takes 5 us */
|
||||||
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write slot duration at least 60 us */
|
||||||
|
ulp_riscv_delay_cycles(60 * ULP_RISCV_CYCLES_PER_US);
|
||||||
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ds18b20_read_bit(void)
|
||||||
|
{
|
||||||
|
bool bit;
|
||||||
|
|
||||||
|
/* Pull low minimum 1 us */
|
||||||
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0);
|
||||||
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1);
|
||||||
|
|
||||||
|
/* Must sample within 15 us of the failing edge */
|
||||||
|
ulp_riscv_delay_cycles(5 * ULP_RISCV_CYCLES_PER_US);
|
||||||
|
bit = ulp_riscv_gpio_get_level(EXAMPLE_1WIRE_GPIO);
|
||||||
|
|
||||||
|
/* Read slot duration at least 60 us */
|
||||||
|
ulp_riscv_delay_cycles(55 * ULP_RISCV_CYCLES_PER_US);
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds18b20_write_byte(uint8_t data)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
ds18b20_write_bit((data >> i) & 0x1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t ds18b20_read_byte(void)
|
||||||
|
{
|
||||||
|
uint8_t data = 0;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
data |= ds18b20_read_bit() << i;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ds18b20_reset_pulse(void)
|
||||||
|
{
|
||||||
|
bool presence_pulse;
|
||||||
|
/* min 480 us reset pulse + 480 us reply time is specified by datasheet */
|
||||||
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0);
|
||||||
|
ulp_riscv_delay_cycles(480 * ULP_RISCV_CYCLES_PER_US);
|
||||||
|
|
||||||
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1);
|
||||||
|
|
||||||
|
/* Wait for ds18b20 to pull low before sampling */
|
||||||
|
ulp_riscv_delay_cycles(60 * ULP_RISCV_CYCLES_PER_US);
|
||||||
|
presence_pulse = ulp_riscv_gpio_get_level(EXAMPLE_1WIRE_GPIO) == 0;
|
||||||
|
|
||||||
|
ulp_riscv_delay_cycles(420 * ULP_RISCV_CYCLES_PER_US);
|
||||||
|
|
||||||
|
return presence_pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
uint8_t temp_high_byte;
|
||||||
|
uint8_t temp_low_byte;
|
||||||
|
|
||||||
|
/* Setup GPIO used for 1wire */
|
||||||
|
ulp_riscv_gpio_init(EXAMPLE_1WIRE_GPIO);
|
||||||
|
ulp_riscv_gpio_input_enable(EXAMPLE_1WIRE_GPIO);
|
||||||
|
ulp_riscv_gpio_output_enable(EXAMPLE_1WIRE_GPIO);
|
||||||
|
ulp_riscv_gpio_set_output_mode(EXAMPLE_1WIRE_GPIO, RTCIO_MODE_OUTPUT_OD);
|
||||||
|
ulp_riscv_gpio_pullup(EXAMPLE_1WIRE_GPIO);
|
||||||
|
ulp_riscv_gpio_pulldown_disable(EXAMPLE_1WIRE_GPIO);
|
||||||
|
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case SENSOR_CONVERSION_INIT:
|
||||||
|
if (!ds18b20_reset_pulse()) {
|
||||||
|
temp_reg_val = INT32_MIN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Start conversion */
|
||||||
|
ds18b20_write_byte(0xCC);
|
||||||
|
ds18b20_write_byte(0x44);
|
||||||
|
|
||||||
|
/* shutdown and wait for next period (750ms) where the data is ready for reading */
|
||||||
|
state = SENSOR_CONVERSION_READ;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SENSOR_CONVERSION_READ:
|
||||||
|
if (!ds18b20_reset_pulse()) {
|
||||||
|
temp_reg_val = INT32_MIN;
|
||||||
|
state = SENSOR_CONVERSION_INIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read scratchpad */
|
||||||
|
ds18b20_write_byte(0xCC);
|
||||||
|
ds18b20_write_byte(0xBE);
|
||||||
|
|
||||||
|
temp_low_byte = ds18b20_read_byte();
|
||||||
|
temp_high_byte = ds18b20_read_byte();
|
||||||
|
|
||||||
|
temp_reg_val = temp_high_byte << 8;
|
||||||
|
temp_reg_val |= temp_low_byte;
|
||||||
|
state = SENSOR_CONVERSION_INIT;
|
||||||
|
|
||||||
|
/* Wakes up the main CPU if the temperature exceeds the limit */
|
||||||
|
if (temp_reg_val > TEMP_ALARM_LIMIT) {
|
||||||
|
ulp_riscv_wakeup_main_processor();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ulp_riscv_shutdown() is called automatically when main exits,
|
||||||
|
main will be executed again at the next timeout period,
|
||||||
|
according to ulp_set_wakeup_period()
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -0,0 +1,72 @@
|
|||||||
|
/* ULP riscv 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 "esp_sleep.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/sens_reg.h"
|
||||||
|
#include "soc/rtc_periph.h"
|
||||||
|
#include "hal/rtc_io_ll.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "driver/rtc_io.h"
|
||||||
|
#include "esp32s2/ulp.h"
|
||||||
|
#include "esp32s2/ulp_riscv.h"
|
||||||
|
#include "ulp_main.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
/* We alternate between start conversion and read result every other ULP wakeup,
|
||||||
|
Conversion time is 750 ms for 12 bit resolution
|
||||||
|
*/
|
||||||
|
#define WAKEUP_PERIOD_US (750000)
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
static void init_ulp_program(void);
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||||
|
/* not a wakeup from ULP, load the firmware */
|
||||||
|
if (cause != ESP_SLEEP_WAKEUP_ULP) {
|
||||||
|
printf("Not a ULP-RISC-V wakeup (cause = %d), initializing it! \n", cause);
|
||||||
|
init_ulp_program();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ULP Risc-V read and detected a temperature above the limit */
|
||||||
|
if (cause == ESP_SLEEP_WAKEUP_ULP) {
|
||||||
|
printf("ULP-RISC-V woke up the main CPU, temperature is above set limit! \n");
|
||||||
|
printf("ULP-RISC-V read temperature is %f\n", ulp_temp_reg_val / 16.0);
|
||||||
|
}
|
||||||
|
/* Go back to sleep, only the ULP Risc-V will run */
|
||||||
|
printf("Entering in deep sleep\n\n");
|
||||||
|
|
||||||
|
/* Small delay to ensure the messages are printed */
|
||||||
|
vTaskDelay(100);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup());
|
||||||
|
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
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: 750ms
|
||||||
|
*/
|
||||||
|
ulp_set_wakeup_period(0, WAKEUP_PERIOD_US);
|
||||||
|
|
||||||
|
/* Start the program */
|
||||||
|
err = ulp_riscv_run();
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
}
|
@@ -9,7 +9,7 @@ from tiny_test_fw import DUT
|
|||||||
|
|
||||||
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2'])
|
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2'])
|
||||||
def test_examples_ulp_riscv(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument
|
def test_examples_ulp_riscv(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument
|
||||||
dut = env.get_dut('ulp_riscv', 'examples/system/ulp_riscv')
|
dut = env.get_dut('ulp_riscv', 'examples/system/ulp_riscv/gpio')
|
||||||
dut.start_app()
|
dut.start_app()
|
||||||
|
|
||||||
dut.expect_all('Not a ULP-RISC-V wakeup, initializing it!',
|
dut.expect_all('Not a ULP-RISC-V wakeup, initializing it!',
|
@@ -14,7 +14,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "ulp_riscv/ulp_riscv.h"
|
#include "ulp_riscv/ulp_riscv.h"
|
||||||
#include "ulp_riscv/ulp_riscv_utils.h"
|
#include "ulp_riscv/ulp_riscv_utils.h"
|
||||||
#include "example_ulp_gpio.h"
|
#include "ulp_riscv/ulp_riscv_gpio.h"
|
||||||
|
|
||||||
static bool gpio_level = false;
|
static bool gpio_level = false;
|
||||||
|
|
||||||
@@ -23,11 +23,11 @@ bool gpio_level_previous = false;
|
|||||||
|
|
||||||
int main (void)
|
int main (void)
|
||||||
{
|
{
|
||||||
gpio_level = (bool)example_ulp_gpio_get_level(GPIO_NUM_0);
|
gpio_level = (bool)ulp_riscv_gpio_get_level(GPIO_NUM_0);
|
||||||
gpio_level_previous = gpio_level;
|
gpio_level_previous = gpio_level;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
gpio_level = (bool)example_ulp_gpio_get_level(GPIO_NUM_0);
|
gpio_level = (bool)ulp_riscv_gpio_get_level(GPIO_NUM_0);
|
||||||
|
|
||||||
/* Wakes up the main CPU if pin changed its state */
|
/* Wakes up the main CPU if pin changed its state */
|
||||||
if(gpio_level != gpio_level_previous) {
|
if(gpio_level != gpio_level_previous) {
|
||||||
@@ -35,7 +35,6 @@ int main (void)
|
|||||||
ulp_riscv_wakeup_main_processor();
|
ulp_riscv_wakeup_main_processor();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/* ulp_riscv_shutdown() is called automatically when main exits */
|
/* ulp_riscv_shutdown() is called automatically when main exits */
|
||||||
return 0;
|
return 0;
|
@@ -1,4 +1,4 @@
|
|||||||
/* ULP riscv example
|
/* ULP riscv DS18B20 1wire temperature sensor example
|
||||||
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
10
examples/system/ulp_riscv/gpio/sdkconfig.defaults
Normal file
10
examples/system/ulp_riscv/gpio/sdkconfig.defaults
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
CONFIG_IDF_TARGET="esp32s2"
|
||||||
|
# Enable ULP
|
||||||
|
CONFIG_ESP32S2_ULP_COPROC_ENABLED=y
|
||||||
|
CONFIG_ESP32S2_ULP_COPROC_RISCV=y
|
||||||
|
CONFIG_ESP32S2_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
|
@@ -144,8 +144,8 @@ examples/system/startup_time/example_test.py
|
|||||||
examples/system/sysview_tracing/example_test.py
|
examples/system/sysview_tracing/example_test.py
|
||||||
examples/system/sysview_tracing_heap_log/example_test.py
|
examples/system/sysview_tracing_heap_log/example_test.py
|
||||||
examples/system/task_watchdog/example_test.py
|
examples/system/task_watchdog/example_test.py
|
||||||
examples/system/ulp/example_test.py
|
examples/system/ulp_fsm/ulp/example_test.py
|
||||||
examples/system/ulp_adc/example_test.py
|
examples/system/ulp_fsm/ulp_adc/example_test.py
|
||||||
examples/system/unit_test/example_test.py
|
examples/system/unit_test/example_test.py
|
||||||
examples/wifi/iperf/iperf_test.py
|
examples/wifi/iperf/iperf_test.py
|
||||||
tools/ble/lib_ble_client.py
|
tools/ble/lib_ble_client.py
|
||||||
|
Reference in New Issue
Block a user