Skip to content

Commit

Permalink
Merge pull request #18260 from gschorcht/cpu/esp32/add_riscv_platform…
Browse files Browse the repository at this point in the history
…_code

cpu/esp32: add platform code for RISC-V based ESP32x SoCs
  • Loading branch information
benpicco authored Jul 18, 2022
2 parents 263b918 + 778ff10 commit e1bc176
Show file tree
Hide file tree
Showing 11 changed files with 435 additions and 10 deletions.
2 changes: 1 addition & 1 deletion cpu/esp32/esp_ztimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void ets_timer_done(ETSTimer *ptimer)

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);
DEBUG("%s timer=%p tmout=%"PRIu32" repeat=%d\n", __func__, timer, tmout, repeat);

struct _ets_to_ztimer* e2xt = _ets_to_ztimer_get(timer);

Expand Down
20 changes: 11 additions & 9 deletions cpu/esp32/periph/rtt.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Gunar Schorcht
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
Expand Down Expand Up @@ -82,7 +82,8 @@ void rtt_init(void)
}
}

DEBUG("%s rtt_offset=%u @rtc=%llu rtc_active=%d @sys_time=%llu\n", __func__,
DEBUG("%s rtt_offset=%" PRIu32 " @rtc=%" PRIu64
" rtc_active=%d @sys_time=%" PRIi64 "\n", __func__,
_rtt_offset, _rtc_get_counter(),
(_rtt_hw == &_rtt_hw_sys_driver) ? 1 : 0, system_get_time_64());

Expand Down Expand Up @@ -132,7 +133,8 @@ uint32_t rtt_get_counter(void)
{
/* we use only the lower 32 bit of the 48-bit RTC counter */
uint32_t counter = _rtt_hw->get_counter() + _rtt_offset;
DEBUG("%s counter=%u @sys_time=%u\n", __func__, counter, system_get_time());
DEBUG("%s counter=%" PRIu32 " @sys_time=%" PRIu32" \n",
__func__, counter, system_get_time());
return counter;
}

Expand All @@ -141,7 +143,7 @@ void rtt_set_counter(uint32_t counter)
uint32_t _rtt_current = _rtt_hw->get_counter();
_rtt_offset = counter - _rtt_current;

DEBUG("%s set=%u rtt_offset=%u @rtt=%u\n",
DEBUG("%s set=%" PRIu32 " rtt_offset=%" PRIu32 " @rtt=%" PRIu32 "\n",
__func__, counter, _rtt_offset, _rtt_current);

_rtt_update_hw_alarm();
Expand All @@ -154,7 +156,7 @@ void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
rtt_counter.alarm_cb = cb;
rtt_counter.alarm_arg = arg;

DEBUG("%s alarm=%u @rtt=%u\n", __func__, alarm, counter);
DEBUG("%s alarm=%" PRIu32 " @rtt=%" PRIu32 "\n", __func__, alarm, counter);

_rtt_update_hw_alarm();
}
Expand All @@ -166,7 +168,7 @@ void rtt_clear_alarm(void)
rtt_counter.alarm_cb = NULL;
rtt_counter.alarm_arg = NULL;

DEBUG("%s @rtt=%u\n", __func__, (uint32_t)_rtt_hw->get_counter());
DEBUG("%s @rtt=%" PRIu32 "\n", __func__, (uint32_t)_rtt_hw->get_counter());

_rtt_update_hw_alarm();
}
Expand Down Expand Up @@ -197,7 +199,7 @@ uint64_t rtt_pm_sleep_enter(unsigned mode)
uint32_t counter = rtt_get_counter();
uint64_t t_diff = RTT_TICKS_TO_US(rtt_counter.alarm_active - counter);

DEBUG("%s rtt_alarm=%u @rtt=%u t_diff=%llu\n", __func__,
DEBUG("%s rtt_alarm=%" PRIu32 " @rtt=%" PRIu32 " t_diff=%llu\n", __func__,
rtt_counter.alarm_active, counter, t_diff);

if (t_diff) {
Expand Down Expand Up @@ -250,7 +252,7 @@ static void IRAM_ATTR _rtt_isr(void *arg)

if (rtt_counter.wakeup) {
rtt_counter.wakeup = false;
DEBUG("%s wakeup alarm alarm=%u rtt_alarm=%u @rtt=%u\n",
DEBUG("%s wakeup alarm alarm=%" PRIu32 " rtt_alarm=%" PRIu32 " @rtt=%" PRIu32 "\n",
__func__, alarm, rtt_counter.alarm_active, rtt_get_counter());
}

Expand All @@ -276,7 +278,7 @@ static void IRAM_ATTR _rtt_isr(void *arg)
}
}

DEBUG("%s next rtt=%u\n", __func__, rtt_counter.alarm_active);
DEBUG("%s next rtt=%" PRIu32 "\n", __func__, rtt_counter.alarm_active);
}

uint32_t _rtt_hw_to_rtt_counter(uint32_t hw_counter)
Expand Down
6 changes: 6 additions & 0 deletions cpu/esp_common/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ config HAS_ARCH_ESP_XTENSA
help
Indicates that an Xtensa-based 'ESP' architecture is being used.

config HAS_ARCH_ESP_RISCV
bool
help
Indicates that an RISC-V-based 'ESP' architecture is being used.

config HAS_ESP_WIFI_ENTERPRISE
bool
help
Expand Down Expand Up @@ -119,6 +124,7 @@ config MODULE_ESP_LOG_STARTUP
config MODULE_ESP_QEMU
bool "Simulate ESP with QEMU"

rsource "esp-riscv/Kconfig"
rsource "esp-xtensa/Kconfig"
rsource "freertos/Kconfig"
rsource "periph/Kconfig"
Expand Down
4 changes: 4 additions & 0 deletions cpu/esp_common/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ ifneq (,$(filter esp_xtensa,$(USEMODULE)))
DIRS += esp-xtensa
endif

ifneq (,$(filter esp_riscv,$(USEMODULE)))
DIRS += esp-riscv
endif

include $(RIOTBASE)/Makefile.base
4 changes: 4 additions & 0 deletions cpu/esp_common/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ ifeq (xtensa,$(CPU_ARCH))
USEMODULE += xtensa
endif

ifeq (riscv_esp32,$(CPU_ARCH))
USEMODULE += esp_riscv
endif

# Features used by ESP*

FEATURES_REQUIRED += newlib
Expand Down
4 changes: 4 additions & 0 deletions cpu/esp_common/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ ifeq (xtensa,$(CPU_ARCH))
FEATURES_PROVIDED += arch_esp_xtensa
endif

ifeq (riscv_esp32,$(CPU_ARCH))
FEATURES_PROVIDED += arch_esp_riscv
endif

FEATURES_CONFLICT += esp_wifi_ap:esp_now
FEATURES_CONFLICT_MSG += "ESP_NOW and ESP_WIFI_AP can not be used at the same time."

Expand Down
14 changes: 14 additions & 0 deletions cpu/esp_common/esp-riscv/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2022 Gunar Schorcht
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
#

config MODULE_ESP_RISCV
bool
depends on TEST_KCONFIG
depends on HAS_ARCH_ESP_RISCV
default y
help
Platform-dependent code for Xtensa-based ESP SoCs.
3 changes: 3 additions & 0 deletions cpu/esp_common/esp-riscv/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE=esp_riscv

include $(RIOTBASE)/Makefile.base
75 changes: 75 additions & 0 deletions cpu/esp_common/esp-riscv/exceptions.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup cpu_esp_common
* @{
*
* @file
* @brief Exception handling for RISC-V-based ESP SoCs
*
* @author Gunar Schorcht <[email protected]>
* @}
*/

#include <inttypes.h>

#include "kernel_defines.h"
#include "panic.h"
#include "periph/pm.h"

#include "esp_attr.h"
#include "riscv/rvruntime-frames.h"
#include "rom/ets_sys.h"

static const char *exceptions[] = {
"nil",
"0x1: PMP Instruction access fault",
"0x2: Illegal Instruction",
"0x3: Hardware Breakpoint/Watchpoint or EBREAK",
"nil",
"0x5: PMP Load access fault",
"nil",
"0x7: PMP Store access fault",
"0x8: ECALL from U mode",
"nil",
"nil",
"0xb: ECALL from M mode",
};

static RvExcFrame *_frame = NULL;

void init_exceptions (void)
{
}

void IRAM_ATTR xt_unhandled_exception(RvExcFrame *frame)
{
_frame = frame;
core_panic(PANIC_GENERAL_ERROR, "Unhandled exception");
}

void IRAM_ATTR panicHandler(RvExcFrame *frame)
{
_frame = frame;
core_panic(PANIC_GENERAL_ERROR, "Panic handler");
}

extern void heap_stats(void);

void panic_arch(void)
{
if (_frame) {
/* TODO */
ets_printf("Exception @0x%08"PRIx32", cause %s\n",
_frame->mepc, exceptions[_frame->mcause]);
}
#if defined(DEVELHELP)
heap_stats();
#endif
}
97 changes: 97 additions & 0 deletions cpu/esp_common/esp-riscv/irq_arch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright (C) 2022 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup cpu_esp32
* @{
*
* @file
* @brief Implementation of the kernels irq interface
*
* @author Gunar Schorcht <[email protected]>
*
* @}
*/

#include "irq_arch.h"

#include "esp_attr.h"
#include "hal/interrupt_controller_types.h"
#include "hal/interrupt_controller_ll.h"
#include "soc/periph_defs.h"

#define ENABLE_DEBUG 0
#include "debug.h"

#define RVHAL_EXCM_LEVEL 4

/**
* @brief Disable all maskable interrupts
*/
unsigned int IRAM_ATTR irq_disable(void)
{
uint32_t mstatus;
/* clear MIE bit in register mstatus */
__asm__ volatile ("csrrc %0, mstatus, %1" : "=r"(mstatus) : "rK"(MSTATUS_MIE) : "memory");

/* save interrupt priority level threshold */
uint32_t state = *((volatile uint32_t *)INTERRUPT_CORE0_CPU_INT_THRESH_REG);
/* set interrupt priority level threshold to exception level */
*((volatile uint32_t *)INTERRUPT_CORE0_CPU_INT_THRESH_REG) = RVHAL_EXCM_LEVEL;

/* set MIE bit in register mstatus */
__asm__ volatile ("csrrs %0, mstatus, %1" : "=r"(mstatus) : "rK"(MSTATUS_MIE) : "memory");

DEBUG("%s %02x(%02x)\n", __func__, RVHAL_EXCM_LEVEL, (unsigned)state);
return state;
}

/**
* @brief Enable all maskable interrupts
*/
unsigned int IRAM_ATTR irq_enable(void)
{
uint32_t state = *((volatile uint32_t *)INTERRUPT_CORE0_CPU_INT_THRESH_REG);

/* set interrupt priority level threshold to 0 */
*((volatile uint32_t *)INTERRUPT_CORE0_CPU_INT_THRESH_REG) = 0;

/* small delay needed here */
__asm__ volatile ( "nop" );
__asm__ volatile ( "nop" );
__asm__ volatile ( "nop" );

DEBUG("%s %02x(%02x)\n", __func__, 0, (unsigned)state);
return state;
}

/**
* @brief Restore the state of the IRQ flags
*/
void IRAM_ATTR irq_restore(unsigned int state)
{
uint32_t old = *((volatile uint32_t *)INTERRUPT_CORE0_CPU_INT_THRESH_REG);

/* set interrupt priority level threshold to old level */
*((volatile uint32_t *)INTERRUPT_CORE0_CPU_INT_THRESH_REG) = state;

/* small delay needed here */
__asm__ volatile ( "nop" );
__asm__ volatile ( "nop" );
__asm__ volatile ( "nop" );

DEBUG("%s %02x(%02x)\n", __func__, (unsigned)state, (unsigned)old);
}

/**
* @brief Test if IRQs are currently enabled
*/
bool IRAM_ATTR irq_is_enabled(void)
{
return *((volatile uint32_t *)INTERRUPT_CORE0_CPU_INT_THRESH_REG) == 0;
}
Loading

0 comments on commit e1bc176

Please sign in to comment.