Skip to content

Commit 8e354ae

Browse files
committed
riscv: pmp: Extract region address calculation to helper function
The logic to decode PMP addressing modes (**TOR**, **NA4**, **NAPOT**) into physical start and end addresses was previously embedded in `print_pmp_entries()`. Extract this calculation into a new static helper function, `pmp_decode_region()`, to significantly improve the readability and modularity of the PMP debug printing code. The new helper function is fully self-contained and exposes a defined API for the PMP address decoding logic. This enables **direct reuse** in **unit tests** (e.g., using **Ztest**) to verify the core address calculation accuracy for all PMP modes and boundary conditions, independent of the main PMP initialization or logging path. Signed-off-by: Firas Sammoura <fsammoura@google.com>
1 parent 4c0d513 commit 8e354ae

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

arch/riscv/core/pmp.c

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,47 @@ LOG_MODULE_REGISTER(mpu);
5858

5959
#define PMP_NONE 0
6060

61+
/**
62+
* @brief Decodes PMP configuration and address registers into a memory region's
63+
* start/end addresses.
64+
*
65+
* @param cfg_byte The PMP configuration byte (pmpcfg_n).
66+
* @param pmp_addr A pointer to the full array of PMP address registers (pmpaddr_n).
67+
* @param index The current PMP entry index.
68+
* @param start Pointer to where the calculated start address should be stored.
69+
* @param end Pointer to where the calculated end address should be stored.
70+
*/
71+
static void pmp_decode_region(uint8_t cfg_byte,
72+
unsigned long *pmp_addr,
73+
unsigned int index,
74+
unsigned long *start,
75+
unsigned long *end)
76+
{
77+
unsigned long tmp;
78+
unsigned long pmp_addr_val = pmp_addr[index];
79+
unsigned long pmp_prev_addr_val = (index == 0) ? 0 : pmp_addr[index - 1];
80+
81+
switch (cfg_byte & PMP_A) {
82+
case PMP_TOR:
83+
*start = (index == 0) ? 0 : (pmp_prev_addr_val << 2);
84+
*end = (pmp_addr_val << 2) - 1;
85+
break;
86+
case PMP_NA4:
87+
*start = pmp_addr_val << 2;
88+
*end = *start + 3;
89+
break;
90+
case PMP_NAPOT:
91+
tmp = (pmp_addr_val << 2) | 0x3;
92+
*start = tmp & (tmp + 1);
93+
*end = tmp | (tmp + 1);
94+
break;
95+
default:
96+
*start = 0;
97+
*end = 0;
98+
break;
99+
}
100+
}
101+
61102
static void print_pmp_entries(unsigned int pmp_start, unsigned int pmp_end,
62103
unsigned long *pmp_addr, unsigned long *pmp_cfg,
63104
const char *banner)
@@ -67,27 +108,9 @@ static void print_pmp_entries(unsigned int pmp_start, unsigned int pmp_end,
67108

68109
LOG_DBG("PMP %s:", banner);
69110
for (index = pmp_start; index < pmp_end; index++) {
70-
unsigned long start, end, tmp;
111+
unsigned long start, end;
71112

72-
switch (pmp_n_cfg[index] & PMP_A) {
73-
case PMP_TOR:
74-
start = (index == 0) ? 0 : (pmp_addr[index - 1] << 2);
75-
end = (pmp_addr[index] << 2) - 1;
76-
break;
77-
case PMP_NA4:
78-
start = pmp_addr[index] << 2;
79-
end = start + 3;
80-
break;
81-
case PMP_NAPOT:
82-
tmp = (pmp_addr[index] << 2) | 0x3;
83-
start = tmp & (tmp + 1);
84-
end = tmp | (tmp + 1);
85-
break;
86-
default:
87-
start = 0;
88-
end = 0;
89-
break;
90-
}
113+
pmp_decode_region(pmp_n_cfg[index], pmp_addr, index, &start, &end);
91114

92115
if (end == 0) {
93116
LOG_DBG("%3d: "PR_ADDR" 0x%02x", index,

0 commit comments

Comments
 (0)