Skip to content

Commit 1d0471d

Browse files
committed
pbio/include/pbdrv/cache.h: Turn into proper driver module
This makes this common header extensible in case future platforms also require cache management. It also makes it clear which functionality is specific to how Pybricks sets up the EV3.
1 parent 39c1f48 commit 1d0471d

File tree

5 files changed

+53
-19
lines changed

5 files changed

+53
-19
lines changed

bricks/_common/sources.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
135135
drv/button/button_nxt.c \
136136
drv/button/button_resistor_ladder.c \
137137
drv/button/button_test.c \
138+
drv/cache/cache_ev3.c \
138139
drv/charger/charger_mp2639a.c \
139140
drv/clock/clock_ev3.c \
140141
drv/clock/clock_linux.c \

lib/pbio/drv/cache/cache_ev3.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) 2025 The Pybricks Authors
3+
4+
#include <pbdrv/config.h>
5+
6+
#if PBDRV_CONFIG_CACHE_EV3
7+
8+
#include <stddef.h>
9+
#include <stdint.h>
10+
11+
#include <tiam1808/armv5/cp15.h>
12+
13+
#include <pbdrv/compiler.h>
14+
15+
void pbdrv_cache_prepare_before_dma(const void *buf, size_t sz) {
16+
// Make sure all data is written by the compiler...
17+
pbdrv_compiler_memory_barrier();
18+
// and then make sure it's written out of the cache...
19+
CP15DCacheCleanBuff((uint32_t)buf, sz);
20+
// and also the write buffer, in case the cache missed.
21+
CP15DrainWriteBuffer();
22+
}
23+
24+
void pbdrv_cache_prepare_after_dma(const void *buf, size_t sz) {
25+
// Invalidate stale data in the cache...
26+
CP15DCacheFlushBuff((uint32_t)buf, sz);
27+
// and then make sure _subsequent_ reads cannot be reordered earlier.
28+
pbdrv_compiler_memory_barrier();
29+
}
30+
31+
#endif // PBDRV_CONFIG_CACHE_EV3

lib/pbio/include/pbdrv/cache.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
#ifndef _PBDRV_CACHE_H_
55

6+
#include <pbdrv/config.h>
7+
8+
#if PBDRV_CONFIG_CACHE
9+
610
#include <stddef.h>
711

812
// Gets data ready so that the data that we (the CPU) have written
@@ -15,15 +19,17 @@ void pbdrv_cache_prepare_before_dma(const void *buf, size_t sz);
1519
void pbdrv_cache_prepare_after_dma(const void *buf, size_t sz);
1620

1721
// Accesses a variable via the uncached memory alias
18-
#define PBDRV_UNCACHED(x) (*(volatile __typeof__(x) *)((uint32_t)(&(x)) + 0x10000000))
22+
#define PBDRV_UNCACHED(x) (*(volatile __typeof__(x) *)((uintptr_t)(&(x)) + PBDRV_CONFIG_CACHE_UNCACHED_OFFSET))
1923

2024
// Gets the address of the uncached memory alias of a variable
21-
#define PBDRV_UNCACHED_ADDR(x) ((__typeof__(x) *)((uint32_t)(&(x)) + 0x10000000))
25+
#define PBDRV_UNCACHED_ADDR(x) ((__typeof__(x) *)((uintptr_t)(&(x)) + PBDRV_CONFIG_CACHE_UNCACHED_OFFSET))
2226

2327
// Cache line size
2428
#define PBDRV_CACHE_LINE_SZ 32
2529

2630
// Align data to a cache line, which is needed for clean RX DMA
2731
#define PBDRV_DMA_BUF __attribute__((aligned(PBDRV_CACHE_LINE_SZ), section(".dma")))
2832

33+
#endif // PBDRV_CONFIG_CACHE
34+
2935
#endif

lib/pbio/platform/ev3/pbdrvconfig.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@
77
#define PBDRV_CONFIG_ADC_EV3 (1)
88
#define PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS (16)
99

10+
#define PBDRV_CONFIG_CACHE (1)
11+
#define PBDRV_CONFIG_CACHE_EV3 (1)
12+
// The EV3 MMU is configured to additionally map
13+
// VA 0xDxxxxxxx onto PA 0xCxxxxxxx, covering the DDR RAM region.
14+
// The 0xD alias is mapped as non-cacheable and non-bufferable
15+
// and can be used when data needs to be shared with bus-mastering
16+
// hardware peripherals. The 0xD region is unused in the physical
17+
// address map and lies at a convenient offset from the 0xC region.
18+
// The 0xC region, which is the region typically used to access RAM,
19+
// is cacheable and bufferable.
20+
#define PBDRV_CONFIG_CACHE_UNCACHED_OFFSET (0x10000000)
21+
1022
#define PBDRV_CONFIG_CLOCK (1)
1123
#define PBDRV_CONFIG_CLOCK_TIAM1808 (1)
1224

lib/pbio/platform/ev3/platform.c

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -397,22 +397,6 @@ unsigned int EDMAVersionGet(void) {
397397
return 1;
398398
}
399399

400-
void pbdrv_cache_prepare_before_dma(const void *buf, size_t sz) {
401-
// Make sure all data is written by the compiler...
402-
pbdrv_compiler_memory_barrier();
403-
// and then make sure it's written out of the cache...
404-
CP15DCacheCleanBuff((uint32_t)buf, sz);
405-
// and also the write buffer, in case the cache missed.
406-
CP15DrainWriteBuffer();
407-
}
408-
409-
void pbdrv_cache_prepare_after_dma(const void *buf, size_t sz) {
410-
// Invalidate stale data in the cache...
411-
CP15DCacheFlushBuff((uint32_t)buf, sz);
412-
// and then make sure _subsequent_ reads cannot be reordered earlier.
413-
pbdrv_compiler_memory_barrier();
414-
}
415-
416400
static void panic_puts(const char *c) {
417401
while (*c) {
418402
UARTCharPut(SOC_UART_1_REGS, *(c++));
@@ -727,7 +711,7 @@ static void mmu_init(void) {
727711
// Off-chip main DDR RAM, uncacheable mirror @ 0xD0000000
728712
for (unsigned int i = 0; i < SYSTEM_RAM_SZ_MB; i++) {
729713
uint32_t addr_phys = 0xC0000000 + i * MMU_SECTION_SZ;
730-
uint32_t addr_virt = 0xD0000000 + i * MMU_SECTION_SZ;
714+
uint32_t addr_virt = addr_phys + PBDRV_CONFIG_CACHE_UNCACHED_OFFSET;
731715
l1_page_table[addr_virt >> MMU_SECTION_SHIFT] = MMU_L1_SECTION(addr_phys, 0, 1, 0, 0);
732716
}
733717

0 commit comments

Comments
 (0)