adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.03k stars 1.19k forks source link

RP2040 lacks raw memory map access #8334

Closed eightycc closed 1 year ago

eightycc commented 1 year ago

The RP2040 port lacks support for raw memory map access. Implementing the core memorymap module will provide access to RP2040 registers that are not otherwise available in CircuitPython, such as setting pad hysteresis. Let me know if this is desirable and I'll code a pull.

eightycc commented 1 year ago

The overall RP2 memory map is interesting, with different access rules and restrictions for various sections of the memory map.

Memory-mapped I/O register write accesses are uniformly treated as 32-bit writes that ignore the low-order 2 bits of the address. Therefore, write accesses to these areas of the address map need to be restricted to a size of 32 bits with natural alignment.

If a write access to a field narrower than 32 bits within an I/O register is desired, RP2 implements atomic set/clear/XOR access semantics. Each 4kB block of peripheral address space is aliased into the next three 4kB blocks of the address space. Depending on the 4kB block that is addressed, the write access semantics are normal, atomic XOR, atomic set, or atomic clear.

Additional methods may be added to support atomic write accesses to sub-fields within an I/O register.

tannewt commented 1 year ago

I'd love to see this support added and am happy to review. I don't think we'll need more for atomic access since there are separate registers at a different address for them. Let's start with the existing API.

eightycc commented 1 year ago

OK, I'll stick with the existing API for now. Just thinking out loud about some might be nice tweaks.

At any rate, I will enforce alignment, write allowed, and size where required according to the RP2 address map area.

eightycc commented 1 year ago

Just a small taste of difficulty. The RP2 places IOPORT and Cortex-M0+ registers above the 2G line in its address map. As it is, memorymap.AddressRange() treats its start argument as a signed integer, so it will not accept an address above the 2G line. Digging deeper, unsigned integer argument interpretation and validation isn't implemented in runtime. This problem also affects the NRF53 series.