Skip to content

Commit

Permalink
cpu/esp*: migrate from xtimer to ztimer
Browse files Browse the repository at this point in the history
  • Loading branch information
fjmolinas committed Dec 14, 2021
1 parent efa24b3 commit b805821
Show file tree
Hide file tree
Showing 23 changed files with 115 additions and 99 deletions.
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
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
6 changes: 3 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 @@ -442,7 +442,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.*)

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

0 comments on commit b805821

Please sign in to comment.