Code Monkey home page Code Monkey logo

esp32-ulp-i2c's People

Contributors

wardjm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

pikot

esp32-ulp-i2c's Issues

ULP hangs

Hi,

I am trying your code with a BME280 connected to GPIO04 and GPIO00....unluckily the ulp code hangs foreover on the I2C_RD call (if I comment it ulp wakes up correctly the ESP32). Here follows my changes:

ulp.s (switched to version 0 and to RTC_IO_TOUCH_PAD0/1_RE regs, changed I2C_ADDR and I2C_RD register)

#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc_ulp.h"
#include "soc/sens_reg.h"
#include "soc/rtc_i2c_reg.h"

/* Define variables, which go into .bss section (zero-initialized data) */
    .bss
.global dummy
dummy: .long 0

/* Code goes into .text section */
    .text


    .global entry
entry:
    // Release hold on pins, so that we can manipulate them
    WRITE_RTC_REG(RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_HOLD_S, RTC_IO_TOUCH_PAD1_HOLD_M, 0);
    WRITE_RTC_REG(RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_HOLD_S, RTC_IO_TOUCH_PAD0_HOLD_M, 0);

    // Select SDA/SCL pins to version 1, TOUCH2 and TOUCH3 (version 0 is TOUCH0 and TOUCH1)
    WRITE_RTC_REG(RTC_IO_SAR_I2C_IO_REG, RTC_IO_SAR_I2C_SDA_SEL_S, RTC_IO_SAR_I2C_SDA_SEL_M, 0);
    WRITE_RTC_REG(RTC_IO_SAR_I2C_IO_REG, RTC_IO_SAR_I2C_SCL_SEL_S, RTC_IO_SAR_I2C_SCL_SEL_M, 0);

    // Set slave address for i2c device we are talking to (ADDR1_REG contains both ADDR0 and ADDR1)
    // 0x5a is for CCS811
    WRITE_RTC_REG(SENS_SAR_SLAVE_ADDR1_REG, SENS_I2C_SLAVE_ADDR0_S, SENS_I2C_SLAVE_ADDR0_M, 0x76);
    WRITE_RTC_REG(SENS_SAR_SLAVE_ADDR1_REG, SENS_I2C_SLAVE_ADDR1_S, SENS_I2C_SLAVE_ADDR1_M, 0x76);

    // Set SCL speed to 100khz
    WRITE_RTC_REG(RTC_I2C_SCL_LOW_PERIOD_REG, RTC_I2C_SCL_LOW_PERIOD_S, RTC_I2C_SCL_LOW_PERIOD_M, 40);
    WRITE_RTC_REG(RTC_I2C_SCL_HIGH_PERIOD_REG, RTC_I2C_SCL_HIGH_PERIOD_S, RTC_I2C_SCL_HIGH_PERIOD_M, 40);

    // SDA duty (delay) cycles from falling edge of SCL when SDA changes.
    WRITE_RTC_REG(RTC_I2C_SDA_DUTY_REG, RTC_I2C_SDA_DUTY_S, RTC_I2C_SDA_DUTY_M, 16);

    // Number of cycles after start/stop condition
    WRITE_RTC_REG(RTC_I2C_SCL_START_PERIOD_REG, RTC_I2C_SCL_START_PERIOD_S, RTC_I2C_SCL_START_PERIOD_M, 30);
    WRITE_RTC_REG(RTC_I2C_SCL_STOP_PERIOD_REG, RTC_I2C_SCL_STOP_PERIOD_S, RTC_I2C_SCL_STOP_PERIOD_M, 44);

    // cycles before timeout
    WRITE_RTC_REG(RTC_I2C_TIMEOUT_REG, RTC_I2C_TIMEOUT_S, RTC_I2C_TIMEOUT_M, 10000);

    // Set mode to master
    WRITE_RTC_REG(RTC_I2C_CTRL_REG, RTC_I2C_MS_MODE_S, RTC_I2C_MS_MODE_M, 1);

    // Main code, store the i2c read (0x20 = get hardware id) into dummy and return the value to main process
    move    r3, dummy
    i2c_rd  0xd0, 7, 0, 1
    st      r0, r3, 0
    jump    wake_up
    jump    entry

/* end the program */
.global exit
exit:
/* Set the GPIO13 output LOW (clear output) to signal that ULP is now going down (the 14 is because GPIO13 = RTC_GPIO_14) */
WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S + 14, 1, 1)
/* Enable hold on GPIO13 output */
WRITE_RTC_REG(RTC_IO_TOUCH_PAD4_REG, RTC_IO_TOUCH_PAD4_HOLD_S, 1, 1)
halt

.global wake_up
wake_up:
/* Check if the system can be woken up */
READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
and r0, r0, 1
jump exit, eq

/* Wake up the SoC, end program */
wake
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
jump exit

ulp_test.ino (changed to version 0 and i2c_address)

#include "esp32/ulp.h"
#include "esp_sleep.h"
#include "driver/rtc_io.h"
#include "soc/sens_reg.h"
#include "soc/rtc_i2c_reg.h"
#include "esp_deep_sleep.h"
// Our header
#include "ulp_main.h"


// Unlike the esp-idf always use these binary blob names
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_run_ulp(uint32_t usec);

void setup() {
  
    esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
    if (cause != ESP_SLEEP_WAKEUP_ULP) {
        init_run_ulp(5000 * 1000); // 100 msec
    }
  
    else {
    
      // ***** HERE YOUR SKETCH ***** 
      printf("Deep sleep wakeup\n");
      printf("ULP dummy i2c read value: %08x\n", ulp_dummy & UINT16_MAX);
    }

    // Re-entering deep sleep
    delay(1000); // Otherwise we are just spinning reading the same thing like crazy
    start_ulp_program();
    ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
    printf("Before sleep\n");
    esp_deep_sleep_start();
}

void loop() {
    // Nothing goes here
}

// Use this function for all your first time init like setup() used to be
static void init_run_ulp(uint32_t usec) {
  
    // initialize ulp variables
    printf("initing...\n");
    
    ulp_set_wakeup_period(0, usec);

    // You MUST load the binary before setting shared variables!
    esp_err_t err = ulp_load_binary(0, ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
    ESP_ERROR_CHECK(err);

    // Setup RTC I2C controller, selection either 0 or 1, see below for exact description and wiring (you can mix and match and comment out unused gpios)
    SET_PERI_REG_BITS(RTC_IO_SAR_I2C_IO_REG, RTC_IO_SAR_I2C_SDA_SEL, 0, RTC_IO_SAR_I2C_SDA_SEL_S);
    SET_PERI_REG_BITS(RTC_IO_SAR_I2C_IO_REG, RTC_IO_SAR_I2C_SCL_SEL, 0, RTC_IO_SAR_I2C_SCL_SEL_S);

    // SDA/SCL selection 0 is for 
    // TOUCH0 = GPIO4 = SCL
    // TOUCH1 = GPIO0 = SDA
    rtc_gpio_init(GPIO_NUM_0);
    rtc_gpio_init(GPIO_NUM_4);

    // SDA/SCL selection 1 is for
    // TOUCH2 = GPIO2 = SCL
    // TOUCH3 = GPIO15 = SDA
    //rtc_gpio_init(GPIO_NUM_2);
    //rtc_gpio_init(GPIO_NUM_15);

    // We will be reading and writing on these gpio
    //rtc_gpio_set_direction(GPIO_NUM_15, RTC_GPIO_MODE_INPUT_OUTPUT);
    rtc_gpio_set_direction(GPIO_NUM_4, RTC_GPIO_MODE_INPUT_OUTPUT);
    //rtc_gpio_set_direction(GPIO_NUM_2, RTC_GPIO_MODE_INPUT_OUTPUT);
    rtc_gpio_set_direction(GPIO_NUM_0, RTC_GPIO_MODE_INPUT_OUTPUT);

    printf("rtc io...\n");

    // Look up your device for these standard values needed to do i2c:
    WRITE_PERI_REG(RTC_I2C_SCL_LOW_PERIOD_REG, 40); // SCL low/high period = 40, which result driving SCL with 100kHz.
    WRITE_PERI_REG(RTC_I2C_SCL_HIGH_PERIOD_REG, 40);  
    WRITE_PERI_REG(RTC_I2C_SDA_DUTY_REG, 16);     // SDA duty (delay) cycles from falling edge of SCL when SDA changes.
    WRITE_PERI_REG(RTC_I2C_SCL_START_PERIOD_REG, 30); // Number of cycles to wait after START condition.
    WRITE_PERI_REG(RTC_I2C_SCL_STOP_PERIOD_REG, 44);  // Number of cycles to wait after STOP condition.
    WRITE_PERI_REG(RTC_I2C_TIMEOUT_REG, 10000);     // Number of cycles before timeout.
    SET_PERI_REG_BITS(RTC_I2C_CTRL_REG, RTC_I2C_MS_MODE, 1, RTC_I2C_MS_MODE_S); // Set i2c mode to master for the ulp controller

    // Both aren't necessary, but for example of how to get ADDR0 when there is no ADDR0_REG
    // Also note this is SENS_SAR regs but everything else uses RTC_*
    SET_PERI_REG_BITS(SENS_SAR_SLAVE_ADDR1_REG, SENS_I2C_SLAVE_ADDR0, 0x76, SENS_I2C_SLAVE_ADDR0_S);  // Set I2C device address.
    SET_PERI_REG_BITS(SENS_SAR_SLAVE_ADDR1_REG, SENS_I2C_SLAVE_ADDR1, 0x76, SENS_I2C_SLAVE_ADDR1_S);  // Set I2C device address.

    
    esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);

    // Any other ulp variables can be assigned here
 
    printf("end of init\n");
    delay(100);
}

static void start_ulp_program() {
    /* Start the program */
    printf("Going to sleep...\n");
    delay(100);
    esp_err_t err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t));
    ESP_ERROR_CHECK(err);
}

Hardware wiring is correct because by I tested it with ESP32 and it can access the BME280 through I2C. Do you have an idea of what it could be ?

How can I compile your project ?

On stock Arduino 1.8.12 (Windows) it gives these errors, it seems that the .S file is not compiled. Shall I have to install some extensions ? I attach a verbose compilation log

Arduino: 1.8.12 (Windows 10), Board: "ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 230400, None"

sketch\ulp_test.ino.cpp.o:(.literal._Z5setupv+0x8): undefined reference to `_binary_ulp_main_bin_end'

sketch\ulp_test.ino.cpp.o:(.literal._Z5setupv+0xc): undefined reference to `_binary_ulp_main_bin_start'

sketch\ulp_test.ino.cpp.o:(.literal._Z5setupv+0x64): undefined reference to `ulp_dummy'

sketch\ulp_test.ino.cpp.o:(.literal._Z5setupv+0x70): undefined reference to `ulp_entry'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board ESP32 Dev Module.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

verbose arduino.txt

ULP

how do you instal for using de ULP, because i compile the file and somethings is messing. Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.