diff --git a/Sming/Arch/Esp8266/Core/Digital.cpp b/Sming/Arch/Esp8266/Core/Digital.cpp index d8bb1e6021..7a7af26d1e 100644 --- a/Sming/Arch/Esp8266/Core/Digital.cpp +++ b/Sming/Arch/Esp8266/Core/Digital.cpp @@ -9,19 +9,42 @@ ****/ #include -#include "ESP8266EX.h" #include #include #include #include +#define TOTAL_PINS 16 + +#define PINMUX_OFFSET(addr) uint8_t((addr)-PERIPHS_IO_MUX) + +// Used for pullup/noPullup +extern const uint8_t esp8266_pinmuxOffset[] = { + PINMUX_OFFSET(PERIPHS_IO_MUX_GPIO0_U), // 0 FLASH + PINMUX_OFFSET(PERIPHS_IO_MUX_U0TXD_U), // 1 TXD0 + PINMUX_OFFSET(PERIPHS_IO_MUX_GPIO2_U), // 2 TXD1 + PINMUX_OFFSET(PERIPHS_IO_MUX_U0RXD_U), // 3 RXD0 + PINMUX_OFFSET(PERIPHS_IO_MUX_GPIO4_U), // 4 + PINMUX_OFFSET(PERIPHS_IO_MUX_GPIO5_U), // 5 + PINMUX_OFFSET(PERIPHS_IO_MUX_SD_CLK_U), // 6 SD_CLK_U + PINMUX_OFFSET(PERIPHS_IO_MUX_SD_DATA0_U), // 7 SD_DATA0_U + PINMUX_OFFSET(PERIPHS_IO_MUX_SD_DATA1_U), // 8 SD_DATA1_U + PINMUX_OFFSET(PERIPHS_IO_MUX_SD_DATA2_U), // 9 + PINMUX_OFFSET(PERIPHS_IO_MUX_SD_DATA3_U), // 10 + PINMUX_OFFSET(PERIPHS_IO_MUX_SD_CMD_U), // 11 SD_CMD_U + PINMUX_OFFSET(PERIPHS_IO_MUX_MTDI_U), // 12 HSPIQ + PINMUX_OFFSET(PERIPHS_IO_MUX_MTCK_U), // 13 HSPID + PINMUX_OFFSET(PERIPHS_IO_MUX_MTMS_U), // 14 HSPICLK + PINMUX_OFFSET(PERIPHS_IO_MUX_MTDO_U), // 15 HSPICS +}; + // Prototype declared in esp8266-peri.h -const uint8_t esp8266_gpioToFn[16] = {0x34, 0x18, 0x38, 0x14, 0x3C, 0x40, 0x1C, 0x20, - 0x24, 0x28, 0x2C, 0x30, 0x04, 0x08, 0x0C, 0x10}; +const uint8_t esp8266_gpioToFn[TOTAL_PINS] = {0x34, 0x18, 0x38, 0x14, 0x3C, 0x40, 0x1C, 0x20, + 0x24, 0x28, 0x2C, 0x30, 0x04, 0x08, 0x0C, 0x10}; void pinMode(uint16_t pin, uint8_t mode) { - if(pin < 16) { + if(pin < TOTAL_PINS) { if(mode == SPECIAL) { GPC(pin) = (GPC(pin) & (0xF << GPCI)); //SOURCE(GPIO) | DRIVER(NORMAL) | INT_TYPE(UNCHANGED) | WAKEUP_ENABLE(DISABLED) @@ -100,38 +123,32 @@ void digitalWrite(uint16_t pin, uint8_t val) pullup(pin); else noPullup(pin); - } else { - if(pin != 16) - GPIO_REG_WRITE((((val != LOW) ? GPIO_OUT_W1TS_ADDRESS : GPIO_OUT_W1TC_ADDRESS)), (1 << pin)); - else - WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & (uint32_t)0xfffffffe) | (uint32_t)(val & 1)); - - //GPIO_OUTPUT_SET(pin, (val ? 0xFF : 00)); - } + } else if(pin != 16) + GPIO_REG_WRITE((((val != LOW) ? GPIO_OUT_W1TS_ADDRESS : GPIO_OUT_W1TC_ADDRESS)), (1 << pin)); + else + WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & (uint32_t)0xfffffffe) | (uint32_t)(val & 1)); } uint8_t digitalRead(uint16_t pin) { - if(pin != 16) + if(pin != 16) { return ((GPIO_REG_READ(GPIO_IN_ADDRESS) >> pin) & 1); - else - return (uint8_t)(READ_PERI_REG(RTC_GPIO_IN_DATA) & 1); - - //return GPIO_INPUT_GET(pin); + } + return (uint8_t)(READ_PERI_REG(RTC_GPIO_IN_DATA) & 1); } void pullup(uint16_t pin) { - if(pin >= 16) - return; - PIN_PULLUP_EN((EspDigitalPins[pin].mux)); + if(pin < TOTAL_PINS) { + PIN_PULLUP_EN(PERIPHS_IO_MUX + esp8266_pinmuxOffset[pin]); + } } void noPullup(uint16_t pin) { - if(pin >= 16) - return; - PIN_PULLUP_DIS((EspDigitalPins[pin].mux)); + if(pin < TOTAL_PINS) { + PIN_PULLUP_DIS(PERIPHS_IO_MUX + esp8266_pinmuxOffset[pin]); + } } /* Measures the length (in microseconds) of a pulse on the pin; state is HIGH diff --git a/Sming/Arch/Esp8266/Core/ESP8266EX.cpp b/Sming/Arch/Esp8266/Core/ESP8266EX.cpp deleted file mode 100644 index 59e8bd4250..0000000000 --- a/Sming/Arch/Esp8266/Core/ESP8266EX.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * ESP8266EX.cpp - * - ****/ - -#include "Digital.h" -#include "ESP8266EX.h" -#include "Digital.h" -#include - -const EspDigitalPin EspDigitalPins[] = { - {0, PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0}, // FLASH - {1, PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1}, // TXD0 - {2, PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2}, // TXD1 - {3, PERIPHS_IO_MUX_U0RXD_U, FUNC_GPIO3}, // RXD0 - {4, PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4}, - {5, PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5}, - {6, 0, 0}, // SD_CLK_U - {7, 0, 0}, // SD_DATA0_U - {8, 0, 0}, // SD_DATA1_U - {9, PERIPHS_IO_MUX_SD_DATA2_U, FUNC_GPIO9}, - {10, PERIPHS_IO_MUX_SD_DATA3_U, FUNC_GPIO10}, - {11, 0, 0}, // SD_CMD_U - {12, PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12}, // HSPIQ - {13, PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13}, // HSPID - {14, PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14}, // HSPICLK - {15, PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15}, // HSPICS -}; - -void EspDigitalPin::mode(uint8_t mode) const -{ - pinMode(id, mode); -} - -void EspDigitalPin::write(uint8_t val) const -{ - digitalWrite(id, val); -} - -uint8_t EspDigitalPin::read() const -{ - return digitalRead(id); -} diff --git a/Sming/Arch/Esp8266/Core/ESP8266EX.h b/Sming/Arch/Esp8266/Core/ESP8266EX.h deleted file mode 100644 index 6d83620d37..0000000000 --- a/Sming/Arch/Esp8266/Core/ESP8266EX.h +++ /dev/null @@ -1,38 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * ESP8266EX.h - * - ****/ - -#pragma once - -#include - -#define TOTAL_PINS 16 -#define NUM_DIGITAL_PINS TOTAL_PINS - -/** @brief ESP GPIO pin configuration - * @ingroup constants - */ -struct EspDigitalPin { - uint8_t id; - uint32_t mux; - uint8_t gpioFunc; - - operator const int() const - { - return id; - } - void mode(uint8_t mode) const; - void write(uint8_t val) const; - uint8_t read() const; -}; - -/** @brief ESP GPIO pin configuration - * @ingroup gpio - */ -extern const EspDigitalPin EspDigitalPins[]; diff --git a/Sming/Arch/Esp8266/Core/HardwarePWM.cpp b/Sming/Arch/Esp8266/Core/HardwarePWM.cpp index 585f5b813e..13aa43764a 100644 --- a/Sming/Arch/Esp8266/Core/HardwarePWM.cpp +++ b/Sming/Arch/Esp8266/Core/HardwarePWM.cpp @@ -25,11 +25,14 @@ #include #include -#include "ESP8266EX.h" #include +#include "pins_arduino.h" +#include #define PERIOD_TO_MAX_DUTY(x) (x * 25) +extern const uint8_t esp8266_pinmuxOffset[]; + HardwarePWM::HardwarePWM(uint8_t* pins, uint8_t noOfPins) : channel_count(noOfPins) { if(noOfPins == 0) { @@ -38,15 +41,22 @@ HardwarePWM::HardwarePWM(uint8_t* pins, uint8_t noOfPins) : channel_count(noOfPi uint32_t ioInfo[PWM_CHANNEL_NUM_MAX][3]; // pin information uint32_t pwmDutyInit[PWM_CHANNEL_NUM_MAX]; // pwm duty + unsigned pinCount = 0; for(uint8_t i = 0; i < noOfPins; i++) { - ioInfo[i][0] = EspDigitalPins[pins[i]].mux; - ioInfo[i][1] = EspDigitalPins[pins[i]].gpioFunc; - ioInfo[i][2] = EspDigitalPins[pins[i]].id; - pwmDutyInit[i] = 0; // Start with zero output - channels[i] = pins[i]; + auto pin = pins[i]; + assert(pin < 16); + if(pin >= 16) { + continue; + } + ioInfo[pinCount][0] = PERIPHS_IO_MUX + esp8266_pinmuxOffset[pin]; + ioInfo[pinCount][1] = esp8266_gpioToFn[pin]; + ioInfo[pinCount][2] = pin; + pwmDutyInit[pinCount] = 0; // Start with zero output + channels[pinCount] = pin; + ++pinCount; } const int initialPeriod = 1000; - pwm_init(initialPeriod, pwmDutyInit, noOfPins, ioInfo); + pwm_init(initialPeriod, pwmDutyInit, pinCount, ioInfo); update(); maxduty = PERIOD_TO_MAX_DUTY(initialPeriod); // for period of 1000 } diff --git a/Sming/Components/.patches/http-parser.patch b/Sming/Components/.patches/http-parser.patch index ce1eee4d48..8469a2dc19 100644 --- a/Sming/Components/.patches/http-parser.patch +++ b/Sming/Components/.patches/http-parser.patch @@ -1,8 +1,8 @@ diff --git a/http_parser.h b/http_parser.h -index df88252..5935bcf 100644 +index 3772b39..a1f4d38 100644 --- a/http_parser.h +++ b/http_parser.h -@@ -153,7 +153,7 @@ typedef int (*http_cb) (http_parser*); +@@ -155,7 +155,7 @@ typedef int (*http_cb) (http_parser*); enum http_status { @@ -11,7 +11,7 @@ index df88252..5935bcf 100644 HTTP_STATUS_MAP(XX) #undef XX }; -@@ -206,7 +206,7 @@ enum http_status +@@ -208,7 +208,7 @@ enum http_status enum http_method { @@ -20,7 +20,7 @@ index df88252..5935bcf 100644 HTTP_METHOD_MAP(XX) #undef XX }; -@@ -282,17 +282,13 @@ enum flags +@@ -283,17 +283,13 @@ enum flags /* Define HPE_* values for each errno value above */ @@ -39,8 +39,24 @@ index df88252..5935bcf 100644 struct http_parser { /** PRIVATE **/ unsigned int type : 2; /* enum http_parser_type */ +@@ -417,15 +413,6 @@ int http_should_keep_alive(const http_parser *parser); + /* Returns a string version of the HTTP method. */ + const char *http_method_str(enum http_method m); + +-/* Returns a string version of the HTTP status code. */ +-const char *http_status_str(enum http_status s); +- +-/* Return a string name of the given error */ +-const char *http_errno_name(enum http_errno err); +- +-/* Return a string description of the given error */ +-const char *http_errno_description(enum http_errno err); +- + /* Initialize all http_parser_url members to 0 */ + void http_parser_url_init(struct http_parser_url *u); + diff --git a/http_parser.c b/http_parser.c -index 95ff42f..beaf1f7 100644 +index 9be003e..e6b0051 100644 --- a/http_parser.c +++ b/http_parser.c @@ -20,11 +20,19 @@ @@ -65,7 +81,43 @@ index 95ff42f..beaf1f7 100644 static uint32_t max_header_size = HTTP_MAX_HEADER_SIZE; #ifndef ULLONG_MAX -@@ -186,7 +194,7 @@ static const char *method_strings[] = +@@ -160,7 +168,6 @@ do { \ + } \ + } while (0) + +- + #define PROXY_CONNECTION "proxy-connection" + #define CONNECTION "connection" + #define CONTENT_LENGTH "content-length" +@@ -170,10 +177,25 @@ do { \ + #define KEEP_ALIVE "keep-alive" + #define CLOSE "close" + ++static const char STR_PROXY_CONNECTION[] PROGMEM_PSTR = "proxy-connection"; ++static const char STR_CONNECTION[] PROGMEM_PSTR = "connection"; ++static const char STR_CONTENT_LENGTH[] PROGMEM_PSTR = "content-length"; ++static const char STR_TRANSFER_ENCODING[] PROGMEM_PSTR = "transfer-encoding"; ++static const char STR_UPGRADE[] PROGMEM_PSTR = "upgrade"; ++static const char STR_CHUNKED[] PROGMEM_PSTR = "chunked"; ++static const char STR_KEEP_ALIVE[] PROGMEM_PSTR = "keep-alive"; ++static const char STR_CLOSE[] PROGMEM_PSTR = "close"; + +-static const char *method_strings[] = ++#define get_pstr_char(name, index) (char)pgm_read_byte(&STR_##name[index]) ++ ++ ++#define XX(num, name, string) static const char method_string_##name[] PROGMEM_PSTR = #string; ++ HTTP_METHOD_MAP(XX) ++#undef XX ++ ++static const char *method_strings[] PROGMEM_PSTR = + { +-#define XX(num, name, string) #string, ++#define XX(num, name, string) method_string_##name, + HTTP_METHOD_MAP(XX) + #undef XX + }; +@@ -186,7 +208,7 @@ static const char *method_strings[] = * | "/" | "[" | "]" | "?" | "=" * | "{" | "}" | SP | HT */ @@ -74,7 +126,7 @@ index 95ff42f..beaf1f7 100644 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ 0, 0, 0, 0, 0, 0, 0, 0, /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ -@@ -220,19 +228,10 @@ static const char tokens[256] = { +@@ -220,19 +242,10 @@ static const char tokens[256] = { /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ 'x', 'y', 'z', 0, '|', 0, '~', 0 }; @@ -98,7 +150,7 @@ index 95ff42f..beaf1f7 100644 #if HTTP_PARSER_STRICT # define T(v) 0 #else -@@ -428,14 +427,14 @@ enum http_host_state +@@ -428,14 +441,14 @@ enum http_host_state (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ (c) == '$' || (c) == ',') @@ -115,7 +167,7 @@ index 95ff42f..beaf1f7 100644 #define IS_URL_CHAR(c) \ (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) #define IS_HOST_CHAR(c) \ -@@ -467,16 +466,6 @@ do { \ +@@ -467,16 +480,6 @@ do { \ #endif @@ -132,7 +184,7 @@ index 95ff42f..beaf1f7 100644 int http_message_needs_eof(const http_parser *parser); /* Our URL parser. -@@ -758,7 +747,7 @@ reexecute: +@@ -760,7 +763,7 @@ reexecute: } parser->type = HTTP_REQUEST; @@ -141,7 +193,7 @@ index 95ff42f..beaf1f7 100644 parser->index = 2; UPDATE_STATE(s_req_method); } -@@ -938,23 +927,23 @@ reexecute: +@@ -940,23 +943,23 @@ reexecute: parser->method = (enum http_method) 0; parser->index = 1; switch (ch) { @@ -180,7 +232,18 @@ index 95ff42f..beaf1f7 100644 default: SET_ERRNO(HPE_INVALID_METHOD); goto error; -@@ -983,8 +972,8 @@ reexecute: +@@ -977,16 +980,17 @@ reexecute: + } + + matcher = method_strings[parser->method]; +- if (ch == ' ' && matcher[parser->index] == '\0') { ++ char matcher_char = pgm_read_byte(&matcher[parser->index]); ++ if (ch == ' ' && matcher_char == '\0') { + UPDATE_STATE(s_req_spaces_before_url); +- } else if (ch == matcher[parser->index]) { ++ } else if (ch == matcher_char) { + ; /* nada */ + } else if ((ch >= 'A' && ch <= 'Z') || ch == '-') { switch (parser->method << 16 | parser->index << 8 | ch) { #define XX(meth, pos, ch, new_meth) \ @@ -191,7 +254,7 @@ index 95ff42f..beaf1f7 100644 XX(POST, 1, 'U', PUT) XX(POST, 1, 'A', PATCH) -@@ -1024,7 +1013,7 @@ reexecute: +@@ -1026,7 +1030,7 @@ reexecute: if (ch == ' ') break; MARK(url); @@ -200,7 +263,7 @@ index 95ff42f..beaf1f7 100644 UPDATE_STATE(s_req_server_start); } -@@ -1100,7 +1089,7 @@ reexecute: +@@ -1102,7 +1106,7 @@ reexecute: UPDATE_STATE(s_req_http_H); break; case 'I': @@ -209,7 +272,88 @@ index 95ff42f..beaf1f7 100644 UPDATE_STATE(s_req_http_I); break; } -@@ -1826,7 +1815,7 @@ reexecute: +@@ -1303,7 +1307,7 @@ reexecute: + case h_matching_connection: + parser->index++; + if (parser->index > sizeof(CONNECTION)-1 +- || c != CONNECTION[parser->index]) { ++ || c != get_pstr_char(CONNECTION, parser->index)) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CONNECTION)-2) { + parser->header_state = h_connection; +@@ -1315,7 +1319,7 @@ reexecute: + case h_matching_proxy_connection: + parser->index++; + if (parser->index > sizeof(PROXY_CONNECTION)-1 +- || c != PROXY_CONNECTION[parser->index]) { ++ || c != get_pstr_char(PROXY_CONNECTION, parser->index)) { + parser->header_state = h_general; + } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { + parser->header_state = h_connection; +@@ -1327,7 +1331,7 @@ reexecute: + case h_matching_content_length: + parser->index++; + if (parser->index > sizeof(CONTENT_LENGTH)-1 +- || c != CONTENT_LENGTH[parser->index]) { ++ || c != get_pstr_char(CONTENT_LENGTH, parser->index)) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { + parser->header_state = h_content_length; +@@ -1339,7 +1343,7 @@ reexecute: + case h_matching_transfer_encoding: + parser->index++; + if (parser->index > sizeof(TRANSFER_ENCODING)-1 +- || c != TRANSFER_ENCODING[parser->index]) { ++ || c != get_pstr_char(TRANSFER_ENCODING, parser->index)) { + parser->header_state = h_general; + } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { + parser->header_state = h_transfer_encoding; +@@ -1352,7 +1356,7 @@ reexecute: + case h_matching_upgrade: + parser->index++; + if (parser->index > sizeof(UPGRADE)-1 +- || c != UPGRADE[parser->index]) { ++ || c != get_pstr_char(UPGRADE, parser->index)) { + parser->header_state = h_general; + } else if (parser->index == sizeof(UPGRADE)-2) { + parser->header_state = h_upgrade; +@@ -1597,7 +1601,7 @@ reexecute: + case h_matching_transfer_encoding_chunked: + parser->index++; + if (parser->index > sizeof(CHUNKED)-1 +- || c != CHUNKED[parser->index]) { ++ || c != get_pstr_char(CHUNKED, parser->index)) { + h_state = h_matching_transfer_encoding_token; + } else if (parser->index == sizeof(CHUNKED)-2) { + h_state = h_transfer_encoding_chunked; +@@ -1633,7 +1637,7 @@ reexecute: + case h_matching_connection_keep_alive: + parser->index++; + if (parser->index > sizeof(KEEP_ALIVE)-1 +- || c != KEEP_ALIVE[parser->index]) { ++ || c != get_pstr_char(KEEP_ALIVE, parser->index)) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(KEEP_ALIVE)-2) { + h_state = h_connection_keep_alive; +@@ -1643,7 +1647,7 @@ reexecute: + /* looking for 'Connection: close' */ + case h_matching_connection_close: + parser->index++; +- if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { ++ if (parser->index > sizeof(CLOSE)-1 || c != get_pstr_char(CLOSE, parser->index)) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(CLOSE)-2) { + h_state = h_connection_close; +@@ -1654,7 +1658,7 @@ reexecute: + case h_matching_connection_upgrade: + parser->index++; + if (parser->index > sizeof(UPGRADE) - 1 || +- c != UPGRADE[parser->index]) { ++ c != get_pstr_char(UPGRADE, parser->index)) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(UPGRADE)-2) { + h_state = h_connection_upgrade; +@@ -1833,7 +1837,7 @@ reexecute: parser->upgrade = (parser->type == HTTP_REQUEST || parser->status_code == 101); } else { @@ -218,7 +362,7 @@ index 95ff42f..beaf1f7 100644 } /* Here we call the headers_complete callback. This is somewhat -@@ -1874,7 +1863,7 @@ reexecute: +@@ -1881,7 +1885,7 @@ reexecute: hasBody = parser->flags & F_CHUNKED || (parser->content_length > 0 && parser->content_length != ULLONG_MAX); @@ -227,7 +371,7 @@ index 95ff42f..beaf1f7 100644 (parser->flags & F_SKIPBODY) || !hasBody)) { /* Exit, the rest of the message is in a different protocol. */ UPDATE_STATE(NEW_MESSAGE()); -@@ -1991,7 +1980,7 @@ reexecute: +@@ -1998,7 +2002,7 @@ reexecute: assert(nread == 1); assert(parser->flags & F_CHUNKED); @@ -236,7 +380,7 @@ index 95ff42f..beaf1f7 100644 if (UNLIKELY(unhex_val == -1)) { SET_ERRNO(HPE_INVALID_CHUNK_SIZE); goto error; -@@ -2013,7 +2002,7 @@ reexecute: +@@ -2020,7 +2024,7 @@ reexecute: break; } @@ -245,16 +389,27 @@ index 95ff42f..beaf1f7 100644 if (unhex_val == -1) { if (ch == ';' || ch == ' ') { -@@ -2207,7 +2196,7 @@ const char * - http_status_str (enum http_status s) +@@ -2207,18 +2211,7 @@ http_should_keep_alive (const http_parser *parser) + const char * + http_method_str (enum http_method m) { - switch (s) { +- return ELEM_AT(method_strings, m, ""); +-} +- +-const char * +-http_status_str (enum http_status s) +-{ +- switch (s) { -#define XX(num, name, string) case HTTP_STATUS_##name: return #string; -+#define XX(num, name, string) case HTTP_STATUS_CODE_##name: return #string; - HTTP_STATUS_MAP(XX) - #undef XX - default: return ""; -@@ -2231,18 +2220,6 @@ http_parser_settings_init(http_parser_settings *settings) +- HTTP_STATUS_MAP(XX) +-#undef XX +- default: return ""; +- } ++ return ELEM_AT(method_strings, m, PSTR("")); + } + + void +@@ -2238,18 +2231,6 @@ http_parser_settings_init(http_parser_settings *settings) memset(settings, 0, sizeof(*settings)); } diff --git a/Sming/Components/.patches/ws_parser.patch b/Sming/Components/.patches/ws_parser.patch index b1ff2037ef..c1231824dc 100644 --- a/Sming/Components/.patches/ws_parser.patch +++ b/Sming/Components/.patches/ws_parser.patch @@ -1,16 +1,17 @@ diff --git a/ws_parser.c b/ws_parser.c -index d43adbe..beeb611 100644 +index d43adbe..17040e3 100644 --- a/ws_parser.c +++ b/ws_parser.c -@@ -3,6 +3,7 @@ +@@ -3,6 +3,8 @@ #endif #include "ws_parser.h" +#include ++#include enum { S_OPCODE = 0, -@@ -27,6 +28,7 @@ enum { +@@ -27,6 +29,7 @@ enum { void ws_parser_init(ws_parser_t* parser) { @@ -18,7 +19,7 @@ index d43adbe..beeb611 100644 parser->state = S_OPCODE; parser->fragment = 0; } -@@ -247,7 +249,8 @@ ws_parser_execute( +@@ -247,7 +250,8 @@ ws_parser_execute( } if(parser->mask_flag) { @@ -28,3 +29,12 @@ index d43adbe..beeb611 100644 buff[i] ^= parser->mask[parser->mask_pos++]; } } +@@ -302,7 +306,7 @@ ws_parser_execute( + const char* + ws_parser_error(int rc) + { +- #define XX(name, code) if(rc == code) return #name; ++ #define XX(name, code) if(rc == code) return PSTR(#name); + WS_PARSER_ERROR_CODES(XX) + #undef XX + diff --git a/Sming/Components/Network/src/Network/Http/HttpCommon.h b/Sming/Components/Network/src/Network/Http/HttpCommon.h index 6ee5181b36..57c0785044 100644 --- a/Sming/Components/Network/src/Network/Http/HttpCommon.h +++ b/Sming/Components/Network/src/Network/Http/HttpCommon.h @@ -121,7 +121,8 @@ inline String httpGetStatusText(unsigned code) */ inline String toString(HttpMethod method) { - return http_method_str(http_method(method)); + auto fstr = reinterpret_cast(http_method_str(http_method(method))); + return String(fstr); } /** @} */ diff --git a/Sming/Components/http-parser b/Sming/Components/http-parser index 2343fd6b52..ec8b5ee63f 160000 --- a/Sming/Components/http-parser +++ b/Sming/Components/http-parser @@ -1 +1 @@ -Subproject commit 2343fd6b5214b2ded2cdcf76de2bf60903bb90cd +Subproject commit ec8b5ee63f0e51191ea43bb0c6eac7bfbff3141d diff --git a/Sming/Libraries/RapidXML b/Sming/Libraries/RapidXML index 4a1fe56b85..1e9f276c65 160000 --- a/Sming/Libraries/RapidXML +++ b/Sming/Libraries/RapidXML @@ -1 +1 @@ -Subproject commit 4a1fe56b851fef63b99a1433c743e5ca0043b08d +Subproject commit 1e9f276c656c3319a09ac956d3acf53e74988e85 diff --git a/Tools/ci/scanlog.py b/Tools/ci/scanlog.py new file mode 100644 index 0000000000..80f1d7a12f --- /dev/null +++ b/Tools/ci/scanlog.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +# +# Python application to scan CI build logs and extract useful information +# +# Github action logs must be in raw (text) format for processing. +# +# Use cases: +# +# Generate table of esp8266 memory usage +# Take two log files (cut & paste usually) +# Run scanlog on both +# Use kdiff3 to compare +# + +import argparse +import os +from enum import Enum + + +class State(Enum): + searching = 1 + building = 2 + linking = 3 + + +class Table: + COL_SEP = ' ' + + def __init__(self, name: str): + self.name = name + self.headings = [] + self.rows = [] + self.col_widths = [] + + def append(self, row_data: dict): + for k in row_data.keys(): + if k in self.headings: + continue + self.headings.append(k) + self.col_widths.append(len(k)) + row = ['' for x in self.headings] + for k, v in row_data.items(): + i = self.headings.index(k) + row[i] = v + self.col_widths[i] = max(self.col_widths[i], len(v)) + self.rows.append(row) + + def _format_values(self, values: list): + return self.COL_SEP.join(str(v).ljust(self.col_widths[i]) for i, v in enumerate(values)) + + def format_headings(self): + return self._format_values(self.headings) + + def format_separator(self): + return self.COL_SEP.join(''.ljust(w, '-') for w in self.col_widths) + + def format_row(self, row: int | list): + if isinstance(row, int): + row = self.rows[row] + return self._format_values(row) + + def find_row(self, name: str): + return next((i for i, row in enumerate(self.rows) if row[0] == name), -1) + + def __iter__(self): + return TableFormatter(self) + + +class TableFormatter: + def __init__(self, table: Table): + self.table = table + self.row_index = -2 + + def __next__(self): + table = self.table + idx = self.row_index + if idx == -2: + self.row_index = -1 + return table.format_headings() + if idx == -1: + self.row_index = 0 + return table.format_separator() + if idx < len(table.rows): + self.row_index = idx + 1 + return table.format_row(idx) + raise StopIteration + + +def scan_log(filename: str): + state = State.searching + table = Table(os.path.basename(filename)) + target = None + row = None + log = open(filename, 'rb') + for line in log: + line = line.decode('utf-8-sig') + dtstr, _, line = line.strip().partition(' ') + if not dtstr: + continue + _, sep, c = line.partition('** Building ') + if sep: + target, _, _ = c.partition(' ') + target = target.removeprefix('/home/runner/projects/') + row = { + 'target': target + } + state = State.building + continue + if state == State.building: + if line.startswith(f'{os.path.basename(target)}: Linking'): + state = State.linking + continue + if state == State.linking: + if 'Section' in line: + continue + if line.startswith('----'): + continue + if '|' in line: + cols = line.split('|') + k, v = cols[0], cols[4] + elif ' : ' in line: + k, v = line.split(':') + else: + table.append(row) + row = None + state = State.searching + continue + k, v = k.strip(), v.strip() + row[k] = v + continue + + return table + + +def print_table(table: Table): + print(f'{table.name}') + for line in table: + print(' ', line) + print() + + +def main(): + parser = argparse.ArgumentParser(description='Sming CI log parser') + parser.add_argument('filename', help='Log filename') + parser.add_argument('-c', '--compare', help='Second log to compare') + + args = parser.parse_args() + + table1 = scan_log(args.filename) + if args.compare is None: + print_table(table1) + return + + table2 = scan_log(args.compare) + + for row1 in table1.rows: + target = row1[0] + i = table2.find_row(target) + if i < 0: + print(f'** {target} NOT found in {table2.name}') + continue + row2 = table2.rows.pop(i) + if row2 == row1: + continue + + diff_table = Table(target) + + data = {'log': table1.name} + for k, v in zip(table1.headings[1:], row1[1:]): + data[k] = v + diff_table.append(data) + data = {'log': table2.name} + for k, v in zip(table2.headings[1:], row2[1:]): + data[k] = v + diff_table.append(data) + + data = {'log': 'Difference'} + for name, v1, v2 in zip(table1.headings[1:], row1[1:], row2[1:]): + if v1 == v2: + continue + v1, v2 = int(v1, 0), int(v2, 0) + data[name] = f'{v2-v1:+}' + diff_table.append(data) + + print_table(diff_table) + + if table2.rows: + print(f'** Targets not in {table1.name}') + print_table(table2) + + +if __name__ == "__main__": + main()