Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

250 lines
7.7 KiB

#!/usr/bin/env python
#-------------------------------------------------------------------------------
# ESPurna module memory analyser
# xose.perez@gmail.com
#
# Based on:
# https://github.com/letscontrolit/ESPEasy/blob/mega/memanalyzer.py
# by psy0rz <edwin@datux.nl>
# https://raw.githubusercontent.com/SmingHub/Sming/develop/tools/memanalyzer.py
# by Slavey Karadzhov <slav@attachix.com>
# https://github.com/Sermus/ESP8266_memory_analyzer
# by Andrey Filimonov
#
#-------------------------------------------------------------------------------
from collections import OrderedDict
from sortedcontainers import SortedDict
import shlex
import commands
import subprocess
import sys
import os
import re
import argparse
#-------------------------------------------------------------------------------
TOTAL_IRAM = 32786;
TOTAL_DRAM = 81920;
env="esp8266-4m-ota"
objdump_binary = "xtensa-lx106-elf-objdump"
sections = OrderedDict([
("data", "Initialized Data (RAM)"),
("rodata", "ReadOnly Data (RAM)"),
("bss", "Uninitialized Data (RAM)"),
("text", "Cached Code (IRAM)"),
("irom0_text", "Uncached Code (SPI)")
])
description = "ESPurna Memory Analyzer v0.1"
#-------------------------------------------------------------------------------
def file_size(file):
try:
return os.stat(file).st_size
except:
return 0
def analyse_memory(elf_file):
command = "%s -t '%s' " % (objdump_binary, elf_file)
response = subprocess.check_output(shlex.split(command))
if isinstance(response, bytes):
response = response.decode('utf-8')
lines = response.split('\n')
# print("{0: >10}|{1: >30}|{2: >12}|{3: >12}|{4: >8}".format("Section", "Description", "Start (hex)", "End (hex)", "Used space"));
# print("------------------------------------------------------------------------------");
ret={}
usedRAM = 0
usedIRAM = 0
i = 0
for (id, descr) in list(sections.items()):
sectionStartToken = " _%s_start" % id
sectionEndToken = " _%s_end" % id
sectionStart = -1
sectionEnd = -1
for line in lines:
if sectionStartToken in line:
data = line.split(' ')
sectionStart = int(data[0], 16)
if sectionEndToken in line:
data = line.split(' ')
sectionEnd = int(data[0], 16)
if sectionStart != -1 and sectionEnd != -1:
break
sectionLength = sectionEnd - sectionStart
# if i < 3:
# usedRAM += sectionLength
# if i == 3:
# usedIRAM = TOTAL_IRAM - sectionLength;
ret[id]=sectionLength
# print("{0: >10}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(id, descr, sectionStart, sectionEnd, sectionLength))
# i += 1
# print("Total Used RAM : %d" % usedRAM)
# print("Free RAM : %d" % (TOTAL_DRAM - usedRAM))
# print("Free IRam : %d" % usedIRAM)
return(ret)
def run(env, modules):
flags = ""
for item in modules.items():
flags += "-D%s_SUPPORT=%d " % item
command = "export ESPURNA_BOARD=\"WEMOS_D1_MINI_RELAYSHIELD\"; export ESPURNA_FLAGS=\"%s\"; platformio run --silent --environment %s" % (flags, env)
subprocess.check_call(command, shell=True)
def modules_get():
modules = SortedDict()
for line in open("espurna/config/arduino.h"):
m = re.search(r'(\w*)_SUPPORT', line)
if m:
modules[m.group(1)] = 0
del modules['LLMNR']
del modules['NETBIOS']
return modules
try:
# Parse command line options
parser = argparse.ArgumentParser(description=description)
parser.add_argument("modules", nargs='*', help="Modules to test (use ALL to test them all)")
parser.add_argument("-c", "--core", help="use core as base configuration instead of default", default=0, action='count')
parser.add_argument("-l", "--list", help="list available modules", default=0, action='count')
args = parser.parse_args()
# Hello
print
print description
print
# Check xtensa-lx106-elf-objdump is in the path
status, result = commands.getstatusoutput(objdump_binary)
if status != 512:
print "xtensa-lx106-elf-objdump not found, please check it is in your PATH"
sys.exit(1)
# Load list of all modules
available_modules = modules_get()
if args.list > 0:
print "List of available modules:\n"
for key, value in available_modules.items():
print "* " + key
print
sys.exit(0)
# Which modules to test?
test_modules = []
if len(args.modules) > 0:
if "ALL" in args.modules:
test_modules = available_modules.keys()
else:
test_modules = args.modules
# Check test modules exist
for module in test_modules:
if module not in available_modules:
print "Module %s not found" % module
sys.exit(2)
# Define base configuration
if args.core == 0:
modules = SortedDict()
for m in test_modules:
modules[m] = 0
else:
modules = available_modules
# Show init message
if len(test_modules) > 0:
print "Analyzing module(s) %s on top of %s configuration\n" % (", ".join(test_modules), "CORE" if args.core > 0 else "DEFAULT")
else:
print "Analyzing %s configuration\n" % ("CORE" if args.core > 0 else "DEFAULT")
output_format="{:<20}|{:<11}|{:<11}|{:<11}|{:<11}|{:<11}|{:<12}"
print(output_format.format(
"Module",
"Cache IRAM",
"Init RAM",
"R.O. RAM",
"Uninit RAM",
"Flash ROM",
"Binary size"
))
# Build the core without modules to get base memory usage
run(env, modules)
base = analyse_memory(".pioenvs/%s/firmware.elf" % env)
base['size'] = file_size(".pioenvs/%s/firmware.bin" % env)
print(output_format.format(
"CORE" if args.core == 1 else "DEFAULT",
base['text'],
base['data'],
base['rodata'],
base['bss'],
base['irom0_text'],
base['size'],
))
# Test each module
results = {}
for module in test_modules:
modules[module] = 1
run(env, modules)
results[module]=analyse_memory(".pioenvs/%s/firmware.elf" % env)
results[module]['size'] = file_size(".pioenvs/%s/firmware.bin" % env)
modules[module] = 0
print(output_format.format(
module,
results[module]['text'] - base['text'],
results[module]['data'] - base['data'],
results[module]['rodata'] - base['rodata'],
results[module]['bss'] - base['bss'],
results[module]['irom0_text'] - base['irom0_text'],
results[module]['size'] - base['size'],
))
# Test all modules
if len(test_modules) > 0:
for module in test_modules:
modules[module] = 1
run(env, modules)
total = analyse_memory(".pioenvs/%s/firmware.elf" % env)
total['size'] = file_size(".pioenvs/%s/firmware.bin" % env)
if len(test_modules) > 1:
print(output_format.format(
"ALL MODULES",
total['text'] - base['text'],
total['data'] - base['data'],
total['rodata'] - base['rodata'],
total['bss'] - base['bss'],
total['irom0_text'] - base['irom0_text'],
total['size'] - base['size'],
))
print(output_format.format(
"TOTAL",
total['text'],
total['data'],
total['rodata'],
total['bss'],
total['irom0_text'],
total['size'],
))
except:
raise
subprocess.check_call("export ESPURNA_BOARD=\"\"; export ESPURNA_FLAGS=\"\"", shell=True)
print("\n")