Browse Source

Merged in ryan_jarvis/espurna/dev (pull request #45)

Conflicts:
	code/ota.py
i18n
Xose Pérez 6 years ago
parent
commit
ff2b110b2a
2 changed files with 151 additions and 141 deletions
  1. +94
    -92
      code/memanalyzer.py
  2. +57
    -49
      code/ota.py

+ 94
- 92
code/memanalyzer.py View File

@ -1,5 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
#-------------------------------------------------------------------------------
# coding=utf-8
# -------------------------------------------------------------------------------
# ESPurna module memory analyser # ESPurna module memory analyser
# xose.perez@gmail.com # xose.perez@gmail.com
# #
@ -11,23 +12,24 @@
# https://github.com/Sermus/ESP8266_memory_analyzer # https://github.com/Sermus/ESP8266_memory_analyzer
# by Andrey Filimonov # by Andrey Filimonov
# #
#-------------------------------------------------------------------------------
# -------------------------------------------------------------------------------
from __future__ import print_function
from collections import OrderedDict
from sortedcontainers import SortedDict
import argparse
import os
import re
import shlex import shlex
import commands
import subprocess import subprocess
import sys import sys
import os
import re
import argparse
from collections import OrderedDict
#-------------------------------------------------------------------------------
from sortedcontainers import SortedDict
TOTAL_IRAM = 32786;
TOTAL_DRAM = 81920;
env="esp8266-4m-ota"
# -------------------------------------------------------------------------------
TOTAL_IRAM = 32786
TOTAL_DRAM = 81920
env = "esp8266-4m-ota"
objdump_binary = "xtensa-lx106-elf-objdump" objdump_binary = "xtensa-lx106-elf-objdump"
sections = OrderedDict([ sections = OrderedDict([
("data", "Initialized Data (RAM)"), ("data", "Initialized Data (RAM)"),
@ -38,7 +40,8 @@ sections = OrderedDict([
]) ])
description = "ESPurna Memory Analyzer v0.1" description = "ESPurna Memory Analyzer v0.1"
#-------------------------------------------------------------------------------
# -------------------------------------------------------------------------------
def file_size(file): def file_size(file):
try: try:
@ -46,8 +49,8 @@ def file_size(file):
except: except:
return 0 return 0
def analyse_memory(elf_file):
def analyse_memory(elf_file):
command = "%s -t '%s' " % (objdump_binary, elf_file) command = "%s -t '%s' " % (objdump_binary, elf_file)
response = subprocess.check_output(shlex.split(command)) response = subprocess.check_output(shlex.split(command))
if isinstance(response, bytes): if isinstance(response, bytes):
@ -56,59 +59,59 @@ def analyse_memory(elf_file):
# print("{0: >10}|{1: >30}|{2: >12}|{3: >12}|{4: >8}".format("Section", "Description", "Start (hex)", "End (hex)", "Used space")); # print("{0: >10}|{1: >30}|{2: >12}|{3: >12}|{4: >8}".format("Section", "Description", "Start (hex)", "End (hex)", "Used space"));
# print("------------------------------------------------------------------------------"); # 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
ret = {}
for (id_, descr) in list(sections.items()):
section_start_token = " _%s_start" % id_
section_end_token = " _%s_end" % id_
section_start = -1
section_end = -1
for line in lines: for line in lines:
if sectionStartToken in line:
if section_start_token in line:
data = line.split(' ') data = line.split(' ')
sectionStart = int(data[0], 16)
section_start = int(data[0], 16)
if sectionEndToken in line:
if section_end_token in line:
data = line.split(' ') data = line.split(' ')
sectionEnd = int(data[0], 16)
section_end = int(data[0], 16)
if sectionStart != -1 and sectionEnd != -1:
if section_start != -1 and section_end != -1:
break break
sectionLength = sectionEnd - sectionStart
section_length = section_end - section_start
# if i < 3: # if i < 3:
# usedRAM += sectionLength
# usedRAM += section_length
# if i == 3: # if i == 3:
# usedIRAM = TOTAL_IRAM - sectionLength;
# usedIRAM = TOTAL_IRAM - section_length;
ret[id]=sectionLength
# print("{0: >10}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(id, descr, sectionStart, sectionEnd, sectionLength))
ret[id_] = section_length
# print("{0: >10}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(id_, descr, section_start, section_end, section_length))
# i += 1 # i += 1
# print("Total Used RAM : %d" % usedRAM) # print("Total Used RAM : %d" % usedRAM)
# print("Free RAM : %d" % (TOTAL_DRAM - usedRAM)) # print("Free RAM : %d" % (TOTAL_DRAM - usedRAM))
# print("Free IRam : %d" % usedIRAM) # print("Free IRam : %d" % usedIRAM)
return(ret)
return ret
def run(env, modules):
def run(env_, modules_):
flags = "" flags = ""
for item in modules.items():
for item in modules_.items():
flags += "-D%s_SUPPORT=%d " % item 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)
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) subprocess.check_call(command, shell=True)
def modules_get(): def modules_get():
modules = SortedDict()
modules_ = SortedDict()
for line in open("espurna/config/arduino.h"): for line in open("espurna/config/arduino.h"):
m = re.search(r'(\w*)_SUPPORT', line) m = re.search(r'(\w*)_SUPPORT', line)
if m: if m:
modules[m.group(1)] = 0
del modules['LLMNR']
del modules['NETBIOS']
return modules
modules_[m.group(1)] = 0
del modules_['LLMNR']
del modules_['NETBIOS']
return modules_
try: try:
@ -120,23 +123,22 @@ try:
args = parser.parse_args() args = parser.parse_args()
# Hello # Hello
print
print description
print
print()
print(description)
print()
# Check xtensa-lx106-elf-objdump is in the path # Check xtensa-lx106-elf-objdump is in the path
status, result = commands.getstatusoutput(objdump_binary)
status, result = subprocess.getstatusoutput(objdump_binary)
if status != 512: if status != 512:
print "xtensa-lx106-elf-objdump not found, please check it is in your PATH"
print("xtensa-lx106-elf-objdump not found, please check it is in your PATH")
sys.exit(1) sys.exit(1)
# Load list of all modules # Load list of all modules
available_modules = modules_get() available_modules = modules_get()
if args.list > 0: if args.list > 0:
print "List of available modules:\n"
print("List of available modules:\n")
for key, value in available_modules.items(): for key, value in available_modules.items():
print "* " + key
print
print("* " + key)
print()
sys.exit(0) sys.exit(0)
# Which modules to test? # Which modules to test?
@ -150,7 +152,7 @@ try:
# Check test modules exist # Check test modules exist
for module in test_modules: for module in test_modules:
if module not in available_modules: if module not in available_modules:
print "Module %s not found" % module
print("Module %s not found" % module)
sys.exit(2) sys.exit(2)
# Define base configuration # Define base configuration
@ -163,19 +165,19 @@ try:
# Show init message # Show init message
if len(test_modules) > 0: 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")
print("Analyzing module(s) %s on top of %s configuration\n" % (", ".join(test_modules), "CORE" if args.core > 0 else "DEFAULT"))
else: else:
print "Analyzing %s configuration\n" % ("CORE" if args.core > 0 else "DEFAULT")
print("Analyzing %s configuration\n" % ("CORE" if args.core > 0 else "DEFAULT"))
output_format="{:<20}|{:<11}|{:<11}|{:<11}|{:<11}|{:<11}|{:<12}"
output_format = "{:<20}|{:<11}|{:<11}|{:<11}|{:<11}|{:<11}|{:<12}"
print(output_format.format( print(output_format.format(
"Module",
"Cache IRAM",
"Init RAM",
"R.O. RAM",
"Uninit RAM",
"Flash ROM",
"Binary size"
"Module",
"Cache IRAM",
"Init RAM",
"R.O. RAM",
"Uninit RAM",
"Flash ROM",
"Binary size"
)) ))
# Build the core without modules to get base memory usage # Build the core without modules to get base memory usage
@ -183,13 +185,13 @@ try:
base = analyse_memory(".pioenvs/%s/firmware.elf" % env) base = analyse_memory(".pioenvs/%s/firmware.elf" % env)
base['size'] = file_size(".pioenvs/%s/firmware.bin" % env) base['size'] = file_size(".pioenvs/%s/firmware.bin" % env)
print(output_format.format( print(output_format.format(
"CORE" if args.core == 1 else "DEFAULT",
base['text'],
base['data'],
base['rodata'],
base['bss'],
base['irom0_text'],
base['size'],
"CORE" if args.core == 1 else "DEFAULT",
base['text'],
base['data'],
base['rodata'],
base['bss'],
base['irom0_text'],
base['size'],
)) ))
# Test each module # Test each module
@ -198,18 +200,18 @@ try:
modules[module] = 1 modules[module] = 1
run(env, modules) run(env, modules)
results[module]=analyse_memory(".pioenvs/%s/firmware.elf" % env)
results[module] = analyse_memory(".pioenvs/%s/firmware.elf" % env)
results[module]['size'] = file_size(".pioenvs/%s/firmware.bin" % env) results[module]['size'] = file_size(".pioenvs/%s/firmware.bin" % env)
modules[module] = 0 modules[module] = 0
print(output_format.format( 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'],
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 # Test all modules
@ -223,23 +225,23 @@ try:
if len(test_modules) > 1: if len(test_modules) > 1:
print(output_format.format( 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'],
"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( print(output_format.format(
"TOTAL",
total['text'],
total['data'],
total['rodata'],
total['bss'],
total['irom0_text'],
total['size'],
"TOTAL",
total['text'],
total['data'],
total['rodata'],
total['bss'],
total['irom0_text'],
total['size'],
)) ))
except: except:


+ 57
- 49
code/ota.py View File

@ -1,31 +1,40 @@
#!/usr/bin/env python #!/usr/bin/env python
#-------------------------------------------------------------------------------
# coding=utf-8
# -------------------------------------------------------------------------------
# ESPurna OTA manager # ESPurna OTA manager
# xose.perez@gmail.com # xose.perez@gmail.com
# #
# Requires PlatformIO Core # Requires PlatformIO Core
#-------------------------------------------------------------------------------
# -------------------------------------------------------------------------------
from __future__ import print_function
import sys
import argparse
import re import re
import logging
import socket import socket
import argparse
import subprocess import subprocess
import sys
from time import sleep from time import sleep
from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf
#-------------------------------------------------------------------------------
try:
# noinspection PyUnresolvedReferences
input = raw_input # Python2
except NameError:
pass # Python3
# -------------------------------------------------------------------------------
devices = [] devices = []
description = "ESPurna OTA Manager v0.1" description = "ESPurna OTA Manager v0.1"
#-------------------------------------------------------------------------------
# -------------------------------------------------------------------------------
def on_service_state_change(zeroconf, service_type, name, state_change): def on_service_state_change(zeroconf, service_type, name, state_change):
'''
"""
Callback that adds discovered devices to "devices" list Callback that adds discovered devices to "devices" list
'''
"""
if state_change is ServiceStateChange.Added: if state_change is ServiceStateChange.Added:
info = zeroconf.get_service_info(service_type, name) info = zeroconf.get_service_info(service_type, name)
@ -46,10 +55,11 @@ def on_service_state_change(zeroconf, service_type, name, state_change):
device['free_space'] = info.properties.get('free_space') device['free_space'] = info.properties.get('free_space')
devices.append(device) devices.append(device)
def list(): def list():
'''
"""
Shows the list of discovered devices Shows the list of discovered devices
'''
"""
output_format="{:>3} {:<25}{:<25}{:<15}{:<15}{:<30}{:<10}{:<10}{:<10}" output_format="{:>3} {:<25}{:<25}{:<15}{:<15}{:<30}{:<10}{:<10}{:<10}"
print(output_format.format( print(output_format.format(
"#", "#",
@ -79,12 +89,13 @@ def list():
device.get('free_space', ''), device.get('free_space', ''),
)) ))
print
print()
def get_boards(): def get_boards():
'''
"""
Grabs board types fro hardware.h file Grabs board types fro hardware.h file
'''
"""
boards = [] boards = []
for line in open("espurna/config/hardware.h"): for line in open("espurna/config/hardware.h"):
m = re.search(r'defined\((\w*)\)', line) m = re.search(r'defined\((\w*)\)', line)
@ -92,10 +103,11 @@ def get_boards():
boards.append(m.group(1)) boards.append(m.group(1))
return sorted(boards) return sorted(boards)
def flash(): def flash():
'''
"""
Grabs info from the user about what device to flash Grabs info from the user about what device to flash
'''
"""
# Choose the board # Choose the board
try: try:
@ -103,13 +115,13 @@ def flash():
except: except:
index = 0 index = 0
if index < 0 or len(devices) < index: if index < 0 or len(devices) < index:
print "Board number must be between 1 and %s\n" % str(len(devices))
print("Board number must be between 1 and %s\n" % str(len(devices)))
return None return None
board = {'board': '', 'ip': '', 'size': 0 , 'auth': '', 'flags': ''}
board = {'board': '', 'ip': '', 'size': 0, 'auth': '', 'flags': ''}
if index > 0: if index > 0:
device = devices[index-1]
device = devices[index - 1]
board['board'] = device.get('device', '') board['board'] = device.get('device', '')
board['ip'] = device.get('ip', '') board['ip'] = device.get('ip', '')
board['size'] = int(device.get('mem_size', 0) if device.get('mem_size', 0) == device.get('sdk_size', 0) else 0) / 1024 board['size'] = int(device.get('mem_size', 0) if device.get('mem_size', 0) == device.get('sdk_size', 0) else 0) / 1024
@ -117,68 +129,64 @@ def flash():
# Choose board type if none before # Choose board type if none before
if len(board['board']) == 0: if len(board['board']) == 0:
print
print()
count = 1 count = 1
boards = get_boards() boards = get_boards()
for name in boards: for name in boards:
print "%3d\t%s" % (count, name)
print("%3d\t%s" % (count, name))
count = count + 1 count = count + 1
print
print()
try: try:
index = int(input("Choose the board type you want to flash: ")) index = int(input("Choose the board type you want to flash: "))
except: except:
index = 0 index = 0
if index < 1 or len(boards) < index: if index < 1 or len(boards) < index:
print "Board number must be between 1 and %s\n" % str(len(boards))
print("Board number must be between 1 and %s\n" % str(len(boards)))
return None return None
board['board'] = boards[index-1]
board['board'] = boards[index - 1]
# Choose board size of none before # Choose board size of none before
if board['size'] == 0: if board['size'] == 0:
try: try:
board['size'] = int(input("Board memory size (1 for 1M, 4 for 4M): ")) board['size'] = int(input("Board memory size (1 for 1M, 4 for 4M): "))
except: except:
print "Wrong memory size"
print("Wrong memory size")
return None return None
# Choose IP of none before # Choose IP of none before
if len(board['ip']) == 0: if len(board['ip']) == 0:
try: try:
board['ip'] = raw_input("IP of the device to flash (empty for 192.168.4.1): ") or "192.168.4.1"
board['ip'] = input("IP of the device to flash (empty for 192.168.4.1): ") or "192.168.4.1"
except: except:
print "Wrong IP"
print("Wrong IP")
return None return None
board['auth'] = raw_input("Authorization key of the device to flash: ")
board['flags'] = raw_input("Extra flags for the build: ")
board['auth'] = input("Authorization key of the device to flash: ")
board['flags'] = input("Extra flags for the build: ")
return board return board
def run(device, env): def run(device, env):
command = "export ESPURNA_IP=\"%s\"; export ESPURNA_BOARD=\"%s\"; export ESPURNA_AUTH=\"%s\"; export ESPURNA_FLAGS=\"%s\"; platformio run --silent --environment %s -t upload" command = "export ESPURNA_IP=\"%s\"; export ESPURNA_BOARD=\"%s\"; export ESPURNA_AUTH=\"%s\"; export ESPURNA_FLAGS=\"%s\"; platformio run --silent --environment %s -t upload"
command = command % (device['ip'], device['board'], device['auth'], device['flags'], env) command = command % (device['ip'], device['board'], device['auth'], device['flags'], env)
subprocess.check_call(command, shell=True) subprocess.check_call(command, shell=True)
#-------------------------------------------------------------------------------
# -------------------------------------------------------------------------------
if __name__ == '__main__': if __name__ == '__main__':
# Parse command line options # Parse command line options
parser = argparse.ArgumentParser(description=description) parser = argparse.ArgumentParser(description=description)
#parser.add_argument("-v", "--verbose", help="show verbose output", default=0, action='count')
parser.add_argument("-c", "--core", help="flash ESPurna core", default=0, action='count') parser.add_argument("-c", "--core", help="flash ESPurna core", default=0, action='count')
parser.add_argument("-f", "--flash", help="flash device", default=0, action='count') parser.add_argument("-f", "--flash", help="flash device", default=0, action='count')
parser.add_argument("-s", "--sort", help="sort devices list by field", default='hostname') parser.add_argument("-s", "--sort", help="sort devices list by field", default='hostname')
args = parser.parse_args() args = parser.parse_args()
print
print description
print
# Enable logging if verbose
#logging.basicConfig(level=logging.DEBUG)
#logging.getLogger('zeroconf').setLevel(logging.DEBUG)
print()
print(description)
print()
# Look for sevices # Look for sevices
zeroconf = Zeroconf() zeroconf = Zeroconf()
@ -193,7 +201,7 @@ if __name__ == '__main__':
# Sort list # Sort list
field = args.sort.lower() field = args.sort.lower()
if field not in devices[0]: if field not in devices[0]:
print "Unknown field '%s'\n" % field
print("Unknown field '%s'\n" % field)
sys.exit(1) sys.exit(1)
devices = sorted(devices, key=lambda device: device.get(field, '')) devices = sorted(devices, key=lambda device: device.get(field, ''))
@ -212,14 +220,14 @@ if __name__ == '__main__':
env = "esp8266-%sm-ota" % device['size'] env = "esp8266-%sm-ota" % device['size']
# Summary # Summary
print
print "ESPURNA_IP = %s" % device['ip']
print "ESPURNA_BOARD = %s" % device['board']
print "ESPURNA_AUTH = %s" % device['auth']
print "ESPURNA_FLAGS = %s" % device['flags']
print "ESPURNA_ENV = %s" % env
response = raw_input("\nAre these values right [y/N]: ")
print
print()
print("ESPURNA_IP = %s" % device['ip'])
print("ESPURNA_BOARD = %s" % device['board'])
print("ESPURNA_AUTH = %s" % device['auth'])
print("ESPURNA_FLAGS = %s" % device['flags'])
print("ESPURNA_ENV = %s" % env)
response = input("\nAre these values right [y/N]: ")
print()
if response == "y": if response == "y":
run(device, env) run(device, env)

Loading…
Cancel
Save