1
0
mirror of https://github.com/olofk/serv.git synced 2026-02-03 06:50:17 +00:00

Port Zephyr support to 2.4 and update instructions

This commit is contained in:
Olof Kindgren
2020-12-16 22:52:36 +01:00
parent 731ca8bb45
commit acab804a31
31 changed files with 690 additions and 43 deletions

1
zephyr

Submodule zephyr deleted from a690d52fa6

4
zephyr/CMakeLists.txt Normal file
View File

@@ -0,0 +1,4 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
add_subdirectory(drivers)

8
zephyr/Kconfig Normal file
View File

@@ -0,0 +1,8 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
menu "SweRVolf"
rsource "drivers/Kconfig"
endmenu

View File

@@ -0,0 +1,7 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
#
# SPDX-License-Identifier: Apache-2.0
config BOARD_SERVICE
bool "servant SoC for iCE40"
depends on SOC_RISCV32_SERVANT

View File

@@ -0,0 +1,7 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
#
# SPDX-License-Identifier: Apache-2.0
config BOARD
default "service"
depends on BOARD_SERVICE

View File

@@ -0,0 +1,12 @@
/*
* Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __INC_BOARD_H
#define __INC_BOARD_H
#include <soc.h>
#endif /* __INC_BOARD_H */

View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/dts-v1/;
#include <serv.dtsi>
/ {
chosen {
zephyr,sram = &ram;
};
ram: memory@0 {
compatible = "mmio-sram";
reg = <0x0 0x8000>;
};
};

View File

@@ -0,0 +1,15 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
#
# SPDX-License-Identifier: Apache-2.0
identifier: service
name: servant SoC for iCE40
type: mcu
arch: riscv32
toolchain:
- zephyr
ram: 32
testing:
ignore_tags:
- net
- bluetooth

View File

@@ -0,0 +1,13 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
#
# SPDX-License-Identifier: Apache-2.0
CONFIG_BOARD_SERVICE=y
CONFIG_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_UART_BITBANG=y
CONFIG_UART_CONSOLE=y
CONFIG_UART_CONSOLE_ON_DEV_NAME="uart0"
CONFIG_XIP=n

View File

@@ -0,0 +1,6 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
add_subdirectory_ifdef(CONFIG_SERIAL_HAS_DRIVER serial)
add_subdirectory_ifdef(CONFIG_SYS_CLOCK_EXISTS timer)

10
zephyr/drivers/Kconfig Normal file
View File

@@ -0,0 +1,10 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
menu "Device Drivers"
rsource "serial/Kconfig"
rsource "timer/Kconfig"
endmenu

View File

@@ -0,0 +1,6 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
set(ZEPHYR_CURRENT_LIBRARY drivers__serial)
zephyr_library_sources_ifdef(CONFIG_UART_BITBANG uart_bitbang.c)

View File

@@ -0,0 +1,13 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
if SERIAL
menuconfig UART_BITBANG
bool "SERV bitbang serial driver"
select SERIAL_HAS_DRIVER
help
Enables the SERV bitbang serial driver.
Hardcoded to send at ~57600 baud rate with a 16MHz clock
endif

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <kernel.h>
#include <arch/cpu.h>
#include <drivers/uart.h>
#define reg_uart_data (*(volatile uint32_t*)UART_BITBANG_BASE)
static struct k_spinlock lock;
static void uart_bitbang_poll_out(const struct device *dev, unsigned char c)
{
ARG_UNUSED(dev);
k_spinlock_key_t key = k_spin_lock(&lock);
int cout = (c|0x100) << 1;
do {
reg_uart_data = cout;
cout >>= 1;
__asm__ __volatile__ ("nop");
__asm__ __volatile__ ("nop");
} while (cout);
k_spin_unlock(&lock, key);
}
static int uart_bitbang_poll_in(const struct device *dev, unsigned char *c)
{
ARG_UNUSED(dev);
*c = reg_uart_data;
return 0;
}
static int uart_bitbang_init(const struct device *dev)
{
ARG_UNUSED(dev);
reg_uart_data = 1;
return 0;
}
static const struct uart_driver_api uart_bitbang_driver_api = {
.poll_in = uart_bitbang_poll_in,
.poll_out = uart_bitbang_poll_out,
.err_check = NULL,
};
DEVICE_AND_API_INIT(uart_bitbang, "uart0", &uart_bitbang_init,
NULL, NULL,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&uart_bitbang_driver_api);

View File

@@ -0,0 +1,5 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
zephyr_library_sources_ifdef(CONFIG_SERV_TIMER serv_timer.c)

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
config SERV_TIMER
bool "SERV Timer"
# select TICKLESS_CAPABLE
help
This module implements a kernel device driver for the SERV
timer driver. It provides the standard "system clock driver" interfaces.

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
This is basically a 32-bit version of riscv_machine_timer.c fro Zephyr
*/
#include <drivers/timer/system_timer.h>
#include <sys_clock.h>
#include <spinlock.h>
#include <soc.h>
#define CYC_PER_TICK ((uint32_t)((uint32_t)sys_clock_hw_cycles_per_sec() \
/ (uint32_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC))
#define MAX_CYC 0xffffffffu
#define MAX_TICKS ((MAX_CYC - CYC_PER_TICK) / CYC_PER_TICK)
#define MIN_DELAY 1000
#define TICKLESS IS_ENABLED(CONFIG_TICKLESS_KERNEL)
static struct k_spinlock lock;
static uint32_t last_count;
static ALWAYS_INLINE void set_mtimecmp(uint32_t time)
{
sys_write32(time, SERV_TIMER_BASE);
}
static ALWAYS_INLINE uint32_t mtime(void)
{
return sys_read32(SERV_TIMER_BASE);
}
static void timer_isr(void *arg)
{
ARG_UNUSED(arg);
k_spinlock_key_t key = k_spin_lock(&lock);
uint32_t now = mtime();
uint32_t dticks = ((now - last_count) / CYC_PER_TICK);
last_count += dticks * CYC_PER_TICK;
if (!TICKLESS) {
uint32_t next = last_count + CYC_PER_TICK;
if ((int32_t)(next - now) < MIN_DELAY) {
next += CYC_PER_TICK;
}
set_mtimecmp(next);
}
k_spin_unlock(&lock, key);
z_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? dticks : 1);
}
int z_clock_driver_init(const struct device *device)
{
ARG_UNUSED(device);
IRQ_CONNECT(RISCV_MACHINE_TIMER_IRQ, 0, timer_isr, NULL, 0);
set_mtimecmp(mtime() + (uint32_t)CYC_PER_TICK);
irq_enable(RISCV_MACHINE_TIMER_IRQ);
return 0;
}
void z_clock_set_timeout(int32_t ticks, bool idle)
{
ARG_UNUSED(idle);
#if defined(CONFIG_TICKLESS_KERNEL)
/* RISCV has no idle handler yet, so if we try to spin on the
* logic below to reset the comparator, we'll always bump it
* forward to the "next tick" due to MIN_DELAY handling and
* the interrupt will never fire! Just rely on the fact that
* the OS gave us the proper timeout already.
*/
if (idle) {
return;
}
ticks = ticks == K_TICKS_FOREVER ? MAX_TICKS : ticks;
ticks = MAX(MIN(ticks - 1, (int32_t)MAX_TICKS), 0);
k_spinlock_key_t key = k_spin_lock(&lock);
uint32_t now = mtime();
uint32_t adj, cyc = ticks * CYC_PER_TICK;
/* Round up to next tick boundary. */
adj = (now - last_count) + (CYC_PER_TICK - 1);
if (cyc <= MAX_CYC - adj) {
cyc += adj;
} else {
cyc = MAX_CYC;
}
cyc = (cyc / CYC_PER_TICK) * CYC_PER_TICK;
if ((int32_t)(cyc + last_count - now) < MIN_DELAY) {
cyc += CYC_PER_TICK;
}
set_mtimecmp(cyc + last_count);
k_spin_unlock(&lock, key);
#endif
}
uint32_t z_clock_elapsed(void)
{
if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
return 0;
}
k_spinlock_key_t key = k_spin_lock(&lock);
uint32_t ret = (mtime() - last_count) / CYC_PER_TICK;
k_spin_unlock(&lock, key);
return ret;
}
uint32_t z_timer_cycle_get_32(void)
{
return mtime();
}

View File

@@ -0,0 +1,11 @@
/*
* Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "olofk,servant";
};

5
zephyr/module.yml Normal file
View File

@@ -0,0 +1,5 @@
build:
settings:
board_root: zephyr
dts_root: zephyr
soc_root: zephyr

View File

@@ -0,0 +1,7 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
zephyr_sources(
soc_irq.S
vector.S
irq.c)

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
if SOC_RISCV32_SERVANT
config SOC
string
default "servant"
config SYS_CLOCK_HW_CYCLES_PER_SEC
int
default 16000000
config RISCV_SOC_INTERRUPT_INIT
bool
default y
config NUM_IRQS
int
default 8
config SERV_TIMER
bool
default y
endif # SOC_RISCV32_SERVANT

View File

@@ -0,0 +1,7 @@
# Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
# SPDX-License-Identifier: Apache-2.0
config SOC_RISCV32_SERVANT
bool "servant SoC"
select RISCV
select ATOMIC_OPERATIONS_C

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief interrupt management code for riscv SOCs supporting the riscv
privileged architecture specification
*/
#include <irq.h>
void arch_irq_enable(unsigned int irq)
{
uint32_t mie;
/*
* CSR mie register is updated using atomic instruction csrrs
* (atomic read and set bits in CSR register)
*/
__asm__ volatile ("csrrs %0, mie, %1\n"
: "=r" (mie)
: "r" (1 << irq));
}
void arch_irq_disable(unsigned int irq)
{
uint32_t mie;
/*
* Use atomic instruction csrrc to disable device interrupt in mie CSR.
* (atomic read and clear bits in CSR register)
*/
__asm__ volatile ("csrrc %0, mie, %1\n"
: "=r" (mie)
: "r" (1 << irq));
};
int arch_irq_is_enabled(unsigned int irq)
{
uint32_t mie;
__asm__ volatile ("csrr %0, mie" : "=r" (mie));
return !!(mie & (1 << irq));
}
#if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
void soc_interrupt_init(void)
{
/* ensure that all interrupts are disabled */
(void)irq_lock();
__asm__ volatile ("csrwi mie, 0\n"
"csrwi mip, 0\n");
}
#endif

View File

@@ -0,0 +1,7 @@
/*
* Copyright (c) 2018 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <arch/riscv/common/linker.ld>

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2020 Olof Kindgren <olof.kindgren@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __RISCV32_SERVANT_SOC_H_
#define __RISCV32_SERVANT_SOC_H_
#include <soc_common.h>
#include <devicetree.h>
/* Bitbang UART configuration */
#define UART_BITBANG_BASE 0x40000000
/* Timer configuration */
#define SERV_TIMER_BASE 0x80000000
#define SERV_TIMER_IRQ 7
/* lib-c hooks required RAM defined variables */
#define RISCV_RAM_BASE DT_SRAM_BASE_ADDR_ADDRESS
#define RISCV_RAM_SIZE DT_SRAM_SIZE
#endif /* __RISCV32_SERVANT_SOC_H_ */

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file configuration macros for riscv SOCs supporting the riscv
* privileged architecture specification
*/
#ifndef __SOC_COMMON_H_
#define __SOC_COMMON_H_
/* IRQ numbers */
#define RISCV_MACHINE_SOFT_IRQ 3 /* Machine Software Interrupt */
#define RISCV_MACHINE_TIMER_IRQ 7 /* Machine Timer Interrupt */
#define RISCV_MACHINE_EXT_IRQ 11 /* Machine External Interrupt */
/* ECALL Exception numbers */
#define SOC_MCAUSE_ECALL_EXP 11 /* Machine ECALL instruction */
#define SOC_MCAUSE_USER_ECALL_EXP 8 /* User ECALL instruction */
/* SOC-specific MCAUSE bitfields */
#ifdef CONFIG_64BIT
/* Interrupt Mask */
#define SOC_MCAUSE_IRQ_MASK (1 << 63)
/* Exception code Mask */
#define SOC_MCAUSE_EXP_MASK 0x7FFFFFFFFFFFFFFF
#else
/* Interrupt Mask */
#define SOC_MCAUSE_IRQ_MASK (1 << 31)
/* Exception code Mask */
#define SOC_MCAUSE_EXP_MASK 0x7FFFFFFF
#endif
/* SOC-Specific EXIT ISR command */
#define SOC_ERET mret
#ifndef _ASMLANGUAGE
#if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
void soc_interrupt_init(void);
#endif
#if defined(CONFIG_RISCV_HAS_PLIC)
void riscv_plic_irq_enable(uint32_t irq);
void riscv_plic_irq_disable(uint32_t irq);
int riscv_plic_irq_is_enabled(uint32_t irq);
void riscv_plic_set_priority(uint32_t irq, uint32_t priority);
int riscv_plic_get_irq(void);
#endif
#endif /* !_ASMLANGUAGE */
#endif /* __SOC_COMMON_H_ */

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* common interrupt management code for riscv SOCs supporting the riscv
* privileged architecture specification
*/
#include <kernel_structs.h>
#include <offsets.h>
#include <toolchain.h>
#include <linker/sections.h>
#include <soc.h>
/* exports */
GTEXT(__soc_handle_irq)
/*
* SOC-specific function to handle pending IRQ number generating the interrupt.
* Exception number is given as parameter via register a0.
*/
SECTION_FUNC(exception.other, __soc_handle_irq)
/* Clear exception number from CSR mip register */
li t1, 1
sll t0, t1, a0
csrrc t1, mip, t0
/* Return */
jalr x0, ra
/*
* __soc_is_irq is defined as .weak to allow re-implementation by
* SOCs that does not truly follow the riscv privilege specification.
*/
WTEXT(__soc_is_irq)
/*
* SOC-specific function to determine if the exception is the result of a
* an interrupt or an exception
* return 1 (interrupt) or 0 (exception)
*
*/
SECTION_FUNC(exception.other, __soc_is_irq)
/* Read mcause and check if interrupt bit is set */
csrr t0, mcause
li t1, SOC_MCAUSE_IRQ_MASK
and t0, t0, t1
/* If interrupt bit is not set, return with 0 */
addi a0, x0, 0
beqz t0, not_interrupt
addi a0, a0, 1
not_interrupt:
/* return */
jalr x0, ra

View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
* Contributors: 2018 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <toolchain.h>
/* exports */
GTEXT(__start)
/* imports */
GTEXT(__initialize)
GTEXT(__irq_wrapper)
SECTION_FUNC(vectors, __start)
.option norvc;
/*
* Set mtvec (Machine Trap-Vector Base-Address Register)
* to __irq_wrapper.
*/
la t0, __irq_wrapper
csrw mtvec, t0
/* Jump to __initialize */
tail __initialize