1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #8966 from kenrabold/riotpr

RISC-V: New CPU (FE310) and Board (HiFive1)
This commit is contained in:
Kaspar Schleiser 2018-05-30 09:47:26 +02:00 committed by GitHub
commit 22cb41b874
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 5927 additions and 15 deletions

3
boards/hifive1/Makefile Normal file
View File

@ -0,0 +1,3 @@
MODULE = board
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1 @@
include $(RIOTCPU)/fe310/Makefile.dep

View File

@ -0,0 +1,16 @@
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_gpio
#FEATURES_PROVIDED += periph_pwm
FEATURES_PROVIDED += periph_rtc
FEATURES_PROVIDED += periph_rtt
#FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_uart
ifneq (,$(filter periph_rtc,$(FEATURES_REQUIRED)))
FEATURES_REQUIRED += periph_rtt
endif
# The board MPU family (used for grouping by the CI system)
FEATURES_MCU_GROUP = risc_v

View File

@ -0,0 +1,12 @@
# define the cpu used by the HiFive1 board
export CPU = fe310
export CPU_MODEL = fe310
# Uses UART0 for stdio input/output (comment out to disable)
USEMODULE += uart_stdio
# this board uses openocd
include $(RIOTMAKE)/tools/openocd.inc.mk
# use our own openocd script to flash since HiFive1 has reset problems.
export FLASHER = $(RIOTBASE)/boards/hifive1/dist/flasher.sh

138
boards/hifive1/board.c Normal file
View File

@ -0,0 +1,138 @@
/*
* Copyright (C) 2017 Ken Rabold, JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup boards_hifive
* @{
*
* @file
* @brief Support for the SiFive HiFive1 RISC-V board
*
* @author Ken Rabold, JP Bonn
*
* @}
*/
#include <stdio.h>
#include <errno.h>
#include "cpu.h"
#include "board.h"
#include "periph/gpio.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/prci_driver.h"
/*
* Configure the memory mapped flash for faster throughput
* to minimize interrupt latency on an I-Cache miss and refill
* from flash. Alternatively (and faster) the interrupt
* routine could be put in SRAM. The linker script supports
* code in SRAM using the ".hotcode" section.
* The flash chip on the HiFive1 is the ISSI 25LP128
* http://www.issi.com/WW/pdf/25LP128.pdf
* The maximum frequency it can run at is 133MHz in
* "Fast Read Dual I/O" mode.
* Note the updated data sheet:
* https://static.dev.sifive.com/SiFive-FE310-G000-datasheet-v1.0.4.pdf
* states "Address and write data using DQ[3] for transmission will not
* function properly." This rules out QPI for the XIP memory mapped flash.
* #define MAX_FLASH_FREQ 133000000
* On forum SiFive says "safe" operation would be 40MHz. 50MHz seems to work
* fine.
*/
#define MAX_FLASH_FREQ 50000000
/*
* CPU max is 320MHz+ according to datasheet but
* the relationship between cpu clock and spi clock is determined
* by SCKDIV. Given we're trying to achieve maximum I-cache refill
* for the flash we let MAX_FLASH_FREQ dictate the CPU clock.
*/
#define CPU_DESIRED_FREQ 200000000
/*
* The relationship between the input clock and SCK is given
* by the following formula (Fin is processor/tile-link clock):
* Fsck = Fin/(2(div + 1))
* FYI - For 320MHZ it seems to be tolerating a faster SPI clock (56MHz)
*/
#define SCKDIV ((CPU_DESIRED_FREQ - 1) / (MAX_FLASH_FREQ * 2))
/* This should work for any reasonable cpu clock value. */
#define SCKDIV_SAFE 3
/*
* By default the SPI initialized as:
* https://github.com/sifive/sifive-blocks/blob/master/src/main/scala/devices/spi/SPIFlash.scala
* insn.cmd.en := Bool(true)
* insn.cmd.code := Bits(0x03)
* insn.cmd.proto := SPIProtocol.Single
* insn.addr.len := UInt(3)
* insn.addr.proto := SPIProtocol.Single
* insn.pad.cnt := UInt(0)
* insn.pad.code := Bits(0)
* insn.data.proto := SPIProtocol.Single
*
* 25LP128 appears to left in post-reset default state. Boot code
* does not modify it. We change the SPI configuration here.
*/
void board_init_clock(void)
{
/* In case we are executing from QSPI, (which is quite likely) we need to
* set the QSPI clock divider appropriately before boosting the clock
* frequency. PRCI_set_hfrosctrim_for_f_cpu() tries multiple clocks
* so choose a safe value that should work for all frequencies.
*/
SPI0_REG(SPI_REG_SCKDIV) = SCKDIV_SAFE;
/* Note: The range is limited to ~100MHz and depends on PLL settings */
PRCI_set_hfrosctrim_for_f_cpu(CPU_DESIRED_FREQ, PRCI_FREQ_UNDERSHOOT);
/* disable uncrustify *INDENT-OFF* */
SPI0_REG(SPI_REG_FFMT) = /* setup "Fast Read Dual I/O" 1-1-2 */
SPI_INSN_CMD_EN | /* Enable memory-mapped flash */
SPI_INSN_ADDR_LEN(3) | /* 25LP128 read commands have 3 address bytes */
SPI_INSN_PAD_CNT(4) | /* 25LP128 Table 6.9 Read Dummy Cycles P4,P3=0,0 */
SPI_INSN_CMD_PROTO(SPI_PROTO_S) | /* 25LP128 Table 8.1 "Instruction */
SPI_INSN_ADDR_PROTO(SPI_PROTO_D) | /* Set" shows mode for cmd, addr, and */
SPI_INSN_DATA_PROTO(SPI_PROTO_D) | /* data protocol for given instruction */
SPI_INSN_CMD_CODE(0xbb) | /* Set the instruction to "Fast Read Dual I/O" */
SPI_INSN_PAD_CODE(0x00); /* Dummy cycle sends 0 value bits */
/* *INDENT-ON* */
SPI0_REG(SPI_REG_SCKDIV) = SCKDIV;
}
void board_init(void)
{
/* Initialize CPU and clocks */
cpu_init();
board_init_clock();
/* Configure pin muxing for UART0 */
GPIO_REG(GPIO_OUTPUT_VAL) |= IOF0_UART0_MASK;
GPIO_REG(GPIO_OUTPUT_EN) |= IOF0_UART0_MASK;
GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK;
GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK;
/* Configure GPIOs for LEDs */
gpio_init(LED0_PIN, GPIO_OUT);
gpio_init(LED1_PIN, GPIO_OUT);
gpio_init(LED2_PIN, GPIO_OUT);
/* Turn all the LEDs off */
LED0_OFF;
LED1_OFF;
LED2_OFF;
/* Initialize newlib-nano library stubs */
nanostubs_init();
}

132
boards/hifive1/dist/flasher.sh vendored Normal file
View File

@ -0,0 +1,132 @@
#!/bin/sh
#
# Former Unified OpenOCD script for RIOT..
# This has been modified to not do "reset" or "reset run" commands while
# flashing since the HiFive1 does not support them.
#
# This script is supposed to be called from RIOTs make system,
# as it depends on certain environment variables. An OpenOCD
# configuration file must be present in a the boards dist folder.
#
# Any extra command line arguments after the command name are passed on the
# openocd command line after the configuration file name but before any other
# initialization commands.
#
# Global environment variables used:
# OPENOCD: OpenOCD command name, default: "openocd"
# OPENOCD_CONFIG: OpenOCD configuration file name,
# default: "${RIOTBOARD}/${BOARD}/dist/openocd.cfg"
#
# The script supports the following actions:
#
# flash: flash a given ELF file to the target.
#
# options:
# IMAGE_FILE: Filename of the file that will be flashed
# PRE_FLASH_CHECK_SCRIPT: a command to run before flashing to
# verify the integrity of the image to be flashed. ELFFILE is
# passed as a command line argument to this command.
# Even though the file name variable is named ELFFILE, flashing
# works with any file format recognized by OpenOCD (elf, ihex, s19, bin).
#
# @author Hauke Peteresen <hauke.petersen@fu-berlin.de>
# @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
# Default path to OpenOCD configuration file
: ${OPENOCD_CONFIG:=${RIOTBOARD}/${BOARD}/dist/openocd.cfg}
# Default OpenOCD command
: ${OPENOCD:=openocd}
# This is an optional offset to the base address that can be used to flash an
# image in a different location than it is linked at. This feature can be useful
# when flashing images for firmware swapping/remapping boot loaders.
# Default offset is 0, meaning the image will be flashed at the address that it
# was linked at.
: ${IMAGE_OFFSET:=0}
# Image file used for flashing. Must be in a format that OpenOCD can handle (ELF,
# Intel hex, S19, or raw binary)
# Default is to use $ELFFILE
: ${IMAGE_FILE:=${ELFFILE}}
# Type of image, leave empty to let OpenOCD automatically detect the type from
# the file (default).
# Valid values: elf, hex, s19, bin (see OpenOCD manual for more information)
: ${IMAGE_TYPE:=}
#
# a couple of tests for certain configuration options
#
test_config() {
if [ ! -f "${OPENOCD_CONFIG}" ]; then
echo "Error: Unable to locate OpenOCD configuration file"
echo " (${OPENOCD_CONFIG})"
exit 1
fi
echo "Using OpenOCD configuration file"
echo " (${OPENOCD_CONFIG})"
}
test_elffile() {
if [ ! -f "${ELFFILE}" ]; then
echo "Error: Unable to locate ELFFILE"
echo " (${ELFFILE})"
exit 1
fi
}
test_imagefile() {
if [ ! -f "${IMAGE_FILE}" ]; then
echo "Error: Unable to locate IMAGE_FILE"
echo " (${IMAGE_FILE})"
exit 1
fi
}
#
# now comes the actual actions
#
do_flash() {
test_config
test_imagefile
if [ -n "${PRE_FLASH_CHECK_SCRIPT}" ]; then
sh -c "${PRE_FLASH_CHECK_SCRIPT} '${IMAGE_FILE}'"
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
echo "pre-flash checks failed, status=$RETVAL"
exit $RETVAL
fi
fi
# flash device
echo 'Doing flashing'
# For some reason 'halt' seems to be more reliable then 'reset halt' at
# getting the HiFive's attention.
sh -c "${OPENOCD} -f '${OPENOCD_CONFIG}' \
-c 'tcl_port disabled' \
-c 'telnet_port disabled' \
-c 'gdb_port disabled' \
-c 'init' \
-c 'halt' \
-c 'flash protect 0 64 last off' \
-c 'flash write_image erase \"${IMAGE_FILE}\" ${IMAGE_OFFSET} ${IMAGE_TYPE}' \
-c 'verify_image \"${IMAGE_FILE}\"' \
-c 'reset halt' \
-c 'reg pc 0x20000000' \
-c 'resume' \
-c 'exit'" &&
echo 'Done flashing'
}
#
# parameter dispatching
#
ACTION="$1"
case "${ACTION}" in
flash)
echo "### Flashing Target ###"
do_flash
;;
*)
echo "Usage: $0 flash"
exit 2
;;
esac

44
boards/hifive1/dist/openocd.cfg vendored Normal file
View File

@ -0,0 +1,44 @@
#
# Originally from:
# https://github.com/sifive/freedom-e-sdk/blob/master/bsp/env/freedom-e300-hifive1/openocd.cfg
# Note this is called by riot/dist/tools/openocd/openocd.sh which
# issues a series of openocd commands.
#
# HiFive1 does not support openocd "reset run" aka "reset"
#
adapter_khz 10000
interface ftdi
ftdi_device_desc "Dual RS232-HS"
ftdi_vid_pid 0x0403 0x6010
ftdi_layout_init 0x0008 0x001b
ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020
#Reset Stretcher logic on FE310 is ~1 second long
#This doesn't apply if you use
# ftdi_set_signal, but still good to document
#adapter_nsrst_delay 1500
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAME
#init
#reset -- This type of reset is not implemented yet
if {[ info exists pulse_srst]} {
ftdi_set_signal nSRST 0
ftdi_set_signal nSRST z
#Wait for the reset stretcher
#It will work without this, but
#will incur lots of delays for later commands.
sleep 1500
}
#halt
#flash protect 0 64 last off
#

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup boards_hifive SiFive HiFive1 RISC-V board
* @ingroup boards
* @brief Support for the SiFive HiFive1 RISC-V board
* @{
*
* @file
* @brief Board specific definitions for the SiFive HiFive1 RISC-V board
*
* @author Ken Rabold
*/
#ifndef BOARD_H
#define BOARD_H
#include "periph/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Macros for controlling the on-board LEDs
* @{
*/
#define LED0_PIN GPIO_PIN(0, 22) /* Red */
#define LED1_PIN GPIO_PIN(0, 19) /* Green */
#define LED2_PIN GPIO_PIN(0, 21) /* Blue */
#define LED0_ON gpio_clear(LED0_PIN)
#define LED0_OFF gpio_set(LED0_PIN)
#define LED0_TOGGLE gpio_toggle(LED0_PIN)
#define LED1_ON gpio_clear(LED1_PIN)
#define LED1_OFF gpio_set(LED1_PIN)
#define LED1_TOGGLE gpio_toggle(LED1_PIN)
#define LED2_ON gpio_clear(LED2_PIN)
#define LED2_OFF gpio_set(LED2_PIN)
#define LED2_TOGGLE gpio_toggle(LED2_PIN)
/** @} */
/**
* @brief Initialize board specific hardware, including clock, LEDs and std-IO
*/
void board_init(void);
/**
* @brief Initialize the board clock to use PLL and faster SPI access.
*/
void board_init_clock(void);
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H */
/** @} */

View File

@ -0,0 +1,100 @@
/*
* Copyright (C) 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup boards_hifive
* @{
*
* @file
* @brief Peripheral specific definitions for the HiFive1 RISC-V board
*
* @author Ken Rabold
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Core Clock configuration
* @{
*/
#define CLOCK_CORECLOCK (1600000ul)
/*
* #define CLOCK_CORECLOCK (20000000ul)
* #define CLOCK_CORECLOCK (27000000ul)
* #define CLOCK_CORECLOCK (38400000ul)
*/
/** @} */
/**
* @name Xtimer configuration
* @{
*/
#define XTIMER_DEV (0)
#define XTIMER_CHAN (0)
#define XTIMER_WIDTH (32)
#define XTIMER_HZ (32768ul)
/** @} */
/**
* @name Timer configuration
*
* @{
*/
#define TIMER_NUMOF (1)
/** @} */
/**
* @name RTT/RTC configuration
*
* @{
*/
#define RTT_NUMOF (1)
#define RTT_FREQUENCY (1) /* in Hz */
#define RTT_MAX_VALUE (0xFFFFFFFF)
#define RTT_INTR_PRIORITY (2)
#define RTC_NUMOF (1)
/** @} */
/**
* @name GPIO configuration
*
* @{
*/
#define GPIO_INTR_PRIORITY (3)
/** @} */
/**
* @name PWM configuration
*
* @{
*/
#define PWM_NUMOF (3)
/** @} */
/**
* @name UART configuration
*
* @{
*/
#define UART_NUMOF (2)
#define UART0_RX_INTR_PRIORITY (2)
#define UART1_RX_INTR_PRIORITY (2)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CONF_H */
/** @} */

206
boards/hifive1/include/vendor/LICENSE vendored Normal file
View File

@ -0,0 +1,206 @@
This software, except as otherwise noted in subrepositories,
is licensed under the Apache 2 license, quoted below.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 SiFive, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

78
boards/hifive1/include/vendor/hifive1.h vendored Normal file
View File

@ -0,0 +1,78 @@
// See LICENSE for license details.
#ifndef _SIFIVE_HIFIVE1_H
#define _SIFIVE_HIFIVE1_H
#include <stdint.h>
/****************************************************************************
* GPIO Connections
*****************************************************************************/
// These are the GPIO bit offsets for the RGB LED on HiFive1 Board.
// These are also mapped to RGB LEDs on the Freedom E300 Arty
// FPGA
// Dev Kit.
#define RED_LED_OFFSET 22
#define GREEN_LED_OFFSET 19
#define BLUE_LED_OFFSET 21
// These are the GPIO bit offsets for the differen digital pins
// on the headers for both the HiFive1 Board and the Freedom E300 Arty FPGA Dev Kit.
#define PIN_0_OFFSET 16
#define PIN_1_OFFSET 17
#define PIN_2_OFFSET 18
#define PIN_3_OFFSET 19
#define PIN_4_OFFSET 20
#define PIN_5_OFFSET 21
#define PIN_6_OFFSET 22
#define PIN_7_OFFSET 23
#define PIN_8_OFFSET 0
#define PIN_9_OFFSET 1
#define PIN_10_OFFSET 2
#define PIN_11_OFFSET 3
#define PIN_12_OFFSET 4
#define PIN_13_OFFSET 5
//#define PIN_14_OFFSET 8 //This pin is not connected on either board.
#define PIN_15_OFFSET 9
#define PIN_16_OFFSET 10
#define PIN_17_OFFSET 11
#define PIN_18_OFFSET 12
#define PIN_19_OFFSET 13
// These are *PIN* numbers, not
// GPIO Offset Numbers.
#define PIN_SPI1_SCK (13u)
#define PIN_SPI1_MISO (12u)
#define PIN_SPI1_MOSI (11u)
#define PIN_SPI1_SS0 (10u)
#define PIN_SPI1_SS1 (14u)
#define PIN_SPI1_SS2 (15u)
#define PIN_SPI1_SS3 (16u)
#define SS_PIN_TO_CS_ID(x) \
((x==PIN_SPI1_SS0 ? 0 : \
(x==PIN_SPI1_SS1 ? 1 : \
(x==PIN_SPI1_SS2 ? 2 : \
(x==PIN_SPI1_SS3 ? 3 : \
-1)))))
// These buttons are present only on the Freedom E300 Arty Dev Kit.
#ifdef HAS_BOARD_BUTTONS
#define BUTTON_0_OFFSET 15
#define BUTTON_1_OFFSET 30
#define BUTTON_2_OFFSET 31
#define INT_DEVICE_BUTTON_0 (INT_GPIO_BASE + BUTTON_0_OFFSET)
#define INT_DEVICE_BUTTON_1 (INT_GPIO_BASE + BUTTON_1_OFFSET)
#define INT_DEVICE_BUTTON_2 (INT_GPIO_BASE + BUTTON_2_OFFSET)
#endif
#define HAS_HFXOSC 1
#define HAS_LFROSC_BYPASS 1
#endif /* _SIFIVE_HIFIVE1_H */

7
cpu/fe310/Makefile Normal file
View File

@ -0,0 +1,7 @@
# define the module that is built
MODULE = cpu
# add a list of subdirectories, that should also be built
DIRS = periph nano vendor
include $(RIOTBASE)/Makefile.base

3
cpu/fe310/Makefile.dep Normal file
View File

@ -0,0 +1,3 @@
ifneq (,$(filter periph_rtc,$(USEMODULE)))
USEMODULE += periph_rtt
endif

View File

@ -0,0 +1,2 @@
FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_pm

View File

@ -0,0 +1,12 @@
USEMODULE += newlib_nano
USEMODULE += newlib_syscalls_fe310
USEMODULE += sifive_drivers_fe310
USEMODULE += periph
USEMODULE += periph_pm
CFLAGS += -Wno-pedantic
include $(RIOTMAKE)/arch/riscv.inc.mk

81
cpu/fe310/context_frame.c Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2017 JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu
* @{
*
* @file
* @brief compile-time check of context_switch_frame offsets
*
* @author JP Bonn
* @}
*/
#include "context_frame.h"
#include "thread.h"
#define CHECK_OFFSET(member) \
_Static_assert(offsetof(struct context_switch_frame, member) == member ## _OFFSET, \
"context_switch_frame offset mismatch for offset member");
static void check_context_switch_frame_alignment(void) __attribute__ ((unused));
/**
* @brief Check size and offsets of context_switch_frame
*
* This does nothing at runtime. It is optimized out since it's only
* doing compile-time checks.
*/
static void check_context_switch_frame_alignment(void)
{
_Static_assert(sizeof(struct context_switch_frame) % 16 == 0,
"Stack pointer should be 16 byte aligned");
_Static_assert(sizeof(struct context_switch_frame) == CONTEXT_FRAME_SIZE,
"context_switch_frame size mismatch");
CHECK_OFFSET(pad);
CHECK_OFFSET(pc);
CHECK_OFFSET(s0);
CHECK_OFFSET(s1);
CHECK_OFFSET(s2);
CHECK_OFFSET(s3);
CHECK_OFFSET(s4);
CHECK_OFFSET(s5);
CHECK_OFFSET(s6);
CHECK_OFFSET(s7);
CHECK_OFFSET(s8);
CHECK_OFFSET(s9);
CHECK_OFFSET(s10);
CHECK_OFFSET(s11);
CHECK_OFFSET(ra);
CHECK_OFFSET(tp);
CHECK_OFFSET(t0);
CHECK_OFFSET(t1);
CHECK_OFFSET(t2);
CHECK_OFFSET(t3);
CHECK_OFFSET(t4);
CHECK_OFFSET(t5);
CHECK_OFFSET(t6);
CHECK_OFFSET(a0);
CHECK_OFFSET(a1);
CHECK_OFFSET(a2);
CHECK_OFFSET(a3);
CHECK_OFFSET(a4);
CHECK_OFFSET(a5);
CHECK_OFFSET(a6);
CHECK_OFFSET(a7);
/*
* also check the SP offset in the _frame structure
*/
_Static_assert( offsetof(struct _thread, sp) == SP_OFFSET_IN_THREAD,
"Offset of SP in _thread mismatch");
}

342
cpu/fe310/cpu.c Normal file
View File

@ -0,0 +1,342 @@
/*
* Copyright (C) 2017 Ken Rabold, JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file cpu.c
* @brief Implementation of the CPU initialization for SiFive FE310
*
* @author Ken Rabold
* @}
*/
#include <stdio.h>
#include <errno.h>
#include "thread.h"
#include "irq.h"
#include "sched.h"
#include "thread.h"
#include "irq.h"
#include "cpu.h"
#include "context_frame.h"
#include "periph_cpu.h"
#include "panic.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
/* Default state of mstatus register */
#define MSTATUS_DEFAULT (MSTATUS_MPP | MSTATUS_MPIE)
volatile int __in_isr = 0;
void trap_entry(void);
void thread_start(void);
/* PLIC external ISR function list */
static external_isr_ptr_t _ext_isrs[PLIC_NUM_INTERRUPTS];
/* NULL interrupt handler */
void null_isr(int num)
{
(void) num;
}
/**
* @brief Initialize the CPU, set IRQ priorities, clocks
*/
void cpu_init(void)
{
volatile uint64_t *mtimecmp =
(uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
/* Setup trap handler function */
write_csr(mtvec, &trap_entry);
/* Enable FPU if present */
if (read_csr(misa) & (1 << ('F' - 'A'))) {
write_csr(mstatus, MSTATUS_FS); /* allow FPU instructions without trapping */
write_csr(fcsr, 0); /* initialize rounding mode, undefined at reset */
}
/* Clear all interrupt enables */
write_csr(mie, 0);
/* Initial PLIC external interrupt controller */
PLIC_init(PLIC_CTRL_ADDR, PLIC_NUM_INTERRUPTS, PLIC_NUM_PRIORITIES);
/* Initialize ISR function list */
for (int i = 0; i < PLIC_NUM_INTERRUPTS; i++) {
_ext_isrs[i] = null_isr;
}
/* Set mtimecmp to largest value to avoid spurious timer interrupts */
*mtimecmp = 0xFFFFFFFFFFFFFFFF;
/* Enable SW, timer and external interrupts */
set_csr(mie, MIP_MSIP);
set_csr(mie, MIP_MTIP);
set_csr(mie, MIP_MEIP);
/* Set default state of mstatus */
set_csr(mstatus, MSTATUS_DEFAULT);
}
/**
* @brief Enable all maskable interrupts
*/
unsigned int irq_enable(void)
{
/* Enable all interrupts */
set_csr(mstatus, MSTATUS_MIE);
return read_csr(mstatus);
}
/**
* @brief Disable all maskable interrupts
*/
unsigned int irq_disable(void)
{
unsigned int state = read_csr(mstatus);
/* Disable all interrupts */
clear_csr(mstatus, MSTATUS_MIE);
return state;
}
/**
* @brief Restore the state of the IRQ flags
*/
void irq_restore(unsigned int state)
{
/* Restore all interrupts to given state */
write_csr(mstatus, state);
}
/**
* @brief See if the current context is inside an ISR
*/
int irq_is_in(void)
{
return __in_isr;
}
/**
* @brief Set External ISR callback
*/
void set_external_isr_cb(int intNum, external_isr_ptr_t cbFunc)
{
if ((intNum > 0) && (intNum < PLIC_NUM_INTERRUPTS)) {
_ext_isrs[intNum] = cbFunc;
}
}
/**
* @brief External interrupt handler
*/
void external_isr(void)
{
plic_source intNum = PLIC_claim_interrupt();
if ((intNum > 0) && (intNum < PLIC_NUM_INTERRUPTS)) {
_ext_isrs[intNum]((uint32_t) intNum);
}
PLIC_complete_interrupt(intNum);
}
/**
* @brief Global trap and interrupt handler
*/
void handle_trap(unsigned int mcause)
{
/* Tell RIOT to set sched_context_switch_request instead of
* calling thread_yield(). */
__in_isr = 1;
/* Check for INT or TRAP */
if ((mcause & MCAUSE_INT) == MCAUSE_INT) {
/* Cause is an interrupt - determine type */
switch (mcause & MCAUSE_CAUSE) {
#ifdef MODULE_PERIPH_TIMER
case IRQ_M_TIMER:
/* Handle timer interrupt */
timer_isr();
break;
#endif
case IRQ_M_EXT:
/* Handle external interrupt */
external_isr();
break;
default:
/* Unknown interrupt */
core_panic(PANIC_GENERAL_ERROR, "Unhandled interrupt");
break;
}
}
/* ISR done - no more changes to thread states */
__in_isr = 0;
}
/**
* @brief Noticeable marker marking the beginning of a stack segment
*
* This marker is used e.g. by *thread_start_threading* to identify the
* stacks beginning.
*/
#define STACK_MARKER (0x77777777)
/**
* @brief Initialize a thread's stack
*
* RIOT saves the tasks registers on the stack, not in the task control
* block. thread_stack_init() is responsible for allocating space for
* the registers on the stack and adjusting the stack pointer to account for
* the saved registers.
*
* The stack_start parameter is the bottom of the stack (low address). The
* return value is the top of stack: stack_start + stack_size - space reserved
* for thread context save - space reserved to align stack.
*
* thread_stack_init is called for each thread.
*
* RISCV ABI is here: https://github.com/riscv/riscv-elf-psabi-doc
* From ABI:
* The stack grows downwards and the stack pointer shall be aligned to a
* 128-bit boundary upon procedure entry, except for the RV32E ABI, where it
* need only be aligned to 32 bits. In the standard ABI, the stack pointer
* must remain aligned throughout procedure execution. Non-standard ABI code
* must realign the stack pointer prior to invoking standard ABI procedures.
* The operating system must realign the stack pointer prior to invoking a
* signal handler; hence, POSIX signal handlers need not realign the stack
* pointer. In systems that service interrupts using the interruptee's stack,
* the interrupt service routine must realign the stack pointer if linked
* with any code that uses a non-standard stack-alignment discipline, but
* need not realign the stack pointer if all code adheres to the standard ABI.
*
* @param[in] task_func pointer to the thread's code
* @param[in] arg argument to task_func
* @param[in] stack_start pointer to the start address of the thread
* @param[in] stack_size the maximum size of the stack
*
* @return pointer to the new top of the stack (128bit aligned)
*
*/
char *thread_stack_init(thread_task_func_t task_func,
void *arg,
void *stack_start,
int stack_size)
{
struct context_switch_frame *sf;
uint32_t *reg;
uint32_t *stk_top;
/* calculate the top of the stack */
stk_top = (uint32_t *)((uintptr_t)stack_start + stack_size);
/* Put a marker at the top of the stack. This is used by
* thread_stack_print to determine where to stop dumping the
* stack.
*/
stk_top--;
*stk_top = STACK_MARKER;
/* per ABI align stack pointer to 16 byte boundary. */
stk_top = (uint32_t *)(((uint32_t)stk_top) & ~((uint32_t)0xf));
/* reserve space for the stack frame. */
stk_top = (uint32_t *)((uint8_t *) stk_top - sizeof(*sf));
/* populate the stack frame with default values for starting the thread. */
sf = (struct context_switch_frame *) stk_top;
/* a7 is register with highest memory address in frame */
reg = &sf->a7;
while (reg != &sf->pc) {
*reg-- = 0;
}
sf->pc = (uint32_t) task_func;
sf->a0 = (uint32_t) arg;
/* if the thread exits go to sched_task_exit() */
sf->ra = (uint32_t) sched_task_exit;
return (char *) stk_top;
}
void thread_print_stack(void)
{
int count = 0;
uint32_t *sp = (uint32_t *) sched_active_thread->sp;
printf("printing the current stack of thread %" PRIkernel_pid "\n",
thread_getpid());
#ifdef DEVELHELP
printf("thread name: %s\n", sched_active_thread->name);
printf("stack start: 0x%08x\n", (unsigned int)(sched_active_thread->stack_start));
printf("stack end : 0x%08x\n", (unsigned int)(sched_active_thread->stack_start + sched_active_thread->stack_size));
#endif
printf(" address: data:\n");
do {
printf(" 0x%08x: 0x%08x\n", (unsigned int) sp, (unsigned int) *sp);
sp++;
count++;
} while (*sp != STACK_MARKER);
printf("current stack size: %i words\n", count);
}
int thread_isr_stack_usage(void)
{
return 0;
}
void *thread_isr_stack_pointer(void)
{
return NULL;
}
void *thread_isr_stack_start(void)
{
return NULL;
}
/**
* @brief Start or resume threading by loading a threads initial information
* from the stack.
*
* This is called is two situations: 1) after the initial main and idle threads
* have been created and 2) when a thread exits.
*
* sched_active_thread is not valid when cpu_switch_context_exit() is
* called. sched_run() must be called to determine the next valid thread.
* This is exploited in the context switch code.
*/
void cpu_switch_context_exit(void)
{
/* enable interrupts */
irq_enable();
/* start the thread */
thread_yield();
UNREACHABLE();
}
void thread_yield_higher(void)
{
/* Use SW intr to schedule context switch */
CLINT_REG(CLINT_MSIP) = 1;
}

View File

@ -0,0 +1,135 @@
/*
* Copyright (C) 2017 JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file
* @brief Thread context frame stored on stack.
*
* @author JP Bonn
*/
#ifndef CONTEXT_FRAME_H
#define CONTEXT_FRAME_H
#if !defined(__ASSEMBLER__)
#include <stdint.h>
#include <assert.h>
#endif /* __ASSEMBLER__ */
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(__ASSEMBLER__)
/**
* @brief Stores the registers and PC for a context switch.
*
* This also defines context_switch_frame offsets for assembly language. The
* structure is sized to maintain 16 byte stack alignment per the ABI.
* https://github.com/riscv/riscv-elf-psabi-doc
*
*/
struct context_switch_frame {
uint32_t pad[2]; /**< padding to maintain 16 byte alignment */
uint32_t pc; /**< program counter */
/* Callee saved registers */
uint32_t s0; /**< s0 register */
uint32_t s1; /**< s1 register */
uint32_t s2; /**< s2 register */
uint32_t s3; /**< s3 register */
uint32_t s4; /**< s4 register */
uint32_t s5; /**< s5 register */
uint32_t s6; /**< s6 register */
uint32_t s7; /**< s7 register */
uint32_t s8; /**< s8 register */
uint32_t s9; /**< s9 register */
uint32_t s10; /**< s10 register */
uint32_t s11; /**< s11 register */
/* Caller saved registers */
uint32_t ra; /**< ra register */
uint32_t tp; /**< tp register */
uint32_t t0; /**< t0 register */
uint32_t t1; /**< t1 register */
uint32_t t2; /**< t2 register */
uint32_t t3; /**< t3 register */
uint32_t t4; /**< t4 register */
uint32_t t5; /**< t5 register */
uint32_t t6; /**< t6 register */
uint32_t a0; /**< a0 register */
uint32_t a1; /**< a1 register */
uint32_t a2; /**< a2 register */
uint32_t a3; /**< a3 register */
uint32_t a4; /**< a4 register */
uint32_t a5; /**< a5 register */
uint32_t a6; /**< a6 register */
uint32_t a7; /**< a7 register */
};
#endif /* __ASSEMBLER__ */
/**
* @name Register offsets
* @{
*/
/* These values are checked for correctness in context_frame.c */
#define pad_OFFSET 0
#define pc_OFFSET 8
#define s0_OFFSET 12
#define s1_OFFSET 16
#define s2_OFFSET 20
#define s3_OFFSET 24
#define s4_OFFSET 28
#define s5_OFFSET 32
#define s6_OFFSET 36
#define s7_OFFSET 40
#define s8_OFFSET 44
#define s9_OFFSET 48
#define s10_OFFSET 52
#define s11_OFFSET 56
#define ra_OFFSET 60
#define tp_OFFSET 64
#define t0_OFFSET 68
#define t1_OFFSET 72
#define t2_OFFSET 76
#define t3_OFFSET 80
#define t4_OFFSET 84
#define t5_OFFSET 88
#define t6_OFFSET 92
#define a0_OFFSET 96
#define a1_OFFSET 100
#define a2_OFFSET 104
#define a3_OFFSET 108
#define a4_OFFSET 112
#define a5_OFFSET 116
#define a6_OFFSET 120
#define a7_OFFSET 124
/** @} */
/**
* @brief Size of context switch frame
*/
#define CONTEXT_FRAME_SIZE (a7_OFFSET + 4)
/**
* @brief Offset of stack pointer in struct _thread
*/
#define SP_OFFSET_IN_THREAD 0
#ifdef __cplusplus
}
#endif
#endif /* CONTEXT_FRAME_H */
/** @} */

57
cpu/fe310/include/cpu.h Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup cpu_fe310 SiFive FE310
* @ingroup cpu
* @brief Common implementations and headers for RISC-V
* @{
*
* @file
* @brief Basic definitions for the RISC-V common module
*
* When ever you want to do something hardware related, that is accessing MCUs
* registers, just include this file. It will then make sure that the MCU
* specific headers are included.
*
* @author Ken Rabold
*/
#ifndef CPU_H
#define CPU_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialization of the CPU
*/
void cpu_init(void);
/**
* @brief Print the last instruction's address
*
* @todo: Not supported
*/
static inline void cpu_print_last_instruction(void)
{
/* This function must exist else RIOT won't compile */
}
/**
* @brief Initialization of the Newlib-nano stub
*/
void nanostubs_init(void);
#ifdef __cplusplus
}
#endif
#endif /* CPU_H */
/** @} */

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file
* @brief CPU specific configuration options
*
* @author Ken Rabold
*/
#ifndef CPU_CONF_H
#define CPU_CONF_H
/**
* @name Configuration of default stack sizes
* @{
*/
#ifndef THREAD_EXTRA_STACKSIZE_PRINTF
#define THREAD_EXTRA_STACKSIZE_PRINTF (256)
#endif
#ifndef THREAD_STACKSIZE_DEFAULT
#define THREAD_STACKSIZE_DEFAULT (1024)
#endif
#ifndef THREAD_STACKSIZE_IDLE
#define THREAD_STACKSIZE_IDLE (256)
#endif
/** @} */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* CPU_CONF_H */
/** @} */

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2017 JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file
* @brief Functions to read CPU cycle counter
*
* @author JP Bonn
*/
#ifndef CPUCYCLE_H
#define CPUCYCLE_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Returns a count of the number of clock cycles executed by the
* processor core on which the hart is running from an arbitrary
* start time in the past.
*/
uint64_t get_cycle_count(void);
#ifdef __cplusplus
}
#endif
#endif /* CPUCYCLE_H */
/** @} */

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file
* @brief CPU specific definitions for internal peripheral handling
*
* @author Ken Rabold
*/
#ifndef PERIPH_CPU_H
#define PERIPH_CPU_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Length of the CPU_ID in octets
*/
#define CPUID_LEN (12U)
/**
* @brief Timer ISR
*/
void timer_isr(void);
/**
* @brief External ISR callback
*/
typedef void (*external_isr_ptr_t)(int intNum);
/**
* @brief Set External ISR callback
*/
void set_external_isr_cb(int intNum, external_isr_ptr_t cbFunc);
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_H */
/** @} */

206
cpu/fe310/include/vendor/LICENSE vendored Normal file
View File

@ -0,0 +1,206 @@
This software, except as otherwise noted in subrepositories,
is licensed under the Apache 2 license, quoted below.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 SiFive, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

88
cpu/fe310/include/vendor/aon.h vendored Normal file
View File

@ -0,0 +1,88 @@
// See LICENSE for license details.
#ifndef _SIFIVE_AON_H
#define _SIFIVE_AON_H
/* Register offsets */
#define AON_WDOGCFG 0x000
#define AON_WDOGCOUNT 0x008
#define AON_WDOGS 0x010
#define AON_WDOGFEED 0x018
#define AON_WDOGKEY 0x01C
#define AON_WDOGCMP 0x020
#define AON_RTCCFG 0x040
#define AON_RTCLO 0x048
#define AON_RTCHI 0x04C
#define AON_RTCS 0x050
#define AON_RTCCMP 0x060
#define AON_BACKUP0 0x080
#define AON_BACKUP1 0x084
#define AON_BACKUP2 0x088
#define AON_BACKUP3 0x08C
#define AON_BACKUP4 0x090
#define AON_BACKUP5 0x094
#define AON_BACKUP6 0x098
#define AON_BACKUP7 0x09C
#define AON_BACKUP8 0x0A0
#define AON_BACKUP9 0x0A4
#define AON_BACKUP10 0x0A8
#define AON_BACKUP11 0x0AC
#define AON_BACKUP12 0x0B0
#define AON_BACKUP13 0x0B4
#define AON_BACKUP14 0x0B8
#define AON_BACKUP15 0x0BC
#define AON_PMUWAKEUPI0 0x100
#define AON_PMUWAKEUPI1 0x104
#define AON_PMUWAKEUPI2 0x108
#define AON_PMUWAKEUPI3 0x10C
#define AON_PMUWAKEUPI4 0x110
#define AON_PMUWAKEUPI5 0x114
#define AON_PMUWAKEUPI6 0x118
#define AON_PMUWAKEUPI7 0x11C
#define AON_PMUSLEEPI0 0x120
#define AON_PMUSLEEPI1 0x124
#define AON_PMUSLEEPI2 0x128
#define AON_PMUSLEEPI3 0x12C
#define AON_PMUSLEEPI4 0x130
#define AON_PMUSLEEPI5 0x134
#define AON_PMUSLEEPI6 0x138
#define AON_PMUSLEEPI7 0x13C
#define AON_PMUIE 0x140
#define AON_PMUCAUSE 0x144
#define AON_PMUSLEEP 0x148
#define AON_PMUKEY 0x14C
#define AON_LFROSC 0x070
/* Constants */
#define AON_WDOGKEY_VALUE 0x51F15E
#define AON_WDOGFEED_VALUE 0xD09F00D
#define AON_WDOGCFG_SCALE 0x0000000F
#define AON_WDOGCFG_RSTEN 0x00000100
#define AON_WDOGCFG_ZEROCMP 0x00000200
#define AON_WDOGCFG_ENALWAYS 0x00001000
#define AON_WDOGCFG_ENCOREAWAKE 0x00002000
#define AON_WDOGCFG_CMPIP 0x10000000
#define AON_RTCCFG_SCALE 0x0000000F
#define AON_RTCCFG_ENALWAYS 0x00001000
#define AON_RTCCFG_CMPIP 0x10000000
#define AON_WAKEUPCAUSE_RESET 0x00
#define AON_WAKEUPCAUSE_RTC 0x01
#define AON_WAKEUPCAUSE_DWAKEUP 0x02
#define AON_WAKEUPCAUSE_AWAKEUP 0x03
#define AON_RESETCAUSE_POWERON 0x0000
#define AON_RESETCAUSE_EXTERNAL 0x0100
#define AON_RESETCAUSE_WATCHDOG 0x0200
#define AON_PMUCAUSE_WAKEUPCAUSE 0x00FF
#define AON_PMUCAUSE_RESETCAUSE 0xFF00
#endif /* _SIFIVE_AON_H */

14
cpu/fe310/include/vendor/clint.h vendored Normal file
View File

@ -0,0 +1,14 @@
// See LICENSE for license details
#ifndef _SIFIVE_CLINT_H
#define _SIFIVE_CLINT_H
#define CLINT_MSIP 0x0000
#define CLINT_MSIP_size 0x4
#define CLINT_MTIMECMP 0x4000
#define CLINT_MTIMECMP_size 0x8
#define CLINT_MTIME 0xBFF8
#define CLINT_MTIME_size 0x8
#endif /* _SIFIVE_CLINT_H */

1313
cpu/fe310/include/vendor/encoding.h vendored Normal file

File diff suppressed because it is too large Load Diff

24
cpu/fe310/include/vendor/gpio.h vendored Normal file
View File

@ -0,0 +1,24 @@
// See LICENSE for license details.
#ifndef _SIFIVE_GPIO_H
#define _SIFIVE_GPIO_H
#define GPIO_INPUT_VAL (0x00)
#define GPIO_INPUT_EN (0x04)
#define GPIO_OUTPUT_EN (0x08)
#define GPIO_OUTPUT_VAL (0x0C)
#define GPIO_PULLUP_EN (0x10)
#define GPIO_DRIVE (0x14)
#define GPIO_RISE_IE (0x18)
#define GPIO_RISE_IP (0x1C)
#define GPIO_FALL_IE (0x20)
#define GPIO_FALL_IP (0x24)
#define GPIO_HIGH_IE (0x28)
#define GPIO_HIGH_IP (0x2C)
#define GPIO_LOW_IE (0x30)
#define GPIO_LOW_IP (0x34)
#define GPIO_IOF_EN (0x38)
#define GPIO_IOF_SEL (0x3C)
#define GPIO_OUTPUT_XOR (0x40)
#endif /* _SIFIVE_GPIO_H */

23
cpu/fe310/include/vendor/otp.h vendored Normal file
View File

@ -0,0 +1,23 @@
// See LICENSE for license details.
#ifndef _SIFIVE_OTP_H
#define _SIFIVE_OTP_H
/* Register offsets */
#define OTP_LOCK 0x00
#define OTP_CK 0x04
#define OTP_OE 0x08
#define OTP_SEL 0x0C
#define OTP_WE 0x10
#define OTP_MR 0x14
#define OTP_MRR 0x18
#define OTP_MPP 0x1C
#define OTP_VRREN 0x20
#define OTP_VPPEN 0x24
#define OTP_A 0x28
#define OTP_D 0x2C
#define OTP_Q 0x30
#define OTP_READ_TIMINGS 0x34
#endif

129
cpu/fe310/include/vendor/platform.h vendored Normal file
View File

@ -0,0 +1,129 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PLATFORM_H
#define _SIFIVE_PLATFORM_H
// Some things missing from the official encoding.h
#define MCAUSE_INT 0x80000000
#define MCAUSE_CAUSE 0x7FFFFFFF
#include "vendor/aon.h"
#include "vendor/clint.h"
#include "vendor/gpio.h"
#include "vendor/otp.h"
#include "vendor/plic.h"
#include "vendor/prci.h"
#include "vendor/pwm.h"
#include "vendor/spi.h"
#include "vendor/uart.h"
/****************************************************************************
* Platform definitions
*****************************************************************************/
// Memory map
#define MASKROM_MEM_ADDR (0x00001000)
#define TRAPVEC_TABLE_CTRL_ADDR (0x00001010)
#define OTP_MEM_ADDR (0x00020000)
#define CLINT_CTRL_ADDR (0x02000000)
#define PLIC_CTRL_ADDR (0x0C000000)
#define AON_CTRL_ADDR (0x10000000)
#define PRCI_CTRL_ADDR (0x10008000)
#define OTP_CTRL_ADDR (0x10010000)
#define GPIO_CTRL_ADDR (0x10012000)
#define UART0_CTRL_ADDR (0x10013000)
#define SPI0_CTRL_ADDR (0x10014000)
#define PWM0_CTRL_ADDR (0x10015000)
#define UART1_CTRL_ADDR (0x10023000)
#define SPI1_CTRL_ADDR (0x10024000)
#define PWM1_CTRL_ADDR (0x10025000)
#define SPI2_CTRL_ADDR (0x10034000)
#define PWM2_CTRL_ADDR (0x10035000)
#define SPI0_MEM_ADDR (0x20000000)
#define MEM_CTRL_ADDR (0x80000000)
// IOF masks
#define IOF0_SPI1_MASK (0x000007FC)
#define SPI11_NUM_SS (4)
#define IOF_SPI1_SS0 (2u)
#define IOF_SPI1_SS1 (8u)
#define IOF_SPI1_SS2 (9u)
#define IOF_SPI1_SS3 (10u)
#define IOF_SPI1_MOSI (3u)
#define IOF_SPI1_MISO (4u)
#define IOF_SPI1_SCK (5u)
#define IOF_SPI1_DQ0 (3u)
#define IOF_SPI1_DQ1 (4u)
#define IOF_SPI1_DQ2 (6u)
#define IOF_SPI1_DQ3 (7u)
#define IOF0_SPI2_MASK (0xFC000000)
#define SPI2_NUM_SS (1)
#define IOF_SPI2_SS0 (26u)
#define IOF_SPI2_MOSI (27u)
#define IOF_SPI2_MISO (28u)
#define IOF_SPI2_SCK (29u)
#define IOF_SPI2_DQ0 (27u)
#define IOF_SPI2_DQ1 (28u)
#define IOF_SPI2_DQ2 (30u)
#define IOF_SPI2_DQ3 (31u)
//#define IOF0_I2C_MASK (0x00003000)
#define IOF0_UART0_MASK (0x00030000)
#define IOF_UART0_RX (16u)
#define IOF_UART0_TX (17u)
#define IOF0_UART1_MASK (0x03000000)
#define IOF_UART1_RX (24u)
#define IOF_UART1_TX (25u)
#define IOF1_PWM0_MASK (0x0000000F)
#define IOF1_PWM1_MASK (0x00780000)
#define IOF1_PWM2_MASK (0x00003C00)
// Interrupt numbers
#define INT_RESERVED 0
#define INT_WDOGCMP 1
#define INT_RTCCMP 2
#define INT_UART0_BASE 3
#define INT_UART1_BASE 4
#define INT_SPI0_BASE 5
#define INT_SPI1_BASE 6
#define INT_SPI2_BASE 7
#define INT_GPIO_BASE 8
#define INT_PWM0_BASE 40
#define INT_PWM1_BASE 44
#define INT_PWM2_BASE 48
// Helper functions
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
#define AON_REG(offset) _REG32(AON_CTRL_ADDR, offset)
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
#define OTP_REG(offset) _REG32(OTP_CTRL_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
#define PRCI_REG(offset) _REG32(PRCI_CTRL_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset)
#define PWM1_REG(offset) _REG32(PWM1_CTRL_ADDR, offset)
#define PWM2_REG(offset) _REG32(PWM2_CTRL_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset)
#define SPI1_REG(offset) _REG32(SPI1_CTRL_ADDR, offset)
#define SPI2_REG(offset) _REG32(SPI2_CTRL_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset)
#define UART1_REG(offset) _REG32(UART1_CTRL_ADDR, offset)
// Misc
#define NUM_GPIO 32
#define PLIC_NUM_INTERRUPTS 52
#define PLIC_NUM_PRIORITIES 7
#define RTC_FREQ 32768
#endif /* _SIFIVE_PLATFORM_H */

30
cpu/fe310/include/vendor/plic.h vendored Normal file
View File

@ -0,0 +1,30 @@
// See LICENSE for license details.
#ifndef PLIC_H
#define PLIC_H
// 32 bits per source
#define PLIC_PRIORITY_OFFSET (0x0000)
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
// 1 bit per source (1 address)
#define PLIC_PENDING_OFFSET (0x1000)
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
//0x80 per target
#define PLIC_ENABLE_OFFSET (0x2000)
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
#define PLIC_THRESHOLD_OFFSET (0x200000)
#define PLIC_CLAIM_OFFSET (0x200004)
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
#define PLIC_MAX_SOURCE 1023
#define PLIC_SOURCE_MASK 0x3FF
#define PLIC_MAX_TARGET 15871
#define PLIC_TARGET_MASK 0x3FFF
#endif /* PLIC_H */

34
cpu/fe310/include/vendor/plic_driver.h vendored Normal file
View File

@ -0,0 +1,34 @@
// See LICENSE file for licence details
#ifndef PLIC_DRIVER_H
#define PLIC_DRIVER_H
typedef uint32_t plic_source;
typedef uint32_t plic_priority;
typedef uint32_t plic_threshold;
void PLIC_init (
uintptr_t base_addr,
uint32_t num_sources,
uint32_t num_priorities
);
void PLIC_set_threshold (plic_threshold threshold);
void PLIC_enable_interrupt (plic_source source);
void PLIC_disable_interrupt (plic_source source);
void PLIC_set_priority (
plic_source source,
plic_priority priority);
plic_source PLIC_claim_interrupt(void);
void PLIC_complete_interrupt(plic_source source);
#endif

56
cpu/fe310/include/vendor/prci.h vendored Normal file
View File

@ -0,0 +1,56 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PRCI_H
#define _SIFIVE_PRCI_H
/* Register offsets */
#define PRCI_HFROSCCFG (0x0000)
#define PRCI_HFXOSCCFG (0x0004)
#define PRCI_PLLCFG (0x0008)
#define PRCI_PLLDIV (0x000C)
#define PRCI_PROCMONCFG (0x00F0)
/* Fields */
#define ROSC_DIV(x) (((x) & 0x2F) << 0 )
#define ROSC_TRIM(x) (((x) & 0x1F) << 16)
#define ROSC_EN(x) (((x) & 0x1 ) << 30)
#define ROSC_RDY(x) (((x) & 0x1 ) << 31)
#define XOSC_EN(x) (((x) & 0x1) << 30)
#define XOSC_RDY(x) (((x) & 0x1) << 31)
#define PLL_R(x) (((x) & 0x7) << 0)
// single reserved bit for F LSB.
#define PLL_F(x) (((x) & 0x3F) << 4)
#define PLL_Q(x) (((x) & 0x3) << 10)
#define PLL_SEL(x) (((x) & 0x1) << 16)
#define PLL_REFSEL(x) (((x) & 0x1) << 17)
#define PLL_BYPASS(x) (((x) & 0x1) << 18)
#define PLL_LOCK(x) (((x) & 0x1) << 31)
#define PLL_R_default 0x1
#define PLL_F_default 0x1F
#define PLL_Q_default 0x3
#define PLL_REFSEL_HFROSC 0x0
#define PLL_REFSEL_HFXOSC 0x1
#define PLL_SEL_HFROSC 0x0
#define PLL_SEL_PLL 0x1
#define PLL_FINAL_DIV(x) (((x) & 0x3F) << 0)
#define PLL_FINAL_DIV_BY_1(x) (((x) & 0x1 ) << 8)
#define PROCMON_DIV(x) (((x) & 0x1F) << 0)
#define PROCMON_TRIM(x) (((x) & 0x1F) << 8)
#define PROCMON_EN(x) (((x) & 0x1) << 16)
#define PROCMON_SEL(x) (((x) & 0x3) << 24)
#define PROCMON_NT_EN(x) (((x) & 0x1) << 28)
#define PROCMON_SEL_HFCLK 0
#define PROCMON_SEL_HFXOSCIN 1
#define PROCMON_SEL_PLLOUTDIV 2
#define PROCMON_SEL_PROCMON 3
#endif // _SIFIVE_PRCI_H

79
cpu/fe310/include/vendor/prci_driver.h vendored Normal file
View File

@ -0,0 +1,79 @@
// See LICENSE file for license details
#ifndef _PRCI_DRIVER_H_
#define _PRCI_DRIVER_H_
typedef enum prci_freq_target {
PRCI_FREQ_OVERSHOOT,
PRCI_FREQ_CLOSEST,
PRCI_FREQ_UNDERSHOOT
} PRCI_freq_target;
/* Measure and return the approximate frequency of the
* CPU, as given by measuring the mcycle counter against
* the mtime ticks.
*/
uint32_t PRCI_measure_mcycle_freq(uint32_t mtime_ticks, uint32_t mtime_freq);
/* Safely switch over to the HFROSC using the given div
* and trim settings.
*/
void PRCI_use_hfrosc(int div, int trim);
/* Safely switch over to the 16MHz HFXOSC,
* applying the finaldiv clock divider (1 is the lowest
* legal value).
*/
void PRCI_use_hfxosc(uint32_t finaldiv);
/* Safely switch over to the PLL using the given
* settings.
*
* Note that not all combinations of the inputs are actually
* legal, and this function does not check for their
* legality ("safely" means that this function won't turn off
* or glitch the clock the CPU is actually running off, but
* doesn't protect against you making it too fast or slow.)
*/
void PRCI_use_pll(int refsel, int bypass,
int r, int f, int q, int finaldiv,
int hfroscdiv, int hfrosctrim);
/* Use the default clocks configured at reset.
* This is ~16Mhz HFROSC and turns off the LFROSC
* (on the current FE310 Dev Platforms, an external LFROSC is
* used as it is more power efficient).
*/
void PRCI_use_default_clocks(void);
/* Use the external bypass crystal clock
*/
void PRCI_use_bypass_clock(void);
/* This routine will adjust the HFROSC trim
* while using HFROSC as the clock source,
* measure the resulting frequency, then
* use it as the PLL clock source,
* in an attempt to get over, under, or close to the
* requested frequency. It returns the actual measured
* frequency.
*
* Note that the requested frequency must be within the
* range supported by the PLL so not all values are
* achievable with this function, and not all
* are guaranteed to actually work. The PLL
* is rated higher than the hardware.
*
* There is no check on the desired f_cpu frequency, it
* is up to the user to specify something reasonable.
*/
uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target);
#endif

37
cpu/fe310/include/vendor/pwm.h vendored Normal file
View File

@ -0,0 +1,37 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PWM_H
#define _SIFIVE_PWM_H
/* Register offsets */
#define PWM_CFG 0x00
#define PWM_COUNT 0x08
#define PWM_S 0x10
#define PWM_CMP0 0x20
#define PWM_CMP1 0x24
#define PWM_CMP2 0x28
#define PWM_CMP3 0x2C
/* Constants */
#define PWM_CFG_SCALE 0x0000000F
#define PWM_CFG_STICKY 0x00000100
#define PWM_CFG_ZEROCMP 0x00000200
#define PWM_CFG_DEGLITCH 0x00000400
#define PWM_CFG_ENALWAYS 0x00001000
#define PWM_CFG_ONESHOT 0x00002000
#define PWM_CFG_CMP0CENTER 0x00010000
#define PWM_CFG_CMP1CENTER 0x00020000
#define PWM_CFG_CMP2CENTER 0x00040000
#define PWM_CFG_CMP3CENTER 0x00080000
#define PWM_CFG_CMP0GANG 0x01000000
#define PWM_CFG_CMP1GANG 0x02000000
#define PWM_CFG_CMP2GANG 0x04000000
#define PWM_CFG_CMP3GANG 0x08000000
#define PWM_CFG_CMP0IP 0x10000000
#define PWM_CFG_CMP1IP 0x20000000
#define PWM_CFG_CMP2IP 0x40000000
#define PWM_CFG_CMP3IP 0x80000000
#endif /* _SIFIVE_PWM_H */

80
cpu/fe310/include/vendor/spi.h vendored Normal file
View File

@ -0,0 +1,80 @@
// See LICENSE for license details.
#ifndef _SIFIVE_SPI_H
#define _SIFIVE_SPI_H
/* Register offsets */
#define SPI_REG_SCKDIV 0x00
#define SPI_REG_SCKMODE 0x04
#define SPI_REG_CSID 0x10
#define SPI_REG_CSDEF 0x14
#define SPI_REG_CSMODE 0x18
#define SPI_REG_DCSSCK 0x28
#define SPI_REG_DSCKCS 0x2a
#define SPI_REG_DINTERCS 0x2c
#define SPI_REG_DINTERXFR 0x2e
#define SPI_REG_FMT 0x40
#define SPI_REG_TXFIFO 0x48
#define SPI_REG_RXFIFO 0x4c
#define SPI_REG_TXCTRL 0x50
#define SPI_REG_RXCTRL 0x54
#define SPI_REG_FCTRL 0x60
#define SPI_REG_FFMT 0x64
#define SPI_REG_IE 0x70
#define SPI_REG_IP 0x74
/* Fields */
#define SPI_SCK_POL 0x1
#define SPI_SCK_PHA 0x2
#define SPI_FMT_PROTO(x) ((x) & 0x3)
#define SPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)
#define SPI_FMT_DIR(x) (((x) & 0x1) << 3)
#define SPI_FMT_LEN(x) (((x) & 0xf) << 16)
/* TXCTRL register */
#define SPI_TXWM(x) ((x) & 0xffff)
/* RXCTRL register */
#define SPI_RXWM(x) ((x) & 0xffff)
#define SPI_IP_TXWM 0x1
#define SPI_IP_RXWM 0x2
#define SPI_FCTRL_EN 0x1
#define SPI_INSN_CMD_EN 0x1
#define SPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1)
#define SPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4)
#define SPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8)
#define SPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10)
#define SPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12)
#define SPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16)
#define SPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24)
#define SPI_TXFIFO_FULL (1 << 31)
#define SPI_RXFIFO_EMPTY (1 << 31)
/* Values */
#define SPI_CSMODE_AUTO 0
#define SPI_CSMODE_HOLD 2
#define SPI_CSMODE_OFF 3
#define SPI_DIR_RX 0
#define SPI_DIR_TX 1
#define SPI_PROTO_S 0
#define SPI_PROTO_D 1
#define SPI_PROTO_Q 2
#define SPI_ENDIAN_MSB 0
#define SPI_ENDIAN_LSB 1
#endif /* _SIFIVE_SPI_H */

31
cpu/fe310/include/vendor/uart.h vendored Normal file
View File

@ -0,0 +1,31 @@
// See LICENSE for license details.
#ifndef _SIFIVE_UART_H
#define _SIFIVE_UART_H
/* Register offsets */
#define UART_REG_TXFIFO 0x00
#define UART_REG_RXFIFO 0x04
#define UART_REG_TXCTRL 0x08
#define UART_REG_RXCTRL 0x0c
#define UART_REG_IE 0x10
#define UART_REG_IP 0x14
#define UART_REG_DIV 0x18
/* TXFIFO register */
#define UART_TXFIFO_FULL (1 << 31)
#define UART_RXFIFO_EMPTY (1 << 31)
/* TXCTRL register */
#define UART_TXEN 0x1
#define UART_TXWM(x) (((x) & 0xffff) << 16)
/* RXCTRL register */
#define UART_RXEN 0x1
#define UART_RXWM(x) (((x) & 0xffff) << 16)
/* IP register */
#define UART_IP_TXWM 0x1
#define UART_IP_RXWM 0x2
#endif /* _SIFIVE_UART_H */

151
cpu/fe310/intr.S Normal file
View File

@ -0,0 +1,151 @@
/*
* Copyright (C) 2017 JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include "vendor/encoding.h"
#include "context_frame.h"
/* from platform.h TODO:fix this hard code.... */
CLINT_CTRL_ADDR = 0x02000000
.section .text.entry
.align 2
.global trap_entry
trap_entry:
/*
* Save all regs on the currently active stack.
* This coule be the active thread's stack,
* or if no thread is active, it is saved on ISR stack
* (if initial startup) or on the deactivated threads
* stack (in the case of thread exit). In the latter
* two cases the stack is just abandoned.
*/
addi sp, sp, -CONTEXT_FRAME_SIZE
sw s0, s0_OFFSET(sp)
sw s1, s1_OFFSET(sp)
sw s2, s2_OFFSET(sp)
sw s3, s3_OFFSET(sp)
sw s4, s4_OFFSET(sp)
sw s5, s5_OFFSET(sp)
sw s6, s6_OFFSET(sp)
sw s7, s7_OFFSET(sp)
sw s8, s8_OFFSET(sp)
sw s9, s9_OFFSET(sp)
sw s10, s10_OFFSET(sp)
sw s11, s11_OFFSET(sp)
sw ra, ra_OFFSET(sp)
sw tp, tp_OFFSET(sp)
sw t0, t0_OFFSET(sp)
sw t1, t1_OFFSET(sp)
sw t2, t2_OFFSET(sp)
sw t3, t3_OFFSET(sp)
sw t4, t4_OFFSET(sp)
sw t5, t5_OFFSET(sp)
sw t6, t6_OFFSET(sp)
sw a0, a0_OFFSET(sp)
sw a1, a1_OFFSET(sp)
sw a2, a2_OFFSET(sp)
sw a3, a3_OFFSET(sp)
sw a4, a4_OFFSET(sp)
sw a5, a5_OFFSET(sp)
sw a6, a6_OFFSET(sp)
sw a7, a7_OFFSET(sp)
/* Get the interrupt cause */
csrr a0, mcause
/* Save active thread stack pointer in a callee save register */
mv s1, sp
/* Switch to ISR stack. Interrupts are not nested so use fixed
* starting address and just abandon stack when finished. */
la sp, _sp
addi sp, sp, -4
/* Is it a software interrupt? */
li t0, 0x80000003
beq a0, t0, context_switch
/* Call handle_trap with MCAUSE register value as arg */
jal handle_trap
/* See if a context switch was requested by the ISR */
lw a0, sched_context_switch_request
bnez a0, context_switch
/* Restore active thread stack pointer */
mv sp, s1
/* Restore remaining registers */
trap_exit:
lw s0, s0_OFFSET(sp)
lw s1, s1_OFFSET(sp)
lw s2, s2_OFFSET(sp)
lw s3, s3_OFFSET(sp)
lw s4, s4_OFFSET(sp)
lw s5, s5_OFFSET(sp)
lw s6, s6_OFFSET(sp)
lw s7, s7_OFFSET(sp)
lw s8, s8_OFFSET(sp)
lw s9, s9_OFFSET(sp)
lw s10, s10_OFFSET(sp)
lw s11, s11_OFFSET(sp)
lw ra, ra_OFFSET(sp)
lw tp, tp_OFFSET(sp)
lw t0, t0_OFFSET(sp)
lw t1, t1_OFFSET(sp)
lw t2, t2_OFFSET(sp)
lw t3, t3_OFFSET(sp)
lw t4, t4_OFFSET(sp)
lw t5, t5_OFFSET(sp)
lw t6, t6_OFFSET(sp)
lw a0, a0_OFFSET(sp)
lw a1, a1_OFFSET(sp)
lw a2, a2_OFFSET(sp)
lw a3, a3_OFFSET(sp)
lw a4, a4_OFFSET(sp)
lw a5, a5_OFFSET(sp)
lw a6, a6_OFFSET(sp)
lw a7, a7_OFFSET(sp)
addi sp, sp, CONTEXT_FRAME_SIZE
mret
context_switch:
/* clear the software interrupt */
li t0, CLINT_CTRL_ADDR
sw zero, (t0)
/* save the active thread's PC prior to interrupt on the stack */
csrr a0, mepc
sw a0, pc_OFFSET(s1)
/* get the active thread - it may be 0 if none currently active */
lw t0, sched_active_thread
/* was there a previously running thread? */
beqz t0, no_sp_save
/* if so, save the thread's SP in the _thread structure */
sw s1,SP_OFFSET_IN_THREAD(t0)
no_sp_save:
/* all current thread state is saved - schedule a new thread */
call sched_run
lw tp, sched_active_thread
/* set the threads SP from the newly scheduled thread
* and abandon ISR stack. */
lw sp, SP_OFFSET_IN_THREAD(tp)
/* restore the PC */
lw a0, pc_OFFSET(sp)
csrw mepc, a0
j trap_exit

View File

@ -0,0 +1,182 @@
/*
* Copyright (C) 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @addtogroup cpu_fe310
* @{
*
* @file
* @brief Memory definitions for the SiFive FE310
*
* @author Ken Rabold
*
* @}
*/
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 1K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash :flash
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >flash AT>flash :flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >flash AT>flash :flash
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
} >flash AT>flash :flash
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >flash AT>flash :flash
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >flash AT>flash :flash
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >flash AT>flash :flash
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >flash AT>flash :flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >flash AT>flash :flash
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >flash AT>flash :flash
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>flash :ram_init
.data :
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
PROVIDE( _heap_start = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram :ram
}

3
cpu/fe310/nano/Makefile Normal file
View File

@ -0,0 +1,3 @@
MODULE = newlib_syscalls_fe310
include $(RIOTBASE)/Makefile.base

177
cpu/fe310/nano/nanostubs.c Normal file
View File

@ -0,0 +1,177 @@
/*
* Copyright (C) 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file nanostubs.c
* @brief Implementation of the Newlib-nano for SiFive FE310
*
* @author Ken Rabold
* @}
*/
#include <reent.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include "sched.h"
#include "thread.h"
#include "irq.h"
#include "cpu.h"
#include "uart_stdio.h"
extern char _heap_start; /* Heap markers from fe310.ld file */
extern char _heap_end;
char *heap_top = &_heap_start + 4;
/**
* @brief Initialize the Newlib-nano functions (also forces inclusion of stubs for linking)
*/
void nanostubs_init(void)
{
#if defined(MODULE_UART_STDIO)
/* STDIO redirected to UART, no line buffering */
uart_stdio_init();
setvbuf(stdout, NULL, _IONBF, 0);
#endif
}
void _init(void)
{
}
void _fini(void)
{
}
void *_sbrk(ptrdiff_t incr)
{
unsigned int state = irq_disable();
void *res = heap_top;
/* Allocate memory from heap */
if ((heap_top + incr > &_heap_end) || (heap_top + incr < &_heap_start)) {
errno = ENOMEM;
res = (void *) -1;
}
else {
heap_top += incr;
}
irq_restore(state);
return res;
}
int _open(const char *name, int flags, int mode)
{
(void) name;
(void) flags;
(void) mode;
errno = ENODEV;
return -1;
}
_ssize_t _read(int fd, void *buffer, size_t count)
{
#if defined(MODULE_UART_STDIO)
if (fd == STDIN_FILENO) {
return uart_stdio_read(buffer, count);
}
errno = EBADF;
return -1;
#else
(void) fd;
(void) buffer;
(void) count;
errno = ENODEV;
return -1;
#endif
}
_ssize_t _write(int fd, const void *data, size_t count)
{
#if defined(MODULE_UART_STDIO)
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
return uart_stdio_write(data, count);
}
errno = EBADF;
return -1;
#else
(void) fd;
(void) data;
(void) count;
errno = ENODEV;
return -1;
#endif
}
int _close(int fd)
{
(void) fd;
errno = ENODEV;
return -1;
}
int _isatty(int fd)
{
errno = 0;
if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) {
return 1;
}
return 0;
}
int _fstat(int fd, struct stat *st)
{
(void) fd;
(void) st;
errno = ENODEV;
return -1;
}
_off_t _lseek(int fd, _off_t pos, int dir)
{
(void) fd;
(void) pos;
(void) dir;
errno = ENODEV;
return -1;
}
int _gettimeofday(struct timeval *tp, void *tzp)
{
(void) tp;
(void) tzp;
errno = EINVAL;
return -1;
}
int _getpid(void)
{
return thread_getpid();
}
int _kill(int pid, int sig)
{
(void) pid;
(void) sig;
errno = EINVAL;
return -1;
}
void _exit(int _status)
{
(void) _status;
while(1);
}

View File

@ -0,0 +1 @@
include $(RIOTMAKE)/periph.mk

View File

@ -0,0 +1,34 @@
/*
* Copyright 2017 JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file cpu_cycle.c
* @brief Read CPU cycle counter
*
* @author JP Bonn
* @}
*/
#include "cpucycle.h"
#include "vendor/encoding.h"
uint64_t get_cycle_count(void)
{
uint32_t lo, hi, hi2;
__asm__ __volatile__ ("1:\n\t" \
"csrr %0, mcycleh\n\t" \
"csrr %1, mcycle\n\t" \
"csrr %2, mcycleh\n\t" \
"bne %0, %2, 1b\n\t" \
: "=r" (hi), "=r" (lo), "=r" (hi2));
return lo | ((uint64_t) hi << 32);
}

38
cpu/fe310/periph/cpuid.c Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file cpuid.c
* @brief Low-level CPUID driver implementation
*
* @author Ken Rabold
* @}
*/
#include <stdint.h>
#include <string.h>
#include "periph/cpuid.h"
#include "cpu.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
void cpuid_get(void *id)
{
uint32_t result[5];
/* Read RISC-V CSRs for CPU ID */
result[0] = read_csr(mvendorid);
result[1] = read_csr(marchid);
result[2] = read_csr(mimpid);
memcpy(id, &result[0], CPUID_LEN);
}

214
cpu/fe310/periph/gpio.c Normal file
View File

@ -0,0 +1,214 @@
/*
* Copyright 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file gpio.c
* @brief Low-level GPIO implementation
*
* @author Ken Rabold
* @}
*/
#include <stdlib.h>
#include <unistd.h>
#include "irq.h"
#include "cpu.h"
#include "periph_cpu.h"
#include "periph_conf.h"
#include "periph/gpio.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
/* Num of GPIOs supported */
#define GPIO_NUMOF (32)
static gpio_flank_t isr_flank[GPIO_NUMOF];
static gpio_isr_ctx_t isr_ctx[GPIO_NUMOF];
void gpio_isr(int num)
{
uint32_t pin = num - INT_GPIO_BASE;
/* Invoke callback function */
if (isr_ctx[pin].cb) {
isr_ctx[pin].cb(isr_ctx[pin].arg);
}
/* Clear interupt */
switch (isr_flank[pin]) {
case GPIO_FALLING:
GPIO_REG(GPIO_FALL_IP) |= (1 << pin);
break;
case GPIO_RISING:
GPIO_REG(GPIO_RISE_IP) |= (1 << pin);
break;
case GPIO_BOTH:
GPIO_REG(GPIO_FALL_IP) |= (1 << pin);
GPIO_REG(GPIO_RISE_IP) |= (1 << pin);
break;
}
}
int gpio_init(gpio_t pin, gpio_mode_t mode)
{
/* Check for valid pin */
if (pin >= GPIO_NUMOF) {
return -1;
}
/* Configure the mode */
switch (mode) {
case GPIO_IN:
GPIO_REG(GPIO_INPUT_EN) |= (1 << pin);
GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << pin);
GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << pin);
break;
case GPIO_IN_PU:
GPIO_REG(GPIO_INPUT_EN) |= (1 << pin);
GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << pin);
GPIO_REG(GPIO_PULLUP_EN) |= (1 << pin);
break;
case GPIO_OUT:
GPIO_REG(GPIO_INPUT_EN) &= ~(1 << pin);
GPIO_REG(GPIO_OUTPUT_EN) |= (1 << pin);
GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << pin);
break;
default:
return -1;
}
/* Configure the pin muxing for the GPIO */
GPIO_REG(GPIO_IOF_EN) &= ~(1 << pin);
GPIO_REG(GPIO_IOF_SEL) &= ~(1 << pin);
return 0;
}
int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
gpio_cb_t cb, void *arg)
{
/* Configure pin */
if (gpio_init(pin, mode) != 0) {
return -1;
}
/* Disable ext interrupts when setting up */
clear_csr(mie, MIP_MEIP);
/* Configure GPIO ISR with PLIC */
set_external_isr_cb(INT_GPIO_BASE + pin, gpio_isr);
PLIC_enable_interrupt(INT_GPIO_BASE + pin);
PLIC_set_priority(INT_GPIO_BASE + pin, GPIO_INTR_PRIORITY);
/* Configure the active flank(s) */
gpio_irq_enable(pin);
/* Save callback */
isr_ctx[pin].cb = cb;
isr_ctx[pin].arg = arg;
isr_flank[pin] = flank;
/* Re-eanble ext interrupts */
set_csr(mie, MIP_MEIP);
return 0;
}
void gpio_irq_enable(gpio_t pin)
{
/* Check for valid pin */
if (pin >= GPIO_NUMOF) {
return;
}
/* Enable interupt for pin */
switch (isr_flank[pin]) {
case GPIO_FALLING:
GPIO_REG(GPIO_FALL_IE) |= (1 << pin);
break;
case GPIO_RISING:
GPIO_REG(GPIO_RISE_IE) |= (1 << pin);
break;
case GPIO_BOTH:
GPIO_REG(GPIO_FALL_IE) |= (1 << pin);
GPIO_REG(GPIO_RISE_IE) |= (1 << pin);
break;
default:
break;
}
}
void gpio_irq_disable(gpio_t pin)
{
/* Check for valid pin */
if (pin >= GPIO_NUMOF) {
return;
}
/* Disable interupt for pin */
switch (isr_flank[pin]) {
case GPIO_FALLING:
GPIO_REG(GPIO_FALL_IE) &= ~(1 << pin);
break;
case GPIO_RISING:
GPIO_REG(GPIO_RISE_IE) &= ~(1 << pin);
break;
case GPIO_BOTH:
GPIO_REG(GPIO_FALL_IE) &= ~(1 << pin);
GPIO_REG(GPIO_RISE_IE) &= ~(1 << pin);
break;
default:
break;
}
}
int gpio_read(gpio_t pin)
{
return (GPIO_REG(GPIO_INPUT_VAL) & (1 << pin)) ? 1 : 0;
}
void gpio_set(gpio_t pin)
{
GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << pin);
}
void gpio_clear(gpio_t pin)
{
GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << pin);
}
void gpio_toggle(gpio_t pin)
{
GPIO_REG(GPIO_OUTPUT_VAL) ^= (1 << pin);
}
void gpio_write(gpio_t pin, int value)
{
if (value) {
GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << pin);
}
else {
GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << pin);
}
}

33
cpu/fe310/periph/pm.c Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file pm.c
* @brief Implementation of the CPU power management for SiFive FE310
*
* @author Ken Rabold
* @}
*/
#include "periph/pm.h"
void pm_set_lowest(void)
{
/* __asm__("wfi"); */
}
void pm_off(void)
{
}
void pm_reboot(void)
{
}

106
cpu/fe310/periph/rtc.c Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file rtc.c
* @brief RTC interface wrapper for use with RTT modules
*
* @author Ken Rabold
* @}
*/
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "cpu.h"
#include "periph_cpu.h"
#include "periph_conf.h"
#include "periph/rtt.h"
#include "periph/rtc.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
typedef struct {
rtc_alarm_cb_t cb; /**< callback called from RTC interrupt */
}rtc_state_t;
static rtc_state_t rtc_callback;
static void rtc_cb(void *arg);
void rtc_init(void)
{
rtt_init();
}
int rtc_set_time(struct tm *time)
{
time_t t = mktime(time);
rtt_set_counter((uint32_t)t);
return 0;
}
int rtc_get_time(struct tm *time)
{
time_t t = (time_t)rtt_get_counter();
gmtime_r(&t, time);
return 0;
}
int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
{
time_t t = mktime(time);
rtc_callback.cb = cb;
rtt_set_alarm((uint32_t)t, rtc_cb, arg);
return 0;
}
int rtc_get_alarm(struct tm *time)
{
time_t t = (time_t)rtt_get_alarm();
gmtime_r(&t, time);
return 0;
}
void rtc_clear_alarm(void)
{
rtt_clear_alarm();
rtc_callback.cb = NULL;
}
void rtc_poweron(void)
{
rtt_poweron();
}
void rtc_poweroff(void)
{
rtt_poweroff();
}
static void rtc_cb(void *arg)
{
if (rtc_callback.cb != NULL) {
rtc_callback.cb(arg);
}
}

206
cpu/fe310/periph/rtt.c Normal file
View File

@ -0,0 +1,206 @@
/*
* Copyright 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file rtt.c
* @brief Low-level RTT interface implementation for SiFive FE310
* The FE320's RTC module is what RIOT calls a Real-Time
* Timer (RTT), a simple counter which counts seconds; RIOT Real-
* Time Clocks (RTC) counts seconds, minutes, hours etc. There is
* an RTT->RTC wrapper layer in a separate file to allow using the
* RTT as a system real time clock.
*
* @author Ken Rabold
* @}
*/
#include <stdlib.h>
#include <unistd.h>
#include "cpu.h"
#include "periph_cpu.h"
#include "periph_conf.h"
#include "periph/rtt.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/* Convert RTT freq to pre-scaler value */
#if (RTT_FREQUENCY == 32768)
#define RTT_SCALE (0)
#elif (RTT_FREQUENCY == 16384)
#define RTT_SCALE (1)
#elif (RTT_FREQUENCY == 8192)
#define RTT_SCALE (2)
#elif (RTT_FREQUENCY == 4096)
#define RTT_SCALE (3)
#elif (RTT_FREQUENCY == 2048)
#define RTT_SCALE (4)
#elif (RTT_FREQUENCY == 1024)
#define RTT_SCALE (5)
#elif (RTT_FREQUENCY == 512)
#define RTT_SCALE (6)
#elif (RTT_FREQUENCY == 256)
#define RTT_SCALE (7)
#elif (RTT_FREQUENCY == 128)
#define RTT_SCALE (8)
#elif (RTT_FREQUENCY == 64)
#define RTT_SCALE (9)
#elif (RTT_FREQUENCY == 32)
#define RTT_SCALE (10)
#elif (RTT_FREQUENCY == 16)
#define RTT_SCALE (11)
#elif (RTT_FREQUENCY == 8)
#define RTT_SCALE (12)
#elif (RTT_FREQUENCY == 4)
#define RTT_SCALE (13)
#elif (RTT_FREQUENCY == 2)
#define RTT_SCALE (14)
#elif (RTT_FREQUENCY == 1)
#define RTT_SCALE (15)
#else
#error "Invalid RTT_FREQUENCY: Must be power of 2"
#endif
typedef struct {
uint32_t alarm_val; /**< cached alarm val */
rtt_cb_t alarm_cb; /**< callback called from RTC alarm */
void *alarm_arg; /**< argument passed to the callback */
rtt_cb_t overflow_cb; /**< callback called when RTC overflows */
void *overflow_arg; /**< argument passed to the callback */
}rtt_state_t;
static rtt_state_t rtt_callback;
void rtt_isr(int num)
{
(void) num;
/* Clear intr */
AON_REG(AON_RTCCMP) = RTT_MAX_VALUE;
/* Invoke callback function for alarm or overflow */
if (rtt_callback.alarm_cb) {
rtt_callback.alarm_cb(rtt_callback.alarm_arg);
}
else if (rtt_callback.overflow_cb) {
rtt_callback.overflow_cb(rtt_callback.overflow_arg);
}
}
void rtt_init(void)
{
/* Disable ext interrupts when setting up */
clear_csr(mie, MIP_MEIP);
/* Configure RTC ISR with PLIC */
set_external_isr_cb(INT_RTCCMP, rtt_isr);
PLIC_enable_interrupt(INT_RTCCMP);
PLIC_set_priority(INT_RTCCMP, RTT_INTR_PRIORITY);
/* Configure RTC scaler, etc... */
AON_REG(AON_RTCCFG) = RTT_SCALE;
AON_REG(AON_RTCLO) = 0;
AON_REG(AON_RTCHI) = 0;
AON_REG(AON_RTCCMP) = RTT_MAX_VALUE;
/* Configure state struct */
rtt_callback.alarm_val = RTT_MAX_VALUE;
rtt_callback.alarm_cb = NULL;
rtt_callback.alarm_arg = NULL;
rtt_callback.overflow_cb = NULL;
rtt_callback.overflow_arg = NULL;
/* Enable the RTC counter */
rtt_poweron();
/* Re-eanble ext interrupts */
set_csr(mie, MIP_MEIP);
}
void rtt_set_overflow_cb(rtt_cb_t cb, void *arg)
{
/*
* No separate overflow intr
* If no alarm cb is set, this cb will fire on RTC intr
*/
rtt_callback.overflow_cb = cb;
rtt_callback.overflow_arg = arg;
}
void rtt_clear_overflow_cb(void)
{
/* No separate overflow intr */
rtt_callback.overflow_cb = NULL;
rtt_callback.overflow_arg = NULL;
}
uint32_t rtt_get_counter(void)
{
/* Read scaled counter reg value */
uint32_t t = AON_REG(AON_RTCS);
return t;
}
void rtt_set_counter(uint32_t counter)
{
/*
* Can't write to scaled RTC reg
* Must program HI/LO regs
* Write scaled counter reg value
*/
AON_REG(AON_RTCLO) = counter << RTT_SCALE;
AON_REG(AON_RTCHI) = counter >> (32 - RTT_SCALE);
}
void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
{
/* Set cmp reg to given value */
AON_REG(AON_RTCCMP) = alarm;
rtt_callback.alarm_val = alarm;
rtt_callback.alarm_cb = cb;
rtt_callback.alarm_arg = arg;
}
uint32_t rtt_get_alarm(void)
{
/*
* Read back cached alarm value
* When alarm fires, cmp reg is set to highest val
* to clear intr, so used cached value for this function
*/
return rtt_callback.alarm_val;
}
void rtt_clear_alarm(void)
{
/* Set cmp reg to highest value */
AON_REG(AON_RTCCMP) = RTT_MAX_VALUE;
rtt_callback.alarm_val = RTT_MAX_VALUE;
rtt_callback.alarm_cb = NULL;
rtt_callback.alarm_arg = NULL;
}
void rtt_poweron(void)
{
/* Enable the RTC counter */
AON_REG(AON_RTCCFG) |= AON_RTCCFG_ENALWAYS;
}
void rtt_poweroff(void)
{
/* Disable the RTC counter */
AON_REG(AON_RTCCFG) &= ~AON_RTCCFG_ENALWAYS;
}

171
cpu/fe310/periph/timer.c Normal file
View File

@ -0,0 +1,171 @@
/*
* Copyright 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file timer.c
* @brief Low-level timer implementation
*
* @author Ken Rabold
* @}
*/
#include <stdlib.h>
#include <unistd.h>
#include "cpu.h"
#include "periph_cpu.h"
#include "periph_conf.h"
#include "periph/timer.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
/**
* @brief Save reference to the timer callback
*/
static timer_cb_t isr_cb;
/**
* @brief Save argument for the callback
*/
static void *isr_arg;
int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg)
{
/* Using RISC-V built in timer (64bit value) */
if (dev != 0) {
return -1;
}
/* Built in timer for FE310 is 32KHz */
if (freq != RTC_FREQ) {
return -1;
}
/* Save timer callback and arg */
isr_cb = cb;
isr_arg = arg;
/* No other configuration */
return 0;
}
int timer_set(tim_t dev, int channel, unsigned int timeout)
{
volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME);
volatile uint64_t *mtimecmp =
(uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
/* Compute delta for timer */
uint64_t now = *mtime;
uint64_t then = now + (uint64_t) timeout;
if (dev != 0 || channel != 0) {
return -1;
}
/* Avoid spurious timer intr */
clear_csr(mie, MIP_MTIP);
/* New intr time */
*mtimecmp = then;
/* Re-enalble timer intr */
set_csr(mie, MIP_MTIP);
return 0;
}
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
{
volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME);
volatile uint64_t *mtimecmp =
(uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
/* Compute absolute for timer */
uint64_t now = *mtime;
uint64_t then = (now & 0xFFFFFFFF00000000) + (uint64_t) value;
if (dev != 0 || channel != 0) {
return -1;
}
/* Avoid spurious timer intr */
clear_csr(mie, MIP_MTIP);
/* New intr time (handle 32bit rollover) */
*mtimecmp = (then > now) ? then : then + 0x100000000;
/* Re-enable timer intr */
set_csr(mie, MIP_MTIP);
return 0;
}
int timer_clear(tim_t dev, int channel)
{
if (dev != 0 || channel != 0) {
return -1;
}
return 0;
}
unsigned int timer_read(tim_t dev)
{
uint32_t lo = *(volatile uint32_t *) (CLINT_CTRL_ADDR + CLINT_MTIME);
if (dev != 0) {
return 0;
}
/* Read current timer value */
return (unsigned int) lo;
}
void timer_start(tim_t dev)
{
if (dev != 0) {
return;
}
/* Timer is continuous running
* Enable the timer interrupt */
set_csr(mie, MIP_MTIP);
}
void timer_stop(tim_t dev)
{
if (dev != 0) {
return;
}
/* Disable the timer interrupt */
clear_csr(mie, MIP_MTIP);
}
void timer_isr(void)
{
volatile uint64_t *mtimecmp =
(uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
/* Clear intr */
clear_csr(mie, MIP_MTIP);
/* Set mtimecmp to largest value to clear the interrupt */
*mtimecmp = 0xFFFFFFFFFFFFFFFF;
/* Call timer callback function */
if (isr_cb) {
isr_cb(isr_arg, 0);
}
/* Reset interrupt */
set_csr(mie, MIP_MTIP);
}

170
cpu/fe310/periph/uart.c Normal file
View File

@ -0,0 +1,170 @@
/*
* Copyright 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file timer.c
* @brief Low-level timer implementation
*
* @author Ken Rabold
* @}
*/
#include <stdlib.h>
#include <unistd.h>
#include "irq.h"
#include "cpu.h"
#include "periph_cpu.h"
#include "periph_conf.h"
#include "periph/uart.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
#include "vendor/prci_driver.h"
/**
* @brief Allocate memory to store the callback functions
*/
static uart_isr_ctx_t isr_ctx[UART_NUMOF];
void uart_isr(int num)
{
uint32_t data;
/* Invoke callback function */
if (num == INT_UART0_BASE) {
data = UART0_REG(UART_REG_RXFIFO);
/* Intr cleared automatically when data is read */
while ((data & UART_RXFIFO_EMPTY) != (uint32_t)UART_RXFIFO_EMPTY) {
isr_ctx[0].rx_cb(isr_ctx[0].arg, (uint8_t) data);
data = UART0_REG(UART_REG_RXFIFO);
}
}
if (num == INT_UART1_BASE) {
data = UART1_REG(UART_REG_RXFIFO);
/* Intr cleared automatically when data is read */
while ((data & UART_RXFIFO_EMPTY) != (uint32_t)UART_RXFIFO_EMPTY) {
isr_ctx[1].rx_cb(isr_ctx[1].arg, (uint8_t) data);
data = UART1_REG(UART_REG_RXFIFO);
}
}
}
int uart_init(uart_t dev, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
{
uint32_t uartDiv;
/* Check for valid UART dev */
if (dev >= UART_NUMOF) {
return UART_NODEV;
}
/* Save interrupt callback context */
isr_ctx[dev].rx_cb = rx_cb;
isr_ctx[dev].arg = arg;
/* Power on the device */
uart_poweron(dev);
/* Calculate buadrate divisor given current CPU clk rate
* Ignore the first run (icache needs to be warm) */
uartDiv = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
/* cppcheck-suppress redundantAssignment */
uartDiv = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
uartDiv = uartDiv / baudrate;
/* Enable UART 8-N-1 at given baudrate */
if (dev == 0) {
/* Config UART */
UART0_REG(UART_REG_DIV) = uartDiv;
UART0_REG(UART_REG_TXCTRL) = UART_TXEN;
/* Enable RX intr if there is a callback */
if (rx_cb != NULL) {
/* Disable ext interrupts when setting up */
clear_csr(mie, MIP_MEIP);
/* Configure UART ISR with PLIC */
set_external_isr_cb(INT_UART0_BASE, uart_isr);
PLIC_enable_interrupt(INT_UART0_BASE);
PLIC_set_priority(INT_UART0_BASE, UART0_RX_INTR_PRIORITY);
UART0_REG(UART_REG_IE) = UART_IP_RXWM;
UART0_REG(UART_REG_RXCTRL) = UART_RXEN;
/* Re-eanble ext interrupts */
set_csr(mie, MIP_MEIP);
}
}
if (dev == 1) {
/* Config UART */
UART1_REG(UART_REG_DIV) = uartDiv;
UART1_REG(UART_REG_TXCTRL) = UART_TXEN;
/* Enable RX intr if there is a callback */
if (rx_cb != NULL) {
/* Disable ext interrupts when setting up */
clear_csr(mie, MIP_MEIP);
/* Configure UART ISR with PLIC */
set_external_isr_cb(INT_UART1_BASE, uart_isr);
PLIC_enable_interrupt(INT_UART1_BASE);
PLIC_set_priority(INT_UART1_BASE, UART1_RX_INTR_PRIORITY);
UART1_REG(UART_REG_IE) = UART_IP_RXWM;
UART1_REG(UART_REG_RXCTRL) = UART_RXEN;
/* Re-eanble ext interrupts */
set_csr(mie, MIP_MEIP);
}
}
return UART_OK;
}
void uart_write(uart_t dev, const uint8_t *data, size_t len)
{
if (dev == 0) {
for (size_t i = 0; i < len; i++) {
/* Wait for FIFO to empty */
while ((UART0_REG(UART_REG_TXFIFO) & UART_TXFIFO_FULL)
== (uint32_t)UART_TXFIFO_FULL)
;
/* Write a byte */
UART0_REG(UART_REG_TXFIFO) = data[i];
}
}
if (dev == 1) {
for (size_t i = 0; i < len; i++) {
/* Wait for FIFO to empty */
while ((UART1_REG(UART_REG_TXFIFO) & UART_TXFIFO_FULL)
== (uint32_t)UART_TXFIFO_FULL)
;
/* Write a byte */
UART1_REG(UART_REG_TXFIFO) = data[i];
}
}
}
void uart_poweron(uart_t dev)
{
(void) dev;
}
void uart_poweroff(uart_t dev)
{
(void) dev;
}

59
cpu/fe310/start.S Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2017 JP Bonn, Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
.section .init
.globl _start
.type _start,@function
_start:
.cfi_startproc
.cfi_undefined ra
.option push
.option norelax
la gp, __global_pointer$
.option pop
la sp, _sp
/* Load data section */
la a0, _data_lma
la a1, _data
la a2, _edata
bgeu a1, a2, 2f
1:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
/* Clear bss section */
la a0, __bss_start
la a1, _end
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
/* Call global constructors */
la a0, __libc_fini_array
call atexit
call __libc_init_array
/* Initialize board and start kernel */
call board_init
call kernel_init
/* Loop forever (should never get here) */
1:
j 1b
.cfi_endproc

206
cpu/fe310/vendor/LICENSE vendored Normal file
View File

@ -0,0 +1,206 @@
This software, except as otherwise noted in subrepositories,
is licensed under the Apache 2 license, quoted below.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 SiFive, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

3
cpu/fe310/vendor/Makefile vendored Normal file
View File

@ -0,0 +1,3 @@
MODULE = sifive_drivers_fe310
include $(RIOTBASE)/Makefile.base

153
cpu/fe310/vendor/plic_driver.c vendored Normal file
View File

@ -0,0 +1,153 @@
// See LICENSE for license details.
#include <stdlib.h>
#include <unistd.h>
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
typedef struct __plic_instance_t
{
uintptr_t base_addr;
uint32_t num_sources;
uint32_t num_priorities;
} plic_instance_t;
// PLIC instance
static plic_instance_t _plic;
// Note that there are no assertions or bounds checking on these
// parameter values.
void volatile_memzero(uint8_t * base, unsigned int size)
{
volatile uint8_t * ptr;
for (ptr = base; ptr < (base + size); ptr++){
*ptr = 0;
}
}
void PLIC_init (
uintptr_t base_addr,
uint32_t num_sources,
uint32_t num_priorities
)
{
plic_instance_t* this_plic = &_plic;
this_plic->base_addr = base_addr;
this_plic->num_sources = num_sources;
this_plic->num_priorities = num_priorities;
// Disable all interrupts (don't assume that these registers are reset).
unsigned long hart_id = read_csr(mhartid);
volatile_memzero((uint8_t*) (this_plic->base_addr +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)),
(num_sources + 8) / 8);
// Set all priorities to 0 (equal priority -- don't assume that these are reset).
volatile_memzero ((uint8_t *)(this_plic->base_addr +
PLIC_PRIORITY_OFFSET),
(num_sources + 1) << PLIC_PRIORITY_SHIFT_PER_SOURCE);
// Set the threshold to 0.
volatile plic_threshold* threshold = (plic_threshold*)
(this_plic->base_addr +
PLIC_THRESHOLD_OFFSET +
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
*threshold = 0;
}
void PLIC_set_threshold (plic_threshold threshold)
{
plic_instance_t* this_plic = &_plic;
unsigned long hart_id = read_csr(mhartid);
volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr +
PLIC_THRESHOLD_OFFSET +
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
*threshold_ptr = threshold;
}
void PLIC_enable_interrupt (plic_source source)
{
plic_instance_t* this_plic = &_plic;
unsigned long hart_id = read_csr(mhartid);
volatile uint8_t * current_ptr = (volatile uint8_t *)(this_plic->base_addr +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
(source >> 3));
uint8_t current = *current_ptr;
current = current | ( 1 << (source & 0x7));
*current_ptr = current;
}
void PLIC_disable_interrupt (plic_source source)
{
plic_instance_t* this_plic = &_plic;
unsigned long hart_id = read_csr(mhartid);
volatile uint8_t * current_ptr = (volatile uint8_t *) (this_plic->base_addr +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
(source >> 3));
uint8_t current = *current_ptr;
current = current & ~(( 1 << (source & 0x7)));
*current_ptr = current;
}
void PLIC_set_priority (plic_source source, plic_priority priority)
{
plic_instance_t* this_plic = &_plic;
if (this_plic->num_priorities > 0) {
volatile plic_priority * priority_ptr = (volatile plic_priority *)
(this_plic->base_addr +
PLIC_PRIORITY_OFFSET +
(source << PLIC_PRIORITY_SHIFT_PER_SOURCE));
*priority_ptr = priority;
}
}
plic_source PLIC_claim_interrupt(void)
{
plic_instance_t* this_plic = &_plic;
unsigned long hart_id = read_csr(mhartid);
volatile plic_source * claim_addr = (volatile plic_source * )
(this_plic->base_addr +
PLIC_CLAIM_OFFSET +
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
return *claim_addr;
}
void PLIC_complete_interrupt(plic_source source)
{
plic_instance_t* this_plic = &_plic;
unsigned long hart_id = read_csr(mhartid);
volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr +
PLIC_CLAIM_OFFSET +
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
*claim_addr = source;
}

268
cpu/fe310/vendor/prci_driver.c vendored Normal file
View File

@ -0,0 +1,268 @@
// See LICENSE file for license details
#include <stdlib.h>
#include <unistd.h>
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/prci_driver.h"
#define rdmcycle(x) { \
uint32_t lo, hi, hi2; \
__asm__ __volatile__ ("1:\n\t" \
"csrr %0, mcycleh\n\t" \
"csrr %1, mcycle\n\t" \
"csrr %2, mcycleh\n\t" \
"bne %0, %2, 1b\n\t" \
: "=r" (hi), "=r" (lo), "=r" (hi2)) ; \
*(x) = lo | ((uint64_t) hi << 32); \
}
uint32_t PRCI_measure_mcycle_freq(uint32_t mtime_ticks, uint32_t mtime_freq)
{
uint32_t start_mtime = CLINT_REG(CLINT_MTIME);
uint32_t end_mtime = start_mtime + mtime_ticks + 1;
// Make sure we won't get rollover.
while (end_mtime < start_mtime){
start_mtime = CLINT_REG(CLINT_MTIME);
end_mtime = start_mtime + mtime_ticks + 1;
}
// Don't start measuring until mtime edge.
uint32_t tmp = start_mtime;
do {
start_mtime = CLINT_REG(CLINT_MTIME);
} while (start_mtime == tmp);
uint64_t start_mcycle;
rdmcycle(&start_mcycle);
while (CLINT_REG(CLINT_MTIME) < end_mtime) ;
uint64_t end_mcycle;
rdmcycle(&end_mcycle);
uint32_t difference = (uint32_t) (end_mcycle - start_mcycle);
uint64_t freq = ((uint64_t) difference * mtime_freq) / mtime_ticks;
return (uint32_t) freq & 0xFFFFFFFF;
}
void PRCI_use_hfrosc(int div, int trim)
{
// Make sure the HFROSC is running at its default setting
// It is OK to change this even if we are running off of it.
PRCI_REG(PRCI_HFROSCCFG) = (ROSC_DIV(div) | ROSC_TRIM(trim) | ROSC_EN(1));
while ((PRCI_REG(PRCI_HFROSCCFG) & ROSC_RDY(1)) == 0);
PRCI_REG(PRCI_PLLCFG) &= ~PLL_SEL(1);
}
void PRCI_use_pll(int refsel, int bypass,
int r, int f, int q, int finaldiv,
int hfroscdiv, int hfrosctrim)
{
// Ensure that we aren't running off the PLL before we mess with it.
if (PRCI_REG(PRCI_PLLCFG) & PLL_SEL(1)) {
// Make sure the HFROSC is running at its default setting
PRCI_use_hfrosc(4, 16);
}
// Set PLL Source to be HFXOSC if desired.
uint32_t config_value = 0;
config_value |= PLL_REFSEL(refsel);
if (bypass) {
// Bypass
config_value |= PLL_BYPASS(1);
PRCI_REG(PRCI_PLLCFG) = config_value;
// If we don't have an HFXTAL, this doesn't really matter.
// Set our Final output divide to divide-by-1:
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
} else {
// To overclock, use the hfrosc
if (hfrosctrim >= 0 && hfroscdiv >= 0) {
PRCI_use_hfrosc(hfroscdiv, hfrosctrim);
}
// Set DIV Settings for PLL
// (Legal values of f_REF are 6-48MHz)
// Set DIVR to divide-by-2 to get 8MHz frequency
// (legal values of f_R are 6-12 MHz)
config_value |= PLL_BYPASS(1);
config_value |= PLL_R(r);
// Set DIVF to get 512Mhz frequncy
// There is an implied multiply-by-2, 16Mhz.
// So need to write 32-1
// (legal values of f_F are 384-768 MHz)
config_value |= PLL_F(f);
// Set DIVQ to divide-by-2 to get 256 MHz frequency
// (legal values of f_Q are 50-400Mhz)
config_value |= PLL_Q(q);
// Set our Final output divide to divide-by-1:
if (finaldiv == 1){
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
} else {
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV(finaldiv-1));
}
PRCI_REG(PRCI_PLLCFG) = config_value;
// Un-Bypass the PLL.
PRCI_REG(PRCI_PLLCFG) &= ~PLL_BYPASS(1);
// Wait for PLL Lock
// Note that the Lock signal can be glitchy.
// Need to wait 100 us
// RTC is running at 32kHz.
// So wait 4 ticks of RTC.
uint32_t now = CLINT_REG(CLINT_MTIME);
while (CLINT_REG(CLINT_MTIME) - now < 4) ;
// Now it is safe to check for PLL Lock
while ((PRCI_REG(PRCI_PLLCFG) & PLL_LOCK(1)) == 0);
}
// Switch over to PLL Clock source
PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1);
// If we're running off HFXOSC, turn off the HFROSC to
// save power.
if (refsel) {
PRCI_REG(PRCI_HFROSCCFG) &= ~ROSC_EN(1);
}
}
void PRCI_use_default_clocks(void)
{
// Turn off the LFROSC
AON_REG(AON_LFROSC) &= ~ROSC_EN(1);
// Use HFROSC
PRCI_use_hfrosc(4, 16);
}
void PRCI_use_hfxosc(uint32_t finaldiv)
{
PRCI_use_pll(1, // Use HFXTAL
1, // Bypass = 1
0, // PLL settings don't matter
0, // PLL settings don't matter
0, // PLL settings don't matter
finaldiv,
-1,
-1);
}
void PRCI_use_bypass_clock(void)
{
// Make sure the HFROSC is on before the next line:
PRCI_REG(PRCI_HFROSCCFG) |= ROSC_EN(1);
// Run off 16 MHz crystal
PRCI_REG(PRCI_PLLCFG) = (PLL_REFSEL(1) | PLL_BYPASS(1));
PRCI_REG(PRCI_PLLCFG) |= (PLL_SEL(1));
// Turn off HFROSC to save power
PRCI_REG(PRCI_HFROSCCFG) &= ~(ROSC_EN(1));
}
// This is a generic function, which
// doesn't span the entire range of HFROSC settings.
// It only adjusts the trim, which can span a hundred MHz or so.
// This function does not check the legality of the PLL settings
// at all, and it is quite possible to configure invalid PLL settings
// this way.
// It returns the actual measured CPU frequency.
uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target )
{
uint32_t hfrosctrim = 0;
uint32_t hfroscdiv = 4;
uint32_t prev_trim = 0;
// In this function we use PLL settings which
// will give us a 32x multiplier from the output
// of the HFROSC source to the output of the
// PLL. We first measure our HFROSC to get the
// right trim, then finally use it as the PLL source.
// We should really check here that the f_cpu
// requested is something in the limit of the PLL. For
// now that is up to the user.
// This will undershoot for frequencies not divisible by 16.
uint32_t desired_hfrosc_freq = (f_cpu/ 16);
PRCI_use_hfrosc(hfroscdiv, hfrosctrim);
// Ignore the first run (for icache reasons)
uint32_t cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
uint32_t prev_freq = cpu_freq;
while ((cpu_freq < desired_hfrosc_freq) && (hfrosctrim < 0x1F)){
prev_trim = hfrosctrim;
prev_freq = cpu_freq;
hfrosctrim ++;
PRCI_use_hfrosc(hfroscdiv, hfrosctrim);
cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
}
// We couldn't go low enough
if (prev_freq > desired_hfrosc_freq){
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim);
cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
return cpu_freq;
}
// We couldn't go high enough
if (cpu_freq < desired_hfrosc_freq){
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim);
cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
return cpu_freq;
}
// Check for over/undershoot
switch(target) {
case(PRCI_FREQ_CLOSEST):
if ((desired_hfrosc_freq - prev_freq) < (cpu_freq - desired_hfrosc_freq)) {
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim);
} else {
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, hfrosctrim);
}
break;
case(PRCI_FREQ_UNDERSHOOT):
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim);
break;
default:
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, hfrosctrim);
}
cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
return cpu_freq;
}

View File

@ -8,7 +8,7 @@
changed_files() {
: ${FILEREGEX:='\.([CcHh]|[ch]pp)$'}
: ${EXCLUDE:='^(.+/include/vendor/|dist/tools/coccinelle/include|boards/common/msba2/tools/src)'}
: ${EXCLUDE:='^(.+/vendor/|dist/tools/coccinelle/include|boards/common/msba2/tools/src)'}
: ${DIFFFILTER:='ACMR'}
DIFFFILTER="--diff-filter=${DIFFFILTER}"

View File

@ -6,7 +6,7 @@
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
NOVENDOR=":!*/include/vendor/*"
NOVENDOR=":!*/vendor/*"
# If no branch but an option is given, unset BRANCH.
# Otherwise, consume this parameter.

View File

@ -13,7 +13,7 @@ BOARD_BLACKLIST := arduino-duemilanove arduino-mega2560 arduino-uno chronos \
z1 jiminy-mega256rfr2 mega-xplained
BOARD_INSUFFICIENT_MEMORY := airfy-beacon b-l072z-lrwan1 bluepill calliope-mini \
cc2650-launchpad cc2650stk maple-mini \
cc2650-launchpad cc2650stk hifive1 maple-mini \
microbit nrf51dongle nrf6310 nucleo-f031k6 \
nucleo-f042k6 nucleo-f303k8 nucleo-l031k6 nucleo-f030r8 \
nucleo-f070rb nucleo-f072rb nucleo-f103rb nucleo-f302r8 nucleo-f334r8 \

View File

@ -8,7 +8,7 @@ BOARD ?= native
RIOTBASE ?= $(CURDIR)/../..
BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-mega2560 arduino-uno \
chronos msb-430 msb-430h nucleo-f031k6 nucleo-f042k6 \
chronos hifive1 msb-430 msb-430h nucleo-f031k6 nucleo-f042k6 \
nucleo-f303k8 nucleo-l031k6 nucleo-f030r8 nucleo-f070rb \
nucleo-f072rb nucleo-f302r8 nucleo-f334r8 nucleo-l053r8 \
stm32f0discovery telosb waspmote-pro wsn430-v1_3b \

View File

@ -8,7 +8,7 @@ BOARD ?= samr21-xpro
RIOTBASE ?= $(CURDIR)/../..
BOARD_INSUFFICIENT_MEMORY := airfy-beacon b-l072z-lrwan1 bluepill calliope-mini \
cc2650-launchpad cc2650stk maple-mini \
cc2650-launchpad cc2650stk hifive1 maple-mini \
microbit msb-430 msb-430h nrf51dongle nrf6310 \
nucleo-f031k6 nucleo-f042k6 nucleo-f303k8 nucleo-l031k6 \
nucleo-f030r8 nucleo-f070rb nucleo-f072rb nucleo-f103rb nucleo-f302r8 \

View File

@ -7,7 +7,7 @@ BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..
BOARD_INSUFFICIENT_MEMORY := calliope-mini chronos microbit msb-430 msb-430h \
BOARD_INSUFFICIENT_MEMORY := calliope-mini chronos hifive1 microbit msb-430 msb-430h \
nucleo-f031k6 nucleo-f042k6 nucleo-f303k8 nucleo-l031k6 \
nucleo-f030r8 nucleo-f070rb nucleo-f072rb nucleo-f103rb nucleo-f302r8 \
nucleo-f334r8 nucleo-l053r8 spark-core stm32f0discovery telosb \

View File

@ -8,7 +8,7 @@ BOARD ?= native
RIOTBASE ?= $(CURDIR)/../..
BOARD_INSUFFICIENT_MEMORY := airfy-beacon b-l072z-lrwan1 bluepill calliope-mini chronos \
microbit msb-430 msb-430h nrf51dongle nrf6310 nucleo-f031k6 \
hifive1 microbit msb-430 msb-430h nrf51dongle nrf6310 nucleo-f031k6 \
nucleo-f042k6 nucleo-f303k8 nucleo-l031k6 nucleo-f030r8 \
nucleo-f070rb nucleo-f072rb nucleo-f103rb nucleo-f302r8 nucleo-f334r8 \
nucleo-l053r8 spark-core stm32f0discovery \

View File

@ -8,7 +8,7 @@ BOARD ?= native
RIOTBASE ?= $(CURDIR)/../..
BOARD_INSUFFICIENT_MEMORY := airfy-beacon b-l072z-lrwan1 bluepill calliope-mini \
cc2650-launchpad cc2650stk maple-mini \
cc2650-launchpad cc2650stk hifive1 maple-mini \
microbit nrf51dongle nrf6310 nucleo-f030r8 nucleo-f070rb \
nucleo-f072rb nucleo-f103rb nucleo-f302r8 nucleo-f334r8 nucleo-f410rb \
nucleo-l053r8 nucleo-l073rz nucleo-f031k6 nucleo-f042k6 \

View File

@ -15,7 +15,7 @@ BOARD_INSUFFICIENT_MEMORY := bluepill calliope-mini cc2650-launchpad \
opencm904 spark-core stm32f0discovery
BOARD_BLACKLIST := arduino-duemilanove arduino-mega2560 arduino-uno \
chronos jiminy-mega256rfr2 mega-xplained mips-malta \
chronos hifive1 jiminy-mega256rfr2 mega-xplained mips-malta \
msb-430 msb-430h pic32-clicker pic32-wifire telosb \
waspmote-pro wsn430-v1_3b wsn430-v1_4 z1

View File

@ -7,7 +7,7 @@ BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..
BOARD_INSUFFICIENT_MEMORY := chronos msb-430 msb-430h nucleo-f030r8 nucleo-l053r8 \
BOARD_INSUFFICIENT_MEMORY := chronos hifive1 msb-430 msb-430h nucleo-f030r8 nucleo-l053r8 \
nucleo-f031k6 nucleo-f042k6 nucleo-l031k6 \
stm32f0discovery telosb wsn430-v1_3b wsn430-v1_4 \
z1

View File

@ -0,0 +1,19 @@
# Target architecture for the build.
export TARGET_ARCH ?= riscv-none-embed
# define build specific options
CFLAGS_CPU = -march=rv32imac -mabi=ilp32 -mcmodel=medlow -msmall-data-limit=8
CFLAGS_LINK = -nostartfiles -ffunction-sections -fdata-sections
CFLAGS_DBG ?= -g3 -Og
#CFLAGS_OPT ?= -Os
export LINKFLAGS += -L$(RIOTCPU)/$(CPU)/ldscripts
export LINKER_SCRIPT ?= $(CPU_MODEL).ld
export LINKFLAGS += -T$(LINKER_SCRIPT)
# export compiler flags
export CFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) $(CFLAGS_OPT) $(CFLAGS_LINK)
# export assmebly flags
export ASFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG)
# export linker flags
export LINKFLAGS += $(CFLAGS_CPU) $(CFLAGS_LINK) $(CFLAGS_DBG) $(CFLAGS_OPT) -Wl,--gc-sections -static -lgcc

View File

@ -1,6 +1,6 @@
include ../Makefile.tests_common
BOARD_INSUFFICIENT_MEMORY := chronos msb-430 msb-430h nucleo-f031k6 nucleo-f042k6 \
BOARD_INSUFFICIENT_MEMORY := chronos hifive1 msb-430 msb-430h nucleo-f031k6 nucleo-f042k6 \
nucleo-f303k8 nucleo-l031k6 nucleo-f030r8 nucleo-f070rb \
nucleo-f072rb nucleo-f302r8 nucleo-f303re nucleo-f334r8 \
nucleo-l053r8 stm32f0discovery telosb wsn430-v1_3b \

View File

@ -1,7 +1,7 @@
include ../Makefile.tests_common
BOARD_INSUFFICIENT_MEMORY := airfy-beacon b-l072z-lrwan1 bluepill calliope-mini \
cc2650-launchpad cc2650stk chronos maple-mini \
cc2650-launchpad cc2650stk chronos hifive1 maple-mini \
microbit msb-430 msb-430h nrf51dongle nrf6310 \
nucleo-f030r8 nucleo-f070rb nucleo-f072rb nucleo-f103rb \
nucleo-f302r8 nucleo-f334r8 nucleo-l053r8 nucleo-l073rz \

View File

@ -10,7 +10,7 @@ TCP_TEST_CYCLES ?= 3
# Mark Boards with insufficient memory
BOARD_INSUFFICIENT_MEMORY := airfy-beacon arduino-duemilanove arduino-mega2560 \
arduino-uno calliope-mini chronos mega-xplained microbit \
arduino-uno calliope-mini chronos hifive1 mega-xplained microbit \
msb-430 msb-430h nrf51dongle nrf6310 nucleo-f031k6 \
nucleo-f042k6 nucleo-f303k8 nucleo-l031k6 nucleo-f030r8 \
nucleo-f070rb nucleo-f072rb nucleo-f302r8 nucleo-f334r8 nucleo-l053r8 \

View File

@ -10,7 +10,7 @@ TCP_TEST_CYCLES ?= 3
# Mark Boards with insufficient memory
BOARD_INSUFFICIENT_MEMORY := airfy-beacon arduino-duemilanove arduino-mega2560 \
arduino-uno calliope-mini chronos mega-xplained \
arduino-uno calliope-mini chronos hifive1 mega-xplained \
microbit msb-430 msb-430h nrf51dongle nrf6310 nucleo-f031k6 \
nucleo-f042k6 nucleo-f303k8 nucleo-l031k6 nucleo-f030r8 \
nucleo-f070rb nucleo-f072rb nucleo-f302r8 nucleo-f334r8 nucleo-l053r8 \

View File

@ -5,7 +5,7 @@ include ../Makefile.tests_common
BOARD_BLACKLIST := arduino-uno arduino-duemilanove arduino-mega2560 chronos \
msb-430 msb-430h telosb waspmote-pro wsn430-v1_3b \
wsn430-v1_4 z1 jiminy-mega256rfr2 mega-xplained
BOARD_INSUFFICIENT_MEMORY := airfy-beacon nrf6310 nucleo-f031k6 nucleo-f042k6 \
BOARD_INSUFFICIENT_MEMORY := airfy-beacon hifive1 nrf6310 nucleo-f031k6 nucleo-f042k6 \
nucleo-l031k6 nucleo-f030r8 nucleo-f334r8 nucleo-l053r8 \
stm32f0discovery yunjia-nrf51822