Skip to content

Commit daea578

Browse files
committed
Add APB change callbacks and move cpu code to own file
1 parent 6dd8be3 commit daea578

File tree

5 files changed

+224
-58
lines changed

5 files changed

+224
-58
lines changed

Diff for: CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ set(CORE_SRCS
33
cores/esp32/cbuf.cpp
44
cores/esp32/esp32-hal-adc.c
55
cores/esp32/esp32-hal-bt.c
6+
cores/esp32/esp32-hal-cpu.c
67
cores/esp32/esp32-hal-dac.c
78
cores/esp32/esp32-hal-gpio.c
89
cores/esp32/esp32-hal-i2c.c

Diff for: cores/esp32/esp32-hal-cpu.c

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "sdkconfig.h"
16+
#include "freertos/FreeRTOS.h"
17+
#include "freertos/semphr.h"
18+
#include "freertos/task.h"
19+
#include "esp_attr.h"
20+
#include "esp_log.h"
21+
#include "soc/rtc.h"
22+
#include "soc/rtc_cntl_reg.h"
23+
#include "rom/rtc.h"
24+
#include "esp32-hal.h"
25+
#include "esp32-hal-cpu.h"
26+
27+
typedef struct apb_change_cb_s {
28+
struct apb_change_cb_s * next;
29+
void * arg;
30+
apb_change_cb_t cb;
31+
} apb_change_t;
32+
33+
static apb_change_t * apb_change_callbacks = NULL;
34+
static xSemaphoreHandle apb_change_lock = NULL;
35+
36+
static uint32_t _cpu_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
37+
static uint32_t _sys_time_multiplier = 1;
38+
39+
uint64_t IRAM_ATTR micros64(){
40+
return (uint64_t)(esp_timer_get_time()) * _sys_time_multiplier;
41+
}
42+
43+
//ToDo: figure out how to set FreeRTOS tick properly
44+
void delay(uint32_t ms){
45+
vTaskDelay((ms * _cpu_freq_mhz) / (portTICK_PERIOD_MS * CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ));
46+
}
47+
48+
static uint32_t calculateApb(rtc_cpu_freq_config_t * conf){
49+
if(conf->freq_mhz >= 80){
50+
return 80000000;
51+
}
52+
return (conf->source_freq_mhz * 1000000) / conf->div;
53+
}
54+
55+
static void initApbChangeCallback(){
56+
static volatile bool initialized = false;
57+
if(!initialized){
58+
initialized = true;
59+
apb_change_lock = xSemaphoreCreateMutex();
60+
if(!apb_change_lock){
61+
initialized = false;
62+
}
63+
}
64+
}
65+
66+
static void triggerApbChangeCallback(apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
67+
initApbChangeCallback();
68+
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
69+
apb_change_t * r = apb_change_callbacks;
70+
while(r != NULL){
71+
r->cb(r->arg, ev_type, old_apb, new_apb);
72+
}
73+
xSemaphoreGive(apb_change_lock);
74+
}
75+
76+
bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
77+
initApbChangeCallback();
78+
apb_change_t * c = (apb_change_t*)malloc(sizeof(apb_change_t));
79+
if(!c){
80+
log_e("Callback Object Malloc Failed");
81+
return false;
82+
}
83+
c->next = NULL;
84+
c->arg = arg;
85+
c->cb = cb;
86+
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
87+
if(apb_change_callbacks == NULL){
88+
apb_change_callbacks = c;
89+
} else {
90+
apb_change_t * r = apb_change_callbacks;
91+
if(r->cb != cb || r->arg != arg){
92+
while(r->next){
93+
r = r->next;
94+
if(r->cb == cb && r->arg == arg){
95+
goto unlock_and_exit;
96+
}
97+
}
98+
r->next = c;
99+
}
100+
}
101+
unlock_and_exit:
102+
xSemaphoreGive(apb_change_lock);
103+
return true;
104+
}
105+
106+
bool removeApbChangeCallback(void * arg, apb_change_cb_t cb){
107+
initApbChangeCallback();
108+
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
109+
apb_change_t * r = apb_change_callbacks;
110+
if(r == NULL){
111+
xSemaphoreGive(apb_change_lock);
112+
return false;
113+
}
114+
if(r->cb == cb && r->arg == arg){
115+
apb_change_callbacks = r->next;
116+
free(r);
117+
} else {
118+
while(r->next && (r->next->cb != cb || r->next->arg != arg)){
119+
r = r->next;
120+
}
121+
if(r->next == NULL || r->next->cb != cb || r->next->arg != arg){
122+
xSemaphoreGive(apb_change_lock);
123+
return false;
124+
}
125+
apb_change_t * c = r->next;
126+
r->next = c->next;
127+
free(c);
128+
}
129+
xSemaphoreGive(apb_change_lock);
130+
return true;
131+
}
132+
133+
bool setCpuFrequency(uint32_t cpu_freq_mhz){
134+
rtc_cpu_freq_config_t conf, cconf;
135+
uint32_t capb, apb;
136+
rtc_clk_cpu_freq_get_config(&cconf);
137+
if(cconf.freq_mhz == cpu_freq_mhz && _cpu_freq_mhz == cpu_freq_mhz){
138+
return true;
139+
}
140+
if(!rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &conf)){
141+
log_e("CPU clock could not be set to %u MHz", cpu_freq_mhz);
142+
return false;
143+
}
144+
capb = calculateApb(&cconf);
145+
apb = calculateApb(&conf);
146+
log_i("%s: %u / %u = %u Mhz", (conf.source == RTC_CPU_FREQ_SRC_PLL)?"PLL":((conf.source == RTC_CPU_FREQ_SRC_APLL)?"APLL":((conf.source == RTC_CPU_FREQ_SRC_XTAL)?"XTAL":"8M")), conf.source_freq_mhz, conf.div, conf.freq_mhz);
147+
if(capb != apb && apb_change_callbacks){
148+
triggerApbChangeCallback(APB_BEFORE_CHANGE, capb, apb);
149+
}
150+
rtc_clk_cpu_freq_set_config_fast(&conf);
151+
_cpu_freq_mhz = conf.freq_mhz;
152+
_sys_time_multiplier = 80000000 / apb;
153+
if(capb != apb && apb_change_callbacks){
154+
triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb);
155+
}
156+
return true;
157+
}
158+
159+
uint32_t getCpuFrequency(){
160+
rtc_cpu_freq_config_t conf;
161+
rtc_clk_cpu_freq_get_config(&conf);
162+
return conf.freq_mhz;
163+
}
164+
165+
uint32_t getApbFrequency(){
166+
rtc_cpu_freq_config_t conf;
167+
rtc_clk_cpu_freq_get_config(&conf);
168+
return calculateApb(&conf);
169+
}

Diff for: cores/esp32/esp32-hal-cpu.h

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef _ESP32_HAL_CPU_H_
16+
#define _ESP32_HAL_CPU_H_
17+
18+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif
21+
22+
#include <stdint.h>
23+
#include <stdbool.h>
24+
#include <stdlib.h>
25+
26+
typedef enum { APB_BEFORE_CHANGE, APB_AFTER_CHANGE } apb_change_ev_t;
27+
28+
typedef void (* apb_change_cb_t)(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);
29+
30+
bool addApbChangeCallback(void * arg, apb_change_cb_t cb);
31+
bool removeApbChangeCallback(void * arg, apb_change_cb_t cb);
32+
33+
//function takes the following frequencies as valid values:
34+
// 240, 160, 80 <<< For all XTAL types
35+
// 40, 20, 13, 10, 8, 5, 4, 3, 2, 1 <<< For 40MHz XTAL
36+
// 26, 13, 5, 4, 3, 2, 1 <<< For 26MHz XTAL
37+
// 24, 12, 8, 6, 4, 3, 2, 1 <<< For 24MHz XTAL
38+
bool setCpuFrequency(uint32_t cpu_freq_mhz);
39+
40+
uint32_t getCpuFrequency(); // In MHz
41+
uint32_t getApbFrequency(); // In Hz
42+
43+
uint64_t micros64(); // 64bit version of micros()
44+
45+
#ifdef __cplusplus
46+
}
47+
#endif
48+
49+
#endif /* _ESP32_HAL_CPU_H_ */

Diff for: cores/esp32/esp32-hal-misc.c

+4-49
Original file line numberDiff line numberDiff line change
@@ -100,57 +100,12 @@ void disableCore1WDT(){
100100
}
101101
#endif
102102

103-
static uint32_t _cpu_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
104-
static uint32_t _sys_time_multiplier = 1;
105-
106-
bool setCpuFrequency(uint32_t cpu_freq_mhz){
107-
rtc_cpu_freq_config_t conf, cconf;
108-
rtc_clk_cpu_freq_get_config(&cconf);
109-
if(cconf.freq_mhz == cpu_freq_mhz && _cpu_freq_mhz == cpu_freq_mhz){
110-
return true;
111-
}
112-
if(!rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &conf)){
113-
log_e("CPU clock could not be set to %u MHz", cpu_freq_mhz);
114-
return false;
115-
}
116-
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
117-
log_i("%s: %u / %u = %u Mhz", (conf.source == RTC_CPU_FREQ_SRC_PLL)?"PLL":((conf.source == RTC_CPU_FREQ_SRC_APLL)?"APLL":((conf.source == RTC_CPU_FREQ_SRC_XTAL)?"XTAL":"8M")), conf.source_freq_mhz, conf.div, conf.freq_mhz);
118-
delay(10);
119-
#endif
120-
rtc_clk_cpu_freq_set_config_fast(&conf);
121-
_cpu_freq_mhz = conf.freq_mhz;
122-
_sys_time_multiplier = 80000000 / getApbFrequency();
123-
return true;
124-
}
125-
126-
uint32_t getCpuFrequency(){
127-
rtc_cpu_freq_config_t conf;
128-
rtc_clk_cpu_freq_get_config(&conf);
129-
return conf.freq_mhz;
130-
}
131-
132-
uint32_t getApbFrequency(){
133-
rtc_cpu_freq_config_t conf;
134-
rtc_clk_cpu_freq_get_config(&conf);
135-
if(conf.freq_mhz >= 80){
136-
return 80000000;
137-
}
138-
return (conf.source_freq_mhz * 1000000) / conf.div;
103+
unsigned long IRAM_ATTR micros(){
104+
return (unsigned long) (micros64());
139105
}
140106

141-
unsigned long IRAM_ATTR micros()
142-
{
143-
return (unsigned long) (esp_timer_get_time()) * _sys_time_multiplier;
144-
}
145-
146-
unsigned long IRAM_ATTR millis()
147-
{
148-
return (unsigned long) (micros() / 1000);
149-
}
150-
151-
void delay(uint32_t ms)
152-
{
153-
vTaskDelay((ms * _cpu_freq_mhz) / (portTICK_PERIOD_MS * 240));
107+
unsigned long IRAM_ATTR millis(){
108+
return (unsigned long) (micros64() / 1000);
154109
}
155110

156111
void IRAM_ATTR delayMicroseconds(uint32_t us)

Diff for: cores/esp32/esp32-hal.h

+1-9
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ void yield(void);
6262
#include "esp32-hal-timer.h"
6363
#include "esp32-hal-bt.h"
6464
#include "esp32-hal-psram.h"
65+
#include "esp32-hal-cpu.h"
6566

6667
#ifndef BOARD_HAS_PSRAM
6768
#ifdef CONFIG_SPIRAM_SUPPORT
@@ -87,15 +88,6 @@ void enableCore1WDT();
8788
void disableCore1WDT();
8889
#endif
8990

90-
//function takes the following frequencies as valid values:
91-
// 240, 160, 80 <<< For all XTAL types
92-
// 40, 20, 13, 10, 8, 5, 4, 3, 2, 1 <<< For 40MHz XTAL
93-
// 26, 13, 5, 4, 3, 2, 1 <<< For 26MHz XTAL
94-
// 24, 12, 8, 6, 4, 3, 2, 1 <<< For 24MHz XTAL
95-
bool setCpuFrequency(uint32_t cpu_freq_mhz);
96-
uint32_t getCpuFrequency();
97-
uint32_t getApbFrequency();
98-
9991
unsigned long micros();
10092
unsigned long millis();
10193
void delay(uint32_t);

0 commit comments

Comments
 (0)