ESP8266 early init for pins (#3144)

This commit is contained in:
Otto Winter 2022-02-17 04:59:46 +01:00 committed by GitHub
parent ffa19426d7
commit 5a0b8328d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 89 additions and 6 deletions

View file

@ -17,11 +17,16 @@ import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
from esphome.helpers import copy_file_if_changed from esphome.helpers import copy_file_if_changed
from .const import CONF_RESTORE_FROM_FLASH, KEY_BOARD, KEY_ESP8266, esp8266_ns from .const import (
CONF_RESTORE_FROM_FLASH,
KEY_BOARD,
KEY_ESP8266,
KEY_PIN_INITIAL_STATES,
esp8266_ns,
)
from .boards import ESP8266_FLASH_SIZES, ESP8266_LD_SCRIPTS from .boards import ESP8266_FLASH_SIZES, ESP8266_LD_SCRIPTS
# force import gpio to register pin schema from .gpio import PinInitialState, add_pin_initial_states_array
from .gpio import esp8266_pin_to_code # noqa
CODEOWNERS = ["@esphome/core"] CODEOWNERS = ["@esphome/core"]
@ -37,6 +42,9 @@ def set_core_data(config):
config[CONF_FRAMEWORK][CONF_VERSION] config[CONF_FRAMEWORK][CONF_VERSION]
) )
CORE.data[KEY_ESP8266][KEY_BOARD] = config[CONF_BOARD] CORE.data[KEY_ESP8266][KEY_BOARD] = config[CONF_BOARD]
CORE.data[KEY_ESP8266][KEY_PIN_INITIAL_STATES] = [
PinInitialState() for _ in range(16)
]
return config return config
@ -221,6 +229,8 @@ async def to_code(config):
if ld_script is not None: if ld_script is not None:
cg.add_platformio_option("board_build.ldscript", ld_script) cg.add_platformio_option("board_build.ldscript", ld_script)
CORE.add_job(add_pin_initial_states_array)
# Called by writer.py # Called by writer.py
def copy_files(): def copy_files():

View file

@ -2,6 +2,7 @@ import esphome.codegen as cg
KEY_ESP8266 = "esp8266" KEY_ESP8266 = "esp8266"
KEY_BOARD = "board" KEY_BOARD = "board"
KEY_PIN_INITIAL_STATES = "pin_initial_states"
CONF_RESTORE_FROM_FLASH = "restore_from_flash" CONF_RESTORE_FROM_FLASH = "restore_from_flash"
# esp8266 namespace is already defined by arduino, manually prefix esphome # esp8266 namespace is already defined by arduino, manually prefix esphome

View file

@ -1,5 +1,6 @@
#ifdef USE_ESP8266 #ifdef USE_ESP8266
#include "core.h"
#include "esphome/core/hal.h" #include "esphome/core/hal.h"
#include "esphome/core/helpers.h" #include "esphome/core/helpers.h"
#include "preferences.h" #include "preferences.h"
@ -53,6 +54,15 @@ extern "C" void resetPins() { // NOLINT
// however, not strictly needed as we set up the pins properly // however, not strictly needed as we set up the pins properly
// ourselves and this causes pins to toggle during reboot. // ourselves and this causes pins to toggle during reboot.
force_link_symbols(); force_link_symbols();
for (int i = 0; i < 16; i++) {
uint8_t mode = ESPHOME_ESP8266_GPIO_INITIAL_MODE[i];
uint8_t level = ESPHOME_ESP8266_GPIO_INITIAL_LEVEL[i];
if (mode != 255)
pinMode(i, mode); // NOLINT
if (level != 255)
digitalWrite(i, level); // NOLINT
}
} }
} // namespace esphome } // namespace esphome

View file

@ -0,0 +1,14 @@
#pragma once
#ifdef USE_ESP8266
#include <cstdint>
extern const uint8_t ESPHOME_ESP8266_GPIO_INITIAL_MODE[16];
extern const uint8_t ESPHOME_ESP8266_GPIO_INITIAL_LEVEL[16];
namespace esphome {
namespace esp8266 {} // namespace esp8266
} // namespace esphome
#endif // USE_ESP8266

View file

@ -1,4 +1,6 @@
import logging import logging
from dataclasses import dataclass
from typing import List
from esphome.const import ( from esphome.const import (
CONF_ID, CONF_ID,
@ -12,12 +14,12 @@ from esphome.const import (
CONF_PULLUP, CONF_PULLUP,
) )
from esphome import pins from esphome import pins
from esphome.core import CORE from esphome.core import CORE, coroutine_with_priority
import esphome.config_validation as cv import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
from . import boards from . import boards
from .const import KEY_BOARD, KEY_ESP8266, esp8266_ns from .const import KEY_BOARD, KEY_ESP8266, KEY_PIN_INITIAL_STATES, esp8266_ns
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -160,11 +162,57 @@ ESP8266_PIN_SCHEMA = cv.All(
) )
@dataclass
class PinInitialState:
mode = 255
level: int = 255
@pins.PIN_SCHEMA_REGISTRY.register("esp8266", ESP8266_PIN_SCHEMA) @pins.PIN_SCHEMA_REGISTRY.register("esp8266", ESP8266_PIN_SCHEMA)
async def esp8266_pin_to_code(config): async def esp8266_pin_to_code(config):
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID])
num = config[CONF_NUMBER] num = config[CONF_NUMBER]
mode = config[CONF_MODE]
cg.add(var.set_pin(num)) cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED])) cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE]))) cg.add(var.set_flags(pins.gpio_flags_expr(mode)))
if num < 16:
initial_state: PinInitialState = CORE.data[KEY_ESP8266][KEY_PIN_INITIAL_STATES][
num
]
if mode[CONF_INPUT]:
if mode[CONF_PULLDOWN]:
initial_state.mode = cg.global_ns.INPUT_PULLDOWN_16
elif mode[CONF_PULLUP]:
initial_state.mode = cg.global_ns.INPUT_PULLUP
else:
initial_state.mode = cg.global_ns.INPUT
elif mode[CONF_OUTPUT]:
if mode[CONF_OPEN_DRAIN]:
initial_state.mode = cg.global_ns.OUTPUT_OPEN_DRAIN
else:
initial_state.mode = cg.global_ns.OUTPUT
initial_state.level = int(config[CONF_INVERTED])
return var return var
@coroutine_with_priority(-999.0)
async def add_pin_initial_states_array():
# Add includes at the very end, so that they override everything
initial_states: List[PinInitialState] = CORE.data[KEY_ESP8266][
KEY_PIN_INITIAL_STATES
]
initial_modes_s = ", ".join(str(x.mode) for x in initial_states)
initial_levels_s = ", ".join(str(x.level) for x in initial_states)
cg.add_global(
cg.RawExpression(
f"const uint8_t ESPHOME_ESP8266_GPIO_INITIAL_MODE[16] = {{{initial_modes_s}}}"
)
)
cg.add_global(
cg.RawExpression(
f"const uint8_t ESPHOME_ESP8266_GPIO_INITIAL_LEVEL[16] = {{{initial_levels_s}}}"
)
)