Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bricks/_common/micropython.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ static uint8_t *mpy_data_get_buf(mpy_info_t *info) {
static mpy_info_t *mpy_data_find(qstr name) {
const char *name_str = qstr_str(name);

for (mpy_info_t *info = mpy_first; info < mpy_end;
for (mpy_info_t *info = mpy_first; (uintptr_t)info + sizeof(uint32_t) < (uintptr_t)mpy_end;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We currently only support 32-bit platforms, but I think this should be pointer-size aligned rather than 32-bit aligned.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mpy_info_t is explicitly defined with a 32-bit size regardless of platform pointer size

 uint8_t mpy_size[4];

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what that has to do with the binary file itself needing to be pointer-aligned in memory.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds like we are planning to fix alignment issues later.

The check here is sufficient for preventing an invalid read.

info = (mpy_info_t *)(mpy_data_get_buf(info) + pbio_get_uint32_le(info->mpy_size))) {
if (strcmp(info->mpy_name, name_str) == 0) {
return info;
Expand Down
1 change: 1 addition & 0 deletions bricks/_common/sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
drv/button/button_nxt.c \
drv/button/button_resistor_ladder.c \
drv/button/button_test.c \
drv/cache/cache_ev3.c \
drv/charger/charger_mp2639a.c \
drv/clock/clock_ev3.c \
drv/clock/clock_linux.c \
Expand Down
31 changes: 31 additions & 0 deletions lib/pbio/drv/cache/cache_ev3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2025 The Pybricks Authors

#include <pbdrv/config.h>

#if PBDRV_CONFIG_CACHE_EV3

#include <stddef.h>
#include <stdint.h>

#include <tiam1808/armv5/cp15.h>

#include <pbdrv/compiler.h>

void pbdrv_cache_prepare_before_dma(const void *buf, size_t sz) {
// Make sure all data is written by the compiler...
pbdrv_compiler_memory_barrier();
// and then make sure it's written out of the cache...
CP15DCacheCleanBuff((uint32_t)buf, sz);
// and also the write buffer, in case the cache missed.
CP15DrainWriteBuffer();
}

void pbdrv_cache_prepare_after_dma(const void *buf, size_t sz) {
// Invalidate stale data in the cache...
CP15DCacheFlushBuff((uint32_t)buf, sz);
// and then make sure _subsequent_ reads cannot be reordered earlier.
pbdrv_compiler_memory_barrier();
}

#endif // PBDRV_CONFIG_CACHE_EV3
9 changes: 5 additions & 4 deletions lib/pbio/drv/sound/sound_ev3.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ void pbdrv_beep_start(uint32_t frequency, uint16_t sample_attenuator) {
return;
}

// Turn speaker amplifier on
// We turn the amplifier on and leave it turned on, because otherwise
// it will generate a popping sound each time it is enabled.
pbdrv_gpio_out_high(&pin_sound_en);

// Clamp the frequency into the supported range
if (frequency < 64) {
frequency = 64;
Expand Down Expand Up @@ -132,10 +137,6 @@ void pbdrv_sound_init() {

// Configure IO pin mode
pbdrv_gpio_alt(&pin_audio, SYSCFG_PINMUX3_PINMUX3_7_4_EPWM0B);
// Turn speaker amplifier on
// We turn the amplifier on and leave it turned on, because otherwise
// it will generate a popping sound whenever it is enabled.
pbdrv_gpio_out_high(&pin_sound_en);
}

#endif // PBDRV_CONFIG_SOUND_EV3
10 changes: 8 additions & 2 deletions lib/pbio/include/pbdrv/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

#ifndef _PBDRV_CACHE_H_

#include <pbdrv/config.h>

#if PBDRV_CONFIG_CACHE

#include <stddef.h>

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

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

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

// Cache line size
#define PBDRV_CACHE_LINE_SZ 32

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

#endif // PBDRV_CONFIG_CACHE

#endif
12 changes: 12 additions & 0 deletions lib/pbio/platform/ev3/pbdrvconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
#define PBDRV_CONFIG_ADC_EV3 (1)
#define PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS (16)

#define PBDRV_CONFIG_CACHE (1)
#define PBDRV_CONFIG_CACHE_EV3 (1)
// The EV3 MMU is configured to additionally map
// VA 0xDxxxxxxx onto PA 0xCxxxxxxx, covering the DDR RAM region.
// The 0xD alias is mapped as non-cacheable and non-bufferable
// and can be used when data needs to be shared with bus-mastering
// hardware peripherals. The 0xD region is unused in the physical
// address map and lies at a convenient offset from the 0xC region.
// The 0xC region, which is the region typically used to access RAM,
// is cacheable and bufferable.
#define PBDRV_CONFIG_CACHE_UNCACHED_OFFSET (0x10000000)

#define PBDRV_CONFIG_CLOCK (1)
#define PBDRV_CONFIG_CLOCK_TIAM1808 (1)

Expand Down
18 changes: 1 addition & 17 deletions lib/pbio/platform/ev3/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,22 +397,6 @@ unsigned int EDMAVersionGet(void) {
return 1;
}

void pbdrv_cache_prepare_before_dma(const void *buf, size_t sz) {
// Make sure all data is written by the compiler...
pbdrv_compiler_memory_barrier();
// and then make sure it's written out of the cache...
CP15DCacheCleanBuff((uint32_t)buf, sz);
// and also the write buffer, in case the cache missed.
CP15DrainWriteBuffer();
}

void pbdrv_cache_prepare_after_dma(const void *buf, size_t sz) {
// Invalidate stale data in the cache...
CP15DCacheFlushBuff((uint32_t)buf, sz);
// and then make sure _subsequent_ reads cannot be reordered earlier.
pbdrv_compiler_memory_barrier();
}

static void panic_puts(const char *c) {
while (*c) {
UARTCharPut(SOC_UART_1_REGS, *(c++));
Expand Down Expand Up @@ -727,7 +711,7 @@ static void mmu_init(void) {
// Off-chip main DDR RAM, uncacheable mirror @ 0xD0000000
for (unsigned int i = 0; i < SYSTEM_RAM_SZ_MB; i++) {
uint32_t addr_phys = 0xC0000000 + i * MMU_SECTION_SZ;
uint32_t addr_virt = 0xD0000000 + i * MMU_SECTION_SZ;
uint32_t addr_virt = addr_phys + PBDRV_CONFIG_CACHE_UNCACHED_OFFSET;
l1_page_table[addr_virt >> MMU_SECTION_SHIFT] = MMU_L1_SECTION(addr_phys, 0, 1, 0, 0);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/pbio/platform/ev3/platform.ld
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ SECTIONS
*(.data.*)
} > DDR

.bss :
.bss (NOLOAD) :
{
. = ALIGN(4);
_bss_start = .;
Expand Down