RISC-V: A Baremetal Introduction using C++. Overview.

Blinky in C++

    struct mtimer_address_spec {
static constexpr std::uintptr_t MTIMECMP_ADDR = 0x20004000;
static constexpr std::uintptr_t MTIME_ADDR = 0x2000BFF8;
};
struct mtimer_timer_config {
static constexpr unsigned int MTIME_FREQ_HZ=32768;
};
static constexpr uintptr_t SIFIVE_GPIO0_0 = 0x10012000;
...
driver::timer<mtimer_address_spec, mtimer_timer_config> mtimer;
driver::sifive_gpio0_0_dev<SIFIVE_GPIO0_0> gpio_dev;
mtimer.set_time_cmp(std::chrono::seconds{1});
    static constexpr int LED_RED=22;
static constexpr int LED_GREEN=19;
static constexpr int LED_BLUE=21;
static constexpr unsigned int LED_MASK_WHITE=
bitmask(LED_RED)|bitmask(LED_GREEN)|bitmask(LED_BLUE);
...
gpio_dev.output_val &= ~(LED_MASK_WHITE);
gpio_dev.output_en |= (LED_MASK_WHITE);
   static const auto handler = [&] (void) 
{
auto this_cause = riscv::csrs.mcause.read();
// ...more code...
}
irq::handler irq_handler(handler);
    #include "riscv-csr.hpp"
...
riscv::csrs.mie.mti.set();
riscv::csrs.mstatus.mie.set();
    do {
__asm__ volatile ("wfi");
} while (true);
auto this_cause = riscv::csrs.mcause.read();
if (this_cause &
riscv::csr::mcause_data::interrupt::BIT_MASK) {
this_cause &= 0xFF;
switch (this_cause) {
case riscv::interrupts::mti :
mtimer.set_time_cmp(std::chrono::seconds{1});
timestamp =
mtimer.get_time<
driver::timer<>::timer_ticks>().count();
gpio_dev.output_val ^= (LED_MASK_WHITE);
break;
}
}

The Complete Example

int main(void) {// Device drivers
driver::sifive_gpio0_0_dev<SIFIVE_GPIO0_0> gpio_dev;
driver::timer<> mtimer;
// Device Setup // Save the timer value at this time.
auto timestamp =
mtimer.get_time<driver::timer<>::timer_ticks>().count();
// Setup timer for 1 second interval
mtimer.set_time_cmp(std::chrono::seconds{1});
// Enable GPIO
gpio_dev.output_val &= ~(LED_MASK_WHITE);
gpio_dev.output_en |= (LED_MASK_WHITE);
// The periodic interrupt lambda function.
// The context (drivers etc) is captured via reference using [&]
static const auto handler = [&] (void)
{
// In RISC-V the mcause register stores the
// cause of any interrupt or exception.
auto this_cause = riscv::csrs.mcause.read();
// For simplicity non-vectored interrupt mode is used.
// The top bit of the mcause register indicates
// if this is an interrupt or exception.
if (this_cause &
riscv::csr::mcause_data::interrupt::BIT_MASK) {
this_cause &= 0xFF;
// De-multiplex the interrupt
// The cause register LSBs hold an integer value
// that represents the interrupt source
switch (this_cause) {
case riscv::interrupts::mti :
// A machine timer interrupt
// RISC-V machine mode timer interrupts
// are not repeating.
// Set the timer compare register to the
// current time + one second
mtimer.set_time_cmp(std::chrono::seconds{1});
// Save the timestamp as a raw counter in
// units of the hardware counter.
// While there is quite a bit of code here,
// it can be resolved at compile time to a
// simple MMIO register read.
timestamp =
mtimer.get_time<
driver::timer<>::timer_ticks>().count();
// Xor to invert. This can be compiled to a
// write to the toggle register via
// operator overloading.
gpio_dev.output_val ^= (LED_MASK_WHITE);
break;
}
}
};
// Install the above lambda function as the machine mode
// IRQ handler.
irq::handler irq_handler(handler);
// Enable interrupts
riscv::csrs.mie.mti.set();
// Global interrupt enable
riscv::csrs.mstatus.mie.set();
// Busy loop
do {
__asm__ volatile ("wfi");
} while (true);
return 0; // Never executed
}

Last Words

--

--

--

Software Engineer, Software Architect, Embedded Systems, Distributed Systems, Digital Design, ソフトウェアエンジニア http://www.linkedin.com/in/phil-mulholland-884a8

Love podcasts or audiobooks? Learn on the go with our new app.

Picking the right database for the job

領導企業敏捷轉型 / 領袖工作坊 / Jutta Eckstein 筆記

The Top 20 Team Management Software of 2019

Datadog Log Management from Zero to One

CDC Strategies for Real Time Data Lakes/Data Platform

I’ve been using Behat wrong this whole time

Site Reliability Engineering (SRE) Tips #3

Understanding of Linux Permissions & Ownership.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Phil Mulholland

Phil Mulholland

Software Engineer, Software Architect, Embedded Systems, Distributed Systems, Digital Design, ソフトウェアエンジニア http://www.linkedin.com/in/phil-mulholland-884a8

More from Medium

C++20 Concepts: part 3

System Embedded

[C++] namespace

C++: Complete Developer Guide — Part 1

C++ Fast development reference khizaruddins, khizaruddins.medium.com mother of programming language