Skip to content

Commit aaef175

Browse files
committed
# This is a combination of 13 commits.
# This is the 1st commit message: cpu/riscv_common: Add periph xh3irq support # The commit message #2 will be skipped: # fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #3 will be skipped: # fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #4 will be skipped: # fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #5 will be skipped: # fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #6 will be skipped: # fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #7 will be skipped: # fixup! fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #8 will be skipped: # fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #9 will be skipped: # fixup! fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #10 will be skipped: # fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #11 will be skipped: # fixup! fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #12 will be skipped: # fixup! fixup! fixup! cpu/riscv_common: Add periph xh3irq support # The commit message #13 will be skipped: # fixup! fixup! fixup! cpu/riscv_common: Add periph xh3irq support
1 parent d112af9 commit aaef175

File tree

3 files changed

+98
-29
lines changed

3 files changed

+98
-29
lines changed

cpu/riscv_common/include/xh3irq.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
#pragma once
88

99
#include <stdio.h>
10-
#include "cpu_conf.h"
10+
1111
#include "panic.h"
12+
#include "cpu_conf.h"
1213

1314
/**
1415
* @ingroup cpu_riscv_common
@@ -29,6 +30,32 @@ extern "C" {
2930
*/
3031
extern const void *vector_cpu[CPU_IRQ_NUMOF];
3132

33+
/**
34+
* Hazard3 has internal registers to individually filter which
35+
* external IRQs appear in meip. When meip is 1,
36+
* this indicates there is at least one external interrupt
37+
* which is asserted (hence pending in mieipa), enabled in meiea,
38+
* and of priority greater than or equal to the current
39+
* preemption level in meicontext.preempt.
40+
*/
41+
#define MEIP_OFFSET 11
42+
/* Mask to extract the MEIP bit from MIP/MISE */
43+
#define MEIP_MASK 0x1
44+
/**
45+
* Index of the highest-priority active external interrupt.
46+
* Zero when no external interrupts with sufficient priority
47+
* are both pending and enabled
48+
*/
49+
#define MEINEXT_IRQ_OFFSET 2
50+
/** Mask to extract the IRQ number from MEINEXT */
51+
#define MEINEXT_MASK 0x1FF
52+
/** XH3IRQ Interrupt arrays have a window to access the IRQ bits */
53+
#define INTERRUPT_ARRAY_MASK_OFFSET 16
54+
55+
/**
56+
* @brief Check if there are any pending interrupts
57+
* @return 1 if there are pending interrupts, 0 otherwise
58+
*/
3259
uint32_t xh3irq_has_pending(void);
3360
void xh3irq_handler(void);
3461

cpu/riscv_common/irq_arch.c

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -98,27 +98,45 @@ __attribute((used)) static void handle_trap(uword_t mcause)
9898

9999
#ifdef DEVELHELP
100100
printf("Trap: mcause=0x%" PRIx32 " mepc=0x%lx mtval=0x%lx\n",
101-
(uint32_t)mcause, read_csr(mepc), read_csr(mtval));
101+
(uint32_t)mcause, read_csr(mepc), read_csr(mtval));
102102

103+
/* See https://riscv.github.io/riscv-isa-manual/snapshot/privileged/#mcause */
103104
if ((mcause & ~MCAUSE_INT) <= 0xb) {
104105
const char *error_messages[] = {
105-
"Instruction alignment: Does not occur on RP2350, because 16-bit compressed instructions are implemented, and it is impossible to jump to a byte-aligned address.",
106-
"Instruction fetch fault: Attempted to fetch from an address that does not support instruction fetch (like APB/AHB peripherals on RP2350), or lacks PMP execute permission, or is forbidden by ACCESSCTRL, or returned a fault from the memory device itself.",
107-
"Illegal instruction: Encountered an instruction that was not a valid RISC-V opcode implemented by this processor, or attempted to access a nonexistent CSR, or attempted to execute a privileged instruction or access a privileged CSR without sufficient privilege.",
108-
"Breakpoint: An ebreak or c.ebreak instruction was executed, and no external debug host caught it (DCSR.EBREAKM or DCSR.EBREAKU was not set).",
109-
"Load alignment: Attempted to load from an address that was not a multiple of access size.",
110-
"Load fault: Attempted to load from an address that does not exist, or lacks PMP read permissions, or is forbidden by ACCESSCTRL, or returned a fault from a peripheral.",
111-
"Store/AMO alignment: Attempted to write to an address that was not a multiple of access size.",
112-
"Store/AMO fault: Attempted to write to an address that does not exist, or lacks PMP write permissions, or is forbidden by ACCESSCTRL, or returned a fault from a peripheral. Also raised when attempting an AMO on an address that does not support AHB5 exclusives.",
113-
"An ecall instruction was executed in U-mode.",
114-
NULL, /* 0x9 - not defined */
115-
NULL, /* 0xa - not defined */
116-
"An ecall instruction was executed in M-mode."
106+
"Instruction address misaligned",
107+
"Instruction access fault",
108+
"Illegal instruction",
109+
"Breakpoint",
110+
"Load address misaligned",
111+
"Load access fault",
112+
"Store/AMO address misaligned",
113+
"Store/AMO access fault",
114+
"Environment call from U-mode",
115+
"Environment call from S-mode",
116+
NULL,
117+
"Environment call from M-mode",
118+
"Instruction page fault",
119+
"Load page fault",
120+
NULL,
121+
"Store/AMO page fault",
122+
"Double trap",
123+
NULL,
124+
"Software check",
125+
"Hardware error"
117126
};
118127

119128
uword_t cause_code = mcause & ~MCAUSE_INT;
120-
if (cause_code <= 0xb && error_messages[cause_code] != NULL) {
121-
printf("Error 0x%lx: %s\n", cause_code, error_messages[cause_code]);
129+
if (cause_code <= (ARRAY_SIZE(error_messages) - 1)) {
130+
if (error_messages[cause_code] != NULL) {
131+
printf("Machine Cause Error 0x%lx: %s\n",
132+
cause_code, error_messages[cause_code]
133+
);
134+
} else {
135+
printf("Machine Cause indicates that 0x%lx"
136+
" is a reserved or custom cause code\n",
137+
cause_code
138+
);
139+
}
122140
}
123141
}
124142
#endif
@@ -156,8 +174,8 @@ __attribute((used)) static void handle_trap(uword_t mcause)
156174
}
157175
else {
158176
switch (trap) {
159-
case CAUSE_USER_ECALL: /* ECALL from user mode */
160-
case CAUSE_MACHINE_ECALL: /* ECALL from machine mode */
177+
case CAUSE_USER_ECALL: /* ECALL from user mode */
178+
case CAUSE_MACHINE_ECALL: /* ECALL from machine mode */
161179
{
162180
/* TODO: get the ecall arguments */
163181
sched_context_switch_request = 1;

cpu/riscv_common/periph/xh3irq.c

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,49 @@
22
#include <stdio.h>
33

44
uint32_t xh3irq_has_pending(void) {
5-
// Get MEIP at 0x344 which is the external interrupt pending bit
6-
uint32_t meip = (read_csr(0x344) >> 11) & 0x1;
5+
/*
6+
* Get MEIP which is the external interrupt pending bit
7+
* from the Machine Interrupt Pending Register address
8+
*/
9+
uint32_t meip = (read_csr(0x344) >> MEIP_OFFSET) & MEIP_MASK;
710

811
return (meip != 0);
912
}
1013

1114
void xh3irq_handler(void) {
12-
/* Get MEINEXT at 0xbe4 which is the next highest interrupt to handle (Bit 2-10) */
13-
/* This will also automagically clear the interrupt (See 3.8.6.1.2.) */
14-
uint32_t meinext = (read_csr(0xbe4) >> 2) & 0x1ff;
15+
/*
16+
* Get MEINEXT at 0xbe4 which is the next highest interrupt to handle (Bit 2-10).
17+
* This will also automagically clear the interrupt (See 3.8.6.1.2.)
18+
*
19+
* Contains the index of the highest-priority external interrupt
20+
* which is both asserted in meipa and enabled in meiea, left-
21+
* shifted by 2 so that it can be used to index an array of 32-bit
22+
* function pointers. If there is no such interrupt, the MSB is set.
23+
*/
24+
uint32_t meinext = (read_csr(0xBE4) >> MEINEXT_IRQ_OFFSET) & MEINEXT_MASK;
1525

1626
void (*isr)(void) = (void (*)(void))vector_cpu[meinext];
27+
#ifdef DEVELHELP
1728
printf("Calling isr %p for irq %ld\n", isr, meinext);
29+
#endif
1830
isr();
1931
}
2032

2133
void _meiea_set_req_bit(uint32_t irq_no, uint32_t bit_val) {
22-
uint32_t index = irq_no / 16;
23-
uint32_t mask = bit_val << (irq_no % 16);
34+
uint32_t index = irq_no / INTERRUPT_ARRAY_MASK_OFFSET;
35+
uint32_t mask = bit_val << (irq_no % INTERRUPT_ARRAY_MASK_OFFSET);
2436

37+
/*
38+
* 0xbe0 is the external interrupt enable array.
39+
* The array contains a read-write bit for each external interrupt request:
40+
* a 1 bit indicates that interrupt is currently enabled.
41+
* There are up to 512 external interrupts.
42+
* The upper half of this register contains a 16-bit window into the full
43+
* 512-bit vector. The window is indexed by the 5 LSBs of the write data.
44+
*/
2545
__asm__ volatile(
2646
"csrs 0xbe0, %0\n"
27-
: : "r"(index | (mask << 16))
47+
: : "r"(index | (mask << INTERRUPT_ARRAY_MASK_OFFSET))
2848

2949
);
3050
}
@@ -41,11 +61,15 @@ void xh3irq_disable_irq(uint32_t irq_no)
4161

4262
void xh3irq_force_irq(uint32_t irq_no)
4363
{
44-
uint32_t index = irq_no / 16;
45-
uint32_t mask = 1u << (irq_no % 16);
64+
uint32_t index = irq_no / INTERRUPT_ARRAY_MASK_OFFSET;
65+
uint32_t mask = 1u << (irq_no % INTERRUPT_ARRAY_MASK_OFFSET);
4666

67+
/**
68+
* 0xbe2 is the external interrupt force array.
69+
* See _meiea_set_req_bit / 0xbe0 for more details.
70+
*/
4771
__asm__ volatile(
4872
"csrs 0xbe2, %0\n"
49-
: : "r"(index | (mask << 16))
73+
: : "r"(index | (mask << INTERRUPT_ARRAY_MASK_OFFSET))
5074
);
5175
}

0 commit comments

Comments
 (0)