Compare commits
No commits in common. "80dc438fd00bea71fe9ce33d83b29db6ec88c4aa" and "ad1ac3f9d77ae3a5f4d6efc8b1bf325bf9149c57" have entirely different histories.
80dc438fd0
...
ad1ac3f9d7
17 changed files with 339 additions and 489 deletions
|
@ -155,7 +155,7 @@ isr:
|
||||||
sd t1, 0x90(s1)
|
sd t1, 0x90(s1)
|
||||||
|
|
||||||
mv a0, s1
|
mv a0, s1
|
||||||
# jal handle_isr
|
jal handle_isr
|
||||||
|
|
||||||
# Load the saved s1 into sscratch.
|
# Load the saved s1 into sscratch.
|
||||||
ld t0, 0x90(s1)
|
ld t0, 0x90(s1)
|
||||||
|
@ -193,7 +193,7 @@ isr:
|
||||||
sret
|
sret
|
||||||
|
|
||||||
2:
|
2:
|
||||||
# jal isr_frame_overflow
|
jal isr_frame_overflow
|
||||||
unimp
|
unimp
|
||||||
|
|
||||||
.section .bss
|
.section .bss
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
arch_sources = [
|
arch_sources = [
|
||||||
files('entry.S'),
|
files(
|
||||||
|
'entry.S'
|
||||||
|
),
|
||||||
kernel_sources
|
kernel_sources
|
||||||
]
|
]
|
||||||
|
|
||||||
arch_cpp_args = kernel_cpp_args
|
|
||||||
arch_link_args = kernel_link_args
|
|
||||||
|
|
||||||
subdir('platform/' + platform)
|
subdir('platform/' + platform)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
cxx = meson.get_compiler('cpp')
|
cxx = meson.get_compiler('cpp')
|
||||||
# gcc_dep = cxx.find_library('gcc', required: true)
|
gcc_dep = cxx.find_library('gcc', required: true)
|
||||||
objcopy = find_program('riscv64-linux-gnu-objcopy')
|
objcopy = find_program('riscv64-linux-gnu-objcopy')
|
||||||
mkimage = find_program('mkimage')
|
mkimage = find_program('mkimage')
|
||||||
|
|
||||||
|
@ -11,11 +11,10 @@ elf = executable(
|
||||||
'kernel.elf',
|
'kernel.elf',
|
||||||
arch_sources,
|
arch_sources,
|
||||||
include_directories: includes,
|
include_directories: includes,
|
||||||
# dependencies: gcc_dep,
|
dependencies: gcc_dep,
|
||||||
cpp_args: arch_cpp_args,
|
|
||||||
link_args: [
|
link_args: [
|
||||||
arch_link_args,
|
|
||||||
'-Wl,-T,' + meson.current_source_dir() + '/platform.ld',
|
'-Wl,-T,' + meson.current_source_dir() + '/platform.ld',
|
||||||
|
'-static'
|
||||||
],
|
],
|
||||||
link_depends: files('platform.ld'),
|
link_depends: files('platform.ld'),
|
||||||
install: true,
|
install: true,
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace opensbi::legacy {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
SbiRet set_timer(uint64_t stime_value) {
|
SbiRet set_timer(std::uint64_t stime_value) {
|
||||||
#if __riscv_xlen == 64
|
#if __riscv_xlen == 64
|
||||||
return ecall(
|
return ecall(
|
||||||
static_cast<sbiword_t>(ExtensionId::SET_TIMER),
|
static_cast<sbiword_t>(ExtensionId::SET_TIMER),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace drivers {
|
namespace drivers {
|
||||||
namespace opensbi {
|
namespace opensbi {
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace drivers {
|
|
||||||
namespace sunxi_d1_pinctrl {
|
|
||||||
|
|
||||||
struct [[gnu::aligned(4)]] Port {
|
|
||||||
uint32_t config[4];
|
|
||||||
uint32_t data;
|
|
||||||
uint32_t drive[4];
|
|
||||||
uint32_t pull[2];
|
|
||||||
uint32_t _;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::aligned(4)]] PortInt {
|
|
||||||
uint32_t config[4];
|
|
||||||
uint32_t control;
|
|
||||||
uint32_t status;
|
|
||||||
uint32_t debounce;
|
|
||||||
uint32_t _;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::aligned(4)]] PIO {
|
|
||||||
uint32_t mode;
|
|
||||||
uint32_t control;
|
|
||||||
uint32_t value;
|
|
||||||
uint32_t voltage_select;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::aligned(4)]] Registers {
|
|
||||||
volatile Port ports[7];
|
|
||||||
volatile uint32_t _[0x34];
|
|
||||||
volatile PortInt interrupt[7];
|
|
||||||
volatile uint32_t __[0x10];
|
|
||||||
volatile PIO pio;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // End namespace sunxi_d1_pinctrl
|
|
||||||
} // End namespace drivers
|
|
|
@ -1,39 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "registers.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace drivers {
|
|
||||||
namespace sunxi_d1_pinctrl {
|
|
||||||
|
|
||||||
enum Bank {
|
|
||||||
PA,
|
|
||||||
PB,
|
|
||||||
PC,
|
|
||||||
PD,
|
|
||||||
PE,
|
|
||||||
PF,
|
|
||||||
PG,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SunxiD1Pinctrl {
|
|
||||||
SunxiD1Pinctrl(void * const addr);
|
|
||||||
|
|
||||||
void set_pin_mode(
|
|
||||||
const Bank bank,
|
|
||||||
const uint8_t pin,
|
|
||||||
const uint8_t mode);
|
|
||||||
void set_pin_state(
|
|
||||||
const Bank bank,
|
|
||||||
const uint8_t pin,
|
|
||||||
const bool state);
|
|
||||||
bool get_pin_state(
|
|
||||||
const Bank bank,
|
|
||||||
const uint8_t pin);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Registers &m_registers;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // End namespace sunxi_d1_pinctrl
|
|
||||||
} // End namespace drivers
|
|
|
@ -1,9 +0,0 @@
|
||||||
kernel_sources += [
|
|
||||||
files(
|
|
||||||
'sunxi_d1_pinctrl.cpp',
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
kernel_includes += include_directories(
|
|
||||||
'include'
|
|
||||||
)
|
|
|
@ -1,47 +0,0 @@
|
||||||
#include "sunxi_d1_pinctrl/sunxi_d1_pinctrl.h"
|
|
||||||
|
|
||||||
namespace drivers {
|
|
||||||
namespace sunxi_d1_pinctrl {
|
|
||||||
|
|
||||||
SunxiD1Pinctrl::SunxiD1Pinctrl(void * const addr) :
|
|
||||||
m_registers(*reinterpret_cast<Registers *>(addr)) {}
|
|
||||||
|
|
||||||
void SunxiD1Pinctrl::set_pin_mode(
|
|
||||||
const Bank bank,
|
|
||||||
const uint8_t pin,
|
|
||||||
const uint8_t mode) {
|
|
||||||
// Config banks are split up every 8 GPIO pins
|
|
||||||
// Each bank is 32 bits and configures up to 8 pins
|
|
||||||
const int config_bank = pin / 8;
|
|
||||||
// Each config is 4 bits per pin
|
|
||||||
const int shift_amount = pin % 8 * 4;
|
|
||||||
const uint32_t mask = 0b1111 << shift_amount;
|
|
||||||
|
|
||||||
auto config = m_registers.ports[bank].config[config_bank];
|
|
||||||
config &= ~mask;
|
|
||||||
config |= (mode & 0b1111) << shift_amount;
|
|
||||||
m_registers.ports[bank].config[config_bank] = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SunxiD1Pinctrl::set_pin_state(
|
|
||||||
const Bank bank,
|
|
||||||
const uint8_t pin,
|
|
||||||
const bool state) {
|
|
||||||
const uint32_t mask = 0b1 << pin;
|
|
||||||
|
|
||||||
auto data = m_registers.ports[bank].data;
|
|
||||||
if(state)
|
|
||||||
data |= mask;
|
|
||||||
else
|
|
||||||
data &= ~mask;
|
|
||||||
m_registers.ports[bank].data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SunxiD1Pinctrl::get_pin_state(
|
|
||||||
const Bank bank,
|
|
||||||
const uint8_t pin) {
|
|
||||||
return m_registers.ports[bank].data >> pin & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End namespace sunxi_d1_pinctrl
|
|
||||||
} // End namespace drivers
|
|
|
@ -1,161 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace drivers {
|
|
||||||
namespace uart_16550 {
|
|
||||||
|
|
||||||
struct [[gnu::packed]] IER {
|
|
||||||
uint8_t data_ready : 1;
|
|
||||||
uint8_t thr_empty : 1;
|
|
||||||
uint8_t receiver_line_status : 1;
|
|
||||||
uint8_t modem_status : 1;
|
|
||||||
uint8_t : 2;
|
|
||||||
uint8_t dma_rx_end : 1;
|
|
||||||
uint8_t dma_tx_end : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::packed]]ISR {
|
|
||||||
uint8_t status : 1;
|
|
||||||
uint8_t fifos_enabled : 2;
|
|
||||||
uint8_t dma_tx_end : 1;
|
|
||||||
uint8_t dma_rx_end : 1;
|
|
||||||
uint8_t id_code : 3;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::packed]] FCR {
|
|
||||||
uint8_t fifo_enable : 1;
|
|
||||||
uint8_t rx_fifo_reset : 1;
|
|
||||||
uint8_t tx_fifo_reset : 1;
|
|
||||||
uint8_t dma_mode : 1;
|
|
||||||
uint8_t enable_dma_end : 1;
|
|
||||||
uint8_t : 1;
|
|
||||||
uint8_t rx_fifo_trigger_level : 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::packed]] LCR {
|
|
||||||
uint8_t word_length : 2;
|
|
||||||
uint8_t stop_bits : 1;
|
|
||||||
uint8_t parity_enable : 1;
|
|
||||||
uint8_t even_parity : 1;
|
|
||||||
uint8_t force_parity : 1;
|
|
||||||
uint8_t set_break : 1;
|
|
||||||
uint8_t dlab : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::packed]] MCR {
|
|
||||||
uint8_t dtr : 1;
|
|
||||||
uint8_t rts : 1;
|
|
||||||
uint8_t out_1 : 1;
|
|
||||||
uint8_t out2_int_enable : 1;
|
|
||||||
uint8_t loopback : 1;
|
|
||||||
uint8_t : 3;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::packed]] LSR {
|
|
||||||
uint8_t data_ready : 1;
|
|
||||||
uint8_t overrun : 1;
|
|
||||||
uint8_t parity : 1;
|
|
||||||
uint8_t framing : 1;
|
|
||||||
uint8_t break_interrupt : 1;
|
|
||||||
uint8_t thr_empty : 1;
|
|
||||||
uint8_t tx_empty : 1;
|
|
||||||
uint8_t fifo_data_error : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::packed]] PSD {
|
|
||||||
uint8_t prescaler_division_factor: 4;
|
|
||||||
uint8_t : 4;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct [[gnu::packed]] MSR {
|
|
||||||
uint8_t delta_cts : 1;
|
|
||||||
uint8_t delta_dsr : 1;
|
|
||||||
uint8_t trailing_edge_ri : 1;
|
|
||||||
uint8_t delta_cd : 1;
|
|
||||||
uint8_t cts : 1;
|
|
||||||
uint8_t dsr : 1;
|
|
||||||
uint8_t ri : 1;
|
|
||||||
uint8_t cd : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TEMP
|
|
||||||
#define UART_16550_32_BIT
|
|
||||||
#ifdef UART_16550_32_BIT
|
|
||||||
|
|
||||||
struct [[gnu::packed]] Registers {
|
|
||||||
// 0x00
|
|
||||||
union {
|
|
||||||
uint8_t rhr;
|
|
||||||
uint8_t thr;
|
|
||||||
uint8_t dcl;
|
|
||||||
};
|
|
||||||
uint32_t : 24;
|
|
||||||
// 0x04
|
|
||||||
union {
|
|
||||||
IER ier;
|
|
||||||
uint8_t dch;
|
|
||||||
};
|
|
||||||
uint32_t : 24;
|
|
||||||
// 0x08
|
|
||||||
union {
|
|
||||||
ISR isr;
|
|
||||||
FCR fcr;
|
|
||||||
};
|
|
||||||
uint32_t : 24;
|
|
||||||
// 0x0C
|
|
||||||
LCR lcr;
|
|
||||||
uint32_t : 24;
|
|
||||||
// 0x10
|
|
||||||
MCR mcr;
|
|
||||||
uint32_t : 24;
|
|
||||||
// 0x14
|
|
||||||
union {
|
|
||||||
LSR lsr;
|
|
||||||
PSD psd;
|
|
||||||
};
|
|
||||||
uint32_t : 24;
|
|
||||||
// 0x18
|
|
||||||
MSR msr;
|
|
||||||
uint32_t : 24;
|
|
||||||
// 0x1C
|
|
||||||
uint8_t spr;
|
|
||||||
uint32_t : 24;
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
struct [[gnu::packed]] Registers {
|
|
||||||
// 0x00
|
|
||||||
union {
|
|
||||||
uint8_t rhr;
|
|
||||||
uint8_t thr;
|
|
||||||
uint8_t dcl;
|
|
||||||
};
|
|
||||||
// 0x01
|
|
||||||
union {
|
|
||||||
IER ier;
|
|
||||||
uint8_t dch;
|
|
||||||
};
|
|
||||||
// 0x02
|
|
||||||
union {
|
|
||||||
ISR isr;
|
|
||||||
FCR fcr;
|
|
||||||
};
|
|
||||||
// 0x03
|
|
||||||
LCR lcr;
|
|
||||||
// 0x04
|
|
||||||
MCR mcr;
|
|
||||||
// 0x05
|
|
||||||
union {
|
|
||||||
LSR lsr;
|
|
||||||
PSD psd;
|
|
||||||
};
|
|
||||||
// 0x06
|
|
||||||
MSR msr;
|
|
||||||
// 0x07
|
|
||||||
uint8_t spr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // End namespace uart_16550
|
|
||||||
} // End namespace drivers
|
|
|
@ -1,116 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "registers.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace drivers {
|
|
||||||
namespace uart_16550 {
|
|
||||||
|
|
||||||
enum class DataBits {
|
|
||||||
BITS_5,
|
|
||||||
BITS_6,
|
|
||||||
BITS_7,
|
|
||||||
BITS_8,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class StopBits {
|
|
||||||
STOP_1,
|
|
||||||
STOP_1_5,
|
|
||||||
STOP_2,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Parity {
|
|
||||||
NONE,
|
|
||||||
EVEN,
|
|
||||||
ODD,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Uart16550 {
|
|
||||||
Uart16550(void * const addr) :
|
|
||||||
m_registers(*reinterpret_cast<Registers *>(addr)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(
|
|
||||||
const int baud_rate,
|
|
||||||
const DataBits data_bits,
|
|
||||||
const Parity parity,
|
|
||||||
const StopBits stop_bits) const volatile {
|
|
||||||
switch(data_bits) {
|
|
||||||
case DataBits::BITS_5:
|
|
||||||
m_registers.lcr.word_length = 0;
|
|
||||||
break;
|
|
||||||
case DataBits::BITS_6:
|
|
||||||
m_registers.lcr.word_length = 1;
|
|
||||||
break;
|
|
||||||
case DataBits::BITS_7:
|
|
||||||
m_registers.lcr.word_length = 2;
|
|
||||||
break;
|
|
||||||
case DataBits::BITS_8:
|
|
||||||
m_registers.lcr.word_length = 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(parity) {
|
|
||||||
case Parity::NONE:
|
|
||||||
m_registers.lcr.parity_enable = 0;
|
|
||||||
break;
|
|
||||||
case Parity::EVEN:
|
|
||||||
m_registers.lcr.parity_enable = 1;
|
|
||||||
m_registers.lcr.even_parity = 1;
|
|
||||||
break;
|
|
||||||
case Parity::ODD:
|
|
||||||
m_registers.lcr.parity_enable = 1;
|
|
||||||
m_registers.lcr.even_parity = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(stop_bits) {
|
|
||||||
case StopBits::STOP_1:
|
|
||||||
m_registers.lcr.stop_bits = 0;
|
|
||||||
break;
|
|
||||||
case StopBits::STOP_1_5:
|
|
||||||
// TODO: Throw error if data_bits isnt BITS_5
|
|
||||||
m_registers.lcr.stop_bits = 0;
|
|
||||||
break;
|
|
||||||
case StopBits::STOP_2:
|
|
||||||
// TODO: Throw error if data_bits is BITS_5
|
|
||||||
m_registers.lcr.stop_bits = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert DLAB to allow setting the divisor
|
|
||||||
// TODO: Assert CHCFG_AT_BUSY (UART_HALT[1])?
|
|
||||||
m_registers.lcr.dlab = 1;
|
|
||||||
|
|
||||||
// TODO: Get actual clock from TCC
|
|
||||||
const uint16_t divisor = 24000000 / baud_rate / 16;
|
|
||||||
m_registers.dch = divisor >> 8;
|
|
||||||
m_registers.dcl = divisor & 0xFF;
|
|
||||||
|
|
||||||
// TODO: Assert CHANGE_UPDATE (UART_HALT[2])?
|
|
||||||
// TODO: Wait for CHANGE_UPDATE (UART_HALT[2]) to be deasserted?
|
|
||||||
|
|
||||||
// Deassert DLAB to return to normal operation
|
|
||||||
m_registers.lcr.dlab = 0;
|
|
||||||
|
|
||||||
// Disable interrupts
|
|
||||||
// TODO: Move to its own function
|
|
||||||
// TODO: Cheese?
|
|
||||||
reinterpret_cast<volatile uint8_t &>(m_registers.ier) = 0;
|
|
||||||
|
|
||||||
// Enable FIFO
|
|
||||||
// TODO: Move to its own function
|
|
||||||
m_registers.fcr.fifo_enable = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(const char c) {
|
|
||||||
while(m_registers.lsr.thr_empty == 0);
|
|
||||||
m_registers.thr = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
volatile Registers &m_registers;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // End namespace uart_16550
|
|
||||||
} // End namespace drivers
|
|
|
@ -1,9 +0,0 @@
|
||||||
kernel_sources += [
|
|
||||||
files(
|
|
||||||
'uart_16550.cpp',
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
kernel_includes += include_directories(
|
|
||||||
'include'
|
|
||||||
)
|
|
|
@ -1,8 +0,0 @@
|
||||||
#include "uart_16550/uart_16550.h"
|
|
||||||
|
|
||||||
namespace drivers {
|
|
||||||
namespace uart_16550 {
|
|
||||||
|
|
||||||
|
|
||||||
} // End namespace uart_16550
|
|
||||||
} // End namespace drivers
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
// #include <dtb/dtb.h>
|
#include <dtb/dtb.h>
|
||||||
|
|
||||||
#include <opensbi/opensbi.h>
|
#include <opensbi/opensbi.h>
|
||||||
#include <opensbi/extensions/legacy.h>
|
#include <opensbi/extensions/legacy.h>
|
||||||
|
@ -13,8 +13,32 @@
|
||||||
#include <opensbi/extensions/srst.h>
|
#include <opensbi/extensions/srst.h>
|
||||||
#include <opensbi/extensions/pmu.h>
|
#include <opensbi/extensions/pmu.h>
|
||||||
|
|
||||||
#include <sunxi_d1_pinctrl/sunxi_d1_pinctrl.h>
|
#define read_csr(csr) \
|
||||||
#include <uart_16550/uart_16550.h>
|
({ \
|
||||||
|
unsigned long __v; \
|
||||||
|
asm volatile ("csrr %0, " csr : "=r"(__v) : : "memory");\
|
||||||
|
__v;\
|
||||||
|
})
|
||||||
|
|
||||||
|
#define write_csr(csr, v) \
|
||||||
|
({ \
|
||||||
|
unsigned long __v = (v); \
|
||||||
|
asm volatile ("csrw " csr ", %0" : : "r"(__v) : "memory");\
|
||||||
|
})
|
||||||
|
|
||||||
|
#define set_csr_bits(csr, bits) \
|
||||||
|
({ \
|
||||||
|
unsigned long __v = (bits); \
|
||||||
|
asm volatile ("csrs " csr ", %0" : : "r"(__v) : "memory");\
|
||||||
|
})
|
||||||
|
|
||||||
|
#define clear_csr_bits(csr, bits) \
|
||||||
|
({ \
|
||||||
|
unsigned long __v = (bits); \
|
||||||
|
asm volatile ("csrc " csr ", %0" : : "r"(__v) : "memory");\
|
||||||
|
})
|
||||||
|
|
||||||
|
typedef unsigned long sbi_word;
|
||||||
|
|
||||||
void fmt(const char *f, ...) {
|
void fmt(const char *f, ...) {
|
||||||
namespace legacy = drivers::opensbi::legacy;
|
namespace legacy = drivers::opensbi::legacy;
|
||||||
|
@ -45,12 +69,216 @@ void fmt(const char *f, ...) {
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
pte_valid = 1 << 0,
|
||||||
|
pte_r = 1 << 1,
|
||||||
|
pte_w = 1 << 2,
|
||||||
|
pte_x = 1 << 3,
|
||||||
|
pte_user = 1 << 4,
|
||||||
|
pte_access = 1 << 6,
|
||||||
|
pte_dirty = 1 << 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
pte_ppn_shift = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pt_t {
|
||||||
|
unsigned long ptes[512];
|
||||||
|
} __attribute__((aligned(4096)));
|
||||||
|
|
||||||
|
enum {
|
||||||
|
satp_sv48 = 9UL << 60
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *exception_strings[] = {
|
||||||
|
"instruction misaligned",
|
||||||
|
"instruction access fault",
|
||||||
|
"illegal instruction",
|
||||||
|
"breakpoint",
|
||||||
|
"load misaligned",
|
||||||
|
"load access fault",
|
||||||
|
"store misaligned",
|
||||||
|
"store access fault",
|
||||||
|
"u-mode ecall",
|
||||||
|
"s-mode ecall",
|
||||||
|
"reserved (10)",
|
||||||
|
"reserved (11)",
|
||||||
|
"instruction page fault",
|
||||||
|
"load page fault",
|
||||||
|
"reserved (14)",
|
||||||
|
"store page fault",
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
sie_s_software = (1 << 1),
|
||||||
|
sie_s_timer = (1 << 5)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
sstatus_sie = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
void cli() {
|
||||||
|
clear_csr_bits("sstatus", sstatus_sie);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sti() {
|
||||||
|
set_csr_bits("sstatus", sstatus_sie);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *sp;
|
||||||
|
} continuation_t;
|
||||||
|
|
||||||
|
struct task_t;
|
||||||
|
|
||||||
|
struct isr_frame_t {
|
||||||
|
task_t *task;
|
||||||
|
isr_frame_t *next;
|
||||||
|
unsigned long ra; // Offset 0x10.
|
||||||
|
unsigned long a[8]; // Offset 0x18.
|
||||||
|
unsigned long t[7]; // Offset 0x58.
|
||||||
|
unsigned long s1; // Offset 0x90.
|
||||||
|
unsigned long sstatus; // Offset 0x98.
|
||||||
|
unsigned long sepc; // Offset 0xA0.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kernel_stack_size = 0x10000
|
||||||
|
};
|
||||||
|
|
||||||
|
struct task_t {
|
||||||
|
continuation_t cont;
|
||||||
|
isr_frame_t isr_frames[2];
|
||||||
|
isr_frame_t *next_isr;
|
||||||
|
char kernel_stack[kernel_stack_size];
|
||||||
|
};
|
||||||
|
|
||||||
|
task_t task1;
|
||||||
|
task_t task2;
|
||||||
|
task_t *current_task;
|
||||||
|
|
||||||
|
continuation_t prepare_stack(void *s_top, void (*mainfn)(continuation_t)) {
|
||||||
|
void *sp = (void *)((uintptr_t)s_top - 0x78);
|
||||||
|
*((uint64_t *)((uintptr_t)sp + 0x70)) = (uint64_t)mainfn;
|
||||||
|
return (continuation_t){.sp = sp};
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void save_stack(void (*f)(void *, continuation_t), void *ctx);
|
||||||
|
extern "C" void restore_stack(continuation_t c);
|
||||||
|
|
||||||
|
void create_task(task_t *task, void (*mainfn)(continuation_t)) {
|
||||||
|
task->isr_frames[0].task = task;
|
||||||
|
task->isr_frames[1].task = task;
|
||||||
|
task->isr_frames[0].next = &task->isr_frames[1];
|
||||||
|
task->isr_frames[1].next = 0;
|
||||||
|
task->next_isr = &task->isr_frames[0];
|
||||||
|
|
||||||
|
task->cont = prepare_stack((void *)(task->kernel_stack + kernel_stack_size), mainfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void switch_task(void *ctx, continuation_t c) {
|
||||||
|
task_t *task = (task_t *)ctx;
|
||||||
|
if(task) {
|
||||||
|
task->next_isr = (isr_frame_t *)read_csr("sscratch");
|
||||||
|
task->cont = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
task_t *next;
|
||||||
|
if(task == &task1) {
|
||||||
|
next = &task2;
|
||||||
|
}else{
|
||||||
|
next = &task1;
|
||||||
|
}
|
||||||
|
current_task = next;
|
||||||
|
|
||||||
|
write_csr("sscratch", (unsigned long)next->next_isr);
|
||||||
|
|
||||||
|
restore_stack(next->cont);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void isr();
|
||||||
|
|
||||||
|
extern "C" void handle_isr(isr_frame_t *frame) {
|
||||||
|
namespace legacy = drivers::opensbi::legacy;
|
||||||
|
namespace timer = drivers::opensbi::timer;
|
||||||
|
|
||||||
|
unsigned long cause = read_csr("scause");
|
||||||
|
unsigned long code = cause & ~(1UL << 63);
|
||||||
|
if(cause & (1UL << 63)) {
|
||||||
|
if(code == 1) {
|
||||||
|
fmt("it's an IPI\n");
|
||||||
|
clear_csr_bits("sip", sie_s_software);
|
||||||
|
}else if(code == 5) { // Timer interrupt.
|
||||||
|
//clear_csr_bits("sie", sie_s_timer);
|
||||||
|
unsigned long time = read_csr("time");
|
||||||
|
//drivers::opensbi::ecall(0x54494D45, 0, time + 100000);
|
||||||
|
timer::set_timer(time + 10000000);
|
||||||
|
//set_timer(time + 100000);
|
||||||
|
//save_stack(switch_task, current_task);
|
||||||
|
}else{
|
||||||
|
fmt("it's an unhandled interrupt, code: {}\n", code);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(code == 8) { // Syscall.
|
||||||
|
legacy::console_putchar(frame->a[0]);
|
||||||
|
}else{
|
||||||
|
unsigned long sepc = read_csr("sepc");
|
||||||
|
fmt("it's an exception at {}\n", sepc);
|
||||||
|
const char *s = exception_strings[cause];
|
||||||
|
while(*s)
|
||||||
|
legacy::console_putchar(*(s++));
|
||||||
|
while(1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void isr_frame_overflow() {
|
||||||
|
fmt("isr frame overflow\n");
|
||||||
|
while(1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
pt_t pml4;
|
||||||
|
|
||||||
|
extern "C" void enter_umode(void *entry);
|
||||||
|
|
||||||
|
void syscall(int n, unsigned long arg0) {
|
||||||
|
register sbi_word rArg0 asm("a0") = arg0;
|
||||||
|
register sbi_word rN asm("a7") = n;
|
||||||
|
asm volatile("ecall" : "+r"(rArg0) : "r"(rN) : "memory");
|
||||||
|
if(rArg0)
|
||||||
|
__builtin_trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void task1_umode() {
|
||||||
|
while(1)
|
||||||
|
syscall(0, '!');
|
||||||
|
}
|
||||||
|
|
||||||
|
void task1_main(continuation_t c) {
|
||||||
|
fmt("hello from task1\n");
|
||||||
|
sti();
|
||||||
|
//syscall(0, '!');
|
||||||
|
//enter_umode((void *)task1_umode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void task2_main(continuation_t c) {
|
||||||
|
fmt("hello from task2\n");
|
||||||
|
sti();
|
||||||
|
//while(1)
|
||||||
|
//fmt(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
isr_frame_t global_isr_frames[2];
|
||||||
|
|
||||||
extern "C" void kmain(unsigned long hart, void *dtb) {
|
extern "C" void kmain(unsigned long hart, void *dtb) {
|
||||||
(void)hart;
|
(void)hart;
|
||||||
(void)dtb;
|
(void)dtb;
|
||||||
// D1 doesnt give me dtb ptr?
|
// D1 doesnt give me dtb ptr?
|
||||||
/*
|
// dtb = (void *)0x5fb38580;
|
||||||
dtb = (void *)0x5fb38580;
|
|
||||||
|
|
||||||
dtb::DeviceTree dt;
|
dtb::DeviceTree dt;
|
||||||
int res = dtb::validate_and_parse_header(dt, dtb);
|
int res = dtb::validate_and_parse_header(dt, dtb);
|
||||||
|
@ -60,9 +288,11 @@ extern "C" void kmain(unsigned long hart, void *dtb) {
|
||||||
dtb::print_reserved_regions(dt);
|
dtb::print_reserved_regions(dt);
|
||||||
dtb::print_structure_block(dt);
|
dtb::print_structure_block(dt);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
namespace legacy = drivers::opensbi::legacy;
|
||||||
namespace base = drivers::opensbi::base;
|
namespace base = drivers::opensbi::base;
|
||||||
|
namespace timer = drivers::opensbi::timer;
|
||||||
|
namespace ipi = drivers::opensbi::ipi;
|
||||||
|
|
||||||
fmt("test\n");
|
fmt("test\n");
|
||||||
|
|
||||||
|
@ -108,36 +338,96 @@ extern "C" void kmain(unsigned long hart, void *dtb) {
|
||||||
fmt("imp id: {}\n", ret.value);
|
fmt("imp id: {}\n", ret.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fmt("uintmax: {} bits\n", sizeof(uintmax_t) * 8);
|
fmt("uintmax: {} bits\n", sizeof(uintmax_t) * 8);
|
||||||
fmt("HART: {}, DTB: {}\n", hart, dtb);
|
fmt("HART: {}, DTB: {}\n", hart, dtb);
|
||||||
|
|
||||||
// ==================
|
volatile uint32_t *cfg = (uint32_t *)0x2000060;
|
||||||
// == Pinctrl test ==
|
volatile uint32_t *dat = (uint32_t *)0x2000070;
|
||||||
// ==================
|
|
||||||
namespace sunxi_d1_pinctrl = drivers::sunxi_d1_pinctrl;
|
|
||||||
sunxi_d1_pinctrl::SunxiD1Pinctrl pinctrl((void *)0x2000000);
|
|
||||||
|
|
||||||
pinctrl.set_pin_mode(sunxi_d1_pinctrl::Bank::PC, 1, 1);
|
*cfg = 0x10;
|
||||||
pinctrl.set_pin_state(sunxi_d1_pinctrl::Bank::PC, 1, true);
|
*dat = 0xFF;
|
||||||
|
|
||||||
// ===============
|
//while(1);
|
||||||
// == UART test ==
|
|
||||||
// ===============
|
|
||||||
namespace uart_16550 = drivers::uart_16550;
|
|
||||||
uart_16550::Uart16550 uart((void *)0x02500000);
|
|
||||||
// uart_16550::Uart16550 uart((void *)0x02500400);
|
|
||||||
uart.init(115200, uart_16550::DataBits::BITS_8, uart_16550::Parity::NONE, uart_16550::StopBits::STOP_1);
|
|
||||||
|
|
||||||
while(true) {
|
cli();
|
||||||
uart.write('X');
|
|
||||||
uart.write('\n');
|
global_isr_frames[0].next = &global_isr_frames[1];
|
||||||
uint32_t a = 0;
|
write_csr("sscratch", (unsigned long)&global_isr_frames[0]);
|
||||||
for(a = 0; a < 0x10000000; a++);
|
write_csr("stvec", ((unsigned long)&isr));
|
||||||
|
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
set_csr_bits("sie", sie_s_software | sie_s_timer);
|
||||||
|
|
||||||
|
// Self-IPI.
|
||||||
|
ipi::send_ipi({ 1UL << hart, 0 });
|
||||||
|
|
||||||
|
sti();
|
||||||
|
unsigned long timea = read_csr("time");
|
||||||
|
ret = timer::set_timer(timea + 100000);
|
||||||
|
|
||||||
|
drivers::opensbi::rfence::remote_fence_i({0, 0});
|
||||||
|
//ret = drivers::opensbi::hsm::hart_stop();
|
||||||
|
using drivers::opensbi::srst::ResetType;
|
||||||
|
using drivers::opensbi::srst::ResetReason;
|
||||||
|
// ret = drivers::opensbi::srst::system_reset(ResetType::WARM_REBOOT, ResetReason::SYSTEM_FAILURE);
|
||||||
|
|
||||||
|
namespace pmu = drivers::opensbi::pmu;
|
||||||
|
ret = pmu::num_counters();
|
||||||
|
|
||||||
|
fmt("Number of counters: {}\n", ret.value);
|
||||||
|
for(int i = 0; i < ret.value; i++) {
|
||||||
|
ret = pmu::counter_get_info(i);
|
||||||
|
fmt("{} err: {}\n", i, ret.error);
|
||||||
|
fmt("{} val: {}\n", i, ret.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt("HALT\n");
|
|
||||||
while(1);
|
while(1);
|
||||||
|
cli();
|
||||||
|
|
||||||
|
unsigned long time;
|
||||||
|
//volatile uint32_t *meme = (uint32_t *)0x6011010;
|
||||||
|
//while(true) {
|
||||||
|
time = read_csr("time");
|
||||||
|
fmt("hello world {}\n", time);
|
||||||
|
//*meme = *meme | (0xA57 << 1) | (1 << 0);
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Identity map the first 512GiB.
|
||||||
|
pml4.ptes[0] = ((0UL >> 12) << pte_ppn_shift) | pte_valid
|
||||||
|
| pte_r | pte_w | pte_x | pte_access | pte_dirty | pte_user;
|
||||||
|
// Map 512GiB -> 0.
|
||||||
|
pml4.ptes[1] = ((0UL >> 12) << pte_ppn_shift) | pte_valid
|
||||||
|
| pte_r | pte_w | pte_x | pte_access | pte_dirty | pte_user;
|
||||||
|
|
||||||
|
fmt("Writing paging memes\n");
|
||||||
|
unsigned long pml4p = (unsigned long)&pml4;
|
||||||
|
fmt("pml4p @ {}\n", pml4p);
|
||||||
|
fmt("Setting SStatus\n");
|
||||||
|
set_csr_bits("sstatus", 1 << 18);
|
||||||
|
fmt("Setting Satp\n");
|
||||||
|
write_csr("satp", (pml4p >> 12) | satp_sv48);
|
||||||
|
|
||||||
|
fmt("Paging might work?...\n");
|
||||||
|
|
||||||
|
s = "paging works!\n";
|
||||||
|
s += 512UL * 1024 * 1024 * 1024;
|
||||||
|
while(*s)
|
||||||
|
legacy::console_putchar(*(s++));
|
||||||
|
|
||||||
|
create_task(&task1, task1_main);
|
||||||
|
create_task(&task2, task2_main);
|
||||||
|
|
||||||
|
time = read_csr("time");
|
||||||
|
//set_timer(time + 100000);
|
||||||
|
//drivers::opensbi::ecall(0x54494D45, 0, time + 100000);
|
||||||
|
//timer::set_timer(time + 100000);
|
||||||
|
|
||||||
|
//save_stack(switch_task, 0);
|
||||||
|
|
||||||
namespace hsm = drivers::opensbi::hsm;
|
namespace hsm = drivers::opensbi::hsm;
|
||||||
hsm::hart_stop();
|
hsm::hart_stop();
|
||||||
|
// drivers::opensbi::ecall(8, 0, 0);
|
||||||
|
|
||||||
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,11 @@ kernel_includes = [
|
||||||
include_directories('include')
|
include_directories('include')
|
||||||
]
|
]
|
||||||
|
|
||||||
kernel_c_args = []
|
|
||||||
kernel_cpp_args = []
|
|
||||||
kernel_link_args = ['-nostdlib']
|
|
||||||
|
|
||||||
subdir('drivers/opensbi')
|
subdir('drivers/opensbi')
|
||||||
subdir('drivers/uart_16550')
|
subdir('common/dtb')
|
||||||
subdir('drivers/sunxi_d1_pinctrl')
|
|
||||||
# subdir('common/dtb')
|
|
||||||
|
|
||||||
includes = [
|
includes = [
|
||||||
|
# arch_includes,
|
||||||
kernel_includes
|
kernel_includes
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,8 @@ project('riscv-qtech-os', ['c', 'cpp'],
|
||||||
default_options: [
|
default_options: [
|
||||||
'cpp_std=gnu++20',
|
'cpp_std=gnu++20',
|
||||||
'c_std=gnu11',
|
'c_std=gnu11',
|
||||||
'warning_level=3',
|
'c_flags=-Wall -Werror -Wextra',
|
||||||
'werror=false',
|
'cpp_flags=-Wall -Werror -Wextra'
|
||||||
'buildtype=debugoptimized',
|
|
||||||
# 'buildtype=release',
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,8 +11,6 @@ if not meson.is_cross_build()
|
||||||
error('Kernel must be cross compiled')
|
error('Kernel must be cross compiled')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
c = meson.get_compiler('cpp')
|
|
||||||
cxx = meson.get_compiler('cpp')
|
|
||||||
arch = host_machine.cpu_family()
|
arch = host_machine.cpu_family()
|
||||||
platform = 'allwinner-d1'
|
platform = 'allwinner-d1'
|
||||||
# platform = 'qemu'
|
# platform = 'qemu'
|
||||||
|
|
16
riscv.cross
16
riscv.cross
|
@ -1,6 +1,6 @@
|
||||||
[binaries]
|
[binaries]
|
||||||
c = 'riscv64-elf-gcc'
|
c = 'riscv64-linux-gnu-gcc'
|
||||||
cpp = 'riscv64-elf-g++'
|
cpp = 'riscv64-linux-gnu-g++'
|
||||||
|
|
||||||
[host_machine]
|
[host_machine]
|
||||||
system = 'riscv-qtech-os'
|
system = 'riscv-qtech-os'
|
||||||
|
@ -8,11 +8,9 @@ cpu_family = 'riscv64'
|
||||||
cpu = 'rv64'
|
cpu = 'rv64'
|
||||||
endian = 'little'
|
endian = 'little'
|
||||||
|
|
||||||
[constants]
|
|
||||||
args = ['-ffreestanding', '-march=rv64gc', '-mabi=lp64d', '-mcmodel=medany']
|
|
||||||
|
|
||||||
[built-in options]
|
[built-in options]
|
||||||
c_args = args
|
|
||||||
c_link_args = args
|
c_args = '-march=rv64gc -mabi=lp64d -mcmodel=medany -ffreestanding'
|
||||||
cpp_args = args
|
c_link_args = '-march=rv64gc -mabi=lp64d -mcmodel=medany -nostdlib'
|
||||||
cpp_link_args = args
|
cpp_args = '-march=rv64gc -mabi=lp64d -mcmodel=medany -ffreestanding'
|
||||||
|
cpp_link_args = '-march=rv64gc -mabi=lp64d -mcmodel=medany -nostdlib'
|
||||||
|
|
Loading…
Reference in a new issue