diff --git a/hw/drivers/lwip/stm32_eth/pkg.yml b/hw/drivers/lwip/stm32_eth/pkg.yml index c28fe565a2..55d3241de4 100644 --- a/hw/drivers/lwip/stm32_eth/pkg.yml +++ b/hw/drivers/lwip/stm32_eth/pkg.yml @@ -29,6 +29,9 @@ pkg.deps: - "@apache-mynewt-core/hw/hal" - "@apache-mynewt-core/net/ip/lwip_mn" +pkg.deps.STM32_ETH_SYS_CONFIG: + - "@apache-mynewt-core/sys/config" + pkg.deps.MCU_STM32F4: - "@apache-mynewt-core/hw/mcu/stm/stm32f4xx" @@ -47,6 +50,8 @@ app.cflags: - -DCHECKSUM_CHECK_ICMP=0 - -DCHECKSUM_CHECK_ICMP6=0 +pkg.whole_archive: true + pkg.req_apis: pkg.init: diff --git a/hw/drivers/lwip/stm32_eth/src/stm32_eth.c b/hw/drivers/lwip/stm32_eth/src/stm32_eth.c index a896ca34e9..8e6a12da5a 100644 --- a/hw/drivers/lwip/stm32_eth/src/stm32_eth.c +++ b/hw/drivers/lwip/stm32_eth/src/stm32_eth.c @@ -25,6 +25,13 @@ #include #include +#if MYNEWT_VAL(STM32_ETH_SYS_CONFIG) +#include +#endif + +#include +#include + #if MYNEWT_VAL(MCU_STM32F4) #include #include @@ -205,6 +212,149 @@ HAL_ETH_RxLinkCallback(void **p_start, void **p_end, uint8_t *buff, uint16_t len } } +#define _Args(...) __VA_ARGS__ +#define STRIP_PARENS(X) X +#define UNMANGLE_MYNEWT_VAL(X) STRIP_PARENS(_Args X) + +static uint8_t stm32_eth_mac_address[6] = { UNMANGLE_MYNEWT_VAL( + MYNEWT_VAL_STM32_ETH_MAC_ADDR) }; +static uint8_t stm32_eth_auto_up; +static uint8_t stm32_eth_dhcp; + +#if MYNEWT_VAL(STM32_ETH_SYS_CONFIG) +#define equals(a, b) (strcmp(a, b) == 0) + +static uint8_t +format_hex_digit(int v) +{ + v &= 0xF; + + return (v < 10) ? (v + '0') : (v - 10 + 'A'); +} + +static char * +format_mac_address(const uint8_t *mac, char *buf, size_t buf_len) +{ + if (buf_len < 18) { + buf = NULL; + } else { + for (int i = 0; i < 6; ++i) { + buf[i * 3] = format_hex_digit(stm32_eth_mac_address[i] >> 4); + buf[i * 3 + 1] = format_hex_digit(stm32_eth_mac_address[i]); + buf[i * 3 + 2] = i < 5 ? ':' : '\0'; + } + } + return buf; +} + +static char * +stm32_eth_conf_get(int argc, char **argv, char *val, int val_len_max) +{ + char *ret = NULL; + + if (argc == 1) { + if (equals(argv[0], "up")) { + ret = conf_str_from_value(CONF_BOOL, &stm32_eth_auto_up, val, val_len_max); + } else if (equals(argv[0], "dhcp")) { + ret = conf_str_from_value(CONF_BOOL, &stm32_eth_dhcp, val, val_len_max); + } else if (equals(argv[0], "mac") && val_len_max >= 18) { + ret = format_mac_address(stm32_eth_mac_address, val, val_len_max); + } + } + return ret; +} + +static const char * +byte_from_str(const char *str, uint8_t *out_byte) +{ + uint8_t b = 0; + char c; + + for (int i = 0; i < 2; ++i) { + c = toupper(str[i]); + if (isdigit(c)) { + b = (b << 4) + c - '0'; + } else if (isxdigit(c)) { + b = (b << 4) + c - 'A' + 10; + } else { + return NULL; + } + } + *out_byte = b; + return str + 2; +} + +static int +stm32_eth_conf_set(int argc, char **argv, char *val) +{ + uint8_t mac[6]; + int i; + const char *buf = val; + const char *name = argv[0]; + + if (argc != 1) { + return 0; + } + + if (equals(name, "mac")) { + for (i = 0; buf != NULL && i < 6; ++i) { + buf = byte_from_str(buf, &mac[i]); + if (buf == NULL) { + break; + } + if (i < 5 && buf[0] == ':') { + buf++; + } + } + if (i == 6) { + memcpy(stm32_eth_mac_address, mac, 6); + } else { + return -1; + } + } else if (equals(name, "up")) { + CONF_VALUE_SET(val, CONF_BOOL, stm32_eth_auto_up); + } else if (equals(name, "dhcp")) { + CONF_VALUE_SET(val, CONF_BOOL, stm32_eth_dhcp); + } + + return 0; +} + +static int +stm32_eth_conf_commit(void) +{ + return OS_ENOENT; +} + +static int +stm32_eth_conf_export(void (*export_func)(char *name, char *val), + enum conf_export_tgt tgt) +{ + char buf[20]; + + (void)tgt; + + export_func("eth/mac", + format_mac_address(stm32_eth_mac_address, buf, sizeof(buf))); + export_func("eth/up", conf_str_from_value(CONF_BOOL, &stm32_eth_auto_up, + buf, sizeof(buf))); + export_func("eth/dhcp", + conf_str_from_value(CONF_BOOL, &stm32_eth_dhcp, buf, sizeof(buf))); + + return 0; +} + +struct conf_handler stm32_eth_conf = { .ch_name = "eth", + .ch_get = stm32_eth_conf_get, + .ch_commit = stm32_eth_conf_commit, + .ch_set = stm32_eth_conf_set, + .ch_export = stm32_eth_conf_export }; + +/* Register conf handler statically */ +STATIC_CONF_HANDLER(stm32_eth_conf); + +#endif + /* * Hardware configuration. Should be called from BSP init. */ @@ -476,6 +626,10 @@ stm32_eth_open(void) struct netif *nif; struct ip4_addr addr; int rc; + bool up = MYNEWT_VAL(STM32_ETH_SYS_CONFIG) ? stm32_eth_auto_up + : MYNEWT_VAL(STM32_ETH_AUTO_UP); + bool dhcp = MYNEWT_VAL(STM32_ETH_SYS_CONFIG) ? stm32_eth_dhcp + : MYNEWT_VAL(STM32_ETH_DHCP); if (ses->cfg == NULL) { /* @@ -484,7 +638,7 @@ stm32_eth_open(void) return -1; } - stm32_eth_set_hwaddr(MYNEWT_VAL(STM32_MAC_ADDR)); + stm32_eth_set_hwaddr(stm32_eth_mac_address); if (ses->cfg->sec_phy_irq >= 0) { rc = hal_gpio_irq_init(ses->cfg->sec_phy_irq, stm32_phy_isr, ses, @@ -499,5 +653,14 @@ stm32_eth_open(void) nif = netif_add(&ses->st_nif, &addr, &addr, &addr, NULL, stm32_lwip_init, tcpip_input); assert(nif); + + if (up) { + netif_set_up(nif); + netif_set_default(nif); + if (dhcp) { + dhcp_start(nif); + } + } + return 0; } diff --git a/hw/drivers/lwip/stm32_eth/syscfg.yml b/hw/drivers/lwip/stm32_eth/syscfg.yml index 9fc306941f..65ac9f71c4 100644 --- a/hw/drivers/lwip/stm32_eth/syscfg.yml +++ b/hw/drivers/lwip/stm32_eth/syscfg.yml @@ -24,9 +24,30 @@ syscfg.defs: value: 240 STM32_MAC_ADDR: + description: "Use STM32_ETH_MAC_ADDR instead" + defunct: 1 + + STM32_ETH_MAC_ADDR: description: "Use given array of 6 bytes for MAC address." - value: ((uint8_t[6]){0x00, 0x01, 0x01, 0x02, 0x02, 0x03}) + value: 0x00,0x01,0x01,0x02,0x02,0x03 STM32_ETH_RX_BUFFER_CNT: description: "Number of buffers to store RX packets" value: 10 + + STM32_ETH_AUTO_UP: + description: > + When set to 1 interface will be enabled automatically. + value: 1 + + STM32_ETH_DHCP: + description: > + When set to 1 dhcp will be started automatically. + value: 1 + + STM32_ETH_SYS_CONFIG: + description: > + When set to 1 mac address auto up and dhcp settings + are taken from sys/config instead of syscfg. + value: 0 + diff --git a/sys/config/include/config/config.h b/sys/config/include/config/config.h index 81ab7a6f4a..84f67ce08d 100644 --- a/sys/config/include/config/config.h +++ b/sys/config/include/config/config.h @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -426,6 +427,12 @@ void conf_lock(void); */ void conf_unlock(void); +typedef struct conf_handler *conf_handler_t; +LINK_TABLE(struct conf_handler *, static_conf_handlers); + +#define STATIC_CONF_HANDLER(handler) \ + LINK_TABLE_ELEMENT_REF(static_conf_handlers, handler, handler); + #ifdef __cplusplus } #endif diff --git a/sys/config/pkg.yml b/sys/config/pkg.yml index 3866f31f1e..9f78297168 100644 --- a/sys/config/pkg.yml +++ b/sys/config/pkg.yml @@ -41,6 +41,9 @@ pkg.deps.CONFIG_LITTLEFS: pkg.whole_archive: true +pkg.link_tables: + - static_conf_handlers + pkg.init: config_pkg_init: 'MYNEWT_VAL(CONFIG_SYSINIT_STAGE_1)' config_pkg_init_stage2: 'MYNEWT_VAL(CONFIG_SYSINIT_STAGE_2)' diff --git a/sys/config/src/config.c b/sys/config/src/config.c index b03a285e1a..3e675b6b1a 100644 --- a/sys/config/src/config.c +++ b/sys/config/src/config.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "os/mynewt.h" #include "base64/base64.h" @@ -48,7 +49,9 @@ conf_init(void) os_mutex_init(&conf_mtx); - SLIST_INIT(&conf_handlers); + if (MYNEWT_VAL(CONFIG_HANDLERS_DYNAMIC)) { + SLIST_INIT(&conf_handlers); + } conf_store_init(); (void)rc; @@ -104,9 +107,18 @@ conf_handler_lookup(char *name) { struct conf_handler *ch; - SLIST_FOREACH(ch, &conf_handlers, ch_list) { - if (!strcmp(name, ch->ch_name)) { - return ch; + if (MYNEWT_VAL(CONFIG_HANDLERS_STATIC)) { + LINK_TABLE_FOREACH(h, static_conf_handlers) { + if (!strcmp(name, (*h)->ch_name)) { + return *h; + } + } + } + if (MYNEWT_VAL(CONFIG_HANDLERS_DYNAMIC)) { + SLIST_FOREACH(ch, &conf_handlers, ch_list) { + if (!strcmp(name, ch->ch_name)) { + return ch; + } } } return NULL; @@ -412,8 +424,15 @@ conf_export(conf_export_func_t export_func, enum conf_export_tgt tgt) struct conf_handler *ch; conf_lock(); - SLIST_FOREACH(ch, &conf_handlers, ch_list) { - conf_export_cb(ch, export_func, tgt); + if (MYNEWT_VAL(CONFIG_HANDLERS_STATIC)) { + LINK_TABLE_FOREACH(h, static_conf_handlers) { + conf_export_cb(*h, export_func, tgt); + } + } + if (MYNEWT_VAL(CONFIG_HANDLERS_DYNAMIC)) { + SLIST_FOREACH(ch, &conf_handlers, ch_list) { + conf_export_cb(ch, export_func, tgt); + } } conf_unlock(); } @@ -487,11 +506,23 @@ conf_commit(char *name) rc = conf_commit_cb(ch); } else { rc = 0; - SLIST_FOREACH(ch, &conf_handlers, ch_list) { - if (ch->ch_commit) { - rc2 = conf_commit_cb(ch); - if (!rc) { - rc = rc2; + if (MYNEWT_VAL(CONFIG_HANDLERS_STATIC)) { + LINK_TABLE_FOREACH(h, static_conf_handlers) { + if ((*h)->ch_commit) { + rc2 = conf_commit_cb(*h); + if (!rc) { + rc = rc2; + } + }; + } + } + if (MYNEWT_VAL(CONFIG_HANDLERS_DYNAMIC)) { + SLIST_FOREACH(ch, &conf_handlers, ch_list) { + if (ch->ch_commit) { + rc2 = conf_commit_cb(ch); + if (!rc) { + rc = rc2; + } } } } diff --git a/sys/config/src/config_init.c b/sys/config/src/config_init.c index 8108713f5e..2392ede506 100644 --- a/sys/config/src/config_init.c +++ b/sys/config/src/config_init.c @@ -125,6 +125,10 @@ config_pkg_init(void) #elif MYNEWT_VAL(CONFIG_FCB2) config_init_fcb2(); #endif +#if MYNEWT_VAL(CONFIG_AUTO_LOAD) + conf_load(); +#endif + #endif } diff --git a/sys/config/src/config_store.c b/sys/config/src/config_store.c index a5bc5828a7..f1ac586a0c 100644 --- a/sys/config/src/config_store.c +++ b/sys/config/src/config_store.c @@ -304,10 +304,20 @@ conf_save(void) cs->cs_itf->csi_save_start(cs); } rc = 0; - SLIST_FOREACH(ch, &conf_handlers, ch_list) { - rc2 = conf_export_cb(ch, conf_store_one, CONF_EXPORT_PERSIST); - if (!rc) { - rc = rc2; + if (MYNEWT_VAL(CONFIG_HANDLERS_STATIC)) { + LINK_TABLE_FOREACH(h, static_conf_handlers) { + rc2 = conf_export_cb(*h, conf_store_one, CONF_EXPORT_PERSIST); + if (!rc) { + rc = rc2; + } + } + } + if (MYNEWT_VAL(CONFIG_HANDLERS_DYNAMIC)) { + SLIST_FOREACH(ch, &conf_handlers, ch_list) { + rc2 = conf_export_cb(ch, conf_store_one, CONF_EXPORT_PERSIST); + if (!rc) { + rc = rc2; + } } } if (cs->cs_itf->csi_save_end) { diff --git a/sys/config/syscfg.yml b/sys/config/syscfg.yml index f4de27fdba..49731dee26 100644 --- a/sys/config/syscfg.yml +++ b/sys/config/syscfg.yml @@ -83,6 +83,23 @@ syscfg.defs: description: 'Automatically configure a single config region at bootup' value: 1 + CONFIG_AUTO_LOAD: + description: > + Load config values during config init stage. This could be enabled + if all config handlers are statically defined. + value: 0 + + CONFIG_HANDLERS_DYNAMIC: + description: > + Config handler can be registered in runtime via conf_register. + value: 1 + + CONFIG_HANDLERS_STATIC: + description: > + Config handler are configured during build. Reducing memory + footprint and package init dependency + value: 1 + CONFIG_SYSINIT_STAGE_1: description: > Primary sysinit stage for the config package. diff --git a/sys/fault/pkg.yml b/sys/fault/pkg.yml index bf5f460f67..6691fd3c1b 100644 --- a/sys/fault/pkg.yml +++ b/sys/fault/pkg.yml @@ -32,5 +32,7 @@ pkg.deps: pkg.deps.FAULT_CLI: - "@apache-mynewt-core/sys/fault/fault_cli" +pkg.whole_archive: true + pkg.init: fault_init: MYNEWT_VAL(FAULT_SYSINIT_STAGE) diff --git a/sys/fault/src/fault.c b/sys/fault/src/fault.c index b8ff7aa1db..2a372baf27 100644 --- a/sys/fault/src/fault.c +++ b/sys/fault/src/fault.c @@ -345,10 +345,6 @@ fault_register_domain_priv(int domain_id, uint8_t success_delta, void fault_init(void) { - int rc; - - rc = fault_conf_init(); - SYSINIT_PANIC_ASSERT(rc == 0); } #endif /* !MYNEWT_VAL(FAULT_STUB) */ diff --git a/sys/fault/src/fault_conf.c b/sys/fault/src/fault_conf.c index 0e00ab6ca1..73773f17fd 100644 --- a/sys/fault/src/fault_conf.c +++ b/sys/fault/src/fault_conf.c @@ -103,8 +103,4 @@ fault_conf_persist_chronic_counts(void) return conf_save_one("fault/chronfail", buf); } -int -fault_conf_init(void) -{ - return conf_register(&fault_conf_handler); -} +STATIC_CONF_HANDLER(fault_conf_handler) diff --git a/sys/fault/src/fault_priv.h b/sys/fault/src/fault_priv.h index f0aee061ef..4e10c721fe 100644 --- a/sys/fault/src/fault_priv.h +++ b/sys/fault/src/fault_priv.h @@ -26,6 +26,5 @@ extern uint8_t fault_chronic_counts[MYNEWT_VAL(FAULT_MAX_DOMAINS)]; int fault_conf_persist_chronic_counts(void); -int fault_conf_init(void); #endif diff --git a/sys/id/pkg.yml b/sys/id/pkg.yml index ac6cceff0e..4824b2b66a 100644 --- a/sys/id/pkg.yml +++ b/sys/id/pkg.yml @@ -33,5 +33,7 @@ pkg.deps: - "@apache-mynewt-core/sys/mfg" - "@apache-mynewt-core/encoding/base64" +pkg.whole_archive: true + pkg.init: id_init: 'MYNEWT_VAL(ID_SYSINIT_STAGE)' diff --git a/sys/id/src/id.c b/sys/id/src/id.c index 4a6a2e5f8e..8a8ee1bf6e 100644 --- a/sys/id/src/id.c +++ b/sys/id/src/id.c @@ -236,14 +236,11 @@ id_read_mfghash(void) void id_init(void) { - int rc; - /* Ensure this function only gets called by sysinit. */ SYSINIT_ASSERT_ACTIVE(); - rc = conf_register(&id_conf); - SYSINIT_PANIC_ASSERT(rc == 0); - /* Attempt to read the manufacturing image hash from the meta region. */ id_read_mfghash(); } + +STATIC_CONF_HANDLER(id_conf)