Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpu/esp: migrate to ztimer #17386

Merged
merged 1 commit into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cpu/esp32/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Define the module that is built:
MODULE = cpu

SRC = irq_arch.c startup.c syscalls.c

# Add a list of subdirectories, that should also be built:
DIRS += $(RIOTCPU)/esp_common
DIRS += periph
Expand All @@ -14,4 +16,8 @@ ifneq (, $(filter esp_freertos, $(USEMODULE)))
DIRS += freertos
endif

ifneq (,$(filter esp_wifi% esp_eth, $(USEMODULE)))
SRC += esp_ztimer.c
endif

include $(RIOTBASE)/Makefile.base
4 changes: 2 additions & 2 deletions cpu/esp32/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ ifneq (,$(filter esp_eth,$(USEMODULE)))
USEMODULE += esp_idf_eth_phy
USEMODULE += netdev_eth
USEMODULE += netopt
USEMODULE += xtimer
USEMODULE += ztimer_msec
gschorcht marked this conversation as resolved.
Show resolved Hide resolved
endif

ifneq (,$(filter esp_wifi_any,$(USEMODULE)))
Expand Down Expand Up @@ -55,7 +55,7 @@ endif
ifneq (,$(filter periph_i2c,$(USEMODULE)))
ifneq (,$(filter esp_i2c_hw,$(USEMODULE)))
USEMODULE += core_thread_flags
USEMODULE += xtimer
USEMODULE += ztimer_msec
USEMODULE += periph_i2c_hw
else
# PLEASE NOTE: because of the very poor and faulty hardware implementation
Expand Down
4 changes: 2 additions & 2 deletions cpu/esp32/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1212,7 +1212,7 @@ Possible wake-up sources for the _Light-sleep_ mode are:
`ESP_PM_WUP_UART1`)

@note Since the digital core (MCU) is stalled during _Light-sleep_, it
is not possible timers like `periph_timer` or `xtimer` as wake-up source.
is not possible to use timers like `periph_timer` or `ztimer` as wake-up source.

@warning
Since only level interrupts are supported in _Light-sleep_ mode,
Expand Down Expand Up @@ -1569,7 +1569,7 @@ The following parameters are defined for ESP-NOW nodes. These parameters can be

Parameter | Default | Description
:-----------------------|:--------------------------|:-----------
ESP_NOW_SCAN_PERIOD | 10000000UL | Defines the period in us at which an node scans for other nodes in its range. The default period is 10 s.
ESP_NOW_SCAN_PERIOD_MS | 10000UL | Defines the period in ms at which an node scans for other nodes in its range. The default period is 10 s.
ESP_NOW_SOFT_AP_PASS | "ThisistheRIOTporttoESP" | Defines the passphrase as clear text (max. 64 chars) that is used for the SoftAP interface of ESP-NOW nodes. It has to be same for all nodes in one network.
ESP_NOW_CHANNEL | 6 | Defines the channel that is used as the broadcast medium by all nodes together.
ESP_NOW_KEY | NULL | Defines a key that is used for encrypted communication between nodes. If it is NULL, encryption is disabled. The key has to be of type `uint8_t[16]` and has to be exactly 16 bytes long.
Expand Down
10 changes: 6 additions & 4 deletions cpu/esp32/esp-eth/esp_eth_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
#include "net/ethernet.h"
#include "net/netdev/eth.h"

#include "xtimer.h"
#include "timex.h"
#include "ztimer.h"

#include "esp_common.h"
#include "esp_attr.h"
Expand All @@ -43,14 +44,15 @@

#include "esp32/esp_event_loop.h"

#include "board.h"
#if !defined(EMAC_PHY_SMI_MDC_PIN) || !defined(EMAC_PHY_SMI_MDIO_PIN)
#error Board definition does not provide EMAC configuration
#endif

#define SYSTEM_EVENT_ETH_RX_DONE (SYSTEM_EVENT_MAX + 1)
#define SYSTEM_EVENT_ETH_TX_DONE (SYSTEM_EVENT_MAX + 2)

#define EMAC_PHY_CLOCK_DELAY (500 * USEC_PER_MSEC) /* given in us */
#define EMAC_PHY_CLOCK_DELAY_MS (500)

#ifdef EMAC_PHY_LAN8720
#include "eth_phy/phy_lan8720.h"
Expand Down Expand Up @@ -130,7 +132,7 @@ static void _esp_eth_phy_power_enable_gpio(bool enable)
gpio_init(EMAC_PHY_POWER_PIN, GPIO_OUT);
gpio_write(EMAC_PHY_POWER_PIN, enable);

xtimer_usleep (USEC_PER_MSEC);
ztimer_sleep(ZTIMER_MSEC, 1);

if (enable) {
EMAC_ETHERNET_PHY_CONFIG.phy_power_enable(true);
Expand Down Expand Up @@ -171,7 +173,7 @@ static int _esp_eth_init(netdev_t *netdev)
* after activating clock logic it can take some time before we can
* enable EMAC
*/
xtimer_usleep (EMAC_PHY_CLOCK_DELAY);
ztimer_sleep(ZTIMER_MSEC, EMAC_PHY_CLOCK_DELAY_MS);

if (ret == ESP_OK && (ret = esp_eth_enable()) != ESP_OK) {
LOG_TAG_ERROR("esp_eth", "enable failed");
Expand Down
75 changes: 40 additions & 35 deletions cpu/esp32/esp_xtimer.c → cpu/esp32/esp_ztimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* @{
*
* @file
* @brief ETS timer to xtimer mapper
* @brief ETS timer to ztimer mapper
*
* @author Gunar Schorcht <gunar@schorcht.net>
*
Expand All @@ -29,72 +29,73 @@

#include "esp_attr.h"
#include "irq_arch.h"
#include "xtimer.h"
#include "ztimer.h"
#include "timex.h"

#include "rom/ets_sys.h"

struct _ets_to_xtimer {
struct _ets_to_ztimer {
ETSTimer *ets_timer;
xtimer_t xtimer;
ztimer_t ztimer;
};

/* maximum number of ETS timer to xtimer mapper objects */
/* maximum number of ETS timer to ztimer mapper objects */
/* TODO tune the value */
#define ETS_TO_TIMER_NUM 40

/* table of ETS timer to xtimer mapper objects */
static struct _ets_to_xtimer _ets_to_xtimer_map[ETS_TO_TIMER_NUM] = {};
/* table of ETS timer to ztimer mapper objects */
static struct _ets_to_ztimer _ets_to_ztimer_map[ETS_TO_TIMER_NUM] = {};

/**
* @brief Get the ETS timer to xtimer mapper object for the given timer.
* @brief Get the ETS timer to ztimer mapper object for the given timer.
*
* If there is no object, the function registers a new one and returns it.
* If there is no more object available, it returns NULL.
*
* @param pointer to the ETS timer
* @return pointer to the mapper object or NULL in case of error
*/
struct _ets_to_xtimer* _ets_to_xtimer_get(ETSTimer *timer)
struct _ets_to_ztimer* _ets_to_ztimer_get(ETSTimer *timer)
{
/* search for an existing mapper object */
for (int i = 0; i < ETS_TO_TIMER_NUM; i++) {
if (_ets_to_xtimer_map[i].ets_timer == timer) {
return &_ets_to_xtimer_map[i];
if (_ets_to_ztimer_map[i].ets_timer == timer) {
return &_ets_to_ztimer_map[i];
}
}
/* search for a free mapper object */
for (int i = 0; i < ETS_TO_TIMER_NUM; i++) {
if (_ets_to_xtimer_map[i].ets_timer == NULL) {
_ets_to_xtimer_map[i].ets_timer = timer;
return &_ets_to_xtimer_map[i];
if (_ets_to_ztimer_map[i].ets_timer == NULL) {
_ets_to_ztimer_map[i].ets_timer = timer;
return &_ets_to_ztimer_map[i];
}
}
LOG_TAG_ERROR("esp_xtimer", "There is no free ETS timer to xtimer mapper "
LOG_TAG_ERROR("esp_ztimer", "There is no free ETS timer to ztimer mapper "
"object available\n");
return NULL;
}

/**
* @brief Free the ETS timer to xtimer mapper object for the given timer.
* @brief Free the ETS timer to ztimer mapper object for the given timer.
* @param pointer to the ETS timer
*/
void _ets_to_xtimer_free(ETSTimer *timer)
void _ets_to_ztimer_free(ETSTimer *timer)
{
/* search for an existing mapper object */
for (int i = 0; i < ETS_TO_TIMER_NUM; i++) {
if (_ets_to_xtimer_map[i].ets_timer == timer) {
_ets_to_xtimer_map[i].ets_timer = NULL;
if (_ets_to_ztimer_map[i].ets_timer == timer) {
_ets_to_ztimer_map[i].ets_timer = NULL;
return;
}
}
DEBUG("%s There is no ETS timer to xtimer for ETS timer %p\n",
DEBUG("%s There is no ETS timer to ztimer for ETS timer %p\n",
__func__, timer);
}

/* xtimer call back function, distributes ets_timer callbacks */
void IRAM_ATTR _ets_to_xtimer_callback (void *arg)
/* ztimer call back function, distributes ets_timer callbacks */
void IRAM_ATTR _ets_to_ztimer_callback (void *arg)
{
struct _ets_to_xtimer* e2xt = (struct _ets_to_xtimer*)arg;
struct _ets_to_ztimer* e2xt = (struct _ets_to_ztimer*)arg;

assert(arg != NULL);
assert(e2xt->ets_timer != NULL);
Expand All @@ -115,22 +116,22 @@ void ets_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunc, void *parg)
{
DEBUG("%s timer=%p pfunc=%p parg=%p\n", __func__, ptimer, pfunc, parg);

struct _ets_to_xtimer* e2xt = _ets_to_xtimer_get(ptimer);
struct _ets_to_ztimer* e2xt = _ets_to_ztimer_get(ptimer);

assert(e2xt != NULL);

e2xt->ets_timer->timer_func = pfunc;
e2xt->ets_timer->timer_arg = parg;

e2xt->xtimer.callback = &_ets_to_xtimer_callback;
e2xt->xtimer.arg = (void*)e2xt;
e2xt->ztimer.callback = &_ets_to_ztimer_callback;
e2xt->ztimer.arg = (void*)e2xt;
}

void ets_timer_done(ETSTimer *ptimer)
{
DEBUG("%s timer=%p\n", __func__, ptimer);

struct _ets_to_xtimer* e2xt = _ets_to_xtimer_get(ptimer);
struct _ets_to_ztimer* e2xt = _ets_to_ztimer_get(ptimer);

assert(e2xt != NULL);

Expand All @@ -142,31 +143,35 @@ void ets_timer_arm_us(ETSTimer *timer, uint32_t tmout, bool repeat)
{
DEBUG("%s timer=%p tmout=%u repeat=%d\n", __func__, timer, tmout, repeat);

struct _ets_to_xtimer* e2xt = _ets_to_xtimer_get(timer);
struct _ets_to_ztimer* e2xt = _ets_to_ztimer_get(timer);

assert(e2xt != NULL);
assert(e2xt->xtimer.callback != NULL);
assert(e2xt->ztimer.callback != NULL);

xtimer_set(&e2xt->xtimer, tmout);
tmout = (tmout + 500) / 1000;
uint32_t now = ztimer_set(ZTIMER_MSEC, &e2xt->ztimer, tmout);

e2xt->ets_timer->timer_expire = e2xt->xtimer.start_time + e2xt->xtimer.offset;
e2xt->ets_timer->timer_period = repeat ? tmout : 0;
/* Note: this is approximating the expiry time since for very short timeout
this might be set to a minimum value that guarantees the ISR
being executed */
e2xt->ets_timer->timer_expire = (now + tmout) * 1000;
e2xt->ets_timer->timer_period = repeat ? (tmout * 1000) : 0;
}

void ets_timer_arm(ETSTimer *timer, uint32_t tmout, bool repeat)
{
ets_timer_arm_us(timer, tmout * USEC_PER_MSEC, repeat);
ets_timer_arm_us(timer, tmout * US_PER_MS, repeat);
}

void ets_timer_disarm(ETSTimer *timer)
{
DEBUG("%s timer=%p\n", __func__, timer);

struct _ets_to_xtimer* e2xt = _ets_to_xtimer_get(timer);
struct _ets_to_ztimer* e2xt = _ets_to_ztimer_get(timer);

assert(e2xt != NULL);

xtimer_remove(&e2xt->xtimer);
ztimer_remove(ZTIMER_MSEC, &e2xt->ztimer);
}

void ets_timer_init(void)
Expand Down
3 changes: 2 additions & 1 deletion cpu/esp32/periph/Kconfig.i2c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ config MODULE_ESP_I2C_SW
config MODULE_ESP_I2C_HW
bool "Hardware"
select MODULE_CORE_THREAD_FLAGS
select MODULE_XTIMER
select MODULE_ZTIMER
select MODULE_ZTIMER_MSEC
select MODULE_PERIPH_I2C_HW

endchoice
Expand Down
10 changes: 5 additions & 5 deletions cpu/esp32/periph/i2c_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -672,11 +672,11 @@ static const uint32_t transfer_int_mask = I2C_TRANS_COMPLETE_INT_ENA
| I2C_TIME_OUT_INT_ENA;

/* at I2C_SPEED_NORMAL a transfer takes at most 33 byte * 9 clock cycles * 1/100000 s */
#define I2C_TRANSFER_TIMEOUT 3000
#define I2C_TRANSFER_TIMEOUT_MS 3

#define I2C_THREAD_FLAG BIT (0)

#include "xtimer.h"
#include "ztimer.h"

void _i2c_transfer_timeout (void *arg)
{
Expand Down Expand Up @@ -713,10 +713,10 @@ static void _i2c_transfer (i2c_t dev)
_i2c_hw[dev].regs->int_clr.val = transfer_int_mask;

/* set a timer for the case the I2C hardware gets stuck */
xtimer_t i2c_timeout = {};
ztimer_t i2c_timeout = {};
i2c_timeout.callback = _i2c_transfer_timeout;
i2c_timeout.arg = (void*)(uintptr_t)dev;
xtimer_set(&i2c_timeout, I2C_TRANSFER_TIMEOUT);
ztimer_set(ZTIMER_MSEC, &i2c_timeout, I2C_TRANSFER_TIMEOUT_MS);

/* start execution of commands in command pipeline registers */
_i2c_bus[dev].pid = thread_getpid();
Expand All @@ -726,7 +726,7 @@ static void _i2c_transfer (i2c_t dev)

/* wait for transfer results and remove timeout timer*/
thread_flags_wait_one(I2C_THREAD_FLAG);
xtimer_remove(&i2c_timeout);
ztimer_remove(ZTIMER_MSEC, &i2c_timeout);

/* returned from transmission */
DEBUG("%s results=%08x\n", __func__, _i2c_bus[dev].results);
Expand Down
1 change: 0 additions & 1 deletion cpu/esp32/periph/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include "gpio_arch.h"
#include "rtt_arch.h"
#include "syscalls.h"
#include "xtimer.h"

#include "periph/rtc.h"
#include "rom/rtc.h"
Expand Down
7 changes: 4 additions & 3 deletions cpu/esp32/periph/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
#include "esp_common.h"
#include "irq_arch.h"
#include "syscalls.h"
#include "xtimer.h"

#define RTC_PLL_480M 480 /* PLL with 480 MHz at maximum */
#define RTC_PLL_320M 320 /* PLL with 480 MHz at maximum */
Expand Down Expand Up @@ -74,6 +73,7 @@
#define HW_TIMER_CLK_DIV (rtc_clk_apb_freq_get() / 1000000)
#define HW_TIMER_CORRECTION (RTC_PLL_320M / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ)
#define HW_TIMER_DELTA_MIN (MAX(HW_TIMER_CORRECTION << 1, 5))
#define HW_TIMER_FREQUENCY (1000000UL) /* only 1MHz is supported */

struct hw_timer_regs_t {
/* see Technical Reference, section 17.4 */
Expand Down Expand Up @@ -198,7 +198,7 @@ int timer_init (tim_t dev, uint32_t freq, timer_cb_t cb, void *arg)
__func__, dev, freq, cb, arg);

CHECK_PARAM_RET (dev < HW_TIMER_NUMOF, -1);
CHECK_PARAM_RET (freq == XTIMER_HZ_BASE, -1);
CHECK_PARAM_RET (freq == HW_TIMER_FREQUENCY, -1);
CHECK_PARAM_RET (cb != NULL, -1);

if (timers[dev].initialized) {
Expand Down Expand Up @@ -367,6 +367,7 @@ void IRAM timer_stop(tim_t dev)
#define HW_TIMER_DELTA_MAX 0x00ffffff /* in us */
#define HW_TIMER_DELTA_MASK 0x00ffffff
#define HW_TIMER_DELTA_RSHIFT 24
#define HW_TIMER_FREQUENCY (1000000UL) /* only 1MHz is supported */

#define HW_TIMER_CORRECTION (RTC_PLL_480M / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ)
#define HW_TIMER_DELTA_MIN (MAX(HW_TIMER_CORRECTION, 5))
Expand Down Expand Up @@ -442,7 +443,7 @@ int timer_init (tim_t dev, uint32_t freq, timer_cb_t cb, void *arg)
DEBUG("%s dev=%u freq=%u cb=%p arg=%p\n", __func__, dev, freq, cb, arg);

CHECK_PARAM_RET (dev < HW_TIMER_NUMOF, -1);
CHECK_PARAM_RET (freq == XTIMER_HZ_BASE, -1);
CHECK_PARAM_RET (freq == HW_TIMER_FREQUENCY, -1);
CHECK_PARAM_RET (cb != NULL, -1);

if (timers[dev].initialized) {
Expand Down
2 changes: 1 addition & 1 deletion cpu/esp32/syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ uint32_t system_get_time(void)

uint32_t system_get_time_ms(void)
{
return system_get_time_64() / USEC_PER_MSEC;
return system_get_time_64() / US_PER_MS;
}

uint64_t system_get_time_64(void)
Expand Down
2 changes: 1 addition & 1 deletion cpu/esp8266/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ be overridden by [application-specific board configurations](#esp8266_applicatio

Parameter | Default | Description
:---------|:--------|:-----------
#ESP_NOW_SCAN_PERIOD | 10000000UL | Defines the period in us at which an node scans for other nodes in its range. The default period is 10 s.
#ESP_NOW_SCAN_PERIOD_MS | 10000UL | Defines the period in ms at which an node scans for other nodes in its range. The default period is 10 s.
#ESP_NOW_SOFT_AP_PASS | "ThisistheRIOTporttoESP" | Defines the passphrase as clear text (max. 64 chars) that is used for the SoftAP interface of ESP-NOW nodes. It has to be same for all nodes in one network.
#ESP_NOW_CHANNEL | 6 | Defines the channel that is used as the broadcast medium by all nodes together.
#ESP_NOW_KEY | NULL | Defines a key that is used for encrypted communication between nodes. If it is NULL, encryption is disabled. The key has to be of type `uint8_t[16]` and has to be exactly 16 bytes long.
Expand Down
2 changes: 1 addition & 1 deletion cpu/esp8266/ld/esp8266.riot-os.ld
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ SECTIONS
*freertos/*(.literal .text .literal.* .text.*)
*freertos_common/*(.literal .text .literal.* .text.*)
*periph/*(.literal .text .literal.* .text.*)
*xtimer/*(.literal .text .literal.* .text.*)
*ztimer/*(.literal .text .literal.* .text.*)
Copy link
Contributor

@gschorcht gschorcht Dec 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would have to be:

-     *ztimer/*(.literal .text .literal.* .text.*)
+     *ztimer_core/*(.literal .text .literal.* .text.*)

When I was reviewing it, I didn't know that objects are not stored in ztimer but in ztimer_core although the module is called ztimer. But this alone doesn't solve the problem, unfortunatly 😟


*libhal.a:clock.o(.literal .text .literal.* .text.*)
*libhal.a:int_asm--set_intclear.o(.literal .text .literal.* .text.*)
Expand Down
Loading