Skip to content

Commit

Permalink
Patch libalgobsec.a by repackaging archive
Browse files Browse the repository at this point in the history
  • Loading branch information
ruimarinho committed Jul 20, 2020
1 parent f77e047 commit 786eee9
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 73 deletions.
4 changes: 4 additions & 0 deletions code/espurna/config/sensors.h
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,10 @@
#define BME680_I2C_ADDRESS 0x00 // 0x00 means auto
#endif

#ifndef BME680_READ_INTERVAL
#define BME680_READ_INTERVAL 1000 // Read interval between same device
#endif

// -----------------------------------------------------------------------------
// ADC
// -----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion code/espurna/config/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@
#define MAGNITUDE_CO2E 33
#define MAGNITUDE_IAQ 34
#define MAGNITUDE_IAQ_ACCURACY 35
#define MAGNITUDE_STATIC_IAQ 36
#define MAGNITUDE_IAQ_STATIC 36
#define MAGNITUDE_BVOC 37

#define MAGNITUDE_MAX 38
Expand Down
12 changes: 6 additions & 6 deletions code/espurna/sensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ sensor_magnitude_t::sensor_magnitude_t(unsigned char slot, unsigned char index_l

switch (type) {
case MAGNITUDE_IAQ:
case MAGNITUDE_STATIC_IAQ:
case MAGNITUDE_IAQ_STATIC:
case MAGNITUDE_ENERGY:
filter = new LastFilter();
break;
Expand Down Expand Up @@ -657,8 +657,8 @@ String magnitudeTopic(unsigned char type) {
case MAGNITUDE_IAQ_ACCURACY:
result = F("iaq_accuracy");
break;
case MAGNITUDE_STATIC_IAQ:
result = F("static_iaq");
case MAGNITUDE_IAQ_STATIC:
result = F("iaq_static");
break;
case MAGNITUDE_LUX:
result = F("lux");
Expand Down Expand Up @@ -950,7 +950,7 @@ const char * const _magnitudeSettingsPrefix(unsigned char type) {
case MAGNITUDE_BVOC: return "bvoc";
case MAGNITUDE_IAQ: return "iaq";
case MAGNITUDE_IAQ_ACCURACY: return "iaqAccuracy";
case MAGNITUDE_STATIC_IAQ: return "staticIaq";
case MAGNITUDE_IAQ_STATIC: return "iaqStatic";
case MAGNITUDE_LUX: return "lux";
case MAGNITUDE_UVA: return "uva";
case MAGNITUDE_UVB: return "uvb";
Expand Down Expand Up @@ -1185,8 +1185,8 @@ String magnitudeName(unsigned char type) {
case MAGNITUDE_BVOC:
result = F("bVOC");
break;
case MAGNITUDE_STATIC_IAQ:
result = F("Static IAQ");
case MAGNITUDE_IAQ_STATIC:
result = F("IAQ (Static)");
break;
case MAGNITUDE_IAQ:
result = F("IAQ");
Expand Down
63 changes: 33 additions & 30 deletions code/espurna/sensors/BME680Sensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
#include "I2CSensor.h"
#include "bsec.h"

// The maximum allowed time between two `bsec_sensor_control` calls depends on
// configuration profile `bsec_config_iaq` below. With these settings, the
// maximum allowed time is 3s.
#define SENSOR_READ_INTERVAL 1

// Configuration profile `generic_33v_3s_4d`. The default is `generic_18v_300s_4d`.
// In the future, this can be made dynamic.
//
Expand Down Expand Up @@ -126,36 +121,44 @@ class BME680Sensor : public I2CSensor<> {
if (index == 2) return MAGNITUDE_PRESSURE;
if (index == 3) return MAGNITUDE_RESISTANCE;
if (index == 4) return MAGNITUDE_IAQ_ACCURACY;
if (index == 5) return MAGNITUDE_STATIC_IAQ;
if (index == 5) return MAGNITUDE_IAQ_STATIC;
if (index == 6) return MAGNITUDE_IAQ;
if (index == 7) return MAGNITUDE_CO2E;
if (index == 8) return MAGNITUDE_BVOC;

return MAGNITUDE_NONE;
}

// Pre-read hook (usually to populate registers with up-to-date data)
void pre() {
_error = SENSOR_ERROR_OK;

if (!_isSensorOk()) {
_error = SENSOR_ERROR_OTHER;
return;
}

if (iaqSensor.run()) {
_rawTemperature = iaqSensor.rawTemperature;
_rawHumidity = iaqSensor.rawHumidity;
_temperature = iaqSensor.temperature;
_humidity = iaqSensor.humidity;
_pressure = iaqSensor.pressure / 100;
_gasResistance = iaqSensor.gasResistance;
_iaqAccuracy = iaqSensor.iaqAccuracy;
_iaq = iaqSensor.iaq;
_staticIaq = iaqSensor.staticIaq;
_co2Equivalent = iaqSensor.co2Equivalent;
_breathVocEquivalent = iaqSensor.breathVocEquivalent;
}
// The maximum allowed time between two `bsec_sensor_control` calls depends on
// configuration profile `bsec_config_iaq` below. With these settings, the
// maximum allowed time is 3s.
void tick() {
static unsigned long last_millis = 0;

if (millis() - last_millis < BME680_READ_INTERVAL) return;

last_millis = millis();

_error = SENSOR_ERROR_OK;

if (!_isSensorOk()) {
_error = SENSOR_ERROR_OTHER;
return;
}

if (iaqSensor.run()) {
_rawTemperature = iaqSensor.rawTemperature;
_rawHumidity = iaqSensor.rawHumidity;
_temperature = iaqSensor.temperature;
_humidity = iaqSensor.humidity;
_pressure = iaqSensor.pressure / 100;
_gasResistance = iaqSensor.gasResistance;
_iaqAccuracy = iaqSensor.iaqAccuracy;
_iaq = iaqSensor.iaq;
_iaqStatic = iaqSensor.staticIaq;
_co2Equivalent = iaqSensor.co2Equivalent;
_breathVocEquivalent = iaqSensor.breathVocEquivalent;
}
}

// Current value for slot # index
Expand All @@ -166,7 +169,7 @@ class BME680Sensor : public I2CSensor<> {
if (index == 3) return _gasResistance;
if (index == 4) return _iaqAccuracy;
if (index == 5) return _iaq;
if (index == 6) return _staticIaq;
if (index == 6) return _iaqStatic;
if (index == 7) return _co2Equivalent;
if (index == 8) return _breathVocEquivalent;
return 0;
Expand Down Expand Up @@ -230,7 +233,7 @@ class BME680Sensor : public I2CSensor<> {
uint _iaqAccuracy = 0;
double _temperature = 0.0f;
double _humidity = 0.0f;
uint _staticIaq = 0;
uint _iaqStatic = 0;
double _co2Equivalent = 0.0f;
double _breathVocEquivalent = 0.0f;

Expand Down
2 changes: 2 additions & 0 deletions code/scripts/espurna_utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .checks import check_cppcheck, check_printsize
from .float_support import remove_float_support
from .ldscripts import ldscripts_inject_libpath
from .bsec import bsec_inject_patcher
from .lwip import lwip_inject_patcher
from .postmortem import dummy_ets_printf
from .git import app_inject_revision
Expand All @@ -33,6 +34,7 @@
"check_printsize",
"remove_float_support",
"ldscripts_inject_libpath",
"bsec_inject_patcher",
"lwip_inject_patcher",
"dummy_ets_printf",
"app_inject_revision",
Expand Down
107 changes: 107 additions & 0 deletions code/scripts/espurna_utils/bsec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import os

def bsec_inject_patcher(env):
platform = env.PioPlatform()
framework_dir = platform.get_package_dir("framework-arduinoespressif8266")
bsec_dir = os.path.join(
"${PROJECT_LIBDEPS_DIR}", "${PIOENV}", "BSEC Software Library", "src", "esp8266"
)

env.Append(LIBPATH=[bsec_dir])
env.Append(LIBS=["algobsec"])

patchflag_path = os.path.join(env.subst(bsec_dir), ".patching-done")

if os.path.isfile(patchflag_path):
print("Archive libalgosec.a has already been patched")
return

toolchain_ar = os.path.join(
platform.get_package_dir("toolchain-xtensa"), "bin", "xtensa-lx106-elf-ar"
)

# Backup libalgobsec.a into libalgobsec.a.orig.
backup_action = env.VerboseAction(
" ".join(
[
'/bin/mv',
os.path.join(bsec_dir.replace(' ', '\\ '), "libalgobsec.a"),
os.path.join(bsec_dir.replace(' ', '\\ '), "libalgobsec.a.orig")
]
),
"Backing up BSEC libalgosec.a to libalgosec.a.orig",
)

# Extract libalgobsec.a into *.o files.
extract_action = env.VerboseAction(
" ".join(
[
toolchain_ar,
"-xv",
os.path.join(bsec_dir.replace(' ', '\\ '), "libalgobsec.a.orig")
]
),
"Extracting BSEC libalgobsec.a.orig",
)

# Archive *.c.o files into libalgobsec.a.
archive_action = env.VerboseAction(
" ".join(
[
toolchain_ar,
"-crv",
os.path.join(bsec_dir.replace(' ', '\\ '), "libalgobsec.a"),
"*.c.o"
]
),
"Archiving BSEC libalgosec.a",
)

# Create patch flag file.
touch_action = env.VerboseAction(
" ".join(
[
"/usr/bin/touch",
patchflag_path.replace(' ', '\\ '),
]
),
"Touching patch flag",
)

# Remove renamed files.
cleanup_action = env.VerboseAction(
" ".join(
[
"rm",
"*.c.o",
]
),
"Cleaning up",
)

env.Execute(backup_action)
env.Execute(extract_action)

rename_files()

env.Execute(archive_action)
env.Execute(touch_action)
env.Execute(cleanup_action)


# Rename *.o to *.c.o so that the linker places this library
# into ROM instead of RAM.
def rename_files():
folder = os.getcwd();
for filename in os.listdir(folder):
infilename = os.path.join(folder, filename)
if not os.path.isfile(infilename):
continue

(name, ext) = os.path.splitext(filename)
print(ext)
if not ext == ".o":
continue

newname = filename.replace('.o', '.c.o')
output = os.rename(infilename, newname)
36 changes: 0 additions & 36 deletions code/scripts/espurna_utils/ldscripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,3 @@ def check_local_ld(target, source, env):
env.Prepend(LIBPATH=[os.path.join(libpath_base, "latest")])

env.AddPreAction(os.path.join("$BUILD_DIR", "firmware.elf"), check_local_ld)

# Bosch Sensortec Environment Cluster (BSEC) support
build_flags = env.ParseFlags(env['BUILD_FLAGS'])
espurna_flags = env.ParseFlags(env['ESPURNA_FLAGS'])

flags_with_value_list = [build_flag for build_flag in build_flags.get('CPPDEFINES') if type(build_flag) == list]
build_defines = {k: v for (k, v) in flags_with_value_list}

flags_with_value_list = [build_flag for build_flag in espurna_flags.get('CPPDEFINES') if type(build_flag) == list]
espurna_defines = {k: v for (k, v) in flags_with_value_list}

if build_defines.get('BME680_SUPPORT') == '1' or espurna_defines.get('BME680_SUPPORT') == '1':
ldscripts_inject_libpath_bme680(env)

def ldscripts_inject_libpath_bme680(env):
platform = env.PioPlatform()
framework_dir = platform.get_package_dir("framework-arduinoespressif8266")
libpath_sdk = os.path.join(framework_dir, "tools", "sdk", "ld")
ldpath = os.path.join(libpath_sdk, "eagle.app.v6.common.ld")

# Due to the architecture of the ESP8266's memory and current size of the BSEC library,
# we need to modify the linker script and specifically define where the library should
# be placed in memory, otherwise the error 'section `.text1' will not fit in region
# `iram1_0_seg' will be returned.
pattern = re.compile(".*irom0.literal.*")
with open(ldpath, "r") as sources:
lines = sources.readlines()
with open(ldpath, "w") as sources:
for line in lines:
if pattern.match(line):
sources.write(" *libalgobsec.a:(.literal.* .text.*)\n")
sources.write(line)

# Load proprietary BSEC software of precise IAQ measurement.
env.Append(LIBPATH=["${PROJECT_LIBDEPS_DIR}/${PIOENV}/BSEC Software Library/src/esp8266"])
env.Append(LIBS=["algobsec"])
3 changes: 3 additions & 0 deletions code/scripts/pio_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
check_printsize,
remove_float_support,
ldscripts_inject_libpath,
bsec_inject_patcher,
lwip_inject_patcher,
app_inject_revision,
dummy_ets_printf,
Expand Down Expand Up @@ -48,6 +49,8 @@
"$BUILD_DIR/FrameworkArduino/core_esp8266_postmortem.cpp.o", dummy_ets_printf
)

bsec_inject_patcher(env)

# patch lwip1 sources conditionally:
# https://github.com/xoseperez/espurna/issues/1610
lwip_inject_patcher(env)
Expand Down

0 comments on commit 786eee9

Please sign in to comment.