├── custommade.zip ├── firmwares ├── 20191209 │ └── firmware.bin ├── 20191213 │ └── firmware.bin ├── tools │ ├── erase.sh │ └── flash.sh ├── 1-11-20191010 │ └── firmware.bin ├── 1-11-20191026 │ └── firmware.bin ├── 1-11-20191107 │ └── firmware.bin └── README.md ├── esp32-cam-1-11-571 ├── boards │ ├── GENERIC │ │ └── mpconfigboard.h │ ├── manifest.py │ └── sdkconfig.base ├── build-GENERIC │ └── firmware.bin ├── README.md ├── main.c ├── modcamera.c ├── mpconfigport.h └── Makefile ├── esp32-cam-1-11-498 ├── build-GENERIC │ └── firmware.bin ├── boards │ ├── manifest.py │ └── sdkconfig.base ├── README_MODCAMERA.md ├── README.md ├── main.c ├── modcamera.c ├── mpconfigport.h └── Makefile ├── notes ├── README-NO-WEBREPL.txt ├── README-MODIFICATION.txt ├── README_FRAMESIZE.txt ├── README-BUILD-1-11-498 └── README-BUILD.txt ├── webcam ├── README.md ├── Wifi │ ├── Ap.py │ └── Sta.py ├── async_tasks_webcam_ap.py ├── async_tasks_webcam_sta.py ├── uasyncio │ ├── __init__.py │ └── core.py ├── webcam.py └── mth_webcam.py └── README.md /custommade.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython/HEAD/custommade.zip -------------------------------------------------------------------------------- /firmwares/tools/erase.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | esptool.py --port /dev/ttyUSB0 erase_flash 4 | 5 | -------------------------------------------------------------------------------- /firmwares/20191209/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython/HEAD/firmwares/20191209/firmware.bin -------------------------------------------------------------------------------- /firmwares/20191213/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython/HEAD/firmwares/20191213/firmware.bin -------------------------------------------------------------------------------- /firmwares/1-11-20191010/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython/HEAD/firmwares/1-11-20191010/firmware.bin -------------------------------------------------------------------------------- /firmwares/1-11-20191026/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython/HEAD/firmwares/1-11-20191026/firmware.bin -------------------------------------------------------------------------------- /firmwares/1-11-20191107/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython/HEAD/firmwares/1-11-20191107/firmware.bin -------------------------------------------------------------------------------- /esp32-cam-1-11-571/boards/GENERIC/mpconfigboard.h: -------------------------------------------------------------------------------- 1 | #define MICROPY_HW_BOARD_NAME "ESP32 module (camera)" 2 | #define MICROPY_HW_MCU_NAME "ESP32" 3 | -------------------------------------------------------------------------------- /esp32-cam-1-11-498/build-GENERIC/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython/HEAD/esp32-cam-1-11-498/build-GENERIC/firmware.bin -------------------------------------------------------------------------------- /esp32-cam-1-11-571/build-GENERIC/firmware.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shariltumin/esp32-cam-micropython/HEAD/esp32-cam-1-11-571/build-GENERIC/firmware.bin -------------------------------------------------------------------------------- /notes/README-NO-WEBREPL.txt: -------------------------------------------------------------------------------- 1 | 2 | cd modules 3 | 4 | rm webrepl.py 5 | rm webrepl_setup.py 6 | rm websocket_helper.py 7 | 8 | rm upip.py 9 | rm upip_utarfile.py 10 | 11 | -------------------------------------------------------------------------------- /firmwares/tools/flash.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | esptool.py \ 4 | --chip esp32 \ 5 | --port /dev/ttyUSB0 \ 6 | --baud 460800 write_flash \ 7 | -z 0x1000 firmware.bin 8 | 9 | 10 | -------------------------------------------------------------------------------- /notes/README-MODIFICATION.txt: -------------------------------------------------------------------------------- 1 | 2 | In order to compile camera support do: 3 | 4 | 1) Edit Makefile 5 | 2) modcamera.c 6 | 3) Edit mpconfigport.h 7 | 4) Edit main.c 8 | 5) Edit boards/sdkconfig.base 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /esp32-cam-1-11-498/boards/manifest.py: -------------------------------------------------------------------------------- 1 | freeze('$(PORT_DIR)/modules') 2 | # freeze('$(MPY_DIR)/tools', ('upip.py', 'upip_utarfile.py')) 3 | freeze('$(MPY_DIR)/ports/esp8266/modules', 'ntptime.py') 4 | # freeze('$(MPY_DIR)/ports/esp8266/modules', ('webrepl.py', 'webrepl_setup.py', 'websocket_helper.py',)) 5 | freeze('$(MPY_DIR)/drivers/dht', 'dht.py') 6 | freeze('$(MPY_DIR)/drivers/onewire') 7 | -------------------------------------------------------------------------------- /esp32-cam-1-11-571/boards/manifest.py: -------------------------------------------------------------------------------- 1 | freeze('$(PORT_DIR)/modules') 2 | # freeze('$(MPY_DIR)/tools', ('upip.py', 'upip_utarfile.py')) 3 | freeze('$(MPY_DIR)/ports/esp8266/modules', 'ntptime.py') 4 | # freeze('$(MPY_DIR)/ports/esp8266/modules', ('webrepl.py', 'webrepl_setup.py', 'websocket_helper.py',)) 5 | freeze('$(MPY_DIR)/drivers/dht', 'dht.py') 6 | freeze('$(MPY_DIR)/drivers/onewire') 7 | -------------------------------------------------------------------------------- /esp32-cam-1-11-571/README.md: -------------------------------------------------------------------------------- 1 | You can compile and build you own firmware by following this [workflow](https://github.com/shariltumin/esp32-cam-micropython/blob/master/esp32-cam-1-11-498/README.md). 2 | 3 | For this firmware I modified one more file, [mpconfigboard.h](https://github.com/shariltumin/esp32-cam-micropython/blob/master/esp32-cam-1-11-571/boards/GENERIC/mpconfigboard.h) which give label to MicroPython. 4 | -------------------------------------------------------------------------------- /notes/README_FRAMESIZE.txt: -------------------------------------------------------------------------------- 1 | FRAMESIZE_QQVGA, // 160x120 2 | FRAMESIZE_QQVGA2, // 128x160 3 | FRAMESIZE_QCIF, // 176x144 4 | FRAMESIZE_HQVGA, // 240x176 5 | FRAMESIZE_QVGA, // 320x240 6 | FRAMESIZE_CIF, // 400x296 7 | FRAMESIZE_VGA, // 640x480 8 | FRAMESIZE_SVGA, // 800x600 9 | FRAMESIZE_XGA, // 1024x768 10 | FRAMESIZE_SXGA, // 1280x1024 11 | FRAMESIZE_UXGA, // 1600x1200 12 | FRAMESIZE_QXGA, // 2048*1536 13 | -------------------------------------------------------------------------------- /esp32-cam-1-11-498/README_MODCAMERA.md: -------------------------------------------------------------------------------- 1 | I have improved the modcamera.c code to incorporate seven new additional functions: 2 | 3 | 4 | 1) framesize 5 | 6 | 2) quality 7 | 8 | 3) contrast 9 | 10 | 4) saturation 11 | 12 | 5) brightness 13 | 14 | 6) speffect 15 | 16 | 7) whitebalance 17 | 18 | 19 | They are all callable after camera.init(), which means, we can change those properties at the run time. 20 | 21 | Read this [post](https://kopimojo.blogspot.com/2019/10/micropython-v1.html) in my [blog](https://kopimojo.blogspot.com). 22 | -------------------------------------------------------------------------------- /webcam/README.md: -------------------------------------------------------------------------------- 1 | 2 | **Latest** script for webcam is mth_webcam.py a multi-threaded web server. Two threads serving port 80, one thread serving port 81, and the main thread serving port 82. The REPL is blocked. You can start one thread for port 82 if you want. In the main.py: 3 | 4 | ```python 5 | import mth_webcam.py 6 | ``` 7 | will start the webcam server at hard reset (power cycle). Read [this](https://kopimojo.blogspot.com/2019/11/multi-threading-i-previously-used.html) blog concerning my multi-threaded webcam server. 8 | 9 | Simple experimental webcam servers in AP and STA mode built using uasyncio. 10 | 11 | The uasyncio package is provided here for your convenience. Please use the latest official version. 12 | 13 | The WiFi is a utility module. Please change the SSID and password for your home network. 14 | 15 | Read [my blog](https://kopimojo.blogspot.com/) 16 | -------------------------------------------------------------------------------- /webcam/Wifi/Ap.py: -------------------------------------------------------------------------------- 1 | 2 | import network 3 | 4 | class Ap: 5 | 6 | SID = 'ESP32-KUDA2-10041' 7 | PWD = 'Musang6241King' 8 | IP = '10.0.4.1' 9 | 10 | def __init__(my, sid='', pwd=''): 11 | my.ap = network.WLAN(network.AP_IF) 12 | my.ap.active(True) 13 | if sid == '': 14 | my.SID = Ap.SID 15 | my.PWD = Ap.PWD 16 | else: 17 | my.SID = sid 18 | my.PWD = pwd 19 | my.ap.config(essid=my.SID) 20 | my.ap.config(authmode=3, password=my.PWD) 21 | 22 | def ip(my, adr=''): 23 | # default is 24 | # ('192.168.4.1', '255.255.255.0', '192.168.4.1', '0.0.0.0') 25 | # IP address, netmask, gateway, DNS 26 | # setting to another IP, dateway and DNS server 27 | if adr == '': 28 | z = (Ap.IP, '255.255.255.0', Ap.IP, '0.0.0.0') 29 | else: 30 | z = (adr, '255.255.255.0', adr, '0.0.0.0') 31 | my.ap.ifconfig(z) 32 | print(my.ap.ifconfig()) 33 | 34 | def status(my): 35 | return my.ap.ifconfig() 36 | 37 | 38 | -------------------------------------------------------------------------------- /esp32-cam-1-11-498/boards/sdkconfig.base: -------------------------------------------------------------------------------- 1 | # MicroPython on ESP32, ESP IDF configuration 2 | # The following options override the defaults 3 | 4 | CONFIG_IDF_TARGET="esp32" 5 | 6 | # Application manager 7 | CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y 8 | CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=y 9 | 10 | # Bootloader config 11 | CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y 12 | 13 | # ESP32-specific 14 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=n 15 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=n 16 | CONFIG_ESP32_XTAL_FREQ_AUTO=y 17 | 18 | # MicroPython on ESP32, ESP IDF configuration with 240MHz CPU 19 | CONFIG_ESP32_DEFAULT_CPU_FREQ_80= 20 | CONFIG_ESP32_DEFAULT_CPU_FREQ_160= 21 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y 22 | CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 23 | 24 | # SPIRAM 25 | CONFIG_SPIRAM_SUPPORT=y 26 | CONFIG_SPIRAM_IGNORE_NOTFOUND=y 27 | CONFIG_SPIRAM_USE_MEMMAP=y 28 | CONFIG_SPIRAM_USE_MALLOC=y 29 | 30 | # Power Management 31 | CONFIG_PM_ENABLE=y 32 | 33 | # FreeRTOS 34 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 35 | CONFIG_SUPPORT_STATIC_ALLOCATION=y 36 | CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y 37 | 38 | # UDP 39 | CONFIG_LWIP_PPP_SUPPORT=y 40 | CONFIG_LWIP_PPP_PAP_SUPPORT=y 41 | CONFIG_LWIP_PPP_CHAP_SUPPORT=y 42 | CONFIG_PPP_SUPPORT=y 43 | CONFIG_PPP_PAP_SUPPORT=y 44 | CONFIG_PPP_CHAP_SUPPORT=y 45 | 46 | # ESP32-CAMERA 47 | CONFIG_OV2640_SUPPORT=y 48 | #CONFIG_OV7725_SUPPORT=y 49 | 50 | -------------------------------------------------------------------------------- /esp32-cam-1-11-571/boards/sdkconfig.base: -------------------------------------------------------------------------------- 1 | # MicroPython on ESP32, ESP IDF configuration 2 | # The following options override the defaults 3 | 4 | CONFIG_IDF_TARGET="esp32" 5 | 6 | # Application manager 7 | CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y 8 | CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=y 9 | 10 | # Bootloader config 11 | CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y 12 | 13 | # ESP32-specific 14 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=n 15 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=n 16 | CONFIG_ESP32_XTAL_FREQ_AUTO=y 17 | 18 | # MicroPython on ESP32, ESP IDF configuration with 240MHz CPU 19 | CONFIG_ESP32_DEFAULT_CPU_FREQ_80= 20 | CONFIG_ESP32_DEFAULT_CPU_FREQ_160= 21 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y 22 | CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 23 | 24 | # SPIRAM 25 | CONFIG_SPIRAM_SUPPORT=y 26 | CONFIG_SPIRAM_IGNORE_NOTFOUND=y 27 | CONFIG_SPIRAM_USE_MEMMAP=y 28 | CONFIG_SPIRAM_USE_MALLOC=y 29 | 30 | # Power Management 31 | CONFIG_PM_ENABLE=y 32 | 33 | # FreeRTOS 34 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 35 | CONFIG_SUPPORT_STATIC_ALLOCATION=y 36 | CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y 37 | 38 | # UDP 39 | CONFIG_LWIP_PPP_SUPPORT=y 40 | CONFIG_LWIP_PPP_PAP_SUPPORT=y 41 | CONFIG_LWIP_PPP_CHAP_SUPPORT=y 42 | CONFIG_PPP_SUPPORT=y 43 | CONFIG_PPP_PAP_SUPPORT=y 44 | CONFIG_PPP_CHAP_SUPPORT=y 45 | 46 | # ESP32-CAMERA 47 | CONFIG_OV2640_SUPPORT=y 48 | #CONFIG_OV7725_SUPPORT=y 49 | 50 | -------------------------------------------------------------------------------- /webcam/Wifi/Sta.py: -------------------------------------------------------------------------------- 1 | 2 | #Basic WiFi configuration: 3 | 4 | from time import sleep 5 | import network 6 | 7 | class Sta: 8 | 9 | AP = "YourHomeNetSSID" 10 | PWD = "YourHomeNetPassword" 11 | 12 | def __init__(my, ap='', pwd=''): 13 | network.WLAN(network.AP_IF).active(False) # disable access point 14 | my.wlan = network.WLAN(network.STA_IF) 15 | my.wlan.active(True) 16 | if ap == '': 17 | my.ap = Sta.AP 18 | my.pwd = Sta.PWD 19 | else: 20 | my.ap = ap 21 | my.pwd = pwd 22 | 23 | def connect(my, ap='', pwd=''): 24 | if ap != '': 25 | my.ap = ap 26 | my.pwd = pwd 27 | 28 | if not my.wlan.isconnected(): 29 | my.wlan.connect(my.ap, my.pwd) 30 | 31 | def status(my): 32 | if my.wlan.isconnected(): 33 | return my.wlan.ifconfig() 34 | else: 35 | return () 36 | 37 | def wait(my): 38 | cnt = 30 39 | while cnt > 0: 40 | print("Waiting ..." ) 41 | # con(my.ap, my.pwd) # Connect to an AP 42 | if my.wlan.isconnected(): 43 | print("Connected to %s" % my.ap) 44 | print('network config:', my.wlan.ifconfig()) 45 | cnt = 0 46 | else: 47 | sleep(5) 48 | cnt -= 5 49 | return 50 | 51 | def scan(my): 52 | return my.wlan.scan() # Scan for available access points 53 | 54 | -------------------------------------------------------------------------------- /notes/README-BUILD-1-11-498: -------------------------------------------------------------------------------- 1 | 2 | $ cd micropython_src/ 3 | 4 | $ mkdir MP26102019 5 | 6 | $ cd MP26102019 7 | 8 | $ pwd 9 | /home/sharil/micropython_src/MP26102019 10 | 11 | $ git clone https://github.com/espressif/esp-idf.git 12 | 13 | $ git clone https://github.com/micropython/micropython 14 | 15 | $ ls 16 | esp-idf micropython 17 | 18 | $ cat micropython/ports/esp32/Makefile | grep ESPIDF_SUPHASH | head -1 19 | ESPIDF_SUPHASH_V3 := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df 20 | 21 | $ export PATH="/home/sharil/micropython/xtensa-esp32-elf/bin:/home/sharil/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 22 | 23 | $ export ESPIDF=/home/sharil/micropython_src/MP26102019/esp-idf 24 | 25 | $ cd $ESPIDF 26 | 27 | $ git checkout 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df 28 | 29 | $ git submodule update --init --recursive 30 | 31 | $ cd components 32 | 33 | $ git clone https://github.com/espressif/esp32-camera.git 34 | 35 | $ cd ../../micropython/ 36 | 37 | $ git submodule update --init --recursive 38 | 39 | $ make -C mpy-cross 40 | 41 | $ cd ports 42 | 43 | $ cp -r esp32 esp32-cam 44 | 45 | $ cd esp32-cam 46 | 47 | $ export MPTD=/home/sharil/Downloads/esp32-cam-1-11-498 48 | 49 | $ cp $MPTD/main.c . 50 | $ cp $MPTD/Makefile . 51 | $ cp $MPTD/modcamera.c . 52 | $ cp $MPTD/mpconfigport.h . 53 | $ cp $MPTD/boards/manifest.py ./boards/manifest.py 54 | $ cp $MPTD/boards/sdkconfig.base ./boards/sdkconfig.base 55 | 56 | $ make clean 57 | 58 | $ make 59 | 60 | 61 | -------------------------------------------------------------------------------- /firmwares/README.md: -------------------------------------------------------------------------------- 1 | # Micropython firmwares that support esp32-cam. 2 | 3 | **LATEST** - The latest firmware is under 20191213 - MicroPython v1.11-665-gfb0141559-kaki5 4 | 5 | You can download [custommade.zip](https://github.com/shariltumin/esp32-cam-micropython/blob/master/custommade.zip) and read [this blog](https://kopimojo.blogspot.com/2019/12/custom-made-sometimes-it-is-nice-to-be.html) to build custom made firmware. 6 | 7 | To flash the firmware.bin follow the steps below: 8 | 1. connect GPIO0 to GND 9 | 2. press reset or pull out/ push in USB serial adapter 10 | 3. run erase.sh, to erase flash memory 11 | 4. press reset or pull out/ push in USB serial adapter 12 | 5. run flash.sh to upload the firmware.bin to flash memory 13 | 6. disconnect GPIO0 from GND 14 | 15 | You find erase.sh and flash.sh under [tools](https://github.com/shariltumin/esp32-cam-micropython/tree/master/firmwares/tools). 16 | You may need to install esptool.py 17 | 18 | To test (I run this on linux, you may need to change the port) 19 | 20 | ``` 21 | rshell -n -p /dev/ttyUSB0 22 | ... 23 | /home/st> repl 24 | ... 25 | >>> import camera 26 | >>> dir(camera) 27 | ['__class__', '__name__', 'capture', 'deinit', 'flip', 'init'] 28 | >>> camera.init() 29 | True 30 | >>> img = camera.capture() 31 | >>> len(img) 32 | 84145 33 | >>> print(img[0:8]) 34 | b'\xff\xd8\xff\xe0\x00\x10JF' 35 | >>> camera.deinit() 36 | True 37 | ``` 38 | You now have camera enabled micropython. Nice! 39 | 40 | Read [my blog](https://kopimojo.blogspot.com/). 41 | -------------------------------------------------------------------------------- /esp32-cam-1-11-498/README.md: -------------------------------------------------------------------------------- 1 | $ cd micropython_src/ 2 | 3 | $ mkdir MP26102019 4 | 5 | $ cd MP26102019 6 | 7 | $ pwd 8 | 9 | /home/sharil/micropython_src/MP26102019 10 | 11 | $ git clone https://github.com/espressif/esp-idf.git 12 | 13 | $ git clone https://github.com/micropython/micropython 14 | 15 | $ ls 16 | 17 | esp-idf micropython 18 | 19 | $ cat micropython/ports/esp32/Makefile | grep ESPIDF_SUPHASH | head -1 20 | 21 | ESPIDF_SUPHASH_V3 := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df 22 | 23 | $ export PATH="/home/sharil/micropython/xtensa-esp32-elf/bin:/home/sharil/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 24 | 25 | $ export ESPIDF=/home/sharil/micropython_src/MP26102019/esp-idf 26 | 27 | $ cd $ESPIDF 28 | 29 | $ git checkout 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df 30 | 31 | $ git submodule update --init --recursive 32 | 33 | $ cd components 34 | 35 | $ git clone https://github.com/espressif/esp32-camera.git 36 | 37 | $ cd ../../micropython/ 38 | 39 | $ git submodule update --init --recursive 40 | 41 | $ make -C mpy-cross 42 | 43 | $ cd ports 44 | 45 | $ cp -r esp32 esp32-cam 46 | 47 | $ cd esp32-cam 48 | 49 | $ export MPTD=/home/sharil/Downloads/esp32-cam-1-11-498 50 | 51 | $ cp $MPTD/main.c . 52 | 53 | $ cp $MPTD/Makefile . 54 | 55 | $ cp $MPTD/modcamera.c . 56 | 57 | $ cp $MPTD/mpconfigport.h . 58 | 59 | $ cp $MPTD/boards/manifest.py ./boards/manifest.py 60 | 61 | $ cp $MPTD/boards/sdkconfig.base ./boards/sdkconfig.base 62 | 63 | $ make clean 64 | 65 | $ make 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Please go to the new repository https://github.com/shariltumin/esp32-cam-micropython-2022 3 | 4 | # esp32-cam-micropython 5 | 6 | **Latest** custommade.zip, please read [this blog](https://kopimojo.blogspot.com/2019/12/custom-made-sometimes-it-is-nice-to-be.html) and find out what it is good for. 7 | 8 | The custommade.zip now contains files that will also include LittleFS in the firmware for esp32-cam, esp32 and esp8266. Please watch Damien George explaining what LittleFS is good for, at a [Melbourne micropython meeting](https://www.youtube.com/watch?v=wkgU4fGP3eY). 9 | 10 | You can use LittleFS instead of FatFS(default) by doing these in REPL: 11 | 12 | ``` 13 | >>> import os 14 | >>> os.VfsLfs2.mkfs(bdev) 15 | 16 | ``` 17 | 18 | You will save RAM if you use LittleFS. The FS setting will survive reboot and power cycle. 19 | 20 | 21 | The files in the directories under are obsolete: 22 | 23 | 1. esp32-cam-1-11-498 24 | 2. esp32-cam-1-11-571 25 | 26 | 27 | Please use files under Custommade_Template directory packed in the custommade.zip. Better yet run mpb.py to build custom made firmware. 28 | 29 | If you're looking for a compiled firmware that support camera for your esp32-cam board then please click [firmwares](https://github.com/shariltumin/esp32-cam-micropython/tree/master/firmwares). 30 | 31 | You can find some webcam server test scripts in [webcam](https://github.com/shariltumin/esp32-cam-micropython/tree/master/webcam). **Latest** is [mth_webcam.py](https://github.com/shariltumin/esp32-cam-micropython/blob/master/webcam/mth_webcam.py) a multi-threaded three ports web server. Serving webcam at port 80. 32 | 33 | I record my works at [kopimojo.blogspot.com](https://kopimojo.blogspot.com/) feel free to drop by. 34 | -------------------------------------------------------------------------------- /notes/README-BUILD.txt: -------------------------------------------------------------------------------- 1 | 2 | - Change to home directory 3 | $ cd 4 | 5 | - Create working directory 6 | $ mkdir Esp32Cam 7 | 8 | - Go to working directory 9 | $ cd Esp32Cam 10 | 11 | - Get micropython 12 | $ git clone https://github.com/micropython/micropython.git 13 | 14 | - Get espressif esp-idf 15 | $ git clone https://github.com/espressif/esp-idf.git 16 | 17 | - Find out which esp-idf version we need to compile micropython 18 | $ cat micropython/ports/esp32/Makefile | grep ESPIDF_SUPHASH | head -1 19 | ESPIDF_SUPHASH := 6b3da6b1882f3b72e904cc90be67e9c4e3f369a9 20 | 21 | - Prepare esp-idf 22 | $ cd esp-idf 23 | 24 | - Check out the version of esp-idf this micropython need (example) from above 25 | $ git checkout 6b3da6b1882f3b72e904cc90be67e9c4e3f369a9 26 | 27 | - Get all submodule 28 | $ git submodule update --init --recursive 29 | 30 | - Get the camera component of esp-idf 31 | $ cd components 32 | 33 | - from espressif esp32-camera. Note down the name of cloned directory. 34 | $ git clone https://github.com/espressif/esp32-camera.git 35 | 36 | - Now prepare micropython. Change working directory to micropython clone 37 | $ cd ~/Esp32Cam/micropython 38 | 39 | - Get all needed submodule 40 | $ git submodule update --init --recursive 41 | 42 | - Setup PATH variable with xtensa-esp32-elf tool (example) 43 | $ export PATH="/home/st/micropython/xtensa-esp32-elf/bin:/home/st/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 44 | 45 | - Setup ESPIDF (example) 46 | $ export ESPIDF=/home/st/Esp32Cam/esp-idf 47 | 48 | - Make mpy-cross needs for frozen python module 49 | $ make -C mpy-cross 50 | 51 | - Make esp32-cam port 52 | $ cd ports 53 | 54 | - Copy from esp32 port 55 | $ cp -r esp32 esp32-cam 56 | 57 | - Workspace ready under esp32-cam. Do modification 58 | $ cd esp32-cam 59 | 60 | - Copy all files needed which will build micropython with camera module 61 | - assumming these files are under ~/Downloads/esp32-cam 62 | $ cp ~/Downloads/esp32-cam/mpconfigport.h mpconfigport.h 63 | $ cp ~/Downloads/esp32-cam/modcamera.c modcamera.c 64 | $ cp ~/Downloads/esp32-cam/main.c main.c 65 | $ cp ~/Downloads/esp32-cam/Makefile Makefile 66 | $ cp ~/Downloads/esp32-cam/boards/sdkconfig.base boards/sdkconfig.base 67 | 68 | - Edit modcamera.c pixel_format and jpeg_quality 69 | - .frame_size = FRAMESIZE_XGA # good enough for streaming 70 | - .frame_size = FRAMESIZE_UXGA # good still photo 71 | $ vi modcamera.c 72 | 73 | - Reduce the firmware size by deleting modules under modules (example) 74 | $ rm modules/webrepl.py 75 | $ rm modules/webrepl_setup.py 76 | $ rm modules/websocket_helper.py 77 | $ rm modules/upip.py 78 | $ rm modules/upip_utarfile.py 79 | 80 | - Clean up 81 | $ make clean 82 | 83 | - Build micropython with camera support 84 | $ make V=1 85 | 86 | - When done see what micropython we got (example) 87 | $ strings build-GENERIC/firmware.bin | grep MicroPython | tail -1 88 | MicroPython v1.11-292-g5641aa55d-dirty on 2019-09-11; ESP32 module with ESP32 89 | 90 | - Do we have camera? (example) 91 | $ strings build-GENERIC/firmware.bin | grep camera 92 | camera 93 | [0;31mE (%d) %s: Detected camera not supported. 94 | /home/st/Esp32Cam/esp-idf/components/esp32-camera-for-micropython/driver/camera.c 95 | camera_xclk 96 | 97 | - Nice, we did it, celebrate have a cup of coffe with cream and read my blog. 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /esp32-cam-1-11-498/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 | #include "esp_spiram.h" 41 | 42 | #include "py/stackctrl.h" 43 | #include "py/nlr.h" 44 | #include "py/compile.h" 45 | #include "py/runtime.h" 46 | #include "py/repl.h" 47 | #include "py/gc.h" 48 | #include "py/mphal.h" 49 | #include "lib/mp-readline/readline.h" 50 | #include "lib/utils/pyexec.h" 51 | #include "uart.h" 52 | #include "modmachine.h" 53 | #include "modnetwork.h" 54 | #include "mpthreadport.h" 55 | 56 | // MicroPython runs as a task under FreeRTOS 57 | #define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) 58 | #define MP_TASK_STACK_SIZE (16 * 1024) 59 | #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) 60 | 61 | int vprintf_null(const char *format, va_list ap) { 62 | // do nothing: this is used as a log target during raw repl mode 63 | return 0; 64 | } 65 | 66 | void mp_task(void *pvParameter) { 67 | volatile uint32_t sp = (uint32_t)get_sp(); 68 | #if MICROPY_PY_THREAD 69 | mp_thread_init(pxTaskGetStackStart(NULL), MP_TASK_STACK_LEN); 70 | #endif 71 | uart_init(); 72 | 73 | #if CONFIG_SPIRAM_SUPPORT 74 | // allocate part of PSRAM for micropython, leave rest for native camera module 75 | size_t mp_task_heap_size = 2 * 1024 * 1024; 76 | void *mp_task_heap = malloc(mp_task_heap_size); 77 | ESP_LOGI("main", "Allocated %dK for micropython heap at %p", mp_task_heap_size/1024, mp_task_heap); 78 | 79 | #else 80 | // Allocate the uPy heap using malloc and get the largest available region 81 | size_t mp_task_heap_size = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); 82 | void *mp_task_heap = malloc(mp_task_heap_size); 83 | #endif 84 | 85 | soft_reset: 86 | // initialise the stack pointer for the main thread 87 | mp_stack_set_top((void *)sp); 88 | mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024); 89 | gc_init(mp_task_heap, mp_task_heap + mp_task_heap_size); 90 | mp_init(); 91 | mp_obj_list_init(mp_sys_path, 0); 92 | mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); 93 | mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); 94 | mp_obj_list_init(mp_sys_argv, 0); 95 | readline_init0(); 96 | 97 | // initialise peripherals 98 | machine_pins_init(); 99 | 100 | // run boot-up scripts 101 | pyexec_frozen_module("_boot.py"); 102 | pyexec_file_if_exists("boot.py"); 103 | if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { 104 | pyexec_file_if_exists("main.py"); 105 | } 106 | 107 | for (;;) { 108 | if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { 109 | vprintf_like_t vprintf_log = esp_log_set_vprintf(vprintf_null); 110 | if (pyexec_raw_repl() != 0) { 111 | break; 112 | } 113 | esp_log_set_vprintf(vprintf_log); 114 | } else { 115 | if (pyexec_friendly_repl() != 0) { 116 | break; 117 | } 118 | } 119 | } 120 | 121 | machine_timer_deinit_all(); 122 | 123 | #if MICROPY_PY_THREAD 124 | mp_thread_deinit(); 125 | #endif 126 | 127 | gc_sweep_all(); 128 | 129 | mp_hal_stdout_tx_str("MPY: soft reboot\r\n"); 130 | 131 | // deinitialise peripherals 132 | machine_pins_deinit(); 133 | // usocket_events_deinit(); -- no webrepl!! 134 | 135 | mp_deinit(); 136 | fflush(stdout); 137 | goto soft_reset; 138 | } 139 | 140 | void app_main(void) { 141 | nvs_flash_init(); 142 | xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_main_task_handle, MP_TASK_COREID); 143 | } 144 | 145 | void nlr_jump_fail(void *val) { 146 | printf("NLR jump failed, val=%p\n", val); 147 | esp_restart(); 148 | } 149 | 150 | // modussl_mbedtls uses this function but it's not enabled in ESP IDF 151 | void mbedtls_debug_set_threshold(int threshold) { 152 | (void)threshold; 153 | } 154 | -------------------------------------------------------------------------------- /esp32-cam-1-11-571/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 | #include "esp_spiram.h" 41 | 42 | #include "py/stackctrl.h" 43 | #include "py/nlr.h" 44 | #include "py/compile.h" 45 | #include "py/runtime.h" 46 | #include "py/repl.h" 47 | #include "py/gc.h" 48 | #include "py/mphal.h" 49 | #include "lib/mp-readline/readline.h" 50 | #include "lib/utils/pyexec.h" 51 | #include "uart.h" 52 | #include "modmachine.h" 53 | #include "modnetwork.h" 54 | #include "mpthreadport.h" 55 | 56 | // MicroPython runs as a task under FreeRTOS 57 | #define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) 58 | #define MP_TASK_STACK_SIZE (16 * 1024) 59 | #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) 60 | 61 | int vprintf_null(const char *format, va_list ap) { 62 | // do nothing: this is used as a log target during raw repl mode 63 | return 0; 64 | } 65 | 66 | void mp_task(void *pvParameter) { 67 | volatile uint32_t sp = (uint32_t)get_sp(); 68 | #if MICROPY_PY_THREAD 69 | mp_thread_init(pxTaskGetStackStart(NULL), MP_TASK_STACK_LEN); 70 | #endif 71 | uart_init(); 72 | 73 | #if CONFIG_SPIRAM_SUPPORT 74 | // allocate part of PSRAM for micropython, leave rest for native camera module 75 | size_t mp_task_heap_size = 2 * 1024 * 1024; 76 | void *mp_task_heap = malloc(mp_task_heap_size); 77 | ESP_LOGI("main", "Allocated %dK for micropython heap at %p", mp_task_heap_size/1024, mp_task_heap); 78 | 79 | #else 80 | // Allocate the uPy heap using malloc and get the largest available region 81 | size_t mp_task_heap_size = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); 82 | void *mp_task_heap = malloc(mp_task_heap_size); 83 | #endif 84 | 85 | soft_reset: 86 | // initialise the stack pointer for the main thread 87 | mp_stack_set_top((void *)sp); 88 | mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024); 89 | gc_init(mp_task_heap, mp_task_heap + mp_task_heap_size); 90 | mp_init(); 91 | mp_obj_list_init(mp_sys_path, 0); 92 | mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); 93 | mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); 94 | mp_obj_list_init(mp_sys_argv, 0); 95 | readline_init0(); 96 | 97 | // initialise peripherals 98 | machine_pins_init(); 99 | 100 | // run boot-up scripts 101 | pyexec_frozen_module("_boot.py"); 102 | pyexec_file_if_exists("boot.py"); 103 | if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { 104 | pyexec_file_if_exists("main.py"); 105 | } 106 | 107 | for (;;) { 108 | if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { 109 | vprintf_like_t vprintf_log = esp_log_set_vprintf(vprintf_null); 110 | if (pyexec_raw_repl() != 0) { 111 | break; 112 | } 113 | esp_log_set_vprintf(vprintf_log); 114 | } else { 115 | if (pyexec_friendly_repl() != 0) { 116 | break; 117 | } 118 | } 119 | } 120 | 121 | machine_timer_deinit_all(); 122 | 123 | #if MICROPY_PY_THREAD 124 | mp_thread_deinit(); 125 | #endif 126 | 127 | gc_sweep_all(); 128 | 129 | mp_hal_stdout_tx_str("MPY: soft reboot\r\n"); 130 | 131 | // deinitialise peripherals 132 | machine_pins_deinit(); 133 | // usocket_events_deinit(); -- no webrepl!! 134 | 135 | mp_deinit(); 136 | fflush(stdout); 137 | goto soft_reset; 138 | } 139 | 140 | void app_main(void) { 141 | nvs_flash_init(); 142 | xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_main_task_handle, MP_TASK_COREID); 143 | } 144 | 145 | void nlr_jump_fail(void *val) { 146 | printf("NLR jump failed, val=%p\n", val); 147 | esp_restart(); 148 | } 149 | 150 | // modussl_mbedtls uses this function but it's not enabled in ESP IDF 151 | void mbedtls_debug_set_threshold(int threshold) { 152 | (void)threshold; 153 | } 154 | -------------------------------------------------------------------------------- /webcam/async_tasks_webcam_ap.py: -------------------------------------------------------------------------------- 1 | 2 | import usocket as soc 3 | import uasyncio as sy 4 | import camera 5 | import time 6 | import esp 7 | from machine import Pin 8 | import gc 9 | from Wifi.Ap import Ap 10 | 11 | #esp.osdebug(False) 12 | esp.osdebug(True) 13 | 14 | def foo(p): 15 | print('FOO here', p[0]+p[1]) 16 | 17 | async def bar(p): 18 | print('BAR here', p[1]*p[2]) 19 | c = p[0] 20 | if c > 0: 21 | yield 22 | bar([c-1, 3, 2+c]) # call me again 23 | 24 | hdr = { 25 | # start page for streaming 26 | # URL: /apikey/webcam 27 | 'live': """HTTP/1.1 200 OK 28 | Content-Type: text/html; charset=utf-8 29 | 30 | 31 | 32 | Video Streaming Demonstration 33 | 34 | 35 |
36 |

Video Streaming Demonstration

37 | 38 |
39 | 40 | 41 | 42 | """, 43 | # live stream - 44 | # URL: /apikey/live 45 | 'stream': """HTTP/1.1 200 OK 46 | Content-Type: multipart/x-mixed-replace; boundary=frame 47 | Connection: keep-alive 48 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 49 | Expires: Thu, Jan 01 1970 00:00:00 GMT 50 | Pragma: no-cache 51 | 52 | """, 53 | # live stream - 54 | # URL: 55 | 'frame': """--frame 56 | Content-Type: image/jpeg 57 | 58 | """, 59 | # still picture - 60 | # URL: /apikey/snap 61 | 'snap': """HTTP/1.1 200 OK 62 | Content-Type: image/jpeg 63 | Content-Length: """, 64 | # no content error 65 | # URL: all the rest 66 | 'none': """HTTP/1.1 204 No Content 67 | Content-Type: text/plain; charset=utf-8 68 | 69 | Nothing here! 70 | 71 | """, 72 | # bad request error 73 | # URL: /favicon.ico 74 | 'favicon': """HTTP/1.1 404 75 | 76 | 77 | """, 78 | # bad request error 79 | # URL: all the rest 80 | 'err': """HTTP/1.1 400 Bad Request 81 | Content-Type: text/plain; charset=utf-8 82 | 83 | Hello? Can not compile 84 | 85 | """, 86 | # test 87 | # URL: all the rest 88 | 'test': """HTTP/1.1 200 OK 89 | Content-Type: text/plain; charset=utf-8 90 | 91 | Hello there! 92 | 93 | """ 94 | } 95 | 96 | def clean_up(cs): 97 | cs.close() # flash buffer and close socket 98 | del cs 99 | gc.collect() 100 | 101 | def frame_gen(): 102 | #buf = b' ' 103 | while True: 104 | buf = camera.capture() 105 | yield buf 106 | del buf 107 | gc.collect() 108 | 109 | async def send_frame(pp): 110 | cs, h = pp 111 | while True: 112 | ee = '' 113 | try: 114 | cs.send(b'%s' % h) 115 | #cs.send(camera.capture()) 116 | cs.send(next(pic)) 117 | cs.send(b'\r\n') # send and flush the send buffer 118 | except Exception as e: 119 | ee = str(e) 120 | if ee == '': 121 | await sy.sleep_ms(5) # try as fast as we can 122 | else: 123 | break 124 | 125 | clean_up(cs) 126 | return 127 | 128 | def servers(): 129 | socks = [] 130 | # port 80 server - streaming server 131 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 132 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 133 | a = ('0.0.0.0', 80) 134 | s.bind(a) 135 | s.listen(3) # at most 3 clients 136 | socks.append(s) 137 | 138 | # port 81 server - still picture server 139 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 140 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 141 | a = ('0.0.0.0', 81) 142 | s.bind(a) 143 | s.listen(3) 144 | socks.append(s) 145 | 146 | # port 82 server - cmd server 147 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 148 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 149 | a = ('0.0.0.0', 82) 150 | s.bind(a) 151 | s.listen(3) 152 | socks.append(s) 153 | 154 | return socks 155 | 156 | async def port1(cs, rq): 157 | rqp = rq[1].split('/') 158 | if rqp[1] == 'apikey': # Must have /apikey/ 159 | if rqp[2] == 'webcam': 160 | cs.send(b'%s' % hdr['live']) 161 | clean_up(cs) 162 | elif rqp[2] == 'live': # start streaming 163 | cs.send(b'%s' % hdr['stream']) 164 | # schedule frame sending 165 | await send_frame([cs, hdr['frame']]) 166 | else: # 167 | cs.send(b'%s' % hdr['none']) 168 | clean_up(cs) 169 | else: 170 | cs.send(b'%s' % hdr['err']) 171 | clean_up(cs) 172 | 173 | async def port2(cs, rq): 174 | rqp = rq[1].split('/') 175 | if rqp[1] == 'apikey': # Must have /apikey/ 176 | if rqp[2] == 'snap': 177 | try: 178 | #img=camera.capture() 179 | img=next(pic) 180 | cs.send(b'%s %d\r\n\r\n' % (hdr['snap'], len(img))) 181 | cs.send(img) 182 | cs.send(b'\r\n') 183 | except: 184 | pass 185 | elif rqp[2] == 'blitz': 186 | try: 187 | flash_light.on() 188 | #img=camera.capture() 189 | img=next(pic) 190 | flash_light.off() 191 | cs.send(b'%s %d\r\n\r\n' % (hdr['snap'], len(img))) 192 | cs.send(img) 193 | cs.send(b'\r\n') 194 | except: 195 | pass 196 | else: 197 | cs.send(b'%s' % hdr['none']) 198 | else: 199 | cs.send(b'%s' % hdr['err']) 200 | clean_up(cs) 201 | 202 | async def port3(cs, rq): 203 | rqp = rq[1].split('/') 204 | if rqp[1] == 'apikey': # Must have /apikey/ 205 | if rqp[2] == 'flash': # /apikey/flash/ 206 | if rqp[3] == 'on': 207 | flash_light.on() 208 | else: 209 | flash_light.off() 210 | cs.send(b'%s' % hdr['test']) 211 | else: 212 | cs.send(b'%s' % hdr['test']) 213 | else: 214 | loop.create_task(foo([7, 5])) 215 | cs.send(b'%s' % hdr['test']) 216 | 217 | clean_up(cs) 218 | 219 | async def srv(p): 220 | sa = socks[p] # scheduled server 221 | while True: 222 | ok = True 223 | ee = '' 224 | yield 225 | try: 226 | sa.settimeout(0.05) # in sec NB! default browser timeout (5-15 min) 227 | cs, ca = sa.accept() 228 | cs.settimeout(0.5) # in sec 229 | except Exception as e: 230 | ee = str(e) 231 | if ee != '': 232 | # print('Socket %d accept - %s' % (p, ee.split()[-1])) 233 | #ee = '' 234 | pass 235 | ok = False 236 | yield 237 | if ok: # No soc.accept timeout 238 | ee = '' 239 | try: 240 | # client accepted 241 | r = cs.recv(1024) 242 | # REQ: b'' # may be due to very short timeout 243 | except Exception as e: 244 | ee = str(e) 245 | if ee != '': 246 | print(ee) 247 | ok = False 248 | else: 249 | ms = r.decode('utf-8') 250 | if ms.find('favicon.ico') < 0: 251 | rq = ms.split(' ') 252 | print(rq[0], rq[1], ca) 253 | else: 254 | cs.send(b'%s' % hdr['favicon']) # handle favicon request early 255 | clean_up(cs) 256 | ok = False 257 | yield 258 | if ok: # No soc.recv timeout or favicon request 259 | await ports[p](cs, rq) 260 | 261 | wc = 0 262 | while True: 263 | cr = camera.init() 264 | print("Camera ready?: ", cr) 265 | if cr: 266 | break 267 | time.sleep(2) 268 | wc += 1 269 | if wc >= 5: 270 | break 271 | 272 | if not cr: 273 | print("Camera not ready. Can't continue!") 274 | else: 275 | ap = Ap() 276 | print(ap.status()) 277 | # ready to serve 278 | pic = frame_gen() 279 | flash_light = Pin(04,Pin.OUT) 280 | socks = servers() 281 | ports = [port1, port2, port3] # 80, 81, 82 282 | loop = sy.get_event_loop() 283 | # schedule each srv twice 284 | for i in range(len(socks)): 285 | if i == 0: 286 | loop.create_task(srv(i)) # schedule 2 servers for port 80 287 | loop.create_task(srv(i)) # streaming hold socket until client 288 | # terminate, we service at most 2 clients 289 | else: 290 | loop.create_task(srv(i)) # only one for 81 and 82 291 | 292 | # 293 | # schedule other processes here 294 | # 295 | 296 | # go for it! 297 | print("Up Up and Away!") 298 | loop.run_forever() 299 | 300 | -------------------------------------------------------------------------------- /webcam/async_tasks_webcam_sta.py: -------------------------------------------------------------------------------- 1 | 2 | import usocket as soc 3 | import uasyncio as sy 4 | import camera 5 | import time 6 | import esp 7 | from machine import Pin 8 | import gc 9 | from Wifi.Sta import Sta 10 | 11 | #esp.osdebug(False) 12 | esp.osdebug(True) 13 | 14 | def foo(p): 15 | print('FOO here', p[0]+p[1]) 16 | 17 | async def bar(p): 18 | print('BAR here', p[1]*p[2]) 19 | c = p[0] 20 | if c > 0: 21 | yield 22 | bar([c-1, 3, 2+c]) # call me again 23 | 24 | hdr = { 25 | # start page for streaming 26 | # URL: /apikey/webcam 27 | 'live': """HTTP/1.1 200 OK 28 | Content-Type: text/html; charset=utf-8 29 | 30 | 31 | 32 | Video Streaming Demonstration 33 | 34 | 35 |
36 |

Video Streaming Demonstration

37 | 38 |
39 | 40 | 41 | 42 | """, 43 | # live stream - 44 | # URL: /apikey/live 45 | 'stream': """HTTP/1.1 200 OK 46 | Content-Type: multipart/x-mixed-replace; boundary=frame 47 | Connection: keep-alive 48 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 49 | Expires: Thu, Jan 01 1970 00:00:00 GMT 50 | Pragma: no-cache 51 | 52 | """, 53 | # live stream - 54 | # URL: 55 | 'frame': """--frame 56 | Content-Type: image/jpeg 57 | 58 | """, 59 | # still picture - 60 | # URL: /apikey/snap 61 | 'snap': """HTTP/1.1 200 OK 62 | Content-Type: image/jpeg 63 | Content-Length: """, 64 | # no content error 65 | # URL: all the rest 66 | 'none': """HTTP/1.1 204 No Content 67 | Content-Type: text/plain; charset=utf-8 68 | 69 | Nothing here! 70 | 71 | """, 72 | # bad request error 73 | # URL: /favicon.ico 74 | 'favicon': """HTTP/1.1 404 75 | 76 | 77 | """, 78 | # bad request error 79 | # URL: all the rest 80 | 'err': """HTTP/1.1 400 Bad Request 81 | Content-Type: text/plain; charset=utf-8 82 | 83 | Hello? Can not compile 84 | 85 | """, 86 | # test 87 | # URL: all the rest 88 | 'test': """HTTP/1.1 200 OK 89 | Content-Type: text/plain; charset=utf-8 90 | 91 | Hello there! 92 | 93 | """ 94 | } 95 | 96 | def clean_up(cs): 97 | cs.close() # flash buffer and close socket 98 | del cs 99 | gc.collect() 100 | 101 | def frame_gen(): 102 | #buf = b' ' 103 | while True: 104 | buf = camera.capture() 105 | yield buf 106 | del buf 107 | gc.collect() 108 | 109 | async def send_frame(pp): 110 | cs, h = pp 111 | while True: 112 | ee = '' 113 | try: 114 | cs.send(b'%s' % h) 115 | #cs.send(camera.capture()) 116 | cs.send(next(pic)) 117 | cs.send(b'\r\n') # send and flush the send buffer 118 | except Exception as e: 119 | ee = str(e) 120 | if ee == '': 121 | await sy.sleep_ms(5) # try as fast as we can 122 | else: 123 | break 124 | 125 | clean_up(cs) 126 | return 127 | 128 | def servers(): 129 | socks = [] 130 | # port 80 server - streaming server 131 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 132 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 133 | a = ('0.0.0.0', 80) 134 | s.bind(a) 135 | s.listen(3) # at most 3 clients 136 | socks.append(s) 137 | 138 | # port 81 server - still picture server 139 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 140 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 141 | a = ('0.0.0.0', 81) 142 | s.bind(a) 143 | s.listen(3) 144 | socks.append(s) 145 | 146 | # port 82 server - cmd server 147 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 148 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 149 | a = ('0.0.0.0', 82) 150 | s.bind(a) 151 | s.listen(3) 152 | socks.append(s) 153 | 154 | return socks 155 | 156 | async def port1(cs, rq): 157 | rqp = rq[1].split('/') 158 | if rqp[1] == 'apikey': # Must have /apikey/ 159 | if rqp[2] == 'webcam': 160 | cs.send(b'%s' % hdr['live']) 161 | clean_up(cs) 162 | elif rqp[2] == 'live': # start streaming 163 | cs.send(b'%s' % hdr['stream']) 164 | # schedule frame sending 165 | await send_frame([cs, hdr['frame']]) 166 | else: # 167 | cs.send(b'%s' % hdr['none']) 168 | clean_up(cs) 169 | else: 170 | cs.send(b'%s' % hdr['err']) 171 | clean_up(cs) 172 | 173 | async def port2(cs, rq): 174 | rqp = rq[1].split('/') 175 | if rqp[1] == 'apikey': # Must have /apikey/ 176 | if rqp[2] == 'snap': 177 | try: 178 | #img=camera.capture() 179 | img=next(pic) 180 | cs.send(b'%s %d\r\n\r\n' % (hdr['snap'], len(img))) 181 | cs.send(img) 182 | cs.send(b'\r\n') 183 | except: 184 | pass 185 | elif rqp[2] == 'blitz': 186 | try: 187 | flash_light.on() 188 | #img=camera.capture() 189 | img=next(pic) 190 | flash_light.off() 191 | cs.send(b'%s %d\r\n\r\n' % (hdr['snap'], len(img))) 192 | cs.send(img) 193 | cs.send(b'\r\n') 194 | except: 195 | pass 196 | else: 197 | cs.send(b'%s' % hdr['none']) 198 | else: 199 | cs.send(b'%s' % hdr['err']) 200 | clean_up(cs) 201 | 202 | async def port3(cs, rq): 203 | rqp = rq[1].split('/') 204 | if rqp[1] == 'apikey': # Must have /apikey/ 205 | if rqp[2] == 'flash': # /apikey/flash/ 206 | if rqp[3] == 'on': 207 | flash_light.on() 208 | else: 209 | flash_light.off() 210 | cs.send(b'%s' % hdr['test']) 211 | else: 212 | cs.send(b'%s' % hdr['test']) 213 | else: 214 | loop.create_task(foo([7, 5])) 215 | cs.send(b'%s' % hdr['test']) 216 | 217 | clean_up(cs) 218 | 219 | async def srv(p): 220 | sa = socks[p] # scheduled server 221 | while True: 222 | ok = True 223 | ee = '' 224 | yield 225 | try: 226 | sa.settimeout(0.05) # in sec NB! default browser timeout (5-15 min) 227 | cs, ca = sa.accept() 228 | cs.settimeout(0.5) # in sec 229 | except Exception as e: 230 | ee = str(e) 231 | if ee != '': 232 | # print('Socket %d accept - %s' % (p, ee.split()[-1])) 233 | #ee = '' 234 | pass 235 | ok = False 236 | yield 237 | if ok: # No soc.accept timeout 238 | ee = '' 239 | try: 240 | # client accepted 241 | r = cs.recv(1024) 242 | # REQ: b'' # may be due to very short timeout 243 | except Exception as e: 244 | ee = str(e) 245 | if ee != '': 246 | print(ee) 247 | ok = False 248 | else: 249 | ms = r.decode('utf-8') 250 | if ms.find('favicon.ico') < 0: 251 | rq = ms.split(' ') 252 | print(rq[0], rq[1], ca) 253 | else: 254 | cs.send(b'%s' % hdr['favicon']) # handle favicon request early 255 | clean_up(cs) 256 | ok = False 257 | yield 258 | if ok: # No soc.recv timeout or favicon request 259 | await ports[p](cs, rq) 260 | 261 | wc = 0 262 | while True: 263 | cr = camera.init() 264 | print("Camera ready?: ", cr) 265 | if cr: 266 | break 267 | time.sleep(2) 268 | wc += 1 269 | if wc >= 5: 270 | break 271 | 272 | if not cr: 273 | print("Camera not ready. Can't continue!") 274 | else: 275 | w = Sta() 276 | w.connect() 277 | w.wait() 278 | wc = 0 279 | while not w.wlan.isconnected(): 280 | print("WIFI not ready. Wait...") 281 | time.sleep(2) 282 | wc += 1 283 | if wc >= 5: 284 | break 285 | if wc >= 5: 286 | print("WIFI not ready. Can't continue!") 287 | else: 288 | pic = frame_gen() 289 | flash_light = Pin(04,Pin.OUT) 290 | socks = servers() 291 | ports = [port1, port2, port3] # 80, 81, 82 292 | loop = sy.get_event_loop() 293 | # schedule each srv twice 294 | for i in range(len(socks)): 295 | if i == 0: 296 | loop.create_task(srv(i)) # schedule 2 servers for port 80 297 | loop.create_task(srv(i)) # streaming hold socket until client 298 | # terminate, we service at most 2 clients 299 | else: 300 | loop.create_task(srv(i)) # only one for 81 and 82 301 | 302 | # 303 | # schedule other processes here 304 | # 305 | 306 | # go for it! 307 | print("Up Up and Away!") 308 | loop.run_forever() 309 | 310 | -------------------------------------------------------------------------------- /webcam/uasyncio/__init__.py: -------------------------------------------------------------------------------- 1 | import uerrno 2 | import uselect as select 3 | import usocket as _socket 4 | from uasyncio.core import * 5 | 6 | 7 | DEBUG = 0 8 | log = None 9 | 10 | def set_debug(val): 11 | global DEBUG, log 12 | DEBUG = val 13 | if val: 14 | import logging 15 | log = logging.getLogger("uasyncio") 16 | 17 | 18 | class PollEventLoop(EventLoop): 19 | 20 | def __init__(self, runq_len=16, waitq_len=16): 21 | EventLoop.__init__(self, runq_len, waitq_len) 22 | self.poller = select.poll() 23 | self.objmap = {} 24 | 25 | def add_reader(self, sock, cb, *args): 26 | if DEBUG and __debug__: 27 | log.debug("add_reader%s", (sock, cb, args)) 28 | if args: 29 | self.poller.register(sock, select.POLLIN) 30 | self.objmap[id(sock)] = (cb, args) 31 | else: 32 | self.poller.register(sock, select.POLLIN) 33 | self.objmap[id(sock)] = cb 34 | 35 | def remove_reader(self, sock): 36 | if DEBUG and __debug__: 37 | log.debug("remove_reader(%s)", sock) 38 | self.poller.unregister(sock) 39 | del self.objmap[id(sock)] 40 | 41 | def add_writer(self, sock, cb, *args): 42 | if DEBUG and __debug__: 43 | log.debug("add_writer%s", (sock, cb, args)) 44 | if args: 45 | self.poller.register(sock, select.POLLOUT) 46 | self.objmap[id(sock)] = (cb, args) 47 | else: 48 | self.poller.register(sock, select.POLLOUT) 49 | self.objmap[id(sock)] = cb 50 | 51 | def remove_writer(self, sock): 52 | if DEBUG and __debug__: 53 | log.debug("remove_writer(%s)", sock) 54 | try: 55 | self.poller.unregister(sock) 56 | self.objmap.pop(id(sock), None) 57 | except OSError as e: 58 | # StreamWriter.awrite() first tries to write to a socket, 59 | # and if that succeeds, yield IOWrite may never be called 60 | # for that socket, and it will never be added to poller. So, 61 | # ignore such error. 62 | if e.args[0] != uerrno.ENOENT: 63 | raise 64 | 65 | def wait(self, delay): 66 | #print("delay:", delay) 67 | if DEBUG and __debug__: 68 | log.debug("poll.wait(%d)", delay) 69 | # We need one-shot behavior (second arg of 1 to .poll()) 70 | res = self.poller.ipoll(delay, 1) 71 | #print("poll result: %s" % res) 72 | #log.debug("poll result: %s", res) 73 | # Remove "if res" workaround after 74 | # https://github.com/micropython/micropython/issues/2716 fixed. 75 | if res: 76 | for sock, ev in res: 77 | cb = self.objmap[id(sock)] 78 | if ev & (select.POLLHUP | select.POLLERR): 79 | # These events are returned even if not requested, and 80 | # are sticky, i.e. will be returned again and again. 81 | # If the caller doesn't do proper error handling and 82 | # unregister this sock, we'll busy-loop on it, so we 83 | # as well can unregister it now "just in case". 84 | self.remove_reader(sock) 85 | if DEBUG and __debug__: 86 | log.debug("Calling IO callback: %r", cb) 87 | if isinstance(cb, tuple): 88 | cb[0](*cb[1]) 89 | else: 90 | cb.pend_throw(None) 91 | self.call_soon(cb) 92 | 93 | 94 | class StreamReader: 95 | 96 | def __init__(self, polls, ios=None): 97 | if ios is None: 98 | ios = polls 99 | self.polls = polls 100 | self.ios = ios 101 | 102 | def read(self, n=-1): 103 | while True: 104 | yield IORead(self.polls) 105 | res = self.ios.read(n) 106 | if res is not None: 107 | break 108 | # This should not happen for real sockets, but can easily 109 | # happen for stream wrappers (ssl, websockets, etc.) 110 | #log.warn("Empty read") 111 | if not res: 112 | yield IOReadDone(self.polls) 113 | return res 114 | 115 | def readexactly(self, n): 116 | buf = b"" 117 | while n: 118 | yield IORead(self.polls) 119 | res = self.ios.read(n) 120 | assert res is not None 121 | if not res: 122 | yield IOReadDone(self.polls) 123 | break 124 | buf += res 125 | n -= len(res) 126 | return buf 127 | 128 | def readline(self): 129 | if DEBUG and __debug__: 130 | log.debug("StreamReader.readline()") 131 | buf = b"" 132 | while True: 133 | yield IORead(self.polls) 134 | res = self.ios.readline() 135 | assert res is not None 136 | if not res: 137 | yield IOReadDone(self.polls) 138 | break 139 | buf += res 140 | if buf[-1] == 0x0a: 141 | break 142 | if DEBUG and __debug__: 143 | log.debug("StreamReader.readline(): %s", buf) 144 | return buf 145 | 146 | def aclose(self): 147 | yield IOReadDone(self.polls) 148 | self.ios.close() 149 | 150 | def __repr__(self): 151 | return "" % (self.polls, self.ios) 152 | 153 | 154 | class StreamWriter: 155 | 156 | def __init__(self, s, extra): 157 | self.s = s 158 | self.extra = extra 159 | 160 | def awrite(self, buf, off=0, sz=-1): 161 | # This method is called awrite (async write) to not proliferate 162 | # incompatibility with original asyncio. Unlike original asyncio 163 | # whose .write() method is both not a coroutine and guaranteed 164 | # to return immediately (which means it has to buffer all the 165 | # data), this method is a coroutine. 166 | if sz == -1: 167 | sz = len(buf) - off 168 | if DEBUG and __debug__: 169 | log.debug("StreamWriter.awrite(): spooling %d bytes", sz) 170 | while True: 171 | res = self.s.write(buf, off, sz) 172 | # If we spooled everything, return immediately 173 | if res == sz: 174 | if DEBUG and __debug__: 175 | log.debug("StreamWriter.awrite(): completed spooling %d bytes", res) 176 | return 177 | if res is None: 178 | res = 0 179 | if DEBUG and __debug__: 180 | log.debug("StreamWriter.awrite(): spooled partial %d bytes", res) 181 | assert res < sz 182 | off += res 183 | sz -= res 184 | yield IOWrite(self.s) 185 | #assert s2.fileno() == self.s.fileno() 186 | if DEBUG and __debug__: 187 | log.debug("StreamWriter.awrite(): can write more") 188 | 189 | # Write piecewise content from iterable (usually, a generator) 190 | def awriteiter(self, iterable): 191 | for buf in iterable: 192 | yield from self.awrite(buf) 193 | 194 | def aclose(self): 195 | yield IOWriteDone(self.s) 196 | self.s.close() 197 | 198 | def get_extra_info(self, name, default=None): 199 | return self.extra.get(name, default) 200 | 201 | def __repr__(self): 202 | return "" % self.s 203 | 204 | 205 | def open_connection(host, port, ssl=False): 206 | if DEBUG and __debug__: 207 | log.debug("open_connection(%s, %s)", host, port) 208 | ai = _socket.getaddrinfo(host, port, 0, _socket.SOCK_STREAM) 209 | ai = ai[0] 210 | s = _socket.socket(ai[0], ai[1], ai[2]) 211 | s.setblocking(False) 212 | try: 213 | s.connect(ai[-1]) 214 | except OSError as e: 215 | if e.args[0] != uerrno.EINPROGRESS: 216 | raise 217 | if DEBUG and __debug__: 218 | log.debug("open_connection: After connect") 219 | yield IOWrite(s) 220 | # if __debug__: 221 | # assert s2.fileno() == s.fileno() 222 | if DEBUG and __debug__: 223 | log.debug("open_connection: After iowait: %s", s) 224 | if ssl: 225 | print("Warning: uasyncio SSL support is alpha") 226 | import ussl 227 | s.setblocking(True) 228 | s2 = ussl.wrap_socket(s) 229 | s.setblocking(False) 230 | return StreamReader(s, s2), StreamWriter(s2, {}) 231 | return StreamReader(s), StreamWriter(s, {}) 232 | 233 | 234 | def start_server(client_coro, host, port, backlog=10): 235 | if DEBUG and __debug__: 236 | log.debug("start_server(%s, %s)", host, port) 237 | ai = _socket.getaddrinfo(host, port, 0, _socket.SOCK_STREAM) 238 | ai = ai[0] 239 | s = _socket.socket(ai[0], ai[1], ai[2]) 240 | s.setblocking(False) 241 | 242 | s.setsockopt(_socket.SOL_SOCKET, _socket.SO_REUSEADDR, 1) 243 | s.bind(ai[-1]) 244 | s.listen(backlog) 245 | while True: 246 | if DEBUG and __debug__: 247 | log.debug("start_server: Before accept") 248 | yield IORead(s) 249 | if DEBUG and __debug__: 250 | log.debug("start_server: After iowait") 251 | s2, client_addr = s.accept() 252 | s2.setblocking(False) 253 | if DEBUG and __debug__: 254 | log.debug("start_server: After accept: %s", s2) 255 | extra = {"peername": client_addr} 256 | yield client_coro(StreamReader(s2), StreamWriter(s2, extra)) 257 | 258 | 259 | import uasyncio.core 260 | uasyncio.core._event_loop_class = PollEventLoop 261 | -------------------------------------------------------------------------------- /webcam/webcam.py: -------------------------------------------------------------------------------- 1 | 2 | import usocket as soc 3 | import uasyncio as sy 4 | import camera 5 | import time 6 | import esp 7 | from machine import Pin 8 | import gc 9 | from Wifi.Sta import Sta 10 | 11 | #esp.osdebug(False) 12 | esp.osdebug(True) 13 | 14 | def foo(p): 15 | print('FOO here', p[0]+p[1]) 16 | 17 | hdr = { 18 | # start page for streaming 19 | # URL: /apikey/webcam 20 | 'live': """HTTP/1.1 200 OK 21 | Content-Type: text/html; charset=utf-8 22 | 23 | 24 | 25 | Looking out of my window 26 | 27 | 28 |
29 |

Looking out of my window...

30 | 31 |
32 | 33 | 34 | 35 | """, 36 | # live stream - 37 | # URL: /apikey/live 38 | 'stream': """HTTP/1.1 200 OK 39 | Content-Type: multipart/x-mixed-replace; boundary=frame 40 | Connection: keep-alive 41 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 42 | Expires: Thu, Jan 01 1970 00:00:00 GMT 43 | Pragma: no-cache 44 | 45 | """, 46 | # live stream - 47 | # URL: 48 | 'frame': """--frame 49 | Content-Type: image/jpeg 50 | 51 | """, 52 | # still picture - 53 | # URL: /apikey/snap 54 | 'snap': """HTTP/1.1 200 OK 55 | Content-Type: image/jpeg 56 | Content-Length: """, 57 | # no content error 58 | # URL: all the rest 59 | 'none': """HTTP/1.1 204 No Content 60 | Content-Type: text/plain; charset=utf-8 61 | 62 | Nothing here! 63 | 64 | """, 65 | # bad request error 66 | # URL: /favicon.ico 67 | 'favicon': """HTTP/1.1 404 68 | 69 | 70 | """, 71 | # bad request error 72 | # URL: all the rest 73 | 'err': """HTTP/1.1 400 Bad Request 74 | Content-Type: text/plain; charset=utf-8 75 | 76 | Hello? Can not compile 77 | 78 | """, 79 | # OK 80 | # URL: all the rest 81 | 'OK': """HTTP/1.1 200 OK 82 | Content-Type: text/plain; charset=utf-8 83 | 84 | OK! 85 | 86 | """ 87 | } 88 | 89 | def clean_up(cs): 90 | cs.close() # flash buffer and close socket 91 | del cs 92 | gc.collect() 93 | 94 | def frame_gen(): 95 | #buf = b' ' 96 | while True: 97 | buf = camera.capture() 98 | yield buf 99 | del buf 100 | gc.collect() 101 | 102 | async def send_frame(pp): 103 | cs, h = pp 104 | while True: 105 | ee = '' 106 | try: 107 | cs.send(b'%s' % h) 108 | #cs.send(camera.capture()) 109 | cs.send(next(pic)) 110 | cs.send(b'\r\n') # send and flush the send buffer 111 | except Exception as e: 112 | ee = str(e) 113 | if ee == '': 114 | await sy.sleep_ms(5) # try as fast as we can 115 | else: 116 | break 117 | 118 | clean_up(cs) 119 | return 120 | 121 | def servers(): 122 | socks = [] 123 | # port 80 server - streaming server 124 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 125 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 126 | a = ('0.0.0.0', 80) 127 | s.bind(a) 128 | s.listen(3) # at most 3 clients 129 | socks.append(s) 130 | 131 | # port 81 server - still picture server 132 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 133 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 134 | a = ('0.0.0.0', 81) 135 | s.bind(a) 136 | s.listen(3) 137 | socks.append(s) 138 | 139 | # port 82 server - cmd server 140 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 141 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 142 | a = ('0.0.0.0', 82) 143 | s.bind(a) 144 | s.listen(3) 145 | socks.append(s) 146 | 147 | return socks 148 | 149 | async def port1(cs, rq): 150 | rqp = rq[1].split('/') 151 | if rqp[1] == 'apikey': # Must have /apikey/ 152 | if rqp[2] == 'webcam': 153 | cs.send(b'%s' % hdr['live']) 154 | clean_up(cs) 155 | elif rqp[2] == 'live': # start streaming 156 | cs.send(b'%s' % hdr['stream']) 157 | # schedule frame sending 158 | await send_frame([cs, hdr['frame']]) 159 | else: # 160 | cs.send(b'%s' % hdr['none']) 161 | clean_up(cs) 162 | else: 163 | cs.send(b'%s' % hdr['err']) 164 | clean_up(cs) 165 | 166 | async def port2(cs, rq): 167 | rqp = rq[1].split('/') 168 | if rqp[1] == 'apikey': # Must have /apikey/ 169 | if rqp[2] == 'snap': 170 | try: 171 | #img=camera.capture() 172 | img=next(pic) 173 | cs.send(b'%s %d\r\n\r\n' % (hdr['snap'], len(img))) 174 | cs.send(img) 175 | cs.send(b'\r\n') 176 | except: 177 | pass 178 | elif rqp[2] == 'blitz': 179 | try: 180 | flash_light.on() 181 | #img=camera.capture() 182 | img=next(pic) 183 | flash_light.off() 184 | cs.send(b'%s %d\r\n\r\n' % (hdr['snap'], len(img))) 185 | cs.send(img) 186 | cs.send(b'\r\n') 187 | except: 188 | pass 189 | else: 190 | cs.send(b'%s' % hdr['none']) 191 | else: 192 | cs.send(b'%s' % hdr['err']) 193 | clean_up(cs) 194 | 195 | async def port3(cs, rq): 196 | rqp = rq[1].split('/') 197 | if rqp[1] == 'apikey': # Must have /apikey/ 198 | if rqp[2] == 'flash': # /apikey/flash/ 199 | if rqp[3] == 'on': 200 | flash_light.on() 201 | else: 202 | flash_light.off() 203 | cs.send(b'%s' % hdr['OK']) 204 | elif rqp[2] == 'pix': 205 | w = int(rqp[3]) 206 | if w>0 and w<13: 207 | camera.framesize(w) 208 | cs.send(b'%s' % hdr['OK']) 209 | elif rqp[2] == 'qua': 210 | w = int(rqp[3]) 211 | if w>9 and w<64: 212 | camera.quality(w) 213 | cs.send(b'%s' % hdr['OK']) 214 | elif rqp[2] == 'con': 215 | w = int(rqp[3]) 216 | if w>-3 and w<3: 217 | camera.contrast(w) 218 | cs.send(b'%s' % hdr['OK']) 219 | elif rqp[2] == 'sat': 220 | w = int(rqp[3]) 221 | if w>-3 and w<3: 222 | camera.saturation(w) 223 | cs.send(b'%s' % hdr['OK']) 224 | elif rqp[2] == 'bri': 225 | w = int(rqp[3]) 226 | if w>-3 and w<3: 227 | camera.brightness(w) 228 | cs.send(b'%s' % hdr['OK']) 229 | elif rqp[2] == 'spe': 230 | w = int(rqp[3]) 231 | if w>=0 and w<7: 232 | camera.speffect(w) 233 | cs.send(b'%s' % hdr['OK']) 234 | elif rqp[2] == 'wbl': 235 | w = int(rqp[3]) 236 | if w>=0 and w<5: 237 | camera.whitebalance(w) 238 | cs.send(b'%s' % hdr['OK']) 239 | else: 240 | cs.send(b'%s' % hdr['OK']) 241 | else: 242 | loop.create_task(foo([7, 5])) 243 | cs.send(b'%s' % hdr['OK']) 244 | 245 | clean_up(cs) 246 | 247 | async def srv(p): 248 | sa = socks[p] # scheduled server 249 | while True: 250 | ok = True 251 | ee = '' 252 | yield 253 | try: 254 | sa.settimeout(0.05) # in sec NB! default browser timeout (5-15 min) 255 | cs, ca = sa.accept() 256 | cs.settimeout(0.5) # in sec 257 | except Exception as e: 258 | ee = str(e) 259 | if ee != '': 260 | # print('Socket %d accept - %s' % (p, ee.split()[-1])) 261 | #ee = '' 262 | pass 263 | ok = False 264 | yield 265 | if ok: # No soc.accept timeout 266 | ee = '' 267 | try: 268 | # client accepted 269 | r = cs.recv(1024) 270 | # REQ: b'' # may be due to very short timeout 271 | except Exception as e: 272 | ee = str(e) 273 | if ee != '': 274 | print(ee) 275 | ok = False 276 | else: 277 | ms = r.decode('utf-8') 278 | if ms.find('favicon.ico') < 0: 279 | rq = ms.split(' ') 280 | try: 281 | print(rq[0], rq[1], ca) 282 | except: 283 | ok = False 284 | else: 285 | cs.send(b'%s' % hdr['favicon']) # handle favicon request early 286 | clean_up(cs) 287 | ok = False 288 | yield 289 | if ok: # No soc.recv timeout or favicon request 290 | await ports[p](cs, rq) 291 | 292 | wc = 0 293 | while True: 294 | cr = camera.init() 295 | print("Camera ready?: ", cr) 296 | if cr: 297 | break 298 | time.sleep(2) 299 | wc += 1 300 | if wc >= 5: 301 | break 302 | 303 | if not cr: 304 | print("Camera not ready. Can't continue!") 305 | else: 306 | # reconfigure camera 307 | # camera.speffect(2) # black and white 308 | # camera.quality(10) # increase quality from 12 (default) to 10 309 | # setup networking 310 | w = Sta() 311 | w.connect() 312 | w.wait() 313 | wc = 0 314 | while not w.wlan.isconnected(): 315 | print("WIFI not ready. Wait...") 316 | time.sleep(2) 317 | wc += 1 318 | if wc >= 5: 319 | break 320 | if wc >= 5: 321 | print("WIFI not ready. Can't continue!") 322 | else: 323 | pic = frame_gen() 324 | flash_light = Pin(04,Pin.OUT) 325 | socks = servers() 326 | ports = [port1, port2, port3] # 80, 81, 82 327 | loop = sy.get_event_loop() 328 | # schedule each srv twice 329 | for i in range(len(socks)): 330 | if i == 0: 331 | loop.create_task(srv(i)) # schedule 2 servers for port 80 332 | loop.create_task(srv(i)) # streaming hold socket until client 333 | # terminate, we service at most 2 clients 334 | else: 335 | loop.create_task(srv(i)) # only one for 81 and 82 336 | 337 | # 338 | # schedule other processes here 339 | # 340 | 341 | # go for it! 342 | print("Up Up and Away!") 343 | loop.run_forever() 344 | 345 | -------------------------------------------------------------------------------- /esp32-cam-1-11-498/modcamera.c: -------------------------------------------------------------------------------- 1 | // Code adapted from https://github.com/espressif/esp32-camera 2 | 3 | #include "esp_camera.h" 4 | #include "esp_log.h" 5 | 6 | #include "py/nlr.h" 7 | #include "py/obj.h" 8 | #include "py/runtime.h" 9 | #include "py/binary.h" 10 | 11 | #define TAG "camera" 12 | 13 | //WROVER-KIT PIN Map 14 | #define CAM_PIN_PWDN 32 //power down is not used 15 | #define CAM_PIN_RESET -1 //software reset will be performed 16 | #define CAM_PIN_XCLK 0 17 | #define CAM_PIN_SIOD 26 // SDA 18 | #define CAM_PIN_SIOC 27 // SCL 19 | 20 | #define CAM_PIN_D7 35 21 | #define CAM_PIN_D6 34 22 | #define CAM_PIN_D5 39 23 | #define CAM_PIN_D4 36 24 | #define CAM_PIN_D3 21 25 | #define CAM_PIN_D2 19 26 | #define CAM_PIN_D1 18 27 | #define CAM_PIN_D0 5 28 | #define CAM_PIN_VSYNC 25 29 | #define CAM_PIN_HREF 23 30 | #define CAM_PIN_PCLK 22 31 | 32 | static camera_config_t camera_config = { 33 | .pin_pwdn = CAM_PIN_PWDN, 34 | .pin_reset = CAM_PIN_RESET, 35 | .pin_xclk = CAM_PIN_XCLK, 36 | .pin_sscb_sda = CAM_PIN_SIOD, 37 | .pin_sscb_scl = CAM_PIN_SIOC, 38 | 39 | .pin_d7 = CAM_PIN_D7, 40 | .pin_d6 = CAM_PIN_D6, 41 | .pin_d5 = CAM_PIN_D5, 42 | .pin_d4 = CAM_PIN_D4, 43 | .pin_d3 = CAM_PIN_D3, 44 | .pin_d2 = CAM_PIN_D2, 45 | .pin_d1 = CAM_PIN_D1, 46 | .pin_d0 = CAM_PIN_D0, 47 | .pin_vsync = CAM_PIN_VSYNC, 48 | .pin_href = CAM_PIN_HREF, 49 | .pin_pclk = CAM_PIN_PCLK, 50 | 51 | //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) 52 | .xclk_freq_hz = 20000000, 53 | .ledc_timer = LEDC_TIMER_0, 54 | .ledc_channel = LEDC_CHANNEL_0, 55 | 56 | .pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG 57 | // .frame_size = FRAMESIZE_UXGA,//QQVGA-UXGA Do not use sizes above QVGA when not JPEG 58 | // .frame_size = FRAMESIZE_SXGA,//QQVGA-UXGA Do not use sizes above QVGA when not JPEG 59 | .frame_size = FRAMESIZE_XGA,//QQVGA-UXGA Do not use sizes above QVGA when not JPEG 60 | // .frame_size = FRAMESIZE_SVGA,//QQVGA-UXGA Do not use sizes above QVGA when not JPEG 61 | // .frame_size = FRAMESIZE_VGA,//QQVGA-UXGA Do not use sizes above QVGA when not JPEG 62 | // .frame_size = FRAMESIZE_CIF,//QQVGA-UXGA Do not use sizes above QVGA when not JPEG 63 | // .frame_size = FRAMESIZE_QVGA,//QQVGA-UXGA Do not use sizes above QVGA when not JPEG 64 | 65 | .jpeg_quality = 12, //10-63 lower number means higher quality 66 | .fb_count = 1 //if more than one, i2s runs in continuous mode. Use only with JPEG 67 | }; 68 | 69 | #include "esp_system.h" 70 | #include "esp_spi_flash.h" 71 | 72 | 73 | STATIC mp_obj_t camera_init(){ 74 | esp_err_t err = esp_camera_init(&camera_config); 75 | if (err != ESP_OK) { 76 | ESP_LOGE(TAG, "Camera Init Failed"); 77 | return mp_const_false; 78 | } 79 | 80 | return mp_const_true; 81 | } 82 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_init_obj, camera_init); 83 | 84 | 85 | STATIC mp_obj_t camera_deinit(){ 86 | esp_err_t err = esp_camera_deinit(); 87 | if (err != ESP_OK) { 88 | ESP_LOGE(TAG, "Camera deinit Failed"); 89 | return mp_const_false; 90 | } 91 | 92 | return mp_const_true; 93 | } 94 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_deinit_obj, camera_deinit); 95 | 96 | 97 | STATIC mp_obj_t camera_capture(){ 98 | //acquire a frame 99 | camera_fb_t * fb = esp_camera_fb_get(); 100 | if (!fb) { 101 | ESP_LOGE(TAG, "Camera Capture Failed"); 102 | return mp_const_false; 103 | } 104 | 105 | mp_obj_t image = mp_obj_new_bytes(fb->buf, fb->len); 106 | 107 | //return the frame buffer back to the driver for reuse 108 | esp_camera_fb_return(fb); 109 | return image; 110 | } 111 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_capture_obj, camera_capture); 112 | 113 | STATIC mp_obj_t camera_flip(mp_obj_t direction){ 114 | sensor_t * s = esp_camera_sensor_get(); 115 | if (!s) { 116 | ESP_LOGE(TAG, "Flipping Failed"); 117 | return mp_const_false; 118 | } 119 | int test = mp_obj_get_int(direction); 120 | s->set_vflip(s, test); 121 | return mp_const_none; 122 | } 123 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_flip_obj, camera_flip); 124 | 125 | STATIC mp_obj_t camera_framesize(mp_obj_t what){ 126 | sensor_t * s = esp_camera_sensor_get(); 127 | if (!s) { 128 | ESP_LOGE(TAG, "Framesize Failed"); 129 | return mp_const_false; 130 | } 131 | int size = mp_obj_get_int(what); 132 | if (size == 1) { 133 | s->set_framesize(s, FRAMESIZE_QQVGA); // 160x120 134 | } else if (size == 2) { 135 | s->set_framesize(s, FRAMESIZE_QQVGA2); // 128x160 136 | } else if (size == 3) { 137 | s->set_framesize(s, FRAMESIZE_QCIF); // 176x144 138 | } else if (size == 4) { 139 | s->set_framesize(s, FRAMESIZE_HQVGA); // 240x176 140 | } else if (size == 5) { 141 | s->set_framesize(s, FRAMESIZE_QVGA); // 320x240 142 | } else if (size == 6) { 143 | s->set_framesize(s, FRAMESIZE_CIF); // 400x296 144 | } else if (size == 7) { 145 | s->set_framesize(s, FRAMESIZE_VGA); // 640x480 146 | } else if (size == 8) { 147 | s->set_framesize(s, FRAMESIZE_SVGA); // 800x600 148 | } else if (size == 9) { 149 | s->set_framesize(s, FRAMESIZE_XGA); // 1024x768 (default) 150 | } else if (size == 10) { 151 | s->set_framesize(s, FRAMESIZE_SXGA); // 1280x1024 152 | } else if (size == 11) { 153 | s->set_framesize(s, FRAMESIZE_UXGA); // 1600x1200 154 | } else if (size == 12) { 155 | s->set_framesize(s, FRAMESIZE_QXGA); // 2048x1536 156 | } 157 | return mp_const_none; 158 | } 159 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_framesize_obj, camera_framesize); 160 | 161 | STATIC mp_obj_t camera_quality(mp_obj_t what){ 162 | sensor_t * s = esp_camera_sensor_get(); 163 | if (!s) { 164 | ESP_LOGE(TAG, "Quality Failed"); 165 | return mp_const_false; 166 | } 167 | int val = mp_obj_get_int(what); // 10-63 lower number means higher quality 168 | s->set_quality(s, val); 169 | return mp_const_none; 170 | } 171 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_quality_obj, camera_quality); 172 | 173 | STATIC mp_obj_t camera_contrast(mp_obj_t what){ 174 | //acquire a frame 175 | sensor_t * s = esp_camera_sensor_get(); 176 | if (!s) { 177 | ESP_LOGE(TAG, "Contrast Failed"); 178 | return mp_const_false; 179 | } 180 | int val = mp_obj_get_int(what); // -2,2 (default 0). 2 highcontrast 181 | s->set_contrast(s, val); 182 | return mp_const_none; 183 | } 184 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_contrast_obj, camera_contrast); 185 | 186 | STATIC mp_obj_t camera_saturation(mp_obj_t what){ 187 | //acquire a frame 188 | sensor_t * s = esp_camera_sensor_get(); 189 | if (!s) { 190 | ESP_LOGE(TAG, "Saturation Failed"); 191 | return mp_const_false; 192 | } 193 | int val = mp_obj_get_int(what); 194 | s->set_saturation(s, val); // -2,2 (default 0). -2 grayscale 195 | return mp_const_none; 196 | } 197 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_saturation_obj, camera_saturation); 198 | 199 | STATIC mp_obj_t camera_brightness(mp_obj_t what){ 200 | sensor_t * s = esp_camera_sensor_get(); 201 | if (!s) { 202 | ESP_LOGE(TAG, "Brightness Failed"); 203 | return mp_const_false; 204 | } 205 | int val = mp_obj_get_int(what); 206 | s->set_brightness(s, val); // -2,2 (default 0). 2 brightest 207 | return mp_const_none; 208 | } 209 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_brightness_obj, camera_brightness); 210 | 211 | STATIC mp_obj_t camera_speffect(mp_obj_t what){ 212 | sensor_t * s = esp_camera_sensor_get(); 213 | if (!s) { 214 | ESP_LOGE(TAG, "Special Effect Failed"); 215 | return mp_const_false; 216 | } 217 | int val = mp_obj_get_int(what); 218 | s->set_special_effect(s, val); // 0-6 (default 0). 219 | // 0 - no effect 220 | // 1 - negative 221 | // 2 - black and white 222 | // 3 - reddish 223 | // 4 - greenish 224 | // 5 - blue 225 | // 6 - retro 226 | return mp_const_none; 227 | } 228 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_speffect_obj, camera_speffect); 229 | 230 | STATIC mp_obj_t camera_whitebalance(mp_obj_t what){ 231 | sensor_t * s = esp_camera_sensor_get(); 232 | if (!s) { 233 | ESP_LOGE(TAG, "White Balance Failed"); 234 | return mp_const_false; 235 | } 236 | int val = mp_obj_get_int(what); 237 | s->set_wb_mode(s, val); // 0-4 (default 0). 238 | // 0 - no effect 239 | // 1 - sunny 240 | // 2 - cloudy 241 | // 3 - office 242 | // 4 - home 243 | return mp_const_none; 244 | } 245 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_whitebalance_obj, camera_whitebalance); 246 | 247 | STATIC const mp_rom_map_elem_t camera_module_globals_table[] = { 248 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_camera) }, 249 | 250 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&camera_init_obj) }, 251 | { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&camera_deinit_obj) }, 252 | { MP_ROM_QSTR(MP_QSTR_capture), MP_ROM_PTR(&camera_capture_obj) }, 253 | { MP_ROM_QSTR(MP_QSTR_flip), MP_ROM_PTR(&camera_flip_obj) }, 254 | { MP_ROM_QSTR(MP_QSTR_framesize), MP_ROM_PTR(&camera_framesize_obj) }, 255 | { MP_ROM_QSTR(MP_QSTR_quality), MP_ROM_PTR(&camera_quality_obj) }, 256 | { MP_ROM_QSTR(MP_QSTR_contrast), MP_ROM_PTR(&camera_contrast_obj) }, 257 | { MP_ROM_QSTR(MP_QSTR_saturation), MP_ROM_PTR(&camera_saturation_obj) }, 258 | { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&camera_brightness_obj) }, 259 | { MP_ROM_QSTR(MP_QSTR_speffect), MP_ROM_PTR(&camera_speffect_obj) }, 260 | { MP_ROM_QSTR(MP_QSTR_whitebalance), MP_ROM_PTR(&camera_whitebalance_obj) }, 261 | }; 262 | 263 | STATIC MP_DEFINE_CONST_DICT(camera_module_globals, camera_module_globals_table); 264 | 265 | const mp_obj_module_t mp_module_camera = { 266 | .base = { &mp_type_module }, 267 | .globals = (mp_obj_dict_t*)&camera_module_globals, 268 | }; 269 | -------------------------------------------------------------------------------- /webcam/mth_webcam.py: -------------------------------------------------------------------------------- 1 | 2 | import usocket as soc 3 | import _thread as th 4 | import camera 5 | import time 6 | import esp 7 | from machine import Pin 8 | import gc 9 | from Wifi.Sta import Sta 10 | 11 | #esp.osdebug(False) 12 | esp.osdebug(True) 13 | 14 | hdr = { 15 | # start page for streaming 16 | # URL: /apikey/webcam 17 | 'live': """HTTP/1.1 200 OK 18 | Content-Type: text/html; charset=utf-8 19 | 20 | 21 | 22 | Web Camera 23 | 24 | 25 |
26 |

Web Camera

27 | 28 |
29 | 30 | 31 | 32 | """, 33 | # live stream - 34 | # URL: /apikey/live 35 | 'stream': """HTTP/1.1 200 OK 36 | Content-Type: multipart/x-mixed-replace; boundary=frame 37 | Connection: keep-alive 38 | Cache-Control: no-cache, no-store, max-age=0, must-revalidate 39 | Expires: Thu, Jan 01 1970 00:00:00 GMT 40 | Pragma: no-cache 41 | 42 | """, 43 | # live stream - 44 | # URL: 45 | 'frame': """--frame 46 | Content-Type: image/jpeg 47 | 48 | """, 49 | # still picture - 50 | # URL: /apikey/snap 51 | 'snap': """HTTP/1.1 200 OK 52 | Content-Type: image/jpeg 53 | Content-Length: """, 54 | # no content error 55 | # URL: all the rest 56 | 'none': """HTTP/1.1 204 No Content 57 | Content-Type: text/plain; charset=utf-8 58 | 59 | Nothing here! 60 | 61 | """, 62 | # bad request error 63 | # URL: /favicon.ico 64 | 'favicon': """HTTP/1.1 404 65 | 66 | 67 | """, 68 | # bad request error 69 | # URL: all the rest 70 | 'err': """HTTP/1.1 400 Bad Request 71 | Content-Type: text/plain; charset=utf-8 72 | 73 | Hello? Can not compile 74 | 75 | """, 76 | # OK 77 | # URL: all the rest 78 | 'OK': """HTTP/1.1 200 OK 79 | Content-Type: text/plain; charset=utf-8 80 | 81 | OK! 82 | 83 | """ 84 | } 85 | 86 | def clean_up(cs): 87 | cs.close() # flash buffer and close socket 88 | del cs 89 | gc.collect() 90 | 91 | def frame_gen(): 92 | while True: 93 | buf = camera.capture() 94 | yield buf 95 | del buf 96 | gc.collect() 97 | 98 | def send_frame(pp): 99 | cs, h = pp 100 | while True: 101 | ee = '' 102 | try: 103 | cs.send(b'%s' % h) 104 | cs.send(next(pic)) 105 | cs.send(b'\r\n') # send and flush the send buffer 106 | except Exception as e: 107 | ee = str(e) 108 | if ee == '': 109 | time.sleep(0.005) # try as fast as we can 110 | else: 111 | break 112 | 113 | clean_up(cs) 114 | return 115 | 116 | def servers(): 117 | socks = [] 118 | # port 80 server - streaming server 119 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 120 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 121 | a = ('0.0.0.0', 80) 122 | s.bind(a) 123 | s.listen(2) # queue at most 2 clients 124 | socks.append(s) 125 | 126 | # port 81 server - still picture server 127 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 128 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 129 | a = ('0.0.0.0', 81) 130 | s.bind(a) 131 | s.listen(2) 132 | socks.append(s) 133 | 134 | # port 82 server - cmd server 135 | s = soc.socket(soc.AF_INET, soc.SOCK_STREAM) 136 | s.setsockopt(soc.SOL_SOCKET, soc.SO_REUSEADDR, 1) 137 | a = ('0.0.0.0', 82) 138 | s.bind(a) 139 | s.listen(2) 140 | socks.append(s) 141 | 142 | return socks 143 | 144 | def port1(cs, rq): 145 | rqp = rq[1].split('/') 146 | if rqp[1] == 'apikey': # Must have /apikey/ 147 | if rqp[2] == 'webcam': 148 | cs.send(b'%s' % hdr['live']) 149 | clean_up(cs) 150 | elif rqp[2] == 'live': # start streaming 151 | cs.send(b'%s' % hdr['stream']) 152 | # start frame sending 153 | send_frame([cs, hdr['frame']]) 154 | else: # 155 | cs.send(b'%s' % hdr['none']) 156 | clean_up(cs) 157 | else: 158 | cs.send(b'%s' % hdr['err']) 159 | clean_up(cs) 160 | 161 | def port2(cs, rq): 162 | rqp = rq[1].split('/') 163 | if rqp[1] == 'apikey': # Must have /apikey/ 164 | if rqp[2] == 'snap': 165 | try: 166 | img=next(pic) 167 | cs.send(b'%s %d\r\n\r\n' % (hdr['snap'], len(img))) 168 | cs.send(img) 169 | cs.send(b'\r\n') 170 | except: 171 | pass 172 | elif rqp[2] == 'blitz': 173 | try: 174 | flash_light.on() 175 | img=next(pic) 176 | flash_light.off() 177 | cs.send(b'%s %d\r\n\r\n' % (hdr['snap'], len(img))) 178 | cs.send(img) 179 | cs.send(b'\r\n') 180 | except: 181 | pass 182 | else: 183 | cs.send(b'%s' % hdr['none']) 184 | else: 185 | cs.send(b'%s' % hdr['err']) 186 | clean_up(cs) 187 | 188 | def port3(cs, rq): 189 | rqp = rq[1].split('/') 190 | if rqp[1] == 'apikey': # Must have /apikey/ 191 | if rqp[2] == 'flash': # /apikey/flash/ 192 | if rqp[3] == 'on': 193 | flash_light.on() 194 | else: 195 | flash_light.off() 196 | cs.send(b'%s' % hdr['OK']) 197 | elif rqp[2] == 'fmt': 198 | w = int(rqp[3]) 199 | if w>=0 and w<=2: 200 | camera.pixformat(w) 201 | cs.send(b'%s' % hdr['OK']) 202 | elif rqp[2] == 'pix': 203 | w = int(rqp[3]) 204 | if w>0 and w<13: 205 | camera.framesize(w) 206 | cs.send(b'%s' % hdr['OK']) 207 | elif rqp[2] == 'qua': 208 | w = int(rqp[3]) 209 | if w>9 and w<64: 210 | camera.quality(w) 211 | cs.send(b'%s' % hdr['OK']) 212 | elif rqp[2] == 'con': 213 | w = int(rqp[3]) 214 | if w>-3 and w<3: 215 | camera.contrast(w) 216 | cs.send(b'%s' % hdr['OK']) 217 | elif rqp[2] == 'sat': 218 | w = int(rqp[3]) 219 | if w>-3 and w<3: 220 | camera.saturation(w) 221 | cs.send(b'%s' % hdr['OK']) 222 | elif rqp[2] == 'bri': 223 | w = int(rqp[3]) 224 | if w>-3 and w<3: 225 | camera.brightness(w) 226 | cs.send(b'%s' % hdr['OK']) 227 | elif rqp[2] == 'ael': 228 | w = int(rqp[3]) 229 | if w>-3 and w<3: 230 | camera.aelevels(w) 231 | cs.send(b'%s' % hdr['OK']) 232 | elif rqp[2] == 'aev': 233 | w = int(rqp[3]) 234 | if w>=0 and w<=1200: 235 | camera.aecvalue(w) 236 | cs.send(b'%s' % hdr['OK']) 237 | elif rqp[2] == 'agc': 238 | w = int(rqp[3]) 239 | if w>=0 and w<=30: 240 | camera.agcgain(w) 241 | cs.send(b'%s' % hdr['OK']) 242 | elif rqp[2] == 'spe': 243 | w = int(rqp[3]) 244 | if w>=0 and w<7: 245 | camera.speffect(w) 246 | cs.send(b'%s' % hdr['OK']) 247 | elif rqp[2] == 'wbl': 248 | w = int(rqp[3]) 249 | if w>=0 and w<5: 250 | camera.whitebalance(w) 251 | cs.send(b'%s' % hdr['OK']) 252 | else: 253 | cs.send(b'%s' % hdr['none']) 254 | else: 255 | cs.send(b'%s' % hdr['err']) 256 | clean_up(cs) 257 | 258 | def srv(p): 259 | sa = socks[p] # start server; catch error - loop forever 260 | while True: 261 | try: 262 | ok = True 263 | ee = '' 264 | try: 265 | sa.settimeout(0.05) # in sec NB! default browser timeout (5-15 min) 266 | cs, ca = sa.accept() 267 | cs.settimeout(0.5) # in sec 268 | except Exception as e: 269 | ee = str(e) 270 | if ee != '': 271 | # print('Socket %d accept - %s' % (p, ee.split()[-1])) 272 | #ee = '' 273 | pass 274 | ok = False 275 | if ok: # No soc.accept timeout 276 | ee = '' 277 | try: 278 | # client accepted 279 | r = cs.recv(1024) 280 | # REQ: b'' # may be due to very short timeout 281 | except Exception as e: 282 | ee = str(e) 283 | if ee != '': 284 | print(ee) 285 | ok = False 286 | else: 287 | ms = r.decode('utf-8') 288 | if ms.find('favicon.ico') < 0: 289 | rq = ms.split(' ') 290 | try: 291 | print(rq[0], rq[1], ca) 292 | except: 293 | ok = False 294 | else: 295 | cs.send(b'%s' % hdr['favicon']) # handle favicon request early 296 | clean_up(cs) 297 | ok = False 298 | if ok: # No soc.recv timeout or favicon request 299 | try: 300 | ports[p](cs, rq) 301 | except Exception as e: 302 | ee = str(e) 303 | if ee != '': 304 | print(ee) 305 | except Exception as e: 306 | ee = str(e) 307 | if ee != '': 308 | print(ee) 309 | 310 | 311 | #------------------ 312 | wc = 0 313 | while True: 314 | cr = camera.init() 315 | print("Camera ready?: ", cr) 316 | if cr: 317 | break 318 | time.sleep(2) 319 | wc += 1 320 | if wc >= 5: 321 | break 322 | 323 | if not cr: 324 | print("Camera not ready. Can't continue!") 325 | else: 326 | # setup networking 327 | w = Sta() 328 | w.connect() 329 | w.wait() 330 | wc = 0 331 | while not w.wlan.isconnected(): 332 | print("WIFI not ready. Wait...") 333 | time.sleep(2) 334 | wc += 1 335 | if wc >= 5: 336 | break 337 | if wc >= 5: 338 | print("WIFI not ready. Can't continue!") 339 | else: 340 | pic = frame_gen() 341 | flash_light = Pin(04,Pin.OUT) 342 | socks = servers() 343 | ports = [port1, port2, port3] # 80, 81, 82 344 | 345 | # schedule 2 servers for port 80 346 | # streaming hold socket until client terminate, 347 | # so, we service at most 2 clients on port 80 348 | th.start_new_thread(srv, (0,)) 349 | th.start_new_thread(srv, (0,)) 350 | 351 | # schedule 1 server for port 81 352 | th.start_new_thread(srv, (1,)) 353 | 354 | # 355 | # schedule other processes here 356 | # 357 | 358 | # go for it! 359 | print("Up Up and Away!") 360 | 361 | # let the main thread take care of port 82 - block REPL 362 | srv(2) 363 | 364 | -------------------------------------------------------------------------------- /webcam/uasyncio/core.py: -------------------------------------------------------------------------------- 1 | import utime as time 2 | import utimeq 3 | import ucollections 4 | 5 | 6 | type_gen = type((lambda: (yield))()) 7 | 8 | DEBUG = 0 9 | log = None 10 | 11 | def set_debug(val): 12 | global DEBUG, log 13 | DEBUG = val 14 | if val: 15 | import logging 16 | log = logging.getLogger("uasyncio.core") 17 | 18 | 19 | class CancelledError(Exception): 20 | pass 21 | 22 | 23 | class TimeoutError(CancelledError): 24 | pass 25 | 26 | 27 | class EventLoop: 28 | 29 | def __init__(self, runq_len=16, waitq_len=16): 30 | self.runq = ucollections.deque((), runq_len, True) 31 | self.waitq = utimeq.utimeq(waitq_len) 32 | # Current task being run. Task is a top-level coroutine scheduled 33 | # in the event loop (sub-coroutines executed transparently by 34 | # yield from/await, event loop "doesn't see" them). 35 | self.cur_task = None 36 | 37 | def time(self): 38 | return time.ticks_ms() 39 | 40 | def create_task(self, coro): 41 | # CPython 3.4.2 42 | self.call_later_ms(0, coro) 43 | # CPython asyncio incompatibility: we don't return Task object 44 | 45 | def call_soon(self, callback, *args): 46 | if __debug__ and DEBUG: 47 | log.debug("Scheduling in runq: %s", (callback, args)) 48 | self.runq.append(callback) 49 | if not isinstance(callback, type_gen): 50 | self.runq.append(args) 51 | 52 | def call_later(self, delay, callback, *args): 53 | self.call_at_(time.ticks_add(self.time(), int(delay * 1000)), callback, args) 54 | 55 | def call_later_ms(self, delay, callback, *args): 56 | if not delay: 57 | return self.call_soon(callback, *args) 58 | self.call_at_(time.ticks_add(self.time(), delay), callback, args) 59 | 60 | def call_at_(self, time, callback, args=()): 61 | if __debug__ and DEBUG: 62 | log.debug("Scheduling in waitq: %s", (time, callback, args)) 63 | self.waitq.push(time, callback, args) 64 | 65 | def wait(self, delay): 66 | # Default wait implementation, to be overriden in subclasses 67 | # with IO scheduling 68 | if __debug__ and DEBUG: 69 | log.debug("Sleeping for: %s", delay) 70 | time.sleep_ms(delay) 71 | 72 | def run_forever(self): 73 | cur_task = [0, 0, 0] 74 | while True: 75 | # Expire entries in waitq and move them to runq 76 | tnow = self.time() 77 | while self.waitq: 78 | t = self.waitq.peektime() 79 | delay = time.ticks_diff(t, tnow) 80 | if delay > 0: 81 | break 82 | self.waitq.pop(cur_task) 83 | if __debug__ and DEBUG: 84 | log.debug("Moving from waitq to runq: %s", cur_task[1]) 85 | self.call_soon(cur_task[1], *cur_task[2]) 86 | 87 | # Process runq 88 | l = len(self.runq) 89 | if __debug__ and DEBUG: 90 | log.debug("Entries in runq: %d", l) 91 | while l: 92 | cb = self.runq.popleft() 93 | l -= 1 94 | args = () 95 | if not isinstance(cb, type_gen): 96 | args = self.runq.popleft() 97 | l -= 1 98 | if __debug__ and DEBUG: 99 | log.info("Next callback to run: %s", (cb, args)) 100 | cb(*args) 101 | continue 102 | 103 | if __debug__ and DEBUG: 104 | log.info("Next coroutine to run: %s", (cb, args)) 105 | self.cur_task = cb 106 | delay = 0 107 | try: 108 | if args is (): 109 | ret = next(cb) 110 | else: 111 | ret = cb.send(*args) 112 | if __debug__ and DEBUG: 113 | log.info("Coroutine %s yield result: %s", cb, ret) 114 | if isinstance(ret, SysCall1): 115 | arg = ret.arg 116 | if isinstance(ret, SleepMs): 117 | delay = arg 118 | elif isinstance(ret, IORead): 119 | cb.pend_throw(False) 120 | self.add_reader(arg, cb) 121 | continue 122 | elif isinstance(ret, IOWrite): 123 | cb.pend_throw(False) 124 | self.add_writer(arg, cb) 125 | continue 126 | elif isinstance(ret, IOReadDone): 127 | self.remove_reader(arg) 128 | elif isinstance(ret, IOWriteDone): 129 | self.remove_writer(arg) 130 | elif isinstance(ret, StopLoop): 131 | return arg 132 | else: 133 | assert False, "Unknown syscall yielded: %r (of type %r)" % (ret, type(ret)) 134 | elif isinstance(ret, type_gen): 135 | self.call_soon(ret) 136 | elif isinstance(ret, int): 137 | # Delay 138 | delay = ret 139 | elif ret is None: 140 | # Just reschedule 141 | pass 142 | elif ret is False: 143 | # Don't reschedule 144 | continue 145 | else: 146 | assert False, "Unsupported coroutine yield value: %r (of type %r)" % (ret, type(ret)) 147 | except StopIteration as e: 148 | if __debug__ and DEBUG: 149 | log.debug("Coroutine finished: %s", cb) 150 | continue 151 | except CancelledError as e: 152 | if __debug__ and DEBUG: 153 | log.debug("Coroutine cancelled: %s", cb) 154 | continue 155 | # Currently all syscalls don't return anything, so we don't 156 | # need to feed anything to the next invocation of coroutine. 157 | # If that changes, need to pass that value below. 158 | if delay: 159 | self.call_later_ms(delay, cb) 160 | else: 161 | self.call_soon(cb) 162 | 163 | # Wait until next waitq task or I/O availability 164 | delay = 0 165 | if not self.runq: 166 | delay = -1 167 | if self.waitq: 168 | tnow = self.time() 169 | t = self.waitq.peektime() 170 | delay = time.ticks_diff(t, tnow) 171 | if delay < 0: 172 | delay = 0 173 | self.wait(delay) 174 | 175 | def run_until_complete(self, coro): 176 | def _run_and_stop(): 177 | yield from coro 178 | yield StopLoop(0) 179 | self.call_soon(_run_and_stop()) 180 | self.run_forever() 181 | 182 | def stop(self): 183 | self.call_soon((lambda: (yield StopLoop(0)))()) 184 | 185 | def close(self): 186 | pass 187 | 188 | 189 | class SysCall: 190 | 191 | def __init__(self, *args): 192 | self.args = args 193 | 194 | def handle(self): 195 | raise NotImplementedError 196 | 197 | # Optimized syscall with 1 arg 198 | class SysCall1(SysCall): 199 | 200 | def __init__(self, arg): 201 | self.arg = arg 202 | 203 | class StopLoop(SysCall1): 204 | pass 205 | 206 | class IORead(SysCall1): 207 | pass 208 | 209 | class IOWrite(SysCall1): 210 | pass 211 | 212 | class IOReadDone(SysCall1): 213 | pass 214 | 215 | class IOWriteDone(SysCall1): 216 | pass 217 | 218 | 219 | _event_loop = None 220 | _event_loop_class = EventLoop 221 | def get_event_loop(runq_len=16, waitq_len=16): 222 | global _event_loop 223 | if _event_loop is None: 224 | _event_loop = _event_loop_class(runq_len, waitq_len) 225 | return _event_loop 226 | 227 | def sleep(secs): 228 | yield int(secs * 1000) 229 | 230 | # Implementation of sleep_ms awaitable with zero heap memory usage 231 | class SleepMs(SysCall1): 232 | 233 | def __init__(self): 234 | self.v = None 235 | self.arg = None 236 | 237 | def __call__(self, arg): 238 | self.v = arg 239 | #print("__call__") 240 | return self 241 | 242 | def __iter__(self): 243 | #print("__iter__") 244 | return self 245 | 246 | def __next__(self): 247 | if self.v is not None: 248 | #print("__next__ syscall enter") 249 | self.arg = self.v 250 | self.v = None 251 | return self 252 | #print("__next__ syscall exit") 253 | _stop_iter.__traceback__ = None 254 | raise _stop_iter 255 | 256 | _stop_iter = StopIteration() 257 | sleep_ms = SleepMs() 258 | 259 | 260 | def cancel(coro): 261 | prev = coro.pend_throw(CancelledError()) 262 | if prev is False: 263 | _event_loop.call_soon(coro) 264 | 265 | 266 | class TimeoutObj: 267 | def __init__(self, coro): 268 | self.coro = coro 269 | 270 | 271 | def wait_for_ms(coro, timeout): 272 | 273 | def waiter(coro, timeout_obj): 274 | res = yield from coro 275 | if __debug__ and DEBUG: 276 | log.debug("waiter: cancelling %s", timeout_obj) 277 | timeout_obj.coro = None 278 | return res 279 | 280 | def timeout_func(timeout_obj): 281 | if timeout_obj.coro: 282 | if __debug__ and DEBUG: 283 | log.debug("timeout_func: cancelling %s", timeout_obj.coro) 284 | prev = timeout_obj.coro.pend_throw(TimeoutError()) 285 | #print("prev pend", prev) 286 | if prev is False: 287 | _event_loop.call_soon(timeout_obj.coro) 288 | 289 | timeout_obj = TimeoutObj(_event_loop.cur_task) 290 | _event_loop.call_later_ms(timeout, timeout_func, timeout_obj) 291 | return (yield from waiter(coro, timeout_obj)) 292 | 293 | 294 | def wait_for(coro, timeout): 295 | return wait_for_ms(coro, int(timeout * 1000)) 296 | 297 | 298 | def coroutine(f): 299 | return f 300 | 301 | # 302 | # The functions below are deprecated in uasyncio, and provided only 303 | # for compatibility with CPython asyncio 304 | # 305 | 306 | def ensure_future(coro, loop=_event_loop): 307 | _event_loop.call_soon(coro) 308 | # CPython asyncio incompatibility: we don't return Task object 309 | return coro 310 | 311 | 312 | # CPython asyncio incompatibility: Task is a function, not a class (for efficiency) 313 | def Task(coro, loop=_event_loop): 314 | # Same as async() 315 | _event_loop.call_soon(coro) 316 | -------------------------------------------------------------------------------- /esp32-cam-1-11-571/modcamera.c: -------------------------------------------------------------------------------- 1 | // Code adapted from https://github.com/espressif/esp32-camera 2 | 3 | #include "esp_camera.h" 4 | #include "esp_log.h" 5 | 6 | #include "py/nlr.h" 7 | #include "py/obj.h" 8 | #include "py/runtime.h" 9 | #include "py/binary.h" 10 | 11 | #define TAG "camera" 12 | 13 | //WROVER-KIT PIN Map 14 | #define CAM_PIN_PWDN 32 //power down is not used 15 | #define CAM_PIN_RESET -1 //software reset will be performed 16 | #define CAM_PIN_XCLK 0 17 | #define CAM_PIN_SIOD 26 // SDA 18 | #define CAM_PIN_SIOC 27 // SCL 19 | 20 | #define CAM_PIN_D7 35 21 | #define CAM_PIN_D6 34 22 | #define CAM_PIN_D5 39 23 | #define CAM_PIN_D4 36 24 | #define CAM_PIN_D3 21 25 | #define CAM_PIN_D2 19 26 | #define CAM_PIN_D1 18 27 | #define CAM_PIN_D0 5 28 | #define CAM_PIN_VSYNC 25 29 | #define CAM_PIN_HREF 23 30 | #define CAM_PIN_PCLK 22 31 | 32 | static camera_config_t camera_config = { 33 | .pin_pwdn = CAM_PIN_PWDN, 34 | .pin_reset = CAM_PIN_RESET, 35 | .pin_xclk = CAM_PIN_XCLK, 36 | .pin_sscb_sda = CAM_PIN_SIOD, 37 | .pin_sscb_scl = CAM_PIN_SIOC, 38 | 39 | .pin_d7 = CAM_PIN_D7, 40 | .pin_d6 = CAM_PIN_D6, 41 | .pin_d5 = CAM_PIN_D5, 42 | .pin_d4 = CAM_PIN_D4, 43 | .pin_d3 = CAM_PIN_D3, 44 | .pin_d2 = CAM_PIN_D2, 45 | .pin_d1 = CAM_PIN_D1, 46 | .pin_d0 = CAM_PIN_D0, 47 | .pin_vsync = CAM_PIN_VSYNC, 48 | .pin_href = CAM_PIN_HREF, 49 | .pin_pclk = CAM_PIN_PCLK, 50 | 51 | //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) 52 | .xclk_freq_hz = 20000000, 53 | .ledc_timer = LEDC_TIMER_0, 54 | .ledc_channel = LEDC_CHANNEL_0, 55 | 56 | .pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG 57 | .frame_size = FRAMESIZE_XGA,//QQVGA-UXGA Do not use sizes above QVGA when not JPEG 58 | 59 | .jpeg_quality = 12, //10-63 lower number means higher quality 60 | .fb_count = 1 //if more than one, i2s runs in continuous mode. Use only with JPEG 61 | }; 62 | 63 | #include "esp_system.h" 64 | #include "esp_spi_flash.h" 65 | 66 | 67 | STATIC mp_obj_t camera_init(){ 68 | esp_err_t err = esp_camera_init(&camera_config); 69 | if (err != ESP_OK) { 70 | ESP_LOGE(TAG, "Camera Init Failed"); 71 | return mp_const_false; 72 | } 73 | 74 | return mp_const_true; 75 | } 76 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_init_obj, camera_init); 77 | 78 | 79 | STATIC mp_obj_t camera_deinit(){ 80 | esp_err_t err = esp_camera_deinit(); 81 | if (err != ESP_OK) { 82 | ESP_LOGE(TAG, "Camera deinit Failed"); 83 | return mp_const_false; 84 | } 85 | 86 | return mp_const_true; 87 | } 88 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_deinit_obj, camera_deinit); 89 | 90 | 91 | STATIC mp_obj_t camera_capture(){ 92 | //acquire a frame 93 | camera_fb_t * fb = esp_camera_fb_get(); 94 | if (!fb) { 95 | ESP_LOGE(TAG, "Camera Capture Failed"); 96 | return mp_const_false; 97 | } 98 | 99 | mp_obj_t image = mp_obj_new_bytes(fb->buf, fb->len); 100 | 101 | //return the frame buffer back to the driver for reuse 102 | esp_camera_fb_return(fb); 103 | return image; 104 | } 105 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_capture_obj, camera_capture); 106 | 107 | STATIC mp_obj_t camera_flip(mp_obj_t what){ 108 | sensor_t * s = esp_camera_sensor_get(); 109 | if (!s) { 110 | ESP_LOGE(TAG, "Flipping Failed"); 111 | return mp_const_false; 112 | } 113 | int direction = mp_obj_get_int(what); 114 | s->set_vflip(s, direction); 115 | return mp_const_none; 116 | } 117 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_flip_obj, camera_flip); 118 | 119 | STATIC mp_obj_t camera_pixformat(mp_obj_t what){ 120 | sensor_t * s = esp_camera_sensor_get(); 121 | if (!s) { 122 | ESP_LOGE(TAG, "Pixformat Failed"); 123 | return mp_const_false; 124 | } 125 | int size = mp_obj_get_int(what); 126 | if (size == 0) { 127 | s->set_pixformat(s, PIXFORMAT_JPEG); // JPEG (default) compress 128 | } else if (size == 1) { 129 | s->set_pixformat(s, PIXFORMAT_GRAYSCALE); // Grayscale 1 byte/pixel 130 | } else if (size == 2) { 131 | s->set_pixformat(s, PIXFORMAT_RGB565); // Red Green Blue 3 bytes/pixcel 132 | } 133 | return mp_const_none; 134 | } 135 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_pixformat_obj, camera_pixformat); 136 | 137 | STATIC mp_obj_t camera_framesize(mp_obj_t what){ 138 | sensor_t * s = esp_camera_sensor_get(); 139 | if (!s) { 140 | ESP_LOGE(TAG, "Framesize Failed"); 141 | return mp_const_false; 142 | } 143 | int size = mp_obj_get_int(what); 144 | if (size == 1) { 145 | s->set_framesize(s, FRAMESIZE_QQVGA); // 160x120 146 | } else if (size == 2) { 147 | s->set_framesize(s, FRAMESIZE_QQVGA2); // 128x160 148 | } else if (size == 3) { 149 | s->set_framesize(s, FRAMESIZE_QCIF); // 176x144 150 | } else if (size == 4) { 151 | s->set_framesize(s, FRAMESIZE_HQVGA); // 240x176 152 | } else if (size == 5) { 153 | s->set_framesize(s, FRAMESIZE_QVGA); // 320x240 154 | } else if (size == 6) { 155 | s->set_framesize(s, FRAMESIZE_CIF); // 400x296 156 | } else if (size == 7) { 157 | s->set_framesize(s, FRAMESIZE_VGA); // 640x480 158 | } else if (size == 8) { 159 | s->set_framesize(s, FRAMESIZE_SVGA); // 800x600 160 | } else if (size == 9) { 161 | s->set_framesize(s, FRAMESIZE_XGA); // 1024x768 (default) 162 | } else if (size == 10) { 163 | s->set_framesize(s, FRAMESIZE_SXGA); // 1280x1024 164 | } else if (size == 11) { 165 | s->set_framesize(s, FRAMESIZE_UXGA); // 1600x1200 166 | } else if (size == 12) { 167 | s->set_framesize(s, FRAMESIZE_QXGA); // 2048x1536 168 | } 169 | return mp_const_none; 170 | } 171 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_framesize_obj, camera_framesize); 172 | 173 | STATIC mp_obj_t camera_quality(mp_obj_t what){ 174 | sensor_t * s = esp_camera_sensor_get(); 175 | if (!s) { 176 | ESP_LOGE(TAG, "Quality Failed"); 177 | return mp_const_false; 178 | } 179 | int val = mp_obj_get_int(what); // 10-63 lower number means higher quality 180 | s->set_quality(s, val); 181 | return mp_const_none; 182 | } 183 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_quality_obj, camera_quality); 184 | 185 | STATIC mp_obj_t camera_contrast(mp_obj_t what){ 186 | //acquire a frame 187 | sensor_t * s = esp_camera_sensor_get(); 188 | if (!s) { 189 | ESP_LOGE(TAG, "Contrast Failed"); 190 | return mp_const_false; 191 | } 192 | int val = mp_obj_get_int(what); // -2,2 (default 0). 2 highcontrast 193 | s->set_contrast(s, val); 194 | return mp_const_none; 195 | } 196 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_contrast_obj, camera_contrast); 197 | 198 | STATIC mp_obj_t camera_saturation(mp_obj_t what){ 199 | //acquire a frame 200 | sensor_t * s = esp_camera_sensor_get(); 201 | if (!s) { 202 | ESP_LOGE(TAG, "Saturation Failed"); 203 | return mp_const_false; 204 | } 205 | int val = mp_obj_get_int(what); 206 | s->set_saturation(s, val); // -2,2 (default 0). -2 grayscale 207 | return mp_const_none; 208 | } 209 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_saturation_obj, camera_saturation); 210 | 211 | STATIC mp_obj_t camera_brightness(mp_obj_t what){ 212 | sensor_t * s = esp_camera_sensor_get(); 213 | if (!s) { 214 | ESP_LOGE(TAG, "Brightness Failed"); 215 | return mp_const_false; 216 | } 217 | int val = mp_obj_get_int(what); 218 | s->set_brightness(s, val); // -2,2 (default 0). 2 brightest 219 | return mp_const_none; 220 | } 221 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_brightness_obj, camera_brightness); 222 | 223 | STATIC mp_obj_t camera_speffect(mp_obj_t what){ 224 | sensor_t * s = esp_camera_sensor_get(); 225 | if (!s) { 226 | ESP_LOGE(TAG, "Special Effect Failed"); 227 | return mp_const_false; 228 | } 229 | int val = mp_obj_get_int(what); 230 | s->set_special_effect(s, val); // 0-6 (default 0). 231 | // 0 - no effect 232 | // 1 - negative 233 | // 2 - black and white 234 | // 3 - reddish 235 | // 4 - greenish 236 | // 5 - blue 237 | // 6 - retro 238 | return mp_const_none; 239 | } 240 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_speffect_obj, camera_speffect); 241 | 242 | STATIC mp_obj_t camera_whitebalance(mp_obj_t what){ 243 | sensor_t * s = esp_camera_sensor_get(); 244 | if (!s) { 245 | ESP_LOGE(TAG, "White Balance Failed"); 246 | return mp_const_false; 247 | } 248 | int val = mp_obj_get_int(what); 249 | s->set_wb_mode(s, val); // 0-4 (default 0). 250 | // 0 - no effect 251 | // 1 - sunny 252 | // 2 - cloudy 253 | // 3 - office 254 | // 4 - home 255 | return mp_const_none; 256 | } 257 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_whitebalance_obj, camera_whitebalance); 258 | 259 | STATIC mp_obj_t camera_aelevels(mp_obj_t what){ 260 | sensor_t * s = esp_camera_sensor_get(); 261 | if (!s) { 262 | ESP_LOGE(TAG, "AE Levels Failed"); 263 | return mp_const_false; 264 | } 265 | int val = mp_obj_get_int(what); 266 | s->set_ae_level(s, val); // -2 to +2 (default 0). 267 | return mp_const_none; 268 | } 269 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_aelevels_obj, camera_aelevels); 270 | 271 | STATIC mp_obj_t camera_aecvalue(mp_obj_t what){ 272 | sensor_t * s = esp_camera_sensor_get(); 273 | if (!s) { 274 | ESP_LOGE(TAG, "AEC Value Failed"); 275 | return mp_const_false; 276 | } 277 | int val = mp_obj_get_int(what); 278 | s->set_aec_value(s, val); // 0 to 1200 (default 0). 279 | return mp_const_none; 280 | } 281 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_aecvalue_obj, camera_aecvalue); 282 | 283 | STATIC mp_obj_t camera_agcgain(mp_obj_t what){ 284 | sensor_t * s = esp_camera_sensor_get(); 285 | if (!s) { 286 | ESP_LOGE(TAG, "AGC Gain Failed"); 287 | return mp_const_false; 288 | } 289 | int val = mp_obj_get_int(what); 290 | s->set_agc_gain(s, val); // 0 to 30 (default 30). 291 | return mp_const_none; 292 | } 293 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_agcgain_obj, camera_agcgain); 294 | 295 | STATIC const mp_rom_map_elem_t camera_module_globals_table[] = { 296 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_camera) }, 297 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&camera_init_obj) }, 298 | { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&camera_deinit_obj) }, 299 | { MP_ROM_QSTR(MP_QSTR_capture), MP_ROM_PTR(&camera_capture_obj) }, 300 | { MP_ROM_QSTR(MP_QSTR_flip), MP_ROM_PTR(&camera_flip_obj) }, 301 | { MP_ROM_QSTR(MP_QSTR_pixformat), MP_ROM_PTR(&camera_pixformat_obj) }, 302 | { MP_ROM_QSTR(MP_QSTR_framesize), MP_ROM_PTR(&camera_framesize_obj) }, 303 | { MP_ROM_QSTR(MP_QSTR_quality), MP_ROM_PTR(&camera_quality_obj) }, 304 | { MP_ROM_QSTR(MP_QSTR_contrast), MP_ROM_PTR(&camera_contrast_obj) }, 305 | { MP_ROM_QSTR(MP_QSTR_saturation), MP_ROM_PTR(&camera_saturation_obj) }, 306 | { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&camera_brightness_obj) }, 307 | { MP_ROM_QSTR(MP_QSTR_speffect), MP_ROM_PTR(&camera_speffect_obj) }, 308 | { MP_ROM_QSTR(MP_QSTR_whitebalance), MP_ROM_PTR(&camera_whitebalance_obj) }, 309 | { MP_ROM_QSTR(MP_QSTR_aelevels), MP_ROM_PTR(&camera_aelevels_obj) }, 310 | { MP_ROM_QSTR(MP_QSTR_aecvalue), MP_ROM_PTR(&camera_aecvalue_obj) }, 311 | { MP_ROM_QSTR(MP_QSTR_agcgain), MP_ROM_PTR(&camera_agcgain_obj) }, 312 | }; 313 | 314 | STATIC MP_DEFINE_CONST_DICT(camera_module_globals, camera_module_globals_table); 315 | 316 | const mp_obj_module_t mp_module_camera = { 317 | .base = { &mp_type_module }, 318 | .globals = (mp_obj_dict_t*)&camera_module_globals, 319 | }; 320 | -------------------------------------------------------------------------------- /esp32-cam-1-11-498/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 | // object representation and NLR handling 15 | #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) 16 | #define MICROPY_NLR_SETJMP (1) 17 | 18 | // memory allocation policies 19 | #define MICROPY_ALLOC_PATH_MAX (128) 20 | 21 | // emitters 22 | #define MICROPY_PERSISTENT_CODE_LOAD (1) 23 | // -define MICROPY_EMIT_XTENSAWIN (1) 24 | // void *esp_native_code_commit(void*, size_t); 25 | // -define MP_PLAT_COMMIT_EXEC(buf, len) esp_native_code_commit(buf, len) 26 | 27 | // compiler configuration 28 | #define MICROPY_COMP_MODULE_CONST (1) 29 | #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) 30 | 31 | // optimisations 32 | #define MICROPY_OPT_COMPUTED_GOTO (1) 33 | #define MICROPY_OPT_MPZ_BITWISE (1) 34 | 35 | // Python internal features 36 | #define MICROPY_READER_VFS (1) 37 | #define MICROPY_ENABLE_GC (1) 38 | #define MICROPY_ENABLE_FINALISER (1) 39 | #define MICROPY_STACK_CHECK (1) 40 | #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) 41 | #define MICROPY_KBD_EXCEPTION (1) 42 | #define MICROPY_HELPER_REPL (1) 43 | #define MICROPY_REPL_EMACS_KEYS (1) 44 | #define MICROPY_REPL_AUTO_INDENT (1) 45 | #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) 46 | #define MICROPY_ENABLE_SOURCE_LINE (1) 47 | #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) 48 | #define MICROPY_WARNINGS (1) 49 | #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) 50 | #define MICROPY_CPYTHON_COMPAT (1) 51 | #define MICROPY_STREAMS_NON_BLOCK (1) 52 | #define MICROPY_STREAMS_POSIX_API (1) 53 | #define MICROPY_MODULE_BUILTIN_INIT (1) 54 | #define MICROPY_MODULE_WEAK_LINKS (1) 55 | #define MICROPY_MODULE_FROZEN_STR (0) 56 | #define MICROPY_MODULE_FROZEN_MPY (1) 57 | #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool 58 | #define MICROPY_CAN_OVERRIDE_BUILTINS (1) 59 | #define MICROPY_USE_INTERNAL_ERRNO (1) 60 | #define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf 61 | #define MICROPY_ENABLE_SCHEDULER (1) 62 | #define MICROPY_SCHEDULER_DEPTH (8) 63 | #define MICROPY_VFS (1) 64 | #define MICROPY_VFS_FAT (1) 65 | 66 | // control over Python builtins 67 | #define MICROPY_PY_FUNCTION_ATTRS (1) 68 | #define MICROPY_PY_DESCRIPTORS (1) 69 | #define MICROPY_PY_STR_BYTES_CMP_WARN (1) 70 | #define MICROPY_PY_BUILTINS_STR_UNICODE (1) 71 | #define MICROPY_PY_BUILTINS_STR_CENTER (1) 72 | #define MICROPY_PY_BUILTINS_STR_PARTITION (1) 73 | #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) 74 | #define MICROPY_PY_BUILTINS_BYTEARRAY (1) 75 | #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) 76 | #define MICROPY_PY_BUILTINS_SET (1) 77 | #define MICROPY_PY_BUILTINS_SLICE (1) 78 | #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) 79 | #define MICROPY_PY_BUILTINS_FROZENSET (1) 80 | #define MICROPY_PY_BUILTINS_PROPERTY (1) 81 | #define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) 82 | #define MICROPY_PY_BUILTINS_ROUND_INT (1) 83 | #define MICROPY_PY_BUILTINS_TIMEOUTERROR (1) 84 | #define MICROPY_PY_ALL_SPECIAL_METHODS (1) 85 | #define MICROPY_PY_BUILTINS_COMPILE (1) 86 | #define MICROPY_PY_BUILTINS_ENUMERATE (1) 87 | #define MICROPY_PY_BUILTINS_EXECFILE (1) 88 | #define MICROPY_PY_BUILTINS_FILTER (1) 89 | #define MICROPY_PY_BUILTINS_REVERSED (1) 90 | #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) 91 | #define MICROPY_PY_BUILTINS_INPUT (1) 92 | #define MICROPY_PY_BUILTINS_MIN_MAX (1) 93 | #define MICROPY_PY_BUILTINS_POW3 (1) 94 | #define MICROPY_PY_BUILTINS_HELP (0) 95 | #define MICROPY_PY_BUILTINS_HELP_TEXT esp32_help_text 96 | #define MICROPY_PY_BUILTINS_HELP_MODULES (0) 97 | #define MICROPY_PY___FILE__ (1) 98 | #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) 99 | #define MICROPY_PY_ARRAY (1) 100 | #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) 101 | #define MICROPY_PY_ATTRTUPLE (1) 102 | #define MICROPY_PY_COLLECTIONS (1) 103 | #define MICROPY_PY_COLLECTIONS_DEQUE (1) 104 | #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) 105 | #define MICROPY_PY_MATH (1) 106 | #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) 107 | #define MICROPY_PY_MATH_ISCLOSE (1) 108 | #define MICROPY_PY_CMATH (1) 109 | #define MICROPY_PY_GC (1) 110 | #define MICROPY_PY_IO (1) 111 | #define MICROPY_PY_IO_IOBASE (1) 112 | #define MICROPY_PY_IO_FILEIO (1) 113 | #define MICROPY_PY_IO_BYTESIO (1) 114 | #define MICROPY_PY_IO_BUFFEREDWRITER (1) 115 | #define MICROPY_PY_STRUCT (1) 116 | #define MICROPY_PY_SYS (1) 117 | #define MICROPY_PY_SYS_MAXSIZE (1) 118 | #define MICROPY_PY_SYS_MODULES (1) 119 | #define MICROPY_PY_SYS_EXIT (1) 120 | #define MICROPY_PY_SYS_STDFILES (1) 121 | #define MICROPY_PY_SYS_STDIO_BUFFER (1) 122 | #define MICROPY_PY_UERRNO (1) 123 | #define MICROPY_PY_USELECT (1) 124 | #define MICROPY_PY_UTIME_MP_HAL (1) 125 | #define MICROPY_PY_THREAD (1) 126 | #define MICROPY_PY_THREAD_GIL (1) 127 | #define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32) 128 | 129 | // extended modules 130 | #define MICROPY_PY_UCTYPES (1) 131 | #define MICROPY_PY_UZLIB (1) 132 | #define MICROPY_PY_UJSON (1) 133 | #define MICROPY_PY_URE (1) 134 | #define MICROPY_PY_URE_SUB (1) 135 | #define MICROPY_PY_UHEAPQ (1) 136 | #define MICROPY_PY_UTIMEQ (1) 137 | #define MICROPY_PY_UHASHLIB (1) 138 | #define MICROPY_PY_UHASHLIB_SHA1 (1) 139 | #define MICROPY_PY_UHASHLIB_SHA256 (1) 140 | #define MICROPY_PY_UCRYPTOLIB (1) 141 | #define MICROPY_PY_UBINASCII (1) 142 | #define MICROPY_PY_UBINASCII_CRC32 (1) 143 | #define MICROPY_PY_URANDOM (1) 144 | #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) 145 | #define MICROPY_PY_OS_DUPTERM (1) 146 | #define MICROPY_PY_MACHINE (1) 147 | #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new 148 | #define MICROPY_PY_MACHINE_PULSE (1) 149 | #define MICROPY_PY_MACHINE_I2C (1) 150 | #define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hw_i2c_make_new 151 | #define MICROPY_PY_MACHINE_SPI (1) 152 | #define MICROPY_PY_MACHINE_SPI_MSB (0) 153 | #define MICROPY_PY_MACHINE_SPI_LSB (1) 154 | #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hw_spi_make_new 155 | #define MICROPY_HW_ENABLE_SDCARD (1) 156 | #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) 157 | #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly 158 | #define MICROPY_PY_USSL (1) 159 | #define MICROPY_SSL_MBEDTLS (1) 160 | #define MICROPY_PY_USSL_FINALISER (1) 161 | #define MICROPY_PY_UWEBSOCKET (1) 162 | #define MICROPY_PY_WEBREPL (0) 163 | #define MICROPY_PY_FRAMEBUF (1) 164 | // -define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL) 165 | #define MICROPY_PY_BLUETOOTH_RANDOM_ADDR (0) 166 | #define MICROPY_PY_BLUETOOTH_DEFAULT_NAME ("") 167 | 168 | // fatfs configuration 169 | #define MICROPY_FATFS_ENABLE_LFN (1) 170 | #define MICROPY_FATFS_RPATH (2) 171 | #define MICROPY_FATFS_MAX_SS (4096) 172 | #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ 173 | #define mp_type_fileio mp_type_vfs_fat_fileio 174 | #define mp_type_textio mp_type_vfs_fat_textio 175 | 176 | // use vfs's functions for import stat and builtin open 177 | #define mp_import_stat mp_vfs_import_stat 178 | #define mp_builtin_open mp_vfs_open 179 | #define mp_builtin_open_obj mp_vfs_open_obj 180 | 181 | // extra built in names to add to the global namespace 182 | #define MICROPY_PORT_BUILTINS \ 183 | { MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \ 184 | { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, 185 | 186 | // extra built in modules to add to the list of known ones 187 | extern const struct _mp_obj_module_t esp_module; 188 | extern const struct _mp_obj_module_t esp32_module; 189 | extern const struct _mp_obj_module_t utime_module; 190 | extern const struct _mp_obj_module_t uos_module; 191 | extern const struct _mp_obj_module_t mp_module_usocket; 192 | extern const struct _mp_obj_module_t mp_module_machine; 193 | extern const struct _mp_obj_module_t mp_module_network; 194 | extern const struct _mp_obj_module_t mp_module_onewire; 195 | extern const struct _mp_obj_module_t mp_module_camera; 196 | 197 | #define MICROPY_PORT_BUILTIN_MODULES \ 198 | { MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \ 199 | { MP_OBJ_NEW_QSTR(MP_QSTR_esp32), (mp_obj_t)&esp32_module }, \ 200 | { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \ 201 | { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \ 202 | { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \ 203 | { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ 204 | { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \ 205 | { MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \ 206 | { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ 207 | { MP_OBJ_NEW_QSTR(MP_QSTR_camera), (mp_obj_t)&mp_module_camera }, \ 208 | 209 | #define MP_STATE_PORT MP_STATE_VM 210 | 211 | struct _machine_timer_obj_t; 212 | 213 | #if MICROPY_BLUETOOTH_NIMBLE 214 | struct mp_bluetooth_nimble_root_pointers_t; 215 | #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; 216 | #else 217 | #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE 218 | #endif 219 | 220 | #define MICROPY_PORT_ROOT_POINTERS \ 221 | const char *readline_hist[8]; \ 222 | mp_obj_t machine_pin_irq_handler[40]; \ 223 | struct _machine_timer_obj_t *machine_timer_obj_head; \ 224 | MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE 225 | 226 | // type definitions for the specific machine 227 | 228 | #define BYTES_PER_WORD (4) 229 | #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p))) 230 | #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) 231 | #define MP_SSIZE_MAX (0x7fffffff) 232 | 233 | // Note: these "critical nested" macros do not ensure cross-CPU exclusion, 234 | // the only disable interrupts on the current CPU. To full manage exclusion 235 | // one should use portENTER_CRITICAL/portEXIT_CRITICAL instead. 236 | #include "freertos/FreeRTOS.h" 237 | #define MICROPY_BEGIN_ATOMIC_SECTION() portENTER_CRITICAL_NESTED() 238 | #define MICROPY_END_ATOMIC_SECTION(state) portEXIT_CRITICAL_NESTED(state) 239 | 240 | #if MICROPY_PY_USOCKET_EVENTS 241 | #define MICROPY_PY_USOCKET_EVENTS_HANDLER extern void usocket_events_handler(void); usocket_events_handler(); 242 | #else 243 | #define MICROPY_PY_USOCKET_EVENTS_HANDLER 244 | #endif 245 | 246 | #if MICROPY_PY_THREAD 247 | #define MICROPY_EVENT_POLL_HOOK \ 248 | do { \ 249 | extern void mp_handle_pending(void); \ 250 | mp_handle_pending(); \ 251 | MICROPY_PY_USOCKET_EVENTS_HANDLER \ 252 | MP_THREAD_GIL_EXIT(); \ 253 | MP_THREAD_GIL_ENTER(); \ 254 | } while (0); 255 | #else 256 | #define MICROPY_EVENT_POLL_HOOK \ 257 | do { \ 258 | extern void mp_handle_pending(void); \ 259 | mp_handle_pending(); \ 260 | MICROPY_PY_USOCKET_EVENTS_HANDLER \ 261 | asm("waiti 0"); \ 262 | } while (0); 263 | #endif 264 | 265 | #define UINT_FMT "%u" 266 | #define INT_FMT "%d" 267 | 268 | typedef int32_t mp_int_t; // must be pointer size 269 | typedef uint32_t mp_uint_t; // must be pointer size 270 | typedef long mp_off_t; 271 | // ssize_t, off_t as required by POSIX-signatured functions in stream.h 272 | #include 273 | 274 | // board specifics 275 | #define MICROPY_PY_SYS_PLATFORM "esp32" 276 | 277 | #ifndef MICROPY_HW_ENABLE_MDNS_QUERIES 278 | #define MICROPY_HW_ENABLE_MDNS_QUERIES (1) 279 | #endif 280 | 281 | #ifndef MICROPY_HW_ENABLE_MDNS_RESPONDER 282 | #define MICROPY_HW_ENABLE_MDNS_RESPONDER (1) 283 | #endif 284 | -------------------------------------------------------------------------------- /esp32-cam-1-11-571/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 | // object representation and NLR handling 15 | #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) 16 | #define MICROPY_NLR_SETJMP (1) 17 | 18 | // memory allocation policies 19 | #define MICROPY_ALLOC_PATH_MAX (128) 20 | 21 | // emitters 22 | #define MICROPY_PERSISTENT_CODE_LOAD (1) 23 | // -define MICROPY_EMIT_XTENSAWIN (1) 24 | // void *esp_native_code_commit(void*, size_t); 25 | // -define MP_PLAT_COMMIT_EXEC(buf, len) esp_native_code_commit(buf, len) 26 | 27 | // compiler configuration 28 | #define MICROPY_COMP_MODULE_CONST (1) 29 | #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) 30 | 31 | // optimisations 32 | #define MICROPY_OPT_COMPUTED_GOTO (1) 33 | #define MICROPY_OPT_MPZ_BITWISE (1) 34 | 35 | // Python internal features 36 | #define MICROPY_READER_VFS (1) 37 | #define MICROPY_ENABLE_GC (1) 38 | #define MICROPY_ENABLE_FINALISER (1) 39 | #define MICROPY_STACK_CHECK (1) 40 | #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) 41 | #define MICROPY_KBD_EXCEPTION (1) 42 | #define MICROPY_HELPER_REPL (1) 43 | #define MICROPY_REPL_EMACS_KEYS (1) 44 | #define MICROPY_REPL_AUTO_INDENT (1) 45 | #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) 46 | #define MICROPY_ENABLE_SOURCE_LINE (1) 47 | #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) 48 | #define MICROPY_WARNINGS (1) 49 | #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) 50 | #define MICROPY_CPYTHON_COMPAT (1) 51 | #define MICROPY_STREAMS_NON_BLOCK (1) 52 | #define MICROPY_STREAMS_POSIX_API (1) 53 | #define MICROPY_MODULE_BUILTIN_INIT (1) 54 | #define MICROPY_MODULE_WEAK_LINKS (1) 55 | #define MICROPY_MODULE_FROZEN_STR (0) 56 | #define MICROPY_MODULE_FROZEN_MPY (1) 57 | #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool 58 | #define MICROPY_CAN_OVERRIDE_BUILTINS (1) 59 | #define MICROPY_USE_INTERNAL_ERRNO (1) 60 | #define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf 61 | #define MICROPY_ENABLE_SCHEDULER (1) 62 | #define MICROPY_SCHEDULER_DEPTH (8) 63 | #define MICROPY_VFS (1) 64 | #define MICROPY_VFS_FAT (1) 65 | 66 | // control over Python builtins 67 | #define MICROPY_PY_FUNCTION_ATTRS (1) 68 | #define MICROPY_PY_DESCRIPTORS (1) 69 | #define MICROPY_PY_STR_BYTES_CMP_WARN (1) 70 | #define MICROPY_PY_BUILTINS_STR_UNICODE (1) 71 | #define MICROPY_PY_BUILTINS_STR_CENTER (1) 72 | #define MICROPY_PY_BUILTINS_STR_PARTITION (1) 73 | #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) 74 | #define MICROPY_PY_BUILTINS_BYTEARRAY (1) 75 | #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) 76 | #define MICROPY_PY_BUILTINS_SET (1) 77 | #define MICROPY_PY_BUILTINS_SLICE (1) 78 | #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) 79 | #define MICROPY_PY_BUILTINS_FROZENSET (1) 80 | #define MICROPY_PY_BUILTINS_PROPERTY (1) 81 | #define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) 82 | #define MICROPY_PY_BUILTINS_ROUND_INT (1) 83 | #define MICROPY_PY_BUILTINS_TIMEOUTERROR (1) 84 | #define MICROPY_PY_ALL_SPECIAL_METHODS (1) 85 | #define MICROPY_PY_BUILTINS_COMPILE (1) 86 | #define MICROPY_PY_BUILTINS_ENUMERATE (1) 87 | #define MICROPY_PY_BUILTINS_EXECFILE (1) 88 | #define MICROPY_PY_BUILTINS_FILTER (1) 89 | #define MICROPY_PY_BUILTINS_REVERSED (1) 90 | #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) 91 | #define MICROPY_PY_BUILTINS_INPUT (1) 92 | #define MICROPY_PY_BUILTINS_MIN_MAX (1) 93 | #define MICROPY_PY_BUILTINS_POW3 (1) 94 | #define MICROPY_PY_BUILTINS_HELP (0) 95 | #define MICROPY_PY_BUILTINS_HELP_TEXT esp32_help_text 96 | #define MICROPY_PY_BUILTINS_HELP_MODULES (0) 97 | #define MICROPY_PY___FILE__ (1) 98 | #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) 99 | #define MICROPY_PY_ARRAY (1) 100 | #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) 101 | #define MICROPY_PY_ATTRTUPLE (1) 102 | #define MICROPY_PY_COLLECTIONS (1) 103 | #define MICROPY_PY_COLLECTIONS_DEQUE (1) 104 | #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) 105 | #define MICROPY_PY_MATH (1) 106 | #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) 107 | #define MICROPY_PY_MATH_ISCLOSE (1) 108 | #define MICROPY_PY_CMATH (1) 109 | #define MICROPY_PY_GC (1) 110 | #define MICROPY_PY_IO (1) 111 | #define MICROPY_PY_IO_IOBASE (1) 112 | #define MICROPY_PY_IO_FILEIO (1) 113 | #define MICROPY_PY_IO_BYTESIO (1) 114 | #define MICROPY_PY_IO_BUFFEREDWRITER (1) 115 | #define MICROPY_PY_STRUCT (1) 116 | #define MICROPY_PY_SYS (1) 117 | #define MICROPY_PY_SYS_MAXSIZE (1) 118 | #define MICROPY_PY_SYS_MODULES (1) 119 | #define MICROPY_PY_SYS_EXIT (1) 120 | #define MICROPY_PY_SYS_STDFILES (1) 121 | #define MICROPY_PY_SYS_STDIO_BUFFER (1) 122 | #define MICROPY_PY_UERRNO (1) 123 | #define MICROPY_PY_USELECT (1) 124 | #define MICROPY_PY_UTIME_MP_HAL (1) 125 | #define MICROPY_PY_THREAD (1) 126 | #define MICROPY_PY_THREAD_GIL (1) 127 | #define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32) 128 | 129 | // extended modules 130 | #define MICROPY_PY_UCTYPES (1) 131 | #define MICROPY_PY_UZLIB (1) 132 | #define MICROPY_PY_UJSON (1) 133 | #define MICROPY_PY_URE (1) 134 | #define MICROPY_PY_URE_SUB (1) 135 | #define MICROPY_PY_UHEAPQ (1) 136 | #define MICROPY_PY_UTIMEQ (1) 137 | #define MICROPY_PY_UHASHLIB (1) 138 | #define MICROPY_PY_UHASHLIB_SHA1 (1) 139 | #define MICROPY_PY_UHASHLIB_SHA256 (1) 140 | #define MICROPY_PY_UCRYPTOLIB (1) 141 | #define MICROPY_PY_UBINASCII (1) 142 | #define MICROPY_PY_UBINASCII_CRC32 (1) 143 | #define MICROPY_PY_URANDOM (1) 144 | #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) 145 | #define MICROPY_PY_OS_DUPTERM (1) 146 | #define MICROPY_PY_MACHINE (1) 147 | #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new 148 | #define MICROPY_PY_MACHINE_PULSE (1) 149 | #define MICROPY_PY_MACHINE_I2C (1) 150 | #define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hw_i2c_make_new 151 | #define MICROPY_PY_MACHINE_SPI (1) 152 | #define MICROPY_PY_MACHINE_SPI_MSB (0) 153 | #define MICROPY_PY_MACHINE_SPI_LSB (1) 154 | #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hw_spi_make_new 155 | #define MICROPY_HW_ENABLE_SDCARD (1) 156 | #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) 157 | #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly 158 | #define MICROPY_PY_USSL (1) 159 | #define MICROPY_SSL_MBEDTLS (1) 160 | #define MICROPY_PY_USSL_FINALISER (1) 161 | #define MICROPY_PY_UWEBSOCKET (1) 162 | #define MICROPY_PY_WEBREPL (0) 163 | #define MICROPY_PY_FRAMEBUF (1) 164 | // -define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL) 165 | #define MICROPY_PY_BLUETOOTH_RANDOM_ADDR (0) 166 | #define MICROPY_PY_BLUETOOTH_DEFAULT_NAME ("") 167 | 168 | // fatfs configuration 169 | #define MICROPY_FATFS_ENABLE_LFN (1) 170 | #define MICROPY_FATFS_RPATH (2) 171 | #define MICROPY_FATFS_MAX_SS (4096) 172 | #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ 173 | #define mp_type_fileio mp_type_vfs_fat_fileio 174 | #define mp_type_textio mp_type_vfs_fat_textio 175 | 176 | // use vfs's functions for import stat and builtin open 177 | #define mp_import_stat mp_vfs_import_stat 178 | #define mp_builtin_open mp_vfs_open 179 | #define mp_builtin_open_obj mp_vfs_open_obj 180 | 181 | // extra built in names to add to the global namespace 182 | #define MICROPY_PORT_BUILTINS \ 183 | { MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \ 184 | { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, 185 | 186 | // extra built in modules to add to the list of known ones 187 | extern const struct _mp_obj_module_t esp_module; 188 | extern const struct _mp_obj_module_t esp32_module; 189 | extern const struct _mp_obj_module_t utime_module; 190 | extern const struct _mp_obj_module_t uos_module; 191 | extern const struct _mp_obj_module_t mp_module_usocket; 192 | extern const struct _mp_obj_module_t mp_module_machine; 193 | extern const struct _mp_obj_module_t mp_module_network; 194 | extern const struct _mp_obj_module_t mp_module_onewire; 195 | extern const struct _mp_obj_module_t mp_module_camera; 196 | 197 | #define MICROPY_PORT_BUILTIN_MODULES \ 198 | { MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \ 199 | { MP_OBJ_NEW_QSTR(MP_QSTR_esp32), (mp_obj_t)&esp32_module }, \ 200 | { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \ 201 | { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \ 202 | { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \ 203 | { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ 204 | { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \ 205 | { MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \ 206 | { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ 207 | { MP_OBJ_NEW_QSTR(MP_QSTR_camera), (mp_obj_t)&mp_module_camera }, \ 208 | 209 | #define MP_STATE_PORT MP_STATE_VM 210 | 211 | struct _machine_timer_obj_t; 212 | 213 | #if MICROPY_BLUETOOTH_NIMBLE 214 | struct mp_bluetooth_nimble_root_pointers_t; 215 | #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; 216 | #else 217 | #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE 218 | #endif 219 | 220 | #define MICROPY_PORT_ROOT_POINTERS \ 221 | const char *readline_hist[8]; \ 222 | mp_obj_t machine_pin_irq_handler[40]; \ 223 | struct _machine_timer_obj_t *machine_timer_obj_head; \ 224 | MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE 225 | 226 | // type definitions for the specific machine 227 | 228 | #define BYTES_PER_WORD (4) 229 | #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p))) 230 | #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) 231 | #define MP_SSIZE_MAX (0x7fffffff) 232 | 233 | // Note: these "critical nested" macros do not ensure cross-CPU exclusion, 234 | // the only disable interrupts on the current CPU. To full manage exclusion 235 | // one should use portENTER_CRITICAL/portEXIT_CRITICAL instead. 236 | #include "freertos/FreeRTOS.h" 237 | #define MICROPY_BEGIN_ATOMIC_SECTION() portENTER_CRITICAL_NESTED() 238 | #define MICROPY_END_ATOMIC_SECTION(state) portEXIT_CRITICAL_NESTED(state) 239 | 240 | #if MICROPY_PY_USOCKET_EVENTS 241 | #define MICROPY_PY_USOCKET_EVENTS_HANDLER extern void usocket_events_handler(void); usocket_events_handler(); 242 | #else 243 | #define MICROPY_PY_USOCKET_EVENTS_HANDLER 244 | #endif 245 | 246 | #if MICROPY_PY_THREAD 247 | #define MICROPY_EVENT_POLL_HOOK \ 248 | do { \ 249 | extern void mp_handle_pending(void); \ 250 | mp_handle_pending(); \ 251 | MICROPY_PY_USOCKET_EVENTS_HANDLER \ 252 | MP_THREAD_GIL_EXIT(); \ 253 | MP_THREAD_GIL_ENTER(); \ 254 | } while (0); 255 | #else 256 | #define MICROPY_EVENT_POLL_HOOK \ 257 | do { \ 258 | extern void mp_handle_pending(void); \ 259 | mp_handle_pending(); \ 260 | MICROPY_PY_USOCKET_EVENTS_HANDLER \ 261 | asm("waiti 0"); \ 262 | } while (0); 263 | #endif 264 | 265 | #define UINT_FMT "%u" 266 | #define INT_FMT "%d" 267 | 268 | typedef int32_t mp_int_t; // must be pointer size 269 | typedef uint32_t mp_uint_t; // must be pointer size 270 | typedef long mp_off_t; 271 | // ssize_t, off_t as required by POSIX-signatured functions in stream.h 272 | #include 273 | 274 | // board specifics 275 | #define MICROPY_PY_SYS_PLATFORM "esp32" 276 | 277 | #ifndef MICROPY_HW_ENABLE_MDNS_QUERIES 278 | #define MICROPY_HW_ENABLE_MDNS_QUERIES (1) 279 | #endif 280 | 281 | #ifndef MICROPY_HW_ENABLE_MDNS_RESPONDER 282 | #define MICROPY_HW_ENABLE_MDNS_RESPONDER (1) 283 | #endif 284 | -------------------------------------------------------------------------------- /esp32-cam-1-11-498/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 | MICROPY_PY_USSL = 0 31 | MICROPY_SSL_AXTLS = 0 32 | MICROPY_FATFS = 1 33 | MICROPY_PY_BTREE = 1 34 | 35 | FROZEN_MANIFEST ?= boards/manifest.py 36 | 37 | # include py core make definitions 38 | include $(TOP)/py/py.mk 39 | 40 | GIT_SUBMODULES = lib/berkeley-db-1.xx 41 | 42 | PORT ?= /dev/ttyUSB0 43 | BAUD ?= 460800 44 | FLASH_MODE ?= dio 45 | FLASH_FREQ ?= 40m 46 | FLASH_SIZE ?= 4MB 47 | CROSS_COMPILE ?= xtensa-esp32-elf- 48 | OBJDUMP = $(CROSS_COMPILE)objdump 49 | 50 | SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined 51 | SDKCONFIG_H = $(BUILD)/sdkconfig.h 52 | 53 | # the git hash of the currently supported ESP IDF version 54 | ESPIDF_SUPHASH_V3 := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df 55 | ESPIDF_SUPHASH_V4 := 310beae373446ceb9a4ad9b36b5428d7fdf2705f 56 | 57 | define print_supported_git_hash 58 | $(info Supported git hash (v3.3): $(ESPIDF_SUPHASH_V3)) 59 | $(info Supported git hash (v4.0-beta1) (experimental): $(ESPIDF_SUPHASH_V4)) 60 | endef 61 | 62 | # paths to ESP IDF and its components 63 | ifeq ($(ESPIDF),) 64 | ifneq ($(IDF_PATH),) 65 | ESPIDF = $(IDF_PATH) 66 | else 67 | $(info The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.) 68 | $(info See README.md for installation instructions.) 69 | $(call print_supported_git_hash) 70 | $(error ESPIDF not set) 71 | endif 72 | endif 73 | 74 | ESPCOMP = $(ESPIDF)/components 75 | ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py 76 | ESPCOMP_KCONFIGS = $(shell find $(ESPCOMP) -name Kconfig) 77 | ESPCOMP_KCONFIGS_PROJBUILD = $(shell find $(ESPCOMP) -name Kconfig.projbuild) 78 | 79 | # verify the ESP IDF version 80 | ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H') 81 | 82 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) 83 | $(info Building with ESP IDF v3) 84 | else ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 85 | $(info Building with ESP IDF v4) 86 | 87 | PYPARSING_VERSION = $(shell python3 -c 'import pyparsing; print(pyparsing.__version__)') 88 | ifneq ($(PYPARSING_VERSION),2.3.1) 89 | $(info ** ERROR **) 90 | $(info EDP IDF requires pyparsing version less than 2.4) 91 | $(info You will need to set up a Python virtual environment with pyparsing 2.3.1) 92 | $(info Please see README.md for more information) 93 | $(error Incorrect pyparsing version) 94 | endif 95 | else 96 | $(info ** WARNING **) 97 | $(info The git hash of ESP IDF does not match the supported version) 98 | $(info The build may complete and the firmware may work but it is not guaranteed) 99 | $(info ESP IDF path: $(ESPIDF)) 100 | $(info Current git hash: $(ESPIDF_CURHASH)) 101 | $(call print_supported_git_hash) 102 | endif 103 | 104 | # pretty format of ESP IDF version, used internally by the IDF 105 | IDF_VER := $(shell git -C $(ESPIDF) describe) 106 | 107 | ifeq ($(shell which $(CC) 2> /dev/null),) 108 | $(info ** ERROR **) 109 | $(info Cannot find C compiler $(CC)) 110 | $(info Add the xtensa toolchain to your PATH. See README.md) 111 | $(error C compiler missing) 112 | endif 113 | 114 | # Support BLE by default when building with IDF 4.x. 115 | # Can be explicitly disabled on the command line or board config. 116 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 117 | MICROPY_PY_BLUETOOTH ?= 1 118 | ifeq ($(MICROPY_PY_BLUETOOTH),1) 119 | SDKCONFIG += boards/sdkconfig.ble 120 | MICROPY_BLUETOOTH_NIMBLE = 1 121 | endif 122 | endif 123 | 124 | # include sdkconfig to get needed configuration values 125 | include $(SDKCONFIG) 126 | 127 | ################################################################################ 128 | # Compiler and linker flags 129 | 130 | INC += -I. 131 | INC += -I$(TOP) 132 | INC += -I$(TOP)/lib/mp-readline 133 | INC += -I$(TOP)/lib/netutils 134 | INC += -I$(TOP)/lib/timeutils 135 | INC += -I$(BUILD) 136 | 137 | INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include 138 | INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include_bootloader 139 | INC_ESPCOMP += -I$(ESPCOMP)/console 140 | INC_ESPCOMP += -I$(ESPCOMP)/driver/include 141 | INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver 142 | INC_ESPCOMP += -I$(ESPCOMP)/efuse/include 143 | INC_ESPCOMP += -I$(ESPCOMP)/efuse/esp32/include 144 | INC_ESPCOMP += -I$(ESPCOMP)/esp32/include 145 | INC_ESPCOMP += -I$(ESPCOMP)/espcoredump/include 146 | INC_ESPCOMP += -I$(ESPCOMP)/soc/include 147 | INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include 148 | INC_ESPCOMP += -I$(ESPCOMP)/heap/include 149 | INC_ESPCOMP += -I$(ESPCOMP)/log/include 150 | INC_ESPCOMP += -I$(ESPCOMP)/newlib/platform_include 151 | INC_ESPCOMP += -I$(ESPCOMP)/newlib/include 152 | INC_ESPCOMP += -I$(ESPCOMP)/nvs_flash/include 153 | INC_ESPCOMP += -I$(ESPCOMP)/freertos/include 154 | INC_ESPCOMP += -I$(ESPCOMP)/esp_ringbuf/include 155 | INC_ESPCOMP += -I$(ESPCOMP)/esp_event/include 156 | INC_ESPCOMP += -I$(ESPCOMP)/tcpip_adapter/include 157 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/lwip/src/include 158 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/port/esp32/include 159 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps 160 | INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include 161 | INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include 162 | INC_ESPCOMP += -I$(ESPCOMP)/mdns/include 163 | INC_ESPCOMP += -I$(ESPCOMP)/mdns/private_include 164 | INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include 165 | INC_ESPCOMP += -I$(ESPCOMP)/ulp/include 166 | INC_ESPCOMP += -I$(ESPCOMP)/vfs/include 167 | INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include 168 | INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include 169 | INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/port/include 170 | INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include 171 | INC_ESPCOMP += -I$(ESPCOMP)/app_update/include 172 | INC_ESPCOMP += -I$(ESPCOMP)/pthread/include 173 | INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include 174 | INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include 175 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/driver/include 176 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/driver/private_include 177 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/conversions/include 178 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/conversions/private_include 179 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/sensors/private_include 180 | 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 | endif 227 | 228 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 229 | ifeq ($(MICROPY_PY_BLUETOOTH),1) 230 | CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 231 | CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 232 | 233 | ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) 234 | CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1 235 | endif 236 | endif 237 | endif 238 | 239 | # these flags are common to C and C++ compilation 240 | CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ 241 | -mlongcalls -nostdlib \ 242 | -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable \ 243 | -Wno-error=unused-variable -Wno-error=deprecated-declarations \ 244 | -DESP_PLATFORM 245 | 246 | CFLAGS_BASE = -std=gnu99 $(CFLAGS_COMMON) -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H 247 | CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_ESPCOMP) 248 | CFLAGS += -DIDF_VER=\"$(IDF_VER)\" 249 | CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) 250 | CFLAGS += -I$(BOARD_DIR) 251 | 252 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 253 | CFLAGS += -DMICROPY_ESP_IDF_4=1 254 | endif 255 | 256 | # this is what ESPIDF uses for c++ compilation 257 | CXXFLAGS = -std=gnu++11 $(CFLAGS_COMMON) $(INC) $(INC_ESPCOMP) 258 | 259 | LDFLAGS = -nostdlib -Map=$(@:.elf=.map) --cref 260 | LDFLAGS += --gc-sections -static -EL 261 | LDFLAGS += -u call_user_start_cpu0 -u uxTopUsedPriority -u ld_include_panic_highint_hdl 262 | LDFLAGS += -u __cxa_guard_dummy # so that implementation of static guards is taken from cxx_guards.o instead of libstdc++.a 263 | LDFLAGS += -L$(ESPCOMP)/esp32/ld 264 | LDFLAGS += -L$(ESPCOMP)/esp_rom/esp32/ld 265 | LDFLAGS += -T $(BUILD)/esp32_out.ld 266 | LDFLAGS += -T $(BUILD)/esp32.project.ld 267 | LDFLAGS += -T esp32.rom.ld 268 | LDFLAGS += -T esp32.rom.libgcc.ld 269 | LDFLAGS += -T esp32.peripherals.ld 270 | 271 | LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) 272 | LIBSTDCXX_FILE_NAME = $(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a) 273 | 274 | # Debugging/Optimization 275 | ifeq ($(DEBUG), 1) 276 | CFLAGS += -g 277 | COPT = -O0 278 | else 279 | #CFLAGS += -fdata-sections -ffunction-sections 280 | COPT += -Os -DNDEBUG 281 | #LDFLAGS += --gc-sections 282 | endif 283 | 284 | # Enable SPIRAM support if CONFIG_ESP32_SPIRAM_SUPPORT=y in sdkconfig 285 | ifeq ($(CONFIG_ESP32_SPIRAM_SUPPORT),y) 286 | CFLAGS_COMMON += -mfix-esp32-psram-cache-issue 287 | LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc-psram-workaround.a $(ESPCOMP)/newlib/lib/libm-psram-workaround.a 288 | else 289 | # Additional newlib symbols that can only be used with spiram disabled. 290 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 291 | LDFLAGS += -T esp32.rom.newlib-funcs.ld 292 | LDFLAGS += -T esp32.rom.newlib-locale.ld 293 | LDFLAGS += -T esp32.rom.newlib-data.ld 294 | else 295 | LDFLAGS += -T esp32.rom.spiram_incompatible_fns.ld 296 | endif 297 | LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc.a $(ESPCOMP)/newlib/lib/libm.a 298 | endif 299 | 300 | ################################################################################ 301 | # List of MicroPython source and object files 302 | 303 | SRC_C = \ 304 | main.c \ 305 | uart.c \ 306 | gccollect.c \ 307 | mphalport.c \ 308 | fatfs_port.c \ 309 | help.c \ 310 | modutime.c \ 311 | moduos.c \ 312 | machine_timer.c \ 313 | machine_pin.c \ 314 | machine_touchpad.c \ 315 | machine_adc.c \ 316 | machine_dac.c \ 317 | machine_i2c.c \ 318 | machine_pwm.c \ 319 | machine_uart.c \ 320 | modmachine.c \ 321 | modnetwork.c \ 322 | network_lan.c \ 323 | network_ppp.c \ 324 | nimble.c \ 325 | modsocket.c \ 326 | modesp.c \ 327 | esp32_partition.c \ 328 | esp32_ulp.c \ 329 | modesp32.c \ 330 | espneopixel.c \ 331 | machine_hw_spi.c \ 332 | machine_wdt.c \ 333 | mpthreadport.c \ 334 | machine_rtc.c \ 335 | machine_sdcard.c \ 336 | modcamera.c \ 337 | $(wildcard $(BOARD_DIR)/*.c) \ 338 | $(SRC_MOD) 339 | 340 | EXTMOD_SRC_C = $(addprefix extmod/,\ 341 | modonewire.c \ 342 | modbluetooth_nimble.c \ 343 | ) 344 | 345 | LIB_SRC_C = $(addprefix lib/,\ 346 | mp-readline/readline.c \ 347 | netutils/netutils.c \ 348 | timeutils/timeutils.c \ 349 | utils/pyexec.c \ 350 | utils/interrupt_char.c \ 351 | utils/sys_stdio_mphal.c \ 352 | ) 353 | 354 | ifeq ($(MICROPY_FATFS), 1) 355 | LIB_SRC_C += \ 356 | lib/oofatfs/ff.c \ 357 | lib/oofatfs/ffunicode.c 358 | endif 359 | 360 | DRIVERS_SRC_C = $(addprefix drivers/,\ 361 | bus/softspi.c \ 362 | dht/dht.c \ 363 | ) 364 | 365 | OBJ_MP = 366 | OBJ_MP += $(PY_O) 367 | OBJ_MP += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) 368 | OBJ_MP += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) 369 | OBJ_MP += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) 370 | OBJ_MP += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) 371 | 372 | # List of sources for qstr extraction 373 | SRC_QSTR += $(SRC_C) $(EXTMOD_SRC_C) $(LIB_SRC_C) $(DRIVERS_SRC_C) 374 | # Append any auto-generated sources that are needed by sources listed in SRC_QSTR 375 | SRC_QSTR_AUTO_DEPS += 376 | 377 | ################################################################################ 378 | # Generate sdkconfig.h from sdkconfig 379 | 380 | $(SDKCONFIG_COMBINED): $(SDKCONFIG) 381 | $(Q)$(MKDIR) -p $(dir $@) 382 | $(Q)$(CAT) $^ > $@ 383 | 384 | $(SDKCONFIG_H): $(SDKCONFIG_COMBINED) 385 | $(ECHO) "GEN $@" 386 | $(Q)$(MKDIR) -p $(dir $@) 387 | $(Q)$(PYTHON) $(ESPIDF)/tools/kconfig_new/confgen.py \ 388 | --output header $@ \ 389 | --config $< \ 390 | --kconfig $(ESPIDF)/Kconfig \ 391 | --env "IDF_TARGET=esp32" \ 392 | --env "IDF_CMAKE=n" \ 393 | --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ 394 | --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ 395 | --env "IDF_PATH=$(ESPIDF)" 396 | $(Q)touch $@ 397 | 398 | $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) $(BOARD_DIR)/mpconfigboard.h 399 | 400 | ################################################################################ 401 | # List of object files from the ESP32 IDF components 402 | 403 | ESPIDF_BOOTLOADER_SUPPORT_O = $(patsubst %.c,%.o,\ 404 | $(filter-out $(ESPCOMP)/bootloader_support/src/bootloader_init.c,\ 405 | $(wildcard $(ESPCOMP)/bootloader_support/src/*.c) \ 406 | $(wildcard $(ESPCOMP)/bootloader_support/src/idf/*.c) \ 407 | )) 408 | 409 | ESPIDF_DRIVER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/driver/*.c)) 410 | 411 | ESPIDF_EFUSE_O = $(patsubst %.c,%.o,\ 412 | $(wildcard $(ESPCOMP)/efuse/esp32/*.c)\ 413 | $(wildcard $(ESPCOMP)/efuse/src/*.c)\ 414 | ) 415 | 416 | $(BUILD)/$(ESPCOMP)/esp32/dport_access.o: CFLAGS += -Wno-array-bounds 417 | ESPIDF_ESP32_O = \ 418 | $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/*.c)) \ 419 | $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/hwcrypto/*.c)) \ 420 | $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/esp32/*.S)) \ 421 | 422 | ESPIDF_ESP_RINGBUF_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_ringbuf/*.c)) 423 | 424 | ESPIDF_HEAP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/heap/*.c)) 425 | 426 | ESPIDF_SOC_O = $(patsubst %.c,%.o,\ 427 | $(wildcard $(ESPCOMP)/soc/esp32/*.c) \ 428 | $(wildcard $(ESPCOMP)/soc/src/*.c) \ 429 | $(wildcard $(ESPCOMP)/soc/src/hal/*.c) \ 430 | ) 431 | 432 | ESPIDF_CXX_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/cxx/*.cpp)) 433 | 434 | ESPIDF_PTHREAD_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/pthread/*.c)) 435 | 436 | # Assembler .S files need only basic flags, and in particular should not have 437 | # -Os because that generates subtly different code. 438 | # We also need custom CFLAGS for .c files because FreeRTOS has headers with 439 | # generic names (eg queue.h) which can clash with other files in the port. 440 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 441 | 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 442 | else 443 | CFLAGS_ASM = -I$(BUILD) -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I. 444 | endif 445 | $(BUILD)/$(ESPCOMP)/freertos/portasm.o: CFLAGS = $(CFLAGS_ASM) 446 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_context.o: CFLAGS = $(CFLAGS_ASM) 447 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_intr_asm.o: CFLAGS = $(CFLAGS_ASM) 448 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_vectors.o: CFLAGS = $(CFLAGS_ASM) 449 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_vector_defaults.o: CFLAGS = $(CFLAGS_ASM) 450 | $(BUILD)/$(ESPCOMP)/freertos/%.o: CFLAGS = $(CFLAGS_BASE) -I. -I$(BUILD) $(INC_ESPCOMP) -I$(ESPCOMP)/freertos/include/freertos -D_ESP_FREERTOS_INTERNAL 451 | ESPIDF_FREERTOS_O = \ 452 | $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/freertos/*.c)) \ 453 | $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/freertos/*.S)) \ 454 | 455 | ESPIDF_VFS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/vfs/*.c)) 456 | 457 | ESPIDF_LOG_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/log/*.c)) 458 | 459 | ESPIDF_XTENSA_DEBUG_MODULE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/xtensa-debug-module/*.c)) 460 | 461 | ESPIDF_TCPIP_ADAPTER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/tcpip_adapter/*.c)) 462 | 463 | ESPIDF_APP_TRACE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_trace/*.c)) 464 | 465 | ESPIDF_APP_UPDATE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_update/*.c)) 466 | 467 | ESPIDF_NEWLIB_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/newlib/*.c)) 468 | 469 | ESPIDF_NVS_FLASH_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/nvs_flash/src/*.cpp)) 470 | 471 | ESPIDF_SMARTCONFIG_ACK_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/smartconfig_ack/*.c)) 472 | 473 | ESPIDF_SPI_FLASH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/spi_flash/*.c)) 474 | 475 | ESPIDF_ULP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/ulp/*.c)) 476 | 477 | $(BUILD)/$(ESPCOMP)/lwip/%.o: CFLAGS += -Wno-address -Wno-unused-variable -Wno-unused-but-set-variable 478 | ESPIDF_LWIP_O = $(patsubst %.c,%.o,\ 479 | $(wildcard $(ESPCOMP)/lwip/apps/dhcpserver/*.c) \ 480 | $(wildcard $(ESPCOMP)/lwip/lwip/src/api/*.c) \ 481 | $(wildcard $(ESPCOMP)/lwip/lwip/src/apps/sntp/*.c) \ 482 | $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*.c) \ 483 | $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*/*.c) \ 484 | $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*.c) \ 485 | $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*.c) \ 486 | $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*/*.c) \ 487 | $(wildcard $(ESPCOMP)/lwip/port/esp32/*.c) \ 488 | $(wildcard $(ESPCOMP)/lwip/port/esp32/*/*.c) \ 489 | ) 490 | 491 | ESPIDF_MBEDTLS_O = $(patsubst %.c,%.o,\ 492 | $(wildcard $(ESPCOMP)/mbedtls/mbedtls/library/*.c) \ 493 | $(wildcard $(ESPCOMP)/mbedtls/port/*.c) \ 494 | $(wildcard $(ESPCOMP)/mbedtls/port/esp32/*.c) \ 495 | ) 496 | 497 | ESPIDF_MDNS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/mdns/*.c)) 498 | 499 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 500 | $(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -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 501 | else 502 | $(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 503 | endif 504 | ESPIDF_WPA_SUPPLICANT_O = $(patsubst %.c,%.o,\ 505 | $(wildcard $(ESPCOMP)/wpa_supplicant/port/*.c) \ 506 | $(wildcard $(ESPCOMP)/wpa_supplicant/src/*/*.c) \ 507 | ) 508 | 509 | ESP32_CAM_O = $(patsubst %.c,%.o,\ 510 | $(wildcard $(ESPCOMP)/esp32-camera/driver/*.c) \ 511 | $(wildcard $(ESPCOMP)/esp32-camera/sensors/*.c) \ 512 | $(wildcard $(ESPCOMP)/esp32-camera/conversions/*.c) \ 513 | ) 514 | 515 | ESPIDF_SDMMC_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/sdmmc/*.c)) 516 | 517 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 518 | ESPIDF_ESP_COMMON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_common/src/*.c)) 519 | 520 | ESPIDF_ESP_EVENT_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_event/*.c)) 521 | 522 | ESPIDF_ESP_WIFI_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_wifi/src/*.c)) 523 | 524 | ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) 525 | ESPIDF_BT_NIMBLE_O = $(patsubst %.c,%.o,\ 526 | $(wildcard $(ESPCOMP)/bt/controller/*.c) \ 527 | $(wildcard $(ESPCOMP)/bt/common/btc/core/*.c) \ 528 | $(wildcard $(ESPCOMP)/bt/common/osi/*.c) \ 529 | $(wildcard $(ESPCOMP)/bt/host/nimble/esp-hci/src/*.c) \ 530 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/ext/tinycrypt/src/*.c) \ 531 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ans/src/*.c) \ 532 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/bas/src/*.c) \ 533 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gap/src/*.c) \ 534 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gatt/src/*.c) \ 535 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ias/src/*.c) \ 536 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/lls/src/*.c) \ 537 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/tps/src/*.c) \ 538 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/src/*.c) \ 539 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c) \ 540 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c) \ 541 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/ram/src/*.c) \ 542 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/util/src/*.c) \ 543 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/src/*.c) \ 544 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/nimble/src/*.c) \ 545 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/npl/freertos/src/*.c) \ 546 | ) 547 | endif 548 | 549 | $(BUILD)/$(ESPCOMP)/esp_eth/src/esp_eth_mac_dm9051.o: CFLAGS += -fno-strict-aliasing 550 | ESPIDF_ESP_ETH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_eth/src/*.c)) 551 | 552 | ESPIDF_XTENSA_O = $(patsubst %.c,%.o,\ 553 | $(wildcard $(ESPCOMP)/xtensa/*.c) \ 554 | $(wildcard $(ESPCOMP)/xtensa/esp32/*.c) \ 555 | ) 556 | else 557 | ESPIDF_JSON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/json/cJSON/cJSON*.c)) 558 | 559 | ESPIDF_ETHERNET_O = $(patsubst %.c,%.o,\ 560 | $(wildcard $(ESPCOMP)/ethernet/*.c) \ 561 | $(wildcard $(ESPCOMP)/ethernet/eth_phy/*.c) \ 562 | ) 563 | endif 564 | 565 | OBJ_ESPIDF = 566 | LIB_ESPIDF = 567 | BUILD_ESPIDF_LIB = $(BUILD)/esp-idf 568 | 569 | define gen_espidf_lib_rule 570 | OBJ_ESPIDF += $(addprefix $$(BUILD)/,$(2)) 571 | LIB_ESPIDF += $(1) 572 | $(BUILD_ESPIDF_LIB)/$(1)/lib$(1).a: $(addprefix $$(BUILD)/,$(2)) 573 | $(ECHO) "AR $$@" 574 | $(Q)$(AR) cru $$@ $$^ 575 | endef 576 | 577 | $(eval $(call gen_espidf_lib_rule,bootloader_support,$(ESPIDF_BOOTLOADER_SUPPORT_O))) 578 | $(eval $(call gen_espidf_lib_rule,driver,$(ESPIDF_DRIVER_O))) 579 | $(eval $(call gen_espidf_lib_rule,efuse,$(ESPIDF_EFUSE_O))) 580 | $(eval $(call gen_espidf_lib_rule,esp32,$(ESPIDF_ESP32_O))) 581 | $(eval $(call gen_espidf_lib_rule,esp_ringbuf,$(ESPIDF_ESP_RINGBUF_O))) 582 | $(eval $(call gen_espidf_lib_rule,heap,$(ESPIDF_HEAP_O))) 583 | $(eval $(call gen_espidf_lib_rule,soc,$(ESPIDF_SOC_O))) 584 | $(eval $(call gen_espidf_lib_rule,cxx,$(ESPIDF_CXX_O))) 585 | $(eval $(call gen_espidf_lib_rule,pthread,$(ESPIDF_PTHREAD_O))) 586 | $(eval $(call gen_espidf_lib_rule,freertos,$(ESPIDF_FREERTOS_O))) 587 | $(eval $(call gen_espidf_lib_rule,vfs,$(ESPIDF_VFS_O))) 588 | $(eval $(call gen_espidf_lib_rule,json,$(ESPIDF_JSON_O))) 589 | $(eval $(call gen_espidf_lib_rule,log,$(ESPIDF_LOG_O))) 590 | $(eval $(call gen_espidf_lib_rule,xtensa-debug-module,$(ESPIDF_XTENSA_DEBUG_MODULE_O))) 591 | $(eval $(call gen_espidf_lib_rule,tcpip_adapter,$(ESPIDF_TCPIP_ADAPTER_O))) 592 | $(eval $(call gen_espidf_lib_rule,app_trace,$(ESPIDF_APP_TRACE_O))) 593 | $(eval $(call gen_espidf_lib_rule,app_update,$(ESPIDF_APP_UPDATE_O))) 594 | $(eval $(call gen_espidf_lib_rule,newlib,$(ESPIDF_NEWLIB_O))) 595 | $(eval $(call gen_espidf_lib_rule,nvs_flash,$(ESPIDF_NVS_FLASH_O))) 596 | $(eval $(call gen_espidf_lib_rule,smartconfig_ack,$(ESPIDF_SMARTCONFIG_ACK_O))) 597 | $(eval $(call gen_espidf_lib_rule,spi_flash,$(ESPIDF_SPI_FLASH_O))) 598 | $(eval $(call gen_espidf_lib_rule,ulp,$(ESPIDF_ULP_O))) 599 | $(eval $(call gen_espidf_lib_rule,lwip,$(ESPIDF_LWIP_O))) 600 | $(eval $(call gen_espidf_lib_rule,mbedtls,$(ESPIDF_MBEDTLS_O))) 601 | $(eval $(call gen_espidf_lib_rule,mdns,$(ESPIDF_MDNS_O))) 602 | $(eval $(call gen_espidf_lib_rule,wpa_supplicant,$(ESPIDF_WPA_SUPPLICANT_O))) 603 | $(eval $(call gen_espidf_lib_rule,sdmmc,$(ESPIDF_SDMMC_O))) 604 | $(eval $(call gen_espidf_lib_rule,esp32_cam,$(ESP32_CAM_O))) 605 | 606 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 607 | $(eval $(call gen_espidf_lib_rule,esp_common,$(ESPIDF_ESP_COMMON_O))) 608 | $(eval $(call gen_espidf_lib_rule,esp_event,$(ESPIDF_ESP_EVENT_O))) 609 | $(eval $(call gen_espidf_lib_rule,esp_wifi,$(ESPIDF_ESP_WIFI_O))) 610 | ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) 611 | $(eval $(call gen_espidf_lib_rule,bt_nimble,$(ESPIDF_BT_NIMBLE_O))) 612 | endif 613 | $(eval $(call gen_espidf_lib_rule,esp_eth,$(ESPIDF_ESP_ETH_O))) 614 | $(eval $(call gen_espidf_lib_rule,xtensa,$(ESPIDF_XTENSA_O))) 615 | else 616 | $(eval $(call gen_espidf_lib_rule,ethernet,$(ESPIDF_ETHERNET_O))) 617 | endif 618 | 619 | # Create all destination build dirs before compiling IDF source 620 | OBJ_ESPIDF_DIRS = $(sort $(dir $(OBJ_ESPIDF))) $(BUILD_ESPIDF_LIB) $(addprefix $(BUILD_ESPIDF_LIB)/,$(LIB_ESPIDF)) 621 | $(OBJ_ESPIDF): | $(OBJ_ESPIDF_DIRS) 622 | $(OBJ_ESPIDF_DIRS): 623 | $(MKDIR) -p $@ 624 | 625 | # Make all IDF object files depend on sdkconfig 626 | $(OBJ_ESPIDF): $(SDKCONFIG_H) 627 | 628 | # Add all IDF components to the set of libraries 629 | LIB = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) 630 | 631 | ################################################################################ 632 | # ESP IDF ldgen 633 | 634 | LDGEN_FRAGMENTS = $(shell find $(ESPCOMP) -name "*.lf") 635 | 636 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 637 | 638 | LDGEN_LIBRARIES=$(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) 639 | 640 | $(BUILD_ESPIDF_LIB)/ldgen_libraries: $(LDGEN_LIBRARIES) $(ESPIDF)/make/ldgen.mk 641 | printf "$(foreach library,$(LDGEN_LIBRARIES),$(library)\n)" > $(BUILD_ESPIDF_LIB)/ldgen_libraries 642 | 643 | $(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(BUILD_ESPIDF_LIB)/ldgen_libraries 644 | $(ECHO) "GEN $@" 645 | $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ 646 | --input $< \ 647 | --output $@ \ 648 | --config $(SDKCONFIG_COMBINED) \ 649 | --kconfig $(ESPIDF)/Kconfig \ 650 | --fragments $(LDGEN_FRAGMENTS) \ 651 | --libraries-file $(BUILD_ESPIDF_LIB)/ldgen_libraries \ 652 | --env "IDF_TARGET=esp32" \ 653 | --env "IDF_CMAKE=n" \ 654 | --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ 655 | --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ 656 | --env "IDF_PATH=$(ESPIDF)" \ 657 | --objdump $(OBJDUMP) 658 | 659 | else 660 | 661 | LDGEN_SECTIONS_INFO = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a.sections_info) 662 | LDGEN_SECTION_INFOS = $(BUILD_ESPIDF_LIB)/ldgen.section_infos 663 | 664 | define gen_sections_info_rule 665 | $(1).sections_info: $(1) 666 | $(ECHO) "GEN $(1).sections_info" 667 | $(Q)$(OBJDUMP) -h $(1) > $(1).sections_info 668 | endef 669 | 670 | $(eval $(foreach lib,$(LIB_ESPIDF),$(eval $(call gen_sections_info_rule,$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a)))) 671 | 672 | $(LDGEN_SECTION_INFOS): $(LDGEN_SECTIONS_INFO) $(ESPIDF)/make/ldgen.mk 673 | $(Q)printf "$(foreach info,$(LDGEN_SECTIONS_INFO),$(info)\n)" > $@ 674 | 675 | $(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(LDGEN_SECTION_INFOS) 676 | $(ECHO) "GEN $@" 677 | $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ 678 | --input $< \ 679 | --output $@ \ 680 | --config $(SDKCONFIG_COMBINED) \ 681 | --kconfig $(ESPIDF)/Kconfig \ 682 | --fragments $(LDGEN_FRAGMENTS) \ 683 | --sections $(LDGEN_SECTION_INFOS) \ 684 | --env "IDF_TARGET=esp32" \ 685 | --env "IDF_CMAKE=n" \ 686 | --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ 687 | --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ 688 | --env "IDF_PATH=$(ESPIDF)" 689 | 690 | endif 691 | 692 | ################################################################################ 693 | # Main targets 694 | 695 | all: $(BUILD)/firmware.bin 696 | 697 | .PHONY: idf-version deploy erase 698 | 699 | idf-version: 700 | $(ECHO) "ESP IDF supported hash: $(ESPIDF_SUPHASH)" 701 | 702 | $(BUILD)/firmware.bin: $(BUILD)/bootloader.bin $(BUILD)/partitions.bin $(BUILD)/application.bin 703 | $(ECHO) "Create $@" 704 | $(Q)$(PYTHON) makeimg.py $^ $@ 705 | 706 | deploy: $(BUILD)/firmware.bin 707 | $(ECHO) "Writing $^ to the board" 708 | $(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) write_flash -z --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) 0x1000 $^ 709 | 710 | erase: 711 | $(ECHO) "Erasing flash" 712 | $(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) erase_flash 713 | 714 | ################################################################################ 715 | # Declarations to build the application 716 | 717 | OBJ = $(OBJ_MP) 718 | 719 | APP_LD_ARGS = 720 | APP_LD_ARGS += $(LDFLAGS_MOD) 721 | APP_LD_ARGS += $(addprefix -T,$(LD_FILES)) 722 | APP_LD_ARGS += --start-group 723 | APP_LD_ARGS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc 724 | APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++ 725 | APP_LD_ARGS += $(LIBC_LIBM) 726 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 727 | APP_LD_ARGS += -L$(ESPCOMP)/xtensa/esp32 -lhal 728 | APP_LD_ARGS += -L$(ESPCOMP)/bt/controller/lib -lbtdm_app 729 | APP_LD_ARGS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lsmartconfig -lcoexist 730 | else 731 | APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a 732 | APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lwpa -lsmartconfig -lcoexist -lwps -lwpa2 733 | endif 734 | APP_LD_ARGS += $(OBJ) 735 | APP_LD_ARGS += $(LIB) 736 | APP_LD_ARGS += --end-group 737 | 738 | $(BUILD)/esp32_out.ld: $(SDKCONFIG_H) 739 | $(Q)$(CC) -I$(BUILD) -C -P -x c -E $(ESPCOMP)/esp32/ld/esp32.ld -o $@ 740 | 741 | $(BUILD)/application.bin: $(BUILD)/application.elf 742 | $(ECHO) "Create $@" 743 | $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< 744 | 745 | $(BUILD)/application.elf: $(OBJ) $(LIB) $(BUILD)/esp32_out.ld $(BUILD)/esp32.project.ld 746 | $(ECHO) "LINK $@" 747 | $(Q)$(LD) $(LDFLAGS) -o $@ $(APP_LD_ARGS) 748 | $(Q)$(SIZE) $@ 749 | 750 | define compile_cxx 751 | $(ECHO) "CXX $<" 752 | $(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $< 753 | @# The following fixes the dependency file. 754 | @# See http://make.paulandlesley.org/autodep.html for details. 755 | @# Regex adjusted from the above to play better with Windows paths, etc. 756 | @$(CP) $(@:.o=.d) $(@:.o=.P); \ 757 | $(SED) -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' \ 758 | -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ 759 | $(RM) -f $(@:.o=.d) 760 | endef 761 | 762 | vpath %.cpp . $(TOP) 763 | $(BUILD)/%.o: %.cpp 764 | $(call compile_cxx) 765 | 766 | ################################################################################ 767 | # Declarations to build the bootloader 768 | 769 | BOOTLOADER_LIB_DIR = $(BUILD)/bootloader 770 | BOOTLOADER_LIB_ALL = 771 | 772 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 773 | $(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 \ 774 | -I$(ESPCOMP)/esp_common/include \ 775 | -I$(ESPCOMP)/xtensa/include \ 776 | -I$(ESPCOMP)/xtensa/esp32/include 777 | else 778 | $(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 779 | endif 780 | 781 | # libbootloader_support.a 782 | BOOTLOADER_LIB_ALL += bootloader_support 783 | BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 784 | bootloader_support/src/bootloader_clock.o \ 785 | bootloader_support/src/bootloader_common.o \ 786 | bootloader_support/src/bootloader_flash.o \ 787 | bootloader_support/src/bootloader_init.o \ 788 | bootloader_support/src/bootloader_random.o \ 789 | bootloader_support/src/bootloader_utility.o \ 790 | bootloader_support/src/flash_qio_mode.o \ 791 | bootloader_support/src/esp_image_format.o \ 792 | bootloader_support/src/flash_encrypt.o \ 793 | bootloader_support/src/flash_partitions.o \ 794 | ) 795 | 796 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 797 | BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 798 | bootloader_support/src/esp32/bootloader_sha.o \ 799 | bootloader_support/src/bootloader_flash_config.o \ 800 | bootloader_support/src/esp32/secure_boot.o \ 801 | ) 802 | else 803 | BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 804 | bootloader_support/src/bootloader_sha.o \ 805 | bootloader_support/src/secure_boot_signatures.o \ 806 | bootloader_support/src/secure_boot.o \ 807 | ) 808 | endif 809 | 810 | $(BOOTLOADER_LIB_DIR)/libbootloader_support.a: $(BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ) 811 | $(ECHO) "AR $@" 812 | $(Q)$(AR) cr $@ $^ 813 | 814 | # liblog.a 815 | BOOTLOADER_LIB_ALL += log 816 | BOOTLOADER_LIB_LOG_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 817 | log/log.o \ 818 | ) 819 | $(BOOTLOADER_LIB_DIR)/liblog.a: $(BOOTLOADER_LIB_LOG_OBJ) 820 | $(ECHO) "AR $@" 821 | $(Q)$(AR) cr $@ $^ 822 | 823 | # libspi_flash.a 824 | BOOTLOADER_LIB_ALL += spi_flash 825 | BOOTLOADER_LIB_SPI_FLASH_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 826 | spi_flash/spi_flash_rom_patch.o \ 827 | ) 828 | $(BOOTLOADER_LIB_DIR)/libspi_flash.a: $(BOOTLOADER_LIB_SPI_FLASH_OBJ) 829 | $(ECHO) "AR $@" 830 | $(Q)$(AR) cr $@ $^ 831 | 832 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) 833 | # libmicro-ecc.a 834 | BOOTLOADER_LIB_ALL += micro-ecc 835 | BOOTLOADER_LIB_MICRO_ECC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 836 | micro-ecc/micro-ecc/uECC.o \ 837 | ) 838 | $(BOOTLOADER_LIB_DIR)/libmicro-ecc.a: $(BOOTLOADER_LIB_MICRO_ECC_OBJ) 839 | $(ECHO) "AR $@" 840 | $(Q)$(AR) cr $@ $^ 841 | endif 842 | 843 | # libsoc.a 844 | $(BUILD)/bootloader/$(ESPCOMP)/soc/esp32/rtc_clk.o: CFLAGS += -fno-jump-tables -fno-tree-switch-conversion 845 | BOOTLOADER_LIB_ALL += soc 846 | BOOTLOADER_LIB_SOC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/soc/,\ 847 | esp32/cpu_util.o \ 848 | esp32/gpio_periph.o \ 849 | esp32/rtc_clk.o \ 850 | esp32/rtc_clk_init.o \ 851 | esp32/rtc_init.o \ 852 | esp32/rtc_periph.o \ 853 | esp32/rtc_pm.o \ 854 | esp32/rtc_sleep.o \ 855 | esp32/rtc_time.o \ 856 | esp32/rtc_wdt.o \ 857 | esp32/sdio_slave_periph.o \ 858 | esp32/sdmmc_periph.o \ 859 | esp32/soc_memory_layout.o \ 860 | esp32/spi_periph.o \ 861 | src/memory_layout_utils.o \ 862 | ) 863 | $(BOOTLOADER_LIB_DIR)/libsoc.a: $(BOOTLOADER_LIB_SOC_OBJ) 864 | $(ECHO) "AR $@" 865 | $(Q)$(AR) cr $@ $^ 866 | 867 | # libmain.a 868 | BOOTLOADER_LIB_ALL += main 869 | BOOTLOADER_LIB_MAIN_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 870 | bootloader/subproject/main/bootloader_start.o \ 871 | ) 872 | $(BOOTLOADER_LIB_DIR)/libmain.a: $(BOOTLOADER_LIB_MAIN_OBJ) 873 | $(ECHO) "AR $@" 874 | $(Q)$(AR) cr $@ $^ 875 | 876 | # all objects files 877 | BOOTLOADER_OBJ_ALL = \ 878 | $(BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ) \ 879 | $(BOOTLOADER_LIB_LOG_OBJ) \ 880 | $(BOOTLOADER_LIB_SPI_FLASH_OBJ) \ 881 | $(BOOTLOADER_LIB_MICRO_ECC_OBJ) \ 882 | $(BOOTLOADER_LIB_SOC_OBJ) \ 883 | $(BOOTLOADER_LIB_MAIN_OBJ) 884 | 885 | $(BOOTLOADER_OBJ_ALL): $(SDKCONFIG_H) 886 | 887 | BOOTLOADER_LIBS = 888 | BOOTLOADER_LIBS += -Wl,--start-group 889 | BOOTLOADER_LIBS += $(BOOTLOADER_OBJ) 890 | BOOTLOADER_LIBS += -L$(BUILD)/bootloader $(addprefix -l,$(BOOTLOADER_LIB_ALL)) 891 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 892 | BOOTLOADER_LIBS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lrtc 893 | else 894 | BOOTLOADER_LIBS += -L$(ESPCOMP)/esp32/lib -lrtc 895 | endif 896 | BOOTLOADER_LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc 897 | BOOTLOADER_LIBS += -Wl,--end-group 898 | 899 | BOOTLOADER_LDFLAGS = 900 | BOOTLOADER_LDFLAGS += -nostdlib 901 | BOOTLOADER_LDFLAGS += -L$(ESPIDF)/lib 902 | BOOTLOADER_LDFLAGS += -L$(ESPIDF)/ld 903 | BOOTLOADER_LDFLAGS += -u call_user_start_cpu0 904 | BOOTLOADER_LDFLAGS += -Wl,--gc-sections 905 | BOOTLOADER_LDFLAGS += -static 906 | BOOTLOADER_LDFLAGS += -Wl,-EL 907 | BOOTLOADER_LDFLAGS += -Wl,-Map=$(@:.elf=.map) -Wl,--cref 908 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.ld 909 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.rom.ld 910 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 911 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.ld 912 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld 913 | else 914 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.ld 915 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.spiram_incompatible_fns.ld 916 | endif 917 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.peripherals.ld 918 | 919 | BOOTLOADER_OBJ_DIRS = $(sort $(dir $(BOOTLOADER_OBJ_ALL))) 920 | $(BOOTLOADER_OBJ_ALL): | $(BOOTLOADER_OBJ_DIRS) 921 | $(BOOTLOADER_OBJ_DIRS): 922 | $(MKDIR) -p $@ 923 | 924 | $(BUILD)/bootloader/%.o: %.c 925 | $(call compile_c) 926 | 927 | $(BUILD)/bootloader.bin: $(BUILD)/bootloader.elf 928 | $(ECHO) "Create $@" 929 | $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< 930 | 931 | $(BUILD)/bootloader.elf: $(BOOTLOADER_OBJ) $(addprefix $(BOOTLOADER_LIB_DIR)/lib,$(addsuffix .a,$(BOOTLOADER_LIB_ALL))) 932 | $(ECHO) "LINK $@" 933 | $(Q)$(CC) $(BOOTLOADER_LDFLAGS) -o $@ $(BOOTLOADER_LIBS) 934 | 935 | ################################################################################ 936 | # Declarations to build the partitions 937 | 938 | PYTHON2 ?= python2 939 | 940 | # Can be overriden by mkconfigboard.mk. 941 | PART_SRC ?= partitions.csv 942 | 943 | $(BUILD)/partitions.bin: $(PART_SRC) 944 | $(ECHO) "Create $@" 945 | $(Q)$(PYTHON2) $(ESPCOMP)/partition_table/gen_esp32part.py -q $< $@ 946 | 947 | ################################################################################ 948 | 949 | include $(TOP)/py/mkrules.mk 950 | -------------------------------------------------------------------------------- /esp32-cam-1-11-571/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 | MICROPY_PY_USSL = 0 31 | MICROPY_SSL_AXTLS = 0 32 | MICROPY_FATFS = 1 33 | MICROPY_PY_BTREE = 1 34 | 35 | FROZEN_MANIFEST ?= boards/manifest.py 36 | 37 | # include py core make definitions 38 | include $(TOP)/py/py.mk 39 | 40 | GIT_SUBMODULES = lib/berkeley-db-1.xx 41 | 42 | PORT ?= /dev/ttyUSB0 43 | BAUD ?= 460800 44 | FLASH_MODE ?= dio 45 | FLASH_FREQ ?= 40m 46 | FLASH_SIZE ?= 4MB 47 | CROSS_COMPILE ?= xtensa-esp32-elf- 48 | OBJDUMP = $(CROSS_COMPILE)objdump 49 | 50 | SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined 51 | SDKCONFIG_H = $(BUILD)/sdkconfig.h 52 | 53 | # the git hash of the currently supported ESP IDF version 54 | ESPIDF_SUPHASH_V3 := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df 55 | ESPIDF_SUPHASH_V4 := 310beae373446ceb9a4ad9b36b5428d7fdf2705f 56 | 57 | define print_supported_git_hash 58 | $(info Supported git hash (v3.3): $(ESPIDF_SUPHASH_V3)) 59 | $(info Supported git hash (v4.0-beta1) (experimental): $(ESPIDF_SUPHASH_V4)) 60 | endef 61 | 62 | # paths to ESP IDF and its components 63 | ifeq ($(ESPIDF),) 64 | ifneq ($(IDF_PATH),) 65 | ESPIDF = $(IDF_PATH) 66 | else 67 | $(info The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.) 68 | $(info See README.md for installation instructions.) 69 | $(call print_supported_git_hash) 70 | $(error ESPIDF not set) 71 | endif 72 | endif 73 | 74 | ESPCOMP = $(ESPIDF)/components 75 | ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py 76 | ESPCOMP_KCONFIGS = $(shell find $(ESPCOMP) -name Kconfig) 77 | ESPCOMP_KCONFIGS_PROJBUILD = $(shell find $(ESPCOMP) -name Kconfig.projbuild) 78 | 79 | # verify the ESP IDF version 80 | ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H') 81 | 82 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) 83 | $(info Building with ESP IDF v3) 84 | else ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 85 | $(info Building with ESP IDF v4) 86 | 87 | PYPARSING_VERSION = $(shell python3 -c 'import pyparsing; print(pyparsing.__version__)') 88 | ifneq ($(PYPARSING_VERSION),2.3.1) 89 | $(info ** ERROR **) 90 | $(info EDP IDF requires pyparsing version less than 2.4) 91 | $(info You will need to set up a Python virtual environment with pyparsing 2.3.1) 92 | $(info Please see README.md for more information) 93 | $(error Incorrect pyparsing version) 94 | endif 95 | else 96 | $(info ** WARNING **) 97 | $(info The git hash of ESP IDF does not match the supported version) 98 | $(info The build may complete and the firmware may work but it is not guaranteed) 99 | $(info ESP IDF path: $(ESPIDF)) 100 | $(info Current git hash: $(ESPIDF_CURHASH)) 101 | $(call print_supported_git_hash) 102 | endif 103 | 104 | # pretty format of ESP IDF version, used internally by the IDF 105 | IDF_VER := $(shell git -C $(ESPIDF) describe) 106 | 107 | ifeq ($(shell which $(CC) 2> /dev/null),) 108 | $(info ** ERROR **) 109 | $(info Cannot find C compiler $(CC)) 110 | $(info Add the xtensa toolchain to your PATH. See README.md) 111 | $(error C compiler missing) 112 | endif 113 | 114 | # Support BLE by default when building with IDF 4.x. 115 | # Can be explicitly disabled on the command line or board config. 116 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 117 | MICROPY_PY_BLUETOOTH ?= 1 118 | ifeq ($(MICROPY_PY_BLUETOOTH),1) 119 | SDKCONFIG += boards/sdkconfig.ble 120 | MICROPY_BLUETOOTH_NIMBLE = 1 121 | endif 122 | endif 123 | 124 | # include sdkconfig to get needed configuration values 125 | include $(SDKCONFIG) 126 | 127 | ################################################################################ 128 | # Compiler and linker flags 129 | 130 | INC += -I. 131 | INC += -I$(TOP) 132 | INC += -I$(TOP)/lib/mp-readline 133 | INC += -I$(TOP)/lib/netutils 134 | INC += -I$(TOP)/lib/timeutils 135 | INC += -I$(BUILD) 136 | 137 | INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include 138 | INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include_bootloader 139 | INC_ESPCOMP += -I$(ESPCOMP)/console 140 | INC_ESPCOMP += -I$(ESPCOMP)/driver/include 141 | INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver 142 | INC_ESPCOMP += -I$(ESPCOMP)/efuse/include 143 | INC_ESPCOMP += -I$(ESPCOMP)/efuse/esp32/include 144 | INC_ESPCOMP += -I$(ESPCOMP)/esp32/include 145 | INC_ESPCOMP += -I$(ESPCOMP)/espcoredump/include 146 | INC_ESPCOMP += -I$(ESPCOMP)/soc/include 147 | INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include 148 | INC_ESPCOMP += -I$(ESPCOMP)/heap/include 149 | INC_ESPCOMP += -I$(ESPCOMP)/log/include 150 | INC_ESPCOMP += -I$(ESPCOMP)/newlib/platform_include 151 | INC_ESPCOMP += -I$(ESPCOMP)/newlib/include 152 | INC_ESPCOMP += -I$(ESPCOMP)/nvs_flash/include 153 | INC_ESPCOMP += -I$(ESPCOMP)/freertos/include 154 | INC_ESPCOMP += -I$(ESPCOMP)/esp_ringbuf/include 155 | INC_ESPCOMP += -I$(ESPCOMP)/esp_event/include 156 | INC_ESPCOMP += -I$(ESPCOMP)/tcpip_adapter/include 157 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/lwip/src/include 158 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/port/esp32/include 159 | INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps 160 | INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include 161 | INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include 162 | INC_ESPCOMP += -I$(ESPCOMP)/mdns/include 163 | INC_ESPCOMP += -I$(ESPCOMP)/mdns/private_include 164 | INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include 165 | INC_ESPCOMP += -I$(ESPCOMP)/ulp/include 166 | INC_ESPCOMP += -I$(ESPCOMP)/vfs/include 167 | INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include 168 | INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include 169 | INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/port/include 170 | INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include 171 | INC_ESPCOMP += -I$(ESPCOMP)/app_update/include 172 | INC_ESPCOMP += -I$(ESPCOMP)/pthread/include 173 | INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include 174 | INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include 175 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/driver/include 176 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/driver/private_include 177 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/conversions/include 178 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/conversions/private_include 179 | INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/sensors/private_include 180 | 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 | endif 227 | 228 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 229 | ifeq ($(MICROPY_PY_BLUETOOTH),1) 230 | CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 231 | CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 232 | 233 | ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) 234 | CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1 235 | endif 236 | endif 237 | endif 238 | 239 | # these flags are common to C and C++ compilation 240 | CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ 241 | -mlongcalls -nostdlib \ 242 | -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable \ 243 | -Wno-error=unused-variable -Wno-error=deprecated-declarations \ 244 | -DESP_PLATFORM 245 | 246 | CFLAGS_BASE = -std=gnu99 $(CFLAGS_COMMON) -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H 247 | CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_ESPCOMP) 248 | CFLAGS += -DIDF_VER=\"$(IDF_VER)\" 249 | CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) 250 | CFLAGS += -I$(BOARD_DIR) 251 | 252 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 253 | CFLAGS += -DMICROPY_ESP_IDF_4=1 254 | endif 255 | 256 | # this is what ESPIDF uses for c++ compilation 257 | CXXFLAGS = -std=gnu++11 $(CFLAGS_COMMON) $(INC) $(INC_ESPCOMP) 258 | 259 | LDFLAGS = -nostdlib -Map=$(@:.elf=.map) --cref 260 | LDFLAGS += --gc-sections -static -EL 261 | LDFLAGS += -u call_user_start_cpu0 -u uxTopUsedPriority -u ld_include_panic_highint_hdl 262 | LDFLAGS += -u __cxa_guard_dummy # so that implementation of static guards is taken from cxx_guards.o instead of libstdc++.a 263 | LDFLAGS += -L$(ESPCOMP)/esp32/ld 264 | LDFLAGS += -L$(ESPCOMP)/esp_rom/esp32/ld 265 | LDFLAGS += -T $(BUILD)/esp32_out.ld 266 | LDFLAGS += -T $(BUILD)/esp32.project.ld 267 | LDFLAGS += -T esp32.rom.ld 268 | LDFLAGS += -T esp32.rom.libgcc.ld 269 | LDFLAGS += -T esp32.peripherals.ld 270 | 271 | LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) 272 | LIBSTDCXX_FILE_NAME = $(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a) 273 | 274 | # Debugging/Optimization 275 | ifeq ($(DEBUG), 1) 276 | CFLAGS += -g 277 | COPT = -O0 278 | else 279 | #CFLAGS += -fdata-sections -ffunction-sections 280 | COPT += -Os -DNDEBUG 281 | #LDFLAGS += --gc-sections 282 | endif 283 | 284 | # Enable SPIRAM support if CONFIG_ESP32_SPIRAM_SUPPORT=y in sdkconfig 285 | ifeq ($(CONFIG_ESP32_SPIRAM_SUPPORT),y) 286 | CFLAGS_COMMON += -mfix-esp32-psram-cache-issue 287 | LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc-psram-workaround.a $(ESPCOMP)/newlib/lib/libm-psram-workaround.a 288 | else 289 | # Additional newlib symbols that can only be used with spiram disabled. 290 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 291 | LDFLAGS += -T esp32.rom.newlib-funcs.ld 292 | LDFLAGS += -T esp32.rom.newlib-locale.ld 293 | LDFLAGS += -T esp32.rom.newlib-data.ld 294 | else 295 | LDFLAGS += -T esp32.rom.spiram_incompatible_fns.ld 296 | endif 297 | LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc.a $(ESPCOMP)/newlib/lib/libm.a 298 | endif 299 | 300 | ################################################################################ 301 | # List of MicroPython source and object files 302 | 303 | SRC_C = \ 304 | main.c \ 305 | uart.c \ 306 | gccollect.c \ 307 | mphalport.c \ 308 | fatfs_port.c \ 309 | help.c \ 310 | modutime.c \ 311 | moduos.c \ 312 | machine_timer.c \ 313 | machine_pin.c \ 314 | machine_touchpad.c \ 315 | machine_adc.c \ 316 | machine_dac.c \ 317 | machine_i2c.c \ 318 | machine_pwm.c \ 319 | machine_uart.c \ 320 | modmachine.c \ 321 | modnetwork.c \ 322 | network_lan.c \ 323 | network_ppp.c \ 324 | nimble.c \ 325 | modsocket.c \ 326 | modesp.c \ 327 | esp32_partition.c \ 328 | esp32_ulp.c \ 329 | modesp32.c \ 330 | espneopixel.c \ 331 | machine_hw_spi.c \ 332 | machine_wdt.c \ 333 | mpthreadport.c \ 334 | machine_rtc.c \ 335 | machine_sdcard.c \ 336 | modcamera.c \ 337 | $(wildcard $(BOARD_DIR)/*.c) \ 338 | $(SRC_MOD) 339 | 340 | EXTMOD_SRC_C = $(addprefix extmod/,\ 341 | modonewire.c \ 342 | modbluetooth_nimble.c \ 343 | ) 344 | 345 | LIB_SRC_C = $(addprefix lib/,\ 346 | mp-readline/readline.c \ 347 | netutils/netutils.c \ 348 | timeutils/timeutils.c \ 349 | utils/pyexec.c \ 350 | utils/interrupt_char.c \ 351 | utils/sys_stdio_mphal.c \ 352 | ) 353 | 354 | ifeq ($(MICROPY_FATFS), 1) 355 | LIB_SRC_C += \ 356 | lib/oofatfs/ff.c \ 357 | lib/oofatfs/ffunicode.c 358 | endif 359 | 360 | DRIVERS_SRC_C = $(addprefix drivers/,\ 361 | bus/softspi.c \ 362 | dht/dht.c \ 363 | ) 364 | 365 | OBJ_MP = 366 | OBJ_MP += $(PY_O) 367 | OBJ_MP += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) 368 | OBJ_MP += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) 369 | OBJ_MP += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) 370 | OBJ_MP += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) 371 | 372 | # List of sources for qstr extraction 373 | SRC_QSTR += $(SRC_C) $(EXTMOD_SRC_C) $(LIB_SRC_C) $(DRIVERS_SRC_C) 374 | # Append any auto-generated sources that are needed by sources listed in SRC_QSTR 375 | SRC_QSTR_AUTO_DEPS += 376 | 377 | ################################################################################ 378 | # Generate sdkconfig.h from sdkconfig 379 | 380 | $(SDKCONFIG_COMBINED): $(SDKCONFIG) 381 | $(Q)$(MKDIR) -p $(dir $@) 382 | $(Q)$(CAT) $^ > $@ 383 | 384 | $(SDKCONFIG_H): $(SDKCONFIG_COMBINED) 385 | $(ECHO) "GEN $@" 386 | $(Q)$(MKDIR) -p $(dir $@) 387 | $(Q)$(PYTHON) $(ESPIDF)/tools/kconfig_new/confgen.py \ 388 | --output header $@ \ 389 | --config $< \ 390 | --kconfig $(ESPIDF)/Kconfig \ 391 | --env "IDF_TARGET=esp32" \ 392 | --env "IDF_CMAKE=n" \ 393 | --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ 394 | --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ 395 | --env "IDF_PATH=$(ESPIDF)" 396 | $(Q)touch $@ 397 | 398 | $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) $(BOARD_DIR)/mpconfigboard.h 399 | 400 | ################################################################################ 401 | # List of object files from the ESP32 IDF components 402 | 403 | ESPIDF_BOOTLOADER_SUPPORT_O = $(patsubst %.c,%.o,\ 404 | $(filter-out $(ESPCOMP)/bootloader_support/src/bootloader_init.c,\ 405 | $(wildcard $(ESPCOMP)/bootloader_support/src/*.c) \ 406 | $(wildcard $(ESPCOMP)/bootloader_support/src/idf/*.c) \ 407 | )) 408 | 409 | ESPIDF_DRIVER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/driver/*.c)) 410 | 411 | ESPIDF_EFUSE_O = $(patsubst %.c,%.o,\ 412 | $(wildcard $(ESPCOMP)/efuse/esp32/*.c)\ 413 | $(wildcard $(ESPCOMP)/efuse/src/*.c)\ 414 | ) 415 | 416 | $(BUILD)/$(ESPCOMP)/esp32/dport_access.o: CFLAGS += -Wno-array-bounds 417 | ESPIDF_ESP32_O = \ 418 | $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/*.c)) \ 419 | $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/hwcrypto/*.c)) \ 420 | $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/esp32/*.S)) \ 421 | 422 | ESPIDF_ESP_RINGBUF_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_ringbuf/*.c)) 423 | 424 | ESPIDF_HEAP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/heap/*.c)) 425 | 426 | ESPIDF_SOC_O = $(patsubst %.c,%.o,\ 427 | $(wildcard $(ESPCOMP)/soc/esp32/*.c) \ 428 | $(wildcard $(ESPCOMP)/soc/src/*.c) \ 429 | $(wildcard $(ESPCOMP)/soc/src/hal/*.c) \ 430 | ) 431 | 432 | ESPIDF_CXX_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/cxx/*.cpp)) 433 | 434 | ESPIDF_PTHREAD_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/pthread/*.c)) 435 | 436 | # Assembler .S files need only basic flags, and in particular should not have 437 | # -Os because that generates subtly different code. 438 | # We also need custom CFLAGS for .c files because FreeRTOS has headers with 439 | # generic names (eg queue.h) which can clash with other files in the port. 440 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 441 | 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 442 | else 443 | CFLAGS_ASM = -I$(BUILD) -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I. 444 | endif 445 | $(BUILD)/$(ESPCOMP)/freertos/portasm.o: CFLAGS = $(CFLAGS_ASM) 446 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_context.o: CFLAGS = $(CFLAGS_ASM) 447 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_intr_asm.o: CFLAGS = $(CFLAGS_ASM) 448 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_vectors.o: CFLAGS = $(CFLAGS_ASM) 449 | $(BUILD)/$(ESPCOMP)/freertos/xtensa_vector_defaults.o: CFLAGS = $(CFLAGS_ASM) 450 | $(BUILD)/$(ESPCOMP)/freertos/%.o: CFLAGS = $(CFLAGS_BASE) -I. -I$(BUILD) $(INC_ESPCOMP) -I$(ESPCOMP)/freertos/include/freertos -D_ESP_FREERTOS_INTERNAL 451 | ESPIDF_FREERTOS_O = \ 452 | $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/freertos/*.c)) \ 453 | $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/freertos/*.S)) \ 454 | 455 | ESPIDF_VFS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/vfs/*.c)) 456 | 457 | ESPIDF_LOG_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/log/*.c)) 458 | 459 | ESPIDF_XTENSA_DEBUG_MODULE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/xtensa-debug-module/*.c)) 460 | 461 | ESPIDF_TCPIP_ADAPTER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/tcpip_adapter/*.c)) 462 | 463 | ESPIDF_APP_TRACE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_trace/*.c)) 464 | 465 | ESPIDF_APP_UPDATE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_update/*.c)) 466 | 467 | ESPIDF_NEWLIB_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/newlib/*.c)) 468 | 469 | ESPIDF_NVS_FLASH_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/nvs_flash/src/*.cpp)) 470 | 471 | ESPIDF_SMARTCONFIG_ACK_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/smartconfig_ack/*.c)) 472 | 473 | ESPIDF_SPI_FLASH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/spi_flash/*.c)) 474 | 475 | ESPIDF_ULP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/ulp/*.c)) 476 | 477 | $(BUILD)/$(ESPCOMP)/lwip/%.o: CFLAGS += -Wno-address -Wno-unused-variable -Wno-unused-but-set-variable 478 | ESPIDF_LWIP_O = $(patsubst %.c,%.o,\ 479 | $(wildcard $(ESPCOMP)/lwip/apps/dhcpserver/*.c) \ 480 | $(wildcard $(ESPCOMP)/lwip/lwip/src/api/*.c) \ 481 | $(wildcard $(ESPCOMP)/lwip/lwip/src/apps/sntp/*.c) \ 482 | $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*.c) \ 483 | $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*/*.c) \ 484 | $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*.c) \ 485 | $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*.c) \ 486 | $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*/*.c) \ 487 | $(wildcard $(ESPCOMP)/lwip/port/esp32/*.c) \ 488 | $(wildcard $(ESPCOMP)/lwip/port/esp32/*/*.c) \ 489 | ) 490 | 491 | ESPIDF_MBEDTLS_O = $(patsubst %.c,%.o,\ 492 | $(wildcard $(ESPCOMP)/mbedtls/mbedtls/library/*.c) \ 493 | $(wildcard $(ESPCOMP)/mbedtls/port/*.c) \ 494 | $(wildcard $(ESPCOMP)/mbedtls/port/esp32/*.c) \ 495 | ) 496 | 497 | ESPIDF_MDNS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/mdns/*.c)) 498 | 499 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 500 | $(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -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 501 | else 502 | $(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 503 | endif 504 | ESPIDF_WPA_SUPPLICANT_O = $(patsubst %.c,%.o,\ 505 | $(wildcard $(ESPCOMP)/wpa_supplicant/port/*.c) \ 506 | $(wildcard $(ESPCOMP)/wpa_supplicant/src/*/*.c) \ 507 | ) 508 | 509 | ESP32_CAM_O = $(patsubst %.c,%.o,\ 510 | $(wildcard $(ESPCOMP)/esp32-camera/driver/*.c) \ 511 | $(wildcard $(ESPCOMP)/esp32-camera/sensors/*.c) \ 512 | $(wildcard $(ESPCOMP)/esp32-camera/conversions/*.c) \ 513 | ) 514 | 515 | ESPIDF_SDMMC_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/sdmmc/*.c)) 516 | 517 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 518 | ESPIDF_ESP_COMMON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_common/src/*.c)) 519 | 520 | ESPIDF_ESP_EVENT_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_event/*.c)) 521 | 522 | ESPIDF_ESP_WIFI_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_wifi/src/*.c)) 523 | 524 | ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) 525 | ESPIDF_BT_NIMBLE_O = $(patsubst %.c,%.o,\ 526 | $(wildcard $(ESPCOMP)/bt/controller/*.c) \ 527 | $(wildcard $(ESPCOMP)/bt/common/btc/core/*.c) \ 528 | $(wildcard $(ESPCOMP)/bt/common/osi/*.c) \ 529 | $(wildcard $(ESPCOMP)/bt/host/nimble/esp-hci/src/*.c) \ 530 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/ext/tinycrypt/src/*.c) \ 531 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ans/src/*.c) \ 532 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/bas/src/*.c) \ 533 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gap/src/*.c) \ 534 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gatt/src/*.c) \ 535 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ias/src/*.c) \ 536 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/lls/src/*.c) \ 537 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/tps/src/*.c) \ 538 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/src/*.c) \ 539 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c) \ 540 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c) \ 541 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/ram/src/*.c) \ 542 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/util/src/*.c) \ 543 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/src/*.c) \ 544 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/nimble/src/*.c) \ 545 | $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/npl/freertos/src/*.c) \ 546 | ) 547 | endif 548 | 549 | $(BUILD)/$(ESPCOMP)/esp_eth/src/esp_eth_mac_dm9051.o: CFLAGS += -fno-strict-aliasing 550 | ESPIDF_ESP_ETH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_eth/src/*.c)) 551 | 552 | ESPIDF_XTENSA_O = $(patsubst %.c,%.o,\ 553 | $(wildcard $(ESPCOMP)/xtensa/*.c) \ 554 | $(wildcard $(ESPCOMP)/xtensa/esp32/*.c) \ 555 | ) 556 | else 557 | ESPIDF_JSON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/json/cJSON/cJSON*.c)) 558 | 559 | ESPIDF_ETHERNET_O = $(patsubst %.c,%.o,\ 560 | $(wildcard $(ESPCOMP)/ethernet/*.c) \ 561 | $(wildcard $(ESPCOMP)/ethernet/eth_phy/*.c) \ 562 | ) 563 | endif 564 | 565 | OBJ_ESPIDF = 566 | LIB_ESPIDF = 567 | BUILD_ESPIDF_LIB = $(BUILD)/esp-idf 568 | 569 | define gen_espidf_lib_rule 570 | OBJ_ESPIDF += $(addprefix $$(BUILD)/,$(2)) 571 | LIB_ESPIDF += $(1) 572 | $(BUILD_ESPIDF_LIB)/$(1)/lib$(1).a: $(addprefix $$(BUILD)/,$(2)) 573 | $(ECHO) "AR $$@" 574 | $(Q)$(AR) cru $$@ $$^ 575 | endef 576 | 577 | $(eval $(call gen_espidf_lib_rule,bootloader_support,$(ESPIDF_BOOTLOADER_SUPPORT_O))) 578 | $(eval $(call gen_espidf_lib_rule,driver,$(ESPIDF_DRIVER_O))) 579 | $(eval $(call gen_espidf_lib_rule,efuse,$(ESPIDF_EFUSE_O))) 580 | $(eval $(call gen_espidf_lib_rule,esp32,$(ESPIDF_ESP32_O))) 581 | $(eval $(call gen_espidf_lib_rule,esp_ringbuf,$(ESPIDF_ESP_RINGBUF_O))) 582 | $(eval $(call gen_espidf_lib_rule,heap,$(ESPIDF_HEAP_O))) 583 | $(eval $(call gen_espidf_lib_rule,soc,$(ESPIDF_SOC_O))) 584 | $(eval $(call gen_espidf_lib_rule,cxx,$(ESPIDF_CXX_O))) 585 | $(eval $(call gen_espidf_lib_rule,pthread,$(ESPIDF_PTHREAD_O))) 586 | $(eval $(call gen_espidf_lib_rule,freertos,$(ESPIDF_FREERTOS_O))) 587 | $(eval $(call gen_espidf_lib_rule,vfs,$(ESPIDF_VFS_O))) 588 | $(eval $(call gen_espidf_lib_rule,json,$(ESPIDF_JSON_O))) 589 | $(eval $(call gen_espidf_lib_rule,log,$(ESPIDF_LOG_O))) 590 | $(eval $(call gen_espidf_lib_rule,xtensa-debug-module,$(ESPIDF_XTENSA_DEBUG_MODULE_O))) 591 | $(eval $(call gen_espidf_lib_rule,tcpip_adapter,$(ESPIDF_TCPIP_ADAPTER_O))) 592 | $(eval $(call gen_espidf_lib_rule,app_trace,$(ESPIDF_APP_TRACE_O))) 593 | $(eval $(call gen_espidf_lib_rule,app_update,$(ESPIDF_APP_UPDATE_O))) 594 | $(eval $(call gen_espidf_lib_rule,newlib,$(ESPIDF_NEWLIB_O))) 595 | $(eval $(call gen_espidf_lib_rule,nvs_flash,$(ESPIDF_NVS_FLASH_O))) 596 | $(eval $(call gen_espidf_lib_rule,smartconfig_ack,$(ESPIDF_SMARTCONFIG_ACK_O))) 597 | $(eval $(call gen_espidf_lib_rule,spi_flash,$(ESPIDF_SPI_FLASH_O))) 598 | $(eval $(call gen_espidf_lib_rule,ulp,$(ESPIDF_ULP_O))) 599 | $(eval $(call gen_espidf_lib_rule,lwip,$(ESPIDF_LWIP_O))) 600 | $(eval $(call gen_espidf_lib_rule,mbedtls,$(ESPIDF_MBEDTLS_O))) 601 | $(eval $(call gen_espidf_lib_rule,mdns,$(ESPIDF_MDNS_O))) 602 | $(eval $(call gen_espidf_lib_rule,wpa_supplicant,$(ESPIDF_WPA_SUPPLICANT_O))) 603 | $(eval $(call gen_espidf_lib_rule,sdmmc,$(ESPIDF_SDMMC_O))) 604 | $(eval $(call gen_espidf_lib_rule,esp32_cam,$(ESP32_CAM_O))) 605 | 606 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 607 | $(eval $(call gen_espidf_lib_rule,esp_common,$(ESPIDF_ESP_COMMON_O))) 608 | $(eval $(call gen_espidf_lib_rule,esp_event,$(ESPIDF_ESP_EVENT_O))) 609 | $(eval $(call gen_espidf_lib_rule,esp_wifi,$(ESPIDF_ESP_WIFI_O))) 610 | ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) 611 | $(eval $(call gen_espidf_lib_rule,bt_nimble,$(ESPIDF_BT_NIMBLE_O))) 612 | endif 613 | $(eval $(call gen_espidf_lib_rule,esp_eth,$(ESPIDF_ESP_ETH_O))) 614 | $(eval $(call gen_espidf_lib_rule,xtensa,$(ESPIDF_XTENSA_O))) 615 | else 616 | $(eval $(call gen_espidf_lib_rule,ethernet,$(ESPIDF_ETHERNET_O))) 617 | endif 618 | 619 | # Create all destination build dirs before compiling IDF source 620 | OBJ_ESPIDF_DIRS = $(sort $(dir $(OBJ_ESPIDF))) $(BUILD_ESPIDF_LIB) $(addprefix $(BUILD_ESPIDF_LIB)/,$(LIB_ESPIDF)) 621 | $(OBJ_ESPIDF): | $(OBJ_ESPIDF_DIRS) 622 | $(OBJ_ESPIDF_DIRS): 623 | $(MKDIR) -p $@ 624 | 625 | # Make all IDF object files depend on sdkconfig 626 | $(OBJ_ESPIDF): $(SDKCONFIG_H) 627 | 628 | # Add all IDF components to the set of libraries 629 | LIB = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) 630 | 631 | ################################################################################ 632 | # ESP IDF ldgen 633 | 634 | LDGEN_FRAGMENTS = $(shell find $(ESPCOMP) -name "*.lf") 635 | 636 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 637 | 638 | LDGEN_LIBRARIES=$(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) 639 | 640 | $(BUILD_ESPIDF_LIB)/ldgen_libraries: $(LDGEN_LIBRARIES) $(ESPIDF)/make/ldgen.mk 641 | printf "$(foreach library,$(LDGEN_LIBRARIES),$(library)\n)" > $(BUILD_ESPIDF_LIB)/ldgen_libraries 642 | 643 | $(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(BUILD_ESPIDF_LIB)/ldgen_libraries 644 | $(ECHO) "GEN $@" 645 | $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ 646 | --input $< \ 647 | --output $@ \ 648 | --config $(SDKCONFIG_COMBINED) \ 649 | --kconfig $(ESPIDF)/Kconfig \ 650 | --fragments $(LDGEN_FRAGMENTS) \ 651 | --libraries-file $(BUILD_ESPIDF_LIB)/ldgen_libraries \ 652 | --env "IDF_TARGET=esp32" \ 653 | --env "IDF_CMAKE=n" \ 654 | --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ 655 | --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ 656 | --env "IDF_PATH=$(ESPIDF)" \ 657 | --objdump $(OBJDUMP) 658 | 659 | else 660 | 661 | LDGEN_SECTIONS_INFO = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a.sections_info) 662 | LDGEN_SECTION_INFOS = $(BUILD_ESPIDF_LIB)/ldgen.section_infos 663 | 664 | define gen_sections_info_rule 665 | $(1).sections_info: $(1) 666 | $(ECHO) "GEN $(1).sections_info" 667 | $(Q)$(OBJDUMP) -h $(1) > $(1).sections_info 668 | endef 669 | 670 | $(eval $(foreach lib,$(LIB_ESPIDF),$(eval $(call gen_sections_info_rule,$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a)))) 671 | 672 | $(LDGEN_SECTION_INFOS): $(LDGEN_SECTIONS_INFO) $(ESPIDF)/make/ldgen.mk 673 | $(Q)printf "$(foreach info,$(LDGEN_SECTIONS_INFO),$(info)\n)" > $@ 674 | 675 | $(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(LDGEN_SECTION_INFOS) 676 | $(ECHO) "GEN $@" 677 | $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ 678 | --input $< \ 679 | --output $@ \ 680 | --config $(SDKCONFIG_COMBINED) \ 681 | --kconfig $(ESPIDF)/Kconfig \ 682 | --fragments $(LDGEN_FRAGMENTS) \ 683 | --sections $(LDGEN_SECTION_INFOS) \ 684 | --env "IDF_TARGET=esp32" \ 685 | --env "IDF_CMAKE=n" \ 686 | --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ 687 | --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ 688 | --env "IDF_PATH=$(ESPIDF)" 689 | 690 | endif 691 | 692 | ################################################################################ 693 | # Main targets 694 | 695 | all: $(BUILD)/firmware.bin 696 | 697 | .PHONY: idf-version deploy erase 698 | 699 | idf-version: 700 | $(ECHO) "ESP IDF supported hash: $(ESPIDF_SUPHASH)" 701 | 702 | $(BUILD)/firmware.bin: $(BUILD)/bootloader.bin $(BUILD)/partitions.bin $(BUILD)/application.bin 703 | $(ECHO) "Create $@" 704 | $(Q)$(PYTHON) makeimg.py $^ $@ 705 | 706 | deploy: $(BUILD)/firmware.bin 707 | $(ECHO) "Writing $^ to the board" 708 | $(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) write_flash -z --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) 0x1000 $^ 709 | 710 | erase: 711 | $(ECHO) "Erasing flash" 712 | $(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) erase_flash 713 | 714 | ################################################################################ 715 | # Declarations to build the application 716 | 717 | OBJ = $(OBJ_MP) 718 | 719 | APP_LD_ARGS = 720 | APP_LD_ARGS += $(LDFLAGS_MOD) 721 | APP_LD_ARGS += $(addprefix -T,$(LD_FILES)) 722 | APP_LD_ARGS += --start-group 723 | APP_LD_ARGS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc 724 | APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++ 725 | APP_LD_ARGS += $(LIBC_LIBM) 726 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 727 | APP_LD_ARGS += -L$(ESPCOMP)/xtensa/esp32 -lhal 728 | APP_LD_ARGS += -L$(ESPCOMP)/bt/controller/lib -lbtdm_app 729 | APP_LD_ARGS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lsmartconfig -lcoexist 730 | else 731 | APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a 732 | APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lwpa -lsmartconfig -lcoexist -lwps -lwpa2 733 | endif 734 | APP_LD_ARGS += $(OBJ) 735 | APP_LD_ARGS += $(LIB) 736 | APP_LD_ARGS += --end-group 737 | 738 | $(BUILD)/esp32_out.ld: $(SDKCONFIG_H) 739 | $(Q)$(CC) -I$(BUILD) -C -P -x c -E $(ESPCOMP)/esp32/ld/esp32.ld -o $@ 740 | 741 | $(BUILD)/application.bin: $(BUILD)/application.elf 742 | $(ECHO) "Create $@" 743 | $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< 744 | 745 | $(BUILD)/application.elf: $(OBJ) $(LIB) $(BUILD)/esp32_out.ld $(BUILD)/esp32.project.ld 746 | $(ECHO) "LINK $@" 747 | $(Q)$(LD) $(LDFLAGS) -o $@ $(APP_LD_ARGS) 748 | $(Q)$(SIZE) $@ 749 | 750 | define compile_cxx 751 | $(ECHO) "CXX $<" 752 | $(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $< 753 | @# The following fixes the dependency file. 754 | @# See http://make.paulandlesley.org/autodep.html for details. 755 | @# Regex adjusted from the above to play better with Windows paths, etc. 756 | @$(CP) $(@:.o=.d) $(@:.o=.P); \ 757 | $(SED) -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' \ 758 | -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ 759 | $(RM) -f $(@:.o=.d) 760 | endef 761 | 762 | vpath %.cpp . $(TOP) 763 | $(BUILD)/%.o: %.cpp 764 | $(call compile_cxx) 765 | 766 | ################################################################################ 767 | # Declarations to build the bootloader 768 | 769 | BOOTLOADER_LIB_DIR = $(BUILD)/bootloader 770 | BOOTLOADER_LIB_ALL = 771 | 772 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 773 | $(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 \ 774 | -I$(ESPCOMP)/esp_common/include \ 775 | -I$(ESPCOMP)/xtensa/include \ 776 | -I$(ESPCOMP)/xtensa/esp32/include 777 | else 778 | $(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 779 | endif 780 | 781 | # libbootloader_support.a 782 | BOOTLOADER_LIB_ALL += bootloader_support 783 | BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 784 | bootloader_support/src/bootloader_clock.o \ 785 | bootloader_support/src/bootloader_common.o \ 786 | bootloader_support/src/bootloader_flash.o \ 787 | bootloader_support/src/bootloader_init.o \ 788 | bootloader_support/src/bootloader_random.o \ 789 | bootloader_support/src/bootloader_utility.o \ 790 | bootloader_support/src/flash_qio_mode.o \ 791 | bootloader_support/src/esp_image_format.o \ 792 | bootloader_support/src/flash_encrypt.o \ 793 | bootloader_support/src/flash_partitions.o \ 794 | ) 795 | 796 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 797 | BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 798 | bootloader_support/src/esp32/bootloader_sha.o \ 799 | bootloader_support/src/bootloader_flash_config.o \ 800 | bootloader_support/src/esp32/secure_boot.o \ 801 | ) 802 | else 803 | BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 804 | bootloader_support/src/bootloader_sha.o \ 805 | bootloader_support/src/secure_boot_signatures.o \ 806 | bootloader_support/src/secure_boot.o \ 807 | ) 808 | endif 809 | 810 | $(BOOTLOADER_LIB_DIR)/libbootloader_support.a: $(BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ) 811 | $(ECHO) "AR $@" 812 | $(Q)$(AR) cr $@ $^ 813 | 814 | # liblog.a 815 | BOOTLOADER_LIB_ALL += log 816 | BOOTLOADER_LIB_LOG_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 817 | log/log.o \ 818 | ) 819 | $(BOOTLOADER_LIB_DIR)/liblog.a: $(BOOTLOADER_LIB_LOG_OBJ) 820 | $(ECHO) "AR $@" 821 | $(Q)$(AR) cr $@ $^ 822 | 823 | # libspi_flash.a 824 | BOOTLOADER_LIB_ALL += spi_flash 825 | BOOTLOADER_LIB_SPI_FLASH_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 826 | spi_flash/spi_flash_rom_patch.o \ 827 | ) 828 | $(BOOTLOADER_LIB_DIR)/libspi_flash.a: $(BOOTLOADER_LIB_SPI_FLASH_OBJ) 829 | $(ECHO) "AR $@" 830 | $(Q)$(AR) cr $@ $^ 831 | 832 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) 833 | # libmicro-ecc.a 834 | BOOTLOADER_LIB_ALL += micro-ecc 835 | BOOTLOADER_LIB_MICRO_ECC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 836 | micro-ecc/micro-ecc/uECC.o \ 837 | ) 838 | $(BOOTLOADER_LIB_DIR)/libmicro-ecc.a: $(BOOTLOADER_LIB_MICRO_ECC_OBJ) 839 | $(ECHO) "AR $@" 840 | $(Q)$(AR) cr $@ $^ 841 | endif 842 | 843 | # libsoc.a 844 | $(BUILD)/bootloader/$(ESPCOMP)/soc/esp32/rtc_clk.o: CFLAGS += -fno-jump-tables -fno-tree-switch-conversion 845 | BOOTLOADER_LIB_ALL += soc 846 | BOOTLOADER_LIB_SOC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/soc/,\ 847 | esp32/cpu_util.o \ 848 | esp32/gpio_periph.o \ 849 | esp32/rtc_clk.o \ 850 | esp32/rtc_clk_init.o \ 851 | esp32/rtc_init.o \ 852 | esp32/rtc_periph.o \ 853 | esp32/rtc_pm.o \ 854 | esp32/rtc_sleep.o \ 855 | esp32/rtc_time.o \ 856 | esp32/rtc_wdt.o \ 857 | esp32/sdio_slave_periph.o \ 858 | esp32/sdmmc_periph.o \ 859 | esp32/soc_memory_layout.o \ 860 | esp32/spi_periph.o \ 861 | src/memory_layout_utils.o \ 862 | ) 863 | $(BOOTLOADER_LIB_DIR)/libsoc.a: $(BOOTLOADER_LIB_SOC_OBJ) 864 | $(ECHO) "AR $@" 865 | $(Q)$(AR) cr $@ $^ 866 | 867 | # libmain.a 868 | BOOTLOADER_LIB_ALL += main 869 | BOOTLOADER_LIB_MAIN_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ 870 | bootloader/subproject/main/bootloader_start.o \ 871 | ) 872 | $(BOOTLOADER_LIB_DIR)/libmain.a: $(BOOTLOADER_LIB_MAIN_OBJ) 873 | $(ECHO) "AR $@" 874 | $(Q)$(AR) cr $@ $^ 875 | 876 | # all objects files 877 | BOOTLOADER_OBJ_ALL = \ 878 | $(BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ) \ 879 | $(BOOTLOADER_LIB_LOG_OBJ) \ 880 | $(BOOTLOADER_LIB_SPI_FLASH_OBJ) \ 881 | $(BOOTLOADER_LIB_MICRO_ECC_OBJ) \ 882 | $(BOOTLOADER_LIB_SOC_OBJ) \ 883 | $(BOOTLOADER_LIB_MAIN_OBJ) 884 | 885 | $(BOOTLOADER_OBJ_ALL): $(SDKCONFIG_H) 886 | 887 | BOOTLOADER_LIBS = 888 | BOOTLOADER_LIBS += -Wl,--start-group 889 | BOOTLOADER_LIBS += $(BOOTLOADER_OBJ) 890 | BOOTLOADER_LIBS += -L$(BUILD)/bootloader $(addprefix -l,$(BOOTLOADER_LIB_ALL)) 891 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 892 | BOOTLOADER_LIBS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lrtc 893 | else 894 | BOOTLOADER_LIBS += -L$(ESPCOMP)/esp32/lib -lrtc 895 | endif 896 | BOOTLOADER_LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc 897 | BOOTLOADER_LIBS += -Wl,--end-group 898 | 899 | BOOTLOADER_LDFLAGS = 900 | BOOTLOADER_LDFLAGS += -nostdlib 901 | BOOTLOADER_LDFLAGS += -L$(ESPIDF)/lib 902 | BOOTLOADER_LDFLAGS += -L$(ESPIDF)/ld 903 | BOOTLOADER_LDFLAGS += -u call_user_start_cpu0 904 | BOOTLOADER_LDFLAGS += -Wl,--gc-sections 905 | BOOTLOADER_LDFLAGS += -static 906 | BOOTLOADER_LDFLAGS += -Wl,-EL 907 | BOOTLOADER_LDFLAGS += -Wl,-Map=$(@:.elf=.map) -Wl,--cref 908 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.ld 909 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.rom.ld 910 | ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) 911 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.ld 912 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld 913 | else 914 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.ld 915 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.spiram_incompatible_fns.ld 916 | endif 917 | BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.peripherals.ld 918 | 919 | BOOTLOADER_OBJ_DIRS = $(sort $(dir $(BOOTLOADER_OBJ_ALL))) 920 | $(BOOTLOADER_OBJ_ALL): | $(BOOTLOADER_OBJ_DIRS) 921 | $(BOOTLOADER_OBJ_DIRS): 922 | $(MKDIR) -p $@ 923 | 924 | $(BUILD)/bootloader/%.o: %.c 925 | $(call compile_c) 926 | 927 | $(BUILD)/bootloader.bin: $(BUILD)/bootloader.elf 928 | $(ECHO) "Create $@" 929 | $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< 930 | 931 | $(BUILD)/bootloader.elf: $(BOOTLOADER_OBJ) $(addprefix $(BOOTLOADER_LIB_DIR)/lib,$(addsuffix .a,$(BOOTLOADER_LIB_ALL))) 932 | $(ECHO) "LINK $@" 933 | $(Q)$(CC) $(BOOTLOADER_LDFLAGS) -o $@ $(BOOTLOADER_LIBS) 934 | 935 | ################################################################################ 936 | # Declarations to build the partitions 937 | 938 | PYTHON2 ?= python2 939 | 940 | # Can be overriden by mkconfigboard.mk. 941 | PART_SRC ?= partitions.csv 942 | 943 | $(BUILD)/partitions.bin: $(PART_SRC) 944 | $(ECHO) "Create $@" 945 | $(Q)$(PYTHON2) $(ESPCOMP)/partition_table/gen_esp32part.py -q $< $@ 946 | 947 | ################################################################################ 948 | 949 | include $(TOP)/py/mkrules.mk 950 | --------------------------------------------------------------------------------