I want to use both the main core and the ULP core in the following manner:
-The ULP core will read an event input and count the number of events.
-The main core will perform other tasks, and be interrupted by the ULP core when a threshold number of events have occurred.
-When that interrupt occurs the main core will pole the some internal variables and the ULP continues to operate after triggering the interrupt..
After looking at other posts, I have adapted the ulp pulse count example as follows. The main core initializes the ULP and enters a loop where it waits one second and outputs the value of "wakes", which counts the number of times the ISR function has been called. The ULP code increments the stage counter to 20, and then triggers the wake command.
Code: Select all
#include <stdio.h>
#include "esp_sleep.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "soc/rtc_periph.h"
#include "driver/gpio.h"
#include "driver/rtc_io.h"
#include "esp32/ulp.h"
#include "ulp_main.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/rtc_cntl.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");
static void init_ulp_program();
static void ulp_isr_handler();
static void ulp_isr_install();
int wakes;
void app_main()
{
wakes = 0;
ulp_isr_install();
init_ulp_program();
while(1)
{
//update_pulse_count();
vTaskDelay(1000 / portTICK_PERIOD_MS);
printf("1s: %i\n", wakes);
}
printf("Entering deep sleep\n\n");
//ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
esp_deep_sleep_start();
}
static void init_ulp_program()
{
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);
esp_deep_sleep_disable_rom_logging(); // suppress boot messages
/* Set ULP wake up period to T = 20ms.
* Minimum pulse width has to be T * (ulp_debounce_counter + 1) = 80ms.
*/
ulp_set_wakeup_period(0, 20000);
/* Start the program */
err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
ESP_ERROR_CHECK(err);
}
static void IRAM_ATTR ulp_isr_handler(void *args)
{
printf("ULP interrupt: Active ---> Deepsleep\n");
wakes++;
}
static void ulp_isr_install()
{
ESP_ERROR_CHECK( rtc_isr_register(&ulp_isr_handler, NULL, RTC_CNTL_SAR_INT_ST_M) );
REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M);
}
Code: Select all
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc_ulp.h"
/* Define variables, which go into .bss section (zero-initialized data) */
.bss
/* Code goes into .text section */
.text
.global entry
entry:
STAGE_RST
jump counttime
counttime:
wait 100
STAGE_INC 1
jumps wakesys, 20, EQ
jump counttime
wakesys:
wake
wait 100
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
STAGE_RST
jump counttime
So far I have encountered the following problems: since the main core does not go to sleep, the ULP command "wake" causes the code to crash ("abort() was called at PC 0x40082642 on core 0"). Removing the wake command results in the code functioning but no ISR gets triggered. What must I do for this to trigger the interrupt service routine? Why is the ULP "wake" command causing the code to crash, and how do I remedy this.
Other reference posts:
https://www.esp32.com/viewtopic.php?t=17366
https://gist.github.com/igrr/4b002047fc ... main-c-L31
viewtopic.php?f=2&t=4094
Thank you.