MustafaMulla29/rp2040-bldc-motor-controller-new
A USB‑C PD–powered RP2040 BLDC motor controller PCB with 3.3 V logic, MCT8329A sensorless commutation, three MOSFET half-bridges, protected power switching, USB data, controls, and motor connectors.
- Version
- 0.3.82
- License
- unset
- Stars
- 0
firmware/pd_nvm.py
"""STUSB4500 NVM transport; no writes happen on import.
Implements the register protocol in ST's USBPD_CUST_NVM_API.c / USB_PD_defines.h:
https://github.com/usb-c/STUSB4500/tree/master/NVM_Flasher/Src/NVM
Only sectors 3 and 4 are erased/programmed; sectors 0..2 stay untouched.
Every operation is bounded, and the complete image is read back after programming.
"""
import time
from pd_profile import nvm_9v_image, nvm_is_9v
class NVM:
def __init__(self, bus, address=0x28, clock=time):
self.bus, self.address, self.clock = bus, address, clock
def _write(self, reg, value):
self.bus.writeto_mem(self.address, reg, bytes((value,)))
def _read(self, reg, size=1):
return self.bus.readfrom_mem(self.address, reg, size)
def _wait(self):
start = self.clock.ticks_ms()
while self._read(0x96)[0] & 0x10:
if self.clock.ticks_diff(self.clock.ticks_ms(), start) >= 1000:
raise OSError("STUSB4500 NVM operation timed out")
self.clock.sleep_ms(1)
def _enter(self):
self._write(0x95, 0x47)
self._write(0x96, 0)
self._write(0x96, 0xC0)
def _exit(self):
try:
self.bus.writeto_mem(self.address, 0x96, b"\x40\x00")
finally:
self._write(0x95, 0)
def _command(self, opcode, sector=0):
self._write(0x97, opcode)
self._write(0x96, 0xD0 | sector)
self._wait()
def read(self):
try:
self._enter()
image = bytearray()
for sector in range(5):
self._write(0x96, 0xC0)
self._command(0, sector)
image.extend(self._read(0x53, 8))
self._write(0x96, 0)
return bytes(image)
finally:
self._exit()
def provision_9v(self):
original = self.read()
if nvm_is_9v(original):
return False # already provisioned: no erase/write cycle
desired = nvm_9v_image(original)
try:
self._write(0x95, 0x47)
self._write(0x53, 0) # required for partial-sector erase
self._write(0x96, 0)
self._write(0x96, 0xC0)
self._command((0x18 << 3) | 2) # select sectors 3,4 (WRITE_SER)
self._command(7) # SOFT_PROG_SECTOR
self._command(5) # ERASE_SECTOR
for sector in (3, 4):
self.bus.writeto_mem(self.address, 0x53, desired[8*sector:8*sector+8])
self._write(0x96, 0xC0)
self._command(1) # load programming register
self._command(6, sector) # program selected sector
finally:
self._exit()
if self.read() != desired:
raise OSError("NVM readback mismatch; do not connect a PD charger")
return True