Some interesting hardware in this one, not least a hardware TRNG - which could be useful for something, I guess. Accessing involves probing a “ready” status bit before reading the data value. Doing this in Python would be insanely slow, so assembly. In this case, writing the data to the SD card but that turns out to be punishingly slow by comparison.
from machine import Pin, SPI, mem32
from uctypes import addressof
import sdcard
import os
sd = sdcard.SDCard(
SPI(2, mosi=Pin("SD_MOSI"), miso=Pin("SD_MISO"), sck=Pin("SD_SCK")), Pin("SD_CS")
)
os.mount(sd, "/sd")
# set up the RNG
MCLK_BASE = 0x40000800
APBCMASK = MCLK_BASE | 0x1C
mem32[APBCMASK] = mem32[APBCMASK] | 1 << 10
# TRNG -> BASE = 0x42002800
# TRNG enable -> BASE -> bit 1 needs to be toggled
TRNG_BASE = 0x42002800
mem32[0x42002800] = mem32[0x42002800] | 1 << 1
# r0: pointer to data buffer
# r1: count of how many random numbers to collect
#
# internally:
# r2: points at TRNG_BASE address
# r3: scratch register
#
# be wary of PC - this is a pipelined system
@micropython.asm_thumb
def rng(r0, r1):
align(4)
mov(r2, pc)
b(start)
data(4, 0x42002800)
align(2)
label(start)
ldr(r2, [r2, 0])
label(tick)
label(wait)
ldrb(r3, [r2, 0x0A])
cmp(r3, 1)
bne(wait)
ldr(r3, [r2, 0x20])
str(r3, [r0, 0])
add(r0, r0, 4)
sub(r1, r1, 1)
cmp(r1, 0)
bgt(tick)
# storage for 1k uint32_t - assume that this will always be 4-byte aligned?
data = bytearray(1024 * 4)
addr = addressof(data)
with open("/sd/random.dat", "wb") as f:
for j in range(1024):
rng(addr, 1024)
f.write(data, 1024 * 4)
os.umount("/sd")
1<<20
random 32 bit ints took around a second to compute with the basic formalism, but writing to disk took more than 30s. That could well be partly my cheap SD card.
On the whole, a nice little piece of code & good to work out a neat way to do the busy-wait loop for the ready flag.