Skip to content

memorymap: Convert to use memoryview internally.#11110

Open
jepler wants to merge 1 commit into
adafruit:mainfrom
jepler:memorymap-memoryview
Open

memorymap: Convert to use memoryview internally.#11110
jepler wants to merge 1 commit into
adafruit:mainfrom
jepler:memorymap-memoryview

Conversation

@jepler

@jepler jepler commented Jul 10, 2026

Copy link
Copy Markdown

Importantly, a memoryview can be .cast(), and then accesses to it for 4 byte values don't require allocations or to/from_bytes. (as long as the register values actually fit in CircuitPython "small integers")

This does remove the existing protections enforcing aligned accesses to IO blocks on raspberrypi. However, the behavior in these cases is actually well defined: an 8 or 16 bit write access is replicated across all 32 bits of the register. See RP2040 datasheet 2.1.4. Narrow IO Register Writes and RP2350 datasheet 2.1.5. Narrow IO register writes.

As discussed on Discord, this speeds up the keyboard scanner of my Unicomp Mini M firmware by nearly 10x compared to using DigitalInOut, mostly because 12 pins can be read by a single operation, allowing it to scan the full keyboard in under 1ms when overclocked. (https://adafruit-playground.com/u/jepler/pages/unicomp-mini-m-with-circuitpython currently details the original lower performance keyboard, which took about 6ms to scan the full keyboard when overclocked)

Currently tested only on rp2040.

@jepler jepler force-pushed the memorymap-memoryview branch 2 times, most recently from 506fa9c to e8a23f3 Compare July 11, 2026 13:49
@jepler

jepler commented Jul 11, 2026

Copy link
Copy Markdown
Author

Here's the code I use in my program to read & update GPIO pins as a group:

SIO_BASE = const(0xd0000000)
SIO_LEN = const(0x1000)
GPIO_IN = const(4//4)
GPIO_OUT_XOR = const(0x1c//4)

sio = memorymap.AddressRange(start=SIO_BASE, length=SIO_LEN).cast('L')

def gpio_in():
    """Fetch the status of all GPIO inputs"""
    return sio[GPIO_IN]

def gpio_out_xor(x):
    """Invert the given pins simultaneously"""
    sio[GPIO_OUT_XOR] = x

@jepler jepler force-pushed the memorymap-memoryview branch 3 times, most recently from 3b0b1dd to db8b15f Compare July 11, 2026 16:11
@jepler

jepler commented Jul 11, 2026

Copy link
Copy Markdown
Author

Space Savings from this PR, raspberry_pi_pico:

  • 840b flash
  • 256b RAM
    The RAM savings could be had in main just by making the array of regions be "const", so that it resides in flash and is not copied to RAM.

@jepler jepler force-pushed the memorymap-memoryview branch from db8b15f to fd9766d Compare July 11, 2026 16:55
@jepler jepler requested a review from tannewt July 11, 2026 18:24
Importantly, a memoryview can be .cast(), and then accesses to it
for 4 byte values don't require allocations or to/from_bytes.

This does remove the existing protections enforcing aligned
accesses to IO blocks on raspberrypi. However, the behavior
in these cases is actually well defined: an 8 or 16 bit
access is replicated across all 32 bits of the register.
See RP2040 datasheet 2.1.4. Narrow IO Register Writes
and RP2350 datasheet 2.1.5. Narrow IO register writes.

Signed-off-by: Jeff Epler <jepler@unpythonic.net>
@jepler jepler force-pushed the memorymap-memoryview branch from fd9766d to e94f0f5 Compare July 11, 2026 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant