├── main ├── cli-uart.h ├── i2c.h ├── delay.h ├── factory-reset-service.h ├── delay.c ├── usb.h ├── led.h ├── soft-uart-log.h ├── helpers.h ├── network-http.h ├── network-uart.h ├── nvs.h ├── cli │ ├── cli-commands.h │ ├── cli.motd.art │ ├── cli.h │ ├── cli-args.c │ ├── cli-args.h │ ├── cli-commands-device-info.c │ └── cli-commands.c ├── network.h ├── network-gdb.h ├── usb-uart.h ├── soft-uart-log.c ├── nvs-config.h ├── main.c ├── i2c.c ├── CMakeLists.txt ├── nvs.c ├── led.c ├── cli-uart.c ├── factory-reset-service.c ├── network-uart.c ├── nvs-config.c ├── network-gdb.c ├── usb-uart.c ├── usb.c └── network.c ├── components ├── svelte-portal │ ├── .gitignore │ ├── src │ │ ├── main.js │ │ ├── lib │ │ │ ├── Reload.svelte │ │ │ ├── Grid.svelte │ │ │ ├── Spinner.svelte │ │ │ ├── Indicator.svelte │ │ │ ├── Api.svelte │ │ │ ├── Value.svelte │ │ │ ├── ButtonInline.svelte │ │ │ ├── Select.svelte │ │ │ ├── Input.svelte │ │ │ ├── Button.svelte │ │ │ ├── Popup.svelte │ │ │ ├── WebSocket.svelte │ │ │ ├── SpinnerBig.svelte │ │ │ └── terminal.js │ │ ├── tabs │ │ │ ├── TabPS.svelte │ │ │ ├── TabSys.svelte │ │ │ └── TabWiFi.svelte │ │ └── App.svelte │ ├── public │ │ ├── assets │ │ │ ├── ega8.otf │ │ │ └── favicon.ico │ │ ├── index.html │ │ └── build │ │ │ └── bundle.css │ ├── CMakeLists.txt │ ├── package.json │ ├── svelte-portal.h │ ├── rollup.config.js │ └── scripts │ │ └── setupTypeScript.js ├── soft-uart │ ├── CMakeLists.txt │ ├── soft-uart.h │ └── soft-uart.c ├── simple-uart │ ├── CMakeLists.txt │ └── simple-uart.h ├── blackmagic │ ├── esp32-platform │ │ ├── version.h │ │ ├── gdb-glue.h │ │ ├── platform.h │ │ ├── gdb-glue.c │ │ ├── platform.c │ │ └── custom │ │ │ └── swd-spi-tap.c │ └── CMakeLists.txt ├── dap-link │ ├── CMakeLists.txt │ └── dap_config.h ├── mlib │ ├── CMakeLists.txt │ ├── m-string.c │ └── m-string.h └── tinyusb │ ├── drivers │ ├── dual-cdc │ │ ├── dual-cdc-descriptors.h │ │ └── dual-cdc-descriptors.c │ ├── dap-link │ │ ├── dap-link-descriptors.h │ │ └── vendor_device.h │ └── usb-glue.h │ ├── CMakeLists.txt │ └── config │ └── tusb_config.h ├── .gitattributes ├── .gitignore ├── partitions.csv ├── CMakeLists.txt ├── .github └── workflows │ ├── reindex.yml │ └── build.yml ├── .gitmodules ├── scripts ├── flash_nix.sh ├── pack_release_win.bat └── get_env.py ├── README.md └── .clang-format /main/cli-uart.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void cli_uart_init(); -------------------------------------------------------------------------------- /main/i2c.h: -------------------------------------------------------------------------------- 1 | void i2c_init(void); 2 | void i2c_scan(void); -------------------------------------------------------------------------------- /components/svelte-portal/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | 3 | .DS_Store -------------------------------------------------------------------------------- /main/delay.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void delay(uint32_t ms); -------------------------------------------------------------------------------- /main/factory-reset-service.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void factory_reset_service_init(void); -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text eol=lf 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | /build 3 | /sdkconfig.old 4 | /main/wifi-credentials.h 5 | .DS_Store -------------------------------------------------------------------------------- /components/soft-uart/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "soft-uart.c" 2 | INCLUDE_DIRS ".") -------------------------------------------------------------------------------- /components/simple-uart/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "simple-uart.c" 2 | INCLUDE_DIRS ".") -------------------------------------------------------------------------------- /components/blackmagic/esp32-platform/version.h: -------------------------------------------------------------------------------- 1 | // for includes only 2 | // we provide the FIRMWARE_VERSION through the build system -------------------------------------------------------------------------------- /components/dap-link/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "free-dap/dap.c" 2 | PRIV_INCLUDE_DIRS "." 3 | INCLUDE_DIRS "." "free-dap") -------------------------------------------------------------------------------- /components/mlib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "m-string.c" 2 | PRIV_INCLUDE_DIRS "mlib" 3 | INCLUDE_DIRS ".") -------------------------------------------------------------------------------- /components/svelte-portal/src/main.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; -------------------------------------------------------------------------------- /components/svelte-portal/public/assets/ega8.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flipperdevices/blackmagic-esp32-s2/HEAD/components/svelte-portal/public/assets/ega8.otf -------------------------------------------------------------------------------- /components/svelte-portal/public/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flipperdevices/blackmagic-esp32-s2/HEAD/components/svelte-portal/public/assets/favicon.ico -------------------------------------------------------------------------------- /main/delay.c: -------------------------------------------------------------------------------- 1 | #include "delay.h" 2 | #include 3 | #include 4 | 5 | void delay(uint32_t ms) { 6 | vTaskDelay(ms / portTICK_PERIOD_MS); 7 | } -------------------------------------------------------------------------------- /partitions.csv: -------------------------------------------------------------------------------- 1 | # ESP-IDF Partition Table 2 | # Name, Type, SubType, Offset, Size, Flags 3 | nvs,data,nvs,0x9000,24K, 4 | phy_init,data,phy,0xf000,4K, 5 | factory,app,factory,0x10000,2M, 6 | nvs_storage,data,nvs, ,100K -------------------------------------------------------------------------------- /main/usb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Init usb subsystem 5 | */ 6 | void usb_init(void); 7 | 8 | void usb_gdb_tx_char(uint8_t c, bool flush); 9 | 10 | void usb_uart_tx_char(uint8_t c, bool flush); 11 | 12 | bool dap_is_connected(void); -------------------------------------------------------------------------------- /main/led.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void led_init(); 5 | 6 | void led_set(uint8_t red, uint8_t green, uint8_t blue); 7 | 8 | void led_set_red(uint8_t value); 9 | void led_set_green(uint8_t value); 10 | void led_set_blue(uint8_t value); -------------------------------------------------------------------------------- /main/soft-uart-log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file soft-uart-log.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-12-18 6 | * 7 | * 8 | */ 9 | #pragma once 10 | #include 11 | 12 | void soft_uart_log_init(uint8_t pin, uint32_t baudrate); -------------------------------------------------------------------------------- /main/helpers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file helpers.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-11-24 6 | * 7 | * Misc helpers 8 | */ 9 | 10 | #define COUNT_OF(x) (sizeof(x) / sizeof((x)[0])) 11 | #define STRINGIFY_HELPER(X) #X 12 | #define STRINGIFY(X) STRINGIFY_HELPER(X) -------------------------------------------------------------------------------- /components/tinyusb/drivers/dual-cdc/dual-cdc-descriptors.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern tusb_desc_device_t const blackmagic_desc_device; 4 | extern uint8_t const blackmagic_desc_fs_configuration[]; 5 | uint16_t const* blackmagic_descriptor_string_cb(uint8_t index, uint16_t langid); 6 | void blackmagic_set_serial_number(const char* serial_number); -------------------------------------------------------------------------------- /main/network-http.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file network-http.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-11-21 6 | * 7 | * HTTP server API 8 | */ 9 | #pragma once 10 | 11 | /** 12 | * Start HTTP server 13 | */ 14 | void network_http_server_init(void); 15 | 16 | void network_http_uart_write_data(uint8_t* data, size_t size); -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about build system see 2 | # https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html 3 | # The following five lines of boilerplate have to be in your project's 4 | # CMakeLists in this exact order for cmake to work correctly 5 | cmake_minimum_required(VERSION 3.5) 6 | 7 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 8 | project(blackmagic) 9 | -------------------------------------------------------------------------------- /main/network-uart.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /** 5 | * Start uart server 6 | */ 7 | void network_uart_server_init(void); 8 | 9 | /** 10 | * Checks if someone is connected to the uart port 11 | * @return bool 12 | */ 13 | bool network_uart_connected(void); 14 | 15 | /** 16 | * Send data 17 | * @param buffer data 18 | * @param size data size 19 | */ 20 | void network_uart_send(uint8_t* buffer, size_t size); -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Reload.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | {#if api.dev_mode} 7 |
8 |
15 | {/if} 16 | -------------------------------------------------------------------------------- /.github/workflows/reindex.yml: -------------------------------------------------------------------------------- 1 | name: 'Reindex' 2 | 3 | on: 4 | release: 5 | types: [prereleased,released] 6 | 7 | jobs: 8 | reindex: 9 | name: 'Reindex updates' 10 | runs-on: [self-hosted,FlipperZeroShell] 11 | steps: 12 | - name: Trigger reindex 13 | run: | 14 | curl --fail -L -H "Token: ${{ secrets.INDEXER_TOKEN }}" \ 15 | "${{ secrets.INDEXER_URL }}"/blackmagic-firmware/reindex 16 | -------------------------------------------------------------------------------- /components/soft-uart/soft-uart.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file soft-uart.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-12-18 6 | * 7 | * 8 | */ 9 | #pragma once 10 | #include 11 | 12 | typedef struct SoftUart SoftUart; 13 | 14 | SoftUart* soft_uart_init(uint32_t baudrate, uint8_t tx_pin); 15 | 16 | void soft_uart_transmit(SoftUart* uart, const uint8_t* data, uint32_t data_size); 17 | -------------------------------------------------------------------------------- /main/nvs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file nvs.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-12-03 6 | * 7 | * NVS management 8 | */ 9 | #pragma once 10 | #include 11 | #include 12 | 13 | void nvs_init(void); 14 | void nvs_erase(void); 15 | esp_err_t nvs_save_string(const char* key, const mstring_t* value); 16 | esp_err_t nvs_load_string(const char* key, mstring_t* value); -------------------------------------------------------------------------------- /components/svelte-portal/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Blackmagic for Flipper 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Grid.svelte: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 22 | -------------------------------------------------------------------------------- /components/tinyusb/drivers/dap-link/dap-link-descriptors.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | enum { VENDOR_REQUEST_WEBUSB = 1, VENDOR_REQUEST_MICROSOFT = 2 }; 4 | 5 | extern tusb_desc_device_t const dap_link_desc_device; 6 | extern uint8_t const dap_link_desc_configuration[]; 7 | extern uint8_t const dap_link_desc_bos[]; 8 | extern uint8_t const dap_link_desc_ms_os_20[]; 9 | uint16_t const* dap_link_descriptor_string_cb(uint8_t index, uint16_t langid); 10 | void dap_link_set_serial_number(const char* serial_number); -------------------------------------------------------------------------------- /main/cli/cli-commands.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cli-commands.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-12-01 6 | * 7 | * Cli commands list 8 | */ 9 | #pragma once 10 | #include 11 | 12 | typedef void (*CliCallback)(Cli* cli, mstring_t* args); 13 | 14 | struct CliItem { 15 | const char* name; 16 | const char* desc; 17 | CliCallback callback; 18 | }; 19 | 20 | extern const CliItem cli_items[]; 21 | extern size_t cli_items_count; -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "components/blackmagic/blackmagic-fw"] 2 | path = components/blackmagic/blackmagic-fw 3 | url = https://github.com/flipperdevices/blackmagic.git 4 | [submodule "components/mlib/mlib"] 5 | path = components/mlib/mlib 6 | url = https://github.com/P-p-H-d/mlib.git 7 | [submodule "components/tinyusb/tinyusb"] 8 | path = components/tinyusb/tinyusb 9 | url = https://github.com/hathach/tinyusb 10 | [submodule "components/dap-link/free-dap"] 11 | path = components/dap-link/free-dap 12 | url = https://github.com/ataradov/free-dap 13 | -------------------------------------------------------------------------------- /components/svelte-portal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register( 2 | EMBED_FILES "public/index.html" "public/build/bundle.css" "public/build/bundle.js" "public/assets/ega8.otf" "public/assets/favicon.ico" 3 | INCLUDE_DIRS ".") 4 | 5 | # add_custom_command(OUTPUT "public/build/bundle.css" "public/build/bundle.js" 6 | # COMMAND cd ${COMPONENT_DIR} && npm run build 7 | # COMMENT "Generate Svelte site" 8 | # ) 9 | 10 | # add_custom_target(svelte_bundle DEPENDS "public/build/bundle.css" "public/build/bundle.js") 11 | # add_dependencies(${COMPONENT_LIB} svelte_bundle) -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Spinner.svelte: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 31 | -------------------------------------------------------------------------------- /main/network.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file network.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-11-21 6 | * 7 | * Network API 8 | */ 9 | #pragma once 10 | #include 11 | #include "nvs-config.h" 12 | 13 | /** 14 | * Init network module 15 | * @return WiFiMode 16 | */ 17 | WiFiMode network_init(void); 18 | 19 | /** 20 | * Returns current WIFI mode 21 | * @return WiFiMode 22 | */ 23 | WiFiMode network_get_mode(void); 24 | 25 | /** 26 | * Get current IP address 27 | * @return uint32_t 28 | */ 29 | uint32_t network_get_ip(void); -------------------------------------------------------------------------------- /main/network-gdb.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file network-gdb.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-11-25 6 | * 7 | * GDB server API 8 | */ 9 | 10 | #pragma once 11 | #include 12 | 13 | /** 14 | * Start GDB server 15 | */ 16 | void network_gdb_server_init(void); 17 | 18 | /** 19 | * Checks if someone is connected to the GDB server 20 | * @return bool 21 | */ 22 | bool network_gdb_connected(void); 23 | 24 | /** 25 | * Send data 26 | * @param buffer data 27 | * @param size data size 28 | */ 29 | void network_gdb_send(uint8_t* buffer, size_t size); -------------------------------------------------------------------------------- /main/usb-uart.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file usb-uart.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-12-17 6 | * 7 | * 8 | */ 9 | #pragma once 10 | 11 | void usb_uart_init(); 12 | 13 | void usb_uart_write(const uint8_t* data, size_t data_size); 14 | 15 | void usb_uart_set_line_state(bool dtr, bool rts); 16 | 17 | typedef struct { 18 | uint32_t bit_rate; 19 | uint8_t stop_bits; 20 | uint8_t parity; 21 | uint8_t data_bits; 22 | } UsbUartConfig; 23 | 24 | void usb_uart_set_line_coding(UsbUartConfig config); 25 | 26 | UsbUartConfig usb_uart_get_line_coding(); -------------------------------------------------------------------------------- /components/svelte-portal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-app", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "rollup -c", 7 | "dev": "set \"HOST=0.0.0.0\" && rollup -c -w", 8 | "start": "sirv public --no-clear" 9 | }, 10 | "devDependencies": { 11 | "@rollup/plugin-commonjs": "^17.0.0", 12 | "@rollup/plugin-node-resolve": "^11.0.0", 13 | "@rollup/plugin-replace": "^3.0.0", 14 | "rollup": "^2.3.4", 15 | "rollup-plugin-css-only": "^3.1.0", 16 | "rollup-plugin-livereload": "^2.0.0", 17 | "rollup-plugin-svelte": "^7.0.0", 18 | "rollup-plugin-terser": "^7.0.0", 19 | "svelte": "^3.0.0" 20 | }, 21 | "dependencies": { 22 | "sirv-cli": "^1.0.0", 23 | "stringview": "^3.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /scripts/flash_nix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd $(dirname "$0") 4 | 5 | FLASH_COMMAND="$(cat flash.command)" 6 | 7 | if [ -n "$1" ]; then 8 | if [ -c "$1" ]; then 9 | PORT="$1" 10 | 11 | TOOL="$(echo "$FLASH_COMMAND" | sed -e 's/\s.*$//')" 12 | ESPTOOL=`which $TOOL` 13 | if [ -n "$ESPTOOL" ] && [ -x "$ESPTOOL" ]; then 14 | echo "$FLASH_COMMAND" | sed -e "s|(PORT)|$PORT|g" | sh -x 15 | exit $? 16 | else 17 | echo "Can't find executable $ESPTOOL" 18 | echo 19 | fi 20 | else 21 | echo "Invalid port $1" 22 | echo 23 | fi 24 | fi 25 | 26 | echo "Usage: $0 " 27 | echo "Available ports:" 28 | find /dev/tty* | grep -E "ACM|USB|\." --color=never 29 | exit 255; 30 | -------------------------------------------------------------------------------- /components/blackmagic/esp32-platform/gdb-glue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | /** 6 | * Init gdb stream glue 7 | */ 8 | void gdb_glue_init(void); 9 | 10 | /** 11 | * Get free size of rx stream 12 | * @return size_t 13 | */ 14 | size_t gdb_glue_get_free_size(void); 15 | 16 | /** 17 | * Put data to rx stream 18 | * @param buffer data 19 | * @param size data size 20 | */ 21 | void gdb_glue_receive(uint8_t* buffer, size_t size); 22 | 23 | /** 24 | * 25 | * @return bool 26 | */ 27 | bool gdb_glue_can_receive(); 28 | 29 | /** 30 | * Get gdb packet size 31 | * @return size_t 32 | */ 33 | size_t gdb_glue_get_packet_size(); 34 | 35 | /** 36 | * Get blackmagic version 37 | * @return const char* 38 | */ 39 | const char* gdb_glue_get_bm_version(); -------------------------------------------------------------------------------- /main/cli/cli.motd.art: -------------------------------------------------------------------------------- 1 | 2 | ____ BLACK 3 | / /\ MAGIC 4 | / /\ \ 5 | ( / \ \ ' 6 | _/ (___/ /_ . ' 7 | ( _____._.__ ) ,'o 8 | // / '"' | O . 9 | // / ' ' |\ ,,, 10 | // /\ ' '| \_/''/ 11 | // / )______/\ \_/ 12 | // \ ( ) `---' 13 | \\___/ | \ 14 | \( \ | \ 15 | / \_@ | ) 16 | \ , | \ 17 | / / / | / 18 | \ \ : /\ / 19 | \ \ \ : / |\) 20 | \ / |\/| | 21 | / / | |- 22 | \ /|__| 23 | \ / |''| 24 | \ \ -- 25 | \/ 26 | -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Indicator.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 |
U
19 | 20 | 36 | -------------------------------------------------------------------------------- /main/soft-uart-log.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | extern void esp_log_impl_lock(void); 8 | extern void esp_log_impl_unlock(void); 9 | 10 | #define LOG_BUFFER_SIZE (256) 11 | static SoftUart* log_uart = NULL; 12 | static char log_buffer[LOG_BUFFER_SIZE]; 13 | 14 | static int soft_uart_log_vprintf(const char* str, va_list l) { 15 | esp_log_impl_lock(); 16 | 17 | int len = vsnprintf(log_buffer, LOG_BUFFER_SIZE, str, l); 18 | soft_uart_transmit(log_uart, (uint8_t*)log_buffer, strlen(log_buffer)); 19 | 20 | esp_log_impl_unlock(); 21 | return len; 22 | } 23 | 24 | void soft_uart_log_init(uint8_t pin, uint32_t baudrate) { 25 | log_uart = soft_uart_init(baudrate, pin); 26 | 27 | esp_log_set_vprintf(soft_uart_log_vprintf); 28 | } -------------------------------------------------------------------------------- /components/svelte-portal/svelte-portal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | extern const uint8_t index_html_start[] asm("_binary_index_html_start"); 5 | extern const uint8_t index_html_end[] asm("_binary_index_html_end"); 6 | extern const uint8_t build_bundle_css_start[] asm("_binary_bundle_css_start"); 7 | extern const uint8_t build_bundle_css_end[] asm("_binary_bundle_css_end"); 8 | extern const uint8_t build_bundle_js_start[] asm("_binary_bundle_js_start"); 9 | extern const uint8_t build_bundle_js_end[] asm("_binary_bundle_js_end"); 10 | extern const uint8_t assets_ega8_otf_start[] asm("_binary_ega8_otf_start"); 11 | extern const uint8_t assets_ega8_otf_end[] asm("_binary_ega8_otf_end"); 12 | extern const uint8_t assets_favicon_ico_start[] asm("_binary_favicon_ico_start"); 13 | extern const uint8_t assets_favicon_ico_end[] asm("_binary_favicon_ico_end"); -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Api.svelte: -------------------------------------------------------------------------------- 1 | 30 | -------------------------------------------------------------------------------- /scripts/pack_release_win.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd build 3 | setlocal EnableDelayedExpansion 4 | 5 | FOR /F "tokens=* USEBACKQ" %%g IN (`git rev-parse --short HEAD`) do (SET "GIT_COMMIT=%%g") 6 | SET "RELEASE_FILENAME=release_%GIT_COMMIT%" 7 | 8 | echo | set /p="esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32s2 write_flash " > flash.command 9 | for /f "tokens=*" %%a in (flash_args) do ( 10 | echo | set /p=%%a >> flash.command 11 | ) 12 | 13 | del release.zip 14 | "C:\Program Files\7-Zip\7z.exe" a -tzip -mx5 -r0 %RELEASE_FILENAME%.zip blackmagic.bin 15 | "C:\Program Files\7-Zip\7z.exe" a -tzip -mx5 -r0 %RELEASE_FILENAME%.zip bootloader/bootloader.bin 16 | "C:\Program Files\7-Zip\7z.exe" a -tzip -mx5 -r0 %RELEASE_FILENAME%.zip partition_table/partition-table.bin 17 | "C:\Program Files\7-Zip\7z.exe" a -tzip -mx5 -r0 %RELEASE_FILENAME%.zip flash.command 18 | del flash.command 19 | 20 | cd .. -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Value.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | {#if !splitter} 8 |
{name}:
9 |
10 | {:else} 11 |
{name}
12 |
 
13 | {/if} 14 | 15 | 37 | -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/ButtonInline.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 44 | -------------------------------------------------------------------------------- /main/cli/cli.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cli.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-12-01 6 | * 7 | * Cli commands 8 | */ 9 | 10 | #pragma once 11 | #include "stdint.h" 12 | #include "stdlib.h" 13 | 14 | typedef struct Cli Cli; 15 | typedef struct CliItem CliItem; 16 | 17 | typedef void (*CliWrite)(const uint8_t* data, size_t data_size, void* context); 18 | typedef void (*CliFlush)(void* context); 19 | 20 | Cli* cli_init(void); 21 | 22 | void cli_set_context(Cli* cli, void* context); 23 | 24 | void cli_set_write_cb(Cli* cli, CliWrite write_cb); 25 | 26 | void cli_set_flush_cb(Cli* cli, CliFlush flush_cb); 27 | 28 | void cli_write(Cli* cli, const uint8_t* data, size_t data_size); 29 | 30 | void cli_flush(Cli* cli); 31 | 32 | void cli_write_str(Cli* cli, const char* str); 33 | 34 | void cli_write_char(Cli* cli, uint8_t c); 35 | 36 | void cli_handle_char(Cli* cli, uint8_t c); 37 | 38 | void cli_write_eol(Cli* cli); 39 | 40 | void cli_printf(Cli* cli, char* format, ...); 41 | 42 | void cli_force_motd(Cli* cli); -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Select.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 21 | 22 | 65 | -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Input.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 | 3 ? (value + "").length : 3} 30 | on:input={text_input} 31 | /> 32 | 33 | 66 | -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Button.svelte: -------------------------------------------------------------------------------- 1 | 44 | 45 | 53 | 54 | 74 | -------------------------------------------------------------------------------- /main/nvs-config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file nvs-config.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-12-03 6 | * 7 | * Configuration helper 8 | */ 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | #define CFG_WIFI_MODE_AP "AP" 15 | #define CFG_WIFI_MODE_STA "STA" 16 | #define CFG_WIFI_MODE_DISABLED "Disabled" 17 | 18 | #define CFG_USB_MODE_BM "BM" 19 | #define CFG_USB_MODE_DAP "DAP" 20 | 21 | typedef enum { 22 | UsbModeBM, // Blackmagic-probe 23 | UsbModeDAP, // Dap-link 24 | } UsbMode; 25 | 26 | typedef enum { 27 | WiFiModeAP, // host of a WiFi network 28 | WiFiModeSTA, // connected to existing WiFi AP 29 | WiFiModeDisabled, // disabled 30 | } WiFiMode; 31 | 32 | esp_err_t nvs_config_set_wifi_mode(WiFiMode value); 33 | esp_err_t nvs_config_set_usb_mode(UsbMode value); 34 | esp_err_t nvs_config_set_ap_ssid(const mstring_t* ssid); 35 | esp_err_t nvs_config_set_ap_pass(const mstring_t* pass); 36 | esp_err_t nvs_config_set_sta_ssid(const mstring_t* ssid); 37 | esp_err_t nvs_config_set_sta_pass(const mstring_t* pass); 38 | esp_err_t nvs_config_set_hostname(const mstring_t* hostname); 39 | 40 | esp_err_t nvs_config_get_wifi_mode(WiFiMode* value); 41 | esp_err_t nvs_config_get_usb_mode(UsbMode* value); 42 | esp_err_t nvs_config_get_ap_ssid(mstring_t* ssid); 43 | esp_err_t nvs_config_get_ap_pass(mstring_t* pass); 44 | esp_err_t nvs_config_get_sta_ssid(mstring_t* ssid); 45 | esp_err_t nvs_config_get_sta_pass(mstring_t* pass); 46 | esp_err_t nvs_config_get_hostname(mstring_t* hostname); 47 | -------------------------------------------------------------------------------- /components/tinyusb/drivers/usb-glue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | typedef enum { 8 | USBDeviceTypeDapLink, 9 | USBDeviceTypeDualCDC, 10 | } USBDeviceType; 11 | 12 | /***** Common *****/ 13 | 14 | esp_err_t usb_glue_init(USBDeviceType device_type); 15 | 16 | void usb_glue_reset_bus(); 17 | 18 | void usb_glue_set_connected_callback(void (*callback)(void* context), void* context); 19 | 20 | void usb_glue_set_disconnected_callback(void (*callback)(void* context), void* context); 21 | 22 | const char* usb_glue_get_serial_number(); 23 | 24 | /***** USB-UART *****/ 25 | 26 | void usb_glue_cdc_send(const uint8_t* buf, size_t len, bool flush); 27 | 28 | void usb_glue_cdc_set_receive_callback(void (*callback)(void* context), void* context); 29 | 30 | size_t usb_glue_cdc_receive(uint8_t* buf, size_t len); 31 | 32 | void usb_glue_cdc_set_line_coding_callback( 33 | void (*callback)(cdc_line_coding_t const* p_line_coding, void* context), 34 | void* context); 35 | 36 | void usb_glue_cdc_set_line_state_callback( 37 | void (*callback)(bool dtr, bool rts, void* context), 38 | void* context); 39 | 40 | /***** USB-GDB *****/ 41 | 42 | void usb_glue_gdb_send(const uint8_t* buf, size_t len, bool flush); 43 | 44 | void usb_glue_gdb_set_receive_callback(void (*callback)(void* context), void* context); 45 | 46 | size_t usb_glue_gdb_receive(uint8_t* buf, size_t len); 47 | 48 | /***** USB-DAP *****/ 49 | 50 | void usb_glue_dap_send(const uint8_t* buf, size_t len, bool flush); 51 | 52 | void usb_glue_dap_set_receive_callback(void (*callback)(void* context), void* context); 53 | 54 | size_t usb_glue_dap_receive(uint8_t* buf, size_t len); -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/Popup.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | {#if !closed} 14 | 15 | 16 | 17 | X 18 | 19 | 20 | 21 | 22 | 23 | 24 | {/if} 25 | 26 | 81 | -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/WebSocket.svelte: -------------------------------------------------------------------------------- 1 | 68 | -------------------------------------------------------------------------------- /components/blackmagic/esp32-platform/platform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | extern uint32_t swd_delay_cnt; 5 | 6 | void platform_swdio_mode_float(void); 7 | void platform_swdio_mode_drive(void); 8 | void platform_gpio_set_level(int32_t gpio_num, uint32_t value); 9 | void platform_gpio_set(int32_t gpio_num); 10 | void platform_gpio_clear(int32_t gpio_num); 11 | int platform_gpio_get_level(int32_t gpio_num); 12 | 13 | void led_set_red(uint8_t value); 14 | void led_set_green(uint8_t value); 15 | void led_set_blue(uint8_t value); 16 | 17 | #define PLATFORM_IDENT "ESP32-S2" 18 | 19 | #define NO_USB_PLEASE 20 | 21 | #define SET_RUN_STATE(state) \ 22 | { led_set_green(255 * state); } 23 | #define SET_IDLE_STATE(state) \ 24 | { led_set_blue(255 * state); } 25 | #define SET_ERROR_STATE(state) \ 26 | { led_set_red(255 * state); } 27 | 28 | #define TMS_SET_MODE() \ 29 | do { \ 30 | } while(0) 31 | 32 | #define TMS_PIN (-1) 33 | #define TDI_PIN (-1) 34 | #define TDO_PIN (-1) 35 | #define TCK_PIN (-1) 36 | 37 | #undef PLATFORM_HAS_TRACESWO 38 | #define TRACESWO_PIN 18 39 | 40 | // ON ESP32 we dont have the PORTS, this is dummy value until code is corrected 41 | #define SWCLK_PORT (0) 42 | #define SWCLK_PIN (1) 43 | #define SWDIO_PIN (2) 44 | 45 | #if SWDIO_PIN >= 32 || SWCLK_PIN >= 32 46 | #error To support pins greater than 31, change the platform_gpio functions 47 | #endif 48 | 49 | #define gpio_set_val(port, pin, value) \ 50 | do { \ 51 | platform_gpio_set_level(pin, value); \ 52 | } while(0); 53 | 54 | #define gpio_set(port, pin) platform_gpio_set(pin) 55 | #define gpio_clear(port, pin) platform_gpio_clear(pin) 56 | #define gpio_get(port, pin) platform_gpio_get_level(pin) 57 | 58 | #define SWDIO_MODE_FLOAT() \ 59 | do { \ 60 | platform_swdio_mode_float(); \ 61 | } while(0) 62 | 63 | #define SWDIO_MODE_DRIVE() \ 64 | do { \ 65 | platform_swdio_mode_drive(); \ 66 | } while(0) 67 | -------------------------------------------------------------------------------- /main/cli/cli-args.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cli-args.h" 3 | 4 | size_t cli_args_get_first_word_length(mstring_t* args) { 5 | size_t ws = mstring_search_char(args, ' ', 0); 6 | if(ws == STRING_FAILURE) { 7 | ws = mstring_size(args); 8 | } 9 | 10 | return ws; 11 | } 12 | 13 | size_t cli_args_length(mstring_t* args) { 14 | return mstring_size(args); 15 | } 16 | 17 | bool cli_args_read_int_and_trim(mstring_t* args, int* value) { 18 | size_t cmd_length = cli_args_get_first_word_length(args); 19 | 20 | if(cmd_length == 0) { 21 | return false; 22 | } 23 | 24 | if(sscanf(mstring_get_cstr(args), "%d", value) == 1) { 25 | mstring_right(args, cmd_length); 26 | mstring_strim(args, " \r\n\t"); 27 | return true; 28 | } 29 | 30 | return false; 31 | } 32 | 33 | bool cli_args_read_string_and_trim(mstring_t* args, mstring_t* word) { 34 | size_t cmd_length = cli_args_get_first_word_length(args); 35 | 36 | if(cmd_length == 0) { 37 | return false; 38 | } 39 | 40 | mstring_set_n(word, args, 0, cmd_length); 41 | mstring_right(args, cmd_length); 42 | mstring_strim(args, " \r\n\t"); 43 | 44 | return true; 45 | } 46 | 47 | bool cli_args_read_quoted_string_and_trim(mstring_t* args, mstring_t* word) { 48 | if(mstring_size(args) < 2 || mstring_get_char(args, 0) != '\"') { 49 | return false; 50 | } 51 | 52 | size_t second_quote_pos = mstring_search_char(args, '\"', 1); 53 | 54 | if(second_quote_pos == 0) { 55 | return false; 56 | } 57 | 58 | mstring_set_n(word, args, 1, second_quote_pos - 1); 59 | mstring_right(args, second_quote_pos + 1); 60 | mstring_strim(args, " \r\n\t"); 61 | return true; 62 | } 63 | 64 | bool cli_args_read_probably_quoted_string_and_trim(mstring_t* args, mstring_t* word) { 65 | if(mstring_size(args) > 1 && mstring_get_char(args, 0) == '\"') { 66 | return cli_args_read_quoted_string_and_trim(args, word); 67 | } else { 68 | return cli_args_read_string_and_trim(args, word); 69 | } 70 | } -------------------------------------------------------------------------------- /components/soft-uart/soft-uart.c: -------------------------------------------------------------------------------- 1 | #include "soft-uart.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | struct SoftUart { 8 | uint32_t baudrate; 9 | uint32_t bit_time; 10 | uint8_t tx_pin; 11 | bool invert; 12 | }; 13 | 14 | #define wait_cycles(cycles) \ 15 | for(uint32_t start = cycle_count_get(); cycle_count_get() - start < cycles;) 16 | 17 | static inline uint32_t __attribute__((always_inline)) cycle_count_get() { 18 | uint32_t ccount; 19 | __asm__ __volatile__("esync; rsr %0,ccount" : "=a"(ccount)); 20 | return ccount; 21 | } 22 | 23 | void soft_uart_transmit_byte(SoftUart* uart, uint8_t byte) { 24 | if(uart->invert) { 25 | byte = ~byte; 26 | } 27 | 28 | // disable interrupts 29 | portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; 30 | portENTER_CRITICAL(&mux); 31 | 32 | // create tx interrupts to start bit. 33 | gpio_set_level(uart->tx_pin, 1), gpio_set_level(uart->tx_pin, 0); 34 | wait_cycles(uart->bit_time); 35 | 36 | for(uint8_t i = 0; i != 8; i++) { 37 | gpio_set_level(uart->tx_pin, (byte & 1) ? 1 : 0); 38 | wait_cycles(uart->bit_time); 39 | byte >>= 1; 40 | } 41 | 42 | // Stop bit 43 | gpio_set_level(uart->tx_pin, 1); 44 | wait_cycles(uart->bit_time); 45 | 46 | // re-enable interrupts 47 | portEXIT_CRITICAL(&mux); 48 | } 49 | 50 | SoftUart* soft_uart_init(uint32_t baudrate, uint8_t tx_pin) { 51 | SoftUart* uart = malloc(sizeof(SoftUart)); 52 | 53 | uart->baudrate = baudrate; 54 | uart->tx_pin = tx_pin; 55 | uart->invert = false; 56 | 57 | uart->bit_time = (esp_clk_cpu_freq() / uart->baudrate); 58 | 59 | gpio_pad_select_gpio(uart->tx_pin); 60 | gpio_set_direction(uart->tx_pin, GPIO_MODE_OUTPUT); 61 | gpio_set_level(uart->tx_pin, !uart->invert); 62 | return uart; 63 | } 64 | 65 | void soft_uart_transmit(SoftUart* uart, const uint8_t* data, uint32_t data_size) { 66 | for(size_t i = 0; i < data_size; i++) { 67 | soft_uart_transmit_byte(uart, data[i]); 68 | } 69 | } -------------------------------------------------------------------------------- /main/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "usb.h" 8 | #include "nvs.h" 9 | #include "gdb_main.h" 10 | #include "led.h" 11 | #include "cli-uart.h" 12 | #include "i2c.h" 13 | #include "network.h" 14 | #include "network-http.h" 15 | #include "network-gdb.h" 16 | #include "network-uart.h" 17 | #include "factory-reset-service.h" 18 | 19 | #include 20 | #include 21 | 22 | static const char* TAG = "main"; 23 | 24 | void gdb_application_thread(void* pvParameters) { 25 | ESP_LOGI("gdb", "start"); 26 | while(1) { 27 | gdb_main(); 28 | } 29 | ESP_LOGI("gdb", "end"); 30 | } 31 | 32 | #include 33 | #include 34 | 35 | void pins_init() { 36 | gpio_config_t io_conf; 37 | // disable interrupt 38 | io_conf.intr_type = GPIO_PIN_INTR_DISABLE; 39 | // set as output mode 40 | io_conf.mode = GPIO_MODE_OUTPUT; 41 | // bit mask of the pins that you want to set 42 | io_conf.pin_bit_mask = ((1 << SWCLK_PIN) | (1 << SWDIO_PIN)); 43 | // disable pull-down mode 44 | io_conf.pull_down_en = 0; 45 | // disable pull-up mode 46 | io_conf.pull_up_en = 0; 47 | // configure GPIO with the given settings 48 | gpio_config(&io_conf); 49 | } 50 | 51 | void app_main(void) { 52 | // Software UART logging at pin 7, 57600 baud 53 | soft_uart_log_init(7, 57600); 54 | 55 | ESP_LOGI(TAG, "start"); 56 | 57 | factory_reset_service_init(); 58 | 59 | gdb_glue_init(); 60 | 61 | led_init(); 62 | led_set_blue(255); 63 | 64 | nvs_init(); 65 | network_init(); 66 | network_http_server_init(); 67 | network_gdb_server_init(); 68 | network_uart_server_init(); 69 | 70 | usb_init(); 71 | cli_uart_init(); 72 | 73 | // TODO uart and i2c share the same pins, need switching mechanics 74 | // i2c_init(); 75 | // i2c_scan(); 76 | 77 | pins_init(); 78 | xTaskCreate(&gdb_application_thread, "gdb_thread", 4096, NULL, 5, NULL); 79 | led_set_blue(0); 80 | ESP_LOGI(TAG, "end"); 81 | } 82 | -------------------------------------------------------------------------------- /main/i2c.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static gpio_num_t i2c_gpio_sda = 18; 4 | static gpio_num_t i2c_gpio_scl = 17; 5 | static gpio_num_t i2c_pull_enable = 3; 6 | static i2c_port_t i2c_port = I2C_NUM_0; 7 | static uint32_t i2c_frequency = 100000; 8 | 9 | // I2C master doesn't need buffers 10 | #define I2C_MASTER_TX_BUF_DISABLE 0 11 | #define I2C_MASTER_RX_BUF_DISABLE 0 12 | 13 | #define WRITE_BIT I2C_MASTER_WRITE 14 | #define ACK_CHECK_EN 0x1 15 | 16 | void i2c_init(void) { 17 | i2c_driver_install( 18 | i2c_port, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); 19 | 20 | i2c_config_t conf = { 21 | .mode = I2C_MODE_MASTER, 22 | .sda_io_num = i2c_gpio_sda, 23 | .sda_pullup_en = GPIO_PULLUP_ENABLE, 24 | .scl_io_num = i2c_gpio_scl, 25 | .scl_pullup_en = GPIO_PULLUP_ENABLE, 26 | .master.clk_speed = i2c_frequency, 27 | }; 28 | ESP_ERROR_CHECK(i2c_param_config(i2c_port, &conf)); 29 | 30 | gpio_config_t io_conf = {}; 31 | io_conf.intr_type = GPIO_INTR_DISABLE; 32 | io_conf.mode = GPIO_MODE_OUTPUT; 33 | io_conf.pin_bit_mask = (1ULL << i2c_pull_enable); 34 | io_conf.pull_down_en = 0; 35 | io_conf.pull_up_en = 0; 36 | ESP_ERROR_CHECK(gpio_config(&io_conf)); 37 | 38 | // enable pullups 39 | gpio_set_level(i2c_pull_enable, 0); 40 | } 41 | 42 | void i2c_scan(void) { 43 | uint8_t address; 44 | printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); 45 | for(int i = 0; i < 128; i += 16) { 46 | printf("%02x: ", i); 47 | for(int j = 0; j < 16; j++) { 48 | fflush(stdout); 49 | address = i + j; 50 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 51 | i2c_master_start(cmd); 52 | i2c_master_write_byte(cmd, (address << 1) | WRITE_BIT, ACK_CHECK_EN); 53 | i2c_master_stop(cmd); 54 | esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 50 / portTICK_RATE_MS); 55 | i2c_cmd_link_delete(cmd); 56 | if(ret == ESP_OK) { 57 | printf("%02x ", address); 58 | } else if(ret == ESP_ERR_TIMEOUT) { 59 | printf("UU "); 60 | } else { 61 | printf("-- "); 62 | } 63 | } 64 | printf("\r\n"); 65 | } 66 | } -------------------------------------------------------------------------------- /components/svelte-portal/src/tabs/TabPS.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | {#await api.get("/api/v1/system/tasks")} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {:then json} 15 | 16 | Name 17 | State 18 | Handle 19 | Stack base 20 | WMRK 21 | {#each json.list.sort(function (a, b) { 22 | return a.number - b.number; 23 | }) as task} 24 | {task.name} 25 | {task.state} 26 | {task.handle.toString(16).toUpperCase()} 27 | {task.stack_base.toString(16).toUpperCase()} 28 | {task.watermark} 29 | {/each} 30 | 31 | {:catch error} 32 | {error.message} 33 | {/await} 34 | 35 | 77 | -------------------------------------------------------------------------------- /main/cli/cli-args.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cli-args.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-12-01 6 | * 7 | * 8 | */ 9 | 10 | #pragma once 11 | #include 12 | #include 13 | #include 14 | 15 | /** Extract int value and trim arguments string 16 | * @param args - arguments string 17 | * @param word first argument, output 18 | * @return true - success 19 | * @return false - arguments string does not contain int 20 | */ 21 | bool cli_args_read_int_and_trim(mstring_t* args, int* value); 22 | 23 | /** 24 | * @brief Extract first argument from arguments string and trim arguments string 25 | * @param args arguments string 26 | * @param word first argument, output 27 | * @return true - success 28 | * @return false - arguments string does not contain anything 29 | */ 30 | bool cli_args_read_string_and_trim(mstring_t* args, mstring_t* word); 31 | 32 | /** 33 | * @brief Extract the first quoted argument from the argument string and trim the argument string. If the argument is not quoted, returns false. 34 | * @param args arguments string 35 | * @param word first argument, output, without quotes 36 | * @return true - success 37 | * @return false - arguments string does not contain anything or not quoted 38 | */ 39 | bool cli_args_read_quoted_string_and_trim(mstring_t* args, mstring_t* word); 40 | 41 | /** 42 | * @brief Extract the first quoted argument from the argument string and trim the argument string. If the argument is not quoted, calls args_read_string_and_trim. 43 | * @param args arguments string 44 | * @param word first argument, output, without quotes 45 | * @return true - success 46 | * @return false - arguments string does not contain anything 47 | */ 48 | bool cli_args_read_probably_quoted_string_and_trim(mstring_t* args, mstring_t* word); 49 | 50 | /************************************ HELPERS ***************************************/ 51 | 52 | /** 53 | * @brief Get length of first word from arguments string 54 | * @param args arguments string 55 | * @return size_t length of first word 56 | */ 57 | size_t cli_args_get_first_word_length(mstring_t* args); 58 | 59 | /** 60 | * @brief Get length of arguments string 61 | * @param args arguments string 62 | * @return size_t length of arguments string 63 | */ 64 | size_t cli_args_length(mstring_t* args); -------------------------------------------------------------------------------- /components/svelte-portal/rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import resolve from '@rollup/plugin-node-resolve'; 4 | import livereload from 'rollup-plugin-livereload'; 5 | import { terser } from 'rollup-plugin-terser'; 6 | import css from 'rollup-plugin-css-only'; 7 | import replace from "@rollup/plugin-replace"; 8 | 9 | const production = !process.env.ROLLUP_WATCH; 10 | 11 | function serve() { 12 | let server; 13 | 14 | function toExit() { 15 | if (server) server.kill(0); 16 | } 17 | 18 | return { 19 | writeBundle() { 20 | if (server) return; 21 | server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { 22 | stdio: ['ignore', 'inherit', 'inherit'], 23 | shell: true 24 | }); 25 | 26 | process.on('SIGTERM', toExit); 27 | process.on('exit', toExit); 28 | } 29 | }; 30 | } 31 | 32 | export default { 33 | input: 'src/main.js', 34 | output: { 35 | sourcemap: true, 36 | format: 'iife', 37 | name: 'app', 38 | file: 'public/build/bundle.js' 39 | }, 40 | plugins: [ 41 | replace({ 42 | development_mode: !production, 43 | preventAssignment: true, 44 | }), 45 | svelte({ 46 | compilerOptions: { 47 | // enable run-time checks when not in production 48 | dev: !production 49 | } 50 | }), 51 | // we'll extract any component CSS out into 52 | // a separate file - better for performance 53 | css({ output: 'bundle.css' }), 54 | 55 | // If you have external dependencies installed from 56 | // npm, you'll most likely need these plugins. In 57 | // some cases you'll need additional configuration - 58 | // consult the documentation for details: 59 | // https://github.com/rollup/plugins/tree/master/packages/commonjs 60 | resolve({ 61 | browser: true, 62 | dedupe: ['svelte', 'stringview'], 63 | extensions: ['.svelte', '.js', '.mjs'] 64 | }), 65 | commonjs(), 66 | 67 | // In dev mode, call `npm run start` once 68 | // the bundle has been generated 69 | !production && serve(), 70 | 71 | // Watch the `public` directory and refresh the 72 | // browser on changes when not in production 73 | !production && livereload('public'), 74 | 75 | // If we're building for production (npm run build 76 | // instead of npm run dev), minify 77 | production && terser() 78 | ], 79 | watch: { 80 | clearScreen: false 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCES 2 | "main.c" 3 | "usb.c" 4 | "usb-uart.c" 5 | "nvs.c" 6 | "nvs-config.c" 7 | "led.c" 8 | "cli-uart.c" 9 | "i2c.c" 10 | "delay.c" 11 | "network.c" 12 | "network-http.c" 13 | "network-gdb.c" 14 | "network-uart.c" 15 | "cli-uart.c" 16 | "cli/cli.c" 17 | "cli/cli-commands.c" 18 | "cli/cli-commands-gpio.c" 19 | "cli/cli-commands-wifi.c" 20 | "cli/cli-commands-config.c" 21 | "cli/cli-commands-device-info.c" 22 | "cli/cli-args.c" 23 | "soft-uart-log.c" 24 | "factory-reset-service.c" 25 | ) 26 | 27 | set(INCLUDES 28 | "." 29 | ) 30 | 31 | idf_component_register(SRCS ${SOURCES} 32 | INCLUDE_DIRS ${INCLUDES}) 33 | 34 | # Commit 35 | execute_process( 36 | COMMAND git rev-parse --short HEAD 37 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 38 | OUTPUT_VARIABLE FW_GIT_COMMIT 39 | OUTPUT_STRIP_TRAILING_WHITESPACE) 40 | 41 | # Branch 42 | execute_process( 43 | COMMAND git rev-parse --abbrev-ref HEAD 44 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 45 | OUTPUT_VARIABLE FW_GIT_BRANCH 46 | OUTPUT_STRIP_TRAILING_WHITESPACE) 47 | 48 | # Branch number 49 | execute_process( 50 | COMMAND git rev-list --count HEAD 51 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 52 | OUTPUT_VARIABLE FW_GIT_BRANCH_NUM 53 | OUTPUT_STRIP_TRAILING_WHITESPACE) 54 | 55 | # Version 56 | execute_process( 57 | COMMAND git describe --tags --abbrev=0 58 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 59 | OUTPUT_VARIABLE FW_GIT_VERSION 60 | OUTPUT_STRIP_TRAILING_WHITESPACE) 61 | 62 | # Build date 63 | string(TIMESTAMP FW_BUILD_DATE "%d-%m-%Y") 64 | 65 | set(INFO_FLAGS 66 | -DFW_BUILD_DATE="${FW_BUILD_DATE}" 67 | -DFW_GIT_COMMIT="${FW_GIT_COMMIT}" 68 | -DFW_GIT_BRANCH="${FW_GIT_BRANCH}" 69 | -DFW_GIT_BRANCH_NUM="${FW_GIT_BRANCH_NUM}" 70 | -DFW_GIT_VERSION="${FW_GIT_VERSION}" 71 | ) 72 | 73 | message(STATUS "IDF version: ${IDF_VER}") 74 | message(STATUS "FW date: ${FW_BUILD_DATE}") 75 | message(STATUS "FW commit: ${FW_GIT_COMMIT}") 76 | message(STATUS "FW branch: ${FW_GIT_BRANCH}") 77 | message(STATUS "FW branch num: ${FW_GIT_BRANCH_NUM}") 78 | message(STATUS "FW version: ${FW_GIT_VERSION}") 79 | 80 | set_property(SOURCE "cli/cli-commands-device-info.c" APPEND PROPERTY COMPILE_OPTIONS ${INFO_FLAGS}) 81 | set_property(SOURCE "network-http.c" APPEND PROPERTY COMPILE_OPTIONS ${INFO_FLAGS}) -------------------------------------------------------------------------------- /components/svelte-portal/src/lib/SpinnerBig.svelte: -------------------------------------------------------------------------------- 1 | 90 | 91 |
92 | {#each text_pointer as text_line} 93 | {#each text_line as text, i} 94 | {#if text == " "} {:else}{text}{/if} 95 | {#if i < 3} {/if} 96 | {/each} 97 |
98 | {/each} 99 |
100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Black Magic Probe / DapLink for ESP32-S2 2 | 3 | WiFi/USB capable version of the famous BlackMagicProbe (or DapLink) debugger. 4 | 5 | # Clone the Repository 6 | 7 | Clone the repository with: 8 | ```shell 9 | git clone --recursive https://github.com/flipperdevices/blackmagic-esp32-s2.git 10 | ``` 11 | 12 | You must recursively clone the submodules, which `--recursive` will do for you. When you pull new changes, be sure to run `git submodule update --init --recursive`. 13 | 14 | # Develop with ESP-IDF 15 | 16 | Set up __ESP-IDF v4.4__ following [Espressif's instructions](https://docs.espressif.com/projects/esp-idf/en/release-v4.4/esp32/get-started/index.html). Make sure `idf.py` is in your PATH and you can successfully run the program. 17 | 18 | ## Build with ESP-IDF 19 | 20 | In your clone of this repository, run: 21 | ```shell 22 | idf.py build 23 | ``` 24 | > Note: the `sdkconfig` file already configures the project to target the ESP32-S2. You don't need to run `idf.py set-target esp32s2`, which will overwrite some of the necessary settings in `sdkconfig`. 25 | 26 | ## Flash with ESP-IDF 27 | 28 | Connect the dev board to your computer with a USB cable. Find the name of the serial port device on your computer that corresponds to the dev board. See the [Flipper Zero guide] on how to connect to the dev board over USB or [Espressif's guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/establish-serial-connection.html) on how to find the port name. 29 | 30 | Run: 31 | ```shell 32 | idf.py -p flash 33 | ``` 34 | 35 | ## Web interface development 36 | 37 | Web interface is located in `components/svelte-portal` and written in Svelte. To build it, you need to install Node.js and run `npm install` in `components/svelte-portal` directory. Then you can run `npm run dev` to start development server or `npm run build` to build production version. 38 | 39 | Typical workflow is to fix the board's IP address in `components/svelte-portal/src/lib/Api.svelte` and then run `npm run dev`. After that, you can open `http://localhost:5000` in your browser and see changes in the web interface in real time with live reload. 40 | 41 | If you want to change local ip or port, you need to run `export HOST={ip} PORT={port}` before `npm run dev`. 42 | 43 | ```shell 44 | export HOST=127.0.0.1 PORT=3000 45 | npm run dev 46 | ``` 47 | 48 | When you're done, you need to run `npm run build`, `idf.py build` and then `idf.py -p flash`. You can then open `http://blackmagic.local` in your browser and see the changes in the web interface. 49 | ```shell 50 | npm run build 51 | idf.py build 52 | idf.py -p flash 53 | ``` 54 | 55 | 56 | ## Schematic 57 | 58 | [Flipper Zero Wi-Fi Module Schematic](https://cdn.flipperzero.one/Flipper_Zero_WI-FI_Module_V1_Schematic.PDF) 59 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | AccessModifierOffset: -4 2 | AlignAfterOpenBracket: AlwaysBreak 3 | AlignConsecutiveAssignments: false 4 | AlignConsecutiveDeclarations: false 5 | AlignEscapedNewlines: Left 6 | AlignOperands: true 7 | AlignTrailingComments: false 8 | AllowAllParametersOfDeclarationOnNextLine: false 9 | AllowShortBlocksOnASingleLine: Never 10 | AllowShortCaseLabelsOnASingleLine: false 11 | AllowShortFunctionsOnASingleLine: None 12 | AllowShortIfStatementsOnASingleLine: true 13 | AllowShortLoopsOnASingleLine: true 14 | AlwaysBreakAfterDefinitionReturnType: None 15 | AlwaysBreakAfterReturnType: None 16 | AlwaysBreakBeforeMultilineStrings: false 17 | AlwaysBreakTemplateDeclarations: false 18 | BinPackArguments: false 19 | BinPackParameters: false 20 | BreakBeforeBinaryOperators: None 21 | BreakBeforeBraces: Attach 22 | BreakBeforeTernaryOperators: false 23 | BreakConstructorInitializers: BeforeComma 24 | BreakStringLiterals: false 25 | ColumnLimit: 99 26 | CompactNamespaces: false 27 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 28 | ConstructorInitializerIndentWidth: 4 29 | ContinuationIndentWidth: 4 30 | Cpp11BracedListStyle: true 31 | DerivePointerAlignment: false 32 | DisableFormat: false 33 | ExperimentalAutoDetectBinPacking: false 34 | FixNamespaceComments: false 35 | 36 | IncludeBlocks: Preserve 37 | IncludeCategories: 38 | - Regex: '.*' 39 | Priority: 1 40 | IncludeIsMainRegex: '(Test)?$' 41 | IndentCaseLabels: false 42 | IndentPPDirectives: None 43 | IndentWidth: 4 44 | IndentWrappedFunctionNames: true 45 | JavaScriptQuotes: Leave 46 | JavaScriptWrapImports: true 47 | KeepEmptyLinesAtTheStartOfBlocks: false 48 | MacroBlockBegin: '' 49 | MacroBlockEnd: '' 50 | MaxEmptyLinesToKeep: 1 51 | NamespaceIndentation: None 52 | ObjCBinPackProtocolList: Auto 53 | ObjCBlockIndentWidth: 4 54 | ObjCSpaceAfterProperty: true 55 | ObjCSpaceBeforeProtocolList: true 56 | 57 | # Taken from git's rules 58 | PenaltyBreakAssignment: 10 59 | PenaltyBreakBeforeFirstCallParameter: 30 60 | PenaltyBreakComment: 10 61 | PenaltyBreakFirstLessLess: 0 62 | PenaltyBreakString: 10 63 | PenaltyExcessCharacter: 100 64 | PenaltyReturnTypeOnItsOwnLine: 60 65 | 66 | PointerAlignment: Left 67 | ReflowComments: false 68 | SortIncludes: false 69 | SortUsingDeclarations: false 70 | SpaceAfterCStyleCast: false 71 | SpaceAfterTemplateKeyword: true 72 | SpaceBeforeAssignmentOperators: true 73 | SpaceBeforeCtorInitializerColon: true 74 | SpaceBeforeInheritanceColon: true 75 | SpaceBeforeParens: Never 76 | SpaceBeforeRangeBasedForLoopColon: true 77 | SpaceInEmptyParentheses: false 78 | SpacesBeforeTrailingComments: 1 79 | SpacesInAngles: false 80 | SpacesInContainerLiterals: false 81 | SpacesInCStyleCastParentheses: false 82 | SpacesInParentheses: false 83 | SpacesInSquareBrackets: false 84 | Standard: Cpp03 85 | TabWidth: 4 86 | UseTab: Never -------------------------------------------------------------------------------- /main/nvs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "nvs.h" 4 | 5 | #define TAG "nvs" 6 | #define NVS_STORE "nvs_storage" 7 | 8 | void nvs_init(void) { 9 | ESP_LOGI(TAG, "init " NVS_DEFAULT_PART_NAME); 10 | esp_err_t ret = nvs_flash_init_partition(NVS_DEFAULT_PART_NAME); 11 | if(ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { 12 | ESP_LOGI(TAG, "erasing " NVS_DEFAULT_PART_NAME); 13 | ESP_ERROR_CHECK(nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME)); 14 | ret = nvs_flash_init_partition(NVS_DEFAULT_PART_NAME); 15 | } 16 | ESP_ERROR_CHECK(ret); 17 | 18 | ESP_LOGI(TAG, "init " NVS_STORE); 19 | ret = nvs_flash_init_partition(NVS_STORE); 20 | if(ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { 21 | ESP_LOGI(TAG, "erasing " NVS_STORE); 22 | ESP_ERROR_CHECK(nvs_flash_erase_partition(NVS_STORE)); 23 | ret = nvs_flash_init_partition(NVS_STORE); 24 | } 25 | ESP_ERROR_CHECK(ret); 26 | 27 | ESP_LOGI(TAG, "init done"); 28 | } 29 | 30 | void nvs_erase(void) { 31 | ESP_LOGI(TAG, "erasing " NVS_DEFAULT_PART_NAME); 32 | ESP_ERROR_CHECK(nvs_flash_erase()); 33 | ESP_ERROR_CHECK(nvs_flash_init()); 34 | 35 | ESP_LOGI(TAG, "erasing " NVS_STORE); 36 | ESP_ERROR_CHECK(nvs_flash_erase_partition(NVS_STORE)); 37 | ESP_ERROR_CHECK(nvs_flash_init_partition(NVS_STORE)); 38 | 39 | ESP_LOGI(TAG, "erasing done"); 40 | } 41 | 42 | esp_err_t nvs_save_string(const char* key, const mstring_t* value) { 43 | nvs_handle_t nvs_handle; 44 | esp_err_t err; 45 | 46 | do { 47 | err = nvs_open_from_partition(NVS_STORE, "config", NVS_READWRITE, &nvs_handle); 48 | if(err != ESP_OK) break; 49 | 50 | err = nvs_set_str(nvs_handle, key, mstring_get_cstr(value)); 51 | if(err != ESP_OK) break; 52 | 53 | err = nvs_commit(nvs_handle); 54 | if(err != ESP_OK) break; 55 | 56 | nvs_close(nvs_handle); 57 | err = ESP_OK; 58 | } while(0); 59 | 60 | return err; 61 | } 62 | 63 | esp_err_t nvs_load_string(const char* key, mstring_t* value) { 64 | nvs_handle_t nvs_handle; 65 | esp_err_t err; 66 | char* buffer = NULL; 67 | 68 | do { 69 | err = nvs_open_from_partition(NVS_STORE, "config", NVS_READONLY, &nvs_handle); 70 | if(err != ESP_OK) break; 71 | 72 | size_t required_size = 0; 73 | err = nvs_get_str(nvs_handle, key, NULL, &required_size); 74 | if(err != ESP_OK) break; 75 | 76 | buffer = malloc(required_size + sizeof(uint32_t)); 77 | err = nvs_get_str(nvs_handle, key, buffer, &required_size); 78 | if(err != ESP_OK) break; 79 | 80 | mstring_set(value, buffer); 81 | nvs_close(nvs_handle); 82 | err = ESP_OK; 83 | } while(0); 84 | 85 | if(buffer != NULL) free(buffer); 86 | 87 | return err; 88 | } -------------------------------------------------------------------------------- /components/tinyusb/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(REQUIRES esp_rom app_update spi_flash freertos soc driver) 2 | 3 | idf_component_get_property(FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) 4 | 5 | idf_build_get_property(idf_target IDF_TARGET) 6 | 7 | if(${idf_target} STREQUAL "esp32s2") 8 | target_compile_options(${COMPONENT_TARGET} INTERFACE 9 | "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" 10 | ) 11 | endif() 12 | 13 | if(${idf_target} STREQUAL "esp32s3") 14 | target_compile_options(${COMPONENT_TARGET} INTERFACE 15 | "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" 16 | ) 17 | endif() 18 | 19 | target_include_directories(${COMPONENT_TARGET} INTERFACE 20 | "${FREERTOS_ORIG_INCLUDE_PATH}" 21 | "${COMPONENT_DIR}/config/" 22 | "${COMPONENT_DIR}/drivers/" 23 | "${COMPONENT_DIR}/drivers/dual-cdc/" 24 | "${COMPONENT_DIR}/tinyusb/hw/bsp/" 25 | "${COMPONENT_DIR}/tinyusb/src/" 26 | "${COMPONENT_DIR}/tinyusb/src/device" 27 | "${COMPONENT_DIR}/tinyusb/src/class" 28 | ) 29 | 30 | target_sources(${COMPONENT_TARGET} INTERFACE 31 | "${COMPONENT_DIR}/tinyusb/src/tusb.c" 32 | "${COMPONENT_DIR}/tinyusb/src/common/tusb_fifo.c" 33 | "${COMPONENT_DIR}/tinyusb/src/device/usbd.c" 34 | "${COMPONENT_DIR}/tinyusb/src/device/usbd_control.c" 35 | "${COMPONENT_DIR}/tinyusb/src/class/audio/audio_device.c" 36 | "${COMPONENT_DIR}/tinyusb/src/class/bth/bth_device.c" 37 | "${COMPONENT_DIR}/tinyusb/src/class/cdc/cdc_device.c" 38 | "${COMPONENT_DIR}/tinyusb/src/class/cdc/cdc_host.c" 39 | "${COMPONENT_DIR}/tinyusb/src/class/cdc/cdc_rndis_host.c" 40 | "${COMPONENT_DIR}/tinyusb/src/class/dfu/dfu_rt_device.c" 41 | "${COMPONENT_DIR}/tinyusb/src/class/dfu/dfu_device.c" 42 | "${COMPONENT_DIR}/tinyusb/src/class/hid/hid_device.c" 43 | "${COMPONENT_DIR}/tinyusb/src/class/hid/hid_host.c" 44 | "${COMPONENT_DIR}/tinyusb/src/class/midi/midi_device.c" 45 | "${COMPONENT_DIR}/tinyusb/src/class/msc/msc_device.c" 46 | "${COMPONENT_DIR}/tinyusb/src/class/msc/msc_host.c" 47 | "${COMPONENT_DIR}/tinyusb/src/class/net/ncm_device.c" 48 | "${COMPONENT_DIR}/tinyusb/src/class/net/ecm_rndis_device.c" 49 | "${COMPONENT_DIR}/tinyusb/src/class/usbtmc/usbtmc_device.c" 50 | "${COMPONENT_DIR}/tinyusb/src/class/vendor/vendor_device.c" 51 | "${COMPONENT_DIR}/tinyusb/src/class/vendor/vendor_host.c" 52 | "${COMPONENT_DIR}/tinyusb/src/class/video/video_device.c" 53 | "${COMPONENT_DIR}/tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c" 54 | "${COMPONENT_DIR}/tinyusb/src/host/hub.c" 55 | "${COMPONENT_DIR}/tinyusb/src/host/usbh.c" 56 | "${COMPONENT_DIR}/tinyusb/src/host/usbh_control.c" 57 | 58 | "${COMPONENT_DIR}/drivers/usb-glue.c" 59 | 60 | # "${COMPONENT_DIR}/drivers/dual-cdc/dual-cdc-driver.c" 61 | "${COMPONENT_DIR}/drivers/dual-cdc/dual-cdc-descriptors.c" 62 | 63 | # "${COMPONENT_DIR}/drivers/dap-link/vendor_device.c" 64 | "${COMPONENT_DIR}/drivers/dap-link/dap-link-descriptors.c" 65 | ) 66 | -------------------------------------------------------------------------------- /components/blackmagic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(BM_DIR "blackmagic-fw") 2 | set(PLATFORM_DIR "esp32-platform") 3 | 4 | set(BM_SOURCES 5 | 6 | # ${PLATFORM_DIR}/custom/swd-spi-tap.c 7 | ${BM_DIR}/src/platforms/common/swdptap.c 8 | ${BM_DIR}/src/platforms/common/jtagtap.c 9 | ${PLATFORM_DIR}/platform.c 10 | ${PLATFORM_DIR}/gdb-glue.c 11 | ) 12 | 13 | set(BM_TARGETS 14 | ${BM_DIR}/src/target/adiv5.c 15 | ${BM_DIR}/src/target/adiv5_jtagdp.c 16 | ${BM_DIR}/src/target/adiv5_swdp.c 17 | ${BM_DIR}/src/command.c 18 | ${BM_DIR}/src/target/cortexa.c 19 | ${BM_DIR}/src/target/cortexm.c 20 | ${BM_DIR}/src/crc32.c 21 | ${BM_DIR}/src/target/efm32.c 22 | ${BM_DIR}/src/exception.c 23 | 24 | # ${BM_DIR}/src/target/gdb_if.c 25 | ${BM_DIR}/src/gdb_hostio.c 26 | ${BM_DIR}/src/gdb_main.c 27 | ${BM_DIR}/src/gdb_packet.c 28 | ${BM_DIR}/src/target/gdb_reg.c 29 | ${BM_DIR}/src/hex_utils.c 30 | ${BM_DIR}/src/target/jtag_devs.c 31 | ${BM_DIR}/src/target/jtag_scan.c 32 | ${BM_DIR}/src/target/lmi.c 33 | ${BM_DIR}/src/target/lpc_common.c 34 | ${BM_DIR}/src/target/lpc11xx.c 35 | ${BM_DIR}/src/target/lpc17xx.c 36 | ${BM_DIR}/src/target/lpc15xx.c 37 | ${BM_DIR}/src/target/lpc43xx.c 38 | ${BM_DIR}/src/target/lpc546xx.c 39 | ${BM_DIR}/src/target/kinetis.c 40 | ${BM_DIR}/src/main.c 41 | ${BM_DIR}/src/morse.c 42 | ${BM_DIR}/src/target/msp432.c 43 | ${BM_DIR}/src/target/nrf51.c 44 | ${BM_DIR}/src/target/nxpke04.c 45 | 46 | # ${BM_DIR}/src/target/platform.c 47 | ${BM_DIR}/src/remote.c 48 | ${BM_DIR}/src/target/rp.c 49 | ${BM_DIR}/src/target/sam3x.c 50 | ${BM_DIR}/src/target/sam4l.c 51 | ${BM_DIR}/src/target/samd.c 52 | ${BM_DIR}/src/target/samx5x.c 53 | ${BM_DIR}/src/target/sfdp.c 54 | ${BM_DIR}/src/target/stm32f1.c 55 | ${BM_DIR}/src/target/ch32f1.c 56 | ${BM_DIR}/src/target/stm32f4.c 57 | ${BM_DIR}/src/target/stm32h7.c 58 | ${BM_DIR}/src/target/stm32l0.c 59 | ${BM_DIR}/src/target/stm32l4.c 60 | ${BM_DIR}/src/target/stm32g0.c 61 | ${BM_DIR}/src/target/renesas.c 62 | ${BM_DIR}/src/target/target.c 63 | ${BM_DIR}/src/target/target_flash.c 64 | ${BM_DIR}/src/target/target_probe.c 65 | ) 66 | 67 | set(BM_INCLUDE 68 | ${BM_DIR}/src/include 69 | ${BM_DIR}/src/platforms/common 70 | ${BM_DIR}/src/target 71 | ${BM_DIR}/libopencm3/include 72 | ${PLATFORM_DIR} 73 | ) 74 | 75 | # Get the current working branch 76 | execute_process( 77 | COMMAND git describe --always --dirty --tags 78 | WORKING_DIRECTORY ${COMPONENT_DIR}/blackmagic-fw 79 | OUTPUT_VARIABLE BM_GIT_DESC 80 | OUTPUT_STRIP_TRAILING_WHITESPACE) 81 | 82 | message(STATUS "BM version: ${BM_GIT_DESC}") 83 | 84 | idf_component_register(SRCS ${BM_SOURCES} ${BM_TARGETS} 85 | INCLUDE_DIRS ${BM_INCLUDE}) 86 | 87 | target_compile_options(${COMPONENT_LIB} PRIVATE -DPC_HOSTED=0 -DFIRMWARE_VERSION="${BM_GIT_DESC}" -Wno-char-subscripts -Wno-attributes -std=gnu11) -------------------------------------------------------------------------------- /components/blackmagic/esp32-platform/gdb-glue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define GDB_TX_BUFFER_SIZE 4096 9 | #define GDB_RX_BUFFER_SIZE 4096 10 | #define GDB_RX_PACKET_MAX_SIZE 64 11 | #define TAG "gdb-glue" 12 | 13 | typedef struct { 14 | StreamBufferHandle_t rx_stream; 15 | bool rx_stream_full; 16 | uint8_t tx_buffer[GDB_TX_BUFFER_SIZE]; 17 | size_t tx_buffer_index; 18 | } GDBGlue; 19 | 20 | static GDBGlue gdb_glue; 21 | 22 | /* GDB socket */ 23 | bool network_gdb_connected(void); 24 | void network_gdb_send(uint8_t* buffer, size_t size); 25 | 26 | /* USB-CDC */ 27 | void usb_gdb_tx_char(uint8_t c, bool flush); 28 | 29 | size_t gdb_glue_get_free_size(void) { 30 | return xStreamBufferSpacesAvailable(gdb_glue.rx_stream); 31 | } 32 | 33 | void gdb_glue_receive(uint8_t* buffer, size_t size) { 34 | size_t ret = xStreamBufferSend(gdb_glue.rx_stream, buffer, size, portMAX_DELAY); 35 | ESP_ERROR_CHECK(ret != size); 36 | } 37 | 38 | bool gdb_glue_can_receive() { 39 | uint16_t max_len = xStreamBufferSpacesAvailable(gdb_glue.rx_stream); 40 | bool can_receive = true; 41 | 42 | if(max_len <= 0) { 43 | gdb_glue.rx_stream_full = true; 44 | ESP_LOGE(TAG, "Stream is full"); 45 | can_receive = false; 46 | }; 47 | 48 | return can_receive; 49 | } 50 | 51 | size_t gdb_glue_get_packet_size() { 52 | return GDB_RX_PACKET_MAX_SIZE; 53 | } 54 | 55 | const char* gdb_glue_get_bm_version() { 56 | return FIRMWARE_VERSION; 57 | } 58 | 59 | void gdb_glue_init(void) { 60 | gdb_glue.rx_stream = xStreamBufferCreate(GDB_RX_BUFFER_SIZE, 1); 61 | gdb_glue.rx_stream_full = false; 62 | gdb_glue.tx_buffer_index = 0; 63 | } 64 | 65 | unsigned char gdb_if_getchar_to(int timeout) { 66 | uint8_t data; 67 | size_t received = xStreamBufferReceive(gdb_glue.rx_stream, &data, sizeof(uint8_t), timeout); 68 | 69 | if(received == 0) { 70 | return -1; 71 | } 72 | 73 | if(gdb_glue.rx_stream_full && 74 | xStreamBufferSpacesAvailable(gdb_glue.rx_stream) >= GDB_RX_PACKET_MAX_SIZE) { 75 | gdb_glue.rx_stream_full = false; 76 | ESP_LOGW(TAG, "Stream freed"); 77 | } 78 | 79 | return data; 80 | } 81 | 82 | unsigned char gdb_if_getchar(void) { 83 | return gdb_if_getchar_to(portMAX_DELAY); 84 | } 85 | 86 | void gdb_if_putchar(unsigned char c, int flush) { 87 | if(network_gdb_connected()) { 88 | gdb_glue.tx_buffer[gdb_glue.tx_buffer_index] = c; 89 | gdb_glue.tx_buffer_index++; 90 | 91 | if(gdb_glue.tx_buffer_index == GDB_TX_BUFFER_SIZE || flush) { 92 | network_gdb_send(gdb_glue.tx_buffer, gdb_glue.tx_buffer_index); 93 | gdb_glue.tx_buffer_index = 0; 94 | } 95 | } else { 96 | // Not sure why, but I could not get it to work with buffer 97 | usb_gdb_tx_char(c, flush); 98 | } 99 | } -------------------------------------------------------------------------------- /components/mlib/m-string.c: -------------------------------------------------------------------------------- 1 | #include "mlib/m-string.h" 2 | #include "m-string.h" 3 | 4 | struct mstring_t { 5 | string_t str; 6 | }; 7 | 8 | mstring_t* mstring_alloc() { 9 | mstring_t* mstr = malloc(sizeof(mstring_t)); 10 | string_init(mstr->str); 11 | return mstr; 12 | } 13 | 14 | mstring_t* mstring_alloc_set(const char* text) { 15 | mstring_t* mstr = malloc(sizeof(mstring_t)); 16 | string_init(mstr->str); 17 | string_set_str(mstr->str, text); 18 | return mstr; 19 | } 20 | 21 | void mstring_free(mstring_t* mstr) { 22 | string_clear(mstr->str); 23 | free(mstr); 24 | } 25 | 26 | void mstring_set(mstring_t* mstr, const char* text) { 27 | string_set_str(mstr->str, text); 28 | } 29 | 30 | void mstring_reset(mstring_t* mstr) { 31 | string_reset(mstr->str); 32 | } 33 | 34 | void mstring_cat(mstring_t* mstr, const char* text) { 35 | string_cat_str(mstr->str, text); 36 | } 37 | 38 | int mstring_printf(mstring_t* mstr, const char format[], ...) { 39 | va_list args; 40 | va_start(args, format); 41 | int ret = string_vprintf(mstr->str, format, args); 42 | va_end(args); 43 | return ret; 44 | } 45 | 46 | int mstring_vprintf(mstring_t* mstr, const char format[], va_list args) { 47 | return string_vprintf(mstr->str, format, args); 48 | } 49 | 50 | const char* mstring_get_cstr(const mstring_t* mstr) { 51 | return string_get_cstr(mstr->str); 52 | } 53 | 54 | size_t mstring_size(const mstring_t* mstr) { 55 | return string_size(mstr->str); 56 | } 57 | 58 | char mstring_get_char(const mstring_t* mstr, size_t index) { 59 | return string_get_char(mstr->str, index); 60 | } 61 | 62 | int mstring_cmp(const mstring_t* mstr, const mstring_t* mstr2) { 63 | return string_cmp(mstr->str, mstr2->str); 64 | } 65 | 66 | int mstring_cmp_cstr(const mstring_t* mstr, const char* cstr) { 67 | return string_cmp_str(mstr->str, cstr); 68 | } 69 | 70 | void mstring_strim(mstring_t* mstr, const char charac[]) { 71 | string_strim(mstr->str, charac); 72 | } 73 | 74 | size_t mstring_search_char(mstring_t* mstr, char c, size_t start) { 75 | return string_search_char(mstr->str, c, start); 76 | } 77 | 78 | void mstring_set_n(mstring_t* mstr, const mstring_t* mstr_ref, size_t offset, size_t length) { 79 | string_set_n(mstr->str, mstr_ref->str, offset, length); 80 | } 81 | 82 | void mstring_set_strn(mstring_t* mstr, const char str[], size_t n) { 83 | string_set_strn(mstr->str, str, n); 84 | } 85 | 86 | void mstring_push_back(mstring_t* mstr, char c) { 87 | string_push_back(mstr->str, c); 88 | } 89 | 90 | void mstring_right(mstring_t* mstr, size_t index) { 91 | string_right(mstr->str, index); 92 | } 93 | 94 | size_t mstring_count_char(mstring_t* mstr, char c) { 95 | const char* str = string_get_cstr(mstr->str); 96 | size_t count = 0; 97 | 98 | for(size_t i = 0; i < string_size(mstr->str); i++) { 99 | if(str[i] == c) count++; 100 | } 101 | 102 | return count; 103 | } -------------------------------------------------------------------------------- /main/led.c: -------------------------------------------------------------------------------- 1 | #include "led.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define LED_PIN_RED (6) 7 | #define LED_PIN_GREEN (5) 8 | #define LED_PIN_BLUE (4) 9 | 10 | #define LEDC_MODE LEDC_LOW_SPEED_MODE 11 | 12 | #define TAG "led" 13 | 14 | #define LED_PWM_MAX_VAL 256U 15 | 16 | #define LED_RED_MAX_VAL 20U 17 | #define LED_GREEN_MAX_VAL 20U 18 | #define LED_BLUE_MAX_VAL 20U 19 | 20 | typedef enum { 21 | LedChannelRed, 22 | LedChannelGreen, 23 | LedChannelBlue, 24 | } ledc_channel; 25 | 26 | void led_init() { 27 | ESP_LOGI(TAG, "init"); 28 | ledc_timer_config_t ledc_timer = { 29 | .speed_mode = LEDC_MODE, 30 | .timer_num = LEDC_TIMER_0, 31 | .duty_resolution = LEDC_TIMER_8_BIT, 32 | .freq_hz = 5000, // Set output frequency at 5 kHz 33 | .clk_cfg = LEDC_AUTO_CLK}; 34 | ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); 35 | 36 | ledc_channel_config_t ledc_channel_red = { 37 | .speed_mode = LEDC_MODE, 38 | .channel = LedChannelRed, 39 | .timer_sel = LEDC_TIMER_0, 40 | .intr_type = LEDC_INTR_DISABLE, 41 | .gpio_num = LED_PIN_RED, 42 | .duty = LED_PWM_MAX_VAL, // Set duty to 100% 43 | .hpoint = 0}; 44 | ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_red)); 45 | 46 | ledc_channel_config_t ledc_channel_green = { 47 | .speed_mode = LEDC_MODE, 48 | .channel = LedChannelGreen, 49 | .timer_sel = LEDC_TIMER_0, 50 | .intr_type = LEDC_INTR_DISABLE, 51 | .gpio_num = LED_PIN_GREEN, 52 | .duty = LED_PWM_MAX_VAL, // Set duty to 100% 53 | .hpoint = 0}; 54 | ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_green)); 55 | 56 | ledc_channel_config_t ledc_channel_blue = { 57 | .speed_mode = LEDC_MODE, 58 | .channel = LedChannelBlue, 59 | .timer_sel = LEDC_TIMER_0, 60 | .intr_type = LEDC_INTR_DISABLE, 61 | .gpio_num = LED_PIN_BLUE, 62 | .duty = LED_PWM_MAX_VAL, // Set duty to 100% 63 | .hpoint = 0}; 64 | ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_blue)); 65 | ESP_LOGI(TAG, "init done"); 66 | } 67 | 68 | void led_set(uint8_t red, uint8_t green, uint8_t blue) { 69 | led_set_red(red); 70 | led_set_green(green); 71 | led_set_blue(blue); 72 | } 73 | 74 | void led_set_red(uint8_t value) { 75 | uint32_t pwm_value = ((uint32_t)value * LED_RED_MAX_VAL) / 255; 76 | ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LedChannelRed, LED_PWM_MAX_VAL - pwm_value)); 77 | ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LedChannelRed)); 78 | } 79 | 80 | void led_set_green(uint8_t value) { 81 | uint32_t pwm_value = ((uint32_t)value * LED_GREEN_MAX_VAL) / 255; 82 | ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LedChannelGreen, LED_PWM_MAX_VAL - pwm_value)); 83 | ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LedChannelGreen)); 84 | } 85 | 86 | void led_set_blue(uint8_t value) { 87 | uint32_t pwm_value = ((uint32_t)value * LED_BLUE_MAX_VAL) / 255; 88 | ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LedChannelBlue, LED_PWM_MAX_VAL - pwm_value)); 89 | ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LedChannelBlue)); 90 | } 91 | -------------------------------------------------------------------------------- /components/simple-uart/simple-uart.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file uart.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-12-17 6 | * 7 | * 8 | */ 9 | #pragma once 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define UART_NUM_0 (0) /*!< UART port 0 */ 16 | #define UART_NUM_1 (1) /*!< UART port 1 */ 17 | #define UART_NUM_MAX (SOC_UART_NUM) 18 | 19 | typedef void (*uart_isr)(void* context); 20 | 21 | typedef struct { 22 | uint8_t uart_num; /*!< UART index */ 23 | uint32_t baud_rate; /*!< UART baud rate*/ 24 | uart_word_length_t data_bits; /*!< UART byte size*/ 25 | uart_parity_t parity; /*!< UART parity mode*/ 26 | uart_stop_bits_t stop_bits; /*!< UART stop bits*/ 27 | int tx_pin_num; /*!< UART tx pin*/ 28 | int rx_pin_num; /*!< UART rx pin*/ 29 | void* isr_context; /*!< UART isr context*/ 30 | uart_isr rx_isr; /*!< UART isr callback*/ 31 | } UartConfig; 32 | 33 | /** 34 | * Init UART driver 35 | * @param config 36 | */ 37 | void simple_uart_init(UartConfig* config); 38 | 39 | /** 40 | * Write data to UART 41 | * @param uart_num 42 | * @param data 43 | * @param data_size 44 | */ 45 | void simple_uart_write(uint8_t uart_num, const uint8_t* data, const uint32_t data_size); 46 | 47 | /** 48 | * Check if rx data available 49 | * @param uart_num 50 | * @return true 51 | * @return false 52 | */ 53 | bool simple_uart_available(uint8_t uart_num); 54 | 55 | /** 56 | * Read rx data 57 | * @param uart_num 58 | * @param data 59 | * @param data_size 60 | * @return uint32_t 61 | */ 62 | uint32_t simple_uart_read(uint8_t uart_num, uint8_t* data, const uint32_t data_size); 63 | 64 | /** 65 | * Set UART baud rate 66 | * @param uart_num 67 | * @param baud_rate 68 | */ 69 | void simple_uart_set_baud_rate(uint8_t uart_num, uint32_t baud_rate); 70 | 71 | /** 72 | * Set UART stop bits 73 | * @param uart_num 74 | * @param stop_bits 75 | */ 76 | void simple_uart_set_stop_bits(uint8_t uart_num, uart_stop_bits_t stop_bits); 77 | 78 | /** 79 | * Set UART parity 80 | * @param uart_num 81 | * @param parity 82 | */ 83 | void simple_uart_set_parity(uint8_t uart_num, uart_parity_t parity); 84 | 85 | /** 86 | * Set UART data bits 87 | * @param uart_num 88 | * @param data_bits 89 | */ 90 | void simple_uart_set_data_bits(uint8_t uart_num, uart_word_length_t data_bits); 91 | 92 | /** 93 | * @brief Get the UART baud rate 94 | * 95 | * @param uart_num 96 | * @return uint32_t 97 | */ 98 | uint32_t simple_uart_get_baud_rate(uint8_t uart_num); 99 | 100 | /** 101 | * @brief Get the UART stop bits 102 | * 103 | * @param uart_num 104 | * @return uart_stop_bits_t 105 | */ 106 | uart_stop_bits_t simple_uart_get_stop_bits(uint8_t uart_num); 107 | 108 | /** 109 | * @brief Get the UART parity 110 | * 111 | * @param uart_num 112 | * @return uart_parity_t 113 | */ 114 | uart_parity_t simple_uart_get_parity(uint8_t uart_num); 115 | 116 | /** 117 | * @brief Get the UART data bits 118 | * 119 | * @param uart_num 120 | * @return uart_word_length_t 121 | */ 122 | uart_word_length_t simple_uart_get_data_bits(uint8_t uart_num); -------------------------------------------------------------------------------- /main/cli-uart.c: -------------------------------------------------------------------------------- 1 | // #include 2 | // #include 3 | #include 4 | #include "led.h" 5 | #include "cli/cli.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define CLI_UART_PORT_NUM UART_NUM_1 12 | #define CLI_UART_TXD_PIN (17) 13 | #define CLI_UART_RXD_PIN (18) 14 | #define CLI_UART_BAUD_RATE (115200) 15 | #define CLI_UART_TX_BUF_SIZE (64) 16 | #define CLI_UART_RX_BUF_SIZE (64) 17 | 18 | static Cli* cli_uart; 19 | static uint8_t uart_tx_buffer[CLI_UART_TX_BUF_SIZE]; 20 | static size_t uart_tx_index = 0; 21 | static StreamBufferHandle_t uart_rx_stream; 22 | 23 | static void cli_uart_write(const uint8_t* data, size_t data_size, void* context); 24 | static void cli_uart_flush(void* context); 25 | 26 | static void cli_uart_rx_isr(void* context); 27 | 28 | static void cli_uart_rx_task(void* pvParameters) { 29 | while(1) { 30 | uint8_t data[CLI_UART_RX_BUF_SIZE]; 31 | size_t length = 32 | xStreamBufferReceive(uart_rx_stream, data, CLI_UART_RX_BUF_SIZE, portMAX_DELAY); 33 | if(length > 0) { 34 | for(size_t i = 0; i < length; i++) { 35 | cli_handle_char(cli_uart, data[i]); 36 | } 37 | } 38 | } 39 | } 40 | 41 | void cli_uart_init() { 42 | cli_uart = cli_init(); 43 | cli_set_write_cb(cli_uart, cli_uart_write); 44 | cli_set_flush_cb(cli_uart, cli_uart_flush); 45 | 46 | uart_rx_stream = xStreamBufferCreate(CLI_UART_RX_BUF_SIZE * 4, 1); 47 | 48 | xTaskCreate(cli_uart_rx_task, "cli_uart_rx", 4096, NULL, 5, NULL); 49 | 50 | UartConfig config = { 51 | .uart_num = CLI_UART_PORT_NUM, 52 | .baud_rate = CLI_UART_BAUD_RATE, 53 | .data_bits = UART_DATA_8_BITS, 54 | .parity = UART_PARITY_DISABLE, 55 | .stop_bits = UART_STOP_BITS_1, 56 | .tx_pin_num = CLI_UART_TXD_PIN, 57 | .rx_pin_num = CLI_UART_RXD_PIN, 58 | .isr_context = uart_rx_stream, 59 | .rx_isr = cli_uart_rx_isr, 60 | }; 61 | 62 | simple_uart_init(&config); 63 | 64 | cli_force_motd(cli_uart); 65 | } 66 | 67 | static void cli_uart_write(const uint8_t* data, size_t data_size, void* context) { 68 | for(size_t i = 0; i < data_size; i++) { 69 | uart_tx_buffer[uart_tx_index] = data[i]; 70 | uart_tx_index++; 71 | 72 | if(uart_tx_index == CLI_UART_TX_BUF_SIZE) { 73 | cli_uart_flush(NULL); 74 | } 75 | } 76 | } 77 | 78 | static void cli_uart_flush(void* context) { 79 | if(uart_tx_index > 0) { 80 | simple_uart_write(CLI_UART_PORT_NUM, uart_tx_buffer, uart_tx_index); 81 | } 82 | 83 | uart_tx_index = 0; 84 | } 85 | 86 | static void cli_uart_rx_isr(void* context) { 87 | StreamBufferHandle_t stream = context; 88 | BaseType_t xHigherPriorityTaskWoken = pdFALSE; 89 | 90 | uint8_t data; 91 | while(simple_uart_available(CLI_UART_PORT_NUM)) { 92 | simple_uart_read(CLI_UART_PORT_NUM, &data, 1); 93 | 94 | size_t ret __attribute__((unused)); 95 | ret = xStreamBufferSendFromISR(stream, &data, 1, &xHigherPriorityTaskWoken); 96 | // we will drop data if the stream overflows 97 | // ESP_ERROR_CHECK(ret != 1); 98 | } 99 | 100 | portYIELD_FROM_ISR(xHigherPriorityTaskWoken); 101 | } -------------------------------------------------------------------------------- /components/svelte-portal/src/tabs/TabSys.svelte: -------------------------------------------------------------------------------- 1 | 30 | 31 | 38 | 39 | {#await api.get("/api/v1/system/info")} 40 | 41 | 42 | 43 | 44 | 45 | info 46 | 47 | 48 | 49 | 50 | 51 | info 52 | 53 | 54 | 55 | 56 | {:then json} 57 | {print_ip(json.ip)} 58 | {print_mac(json.mac)} 59 | {json.idf_version} 60 | 61 | {json.firmware_branch}#{json.firmware_commit} 62 | 63 | 64 | {json.firmware_version}/{json.firmware_branch_num}/{json.firmware_build_date} 65 | 66 | 67 | {json.model}.{json.revision} 68 | {json.cores}-core 69 | 70 | 71 | info 72 | {json.heap.minimum_free_bytes} 73 | {json.heap.total_free_bytes} 74 | {json.heap.total_allocated_bytes} 75 | {json.heap.largest_free_block} 76 | 77 | info 78 | {json.psram_heap.minimum_free_bytes} 79 | {json.psram_heap.total_free_bytes} 80 | {json.psram_heap.total_allocated_bytes} 81 | {json.psram_heap.largest_free_block} 82 | {:catch error} 83 | {error.message} 84 | {/await} 85 | 86 | -------------------------------------------------------------------------------- /main/factory-reset-service.c: -------------------------------------------------------------------------------- 1 | #include "driver/gpio.h" 2 | #include 3 | #include 4 | #include "freertos/FreeRTOS.h" 5 | #include "freertos/timers.h" 6 | #include "led.h" 7 | #include "nvs.h" 8 | 9 | #define BOOT_PIN (0) 10 | #define ESP_INTR_FLAG_DEFAULT 0 11 | 12 | #define RESET_TIMER_TICK 250 13 | #define RESET_TIMER_TICKS_TO_RESET 40 14 | 15 | // static timer 16 | static StaticTimer_t reset_timer_data; 17 | static TimerHandle_t reset_timer; 18 | static size_t reset_counter = 0; 19 | 20 | static void start_reset_timer() { 21 | BaseType_t xHigherPriorityTaskWoken = pdFALSE; 22 | 23 | if(xPortInIsrContext()) { 24 | xTimerStartFromISR(reset_timer, &xHigherPriorityTaskWoken); 25 | } else { 26 | xTimerStart(reset_timer, portMAX_DELAY); 27 | } 28 | 29 | if(xHigherPriorityTaskWoken != pdFALSE) { 30 | portYIELD_FROM_ISR(pdTRUE); 31 | } 32 | } 33 | 34 | static void stop_reset_timer() { 35 | BaseType_t xHigherPriorityTaskWoken = pdFALSE; 36 | 37 | if(xPortInIsrContext()) { 38 | xTimerStopFromISR(reset_timer, &xHigherPriorityTaskWoken); 39 | } else { 40 | xTimerStop(reset_timer, portMAX_DELAY); 41 | } 42 | 43 | reset_counter = 0; 44 | led_set(0, 0, 0); 45 | 46 | if(xHigherPriorityTaskWoken != pdFALSE) { 47 | portYIELD_FROM_ISR(pdTRUE); 48 | } 49 | } 50 | 51 | static void IRAM_ATTR boot_button_isr_handler(void* arg) { 52 | if(gpio_get_level(BOOT_PIN) == 0) { 53 | start_reset_timer(); 54 | } else { 55 | stop_reset_timer(); 56 | } 57 | } 58 | 59 | static void reset_timer_cb(TimerHandle_t xTimer) { 60 | (void)xTimer; 61 | 62 | if(gpio_get_level(BOOT_PIN) == 1) { 63 | stop_reset_timer(); 64 | } else { 65 | reset_counter++; 66 | 67 | uint8_t led_color = 0; 68 | if(reset_counter < (RESET_TIMER_TICKS_TO_RESET / 2)) { 69 | // slow blink 70 | if(reset_counter % 4 < 2) { 71 | led_color = 0xFF; 72 | } 73 | } else { 74 | // fast blink 75 | if(reset_counter % 2 != 0) { 76 | led_color = 0xFF; 77 | } 78 | } 79 | 80 | if(reset_counter > RESET_TIMER_TICKS_TO_RESET) { 81 | stop_reset_timer(); 82 | 83 | led_set(255, 0, 0); 84 | 85 | // waiting for button release 86 | while(gpio_get_level(BOOT_PIN) == 0) { 87 | } 88 | 89 | led_set(0, 255, 0); 90 | nvs_erase(); 91 | led_set(0, 0, 255); 92 | esp_restart(); 93 | 94 | } else { 95 | led_set(led_color, led_color, led_color); 96 | } 97 | } 98 | } 99 | 100 | void factory_reset_service_init(void) { 101 | gpio_config_t io_conf; 102 | memset(&io_conf, 0, sizeof(gpio_config_t)); 103 | 104 | io_conf.intr_type = GPIO_INTR_ANYEDGE; 105 | io_conf.mode = GPIO_MODE_INPUT; 106 | io_conf.pin_bit_mask = ((1 << BOOT_PIN)); 107 | io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; 108 | io_conf.pull_up_en = GPIO_PULLUP_DISABLE; 109 | gpio_config(&io_conf); 110 | 111 | // install gpio isr service 112 | gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); 113 | // attach interrupt 114 | gpio_isr_handler_add(BOOT_PIN, boot_button_isr_handler, (void*)BOOT_PIN); 115 | 116 | // soft timers 117 | reset_timer = xTimerCreateStatic( 118 | NULL, pdMS_TO_TICKS(RESET_TIMER_TICK), true, NULL, reset_timer_cb, &reset_timer_data); 119 | } 120 | -------------------------------------------------------------------------------- /components/mlib/m-string.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file m-string.h 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-11-21 6 | * 7 | * M*Lib string wrapper, to prevent inline code pollution 8 | */ 9 | #pragma once 10 | #include 11 | #include 12 | 13 | typedef struct mstring_t mstring_t; 14 | 15 | #define STRING_FAILURE ((size_t)-1) 16 | 17 | /** 18 | * Allocate string 19 | * @return mstring_t* 20 | */ 21 | mstring_t* mstring_alloc(); 22 | 23 | /** 24 | * Allocate string and set value 25 | * @param text 26 | * @return mstring_t* 27 | */ 28 | mstring_t* mstring_alloc_set(const char* text); 29 | 30 | /** 31 | * Free string 32 | * @param mstr 33 | */ 34 | void mstring_free(mstring_t* mstr); 35 | 36 | /** 37 | * Set string value 38 | * @param mstr 39 | * @param text 40 | */ 41 | void mstring_set(mstring_t* mstr, const char* text); 42 | 43 | /** 44 | * Reset string value 45 | * @param mstr 46 | * @param text 47 | */ 48 | void mstring_reset(mstring_t* mstr); 49 | 50 | /** 51 | * Concatenate value 52 | * @param mstr 53 | * @param text 54 | */ 55 | void mstring_cat(mstring_t* mstr, const char* text); 56 | 57 | /** 58 | * Printf string value 59 | * @param mstr 60 | * @param format 61 | * @param ... 62 | * @return int 63 | */ 64 | int mstring_printf(mstring_t* mstr, const char format[], ...); 65 | 66 | /** 67 | * 68 | * @param mstr 69 | * @param format 70 | * @param args 71 | * @return int 72 | */ 73 | int mstring_vprintf(mstring_t* mstr, const char format[], va_list args); 74 | 75 | /** 76 | * Get constant pointer to string value 77 | * @param mstr 78 | * @return const char* 79 | */ 80 | const char* mstring_get_cstr(const mstring_t* mstr); 81 | 82 | /** 83 | * Get constant pointer to string value 84 | * @param mstr 85 | * @return size_t 86 | */ 87 | size_t mstring_size(const mstring_t* mstr); 88 | 89 | /** 90 | * Get char at index 91 | * @param mstr 92 | * @param index 93 | * @return char 94 | */ 95 | char mstring_get_char(const mstring_t* mstr, size_t index); 96 | 97 | /** 98 | * Compare the string to the other string 99 | * @param mstr 100 | * @param mstr2 101 | * @return int 102 | */ 103 | int mstring_cmp(const mstring_t* mstr, const mstring_t* mstr2); 104 | 105 | /** 106 | * Compare the string to the C string 107 | * @param mstr 108 | * @param cstr 109 | * @return int 110 | */ 111 | int mstring_cmp_cstr(const mstring_t* mstr, const char* cstr); 112 | 113 | /** 114 | * Remove any characters from c_array that are present in the begining of the string and the end of the string 115 | * @param mstr 116 | * @param charac 117 | */ 118 | void mstring_strim(mstring_t* mstr, const char c_array[]); 119 | 120 | /** 121 | * Search for the position of the character c 122 | * from the position 'start' (include) in the string 123 | * Return STRING_FAILURE if not found. 124 | * @param mstr 125 | * @param c 126 | * @param start 127 | * @return size_t 128 | */ 129 | size_t mstring_search_char(mstring_t* mstr, char c, size_t start); 130 | 131 | /** 132 | * Set the string to the n first characters of other one 133 | * @param mstr 134 | * @param mstr_ref 135 | * @param offset 136 | * @param length 137 | */ 138 | void mstring_set_n(mstring_t* mstr, const mstring_t* mstr_ref, size_t offset, size_t length); 139 | 140 | void mstring_set_strn(mstring_t* mstr, const char str[], size_t n); 141 | 142 | void mstring_push_back(mstring_t* mstr, char c); 143 | 144 | void mstring_right(mstring_t* mstr, size_t index); 145 | 146 | size_t mstring_count_char(mstring_t* mstr, char c); -------------------------------------------------------------------------------- /components/blackmagic/esp32-platform/platform.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "freertos/FreeRTOS.h" 3 | #include "freertos/task.h" 4 | #include "general.h" 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | uint32_t swd_delay_cnt = 0; 13 | // static const char* TAG = "gdb-platform"; 14 | 15 | void __attribute__((always_inline)) platform_swdio_mode_float(void) { 16 | // gpio_set_direction(SWDIO_PIN, GPIO_MODE_INPUT); 17 | // gpio_set_pull_mode(SWDIO_PIN, GPIO_FLOATING); 18 | 19 | // Faster variant 20 | gpio_ll_output_disable(&GPIO, SWDIO_PIN); 21 | gpio_ll_input_enable(&GPIO, SWDIO_PIN); 22 | } 23 | 24 | void __attribute__((always_inline)) platform_swdio_mode_drive(void) { 25 | // gpio_set_direction(SWDIO_PIN, GPIO_MODE_OUTPUT); 26 | 27 | // Faster variant 28 | // Supports only gpio less than 32 29 | GPIO.enable_w1ts = (0x1 << SWDIO_PIN); 30 | esp_rom_gpio_connect_out_signal(SWDIO_PIN, SIG_GPIO_OUT_IDX, false, false); 31 | } 32 | 33 | void __attribute__((always_inline)) platform_gpio_set_level(int32_t gpio_num, uint32_t value) { 34 | // gpio_set_level(gpio_num, value); 35 | 36 | // Faster variant 37 | // Supports only gpio less than 32 38 | if(value) { 39 | GPIO.out_w1ts = (1 << gpio_num); 40 | } else { 41 | GPIO.out_w1tc = (1 << gpio_num); 42 | } 43 | } 44 | 45 | void __attribute__((always_inline)) platform_gpio_set(int32_t gpio_num) { 46 | // platform_gpio_set_level(gpio_num, 1); 47 | 48 | // Faster variant 49 | // Supports only gpio less than 32 50 | GPIO.out_w1ts = (1 << gpio_num); 51 | } 52 | 53 | void __attribute__((always_inline)) platform_gpio_clear(int32_t gpio_num) { 54 | // platform_gpio_set_level(gpio_num, 0); 55 | 56 | // faster variant 57 | // supports only gpio less than 32 58 | GPIO.out_w1tc = (1 << gpio_num); 59 | } 60 | 61 | int __attribute__((always_inline)) platform_gpio_get_level(int32_t gpio_num) { 62 | // int level = gpio_get_level(gpio_num); 63 | 64 | // Faster variant 65 | // Supports only gpio less than 32 66 | int level = (GPIO.in >> gpio_num) & 0x1; 67 | return level; 68 | } 69 | 70 | // init platform 71 | void platform_init() { 72 | } 73 | 74 | // set reset target pin level 75 | void platform_srst_set_val(bool assert) { 76 | (void)assert; 77 | } 78 | 79 | // get reset target pin level 80 | bool platform_srst_get_val(void) { 81 | return false; 82 | } 83 | 84 | // target voltage 85 | const char* platform_target_voltage(void) { 86 | return NULL; 87 | } 88 | 89 | // platform time counter 90 | uint32_t platform_time_ms(void) { 91 | int64_t time_milli = esp_timer_get_time() / 1000; 92 | return ((uint32_t)time_milli); 93 | } 94 | 95 | // delay ms 96 | void platform_delay(uint32_t ms) { 97 | vTaskDelay((ms) / portTICK_PERIOD_MS); 98 | } 99 | 100 | // hardware version 101 | int platform_hwversion(void) { 102 | return 0; 103 | } 104 | 105 | // set timeout 106 | void platform_timeout_set(platform_timeout_s* t, uint32_t ms) { 107 | t->time = platform_time_ms() + ms; 108 | } 109 | 110 | // check timeout 111 | bool platform_timeout_is_expired(const platform_timeout_s* t) { 112 | return platform_time_ms() > t->time; 113 | } 114 | 115 | // set interface freq 116 | void platform_max_frequency_set(uint32_t freq) { 117 | } 118 | 119 | // get interface freq 120 | uint32_t platform_max_frequency_get(void) { 121 | return 0; 122 | } 123 | 124 | void platform_nrst_set_val(bool assert) { 125 | (void)assert; 126 | } 127 | 128 | bool platform_nrst_get_val() { 129 | return false; 130 | } 131 | 132 | void platform_target_clk_output_enable(bool enable) { 133 | (void)enable; 134 | } -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: 'Build' 2 | 3 | on: 4 | push: 5 | branches: 6 | - dev 7 | tags: 8 | - '*' 9 | pull_request: 10 | 11 | jobs: 12 | build: 13 | runs-on: [self-hosted,FlipperZeroShell] 14 | steps: 15 | - name: 'Store UID' 16 | id: uid 17 | run: | 18 | echo id="$(id -u $USER)" >> $GITHUB_OUTPUT 19 | 20 | - name: 'Wipe workspace' 21 | run: find ./ -mount -maxdepth 1 -exec rm -rf {} \; 22 | 23 | - name: 'Checkout code' 24 | uses: actions/checkout@v3 25 | with: 26 | ref: ${{ github.event.pull_request.head.sha }} 27 | fetch-depth: 1 28 | 29 | - name: 'Checkout submodules' 30 | run: 31 | git submodule update --init --recursive --depth 1 --jobs "$(getconf _NPROCESSORS_ONLN)"; 32 | 33 | - name: 'Setup python' 34 | uses: actions/setup-python@v4 35 | with: 36 | python-version: '3.11' 37 | 38 | - name: 'Get commit details' 39 | id: names 40 | run: | 41 | if [[ ${{ github.event_name }} == 'pull_request' ]]; then 42 | TYPE="pull" 43 | elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then 44 | TYPE="tag" 45 | else 46 | TYPE="other" 47 | fi 48 | python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" 49 | echo "event_type=$TYPE" >> $GITHUB_OUTPUT 50 | 51 | - name: 'Setup node' 52 | uses: actions/setup-node@v3 53 | with: 54 | node-version: '18' 55 | cache: 'npm' 56 | cache-dependency-path: components/svelte-portal 57 | 58 | - name: 'Install node dependencies' 59 | run: npm install 60 | working-directory: components/svelte-portal 61 | 62 | - name: 'Build captive portal' 63 | run: npm run build 64 | working-directory: components/svelte-portal 65 | 66 | - name: 'Build firmware' 67 | uses: Intake-Health/esp-idf-ci-action@release-v4.4 68 | 69 | - name: 'Fix ownership' 70 | uses: peter-murray/reset-workspace-ownership-action@v1 71 | with: 72 | user_id: ${{ steps.uid.outputs.id }} 73 | 74 | - name: 'Make artifacts directory' 75 | if: ${{ !github.event.pull_request.head.repo.fork }} 76 | run: | 77 | rm -rf artifacts 78 | mkdir artifacts 79 | 80 | - name: 'Move upload files' 81 | if: ${{ !github.event.pull_request.head.repo.fork }} 82 | run: | 83 | mv build/bootloader/bootloader.bin artifacts/ 84 | mv build/partition_table/partition-table.bin artifacts/ 85 | mv build/blackmagic.bin artifacts/ 86 | cp scripts/flash_nix.sh artifacts/ 87 | 88 | - name: 'Generate flash.command file' 89 | if: ${{ !github.event.pull_request.head.repo.fork }} 90 | run: | 91 | echo "esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32s2 write_flash $(tr '\n' ' ' < build/flash_args)" > artifacts/flash.command 92 | sed -i 's/partition_table\///g' artifacts/flash.command 93 | sed -i 's/bootloader\///g' artifacts/flash.command 94 | 95 | - name: 'Generate archive' 96 | if: ${{ !github.event.pull_request.head.repo.fork }} 97 | run: | 98 | mkdir -p "artifacts-archive" 99 | tar -czvf artifacts-archive/blackmagic-firmware-s2-full-${SUFFIX}.tgz -C artifacts/ . 100 | 101 | - name: 'Upload artifacts to update server' 102 | if: ${{ !github.event.pull_request.head.repo.fork }} 103 | run: | 104 | FILES=$(for CUR in $(ls artifacts-archive/); do echo "-F files=@artifacts-archive/$CUR"; done) 105 | curl --fail -L -H "Token: ${{ secrets.INDEXER_TOKEN }}" \ 106 | -F "branch=${BRANCH_NAME}" \ 107 | ${FILES[@]} \ 108 | "${{ secrets.INDEXER_URL }}"/blackmagic-firmware/uploadfiles 109 | -------------------------------------------------------------------------------- /components/tinyusb/drivers/dap-link/vendor_device.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT 2 | * 3 | * Copyright (c) 2022 Koji KITAYAMA 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. */ 22 | 23 | #ifndef _TUSB_VENDOR_DEVICE_H_ 24 | #define _TUSB_VENDOR_DEVICE_H_ 25 | 26 | #include "common/tusb_common.h" 27 | 28 | #ifndef CFG_TUD_VENDOR_EPSIZE 29 | #define CFG_TUD_VENDOR_EPSIZE 64 30 | #endif 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | //--------------------------------------------------------------------+ 37 | // Application API (Multiple Interfaces) 38 | //--------------------------------------------------------------------+ 39 | bool tud_vendor_n_mounted(uint8_t itf); 40 | uint32_t tud_vendor_n_acquire_request_buffer(uint8_t itf, const uint8_t** pbuf); 41 | void tud_vendor_n_release_request_buffer(uint8_t itf); 42 | uint32_t tud_vendor_n_acquire_response_buffer(uint8_t itf, uint8_t** pbuf); 43 | void tud_vendor_n_release_response_buffer(uint8_t itf, uint32_t bufsize); 44 | 45 | //--------------------------------------------------------------------+ 46 | // Application API (Single Port) 47 | //--------------------------------------------------------------------+ 48 | static inline bool tud_vendor_mounted(void); 49 | static inline uint32_t tud_vendor_acquire_request_buffer(const uint8_t** pbuf); 50 | static inline void tud_vendor_release_request_buffer(void); 51 | static inline uint32_t tud_vendor_acquire_response_buffer(uint8_t** pbuf); 52 | static inline void tud_vendor_release_response_buffer(uint32_t bufsize); 53 | 54 | //--------------------------------------------------------------------+ 55 | // Application Callback API (weak is optional) 56 | //--------------------------------------------------------------------+ 57 | 58 | // Invoked when received new data 59 | TU_ATTR_WEAK void tud_vendor_transfer_abort_cb(uint8_t itf); 60 | 61 | //--------------------------------------------------------------------+ 62 | // Inline Functions 63 | //--------------------------------------------------------------------+ 64 | 65 | static inline bool tud_vendor_mounted(void) { 66 | return tud_vendor_n_mounted(0); 67 | } 68 | 69 | static inline uint32_t tud_vendor_acquire_request_buffer(const uint8_t** pbuf) { 70 | return tud_vendor_n_acquire_request_buffer(0, pbuf); 71 | } 72 | 73 | static inline void tud_vendor_release_request_buffer(void) { 74 | return tud_vendor_n_release_request_buffer(0); 75 | } 76 | 77 | static inline uint32_t tud_vendor_acquire_response_buffer(uint8_t** pbuf) { 78 | return tud_vendor_n_acquire_response_buffer(0, pbuf); 79 | } 80 | 81 | static inline void tud_vendor_release_response_buffer(uint32_t bufsize) { 82 | return tud_vendor_n_release_response_buffer(0, bufsize); 83 | } 84 | 85 | //--------------------------------------------------------------------+ 86 | // Internal Class Driver API 87 | //--------------------------------------------------------------------+ 88 | void vendord_init(void); 89 | void vendord_reset(uint8_t rhport); 90 | uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const* itf_desc, uint16_t max_len); 91 | bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif /* _TUSB_VENDOR_DEVICE_H_ */ -------------------------------------------------------------------------------- /components/blackmagic/esp32-platform/custom/swd-spi-tap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file swd-spi-tap.c 3 | * @author Sergey Gavrilov (who.just.the.doctor@gmail.com) 4 | * @version 1.0 5 | * @date 2021-11-25 6 | * 7 | * Does not work due to bug with switching 3-wire mode to RX. 8 | * 9 | * https://github.com/espressif/esp-idf/issues/7800 10 | * 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include "../platform.h" 21 | #include 22 | 23 | #define SWDTAP_DEBUG 0 24 | 25 | typedef enum { 26 | SpiSwdDirFloat, 27 | SpiSwdDirDrive, 28 | } SpiSwdDirection; 29 | 30 | static bool spi_bus_initialized = false; 31 | static spi_device_handle_t swd_spi_device; 32 | 33 | inline static void swd_spi_transmit(spi_transaction_t* swd_spi_transaction) { 34 | ESP_ERROR_CHECK(spi_device_polling_transmit(swd_spi_device, swd_spi_transaction)); 35 | } 36 | 37 | inline static uint32_t swd_spi_rx(int ticks) { 38 | uint32_t data = 0; 39 | spi_transaction_t swd_spi_transaction = { 40 | .rxlength = ticks, 41 | .tx_buffer = NULL, 42 | .rx_buffer = &data, 43 | }; 44 | 45 | swd_spi_transmit(&swd_spi_transaction); 46 | 47 | #if SWDTAP_DEBUG == 1 48 | ESP_LOGW("spi_rx", "< [%02u] 0x%08x", ticks, data); 49 | #endif 50 | 51 | return data; 52 | } 53 | 54 | inline static void swd_spi_tx(uint32_t data, int ticks) { 55 | spi_transaction_t swd_spi_transaction = { 56 | .length = ticks, 57 | .tx_buffer = &data, 58 | .rx_buffer = NULL, 59 | }; 60 | 61 | swd_spi_transmit(&swd_spi_transaction); 62 | 63 | #if SWDTAP_DEBUG == 1 64 | ESP_LOGI("spi_tx", "> [%02u] 0x%08x", ticks, data); 65 | #endif 66 | } 67 | 68 | static void swdspitap_turnaround(SpiSwdDirection direction) { 69 | static SpiSwdDirection old_direction = SpiSwdDirFloat; 70 | 71 | if(direction == old_direction) return; 72 | old_direction = direction; 73 | 74 | swd_spi_tx(1, 1); 75 | } 76 | 77 | static uint32_t swdspitap_seq_in(int ticks) { 78 | swdspitap_turnaround(SpiSwdDirFloat); 79 | return swd_spi_rx(ticks); 80 | } 81 | 82 | static bool swdspitap_seq_in_parity(uint32_t* ret, int ticks) { 83 | swdspitap_turnaround(SpiSwdDirFloat); 84 | *ret = swd_spi_rx(ticks); 85 | int parity = __builtin_popcount(*ret); 86 | uint32_t data = swd_spi_rx(1); 87 | parity += (data & 1); 88 | swdspitap_turnaround(SpiSwdDirDrive); 89 | return (parity & 1); 90 | } 91 | 92 | static void swdspitap_seq_out(uint32_t MS, int ticks) { 93 | swdspitap_turnaround(SpiSwdDirDrive); 94 | swd_spi_tx(MS, ticks); 95 | } 96 | 97 | static void swdspitap_seq_out_parity(uint32_t MS, int ticks) { 98 | int parity = __builtin_popcount(MS); 99 | swdspitap_turnaround(SpiSwdDirDrive); 100 | swd_spi_tx(MS, ticks); 101 | swd_spi_tx(parity & 1, 1); 102 | } 103 | 104 | int swdptap_init(ADIv5_DP_t* dp) { 105 | if(!spi_bus_initialized) { 106 | // config bus 107 | spi_bus_config_t swd_spi_pins = { 108 | .mosi_io_num = SWDIO_PIN, // SWD I/O 109 | .miso_io_num = -1, 110 | .sclk_io_num = SWCLK_PIN, // SWD CLK 111 | .quadwp_io_num = -1, 112 | .quadhd_io_num = -1, 113 | }; 114 | ESP_ERROR_CHECK(spi_bus_initialize(HSPI_HOST, &swd_spi_pins, SPI_DMA_DISABLED)); 115 | 116 | // add device to bus with config 117 | spi_device_interface_config_t swd_spi_config = { 118 | .mode = 0, 119 | .clock_speed_hz = 10 * 1000, 120 | .spics_io_num = -1, 121 | .flags = SPI_DEVICE_3WIRE | SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_BIT_LSBFIRST, 122 | .queue_size = 24, 123 | .pre_cb = NULL, 124 | .post_cb = NULL, 125 | }; 126 | ESP_ERROR_CHECK(spi_bus_add_device(HSPI_HOST, &swd_spi_config, &swd_spi_device)); 127 | 128 | spi_bus_initialized = true; 129 | } 130 | 131 | // set functions 132 | dp->seq_in = swdspitap_seq_in; 133 | dp->seq_in_parity = swdspitap_seq_in_parity; 134 | dp->seq_out = swdspitap_seq_out; 135 | dp->seq_out_parity = swdspitap_seq_out_parity; 136 | 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /scripts/get_env.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import ssl 4 | import json 5 | import os 6 | import shlex 7 | import re 8 | import string 9 | import random 10 | import argparse 11 | import datetime 12 | import urllib.request 13 | 14 | 15 | def id_gen(size=5, chars=string.ascii_uppercase + string.digits): 16 | return "".join(random.choice(chars) for _ in range(size)) 17 | 18 | 19 | def parse_args(): 20 | parser = argparse.ArgumentParser() 21 | parser.add_argument("--event_file", help="Current GitHub event file", required=True) 22 | parser.add_argument( 23 | "--type", 24 | help="Event file type", 25 | required=True, 26 | choices=["pull", "tag", "other"], 27 | ) 28 | args = parser.parse_args() 29 | return args 30 | 31 | 32 | def get_commit_json(event): 33 | context = ssl._create_unverified_context() 34 | commit_url = event["pull_request"]["base"]["repo"]["commits_url"].replace( 35 | "{/sha}", f"/{event['pull_request']['head']['sha']}" 36 | ) 37 | with urllib.request.urlopen(commit_url, context=context) as commit_file: 38 | commit_json = json.loads(commit_file.read().decode("utf-8")) 39 | return commit_json 40 | 41 | 42 | def get_details(event, args): 43 | data = {} 44 | current_time = datetime.datetime.utcnow().date() 45 | if args.type == "pull": 46 | commit_json = get_commit_json(event) 47 | data["commit_comment"] = shlex.quote(commit_json["commit"]["message"]) 48 | data["commit_hash"] = commit_json["sha"] 49 | ref = event["pull_request"]["head"]["ref"] 50 | data["pull_id"] = event["pull_request"]["number"] 51 | data["pull_name"] = shlex.quote(event["pull_request"]["title"]) 52 | elif args.type == "tag": 53 | data["commit_comment"] = shlex.quote(event["head_commit"]["message"]) 54 | data["commit_hash"] = event["head_commit"]["id"] 55 | ref = event["ref"] 56 | else: 57 | data["commit_comment"] = shlex.quote(event["commits"][-1]["message"]) 58 | data["commit_hash"] = event["commits"][-1]["id"] 59 | ref = event["ref"] 60 | data["commit_sha"] = data["commit_hash"][:8] 61 | data["branch_name"] = re.sub("refs/\w+/", "", ref) 62 | data["suffix"] = ( 63 | data["branch_name"].replace("/", "_") 64 | + "-" 65 | + current_time.strftime("%d%m%Y") 66 | + "-" 67 | + data["commit_sha"] 68 | ) 69 | if ref.startswith("refs/tags/"): 70 | data["suffix"] = data["branch_name"].replace("/", "_") 71 | return data 72 | 73 | 74 | def add_env(name, value, file): 75 | delimeter = id_gen() 76 | print(f"{name}<<{delimeter}", file=file) 77 | print(f"{value}", file=file) 78 | print(f"{delimeter}", file=file) 79 | 80 | 81 | def add_set_output_var(name, value, file): 82 | print(f"{name}={value}", file=file) 83 | 84 | 85 | def add_envs(data, gh_env_file, gh_out_file, args): 86 | add_env("COMMIT_MSG", data["commit_comment"], gh_env_file) 87 | add_env("COMMIT_HASH", data["commit_hash"], gh_env_file) 88 | add_env("COMMIT_SHA", data["commit_sha"], gh_env_file) 89 | add_env("SUFFIX", data["suffix"], gh_env_file) 90 | add_env("BRANCH_NAME", data["branch_name"], gh_env_file) 91 | add_env("DIST_SUFFIX", data["suffix"], gh_env_file) 92 | add_env("WORKFLOW_BRANCH_OR_TAG", data["branch_name"], gh_env_file) 93 | add_set_output_var("branch_name", data["branch_name"], gh_out_file) 94 | add_set_output_var("commit_sha", data["commit_sha"], gh_out_file) 95 | add_set_output_var("default_target", os.getenv("DEFAULT_TARGET"), gh_out_file) 96 | add_set_output_var("suffix", data["suffix"], gh_out_file) 97 | if args.type == "pull": 98 | add_env("PULL_ID", data["pull_id"], gh_env_file) 99 | add_env("PULL_NAME", data["pull_name"], gh_env_file) 100 | 101 | 102 | def main(): 103 | args = parse_args() 104 | event_file = open(args.event_file, "r") 105 | event = json.load(event_file) 106 | gh_env_file = open(os.environ["GITHUB_ENV"], "a") 107 | gh_out_file = open(os.environ["GITHUB_OUTPUT"], "a") 108 | data = get_details(event, args) 109 | add_envs(data, gh_env_file, gh_out_file, args) 110 | event_file.close() 111 | gh_env_file.close() 112 | gh_out_file.close() 113 | 114 | 115 | if __name__ == "__main__": 116 | main() 117 | -------------------------------------------------------------------------------- /components/svelte-portal/scripts/setupTypeScript.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** This script modifies the project to support TS code in .svelte files like: 4 | 5 | 8 | 9 | As well as validating the code for CI. 10 | */ 11 | 12 | /** To work on this script: 13 | rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template 14 | */ 15 | 16 | const fs = require("fs") 17 | const path = require("path") 18 | const { argv } = require("process") 19 | 20 | const projectRoot = argv[2] || path.join(__dirname, "..") 21 | 22 | // Add deps to pkg.json 23 | const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) 24 | packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { 25 | "svelte-check": "^2.0.0", 26 | "svelte-preprocess": "^4.0.0", 27 | "@rollup/plugin-typescript": "^8.0.0", 28 | "typescript": "^4.0.0", 29 | "tslib": "^2.0.0", 30 | "@tsconfig/svelte": "^2.0.0" 31 | }) 32 | 33 | // Add script for checking 34 | packageJSON.scripts = Object.assign(packageJSON.scripts, { 35 | "check": "svelte-check --tsconfig ./tsconfig.json" 36 | }) 37 | 38 | // Write the package JSON 39 | fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) 40 | 41 | // mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too 42 | const beforeMainJSPath = path.join(projectRoot, "src", "main.js") 43 | const afterMainTSPath = path.join(projectRoot, "src", "main.ts") 44 | fs.renameSync(beforeMainJSPath, afterMainTSPath) 45 | 46 | // Switch the app.svelte file to use TS 47 | const appSveltePath = path.join(projectRoot, "src", "App.svelte") 48 | let appFile = fs.readFileSync(appSveltePath, "utf8") 49 | appFile = appFile.replace(" 57 | 58 | 59 | {#await api.get("/api/v1/wifi/get_credentials")} 60 | 61 | (join another network) 62 | 63 | 64 | (own access point) 65 | 66 | 67 | 68 | 69 | {:then json} 70 | 71 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | (own access point) 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 |