ULP WakeUP
Posted: Tue Oct 17, 2017 10:15 pm
Playing around with the wake instruction of the ULP I found some strange behaviour. Maybe someone can explain. So I came across this testing the I2C code from tomtor: https://github.com/tomtor/ulp-i2c/blob/ ... ulp/main.S
The critical part is the disabling of the ULP Wakup Timer with:
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
When I included this line in my code. The Main processor didn't seem to wakeup at all. I tried to isolate the problem. A small delay between between the wake call and the WRITE_RTC_FIELD seems to solve it. At least I thought so. When I used the delay as a function with tomtors "ret" macro it worked. With just a simple jump instruction it didn't. So I simplified the problem even further in one small example. I managed to build 2 nearly identical assembler codes. One working as expected the other one not.
So the non working one:
So when I change the last jump to using a register (which also would happen when using tomtors "ret" macro):
it suddenly works although both jumps should definitely do the same.
Here is also the code for the main (lightly modified from the examples):
When its working there should appear the wakeup message every 2 seconds. If I use the first assembler code I just see how the processor goes to sleep and then nothing happens. So my question is if someone can reproduce this behaviour and if someone has any idea why this is happening. For me this really makes no sense at all.
The critical part is the disabling of the ULP Wakup Timer with:
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
When I included this line in my code. The Main processor didn't seem to wakeup at all. I tried to isolate the problem. A small delay between between the wake call and the WRITE_RTC_FIELD seems to solve it. At least I thought so. When I used the delay as a function with tomtors "ret" macro it worked. With just a simple jump instruction it didn't. So I simplified the problem even further in one small example. I managed to build 2 nearly identical assembler codes. One working as expected the other one not.
So the non working one:
Code: Select all
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc_ulp.h"
.bss
.text
.global entry
entry:
nop
wake
move r2,2000
jump myWait
myEnd:
//disable rtc timer wakeup
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
halt
// Wait for r2 milliseconds
myWait:
wait 8000
sub r2,r2,1
jump doneMyWait,eq
jump myWait
doneMyWait:
move r1,myEnd
jump myEnd
Code: Select all
doneMyWait:
move r1,myEnd
jump r1
Here is also the code for the main (lightly modified from the examples):
Code: Select all
/* Hello World 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 "freertos/FreeRTOS.h"
#include "esp_sleep.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp32/ulp.h"
#include "ulp_main.h"
extern const uint8_t bin_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t bin_end[] asm("_binary_ulp_main_bin_end");
static void init_ulp_program();
void app_main()
{
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
if (cause != ESP_SLEEP_WAKEUP_ULP) {
printf("Not ULP wakeup, initializing ULP\n");
init_ulp_program();
} else {
printf("ULP wakeup \n");
}
printf("Entering deep sleep\n\n");
ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
esp_deep_sleep_start();
}
void init_ulp_program()
{
ESP_ERROR_CHECK(ulp_load_binary(0, bin_start,
(bin_end - bin_start) / sizeof(uint32_t)));
ulp_set_wakeup_period(0, 150);
ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t)) );
}