Merge pull request 'Handle partitioned and unpartitioned SD cards' (#32) from sd-partition-support into main
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m30s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m30s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Reviewed-on: #32 Reviewed-by: Stefan Kratochwil <kratochwil-la@gmx.de>
This commit was merged in pull request #32.
This commit is contained in:
@@ -5,7 +5,6 @@ import aiorepl
|
|||||||
import asyncio
|
import asyncio
|
||||||
import machine
|
import machine
|
||||||
import micropython
|
import micropython
|
||||||
import os
|
|
||||||
import time
|
import time
|
||||||
from machine import Pin
|
from machine import Pin
|
||||||
from math import pi, sin, pow
|
from math import pi, sin, pow
|
||||||
@@ -17,8 +16,7 @@ from mfrc522 import MFRC522
|
|||||||
from mp3player import MP3Player
|
from mp3player import MP3Player
|
||||||
from nfc import Nfc
|
from nfc import Nfc
|
||||||
from rp2_neopixel import NeoPixel
|
from rp2_neopixel import NeoPixel
|
||||||
from rp2_sd import SDCard
|
from utils import Buttons, SDContext, TimerManager
|
||||||
from utils import Buttons, TimerManager
|
|
||||||
|
|
||||||
micropython.alloc_emergency_exception_buf(100)
|
micropython.alloc_emergency_exception_buf(100)
|
||||||
|
|
||||||
@@ -54,30 +52,6 @@ machine.mem32[0x4001c004 + 8*4] = 0x67
|
|||||||
machine.mem32[0x40030000 + 0x00] = 0x10
|
machine.mem32[0x40030000 + 0x00] = 0x10
|
||||||
|
|
||||||
|
|
||||||
class SDContext:
|
|
||||||
def __init__(self, mosi, miso, sck, ss, baudrate):
|
|
||||||
self.mosi = mosi
|
|
||||||
self.miso = miso
|
|
||||||
self.sck = sck
|
|
||||||
self.ss = ss
|
|
||||||
self.baudrate = baudrate
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
self.sdcard = SDCard(self.mosi, self.miso, self.sck, self.ss, self.baudrate)
|
|
||||||
try:
|
|
||||||
os.mount(self.sdcard, '/sd')
|
|
||||||
except Exception:
|
|
||||||
self.sdcard.deinit()
|
|
||||||
raise
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_value, traceback):
|
|
||||||
try:
|
|
||||||
os.umount('/sd')
|
|
||||||
finally:
|
|
||||||
self.sdcard.deinit()
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
asyncio.new_event_loop()
|
asyncio.new_event_loop()
|
||||||
# Setup LEDs
|
# Setup LEDs
|
||||||
@@ -105,4 +79,6 @@ def run():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
run()
|
if machine.Pin(17, machine.Pin.IN, machine.Pin.PULL_UP).value() != 0:
|
||||||
|
time.sleep(5)
|
||||||
|
run()
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
|
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
|
||||||
|
|
||||||
from utils.buttons import Buttons
|
from utils.buttons import Buttons
|
||||||
|
from utils.mbrpartition import MBRPartition
|
||||||
|
from utils.sdcontext import SDContext
|
||||||
from utils.timer import TimerManager
|
from utils.timer import TimerManager
|
||||||
|
|
||||||
__all__ = ["Buttons", "TimerManager"]
|
__all__ = ["Buttons", "MBRPartition", "SDContext", "TimerManager"]
|
||||||
|
|||||||
46
software/src/utils/mbrpartition.py
Normal file
46
software/src/utils/mbrpartition.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
|
||||||
|
|
||||||
|
from array import array
|
||||||
|
import struct
|
||||||
|
|
||||||
|
|
||||||
|
class MBRPartition:
|
||||||
|
def __init__(self, bdev, partno):
|
||||||
|
assert partno >= 0 and partno < 4
|
||||||
|
self.bdev = bdev
|
||||||
|
bdev_len = bdev.ioctl(4, None)
|
||||||
|
bdev_bs = bdev.ioctl(5, None)
|
||||||
|
assert bdev_bs == 512
|
||||||
|
mbr = array('B', 512*b'0')
|
||||||
|
bdev.readblocks(0, mbr)
|
||||||
|
if mbr[510] != 0x55 or mbr[511] != 0xaa:
|
||||||
|
raise ValueError("Not a valid MBR")
|
||||||
|
partofs = 0x1be + partno*16
|
||||||
|
(boot_ind, _, _, _,
|
||||||
|
parttype, _, _, _,
|
||||||
|
lba_start, lba_len) = struct.unpack_from('<BBBBBBBBLL', mbr, partofs)
|
||||||
|
print(f'Partition {partno} bi {boot_ind} type {parttype} start {lba_start} len {lba_len}')
|
||||||
|
if (boot_ind != 0x00 and boot_ind != 0x80) or parttype == 0x00:
|
||||||
|
raise ValueError("Not a valid partition")
|
||||||
|
self.offset = lba_start
|
||||||
|
self.size = lba_len
|
||||||
|
assert lba_start + lba_len <= bdev_len
|
||||||
|
|
||||||
|
def ioctl(self, op, arg):
|
||||||
|
if op == 4:
|
||||||
|
return self.size
|
||||||
|
elif op == 5:
|
||||||
|
return 512
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def readblocks(self, block, buf):
|
||||||
|
if block >= self.size:
|
||||||
|
raise ValueError("Block out of range")
|
||||||
|
return self.bdev.readblocks(block+self.offset, buf)
|
||||||
|
|
||||||
|
def writeblocks(self, block, buf):
|
||||||
|
if block >= self.size:
|
||||||
|
raise ValueError("Block out of range")
|
||||||
|
return self.bdev.writeblocks(block+self.offset, buf)
|
||||||
39
software/src/utils/sdcontext.py
Normal file
39
software/src/utils/sdcontext.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from . import MBRPartition
|
||||||
|
from rp2_sd import SDCard
|
||||||
|
|
||||||
|
|
||||||
|
class SDContext:
|
||||||
|
def __init__(self, mosi, miso, sck, ss, baudrate):
|
||||||
|
self.mosi = mosi
|
||||||
|
self.miso = miso
|
||||||
|
self.sck = sck
|
||||||
|
self.ss = ss
|
||||||
|
self.baudrate = baudrate
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.sdcard = SDCard(self.mosi, self.miso, self.sck, self.ss, self.baudrate)
|
||||||
|
# Try first partition
|
||||||
|
try:
|
||||||
|
self.part = MBRPartition(self.sdcard, 0)
|
||||||
|
os.mount(self.part, '/sd')
|
||||||
|
return self
|
||||||
|
except Exception:
|
||||||
|
print("Failed to mount SDCard partition, trying whole device...")
|
||||||
|
# Try whole device
|
||||||
|
try:
|
||||||
|
os.mount(self.sdcard, '/sd')
|
||||||
|
return self
|
||||||
|
except Exception as ex:
|
||||||
|
self.sdcard.deinit()
|
||||||
|
raise RuntimeError("Could not mount SD card") from ex
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
|
try:
|
||||||
|
os.umount('/sd')
|
||||||
|
finally:
|
||||||
|
self.sdcard.deinit()
|
||||||
Reference in New Issue
Block a user