def safe_mode_act(boot_pin): if boot_pin.safe_mode: led_pin = boot_pin.led_pin led_on = boot_pin.led_on btn_pin = boot_pin.btn_pin reset_val = boot_pin.reset_val print("Pin Control: LED {}, BTN: {}".format(led_pin, btn_pin)) safe_pin = Pin(btn_pin, Pin.IN, Pin.PULL_DOWN) led_pin = Pin(led_pin, Pin.OUT) led_pin.value(led_on) print("Wait 5sec - Safe Mode") sleep(5) print("Safe Mode Activate: {}".format(safe_pin.value() == reset_val)) if safe_pin.value() == reset_val: led_pin.value(1 - led_on) Partition.set_boot(Partition('factory')) reset() sleep(1) led_pin.value(1 - led_on) else: print("Safe Mode: not present")
def reboot(part="ota_0"): ota_0 = Partition(part) Partition.set_boot(ota_0) reset()
if safe_mode: print("Pin Control: LED {}, BTN: {}".format(boot_pin.led_pin, boot_pin.btn_pin)) safe_pin = Pin(boot_pin.btn_pin, Pin.IN, Pin.PULL_DOWN) led_pin = Pin(boot_pin.led_pin, Pin.OUT) led_pin.value(boot_pin.led_on) print("Wait 5sec - Safe Mode") sleep(5) print("Safe Mode Activate: {}".format( safe_pin.value() == boot_pin.reset_val)) if safe_pin.value() == boot_pin.reset_val: led_pin.value(1 - boot_pin.led_on) Partition.set_boot(Partition('factory')) reset() sleep(1) led_pin.value(1 - boot_pin.led_on) else: print("Not Board Detect for - Safe Mode") # PARTITIONS part_info = runningpart.info() part_name = part_info[4] try: uos.mkdir(part_name)
def reboot(part=None): if part: _part = Partition(part) Partition.set_boot(_part) machine.reset()
class OTA: def __init__(self): self.part = Partition(Partition.RUNNING).get_next_update() self.sha = hashlib.sha256() self.seq = 0 self.block = 0 self.buf = bytearray(BLOCKLEN) self.buflen = 0 # handle processes one message with a chunk of data in msg. The sequence number seq needs # to increment sequentially and the last call needs to have last==True as well as the # sha set to the hashlib.sha256(entire_data).hexdigest(). def handle(self, sha, msg, seq, last): if self.seq is None: raise ValueError("missing first message") elif self.seq < seq: # "duplicate message" log.warning("Duplicate OTA message seq=%d", seq) return None elif self.seq > seq: raise ValueError("message missing") else: self.seq += 1 self.sha.update(msg) # avoid allocating memory: use buf as-is msglen = len(msg) if self.buflen + msglen >= BLOCKLEN: # got a full block, assemble it and write to flash cpylen = BLOCKLEN - self.buflen self.buf[self.buflen:BLOCKLEN] = msg[:cpylen] self.part.writeblocks(self.block, self.buf) self.block += 1 msglen -= cpylen if msglen > 0: self.buf[:msglen] = msg[cpylen:] self.buflen = msglen else: self.buf[self.buflen:self.buflen + msglen] = msg self.buflen += msglen if last and self.buflen > 0: for i in range(BLOCKLEN - self.buflen): self.buf[self.buflen + i] = 0xFF # erased flash is ff self.part.writeblocks(self.block, self.buf) self.block += 1 assert len(self.buf) == BLOCKLEN if last: return self.finish(sha) elif (seq & 7) == 0: # log.info("Sending ACK {}".format(seq)) return "SEQ {}".format(seq).encode() def finish(self, check_sha): del self.buf self.seq = None calc_sha = binascii.hexlify(self.sha.digest()) check_sha = check_sha.encode() if calc_sha != check_sha: raise ValueError("SHA mismatch calc:{} check={}".format( calc_sha, check_sha)) self.part.set_boot() return "OK"
class OTA: # constructor, follow by calling ota(...) def __init__(self, verbose=False): self.verbose = verbose # the partition we are writing to self.part = Partition(Partition.RUNNING).get_next_update() # sha of the new app, computed in _app_data self.sha = hashlib.sha256() # keeping track (_app_data) self.block = 0 self.buf = bytearray(BLOCKLEN) self.buflen = 0 # length of current content of self.buf # load app into the next partition and set it as the next one to boot upon restart # :param: url of app # :sha256: sha256 of app def ota(self, url, sha256): if sys.platform != 'esp32': raise ValueError("N/A") if self.verbose: print('OTA ', end='') buffer = bytearray(BLOCKLEN) mv = memoryview(buffer) sock = open_url(url) while True: sz = sock.readinto(buffer) if not sz: break self._app_data(mv[0:sz]) self._finish(sha256) buffer = None gc.collect() # accept chunks of the app and write to self.part def _app_data(self, data, last=False): global BLOCKLEN, buf, buflen, block data_len = len(data) self.sha.update(data) if self.buflen + data_len >= BLOCKLEN: # got a full block, assemble it and write to flash cpylen = BLOCKLEN - self.buflen self.buf[self.buflen:BLOCKLEN] = data[:cpylen] assert len(self.buf) == BLOCKLEN if self.verbose: print('.', end='') self.part.writeblocks(self.block, self.buf) self.block += 1 data_len -= cpylen if data_len > 0: self.buf[:data_len] = data[cpylen:] self.buflen = data_len else: self.buf[self.buflen:self.buflen + data_len] = data self.buflen += data_len if last and self.buflen > 0: for i in range(BLOCKLEN - self.buflen): self.buf[self.buflen + i] = 0xFF # ord('-') # erased flash is ff if self.verbose: print('.', end='') self.part.writeblocks(self.block, self.buf) assert len(self.buf) == BLOCKLEN # finish writing the app to the partition and check the sha def _finish(self, check_sha): # flush the app buffer and complete the write self._app_data(b'', last=False) self._app_data(b'', last=True) del self.buf # check the sha calc_sha = binascii.hexlify(self.sha.digest()) check_sha = check_sha.encode() if calc_sha != check_sha: raise ValueError( "SHA mismatch\n calc: {}\n check: {}".format( calc_sha, check_sha)) self.part.set_boot() if self.verbose: print(' Done.')