Rust-USB support using riscv-blink c-code

This commit is contained in:
Carsten Thiele 2021-10-08 18:06:03 +02:00
parent 8e3ba84d78
commit 66939a4fbf
7 changed files with 240 additions and 1 deletions

View File

@ -1,6 +1,6 @@
[target.riscv32i-unknown-none-elf]
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tld/linker.ld",
]

View File

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.13"
@ -24,6 +26,12 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0"
[[package]]
name = "cc"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
[[package]]
name = "fomu-pac"
version = "0.0.4"
@ -157,6 +165,7 @@ dependencies = [
name = "riscv-rust-blink"
version = "0.1.0"
dependencies = [
"cc",
"fomu-pac",
"fomu-rt",
"panic-halt",

View File

@ -12,6 +12,9 @@ fomu-rt = "0.0.6"
panic-halt = "0.2"
[build-dependencies]
cc = "1.0.71"
[profile.release]
# Keep debug information for release builds, for easier debugging.
# It will be removed during the conversion to the .dfu file.

16
riscv-rust-blink/build.rs Normal file
View File

@ -0,0 +1,16 @@
use cc;
// Build the USB-Support from the riscv-blink c-code
fn main() {
cc::Build::new()
.file("../riscv-blink/src/usb-dev.c")
.file("../riscv-blink/src/usb-epfifo.c")
.file("../riscv-blink/src/usb-eptri.c")
.file("../riscv-blink/src/usb.c")
.file("../riscv-blink/src/rgb.c")
.file("src/c/irq.c")
.include("../riscv-blink/include")
.define("__vexriscv__", None)
.compile("fomu-usb");
}

View File

@ -0,0 +1,162 @@
MEMORY
{
RAM : ORIGIN = 0x10000000, LENGTH = 128K
FLASH : ORIGIN = 0x20040000, LENGTH = 2M - 0x40000
}
REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_RODATA", FLASH);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_HEAP", RAM);
REGION_ALIAS("REGION_STACK", RAM);
PROVIDE(_stext = ORIGIN(REGION_TEXT));
PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
PROVIDE(_max_hart_id = 0);
PROVIDE(_hart_stack_size = 2K);
PROVIDE(_heap_size = 0);
PROVIDE(trap_handler = default_trap_handler);
/* # Pre-initialization function */
/* If the user overrides this using the `#[pre_init]` attribute or by creating a `__pre_init` function,
then the function this points to will be called before the RAM is initialized. */
PROVIDE(__pre_init = default_pre_init);
/* # Multi-processing hook function
fn _mp_hook() -> bool;
This function is called from all the harts and must return true only for one hart,
which will perform memory initialization. For other harts it must return false
and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt).
*/
PROVIDE(_mp_hook = default_mp_hook);
SECTIONS
{
.text.dummy (NOLOAD) :
{
/* This section is intended to make _stext address work */
. = _stext;
} > REGION_TEXT
.text _stext :
{
/* Put reset handler first in .text section so it ends up as the entry */
/* point of the program. */
KEEP(*(.init));
KEEP(*(.init.rust));
. = ALIGN(4);
KEEP(*(.trap));
KEEP(*(.trap.rust));
*(.text .text.*);
} > REGION_TEXT
.rodata : ALIGN(4)
{
*(.rodata .rodata.*);
/* 4-byte align the end (VMA) of this section.
This is required by LLD to ensure the LMA of the following .data
section will have the correct alignment. */
. = ALIGN(4);
} > REGION_RODATA
.data : ALIGN(4)
{
_sidata = LOADADDR(.data);
_sdata = .;
*(.ramtext .ramtext.*)
/* Must be called __global_pointer$ for linker relaxations to work. */
PROVIDE(__global_pointer$ = . + 0x800);
*(.sdata .sdata.* .sdata2 .sdata2.*);
*(.data .data.*);
. = ALIGN(4);
_edata = .;
} > REGION_DATA AT > REGION_RODATA
.bss (NOLOAD) :
{
_sbss = .;
*(.sbss .sbss.* .bss .bss.*);
. = ALIGN(4);
_ebss = .;
} > REGION_BSS
/* fictitious region that represents the memory available for the heap */
.heap (NOLOAD) :
{
_sheap = .;
. += _heap_size;
. = ALIGN(4);
_eheap = .;
} > REGION_HEAP
/* fake output .got section */
/* Dynamic relocations are unsupported. This section is only used to detect
relocatable code in the input files and raise an error if relocatable code
is found */
.got (INFO) :
{
KEEP(*(.got .got.*));
}
/* Discard .eh_frame, we are not doing unwind on panic so it is not needed */
/DISCARD/ :
{
*(.eh_frame);
*(.eh_frame_hdr);
}
}
_estack = ORIGIN(RAM) + LENGTH(RAM);
/* Do not exceed this mark in the error messages above | */
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, "
ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
ASSERT(ORIGIN(REGION_STACK) % 4 == 0, "
ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned");
ASSERT(_stext % 4 == 0, "
ERROR(riscv-rt): `_stext` must be 4-byte aligned");
ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, "
BUG(riscv-rt): .data is not 4-byte aligned");
ASSERT(_sidata % 4 == 0, "
BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
ASSERT(_sbss % 4 == 0 && _ebss % 4 == 0, "
BUG(riscv-rt): .bss is not 4-byte aligned");
ASSERT(_sheap % 4 == 0, "
BUG(riscv-rt): start of .heap is not 4-byte aligned");
ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
ASSERT(SIZEOF(.got) == 0, "
.got section detected in the input files. Dynamic relocations are not
supported. If you are linking to C code compiled using the `gcc` crate
then modify your build script to compile the C code _without_ the
-fPIC flag. See the documentation of the `gcc::Config.fpic` method for
details.");
/* Do not exceed this mark in the error messages above | */

View File

@ -0,0 +1,22 @@
#include <generated/csr.h>
#include <irq.h>
#include <usb.h>
#include <system.h>
void isr(void) {
unsigned int irqs;
irqs = irq_pending() & irq_getmask();
if (irqs & (1 << USB_INTERRUPT)) {
usb_isr();
}
}
void irq_init() {
irq_setmask(0);
irq_setie(1);
csrw(mie, 0x880);
}

View File

@ -14,10 +14,37 @@ use timer::Timer;
const SYSTEM_CLOCK_FREQUENCY: u32 = 12_000_000;
// USB-support using the c-code from riscv-blink
#[link(name = "fomu-usb", kind = "static")]
extern "C" {
fn usb_init();
fn usb_connect();
fn irq_init();
fn isr();
fn _start_trap_rust();
}
// set irq handler and call c-implementation
#[doc(hidden)]
#[link_section = ".trap.rust"]
#[no_mangle]
fn trap_handler() {
unsafe {isr();}
}
// This is the entry point for the application.
// It is not allowed to return.
#[entry]
fn main() -> ! {
// Call riscv-blink c-usb-initialization code
unsafe {
irq_init();
usb_init();
usb_connect();
}
let peripherals = fomu_pac::Peripherals::take().unwrap();
let mut rgb_control = rgb::RgbControl::new(peripherals.RGB);