mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2026-10-06 06:59:08 +08:00
* riscv32: spec compliance and regression test fix Signed-off-by: Akif Ejaz <akifejaz40@gmail.com> * Derived the RISC-V32 frame sizes from the port contract in one place tx_port.h published TX_RISCV_TRAP_FRAME_SIZE for the GNU BSP assembly, but nothing in the port consumed it. Six .S files each rebuilt the same numbers from their own #if, so the interrupt frame size was written out in seven places and the solicited frame size in three. That is the shape that produced the RISC-V64 fault fixed in #708, where the port moved to a padded frame and one copy of the constant did not. The sources now include tx_port.h and take both sizes from it, and no literal frame size remains in the port. TX_RISCV_SOL_FRAME_SIZE joins the contract, since the solicited frame was never published at all. The emitted code is unchanged: 400 and 176 bytes for ILP32D, 128 for soft-float, confirmed by disassembly before and after. Two further corrections: _tx_initialize_low_level carried .global immediately followed by .weak, so the symbol stayed weak and the .global did nothing. Weak is what the port wants, because the example and regression BSPs both provide their own definition, so the stray .global is removed rather than the .weak. Verified with nm that the symbol is still W. The QEMU runner seeded fpu_verified from skip_fpu, so a soft-float run satisfied the FPU gate whether or not the script ever reported the skip. It now starts false and is set only when the skip marker is present, so a run that dies before reaching that point fails instead of passing. Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com> --------- Signed-off-by: Akif Ejaz <akifejaz40@gmail.com> Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
103 lines
2.4 KiB
C
103 lines
2.4 KiB
C
/***************************************************************************
|
|
* Copyright (c) 2026 10xEngineers
|
|
*
|
|
* 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.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
**************************************************************************/
|
|
|
|
#include "plic.h"
|
|
#include <stddef.h>
|
|
|
|
irq_callback callbacks[MAX_CALLBACK_NUM];
|
|
|
|
void plic_irq_enable(int irqno)
|
|
{
|
|
uintptr_t hart = riscv_get_core();
|
|
volatile uint32_t *reg = (volatile uint32_t *)(PLIC_MENABLE(hart) + (irqno / 32) * 4);
|
|
*reg = *reg | (1U << (irqno % 32));
|
|
}
|
|
|
|
void plic_irq_disable(int irqno)
|
|
{
|
|
uintptr_t hart = riscv_get_core();
|
|
volatile uint32_t *reg = (volatile uint32_t *)(PLIC_MENABLE(hart) + (irqno / 32) * 4);
|
|
*reg = *reg & ~(1U << (irqno % 32));
|
|
}
|
|
|
|
void plic_prio_set(int irqno, int prio)
|
|
{
|
|
PLIC_SET_PRIO(irqno, prio);
|
|
}
|
|
|
|
int plic_prio_get(int irqno)
|
|
{
|
|
return (int)PLIC_GET_PRIO(irqno);
|
|
}
|
|
|
|
int plic_register_callback(int irqno, irq_callback callback)
|
|
{
|
|
if (!(irqno >= 0 && irqno < MAX_CALLBACK_NUM))
|
|
return -1;
|
|
callbacks[irqno] = callback;
|
|
return 0;
|
|
}
|
|
|
|
int plic_unregister_callback(int irqno)
|
|
{
|
|
return plic_register_callback(irqno, NULL);
|
|
}
|
|
|
|
int plic_init(void)
|
|
{
|
|
uintptr_t hart = riscv_get_core();
|
|
|
|
for (int i = 0; i < MAX_CALLBACK_NUM; i++)
|
|
{
|
|
callbacks[i] = NULL;
|
|
}
|
|
|
|
/* Do not depend on the reset state or on a prior boot stage: accept
|
|
every priority (threshold 0) and start with all sources for this
|
|
hart disabled. */
|
|
*(volatile uint32_t *)PLIC_MPRIORITY(hart) = 0;
|
|
for (int w = 0; w < MAX_CALLBACK_NUM / 32; w++)
|
|
*(volatile uint32_t *)(PLIC_MENABLE(hart) + w * 4) = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int plic_claim(void)
|
|
{
|
|
uintptr_t hart = riscv_get_core();
|
|
return (int)(*(volatile uint32_t *)PLIC_MCLAIM(hart));
|
|
}
|
|
|
|
void plic_complete(int irqno)
|
|
{
|
|
uintptr_t hart = riscv_get_core();
|
|
*(volatile uint32_t *)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno;
|
|
}
|
|
|
|
int plic_irq_intr(void)
|
|
{
|
|
int ret = -1;
|
|
int irqno = plic_claim();
|
|
|
|
if (irqno == 0)
|
|
return 0;
|
|
|
|
if (irqno < 0 || irqno >= MAX_CALLBACK_NUM) {
|
|
if (irqno > 0)
|
|
plic_complete(irqno);
|
|
return -1;
|
|
}
|
|
if (callbacks[irqno] != NULL)
|
|
ret = (callbacks[irqno])(irqno);
|
|
|
|
plic_complete(irqno);
|
|
return ret;
|
|
}
|