From 229b921a6a87f81ece6019ce10066613656933b4 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 9 Feb 2016 16:06:25 +1100 Subject: [PATCH 1/3] gcc __attribute__((constructor)): Remove hacked calling, move ctor sections to flash More hacky moving of parts of .rodata to flash, until we can move all of it. Candidate fix for #128 --- FreeRTOS/Source/portable/esp8266/port.c | 11 ------ core/app_main.c | 9 +++++ core/sdk_compat.c | 14 -------- ld/common.ld | 45 +++++++++++++------------ 4 files changed, 33 insertions(+), 46 deletions(-) diff --git a/FreeRTOS/Source/portable/esp8266/port.c b/FreeRTOS/Source/portable/esp8266/port.c index fc452f0..21a0d55 100644 --- a/FreeRTOS/Source/portable/esp8266/port.c +++ b/FreeRTOS/Source/portable/esp8266/port.c @@ -178,9 +178,6 @@ void xPortSysTickHandle (void) //OpenNMI(); } -static bool sdk_compat_initialised; -void sdk_compat_initialise(void); - /* * See header file for description. */ @@ -189,14 +186,6 @@ portBASE_TYPE xPortStartScheduler( void ) _xt_isr_attach(INUM_SOFT, SV_ISR); _xt_isr_unmask(BIT(INUM_SOFT)); - /* ENORMOUS HACK: Call the sdk_compat_initialise() function. - This can be removed happily once we have open source startup code. - */ - if(!sdk_compat_initialised) { - sdk_compat_initialised = true; - sdk_compat_initialise(); - } - /* Initialize system tick timer interrupt and schedule the first tick. */ _xt_isr_attach(INUM_TICK, sdk__xt_timer_int); _xt_isr_unmask(BIT(INUM_TICK)); diff --git a/core/app_main.c b/core/app_main.c index 7a9bf8d..a6e0f49 100644 --- a/core/app_main.c +++ b/core/app_main.c @@ -407,6 +407,9 @@ void sdk_user_init_task(void *params) { vTaskDelete(NULL); } +extern void (*__init_array_start)(void); +extern void (*__init_array_end)(void); + // .Lfunc009 -- .irom0.text+0x5b4 static void user_start_phase2(void) { uint8_t *buf; @@ -437,6 +440,12 @@ static void user_start_phase2(void) { uart_flush_txfifo(0); uart_flush_txfifo(1); + // Call gcc constructor functions + void (**ctor)(void); + for ( ctor = &__init_array_start; ctor != &__init_array_end; ++ctor) { + (*ctor)(); + } + if (phy_info[0] != 5) { // Bad version byte. Discard what we read and use default values // instead. diff --git a/core/sdk_compat.c b/core/sdk_compat.c index b0d6789..1e60b85 100644 --- a/core/sdk_compat.c +++ b/core/sdk_compat.c @@ -17,20 +17,6 @@ void IRAM *zalloc(size_t nbytes) return calloc(1, nbytes); } -extern void (*__init_array_start)(void); -extern void (*__init_array_end)(void); - -/* Do things which should be done as part of the SDK startup code, but aren't. - TODO: Move into app_main.c -*/ -void sdk_compat_initialise() -{ - /* Call C++ constructors or C functions marked with __attribute__((constructor)) */ - void (**p)(void); - for ( p = &__init_array_start; p != &__init_array_end; ++p) - (*p)(); -} - /* UART RX function from Espressif SDK internals. * * Not part of published API. diff --git a/ld/common.ld b/ld/common.ld index 1413c1c..cc8a8ce 100644 --- a/ld/common.ld +++ b/ld/common.ld @@ -139,13 +139,34 @@ SECTIONS (except for libgcc which is matched above.) */ *(.literal .text .literal.* .text.*) + /* Anything explicitly marked as "irom" or "irom0" should go here */ + *(.irom.* .irom.*.* .irom0.*) + _irom0_text_end = ABSOLUTE(.); + + /* Temporary .rodata hacks start here, eventually all rodata will + be in irom by default */ /* mbedtls rodata */ *mbedtls.a:*.o(.rodata.* .rodata) /* actual certificate in example (TEMPORARY HACK) */ *:cert.o(.rodata.* .rodata) - /* Anything explicitly marked as "irom" or "irom0" should go here */ - *(.irom.* .irom.*.* .irom0.*) - _irom0_text_end = ABSOLUTE(.); + /* C++ constructor and destructor tables, properly ordered: */ + __init_array_start = ABSOLUTE(.); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + } >irom0_0_seg :irom0_0_phdr .data : ALIGN(4) @@ -179,23 +200,6 @@ SECTIONS *(.gnu.version_r) *(.eh_frame) . = (. + 3) & ~ 3; - /* C++ constructor and destructor tables, properly ordered: */ - __init_array_start = ABSOLUTE(.); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) *(.dynamic) *(.gnu.version_d) . = ALIGN(4); /* this table MUST be 4-byte aligned */ @@ -230,7 +234,6 @@ SECTIONS } >dram0_0_seg :dram0_0_bss_phdr /* __stack = 0x3ffc8000; */ - .lit4 : ALIGN(4) { _lit4_start = ABSOLUTE(.); From 5792bd1c4ad4c33d647b99a13674a716407c17d9 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 21 Apr 2016 09:54:15 +1000 Subject: [PATCH 2/3] Move static constructor calls to after PHY, clock & baud rate are setup Otherwise anything printed inside the constructor happens at unexpected baud rate. Ref #128 --- core/app_main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/app_main.c b/core/app_main.c index a6e0f49..2f4f7f1 100644 --- a/core/app_main.c +++ b/core/app_main.c @@ -440,12 +440,6 @@ static void user_start_phase2(void) { uart_flush_txfifo(0); uart_flush_txfifo(1); - // Call gcc constructor functions - void (**ctor)(void); - for ( ctor = &__init_array_start; ctor != &__init_array_end; ++ctor) { - (*ctor)(); - } - if (phy_info[0] != 5) { // Bad version byte. Discard what we read and use default values // instead. @@ -453,6 +447,13 @@ static void user_start_phase2(void) { } init_networking(phy_info, sdk_info.sta_mac_addr); free(phy_info); + + // Call gcc constructor functions + void (**ctor)(void); + for ( ctor = &__init_array_start; ctor != &__init_array_end; ++ctor) { + (*ctor)(); + } + tcpip_init(NULL, NULL); sdk_wdt_init(); xTaskCreate(sdk_user_init_task, (signed char *)"uiT", 1024, 0, 14, &sdk_xUserTaskHandle); From cc8e8da0347ec93b6d47a7f016c6880ac57378fe Mon Sep 17 00:00:00 2001 From: Drasko DRASKOVIC Date: Wed, 4 May 2016 22:43:02 +0200 Subject: [PATCH 3/3] Add JSON support This commits adds JSON support by adding Jsmn (http://zserge.com/jsmn.html), a minimalistic JSON parser. Signed-off-by: Drasko DRASKOVIC --- .gitmodules | 3 + examples/json_jsmn_simple/Makefile | 4 + examples/json_jsmn_simple/json_jsmn_simple.c | 112 +++++++++++++++++++ extras/jsmn/component.mk | 10 ++ extras/jsmn/jsmn | 1 + 5 files changed, 130 insertions(+) create mode 100644 examples/json_jsmn_simple/Makefile create mode 100644 examples/json_jsmn_simple/json_jsmn_simple.c create mode 100644 extras/jsmn/component.mk create mode 160000 extras/jsmn/jsmn diff --git a/.gitmodules b/.gitmodules index 8dc737e..52708f8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "extras/mbedtls/mbedtls"] path = extras/mbedtls/mbedtls url = https://github.com/ARMmbed/mbedtls.git +[submodule "extras/jsmn/jsmn"] + path = extras/jsmn/jsmn + url = https://github.com/zserge/jsmn.git diff --git a/examples/json_jsmn_simple/Makefile b/examples/json_jsmn_simple/Makefile new file mode 100644 index 0000000..89e6ba7 --- /dev/null +++ b/examples/json_jsmn_simple/Makefile @@ -0,0 +1,4 @@ +# Simple makefile for simple example +PROGRAM=json_jsmn_simple +EXTRA_COMPONENTS = extras/jsmn +include ../../common.mk diff --git a/examples/json_jsmn_simple/json_jsmn_simple.c b/examples/json_jsmn_simple/json_jsmn_simple.c new file mode 100644 index 0000000..3a65ddf --- /dev/null +++ b/examples/json_jsmn_simple/json_jsmn_simple.c @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2010 Serge A. Zaitsev and + * 2016 Drasko DRASKOVIC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "espressif/esp_common.h" +#include "esp/uart.h" +#include "FreeRTOS.h" +#include "task.h" +#include +#include +#include +#include "jsmn.h" + +/** + * A small example of jsmn parsing when JSON structure is known and number of + * tokens is predictable. + */ + +const char *JSON_STRING = + "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n " + "\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"]}"; + +static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { + if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && + strncmp(json + tok->start, s, tok->end - tok->start) == 0) { + return 0; + } + return -1; +} + +void json_test(void *pvParameters) +{ + int i; + int r; + jsmn_parser p; + jsmntok_t t[128]; /* We expect no more than 128 tokens */ + + jsmn_init(&p); + r = jsmn_parse(&p, JSON_STRING, strlen(JSON_STRING), t, sizeof(t)/sizeof(t[0])); + if (r < 0) { + printf("Failed to parse JSON: %d\n", r); + } + + /* Assume the top-level element is an object */ + if (r < 1 || t[0].type != JSMN_OBJECT) { + printf("Object expected\n"); + } + + /* Loop over all keys of the root object */ + for (i = 1; i < r; i++) { + if (jsoneq(JSON_STRING, &t[i], "user") == 0) { + /* We may use strndup() to fetch string value */ + printf("- User: %.*s\n", t[i+1].end-t[i+1].start, + JSON_STRING + t[i+1].start); + i++; + } else if (jsoneq(JSON_STRING, &t[i], "admin") == 0) { + /* We may additionally check if the value is either "true" or "false" */ + printf("- Admin: %.*s\n", t[i+1].end-t[i+1].start, + JSON_STRING + t[i+1].start); + i++; + } else if (jsoneq(JSON_STRING, &t[i], "uid") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf("- UID: %.*s\n", t[i+1].end-t[i+1].start, + JSON_STRING + t[i+1].start); + i++; + } else if (jsoneq(JSON_STRING, &t[i], "groups") == 0) { + int j; + printf("- Groups:\n"); + if (t[i+1].type != JSMN_ARRAY) { + continue; /* We expect groups to be an array of strings */ + } + for (j = 0; j < t[i+1].size; j++) { + jsmntok_t *g = &t[i+j+2]; + printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start); + } + i += t[i+1].size + 1; + } else { + printf("Unexpected key: %.*s\n", t[i].end-t[i].start, + JSON_STRING + t[i].start); + } + } + + while (1) + ; +} + + +void user_init(void) +{ + uart_set_baud(0, 115200); + printf("SDK version:%s\n", sdk_system_get_sdk_version()); + xTaskCreate(json_test, (signed char *)"jsont", 1024, NULL, 2, NULL); +} diff --git a/extras/jsmn/component.mk b/extras/jsmn/component.mk new file mode 100644 index 0000000..13beac4 --- /dev/null +++ b/extras/jsmn/component.mk @@ -0,0 +1,10 @@ +# Component makefile for extras/jsmn + +# expected anyone using jsmn json component includes it as 'jsmn/jsmn.h' +INC_DIRS += $(jsmn_ROOT)jsmn + +# args for passing into compile rule generation +jsmn_INC_DIR = +jsmn_SRC_DIR = $(jsmn_ROOT)jsmn + +$(eval $(call component_compile_rules,jsmn)) diff --git a/extras/jsmn/jsmn b/extras/jsmn/jsmn new file mode 160000 index 0000000..bbc6755 --- /dev/null +++ b/extras/jsmn/jsmn @@ -0,0 +1 @@ +Subproject commit bbc6755fce14c713f9bb4ba47c688d15efc1394b