├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── Makefile ├── README.md ├── blinky-lib ├── Makefile └── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ └── user_config.h ├── blinky ├── Makefile └── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ └── user_config.h ├── constraints.nims ├── fota ├── Makefile └── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ ├── user_config.h │ └── user_data.nim ├── gc-arc ├── Makefile └── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ └── user_config.h ├── gc-regions ├── Makefile └── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ └── user_config.h ├── hello-world-sdk ├── Makefile └── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ ├── user_config.h │ └── user_main.c ├── hello-world ├── Makefile └── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ ├── user_config.h │ └── user_main.c ├── mqtt-blinky ├── Makefile ├── README.md ├── config.sh ├── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ ├── user_config.h │ └── user_data.nim └── user_data.py ├── panic ├── Makefile └── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ ├── user_config.h │ └── user_main.c ├── read-flash ├── Makefile ├── Makefile.orig ├── Makefile.rej ├── data.bin └── user │ ├── main.nim │ ├── main.nim.cfg │ ├── panicoverride.nim │ └── user_config.h ├── release-notes ├── 20191031.md ├── 20191110.md ├── 20200529.md └── 20200612.md └── wifi ├── Makefile ├── user ├── main.nim ├── main.nim.cfg ├── panicoverride.nim ├── user_config.h └── user_data.nim └── user_data.py /.gitignore: -------------------------------------------------------------------------------- 1 | */build 2 | */firmware 3 | nim_esp8266_examples-*.zip 4 | nim_esp8266_examples-*.tar.gz 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: minimal 2 | 3 | sudo: required 4 | 5 | services: 6 | - docker 7 | 8 | before_install: 9 | - docker pull nimesp/esp8266 10 | 11 | install: 12 | - curl -L $(curl -L https://api.github.com/repos/clj/nim-esp8266-sdk/releases/latest | jq -r '.assets[].browser_download_url | select(. | test(".tar.gz"))') | tar -xz 13 | - curl -L https://github.com/espressif/ESP8266_NONOS_SDK/archive/v3.0.3.tar.gz | tar -xz 14 | - rm ESP8266_NONOS_SDK-3.0.3/Makefile 15 | 16 | script: 17 | - docker run nimesp/esp8266 nim --version 18 | - docker run -v "$(pwd):/project" -w /project nimesp/esp8266 sh -c "make SDK_BASE=ESP8266_NONOS_SDK-3.0.3 NIM_SDK_BASE=nim-esp8266-sdk/3.0.3" 19 | 20 | before_deploy: 21 | - export RELEASE_DATE=${TRAVIS_TAG:8} 22 | - docker run -v "$(pwd):/project" -w /project nimesp/esp8266 sh -c "make SDK_BASE=ESP8266_NONOS_SDK-3.0.3 NIM_SDK_BASE=nim-esp8266-sdk/3.0.3 dist" 23 | 24 | deploy: 25 | provider: releases 26 | api_key: 27 | secure: uN4Sfg3mI5onJsbpG32XU7vvPbqcZnfvLQwcug4cUYRkOhRLsIEPcgtGTln9N6m+Dm/z5wUUGwxnbgX6Lb197fvATYN4cH2ZGyhjI8fD/ar9LdNrfr1QNba9C7fOyq5AXJL1nqPq6lthmMO4nLMsqZM8nnN0iUwd1g56R1LOgBaLCOwn1bIDlORuSQ6mIlVq2R8YL5eYaH/PtaohEFsouGUDE4t25VRcYNiiKVAK+npsJaZtovK4LmcSbQ2w8be0H2IBZCNe+DKO6eTA/i/p5Ns5J1rtS5BCfbylgMjs/LR/aPAmpC330YLwu8rHDL5daXuESi3hrxeTYC5DZAaX+7wzz9HvzsMka3rKQLzoXI40qqoK36L5jK7D6K45Zn/E8kZBs3eokodS8gzVTVnheVE2zUGnusj2YYBK2kEGxmCjg1C1WU1WUeehIq47CAS+z5GDfAwhMDGvmUXCK7Co8Dc0N1hhtgYNm+P1BAEoXaOGr4Xz6nmu6/GWiP5KcYr1PE7Jtvm+kKYtmGyP+SDgClXsi4umKp+GInB6RgZ1IW0Vxu0K1hio0clvPdp9iRSDd1YSUiNnwRCvGbW92sTcoa/sG1H0fb9fD5aw/U+Wj7PyXrxElGckp7L82OdkurO35YhGdBx1F/vUu0CQGVwm6TrU+AfGJIb9gfO4UJmiIQ0= 28 | file_glob: true 29 | file: nim_esp8266_examples-* 30 | edge: true 31 | release_notes_file: 'release-notes/${RELEASE_DATE}.md' 32 | name: "Release ${RELEASE_DATE}" 33 | skip_cleanup: true 34 | on: 35 | repo: clj/nim-esp8266-examples 36 | tags: true 37 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Christian Lyder Jacobsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | subdir_targets := all clean 2 | subdirs := $(dir $(wildcard */Makefile)) 3 | subdirs := $(shell echo "$(subdirs)" | nim --hints:off constraints.nims) 4 | goals := $(MAKECMDGOALS) 5 | firmwares := $(addsuffix firmware/,$(subdirs)) 6 | release_tag := $(shell (git describe --exact-match --tags $$(git log -n1 --pretty='%h') 2>/dev/null || git describe --tags) | sed -e "s/release-//") 7 | release_name = nim_esp8266_examples-$(release_tag) 8 | 9 | # Set path related variables to have absolute paths 10 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 11 | override SDK_BASE := $(abspath $(SDK_BASE)) 12 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 13 | 14 | # Pass the absolute paths to recursive makes even if overriden on command line 15 | _PATH_VARS := \ 16 | XTENSA_TOOLS_ROOT \ 17 | SDK_BASE \ 18 | NIM_SDK_BASE 19 | MAKEOVERRIDES += $(foreach v,$(_PATH_VARS),$(v)=$($(v))) 20 | 21 | V ?= $(VERBOSE) 22 | ifeq ("$(V)","1") 23 | Q := 24 | vecho := @true 25 | print_dirs := 26 | else 27 | Q := @ 28 | vecho := @echo 29 | print_dirs := --no-print-directory 30 | endif 31 | 32 | .PHONY: $(subdir_targets) $(subdirs) dist 33 | 34 | $(subdir_targets): $(subdirs) 35 | $(subdirs): 36 | $(vecho) "MAKE $(goals) $@" 37 | $(Q) $(MAKE) $(print_dirs) -C $@ $(goals) 38 | 39 | dist: goals=all 40 | dist: $(release_name).tar.gz $(release_name).zip 41 | 42 | $(release_name).tar.gz: all 43 | $(vecho) "TAR $@" 44 | $(Q) tar -czf $@ $(firmwares) 45 | 46 | $(release_name).zip: all 47 | $(vecho) "ZIP $@" 48 | $(Q) zip -qr $(@F) $(firmwares) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nim on the ESP8266 -- Example Code 2 | 3 | [![Build Status](https://travis-ci.org/clj/nim-esp8266-examples.svg?branch=master)](https://travis-ci.org/clj/nim-esp8266-examples) 4 | 5 | ## Dependencies 6 | 7 | * [Nim compiler](https://nim-lang.org) 8 | * [esptool](https://github.com/espressif/esptool) 9 | * xtensa-lx106 toolchain, e.g. from the [esp-open-sdk](https://github.com/pfalcon/esp-open-sdk) 10 | * [Espressif ESP8266_NONOS_SDK](https://github.com/espressif/ESP8266_NONOS_SDK) 11 | * [nim-esp8266-sdk](https://github.com/clj/nim-esp8266-sdk) 12 | 13 | All examples, except for: 14 | 15 | * hello-world 16 | * panic 17 | 18 | require the [nim-esp8266-sdk](https://github.com/clj/nim-esp8266-examples). 19 | 20 | ## Setting Up 21 | 22 | The easiest way to get set up on all operating systems is to use a vagrant box bootstrapped by the [nim-esp8266-vagrant](https://github.com/clj/nim-esp8266-vagrant) vagrantfile. 23 | 24 | ### Linux 25 | 26 | Install: 27 | 28 | * [Nim compiler](https://nim-lang.org) 29 | - For example using [choosenim](https://github.com/dom96/choosenim) 30 | * [esp-open-sdk](https://github.com/pfalcon/esp-open-sdk) 31 | - For use with the nim-esp8266-sdk installing with `make STANDALONE=n` is recommended 32 | * [nim-esp8266-sdk](https://github.com/clj/nim-esp8266-examples) 33 | - Download the latest release from the [release](https://github.com/clj/nim-esp8266-examples/releases) page 34 | * [Espressif ESP8266_NONOS_SDK](https://github.com/espressif/ESP8266_NONOS_SDK) 35 | - Check the [nim-esp8266-sdk](https://github.com/clj/nim-esp8266-examples) for supported versions if the Espressif NON-OS SDK 36 | 37 | The esp-open-sdk comes with an old version of esptool; install [esptool](https://github.com/espressif/esptool) for Python 3 support and faster uploads. 38 | 39 | ### OS X/Windows/other 40 | 41 | The pain of trying to build a dev environment is unlikely to be worth the effort. Just use the [nim-esp8266-vagrant](https://github.com/clj/nim-esp8266-vagrant) box or build your own Linux based dev environment. 42 | 43 | ## Compiling and Uploading 44 | 45 | With everything set up correctly, `cd` into one of the example directories and type `make`. 46 | 47 | The following make targets are available: 48 | 49 | * `all` builds the firmware images (default) 50 | * `flash` flashes an ESP (and builds the firmware images if necessary) 51 | * `clean` cleans 52 | 53 | With the following variables which can be set: 54 | 55 | * `XTENSA_TOOLS_ROOT` 56 | * `SDK_BASE` 57 | * `NIM_SDK_BASE` 58 | * `ESPPORT` 59 | * `ESPTOOL_BAUD` 60 | 61 | But see the top of the Makefiles for more info. Please note that the version of the SDK pointed to by `SDK_BASE` and `NIM_SDK_BASE` should agree. 62 | 63 | It can be convenient to set the above as environment variables to avoid having to pass them to `make` on every invocation. For example, create a file called `nim-esp-build-setup.sh`, with the following contents (but update the paths as required for your system): 64 | 65 | ``` 66 | export XTENSA_TOOLS_ROOT=/opt/esp-open-sdk/xtensa-lx106-elf/bin 67 | export SDK_BASE=/opt/ESP8266_NONOS_SDK-2.2.1 68 | export NIM_SDK_BASE=/opt/nim-esp8266-sdk/2.2.1/ 69 | ``` 70 | 71 | which you can then source into the shell from which building by calling `source nim-esp-build-setup.sh`, once, at the beginning of your session. 72 | 73 | ## Examples 74 | 75 | The examples in this repository, listed roughly in increasing order of complexity 76 | 77 | ### Hello World 78 | 79 | This example prints hello world on the serial console, at the default baud rate, use `miniterm.py /dev/ttyUSB0 74880` to view. 80 | 81 | ### Hello Nim SDK World 82 | 83 | This example prints hello world on the serial console using the same wrapped ESP8266 NONOS SDK function as above, but wrapped using the nim-esp8266-sdk. Use `miniterm.py /dev/ttyUSB0 74880` to view. 84 | 85 | ### Panic 86 | 87 | This example causes the running Nim program to panic and outputs a panic message on the console. Use `miniterm.py /dev/ttyUSB0 74880` to view. 88 | 89 | ### Blinky 90 | 91 | This example blinks the LED on pin 2. 92 | 93 | ### Blinky Lib 94 | 95 | Identical behaviour to Blinky, but uses a library to abstract the raw sdk pin functions. 96 | 97 | ### Garbage Collection: Regions 98 | 99 | Shows how to enable and use the *Regions* garbage collector. 100 | 101 | **Note:** There are quite a few aspects of this garbage collector which does not work in the current version of Nim (1.2.0). See the source code for details. 102 | 103 | ### Garbage Collection: ARC 104 | 105 | Shows how to enable and use the *ARC* garbage collector. Requires Nim 1.2.0+ (**Note:** ARC is currently experimental in 1.2.0). 106 | 107 | ### Read Data Store in Flash 108 | 109 | Shows how to read data stored in flash memory. 110 | 111 | Generating an example data.bin: 112 | 113 | ``` 114 | echo "hello world!" > data.bin && cat $SDK_BASE/bin/blank.bin >> data.bin && truncate -s 4096 data.bin 115 | ``` 116 | 117 | You can then upload this data by using the appropriate make target: 118 | 119 | ``` 120 | make flash-data 121 | ``` 122 | 123 | ### WiFi 124 | 125 | Shows how to read WiFi credentials from flash and set up the Wifi using those credentials. 126 | 127 | To flash wifi credentials run the following commands: 128 | 129 | ``` 130 | make gen-data 131 | make flash-data 132 | ``` 133 | 134 | To view the generated data you can use a command, such as, `hexdump -C user_data.bin`. 135 | 136 | ### Firmware Over the Air (FOTA) 137 | 138 | Shows how to do a FOTA update. A simple firmware server can be started using the following Python command: `python3 -m http.server 8000` in the fota example directory. 139 | 140 | **Note:** If you are using a virtual machine for development then you probably want to start the Python webserver on the **host** machine to make sure the ESP can connect to the web server. 141 | 142 | **Note:** The warning that is emitted when compiling this program is expected and due to the line that makes the following assignment: `update.ip = ip`. 143 | 144 | ### MQTT: Blinky 145 | 146 | Blinks the LED on pin 2, but controllable via MQTT. A WiFi connection is required. See more information in the [mqtt-blinky example readme](mqtt-blinky/README.md). 147 | 148 | ## Troubleshooting 149 | 150 | ### rf_cal[0] !=0x05,is 0xFF 151 | 152 | If the ESP8266 reboots repeatedly, displaying `rf_cal[0] !=0x05,is 0xFF`, then you need to flash the default init data onto the ESP: 153 | 154 | * `esptool.py write_flash ADDRESS esp_init_data_default_v08.bin` 155 | 156 | At the following address, depending on the flash size: 157 | 158 | * `0x7c000` for 512kB 159 | * `0xfc000` for 1MB 160 | * `0x1fc000` for 2MB 161 | * `0x3fc000` for 4MB 162 | 163 | The `esp_init_data_default_v08.bin` file can be found in the [Espressif ESP8266_NONOS_SDK](https://github.com/espressif/ESP8266_NONOS_SDK)s. 164 | 165 | ## License 166 | 167 | The files in this repository are licensed under the MIT license, see the LICENSE file. 168 | 169 | The Makefile has been adapted from https://github.com/esp8266/source-code-examples/blob/master/example.Makefile, this repository sadly has no explicit license (see [issue #8](https://github.com/esp8266/source-code-examples/issues/8)). The Nim related changes in these Makefiles are licensed under the MIT license. 170 | -------------------------------------------------------------------------------- /blinky-lib/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Set path related variables to have absolute paths 31 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 32 | override SDK_BASE := $(abspath $(SDK_BASE)) 33 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 34 | 35 | # esptool.py options 36 | ESPPORT ?= /dev/ttyUSB0 37 | ESPTOOL ?= esptool.py 38 | ESPTOOL_BAUD ?= 115200 39 | 40 | # name for the target project 41 | TARGET = app 42 | 43 | # which modules (subdirectories) of the project to include in compiling 44 | MODULES = driver user 45 | EXTRA_INCDIR = include 46 | 47 | # libraries used in this project, mainly provided by the SDK 48 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main 49 | 50 | # compiler flags using during compilation of source files 51 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 52 | 53 | # linker flags used to generate the main object file 54 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 55 | 56 | # linker script used for the above linkier step 57 | LD_SCRIPT ?= eagle.app.v6.ld 58 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 59 | 60 | # various paths from the SDK used in this project 61 | SDK_LIBDIR = lib 62 | SDK_LDDIR = ld 63 | SDK_INCDIR = include include/json 64 | 65 | # nim library path 66 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 67 | 68 | FLASH_SIZE ?= 1MB 69 | # we create two different files for uploading into the flash 70 | # these are the names and options to generate them 71 | FW_FILE_1_ADDR = 0x00000 72 | FW_FILE_2_ADDR = 0x10000 73 | 74 | # select which tools to use as compiler, librarian and linker 75 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 76 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 77 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 78 | 79 | 80 | 81 | #### 82 | #### no user configurable options below here 83 | #### 84 | SRC_DIR := $(MODULES) 85 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 86 | NIM_BUILD_DIR := $(NIM_CACHE) 87 | 88 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 89 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 90 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk) $(NIM_SEARCH_PATHS) 91 | 92 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 93 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 94 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 95 | LIBS := $(addprefix -l,$(LIBS)) 96 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 97 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 98 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 99 | 100 | LD_SCRIPT := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT)) 101 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 102 | 103 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk) 104 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 105 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 106 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 107 | 108 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 109 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 110 | 111 | V ?= $(VERBOSE) 112 | ifeq ("$(V)","1") 113 | Q := 114 | vecho := @true 115 | else 116 | Q := @ 117 | vecho := @echo 118 | endif 119 | 120 | vpath %.c $(SRC_DIR) 121 | 122 | define compile-objects 123 | $1/%.o: %.c 124 | $(vecho) "CC $$<" 125 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 126 | endef 127 | 128 | .PHONY: all checkdirs flash clean 129 | 130 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 131 | 132 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 133 | $(vecho) "FW $(FW_BASE)/" 134 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 135 | 136 | $(TARGET_OUT): $(APP_AR) 137 | $(vecho) "LD $@" 138 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 139 | 140 | $(APP_AR): $(OBJ) $(NIM_OBJ) 141 | $(vecho) "AR $@" 142 | $(Q) $(AR) cru $@ $^ 143 | 144 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 145 | 146 | $(BUILD_DIR): 147 | $(vecho) "MKDIR $@" 148 | $(Q) mkdir -p $@ 149 | 150 | $(FW_BASE): 151 | $(vecho) "MKDIR $@" 152 | $(Q) mkdir -p $@ 153 | 154 | flash: $(FW_FILE_1) $(FW_FILE_2) 155 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 156 | 157 | clean: 158 | $(vecho) "CLEAN" 159 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 160 | 161 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 162 | $(vecho) "NIM $@" 163 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h $(NIM_SEARCH_PATHS) $< 164 | $(Q) touch $@ 165 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 166 | 167 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 168 | $(vecho) "TOUCH $@" 169 | $(Q) touch $@ 170 | 171 | 172 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 173 | 174 | %.o: %.c 175 | %.o: %.c 176 | $(vecho) "CC $<" 177 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 178 | 179 | user_main.c: $(NIM_CACHE)/nim_main.h 180 | 181 | $(NIM_CACHE)/main.deps.mk: 182 | 183 | ifneq ($(MAKECMDGOALS), clean) 184 | -include $(NIM_CACHE)/nim_built.mk 185 | -include $(NIM_CACHE)/main.deps.mk 186 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 187 | ifneq ($(sdk_version_check),) 188 | $(error $(sdk_version_check)) 189 | endif 190 | endif 191 | -------------------------------------------------------------------------------- /blinky-lib/user/main.nim: -------------------------------------------------------------------------------- 1 | import esp8266/nonos-sdk/eagle_soc 2 | import esp8266/nonos-sdk/gpio 3 | import esp8266/nonos-sdk/os_type 4 | import esp8266/nonos-sdk/osapi 5 | import esp8266/pins 6 | import esp8266/user_fns/default_user_rf_cal_sector_set 7 | import esp8266/user_fns/user_init 8 | import esp8266/user_fns/user_pre_init 9 | 10 | 11 | var 12 | led_timer: os_timer_t 13 | 14 | 15 | const 16 | pin = 2 17 | 18 | 19 | proc led_timer_fn(arg: pointer) {.cdecl.} = 20 | let value = get_pin_state(pin) 21 | pin_set(pin, not value) 22 | 23 | 24 | proc nim_user_init() {.exportc.} = 25 | gpio_init() 26 | 27 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2); 28 | pin_set(pin, 1) 29 | 30 | os_timer_setfn(addr led_timer, led_timer_fn, nil) 31 | os_timer_arm(addr led_timer, 1000, true) 32 | -------------------------------------------------------------------------------- /blinky-lib/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:none 2 | --deadCodeElim:on 3 | -------------------------------------------------------------------------------- /blinky-lib/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /blinky-lib/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/blinky-lib/user/user_config.h -------------------------------------------------------------------------------- /blinky/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Set path related variables to have absolute paths 31 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 32 | override SDK_BASE := $(abspath $(SDK_BASE)) 33 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 34 | 35 | # esptool.py options 36 | ESPPORT ?= /dev/ttyUSB0 37 | ESPTOOL ?= esptool.py 38 | ESPTOOL_BAUD ?= 115200 39 | 40 | # name for the target project 41 | TARGET = app 42 | 43 | # which modules (subdirectories) of the project to include in compiling 44 | MODULES = driver user 45 | EXTRA_INCDIR = include 46 | 47 | # libraries used in this project, mainly provided by the SDK 48 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main 49 | 50 | # compiler flags using during compilation of source files 51 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 52 | 53 | # linker flags used to generate the main object file 54 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 55 | 56 | # linker script used for the above linkier step 57 | LD_SCRIPT ?= eagle.app.v6.ld 58 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 59 | 60 | # various paths from the SDK used in this project 61 | SDK_LIBDIR = lib 62 | SDK_LDDIR = ld 63 | SDK_INCDIR = include include/json 64 | 65 | # nim library path 66 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 67 | 68 | FLASH_SIZE ?= 1MB 69 | # we create two different files for uploading into the flash 70 | # these are the names and options to generate them 71 | FW_FILE_1_ADDR = 0x00000 72 | FW_FILE_2_ADDR = 0x10000 73 | 74 | # select which tools to use as compiler, librarian and linker 75 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 76 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 77 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 78 | 79 | 80 | 81 | #### 82 | #### no user configurable options below here 83 | #### 84 | SRC_DIR := $(MODULES) 85 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 86 | NIM_BUILD_DIR := $(NIM_CACHE) 87 | 88 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 89 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 90 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk) $(NIM_SEARCH_PATHS) 91 | 92 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 93 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 94 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 95 | LIBS := $(addprefix -l,$(LIBS)) 96 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 97 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 98 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 99 | 100 | LD_SCRIPT := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT)) 101 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 102 | 103 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk) 104 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 105 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 106 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 107 | 108 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 109 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 110 | 111 | V ?= $(VERBOSE) 112 | ifeq ("$(V)","1") 113 | Q := 114 | vecho := @true 115 | else 116 | Q := @ 117 | vecho := @echo 118 | endif 119 | 120 | vpath %.c $(SRC_DIR) 121 | 122 | define compile-objects 123 | $1/%.o: %.c 124 | $(vecho) "CC $$<" 125 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 126 | endef 127 | 128 | .PHONY: all checkdirs flash clean 129 | 130 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 131 | 132 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 133 | $(vecho) "FW $(FW_BASE)/" 134 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 135 | 136 | $(TARGET_OUT): $(APP_AR) 137 | $(vecho) "LD $@" 138 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 139 | 140 | $(APP_AR): $(OBJ) $(NIM_OBJ) 141 | $(vecho) "AR $@" 142 | $(Q) $(AR) cru $@ $^ 143 | 144 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 145 | 146 | $(BUILD_DIR): 147 | $(vecho) "MKDIR $@" 148 | $(Q) mkdir -p $@ 149 | 150 | $(FW_BASE): 151 | $(vecho) "MKDIR $@" 152 | $(Q) mkdir -p $@ 153 | 154 | flash: $(FW_FILE_1) $(FW_FILE_2) 155 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 156 | 157 | clean: 158 | $(vecho) "CLEAN" 159 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 160 | 161 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 162 | $(vecho) "NIM $@" 163 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h $(NIM_SEARCH_PATHS) $< 164 | $(Q) touch $@ 165 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 166 | 167 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 168 | $(vecho) "TOUCH $@" 169 | $(Q) touch $@ 170 | 171 | 172 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 173 | 174 | %.o: %.c 175 | %.o: %.c 176 | $(vecho) "CC $<" 177 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 178 | 179 | $(NIM_CACHE)/main.deps.mk: 180 | 181 | ifneq ($(MAKECMDGOALS), clean) 182 | -include $(NIM_CACHE)/nim_built.mk 183 | -include $(NIM_CACHE)/main.deps.mk 184 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 185 | ifneq ($(sdk_version_check),) 186 | $(error $(sdk_version_check)) 187 | endif 188 | endif 189 | -------------------------------------------------------------------------------- /blinky/user/main.nim: -------------------------------------------------------------------------------- 1 | import esp8266/nonos-sdk/eagle_soc 2 | import esp8266/nonos-sdk/gpio 3 | import esp8266/nonos-sdk/os_type 4 | import esp8266/nonos-sdk/osapi 5 | import esp8266/user_fns/default_user_rf_cal_sector_set 6 | import esp8266/user_fns/user_init 7 | import esp8266/user_fns/user_pre_init 8 | 9 | 10 | var 11 | led_timer: os_timer_t 12 | 13 | 14 | const 15 | pin = 2 16 | 17 | 18 | proc led_timer_fn(arg: pointer) {.cdecl.} = 19 | let value = (GPIO_REG_READ(GPIO_OUT_ADDRESS) and uint32(1 shl pin)) shr pin 20 | gpio_output_set(uint32((not value) shl pin), 21 | uint32(value shl pin), 22 | uint32(1 shl pin), 0) 23 | 24 | 25 | proc nim_user_init() {.exportc.} = 26 | gpio_init() 27 | 28 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2); 29 | gpio_output_set(0, uint32(1 shl pin), uint32(1 shl pin), 0) 30 | 31 | os_timer_setfn(addr led_timer, led_timer_fn, nil) 32 | os_timer_arm(addr led_timer, 1000, true) 33 | -------------------------------------------------------------------------------- /blinky/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:none 2 | --deadCodeElim:on 3 | -------------------------------------------------------------------------------- /blinky/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /blinky/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/blinky/user/user_config.h -------------------------------------------------------------------------------- /constraints.nims: -------------------------------------------------------------------------------- 1 | # mmm... totally overkill! 2 | import pegs 3 | import strutils 4 | import tables 5 | 6 | 7 | type 8 | constraint = tuple[op: string, version: string] 9 | 10 | 11 | var 12 | constraints = initTable[string, seq[constraint]]() 13 | 14 | 15 | proc constrain(constraint: string) = 16 | if constraint =~ peg"""rule <- {name} ws constraints 17 | name <- [a-zA-Z_0-9-]+ 18 | ws <- \s+ 19 | constraints <- constraint (ws constraint)* 20 | constraint <- {op} ws {version} 21 | op <- '<=' / '>=' / '!=' / '==' / '<' / '>' 22 | version <- [0-9\.]+ 23 | """: 24 | var 25 | c: seq[constraint] 26 | i = 1 27 | while matches[i] != "": 28 | c.add((matches[i], matches[i + 1])) 29 | i += 2 30 | constraints[matches[0]] = c 31 | else: 32 | echo "Syntax error: " & constraint 33 | quit(QuitFailure) 34 | 35 | 36 | constrain "blinky-lib < 1.2.0" 37 | 38 | for line in readAllFromStdin().split(): 39 | let dir = line.strip(chars = {'/'}) 40 | if dir in constraints: 41 | var result = true 42 | for constraint in constraints[dir]: 43 | case constraint.op 44 | of "<=": result = result and NimVersion <= constraint.version 45 | of ">=": result = result and NimVersion >= constraint.version 46 | of "!=": result = result and NimVersion != constraint.version 47 | of "==": result = result and NimVersion == constraint.version 48 | of "<": result = result and NimVersion < constraint.version 49 | of ">": result = result and NimVersion > constraint.version 50 | else: 51 | echo("Should not get here...") 52 | quit(QuitFailure) 53 | if not result: 54 | continue 55 | echo(line) 56 | -------------------------------------------------------------------------------- /fota/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Set path related variables to have absolute paths 31 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 32 | override SDK_BASE := $(abspath $(SDK_BASE)) 33 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 34 | 35 | # esptool.py options 36 | ESPPORT ?= /dev/ttyUSB0 37 | ESPTOOL ?= esptool.py 38 | ESPTOOL_BAUD ?= 115200 39 | 40 | # name for the target project 41 | TARGET = user 42 | 43 | # which modules (subdirectories) of the project to include in compiling 44 | MODULES = driver user 45 | EXTRA_INCDIR = include 46 | 47 | # libraries used in this project, mainly provided by the SDK 48 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main upgrade 49 | 50 | # compiler flags using during compilation of source files 51 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 52 | 53 | # linker flags used to generate the main object file 54 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 55 | 56 | # linker script used for the above linkier step 57 | LD_SCRIPT_1 ?= eagle.app.v6.new.1024.app1.ld 58 | LD_SCRIPT_2 ?= eagle.app.v6.new.1024.app2.ld 59 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 60 | #LD_SCRIPT_DIR = $(SDK_BASE)/ld/ 61 | 62 | # various paths from the SDK used in this project 63 | SDK_LIBDIR = lib 64 | SDK_LDDIR = ld 65 | SDK_INCDIR = include include/json 66 | 67 | # nim library path 68 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 69 | 70 | FLASH_SIZE ?= 1MB 71 | # FOTA addresses 72 | # See Table 4-4 in https://www.espressif.com/sites/default/files/2a-esp8266-sdk_getting_started_guide_en_0.pdf 73 | BIN_ADDRESS_1 ?= 0x01000 74 | BIN_ADDRESS_2 ?= 0x81000 75 | BOOTLOADER_ADDRESS ?= 0x00000 76 | ESP_INIT_DATA_DEFAULT_ADDR = 0xFC000 77 | BLANK_1_ADDR ?= 0XFB000 78 | BLANK_2_ADDR ?= 0XFE000 79 | USER_DATA_ADDR = 0xE1000 80 | 81 | BOOT_BIN ?= $(addprefix $(SDK_BASE)/bin/,boot_v1.7.bin) 82 | ESP_INIT_DATA_DEFAULT_BIN ?= $(SDK_BASE)/bin/esp_init_data_default_v08.bin 83 | BLANK_BIN ?= $(SDK_BASE)/bin/blank.bin 84 | 85 | # select which tools to use as compiler, librarian and linker 86 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 87 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 88 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 89 | 90 | 91 | 92 | #### 93 | #### no user configurable options below here 94 | #### 95 | SRC_DIR := $(MODULES) 96 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 97 | NIM_BUILD_DIR := $(NIM_CACHE) 98 | 99 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 100 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 101 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk) $(NIM_SEARCH_PATHS) 102 | 103 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 104 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 105 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 106 | LIBS := $(addprefix -l,$(LIBS)) 107 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 108 | TARGET_OUT_1 := $(addprefix $(BUILD_BASE)/,$(TARGET)_1.out) 109 | TARGET_MAP_1 := $(TARGET_OUT_1:out=map) 110 | TARGET_OUT_2 := $(addprefix $(BUILD_BASE)/,$(TARGET)_2.out) 111 | TARGET_MAP_2 := $(TARGET_OUT_2:out=map) 112 | 113 | LD_SCRIPT_1 := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT_1)) 114 | LD_SCRIPT_2 := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT_2)) 115 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 116 | 117 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk) 118 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 119 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 120 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 121 | 122 | OUTPUT_1 := $(addprefix $(FW_BASE)/,$(TARGET)1.bin) 123 | OUTPUT_2 := $(addprefix $(FW_BASE)/,$(TARGET)2.bin) 124 | 125 | V ?= $(VERBOSE) 126 | ifeq ("$(V)","1") 127 | Q := 128 | vecho := @true 129 | else 130 | Q := @ 131 | vecho := @echo 132 | endif 133 | 134 | vpath %.c $(SRC_DIR) 135 | 136 | define compile-objects 137 | $1/%.o: %.c 138 | $(vecho) "CC $$<" 139 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 140 | endef 141 | 142 | .PHONY: all checkdirs flash flash-data gen-data flash-all clean 143 | 144 | all: checkdirs $(OUTPUT_1) $(OUTPUT_2) 145 | 146 | $(OUTPUT_1): $(TARGET_OUT_1) | $(FW_BASE) 147 | $(vecho) "FW $@" 148 | $(Q) $(ESPTOOL) elf2image --version=2 --flash_size $(FLASH_SIZE) $< -o $@ 149 | 150 | $(OUTPUT_2): $(TARGET_OUT_2) | $(FW_BASE) 151 | $(vecho) "FW $@" 152 | $(Q) $(ESPTOOL) elf2image --version=2 --flash_size $(FLASH_SIZE) $< -o $@ 153 | 154 | $(TARGET_OUT_1): TARGET_MAP=$(TARGET_MAP_1) 155 | $(TARGET_OUT_1): LD_SCRIPT=$(LD_SCRIPT_1) 156 | $(TARGET_OUT_1): $(APP_AR) 157 | $(vecho) "LD $@" 158 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 159 | 160 | $(TARGET_OUT_2): TARGET_MAP=$(TARGET_MAP_2) 161 | $(TARGET_OUT_2): LD_SCRIPT=$(LD_SCRIPT_2) 162 | $(TARGET_OUT_2): $(APP_AR) 163 | $(vecho) "LD $@" 164 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 165 | 166 | $(APP_AR): $(OBJ) $(NIM_OBJ) 167 | $(vecho) "AR $@" 168 | $(Q) $(AR) cru $@ $^ 169 | 170 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 171 | 172 | $(BUILD_DIR): 173 | $(vecho) "MKDIR $@" 174 | $(Q) mkdir -p $@ 175 | 176 | $(FW_BASE): 177 | $(vecho) "MKDIR $@" 178 | $(Q) mkdir -p $@ 179 | 180 | flash: $(OUTPUT_1) 181 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(BOOTLOADER_ADDRESS) $(BOOT_BIN) $(BIN_ADDRESS_1) $(OUTPUT_1) $(ESP_INIT_DATA_DEFAULT_ADDR) $(ESP_INIT_DATA_DEFAULT_BIN) $(BLANK_1_ADDR) $(BLANK_BIN) $(BLANK_2_ADDR) $(BLANK_BIN) 182 | 183 | gen-data: 184 | $(vecho) "NIM RUN $@" 185 | nim c -r $(NIM_SEARCH_PATHS) user/user_data.nim 186 | 187 | flash-data: 188 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(USER_DATA_ADDR) user_data.bin 189 | 190 | #$(FW_BASE)/user_data.py: user_data.py 191 | # $(vecho) "CP $@" 192 | # $(Q) cp $< $@ 193 | 194 | flash-all: flash $(OUTPUT_2) 195 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(BIN_ADDRESS_2) $(OUTPUT_2) 196 | 197 | clean: 198 | $(vecho) "CLEAN" 199 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 200 | 201 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 202 | $(vecho) "NIM $@" 203 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h -d:nimMinHeapPages=1 $(NIM_SEARCH_PATHS) $< 204 | $(Q) touch $@ 205 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 206 | 207 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 208 | $(vecho) "TOUCH $@" 209 | $(Q) touch $@ 210 | 211 | 212 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 213 | 214 | %.o: %.c 215 | %.o: %.c 216 | $(vecho) "CC $<" 217 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 218 | 219 | $(NIM_CACHE)/stdlib_system.nim.o: CFLAGS:=$(CFLAGS) -D'realloc(ptr, size)=os_realloc(ptr, size)' -D'calloc(count, size)=os_calloc(count, size)' -D'malloc(size)=os_malloc(size)' -D'free(ptr)=os_free(ptr)' -include stdlib.h -include mem.h 220 | 221 | $(NIM_CACHE)/main.deps.mk: 222 | 223 | ifneq ($(MAKECMDGOALS), clean) 224 | -include $(NIM_CACHE)/nim_built.mk 225 | -include $(NIM_CACHE)/main.deps.mk 226 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 227 | ifneq ($(sdk_version_check),) 228 | $(error $(sdk_version_check)) 229 | endif 230 | endif 231 | -------------------------------------------------------------------------------- /fota/user/main.nim: -------------------------------------------------------------------------------- 1 | import strutils 2 | 3 | import esp8266/nonos-sdk/espconn 4 | import esp8266/nonos-sdk/os_type 5 | import esp8266/nonos-sdk/osapi 6 | import esp8266/nonos-sdk/spi_flash 7 | import esp8266/nonos-sdk/upgrade 8 | import esp8266/nonos-sdk/user_interface 9 | import esp8266/types 10 | import esp8266/user_fns/default_user_rf_cal_sector_set 11 | import esp8266/user_fns/user_init 12 | import esp8266/user_fns/user_pre_init 13 | 14 | import user_data 15 | 16 | 17 | var 18 | data: Data 19 | wifi_config: station_config 20 | update: upgrade_server_info 21 | conn: espconn 22 | timer: os_timer_t 23 | url: string 24 | count = 10 25 | 26 | 27 | proc timer_fn(arg: pointer) {.cdecl.} 28 | 29 | 30 | proc ota_finished_callback(arg: pointer) {.cdecl.} = 31 | var update = cast[ptr upgrade_server_info](arg) 32 | if update.upgrade_flag != 0: 33 | os_printf("\nFOTA success: rebooting!\n") 34 | system_upgrade_reboot() 35 | else: 36 | os_printf("\nFOTA failed!\n") 37 | os_printf("Trying again in:\n") 38 | count = 10 39 | os_timer_disarm(addr timer) 40 | os_timer_setfn(addr timer, timer_fn, nil) 41 | os_timer_arm(addr timer, 1000, true) 42 | 43 | 44 | proc updateHost(): string = 45 | return join(data.settings.fota.ip, ".") & ":" & $data.settings.fota.port 46 | 47 | 48 | proc updatePath(): string = 49 | # Lets hope there is still a terminating null char :) 50 | return $cast[cstring](addr data.settings.fota.path) 51 | 52 | 53 | proc start_update() = 54 | os_printf("\n\n") 55 | 56 | var user_bin: string 57 | if system_upgrade_userbin_check() == 0: 58 | user_bin = "user2.bin" 59 | else: 60 | user_bin = "user1.bin" 61 | 62 | url = ("GET " & updatePath() & user_bin & " HTTP/1.1\r\n" & 63 | "Host: " & updateHost() & "\r\n" & 64 | "Connection: close\r\n" & 65 | "\r\n") 66 | update.pespconn = addr conn 67 | update.ip = data.settings.fota.ip 68 | update.port = data.settings.fota.port 69 | update.check_cb = ota_finished_callback 70 | update.check_times = 10000 71 | update.url = cast[ptr uint8](cstring(url)) 72 | 73 | if system_upgrade_start(addr update) == false: 74 | os_printf("Could not start upgrade\n") 75 | else: 76 | os_printf("Upgrading...\n") 77 | 78 | 79 | proc timer_fn(arg: pointer) {.cdecl.} = 80 | if count == 0: 81 | os_timer_disarm(addr timer) 82 | os_printf("0!") 83 | start_update() 84 | else: 85 | os_printf("%d..", count) 86 | count -= 1 87 | 88 | 89 | proc wifi_connect_handle_event_cb(event: ptr System_Event_t) {.cdecl.} = 90 | case event.event: 91 | of EVENT_STAMODE_GOT_IP: 92 | os_timer_disarm(addr timer) 93 | os_timer_setfn(addr timer, timer_fn, nil) 94 | os_timer_arm(addr timer, 1000, true) 95 | of EVENT_STAMODE_DISCONNECTED: 96 | os_timer_disarm(addr timer) 97 | else: 98 | discard 99 | 100 | 101 | proc wifi_setup() = 102 | wifi_set_event_handler_cb(wifi_connect_handle_event_cb) 103 | 104 | discard wifi_set_opmode(uint8(STATION_MODE)) 105 | wifi_config.bssid_set = 0 106 | wifi_config.ssid = data.settings.wifi.ssid 107 | wifi_config.password = data.settings.wifi.password 108 | discard wifi_station_set_config(addr wifi_config) 109 | discard wifi_station_set_auto_connect((uint8)false) 110 | discard wifi_station_ap_number_set(0) 111 | 112 | 113 | proc app_init() {.cdecl.} = 114 | os_printf("\n\n") 115 | os_printf("system_upgrade_userbin_check: %d\n", system_upgrade_userbin_check()) 116 | os_printf("upgrade server: %s%s\n", updateHost(), updatePath()) 117 | os_printf("compile timestamp: %sT%sZ\n", CompileDate, CompileTime) 118 | os_printf("\n\n") 119 | 120 | discard wifi_station_connect() 121 | 122 | 123 | proc nim_user_init() {.exportc.} = 124 | os_printf("\n\n") 125 | 126 | var 127 | part_info: partition_item_t 128 | 129 | block: 130 | let result = system_partition_get_item(partition_type_t(100), 131 | addr part_info) 132 | if not result: 133 | os_printf("system_partition_get_item returned an error\n") 134 | return 135 | 136 | block: 137 | let result = spi_flash_read(part_info.`addr`, addr data, uint32(sizeof(data))) 138 | if result != SPI_FLASH_RESULT_OK: 139 | os_printf("spi_flash_read returned an error %d\n", result) 140 | return 141 | 142 | let (ok, msg) = data.verify() 143 | if ok: 144 | wifi_setup() 145 | 146 | system_init_done_cb(app_init) 147 | else: 148 | os_printf( 149 | "No valid user data found: %s\n" & 150 | "please upload valid data to flash @0x%08x\n", 151 | msg, part_info.`addr`) 152 | -------------------------------------------------------------------------------- /fota/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:arc 2 | --define:useMalloc 3 | --exceptions:quirky 4 | --deadCodeElim:on 5 | --define:fota 6 | --define:userPartitions="{ USER_DATA_PARTITION_BEGIN + 0, SYSTEM_PROGRAM_END, 0x1000}," 7 | -------------------------------------------------------------------------------- /fota/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /fota/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/fota/user/user_config.h -------------------------------------------------------------------------------- /fota/user/user_data.nim: -------------------------------------------------------------------------------- 1 | import esp8266/crc 2 | import esp8266/types 3 | 4 | 5 | const 6 | magic = 0x0A0CDCBA'u32 7 | app = "fota" 8 | 9 | 10 | type 11 | WiFiSsid* = array[32, uint8] 12 | WiFiPassword* = array[64, uint8] 13 | WiFiCreds* {.packed.} = object 14 | ssid*: WiFiSsid 15 | password*: WiFiPassword 16 | Fota* {.packed.} = object 17 | ip*: array[4, uint8] 18 | port*: uint16 19 | path* {.align(4).}: array[64, uint8] 20 | Settings* {.packed.} = object 21 | magic*: uint32 22 | app: array[4, uint8] 23 | wifi*: WifiCreds 24 | fota*: Fota 25 | Data* {.packed.} = object 26 | settings*: Settings 27 | crc32*: uint32 28 | 29 | 30 | proc verify*(data: var Data): (bool, string) = 31 | if data.settings.magic != magic: 32 | return (false, "wrong magic") 33 | if data.settings.app != app.toArray(4, uint8): 34 | return (false, "wrong app") 35 | let crc = crc32(data.settings) 36 | if data.crc32 != crc: 37 | return (false, "bad crc") 38 | return (true, "") 39 | 40 | 41 | when isMainModule: 42 | import endians 43 | import net 44 | import parseopt 45 | import streams 46 | import strutils 47 | 48 | import esp8266/types 49 | 50 | const 51 | default_port = "8080" 52 | default_path = "/firmware/" 53 | 54 | var 55 | data: Data 56 | ssid: string 57 | password: string 58 | host: string 59 | dest = "user_data.bin" 60 | optParser = initOptParser() 61 | 62 | while true: 63 | optParser.next() 64 | case optParser.kind 65 | of cmdEnd: break 66 | of cmdShortOption, cmdLongOption: 67 | case optParser.key: 68 | of "ssid", "s": 69 | ssid = optParser.val 70 | of "password", "passwd", "pass", "p": 71 | password = optParser.val 72 | of "host": 73 | host = optParser.val 74 | else: 75 | echo("Unknown option: ", optParser.key) 76 | quit(QuitFailure) 77 | if optParser.val == "": 78 | echo("Option: ", optParser.key, " takes one argument") 79 | quit(QuitFailure) 80 | of cmdArgument: 81 | dest = optParser.key 82 | 83 | if ssid == "": 84 | stdout.write("SSID: ") 85 | ssid = readLine(stdin) 86 | if password == "": 87 | stdout.write("Password: ") 88 | password = readLine(stdin) 89 | if host == "": 90 | let default_host = $getPrimaryIPAddr() & ":" & default_port & default_path 91 | stdout.write("Using the format: IPv4:PORT/[PATH]\n") 92 | stdout.write("Leave blank for: " & default_host & "\n") 93 | stdout.write("Host: ") 94 | host = readLine(stdin) 95 | if host == "": 96 | host = default_host 97 | 98 | var rest = host.split(':', 1) 99 | let ip = parseIpAddress(rest[0]) 100 | rest = rest[1].split('/', 1) 101 | let port = rest[0].parseUInt() 102 | let path = "/" & rest[1] & (if len(rest[1]) != 0 and rest[1][high(rest[1])] != '/': "/" else: "") 103 | 104 | data.settings.magic = magic 105 | data.settings.app.setString(app) 106 | data.settings.wifi.ssid.setString(ssid) 107 | data.settings.wifi.password.setString(password) 108 | data.settings.fota.ip = ip.address_v4 109 | data.settings.fota.port = uint16(port) 110 | data.settings.fota.path.setString(path) 111 | data.crc32 = crc32(data.settings) 112 | 113 | littleEndian32(addr data.settings.magic, addr data.settings.magic) 114 | littleEndian32(addr data.settings.fota.port, addr data.settings.fota.port) 115 | littleEndian32(addr data.crc32, addr data.crc32) 116 | 117 | let padding = '\xff'.repeat(4096 - sizeof(data)) 118 | 119 | let fp = open(dest, fmWrite) 120 | discard fp.writeBuffer(addr data, sizeof(data)) 121 | fp.write(padding) 122 | fp.close() 123 | -------------------------------------------------------------------------------- /gc-arc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Set path related variables to have absolute paths 31 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 32 | override SDK_BASE := $(abspath $(SDK_BASE)) 33 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 34 | 35 | # esptool.py options 36 | ESPPORT ?= /dev/ttyUSB0 37 | ESPTOOL ?= esptool.py 38 | ESPTOOL_BAUD ?= 115200 39 | 40 | # name for the target project 41 | TARGET = app 42 | 43 | # which modules (subdirectories) of the project to include in compiling 44 | MODULES = driver user 45 | EXTRA_INCDIR = include 46 | 47 | # libraries used in this project, mainly provided by the SDK 48 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main 49 | 50 | # compiler flags using during compilation of source files 51 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 52 | 53 | # linker flags used to generate the main object file 54 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 55 | 56 | # linker script used for the above linkier step 57 | LD_SCRIPT ?= eagle.app.v6.ld 58 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 59 | 60 | # various paths from the SDK used in this project 61 | SDK_LIBDIR = lib 62 | SDK_LDDIR = ld 63 | SDK_INCDIR = include include/json 64 | 65 | # nim library path 66 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 67 | 68 | FLASH_SIZE ?= 1MB 69 | # we create two different files for uploading into the flash 70 | # these are the names and options to generate them 71 | FW_FILE_1_ADDR = 0x00000 72 | FW_FILE_2_ADDR = 0x10000 73 | 74 | # select which tools to use as compiler, librarian and linker 75 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 76 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 77 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 78 | 79 | 80 | 81 | #### 82 | #### no user configurable options below here 83 | #### 84 | SRC_DIR := $(MODULES) 85 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 86 | NIM_BUILD_DIR := $(NIM_CACHE) 87 | 88 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 89 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 90 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk) $(NIM_SEARCH_PATHS) 91 | 92 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 93 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 94 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 95 | LIBS := $(addprefix -l,$(LIBS)) 96 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 97 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 98 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 99 | 100 | LD_SCRIPT := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT)) 101 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 102 | 103 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk) 104 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 105 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 106 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 107 | 108 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 109 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 110 | 111 | V ?= $(VERBOSE) 112 | ifeq ("$(V)","1") 113 | Q := 114 | vecho := @true 115 | else 116 | Q := @ 117 | vecho := @echo 118 | endif 119 | 120 | vpath %.c $(SRC_DIR) 121 | 122 | define compile-objects 123 | $1/%.o: %.c 124 | $(vecho) "CC $$<" 125 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 126 | endef 127 | 128 | .PHONY: all checkdirs flash clean 129 | 130 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 131 | 132 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 133 | $(vecho) "FW $(FW_BASE)/" 134 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 135 | 136 | $(TARGET_OUT): $(APP_AR) 137 | $(vecho) "LD $@" 138 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 139 | 140 | $(APP_AR): $(OBJ) $(NIM_OBJ) 141 | $(vecho) "AR $@" 142 | $(Q) $(AR) cru $@ $^ 143 | 144 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 145 | 146 | $(BUILD_DIR): 147 | $(vecho) "MKDIR $@" 148 | $(Q) mkdir -p $@ 149 | 150 | $(FW_BASE): 151 | $(vecho) "MKDIR $@" 152 | $(Q) mkdir -p $@ 153 | 154 | flash: $(FW_FILE_1) $(FW_FILE_2) 155 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 156 | 157 | clean: 158 | $(vecho) "CLEAN" 159 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 160 | 161 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 162 | $(vecho) "NIM $@" 163 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h -d:nimMinHeapPages=1 $(NIM_SEARCH_PATHS) $< 164 | $(Q) touch $@ 165 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 166 | 167 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 168 | $(vecho) "TOUCH $@" 169 | $(Q) touch $@ 170 | 171 | 172 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 173 | 174 | %.o: %.c 175 | %.o: %.c 176 | $(vecho) "CC $<" 177 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 178 | 179 | $(NIM_CACHE)/stdlib_system.nim.o: CFLAGS:=$(CFLAGS) -D'realloc(ptr, size)=os_realloc(ptr, size)' -D'calloc(count, size)=os_calloc(count, size)' -D'malloc(size)=os_malloc(size)' -D'free(ptr)=os_free(ptr)' -include stdlib.h -include mem.h 180 | 181 | $(NIM_CACHE)/main.deps.mk: 182 | 183 | ifneq ($(MAKECMDGOALS), clean) 184 | -include $(NIM_CACHE)/nim_built.mk 185 | -include $(NIM_CACHE)/main.deps.mk 186 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 187 | ifneq ($(sdk_version_check),) 188 | $(error $(sdk_version_check)) 189 | endif 190 | endif 191 | -------------------------------------------------------------------------------- /gc-arc/user/main.nim: -------------------------------------------------------------------------------- 1 | import esp8266/nonos-sdk/os_type 2 | import esp8266/nonos-sdk/osapi 3 | import esp8266/nonos-sdk/user_interface 4 | import esp8266/user_fns/default_user_rf_cal_sector_set 5 | import esp8266/user_fns/user_init 6 | import esp8266/user_fns/user_pre_init 7 | 8 | 9 | var 10 | timer: os_timer_t 11 | str: string 12 | 13 | 14 | proc timer_fn(arg: pointer) {.cdecl.} = 15 | os_printf("Time: " & $system_get_time() & "\n") 16 | os_printf("Mem; system free heap: " & $system_get_free_heap_size() & "\n") 17 | if len(str) > 100: 18 | str = "" 19 | else: 20 | str &= "0123456789" 21 | os_printf(str & "\n") 22 | 23 | 24 | proc nim_user_init() {.exportc.} = 25 | os_printf("\n\n") 26 | 27 | os_timer_setfn(addr timer, timer_fn, nil) 28 | os_timer_arm(addr timer, 1000, true) 29 | -------------------------------------------------------------------------------- /gc-arc/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:arc 2 | --define:useMalloc 3 | --exceptions:quirky 4 | --deadCodeElim:on 5 | -------------------------------------------------------------------------------- /gc-arc/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /gc-arc/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/gc-arc/user/user_config.h -------------------------------------------------------------------------------- /gc-regions/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Set path related variables to have absolute paths 31 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 32 | override SDK_BASE := $(abspath $(SDK_BASE)) 33 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 34 | 35 | # esptool.py options 36 | ESPPORT ?= /dev/ttyUSB0 37 | ESPTOOL ?= esptool.py 38 | ESPTOOL_BAUD ?= 115200 39 | 40 | # name for the target project 41 | TARGET = app 42 | 43 | # which modules (subdirectories) of the project to include in compiling 44 | MODULES = driver user 45 | EXTRA_INCDIR = include 46 | 47 | # libraries used in this project, mainly provided by the SDK 48 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main 49 | 50 | # compiler flags using during compilation of source files 51 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 52 | 53 | # linker flags used to generate the main object file 54 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 55 | 56 | # linker script used for the above linkier step 57 | LD_SCRIPT ?= eagle.app.v6.ld 58 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 59 | 60 | # various paths from the SDK used in this project 61 | SDK_LIBDIR = lib 62 | SDK_LDDIR = ld 63 | SDK_INCDIR = include include/json 64 | 65 | # nim library path 66 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 67 | 68 | FLASH_SIZE ?= 1MB 69 | # we create two different files for uploading into the flash 70 | # these are the names and options to generate them 71 | FW_FILE_1_ADDR = 0x00000 72 | FW_FILE_2_ADDR = 0x10000 73 | 74 | # select which tools to use as compiler, librarian and linker 75 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 76 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 77 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 78 | 79 | 80 | 81 | #### 82 | #### no user configurable options below here 83 | #### 84 | SRC_DIR := $(MODULES) 85 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 86 | NIM_BUILD_DIR := $(NIM_CACHE) 87 | 88 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 89 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 90 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk) $(NIM_SEARCH_PATHS) 91 | 92 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 93 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 94 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 95 | LIBS := $(addprefix -l,$(LIBS)) 96 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 97 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 98 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 99 | 100 | LD_SCRIPT := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT)) 101 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 102 | 103 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk) 104 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 105 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 106 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 107 | 108 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 109 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 110 | 111 | V ?= $(VERBOSE) 112 | ifeq ("$(V)","1") 113 | Q := 114 | vecho := @true 115 | else 116 | Q := @ 117 | vecho := @echo 118 | endif 119 | 120 | vpath %.c $(SRC_DIR) 121 | 122 | define compile-objects 123 | $1/%.o: %.c 124 | $(vecho) "CC $$<" 125 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 126 | endef 127 | 128 | .PHONY: all checkdirs flash clean 129 | 130 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 131 | 132 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 133 | $(vecho) "FW $(FW_BASE)/" 134 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 135 | 136 | $(TARGET_OUT): $(APP_AR) 137 | $(vecho) "LD $@" 138 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 139 | 140 | $(APP_AR): $(OBJ) $(NIM_OBJ) 141 | $(vecho) "AR $@" 142 | $(Q) $(AR) cru $@ $^ 143 | 144 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 145 | 146 | $(BUILD_DIR): 147 | $(vecho) "MKDIR $@" 148 | $(Q) mkdir -p $@ 149 | 150 | $(FW_BASE): 151 | $(vecho) "MKDIR $@" 152 | $(Q) mkdir -p $@ 153 | 154 | flash: $(FW_FILE_1) $(FW_FILE_2) 155 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 156 | 157 | clean: 158 | $(vecho) "CLEAN" 159 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 160 | 161 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 162 | $(vecho) "NIM $@" 163 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h -d:nimMinHeapPages=1 $(NIM_SEARCH_PATHS) $< 164 | $(Q) touch $@ 165 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 166 | 167 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 168 | $(vecho) "TOUCH $@" 169 | $(Q) touch $@ 170 | 171 | 172 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 173 | 174 | %.o: %.c 175 | %.o: %.c 176 | $(vecho) "CC $<" 177 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 178 | 179 | $(NIM_CACHE)/stdlib_system.nim.o: CFLAGS:=$(CFLAGS) -D'malloc(size)=os_malloc(size)' -D'free(ptr)=os_free(ptr)' -include stdlib.h -include mem.h 180 | 181 | $(NIM_CACHE)/main.deps.mk: 182 | 183 | ifneq ($(MAKECMDGOALS), clean) 184 | -include $(NIM_CACHE)/nim_built.mk 185 | -include $(NIM_CACHE)/main.deps.mk 186 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 187 | ifneq ($(sdk_version_check),) 188 | $(error $(sdk_version_check)) 189 | endif 190 | endif 191 | -------------------------------------------------------------------------------- /gc-regions/user/main.nim: -------------------------------------------------------------------------------- 1 | import esp8266/nonos-sdk/os_type 2 | import esp8266/nonos-sdk/osapi 3 | import esp8266/nonos-sdk/user_interface 4 | import esp8266/user_fns/default_user_rf_cal_sector_set 5 | import esp8266/user_fns/user_init 6 | import esp8266/user_fns/user_pre_init 7 | 8 | 9 | var 10 | timer: os_timer_t 11 | obstack_reset = obstackPtr() 12 | 13 | proc timer_fn(arg: pointer) {.cdecl.} = 14 | os_printf("Time: " & $system_get_time() & "\n") 15 | os_printf("Mem; occupied:" & $getOccupiedMem() & ", free:" & 16 | $getFreeMem() & ", total:" & $getTotalMem() & "\n") 17 | setObstackPtr(obstack_reset) # Deallocate everything since the last 18 | # `obstack_reset = obstackPtr()` assignment 19 | 20 | 21 | # There are a few other ways to work with the Regions GC, e.g. using: 22 | # * withScratchRegion; or 23 | # * withRegion 24 | # but neither of these work in the current version of Nim (1.0.2). Example 25 | # code of what this would look like if it worked is provided below. 26 | # 27 | # Ideally one could also get rid if the call to `obstackPtr()` in the 28 | # declaration of `obstack_reset` above, but the type returned by `obstackPtr` 29 | # and passed to `setObstackPtr` is not exported (and I don't know of a way 30 | # to declare a variable of a non-exported type other than using assignment). 31 | 32 | 33 | ### withScratchRegion 34 | # 35 | # proc timer_fn(arg: pointer) {.cdecl.} = 36 | # withScratchRegion: 37 | # os_printf("Time: " & $system_get_time() & "\n") 38 | # os_printf("Mem; occupied:" & $getOccupiedMem() & ", free:" & 39 | # $getFreeMem() & ", total:" & $getTotalMem() & "\n") 40 | 41 | 42 | ### withRegion 43 | # 44 | # var timer_region: MemRegion 45 | # 46 | # proc timer_fn(arg: pointer) {.cdecl.} = 47 | # withRegion(timer_region): 48 | # os_printf("Time: " & $system_get_time() & "\n") 49 | # os_printf("Mem; occupied:" & $getOccupiedMem() & ", free:" & 50 | # $getFreeMem() & ", total:" & $getTotalMem() & "\n") 51 | 52 | 53 | ### With exported StackPtr type 54 | # 55 | # var obstack_reset: StackPtr 56 | # 57 | # proc timer_fn(arg: pointer) {.cdecl.} = 58 | # os_printf("Time: " & $system_get_time() & "\n") 59 | # os_printf("Mem; occupied:" & $getOccupiedMem() & ", free:" & 60 | # $getFreeMem() & ", total:" & $getTotalMem() & "\n") 61 | # setObstackPtr(obstack_reset) 62 | 63 | 64 | proc nim_user_init() {.exportc.} = 65 | os_printf("\n\n") 66 | 67 | let dummy = $system_get_time() # Force something to have been allocated 68 | # As setObstackPtr() is broken when nothing 69 | # is allocated by the time obstackPtr is 70 | # called 71 | # This is unnecessary if your program 72 | # happens to make allocations as a 73 | # side-effect of doing something useful 74 | 75 | obstack_reset = obstackPtr() # Anything allocated before this call 76 | # will be preserved even after calling 77 | # setObstackPtr 78 | 79 | os_timer_setfn(addr timer, timer_fn, nil) 80 | os_timer_arm(addr timer, 1000, true) 81 | -------------------------------------------------------------------------------- /gc-regions/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:regions 2 | --define:useMalloc 3 | --deadCodeElim:on 4 | -------------------------------------------------------------------------------- /gc-regions/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /gc-regions/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/gc-regions/user/user_config.h -------------------------------------------------------------------------------- /hello-world-sdk/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Set path related variables to have absolute paths 31 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 32 | override SDK_BASE := $(abspath $(SDK_BASE)) 33 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 34 | 35 | # esptool.py options 36 | ESPPORT ?= /dev/ttyUSB0 37 | ESPTOOL ?= esptool.py 38 | ESPTOOL_BAUD ?= 115200 39 | 40 | # name for the target project 41 | TARGET = app 42 | 43 | # which modules (subdirectories) of the project to include in compiling 44 | MODULES = driver user 45 | EXTRA_INCDIR = include 46 | 47 | # libraries used in this project, mainly provided by the SDK 48 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main 49 | 50 | # compiler flags using during compilation of source files 51 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 52 | 53 | # linker flags used to generate the main object file 54 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 55 | 56 | # linker script used for the above linkier step 57 | LD_SCRIPT ?= eagle.app.v6.ld 58 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 59 | 60 | # various paths from the SDK used in this project 61 | SDK_LIBDIR = lib 62 | SDK_LDDIR = ld 63 | SDK_INCDIR = include include/json 64 | 65 | # nim library path 66 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 67 | 68 | FLASH_SIZE ?= 1MB 69 | # we create two different files for uploading into the flash 70 | # these are the names and options to generate them 71 | FW_FILE_1_ADDR = 0x00000 72 | FW_FILE_2_ADDR = 0x10000 73 | 74 | # select which tools to use as compiler, librarian and linker 75 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 76 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 77 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 78 | 79 | 80 | 81 | #### 82 | #### no user configurable options below here 83 | #### 84 | SRC_DIR := $(MODULES) 85 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 86 | NIM_BUILD_DIR := $(NIM_CACHE) 87 | 88 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 89 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 90 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk) $(NIM_SEARCH_PATHS) 91 | 92 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 93 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 94 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 95 | LIBS := $(addprefix -l,$(LIBS)) 96 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 97 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 98 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 99 | 100 | LD_SCRIPT := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT)) 101 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 102 | 103 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk) 104 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 105 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 106 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 107 | 108 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 109 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 110 | 111 | V ?= $(VERBOSE) 112 | ifeq ("$(V)","1") 113 | Q := 114 | vecho := @true 115 | else 116 | Q := @ 117 | vecho := @echo 118 | endif 119 | 120 | vpath %.c $(SRC_DIR) 121 | 122 | define compile-objects 123 | $1/%.o: %.c 124 | $(vecho) "CC $$<" 125 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 126 | endef 127 | 128 | .PHONY: all checkdirs flash clean 129 | 130 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 131 | 132 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 133 | $(vecho) "FW $(FW_BASE)/" 134 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 135 | 136 | $(TARGET_OUT): $(APP_AR) 137 | $(vecho) "LD $@" 138 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 139 | 140 | $(APP_AR): $(OBJ) $(NIM_OBJ) 141 | $(vecho) "AR $@" 142 | $(Q) $(AR) cru $@ $^ 143 | 144 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 145 | 146 | $(BUILD_DIR): 147 | $(vecho) "MKDIR $@" 148 | $(Q) mkdir -p $@ 149 | 150 | $(FW_BASE): 151 | $(vecho) "MKDIR $@" 152 | $(Q) mkdir -p $@ 153 | 154 | flash: $(FW_FILE_1) $(FW_FILE_2) 155 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 156 | 157 | clean: 158 | $(vecho) "CLEAN" 159 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 160 | 161 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 162 | $(vecho) "NIM $@" 163 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h $(NIM_SEARCH_PATHS) $< 164 | $(Q) touch $@ 165 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 166 | 167 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 168 | $(vecho) "TOUCH $@" 169 | $(Q) touch $@ 170 | 171 | 172 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 173 | 174 | %.o: %.c 175 | %.o: %.c 176 | $(vecho) "CC $<" 177 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 178 | 179 | $(NIM_CACHE)/main.deps.mk: 180 | 181 | ifneq ($(MAKECMDGOALS), clean) 182 | -include $(NIM_CACHE)/nim_built.mk 183 | -include $(NIM_CACHE)/main.deps.mk 184 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 185 | ifneq ($(sdk_version_check),) 186 | $(error $(sdk_version_check)) 187 | endif 188 | endif 189 | -------------------------------------------------------------------------------- /hello-world-sdk/user/main.nim: -------------------------------------------------------------------------------- 1 | import esp8266/nonos-sdk/osapi 2 | import esp8266/user_fns/default_user_rf_cal_sector_set 3 | import esp8266/user_fns/user_init 4 | import esp8266/user_fns/user_pre_init 5 | 6 | 7 | proc nim_user_init() {.exportc.} = 8 | os_printf("\n\nHello world!\n\n") 9 | -------------------------------------------------------------------------------- /hello-world-sdk/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:none 2 | --deadCodeElim:on 3 | -------------------------------------------------------------------------------- /hello-world-sdk/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /hello-world-sdk/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/hello-world-sdk/user/user_config.h -------------------------------------------------------------------------------- /hello-world-sdk/user/user_main.c: -------------------------------------------------------------------------------- 1 | #include "user_interface.h" 2 | 3 | #include "nim_main.h" 4 | 5 | void ICACHE_FLASH_ATTR 6 | user_init() 7 | { 8 | NimMain(); 9 | nim_user_init(); 10 | } 11 | -------------------------------------------------------------------------------- /hello-world/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 SDK package 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | 29 | # Set path related variables to have absolute paths 30 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 31 | override SDK_BASE := $(abspath $(SDK_BASE)) 32 | 33 | # esptool.py options 34 | ESPPORT ?= /dev/ttyUSB0 35 | ESPTOOL ?= esptool.py 36 | ESPTOOL_BAUD ?= 115200 37 | 38 | # name for the target project 39 | TARGET = app 40 | 41 | # which modules (subdirectories) of the project to include in compiling 42 | MODULES = driver user 43 | EXTRA_INCDIR = include 44 | 45 | # libraries used in this project, mainly provided by the SDK 46 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main 47 | 48 | # compiler flags using during compilation of source files 49 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 50 | 51 | # linker flags used to generate the main object file 52 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 53 | 54 | # linker script used for the above linkier step 55 | LD_SCRIPT = eagle.app.v6.ld 56 | 57 | # various paths from the SDK used in this project 58 | SDK_LIBDIR = lib 59 | SDK_LDDIR = ld 60 | SDK_INCDIR = include include/json 61 | 62 | # nim library path 63 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 64 | 65 | FLASH_SIZE ?= 1MB 66 | # we create two different files for uploading into the flash 67 | # these are the names and options to generate them 68 | FW_FILE_1_ADDR = 0x00000 69 | FW_FILE_2_ADDR = 0x10000 70 | 71 | # select which tools to use as compiler, librarian and linker 72 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 73 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 74 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 75 | 76 | 77 | 78 | #### 79 | #### no user configurable options below here 80 | #### 81 | SRC_DIR := $(MODULES) 82 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 83 | NIM_BUILD_DIR := $(NIM_CACHE) 84 | 85 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 86 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 87 | 88 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 89 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 90 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 91 | LIBS := $(addprefix -l,$(LIBS)) 92 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 93 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 94 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 95 | 96 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 97 | 98 | INCDIR := $(addprefix -I,$(SRC_DIR)) 99 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 100 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 101 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 102 | 103 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 104 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 105 | 106 | V ?= $(VERBOSE) 107 | ifeq ("$(V)","1") 108 | Q := 109 | vecho := @true 110 | else 111 | Q := @ 112 | vecho := @echo 113 | endif 114 | 115 | vpath %.c $(SRC_DIR) 116 | 117 | define compile-objects 118 | $1/%.o: %.c 119 | $(vecho) "CC $$<" 120 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 121 | endef 122 | 123 | .PHONY: all checkdirs flash clean 124 | 125 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 126 | 127 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 128 | $(vecho) "FW $(FW_BASE)/" 129 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 130 | 131 | $(TARGET_OUT): $(APP_AR) 132 | $(vecho) "LD $@" 133 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 134 | 135 | $(APP_AR): $(OBJ) $(NIM_OBJ) 136 | $(vecho) "AR $@" 137 | $(Q) $(AR) cru $@ $^ 138 | 139 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 140 | 141 | $(BUILD_DIR): 142 | $(vecho) "MKDIR $@" 143 | $(Q) mkdir -p $@ 144 | 145 | $(FW_BASE): 146 | $(vecho) "MKDIR $@" 147 | $(Q) mkdir -p $@ 148 | 149 | flash: $(FW_FILE_1) $(FW_FILE_2) 150 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 151 | 152 | clean: 153 | $(vecho) "CLEAN" 154 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 155 | 156 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 157 | $(vecho) "NIM $@" 158 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h $< 159 | $(Q) touch $@ 160 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 161 | 162 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 163 | $(vecho) "TOUCH $@" 164 | $(Q) touch $@ 165 | 166 | 167 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 168 | 169 | %.o: %.c 170 | %.o: %.c 171 | $(vecho) "CC $<" 172 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 173 | 174 | user_main.c: $(NIM_CACHE)/nim_main.h 175 | 176 | $(NIM_CACHE)/main.deps.mk: 177 | 178 | ifneq ($(MAKECMDGOALS), clean) 179 | -include $(NIM_CACHE)/nim_built.mk 180 | -include $(NIM_CACHE)/main.deps.mk 181 | endif 182 | -------------------------------------------------------------------------------- /hello-world/user/main.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | 3 | 4 | proc nim_user_init() {.exportc.} = 5 | os_printf("\n\nHello world!\n\n") 6 | -------------------------------------------------------------------------------- /hello-world/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:none 2 | --deadCodeElim:on 3 | -------------------------------------------------------------------------------- /hello-world/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /hello-world/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/hello-world/user/user_config.h -------------------------------------------------------------------------------- /hello-world/user/user_main.c: -------------------------------------------------------------------------------- 1 | #include "c_types.h" 2 | #include "osapi.h" 3 | #include "spi_flash.h" 4 | #include "user_interface.h" 5 | 6 | #include "nim_main.h" 7 | 8 | void ICACHE_FLASH_ATTR 9 | user_init() 10 | { 11 | NimMain(); 12 | nim_user_init(); 13 | } 14 | 15 | // Source: https://github.com/pfalcon/esp-open-sdk/blob/e629109c762b505839cb2a06763f8615447e6e67/user_rf_cal_sector_set.c 16 | // License: https://github.com/pfalcon/esp-open-sdk/tree/e629109c762b505839cb2a06763f8615447e6e67#license 17 | uint32 user_rf_cal_sector_set(void) { 18 | extern char flashchip; 19 | SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4); 20 | uint32_t sec_num = flash->chip_size >> 12; 21 | return sec_num - 5; 22 | } 23 | 24 | #define EAGLE_FLASH_BIN_ADDR (SYSTEM_PARTITION_CUSTOMER_BEGIN + 1) 25 | #define EAGLE_IROM0TEXT_BIN_ADDR (SYSTEM_PARTITION_CUSTOMER_BEGIN + 2) 26 | 27 | #ifndef SPI_FLASH_SIZE_MAP 28 | #define SPI_FLASH_SIZE_MAP 2 29 | #endif 30 | 31 | #if ((SPI_FLASH_SIZE_MAP == 0) || (SPI_FLASH_SIZE_MAP == 1)) 32 | #error "The flash map is not supported" 33 | #elif (SPI_FLASH_SIZE_MAP == 2) 34 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0xfb000 35 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0xfc000 36 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0xfd000 37 | #elif (SPI_FLASH_SIZE_MAP == 3) 38 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x1fb000 39 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x1fc000 40 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x1fd000 41 | #elif (SPI_FLASH_SIZE_MAP == 4) 42 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x3fb000 43 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x3fc000 44 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x3fd000 45 | #elif (SPI_FLASH_SIZE_MAP == 5) 46 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x1fb000 47 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x1fc000 48 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x1fd000 49 | #elif (SPI_FLASH_SIZE_MAP == 6) 50 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x3fb000 51 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x3fc000 52 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x3fd000 53 | #else 54 | #error "The flash map is not supported" 55 | #endif 56 | 57 | static const partition_item_t partition_table[] = { 58 | { EAGLE_FLASH_BIN_ADDR, 0x00000, 0x10000}, 59 | { EAGLE_IROM0TEXT_BIN_ADDR, 0x10000, 0x60000}, 60 | { SYSTEM_PARTITION_RF_CAL, SYSTEM_PARTITION_RF_CAL_ADDR, 0x1000}, 61 | { SYSTEM_PARTITION_PHY_DATA, SYSTEM_PARTITION_PHY_DATA_ADDR, 0x1000}, 62 | { SYSTEM_PARTITION_SYSTEM_PARAMETER, SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR, 0x3000}, 63 | }; 64 | 65 | void ICACHE_FLASH_ATTR user_pre_init(void) 66 | { 67 | if(!system_partition_table_regist(partition_table, sizeof(partition_table)/sizeof(partition_table[0]), SPI_FLASH_SIZE_MAP)) { 68 | os_printf("system_partition_table_regist fail\r\n"); 69 | while(1); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /mqtt-blinky/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Override MQTT_LIB to use a custom compiled libmqtt 31 | MQTT_INC ?= $(NIM_SDK_BASE)/../libs/esp8266/mqtt 32 | MQTT_LIB ?= $(NIM_SDK_BASE)/../libs/esp8266/mqtt 33 | 34 | # Set path related variables to have absolute paths 35 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 36 | override SDK_BASE := $(abspath $(SDK_BASE)) 37 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 38 | 39 | # esptool.py options 40 | ESPPORT ?= /dev/ttyUSB0 41 | ESPTOOL ?= esptool.py 42 | ESPTOOL_BAUD ?= 115200 43 | 44 | # name for the target project 45 | TARGET = app 46 | 47 | # which modules (subdirectories) of the project to include in compiling 48 | MODULES = driver user 49 | EXTRA_INCDIR = include 50 | 51 | # libraries used in this project, mainly provided by the SDK 52 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main mqtt 53 | 54 | # compiler flags using during compilation of source files 55 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 56 | 57 | # linker flags used to generate the main object file 58 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 59 | 60 | # linker script used for the above linkier step 61 | LD_SCRIPT ?= eagle.app.v6.ld 62 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 63 | 64 | # various paths from the SDK used in this project 65 | SDK_LIBDIR = lib 66 | SDK_LDDIR = ld 67 | SDK_INCDIR = include include/json 68 | 69 | # nim library path 70 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 71 | 72 | LIB_DIRS = $(addprefix -L,$(MQTT_LIB)) 73 | 74 | FLASH_SIZE ?= 1MB 75 | # we create two different files for uploading into the flash 76 | # these are the names and options to generate them 77 | FW_FILE_1_ADDR = 0x00000 78 | FW_FILE_2_ADDR = 0x10000 79 | USER_DATA_ADDR = 0x70000 80 | 81 | # select which tools to use as compiler, librarian and linker 82 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 83 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 84 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 85 | 86 | 87 | 88 | #### 89 | #### no user configurable options below here 90 | #### 91 | SRC_DIR := $(MODULES) 92 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 93 | NIM_BUILD_DIR := $(NIM_CACHE) 94 | 95 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 96 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 97 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk $(NIM_SDK_BASE)/../libs) $(NIM_SEARCH_PATHS) 98 | 99 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 100 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 101 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 102 | LIBS := $(addprefix -l,$(LIBS)) 103 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 104 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 105 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 106 | 107 | LD_SCRIPT := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT)) 108 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 109 | 110 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk $(MQTT_INC)) 111 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 112 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 113 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 114 | 115 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 116 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 117 | 118 | V ?= $(VERBOSE) 119 | ifeq ("$(V)","1") 120 | Q := 121 | vecho := @true 122 | else 123 | Q := @ 124 | vecho := @echo 125 | endif 126 | 127 | vpath %.c $(SRC_DIR) 128 | 129 | define compile-objects 130 | $1/%.o: %.c 131 | $(vecho) "CC $$<" 132 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 133 | endef 134 | 135 | .PHONY: all checkdirs flash flash-data gen-data clean 136 | 137 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 138 | 139 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 140 | $(vecho) "FW $(FW_BASE)/" 141 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 142 | 143 | $(TARGET_OUT): $(APP_AR) 144 | $(vecho) "LD $@" 145 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LIB_DIRS) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 146 | 147 | $(APP_AR): $(OBJ) $(NIM_OBJ) 148 | $(vecho) "AR $@" 149 | $(Q) $(AR) cru $@ $^ 150 | 151 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 152 | 153 | $(BUILD_DIR): 154 | $(vecho) "MKDIR $@" 155 | $(Q) mkdir -p $@ 156 | 157 | $(FW_BASE): 158 | $(vecho) "MKDIR $@" 159 | $(Q) mkdir -p $@ 160 | 161 | flash: $(FW_FILE_1) $(FW_FILE_2) 162 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 163 | 164 | gen-data: 165 | $(vecho) "NIM RUN $@" 166 | nim c -r $(NIM_SEARCH_PATHS) user/user_data.nim 167 | 168 | flash-data: 169 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(USER_DATA_ADDR) user_data.bin 170 | 171 | $(FW_BASE)/user_data.py: user_data.py 172 | $(vecho) "CP $@" 173 | $(Q) cp $< $@ 174 | 175 | clean: 176 | $(vecho) "CLEAN" 177 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 178 | 179 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 180 | $(vecho) "NIM $@" 181 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h -d:nimMinHeapPages=1 $(NIM_SEARCH_PATHS) $< 182 | $(Q) touch $@ 183 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 184 | 185 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 186 | $(vecho) "TOUCH $@" 187 | $(Q) touch $@ 188 | 189 | 190 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 191 | 192 | %.o: %.c 193 | %.o: %.c 194 | $(vecho) "CC $<" 195 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 196 | 197 | $(NIM_CACHE)/stdlib_system.nim.o: CFLAGS:=$(CFLAGS) -D'malloc(size)=os_malloc(size)' -D'free(ptr)=os_free(ptr)' -include stdlib.h -include mem.h 198 | 199 | $(NIM_CACHE)/main.deps.mk: 200 | 201 | ifneq ($(MAKECMDGOALS), clean) 202 | -include $(NIM_CACHE)/nim_built.mk 203 | -include $(NIM_CACHE)/main.deps.mk 204 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 205 | ifneq ($(sdk_version_check),) 206 | $(error $(sdk_version_check)) 207 | endif 208 | endif 209 | -------------------------------------------------------------------------------- /mqtt-blinky/README.md: -------------------------------------------------------------------------------- 1 | # MQTT Blinky 2 | 3 | An MQTT controlled firmware that blinks an LED! 4 | 5 | The code in this example builds on the following other examples: 6 | 7 | * blinkly-lib 8 | 9 | * gc-regions 10 | 11 | ## Building 12 | 13 | A number of Makefile variables can be used to configure the application. Defaults will be used if nothing is specified, but then the firmware will not be able to connect to WiFi or an MQTT server. 14 | 15 | Variables: 16 | 17 | - `WIFI_SSID` 18 | 19 | - `WIFI_PASSWD` 20 | 21 | - `MQTT_BROKER_IP` 22 | 23 | - `MQTT_BROKER_PORT` 24 | 25 | - `MQTT_USER` 26 | 27 | - `MQTT_PASSWD` 28 | 29 | The WiFi password can be left blank if for open networks. The MQTT broker port can be left blank if using the default port of 1883. The MQTT user name and password can be left blank if no user name and password is required to connect to the MQTT server. 30 | 31 | To compile and upload the firmware: 32 | 33 | ``` 34 | $ make WIFI_SSID=blinky MQTT_BROKER_IP=192.168.1.10 flash 35 | ``` 36 | 37 | These can also be set as environment variables to avoid having to remember to pass them on every `make` invocation. 38 | 39 | ## MQTT 40 | 41 | ### Controlling 42 | 43 | The firmware will connect to the configured MQTT server and listen on the following topics: 44 | 45 | 1. `blinky` 46 | 47 | 2. `blinky/` 48 | 49 | to which `on`, `off`, or `blink` can be sent. The first topic will control all connected mqtt-blinky devices, where as the second will control a specific device addressed by its WiFi MAC address. 50 | 51 | ### Status 52 | 53 | In case you can't see it, the current status of the LED of an mqtt-blinky device is published to: 54 | 55 | * `blinky//sate` 56 | 57 | as either `on` or `off`. 58 | 59 | ### Example 60 | 61 | You should be able to use any MQTT server to control the blinky, this example shows how to control it using [Mosquitto](https://mosquitto.org). 62 | 63 | #### Installing Mosquitto 64 | 65 | On Mac OS X: 66 | 67 | ``` 68 | $ brew cask install mosquitto 69 | ``` 70 | 71 | Debian: 72 | 73 | ``` 74 | $ apt install mosquitto mosquitto-clients 75 | ``` 76 | 77 | #### Running a Mosquitto Server 78 | 79 | Using the default port 1883: 80 | 81 | ``` 82 | OS X: $ /usr/local/sbin/mosquitto 83 | Linux: $ /usr/sbin/mosquitto 84 | ``` 85 | 86 | Using a custom port if, for example, another application is already using port 1883: 87 | 88 | ``` 89 | OS X: $ /usr/local/sbin/mosquitto -p PORT 90 | Linux: $ /usr/sbin/mosquitto -p PORT 91 | ``` 92 | 93 | #### Controlling the Blinky 94 | 95 | Sending an on message on the default MQTT port: 96 | 97 | ```shell 98 | $ mosquitto_pub -t blinky -m on 99 | ``` 100 | 101 | Sending a message on a custom port: 102 | 103 | ``` 104 | $ mosquitto_pub -p PORT -t blinky -m on 105 | ``` 106 | 107 | Tell a specific blinky (with MAC address: 0xD1CEDCO1DICE) to start blinking: 108 | 109 | ``` 110 | $ mosquitto_pub -t blinky/D1CEDCO1DICE -m blink 111 | ``` 112 | 113 | #### Observing the State 114 | 115 | Listen to all topics on the default MQTT port: 116 | 117 | ``` 118 | $ mosquitto_sub -v -t "#" 119 | ``` 120 | 121 | Listen to all topics on a custom port: 122 | 123 | ``` 124 | mosquitto_sub -p PORT -v -t "#" 125 | ``` 126 | 127 | Listen to a specific blinky's (with MAC address: 0xD1CEDCO1DICE) state topic: 128 | 129 | ``` 130 | mosquitto_sub -t blinky/D1CEDCO1DICE/state 131 | ``` 132 | -------------------------------------------------------------------------------- /mqtt-blinky/config.sh: -------------------------------------------------------------------------------- 1 | export WIFI_SSID="\\\\o/" 2 | export WIFI_PASSWD="p@p@rla143" 3 | export MQTT_BROKER_IP="192.168.2.197" 4 | #export WIFI_SSID="Stendaler_2OG" 5 | #export WIFI_PASSWD="raumstar-2OG" 6 | #export MQTT_BROKER_IP="192.168.176.55" 7 | export MQTT_BROKER_PORT="2883" 8 | export ESPTOOL_BAUD="460800" 9 | -------------------------------------------------------------------------------- /mqtt-blinky/user/main.nim: -------------------------------------------------------------------------------- 1 | import strutils 2 | 3 | import esp8266/mqtt 4 | import esp8266/nonos-sdk/eagle_soc 5 | import esp8266/nonos-sdk/gpio 6 | import esp8266/nonos-sdk/os_type 7 | import esp8266/nonos-sdk/osapi 8 | import esp8266/nonos-sdk/spi_flash 9 | import esp8266/nonos-sdk/user_interface 10 | import esp8266/pins 11 | import esp8266/types 12 | import esp8266/user_fns/default_user_rf_cal_sector_set 13 | import esp8266/user_fns/user_init 14 | import esp8266/user_fns/user_pre_init 15 | 16 | import user_data 17 | 18 | 19 | const 20 | pin = 2 21 | states = ["off", "on"] 22 | 23 | 24 | var 25 | data: Data 26 | wifi_config: station_config 27 | mqtt_client: MQTT_Client 28 | led_timer: os_timer_t 29 | state_topic: string 30 | ctrl_topic: string 31 | 32 | 33 | proc mac_address(): string = 34 | var 35 | mac: array[6, uint8] 36 | discard wifi_get_macaddr(0, cast[ptr uint8](addr mac)) 37 | for i in 0..", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /mqtt-blinky/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/mqtt-blinky/user/user_config.h -------------------------------------------------------------------------------- /mqtt-blinky/user/user_data.nim: -------------------------------------------------------------------------------- 1 | import esp8266/crc 2 | import esp8266/types 3 | 4 | 5 | const 6 | magic = 0x0A0CDCBA'u32 7 | app = "mqbl" 8 | 9 | 10 | type 11 | WiFiSsid* = array[32, uint8] 12 | WiFiPassword* = array[64, uint8] 13 | WiFiCreds* {.packed.} = object 14 | ssid*: WiFiSsid 15 | password*: WiFiPassword 16 | Mqtt* {.packed.} = object 17 | ip*: array[4, uint8] 18 | port*: uint16 19 | username* {.align(4).}: array[64, uint8] 20 | password* {.align(4).}: array[64, uint8] 21 | Settings* {.packed.} = object 22 | magic*: uint32 23 | app: array[4, uint8] 24 | wifi*: WifiCreds 25 | mqtt*: Mqtt 26 | Data* {.packed.} = object 27 | settings*: Settings 28 | crc32*: uint32 29 | 30 | 31 | proc verify*(data: var Data): (bool, string) = 32 | if data.settings.magic != magic: 33 | return (false, "wrong magic") 34 | if data.settings.app != app.toArray(4, uint8): 35 | return (false, "wrong app") 36 | let crc = crc32(data.settings) 37 | if data.crc32 != crc: 38 | return (false, "bad crc") 39 | return (true, "") 40 | 41 | 42 | when isMainModule: 43 | import endians 44 | import net 45 | import parseopt 46 | import streams 47 | import strutils 48 | 49 | import esp8266/types 50 | 51 | var 52 | data: Data 53 | ssid: string 54 | wifiPassword: string 55 | mqttUsername: string 56 | mqttPassword: string 57 | host: string 58 | dest = "user_data.bin" 59 | optParser = initOptParser() 60 | 61 | while true: 62 | optParser.next() 63 | case optParser.kind 64 | of cmdEnd: break 65 | of cmdShortOption, cmdLongOption: 66 | case optParser.key: 67 | of "ssid", "s": 68 | ssid = optParser.val 69 | of "password", "passwd", "pass", "p": 70 | wifiPassword = optParser.val 71 | of "host": 72 | host = optParser.val 73 | of "mqtt-username": 74 | mqttUsername = optParser.val 75 | of "mqtt-password": 76 | mqttPassword = optParser.val 77 | else: 78 | echo("Unknown option: ", optParser.key) 79 | quit(QuitFailure) 80 | if optParser.val == "": 81 | echo("Option: ", optParser.key, " takes one argument") 82 | quit(QuitFailure) 83 | of cmdArgument: 84 | dest = optParser.key 85 | 86 | if ssid == "": 87 | stdout.write("SSID: ") 88 | ssid = readLine(stdin) 89 | if wifiPassword == "": 90 | stdout.write("WiFi Password: ") 91 | wifiPassword = readLine(stdin) 92 | if host == "": 93 | let default_host = $getPrimaryIPAddr() & ":1883" 94 | stdout.write("Using the format: IPv4:PORT\n") 95 | stdout.write("Leave blank for: " & default_host & "\n") 96 | stdout.write("Host: ") 97 | host = readLine(stdin) 98 | if host == "": 99 | host = default_host 100 | if mqttUsername == "": 101 | stdout.write("MQTT Username (blank for none): ") 102 | mqttUsername = readLine(stdin) 103 | if mqttPassword == "": 104 | stdout.write("MQTT Password (blank for none): ") 105 | mqttPassword = readLine(stdin) 106 | 107 | var parts = host.split(':', 1) 108 | let ip = parseIpAddress(parts[0]) 109 | let port = parts[1].parseUInt() 110 | 111 | data.settings.magic = magic 112 | data.settings.app.setString(app) 113 | data.settings.wifi.ssid.setString(ssid) 114 | data.settings.wifi.password.setString(wifiPassword) 115 | data.settings.mqtt.ip = ip.address_v4 116 | data.settings.mqtt.port = uint16(port) 117 | data.settings.mqtt.username.setString(mqttUsername) 118 | data.settings.mqtt.password.setString(mqttPassword) 119 | data.crc32 = crc32(data.settings) 120 | 121 | littleEndian32(addr data.settings.magic, addr data.settings.magic) 122 | littleEndian32(addr data.settings.mqtt.port, addr data.settings.mqtt.port) 123 | littleEndian32(addr data.crc32, addr data.crc32) 124 | 125 | let padding = '\xff'.repeat(4096 - sizeof(data)) 126 | 127 | let fp = open(dest, fmWrite) 128 | discard fp.writeBuffer(addr data, sizeof(data)) 129 | fp.write(padding) 130 | fp.close() 131 | -------------------------------------------------------------------------------- /mqtt-blinky/user_data.py: -------------------------------------------------------------------------------- 1 | # A cross platform Python script to generate a user_data.bin file 2 | # for the FOTA example. 3 | import binascii 4 | import struct 5 | import sys 6 | import socket 7 | 8 | try: 9 | input = raw_input 10 | except NameError: 11 | pass 12 | 13 | 14 | def get_primary_ip(): 15 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 16 | try: 17 | s.connect(('10.255.255.255', 1)) # doesn't have to be reachable 18 | ip = s.getsockname()[0] 19 | except Exception: 20 | ip = '127.0.0.1' 21 | finally: 22 | s.close() 23 | return ip 24 | 25 | 26 | default_host = get_primary_ip() + ':1883' 27 | 28 | magic = 0x0a0cdcba 29 | app = 'mqbl' 30 | ssid = input('SSID: ').encode('ascii') 31 | password = input('Password: ').encode('ascii') 32 | print('Using the format: IPv4:PORT') 33 | print('Leave blank for: ' + default_host) 34 | host = input('Host: ') 35 | if not host: 36 | host = default_host 37 | mqtt_username = input('MQTT Username (leave blank for none): ').encode('ascii') 38 | mqtt_password = input('MQTT Password (leave blank for none): ').encode('ascii') 39 | 40 | 41 | ip, port = host.split(':', 1) 42 | ip = socket.inet_aton(ip) 43 | port = int(port) 44 | 45 | 46 | filename = sys.argv[1] if len(sys.argv) > 1 else '0x70000.bin' 47 | with open(filename, 'wb') as fp: 48 | settings = struct.pack('&1 | grep '/lib$$' | head -n 1) 64 | 65 | FLASH_SIZE ?= 1MB 66 | # we create two different files for uploading into the flash 67 | # these are the names and options to generate them 68 | FW_FILE_1_ADDR = 0x00000 69 | FW_FILE_2_ADDR = 0x10000 70 | 71 | # select which tools to use as compiler, librarian and linker 72 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 73 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 74 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 75 | 76 | 77 | 78 | #### 79 | #### no user configurable options below here 80 | #### 81 | SRC_DIR := $(MODULES) 82 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 83 | NIM_BUILD_DIR := $(NIM_CACHE) 84 | 85 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 86 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 87 | 88 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 89 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 90 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 91 | LIBS := $(addprefix -l,$(LIBS)) 92 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 93 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 94 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 95 | 96 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 97 | 98 | INCDIR := $(addprefix -I,$(SRC_DIR)) 99 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 100 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 101 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 102 | 103 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 104 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 105 | 106 | V ?= $(VERBOSE) 107 | ifeq ("$(V)","1") 108 | Q := 109 | vecho := @true 110 | else 111 | Q := @ 112 | vecho := @echo 113 | endif 114 | 115 | vpath %.c $(SRC_DIR) 116 | 117 | define compile-objects 118 | $1/%.o: %.c 119 | $(vecho) "CC $$<" 120 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 121 | endef 122 | 123 | .PHONY: all checkdirs flash clean 124 | 125 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 126 | 127 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 128 | $(vecho) "FW $(FW_BASE)/" 129 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 130 | 131 | $(TARGET_OUT): $(APP_AR) 132 | $(vecho) "LD $@" 133 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 134 | 135 | $(APP_AR): $(OBJ) $(NIM_OBJ) 136 | $(vecho) "AR $@" 137 | $(Q) $(AR) cru $@ $^ 138 | 139 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 140 | 141 | $(BUILD_DIR): 142 | $(vecho) "MKDIR $@" 143 | $(Q) mkdir -p $@ 144 | 145 | $(FW_BASE): 146 | $(vecho) "MKDIR $@" 147 | $(Q) mkdir -p $@ 148 | 149 | flash: $(FW_FILE_1) $(FW_FILE_2) 150 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 151 | 152 | clean: 153 | $(vecho) "CLEAN" 154 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 155 | 156 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 157 | $(vecho) "NIM $@" 158 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h $< 159 | $(Q) touch $@ 160 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 161 | 162 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 163 | $(vecho) "TOUCH $@" 164 | $(Q) touch $@ 165 | 166 | 167 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 168 | 169 | %.o: %.c 170 | %.o: %.c 171 | $(vecho) "CC $<" 172 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 173 | 174 | user_main.c: $(NIM_CACHE)/nim_main.h 175 | 176 | $(NIM_CACHE)/main.deps.mk: 177 | 178 | ifneq ($(MAKECMDGOALS), clean) 179 | -include $(NIM_CACHE)/nim_built.mk 180 | -include $(NIM_CACHE)/main.deps.mk 181 | endif 182 | -------------------------------------------------------------------------------- /panic/user/main.nim: -------------------------------------------------------------------------------- 1 | var 2 | v: int8 3 | 4 | 5 | proc nim_user_init() {.exportc.} = 6 | v = high(int8) 7 | inc v 8 | -------------------------------------------------------------------------------- /panic/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:none 2 | --deadCodeElim:on 3 | -------------------------------------------------------------------------------- /panic/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /panic/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/panic/user/user_config.h -------------------------------------------------------------------------------- /panic/user/user_main.c: -------------------------------------------------------------------------------- 1 | #include "c_types.h" 2 | #include "osapi.h" 3 | #include "spi_flash.h" 4 | #include "user_interface.h" 5 | 6 | #include "nim_main.h" 7 | 8 | void ICACHE_FLASH_ATTR 9 | user_init() 10 | { 11 | NimMain(); 12 | nim_user_init(); 13 | } 14 | 15 | // Source: https://github.com/pfalcon/esp-open-sdk/blob/e629109c762b505839cb2a06763f8615447e6e67/user_rf_cal_sector_set.c 16 | // License: https://github.com/pfalcon/esp-open-sdk/tree/e629109c762b505839cb2a06763f8615447e6e67#license 17 | uint32 user_rf_cal_sector_set(void) { 18 | extern char flashchip; 19 | SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4); 20 | uint32_t sec_num = flash->chip_size >> 12; 21 | return sec_num - 5; 22 | } 23 | 24 | #define EAGLE_FLASH_BIN_ADDR (SYSTEM_PARTITION_CUSTOMER_BEGIN + 1) 25 | #define EAGLE_IROM0TEXT_BIN_ADDR (SYSTEM_PARTITION_CUSTOMER_BEGIN + 2) 26 | 27 | #ifndef SPI_FLASH_SIZE_MAP 28 | #define SPI_FLASH_SIZE_MAP 4 29 | #endif 30 | 31 | #if ((SPI_FLASH_SIZE_MAP == 0) || (SPI_FLASH_SIZE_MAP == 1)) 32 | #error "The flash map is not supported" 33 | #elif (SPI_FLASH_SIZE_MAP == 2) 34 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0xfb000 35 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0xfc000 36 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0xfd000 37 | #elif (SPI_FLASH_SIZE_MAP == 3) 38 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x1fb000 39 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x1fc000 40 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x1fd000 41 | #elif (SPI_FLASH_SIZE_MAP == 4) 42 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x3fb000 43 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x3fc000 44 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x3fd000 45 | #elif (SPI_FLASH_SIZE_MAP == 5) 46 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x1fb000 47 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x1fc000 48 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x1fd000 49 | #elif (SPI_FLASH_SIZE_MAP == 6) 50 | #define SYSTEM_PARTITION_RF_CAL_ADDR 0x3fb000 51 | #define SYSTEM_PARTITION_PHY_DATA_ADDR 0x3fc000 52 | #define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR 0x3fd000 53 | #else 54 | #error "The flash map is not supported" 55 | #endif 56 | 57 | static const partition_item_t partition_table[] = { 58 | { EAGLE_FLASH_BIN_ADDR, 0x00000, 0x10000}, 59 | { EAGLE_IROM0TEXT_BIN_ADDR, 0x10000, 0x60000}, 60 | { SYSTEM_PARTITION_RF_CAL, SYSTEM_PARTITION_RF_CAL_ADDR, 0x1000}, 61 | { SYSTEM_PARTITION_PHY_DATA, SYSTEM_PARTITION_PHY_DATA_ADDR, 0x1000}, 62 | { SYSTEM_PARTITION_SYSTEM_PARAMETER, SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR, 0x3000}, 63 | }; 64 | 65 | void ICACHE_FLASH_ATTR user_pre_init(void) 66 | { 67 | if(!system_partition_table_regist(partition_table, sizeof(partition_table)/sizeof(partition_table[0]), SPI_FLASH_SIZE_MAP)) { 68 | os_printf("system_partition_table_regist fail\r\n"); 69 | while(1); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /read-flash/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Set path related variables to have absolute paths 31 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 32 | override SDK_BASE := $(abspath $(SDK_BASE)) 33 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 34 | 35 | # esptool.py options 36 | ESPPORT ?= /dev/ttyUSB0 37 | ESPTOOL ?= esptool.py 38 | ESPTOOL_BAUD ?= 115200 39 | 40 | # name for the target project 41 | TARGET = app 42 | 43 | # which modules (subdirectories) of the project to include in compiling 44 | MODULES = driver user 45 | EXTRA_INCDIR = include 46 | 47 | # libraries used in this project, mainly provided by the SDK 48 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main 49 | 50 | # compiler flags using during compilation of source files 51 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 52 | 53 | # linker flags used to generate the main object file 54 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 55 | 56 | # linker script used for the above linkier step 57 | LD_SCRIPT ?= eagle.app.v6.ld 58 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 59 | 60 | # various paths from the SDK used in this project 61 | SDK_LIBDIR = lib 62 | SDK_LDDIR = ld 63 | SDK_INCDIR = include include/json 64 | 65 | # nim library path 66 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 67 | 68 | FLASH_SIZE ?= 1MB 69 | # we create two different files for uploading into the flash 70 | # these are the names and options to generate them 71 | FW_FILE_1_ADDR = 0x00000 72 | FW_FILE_2_ADDR = 0x10000 73 | USER_DATA_ADDR = 0x70000 74 | 75 | BLANK_BIN ?= $(SDK_BASE)/bin/blank.bin 76 | 77 | # select which tools to use as compiler, librarian and linker 78 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 79 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 80 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 81 | 82 | 83 | 84 | #### 85 | #### no user configurable options below here 86 | #### 87 | SRC_DIR := $(MODULES) 88 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 89 | NIM_BUILD_DIR := $(NIM_CACHE) 90 | 91 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 92 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 93 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk) $(NIM_SEARCH_PATHS) 94 | 95 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 96 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 97 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 98 | LIBS := $(addprefix -l,$(LIBS)) 99 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 100 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 101 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 102 | 103 | LD_SCRIPT := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT)) 104 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 105 | 106 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk) 107 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 108 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 109 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 110 | 111 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 112 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 113 | 114 | V ?= $(VERBOSE) 115 | ifeq ("$(V)","1") 116 | Q := 117 | vecho := @true 118 | else 119 | Q := @ 120 | vecho := @echo 121 | endif 122 | 123 | vpath %.c $(SRC_DIR) 124 | 125 | define compile-objects 126 | $1/%.o: %.c 127 | $(vecho) "CC $$<" 128 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 129 | endef 130 | 131 | .PHONY: all checkdirs flash flash-data clean 132 | 133 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 134 | 135 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 136 | $(vecho) "FW $(FW_BASE)/" 137 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 138 | 139 | $(TARGET_OUT): $(APP_AR) 140 | $(vecho) "LD $@" 141 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 142 | 143 | $(APP_AR): $(OBJ) $(NIM_OBJ) 144 | $(vecho) "AR $@" 145 | $(Q) $(AR) cru $@ $^ 146 | 147 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 148 | 149 | $(BUILD_DIR): 150 | $(vecho) "MKDIR $@" 151 | $(Q) mkdir -p $@ 152 | 153 | $(FW_BASE): 154 | $(vecho) "MKDIR $@" 155 | $(Q) mkdir -p $@ 156 | 157 | flash: $(FW_FILE_1) $(FW_FILE_2) 158 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 0x00070000 $(BLANK_BIN) 159 | 160 | flash-data: 161 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(USER_DATA_ADDR) data.bin 162 | 163 | clean: 164 | $(vecho) "CLEAN" 165 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 166 | 167 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 168 | $(vecho) "NIM $@" 169 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h -d:nimMinHeapPages=1 $(NIM_SEARCH_PATHS) $< 170 | $(Q) touch $@ 171 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 172 | 173 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 174 | $(vecho) "TOUCH $@" 175 | $(Q) touch $@ 176 | 177 | 178 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 179 | 180 | %.o: %.c 181 | %.o: %.c 182 | $(vecho) "CC $<" 183 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 184 | 185 | $(NIM_CACHE)/stdlib_system.nim.o: CFLAGS:=$(CFLAGS) -D'realloc(ptr, size)=os_realloc(ptr, size)' -D'calloc(count, size)=os_calloc(count, size)' -D'malloc(size)=os_malloc(size)' -D'free(ptr)=os_free(ptr)' -include stdlib.h -include mem.h 186 | 187 | $(NIM_CACHE)/main.deps.mk: 188 | 189 | ifneq ($(MAKECMDGOALS), clean) 190 | -include $(NIM_CACHE)/nim_built.mk 191 | -include $(NIM_CACHE)/main.deps.mk 192 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 193 | ifneq ($(sdk_version_check),) 194 | $(error $(sdk_version_check)) 195 | endif 196 | endif 197 | -------------------------------------------------------------------------------- /read-flash/Makefile.orig: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Set path related variables to have absolute paths 31 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 32 | override SDK_BASE := $(abspath $(SDK_BASE)) 33 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 34 | 35 | # esptool.py options 36 | ESPPORT ?= /dev/ttyUSB0 37 | ESPTOOL ?= esptool.py 38 | ESPTOOL_BAUD ?= 115200 39 | 40 | # name for the target project 41 | TARGET = app 42 | 43 | # which modules (subdirectories) of the project to include in compiling 44 | MODULES = driver user 45 | EXTRA_INCDIR = include 46 | 47 | # libraries used in this project, mainly provided by the SDK 48 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main 49 | 50 | # compiler flags using during compilation of source files 51 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 52 | 53 | # linker flags used to generate the main object file 54 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 55 | 56 | # linker script used for the above linkier step 57 | LD_SCRIPT ?= eagle.app.v6.ld 58 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 59 | 60 | # various paths from the SDK used in this project 61 | SDK_LIBDIR = lib 62 | SDK_LDDIR = ld 63 | SDK_INCDIR = include include/json 64 | 65 | # nim library path 66 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 67 | 68 | # we create two different files for uploading into the flash 69 | # these are the names and options to generate them 70 | FW_FILE_1_ADDR = 0x00000 71 | FW_FILE_2_ADDR = 0x10000 72 | USER_DATA_ADDR = 0x70000 73 | 74 | BLANK_BIN ?= $(SDK_BASE)/bin/blank.bin 75 | 76 | # select which tools to use as compiler, librarian and linker 77 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 78 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 79 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 80 | 81 | 82 | 83 | #### 84 | #### no user configurable options below here 85 | #### 86 | SRC_DIR := $(MODULES) 87 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 88 | NIM_BUILD_DIR := $(NIM_CACHE) 89 | 90 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 91 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 92 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk) $(NIM_SEARCH_PATHS) 93 | 94 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 95 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 96 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 97 | LIBS := $(addprefix -l,$(LIBS)) 98 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 99 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 100 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 101 | 102 | LD_SCRIPT := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT)) 103 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 104 | 105 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk) 106 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 107 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 108 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 109 | 110 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 111 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 112 | 113 | V ?= $(VERBOSE) 114 | ifeq ("$(V)","1") 115 | Q := 116 | vecho := @true 117 | else 118 | Q := @ 119 | vecho := @echo 120 | endif 121 | 122 | vpath %.c $(SRC_DIR) 123 | 124 | define compile-objects 125 | $1/%.o: %.c 126 | $(vecho) "CC $$<" 127 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 128 | endef 129 | 130 | .PHONY: all checkdirs flash flash-data clean 131 | 132 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 133 | 134 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 135 | $(vecho) "FW $(FW_BASE)/" 136 | $(Q) $(ESPTOOL) elf2image -o $(FW_BASE)/ $(TARGET_OUT) 137 | 138 | $(TARGET_OUT): $(APP_AR) 139 | $(vecho) "LD $@" 140 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 141 | 142 | $(APP_AR): $(OBJ) $(NIM_OBJ) 143 | $(vecho) "AR $@" 144 | $(Q) $(AR) cru $@ $^ 145 | 146 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 147 | 148 | $(BUILD_DIR): 149 | $(vecho) "MKDIR $@" 150 | $(Q) mkdir -p $@ 151 | 152 | $(FW_BASE): 153 | $(vecho) "MKDIR $@" 154 | $(Q) mkdir -p $@ 155 | 156 | flash: $(FW_FILE_1) $(FW_FILE_2) 157 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 0x00070000 $(BLANK_BIN) 158 | 159 | flash-data: 160 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash $(USER_DATA_ADDR) data.bin 161 | 162 | clean: 163 | $(vecho) "CLEAN" 164 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 165 | 166 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 167 | $(vecho) "NIM $@" 168 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h -d:nimMinHeapPages=1 $(NIM_SEARCH_PATHS) $< 169 | $(Q) touch $@ 170 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 171 | 172 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 173 | $(vecho) "TOUCH $@" 174 | $(Q) touch $@ 175 | 176 | 177 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 178 | 179 | %.o: %.c 180 | %.o: %.c 181 | $(vecho) "CC $<" 182 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 183 | 184 | $(NIM_CACHE)/stdlib_system.nim.o: CFLAGS:=$(CFLAGS) -D'realloc(ptr, size)=os_realloc(ptr, size)' -D'calloc(count, size)=os_calloc(count, size)' -D'malloc(size)=os_malloc(size)' -D'free(ptr)=os_free(ptr)' -include stdlib.h -include mem.h 185 | 186 | $(NIM_CACHE)/main.deps.mk: 187 | 188 | ifneq ($(MAKECMDGOALS), clean) 189 | -include $(NIM_CACHE)/nim_built.mk 190 | -include $(NIM_CACHE)/main.deps.mk 191 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 192 | ifneq ($(sdk_version_check),) 193 | $(error $(sdk_version_check)) 194 | endif 195 | endif 196 | -------------------------------------------------------------------------------- /read-flash/Makefile.rej: -------------------------------------------------------------------------------- 1 | *************** 2 | *** 154,160 **** 3 | $(Q) mkdir -p $@ 4 | 5 | flash: $(FW_FILE_1) $(FW_FILE_2) 6 | - $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 7 | 8 | clean: 9 | $(vecho) "CLEAN" 10 | --- 155,161 ---- 11 | $(Q) mkdir -p $@ 12 | 13 | flash: $(FW_FILE_1) $(FW_FILE_2) 14 | + $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 15 | 16 | clean: 17 | $(vecho) "CLEAN" 18 | -------------------------------------------------------------------------------- /read-flash/data.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/read-flash/data.bin -------------------------------------------------------------------------------- /read-flash/user/main.nim: -------------------------------------------------------------------------------- 1 | import esp8266/nonos-sdk/os_type 2 | import esp8266/nonos-sdk/osapi 3 | import esp8266/nonos-sdk/spi_flash 4 | import esp8266/nonos-sdk/user_interface 5 | import esp8266/user_fns/default_user_rf_cal_sector_set 6 | import esp8266/user_fns/user_init 7 | import esp8266/user_fns/user_pre_init 8 | 9 | 10 | proc nim_user_init() {.exportc.} = 11 | var 12 | part_info: partition_item_t 13 | data: array[256, byte] 14 | 15 | block: 16 | let result = system_partition_get_item(partition_type_t(103), addr part_info) 17 | if not result: 18 | os_printf("system_partition_get_item returned an error") 19 | return 20 | 21 | block: 22 | let result = spi_flash_read(part_info.`addr`, addr data, uint32(len(data))) 23 | if result != SPI_FLASH_RESULT_OK: 24 | os_printf("spi_flash_read returned an error %d", result) 25 | return 26 | 27 | for i in countup(0, len(data) - 1, 16): 28 | os_printf("0x%08x ", part_info.`addr` + uint(i)) 29 | for j in i..i+15: 30 | let c = data[j] 31 | if c < 0x20 or c > 0x7E: 32 | os_printf(".") 33 | else: 34 | os_printf("%c", c) 35 | os_printf("\n") 36 | 37 | -------------------------------------------------------------------------------- /read-flash/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:arc 2 | --define:useMalloc 3 | --exceptions:quirky 4 | --deadCodeElim:on 5 | --define:userPartitions="{ USER_DATA_PARTITION_BEGIN + 0, SYSTEM_PROGRAM_END, 0x1000}," -------------------------------------------------------------------------------- /read-flash/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler:off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /read-flash/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/read-flash/user/user_config.h -------------------------------------------------------------------------------- /release-notes/20191031.md: -------------------------------------------------------------------------------- 1 | Initial release -------------------------------------------------------------------------------- /release-notes/20191110.md: -------------------------------------------------------------------------------- 1 | * Added gc-regions example 2 | * Added mqtt-blinky example -------------------------------------------------------------------------------- /release-notes/20200529.md: -------------------------------------------------------------------------------- 1 | * New examples 2 | * ARC garbage collection 3 | * FOTA 4 | * Base mqtt-blinky off the ARC example 5 | * Use linker scripts from (Nim ESP) SDK 6 | * Add (Nim ESP) SDK version check 7 | * Skip examples that don't compile with active Nim version 8 | * Get rid of user_main.c and use the Nim module instead 9 | -------------------------------------------------------------------------------- /release-notes/20200612.md: -------------------------------------------------------------------------------- 1 | * New examples 2 | * Read data from flash 3 | * Connect to WiFi (with settings in flash) 4 | * Change the following examples to read settings from flash: 5 | * mqtt-blinky 6 | * fota 7 | * Build all examples for 1MB flash 8 | * Fix travis build to no longer include dummy crendentials as 9 | these are now read from flash 10 | -------------------------------------------------------------------------------- /wifi/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # - Christian Jacobsen (clj) 9 | # 10 | # Changelog: 11 | # - 2014-10-06: Changed the variables to include the header file directory 12 | # - 2014-10-06: Added global var for the Xtensa tool root 13 | # - 2014-11-23: Updated for SDK 0.9.3 14 | # - 2014-12-25: Replaced esptool by esptool.py 15 | # - 2019-09-09: Added Nim support 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | NIM_CACHE = $(BUILD_BASE)/user/nimcache 22 | 23 | # base directory for the compiler 24 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 25 | 26 | # base directory of the ESP8266 related SDKS 27 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 28 | NIM_SDK_BASE ?= /opt/nim-esp8266-sdk 29 | 30 | # Set path related variables to have absolute paths 31 | override XTENSA_TOOLS_ROOT := $(abspath $(XTENSA_TOOLS_ROOT)) 32 | override SDK_BASE := $(abspath $(SDK_BASE)) 33 | override NIM_SDK_BASE := $(abspath $(NIM_SDK_BASE)) 34 | 35 | # esptool.py options 36 | ESPPORT ?= /dev/ttyUSB0 37 | ESPTOOL ?= esptool.py 38 | ESPTOOL_BAUD ?= 115200 39 | 40 | # name for the target project 41 | TARGET = app 42 | 43 | # which modules (subdirectories) of the project to include in compiling 44 | MODULES = driver user 45 | EXTRA_INCDIR = include 46 | 47 | # libraries used in this project, mainly provided by the SDK 48 | LIBS = c gcc hal pp phy net80211 lwip wpa crypto main 49 | 50 | # compiler flags using during compilation of source files 51 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DHAVE_STDINT_H 52 | 53 | # linker flags used to generate the main object file 54 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,-Map,$(TARGET_MAP) 55 | 56 | # linker script used for the above linkier step 57 | LD_SCRIPT ?= eagle.app.v6.ld 58 | LD_SCRIPT_DIR ?= $(NIM_SDK_BASE)/esp8266/nonos-sdk/ld/ 59 | 60 | # various paths from the SDK used in this project 61 | SDK_LIBDIR = lib 62 | SDK_LDDIR = ld 63 | SDK_INCDIR = include include/json 64 | 65 | # nim library path 66 | NIM_LIBDIR := $(shell nim dump 2>&1 | grep '/lib$$' | head -n 1) 67 | 68 | FLASH_SIZE ?= 1MB 69 | # we create two different files for uploading into the flash 70 | # these are the names and options to generate them 71 | FW_FILE_1_ADDR = 0x00000 72 | FW_FILE_2_ADDR = 0x10000 73 | USER_DATA_ADDR = 0x70000 74 | 75 | BLANK_BIN ?= $(SDK_BASE)/bin/blank.bin 76 | 77 | # select which tools to use as compiler, librarian and linker 78 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 79 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 80 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 81 | 82 | 83 | 84 | #### 85 | #### no user configurable options below here 86 | #### 87 | SRC_DIR := $(MODULES) 88 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 89 | NIM_BUILD_DIR := $(NIM_CACHE) 90 | 91 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 92 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 93 | NIM_SEARCH_PATHS:= $(addprefix --path:,$(NIM_SDK_BASE) $(NIM_SDK_BASE)/../nim-sdk) $(NIM_SEARCH_PATHS) 94 | 95 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 96 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 97 | NIM_OBJ := $(patsubst %.c,$(NIM_CACHE)/%.o,$(shell awk '/gcc -c/{ print $$NF }' $(NIM_CACHE)/compile_main.sh 2> /dev/null)) 98 | LIBS := $(addprefix -l,$(LIBS)) 99 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 100 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 101 | TARGET_MAP := $(addprefix $(BUILD_BASE)/,$(TARGET).map) 102 | 103 | LD_SCRIPT := $(addprefix -T$(LD_SCRIPT_DIR),$(LD_SCRIPT)) 104 | LD_SCRIPT_INCL := $(addprefix -L,$(LD_SCRIPT_DIR)) 105 | 106 | INCDIR := $(addprefix -I,$(SRC_DIR) $(NIM_SDK_BASE)/esp8266/nonos-sdk) 107 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 108 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 109 | NIM_INCDIR := -I$(NIM_CACHE) -I$(NIM_LIBDIR) 110 | 111 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 112 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 113 | 114 | V ?= $(VERBOSE) 115 | ifeq ("$(V)","1") 116 | Q := 117 | vecho := @true 118 | else 119 | Q := @ 120 | vecho := @echo 121 | endif 122 | 123 | vpath %.c $(SRC_DIR) 124 | 125 | define compile-objects 126 | $1/%.o: %.c 127 | $(vecho) "CC $$<" 128 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 129 | endef 130 | 131 | .PHONY: all checkdirs flash flash-data gen-data clean 132 | 133 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) $(FW_BASE)/user_data.py 134 | 135 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 136 | $(vecho) "FW $(FW_BASE)/" 137 | $(Q) $(ESPTOOL) elf2image --flash_size $(FLASH_SIZE) -o $(FW_BASE)/ $(TARGET_OUT) 138 | 139 | $(TARGET_OUT): $(APP_AR) 140 | $(vecho) "LD $@" 141 | $(Q) $(LD) $(LD_SCRIPT_INCL) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 142 | 143 | $(APP_AR): $(OBJ) $(NIM_OBJ) 144 | $(vecho) "AR $@" 145 | $(Q) $(AR) cru $@ $^ 146 | 147 | checkdirs: | $(BUILD_DIR) $(FW_BASE) 148 | 149 | $(BUILD_DIR): 150 | $(vecho) "MKDIR $@" 151 | $(Q) mkdir -p $@ 152 | 153 | $(FW_BASE): 154 | $(vecho) "MKDIR $@" 155 | $(Q) mkdir -p $@ 156 | 157 | flash: $(FW_FILE_1) $(FW_FILE_2) 158 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 159 | 160 | gen-data: 161 | $(vecho) "NIM RUN $@" 162 | nim c -r $(NIM_SEARCH_PATHS) user/user_data.nim 163 | 164 | flash-data: 165 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOL_BAUD) write_flash --flash_size $(FLASH_SIZE) $(USER_DATA_ADDR) user_data.bin 166 | 167 | $(FW_BASE)/user_data.py: user_data.py 168 | $(vecho) "CP $@" 169 | $(Q) cp $< $@ 170 | 171 | clean: 172 | $(vecho) "CLEAN" 173 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 174 | 175 | $(NIM_CACHE)/%.nim.c $(NIM_CACHE)/nim_%.h: user/%.nim user/%.nim.cfg 176 | $(vecho) "NIM $@" 177 | $(Q) nim c --cpu:arm --os:standalone --noMain --compileOnly --verbosity:0 --genDeps:on --nimcache:$(NIM_CACHE) --header:nim_$*.h -d:nimMinHeapPages=1 $(NIM_SEARCH_PATHS) $< 178 | $(Q) touch $@ 179 | $(Q) sed -e 's!^!$(NIM_CACHE)/main.nim.c: !' -e 's!#!\\#!' < $(NIM_CACHE)/main.deps > $(NIM_CACHE)/main.deps.mk 180 | 181 | $(NIM_CACHE)/nim_built.mk: $(NIM_CACHE)/main.nim.c 182 | $(vecho) "TOUCH $@" 183 | $(Q) touch $@ 184 | 185 | 186 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 187 | 188 | %.o: %.c 189 | %.o: %.c 190 | $(vecho) "CC $<" 191 | $(Q) $(CC) $(NIM_INCDIR) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $< -o $@ 192 | 193 | $(NIM_CACHE)/stdlib_system.nim.o: CFLAGS:=$(CFLAGS) -D'realloc(ptr, size)=os_realloc(ptr, size)' -D'calloc(count, size)=os_calloc(count, size)' -D'malloc(size)=os_malloc(size)' -D'free(ptr)=os_free(ptr)' -include stdlib.h -include mem.h 194 | 195 | $(NIM_CACHE)/main.deps.mk: 196 | 197 | ifneq ($(MAKECMDGOALS), clean) 198 | -include $(NIM_CACHE)/nim_built.mk 199 | -include $(NIM_CACHE)/main.deps.mk 200 | sdk_version_check=$(shell $(NIM_SDK_BASE)/esp8266/nonos-sdk/bin/check_sdk_version.sh $(SDK_BASE)) 201 | ifneq ($(sdk_version_check),) 202 | $(error $(sdk_version_check)) 203 | endif 204 | endif 205 | -------------------------------------------------------------------------------- /wifi/user/main.nim: -------------------------------------------------------------------------------- 1 | import esp8266/nonos-sdk/os_type 2 | import esp8266/nonos-sdk/osapi 3 | import esp8266/nonos-sdk/spi_flash 4 | import esp8266/nonos-sdk/user_interface 5 | import esp8266/types 6 | import esp8266/user_fns/default_user_rf_cal_sector_set 7 | import esp8266/user_fns/user_init 8 | import esp8266/user_fns/user_pre_init 9 | 10 | import user_data 11 | 12 | var wifi_config: station_config 13 | 14 | 15 | proc wifi_connect_handle_event_cb(event: ptr System_Event_t) {.cdecl.} = 16 | case event.event: 17 | of EVENT_STAMODE_CONNECTED: 18 | os_printf("WiFi connected\n") 19 | of EVENT_STAMODE_GOT_IP: 20 | os_printf("Got an IP address\n") 21 | of EVENT_STAMODE_DISCONNECTED: 22 | os_printf("WiFi disconnected\n") 23 | else: 24 | discard 25 | 26 | 27 | proc wifi_setup(ssid: WiFiSsid, password: WiFiPassword) = 28 | wifi_set_event_handler_cb(wifi_connect_handle_event_cb) 29 | 30 | discard wifi_set_opmode(uint8(STATION_MODE)) 31 | wifi_config.bssid_set = 0 32 | wifi_config.ssid = ssid 33 | wifi_config.password = password 34 | discard wifi_station_set_config(addr wifi_config) 35 | discard wifi_station_set_auto_connect((uint8)false) 36 | discard wifi_station_ap_number_set(0) 37 | 38 | 39 | proc app_init() {.cdecl.} = 40 | discard wifi_station_connect() 41 | 42 | 43 | proc nim_user_init() {.exportc.} = 44 | var 45 | part_info: partition_item_t 46 | data: Data 47 | 48 | block: 49 | let result = system_partition_get_item(partition_type_t(103), 50 | addr part_info) 51 | if not result: 52 | os_printf("system_partition_get_item returned an error\n") 53 | return 54 | 55 | block: 56 | let result = spi_flash_read(part_info.`addr`, addr data, uint32(sizeof(data))) 57 | if result != SPI_FLASH_RESULT_OK: 58 | os_printf("spi_flash_read returned an error %d\n", result) 59 | return 60 | 61 | let (ok, msg) = data.verify() 62 | if ok: 63 | wifi_setup(data.settings.wifi.ssid, data.settings.wifi.password) 64 | 65 | system_init_done_cb(app_init) 66 | else: 67 | os_printf( 68 | "No valid user data found: %s\n" & 69 | "please upload valid data to flash @0x%08x\n", 70 | msg, part_info.`addr`) 71 | -------------------------------------------------------------------------------- /wifi/user/main.nim.cfg: -------------------------------------------------------------------------------- 1 | --gc:arc 2 | --define:useMalloc 3 | --exceptions:quirky 4 | --deadCodeElim:on 5 | --define:userPartitions="{ USER_DATA_PARTITION_BEGIN + 0, SYSTEM_PROGRAM_END, 0x1000}," -------------------------------------------------------------------------------- /wifi/user/panicoverride.nim: -------------------------------------------------------------------------------- 1 | proc os_printf(formatstr: cstring) {.header: "", importc, cdecl, varargs.} 2 | proc system_soft_wdt_feed() {.header: "", importc, cdecl.} 3 | 4 | {.push stack_trace: off, profiler: off.} 5 | 6 | proc rawoutput(s: string) = 7 | os_printf("\r\npanic: %s\r\n", s) 8 | 9 | proc panic(s: string) {.noreturn.} = 10 | rawoutput(s) 11 | 12 | while true: 13 | system_soft_wdt_feed() 14 | 15 | {.pop.} 16 | -------------------------------------------------------------------------------- /wifi/user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clj/nim-esp8266-examples/ba747cee4c784be23b04a34db118d97d0475fc10/wifi/user/user_config.h -------------------------------------------------------------------------------- /wifi/user/user_data.nim: -------------------------------------------------------------------------------- 1 | import esp8266/crc 2 | import esp8266/types 3 | 4 | 5 | const 6 | magic = 0x0A0CDCBA'u32 7 | app = "wifi" 8 | 9 | 10 | type 11 | WiFiSsid* = array[32, uint8] 12 | WiFiPassword* = array[64, uint8] 13 | WiFiCreds* {.packed.} = object 14 | ssid*: WiFiSsid 15 | password*: WiFiPassword 16 | Settings* {.packed.} = object 17 | magic*: uint32 18 | app: array[4, uint8] 19 | wifi*: WifiCreds 20 | Data* {.packed.} = object 21 | settings*: Settings 22 | crc32*: uint32 23 | 24 | 25 | proc verify*(data: var Data): (bool, string) = 26 | if data.settings.magic != magic: 27 | return (false, "wrong magic") 28 | if data.settings.app != app.toArray(4, uint8): 29 | return (false, "wrong app") 30 | let crc = crc32(data.settings) 31 | if data.crc32 != crc: 32 | return (false, "bad crc") 33 | return (true, "") 34 | 35 | 36 | when isMainModule: 37 | import endians 38 | import parseopt 39 | import streams 40 | import strutils 41 | 42 | import esp8266/types 43 | 44 | var 45 | data: Data 46 | ssid: string 47 | password: string 48 | dest = "user_data.bin" 49 | optParser = initOptParser() 50 | 51 | while true: 52 | optParser.next() 53 | case optParser.kind 54 | of cmdEnd: break 55 | of cmdShortOption, cmdLongOption: 56 | case optParser.key: 57 | of "ssid", "s": 58 | ssid = optParser.val 59 | of "password", "passwd", "pass", "p": 60 | password = optParser.val 61 | else: 62 | echo("Unknown option: ", optParser.key) 63 | quit(QuitFailure) 64 | if optParser.val == "": 65 | echo("Option: ", optParser.key, " takes one argument") 66 | quit(QuitFailure) 67 | of cmdArgument: 68 | dest = optParser.key 69 | 70 | if ssid == "": 71 | stdout.write("SSID: ") 72 | ssid = readLine(stdin) 73 | if password == "": 74 | stdout.write("Password: ") 75 | password = readLine(stdin) 76 | 77 | data.settings.magic = magic 78 | data.settings.app.setString(app) 79 | data.settings.wifi.ssid.setString(ssid) 80 | data.settings.wifi.password.setString(password) 81 | 82 | data.crc32 = crc32(data.settings) 83 | 84 | littleEndian32(addr data.settings.magic, addr data.settings.magic) 85 | littleEndian32(addr data.crc32, addr data.crc32) 86 | 87 | let padding = '\xff'.repeat(4096 - sizeof(data)) 88 | 89 | let fp = open(dest, fmWrite) 90 | discard fp.writeBuffer(addr data, sizeof(data)) 91 | fp.write(padding) 92 | fp.close() 93 | -------------------------------------------------------------------------------- /wifi/user_data.py: -------------------------------------------------------------------------------- 1 | # A cross platform Python script to generate a user_data.bin file 2 | # for the WiFi example. 3 | import binascii 4 | import struct 5 | import sys 6 | 7 | try: 8 | input = raw_input 9 | except NameError: 10 | pass 11 | 12 | magic = 0x0a0cdcba 13 | app = "wifi" 14 | ssid = input('SSID: ').encode('ascii') 15 | password = input('Password: ').encode('ascii') 16 | 17 | filename = sys.argv[1] if len(sys.argv) > 1 else '0x70000.bin' 18 | with open(filename, 'wb') as fp: 19 | settings = struct.pack('