mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2026-08-17 09:33:32 +08:00
Added port for the OpenHW CORE-V MCU platform (#535)
Adds a complete ThreadX port for the OpenHW CORE-V MCU SoC, targeting the Digilent Nexys A7 FPGA board with an Ashling Opella-LD debug probe.
New files
---------
cmake/riscv64-gcc-rv32imc.cmake
CMake toolchain file for riscv64-unknown-elf-gcc targeting rv32imc_zicsr/ilp32.
ports/risc-v32/gnu/example_build/core_v_mcu/ -- Full BSP + demo application:
Assembly
crt0.S C runtime startup (BSS clear, GP/SP init, call main)
vectors.S 32-entry vectored interrupt table at 0x1c000800
tx_initialize_low_level.S mtvec setup (vectored mode), stack/free-mem pointers
BSP drivers (bsp/)
system_core_v_mcu.c Top-level init and ISR dispatcher (isr_table[32])
irq.c PULP APB interrupt controller (enable/disable/mask)
timer_irq.c PULP FC Timer -- 100 Hz tick from 10 MHz SOC clock
fll.c Frequency Locked Loop -- 5 MHz to 50 MHz (FPGA)
uart_driver.c UDMA UART channel 0 -- polled TX, non-blocking RX (8-bit transfer width)
gpio.c PULP apb_gpiov2 driver: set/clear/toggle/direction by pin index;
pad-mux via per-pad indexed registers at APB_SOC_CTRL + 0x400 + pad*4;
full pinmux API (gpio_setpinmux, gpio_getpinmux, gpio_pin_set_dir,
gpio_pin_read_status)
i2c_master.c Polled UDMA I2C master
adt7420.c ADT7420 temperature sensor driver
string.c Freestanding memset/memcpy shim (no newlib)
Headers (include/)
Peripheral register maps, MMIO inlines, BSP API declarations, tx_user.h
Application
demo_threadx.c Two threads: LED[0] blink at 1 Hz (IO pad 11, GPIO pin 4, MUX=2)
+ UART heartbeat with startup banner
("Eclipse ThreadX for OpenHW CORE-V MCU vX.Y.Z.BBBBB")
link.ld Linker script: .vectors@0x1c000800, .text@0x1c000880
CMakeLists.txt Build definition (references THREADX_ROOT)
build.sh One-shot CMake+Ninja build script
Tooling
install_deps.sh Automates toolchain/OpenOCD dependency setup
deploy.sh One-step GDB flashing via Ashling Opella-LD;
gdb-multiarch fallback when riscv64-unknown-elf-gdb is absent;
supports --wsl flag required by usbipd-win v5.x
openocd-nexys-Ashling-Opella-LD.cfg OpenOCD config for Opella-LD over JTAG
Tests (tests/)
test_irq.c / test_timer.c Host-compiled unit tests (2/2 pass)
mock/mmio_mock.* Software MMIO register map for host testing
Documentation
README.md Hardware overview, build, flash/debug, BSP API reference
Architecture notes
------------------
- CV32E40P uses the PULP/PULPissimo interrupt controller (not CLINT); IRQ lines
are masked via APB registers, not the mie CSR.
- mtvec must be 256-byte aligned; vectors placed at 0x1c000800 (vectored mode).
- Timer IRQ = line 10; dispatch via isr_table[mcause & 0x1f].
- Build: -march=rv32imc_zicsr -mabi=ilp32, -ffreestanding, -nodefaultlibs.
- Verified: ELF 11 KB text, sections at correct addresses, unit tests pass.
Third-party attributions
------------------------
BSP files derived from core-v-freertos (Apache-2.0):
(c) 2019-2020 ETH Zurich and University of Bologna
(c) 2020 GreenWaves Technologies
(c) 2011-2014 Wind River Systems, Inc.
(c) 2017 SiFive Inc. (crt0.S, BSD-2-Clause portions)
All original copyright notices retained; see individual file headers.
SPDX: Apache-2.0 AND MIT (crt0.S: (Apache-2.0 OR BSD-2-Clause) AND MIT).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# /***************************************************************************
|
||||
# * Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
# *
|
||||
# * This program and the accompanying materials are made available under the
|
||||
# * terms of the MIT License which is available at
|
||||
# * https://opensource.org/licenses/MIT.
|
||||
# *
|
||||
# * AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
# * The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
# * and not subject to the project's licence. The human contributor has
|
||||
# * reviewed and verified that the code is correct.
|
||||
# *
|
||||
# * SPDX-License-Identifier: MIT and CC0-1.0
|
||||
# ***************************************************************************/
|
||||
|
||||
# CMake toolchain file for CORE-V MCU (CV32E40P, RV32IMC)
|
||||
#
|
||||
# Uses the riscv64-unknown-elf-gcc multi-lib toolchain (Ubuntu package
|
||||
# gcc-riscv64-unknown-elf) to cross-compile for a 32-bit RISC-V target.
|
||||
#
|
||||
# Target ISA : rv32imc_zicsr (integer, multiply, compressed, Zicsr)
|
||||
# ABI : ilp32 (32-bit int/long/ptr, no hardware FP)
|
||||
# Code model : medlow (addresses in [0, 2 GiB))
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR riscv)
|
||||
|
||||
set(THREADX_ARCH "risc-v32")
|
||||
set(THREADX_TOOLCHAIN "gnu")
|
||||
|
||||
set(ARCH_FLAGS "-march=rv32imc_zicsr -mabi=ilp32 -mcmodel=medlow")
|
||||
set(CFLAGS "${ARCH_FLAGS}")
|
||||
set(ASFLAGS "${ARCH_FLAGS}")
|
||||
set(LDFLAGS "${ARCH_FLAGS}")
|
||||
|
||||
# Toolchain binaries (riscv64-unknown-elf can target rv32 via multilib)
|
||||
set(CMAKE_C_COMPILER riscv64-unknown-elf-gcc)
|
||||
set(CMAKE_CXX_COMPILER riscv64-unknown-elf-g++)
|
||||
set(AS riscv64-unknown-elf-as)
|
||||
set(AR riscv64-unknown-elf-ar)
|
||||
set(OBJCOPY riscv64-unknown-elf-objcopy)
|
||||
set(OBJDUMP riscv64-unknown-elf-objdump)
|
||||
set(SIZE riscv64-unknown-elf-size)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
# Use static library for compiler feature probing (no linker script yet)
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CFLAGS}" CACHE INTERNAL "c compiler flags")
|
||||
set(CMAKE_CXX_FLAGS "${CFLAGS}" CACHE INTERNAL "cxx compiler flags")
|
||||
set(CMAKE_ASM_FLAGS "${ASFLAGS} -D__ASSEMBLER__" CACHE INTERNAL "asm compiler flags")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${LDFLAGS}" CACHE INTERNAL "exe link flags")
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "c debug flags")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "cxx debug flags")
|
||||
set(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug flags")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "-Os" CACHE INTERNAL "c release flags")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-Os" CACHE INTERNAL "cxx release flags")
|
||||
set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release flags")
|
||||
@@ -0,0 +1,65 @@
|
||||
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
|
||||
|
||||
project(demo_threadx_core_v_mcu LANGUAGES C ASM)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CORE_V_MCU_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
set(THREADX_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../../..)
|
||||
set(TX_USER_FILE ${CORE_V_MCU_DIR}/include/tx_user.h)
|
||||
|
||||
set(THREADX_ARCH "risc-v32")
|
||||
set(THREADX_TOOLCHAIN "gnu")
|
||||
add_subdirectory(${THREADX_ROOT} threadx)
|
||||
target_include_directories(threadx PRIVATE ${CORE_V_MCU_DIR}/include)
|
||||
|
||||
set(SRCS
|
||||
${CORE_V_MCU_DIR}/crt0.S
|
||||
${CORE_V_MCU_DIR}/vectors.S
|
||||
${CORE_V_MCU_DIR}/tx_initialize_low_level.S
|
||||
${CORE_V_MCU_DIR}/bsp/irq.c
|
||||
${CORE_V_MCU_DIR}/bsp/timer_irq.c
|
||||
${CORE_V_MCU_DIR}/bsp/fll.c
|
||||
${CORE_V_MCU_DIR}/bsp/gpio.c
|
||||
${CORE_V_MCU_DIR}/bsp/uart_driver.c
|
||||
${CORE_V_MCU_DIR}/bsp/i2c_master.c
|
||||
${CORE_V_MCU_DIR}/bsp/temp_sensor.c
|
||||
${CORE_V_MCU_DIR}/bsp/system_core_v_mcu.c
|
||||
${CORE_V_MCU_DIR}/bsp/string.c
|
||||
${CORE_V_MCU_DIR}/demo_threadx.c
|
||||
)
|
||||
|
||||
add_executable(demo_threadx ${SRCS})
|
||||
set_target_properties(demo_threadx PROPERTIES OUTPUT_NAME "demo_threadx.elf")
|
||||
|
||||
target_include_directories(demo_threadx PRIVATE
|
||||
${CORE_V_MCU_DIR}/include
|
||||
${THREADX_ROOT}/common/inc
|
||||
${THREADX_ROOT}/ports/risc-v32/gnu/inc
|
||||
)
|
||||
|
||||
target_link_libraries(demo_threadx PRIVATE threadx gcc)
|
||||
|
||||
target_link_options(demo_threadx PRIVATE
|
||||
-T${CORE_V_MCU_DIR}/link.ld
|
||||
-nostartfiles
|
||||
-nodefaultlibs
|
||||
-Wl,--gc-sections
|
||||
-Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/demo_threadx.map
|
||||
)
|
||||
|
||||
target_compile_options(demo_threadx PRIVATE
|
||||
-Os
|
||||
-g
|
||||
-Wall
|
||||
-Wextra
|
||||
-ffreestanding
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-DTX_INCLUDE_USER_DEFINE_FILE
|
||||
)
|
||||
|
||||
add_custom_command(TARGET demo_threadx POST_BUILD
|
||||
COMMAND ${OBJCOPY} -O binary $<TARGET_FILE:demo_threadx> ${CMAKE_CURRENT_BINARY_DIR}/demo_threadx.bin
|
||||
COMMENT "Generating demo_threadx.bin"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,209 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright 2020 GreenWaves Technologies
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bits.h"
|
||||
#include "csr.h"
|
||||
#include "fll.h"
|
||||
#include "irq.h"
|
||||
#include "properties.h"
|
||||
#include "system_core_v_mcu.h"
|
||||
|
||||
#define FLL_LOG2_MAXDCO 29U
|
||||
#define FLL_LOG2_REFCLK ARCHI_REF_CLOCK_LOG2
|
||||
#define FLL_LOG2_MAXM (FLL_LOG2_MAXDCO - FLL_LOG2_REFCLK)
|
||||
|
||||
static volatile uint32_t flls_frequency[FLL_NUM];
|
||||
|
||||
static uint32_t fll_max_u32(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
static uint32_t fll_fl1(uint32_t value)
|
||||
{
|
||||
return (uint32_t)(31U - (uint32_t)__builtin_clz(value));
|
||||
}
|
||||
|
||||
static uint32_t fll_get_mult_div_from_frequency(uint32_t freq, uint32_t *mult,
|
||||
uint32_t *div)
|
||||
{
|
||||
uint32_t fref = FLL_REF_CLK;
|
||||
uint32_t log2_m;
|
||||
uint32_t d;
|
||||
uint32_t m;
|
||||
uint32_t fres;
|
||||
|
||||
if ((freq == 0U) || (mult == NULL) || (div == NULL))
|
||||
{
|
||||
if (mult != NULL)
|
||||
{
|
||||
*mult = 0U;
|
||||
}
|
||||
if (div != NULL)
|
||||
{
|
||||
*div = 0U;
|
||||
}
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if (freq > fref)
|
||||
{
|
||||
log2_m = fll_fl1(freq) - fll_fl1(fref);
|
||||
}
|
||||
else
|
||||
{
|
||||
log2_m = 0U;
|
||||
}
|
||||
|
||||
if (FLL_LOG2_MAXM > log2_m)
|
||||
{
|
||||
d = fll_max_u32(1U, (FLL_LOG2_MAXM - log2_m) >> 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
d = 1U;
|
||||
}
|
||||
|
||||
m = (freq << d) / fref;
|
||||
fres = (fref * m + (1UL << (d - 1U))) >> d;
|
||||
|
||||
*mult = m;
|
||||
*div = d + 1U;
|
||||
return fres;
|
||||
}
|
||||
|
||||
static uint32_t fll_get_frequency_from_mult_div(uint32_t mult, uint32_t div)
|
||||
{
|
||||
uint32_t fref = FLL_REF_CLK;
|
||||
|
||||
if (div == 0U)
|
||||
{
|
||||
return fref * mult;
|
||||
}
|
||||
|
||||
return (fref * mult) >> (div - 1U);
|
||||
}
|
||||
|
||||
int pi_fll_set_frequency(fll_type_t which_fll, uint32_t frequency, int check)
|
||||
{
|
||||
uint32_t mult;
|
||||
uint32_t div;
|
||||
uint32_t reg1;
|
||||
uint32_t saved_irq;
|
||||
|
||||
(void)check;
|
||||
|
||||
if ((uint32_t)which_fll >= FLL_NUM)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (frequency == 0U)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
saved_irq = irq_clint_disable();
|
||||
(void)fll_get_mult_div_from_frequency(frequency, &mult, &div);
|
||||
|
||||
reg1 = FLL_CTRL[which_fll].FLL_CONF1;
|
||||
reg1 &= ~FLL_CTRL_CONF1_MULTI_FACTOR_MASK;
|
||||
reg1 |= REG_SET(FLL_CTRL_CONF1_MULTI_FACTOR, mult);
|
||||
reg1 &= ~FLL_CTRL_CONF1_CLK_OUT_DIV_MASK;
|
||||
reg1 |= REG_SET(FLL_CTRL_CONF1_CLK_OUT_DIV, div);
|
||||
FLL_CTRL[which_fll].FLL_CONF1 = reg1;
|
||||
|
||||
flls_frequency[which_fll] = frequency;
|
||||
if (which_fll == FLL_SOC)
|
||||
{
|
||||
system_core_clock = frequency;
|
||||
}
|
||||
|
||||
if ((saved_irq & MSTATUS_IE) != 0U)
|
||||
{
|
||||
(void)irq_clint_enable();
|
||||
}
|
||||
|
||||
return (int)frequency;
|
||||
}
|
||||
|
||||
void pi_fll_init(fll_type_t which_fll, uint32_t ret_state)
|
||||
{
|
||||
uint32_t reg1;
|
||||
|
||||
if ((uint32_t)which_fll >= FLL_NUM)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret_state != 0U)
|
||||
{
|
||||
(void)pi_fll_get_frequency(which_fll, 1U);
|
||||
return;
|
||||
}
|
||||
|
||||
reg1 = FLL_CTRL[which_fll].FLL_CONF1;
|
||||
if (REG_GET(FLL_CTRL_CONF1_MODE, reg1) == 0U)
|
||||
{
|
||||
uint32_t reg2 = FLL_CTRL[which_fll].FLL_CONF2;
|
||||
uint32_t regint = FLL_CTRL[which_fll].FLL_INTEGRATOR;
|
||||
|
||||
reg2 &= ~FLL_CTRL_CONF2_ASSERT_CYCLES_MASK;
|
||||
reg2 |= REG_SET(FLL_CTRL_CONF2_ASSERT_CYCLES, 0x6U);
|
||||
reg2 &= ~FLL_CTRL_CONF2_LOCK_TOLERANCE_MASK;
|
||||
reg2 |= REG_SET(FLL_CTRL_CONF2_LOCK_TOLERANCE, 0x50U);
|
||||
FLL_CTRL[which_fll].FLL_CONF2 = reg2;
|
||||
|
||||
regint &= ~FLL_CTRL_INTEGRATOR_INT_PART_MASK;
|
||||
regint |= REG_SET(FLL_CTRL_INTEGRATOR_INT_PART, 332U);
|
||||
FLL_CTRL[which_fll].FLL_INTEGRATOR = regint;
|
||||
|
||||
reg1 &= ~FLL_CTRL_CONF1_OUTPUT_LOCK_EN_MASK;
|
||||
reg1 |= REG_SET(FLL_CTRL_CONF1_OUTPUT_LOCK_EN, 1U);
|
||||
reg1 &= ~FLL_CTRL_CONF1_MODE_MASK;
|
||||
reg1 |= REG_SET(FLL_CTRL_CONF1_MODE, 1U);
|
||||
FLL_CTRL[which_fll].FLL_CONF1 = reg1;
|
||||
}
|
||||
|
||||
if (flls_frequency[which_fll] != 0U)
|
||||
{
|
||||
(void)pi_fll_set_frequency(which_fll, flls_frequency[which_fll], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
flls_frequency[which_fll] = fll_get_frequency_from_mult_div(
|
||||
REG_GET(FLL_CTRL_CONF1_MULTI_FACTOR, reg1),
|
||||
REG_GET(FLL_CTRL_CONF1_CLK_OUT_DIV, reg1));
|
||||
}
|
||||
}
|
||||
|
||||
int pi_fll_get_frequency(fll_type_t which_fll, uint8_t real)
|
||||
{
|
||||
if ((uint32_t)which_fll >= FLL_NUM)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (real != 0U)
|
||||
{
|
||||
flls_frequency[which_fll] = fll_get_frequency_from_mult_div(
|
||||
FLL_CTRL[which_fll].FLL_STATUS,
|
||||
REG_GET(FLL_CTRL_CONF1_CLK_OUT_DIV, FLL_CTRL[which_fll].FLL_CONF1));
|
||||
}
|
||||
|
||||
return (int)flls_frequency[which_fll];
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "pulp_mem_map.h"
|
||||
#include "io.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/* APB SOC CTRL pad-mux interface (apb_soc_ctrl v1.0.0):
|
||||
* Each IO pad has a dedicated 32-bit register at base + 0x400 + pad_index*4.
|
||||
* PWDATA[1:0] = mux function (0=sys, 1=perio, 2=apbio/GPIO, 3=fpgaio)
|
||||
* PWDATA[13:8] = pad config (drive/pull, optional)
|
||||
*
|
||||
* FUNC_C (2) routes the pad to the GPIO (apbio) controller.
|
||||
* For the standard GPIO pins: io_pad = gpio_pin + GPIO_IO_PAD_OFFSET (=7).
|
||||
* Verified in pad_control.sv: apbio[N] ↔ io_pad[N+7] when pad_mux[N+7]==2. */
|
||||
#define APB_SOC_PADMUX_BASE 0x400U
|
||||
#define PINMUX_FUNC_C 2U
|
||||
#define GPIO_IO_PAD_OFFSET 7U
|
||||
|
||||
static void gpio_pinmux_set_func_c(uint32_t pin_mask)
|
||||
{
|
||||
for (uint32_t gpio_pin = 0U; gpio_pin < 32U; gpio_pin++)
|
||||
{
|
||||
if ((pin_mask & (1UL << gpio_pin)) == 0U)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
uint32_t io_pad = gpio_pin + GPIO_IO_PAD_OFFSET;
|
||||
uintptr_t reg = PULP_APB_SOC_CTRL_ADDR + APB_SOC_PADMUX_BASE
|
||||
+ io_pad * 4U;
|
||||
writew(PINMUX_FUNC_C, reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate over every set bit in pin_mask and call writew(pin_number, addr).
|
||||
* The apb_gpiov2 SETGPIO/CLRGPIO/TOGGPIO/SETDIR registers are all
|
||||
* pin-indexed: the written word encodes a pin number, not a bitmask. */
|
||||
static void gpio_foreach_pin(uint32_t pin_mask, uintptr_t reg_addr, uint32_t extra_bits)
|
||||
{
|
||||
for (uint32_t pin = 0U; pin < 32U; pin++)
|
||||
{
|
||||
if ((pin_mask & (1UL << pin)) != 0U)
|
||||
{
|
||||
writew(pin | extra_bits, reg_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_init(void)
|
||||
{
|
||||
/* GPIO clocking is handled by platform boot code on CORE-V MCU. */
|
||||
}
|
||||
|
||||
void gpio_set_output(uint32_t pin_mask)
|
||||
{
|
||||
/* Route physical pads to the GPIO controller via the pad-mux (FUNC_C). */
|
||||
gpio_pinmux_set_func_c(pin_mask);
|
||||
|
||||
/* Configure each pin as push-pull output via SETDIR. */
|
||||
gpio_foreach_pin(pin_mask,
|
||||
(uintptr_t)(PULP_GPIO_ADDR + GPIO_SETDIR_OFFSET),
|
||||
GPIO_DIR_OUTPUT);
|
||||
}
|
||||
|
||||
void gpio_toggle(uint32_t pin_mask)
|
||||
{
|
||||
gpio_foreach_pin(pin_mask,
|
||||
(uintptr_t)(PULP_GPIO_ADDR + GPIO_TOGGPIO_OFFSET),
|
||||
0U);
|
||||
}
|
||||
|
||||
void gpio_set(uint32_t pin_mask)
|
||||
{
|
||||
gpio_foreach_pin(pin_mask,
|
||||
(uintptr_t)(PULP_GPIO_ADDR + GPIO_SETGPIO_OFFSET),
|
||||
0U);
|
||||
}
|
||||
|
||||
void gpio_clear(uint32_t pin_mask)
|
||||
{
|
||||
gpio_foreach_pin(pin_mask,
|
||||
(uintptr_t)(PULP_GPIO_ADDR + GPIO_CLRGPIO_OFFSET),
|
||||
0U);
|
||||
}
|
||||
|
||||
void gpio_setpinmux(uint8_t io_pad, uint8_t mux)
|
||||
{
|
||||
uintptr_t reg = PULP_APB_SOC_CTRL_ADDR + APB_SOC_PADMUX_BASE
|
||||
+ (uintptr_t)io_pad * 4U;
|
||||
writew((uint32_t)mux & 0x3U, reg);
|
||||
}
|
||||
|
||||
uint8_t gpio_getpinmux(uint8_t io_pad)
|
||||
{
|
||||
uintptr_t reg = PULP_APB_SOC_CTRL_ADDR + APB_SOC_PADMUX_BASE
|
||||
+ (uintptr_t)io_pad * 4U;
|
||||
return (uint8_t)(readw(reg) & 0x3U);
|
||||
}
|
||||
|
||||
void gpio_pin_set_dir(uint8_t pin, uint8_t dir)
|
||||
{
|
||||
uint32_t val = (uint32_t)pin;
|
||||
if (dir != 0U)
|
||||
{
|
||||
val |= GPIO_DIR_OUTPUT;
|
||||
}
|
||||
writew(val, (uintptr_t)(PULP_GPIO_ADDR + GPIO_SETDIR_OFFSET));
|
||||
}
|
||||
|
||||
uint32_t gpio_pin_read_status(uint8_t pin)
|
||||
{
|
||||
writew((uint32_t)pin, (uintptr_t)(PULP_GPIO_ADDR + GPIO_SETSEL_OFFSET));
|
||||
return readw((uintptr_t)(PULP_GPIO_ADDR + GPIO_RDSTAT_OFFSET));
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bits.h"
|
||||
#include "i2c_master.h"
|
||||
#include "io.h"
|
||||
#include "pulp_mem_map.h"
|
||||
|
||||
#define UDMA_I2C_RX_SADDR_OFFSET 0x00U
|
||||
#define UDMA_I2C_RX_SIZE_OFFSET 0x04U
|
||||
#define UDMA_I2C_RX_CFG_OFFSET 0x08U
|
||||
#define UDMA_I2C_TX_SADDR_OFFSET 0x10U
|
||||
#define UDMA_I2C_TX_SIZE_OFFSET 0x14U
|
||||
#define UDMA_I2C_TX_CFG_OFFSET 0x18U
|
||||
#define UDMA_I2C_STATUS_OFFSET 0x20U
|
||||
#define UDMA_I2C_SETUP_OFFSET 0x24U
|
||||
|
||||
#define UDMA_CTRL_CG_OFFSET 0x00U
|
||||
#define UDMA_CFG_EN_BIT BIT(4)
|
||||
#define UDMA_CFG_PENDING_BIT BIT(5)
|
||||
#define UDMA_I2C_STATUS_AL_BIT BIT(1)
|
||||
#define UDMA_I2C_SETUP_RESET_BIT BIT(0)
|
||||
#define I2C_MASTER_COUNT 2U
|
||||
#define I2C_TIMEOUT_ITERATIONS 1000000U
|
||||
|
||||
#define I2C_CMD_CFG 0xE0U
|
||||
#define I2C_CMD_START 0x00U
|
||||
#define I2C_CMD_STOP 0x20U
|
||||
#define I2C_CMD_RD_ACK 0x40U
|
||||
#define I2C_CMD_RD_NACK 0x60U
|
||||
#define I2C_CMD_WR 0x80U
|
||||
#define I2C_CMD_WAIT 0xA0U
|
||||
#define I2C_CMD_RPT 0xC0U
|
||||
|
||||
static uint8_t s_cmd_buf[32];
|
||||
static uint8_t s_clkdiv[I2C_MASTER_COUNT];
|
||||
|
||||
static uintptr_t i2c_master_base(uint8_t id)
|
||||
{
|
||||
return (id == 0U) ? (uintptr_t)UDMA_CH_ADDR_I2CM0 : (uintptr_t)UDMA_CH_ADDR_I2CM1;
|
||||
}
|
||||
|
||||
int i2c_master_init(uint8_t id, uint32_t i2c_freq, uint32_t periph_freq)
|
||||
{
|
||||
uint32_t cg;
|
||||
uint32_t clk_div;
|
||||
uintptr_t base;
|
||||
|
||||
if ((id >= I2C_MASTER_COUNT) || (i2c_freq == 0U) || (periph_freq == 0U))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
cg = readw((uintptr_t)(UDMA_CH_ADDR_CTRL + UDMA_CTRL_CG_OFFSET));
|
||||
cg |= (id == 0U) ? UDMA_CTRL_I2CM0_CLKEN : UDMA_CTRL_I2CM1_CLKEN;
|
||||
writew(cg, (uintptr_t)(UDMA_CH_ADDR_CTRL + UDMA_CTRL_CG_OFFSET));
|
||||
|
||||
clk_div = periph_freq / i2c_freq;
|
||||
if (clk_div == 0U)
|
||||
{
|
||||
clk_div = 1U;
|
||||
}
|
||||
else if (clk_div > 255U)
|
||||
{
|
||||
clk_div = 255U;
|
||||
}
|
||||
s_clkdiv[id] = (uint8_t)clk_div;
|
||||
|
||||
base = i2c_master_base(id);
|
||||
writew(UDMA_I2C_SETUP_RESET_BIT, base + UDMA_I2C_SETUP_OFFSET);
|
||||
writew(0U, base + UDMA_I2C_SETUP_OFFSET);
|
||||
writew(0U, base + UDMA_I2C_RX_CFG_OFFSET);
|
||||
writew(0U, base + UDMA_I2C_TX_CFG_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_master_read_reg(uint8_t id, uint8_t dev_addr7, uint8_t reg_addr,
|
||||
uint8_t *buf, uint8_t len)
|
||||
{
|
||||
uintptr_t base;
|
||||
uint32_t timeout;
|
||||
uint32_t cmd_len;
|
||||
uint32_t status;
|
||||
|
||||
if ((id >= I2C_MASTER_COUNT) || (dev_addr7 > 0x7FU) || (buf == NULL) || (len == 0U))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd_len = 0U;
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_CFG;
|
||||
s_cmd_buf[cmd_len++] = 0U;
|
||||
s_cmd_buf[cmd_len++] = s_clkdiv[id];
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_START;
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_WR;
|
||||
s_cmd_buf[cmd_len++] = (uint8_t)(dev_addr7 << 1U);
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_WR;
|
||||
s_cmd_buf[cmd_len++] = reg_addr;
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_START;
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_WR;
|
||||
s_cmd_buf[cmd_len++] = (uint8_t)((dev_addr7 << 1U) | 1U);
|
||||
if (len > 1U)
|
||||
{
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_RPT;
|
||||
s_cmd_buf[cmd_len++] = (uint8_t)(len - 1U);
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_RD_ACK;
|
||||
}
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_RD_NACK;
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_STOP;
|
||||
s_cmd_buf[cmd_len++] = I2C_CMD_WAIT;
|
||||
s_cmd_buf[cmd_len++] = 0U;
|
||||
|
||||
base = i2c_master_base(id);
|
||||
writew((uint32_t)(uintptr_t)buf, base + UDMA_I2C_RX_SADDR_OFFSET);
|
||||
writew((uint32_t)len, base + UDMA_I2C_RX_SIZE_OFFSET);
|
||||
writew(UDMA_CFG_EN_BIT, base + UDMA_I2C_RX_CFG_OFFSET);
|
||||
|
||||
writew((uint32_t)(uintptr_t)s_cmd_buf, base + UDMA_I2C_TX_SADDR_OFFSET);
|
||||
writew(cmd_len, base + UDMA_I2C_TX_SIZE_OFFSET);
|
||||
writew(UDMA_CFG_EN_BIT, base + UDMA_I2C_TX_CFG_OFFSET);
|
||||
|
||||
for (timeout = 0U; timeout < I2C_TIMEOUT_ITERATIONS; ++timeout)
|
||||
{
|
||||
status = readw(base + UDMA_I2C_STATUS_OFFSET);
|
||||
if ((status & UDMA_I2C_STATUS_AL_BIT) != 0U)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (((readw(base + UDMA_I2C_TX_CFG_OFFSET) & UDMA_CFG_PENDING_BIT) == 0U) &&
|
||||
((readw(base + UDMA_I2C_RX_CFG_OFFSET) & UDMA_CFG_PENDING_BIT) == 0U))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright (C) 2019 ETH Zurich and University of Bologna
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "pulp_mem_map.h"
|
||||
#include "io.h"
|
||||
#include "irq.h"
|
||||
#include "csr.h"
|
||||
|
||||
void irq_mask(uint32_t mask)
|
||||
{
|
||||
writew(mask, (uintptr_t)(PULP_FC_IRQ_ADDR + IRQ_REG_MASK_OFFSET));
|
||||
}
|
||||
|
||||
void irq_enable(uint32_t mask)
|
||||
{
|
||||
writew(mask, (uintptr_t)(PULP_FC_IRQ_ADDR + IRQ_REG_MASK_SET_OFFSET));
|
||||
}
|
||||
|
||||
void irq_disable(uint32_t mask)
|
||||
{
|
||||
writew(mask, (uintptr_t)(PULP_FC_IRQ_ADDR + IRQ_REG_MASK_CLEAR_OFFSET));
|
||||
}
|
||||
|
||||
uint32_t irq_clint_disable(void)
|
||||
{
|
||||
return (uint32_t)csr_read_clear(CSR_MSTATUS, MSTATUS_IE);
|
||||
}
|
||||
|
||||
uint32_t irq_clint_enable(void)
|
||||
{
|
||||
return (uint32_t)csr_read_set(CSR_MSTATUS, MSTATUS_IE);
|
||||
}
|
||||
|
||||
void pulp_irq_init(void)
|
||||
{
|
||||
irq_disable(0xFFFFFFFFUL);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
size_t index;
|
||||
uint8_t *dst = (uint8_t *)dest;
|
||||
const uint8_t *source = (const uint8_t *)src;
|
||||
|
||||
for (index = 0U; index < n; ++index)
|
||||
{
|
||||
dst[index] = source[index];
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *dest, int c, size_t n)
|
||||
{
|
||||
size_t index;
|
||||
uint8_t *dst = (uint8_t *)dest;
|
||||
uint8_t value = (uint8_t)c;
|
||||
|
||||
for (index = 0U; index < n; ++index)
|
||||
{
|
||||
dst[index] = value;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int memcmp(const void *lhs, const void *rhs, size_t n)
|
||||
{
|
||||
size_t index;
|
||||
const uint8_t *left = (const uint8_t *)lhs;
|
||||
const uint8_t *right = (const uint8_t *)rhs;
|
||||
|
||||
for (index = 0U; index < n; ++index)
|
||||
{
|
||||
if (left[index] != right[index])
|
||||
{
|
||||
return (left[index] < right[index]) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "csr.h"
|
||||
#include "fll.h"
|
||||
#include "gpio.h"
|
||||
#include "irq.h"
|
||||
#include "properties.h"
|
||||
#include "system_core_v_mcu.h"
|
||||
#include "timer_irq.h"
|
||||
#include "tx_api.h"
|
||||
#include "uart_driver.h"
|
||||
|
||||
extern void _tx_timer_interrupt(void);
|
||||
|
||||
volatile uint32_t system_core_clock = DEFAULT_SYSTEM_CLOCK;
|
||||
volatile uint32_t last_trap_mcause;
|
||||
void (*isr_table[32])(void);
|
||||
|
||||
static uint32_t uart_console_ready;
|
||||
|
||||
static void uart_write_hex32(uint32_t value)
|
||||
{
|
||||
static const char hex[] = "0123456789ABCDEF";
|
||||
int shift;
|
||||
|
||||
uart_write_str(0U, "0x");
|
||||
for (shift = 28; shift >= 0; shift -= 4)
|
||||
{
|
||||
uart_write_byte(0U, (uint8_t)hex[(value >> (uint32_t)shift) & 0xFU]);
|
||||
}
|
||||
}
|
||||
|
||||
void tx_undefined_irq_handler(void)
|
||||
{
|
||||
if (uart_console_ready != 0U)
|
||||
{
|
||||
uart_write_str(0U, "\r\nUndefined IRQ\r\n");
|
||||
}
|
||||
|
||||
/* MISRA deviation: intentional infinite loop used as a fault sink. */
|
||||
for (;;)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void tx_timer_irq_handler(void)
|
||||
{
|
||||
_tx_timer_interrupt();
|
||||
}
|
||||
|
||||
void system_init(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0U; i < 32U; ++i)
|
||||
{
|
||||
isr_table[i] = tx_undefined_irq_handler;
|
||||
}
|
||||
|
||||
isr_table[7U] = tx_timer_irq_handler;
|
||||
|
||||
for (i = 0U; i < ARCHI_NB_FLL; ++i)
|
||||
{
|
||||
pi_fll_init((fll_type_t)i, 0U);
|
||||
}
|
||||
|
||||
pulp_irq_init();
|
||||
(void)timer_irq_init(ARCHI_SOC_FREQUENCY / (uint32_t)TX_TIMER_TICKS_PER_SECOND);
|
||||
/* CV32E40P routes the FC Timer LO to irq_i[7] (MTI, bit 7), which maps
|
||||
* to mip[7]. IRQ_MASK in cv32e40p_cs_registers forces mie[10] to zero,
|
||||
* so bit 7 is the correct enable bit. mcause will be 0x80000007. */
|
||||
(void)csr_read_set(CSR_MIE, BIT(7));
|
||||
|
||||
gpio_init();
|
||||
if (uart_init(0U, 115200U, ARCHI_FPGA_FREQUENCY) == 0)
|
||||
{
|
||||
uart_console_ready = 1U;
|
||||
}
|
||||
}
|
||||
|
||||
void tx_trap_handler(uint32_t mcause, uint32_t mepc, uint32_t mtval)
|
||||
{
|
||||
last_trap_mcause = mcause;
|
||||
|
||||
if ((mcause & 0x80000000UL) != 0UL)
|
||||
{
|
||||
uint32_t irq_id = mcause & 0x1FUL;
|
||||
|
||||
if (isr_table[irq_id] != NULL)
|
||||
{
|
||||
isr_table[irq_id]();
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_undefined_irq_handler();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uart_console_ready != 0U)
|
||||
{
|
||||
uart_write_str(0U, "\r\nTrap mcause=");
|
||||
uart_write_hex32(mcause);
|
||||
uart_write_str(0U, " mepc=");
|
||||
uart_write_hex32(mepc);
|
||||
uart_write_str(0U, " mtval=");
|
||||
uart_write_hex32(mtval);
|
||||
uart_write_str(0U, "\r\n");
|
||||
}
|
||||
|
||||
/* MISRA deviation: intentional infinite loop used as a fault sink. */
|
||||
for (;;)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "i2c_master.h"
|
||||
#include "properties.h"
|
||||
#include "temp_sensor.h"
|
||||
|
||||
#define ADT7420_I2C_ID 1U
|
||||
#define ADT7420_ADDR7 0x4BU
|
||||
#define ADT7420_TEMP_REG 0x00U
|
||||
#define ADT7420_I2C_FREQ_HZ 200000U
|
||||
|
||||
void temp_sensor_init(void)
|
||||
{
|
||||
(void)i2c_master_init(ADT7420_I2C_ID, ADT7420_I2C_FREQ_HZ, ARCHI_FPGA_FREQUENCY);
|
||||
}
|
||||
|
||||
int16_t temp_read_celsius_x10(void)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
int16_t raw;
|
||||
int16_t value;
|
||||
|
||||
if (i2c_master_read_reg(ADT7420_I2C_ID, ADT7420_ADDR7, ADT7420_TEMP_REG, &buf[0], 2U) != 0)
|
||||
{
|
||||
return INT16_MIN;
|
||||
}
|
||||
|
||||
raw = (int16_t)(((uint16_t)buf[0] << 8U) | (uint16_t)buf[1]);
|
||||
value = (int16_t)(raw >> 3);
|
||||
return (int16_t)(((int32_t)value * 5) / 8);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright (C) 2019 ETH Zurich and University of Bologna
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "pulp_mem_map.h"
|
||||
#include "io.h"
|
||||
#include "timer.h"
|
||||
#include "timer_irq.h"
|
||||
|
||||
static uint32_t last_count;
|
||||
|
||||
int timer_irq_init(uint32_t ticks)
|
||||
{
|
||||
(void)timer_irq_set_timeout(ticks);
|
||||
|
||||
writew(TIMER_CFG_LO_ENABLE_MASK |
|
||||
TIMER_CFG_LO_RESET_MASK |
|
||||
TIMER_CFG_LO_MODE_MASK |
|
||||
TIMER_CFG_LO_IRQEN_MASK,
|
||||
(uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CFG_LO_OFFSET));
|
||||
|
||||
last_count = 0U;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_irq_set_timeout(uint32_t ticks)
|
||||
{
|
||||
writew(1U, (uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_RESET_LO_OFFSET));
|
||||
writew(ticks, (uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CMP_LO_OFFSET));
|
||||
last_count = 0U;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t timer_irq_clock_elapsed(void)
|
||||
{
|
||||
uint32_t current = timer_irq_cycle_get_32();
|
||||
uint32_t elapsed = current - last_count;
|
||||
|
||||
last_count = current;
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
uint32_t timer_irq_cycle_get_32(void)
|
||||
{
|
||||
return readw((uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CNT_LO_OFFSET));
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bits.h"
|
||||
#include "io.h"
|
||||
#include "pulp_mem_map.h"
|
||||
#include "uart_driver.h"
|
||||
|
||||
#define UDMA_CTRL_CG_OFFSET 0x00U
|
||||
#define UDMA_CTRL_UART0_CLKEN BIT(0)
|
||||
|
||||
#define UDMA_UART_RX_SADDR_OFFSET 0x00U
|
||||
#define UDMA_UART_RX_SIZE_OFFSET 0x04U
|
||||
#define UDMA_UART_RX_CFG_OFFSET 0x08U
|
||||
#define UDMA_UART_TX_SADDR_OFFSET 0x10U
|
||||
#define UDMA_UART_TX_SIZE_OFFSET 0x14U
|
||||
#define UDMA_UART_TX_CFG_OFFSET 0x18U
|
||||
#define UDMA_UART_STATUS_OFFSET 0x20U
|
||||
#define UDMA_UART_SETUP_OFFSET 0x24U
|
||||
#define UDMA_UART_VALID_OFFSET 0x30U
|
||||
#define UDMA_UART_DATA_OFFSET 0x34U
|
||||
|
||||
#define UDMA_CFG_EN_BIT BIT(4)
|
||||
/* EN (bit 4) only; DATASIZE=0 for 8-bit transfers; 0x12 would set DATASIZE=1
|
||||
* (16-bit) and cause the EN bit to never clear for single-byte buffers. */
|
||||
#define UDMA_UART_TX_CFG_ENABLE 0x10U
|
||||
#define UDMA_UART_WORDLEN_8_BITS 3U
|
||||
#define UDMA_UART_TX_ENABLE_BIT BIT(8)
|
||||
#define UDMA_UART_RX_ENABLE_BIT BIT(9)
|
||||
#define UDMA_UART_RX_POLLING_BIT BIT(4)
|
||||
#define UDMA_UART_RX_CLEAN_BIT BIT(5)
|
||||
#define UDMA_UART_DIV_SHIFT 16U
|
||||
#define UDMA_UART_VALID_DATA_BIT BIT(0)
|
||||
#define UDMA_UART_STATUS_TX_BUSY BIT(0)
|
||||
#define UDMA_UART_MAX_TRANSFER 0xFFFFU
|
||||
|
||||
static uint8_t uart_tx_byte[N_UART];
|
||||
|
||||
static uintptr_t uart_base(uint8_t uart_id)
|
||||
{
|
||||
return (uintptr_t)(UDMA_CH_ADDR_UART + ((uintptr_t)uart_id * (uintptr_t)UDMA_CH_SIZE));
|
||||
}
|
||||
|
||||
int uart_init(uint8_t uart_id, uint32_t baudrate, uint32_t periph_freq)
|
||||
{
|
||||
uint32_t clk_div;
|
||||
uint32_t setup;
|
||||
uint32_t cg;
|
||||
|
||||
if ((uart_id >= N_UART) || (baudrate == 0U) || (periph_freq == 0U))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
cg = readw((uintptr_t)(UDMA_CH_ADDR_CTRL + UDMA_CTRL_CG_OFFSET));
|
||||
cg |= (uint32_t)(UDMA_CTRL_UART0_CLKEN << uart_id);
|
||||
writew(cg, (uintptr_t)(UDMA_CH_ADDR_CTRL + UDMA_CTRL_CG_OFFSET));
|
||||
|
||||
clk_div = periph_freq / baudrate;
|
||||
if (clk_div == 0U)
|
||||
{
|
||||
clk_div = 1U;
|
||||
}
|
||||
|
||||
setup = (clk_div << UDMA_UART_DIV_SHIFT) |
|
||||
UDMA_UART_TX_ENABLE_BIT |
|
||||
UDMA_UART_RX_ENABLE_BIT |
|
||||
UDMA_UART_RX_POLLING_BIT |
|
||||
UDMA_UART_RX_CLEAN_BIT |
|
||||
(UDMA_UART_WORDLEN_8_BITS << 1U);
|
||||
writew(setup, uart_base(uart_id) + UDMA_UART_SETUP_OFFSET);
|
||||
|
||||
writew(0U, uart_base(uart_id) + UDMA_UART_RX_SADDR_OFFSET);
|
||||
writew(0U, uart_base(uart_id) + UDMA_UART_RX_SIZE_OFFSET);
|
||||
writew(0U, uart_base(uart_id) + UDMA_UART_RX_CFG_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart_write_byte(uint8_t uart_id, uint8_t c)
|
||||
{
|
||||
if (uart_id >= N_UART)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uart_tx_byte[uart_id] = c;
|
||||
uart_write_buf(uart_id, &uart_tx_byte[uart_id], 1U);
|
||||
}
|
||||
|
||||
int uart_read_byte(uint8_t uart_id)
|
||||
{
|
||||
if (uart_id >= N_UART)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((readw(uart_base(uart_id) + UDMA_UART_VALID_OFFSET) & UDMA_UART_VALID_DATA_BIT) == 0U)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)(readw(uart_base(uart_id) + UDMA_UART_DATA_OFFSET) & 0xFFU);
|
||||
}
|
||||
|
||||
void uart_write_str(uint8_t uart_id, const char *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (*str != '\0')
|
||||
{
|
||||
uart_write_byte(uart_id, (uint8_t)*str);
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_write_buf(uint8_t uart_id, const uint8_t *buf, uint32_t len)
|
||||
{
|
||||
uintptr_t base_addr;
|
||||
const uint8_t *current;
|
||||
uint32_t remaining;
|
||||
|
||||
if ((uart_id >= N_UART) || (buf == NULL) || (len == 0U))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
base_addr = uart_base(uart_id);
|
||||
current = buf;
|
||||
remaining = len;
|
||||
|
||||
while (remaining > 0U)
|
||||
{
|
||||
uint32_t chunk = (remaining > UDMA_UART_MAX_TRANSFER) ? UDMA_UART_MAX_TRANSFER : remaining;
|
||||
|
||||
while ((readw(base_addr + UDMA_UART_STATUS_OFFSET) & UDMA_UART_STATUS_TX_BUSY) != 0U)
|
||||
{
|
||||
}
|
||||
|
||||
writew((uint32_t)(uintptr_t)current, base_addr + UDMA_UART_TX_SADDR_OFFSET);
|
||||
writew(chunk, base_addr + UDMA_UART_TX_SIZE_OFFSET);
|
||||
writew(UDMA_UART_TX_CFG_ENABLE, base_addr + UDMA_UART_TX_CFG_OFFSET);
|
||||
|
||||
while ((readw(base_addr + UDMA_UART_TX_CFG_OFFSET) & UDMA_CFG_EN_BIT) != 0U)
|
||||
{
|
||||
}
|
||||
|
||||
current += chunk;
|
||||
remaining -= chunk;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
THREADX_ROOT="${SCRIPT_DIR}/../../../../.."
|
||||
cmake -B "${SCRIPT_DIR}/build" \
|
||||
-G Ninja \
|
||||
-DCMAKE_TOOLCHAIN_FILE="${THREADX_ROOT}/cmake/riscv64-gcc-rv32imc.cmake" \
|
||||
"${SCRIPT_DIR}"
|
||||
cmake --build "${SCRIPT_DIR}/build"
|
||||
@@ -0,0 +1,48 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright 2020 ETH Zurich
|
||||
* Copyright (c) 2017 SiFive Inc. All rights reserved.
|
||||
* Copyright (c) 2019 ETH Zürich and University of Bologna
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0 (Apache-2.0)
|
||||
* or the BSD 2-Clause License (BSD-2-Clause) at your option.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: (Apache-2.0 OR BSD-2-Clause) AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
.section .text.start
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
||||
_start:
|
||||
.option push
|
||||
.option norelax
|
||||
1: auipc gp, %pcrel_hi(__global_pointer$)
|
||||
addi gp, gp, %pcrel_lo(1b)
|
||||
.option pop
|
||||
|
||||
la sp, __stack_top
|
||||
|
||||
la a0, __vector_start
|
||||
ori a0, a0, 1
|
||||
csrw mtvec, a0
|
||||
|
||||
la t0, __bss_start
|
||||
la t1, __bss_end
|
||||
2:
|
||||
bgeu t0, t1, 3f
|
||||
sw zero, 0(t0)
|
||||
addi t0, t0, 4
|
||||
j 2b
|
||||
3:
|
||||
call main
|
||||
4:
|
||||
wfi
|
||||
j 4b
|
||||
|
||||
.size _start, .-_start
|
||||
@@ -0,0 +1,134 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "gpio.h"
|
||||
#include "system_core_v_mcu.h"
|
||||
#include "tx_api.h"
|
||||
#include "uart_driver.h"
|
||||
|
||||
#define DEMO_STACK_SIZE 1024U
|
||||
#define DEMO_BYTE_POOL_SIZE 4096U
|
||||
/*
|
||||
* LED[0] on Nexys A7 = IO pad 11 = GPIO/apbio pin 4 (MUX=2).
|
||||
* Verified in the quick-start guide and the 2022 nexys-pin-table.csv used to
|
||||
* synthesise the pre-built bitfile (io_pad = gpio_pin + 7).
|
||||
*/
|
||||
#define DEMO_LED_PIN 4U
|
||||
#define DEMO_LED_MASK (1UL << DEMO_LED_PIN)
|
||||
|
||||
/* Assemble the version banner string at compile time from tx_api.h constants. */
|
||||
#define _TX_STR(x) #x
|
||||
#define TX_STR(x) _TX_STR(x)
|
||||
#define TX_VERSION_STRING \
|
||||
"v" TX_STR(THREADX_MAJOR_VERSION) \
|
||||
"." TX_STR(THREADX_MINOR_VERSION) \
|
||||
"." TX_STR(THREADX_PATCH_VERSION) \
|
||||
"." TX_STR(THREADX_BUILD_VERSION)
|
||||
|
||||
static const char banner[] =
|
||||
"\r\nEclipse ThreadX for OpenHW CORE-V MCU " TX_VERSION_STRING "\r\n"
|
||||
"Copyright (c) 2026 Eclipse ThreadX Contributors\r\n\r\n";
|
||||
|
||||
static TX_THREAD blinky_thread;
|
||||
static TX_THREAD uart_thread;
|
||||
static TX_BYTE_POOL byte_pool;
|
||||
static uint8_t memory_area[DEMO_BYTE_POOL_SIZE];
|
||||
|
||||
static void demo_error_loop(void)
|
||||
{
|
||||
/* MISRA deviation: intentional infinite loop used as a fault sink. */
|
||||
for (;;)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static void blinky_thread_entry(ULONG arg)
|
||||
{
|
||||
TX_PARAMETER_NOT_USED(arg);
|
||||
|
||||
/* Configure LED[0] as push-pull output (sets pad-mux to FUNC_C = 2). */
|
||||
gpio_set_output((uint32_t)DEMO_LED_MASK);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
gpio_set((uint32_t)DEMO_LED_MASK);
|
||||
tx_thread_sleep(100U); /* 1 s on (100 ticks × 10 ms) */
|
||||
gpio_clear((uint32_t)DEMO_LED_MASK);
|
||||
tx_thread_sleep(100U); /* 1 s off */
|
||||
}
|
||||
}
|
||||
|
||||
static void uart_thread_entry(ULONG arg)
|
||||
{
|
||||
TX_PARAMETER_NOT_USED(arg);
|
||||
|
||||
uart_write_str(0U, banner);
|
||||
for (;;)
|
||||
{
|
||||
uart_write_str(0U, ".");
|
||||
tx_thread_sleep(100U);
|
||||
}
|
||||
}
|
||||
|
||||
void tx_application_define(void *first_unused_memory)
|
||||
{
|
||||
CHAR *stack_ptr = TX_NULL;
|
||||
UINT status;
|
||||
|
||||
TX_PARAMETER_NOT_USED(first_unused_memory);
|
||||
|
||||
status = tx_byte_pool_create(&byte_pool, "demo pool", memory_area, DEMO_BYTE_POOL_SIZE);
|
||||
if (status != TX_SUCCESS)
|
||||
{
|
||||
demo_error_loop();
|
||||
}
|
||||
|
||||
status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
if (status != TX_SUCCESS)
|
||||
{
|
||||
demo_error_loop();
|
||||
}
|
||||
|
||||
status = tx_thread_create(&blinky_thread, "blinky", blinky_thread_entry, 0U,
|
||||
stack_ptr, DEMO_STACK_SIZE, 1U, 1U,
|
||||
TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
if (status != TX_SUCCESS)
|
||||
{
|
||||
demo_error_loop();
|
||||
}
|
||||
|
||||
status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
if (status != TX_SUCCESS)
|
||||
{
|
||||
demo_error_loop();
|
||||
}
|
||||
|
||||
status = tx_thread_create(&uart_thread, "uart", uart_thread_entry, 0U,
|
||||
stack_ptr, DEMO_STACK_SIZE, 2U, 2U,
|
||||
TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
if (status != TX_SUCCESS)
|
||||
{
|
||||
demo_error_loop();
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
system_init();
|
||||
tx_kernel_enter();
|
||||
return 0;
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env bash
|
||||
# /***************************************************************************/
|
||||
# /* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
# *
|
||||
# * This program and the accompanying materials are made available under the
|
||||
# * terms of the MIT License which is available at
|
||||
# * https://opensource.org/licenses/MIT.
|
||||
# *
|
||||
# * AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
# * The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
# * and not subject to the project's licence.
|
||||
# *
|
||||
# * SPDX-License-Identifier: MIT AND CC0-1.0
|
||||
# ***************************************************************************/
|
||||
|
||||
# deploy.sh -- build (optionally), flash, and run/debug the CORE-V MCU target
|
||||
# via the Ashling Opella LD debug probe.
|
||||
#
|
||||
# Usage:
|
||||
# bash deploy.sh [options]
|
||||
#
|
||||
# Options:
|
||||
# --build Run build.sh before flashing (default: skip).
|
||||
# --debug After loading, stop at main and leave GDB attached
|
||||
# (default: run free and exit GDB).
|
||||
# --elf <path> Override the ELF to flash
|
||||
# (default: build/demo_threadx.elf).
|
||||
# --openocd-cfg <p> Override the OpenOCD config file.
|
||||
#
|
||||
# Prerequisites:
|
||||
# * riscv64-unknown-elf-gdb and openocd must be on PATH.
|
||||
# * Run setup_opella.sh once to configure udev rules.
|
||||
# * The Nexys A7 board must be powered on.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# Prefer a bare-metal RISC-V GDB; fall back to gdb-multiarch (Ubuntu apt default)
|
||||
if command -v riscv64-unknown-elf-gdb >/dev/null 2>&1; then
|
||||
GDB="riscv64-unknown-elf-gdb"
|
||||
elif command -v gdb-multiarch >/dev/null 2>&1; then
|
||||
GDB="gdb-multiarch"
|
||||
else
|
||||
GDB="riscv64-unknown-elf-gdb" # will produce a clear error below
|
||||
fi
|
||||
OPENOCD_LOG="/tmp/openocd_demo_threadx.log"
|
||||
OPENOCD_PID=""
|
||||
OPENOCD_TIMEOUT=10
|
||||
|
||||
DEFAULT_ELF="${SCRIPT_DIR}/build/demo_threadx.elf"
|
||||
DEFAULT_CFG="${SCRIPT_DIR}/openocd-nexys-Ashling-Opella-LD.cfg"
|
||||
|
||||
OPT_BUILD=0
|
||||
OPT_DEBUG=0
|
||||
OPT_ELF=""
|
||||
OPT_CFG=""
|
||||
|
||||
usage() { grep '^# ' "$0" | sed 's/^# //' | head -30; exit 0; }
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--build) OPT_BUILD=1; shift ;;
|
||||
--debug) OPT_DEBUG=1; shift ;;
|
||||
--elf) OPT_ELF="$2"; shift 2 ;;
|
||||
--openocd-cfg) OPT_CFG="$2"; shift 2 ;;
|
||||
-h|--help) usage ;;
|
||||
*) echo "[ERROR] Unknown option: $1" >&2; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
ELF="${OPT_ELF:-${DEFAULT_ELF}}"
|
||||
CFG="${OPT_CFG:-${DEFAULT_CFG}}"
|
||||
|
||||
info() { echo "[INFO] $*"; }
|
||||
die() { echo "[ERROR] $*" >&2; exit 1; }
|
||||
|
||||
stop_openocd() {
|
||||
if [ -n "${OPENOCD_PID}" ] && kill -0 "${OPENOCD_PID}" 2>/dev/null; then
|
||||
info "Stopping OpenOCD (PID ${OPENOCD_PID}) ..."
|
||||
kill "${OPENOCD_PID}" 2>/dev/null || true
|
||||
wait "${OPENOCD_PID}" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
trap stop_openocd EXIT INT TERM
|
||||
|
||||
if [ "${OPT_BUILD}" -eq 1 ]; then
|
||||
info "Running build.sh ..."
|
||||
bash "${SCRIPT_DIR}/build.sh"
|
||||
fi
|
||||
|
||||
[ -f "${ELF}" ] || die "ELF not found: ${ELF} (run with --build to build first)"
|
||||
[ -f "${CFG}" ] || die "OpenOCD config not found: ${CFG}"
|
||||
command -v openocd >/dev/null 2>&1 || die "openocd not found on PATH"
|
||||
command -v "${GDB}" >/dev/null 2>&1 || die "${GDB} not found on PATH"
|
||||
|
||||
info "Starting OpenOCD with config: ${CFG}"
|
||||
info "Log: ${OPENOCD_LOG}"
|
||||
openocd -f "${CFG}" >"${OPENOCD_LOG}" 2>&1 &
|
||||
OPENOCD_PID=$!
|
||||
|
||||
info "Waiting for OpenOCD to be ready (up to ${OPENOCD_TIMEOUT}s) ..."
|
||||
ELAPSED=0
|
||||
while ! grep -q "Ready for Remote Connections" "${OPENOCD_LOG}" 2>/dev/null; do
|
||||
sleep 1
|
||||
ELAPSED=$((ELAPSED + 1))
|
||||
if [ "${ELAPSED}" -ge "${OPENOCD_TIMEOUT}" ]; then
|
||||
echo "--- OpenOCD log ---" && cat "${OPENOCD_LOG}"
|
||||
die "OpenOCD did not become ready within ${OPENOCD_TIMEOUT}s"
|
||||
fi
|
||||
if ! kill -0 "${OPENOCD_PID}" 2>/dev/null; then
|
||||
echo "--- OpenOCD log ---" && cat "${OPENOCD_LOG}"
|
||||
die "OpenOCD exited unexpectedly"
|
||||
fi
|
||||
done
|
||||
info "OpenOCD is ready."
|
||||
|
||||
GDB_INIT_FILE="/tmp/gdb_deploy_demo_threadx.gdb"
|
||||
printf 'set confirm off
|
||||
set remotetimeout 60
|
||||
file %s
|
||||
target extended-remote localhost:3333
|
||||
load
|
||||
' "${ELF}" > "${GDB_INIT_FILE}"
|
||||
|
||||
if [ "${OPT_DEBUG}" -eq 0 ]; then
|
||||
info "Flashing and running (detached) ..."
|
||||
printf 'monitor resume\ndisconnect\nquit\n' >> "${GDB_INIT_FILE}"
|
||||
info "ELF: ${ELF}"
|
||||
riscv64-unknown-elf-size "${ELF}"
|
||||
"${GDB}" --batch --command="${GDB_INIT_FILE}" 2>&1 \
|
||||
| grep -v "keep_alive() was not invoked" \
|
||||
| grep -v "GDB alive packet not sent"
|
||||
info "Flash complete. Application is running on the target."
|
||||
info "Serial console: minicom -b 115200 -D /dev/ttyUSBx"
|
||||
else
|
||||
info "Flashing and stopping at main for interactive debug ..."
|
||||
printf 'break main\ncontinue\n' >> "${GDB_INIT_FILE}"
|
||||
info "ELF: ${ELF}"
|
||||
riscv64-unknown-elf-size "${ELF}"
|
||||
"${GDB}" --command="${GDB_INIT_FILE}"
|
||||
fi
|
||||
@@ -0,0 +1,6 @@
|
||||
set arch riscv:rv32
|
||||
target extended-remote localhost:3333
|
||||
file build/demo_threadx.elf
|
||||
load
|
||||
break main
|
||||
continue
|
||||
@@ -0,0 +1,59 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright (c) 2011-2014, Wind River Systems, Inc.
|
||||
* Copyright 2020 ETH Zurich
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef BITS_H
|
||||
#define BITS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Helper to pass an integer as a pointer or vice versa. */
|
||||
#define POINTER_TO_UINT(x) ((uintptr_t)(x))
|
||||
#define UINT_TO_POINTER(x) ((void *)(uintptr_t)(x))
|
||||
#define POINTER_TO_INT(x) ((intptr_t)(x))
|
||||
#define INT_TO_POINTER(x) ((void *)(intptr_t)(x))
|
||||
|
||||
#if !(defined(__CHAR_BIT__) && defined(__SIZEOF_LONG__))
|
||||
#error Missing required predefined macros for BITS_PER_LONG calculation
|
||||
#endif
|
||||
|
||||
#define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__)
|
||||
#define GENMASK(h, l) \
|
||||
(((~0UL) - (1UL << (l)) + 1UL) & (~0UL >> (BITS_PER_LONG - 1UL - (h))))
|
||||
|
||||
#define KB(x) ((x) << 10)
|
||||
#define MB(x) (KB(x) << 10)
|
||||
#define GB(x) (MB(x) << 10)
|
||||
|
||||
#define KHZ(x) ((x) * 1000)
|
||||
#define MHZ(x) (KHZ(x) * 1000)
|
||||
|
||||
#ifndef BIT
|
||||
#ifdef _ASMLANGUAGE
|
||||
#define BIT(n) (1 << (n))
|
||||
#else
|
||||
#define BIT(n) (1UL << (n))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define WRITE_BIT(var, bit, set) \
|
||||
((var) = ((set) != 0) ? ((var) | BIT(bit)) : ((var) & ~BIT(bit)))
|
||||
|
||||
#define BIT_MASK(n) (BIT(n) - 1UL)
|
||||
|
||||
#define REG_SET(FIELD, v) (((uint32_t)(v) << FIELD##_SHIFT) & FIELD##_MASK)
|
||||
#define REG_GET(FIELD, v) (((uint32_t)(v) & FIELD##_MASK) >> FIELD##_SHIFT)
|
||||
|
||||
#endif /* BITS_H */
|
||||
@@ -0,0 +1,75 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright (C) 2020 ETH Zurich and University of Bologna
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CSR_H
|
||||
#define CSR_H
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
#define CSR_MSTATUS 0x300
|
||||
#define CSR_MISA 0x301
|
||||
#define CSR_MIE 0x304
|
||||
#define CSR_MTVEC 0x305
|
||||
#define CSR_MSCRATCH 0x340
|
||||
#define CSR_MEPC 0x341
|
||||
#define CSR_MCAUSE 0x342
|
||||
#define CSR_MTVAL 0x343
|
||||
#define CSR_MIP 0x344
|
||||
#define CSR_PMPCFG0 0x3A0
|
||||
#define CSR_PMPADDR0 0x3B0
|
||||
#define CSR_MVENDORID 0xF11
|
||||
#define CSR_MARCHID 0xF12
|
||||
#define CSR_MIMPID 0xF13
|
||||
#define CSR_MHARTID 0xF14
|
||||
|
||||
#define MSTATUS_IE BIT(3)
|
||||
|
||||
#define __CSR_EXPAND(x) #x
|
||||
|
||||
#ifndef csr_read
|
||||
#define csr_read(csr) \
|
||||
({ \
|
||||
register unsigned long __val; \
|
||||
__asm__ volatile("csrr %0, " __CSR_EXPAND(csr) : "=r"(__val) : : "memory"); \
|
||||
__val; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef csr_write
|
||||
#define csr_write(csr, val) \
|
||||
({ \
|
||||
unsigned long __val = (unsigned long)(val); \
|
||||
__asm__ volatile("csrw " __CSR_EXPAND(csr) ", %0" : : "rK"(__val) : "memory"); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef csr_read_clear
|
||||
#define csr_read_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __val = (unsigned long)(val); \
|
||||
__asm__ volatile("csrrc %0, " __CSR_EXPAND(csr) ", %1" : "=r"(__val) : "rK"(__val) : "memory"); \
|
||||
__val; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef csr_read_set
|
||||
#define csr_read_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __val = (unsigned long)(val); \
|
||||
__asm__ volatile("csrrs %0, " __CSR_EXPAND(csr) ", %1" : "=r"(__val) : "rK"(__val) : "memory"); \
|
||||
__val; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#endif /* CSR_H */
|
||||
@@ -0,0 +1,93 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright 2020 GreenWaves Technologies
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef FLL_H
|
||||
#define FLL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "properties.h"
|
||||
#include "pulp_mem_map.h"
|
||||
|
||||
#define FLL_STATUS_OFFSET 0x000U
|
||||
#define FLL_CONF1_OFFSET 0x004U
|
||||
#define FLL_CONF2_OFFSET 0x008U
|
||||
#define FLL_INTEGRATOR_OFFSET 0x00CU
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t FLL_STATUS;
|
||||
volatile uint32_t FLL_CONF1;
|
||||
volatile uint32_t FLL_CONF2;
|
||||
volatile uint32_t FLL_INTEGRATOR;
|
||||
} fll_ctrl_t;
|
||||
|
||||
typedef enum _fll_type
|
||||
{
|
||||
FLL_SOC = 0,
|
||||
FLL_PERI = 1,
|
||||
FLL_CLUSTER = 2
|
||||
} fll_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PI_FREQ_DOMAIN_FC = 0,
|
||||
PI_FREQ_DOMAIN_CL = 1,
|
||||
PI_FREQ_DOMAIN_PERIPH = 2
|
||||
} pi_freq_domain_e;
|
||||
|
||||
#define FLL_CTRL_STATUS_MULTI_FACTOR_MASK 0xFFFFU
|
||||
#define FLL_CTRL_STATUS_MULTI_FACTOR_SHIFT 0U
|
||||
#define FLL_CTRL_CONF1_MULTI_FACTOR_MASK 0xFFFFU
|
||||
#define FLL_CTRL_CONF1_MULTI_FACTOR_SHIFT 0U
|
||||
#define FLL_CTRL_CONF1_DCO_INPUT_MASK 0x03FF0000U
|
||||
#define FLL_CTRL_CONF1_DCO_INPUT_SHIFT 16U
|
||||
#define FLL_CTRL_CONF1_CLK_OUT_DIV_MASK 0x3C000000U
|
||||
#define FLL_CTRL_CONF1_CLK_OUT_DIV_SHIFT 26U
|
||||
#define FLL_CTRL_CONF1_OUTPUT_LOCK_EN_MASK 0x40000000U
|
||||
#define FLL_CTRL_CONF1_OUTPUT_LOCK_EN_SHIFT 30U
|
||||
#define FLL_CTRL_CONF1_MODE_MASK 0x80000000U
|
||||
#define FLL_CTRL_CONF1_MODE_SHIFT 31U
|
||||
#define FLL_CTRL_CONF2_LOOPGAIN_MASK 0xFU
|
||||
#define FLL_CTRL_CONF2_LOOPGAIN_SHIFT 0U
|
||||
#define FLL_CTRL_CONF2_DEASSERT_CYCLES_MASK 0x3F0U
|
||||
#define FLL_CTRL_CONF2_DEASSERT_CYCLES_SHIFT 4U
|
||||
#define FLL_CTRL_CONF2_ASSERT_CYCLES_MASK 0xFC00U
|
||||
#define FLL_CTRL_CONF2_ASSERT_CYCLES_SHIFT 10U
|
||||
#define FLL_CTRL_CONF2_LOCK_TOLERANCE_MASK 0x0FFF0000U
|
||||
#define FLL_CTRL_CONF2_LOCK_TOLERANCE_SHIFT 16U
|
||||
#define FLL_CTRL_CONF2_CONF_CLK_SEL_MASK 0x20000000U
|
||||
#define FLL_CTRL_CONF2_CONF_CLK_SEL_SHIFT 29U
|
||||
#define FLL_CTRL_CONF2_OPEN_LOOP_MASK 0x40000000U
|
||||
#define FLL_CTRL_CONF2_OPEN_LOOP_SHIFT 30U
|
||||
#define FLL_CTRL_CONF2_DITHERING_MASK 0x80000000U
|
||||
#define FLL_CTRL_CONF2_DITHERING_SHIFT 31U
|
||||
#define FLL_CTRL_INTEGRATOR_FRACT_PART_MASK 0x0000FFC0U
|
||||
#define FLL_CTRL_INTEGRATOR_FRACT_PART_SHIFT 6U
|
||||
#define FLL_CTRL_INTEGRATOR_INT_PART_MASK 0x03FF0000U
|
||||
#define FLL_CTRL_INTEGRATOR_INT_PART_SHIFT 16U
|
||||
#define FLL_CTRL_SOC_FLL_CONV_MASK 0x1U
|
||||
#define FLL_CTRL_SOC_FLL_CONV_SHIFT 0U
|
||||
#define FLL_CTRL_CLUSTER_FLL_CONV_MASK 0x2U
|
||||
#define FLL_CTRL_CLUSTER_FLL_CONV_SHIFT 1U
|
||||
|
||||
#define FLL_NUM ARCHI_NB_FLL
|
||||
#define FLL_REF_CLK ARCHI_REF_CLOCK
|
||||
#define FLL_CTRL ((volatile fll_ctrl_t *)PULP_FLL_ADDR)
|
||||
|
||||
void pi_fll_init(fll_type_t which_fll, uint32_t ret_state);
|
||||
int pi_fll_set_frequency(fll_type_t which_fll, uint32_t frequency, int check);
|
||||
int pi_fll_get_frequency(fll_type_t which_fll, uint8_t real);
|
||||
|
||||
#endif /* FLL_H */
|
||||
@@ -0,0 +1,68 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GPIO_H
|
||||
#define GPIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* apb_gpiov2 register map (pin-indexed interface)
|
||||
*
|
||||
* Offset Name Access Description
|
||||
* 0x000 SETGPIO W PWDATA[6:0] = pin number → drive pin high
|
||||
* 0x004 CLRGPIO W PWDATA[6:0] = pin number → drive pin low
|
||||
* 0x008 TOGGPIO W PWDATA[6:0] = pin number → toggle pin
|
||||
* 0x010 PIN0 R bits [31:0] = sampled input state of pins 0-31
|
||||
* 0x020 OUT0 R/W bits [31:0] = output state bitmask, pins 0-31
|
||||
* 0x030 SETSEL W select pin for RDSTAT
|
||||
* 0x034 RDSTAT R status of selected pin
|
||||
* 0x038 SETDIR W PWDATA[6:0]=pin, PWDATA[25:24]=dir
|
||||
* dir[0]=1 → push-pull output; dir[1]=1 → open-drain
|
||||
* 0x03C SETINT W interrupt configuration
|
||||
* 0x040 INTACK W interrupt acknowledge
|
||||
*/
|
||||
#define GPIO_SETGPIO_OFFSET 0x000U
|
||||
#define GPIO_CLRGPIO_OFFSET 0x004U
|
||||
#define GPIO_TOGGPIO_OFFSET 0x008U
|
||||
#define GPIO_PIN0_OFFSET 0x010U
|
||||
#define GPIO_OUT0_OFFSET 0x020U
|
||||
#define GPIO_SETSEL_OFFSET 0x030U
|
||||
#define GPIO_RDSTAT_OFFSET 0x034U
|
||||
#define GPIO_SETDIR_OFFSET 0x038U
|
||||
#define GPIO_SETINT_OFFSET 0x03CU
|
||||
#define GPIO_INTACK_OFFSET 0x040U
|
||||
|
||||
/* Direction field in SETDIR: bits [25:24] of the written word.
|
||||
* 0b01 = push-pull output enable; 0b10 = open-drain; 0b00 = input */
|
||||
#define GPIO_DIR_OUTPUT (1U << 24U)
|
||||
|
||||
void gpio_init(void);
|
||||
void gpio_set_output(uint32_t pin_mask);
|
||||
void gpio_toggle(uint32_t pin_mask);
|
||||
void gpio_set(uint32_t pin_mask);
|
||||
void gpio_clear(uint32_t pin_mask);
|
||||
|
||||
/* Pad-mux control (APB SOC CTRL v1.0.0).
|
||||
* Each IO pad has a 32-bit register at SOC_CTRL_BASE + 0x400 + pad*4.
|
||||
* bits[1:0] = mux function: 0=sys, 1=perio, 2=apbio/GPIO, 3=fpgaio. */
|
||||
void gpio_setpinmux(uint8_t io_pad, uint8_t mux);
|
||||
uint8_t gpio_getpinmux(uint8_t io_pad);
|
||||
|
||||
/* Single-pin direction and status (for CLI use).
|
||||
* dir: 0 = input, 1 = push-pull output. */
|
||||
void gpio_pin_set_dir(uint8_t pin, uint8_t dir);
|
||||
uint32_t gpio_pin_read_status(uint8_t pin);
|
||||
|
||||
#endif /* GPIO_H */
|
||||
@@ -0,0 +1,38 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef I2C_MASTER_H
|
||||
#define I2C_MASTER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* i2c_master_init: enable I2C channel clock gate, configure clock divider.
|
||||
* id: 0 or 1 (I2CM0 or I2CM1)
|
||||
* i2c_freq: desired I2C clock in Hz (e.g. 200000)
|
||||
* periph_freq: UDMA peripheral clock in Hz (5000000 on CORE-V FPGA)
|
||||
* Returns 0 on success, -1 on bad params. */
|
||||
int i2c_master_init(uint8_t id, uint32_t i2c_freq, uint32_t periph_freq);
|
||||
|
||||
/* i2c_master_read_reg: read len bytes from register reg_addr of 7-bit addressed device.
|
||||
* id: I2CM channel (0 or 1)
|
||||
* dev_addr7: 7-bit I2C device address
|
||||
* reg_addr: register address to read from
|
||||
* buf: output buffer (must be in RAM, not stack if possible)
|
||||
* len: number of bytes to read (1..255)
|
||||
* Returns 0 on success, -1 on timeout or arbitration loss. */
|
||||
int i2c_master_read_reg(uint8_t id, uint8_t dev_addr7, uint8_t reg_addr,
|
||||
uint8_t *buf, uint8_t len);
|
||||
|
||||
#endif /* I2C_MASTER_H */
|
||||
@@ -0,0 +1,61 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright 2020 ETH Zurich
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef CORE_V_MCU_MMIO_MOCK
|
||||
static inline void writeb(uint8_t val, uintptr_t addr)
|
||||
{
|
||||
__asm__ volatile("sb %0, 0(%1)" : : "r"(val), "r"((volatile uint8_t *)addr));
|
||||
}
|
||||
|
||||
static inline void writeh(uint16_t val, uintptr_t addr)
|
||||
{
|
||||
__asm__ volatile("sh %0, 0(%1)" : : "r"(val), "r"((volatile uint16_t *)addr));
|
||||
}
|
||||
|
||||
static inline void writew(uint32_t val, uintptr_t addr)
|
||||
{
|
||||
__asm__ volatile("sw %0, 0(%1)" : : "r"(val), "r"((volatile uint32_t *)addr));
|
||||
}
|
||||
|
||||
static inline uint8_t readb(const uintptr_t addr)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
__asm__ volatile("lb %0, 0(%1)" : "=r"(val) : "r"((const volatile uint8_t *)addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint16_t readh(const uintptr_t addr)
|
||||
{
|
||||
uint16_t val;
|
||||
|
||||
__asm__ volatile("lh %0, 0(%1)" : "=r"(val) : "r"((const volatile uint16_t *)addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t readw(const uintptr_t addr)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
__asm__ volatile("lw %0, 0(%1)" : "=r"(val) : "r"((const volatile uint32_t *)addr));
|
||||
return val;
|
||||
}
|
||||
#endif /* CORE_V_MCU_MMIO_MOCK */
|
||||
|
||||
#endif /* IO_H */
|
||||
@@ -0,0 +1,64 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright (C) 2019 ETH Zurich and University of Bologna
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef IRQ_H
|
||||
#define IRQ_H
|
||||
|
||||
#include "pulp_mem_map.h"
|
||||
#include "io.h"
|
||||
#include "bits.h"
|
||||
|
||||
#define IRQ_REG_MASK_OFFSET 0x000U
|
||||
#define IRQ_REG_MASK_SET_OFFSET 0x004U
|
||||
#define IRQ_REG_MASK_CLEAR_OFFSET 0x008U
|
||||
#define IRQ_REG_INT_OFFSET 0x00CU
|
||||
#define IRQ_REG_INT_SET_OFFSET 0x010U
|
||||
#define IRQ_REG_INT_CLEAR_OFFSET 0x014U
|
||||
#define IRQ_REG_ACK_OFFSET 0x018U
|
||||
#define IRQ_REG_ACK_SET_OFFSET 0x01CU
|
||||
#define IRQ_REG_ACK_CLEAR_OFFSET 0x020U
|
||||
#define IRQ_REG_FIFO_OFFSET 0x024U
|
||||
|
||||
#define IRQ_FC_EVT_SW0 BIT(0)
|
||||
#define IRQ_FC_EVT_SW1 BIT(1)
|
||||
#define IRQ_FC_EVT_SW2 BIT(2)
|
||||
#define IRQ_FC_EVT_SW3 BIT(3)
|
||||
#define IRQ_FC_EVT_SW4 BIT(4)
|
||||
#define IRQ_FC_EVT_SW5 BIT(5)
|
||||
#define IRQ_FC_EVT_SW6 BIT(6)
|
||||
#define IRQ_FC_EVT_SW7 BIT(7)
|
||||
#define IRQ_FC_EVT_DMA_PE_EVT BIT(8)
|
||||
#define IRQ_FC_EVT_DMA_PE_IRQ BIT(9)
|
||||
#define IRQ_FC_EVT_TIMER0_LO BIT(10)
|
||||
#define IRQ_FC_EVT_TIMER0_HI BIT(11)
|
||||
#define IRQ_FC_EVT_PF BIT(12)
|
||||
#define IRQ_FC_EVT_CLK_REF BIT(14)
|
||||
#define IRQ_FC_EVT_GPIO BIT(15)
|
||||
#define IRQ_FC_EVT_ADV_TIMER0 BIT(17)
|
||||
#define IRQ_FC_EVT_ADV_TIMER1 BIT(18)
|
||||
#define IRQ_FC_EVT_ADV_TIMER2 BIT(19)
|
||||
#define IRQ_FC_EVT_ADV_TIMER3 BIT(20)
|
||||
#define IRQ_FC_EVT_SOC_EVT BIT(26)
|
||||
#define IRQ_FC_EVT_QUIRQE_ERROR BIT(29)
|
||||
#define IRQ_FC_EVT_PERIPH0 BIT(30)
|
||||
#define IRQ_FC_EVT_PERIPH1 BIT(31)
|
||||
|
||||
void irq_mask(uint32_t mask);
|
||||
void irq_enable(uint32_t mask);
|
||||
void irq_disable(uint32_t mask);
|
||||
uint32_t irq_clint_disable(void);
|
||||
uint32_t irq_clint_enable(void);
|
||||
void pulp_irq_init(void);
|
||||
|
||||
#endif /* IRQ_H */
|
||||
@@ -0,0 +1,39 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright (C) 2019 ETH Zurich, University of Bologna and GreenWaves Technologies
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MEMORY_MAP_H
|
||||
#define MEMORY_MAP_H
|
||||
|
||||
#include "pulp_mem_map.h"
|
||||
|
||||
#define L2_BASE 0x1C000000UL
|
||||
#define L2_SIZE 0x80000UL
|
||||
#define L2_SHARED_ADDR L2_BASE
|
||||
#define L2_SHARED_SIZE L2_SIZE
|
||||
#define ROM_ADDR 0x1A000000UL
|
||||
#define ROM_SIZE 0x00002000UL
|
||||
|
||||
#define SOC_PERIPHERALS_ADDR PULP_SOC_PERIPHERALS_ADDR
|
||||
#define SOC_FLL_ADDR PULP_FLL_ADDR
|
||||
#define GPIO_ADDR PULP_GPIO_ADDR
|
||||
#define UDMA_CTRL_ADDR PULP_UDMA_ADDR
|
||||
#define APB_SOC_CTRL_ADDR PULP_APB_SOC_CTRL_ADDR
|
||||
#define ADV_TIMER_ADDR PULP_ADV_TIMER_ADDR
|
||||
#define SOC_EU_ADDR PULP_SOC_EU_ADDR
|
||||
#define FC_IRQ_ADDR PULP_FC_IRQ_ADDR
|
||||
#define FC_TIMER_ADDR PULP_FC_TIMER_ADDR
|
||||
#define FC_HWPE_ADDR PULP_FC_HWPE_ADDR
|
||||
#define STDOUT_ADDR PULP_STDOUT_ADDR
|
||||
|
||||
#endif /* MEMORY_MAP_H */
|
||||
@@ -0,0 +1,43 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright (C) 2019 ETH Zurich, University of Bologna and GreenWaves Technologies
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PROPERTIES_H
|
||||
#define PROPERTIES_H
|
||||
|
||||
#define PULP
|
||||
|
||||
/* Peripheral bus clock (clk_per): PER_CLK_PERIOD_NS=200 → 5 MHz */
|
||||
#define ARCHI_FPGA_FREQUENCY 5000000U
|
||||
/* FC/SOC clock (clk_soc): FC_CLK_PERIOD_NS=100 → 10 MHz */
|
||||
#define ARCHI_SOC_FREQUENCY 10000000U
|
||||
#define ARCHI_NUM_TIMER 1U
|
||||
#define ARCHI_NUM_FLL 2U
|
||||
|
||||
#define ARCHI_REF_CLOCK_LOG2 15U
|
||||
#define ARCHI_REF_CLOCK (1U << ARCHI_REF_CLOCK_LOG2)
|
||||
|
||||
#define ARCHI_NB_FLL 3U
|
||||
|
||||
#define __RT_FLL_CL 2U
|
||||
#define __RT_FLL_PERIPH 1U
|
||||
#define __RT_FLL_FC 0U
|
||||
|
||||
#define __RT_FREQ_DOMAIN_FC 0U
|
||||
#define __RT_FREQ_DOMAIN_CL 2U
|
||||
#define __RT_FREQ_DOMAIN_PERIPH 1U
|
||||
#define RT_FREQ_NB_DOMAIN 3U
|
||||
|
||||
#define DEFAULT_SYSTEM_CLOCK 50000000U
|
||||
|
||||
#endif /* PROPERTIES_H */
|
||||
@@ -0,0 +1,103 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright (C) 2019 ETH Zurich and University of Bologna
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PULP_MEM_MAP_H
|
||||
#define PULP_MEM_MAP_H
|
||||
|
||||
#ifndef PULP_SOC_PERIPHERALS_ADDR
|
||||
#define PULP_SOC_PERIPHERALS_ADDR 0x1A100000UL
|
||||
#endif
|
||||
|
||||
#ifndef PULP_FC_TIMER_SIZE
|
||||
#define PULP_FC_TIMER_SIZE 0x00000800UL
|
||||
#endif
|
||||
|
||||
#ifndef PULP_FLL_OFFSET
|
||||
#define PULP_FLL_OFFSET 0x00000000UL
|
||||
#endif
|
||||
#ifndef PULP_GPIO_OFFSET
|
||||
#define PULP_GPIO_OFFSET 0x00001000UL
|
||||
#endif
|
||||
#ifndef PULP_UDMA_OFFSET
|
||||
#define PULP_UDMA_OFFSET 0x00002000UL
|
||||
#endif
|
||||
#ifndef PULP_APB_SOC_CTRL_OFFSET
|
||||
#define PULP_APB_SOC_CTRL_OFFSET 0x00004000UL
|
||||
#endif
|
||||
#ifndef PULP_ADV_TIMER_OFFSET
|
||||
#define PULP_ADV_TIMER_OFFSET 0x00005000UL
|
||||
#endif
|
||||
#ifndef PULP_SOC_EU_OFFSET
|
||||
#define PULP_SOC_EU_OFFSET 0x00006000UL
|
||||
#endif
|
||||
#ifndef PULP_FC_IRQ_OFFSET
|
||||
#define PULP_FC_IRQ_OFFSET 0x00009800UL
|
||||
#endif
|
||||
#ifndef PULP_FC_TIMER_OFFSET
|
||||
#define PULP_FC_TIMER_OFFSET 0x0000B000UL
|
||||
#endif
|
||||
#ifndef PULP_FC_HWPE_OFFSET
|
||||
#define PULP_FC_HWPE_OFFSET 0x0000C000UL
|
||||
#endif
|
||||
#ifndef PULP_STDOUT_OFFSET
|
||||
#define PULP_STDOUT_OFFSET 0x0000F000UL
|
||||
#endif
|
||||
#ifndef PULP_DEBUG_OFFSET
|
||||
#define PULP_DEBUG_OFFSET 0x00010000UL
|
||||
#endif
|
||||
|
||||
#ifndef PULP_FLL_ADDR
|
||||
#define PULP_FLL_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_FLL_OFFSET)
|
||||
#endif
|
||||
#ifndef PULP_GPIO_ADDR
|
||||
#define PULP_GPIO_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_GPIO_OFFSET)
|
||||
#endif
|
||||
#ifndef PULP_UDMA_ADDR
|
||||
#define PULP_UDMA_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_UDMA_OFFSET)
|
||||
#endif
|
||||
#ifndef PULP_APB_SOC_CTRL_ADDR
|
||||
#define PULP_APB_SOC_CTRL_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_APB_SOC_CTRL_OFFSET)
|
||||
#endif
|
||||
#ifndef PULP_ADV_TIMER_ADDR
|
||||
#define PULP_ADV_TIMER_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_ADV_TIMER_OFFSET)
|
||||
#endif
|
||||
#ifndef PULP_SOC_EU_ADDR
|
||||
#define PULP_SOC_EU_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_SOC_EU_OFFSET)
|
||||
#endif
|
||||
#ifndef PULP_FC_IRQ_ADDR
|
||||
#define PULP_FC_IRQ_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_FC_IRQ_OFFSET)
|
||||
#endif
|
||||
#ifndef PULP_FC_TIMER_ADDR
|
||||
#define PULP_FC_TIMER_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_FC_TIMER_OFFSET)
|
||||
#endif
|
||||
#ifndef PULP_FC_HWPE_ADDR
|
||||
#define PULP_FC_HWPE_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_FC_HWPE_OFFSET)
|
||||
#endif
|
||||
#ifndef PULP_STDOUT_ADDR
|
||||
#define PULP_STDOUT_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_STDOUT_OFFSET)
|
||||
#endif
|
||||
|
||||
#define PULP_FLL_AREA_SIZE 0x00000010UL
|
||||
|
||||
/* UDMA */
|
||||
#define UDMA_CH_ADDR_CTRL (PULP_UDMA_ADDR)
|
||||
#define UDMA_CH_ADDR_UART (PULP_UDMA_ADDR + 0x80U)
|
||||
#define UDMA_CH_ADDR_I2CM0 (PULP_UDMA_ADDR + 5U * UDMA_CH_SIZE)
|
||||
#define UDMA_CH_ADDR_I2CM1 (PULP_UDMA_ADDR + 6U * UDMA_CH_SIZE)
|
||||
#define UDMA_CTRL_I2CM0_CLKEN BIT(4)
|
||||
#define UDMA_CTRL_I2CM1_CLKEN BIT(5)
|
||||
#define UDMA_CH_SIZE (0x80U)
|
||||
#define N_UART (2U)
|
||||
|
||||
#endif /* PULP_MEM_MAP_H */
|
||||
@@ -0,0 +1,25 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef STRING_H
|
||||
#define STRING_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memset(void *dest, int c, size_t n);
|
||||
int memcmp(const void *lhs, const void *rhs, size_t n);
|
||||
|
||||
#endif /* STRING_H */
|
||||
@@ -0,0 +1,29 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SYSTEM_CORE_V_MCU_H
|
||||
#define SYSTEM_CORE_V_MCU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern void (*isr_table[32])(void);
|
||||
extern volatile uint32_t system_core_clock;
|
||||
|
||||
void system_init(void);
|
||||
void tx_trap_handler(uint32_t mcause, uint32_t mepc, uint32_t mtval);
|
||||
void tx_timer_irq_handler(void);
|
||||
void tx_undefined_irq_handler(void);
|
||||
|
||||
#endif /* SYSTEM_CORE_V_MCU_H */
|
||||
@@ -0,0 +1,29 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef TEMP_SENSOR_H
|
||||
#define TEMP_SENSOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Read ADT7420 temperature sensor on I2CM1 (Nexys A7 on-board sensor).
|
||||
* Returns temperature in tenths of degrees Celsius (e.g. 213 = 21.3°C).
|
||||
* Returns INT16_MIN on I2C error. */
|
||||
int16_t temp_read_celsius_x10(void);
|
||||
|
||||
/* Initialize the temperature sensor I2C channel. Call once at startup. */
|
||||
void temp_sensor_init(void);
|
||||
|
||||
#endif /* TEMP_SENSOR_H */
|
||||
@@ -0,0 +1,120 @@
|
||||
/***************************************************************************/
|
||||
/* Copyright (C) 2019 ETH Zurich and University of Bologna
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos)
|
||||
* Original work licensed under the Apache License, Version 2.0.
|
||||
* See https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Modifications licensed under MIT (https://opensource.org/licenses/MIT).
|
||||
*
|
||||
* AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6).
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 AND MIT
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
#define TIMER_CFG_LO_OFFSET 0x0U
|
||||
#define TIMER_CFG_HI_OFFSET 0x4U
|
||||
#define TIMER_CNT_LO_OFFSET 0x8U
|
||||
#define TIMER_CNT_HI_OFFSET 0xCU
|
||||
#define TIMER_CMP_LO_OFFSET 0x10U
|
||||
#define TIMER_CMP_HI_OFFSET 0x14U
|
||||
#define TIMER_START_LO_OFFSET 0x18U
|
||||
#define TIMER_START_HI_OFFSET 0x1CU
|
||||
#define TIMER_RESET_LO_OFFSET 0x20U
|
||||
#define TIMER_RESET_HI_OFFSET 0x24U
|
||||
|
||||
#define TIMER_CFG_LO_ENABLE_BIT 0U
|
||||
#define TIMER_CFG_LO_ENABLE_WIDTH 1U
|
||||
#define TIMER_CFG_LO_ENABLE_MASK 0x1U
|
||||
#define TIMER_CFG_LO_RESET_BIT 1U
|
||||
#define TIMER_CFG_LO_RESET_WIDTH 1U
|
||||
#define TIMER_CFG_LO_RESET_MASK 0x2U
|
||||
#define TIMER_CFG_LO_IRQEN_BIT 2U
|
||||
#define TIMER_CFG_LO_IRQEN_WIDTH 1U
|
||||
#define TIMER_CFG_LO_IRQEN_MASK 0x4U
|
||||
#define TIMER_CFG_LO_IEM_BIT 3U
|
||||
#define TIMER_CFG_LO_IEM_WIDTH 1U
|
||||
#define TIMER_CFG_LO_IEM_MASK 0x8U
|
||||
#define TIMER_CFG_LO_MODE_BIT 4U
|
||||
#define TIMER_CFG_LO_MODE_WIDTH 1U
|
||||
#define TIMER_CFG_LO_MODE_MASK 0x10U
|
||||
#define TIMER_CFG_LO_ONE_S_BIT 5U
|
||||
#define TIMER_CFG_LO_ONE_S_WIDTH 1U
|
||||
#define TIMER_CFG_LO_ONE_S_MASK 0x20U
|
||||
#define TIMER_CFG_LO_PEN_BIT 6U
|
||||
#define TIMER_CFG_LO_PEN_WIDTH 1U
|
||||
#define TIMER_CFG_LO_PEN_MASK 0x40U
|
||||
#define TIMER_CFG_LO_CCFG_BIT 7U
|
||||
#define TIMER_CFG_LO_CCFG_WIDTH 1U
|
||||
#define TIMER_CFG_LO_CCFG_MASK 0x80U
|
||||
#define TIMER_CFG_LO_PVAL_BIT 8U
|
||||
#define TIMER_CFG_LO_PVAL_WIDTH 8U
|
||||
#define TIMER_CFG_LO_PVAL_MASK 0xFF00U
|
||||
#define TIMER_CFG_LO_CASC_BIT 31U
|
||||
#define TIMER_CFG_LO_CASC_WIDTH 1U
|
||||
#define TIMER_CFG_LO_CASC_MASK 0x80000000UL
|
||||
|
||||
#define TIMER_CFG_HI_ENABLE_BIT 0U
|
||||
#define TIMER_CFG_HI_ENABLE_WIDTH 1U
|
||||
#define TIMER_CFG_HI_ENABLE_MASK 0x1U
|
||||
#define TIMER_CFG_HI_RESET_BIT 1U
|
||||
#define TIMER_CFG_HI_RESET_WIDTH 1U
|
||||
#define TIMER_CFG_HI_RESET_MASK 0x2U
|
||||
#define TIMER_CFG_HI_IRQEN_BIT 2U
|
||||
#define TIMER_CFG_HI_IRQEN_WIDTH 1U
|
||||
#define TIMER_CFG_HI_IRQEN_MASK 0x4U
|
||||
#define TIMER_CFG_HI_IEM_BIT 3U
|
||||
#define TIMER_CFG_HI_IEM_WIDTH 1U
|
||||
#define TIMER_CFG_HI_IEM_MASK 0x8U
|
||||
#define TIMER_CFG_HI_MODE_BIT 4U
|
||||
#define TIMER_CFG_HI_MODE_WIDTH 1U
|
||||
#define TIMER_CFG_HI_MODE_MASK 0x10U
|
||||
#define TIMER_CFG_HI_ONE_S_BIT 5U
|
||||
#define TIMER_CFG_HI_ONE_S_WIDTH 1U
|
||||
#define TIMER_CFG_HI_ONE_S_MASK 0x20U
|
||||
#define TIMER_CFG_HI_PEN_BIT 6U
|
||||
#define TIMER_CFG_HI_PEN_WIDTH 1U
|
||||
#define TIMER_CFG_HI_PEN_MASK 0x40U
|
||||
#define TIMER_CFG_HI_CLKCFG_BIT 7U
|
||||
#define TIMER_CFG_HI_CLKCFG_WIDTH 1U
|
||||
#define TIMER_CFG_HI_CLKCFG_MASK 0x80U
|
||||
|
||||
#define TIMER_CNT_LO_CNT_LO_BIT 0U
|
||||
#define TIMER_CNT_LO_CNT_LO_WIDTH 32U
|
||||
#define TIMER_CNT_LO_CNT_LO_MASK 0xFFFFFFFFUL
|
||||
#define TIMER_CNT_HI_CNT_HI_BIT 0U
|
||||
#define TIMER_CNT_HI_CNT_HI_WIDTH 32U
|
||||
#define TIMER_CNT_HI_CNT_HI_MASK 0xFFFFFFFFUL
|
||||
#define TIMER_CMP_LO_CMP_LO_BIT 0U
|
||||
#define TIMER_CMP_LO_CMP_LO_WIDTH 32U
|
||||
#define TIMER_CMP_LO_CMP_LO_MASK 0xFFFFFFFFUL
|
||||
#define TIMER_CMP_HI_CMP_HI_BIT 0U
|
||||
#define TIMER_CMP_HI_CMP_HI_WIDTH 32U
|
||||
#define TIMER_CMP_HI_CMP_HI_MASK 0xFFFFFFFFUL
|
||||
|
||||
#define TIMER_START_LO_STRT_LO_BIT 0U
|
||||
#define TIMER_START_LO_STRT_LO_WIDTH 1U
|
||||
#define TIMER_START_LO_STRT_LO_MASK 0x1U
|
||||
#define TIMER_START_HI_STRT_HI_BIT 0U
|
||||
#define TIMER_START_HI_STRT_HI_WIDTH 1U
|
||||
#define TIMER_START_HI_STRT_HI_MASK 0x1U
|
||||
#define TIMER_RESET_LO_RST_LO_BIT 0U
|
||||
#define TIMER_RESET_LO_RST_LO_WIDTH 1U
|
||||
#define TIMER_RESET_LO_RST_LO_MASK 0x1U
|
||||
#define TIMER_RESET_HI_RST_HI_BIT 0U
|
||||
#define TIMER_RESET_HI_RST_HI_WIDTH 1U
|
||||
#define TIMER_RESET_HI_RST_HI_MASK 0x1U
|
||||
|
||||
struct pulp_timer
|
||||
{
|
||||
unsigned int current_time;
|
||||
unsigned int flags;
|
||||
void *base;
|
||||
};
|
||||
|
||||
#endif /* TIMER_H */
|
||||
@@ -0,0 +1,26 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef TIMER_IRQ_H
|
||||
#define TIMER_IRQ_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int timer_irq_init(uint32_t ticks);
|
||||
int timer_irq_set_timeout(uint32_t ticks);
|
||||
uint32_t timer_irq_clock_elapsed(void);
|
||||
uint32_t timer_irq_cycle_get_32(void);
|
||||
|
||||
#endif /* TIMER_IRQ_H */
|
||||
@@ -0,0 +1,22 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef TX_USER_H
|
||||
#define TX_USER_H
|
||||
|
||||
#define TX_TIMER_TICKS_PER_SECOND 100U
|
||||
#define TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
#endif /* TX_USER_H */
|
||||
@@ -0,0 +1,27 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef UART_DRIVER_H
|
||||
#define UART_DRIVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int uart_init(uint8_t uart_id, uint32_t baudrate, uint32_t periph_freq);
|
||||
void uart_write_byte(uint8_t uart_id, uint8_t c);
|
||||
int uart_read_byte(uint8_t uart_id);
|
||||
void uart_write_str(uint8_t uart_id, const char *str);
|
||||
void uart_write_buf(uint8_t uart_id, const uint8_t *buf, uint32_t len);
|
||||
|
||||
#endif /* UART_DRIVER_H */
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# /***************************************************************************/
|
||||
# /* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
# *
|
||||
# * This program and the accompanying materials are made available under the
|
||||
# * terms of the MIT License which is available at
|
||||
# * https://opensource.org/licenses/MIT.
|
||||
# *
|
||||
# * AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
# * The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
# * and not subject to the project's licence.
|
||||
# *
|
||||
# * SPDX-License-Identifier: MIT AND CC0-1.0
|
||||
# ***************************************************************************/
|
||||
|
||||
# install_deps.sh -- Install Linux build/debug dependencies for the CORE-V MCU ThreadX port.
|
||||
#
|
||||
# Supported: Ubuntu 20.04 / 22.04 / 24.04 and Debian derivatives.
|
||||
# Run as a regular user; sudo is invoked internally where needed.
|
||||
#
|
||||
# Usage:
|
||||
# bash install_deps.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
die() { echo "[ERROR] $*" >&2; exit 1; }
|
||||
info() { echo "[INFO] $*"; }
|
||||
|
||||
command -v apt-get >/dev/null 2>&1 || die "This script requires apt-get (Ubuntu/Debian)."
|
||||
|
||||
PACKAGES=(
|
||||
cmake
|
||||
ninja-build
|
||||
gcc-riscv64-unknown-elf
|
||||
binutils-riscv64-unknown-elf
|
||||
gdb-multiarch
|
||||
openocd
|
||||
usbutils
|
||||
git
|
||||
)
|
||||
|
||||
info "Updating package lists ..."
|
||||
sudo apt-get update -qq
|
||||
|
||||
info "Installing: ${PACKAGES[*]}"
|
||||
sudo apt-get install -y "${PACKAGES[@]}"
|
||||
|
||||
info ""
|
||||
info "All dependencies installed."
|
||||
info ""
|
||||
info "Next steps:"
|
||||
info " 1. Run scripts/setup_opella.sh to configure udev rules for the Ashling Opella LD."
|
||||
info " 2. (WSL only) Follow the usbipd-win instructions printed by setup_opella.sh."
|
||||
@@ -0,0 +1,65 @@
|
||||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
L2 (rwx) : ORIGIN = 0x1c000000, LENGTH = 0x80000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(__boot_address = 0x1c000880);
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 0x2000;
|
||||
PROVIDE(__stack_size = __stack_size);
|
||||
|
||||
.vectors 0x1c000800 :
|
||||
{
|
||||
__vector_start = .;
|
||||
KEEP(*(.vectors))
|
||||
. = __vector_start + 0x80;
|
||||
__vector_end = .;
|
||||
} > L2
|
||||
|
||||
.text __boot_address :
|
||||
{
|
||||
*(.text.start)
|
||||
*(.text .text.*)
|
||||
*(.rodata .rodata.*)
|
||||
. = ALIGN(4);
|
||||
} > L2
|
||||
|
||||
.data :
|
||||
{
|
||||
__data_begin = .;
|
||||
__sdata_begin = .;
|
||||
*(.sdata .sdata.*)
|
||||
*(.data .data.*)
|
||||
. = ALIGN(4);
|
||||
__data_end = .;
|
||||
} > L2
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
__bss_start = .;
|
||||
*(.sbss .sbss.*)
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end = .;
|
||||
_end = .;
|
||||
} > L2
|
||||
|
||||
PROVIDE(__tx_free_memory_start = __bss_end);
|
||||
PROVIDE(__global_pointer$ = MIN(__sdata_begin + 0x800,
|
||||
MAX(__data_begin + 0x800, __bss_end - 0x800)));
|
||||
|
||||
__stack_top = ORIGIN(L2) + LENGTH(L2);
|
||||
|
||||
ASSERT(SIZEOF(.vectors) <= 128, "Vector table exceeds reserved 128 bytes")
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.eh_frame)
|
||||
*(.note.*)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
interface ftdi
|
||||
ftdi_device_desc "Opella-LD Debug Probe"
|
||||
ftdi_vid_pid 0x0B6B 0x0040
|
||||
ftdi_tdo_sample_edge falling
|
||||
ftdi_layout_init 0x0A68 0xFF7B
|
||||
ftdi_channel 0
|
||||
ftdi_layout_signal JTAGOE -ndata 0x0010
|
||||
ftdi_layout_signal nTRST -data 0x0020
|
||||
ftdi_layout_signal nSRST -data 0x0040
|
||||
ftdi_layout_signal SWD_EN -data 0x0100
|
||||
ftdi_layout_signal SWDIO_OE -data 0x0200
|
||||
ftdi_layout_signal LED -ndata 0x0800
|
||||
transport select jtag
|
||||
|
||||
|
||||
reset_config none
|
||||
|
||||
adapter_khz 1000
|
||||
|
||||
set _CHIPNAME riscv
|
||||
|
||||
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10001C05
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
|
||||
|
||||
gdb_report_data_abort enable
|
||||
gdb_report_register_access_error enable
|
||||
|
||||
riscv set_reset_timeout_sec 120
|
||||
riscv set_command_timeout_sec 120
|
||||
|
||||
# prefer to use sba for system bus access
|
||||
riscv set_prefer_sba on
|
||||
|
||||
# dump jtag chain
|
||||
scan_chain
|
||||
|
||||
init
|
||||
halt
|
||||
echo "Ready for Remote Connections"
|
||||
@@ -0,0 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
|
||||
project(core_v_mcu_tests C)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CORE_V_MCU_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
|
||||
|
||||
add_executable(test_irq
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_irq.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mock/mmio_mock.c
|
||||
)
|
||||
target_include_directories(test_irq PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/mock
|
||||
${CORE_V_MCU_DIR}/include
|
||||
)
|
||||
|
||||
add_executable(test_timer
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_timer.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/mock/mmio_mock.c
|
||||
)
|
||||
target_include_directories(test_timer PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/mock
|
||||
${CORE_V_MCU_DIR}/include
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME irq_tests COMMAND test_irq)
|
||||
add_test(NAME timer_tests COMMAND test_timer)
|
||||
@@ -0,0 +1,18 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include "mmio_mock.h"
|
||||
|
||||
uint32_t mock_mmio[MOCK_MMIO_SIZE];
|
||||
@@ -0,0 +1,45 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MMIO_MOCK_H
|
||||
#define MMIO_MOCK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CORE_V_MCU_MMIO_MOCK 1
|
||||
#define MOCK_MMIO_SIZE 1024U
|
||||
|
||||
extern uint32_t mock_mmio[MOCK_MMIO_SIZE];
|
||||
|
||||
static inline void writew(uint32_t val, uintptr_t addr)
|
||||
{
|
||||
if (addr < (uintptr_t)(MOCK_MMIO_SIZE * 4U))
|
||||
{
|
||||
mock_mmio[addr / 4U] = val;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t readw(const uintptr_t addr)
|
||||
{
|
||||
if (addr < (uintptr_t)(MOCK_MMIO_SIZE * 4U))
|
||||
{
|
||||
return mock_mmio[addr / 4U];
|
||||
}
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#endif /* MMIO_MOCK_H */
|
||||
@@ -0,0 +1,66 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mmio_mock.h"
|
||||
|
||||
static uint32_t mock_mstatus = 0U;
|
||||
#define csr_read(csr) (mock_mstatus)
|
||||
#define csr_write(csr, val) do { mock_mstatus = (uint32_t)(val); } while (0)
|
||||
#define csr_read_clear(csr, val) ({ uint32_t _v = mock_mstatus; mock_mstatus &= ~(uint32_t)(val); _v; })
|
||||
#define csr_read_set(csr, val) ({ uint32_t _v = mock_mstatus; mock_mstatus |= (uint32_t)(val); _v; })
|
||||
|
||||
#include "bits.h"
|
||||
#define PULP_SOC_PERIPHERALS_ADDR 0U
|
||||
#define PULP_FC_IRQ_OFFSET 0U
|
||||
#include "irq.h"
|
||||
#include "../../bsp/irq.c"
|
||||
|
||||
static void test_irq_enable(void)
|
||||
{
|
||||
memset(mock_mmio, 0, sizeof(mock_mmio));
|
||||
irq_enable(BIT(10));
|
||||
assert(mock_mmio[IRQ_REG_MASK_SET_OFFSET / 4U] == BIT(10));
|
||||
printf("test_irq_enable: PASS\n");
|
||||
}
|
||||
|
||||
static void test_irq_disable(void)
|
||||
{
|
||||
memset(mock_mmio, 0, sizeof(mock_mmio));
|
||||
irq_disable(BIT(10));
|
||||
assert(mock_mmio[IRQ_REG_MASK_CLEAR_OFFSET / 4U] == BIT(10));
|
||||
printf("test_irq_disable: PASS\n");
|
||||
}
|
||||
|
||||
static void test_irq_clint_enable(void)
|
||||
{
|
||||
mock_mstatus = 0U;
|
||||
(void)irq_clint_enable();
|
||||
assert((mock_mstatus & 0x8U) != 0U);
|
||||
printf("test_irq_clint_enable: PASS\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_irq_enable();
|
||||
test_irq_disable();
|
||||
test_irq_clint_enable();
|
||||
printf("All IRQ tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mmio_mock.h"
|
||||
#define PULP_SOC_PERIPHERALS_ADDR 0U
|
||||
#define PULP_FC_TIMER_OFFSET 0U
|
||||
|
||||
#include "bits.h"
|
||||
#include "timer.h"
|
||||
#include "timer_irq.h"
|
||||
#include "../../bsp/timer_irq.c"
|
||||
|
||||
static void test_timer_irq_init(void)
|
||||
{
|
||||
uint32_t cfg;
|
||||
int ret;
|
||||
|
||||
memset(mock_mmio, 0, sizeof(mock_mmio));
|
||||
ret = timer_irq_init(327U);
|
||||
assert(ret == 0);
|
||||
assert(mock_mmio[TIMER_CMP_LO_OFFSET / 4U] == 327U);
|
||||
|
||||
cfg = mock_mmio[TIMER_CFG_LO_OFFSET / 4U];
|
||||
assert((cfg & TIMER_CFG_LO_ENABLE_MASK) != 0U);
|
||||
assert((cfg & TIMER_CFG_LO_IRQEN_MASK) != 0U);
|
||||
assert((cfg & TIMER_CFG_LO_CCFG_MASK) != 0U);
|
||||
assert((cfg & TIMER_CFG_LO_MODE_MASK) != 0U);
|
||||
printf("test_timer_irq_init: PASS\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_timer_irq_init();
|
||||
printf("All timer tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
.section .data
|
||||
.global __tx_free_memory_start
|
||||
__tx_free_memory_start:
|
||||
|
||||
.section .text.trap_entry
|
||||
.align 4
|
||||
.global tx_trap_entry
|
||||
.extern _tx_thread_context_save
|
||||
.extern _tx_thread_context_restore
|
||||
.extern tx_trap_handler
|
||||
|
||||
tx_trap_entry:
|
||||
addi sp, sp, -128
|
||||
sw ra, 112(sp)
|
||||
call _tx_thread_context_save
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
csrr a2, mtval
|
||||
addi sp, sp, -4
|
||||
sw ra, 0(sp)
|
||||
call tx_trap_handler
|
||||
lw ra, 0(sp)
|
||||
addi sp, sp, 4
|
||||
call _tx_thread_context_restore
|
||||
1:
|
||||
wfi
|
||||
j 1b
|
||||
|
||||
.section .text
|
||||
.global _tx_initialize_low_level
|
||||
.weak _tx_initialize_low_level
|
||||
.extern _tx_thread_system_stack_ptr
|
||||
.extern _tx_initialize_unused_memory
|
||||
.extern __vector_start
|
||||
|
||||
_tx_initialize_low_level:
|
||||
la t0, _tx_thread_system_stack_ptr
|
||||
sw sp, 0(t0)
|
||||
|
||||
la t0, __tx_free_memory_start
|
||||
la t1, _tx_initialize_unused_memory
|
||||
sw t0, 0(t1)
|
||||
|
||||
la t0, __vector_start
|
||||
ori t0, t0, 1
|
||||
csrw mtvec, t0
|
||||
|
||||
ret
|
||||
@@ -0,0 +1,25 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2026 Eclipse ThreadX contributors
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the MIT License which is available at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*
|
||||
* AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
|
||||
* The AI-generated portions may be considered public domain (CC0-1.0)
|
||||
* and not subject to the project's licence. The human contributor has
|
||||
* reviewed and verified that the code is correct.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT and CC0-1.0
|
||||
**************************************************************************/
|
||||
|
||||
.section .vectors, "ax"
|
||||
.option norvc
|
||||
.align 2
|
||||
.extern tx_trap_entry
|
||||
.global __vector_start
|
||||
|
||||
__vector_start:
|
||||
.rept 32
|
||||
jal zero, tx_trap_entry
|
||||
.endr
|
||||
@@ -149,7 +149,7 @@ _tx_thread_context_restore:
|
||||
/* Clear MPP/MPIE/MIE bits in t1 then set desired values. */
|
||||
|
||||
li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08)
|
||||
li t3, 0x1800 // Set MPP to Machine mode (bits 12:11)
|
||||
li t3, 0x1880 // Set MPP=Machine (0x1800) + MPIE=1 (0x80); mret sets MIE=MPIE
|
||||
|
||||
/* Construct new mstatus in t1: clear mask bits, set MPP/MPIE and optionally FP bit,
|
||||
preserve everything except the bits we will modify. */
|
||||
@@ -284,7 +284,7 @@ _tx_thread_no_preempt_restore:
|
||||
|
||||
csrr t1, mstatus
|
||||
li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08)
|
||||
li t3, 0x1880 // Set MPP=Machine(0x1800) + MPIE(0x80) so mret re-enables MIE
|
||||
li t3, 0x1880 // Set MPP=Machine (0x1800) + MPIE=1 (0x80); mret sets MIE=MPIE
|
||||
li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE
|
||||
and t1, t1, t4
|
||||
or t1, t1, t3
|
||||
|
||||
Reference in New Issue
Block a user