xtensa: move soc to top-level dir soc/
Move the SoC outside of the architecture tree and put them at the same level as boards and architectures allowing both SoCs and boards to be maintained outside the tree. Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
parent
f183444682
commit
cea0b3a9c2
58 changed files with 9 additions and 17 deletions
4
soc/xtensa/esp32/CMakeLists.txt
Normal file
4
soc/xtensa/esp32/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
zephyr_sources(
|
||||
soc.c
|
||||
esp32-mp.c
|
||||
)
|
21
soc/xtensa/esp32/Kconfig.defconfig
Normal file
21
soc/xtensa/esp32/Kconfig.defconfig
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Kconfig - ESP32 board configuration
|
||||
#
|
||||
# Copyright (c) 2017 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if SOC_ESP32
|
||||
|
||||
config SOC
|
||||
string
|
||||
default "esp32"
|
||||
|
||||
config IRQ_OFFLOAD_INTNUM
|
||||
default 7
|
||||
|
||||
config XTENSA_ASM2
|
||||
def_bool y
|
||||
|
||||
config MP_NUM_CPUS
|
||||
default 2
|
||||
|
||||
endif
|
6
soc/xtensa/esp32/Kconfig.soc
Normal file
6
soc/xtensa/esp32/Kconfig.soc
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Copyright (c) 2017 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config SOC_ESP32
|
||||
bool "ESP32"
|
||||
|
223
soc/xtensa/esp32/esp32-mp.c
Normal file
223
soc/xtensa/esp32/esp32-mp.c
Normal file
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Include esp-idf headers first to avoid redefining BIT() macro */
|
||||
#include <soc.h>
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <spinlock.h>
|
||||
#include <kernel_structs.h>
|
||||
|
||||
#define _REG(base, off) (*(volatile u32_t *)((base) + (off)))
|
||||
|
||||
#define RTC_CNTL_BASE 0x3ff48000
|
||||
#define RTC_CNTL_OPTIONS0 _REG(RTC_CNTL_BASE, 0x0)
|
||||
#define RTC_CNTL_SW_CPU_STALL _REG(RTC_CNTL_BASE, 0xac)
|
||||
|
||||
#define DPORT_BASE 0x3ff00000
|
||||
#define DPORT_APPCPU_CTRL_A _REG(DPORT_BASE, 0x02C)
|
||||
#define DPORT_APPCPU_CTRL_B _REG(DPORT_BASE, 0x030)
|
||||
#define DPORT_APPCPU_CTRL_C _REG(DPORT_BASE, 0x034)
|
||||
|
||||
struct cpustart_rec {
|
||||
int cpu;
|
||||
void (*fn)(int, void *);
|
||||
char *stack_top;
|
||||
void *arg;
|
||||
int vecbase;
|
||||
volatile int *alive;
|
||||
};
|
||||
|
||||
volatile struct cpustart_rec *start_rec;
|
||||
static void *appcpu_top;
|
||||
|
||||
static struct k_spinlock loglock;
|
||||
|
||||
/* Note that the logging done here is ACTUALLY REQUIRED FOR RELIABLE
|
||||
* OPERATION! At least one particular board will experience spurious
|
||||
* hangs during initialization (usually the APPCPU fails to start at
|
||||
* all) without these calls present. It's not just time -- careful
|
||||
* use of k_busy_wait() (and even hand-crafted timer loops using the
|
||||
* Xtensa timer SRs directly) that duplicates the timing exactly still
|
||||
* sees hangs. Something is happening inside the ROM UART code that
|
||||
* magically makes the startup sequence reliable.
|
||||
*
|
||||
* Leave this in place until the sequence is understood better.
|
||||
*
|
||||
* (Note that the use of the spinlock is cosmetic only -- if you take
|
||||
* it out the messages will interleave across the two CPUs but startup
|
||||
* will still be reliable.)
|
||||
*/
|
||||
void smp_log(const char *msg)
|
||||
{
|
||||
k_spinlock_key_t key = k_spin_lock(&loglock);
|
||||
|
||||
while (*msg) {
|
||||
esp32_rom_uart_tx_one_char(*msg++);
|
||||
}
|
||||
esp32_rom_uart_tx_one_char('\r');
|
||||
esp32_rom_uart_tx_one_char('\n');
|
||||
|
||||
k_spin_unlock(&loglock, key);
|
||||
}
|
||||
|
||||
static void appcpu_entry2(void)
|
||||
{
|
||||
volatile int ps, ie;
|
||||
smp_log("ESP32: APPCPU running");
|
||||
|
||||
/* Copy over VECBASE from the main CPU for an initial value
|
||||
* (will need to revisit this if we ever allow a user API to
|
||||
* change interrupt vectors at runtime). Make sure interrupts
|
||||
* are locally disabled, then synthesize a PS value that will
|
||||
* enable them for the user code to pass to irq_unlock()
|
||||
* later.
|
||||
*/
|
||||
__asm__ volatile("rsr.PS %0" : "=r"(ps));
|
||||
ps &= ~(PS_EXCM_MASK | PS_INTLEVEL_MASK);
|
||||
__asm__ volatile("wsr.PS %0" : : "r"(ps));
|
||||
|
||||
ie = 0;
|
||||
__asm__ volatile("wsr.INTENABLE %0" : : "r"(ie));
|
||||
__asm__ volatile("wsr.VECBASE %0" : : "r"(start_rec->vecbase));
|
||||
__asm__ volatile("rsync");
|
||||
|
||||
/* Set up the CPU pointer. Really this should be xtensa arch
|
||||
* code, not in the ESP-32 layer
|
||||
*/
|
||||
_cpu_t *cpu = &_kernel.cpus[1];
|
||||
|
||||
__asm__ volatile("wsr.MISC0 %0" : : "r"(cpu));
|
||||
|
||||
*start_rec->alive = 1;
|
||||
start_rec->fn(ps, start_rec->arg);
|
||||
}
|
||||
|
||||
/* Defines a locally callable "function" named _stack-switch(). The
|
||||
* first argument (in register a2 post-ENTRY) is the new stack pointer
|
||||
* to go into register a1. The second (a3) is the entry point.
|
||||
* Because this never returns, a0 is used as a scratch register then
|
||||
* set to zero for the called function (a null return value is the
|
||||
* signal for "top of stack" to the debugger).
|
||||
*/
|
||||
void _appcpu_stack_switch(void *stack, void *entry);
|
||||
__asm__("\n"
|
||||
".align 4" "\n"
|
||||
"_appcpu_stack_switch:" "\n\t"
|
||||
|
||||
"entry a1, 16" "\n\t"
|
||||
|
||||
/* Subtle: we want the stack to be 16 bytes higher than the
|
||||
* top on entry to the called function, because the ABI forces
|
||||
* it to assume that those bytes are for its caller's A0-A3
|
||||
* spill area. (In fact ENTRY instructions with stack
|
||||
* adjustments less than 16 are a warning condition in the
|
||||
* assembler). But we aren't a caller, have no bit set in
|
||||
* WINDOWSTART and will never be asked to spill anything.
|
||||
* Those 16 bytes would otherwise be wasted on the stack, so
|
||||
* adjust
|
||||
*/
|
||||
"addi a1, a2, 16" "\n\t"
|
||||
|
||||
/* Clear WINDOWSTART so called functions never try to spill
|
||||
* our callers' registers into the now-garbage stack pointers
|
||||
* they contain. No need to set the bit corresponding to
|
||||
* WINDOWBASE, our C callee will do that when it does an
|
||||
* ENTRY.
|
||||
*/
|
||||
"movi a0, 0" "\n\t"
|
||||
"wsr.WINDOWSTART a0" "\n\t"
|
||||
|
||||
/* Clear CALLINC field of PS (you would think it would, but
|
||||
* our ENTRY doesn't actually do that) so the callee's ENTRY
|
||||
* doesn't shift the registers
|
||||
*/
|
||||
"rsr.PS a0" "\n\t"
|
||||
"movi a2, 0xfffcffff" "\n\t"
|
||||
"and a0, a0, a2" "\n\t"
|
||||
"wsr.PS a0" "\n\t"
|
||||
|
||||
"rsync" "\n\t"
|
||||
"movi a0, 0" "\n\t"
|
||||
|
||||
"jx a3" "\n\t");
|
||||
|
||||
/* Carefully constructed to use no stack beyond compiler-generated ABI
|
||||
* instructions. WE DO NOT KNOW WHERE THE STACK FOR THIS FUNCTION IS.
|
||||
* The ROM library just picks a spot on its own with no input from our
|
||||
* app linkage and tells us nothing about it until we're already
|
||||
* running.
|
||||
*/
|
||||
static void appcpu_entry1(void)
|
||||
{
|
||||
_appcpu_stack_switch(appcpu_top, appcpu_entry2);
|
||||
}
|
||||
|
||||
/* The calls and sequencing here were extracted from the ESP-32
|
||||
* FreeRTOS integration with just a tiny bit of cleanup. None of the
|
||||
* calls or registers shown are documented, so treat this code with
|
||||
* extreme caution.
|
||||
*/
|
||||
static void appcpu_start(void)
|
||||
{
|
||||
smp_log("ESP32: starting APPCPU");
|
||||
|
||||
/* These two calls are wrapped in a "stall_other_cpu" API in
|
||||
* esp-idf. But in this context the appcpu is stalled by
|
||||
* definition, so we can skip that complexity and just call
|
||||
* the ROM directly.
|
||||
*/
|
||||
esp32_rom_Cache_Flush(1);
|
||||
esp32_rom_Cache_Read_Enable(1);
|
||||
|
||||
RTC_CNTL_SW_CPU_STALL &= ~RTC_CNTL_SW_STALL_APPCPU_C1;
|
||||
RTC_CNTL_OPTIONS0 &= ~RTC_CNTL_SW_STALL_APPCPU_C0;
|
||||
DPORT_APPCPU_CTRL_B |= DPORT_APPCPU_CLKGATE_EN;
|
||||
DPORT_APPCPU_CTRL_C &= ~DPORT_APPCPU_RUNSTALL;
|
||||
|
||||
/* Pulse the RESETTING bit */
|
||||
DPORT_APPCPU_CTRL_A |= DPORT_APPCPU_RESETTING;
|
||||
DPORT_APPCPU_CTRL_A &= ~DPORT_APPCPU_RESETTING;
|
||||
|
||||
/* Seems weird that you set the boot address AFTER starting
|
||||
* the CPU, but this is how they do it...
|
||||
*/
|
||||
esp32_rom_ets_set_appcpu_boot_addr((void *)appcpu_entry1);
|
||||
|
||||
smp_log("ESP32: APPCPU start sequence complete");
|
||||
}
|
||||
|
||||
void _arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
|
||||
void (*fn)(int, void *), void *arg)
|
||||
{
|
||||
volatile struct cpustart_rec sr;
|
||||
int vb;
|
||||
volatile int alive_flag;
|
||||
|
||||
__ASSERT(cpu_num == 1, "ESP-32 supports only two CPUs");
|
||||
|
||||
__asm__ volatile("rsr.VECBASE %0\n\t" : "=r"(vb));
|
||||
|
||||
alive_flag = 0;
|
||||
|
||||
sr.cpu = cpu_num;
|
||||
sr.fn = fn;
|
||||
sr.stack_top = K_THREAD_STACK_BUFFER(stack) + sz;
|
||||
sr.arg = arg;
|
||||
sr.vecbase = vb;
|
||||
sr.alive = &alive_flag;
|
||||
|
||||
appcpu_top = K_THREAD_STACK_BUFFER(stack) + sz;
|
||||
|
||||
start_rec = &sr;
|
||||
|
||||
appcpu_start();
|
||||
|
||||
while (!alive_flag) {
|
||||
}
|
||||
|
||||
smp_log("ESP32: APPCPU initialized");
|
||||
}
|
368
soc/xtensa/esp32/include/_soc_inthandlers.h
Normal file
368
soc/xtensa/esp32/include/_soc_inthandlers.h
Normal file
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
*
|
||||
* Functions here are designed to produce efficient code to
|
||||
* search an Xtensa bitmask of interrupts, inspecting only those bits
|
||||
* declared to be associated with a given interrupt level. Each
|
||||
* dispatcher will handle exactly one flagged interrupt, in numerical
|
||||
* order (low bits first) and will return a mask of that bit that can
|
||||
* then be cleared by the calling code. Unrecognized bits for the
|
||||
* level will invoke an error handler.
|
||||
*/
|
||||
|
||||
#include <xtensa/config/core-isa.h>
|
||||
#include <sw_isr_table.h>
|
||||
|
||||
#if !defined(XCHAL_INT0_LEVEL) || XCHAL_INT0_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT1_LEVEL) || XCHAL_INT1_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT2_LEVEL) || XCHAL_INT2_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT3_LEVEL) || XCHAL_INT3_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT4_LEVEL) || XCHAL_INT4_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT5_LEVEL) || XCHAL_INT5_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT6_LEVEL) || XCHAL_INT6_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT7_LEVEL) || XCHAL_INT7_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT8_LEVEL) || XCHAL_INT8_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT9_LEVEL) || XCHAL_INT9_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT10_LEVEL) || XCHAL_INT10_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT12_LEVEL) || XCHAL_INT12_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT13_LEVEL) || XCHAL_INT13_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT17_LEVEL) || XCHAL_INT17_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT18_LEVEL) || XCHAL_INT18_LEVEL != 1
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT19_LEVEL) || XCHAL_INT19_LEVEL != 2
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT20_LEVEL) || XCHAL_INT20_LEVEL != 2
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT21_LEVEL) || XCHAL_INT21_LEVEL != 2
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT11_LEVEL) || XCHAL_INT11_LEVEL != 3
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT15_LEVEL) || XCHAL_INT15_LEVEL != 3
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT22_LEVEL) || XCHAL_INT22_LEVEL != 3
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT23_LEVEL) || XCHAL_INT23_LEVEL != 3
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT27_LEVEL) || XCHAL_INT27_LEVEL != 3
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT29_LEVEL) || XCHAL_INT29_LEVEL != 3
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT24_LEVEL) || XCHAL_INT24_LEVEL != 4
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT25_LEVEL) || XCHAL_INT25_LEVEL != 4
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT28_LEVEL) || XCHAL_INT28_LEVEL != 4
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT30_LEVEL) || XCHAL_INT30_LEVEL != 4
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT16_LEVEL) || XCHAL_INT16_LEVEL != 5
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT26_LEVEL) || XCHAL_INT26_LEVEL != 5
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT31_LEVEL) || XCHAL_INT31_LEVEL != 5
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
#if !defined(XCHAL_INT14_LEVEL) || XCHAL_INT14_LEVEL != 7
|
||||
#error core-isa.h interrupt level does not match dispatcher!
|
||||
#endif
|
||||
|
||||
static inline int _xtensa_handle_one_int0(unsigned int mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int _xtensa_handle_one_int1(unsigned int mask)
|
||||
{
|
||||
if (mask & 0x7f) {
|
||||
if (mask & 0x7) {
|
||||
if (mask & (1 << 0)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[0];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 0;
|
||||
}
|
||||
if (mask & (1 << 1)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[1];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 1;
|
||||
}
|
||||
if (mask & (1 << 2)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[2];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 2;
|
||||
}
|
||||
} else {
|
||||
if (mask & 0x18) {
|
||||
if (mask & (1 << 3)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[3];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 3;
|
||||
}
|
||||
if (mask & (1 << 4)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[4];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 4;
|
||||
}
|
||||
} else {
|
||||
if (mask & (1 << 5)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[5];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 5;
|
||||
}
|
||||
if (mask & (1 << 6)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[6];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mask & 0x780) {
|
||||
if (mask & 0x180) {
|
||||
if (mask & (1 << 7)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[7];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 7;
|
||||
}
|
||||
if (mask & (1 << 8)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[8];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 8;
|
||||
}
|
||||
} else {
|
||||
if (mask & (1 << 9)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[9];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 9;
|
||||
}
|
||||
if (mask & (1 << 10)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[10];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 10;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mask & 0x3000) {
|
||||
if (mask & (1 << 12)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[12];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 12;
|
||||
}
|
||||
if (mask & (1 << 13)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[13];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 13;
|
||||
}
|
||||
} else {
|
||||
if (mask & (1 << 17)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[17];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 17;
|
||||
}
|
||||
if (mask & (1 << 18)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[18];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 18;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int _xtensa_handle_one_int2(unsigned int mask)
|
||||
{
|
||||
if (mask & (1 << 19)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[19];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 19;
|
||||
}
|
||||
if (mask & (1 << 20)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[20];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 20;
|
||||
}
|
||||
if (mask & (1 << 21)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[21];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 21;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int _xtensa_handle_one_int3(unsigned int mask)
|
||||
{
|
||||
if (mask & 0x408800) {
|
||||
if (mask & (1 << 11)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[11];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 11;
|
||||
}
|
||||
if (mask & (1 << 15)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[15];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 15;
|
||||
}
|
||||
if (mask & (1 << 22)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[22];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 22;
|
||||
}
|
||||
} else {
|
||||
if (mask & (1 << 23)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[23];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 23;
|
||||
}
|
||||
if (mask & (1 << 27)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[27];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 27;
|
||||
}
|
||||
if (mask & (1 << 29)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[29];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 29;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int _xtensa_handle_one_int4(unsigned int mask)
|
||||
{
|
||||
if (mask & 0x3000000) {
|
||||
if (mask & (1 << 24)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[24];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 24;
|
||||
}
|
||||
if (mask & (1 << 25)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[25];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 25;
|
||||
}
|
||||
} else {
|
||||
if (mask & (1 << 28)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[28];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 28;
|
||||
}
|
||||
if (mask & (1 << 30)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[30];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 30;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int _xtensa_handle_one_int5(unsigned int mask)
|
||||
{
|
||||
if (mask & (1 << 16)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[16];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 16;
|
||||
}
|
||||
if (mask & (1 << 26)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[26];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 26;
|
||||
}
|
||||
if (mask & (1 << 31)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[31];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 31;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int _xtensa_handle_one_int6(unsigned int mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int _xtensa_handle_one_int7(unsigned int mask)
|
||||
{
|
||||
if (mask & (1 << 14)) {
|
||||
struct _isr_table_entry *e = &_sw_isr_table[14];
|
||||
|
||||
e->isr(e->arg);
|
||||
return 1 << 14;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
244
soc/xtensa/esp32/linker.ld
Normal file
244
soc/xtensa/esp32/linker.ld
Normal file
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Cadence Design Systems, Inc.
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Linker command/script file
|
||||
*
|
||||
* Linker script for the Xtensa platform.
|
||||
*/
|
||||
|
||||
#define _LINKER
|
||||
#define _ASMLANGUAGE
|
||||
|
||||
#include <autoconf.h>
|
||||
#include <linker/sections.h>
|
||||
#include <linker/linker-defs.h>
|
||||
#include <linker/linker-tool.h>
|
||||
|
||||
#define RAMABLE_REGION dram0_0_seg :dram0_0_phdr
|
||||
#define ROMABLE_REGION iram0_0_seg :iram0_0_phdr
|
||||
|
||||
PROVIDE ( __stack = 0x3ffe3f20 );
|
||||
|
||||
PROVIDE ( esp32_rom_uart_tx_one_char = 0x40009200 );
|
||||
PROVIDE ( esp32_rom_uart_rx_one_char = 0x400092d0 );
|
||||
PROVIDE ( esp32_rom_uart_attach = 0x40008fd0 );
|
||||
PROVIDE ( esp32_rom_intr_matrix_set = 0x4000681c );
|
||||
PROVIDE ( esp32_rom_gpio_matrix_in = 0x40009edc );
|
||||
PROVIDE ( esp32_rom_gpio_matrix_out = 0x40009f0c );
|
||||
PROVIDE ( esp32_rom_Cache_Flush = 0x40009a14 );
|
||||
PROVIDE ( esp32_rom_Cache_Read_Enable = 0x40009a84 );
|
||||
PROVIDE ( esp32_rom_ets_set_appcpu_boot_addr = 0x4000689c );
|
||||
|
||||
MEMORY
|
||||
{
|
||||
iram0_0_seg(RX): org = 0x40080000, len = 0x20000
|
||||
iram0_2_seg(RX): org = 0x400D0018, len = 0x330000
|
||||
dram0_0_seg(RW): org = 0x3FFB0000, len = 0x50000
|
||||
drom0_0_seg(R): org = 0x3F400010, len = 0x800000
|
||||
rtc_iram_seg(RWX): org = 0x400C0000, len = 0x2000
|
||||
rtc_slow_seg(RW): org = 0x50000000, len = 0x1000
|
||||
#ifdef CONFIG_GEN_ISR_TABLES
|
||||
IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000
|
||||
#endif
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
iram0_0_phdr PT_LOAD;
|
||||
dram0_0_phdr PT_LOAD;
|
||||
}
|
||||
|
||||
/* Default entry point: */
|
||||
PROVIDE ( _ResetVector = 0x40000400 );
|
||||
ENTRY(CONFIG_KERNEL_ENTRY)
|
||||
|
||||
_rom_store_table = 0;
|
||||
|
||||
PROVIDE(_memmap_vecbase_reset = 0x40000450);
|
||||
PROVIDE(_memmap_reset_vector = 0x40000400);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* RTC fast memory holds RTC wake stub code,
|
||||
including from any source file named rtc_wake_stub*.c
|
||||
*/
|
||||
.rtc.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rtc.literal .rtc.text)
|
||||
*rtc_wake_stub*.o(.literal .text .literal.* .text.*)
|
||||
} >rtc_iram_seg
|
||||
|
||||
/* RTC slow memory holds RTC wake stub
|
||||
data/rodata, including from any source file
|
||||
named rtc_wake_stub*.c
|
||||
*/
|
||||
.rtc.data :
|
||||
{
|
||||
_rtc_data_start = ABSOLUTE(.);
|
||||
*(.rtc.data)
|
||||
*(.rtc.rodata)
|
||||
*rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*)
|
||||
_rtc_data_end = ABSOLUTE(.);
|
||||
} > rtc_slow_seg
|
||||
|
||||
/* RTC bss, from any source file named rtc_wake_stub*.c */
|
||||
.rtc.bss (NOLOAD) :
|
||||
{
|
||||
_rtc_bss_start = ABSOLUTE(.);
|
||||
*rtc_wake_stub*.o(.bss .bss.*)
|
||||
*rtc_wake_stub*.o(COMMON)
|
||||
_rtc_bss_end = ABSOLUTE(.);
|
||||
} > rtc_slow_seg
|
||||
|
||||
/* Send .iram0 code to iram */
|
||||
.iram0.vectors : ALIGN(4)
|
||||
{
|
||||
/* Vectors go to IRAM */
|
||||
_init_start = ABSOLUTE(.);
|
||||
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
|
||||
. = 0x0;
|
||||
KEEP(*(.WindowVectors.text));
|
||||
. = 0x180;
|
||||
KEEP(*(.Level2InterruptVector.text));
|
||||
. = 0x1c0;
|
||||
KEEP(*(.Level3InterruptVector.text));
|
||||
. = 0x200;
|
||||
KEEP(*(.Level4InterruptVector.text));
|
||||
. = 0x240;
|
||||
KEEP(*(.Level5InterruptVector.text));
|
||||
. = 0x280;
|
||||
KEEP(*(.DebugExceptionVector.text));
|
||||
. = 0x2c0;
|
||||
KEEP(*(.NMIExceptionVector.text));
|
||||
. = 0x300;
|
||||
KEEP(*(.KernelExceptionVector.text));
|
||||
. = 0x340;
|
||||
KEEP(*(.UserExceptionVector.text));
|
||||
. = 0x3C0;
|
||||
KEEP(*(.DoubleExceptionVector.text));
|
||||
. = 0x400;
|
||||
*(.*Vector.literal)
|
||||
|
||||
*(.UserEnter.literal);
|
||||
*(.UserEnter.text);
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
_init_end = ABSOLUTE(.);
|
||||
|
||||
/* This goes here, not at top of linker script, so addr2line finds it last,
|
||||
and uses it in preference to the first symbol in IRAM */
|
||||
_iram_start = ABSOLUTE(0);
|
||||
} GROUP_LINK_IN(ROMABLE_REGION)
|
||||
|
||||
#include <linker/common-ram.ld>
|
||||
#include <linker/common-rom.ld>
|
||||
|
||||
SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4))
|
||||
{
|
||||
/* Code marked as running out of IRAM */
|
||||
_iram_text_start = ABSOLUTE(.);
|
||||
*(.iram1 .iram1.*)
|
||||
*(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text)
|
||||
*(.literal .text .literal.* .text.*)
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} GROUP_LINK_IN(ROMABLE_REGION)
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
KEEP(*(.jcr))
|
||||
*(.dram1 .dram1.*)
|
||||
KEEP(*(SW_ISR_TABLE))
|
||||
_data_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} GROUP_LINK_IN(RAMABLE_REGION)
|
||||
|
||||
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(4))
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
|
||||
KEEP (*(.xt_except_table))
|
||||
KEEP (*(.gcc_except_table))
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
KEEP (*(.eh_frame))
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
/* C++ exception handlers table: */
|
||||
__XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc)
|
||||
*(.gnu.linkonce.h.*)
|
||||
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc_end)
|
||||
*(.dynamic)
|
||||
*(.gnu.version_d)
|
||||
. = ALIGN(4); /* this table MUST be 4-byte aligned */
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
} GROUP_LINK_IN(RAMABLE_REGION)
|
||||
|
||||
|
||||
/* Shared RAM */
|
||||
SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.share.mem)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} GROUP_LINK_IN(RAMABLE_REGION)
|
||||
|
||||
SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),)
|
||||
{
|
||||
. = ALIGN (8);
|
||||
*(.noinit)
|
||||
*(".noinit.*")
|
||||
. = ALIGN (8);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} GROUP_LINK_IN(RAMABLE_REGION)
|
||||
|
||||
#ifdef CONFIG_GEN_ISR_TABLES
|
||||
#include <linker/intlist.ld>
|
||||
#endif
|
||||
}
|
5
soc/xtensa/esp32/sdkconfig.h
Normal file
5
soc/xtensa/esp32/sdkconfig.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
/*
|
||||
* This file is intentionally empty. It is required to build Zephyr with
|
||||
* esp-idf newer than git revision cb31222e.
|
||||
*/
|
||||
|
75
soc/xtensa/esp32/soc.c
Normal file
75
soc/xtensa/esp32/soc.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Include esp-idf headers first to avoid redefining BIT() macro */
|
||||
#include "soc.h"
|
||||
#include <soc/rtc_cntl_reg.h>
|
||||
#include <soc/timer_group_reg.h>
|
||||
#include <xtensa/config/core-isa.h>
|
||||
#include <xtensa/corebits.h>
|
||||
|
||||
#include <kernel_structs.h>
|
||||
#include <string.h>
|
||||
#include <toolchain/gcc.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
extern void _Cstart(void);
|
||||
|
||||
/*
|
||||
* This is written in C rather than assembly since, during the port bring up,
|
||||
* Zephyr is being booted by the Espressif bootloader. With it, the C stack
|
||||
* is already set up.
|
||||
*/
|
||||
void __attribute__((section(".iram1"))) __start(void)
|
||||
{
|
||||
volatile u32_t *wdt_rtc_reg = (u32_t *)RTC_CNTL_WDTCONFIG0_REG;
|
||||
volatile u32_t *wdt_timg_reg = (u32_t *)TIMG_WDTCONFIG0_REG(0);
|
||||
volatile u32_t *app_cpu_config_reg = (u32_t *)DPORT_APPCPU_CTRL_B_REG;
|
||||
extern u32_t _init_start;
|
||||
extern u32_t _bss_start;
|
||||
extern u32_t _bss_end;
|
||||
|
||||
/* Move the exception vector table to IRAM. */
|
||||
__asm__ __volatile__ (
|
||||
"wsr %0, vecbase"
|
||||
:
|
||||
: "r"(&_init_start));
|
||||
|
||||
/* Zero out BSS. Clobber _bss_start to avoid memset() elision. */
|
||||
memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
|
||||
__asm__ __volatile__ (
|
||||
""
|
||||
:
|
||||
: "g"(&_bss_start)
|
||||
: "memory");
|
||||
|
||||
/* The watchdog timer is enabled in the bootloader. We're done booting,
|
||||
* so disable it.
|
||||
*/
|
||||
*wdt_rtc_reg &= ~RTC_CNTL_WDT_FLASHBOOT_MOD_EN;
|
||||
*wdt_timg_reg &= ~TIMG_WDT_FLASHBOOT_MOD_EN;
|
||||
|
||||
/* Disable normal interrupts. */
|
||||
__asm__ __volatile__ (
|
||||
"wsr %0, PS"
|
||||
:
|
||||
: "r"(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE));
|
||||
|
||||
/* Disable CPU1 while we figure out how to have SMP in Zephyr. */
|
||||
*app_cpu_config_reg &= ~DPORT_APPCPU_CLKGATE_EN;
|
||||
|
||||
/* Initialize the architecture CPU pointer. Some of the
|
||||
* initialization code wants a valid _current before
|
||||
* kernel_arch_init() is invoked.
|
||||
*/
|
||||
__asm__ volatile("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0]));
|
||||
|
||||
|
||||
/* Start Zephyr */
|
||||
_Cstart();
|
||||
|
||||
CODE_UNREACHABLE;
|
||||
}
|
62
soc/xtensa/esp32/soc.h
Normal file
62
soc/xtensa/esp32/soc.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __SOC_H__
|
||||
#define __SOC_H__
|
||||
#include <soc/dport_reg.h>
|
||||
#include <soc/rtc_cntl_reg.h>
|
||||
#include <rom/ets_sys.h>
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <arch/xtensa/arch.h>
|
||||
|
||||
/**
|
||||
* @brief Struct to peripheral masks to enable peripheral
|
||||
* clock and reset peripherals.
|
||||
*/
|
||||
struct esp32_peripheral {
|
||||
/** Mask for clock peripheral */
|
||||
int clk;
|
||||
/** Mask for reset peripheral */
|
||||
int rst;
|
||||
};
|
||||
|
||||
static inline void esp32_set_mask32(u32_t v, u32_t mem_addr)
|
||||
{
|
||||
sys_write32(sys_read32(mem_addr) | v, mem_addr);
|
||||
}
|
||||
|
||||
static inline void esp32_clear_mask32(u32_t v, u32_t mem_addr)
|
||||
{
|
||||
sys_write32(sys_read32(mem_addr) & ~v, mem_addr);
|
||||
}
|
||||
|
||||
static inline void esp32_enable_peripheral(const struct esp32_peripheral *peripheral)
|
||||
{
|
||||
esp32_set_mask32(peripheral->clk, DPORT_PERIP_CLK_EN_REG);
|
||||
esp32_clear_mask32(peripheral->rst, DPORT_PERIP_RST_EN_REG);
|
||||
}
|
||||
|
||||
extern int esp32_rom_intr_matrix_set(int cpu_no,
|
||||
int interrupt_src,
|
||||
int interrupt_line);
|
||||
|
||||
extern int esp32_rom_gpio_matrix_in(u32_t gpio, u32_t signal_index,
|
||||
bool inverted);
|
||||
extern int esp32_rom_gpio_matrix_out(u32_t gpio, u32_t signal_index,
|
||||
bool out_inverted,
|
||||
bool out_enabled_inverted);
|
||||
|
||||
extern void esp32_rom_uart_attach(void);
|
||||
extern STATUS esp32_rom_uart_tx_one_char(u8_t chr);
|
||||
extern STATUS esp32_rom_uart_rx_one_char(u8_t *chr);
|
||||
|
||||
extern void esp32_rom_Cache_Flush(int cpu);
|
||||
extern void esp32_rom_Cache_Read_Enable(int cpu);
|
||||
extern void esp32_rom_ets_set_appcpu_boot_addr(void *addr);
|
||||
|
||||
#endif /* __SOC_H__ */
|
Loading…
Add table
Add a link
Reference in a new issue