├── .gitignore ├── .gitmodules ├── .vscode └── settings.json ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── build-flash-monitor.sh ├── components └── micropython │ ├── CMakeLists.txt │ ├── RingBuffer │ ├── RingBufferPosn.h │ ├── RingBufferPosnRTOS.h │ └── RingBufferRTOS.h │ ├── component.mk │ ├── cppif │ ├── FileSysReader.cpp │ ├── FileSysReader.h │ ├── MicropyExecTask.h │ ├── Micropython.cpp │ └── Micropython.h │ └── ports │ └── ric │ ├── Makefile │ ├── MicropythonRICFns.h │ ├── boards │ ├── GENERIC │ │ ├── mpconfigboard.h │ │ └── mpconfigboard.mk │ ├── manifest.py │ ├── manifest_release.py │ └── sdkconfig.base │ ├── gccollect.c │ ├── gccollect.h │ ├── help.c │ ├── main.c │ ├── makeimg.py │ ├── modutime.c │ ├── mpconfigport.h │ ├── mphalport.c │ ├── mphalport.h │ ├── mpthreadport.c │ ├── mpthreadport.h │ ├── partitions.csv │ └── qstrdefsport.h ├── main ├── CMakeLists.txt ├── Kconfig.projbuild ├── component.mk └── main.cpp ├── partitions.csv ├── scripts └── SerialMonitor_curses.py ├── sdkconfig.defaults └── spiffs_image └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | sdkconfig 3 | sdkconfig.old 4 | logs/ 5 | 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/micropython"] 2 | path = external/micropython 3 | url = https://github.com/micropython/micropython.git 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmake.configureOnOpen": false 3 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(MicroPythonEmbedding) 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright 2020 Rob Dobson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := MicroPythonEmbedding 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Embedding MicroPython in an ESP IDF Project 2 | =========================================== 3 | 4 | This is a quick example project to demo the way I managed to embed Micropython into an existing ESP IDF project. 5 | 6 | The program doesn't do much but does incorporate Micropython and it is the build scripts that are the main event. 7 | 8 | The approach is to run the MicroPython build system from within the ESP IDF but then pull all of the source code (including the dynamically generated header files) into the ESP IDF project directly. So the only reason for running the MicroPython build is to generate those dynamic files. 9 | 10 | First you will need to ensure the ESP IDF is installed. I have found that it works fine with the current head of the master branch (which is what the linux and mac instructions end up installing) but you may find that some subsequent commits to the ESP IDF break things and in that case you will need to follow instructions to set a specific version of the IDF - e.g. to select 4.1 11 | 12 | ```shell 13 | cd ~/esp/esp-idf 14 | git checkout v4.1 15 | git submodule update --init 16 | ``` 17 | 18 | Note that after doing this you will probably need to reinstall the ESP IDF toolchain: 19 | ```shell 20 | ./install.sh 21 | ``` 22 | 23 | Then clone the repo to a folder of your choosing (with --recursive to ensure the MicroPython submodule is downloaded) 24 | 25 | ```shell 26 | git clone --recursive https://github.com/robdobsn/MicroPythonESP32Embedding 27 | ``` 28 | 29 | Then follow the instructions in the MicroPython README (in the external/micropython folder), incuding building the mpy-cross cross compiler. 30 | 31 | ```shell 32 | cd ./external/micropython/mpy-cross 33 | make 34 | cd ../../.. 35 | ``` 36 | 37 | Finally setup the environment for IDF building and build: 38 | 39 | ```shell 40 | . $HOME/esp/esp-idf/export.sh 41 | idf.py build 42 | ``` 43 | -------------------------------------------------------------------------------- /build-flash-monitor.sh: -------------------------------------------------------------------------------- 1 | SERIALPORT=${1:-COM5} 2 | SERIALBAUD=${2:-2000000} 3 | IPORHOSTNAME=${3:-} 4 | . $HOME/esp/esp-idf/export.sh 5 | idf.py build &&\ 6 | python.exe $IDF_PATH/components/esptool_py/esptool/esptool.py -p$SERIALPORT -b$SERIALBAUD --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0xe000 build/ota_data_initial.bin 0x10000 build/MicroPythonEmbedding.bin 0x370000 build/spiffs.bin 7 | if [ $? -eq "0" ] 8 | then 9 | python.exe scripts/SerialMonitor_curses.py $SERIALPORT -g 10 | fi 11 | -------------------------------------------------------------------------------- /components/micropython/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXTERNAL_MICROPYTHON_DIR "${PROJECT_DIR}/external/micropython") 2 | set(EXTERNAL_MICROPYTHON_BUILD_DIR "${PROJECT_DIR}/external/micropython/ports/ric/build-GENERIC") 3 | set(EXTERNAL_MICROPYTHON_PORT_DIR, "${PROJECT_DIR}/external/micropython/ports/ric") 4 | set(MICROPYTHON_PORT_DIR "${COMPONENT_DIR}/ports/ric") 5 | set(MICROPYTHON_BOARD_DIR "${COMPONENT_DIR}/ports/ric/boards/GENERIC") 6 | 7 | idf_component_register( 8 | SRCS 9 | "${EXTERNAL_MICROPYTHON_DIR}/py/argcheck.c" 10 | "${EXTERNAL_MICROPYTHON_DIR}/py/asmbase.c" 11 | "${EXTERNAL_MICROPYTHON_DIR}/py/bc.c" 12 | "${EXTERNAL_MICROPYTHON_DIR}/py/binary.c" 13 | "${EXTERNAL_MICROPYTHON_DIR}/py/builtinevex.c" 14 | "${EXTERNAL_MICROPYTHON_DIR}/py/builtinhelp.c" 15 | "${EXTERNAL_MICROPYTHON_DIR}/py/builtinimport.c" 16 | "${EXTERNAL_MICROPYTHON_DIR}/py/compile.c" 17 | "${EXTERNAL_MICROPYTHON_DIR}/py/emitbc.c" 18 | "${EXTERNAL_MICROPYTHON_DIR}/py/emitcommon.c" 19 | "${EXTERNAL_MICROPYTHON_DIR}/py/emitglue.c" 20 | "${EXTERNAL_MICROPYTHON_DIR}/py/formatfloat.c" 21 | "${EXTERNAL_MICROPYTHON_DIR}/py/frozenmod.c" 22 | "${EXTERNAL_MICROPYTHON_DIR}/py/gc.c" 23 | "${EXTERNAL_MICROPYTHON_DIR}/py/lexer.c" 24 | "${EXTERNAL_MICROPYTHON_DIR}/py/malloc.c" 25 | "${EXTERNAL_MICROPYTHON_DIR}/py/map.c" 26 | "${EXTERNAL_MICROPYTHON_DIR}/py/modbuiltins.c" 27 | "${EXTERNAL_MICROPYTHON_DIR}/py/modgc.c" 28 | "${EXTERNAL_MICROPYTHON_DIR}/py/modmicropython.c" 29 | "${EXTERNAL_MICROPYTHON_DIR}/py/modstruct.c" 30 | "${EXTERNAL_MICROPYTHON_DIR}/py/modthread.c" 31 | "${EXTERNAL_MICROPYTHON_DIR}/py/moduerrno.c" 32 | "${EXTERNAL_MICROPYTHON_DIR}/py/mpprint.c" 33 | "${EXTERNAL_MICROPYTHON_DIR}/py/mpstate.c" 34 | "${EXTERNAL_MICROPYTHON_DIR}/py/mpz.c" 35 | "${EXTERNAL_MICROPYTHON_DIR}/py/nativeglue.c" 36 | "${EXTERNAL_MICROPYTHON_DIR}/py/nlr.c" 37 | "${EXTERNAL_MICROPYTHON_DIR}/py/nlrsetjmp.c" 38 | "${EXTERNAL_MICROPYTHON_DIR}/py/obj.c" 39 | "${EXTERNAL_MICROPYTHON_DIR}/py/objarray.c" 40 | "${EXTERNAL_MICROPYTHON_DIR}/py/objbool.c" 41 | "${EXTERNAL_MICROPYTHON_DIR}/py/objboundmeth.c" 42 | "${EXTERNAL_MICROPYTHON_DIR}/py/objcell.c" 43 | "${EXTERNAL_MICROPYTHON_DIR}/py/objclosure.c" 44 | "${EXTERNAL_MICROPYTHON_DIR}/py/objcomplex.c" 45 | "${EXTERNAL_MICROPYTHON_DIR}/py/objdict.c" 46 | "${EXTERNAL_MICROPYTHON_DIR}/py/objenumerate.c" 47 | "${EXTERNAL_MICROPYTHON_DIR}/py/objexcept.c" 48 | "${EXTERNAL_MICROPYTHON_DIR}/py/objfilter.c" 49 | "${EXTERNAL_MICROPYTHON_DIR}/py/objfloat.c" 50 | "${EXTERNAL_MICROPYTHON_DIR}/py/objfun.c" 51 | "${EXTERNAL_MICROPYTHON_DIR}/py/objgenerator.c" 52 | "${EXTERNAL_MICROPYTHON_DIR}/py/objgetitemiter.c" 53 | "${EXTERNAL_MICROPYTHON_DIR}/py/objint.c" 54 | "${EXTERNAL_MICROPYTHON_DIR}/py/objint_mpz.c" 55 | "${EXTERNAL_MICROPYTHON_DIR}/py/objlist.c" 56 | "${EXTERNAL_MICROPYTHON_DIR}/py/objmap.c" 57 | "${EXTERNAL_MICROPYTHON_DIR}/py/objmodule.c" 58 | "${EXTERNAL_MICROPYTHON_DIR}/py/objnone.c" 59 | "${EXTERNAL_MICROPYTHON_DIR}/py/objobject.c" 60 | "${EXTERNAL_MICROPYTHON_DIR}/py/objpolyiter.c" 61 | "${EXTERNAL_MICROPYTHON_DIR}/py/objproperty.c" 62 | "${EXTERNAL_MICROPYTHON_DIR}/py/objrange.c" 63 | "${EXTERNAL_MICROPYTHON_DIR}/py/objreversed.c" 64 | "${EXTERNAL_MICROPYTHON_DIR}/py/objset.c" 65 | "${EXTERNAL_MICROPYTHON_DIR}/py/objsingleton.c" 66 | "${EXTERNAL_MICROPYTHON_DIR}/py/objslice.c" 67 | "${EXTERNAL_MICROPYTHON_DIR}/py/objstr.c" 68 | "${EXTERNAL_MICROPYTHON_DIR}/py/objstrunicode.c" 69 | "${EXTERNAL_MICROPYTHON_DIR}/py/objtuple.c" 70 | "${EXTERNAL_MICROPYTHON_DIR}/py/objtype.c" 71 | "${EXTERNAL_MICROPYTHON_DIR}/py/objzip.c" 72 | "${EXTERNAL_MICROPYTHON_DIR}/py/opmethods.c" 73 | "${EXTERNAL_MICROPYTHON_DIR}/py/parse.c" 74 | "${EXTERNAL_MICROPYTHON_DIR}/py/parsenum.c" 75 | "${EXTERNAL_MICROPYTHON_DIR}/py/parsenumbase.c" 76 | "${EXTERNAL_MICROPYTHON_DIR}/py/persistentcode.c" 77 | "${EXTERNAL_MICROPYTHON_DIR}/py/profile.c" 78 | "${EXTERNAL_MICROPYTHON_DIR}/py/qstr.c" 79 | "${EXTERNAL_MICROPYTHON_DIR}/py/reader.c" 80 | "${EXTERNAL_MICROPYTHON_DIR}/py/repl.c" 81 | "${EXTERNAL_MICROPYTHON_DIR}/py/runtime.c" 82 | "${EXTERNAL_MICROPYTHON_DIR}/py/runtime_utils.c" 83 | "${EXTERNAL_MICROPYTHON_DIR}/py/scope.c" 84 | "${EXTERNAL_MICROPYTHON_DIR}/py/scheduler.c" 85 | "${EXTERNAL_MICROPYTHON_DIR}/py/sequence.c" 86 | "${EXTERNAL_MICROPYTHON_DIR}/py/smallint.c" 87 | "${EXTERNAL_MICROPYTHON_DIR}/py/stream.c" 88 | "${EXTERNAL_MICROPYTHON_DIR}/py/stackctrl.c" 89 | "${EXTERNAL_MICROPYTHON_DIR}/py/unicode.c" 90 | "${EXTERNAL_MICROPYTHON_DIR}/py/vm.c" 91 | "${EXTERNAL_MICROPYTHON_DIR}/py/vstr.c" 92 | "${EXTERNAL_MICROPYTHON_DIR}/py/warning.c" 93 | "${EXTERNAL_MICROPYTHON_DIR}/lib/mp-readline/readline.c" 94 | "${EXTERNAL_MICROPYTHON_DIR}/lib/timeutils/timeutils.c" 95 | "${EXTERNAL_MICROPYTHON_DIR}/lib/utils/interrupt_char.c" 96 | "${EXTERNAL_MICROPYTHON_DIR}/extmod/utime_mphal.c" 97 | "${EXTERNAL_MICROPYTHON_DIR}/lib/utils/pyexec.c" 98 | "${MICROPYTHON_PORT_DIR}/gccollect.c" 99 | "${MICROPYTHON_PORT_DIR}/help.c" 100 | "${MICROPYTHON_PORT_DIR}/mphalport.c" 101 | "${MICROPYTHON_PORT_DIR}/mpthreadport.c" 102 | "${MICROPYTHON_PORT_DIR}/modutime.c" 103 | "cppif/Micropython.cpp" 104 | "cppif/FileSysReader.cpp" 105 | "${EXTERNAL_MICROPYTHON_BUILD_DIR}/frozen_content.c" 106 | INCLUDE_DIRS 107 | "." 108 | ${EXTERNAL_MICROPYTHON_DIR} 109 | ${EXTERNAL_MICROPYTHON_DIR}/py 110 | ${MICROPYTHON_PORT_DIR} 111 | ${MICROPYTHON_BOARD_DIR} 112 | cppif 113 | RingBuffer 114 | REQUIRES 115 | ) 116 | 117 | set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMICROPY_ESP_IDF_4 -Wno-override-init -Wno-implicit-fallthrough -I${EXTERNAL_MICROPYTHON_BUILD_DIR}" ) 118 | set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMICROPY_ESP_IDF_4 -I${EXTERNAL_MICROPYTHON_BUILD_DIR}" ) 119 | 120 | add_custom_command(OUTPUT "${EXTERNAL_MICROPYTHON_BUILD_DIR}/frozen_content.c" 121 | COMMAND echo "------------- Building Micropython externally ---------------" 122 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${COMPONENT_DIR}/ports/ric ${EXTERNAL_MICROPYTHON_DIR}/ports/ric 123 | COMMAND cd ${EXTERNAL_MICROPYTHON_DIR}/ports/ric 124 | COMMAND make BOARD=GENERIC GENERATIONPHASE=y 125 | DEPENDS 126 | ${MICROPYTHON_PORT_DIR}/mpconfigport.h 127 | ) 128 | 129 | add_custom_target(generate_frozen ALL 130 | DEPENDS "${EXTERNAL_MICROPYTHON_BUILD_DIR}/frozen_content.c") 131 | 132 | -------------------------------------------------------------------------------- /components/micropython/RingBuffer/RingBufferPosn.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // RingBufferPosn 4 | // Generic ring buffer pointer class 5 | // Each pointer is only updated by one source 6 | // 7 | // Rob Dobson 2012-2020 8 | // 9 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | #pragma once 12 | 13 | class RingBufferPosn 14 | { 15 | public: 16 | volatile unsigned int _putPos; 17 | volatile unsigned int _getPos; 18 | unsigned int _bufLen; 19 | 20 | RingBufferPosn(int maxLen) 21 | { 22 | init(maxLen); 23 | } 24 | 25 | void init(int maxLen) 26 | { 27 | _bufLen = maxLen; 28 | _putPos = 0; 29 | _getPos = 0; 30 | } 31 | 32 | void clear() 33 | { 34 | _getPos = _putPos = 0; 35 | } 36 | 37 | inline unsigned int posToGet() 38 | { 39 | return _getPos; 40 | } 41 | 42 | inline unsigned int posToPut() 43 | { 44 | return _putPos; 45 | } 46 | 47 | bool canPut() 48 | { 49 | if (_bufLen == 0) 50 | return false; 51 | if (_putPos == _getPos) 52 | return true; 53 | unsigned int gp = _getPos; 54 | if (_putPos > gp) 55 | { 56 | if ((_putPos != _bufLen - 1) || (gp != 0)) 57 | return true; 58 | } 59 | else 60 | { 61 | if (gp - _putPos > 1) 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | bool canGet() 68 | { 69 | return _putPos != _getPos; 70 | } 71 | 72 | void hasPut() 73 | { 74 | _putPos++; 75 | if (_putPos >= _bufLen) 76 | _putPos = 0; 77 | } 78 | 79 | void hasGot() 80 | { 81 | _getPos++; 82 | if (_getPos >= _bufLen) 83 | _getPos = 0; 84 | } 85 | 86 | unsigned int count() 87 | { 88 | unsigned int posToGet = _getPos; 89 | if (posToGet <= _putPos) 90 | return _putPos - posToGet; 91 | return _bufLen - posToGet + _putPos; 92 | } 93 | 94 | // Get Nth element prior to the put position 95 | // 0 is the last element put in the queue 96 | // 1 is the one put in before that 97 | // Returns -1 if invalid 98 | int getNthFromPut(unsigned int N) 99 | { 100 | if (!canGet()) 101 | return -1; 102 | if (N >= _bufLen) 103 | return -1; 104 | int nthPos = _putPos - 1 - N; 105 | if (nthPos < 0) 106 | nthPos += _bufLen; 107 | if (((unsigned int)(nthPos + 1) == _getPos) || ((unsigned int)(nthPos + 1) == _bufLen && _getPos == 0)) 108 | return -1; 109 | return nthPos; 110 | } 111 | 112 | // Get Nth element from the get position 113 | // 0 is the element next got from the queue 114 | // 1 is the one got after that 115 | // returns -1 if invalid 116 | int getNthFromGet(unsigned int N) 117 | { 118 | if (!canGet()) 119 | return -1; 120 | if (N >= _bufLen) 121 | return -1; 122 | unsigned int nthPos = _getPos + N; 123 | if (nthPos >= _bufLen) 124 | nthPos -= _bufLen; 125 | if (nthPos == _putPos) 126 | return -1; 127 | return nthPos; 128 | } 129 | }; 130 | -------------------------------------------------------------------------------- /components/micropython/RingBuffer/RingBufferPosnRTOS.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // RingBufferPosnRTOS 4 | // Generic ring buffer pointer class 5 | // Each pointer is only updated by one source 6 | // 7 | // Rob Dobson 2012-2020 8 | // 9 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | #pragma once 12 | 13 | #include "freertos/FreeRTOS.h" 14 | #include "freertos/semphr.h" 15 | 16 | class RingBufferPosnRTOS 17 | { 18 | public: 19 | volatile unsigned int _putPos; 20 | volatile unsigned int _getPos; 21 | unsigned int _bufLen; 22 | SemaphoreHandle_t _rbMutex; 23 | static const int PUT_TICKS_TO_WAIT = 1; 24 | static const int GET_TICKS_TO_WAIT = 1; 25 | static const int CLEAR_TICKS_TO_WAIT = 2; 26 | 27 | RingBufferPosnRTOS(int maxLen) 28 | { 29 | init(maxLen); 30 | _rbMutex = xSemaphoreCreateMutex(); 31 | } 32 | 33 | void init(int maxLen) 34 | { 35 | _bufLen = maxLen; 36 | _putPos = 0; 37 | _getPos = 0; 38 | } 39 | 40 | void clear() 41 | { 42 | if (xSemaphoreTake(_rbMutex, CLEAR_TICKS_TO_WAIT) == pdTRUE) 43 | { 44 | _getPos = _putPos = 0; 45 | xSemaphoreGive(_rbMutex); 46 | } 47 | } 48 | 49 | inline unsigned int posToGet() 50 | { 51 | return _getPos; 52 | } 53 | 54 | inline unsigned int posToPut() 55 | { 56 | return _putPos; 57 | } 58 | 59 | // If true is returned then the semaphore has been acquired and hasPut must be called 60 | // to return the semaphore 61 | bool canPut() 62 | { 63 | // Validity check - zero length buffer 64 | if (_bufLen == 0) 65 | return false; 66 | 67 | // Acquire semaphore 68 | if (xSemaphoreTake(_rbMutex, PUT_TICKS_TO_WAIT) == pdTRUE) 69 | { 70 | // Check space available 71 | if (_putPos == _getPos) 72 | return true; 73 | unsigned int gp = _getPos; 74 | if (_putPos > gp) 75 | { 76 | if ((_putPos != _bufLen - 1) || (gp != 0)) 77 | return true; 78 | } 79 | else 80 | { 81 | if (gp - _putPos > 1) 82 | return true; 83 | } 84 | // Return semaphore - no space 85 | xSemaphoreGive(_rbMutex); 86 | } 87 | return false; 88 | } 89 | 90 | // If true is returned then the semaphore has been acquired and hasGot must be called 91 | // to return the semaphore 92 | bool canGet() 93 | { 94 | // Acquire semaphore 95 | if (xSemaphoreTake(_rbMutex, GET_TICKS_TO_WAIT) == pdTRUE) 96 | { 97 | bool retVal = _putPos != _getPos; 98 | if (!retVal) 99 | { 100 | // Return semaphore - nothing available 101 | xSemaphoreGive(_rbMutex); 102 | } 103 | return retVal; 104 | } 105 | return false; 106 | } 107 | 108 | void hasPut() 109 | { 110 | // Put 111 | _putPos++; 112 | if (_putPos >= _bufLen) 113 | _putPos = 0; 114 | 115 | // Return the semaphore 116 | xSemaphoreGive(_rbMutex); 117 | } 118 | 119 | void hasGot() 120 | { 121 | // Get 122 | _getPos++; 123 | if (_getPos >= _bufLen) 124 | _getPos = 0; 125 | 126 | // Return the semaphore 127 | xSemaphoreGive(_rbMutex); 128 | } 129 | 130 | unsigned int count() 131 | { 132 | unsigned int retVal = 0; 133 | if (xSemaphoreTake(_rbMutex, GET_TICKS_TO_WAIT) == pdTRUE) 134 | { 135 | unsigned int posToGet = _getPos; 136 | if (posToGet <= _putPos) 137 | retVal = _putPos - posToGet; 138 | else 139 | retVal = _bufLen - posToGet + _putPos; 140 | xSemaphoreGive(_rbMutex); 141 | } 142 | return retVal; 143 | } 144 | 145 | // Get Nth element prior to the put position 146 | // 0 is the last element put in the queue 147 | // 1 is the one put in before that 148 | // Returns -1 if invalid 149 | int getNthFromPut(unsigned int N) 150 | { 151 | if (!canGet()) 152 | return -1; 153 | if (N >= _bufLen) 154 | return -1; 155 | int nthPos = _putPos - 1 - N; 156 | if (nthPos < 0) 157 | nthPos += _bufLen; 158 | if (((unsigned int)(nthPos + 1) == _getPos) || ((unsigned int)(nthPos + 1) == _bufLen && _getPos == 0)) 159 | return -1; 160 | return nthPos; 161 | } 162 | 163 | // Get Nth element from the get position 164 | // 0 is the element next got from the queue 165 | // 1 is the one got after that 166 | // returns -1 if invalid 167 | int getNthFromGet(unsigned int N) 168 | { 169 | if (!canGet()) 170 | return -1; 171 | if (N >= _bufLen) 172 | return -1; 173 | unsigned int nthPos = _getPos + N; 174 | if (nthPos >= _bufLen) 175 | nthPos -= _bufLen; 176 | if (nthPos == _putPos) 177 | return -1; 178 | return nthPos; 179 | } 180 | }; 181 | -------------------------------------------------------------------------------- /components/micropython/RingBuffer/RingBufferRTOS.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // RingBufferRTOS 4 | // Template-based ring bufffer 5 | // 6 | // Rob Dobson 2012-2020 7 | // 8 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | #pragma once 11 | 12 | #include "RingBufferPosnRTOS.h" 13 | #include 14 | 15 | template 16 | class RingBufferRTOS 17 | { 18 | public: 19 | RingBufferRTOS() : 20 | _bufPos(bufferSize) 21 | { 22 | } 23 | 24 | bool put(const ElemT& elem) 25 | { 26 | if (_bufPos.canPut()) 27 | { 28 | _buffer[_bufPos.posToPut()] = elem; 29 | _bufPos.hasPut(); 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | bool get(ElemT& elem) 36 | { 37 | if (_bufPos.canGet()) 38 | { 39 | elem = _buffer[_bufPos.posToGet()]; 40 | _bufPos.hasGot(); 41 | return true; 42 | } 43 | return false; 44 | } 45 | 46 | void clear() 47 | { 48 | _bufPos.clear(); 49 | } 50 | 51 | uint32_t count() 52 | { 53 | return _bufPos.count(); 54 | } 55 | 56 | uint32_t maxLen() 57 | { 58 | return bufferSize; 59 | } 60 | 61 | private: 62 | RingBufferPosnRTOS _bufPos; 63 | ElemT _buffer[bufferSize]; 64 | }; 65 | 66 | -------------------------------------------------------------------------------- /components/micropython/component.mk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robdobsn/MicroPythonESP32Embedding/f7237e4e61aaa94d646c5465e9b585a1cdf56474/components/micropython/component.mk -------------------------------------------------------------------------------- /components/micropython/cppif/FileSysReader.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // RIC Micropython 4 | // 5 | // Rob Dobson 2016-20 6 | // 7 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | #include 10 | #include "string.h" 11 | #include "esp_log.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | #include "py/reader.h" 17 | #include "py/runtime.h" 18 | #include "py/mperrno.h" 19 | #include "py/mpthread.h" 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | FileSysReader::FileSysReader(const char* filename) 25 | { 26 | _cacheLen = 0; 27 | _cachePos = 0; 28 | _filePos = 0; 29 | _isFinal = false; 30 | strlcpy(_filePath, "/spiffs/", sizeof(_filePath)); 31 | strlcat(_filePath, filename, sizeof(_filePath)); 32 | read(); 33 | } 34 | 35 | int FileSysReader::read() 36 | { 37 | // Open file 38 | FILE* pFile = fopen(_filePath, "rb"); 39 | if (!pFile) 40 | { 41 | ESP_LOGE("FileSysReader", "Can't open %s", _filePath); 42 | return 0; 43 | } 44 | 45 | // Move to appropriate place in file 46 | if (fseek(pFile, _filePos, SEEK_SET) == 0) 47 | { 48 | // Read 49 | _cacheLen = fread((char*)_buf, 1, CHARS_TO_CACHE, pFile); 50 | _filePos += _cacheLen; 51 | if (_cacheLen != CHARS_TO_CACHE) 52 | _isFinal = true; 53 | } 54 | else 55 | { 56 | _cacheLen = 0; 57 | _isFinal = true; 58 | } 59 | // Close 60 | fclose(pFile); 61 | if (_cacheLen == 0) 62 | _isFinal = true; 63 | return _cacheLen; 64 | } 65 | 66 | void FileSysReader::close() 67 | { 68 | } 69 | 70 | extern "C" mp_uint_t mp_reader_ric_readbyte(void *data) { 71 | FileSysReader* pFSReader = (FileSysReader*)data; 72 | if (pFSReader->_cachePos >= pFSReader->_cacheLen) { 73 | if (pFSReader->_cacheLen == 0) { 74 | return MP_READER_EOF; 75 | } else { 76 | MP_THREAD_GIL_EXIT(); 77 | int n = pFSReader->read(); 78 | MP_THREAD_GIL_ENTER(); 79 | if (n <= 0) { 80 | return MP_READER_EOF; 81 | } 82 | } 83 | } 84 | int readVal = pFSReader->_buf[pFSReader->_cachePos++]; 85 | return readVal; 86 | } 87 | 88 | extern "C" void mp_reader_ric_close(void *data) { 89 | FileSysReader* pFSReader = (FileSysReader*)data; 90 | MP_THREAD_GIL_EXIT(); 91 | pFSReader->close(); 92 | MP_THREAD_GIL_ENTER(); 93 | if (pFSReader) 94 | delete pFSReader; 95 | pFSReader = NULL; 96 | } 97 | 98 | extern "C" void mp_reader_new_file(mp_reader_t *reader, const char *filename) { 99 | MP_THREAD_GIL_EXIT(); 100 | FileSysReader* pFSReader = new FileSysReader(filename); 101 | MP_THREAD_GIL_ENTER(); 102 | if (!pFSReader) 103 | mp_raise_OSError(MP_EIO); 104 | reader->data = pFSReader; 105 | reader->readbyte = mp_reader_ric_readbyte; 106 | reader->close = mp_reader_ric_close; 107 | } 108 | -------------------------------------------------------------------------------- /components/micropython/cppif/FileSysReader.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // RIC Micropython 4 | // 5 | // Rob Dobson 2016-20 6 | // 7 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | class FileSysReader 14 | { 15 | public: 16 | static const int CHARS_TO_CACHE = 50; 17 | FileSysReader(const char* filename); 18 | int read(); 19 | void close(); 20 | 21 | static const int MAX_FILE_PATH_LEN = 200; 22 | char _filePath[MAX_FILE_PATH_LEN]; 23 | uint8_t _buf[CHARS_TO_CACHE]; 24 | uint32_t _cacheLen; 25 | uint32_t _cachePos; 26 | bool _isFinal; 27 | uint32_t _filePos; 28 | }; 29 | -------------------------------------------------------------------------------- /components/micropython/cppif/MicropyExecTask.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // RIC Micropython 4 | // 5 | // Rob Dobson 2016-20 6 | // 7 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | #pragma once 10 | 11 | #include "string.h" 12 | 13 | class MicropyExecTask 14 | { 15 | public: 16 | MicropyExecTask() 17 | { 18 | _pExecStr = NULL; 19 | _execStrBufLen = 0; 20 | _isFile = false; 21 | } 22 | virtual ~MicropyExecTask() 23 | { 24 | if (_pExecStr) 25 | delete _pExecStr; 26 | } 27 | 28 | MicropyExecTask(const char* execStr, bool isFile) 29 | { 30 | _execStrBufLen = strlen(execStr)+1; 31 | _pExecStr = new char[_execStrBufLen]; 32 | if (_pExecStr) 33 | memcpy(_pExecStr, execStr, _execStrBufLen); 34 | _isFile = isFile; 35 | } 36 | 37 | MicropyExecTask& operator=(const MicropyExecTask& other) 38 | { 39 | if (_pExecStr) 40 | delete _pExecStr; 41 | _pExecStr = NULL; 42 | _execStrBufLen = 0; 43 | if (other._pExecStr) 44 | { 45 | _execStrBufLen = other._execStrBufLen; 46 | _pExecStr = new char[_execStrBufLen]; 47 | if (_pExecStr) 48 | memcpy(_pExecStr, other._pExecStr, _execStrBufLen); 49 | } 50 | _isFile = other._isFile; 51 | return *this; 52 | } 53 | 54 | MicropyExecTask(const MicropyExecTask& other) 55 | { 56 | operator=(other); 57 | } 58 | 59 | char* _pExecStr; 60 | int _execStrBufLen; 61 | bool _isFile; 62 | }; 63 | -------------------------------------------------------------------------------- /components/micropython/cppif/Micropython.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // RIC Micropython 4 | // 5 | // Rob Dobson 2016-20 6 | // 7 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | #include "Micropython.h" 10 | 11 | #include "esp_system.h" 12 | #include "esp_task.h" 13 | #include "soc/cpu.h" 14 | #include "esp_log.h" 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | #include "py/mperrno.h" 20 | #include "py/runtime.h" 21 | #include "py/stackctrl.h" 22 | #include "py/gc.h" 23 | #include "py/lexer.h" 24 | #include "mphal.h" 25 | #include "lib/mp-readline/readline.h" 26 | #include "lib/utils/pyexec.h" 27 | #include "esp32/spiram.h" 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | // Consts and Statics 34 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | 36 | // Logging 37 | static const char* MODULE_PREFIX = "uPy"; 38 | 39 | // Debug 40 | // #define MICROPYTHON_DEBUG_SUBSCRIPTIONS 41 | 42 | // This will be set when start() is called 43 | uint32_t Micropython::_mpSubThreadStackSize = 0; 44 | 45 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 46 | // Constructor / Destructor 47 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | 49 | Micropython::Micropython() 50 | { 51 | mp_main_task_handle = NULL; 52 | _isStarted = false; 53 | _isPythonProgramRunning = false; 54 | 55 | // Event callback 56 | _eventCallback = mp_const_none; 57 | } 58 | 59 | Micropython::~Micropython() 60 | { 61 | } 62 | 63 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 64 | // Start 65 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 66 | 67 | void Micropython::start(bool useSPIRAM, bool useAllStdHeapAvail, uint32_t maxHeapToUse, 68 | uint32_t taskPriority, uint32_t taskStackSize) 69 | { 70 | if (_isStarted) 71 | return; 72 | _useSPIRAM = useSPIRAM; 73 | _useAllStdHeapAvail = useAllStdHeapAvail; 74 | _maxHeapToUse = maxHeapToUse; 75 | _mpSubThreadStackSize = taskStackSize; 76 | 77 | // Start task 78 | xTaskCreatePinnedToCore(mp_task, "mp_task", taskStackSize, this, 79 | taskPriority, &mp_main_task_handle, MP_TASK_COREID); 80 | 81 | // Started 82 | _isStarted = true; 83 | } 84 | 85 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 86 | // Stop 87 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 88 | 89 | void Micropython::stopExecution(bool clearQueue, bool stopExisting) 90 | { 91 | ESP_LOGI(MODULE_PREFIX, "stopExecution clearQueue %d stopExisting %d isRunning %d", 92 | clearQueue, stopExisting, _isPythonProgramRunning); 93 | 94 | // Clear queue if required 95 | if (clearQueue) 96 | _execQueue.clear(); 97 | 98 | // Request stop running task 99 | if (_isPythonProgramRunning && stopExisting) 100 | mp_keyboard_interrupt(); 101 | } 102 | 103 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 104 | // Add to queue 105 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 106 | 107 | void Micropython::addToQueue(const char* pyStr, bool clearQueue, bool stopExisting) 108 | { 109 | // Handle stopping 110 | stopExecution(clearQueue, stopExisting); 111 | 112 | // Add to queue 113 | MicropyExecTask task(pyStr, true); 114 | _execQueue.put(task); 115 | } 116 | 117 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 118 | // Register event callback 119 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 120 | 121 | void Micropython::regEventCallback(void* callbackObj) 122 | { 123 | ESP_LOGI(MODULE_PREFIX, "regEventCallback"); 124 | _eventCallback = callbackObj; 125 | } 126 | 127 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 128 | // Pass event to micropython - calls callback if specified 129 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 130 | 131 | void Micropython::performEventCallback(const char* pJsonStr) 132 | { 133 | mp_obj_t callbackObj = MP_OBJ_FROM_PTR(_eventCallback); 134 | if (callbackObj != mp_const_none) 135 | { 136 | mp_obj_t arg = mp_obj_new_str(pJsonStr, strlen(pJsonStr)); 137 | // ESP_LOGI(MODULE_PREFIX, "performEventCallback %p", MP_OBJ_TO_PTR(arg)); 138 | mp_sched_schedule(callbackObj, arg); 139 | } 140 | } 141 | 142 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 143 | // Micropython task 144 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 145 | 146 | void Micropython::mp_task(void *pvParameter) 147 | { 148 | Micropython* pThis = (Micropython*)pvParameter; 149 | volatile uint32_t sp = (uint32_t)get_sp(); 150 | 151 | #if MICROPY_PY_THREAD 152 | mp_thread_init(pxTaskGetStackStart(NULL), _mpSubThreadStackSize / sizeof(uintptr_t)); 153 | #endif 154 | 155 | // Check memory to use 156 | uint8_t* mp_task_heap = NULL; 157 | size_t mp_task_heap_size = 0; 158 | if (pThis->_useAllStdHeapAvail) 159 | mp_task_heap_size = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); 160 | else 161 | mp_task_heap_size = pThis->_maxHeapToUse; 162 | mp_task_heap = (uint8_t*)malloc(mp_task_heap_size); 163 | ESP_LOGI(MODULE_PREFIX, "mp_task StdHeap size %d bytes ok %d", mp_task_heap_size, mp_task_heap != NULL); 164 | 165 | // Check heap ok 166 | if (!mp_task_heap || (mp_task_heap_size == 0)) 167 | { 168 | // Delete task if it exits 169 | vTaskDelete(NULL); 170 | } 171 | 172 | // initialise the stack pointer for the main thread 173 | mp_stack_set_top((void *)sp); 174 | mp_stack_set_limit(_mpSubThreadStackSize - 1024); 175 | gc_init(mp_task_heap, mp_task_heap + mp_task_heap_size); 176 | mp_init(); 177 | mp_obj_list_init((mp_obj_list_t*)mp_sys_path, 0); 178 | mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); 179 | mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); 180 | mp_obj_list_init((mp_obj_list_t*)mp_sys_argv, 0); 181 | readline_init0(); 182 | 183 | // Loop monitoring for MicropyExecTask(s) and executes 184 | while(1) 185 | { 186 | // See if anything queued up for Micropython to do 187 | MicropyExecTask task; 188 | if (pThis->_execQueue.get(task)) 189 | { 190 | pThis->_isPythonProgramRunning = true; 191 | if (task._isFile && task._pExecStr) 192 | { 193 | int rslt = pyexec_file_if_exists(task._pExecStr); 194 | pThis->_isPythonProgramRunning = false; 195 | ESP_LOGI(MODULE_PREFIX, "mp_task exec %s rslt %d", task._pExecStr, rslt); 196 | } 197 | } 198 | // Allow other threads a look-in 199 | vTaskDelay(1); 200 | } 201 | } 202 | 203 | 204 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 205 | // Helpers 206 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 207 | 208 | int vprintf_null(const char *format, va_list ap) { 209 | // do nothing: this is used as a log target during raw repl mode 210 | return 0; 211 | } 212 | 213 | // This is a fiddle to allow a test file to run 214 | mp_import_stat_t mp_import_stat(const char *path) { 215 | return MP_IMPORT_STAT_FILE; 216 | } 217 | 218 | void nlr_jump_fail(void *val) { 219 | printf("NLR jump failed, val=%p\n", val); 220 | esp_restart(); 221 | } 222 | 223 | -------------------------------------------------------------------------------- /components/micropython/cppif/Micropython.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // RIC Micropython 4 | // 5 | // Rob Dobson 2016-20 6 | // 7 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include "MicropyExecTask.h" 14 | #include 15 | #include "freertos/FreeRTOS.h" 16 | #include "freertos/task.h" 17 | 18 | class Micropython 19 | { 20 | public: 21 | Micropython(); 22 | virtual ~Micropython(); 23 | 24 | // Start micropython 25 | void start(bool useSPIRAM, bool useAllStdHeapAvail, uint32_t maxHeapToUse, 26 | uint32_t taskPriority, uint32_t taskStackSize); 27 | 28 | // Add to task queue 29 | void addToQueue(const char* filename, bool clearQueue, bool stopExisting); 30 | 31 | // Register event callback 32 | void regEventCallback(void* callbackObj); 33 | 34 | // Perform event callback 35 | void performEventCallback(const char* pJsonStr); 36 | 37 | // Stop executing / clear queue 38 | void stopExecution(bool clearQueue, bool stopExisting); 39 | 40 | private: 41 | static void mp_task(void *pvParameter); 42 | 43 | // Queue for micropython execution 44 | static const int EXEC_QUEUE_SIZE = 3; 45 | RingBufferRTOS _execQueue; 46 | 47 | // Task handle 48 | TaskHandle_t mp_main_task_handle; 49 | bool _isStarted; 50 | 51 | // Python program running 52 | volatile bool _isPythonProgramRunning; 53 | 54 | // Heap details 55 | volatile bool _useSPIRAM; 56 | volatile bool _useAllStdHeapAvail; 57 | volatile uint32_t _maxHeapToUse; 58 | 59 | // Sub-thread stack size 60 | static uint32_t _mpSubThreadStackSize; 61 | 62 | // Event callback 63 | void* _eventCallback; 64 | }; 65 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/Makefile: -------------------------------------------------------------------------------- 1 | # Select the board to build for: if not given on the command line, 2 | # then default to GENERIC. 3 | BOARD ?= GENERIC 4 | 5 | # If the build directory is not given, make it reflect the board name. 6 | BUILD ?= build-$(BOARD) 7 | 8 | BOARD_DIR ?= boards/$(BOARD) 9 | ifeq ($(wildcard $(BOARD_DIR)/.),) 10 | $(error Invalid BOARD specified: $(BOARD_DIR)) 11 | endif 12 | 13 | include ../../py/mkenv.mk 14 | 15 | # Optional (not currently used for ESP32) 16 | -include mpconfigport.mk 17 | 18 | ifneq ($(SDKCONFIG),) 19 | $(error Use the BOARD variable instead of SDKCONFIG) 20 | endif 21 | 22 | # Expected to set SDKCONFIG 23 | include $(BOARD_DIR)/mpconfigboard.mk 24 | 25 | # qstr definitions (must come before including py.mk) 26 | QSTR_DEFS = qstrdefsport.h 27 | QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h 28 | QSTR_GLOBAL_REQUIREMENTS = $(SDKCONFIG_H) 29 | 30 | # MicroPython feature configurations 31 | MICROPY_ROM_TEXT_COMPRESSION ?= 1 32 | MICROPY_PY_USSL = 0 33 | MICROPY_SSL_AXTLS = 0 34 | MICROPY_PY_BTREE = 0 35 | MICROPY_VFS_FAT = 0 36 | MICROPY_VFS_LFS2 = 0 37 | 38 | FROZEN_MANIFEST ?= boards/manifest.py 39 | 40 | # include py core make definitions 41 | include $(TOP)/py/py.mk 42 | 43 | GIT_SUBMODULES = lib/berkeley-db-1.xx 44 | 45 | PORT ?= /dev/ttyUSB0 46 | BAUD ?= 460800 47 | FLASH_MODE ?= dio 48 | FLASH_FREQ ?= 40m 49 | FLASH_SIZE ?= 4MB 50 | CROSS_COMPILE ?= xtensa-esp32-elf- 51 | OBJDUMP = $(CROSS_COMPILE)objdump 52 | 53 | SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined 54 | SDKCONFIG_H = $(BUILD)/sdkconfig.h 55 | 56 | # The git hash of the currently supported ESP IDF version. 57 | # These correspond to v3.3.2 and v4.0.1. 58 | ESPIDF_SUPHASH_V3 := 9e70825d1e1cbf7988cf36981774300066580ea7 59 | ESPIDF_SUPHASH_V4 := 4c81978a3e2220674a432a588292a4c860eef27b 60 | 61 | define print_supported_git_hash 62 | $(info Supported git hash (v3.3): $(ESPIDF_SUPHASH_V3)) 63 | $(info Supported git hash (v4.0) (experimental): $(ESPIDF_SUPHASH_V4)) 64 | endef 65 | 66 | # paths to ESP IDF and its components 67 | ifeq ($(ESPIDF),) 68 | ifneq ($(IDF_PATH),) 69 | ESPIDF = $(IDF_PATH) 70 | else 71 | $(info The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.) 72 | $(info See README.md for installation instructions.) 73 | dummy := $(call print_supported_git_hash) 74 | $(error ESPIDF not set) 75 | endif 76 | endif 77 | 78 | ESPCOMP = $(ESPIDF)/components 79 | ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py 80 | ESPCOMP_KCONFIGS = $(shell find $(ESPCOMP) -name Kconfig) 81 | ESPCOMP_KCONFIGS_PROJBUILD = $(shell find $(ESPCOMP) -name Kconfig.projbuild) 82 | 83 | # verify the ESP IDF version 84 | ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H') 85 | 86 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) 87 | $(info Building with ESP IDF v3) 88 | else ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 89 | $(info Building with ESP IDF v4) 90 | 91 | PYPARSING_VERSION = $(shell python3 -c 'import pyparsing; print(pyparsing.__version__)') 92 | ifneq ($(PYPARSING_VERSION),2.3.1) 93 | $(info ** ERROR **) 94 | $(info EDP IDF requires pyparsing version less than 2.4) 95 | $(info You will need to set up a Python virtual environment with pyparsing 2.3.1) 96 | $(info Please see README.md for more information) 97 | $(error Incorrect pyparsing version) 98 | endif 99 | else 100 | $(info ** WARNING **) 101 | $(info The git hash of ESP IDF does not match the supported version) 102 | $(info The build may complete and the firmware may work but it is not guaranteed) 103 | $(info ESP IDF path: $(ESPIDF)) 104 | $(info Current git hash: $(ESPIDF_CURHASH)) 105 | dummy := $(call print_supported_git_hash) 106 | endif 107 | 108 | # pretty format of ESP IDF version, used internally by the IDF 109 | IDF_VER := $(shell git -C $(ESPIDF) describe) 110 | 111 | ifeq ($(shell which $(CC) 2> /dev/null),) 112 | $(info ** ERROR **) 113 | $(info Cannot find C compiler $(CC)) 114 | $(info Add the xtensa toolchain to your PATH. See README.md) 115 | $(error C compiler missing) 116 | endif 117 | 118 | # Support BLE by default. 119 | # Can be explicitly disabled on the command line or board config. 120 | MICROPY_PY_BLUETOOTH ?= 0 121 | ifeq ($(MICROPY_PY_BLUETOOTH),1) 122 | SDKCONFIG += boards/sdkconfig.ble 123 | 124 | # Use NimBLE on ESP32. 125 | MICROPY_BLUETOOTH_NIMBLE ?= 0 126 | # Use Nimble bindings, but ESP32 IDF provides the Nimble library. 127 | MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY = 1 128 | include $(TOP)/extmod/nimble/nimble.mk 129 | endif 130 | 131 | # include sdkconfig to get needed configuration values 132 | include $(SDKCONFIG) 133 | 134 | ################################################################################ 135 | # Compiler and linker flags 136 | 137 | INC += -I. 138 | INC += -I$(TOP) 139 | INC += -I$(TOP)/lib/mp-readline 140 | INC += -I$(TOP)/lib/netutils 141 | INC += -I$(TOP)/lib/timeutils 142 | INC += -I$(BUILD) 143 | 144 | INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include 145 | INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include_bootloader 146 | INC_ESPCOMP += -I$(ESPCOMP)/console 147 | INC_ESPCOMP += -I$(ESPCOMP)/driver/include 148 | INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver 149 | INC_ESPCOMP += -I$(ESPCOMP)/efuse/include 150 | INC_ESPCOMP += -I$(ESPCOMP)/efuse/esp32/include 151 | INC_ESPCOMP += -I$(ESPCOMP)/esp32/include 152 | INC_ESPCOMP += -I$(ESPCOMP)/espcoredump/include 153 | INC_ESPCOMP += -I$(ESPCOMP)/soc/include 154 | INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include 155 | INC_ESPCOMP += -I$(ESPCOMP)/heap/include 156 | INC_ESPCOMP += -I$(ESPCOMP)/log/include 157 | INC_ESPCOMP += -I$(ESPCOMP)/nvs_flash/include 158 | INC_ESPCOMP += -I$(ESPCOMP)/freertos/include 159 | INC_ESPCOMP += -I$(ESPCOMP)/esp_ringbuf/include 160 | INC_ESPCOMP += -I$(ESPCOMP)/esp_event/include 161 | INC_ESPCOMP += -I$(ESPCOMP)/tcpip_adapter/include 162 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/lwip/src/include 163 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/port/esp32/include 164 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps 165 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps/sntp 166 | INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include 167 | INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include 168 | INC_ESPCOMP += -I$(ESPCOMP)/mdns/include 169 | INC_ESPCOMP += -I$(ESPCOMP)/mdns/private_include 170 | INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include 171 | INC_ESPCOMP += -I$(ESPCOMP)/ulp/include 172 | INC_ESPCOMP += -I$(ESPCOMP)/vfs/include 173 | INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include 174 | INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include 175 | INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/port/include 176 | INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include 177 | INC_ESPCOMP += -I$(ESPCOMP)/app_update/include 178 | INC_ESPCOMP += -I$(ESPCOMP)/pthread/include 179 | INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include 180 | INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include 181 | 182 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 183 | INC_ESPCOMP += -I$(ESPCOMP)/esp_common/include 184 | INC_ESPCOMP += -I$(ESPCOMP)/esp_eth/include 185 | INC_ESPCOMP += -I$(ESPCOMP)/esp_event/private_include 186 | INC_ESPCOMP += -I$(ESPCOMP)/esp_rom/include 187 | INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/include 188 | INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/esp32/include 189 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps/sntp 190 | INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/private_include 191 | INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include/esp_supplicant 192 | INC_ESPCOMP += -I$(ESPCOMP)/xtensa/include 193 | INC_ESPCOMP += -I$(ESPCOMP)/xtensa/esp32/include 194 | ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) 195 | INC_ESPCOMP += -I$(ESPCOMP)/bt/include 196 | INC_ESPCOMP += -I$(ESPCOMP)/bt/common/osi/include 197 | INC_ESPCOMP += -I$(ESPCOMP)/bt/common/btc/include 198 | INC_ESPCOMP += -I$(ESPCOMP)/bt/common/include 199 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/porting/nimble/include 200 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/port/include 201 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/include 202 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/include 203 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ans/include 204 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/bas/include 205 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gap/include 206 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gatt/include 207 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ias/include 208 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/lls/include 209 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/tps/include 210 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/util/include 211 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/ram/include 212 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/include 213 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/porting/npl/freertos/include 214 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/ext/tinycrypt/include 215 | INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/esp-hci/include 216 | endif 217 | else 218 | INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include 219 | INC_ESPCOMP += -I$(ESPCOMP)/expat/expat/expat/lib 220 | INC_ESPCOMP += -I$(ESPCOMP)/expat/port/include 221 | INC_ESPCOMP += -I$(ESPCOMP)/json/include 222 | INC_ESPCOMP += -I$(ESPCOMP)/json/port/include 223 | INC_ESPCOMP += -I$(ESPCOMP)/micro-ecc/micro-ecc 224 | INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include 225 | INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes 226 | ifeq ($(CONFIG_NIMBLE_ENABLED),y) 227 | INC_ESPCOMP += -I$(ESPCOMP)/bt/include 228 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/porting/nimble/include 229 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/port/include 230 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/include 231 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/include 232 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/ans/include 233 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/bas/include 234 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/gap/include 235 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/gatt/include 236 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/ias/include 237 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/lls/include 238 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/tps/include 239 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/util/include 240 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/store/ram/include 241 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/store/config/include 242 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/porting/npl/freertos/include 243 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/ext/tinycrypt/include 244 | INC_ESPCOMP += -I$(ESPCOMP)/nimble/esp-hci/include 245 | endif 246 | endif 247 | 248 | INC_NEWLIB += -I$(ESPCOMP)/newlib/platform_include 249 | INC_NEWLIB += -I$(ESPCOMP)/newlib/include 250 | 251 | ifeq ($(MICROPY_PY_BLUETOOTH),1) 252 | CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 253 | CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 254 | endif 255 | 256 | # these flags are common to C and C++ compilation 257 | CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ 258 | -mlongcalls -nostdlib \ 259 | -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable \ 260 | -Wno-error=unused-variable -Wno-error=deprecated-declarations \ 261 | -DESP_PLATFORM 262 | 263 | CFLAGS_BASE = -std=gnu99 $(CFLAGS_COMMON) -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H 264 | CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_ESPCOMP) $(INC_NEWLIB) 265 | CFLAGS += -DIDF_VER=\"$(IDF_VER)\" 266 | CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) 267 | CFLAGS += -I$(BOARD_DIR) 268 | 269 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 270 | CFLAGS += -DMICROPY_ESP_IDF_4=1 271 | endif 272 | 273 | # this is what ESPIDF uses for c++ compilation 274 | CXXFLAGS = -std=gnu++11 $(CFLAGS_COMMON) $(INC) $(INC_ESPCOMP) 275 | 276 | LDFLAGS = -nostdlib -Map=$(@:.elf=.map) --cref 277 | LDFLAGS += --gc-sections -static -EL 278 | LDFLAGS += -u call_user_start_cpu0 -u uxTopUsedPriority -u ld_include_panic_highint_hdl 279 | LDFLAGS += -u __cxa_guard_dummy # so that implementation of static guards is taken from cxx_guards.o instead of libstdc++.a 280 | LDFLAGS += -L$(ESPCOMP)/esp32/ld 281 | LDFLAGS += -L$(ESPCOMP)/esp_rom/esp32/ld 282 | LDFLAGS += -T $(BUILD)/esp32_out.ld 283 | LDFLAGS += -T $(BUILD)/esp32.project.ld 284 | LDFLAGS += -T esp32.rom.ld 285 | LDFLAGS += -T esp32.rom.libgcc.ld 286 | LDFLAGS += -T esp32.peripherals.ld 287 | 288 | LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) 289 | LIBSTDCXX_FILE_NAME = $(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a) 290 | 291 | # Debugging/Optimization 292 | ifeq ($(DEBUG), 1) 293 | CFLAGS += -g 294 | COPT = -O0 295 | else 296 | #CFLAGS += -fdata-sections -ffunction-sections 297 | COPT += -Os -DNDEBUG 298 | #LDFLAGS += --gc-sections 299 | endif 300 | 301 | # Options for mpy-cross 302 | MPY_CROSS_FLAGS += -march=xtensawin 303 | 304 | # Enable SPIRAM support if CONFIG_ESP32_SPIRAM_SUPPORT=y in sdkconfig 305 | ifeq ($(CONFIG_ESP32_SPIRAM_SUPPORT),y) 306 | CFLAGS_COMMON += -mfix-esp32-psram-cache-issue 307 | LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc-psram-workaround.a $(ESPCOMP)/newlib/lib/libm-psram-workaround.a 308 | else 309 | # Additional newlib symbols that can only be used with spiram disabled. 310 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 311 | LDFLAGS += -T esp32.rom.newlib-funcs.ld 312 | LDFLAGS += -T esp32.rom.newlib-locale.ld 313 | LDFLAGS += -T esp32.rom.newlib-data.ld 314 | else 315 | LDFLAGS += -T esp32.rom.spiram_incompatible_fns.ld 316 | endif 317 | LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc.a $(ESPCOMP)/newlib/lib/libm.a 318 | endif 319 | 320 | ################################################################################ 321 | # List of MicroPython source and object files 322 | 323 | SRC_C = \ 324 | main.c \ 325 | gccollect.c \ 326 | mphalport.c \ 327 | help.c \ 328 | modutime.c \ 329 | mpthreadport.c \ 330 | $(wildcard $(BOARD_DIR)/*.c) \ 331 | $(SRC_MOD) 332 | 333 | EXTMOD_SRC_C += $(addprefix extmod/,\ 334 | modonewire.c \ 335 | ) 336 | 337 | LIB_SRC_C = $(addprefix lib/,\ 338 | mbedtls_errors/mp_mbedtls_errors.c \ 339 | mp-readline/readline.c \ 340 | netutils/netutils.c \ 341 | timeutils/timeutils.c \ 342 | utils/pyexec.c \ 343 | utils/interrupt_char.c \ 344 | utils/sys_stdio_mphal.c \ 345 | ) 346 | 347 | DRIVERS_SRC_C = $(addprefix drivers/,\ 348 | bus/softspi.c \ 349 | dht/dht.c \ 350 | ) 351 | 352 | OBJ_MP = 353 | OBJ_MP += $(PY_O) 354 | OBJ_MP += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) 355 | OBJ_MP += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) 356 | OBJ_MP += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) 357 | OBJ_MP += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) 358 | 359 | # Only enable this for the MicroPython source: ignore warnings from esp-idf. 360 | $(OBJ_MP): CFLAGS += -Wdouble-promotion -Wfloat-conversion 361 | 362 | # List of sources for qstr extraction 363 | SRC_QSTR += $(SRC_C) $(EXTMOD_SRC_C) $(LIB_SRC_C) $(DRIVERS_SRC_C) 364 | # Append any auto-generated sources that are needed by sources listed in SRC_QSTR 365 | SRC_QSTR_AUTO_DEPS += 366 | 367 | ################################################################################ 368 | # Generate sdkconfig.h from sdkconfig 369 | 370 | $(SDKCONFIG_COMBINED): $(SDKCONFIG) 371 | $(Q)$(MKDIR) -p $(dir $@) 372 | $(Q)$(CAT) $^ > $@ 373 | 374 | $(SDKCONFIG_H): $(SDKCONFIG_COMBINED) 375 | $(ECHO) "GEN $@" 376 | $(Q)$(MKDIR) -p $(dir $@) 377 | $(Q)$(PYTHON) $(ESPIDF)/tools/kconfig_new/confgen.py \ 378 | --output header $@ \ 379 | --config $< \ 380 | --kconfig $(ESPIDF)/Kconfig \ 381 | --env "IDF_TARGET=esp32" \ 382 | --env "IDF_CMAKE=n" \ 383 | --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ 384 | --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ 385 | --env "IDF_PATH=$(ESPIDF)" 386 | $(Q)touch $@ 387 | 388 | $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) $(BOARD_DIR)/mpconfigboard.h 389 | 390 | ################################################################################ 391 | # List of object files from the ESP32 IDF components 392 | 393 | ESPIDF_BOOTLOADER_SUPPORT_O = $(patsubst %.c,%.o,\ 394 | $(filter-out $(ESPCOMP)/bootloader_support/src/bootloader_init.c,\ 395 | $(wildcard $(ESPCOMP)/bootloader_support/src/*.c) \ 396 | $(wildcard $(ESPCOMP)/bootloader_support/src/idf/*.c) \ 397 | )) 398 | 399 | ESPIDF_DRIVER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/driver/*.c)) 400 | 401 | ESPIDF_EFUSE_O = $(patsubst %.c,%.o,\ 402 | $(wildcard $(ESPCOMP)/efuse/esp32/*.c)\ 403 | $(wildcard $(ESPCOMP)/efuse/src/*.c)\ 404 | ) 405 | 406 | $(BUILD)/$(ESPCOMP)/esp32/dport_access.o: CFLAGS += -Wno-array-bounds 407 | ESPIDF_ESP32_O = \ 408 | $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/*.c)) \ 409 | $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/hwcrypto/*.c)) \ 410 | $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/esp32/*.S)) \ 411 | 412 | ESPIDF_ESP_RINGBUF_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_ringbuf/*.c)) 413 | 414 | ESPIDF_HEAP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/heap/*.c)) 415 | 416 | ESPIDF_SOC_O = $(patsubst %.c,%.o,\ 417 | $(wildcard $(ESPCOMP)/soc/esp32/*.c) \ 418 | $(wildcard $(ESPCOMP)/soc/src/*.c) \ 419 | $(wildcard $(ESPCOMP)/soc/src/hal/*.c) \ 420 | ) 421 | 422 | $(BUILD)/$(ESPCOMP)/cxx/cxx_guards.o: CXXFLAGS += -Wno-error=sign-compare 423 | ESPIDF_CXX_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/cxx/*.cpp)) 424 | 425 | ESPIDF_PTHREAD_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/pthread/*.c)) 426 | 427 | # Assembler .S files need only basic flags, and in particular should not have 428 | # -Os because that generates subtly different code. 429 | # We also need custom CFLAGS for .c files because FreeRTOS has headers with 430 | # generic names (eg queue.h) which can clash with other files in the port. 431 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 432 | CFLAGS_ASM = -I$(BUILD) -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I. -I$(ESPCOMP)/xtensa/include -I$(ESPCOMP)/xtensa/esp32/include -I$(ESPCOMP)/esp_common/include 433 | else 434 | CFLAGS_ASM = -I$(BUILD) -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I. 435 | endif 436 | $(BUILD)/$(ESPCOMP)/freertos/portasm.o: CFLAGS = $(CFLAGS_ASM) 437 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_context.o: CFLAGS = $(CFLAGS_ASM) 438 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_intr_asm.o: CFLAGS = $(CFLAGS_ASM) 439 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_vectors.o: CFLAGS = $(CFLAGS_ASM) 440 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_vector_defaults.o: CFLAGS = $(CFLAGS_ASM) 441 | $(BUILD)/$(ESPCOMP)/freertos/%.o: CFLAGS = $(CFLAGS_BASE) -I. -I$(BUILD) $(INC_ESPCOMP) $(INC_NEWLIB) -I$(ESPCOMP)/freertos/include/freertos -D_ESP_FREERTOS_INTERNAL 442 | ESPIDF_FREERTOS_O = \ 443 | $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/freertos/*.c)) \ 444 | $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/freertos/*.S)) \ 445 | 446 | ESPIDF_VFS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/vfs/*.c)) 447 | 448 | ESPIDF_LOG_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/log/*.c)) 449 | 450 | ESPIDF_XTENSA_DEBUG_MODULE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/xtensa-debug-module/*.c)) 451 | 452 | ESPIDF_TCPIP_ADAPTER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/tcpip_adapter/*.c)) 453 | 454 | ESPIDF_APP_TRACE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_trace/*.c)) 455 | 456 | ESPIDF_APP_UPDATE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_update/*.c)) 457 | 458 | ESPIDF_NEWLIB_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/newlib/*.c)) 459 | 460 | $(BUILD)/$(ESPCOMP)/nvs_flash/src/nvs_api.o: CXXFLAGS += -Wno-error=sign-compare 461 | ESPIDF_NVS_FLASH_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/nvs_flash/src/*.cpp)) 462 | 463 | ESPIDF_SMARTCONFIG_ACK_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/smartconfig_ack/*.c)) 464 | 465 | ESPIDF_SPI_FLASH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/spi_flash/*.c)) 466 | 467 | ESPIDF_ULP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/ulp/*.c)) 468 | 469 | $(BUILD)/$(ESPCOMP)/lwip/%.o: CFLAGS += -Wno-address -Wno-unused-variable -Wno-unused-but-set-variable 470 | ESPIDF_LWIP_O = $(patsubst %.c,%.o,\ 471 | $(wildcard $(ESPCOMP)/lwip/apps/dhcpserver/*.c) \ 472 | $(wildcard $(ESPCOMP)/lwip/lwip/src/api/*.c) \ 473 | $(wildcard $(ESPCOMP)/lwip/lwip/src/apps/sntp/*.c) \ 474 | $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*.c) \ 475 | $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*/*.c) \ 476 | $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*.c) \ 477 | $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*.c) \ 478 | $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*/*.c) \ 479 | $(wildcard $(ESPCOMP)/lwip/port/esp32/*.c) \ 480 | $(wildcard $(ESPCOMP)/lwip/port/esp32/*/*.c) \ 481 | ) 482 | 483 | # Mbedtls source files, exclude error.c in favor of lib/mbedtls_errors/mp_mbedtls_errors.c 484 | ESPIDF_MBEDTLS_O = $(patsubst %.c,%.o, $(filter-out %/error.c,\ 485 | $(wildcard $(ESPCOMP)/mbedtls/mbedtls/library/*.c) \ 486 | $(wildcard $(ESPCOMP)/mbedtls/port/*.c) \ 487 | $(wildcard $(ESPCOMP)/mbedtls/port/esp32/*.c) \ 488 | )) 489 | 490 | ESPIDF_MDNS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/mdns/*.c)) 491 | 492 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 493 | $(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DCONFIG_WPA3_SAE -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing -I$(ESPCOMP)/wpa_supplicant/src -Wno-implicit-function-declaration 494 | else 495 | $(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DALLOW_EVEN_MOD -D__ets__ -Wno-strict-aliasing 496 | endif 497 | ESPIDF_WPA_SUPPLICANT_O = $(patsubst %.c,%.o,\ 498 | $(wildcard $(ESPCOMP)/wpa_supplicant/port/*.c) \ 499 | $(wildcard $(ESPCOMP)/wpa_supplicant/src/*/*.c) \ 500 | ) 501 | 502 | ESPIDF_SDMMC_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/sdmmc/*.c)) 503 | 504 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 505 | ESPIDF_ESP_COMMON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_common/src/*.c)) 506 | 507 | ESPIDF_ESP_EVENT_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_event/*.c)) 508 | 509 | ESPIDF_ESP_WIFI_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_wifi/src/*.c)) 510 | 511 | ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) 512 | ESPIDF_BT_NIMBLE_O = $(patsubst %.c,%.o,\ 513 | $(wildcard $(ESPCOMP)/bt/controller/*.c) \ 514 | $(wildcard $(ESPCOMP)/bt/common/btc/core/*.c) \ 515 | $(wildcard $(ESPCOMP)/bt/common/osi/*.c) \ 516 | $(wildcard $(ESPCOMP)/bt/host/nimble/esp-hci/src/*.c) \ 517 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/ext/tinycrypt/src/*.c) \ 518 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ans/src/*.c) \ 519 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/bas/src/*.c) \ 520 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gap/src/*.c) \ 521 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gatt/src/*.c) \ 522 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ias/src/*.c) \ 523 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/lls/src/*.c) \ 524 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/tps/src/*.c) \ 525 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/src/*.c) \ 526 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c) \ 527 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c) \ 528 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/ram/src/*.c) \ 529 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/util/src/*.c) \ 530 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/src/*.c) \ 531 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/nimble/src/*.c) \ 532 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/npl/freertos/src/*.c) \ 533 | $(wildcard $(ESPCOMP)/bt/host/nimble/port/src/*.c) \ 534 | ) 535 | endif 536 | 537 | $(BUILD)/$(ESPCOMP)/esp_eth/src/esp_eth_mac_dm9051.o: CFLAGS += -fno-strict-aliasing 538 | ESPIDF_ESP_ETH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_eth/src/*.c)) 539 | 540 | ESPIDF_XTENSA_O = $(patsubst %.c,%.o,\ 541 | $(wildcard $(ESPCOMP)/xtensa/*.c) \ 542 | $(wildcard $(ESPCOMP)/xtensa/esp32/*.c) \ 543 | ) 544 | else 545 | ESPIDF_JSON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/json/cJSON/cJSON*.c)) 546 | 547 | ESPIDF_ETHERNET_O = $(patsubst %.c,%.o,\ 548 | $(wildcard $(ESPCOMP)/ethernet/*.c) \ 549 | $(wildcard $(ESPCOMP)/ethernet/eth_phy/*.c) \ 550 | ) 551 | 552 | ifeq ($(CONFIG_NIMBLE_ENABLED),y) 553 | ESPIDF_BT_NIMBLE_O = $(patsubst %.c,%.o,\ 554 | $(wildcard $(ESPCOMP)/bt/*.c) \ 555 | $(wildcard $(ESPCOMP)/nimble/esp-hci/src/*.c) \ 556 | $(wildcard $(ESPCOMP)/nimble/nimble/ext/tinycrypt/src/*.c) \ 557 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/ans/src/*.c) \ 558 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/bas/src/*.c) \ 559 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/gap/src/*.c) \ 560 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/gatt/src/*.c) \ 561 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/ias/src/*.c) \ 562 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/lls/src/*.c) \ 563 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/tps/src/*.c) \ 564 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/src/*.c) \ 565 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/store/config/src/ble_store_config.c) \ 566 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c) \ 567 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/store/ram/src/*.c) \ 568 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/util/src/*.c) \ 569 | $(wildcard $(ESPCOMP)/nimble/nimble/nimble/src/*.c) \ 570 | $(wildcard $(ESPCOMP)/nimble/nimble/porting/nimble/src/*.c) \ 571 | $(wildcard $(ESPCOMP)/nimble/nimble/porting/npl/freertos/src/*.c) \ 572 | $(wildcard $(ESPCOMP)/nimble/port/src/*.c) \ 573 | ) 574 | endif 575 | endif 576 | 577 | OBJ_ESPIDF = 578 | LIB_ESPIDF = 579 | BUILD_ESPIDF_LIB = $(BUILD)/esp-idf 580 | 581 | define gen_espidf_lib_rule 582 | OBJ_ESPIDF += $(addprefix $$(BUILD)/,$(2)) 583 | LIB_ESPIDF += $(1) 584 | $(BUILD_ESPIDF_LIB)/$(1)/lib$(1).a: $(addprefix $$(BUILD)/,$(2)) 585 | $(ECHO) "AR $$@" 586 | $(Q)$(AR) cru $$@ $$^ 587 | endef 588 | 589 | $(eval $(call gen_espidf_lib_rule,bootloader_support,$(ESPIDF_BOOTLOADER_SUPPORT_O))) 590 | $(eval $(call gen_espidf_lib_rule,driver,$(ESPIDF_DRIVER_O))) 591 | $(eval $(call gen_espidf_lib_rule,efuse,$(ESPIDF_EFUSE_O))) 592 | $(eval $(call gen_espidf_lib_rule,esp32,$(ESPIDF_ESP32_O))) 593 | $(eval $(call gen_espidf_lib_rule,esp_ringbuf,$(ESPIDF_ESP_RINGBUF_O))) 594 | $(eval $(call gen_espidf_lib_rule,heap,$(ESPIDF_HEAP_O))) 595 | $(eval $(call gen_espidf_lib_rule,soc,$(ESPIDF_SOC_O))) 596 | $(eval $(call gen_espidf_lib_rule,cxx,$(ESPIDF_CXX_O))) 597 | $(eval $(call gen_espidf_lib_rule,pthread,$(ESPIDF_PTHREAD_O))) 598 | $(eval $(call gen_espidf_lib_rule,freertos,$(ESPIDF_FREERTOS_O))) 599 | $(eval $(call gen_espidf_lib_rule,vfs,$(ESPIDF_VFS_O))) 600 | $(eval $(call gen_espidf_lib_rule,json,$(ESPIDF_JSON_O))) 601 | $(eval $(call gen_espidf_lib_rule,log,$(ESPIDF_LOG_O))) 602 | $(eval $(call gen_espidf_lib_rule,xtensa-debug-module,$(ESPIDF_XTENSA_DEBUG_MODULE_O))) 603 | $(eval $(call gen_espidf_lib_rule,tcpip_adapter,$(ESPIDF_TCPIP_ADAPTER_O))) 604 | $(eval $(call gen_espidf_lib_rule,app_trace,$(ESPIDF_APP_TRACE_O))) 605 | $(eval $(call gen_espidf_lib_rule,app_update,$(ESPIDF_APP_UPDATE_O))) 606 | $(eval $(call gen_espidf_lib_rule,newlib,$(ESPIDF_NEWLIB_O))) 607 | $(eval $(call gen_espidf_lib_rule,nvs_flash,$(ESPIDF_NVS_FLASH_O))) 608 | $(eval $(call gen_espidf_lib_rule,smartconfig_ack,$(ESPIDF_SMARTCONFIG_ACK_O))) 609 | $(eval $(call gen_espidf_lib_rule,spi_flash,$(ESPIDF_SPI_FLASH_O))) 610 | $(eval $(call gen_espidf_lib_rule,ulp,$(ESPIDF_ULP_O))) 611 | $(eval $(call gen_espidf_lib_rule,lwip,$(ESPIDF_LWIP_O))) 612 | $(eval $(call gen_espidf_lib_rule,mbedtls,$(ESPIDF_MBEDTLS_O))) 613 | $(eval $(call gen_espidf_lib_rule,mdns,$(ESPIDF_MDNS_O))) 614 | $(eval $(call gen_espidf_lib_rule,wpa_supplicant,$(ESPIDF_WPA_SUPPLICANT_O))) 615 | $(eval $(call gen_espidf_lib_rule,sdmmc,$(ESPIDF_SDMMC_O))) 616 | $(eval $(call gen_espidf_lib_rule,bt_nimble,$(ESPIDF_BT_NIMBLE_O))) 617 | 618 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 619 | $(eval $(call gen_espidf_lib_rule,esp_common,$(ESPIDF_ESP_COMMON_O))) 620 | $(eval $(call gen_espidf_lib_rule,esp_event,$(ESPIDF_ESP_EVENT_O))) 621 | $(eval $(call gen_espidf_lib_rule,esp_wifi,$(ESPIDF_ESP_WIFI_O))) 622 | $(eval $(call gen_espidf_lib_rule,esp_eth,$(ESPIDF_ESP_ETH_O))) 623 | $(eval $(call gen_espidf_lib_rule,xtensa,$(ESPIDF_XTENSA_O))) 624 | else 625 | $(eval $(call gen_espidf_lib_rule,ethernet,$(ESPIDF_ETHERNET_O))) 626 | endif 627 | 628 | # Create all destination build dirs before compiling IDF source 629 | OBJ_ESPIDF_DIRS = $(sort $(dir $(OBJ_ESPIDF))) $(BUILD_ESPIDF_LIB) $(addprefix $(BUILD_ESPIDF_LIB)/,$(LIB_ESPIDF)) 630 | $(OBJ_ESPIDF): | $(OBJ_ESPIDF_DIRS) 631 | $(OBJ_ESPIDF_DIRS): 632 | $(MKDIR) -p $@ 633 | 634 | # Make all IDF object files depend on sdkconfig 635 | $(OBJ_ESPIDF): $(SDKCONFIG_H) 636 | 637 | # Add all IDF components to the set of libraries 638 | LIB = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) 639 | 640 | ################################################################################ 641 | # ESP IDF ldgen 642 | 643 | LDGEN_FRAGMENTS = $(shell find $(ESPCOMP) -name "*.lf") 644 | 645 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 646 | 647 | LDGEN_LIBRARIES=$(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) 648 | 649 | $(BUILD_ESPIDF_LIB)/ldgen_libraries: $(LDGEN_LIBRARIES) $(ESPIDF)/make/ldgen.mk 650 | printf "$(foreach library,$(LDGEN_LIBRARIES),$(library)\n)" > $(BUILD_ESPIDF_LIB)/ldgen_libraries 651 | 652 | $(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(BUILD_ESPIDF_LIB)/ldgen_libraries 653 | $(ECHO) "GEN $@" 654 | $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ 655 | --input $< \ 656 | --output $@ \ 657 | --config $(SDKCONFIG_COMBINED) \ 658 | --kconfig $(ESPIDF)/Kconfig \ 659 | --fragments $(LDGEN_FRAGMENTS) \ 660 | --libraries-file $(BUILD_ESPIDF_LIB)/ldgen_libraries \ 661 | --env "IDF_TARGET=esp32" \ 662 | --env "IDF_CMAKE=n" \ 663 | --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ 664 | --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ 665 | --env "IDF_PATH=$(ESPIDF)" \ 666 | --objdump $(OBJDUMP) 667 | 668 | else 669 | 670 | LDGEN_SECTIONS_INFO = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a.sections_info) 671 | LDGEN_SECTION_INFOS = $(BUILD_ESPIDF_LIB)/ldgen.section_infos 672 | 673 | define gen_sections_info_rule 674 | $(1).sections_info: $(1) 675 | $(ECHO) "GEN $(1).sections_info" 676 | $(Q)$(OBJDUMP) -h $(1) > $(1).sections_info 677 | endef 678 | 679 | $(eval $(foreach lib,$(LIB_ESPIDF),$(eval $(call gen_sections_info_rule,$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a)))) 680 | 681 | $(LDGEN_SECTION_INFOS): $(LDGEN_SECTIONS_INFO) $(ESPIDF)/make/ldgen.mk 682 | $(Q)printf "$(foreach info,$(LDGEN_SECTIONS_INFO),$(info)\n)" > $@ 683 | 684 | $(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(LDGEN_SECTION_INFOS) 685 | $(ECHO) "GEN $@" 686 | $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ 687 | --input $< \ 688 | --output $@ \ 689 | --config $(SDKCONFIG_COMBINED) \ 690 | --kconfig $(ESPIDF)/Kconfig \ 691 | --fragments $(LDGEN_FRAGMENTS) \ 692 | --sections $(LDGEN_SECTION_INFOS) \ 693 | --env "IDF_TARGET=esp32" \ 694 | --env "IDF_CMAKE=n" \ 695 | --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ 696 | --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ 697 | --env "IDF_PATH=$(ESPIDF)" 698 | 699 | endif 700 | 701 | ################################################################################ 702 | # Main targets 703 | 704 | all: $(BUILD)/firmware.bin 705 | 706 | .PHONY: idf-version deploy erase 707 | 708 | idf-version: 709 | $(ECHO) "ESP IDF supported hash: $(ESPIDF_SUPHASH)" 710 | 711 | $(BUILD)/firmware.bin: $(BUILD)/bootloader.bin $(BUILD)/partitions.bin $(BUILD)/application.bin 712 | $(ECHO) "Create $@" 713 | $(Q)$(PYTHON) makeimg.py $^ $@ 714 | 715 | deploy: $(BUILD)/firmware.bin 716 | $(ECHO) "Writing $^ to the board" 717 | $(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) write_flash -z --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) 0x1000 $^ 718 | 719 | erase: 720 | $(ECHO) "Erasing flash" 721 | $(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) erase_flash 722 | 723 | ################################################################################ 724 | # Declarations to build the application 725 | 726 | OBJ = $(OBJ_MP) 727 | 728 | APP_LD_ARGS = 729 | APP_LD_ARGS += $(LDFLAGS_MOD) 730 | APP_LD_ARGS += $(addprefix -T,$(LD_FILES)) 731 | APP_LD_ARGS += --start-group 732 | APP_LD_ARGS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc 733 | APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++ 734 | APP_LD_ARGS += $(LIBC_LIBM) 735 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 736 | APP_LD_ARGS += -L$(ESPCOMP)/xtensa/esp32 -lhal 737 | APP_LD_ARGS += -L$(ESPCOMP)/bt/controller/lib -lbtdm_app 738 | APP_LD_ARGS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lsmartconfig -lcoexist 739 | else 740 | APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a 741 | APP_LD_ARGS += -L$(ESPCOMP)/bt/lib -lbtdm_app 742 | APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lwpa -lsmartconfig -lcoexist -lwps -lwpa2 743 | endif 744 | APP_LD_ARGS += $(OBJ) 745 | APP_LD_ARGS += $(LIB) 746 | APP_LD_ARGS += --end-group 747 | 748 | $(BUILD)/esp32_out.ld: $(SDKCONFIG_H) 749 | $(Q)$(CC) -I$(BUILD) -C -P -x c -E $(ESPCOMP)/esp32/ld/esp32.ld -o $@ 750 | 751 | $(BUILD)/application.bin: $(BUILD)/application.elf 752 | $(ECHO) "Create $@" 753 | $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< 754 | 755 | $(BUILD)/application.elf: $(OBJ) $(LIB) $(BUILD)/esp32_out.ld $(BUILD)/esp32.project.ld 756 | $(ECHO) "LINK $@" 757 | $(Q)$(LD) $(LDFLAGS) -o $@ $(APP_LD_ARGS) 758 | $(Q)$(SIZE) $@ 759 | 760 | define compile_cxx 761 | $(ECHO) "CXX $<" 762 | $(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $< 763 | @# The following fixes the dependency file. 764 | @# See http://make.paulandlesley.org/autodep.html for details. 765 | @# Regex adjusted from the above to play better with Windows paths, etc. 766 | @$(CP) $(@:.o=.d) $(@:.o=.P); \ 767 | $(SED) -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' \ 768 | -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ 769 | $(RM) -f $(@:.o=.d) 770 | endef 771 | 772 | vpath %.cpp . $(TOP) 773 | $(BUILD)/%.o: %.cpp 774 | $(call compile_cxx) 775 | 776 | ################################################################################ 777 | # Declarations to build the bootloader 778 | 779 | BOOTLOADER_LIB_DIR = $(BUILD)/bootloader 780 | BOOTLOADER_LIB_ALL = 781 | 782 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 783 | $(BUILD)/bootloader/$(ESPCOMP)/%.o: CFLAGS += -DBOOTLOADER_BUILD=1 -I$(ESPCOMP)/bootloader_support/include_priv -I$(ESPCOMP)/bootloader_support/include -I$(ESPCOMP)/efuse/include -I$(ESPCOMP)/esp_rom/include -Wno-error=format \ 784 | -I$(ESPCOMP)/esp_common/include \ 785 | -I$(ESPCOMP)/xtensa/include \ 786 | -I$(ESPCOMP)/xtensa/esp32/include 787 | else 788 | $(BUILD)/bootloader/$(ESPCOMP)/%.o: CFLAGS += -DBOOTLOADER_BUILD=1 -I$(ESPCOMP)/bootloader_support/include_priv -I$(ESPCOMP)/bootloader_support/include -I$(ESPCOMP)/micro-ecc/micro-ecc -I$(ESPCOMP)/efuse/include -I$(ESPCOMP)/esp32 -Wno-error=format 789 | endif 790 | 791 | # libbootloader_support.a 792 | BOOTLOADER_LIB_ALL += bootloader_support 793 | BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 794 | bootloader_support/src/bootloader_clock.o \ 795 | bootloader_support/src/bootloader_common.o \ 796 | bootloader_support/src/bootloader_flash.o \ 797 | bootloader_support/src/bootloader_flash_config.o \ 798 | bootloader_support/src/bootloader_init.o \ 799 | bootloader_support/src/bootloader_random.o \ 800 | bootloader_support/src/bootloader_utility.o \ 801 | bootloader_support/src/flash_qio_mode.o \ 802 | bootloader_support/src/esp_image_format.o \ 803 | bootloader_support/src/flash_encrypt.o \ 804 | bootloader_support/src/flash_partitions.o \ 805 | ) 806 | 807 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 808 | BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 809 | bootloader_support/src/esp32/bootloader_sha.o \ 810 | bootloader_support/src/bootloader_flash_config.o \ 811 | bootloader_support/src/esp32/secure_boot.o \ 812 | ) 813 | else 814 | BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 815 | bootloader_support/src/bootloader_sha.o \ 816 | bootloader_support/src/secure_boot_signatures.o \ 817 | bootloader_support/src/secure_boot.o \ 818 | ) 819 | endif 820 | 821 | $(BOOTLOADER_LIB_DIR)/libbootloader_support.a: $(BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ) 822 | $(ECHO) "AR $@" 823 | $(Q)$(AR) cr $@ $^ 824 | 825 | # liblog.a 826 | BOOTLOADER_LIB_ALL += log 827 | BOOTLOADER_LIB_LOG_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 828 | log/log.o \ 829 | ) 830 | $(BOOTLOADER_LIB_DIR)/liblog.a: $(BOOTLOADER_LIB_LOG_OBJ) 831 | $(ECHO) "AR $@" 832 | $(Q)$(AR) cr $@ $^ 833 | 834 | # libspi_flash.a 835 | BOOTLOADER_LIB_ALL += spi_flash 836 | BOOTLOADER_LIB_SPI_FLASH_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 837 | spi_flash/spi_flash_rom_patch.o \ 838 | ) 839 | $(BOOTLOADER_LIB_DIR)/libspi_flash.a: $(BOOTLOADER_LIB_SPI_FLASH_OBJ) 840 | $(ECHO) "AR $@" 841 | $(Q)$(AR) cr $@ $^ 842 | 843 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) 844 | # libmicro-ecc.a 845 | BOOTLOADER_LIB_ALL += micro-ecc 846 | BOOTLOADER_LIB_MICRO_ECC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 847 | micro-ecc/micro-ecc/uECC.o \ 848 | ) 849 | $(BOOTLOADER_LIB_DIR)/libmicro-ecc.a: $(BOOTLOADER_LIB_MICRO_ECC_OBJ) 850 | $(ECHO) "AR $@" 851 | $(Q)$(AR) cr $@ $^ 852 | endif 853 | 854 | # libsoc.a 855 | $(BUILD)/bootloader/$(ESPCOMP)/soc/esp32/rtc_clk.o: CFLAGS += -fno-jump-tables -fno-tree-switch-conversion 856 | BOOTLOADER_LIB_ALL += soc 857 | BOOTLOADER_LIB_SOC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/soc/,\ 858 | esp32/cpu_util.o \ 859 | esp32/gpio_periph.o \ 860 | esp32/rtc_clk.o \ 861 | esp32/rtc_clk_init.o \ 862 | esp32/rtc_init.o \ 863 | esp32/rtc_periph.o \ 864 | esp32/rtc_pm.o \ 865 | esp32/rtc_sleep.o \ 866 | esp32/rtc_time.o \ 867 | esp32/rtc_wdt.o \ 868 | esp32/sdio_slave_periph.o \ 869 | esp32/sdmmc_periph.o \ 870 | esp32/soc_memory_layout.o \ 871 | esp32/spi_periph.o \ 872 | src/memory_layout_utils.o \ 873 | ) 874 | $(BOOTLOADER_LIB_DIR)/libsoc.a: $(BOOTLOADER_LIB_SOC_OBJ) 875 | $(ECHO) "AR $@" 876 | $(Q)$(AR) cr $@ $^ 877 | 878 | # libmain.a 879 | BOOTLOADER_LIB_ALL += main 880 | BOOTLOADER_LIB_MAIN_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 881 | bootloader/subproject/main/bootloader_start.o \ 882 | ) 883 | $(BOOTLOADER_LIB_DIR)/libmain.a: $(BOOTLOADER_LIB_MAIN_OBJ) 884 | $(ECHO) "AR $@" 885 | $(Q)$(AR) cr $@ $^ 886 | 887 | # all objects files 888 | BOOTLOADER_OBJ_ALL = \ 889 | $(BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ) \ 890 | $(BOOTLOADER_LIB_LOG_OBJ) \ 891 | $(BOOTLOADER_LIB_SPI_FLASH_OBJ) \ 892 | $(BOOTLOADER_LIB_MICRO_ECC_OBJ) \ 893 | $(BOOTLOADER_LIB_SOC_OBJ) \ 894 | $(BOOTLOADER_LIB_MAIN_OBJ) 895 | 896 | $(BOOTLOADER_OBJ_ALL): $(SDKCONFIG_H) 897 | 898 | BOOTLOADER_LIBS = 899 | BOOTLOADER_LIBS += -Wl,--start-group 900 | BOOTLOADER_LIBS += $(BOOTLOADER_OBJ) 901 | BOOTLOADER_LIBS += -L$(BUILD)/bootloader $(addprefix -l,$(BOOTLOADER_LIB_ALL)) 902 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 903 | BOOTLOADER_LIBS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lrtc 904 | else 905 | BOOTLOADER_LIBS += -L$(ESPCOMP)/esp32/lib -lrtc 906 | endif 907 | BOOTLOADER_LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc 908 | BOOTLOADER_LIBS += -Wl,--end-group 909 | 910 | BOOTLOADER_LDFLAGS = 911 | BOOTLOADER_LDFLAGS += -nostdlib 912 | BOOTLOADER_LDFLAGS += -L$(ESPIDF)/lib 913 | BOOTLOADER_LDFLAGS += -L$(ESPIDF)/ld 914 | BOOTLOADER_LDFLAGS += -u call_user_start_cpu0 915 | BOOTLOADER_LDFLAGS += -Wl,--gc-sections 916 | BOOTLOADER_LDFLAGS += -static 917 | BOOTLOADER_LDFLAGS += -Wl,-EL 918 | BOOTLOADER_LDFLAGS += -Wl,-Map=$(@:.elf=.map) -Wl,--cref 919 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.ld 920 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.rom.ld 921 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 922 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.ld 923 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld 924 | else 925 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.ld 926 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.spiram_incompatible_fns.ld 927 | endif 928 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.peripherals.ld 929 | 930 | BOOTLOADER_OBJ_DIRS = $(sort $(dir $(BOOTLOADER_OBJ_ALL))) 931 | $(BOOTLOADER_OBJ_ALL): | $(BOOTLOADER_OBJ_DIRS) 932 | $(BOOTLOADER_OBJ_DIRS): 933 | $(MKDIR) -p $@ 934 | 935 | $(BUILD)/bootloader/%.o: %.c 936 | $(call compile_c) 937 | 938 | $(BUILD)/bootloader.bin: $(BUILD)/bootloader.elf 939 | $(ECHO) "Create $@" 940 | $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< 941 | 942 | $(BUILD)/bootloader.elf: $(BOOTLOADER_OBJ) $(addprefix $(BOOTLOADER_LIB_DIR)/lib,$(addsuffix .a,$(BOOTLOADER_LIB_ALL))) 943 | $(ECHO) "LINK $@" 944 | $(Q)$(CC) $(BOOTLOADER_LDFLAGS) -o $@ $(BOOTLOADER_LIBS) 945 | 946 | ################################################################################ 947 | # Declarations to build the partitions 948 | 949 | PYTHON2 ?= python2 950 | 951 | # Can be overriden by mkconfigboard.mk. 952 | PART_SRC ?= partitions.csv 953 | 954 | $(BUILD)/partitions.bin: $(PART_SRC) 955 | $(ECHO) "Create $@" 956 | $(Q)$(PYTHON2) $(ESPCOMP)/partition_table/gen_esp32part.py -q $< $@ 957 | 958 | ################################################################################ 959 | 960 | include $(TOP)/py/mkrules.mk 961 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/MicropythonRICFns.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // RIC Micropython 4 | // 5 | // Rob Dobson 2016-20 6 | // 7 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif -------------------------------------------------------------------------------- /components/micropython/ports/ric/boards/GENERIC/mpconfigboard.h: -------------------------------------------------------------------------------- 1 | #define MICROPY_HW_BOARD_NAME "ESP32 module" 2 | #define MICROPY_HW_MCU_NAME "ESP32" 3 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/boards/GENERIC/mpconfigboard.mk: -------------------------------------------------------------------------------- 1 | SDKCONFIG += boards/sdkconfig.base 2 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/boards/manifest.py: -------------------------------------------------------------------------------- 1 | freeze("$(PORT_DIR)/modules") 2 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/boards/manifest_release.py: -------------------------------------------------------------------------------- 1 | include("manifest.py") 2 | 3 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/boards/sdkconfig.base: -------------------------------------------------------------------------------- 1 | # MicroPython on ESP32, ESP IDF configuration 2 | # The following options override the defaults 3 | 4 | CONFIG_IDF_TARGET="esp32" 5 | CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 6 | 7 | # Application manager 8 | CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y 9 | CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=y 10 | 11 | # Bootloader config 12 | CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y 13 | 14 | # ESP32-specific 15 | CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n 16 | CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n 17 | CONFIG_ESP32_XTAL_FREQ_AUTO=y 18 | 19 | # Power Management 20 | CONFIG_PM_ENABLE=y 21 | 22 | # FreeRTOS 23 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 24 | CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y 25 | CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=y 26 | 27 | # UDP 28 | CONFIG_LWIP_PPP_SUPPORT=y 29 | CONFIG_LWIP_PPP_PAP_SUPPORT=y 30 | CONFIG_LWIP_PPP_CHAP_SUPPORT=y 31 | 32 | # SSL 33 | # Use 4kiB output buffer instead of default 16kiB (because IDF heap is fragmented in 4.0) 34 | CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y 35 | 36 | # ULP coprocessor support 37 | CONFIG_ESP32_ULP_COPROC_ENABLED=y 38 | 39 | # v3.3-only (renamed in 4.0) 40 | CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y 41 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=n 42 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=n 43 | CONFIG_SUPPORT_STATIC_ALLOCATION=y 44 | CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y 45 | CONFIG_PPP_SUPPORT=y 46 | CONFIG_PPP_PAP_SUPPORT=y 47 | CONFIG_PPP_CHAP_SUPPORT=y 48 | CONFIG_ULP_COPROC_ENABLED=y 49 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/gccollect.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * Development of the code in this file was sponsored by Microbric Pty Ltd 5 | * 6 | * The MIT License (MIT) 7 | * 8 | * Copyright (c) 2014 Damien P. George 9 | * Copyright (c) 2017 Pycom Limited 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | * THE SOFTWARE. 28 | */ 29 | 30 | #include 31 | 32 | #include "py/mpconfig.h" 33 | #include "py/mpstate.h" 34 | #include "py/gc.h" 35 | #include "py/mpthread.h" 36 | #include "gccollect.h" 37 | #include "soc/cpu.h" 38 | #include "xtensa/hal.h" 39 | 40 | 41 | static void gc_collect_inner(int level) { 42 | if (level < XCHAL_NUM_AREGS / 8) { 43 | gc_collect_inner(level + 1); 44 | if (level != 0) { 45 | return; 46 | } 47 | } 48 | 49 | if (level == XCHAL_NUM_AREGS / 8) { 50 | // get the sp 51 | volatile uint32_t sp = (uint32_t)get_sp(); 52 | gc_collect_root((void **)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); 53 | return; 54 | } 55 | 56 | // trace root pointers from any threads 57 | #if MICROPY_PY_THREAD 58 | mp_thread_gc_others(); 59 | #endif 60 | } 61 | 62 | void gc_collect(void) { 63 | gc_collect_start(); 64 | gc_collect_inner(0); 65 | gc_collect_end(); 66 | } 67 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/gccollect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * Development of the code in this file was sponsored by Microbric Pty Ltd 5 | * 6 | * The MIT License (MIT) 7 | * 8 | * Copyright (c) 2014 Damien P. George 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | extern uint32_t _text_start; 30 | extern uint32_t _text_end; 31 | extern uint32_t _irom0_text_start; 32 | extern uint32_t _irom0_text_end; 33 | extern uint32_t _data_start; 34 | extern uint32_t _data_end; 35 | extern uint32_t _rodata_start; 36 | extern uint32_t _rodata_end; 37 | extern uint32_t _bss_start; 38 | extern uint32_t _bss_end; 39 | extern uint32_t _heap_start; 40 | extern uint32_t _heap_end; 41 | 42 | void gc_collect(void); 43 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/help.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * Development of the code in this file was sponsored by Microbric Pty Ltd 5 | * 6 | * The MIT License (MIT) 7 | * 8 | * Copyright (c) 2013-2016 Damien P. George 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | #include "py/builtin.h" 30 | 31 | // TODO RD Help text needs work! 32 | 33 | const char esp32_help_text[] = 34 | "Welcome to MicroPython on the ESP32!\n" 35 | "\n" 36 | "For generic online docs please visit http://docs.micropython.org/\n" 37 | "\n" 38 | "For access to the hardware use the 'machine' module:\n" 39 | "\n" 40 | "import machine\n" 41 | "pin12 = machine.Pin(12, machine.Pin.OUT)\n" 42 | "pin12.value(1)\n" 43 | "pin13 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)\n" 44 | "print(pin13.value())\n" 45 | "i2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22))\n" 46 | "i2c.scan()\n" 47 | "i2c.writeto(addr, b'1234')\n" 48 | "i2c.readfrom(addr, 4)\n" 49 | "\n" 50 | "Basic WiFi configuration:\n" 51 | "\n" 52 | "import network\n" 53 | "sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\n" 54 | "sta_if.scan() # Scan for available access points\n" 55 | "sta_if.connect(\"\", \"\") # Connect to an AP\n" 56 | "sta_if.isconnected() # Check for successful connection\n" 57 | "\n" 58 | "Control commands:\n" 59 | " CTRL-A -- on a blank line, enter raw REPL mode\n" 60 | " CTRL-B -- on a blank line, enter normal REPL mode\n" 61 | " CTRL-C -- interrupt a running program\n" 62 | " CTRL-D -- on a blank line, do a soft reset of the board\n" 63 | " CTRL-E -- on a blank line, enter paste mode\n" 64 | "\n" 65 | "For further help on a specific object, type help(obj)\n" 66 | "For a list of available modules, type help('modules')\n" 67 | ; 68 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * Development of the code in this file was sponsored by Microbric Pty Ltd 5 | * 6 | * The MIT License (MIT) 7 | * 8 | * Copyright (c) 2016 Damien P. George 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "freertos/FreeRTOS.h" 34 | #include "freertos/task.h" 35 | #include "esp_system.h" 36 | #include "nvs_flash.h" 37 | #include "esp_task.h" 38 | #include "soc/cpu.h" 39 | #include "esp_log.h" 40 | #if MICROPY_ESP_IDF_4 41 | #include "esp32/spiram.h" 42 | #else 43 | #include "esp_spiram.h" 44 | #endif 45 | 46 | #include "py/stackctrl.h" 47 | #include "py/nlr.h" 48 | #include "py/compile.h" 49 | #include "py/runtime.h" 50 | #include "py/persistentcode.h" 51 | #include "py/repl.h" 52 | #include "py/gc.h" 53 | #include "py/mphal.h" 54 | #include "lib/mp-readline/readline.h" 55 | #include "lib/utils/pyexec.h" 56 | 57 | int vprintf_null(const char *format, va_list ap) { 58 | // do nothing: this is used as a log target during raw repl mode 59 | return 0; 60 | } 61 | 62 | void app_main(void) { 63 | } 64 | 65 | void nlr_jump_fail(void *val) { 66 | printf("NLR jump failed, val=%p\n", val); 67 | esp_restart(); 68 | } 69 | 70 | // modussl_mbedtls uses this function but it's not enabled in ESP IDF 71 | void mbedtls_debug_set_threshold(int threshold) { 72 | (void)threshold; 73 | } 74 | 75 | void *esp_native_code_commit(void *buf, size_t len, void *reloc) { 76 | len = (len + 3) & ~3; 77 | uint32_t *p = heap_caps_malloc(len, MALLOC_CAP_EXEC); 78 | if (p == NULL) { 79 | m_malloc_fail(len); 80 | } 81 | if (reloc) { 82 | mp_native_relocate(reloc, buf, (uintptr_t)p); 83 | } 84 | memcpy(p, buf, len); 85 | return p; 86 | } 87 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/makeimg.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | OFFSET_BOOTLOADER = 0x1000 4 | OFFSET_PARTITIONS = 0x8000 5 | OFFSET_APPLICATION = 0x10000 6 | 7 | files_in = [ 8 | ("bootloader", OFFSET_BOOTLOADER, sys.argv[1]), 9 | ("partitions", OFFSET_PARTITIONS, sys.argv[2]), 10 | ("application", OFFSET_APPLICATION, sys.argv[3]), 11 | ] 12 | file_out = sys.argv[4] 13 | 14 | cur_offset = OFFSET_BOOTLOADER 15 | with open(file_out, "wb") as fout: 16 | for name, offset, file_in in files_in: 17 | assert offset >= cur_offset 18 | fout.write(b"\xff" * (offset - cur_offset)) 19 | cur_offset = offset 20 | with open(file_in, "rb") as fin: 21 | data = fin.read() 22 | fout.write(data) 23 | cur_offset += len(data) 24 | print("%-12s% 8d" % (name, len(data))) 25 | print("%-12s% 8d" % ("total", cur_offset)) 26 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/modutime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * Development of the code in this file was sponsored by Microbric Pty Ltd 5 | * 6 | * The MIT License (MIT) 7 | * 8 | * Copyright (c) 2016 Damien P. George 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "py/runtime.h" 34 | #include "lib/timeutils/timeutils.h" 35 | #include "extmod/utime_mphal.h" 36 | 37 | STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { 38 | timeutils_struct_time_t tm; 39 | mp_int_t seconds; 40 | if (n_args == 0 || args[0] == mp_const_none) { 41 | struct timeval tv; 42 | gettimeofday(&tv, NULL); 43 | seconds = tv.tv_sec; 44 | } else { 45 | seconds = mp_obj_get_int(args[0]); 46 | } 47 | timeutils_seconds_since_2000_to_struct_time(seconds, &tm); 48 | mp_obj_t tuple[8] = { 49 | tuple[0] = mp_obj_new_int(tm.tm_year), 50 | tuple[1] = mp_obj_new_int(tm.tm_mon), 51 | tuple[2] = mp_obj_new_int(tm.tm_mday), 52 | tuple[3] = mp_obj_new_int(tm.tm_hour), 53 | tuple[4] = mp_obj_new_int(tm.tm_min), 54 | tuple[5] = mp_obj_new_int(tm.tm_sec), 55 | tuple[6] = mp_obj_new_int(tm.tm_wday), 56 | tuple[7] = mp_obj_new_int(tm.tm_yday), 57 | }; 58 | return mp_obj_new_tuple(8, tuple); 59 | } 60 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime); 61 | 62 | STATIC mp_obj_t time_mktime(mp_obj_t tuple) { 63 | size_t len; 64 | mp_obj_t *elem; 65 | mp_obj_get_array(tuple, &len, &elem); 66 | 67 | // localtime generates a tuple of len 8. CPython uses 9, so we accept both. 68 | if (len < 8 || len > 9) { 69 | mp_raise_msg_varg(&mp_type_TypeError, MP_ERROR_TEXT("mktime needs a tuple of length 8 or 9 (%d given)"), len); 70 | } 71 | 72 | return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), 73 | mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]), 74 | mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]))); 75 | } 76 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); 77 | 78 | STATIC mp_obj_t time_time(void) { 79 | struct timeval tv; 80 | gettimeofday(&tv, NULL); 81 | return mp_obj_new_int(tv.tv_sec); 82 | } 83 | MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); 84 | 85 | STATIC const mp_rom_map_elem_t time_module_globals_table[] = { 86 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, 87 | 88 | { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) }, 89 | { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) }, 90 | { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, 91 | { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, 92 | { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, 93 | { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, 94 | { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, 95 | { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, 96 | { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, 97 | { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, 98 | { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, 99 | }; 100 | 101 | STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); 102 | 103 | const mp_obj_module_t utime_module = { 104 | .base = { &mp_type_module }, 105 | .globals = (mp_obj_dict_t *)&time_module_globals, 106 | }; 107 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/mpconfigport.h: -------------------------------------------------------------------------------- 1 | // Options to control how MicroPython is built for this port, 2 | // overriding defaults in py/mpconfig.h. 3 | 4 | // Board-specific definitions 5 | #include "mpconfigboard.h" 6 | 7 | #include 8 | #include 9 | 10 | #if !MICROPY_ESP_IDF_4 11 | #include "rom/ets_sys.h" 12 | #endif 13 | 14 | #define MODULE_RIC_ENABLED (1) 15 | 16 | // You can disable the built-in MicroPython compiler by setting the following 17 | // config option to 0. If you do this then you won't get a REPL prompt, but you 18 | // will still be able to execute pre-compiled scripts, compiled with mpy-cross. 19 | #define MICROPY_ENABLE_COMPILER (1) 20 | #define MICROPY_REPL_EVENT_DRIVEN (1) 21 | 22 | // #define MICROPY_DYNAMIC_COMPILER (1) 23 | 24 | // object representation and NLR handling 25 | #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) 26 | #define MICROPY_NLR_SETJMP (1) 27 | 28 | // memory allocation policies 29 | #define MICROPY_ALLOC_PATH_MAX (128) 30 | 31 | // emitters 32 | #define MICROPY_PERSISTENT_CODE_LOAD (1) 33 | #define MICROPY_EMIT_XTENSAWIN (0) 34 | 35 | // compiler configuration 36 | #define MICROPY_COMP_MODULE_CONST (1) 37 | #define MICROPY_COMP_CONST (1) 38 | #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) 39 | #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) 40 | 41 | // optimisations 42 | #define MICROPY_OPT_COMPUTED_GOTO (1) 43 | #define MICROPY_OPT_MPZ_BITWISE (1) 44 | 45 | // Python internal features 46 | #define MICROPY_READER_VFS (1) 47 | #define MICROPY_ENABLE_GC (1) 48 | #define MICROPY_ENABLE_FINALISER (0) 49 | #define MICROPY_STACK_CHECK (1) 50 | #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) 51 | #define MICROPY_KBD_EXCEPTION (1) 52 | #define MICROPY_HELPER_REPL (1) 53 | #define MICROPY_REPL_EMACS_KEYS (0) 54 | #define MICROPY_REPL_AUTO_INDENT (1) 55 | #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) 56 | #define MICROPY_ENABLE_SOURCE_LINE (0) 57 | #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) 58 | #define MICROPY_WARNINGS (1) 59 | #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) 60 | #define MICROPY_CPYTHON_COMPAT (0) 61 | #define MICROPY_STREAMS_NON_BLOCK (0) 62 | #define MICROPY_STREAMS_POSIX_API (1) 63 | #define MICROPY_MODULE_BUILTIN_INIT (0) 64 | #define MICROPY_MODULE_WEAK_LINKS (1) 65 | #define MICROPY_MODULE_FROZEN_STR (0) 66 | #define MICROPY_MODULE_FROZEN_MPY (1) 67 | #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool 68 | #define MICROPY_CAN_OVERRIDE_BUILTINS (1) 69 | #define MICROPY_USE_INTERNAL_ERRNO (1) 70 | #define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf 71 | #define MICROPY_ENABLE_SCHEDULER (1) 72 | #define MICROPY_SCHEDULER_DEPTH (8) 73 | #define MICROPY_VFS (0) 74 | 75 | // control over Python builtins 76 | #define MICROPY_PY_FUNCTION_ATTRS (1) 77 | #define MICROPY_PY_DESCRIPTORS (1) 78 | #define MICROPY_PY_STR_BYTES_CMP_WARN (1) 79 | #define MICROPY_PY_BUILTINS_DICT_FROMKEYS (0) 80 | #define MICROPY_PY_BUILTINS_STR_UNICODE (1) 81 | #define MICROPY_PY_BUILTINS_STR_CENTER (1) 82 | #define MICROPY_PY_BUILTINS_STR_PARTITION (1) 83 | #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) 84 | #define MICROPY_PY_BUILTINS_BYTEARRAY (1) 85 | #define MICROPY_PY_BUILTINS_MEMORYVIEW (0) 86 | #define MICROPY_PY_BUILTINS_SET (0) 87 | #define MICROPY_PY_BUILTINS_SLICE (1) 88 | #define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) 89 | #define MICROPY_PY_BUILTINS_SLICE_INDICES (0) 90 | #define MICROPY_PY_BUILTINS_FROZENSET (0) 91 | #define MICROPY_PY_BUILTINS_PROPERTY (0) 92 | #define MICROPY_PY_BUILTINS_RANGE_ATTRS (0) 93 | #define MICROPY_PY_BUILTINS_ROUND_INT (1) 94 | #define MICROPY_PY_ALL_SPECIAL_METHODS (0) 95 | #define MICROPY_PY_BUILTINS_COMPILE (0) 96 | #define MICROPY_PY_BUILTINS_ENUMERATE (0) 97 | #define MICROPY_PY_BUILTINS_EXECFILE (0) 98 | #define MICROPY_PY_BUILTINS_FILTER (0) 99 | #define MICROPY_PY_BUILTINS_REVERSED (0) 100 | #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0) 101 | #define MICROPY_PY_BUILTINS_INPUT (0) 102 | #define MICROPY_PY_BUILTINS_MIN_MAX (1) 103 | #define MICROPY_PY_BUILTINS_POW3 (1) 104 | #define MICROPY_PY_BUILTINS_HELP (1) 105 | #define MICROPY_PY_BUILTINS_HELP_TEXT esp32_help_text 106 | #define MICROPY_PY_BUILTINS_HELP_MODULES (0) 107 | #define MICROPY_PY___FILE__ (0) 108 | #define MICROPY_PY_MICROPYTHON_MEM_INFO (0) 109 | #define MICROPY_PY_ARRAY (0) 110 | #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) 111 | #define MICROPY_PY_ATTRTUPLE (0) 112 | #define MICROPY_PY_COLLECTIONS (0) 113 | #define MICROPY_PY_COLLECTIONS_DEQUE (0) 114 | #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0) 115 | #define MICROPY_PY_MATH (0) 116 | #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0) 117 | #define MICROPY_PY_MATH_ISCLOSE (0) 118 | #define MICROPY_PY_CMATH (0) 119 | #define MICROPY_PY_GC (1) 120 | #define MICROPY_PY_IO (0) 121 | #define MICROPY_PY_IO_IOBASE (0) 122 | #define MICROPY_PY_IO_FILEIO (0) 123 | #define MICROPY_PY_IO_BYTESIO (0) 124 | #define MICROPY_PY_IO_BUFFEREDWRITER (0) 125 | #define MICROPY_PY_STRUCT (1) 126 | #define MICROPY_PY_SYS (0) 127 | #define MICROPY_PY_SYS_MAXSIZE (0) 128 | #define MICROPY_PY_SYS_MODULES (0) 129 | #define MICROPY_PY_SYS_EXIT (0) 130 | #define MICROPY_PY_SYS_STDFILES (0) 131 | #define MICROPY_PY_SYS_STDIO_BUFFER (0) 132 | #define MICROPY_PY_UERRNO (0) 133 | #define MICROPY_PY_USELECT (0) 134 | #define MICROPY_PY_UTIME_MP_HAL (1) 135 | #define MICROPY_PY_THREAD (1) 136 | #define MICROPY_PY_THREAD_GIL (1) 137 | #define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32) 138 | 139 | // extended modules 140 | #define MICROPY_PY_UASYNCIO (0) 141 | #define MICROPY_PY_UCTYPES (0) 142 | #define MICROPY_PY_UZLIB (0) 143 | #define MICROPY_PY_UJSON (0) 144 | #define MICROPY_PY_URE (0) 145 | #define MICROPY_PY_URE_SUB (0) 146 | #define MICROPY_PY_UHEAPQ (0) 147 | #define MICROPY_PY_UTIMEQ (0) 148 | #define MICROPY_PY_UHASHLIB (0) 149 | #define MICROPY_PY_UHASHLIB_SHA1 (0) 150 | #define MICROPY_PY_UHASHLIB_SHA256 (0) 151 | #define MICROPY_PY_UCRYPTOLIB (0) 152 | #define MICROPY_PY_UBINASCII (0) 153 | #define MICROPY_PY_UBINASCII_CRC32 (0) 154 | #define MICROPY_PY_URANDOM (0) 155 | #define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) 156 | #define MICROPY_PY_OS_DUPTERM (0) 157 | #define MICROPY_PY_MACHINE (0) 158 | #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new 159 | #define MICROPY_PY_MACHINE_PULSE (0) 160 | #define MICROPY_PY_MACHINE_I2C (0) 161 | #define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hw_i2c_make_new 162 | #define MICROPY_PY_MACHINE_SPI (0) 163 | #define MICROPY_PY_MACHINE_SPI_MSB (0) 164 | #define MICROPY_PY_MACHINE_SPI_LSB (1) 165 | #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hw_spi_make_new 166 | #define MICROPY_HW_ENABLE_SDCARD (0) 167 | #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) 168 | #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly 169 | #define MICROPY_PY_USSL (0) 170 | #define MICROPY_SSL_MBEDTLS (0) 171 | #define MICROPY_PY_USSL_FINALISER (0) 172 | #define MICROPY_PY_UWEBSOCKET (0) 173 | #define MICROPY_PY_WEBREPL (0) 174 | #define MICROPY_PY_FRAMEBUF (0) 175 | #define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL) 176 | #define MICROPY_PY_BLUETOOTH_RANDOM_ADDR (0) 177 | #define MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME ("ESP32") 178 | 179 | // fatfs configuration 180 | #define MICROPY_FATFS_ENABLE_LFN (1) 181 | #define MICROPY_FATFS_RPATH (2) 182 | #define MICROPY_FATFS_MAX_SS (4096) 183 | #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ 184 | #define mp_type_fileio mp_type_vfs_fat_fileio 185 | #define mp_type_textio mp_type_vfs_fat_textio 186 | 187 | // use vfs's functions for import stat and builtin open 188 | // #define mp_import_stat mp_vfs_import_stat 189 | // #define mp_builtin_open mp_vfs_open 190 | // #define mp_builtin_open_obj mp_vfs_open_obj 191 | 192 | // extra built in names to add to the global namespace 193 | /*#define MICROPY_PORT_BUILTINS \ 194 | { MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \ 195 | { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, 196 | */ 197 | 198 | // extra built in modules to add to the list of known ones 199 | // extern const struct _mp_obj_module_t esp_module; 200 | // extern const struct _mp_obj_module_t esp32_module; 201 | extern const struct _mp_obj_module_t utime_module; 202 | // extern const struct _mp_obj_module_t uos_module; 203 | // extern const struct _mp_obj_module_t mp_module_usocket; 204 | // extern const struct _mp_obj_module_t mp_module_machine; 205 | // extern const struct _mp_obj_module_t mp_module_network; 206 | // extern const struct _mp_obj_module_t mp_module_onewire; 207 | 208 | #define MICROPY_PORT_BUILTIN_MODULES \ 209 | { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, 210 | 211 | /* { MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \ 212 | { MP_OBJ_NEW_QSTR(MP_QSTR_esp32), (mp_obj_t)&esp32_module }, \ 213 | { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \ 214 | { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \ 215 | { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ 216 | { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \ 217 | { MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \ 218 | { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ 219 | */ 220 | 221 | #define MP_STATE_PORT MP_STATE_VM 222 | 223 | struct _machine_timer_obj_t; 224 | 225 | #if MICROPY_BLUETOOTH_NIMBLE 226 | struct mp_bluetooth_nimble_root_pointers_t; 227 | #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; 228 | #else 229 | #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE 230 | #endif 231 | 232 | #define MICROPY_PORT_ROOT_POINTERS \ 233 | const char *readline_hist[8]; \ 234 | mp_obj_t machine_pin_irq_handler[40]; \ 235 | struct _machine_timer_obj_t *machine_timer_obj_head; \ 236 | mp_obj_t ric_event_callback; \ 237 | MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE 238 | 239 | // type definitions for the specific machine 240 | 241 | #define BYTES_PER_WORD (4) 242 | #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p))) 243 | #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) 244 | void *esp_native_code_commit(void *, size_t, void *); 245 | #define MP_PLAT_COMMIT_EXEC(buf, len, reloc) esp_native_code_commit(buf, len, reloc) 246 | #define MP_SSIZE_MAX (0x7fffffff) 247 | 248 | // Note: these "critical nested" macros do not ensure cross-CPU exclusion, 249 | // the only disable interrupts on the current CPU. To full manage exclusion 250 | // one should use portENTER_CRITICAL/portEXIT_CRITICAL instead. 251 | #include "freertos/FreeRTOS.h" 252 | #define MICROPY_BEGIN_ATOMIC_SECTION() portENTER_CRITICAL_NESTED() 253 | #define MICROPY_END_ATOMIC_SECTION(state) portEXIT_CRITICAL_NESTED(state) 254 | 255 | #if MICROPY_PY_USOCKET_EVENTS 256 | #define MICROPY_PY_USOCKET_EVENTS_HANDLER extern void usocket_events_handler(void); usocket_events_handler(); 257 | #else 258 | #define MICROPY_PY_USOCKET_EVENTS_HANDLER 259 | #endif 260 | 261 | #if MICROPY_PY_THREAD 262 | #define MICROPY_EVENT_POLL_HOOK \ 263 | do { \ 264 | extern void mp_handle_pending(bool); \ 265 | mp_handle_pending(true); \ 266 | MICROPY_PY_USOCKET_EVENTS_HANDLER \ 267 | MP_THREAD_GIL_EXIT(); \ 268 | MP_THREAD_GIL_ENTER(); \ 269 | } while (0); 270 | #else 271 | #define MICROPY_EVENT_POLL_HOOK \ 272 | do { \ 273 | extern void mp_handle_pending(bool); \ 274 | mp_handle_pending(true); \ 275 | MICROPY_PY_USOCKET_EVENTS_HANDLER \ 276 | asm ("waiti 0"); \ 277 | } while (0); 278 | #endif 279 | 280 | // Functions that should go in IRAM 281 | #define MICROPY_WRAP_MP_KEYBOARD_INTERRUPT(f) IRAM_ATTR f 282 | 283 | #define UINT_FMT "%u" 284 | #define INT_FMT "%d" 285 | 286 | typedef int32_t mp_int_t; // must be pointer size 287 | typedef uint32_t mp_uint_t; // must be pointer size 288 | typedef long mp_off_t; 289 | // ssize_t, off_t as required by POSIX-signatured functions in stream.h 290 | #include 291 | 292 | // board specifics 293 | #define MICROPY_PY_SYS_PLATFORM "esp32" 294 | 295 | // #ifndef MICROPY_HW_ENABLE_MDNS_QUERIES 296 | // #define MICROPY_HW_ENABLE_MDNS_QUERIES (1) 297 | // #endif 298 | 299 | // #ifndef MICROPY_HW_ENABLE_MDNS_RESPONDER 300 | // #define MICROPY_HW_ENABLE_MDNS_RESPONDER (1) 301 | // #endif 302 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/mphalport.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * Development of the code in this file was sponsored by Microbric Pty Ltd 5 | * 6 | * The MIT License (MIT) 7 | * 8 | * Copyright (c) 2014 Damien P. George 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "freertos/FreeRTOS.h" 34 | #include "freertos/task.h" 35 | 36 | #if MICROPY_ESP_IDF_4 37 | #include "esp32/rom/uart.h" 38 | #else 39 | #include "rom/uart.h" 40 | #endif 41 | #include "driver/uart.h" 42 | #include "esp_log.h" 43 | 44 | #include "py/obj.h" 45 | #include "py/objstr.h" 46 | #include "py/stream.h" 47 | #include "py/mpstate.h" 48 | #include "py/mphal.h" 49 | #include "extmod/misc.h" 50 | #include "lib/timeutils/timeutils.h" 51 | #include "lib/utils/pyexec.h" 52 | #include "mphalport.h" 53 | 54 | TaskHandle_t mp_main_task_handle; 55 | 56 | STATIC uint8_t stdin_ringbuf_array[256]; 57 | ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0}; 58 | 59 | // Check the ESP-IDF error code and raise an OSError if it's not ESP_OK. 60 | void check_esp_err(esp_err_t code) { 61 | if (code != ESP_OK) { 62 | // map esp-idf error code to posix error code 63 | uint32_t pcode = -code; 64 | switch (code) { 65 | case ESP_ERR_NO_MEM: 66 | pcode = MP_ENOMEM; 67 | break; 68 | case ESP_ERR_TIMEOUT: 69 | pcode = MP_ETIMEDOUT; 70 | break; 71 | case ESP_ERR_NOT_SUPPORTED: 72 | pcode = MP_EOPNOTSUPP; 73 | break; 74 | } 75 | // construct string object 76 | mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); 77 | if (o_str == NULL) { 78 | mp_raise_OSError(pcode); 79 | return; 80 | } 81 | o_str->base.type = &mp_type_str; 82 | o_str->data = (const byte *)esp_err_to_name(code); // esp_err_to_name ret's ptr to const str 83 | o_str->len = strlen((char *)o_str->data); 84 | o_str->hash = qstr_compute_hash(o_str->data, o_str->len); 85 | // raise 86 | mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(pcode), MP_OBJ_FROM_PTR(o_str)}; 87 | nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args)); 88 | } 89 | } 90 | 91 | uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { 92 | uintptr_t ret = 0; 93 | if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) { 94 | ret |= MP_STREAM_POLL_RD; 95 | } 96 | return ret; 97 | } 98 | 99 | int mp_hal_stdin_rx_chr(void) { 100 | for (;;) { 101 | int c = ringbuf_get(&stdin_ringbuf); 102 | if (c != -1) { 103 | return c; 104 | } 105 | MICROPY_EVENT_POLL_HOOK 106 | ulTaskNotifyTake(pdFALSE, 1); 107 | } 108 | } 109 | 110 | void mp_hal_stdout_tx_str(const char *str) { 111 | mp_hal_stdout_tx_strn(str, strlen(str)); 112 | } 113 | 114 | void mp_hal_stdout_tx_strn(const char *str, uint32_t len) { 115 | // Only release the GIL if many characters are being sent 116 | bool release_gil = len > 20; 117 | if (release_gil) { 118 | MP_THREAD_GIL_EXIT(); 119 | } 120 | // uart_write_bytes(0, str, len); 121 | char tmpStr[len+1]; 122 | memcpy(tmpStr, str, len); 123 | tmpStr[len] = 0; 124 | // ESP_LOGI("MPHAL", "%s", tmpStr); 125 | for (uint32_t i = 0; i < len; ++i) { 126 | uart_tx_one_char(str[i]); 127 | } 128 | if (release_gil) { 129 | MP_THREAD_GIL_ENTER(); 130 | } 131 | mp_uos_dupterm_tx_strn(str, len); 132 | } 133 | 134 | // Efficiently convert "\n" to "\r\n" 135 | void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { 136 | const char *last = str; 137 | while (len--) { 138 | if (*str == '\n') { 139 | if (str > last) { 140 | mp_hal_stdout_tx_strn(last, str - last); 141 | } 142 | mp_hal_stdout_tx_strn("\r\n", 2); 143 | ++str; 144 | last = str; 145 | } else { 146 | ++str; 147 | } 148 | } 149 | if (str > last) { 150 | mp_hal_stdout_tx_strn(last, str - last); 151 | } 152 | } 153 | 154 | uint32_t mp_hal_ticks_ms(void) { 155 | return esp_timer_get_time() / 1000; 156 | } 157 | 158 | uint32_t mp_hal_ticks_us(void) { 159 | return esp_timer_get_time(); 160 | } 161 | 162 | void mp_hal_delay_ms(uint32_t ms) { 163 | uint64_t us = ms * 1000; 164 | uint64_t dt; 165 | uint64_t t0 = esp_timer_get_time(); 166 | for (;;) { 167 | uint64_t t1 = esp_timer_get_time(); 168 | dt = t1 - t0; 169 | if (dt + portTICK_PERIOD_MS * 1000 >= us) { 170 | // doing a vTaskDelay would take us beyond requested delay time 171 | break; 172 | } 173 | MICROPY_EVENT_POLL_HOOK 174 | ulTaskNotifyTake(pdFALSE, 1); 175 | } 176 | if (dt < us) { 177 | // do the remaining delay accurately 178 | mp_hal_delay_us(us - dt); 179 | } 180 | } 181 | 182 | void mp_hal_delay_us(uint32_t us) { 183 | // these constants are tested for a 240MHz clock 184 | const uint32_t this_overhead = 5; 185 | const uint32_t pend_overhead = 150; 186 | 187 | // return if requested delay is less than calling overhead 188 | if (us < this_overhead) { 189 | return; 190 | } 191 | us -= this_overhead; 192 | 193 | uint64_t t0 = esp_timer_get_time(); 194 | for (;;) { 195 | uint64_t dt = esp_timer_get_time() - t0; 196 | if (dt >= us) { 197 | return; 198 | } 199 | if (dt + pend_overhead < us) { 200 | // we have enough time to service pending events 201 | // (don't use MICROPY_EVENT_POLL_HOOK because it also yields) 202 | mp_handle_pending(true); 203 | } 204 | } 205 | } 206 | 207 | // Wake up the main task if it is sleeping 208 | void mp_hal_wake_main_task_from_isr(void) { 209 | BaseType_t xHigherPriorityTaskWoken = pdFALSE; 210 | vTaskNotifyGiveFromISR(mp_main_task_handle, &xHigherPriorityTaskWoken); 211 | if (xHigherPriorityTaskWoken == pdTRUE) { 212 | portYIELD_FROM_ISR(); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/mphalport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * Development of the code in this file was sponsored by Microbric Pty Ltd 5 | * 6 | * The MIT License (MIT) 7 | * 8 | * Copyright (c) 2014 Damien P. George 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | #ifndef INCLUDED_MPHALPORT_H 30 | #define INCLUDED_MPHALPORT_H 31 | 32 | #include "py/ringbuf.h" 33 | #include "lib/utils/interrupt_char.h" 34 | 35 | #include "freertos/FreeRTOS.h" 36 | #include "freertos/task.h" 37 | 38 | // The core that the MicroPython task(s) are pinned to 39 | #define MP_TASK_COREID (1) 40 | 41 | extern TaskHandle_t mp_main_task_handle; 42 | 43 | extern ringbuf_t stdin_ringbuf; 44 | 45 | // Check the ESP-IDF error code and raise an OSError if it's not ESP_OK. 46 | void check_esp_err(esp_err_t code); 47 | 48 | uint32_t mp_hal_ticks_us(void); 49 | __attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) { 50 | uint32_t ccount; 51 | __asm__ __volatile__ ("rsr %0,ccount" : "=a" (ccount)); 52 | return ccount; 53 | } 54 | 55 | void mp_hal_delay_us(uint32_t); 56 | #define mp_hal_delay_us_fast(us) ets_delay_us(us) 57 | void mp_hal_set_interrupt_char(int c); 58 | uint32_t mp_hal_get_cpu_freq(void); 59 | 60 | #define mp_hal_quiet_timing_enter() MICROPY_BEGIN_ATOMIC_SECTION() 61 | #define mp_hal_quiet_timing_exit(irq_state) MICROPY_END_ATOMIC_SECTION(irq_state) 62 | 63 | // Wake up the main task if it is sleeping 64 | void mp_hal_wake_main_task_from_isr(void); 65 | 66 | // C-level pin HAL 67 | #include "py/obj.h" 68 | #include "driver/gpio.h" 69 | #define MP_HAL_PIN_FMT "%u" 70 | #define mp_hal_pin_obj_t gpio_num_t 71 | mp_hal_pin_obj_t machine_pin_get_id(mp_obj_t pin_in); 72 | #define mp_hal_get_pin_obj(o) machine_pin_get_id(o) 73 | #define mp_obj_get_pin(o) machine_pin_get_id(o) // legacy name; only to support esp8266/modonewire 74 | #define mp_hal_pin_name(p) (p) 75 | static inline void mp_hal_pin_input(mp_hal_pin_obj_t pin) { 76 | gpio_pad_select_gpio(pin); 77 | gpio_set_direction(pin, GPIO_MODE_INPUT); 78 | } 79 | static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) { 80 | gpio_pad_select_gpio(pin); 81 | gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT); 82 | } 83 | static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { 84 | gpio_pad_select_gpio(pin); 85 | gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT_OD); 86 | } 87 | static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) { 88 | gpio_set_level(pin, 0); 89 | } 90 | static inline void mp_hal_pin_od_high(mp_hal_pin_obj_t pin) { 91 | gpio_set_level(pin, 1); 92 | } 93 | static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) { 94 | return gpio_get_level(pin); 95 | } 96 | static inline void mp_hal_pin_write(mp_hal_pin_obj_t pin, int v) { 97 | gpio_set_level(pin, v); 98 | } 99 | 100 | #endif // INCLUDED_MPHALPORT_H 101 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/mpthreadport.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd 7 | * Copyright (c) 2017 Pycom Limited 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #include "stdio.h" 29 | 30 | #include "py/runtime.h" 31 | #include "py/gc.h" 32 | #include "py/mpthread.h" 33 | #include "py/mphal.h" 34 | #include "mpthreadport.h" 35 | 36 | #include "esp_task.h" 37 | #if !MICROPY_ESP_IDF_4 38 | #include "freertos/semphr.h" 39 | #endif 40 | 41 | #if MICROPY_PY_THREAD 42 | 43 | #define MP_THREAD_MIN_STACK_SIZE (4 * 1024) 44 | #define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024) 45 | #define MP_THREAD_PRIORITY (ESP_TASK_PRIO_MIN + 1) 46 | 47 | // this structure forms a linked list, one node per active thread 48 | typedef struct _thread_t { 49 | TaskHandle_t id; // system id of thread 50 | int ready; // whether the thread is ready and running 51 | void *arg; // thread Python args, a GC root pointer 52 | void *stack; // pointer to the stack 53 | size_t stack_len; // number of words in the stack 54 | struct _thread_t *next; 55 | } thread_t; 56 | 57 | // the mutex controls access to the linked list 58 | STATIC mp_thread_mutex_t thread_mutex; 59 | STATIC thread_t thread_entry0; 60 | STATIC thread_t *thread = NULL; // root pointer, handled by mp_thread_gc_others 61 | 62 | void mp_thread_init(void *stack, uint32_t stack_len) { 63 | mp_thread_set_state(&mp_state_ctx.thread); 64 | // create the first entry in the linked list of all threads 65 | thread = &thread_entry0; 66 | thread->id = xTaskGetCurrentTaskHandle(); 67 | thread->ready = 1; 68 | thread->arg = NULL; 69 | thread->stack = stack; 70 | thread->stack_len = stack_len; 71 | thread->next = NULL; 72 | mp_thread_mutex_init(&thread_mutex); 73 | } 74 | 75 | void mp_thread_gc_others(void) { 76 | mp_thread_mutex_lock(&thread_mutex, 1); 77 | for (thread_t *th = thread; th != NULL; th = th->next) { 78 | gc_collect_root((void **)&th, 1); 79 | gc_collect_root(&th->arg, 1); // probably not needed 80 | if (th->id == xTaskGetCurrentTaskHandle()) { 81 | continue; 82 | } 83 | if (!th->ready) { 84 | continue; 85 | } 86 | gc_collect_root(th->stack, th->stack_len); 87 | } 88 | mp_thread_mutex_unlock(&thread_mutex); 89 | } 90 | 91 | mp_state_thread_t *mp_thread_get_state(void) { 92 | return pvTaskGetThreadLocalStoragePointer(NULL, 1); 93 | } 94 | 95 | void mp_thread_set_state(mp_state_thread_t *state) { 96 | vTaskSetThreadLocalStoragePointer(NULL, 1, state); 97 | } 98 | 99 | void mp_thread_start(void) { 100 | mp_thread_mutex_lock(&thread_mutex, 1); 101 | for (thread_t *th = thread; th != NULL; th = th->next) { 102 | if (th->id == xTaskGetCurrentTaskHandle()) { 103 | th->ready = 1; 104 | break; 105 | } 106 | } 107 | mp_thread_mutex_unlock(&thread_mutex); 108 | } 109 | 110 | STATIC void *(*ext_thread_entry)(void *) = NULL; 111 | 112 | STATIC void freertos_entry(void *arg) { 113 | if (ext_thread_entry) { 114 | ext_thread_entry(arg); 115 | } 116 | vTaskDelete(NULL); 117 | for (;;) {; 118 | } 119 | } 120 | 121 | void mp_thread_create_ex(void *(*entry)(void *), void *arg, size_t *stack_size, int priority, char *name) { 122 | // store thread entry function into a global variable so we can access it 123 | ext_thread_entry = entry; 124 | 125 | if (*stack_size == 0) { 126 | *stack_size = MP_THREAD_DEFAULT_STACK_SIZE; // default stack size 127 | } else if (*stack_size < MP_THREAD_MIN_STACK_SIZE) { 128 | *stack_size = MP_THREAD_MIN_STACK_SIZE; // minimum stack size 129 | } 130 | 131 | // Allocate linked-list node (must be outside thread_mutex lock) 132 | thread_t *th = m_new_obj(thread_t); 133 | 134 | mp_thread_mutex_lock(&thread_mutex, 1); 135 | 136 | // create thread 137 | BaseType_t result = xTaskCreatePinnedToCore(freertos_entry, name, *stack_size / sizeof(StackType_t), 138 | arg, priority, &th->id, MP_TASK_COREID); 139 | if (result != pdPASS) { 140 | mp_thread_mutex_unlock(&thread_mutex); 141 | mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("can't create thread")); 142 | } 143 | 144 | // add thread to linked list of all threads 145 | th->ready = 0; 146 | th->arg = arg; 147 | th->stack = pxTaskGetStackStart(th->id); 148 | th->stack_len = *stack_size / sizeof(uintptr_t); 149 | th->next = thread; 150 | thread = th; 151 | 152 | // adjust the stack_size to provide room to recover from hitting the limit 153 | *stack_size -= 1024; 154 | 155 | mp_thread_mutex_unlock(&thread_mutex); 156 | } 157 | 158 | void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { 159 | mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread"); 160 | } 161 | 162 | void mp_thread_finish(void) { 163 | mp_thread_mutex_lock(&thread_mutex, 1); 164 | for (thread_t *th = thread; th != NULL; th = th->next) { 165 | if (th->id == xTaskGetCurrentTaskHandle()) { 166 | th->ready = 0; 167 | break; 168 | } 169 | } 170 | mp_thread_mutex_unlock(&thread_mutex); 171 | } 172 | 173 | void vPortCleanUpTCB(void *tcb) { 174 | if (thread == NULL) { 175 | // threading not yet initialised 176 | return; 177 | } 178 | thread_t *prev = NULL; 179 | mp_thread_mutex_lock(&thread_mutex, 1); 180 | for (thread_t *th = thread; th != NULL; prev = th, th = th->next) { 181 | // unlink the node from the list 182 | if ((void *)th->id == tcb) { 183 | if (prev != NULL) { 184 | prev->next = th->next; 185 | } else { 186 | // move the start pointer 187 | thread = th->next; 188 | } 189 | // explicitly release all its memory 190 | m_del(thread_t, th, 1); 191 | break; 192 | } 193 | } 194 | mp_thread_mutex_unlock(&thread_mutex); 195 | } 196 | 197 | void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { 198 | mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer); 199 | } 200 | 201 | int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) { 202 | return pdTRUE == xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0); 203 | } 204 | 205 | void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { 206 | xSemaphoreGive(mutex->handle); 207 | } 208 | 209 | void mp_thread_deinit(void) { 210 | for (;;) { 211 | // Find a task to delete 212 | TaskHandle_t id = NULL; 213 | mp_thread_mutex_lock(&thread_mutex, 1); 214 | for (thread_t *th = thread; th != NULL; th = th->next) { 215 | // Don't delete the current task 216 | if (th->id != xTaskGetCurrentTaskHandle()) { 217 | id = th->id; 218 | break; 219 | } 220 | } 221 | mp_thread_mutex_unlock(&thread_mutex); 222 | 223 | if (id == NULL) { 224 | // No tasks left to delete 225 | break; 226 | } else { 227 | // Call FreeRTOS to delete the task (it will call vPortCleanUpTCB) 228 | vTaskDelete(id); 229 | } 230 | } 231 | } 232 | 233 | #else 234 | 235 | void vPortCleanUpTCB(void *tcb) { 236 | } 237 | 238 | #endif // MICROPY_PY_THREAD 239 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/mpthreadport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd 7 | * Copyright (c) 2017 Pycom Limited 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #ifndef MICROPY_INCLUDED_ESP32_MPTHREADPORT_H 29 | #define MICROPY_INCLUDED_ESP32_MPTHREADPORT_H 30 | 31 | #include "freertos/FreeRTOS.h" 32 | #include "freertos/task.h" 33 | #include "freertos/semphr.h" 34 | #include "freertos/queue.h" 35 | 36 | typedef struct _mp_thread_mutex_t { 37 | SemaphoreHandle_t handle; 38 | StaticSemaphore_t buffer; 39 | } mp_thread_mutex_t; 40 | 41 | void mp_thread_init(void *stack, uint32_t stack_len); 42 | void mp_thread_gc_others(void); 43 | void mp_thread_deinit(void); 44 | 45 | #endif // MICROPY_INCLUDED_ESP32_MPTHREADPORT_H 46 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/partitions.csv: -------------------------------------------------------------------------------- 1 | # Notes: the offset of the partition table itself is set in 2 | # $ESPIDF/components/partition_table/Kconfig.projbuild and the 3 | # offset of the factory/ota_0 partition is set in makeimg.py 4 | # Name, Type, SubType, Offset, Size, Flags 5 | nvs, data, nvs, 0x9000, 0x6000, 6 | phy_init, data, phy, 0xf000, 0x1000, 7 | factory, app, factory, 0x10000, 0x180000, 8 | vfs, data, fat, 0x200000, 0x200000, 9 | -------------------------------------------------------------------------------- /components/micropython/ports/ric/qstrdefsport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2014 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | // qstrs specific to this port, only needed if they aren't auto-generated 28 | // *FORMAT-OFF* 29 | 30 | // Entries for sys.path 31 | Q(/lib) 32 | -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Edit following two lines to set component requirements (see docs) 2 | set(COMPONENT_REQUIRES ) 3 | set(COMPONENT_PRIV_REQUIRES ) 4 | 5 | set(COMPONENT_SRCS "main.cpp") 6 | set(COMPONENT_ADD_INCLUDEDIRS "") 7 | 8 | register_component() 9 | 10 | # Create a SPIFFS image from the contents of the 'spiffs_image' directory 11 | # that fits the partition named 'spiffs'. FLASH_IN_PROJECT indicates that 12 | # the generated image should be flashed when the entire project is flashed to 13 | # the target with 'idf.py -p PORT flash'. 14 | spiffs_create_partition_image(spiffs ../spiffs_image FLASH_IN_PROJECT) 15 | -------------------------------------------------------------------------------- /main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Main component makefile. 3 | # 4 | # This Makefile can be left empty. By default, it will take the sources in the 5 | # src/ directory, compile them and link them into lib(subdirectory_name).a 6 | # in the build directory. This behaviour is entirely configurable, 7 | # please read the ESP-IDF documents if you need to do this. 8 | # 9 | -------------------------------------------------------------------------------- /main/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "freertos/FreeRTOS.h" 3 | #include "freertos/task.h" 4 | #include 5 | #include 6 | 7 | #include "Micropython.h" 8 | 9 | // Micropython 10 | Micropython _micropython; 11 | 12 | static const char* MODULE_PREFIX = "MAIN"; 13 | 14 | extern "C" void registerSPIFFS() 15 | { 16 | // Using ESP32 native SPIFFS support 17 | esp_vfs_spiffs_conf_t conf = { 18 | .base_path = "/spiffs", 19 | .partition_label = NULL, 20 | .max_files = 5, 21 | .format_if_mount_failed = false 22 | }; 23 | // Use settings defined above to initialize and mount SPIFFS filesystem. 24 | // Note: esp_vfs_spiffs_register is an all-in-one convenience function. 25 | esp_err_t ret = esp_vfs_spiffs_register(&conf); 26 | if (ret != ESP_OK) 27 | { 28 | if (ret == ESP_FAIL) 29 | ESP_LOGW(MODULE_PREFIX, "setup failed mount/format SPIFFS"); 30 | else if (ret == ESP_ERR_NOT_FOUND) 31 | ESP_LOGW(MODULE_PREFIX, "setup failed to find SPIFFS partition"); 32 | else 33 | ESP_LOGW(MODULE_PREFIX, "setup failed to init SPIFFS (error %s)", esp_err_to_name(ret)); 34 | } 35 | else 36 | { 37 | // Get SPIFFS info 38 | size_t total = 0, used = 0; 39 | esp_err_t ret = esp_spiffs_info(NULL, &total, &used); 40 | if (ret != ESP_OK) 41 | ESP_LOGW(MODULE_PREFIX, "setup failed to get SPIFFS info (error %s)", esp_err_to_name(ret)); 42 | else 43 | ESP_LOGI(MODULE_PREFIX, "setup SPIFFS partition size total %d, used %d", total, used); 44 | } 45 | } 46 | 47 | extern "C" void app_main(void) 48 | { 49 | registerSPIFFS(); 50 | int i = 0; 51 | _micropython.start(true, true, 65536, 1, 16384); 52 | while (1) { 53 | printf("[%d] Hello world!\n", i); 54 | i++; 55 | vTaskDelay(1000 / portTICK_PERIOD_MS); 56 | _micropython.addToQueue("test.py", false, false); 57 | vTaskDelay(5000 / portTICK_PERIOD_MS); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /partitions.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | nvs, data, nvs, 0x009000, 0x005000, 3 | otadata, data, ota, 0x00e000, 0x002000, 4 | app0, app, ota_0, 0x010000, 0x1b0000, 5 | app1, app, ota_1, 0x1c0000, 0x1b0000, 6 | spiffs, data, spiffs, 0x370000, 0x090000, -------------------------------------------------------------------------------- /scripts/SerialMonitor_curses.py: -------------------------------------------------------------------------------- 1 | # 2 | # Serial Monitor Utility for RIC Firmware Development 3 | # 4 | # Rob Dobson 2020 5 | # 6 | 7 | import time 8 | import logging 9 | import serial 10 | import sys, os 11 | import json 12 | import keyboard 13 | if os.name == 'nt': 14 | import msvcrt 15 | import threading 16 | import re 17 | import argparse 18 | import binascii 19 | 20 | import curses 21 | 22 | class SerialMon: 23 | 24 | def __init__(self): 25 | self.running = False 26 | self.removeESC = re.compile(r'\x1b[^m]*m') 27 | 28 | def open(self, serialPort, serialBaud, logToFile): 29 | 30 | self.logger = logging.getLogger(__name__) 31 | self.logger.setLevel(logging.DEBUG) 32 | self.serialPort = serialPort 33 | self.serialBaud = serialBaud 34 | # logch = logging.StreamHandler() 35 | # logch.setLevel(logging.DEBUG) 36 | # self.logger.addHandler(logch) 37 | 38 | # Log to file if required 39 | if logToFile: 40 | # Check the log folder exists 41 | logsFolder = "logs" 42 | if not os.path.exists(logsFolder): 43 | os.mkdir(logsFolder) 44 | 45 | # Form log file name 46 | logFileName = time.strftime("%Y%m%d-%H%M%S") + ".log" 47 | logFileName = os.path.join(logsFolder, logFileName) 48 | print("Logging to file " + logFileName) 49 | logfh = logging.FileHandler(logFileName) 50 | logfh.setLevel(logging.DEBUG) 51 | # logformatter = logging.Formatter('%(asctime)s: %(name)s %(levelname)s %(message)s') 52 | # logfh.setFormatter(logformatter) 53 | self.logger.addHandler(logfh) 54 | 55 | return self.portOpen() 56 | 57 | def portOpen(self): 58 | # Open the serial connection 59 | try: 60 | self.ser = serial.Serial( 61 | port=self.serialPort, 62 | baudrate=self.serialBaud, 63 | parity=serial.PARITY_NONE, 64 | stopbits=serial.STOPBITS_ONE, 65 | bytesize=serial.EIGHTBITS 66 | ) 67 | except Exception as excp: 68 | self.logger.error("Serial Port " + self.serialPort + " " + str(excp)) 69 | return False 70 | try: 71 | self.ser.set_buffer_size(20000, None) 72 | except Exception: 73 | self.logger.error("Failed to set serial buffer size") 74 | 75 | self.logger.info(f"SerialMonitor port {self.serialPort} baudrate {self.serialBaud}") 76 | sys.stdout.flush() 77 | 78 | # Setup serial 79 | self.startReader(self.onRx) 80 | return True 81 | 82 | def close(self): 83 | try: 84 | self.stopReader() 85 | self.ser.close() 86 | except Exception as excp: 87 | print("Error stopping and closing port", excp) 88 | 89 | def send(self, data): 90 | self.ser.write(data) 91 | 92 | def onRx(self, rxData): 93 | print(rxData, end="") 94 | rxLines = rxData.splitlines() 95 | for line in rxLines: 96 | sLine = line.strip() 97 | if len(sLine) == 0: 98 | continue 99 | self.logger.info(sLine) 100 | 101 | def startReader(self, onData): 102 | if self.running: 103 | raise RuntimeError("reader already running") 104 | self.reader = threading.Thread(target=self._receiveLoop) 105 | self.reader.setDaemon(True) 106 | self.data_callback = onData 107 | self.running = True 108 | self.reader.start() 109 | 110 | def stopReader(self): 111 | self.running = False 112 | try: 113 | self.reader.join() 114 | except: 115 | pass 116 | self.reader = None 117 | 118 | def _receiveLoop(self): 119 | while self.running: 120 | try: 121 | numWaiting = self.ser.in_waiting 122 | if numWaiting < 1: 123 | time.sleep(0.001) 124 | # print(".", end="") 125 | # sys.stdout.flush() 126 | continue 127 | rxBytes = bytearray(self.ser.read(numWaiting)) 128 | endPos = -1 129 | for i in range(len(rxBytes)): 130 | if rxBytes[i] > 127: 131 | endPos = i 132 | break 133 | if endPos >= 0: 134 | rxAscii = rxBytes[:endPos] 135 | rxBytes = rxBytes[endPos:] 136 | else: 137 | rxAscii = rxBytes 138 | for i in range(len(rxAscii)): 139 | if rxAscii[i] > 127: 140 | print("SOMETHING WENT WRONG pos", i, "endPos", endPos) 141 | ascText = rxAscii.decode("utf-8") 142 | # ascText = self.removeESC.sub('', ascText) 143 | self.data_callback(ascText) 144 | if endPos >= 0: 145 | self.data_callback("\n" + binascii.hexlify(rxBytes).decode("utf-8") + "\n") 146 | except Exception as excp: 147 | print("Error in serial", excp) 148 | time.sleep(5.0) 149 | try: 150 | self.close() 151 | self.portOpen() 152 | except Exception as excp2: 153 | print("Error reopening serial", excp2) 154 | 155 | # Mac and Linux only 156 | def handleKey(keyInfo): 157 | global breakRequested 158 | if keyInfo.name == 'esc': 159 | breakRequested = True 160 | # User is providing command input 161 | if keyInfo.name == 'i': 162 | handleCommand() 163 | 164 | def handleCommand(): 165 | # Initialise curses and open a window object/terminal screen for command input in the 166 | # current terminal screen. 167 | stdscr = curses.initscr() 168 | stdscr.addstr("Enter your command to send to Marty: ") 169 | stdscr.refresh() 170 | # Store the command entered (in bytes automatically) and exit curses terminal screen 171 | command = stdscr.getstr() + b"\r" 172 | curses.endwin() 173 | # Send command through the serial port 174 | serialMon.send(command) 175 | 176 | def sendCommand(command): 177 | serialMon.send((command + "\r").encode('utf-8')) 178 | 179 | def sendCommands(command, n, moveTime): 180 | print(command) 181 | while n > 0: 182 | sendCommand(command) 183 | time.sleep(moveTime ) 184 | n -= 1 185 | 186 | def demo(): 187 | moveTimeFast = "?moveTime=1000" 188 | moveTimeSlow = "?moveTime=2500" 189 | moveTimeVerySlow = "?moveTime=4500" 190 | dance = "traj/dance" 191 | step = "traj/step" 192 | turn = "traj/step?turn=50" 193 | kick = "traj/kick" 194 | kickLeft = kick + moveTimeSlow + "side=0" 195 | kickRight = kick + moveTimeSlow + "side=1" 196 | sidestep = "traj/sidestep" 197 | sidefall = "traj/sidefall" 198 | wiggle = "traj/wiggle" 199 | wave = "traj/wave" 200 | waveLeft = wave + moveTimeSlow + "side=0" 201 | waveRight = wave + moveTimeSlow + "side=1" 202 | wiggleEyes = "traj/wiggleEyes" 203 | circle = "traj/circle" 204 | eyesAngry = "traj/eyesAngry" 205 | eyesExcited = "traj/eyesExcited" 206 | eyesNormal = "traj/eyesNormal" 207 | eyesWide = "traj/eyesWide" 208 | hold = "traj/hold" 209 | getReady = "traj/getReady" 210 | joint = "traj/joint" 211 | liftFoot = "traj/liftFoot" 212 | lowerFoot = "traj/lowerFoot" 213 | 214 | sendCommands(getReady + moveTimeFast, 2, 1) 215 | sendCommands(step + moveTimeFast, 10, 1) 216 | sendCommands(circle + moveTimeSlow, 1, 2.5) 217 | sendCommands(dance + moveTimeVerySlow, 1, 4.5) 218 | sendCommands(turn + moveTimeFast, 12, 1) 219 | time.sleep(3) 220 | sendCommands(waveLeft, 1, 1) 221 | sendCommands(waveRight, 1, 1) 222 | sendCommands(kickLeft, 1, 2.5) 223 | sendCommands(kickRight, 1, 2.5) 224 | time.sleep(3) 225 | sendCommands(dance + moveTimeSlow, 1, 1.5) 226 | sendCommands(getReady, 1, 1) 227 | 228 | 229 | # Handle arguments 230 | argparser = argparse.ArgumentParser(description='Serial Monitor') 231 | argparser.add_argument('serialPort', action='store') 232 | argparser.add_argument('-b', action='store', default=115200, dest='serialbaud') 233 | argparser.add_argument('-g', action='store_true', default=False, dest='logToFile', 234 | help='log to a file in ./logs folder with date-time based name') 235 | args = argparser.parse_args() 236 | 237 | # Serial 238 | serialMon = SerialMon() 239 | serMonOpenOk = serialMon.open(args.serialPort, args.serialbaud, args.logToFile) 240 | if os.name != 'nt': 241 | keyboard.on_press(handleKey) 242 | breakRequested = False 243 | if serMonOpenOk: 244 | print("Serial Monitor Started") 245 | else: 246 | print("Couldn't open serial port") 247 | while serMonOpenOk and not breakRequested: 248 | if os.name == 'nt': 249 | if msvcrt.kbhit(): 250 | ch = msvcrt.getch() 251 | if ord(ch) == 27: # ESC 252 | breakRequested = True 253 | print("Stopping - user hit ESC") 254 | elif ord(ch) == ord('i'): #i sets up input 255 | handleCommand() 256 | elif ord(ch) == ord("d"): #d sets up demo 257 | demo() 258 | time.sleep(0.1) 259 | serialMon.close() 260 | -------------------------------------------------------------------------------- /sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # Define configuration 2 | # Remove/repace these comments to set level to debug/info 3 | 4 | #CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y 5 | #CONFIG_LOG_DEFAULT_LEVEL=4 6 | 7 | # Partition Table 8 | CONFIG_PARTITION_TABLE_CUSTOM=y 9 | CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" 10 | 11 | # Serial flasher config 12 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 13 | CONFIG_ESPTOOLPY_FLASHSIZE="4MB" 14 | 15 | # FreeRTOS 16 | CONFIG_FREERTOS_HZ=100 17 | 18 | # For MicroPython 19 | CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y 20 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 21 | 22 | # SPIRAM 23 | #CONFIG_ESP32_SPIRAM_SUPPORT=y 24 | #CONFIG_SPIRAM_CACHE_WORKAROUND=y 25 | #CONFIG_SPIRAM_IGNORE_NOTFOUND=y 26 | #CONFIG_SPIRAM_USE_MEMMAP=y 27 | -------------------------------------------------------------------------------- /spiffs_image/test.py: -------------------------------------------------------------------------------- 1 | print("Hello from MicroPython") 2 | --------------------------------------------------------------------------------