Expose the existing registers through Modbus and service CAN using one GAS provider only in M95M02 builds. Include the EEPROM layout/driver, LOAD protection and calibration, firmware identity and shared CCS build workflow. Add transport/profile and SCI8 validation tests, documentation and the checked M95M02 firmware image.
49 lines
2.0 KiB
Python
49 lines
2.0 KiB
Python
"""Validate the PM35 RAM-load SCI8 image against the selected EEPROM profile."""
|
|
import argparse
|
|
from pathlib import Path
|
|
import struct
|
|
|
|
|
|
def check_image(path, eeprom):
|
|
data = path.read_bytes()
|
|
limit = {"AT25256B": 32508, "M95M02": 261884}[eeprom]
|
|
if not 24 <= len(data) <= limit:
|
|
raise ValueError(f"Image size {len(data)} outside 24..{limit}")
|
|
if struct.unpack_from("<H", data)[0] != 0x08AA:
|
|
raise ValueError("Not a SCI8 boot image")
|
|
high, low = struct.unpack_from("<HH", data, 18)
|
|
entry = (high << 16) | low
|
|
position, blocks = 22, []
|
|
while True:
|
|
if position + 2 > len(data):
|
|
raise ValueError("Missing boot terminator")
|
|
words = struct.unpack_from("<H", data, position)[0]
|
|
position += 2
|
|
if not words:
|
|
if position != len(data):
|
|
raise ValueError("Trailing bytes after boot terminator")
|
|
break
|
|
if position + 4 + words * 2 > len(data):
|
|
raise ValueError("Truncated boot block")
|
|
high, low = struct.unpack_from("<HH", data, position)
|
|
address = (high << 16) | low
|
|
end = address + words
|
|
if not 0x8000 <= address < end <= 0xD000:
|
|
raise ValueError(f"Boot destination {address:#x}..{end:#x} outside code RAM")
|
|
if any(address < old_end and old_start < end for old_start, old_end in blocks):
|
|
raise ValueError("Overlapping boot blocks")
|
|
blocks.append((address, end))
|
|
position += 4 + words * 2
|
|
if not any(start <= entry < end for start, end in blocks):
|
|
raise ValueError("Entry point not loaded by the boot table")
|
|
return len(data), len(blocks), limit - len(data)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("image", type=Path)
|
|
parser.add_argument("--eeprom", choices=("AT25256B", "M95M02"), required=True)
|
|
args = parser.parse_args()
|
|
size, blocks, free = check_image(args.image, args.eeprom)
|
|
print(f"PASS SCI8 {args.eeprom}: {size} bytes, {blocks} RAM blocks, {free} bytes free")
|