1
6
7
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
120
123
126
127
128
129
130
131
134
135
136
137
138
139
140
141
142
145
146
147
148
149
150
151
152
153
/* ... */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_private/esp_clk.h"8 includes
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/ulp.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/ulp.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/ulp.h"
#endif
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "ulp_common.h"
#include "esp_rom_sys.h"
#include "esp_check.h"
#include "esp_private/rtc_ctrl.h"8 includes
typedef struct {
uint32_t magic;
uint16_t text_offset;
uint16_t text_size;
uint16_t data_size;
uint16_t bss_size;
}{ ... } ulp_binary_header_t;
#define ULP_BINARY_MAGIC_ESP32 (0x00706c75)
static const char* TAG = "ulp";
esp_err_t ulp_isr_register(intr_handler_t fn, void *arg)
{
ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TAG, "ULP ISR is NULL");
REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M);
#if CONFIG_IDF_TARGET_ESP32
return rtc_isr_register(fn, arg, RTC_CNTL_SAR_INT_ST_M, 0);
#else
return rtc_isr_register(fn, arg, RTC_CNTL_ULP_CP_INT_ST_M, 0);
#endif
}{ ... }
esp_err_t ulp_isr_deregister(intr_handler_t fn, void *arg)
{
ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TAG, "ULP ISR is NULL");
REG_CLR_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_ULP_CP_INT_ENA_M);
return rtc_isr_deregister(fn, arg);
}{ ... }
esp_err_t ulp_run(uint32_t entry_point)
{
#if CONFIG_IDF_TARGET_ESP32
CLEAR_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);
esp_rom_delay_us(10);
REG_SET_FIELD(SENS_SAR_START_FORCE_REG, SENS_PC_INIT, entry_point);
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_FORCE_START_TOP_M);
REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL, RTC_CNTL_MIN_SLP_VAL_MIN);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FOLW_8M);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_CORE_FOLW_8M);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_SLEEP_FOLW_8M);
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);/* ... */
#else
SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_RESET);
esp_rom_delay_us(20);
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_RESET);
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);
esp_rom_delay_us(10);
REG_SET_FIELD(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_PC_INIT, entry_point);
SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SEL);
SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_CLK_FO);
CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_DONE_FORCE);
#if CONFIG_IDF_TARGET_ESP32S3
SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_CLKGATE_EN);/* ... */
#endif
REG_WRITE(RTC_CNTL_INT_CLR_REG, RTC_CNTL_COCPU_INT_CLR | RTC_CNTL_COCPU_TRAP_INT_CLR | RTC_CNTL_ULP_CP_INT_CLR);
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP);
SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); /* ... */
#endif
return ESP_OK;
}{ ... }
esp_err_t ulp_load_binary(uint32_t load_addr, const uint8_t* program_binary, size_t program_size)
{
size_t program_size_bytes = program_size * sizeof(uint32_t);
size_t load_addr_bytes = load_addr * sizeof(uint32_t);
if (program_size_bytes < sizeof(ulp_binary_header_t)) {
return ESP_ERR_INVALID_SIZE;
}{...}
if (load_addr_bytes > CONFIG_ULP_COPROC_RESERVE_MEM) {
return ESP_ERR_INVALID_ARG;
}{...}
if (load_addr_bytes + program_size_bytes > CONFIG_ULP_COPROC_RESERVE_MEM) {
return ESP_ERR_INVALID_SIZE;
}{...}
ulp_binary_header_t header;
memcpy(&header, program_binary, sizeof(header));
if (header.magic != ULP_BINARY_MAGIC_ESP32) {
return ESP_ERR_NOT_SUPPORTED;
}{...}
size_t total_size = (size_t) header.text_offset + (size_t) header.text_size +
(size_t) header.data_size;
ESP_LOGD(TAG, "program_size_bytes: %d total_size: %d offset: %d .text: %d, .data: %d, .bss: %d",
program_size_bytes, total_size, header.text_offset,
header.text_size, header.data_size, header.bss_size);
if (total_size != program_size_bytes) {
return ESP_ERR_INVALID_SIZE;
}{...}
size_t text_data_size = header.text_size + header.data_size;
uint8_t* base = (uint8_t*) RTC_SLOW_MEM;
memcpy(base + load_addr_bytes, program_binary + header.text_offset, text_data_size);
memset(base + load_addr_bytes + text_data_size, 0, header.bss_size);
return ESP_OK;
}{ ... }