aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFarouk Bouabid <farouk.bouabid@theobroma-systems.com>2023-10-13 11:50:58 +0200
committerFarouk Bouabid <farouk.bouabid@theobroma-systems.com>2023-10-13 12:16:22 +0200
commit893ef579c6ca9e2cbcc09cb2112e0b06b2b07556 (patch)
treed689f5e12884d93ce4012b90eab64f3d22fdcb29
parentb5707693f5ec9d8f7ef8c51c5ac78ae4f39a6858 (diff)
mule-attiny: i2c_flash: implement bl_data reading from flashloader
After entering the flashloader mode, clearing the boot request gpio sets the flashloader into read-only mode where the flashing tool can read bootloader data through i2c (i2c-write ops are ignored). This data contain: * Bootloader version This tool will print out all bootloader data to the console. Relates-to: RNG-147 Signed-off-by: Farouk Bouabid <farouk.bouabid@theobroma-systems.com>
-rwxr-xr-xmule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/mule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py b/mule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py
index c867558..7beea78 100755
--- a/mule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py
+++ b/mule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py
@@ -11,6 +11,9 @@ from time import sleep
from argparse import ArgumentParser
import pathlib
import logging
+from abc import abstractmethod
+from enum import IntEnum
+
# Bootloader I2C slave address
BL_I2C_DEV = 0x6f # Reuse isl1208 address
@@ -82,6 +85,83 @@ class BootModeController:
raise Exception("UPDI Reset command failed!")
+class BLHdrID(IntEnum):
+ VERSION = 0
+ # Add other bootloader header IDs here
+
+
+def get_blhdr(blhdr):
+ id = (blhdr & (0b111 << 5))
+ if id == BLHdrID.VERSION:
+ return BLVersionHdr(blhdr)
+ # Add other bootloader header IDs here
+ raise Exception(f"Unknown {id} ID for payload header")
+
+
+class BLHdr():
+ def __init__(self, hdr):
+ self.hdr = hdr
+
+ @abstractmethod
+ def len(self):
+ """Returns length of payload excluding header"""
+ pass
+
+ @abstractmethod
+ def payload_class(self):
+ """Returns the class to use for representing the data following the header"""
+ pass
+
+
+class BLVersionHdr(BLHdr):
+ DIRTY_BIT_p = 4
+ DIRTY_BIT_m = (0b1 << DIRTY_BIT_p)
+ LAST_HASH_CHAR_p = 0
+ LAST_HASH_CHAR_m = (0xf << LAST_HASH_CHAR_p)
+
+ def len(self):
+ """1B for MAJOR + 1B for MINOR + 1B for PATCH + 1B for NCOMMITS + 3B for 6 hex digits of the hash"""
+ return 7
+
+ def payload_class(self):
+ return BLVersion
+
+ def is_dirty(self):
+ return bool(self.hdr & BLVersionHdr.DIRTY_BIT_m)
+
+ def last_hash(self):
+ return self.hdr & BLVersionHdr.LAST_HASH_CHAR_m
+
+
+class BLVersion():
+ def __init__(self, header, payload):
+ self.major, self.minor, self.patch, self.ncommits, hash_12, hash_34, hash_56 = payload
+ self.header = header
+ self.dirty = self.header.is_dirty()
+ self.hash = f"{hash_12:02x}{hash_34:02x}{hash_56:02x}{self.header.last_hash():0x}"
+
+ def __str__(self):
+ return f"Bootloader v{self.major}.{self.minor}.{self.patch}-{self.ncommits}-g{self.hash}{'-dirty' if self.dirty else ''} is online" # noqa: E501
+
+
+class BLParser():
+ @classmethod
+ def parse(cls, payload):
+ if not payload:
+ logging.error("No bootloader data is available!")
+ return
+ cursor = 0
+ while cursor < len(payload):
+ blhdr = get_blhdr(payload[cursor])
+ clss = blhdr.payload_class()
+ cursor += 1
+ if len(payload) < cursor + blhdr.len():
+ logging.error(f"Invalid data header of type {type(blhdr).__name__}")
+ return
+ yield clss(blhdr, payload[cursor:cursor + blhdr.len()])
+ cursor += blhdr.len()
+
+
def crc16_xmodem(data):
# Credits: https://gist.github.com/oysstu/68072c44c02879a2abf94ef350d1c7c6?permalink_comment_id=3943460#gistcomment-3943460 # noqa: E501
'''
@@ -190,6 +270,22 @@ def main():
try:
# Request flashloader through bootloader (Set to read-only-mode by default)
bootCtrl.enterFlashloader()
+
+ bus = SMBus(args.i2c_bus)
+ bl_raw_data = []
+ while True:
+ try:
+ # Read bl_data byte per byte
+ bl_raw_data.append(bus.read_byte(BL_I2C_DEV))
+ except IOError:
+ # Bootloader finished sending bl_data
+ break
+
+ bl_data = BLParser.parse(bl_raw_data)
+
+ for d in bl_data:
+ logging.info(d)
+
bootCtrl.exitRoMode()
ret = fw_flash(_bin, args.i2c_bus)