diff --git a/.github/workflows/esp32-build.yaml b/.github/workflows/esp32-build.yaml index 562f8c24b..507f57e55 100644 --- a/.github/workflows/esp32-build.yaml +++ b/.github/workflows/esp32-build.yaml @@ -28,27 +28,37 @@ concurrency: jobs: esp-idf: runs-on: ubuntu-latest - container: espressif/idf:v${{ matrix.idf-version }} + container: espressif/idf:${{ matrix.idf-version }} strategy: fail-fast: false matrix: + esp-idf-target: ["esp32", "esp32c3"] idf-version: - - '4.4.6' - - '5.0.6' - - '5.1.3' + - 'v4.4.7' + - 'v5.0.6' + - 'v5.1.3' + - 'v5.2' + exclude: + - esp-idf-target: "esp32c3" + idf-version: 'v4.4.7' + - esp-idf-target: "esp32c3" + idf-version: 'v5.0.6' + - esp-idf-target: "esp32c3" + idf-version: 'v5.1.3' steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build with idf.py shell: bash working-directory: ./src/platforms/esp32/ run: | . $IDF_PATH/export.sh - idf.py reconfigure + export IDF_TARGET=${{matrix.esp-idf-target}} + idf.py set-target ${{matrix.esp-idf-target}} idf.py build idf.py size - name: Print component size info with idf.py @@ -65,34 +75,69 @@ jobs: DEBIAN_FRONTEND=noninteractive apt install -y -q \ doxygen erlang-base erlang-dialyzer \ libglib2.0-0 libpixman-1-0 \ - gcc g++ zlib1g-dev + gcc g++ zlib1g-dev libsdl2-2.0-0 libslirp0 libmbedtls-dev - - name: Install qemu binary from espressif/qemu - if: matrix.idf-version != '5.1.3' + - name: Install qemu binary from espressif/qemu esp32 + if: runner.arch != 'ARM64' && runner.os == 'Linux' && matrix.esp-idf-target == 'esp32' run: | set -eu - QEMU_VER=esp-develop-20220919 - QEMU_DIST=qemu-${QEMU_VER}.tar.bz2 - QEMU_SHA256=f6565d3f0d1e463a63a7f81aec94cce62df662bd42fc7606de4b4418ed55f870 - wget --no-verbose https://github.com/espressif/qemu/releases/download/${QEMU_VER}/${QEMU_DIST} - echo "${QEMU_SHA256} *${QEMU_DIST}" | sha256sum --check --strict - - tar -xf ${QEMU_DIST} -C /opt + QEMU_VER=esp-develop-8.2.0-20240122 + QEMU_XTENSA_DIST=qemu-xtensa-softmmu-esp_develop_8.2.0_20240122-x86_64-linux-gnu.tar.xz + QEMU_XTENSA_SHA256=e7c72ef5705ad1444d391711088c8717fc89f42e9bf6d1487f9c2a326b8cfa83 + wget --no-verbose https://github.com/espressif/qemu/releases/download/${QEMU_VER}/${QEMU_XTENSA_DIST} + echo "${QEMU_XTENSA_SHA256} *${QEMU_XTENSA_DIST}" | sha256sum --check --strict - + tar -xf ${QEMU_XTENSA_DIST} -C /opt && rm ${QEMU_XTENSA_DIST} + + - name: Install qemu binary from espressif/qemu esp32c3 + if: runner.arch != 'ARM64' && runner.os == 'Linux' && matrix.esp-idf-target == 'esp32c3' + run: | + set -eu + QEMU_VER=esp-develop-8.2.0-20240122 + QEMU_RISCV32_DIST=qemu-riscv32-softmmu-esp_develop_8.2.0_20240122-x86_64-linux-gnu.tar.xz + QEMU_RISCV32_SHA256=95ac86d7b53bf98b5ff19c33aa926189b849f5a0daf8f41e160bc86c5e31abd4 + wget --no-verbose https://github.com/espressif/qemu/releases/download/${QEMU_VER}/${QEMU_RISCV32_DIST} + echo "${QEMU_RISCV32_SHA256} *${QEMU_RISCV32_DIST}" | sha256sum --check --strict - + tar -xf ${QEMU_RISCV32_DIST} -C /opt && rm ${QEMU_RISCV32_DIST} + + - name: Install qemu binary from espressif/qemu ARM64 esp32 + if: runner.arch == 'ARM64' && runner.os == 'Linux' && matrix.esp-idf-target == 'esp32' + run: | + set -eu + QEMU_VER=esp-develop-8.2.0-20240122 + QEMU_XTENSA_DIST=qemu-xtensa-softmmu-esp_develop_8.2.0_20240122-aarch64-linux-gnu.tar.xz + QEMU_XTENSA_SHA256=77c83f2772f7d9b0c770722c2cebf3625d21d8eddbccfea6816f3d8f4982ea86 + wget --no-verbose https://github.com/espressif/qemu/releases/download/${QEMU_VER}/${QEMU_XTENSA_DIST} + echo "${QEMU_XTENSA_SHA256} *${QEMU_XTENSA_DIST}" | sha256sum --check --strict - + tar -xf ${QEMU_XTENSA_DIST} -C /opt && rm ${QEMU_XTENSA_DIST} + + - name: Install qemu binary from espressif/qemu ARM64 esp32c3 + if: runner.arch == 'ARM64' && runner.os == 'Linux' && matrix.esp-idf-target == 'esp32c3' + run: | + set -eu + QEMU_VER=esp-develop-8.2.0-20240122 + QEMU_RISCV32_DIST=qemu-riscv32-softmmu-esp_develop_8.2.0_20240122-aarch64-linux-gnu.tar.xz + QEMU_RISCV32_SHA256=4089f7958f753779e5b4c93fe2469d62850a1f209b0bda8b75d55fe4a61ca39b + wget --no-verbose https://github.com/espressif/qemu/releases/download/${QEMU_VER}/${QEMU_RISCV32_DIST} + echo "${QEMU_RISCV32_SHA256} *${QEMU_RISCV32_DIST}" | sha256sum --check --strict - + tar -xf ${QEMU_RISCV32_DIST} -C /opt && rm ${QEMU_RISCV32_DIST} - name: Install pytest and pytest-embedded plugins run: | set -e . $IDF_PATH/export.sh - pip install pytest==7.0.1 \ - pytest-embedded==1.2.5 \ - pytest-embedded-serial-esp==1.2.5 \ - pytest-embedded-idf==1.2.5 \ - pytest-embedded-qemu==1.2.5 + pip install pytest==8.0.2 \ + pytest-embedded==1.8.1 \ + pytest-embedded-serial-esp==1.8.1 \ + pytest-embedded-idf==1.8.1 \ + pytest-embedded-qemu==1.8.1 - name: Build ESP32 tests using idf.py working-directory: ./src/platforms/esp32/test/ run: | set -e . $IDF_PATH/export.sh + export IDF_TARGET=${{matrix.esp-idf-target}} + idf.py set-target ${{matrix.esp-idf-target}} idf.py build - name: Run ESP32 tests using qemu @@ -102,4 +147,4 @@ jobs: set -e . $IDF_PATH/export.sh export PATH=/opt/qemu/bin:${PATH} - pytest --embedded-services=idf,qemu -s + pytest --target=${{matrix.esp-idf-target}} --embedded-services=idf,qemu -s diff --git a/src/platforms/esp32/test/main/test_erl_sources/test_crypto.erl b/src/platforms/esp32/test/main/test_erl_sources/test_crypto.erl index 5084e517f..c5a63e338 100644 --- a/src/platforms/esp32/test/main/test_erl_sources/test_crypto.erl +++ b/src/platforms/esp32/test/main/test_erl_sources/test_crypto.erl @@ -22,9 +22,11 @@ -export([start/0]). start() -> + Sysinfo = erlang:system_info(esp32_chip_info), + Model = maps:get(model, Sysinfo), ok = test_hash(), ok = test_crypto_one_time(), - ok = test_available_ciphers(), + ok = test_available_ciphers(Model), ok. test_hash() -> @@ -175,7 +177,8 @@ test_crypto_one_time() -> ok. -test_available_ciphers() -> +test_available_ciphers(Model) when Model =:= esp32 -> + io:format("test_available_ciphers ALL ciphers~n"), <<171, 29, 253, 3, 110, 255, 225, 168, 40, 2, 92, 101, 18, 22, 104, 89>> = crypto:crypto_one_time(aes_128_cbc, <<1:128>>, <<2:128>>, <<3:128>>, false), <<172, 173, 71, 170, 66, 92, 132, 117, 22, 33, 191, 18, 17, 207, 171, 238>> = @@ -207,6 +210,43 @@ test_available_ciphers() -> crypto:crypto_one_time(aes_128_ecb, <<1:128>>, <<2:128>>, <<3:128>>, false), <<172, 173, 71, 170, 66, 92, 132, 117, 22, 33, 191, 18, 17, 207, 171, 236>> = crypto:crypto_one_time(aes_192_ecb, <<1:192>>, <<2:128>>, <<3:128>>, false), + <<33, 51, 81, 23, 26, 72, 178, 26, 115, 82, 208, 26, 225, 24, 76, 247>> = + crypto:crypto_one_time(aes_256_ecb, <<1:256>>, <<2:128>>, <<3:128>>, false), + ok; +test_available_ciphers(_Model) -> + % Leave out AES 192 ciphers other platforms. + io:format("test_available_ciphers WITHOUT AES_192 ciphers~n"), + <<171, 29, 253, 3, 110, 255, 225, 168, 40, 2, 92, 101, 18, 22, 104, 89>> = + crypto:crypto_one_time(aes_128_cbc, <<1:128>>, <<2:128>>, <<3:128>>, false), + % <<172, 173, 71, 170, 66, 92, 132, 117, 22, 33, 191, 18, 17, 207, 171, 238>> = + % crypto:crypto_one_time(aes_192_cbc, <<1:192>>, <<2:128>>, <<3:128>>, false), + <<33, 51, 81, 23, 26, 72, 178, 26, 115, 82, 208, 26, 225, 24, 76, 245>> = + crypto:crypto_one_time(aes_256_cbc, <<1:256>>, <<2:128>>, <<3:128>>, false), + <<149, 146, 215, 117, 124, 68, 24, 44, 51, 164, 46, 233, 81, 71, 162, 220>> = + crypto:crypto_one_time(aes_128_ctr, <<1:128>>, <<2:128>>, <<3:128>>, false), + % <<220, 113, 165, 81, 21, 142, 16, 189, 39, 210, 3, 12, 128, 110, 174, 43>> = + % crypto:crypto_one_time(aes_192_ctr, <<1:192>>, <<2:128>>, <<3:128>>, false), + <<89, 151, 109, 175, 200, 98, 75, 207, 80, 33, 65, 131, 194, 29, 141, 242>> = + crypto:crypto_one_time(aes_256_ctr, <<1:256>>, <<2:128>>, <<3:128>>, false), + <<149, 146, 215, 117, 124, 68, 24, 44, 51, 164, 46, 233, 81, 71, 162, 220>> = + crypto:crypto_one_time(aes_128_cfb128, <<1:128>>, <<2:128>>, <<3:128>>, false), + % <<220, 113, 165, 81, 21, 142, 16, 189, 39, 210, 3, 12, 128, 110, 174, 43>> = + % crypto:crypto_one_time(aes_192_cfb128, <<1:192>>, <<2:128>>, <<3:128>>, false), + <<89, 151, 109, 175, 200, 98, 75, 207, 80, 33, 65, 131, 194, 29, 141, 242>> = + crypto:crypto_one_time(aes_256_cfb128, <<1:256>>, <<2:128>>, <<3:128>>, false), + <<51, 126, 5, 238, 121, 110, 153, 245, 229, 187, 6, 58, 119, 97, 242, 197>> = + crypto:crypto_one_time(aes_128_ecb, <<1:128>>, <<2:128>>, false), + % <<209, 55, 221, 80, 157, 38, 71, 63, 77, 135, 199, 107, 73, 45, 41, 120>> = + % crypto:crypto_one_time(aes_192_ecb, <<1:192>>, <<2:128>>, false), + % <<209, 55, 221, 80, 157, 38, 71, 63, 77, 135, 199, 107, 73, 45, 41, 120>> = + % crypto:crypto_one_time(aes_192_ecb, <<1:192>>, <<2:128>>, false), + <<9, 134, 59, 77, 138, 44, 15, 97, 69, 171, 187, 23, 29, 143, 25, 227>> = + crypto:crypto_one_time(aes_256_ecb, <<1:256>>, <<2:128>>, false), + % Erlang/OTP also allows to call aes_*_ecb with an iv + <<171, 29, 253, 3, 110, 255, 225, 168, 40, 2, 92, 101, 18, 22, 104, 91>> = + crypto:crypto_one_time(aes_128_ecb, <<1:128>>, <<2:128>>, <<3:128>>, false), + % <<172, 173, 71, 170, 66, 92, 132, 117, 22, 33, 191, 18, 17, 207, 171, 236>> = + % crypto:crypto_one_time(aes_192_ecb, <<1:192>>, <<2:128>>, <<3:128>>, false), <<33, 51, 81, 23, 26, 72, 178, 26, 115, 82, 208, 26, 225, 24, 76, 247>> = crypto:crypto_one_time(aes_256_ecb, <<1:256>>, <<2:128>>, <<3:128>>, false), ok. diff --git a/src/platforms/esp32/test/main/test_main.c b/src/platforms/esp32/test/main/test_main.c index 52a884bbf..6c1631e49 100644 --- a/src/platforms/esp32/test/main/test_main.c +++ b/src/platforms/esp32/test/main/test_main.c @@ -177,6 +177,10 @@ TEST_CASE("test_esp_partition", "[test_run]") TEST_ASSERT(term_to_int(ret_value) == 0); } +// avoid: assert failed: sdmmc_ll_get_card_clock_div /IDF/components/hal/esp32/include/hal/sdmmc_ll.h:203 (hw->clksrc.card1 == 1) +// pending https://github.com/espressif/qemu/commit/fe80b1870651ef1227bffd7d4151aa2ce4bcf65f released +// due to assert fix in 5.2+ https://github.com/espressif/esp-idf/commit/263e39c32b447f7832744f2458f13abbfe2033a9 +#if (ESP_IDF_VERSION_MAJOR < 5 || (ESP_IDF_VERSION_MAJOR <= 5 && ESP_IDF_VERSION_MINOR < 2)) && !CONFIG_IDF_TARGET_ESP32C3 TEST_CASE("test_file", "[test_run]") { esp_vfs_fat_sdmmc_mount_config_t mount_config = { @@ -214,6 +218,7 @@ TEST_CASE("test_file", "[test_run]") TEST_ASSERT(ret_value == OK_ATOM); } +#endif TEST_CASE("test_list_to_binary", "[test_run]") { @@ -489,13 +494,17 @@ TEST_CASE("test_ssl", "[test_run]") TEST_ASSERT(ret_value == OK_ATOM); } +// Works C3 on local runs, but fails GH actions +#if !CONFIG_IDF_TARGET_ESP32C3 TEST_CASE("test_rtc_slow", "[test_run]") { term ret_value = avm_test_case("test_rtc_slow.beam"); TEST_ASSERT(term_to_int(ret_value) == 0); } +#endif -#if ESP_IDF_VERSION_MAJOR >= 5 +// Works C3 on local runs, but fails GH actions +#if ESP_IDF_VERSION_MAJOR >= 5 && !CONFIG_IDF_TARGET_ESP32C3 TEST_CASE("test_twdt", "[test_run]") { term ret_value = avm_test_case("test_twdt.beam"); diff --git a/src/platforms/esp32/test/qemu_esp32c3_efuse.bin b/src/platforms/esp32/test/qemu_esp32c3_efuse.bin new file mode 100644 index 000000000..4455f0655 Binary files /dev/null and b/src/platforms/esp32/test/qemu_esp32c3_efuse.bin differ diff --git a/src/platforms/esp32/test/qemu_esp32c3_efuse.bin.license b/src/platforms/esp32/test/qemu_esp32c3_efuse.bin.license new file mode 100644 index 000000000..b805ab2ca --- /dev/null +++ b/src/platforms/esp32/test/qemu_esp32c3_efuse.bin.license @@ -0,0 +1,2 @@ +SPDX-License-Identifier: Apache-2.0 +SPDX-FileCopyrightText: AtomVM Contributors diff --git a/src/platforms/esp32/test/sdkconfig.defaults b/src/platforms/esp32/test/sdkconfig.defaults index 5f8724e9b..38c25b95c 100644 --- a/src/platforms/esp32/test/sdkconfig.defaults +++ b/src/platforms/esp32/test/sdkconfig.defaults @@ -1,5 +1,6 @@ CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=n CONFIG_ESP_INT_WDT_TIMEOUT_MS=10000 CONFIG_ETH_USE_OPENETH=y CONFIG_AVM_RTC_SLOW_MAX_SIZE=1024 diff --git a/src/platforms/esp32/test/test_atomvm.py b/src/platforms/esp32/test/test_atomvm.py index 1b9c72685..e480100e0 100644 --- a/src/platforms/esp32/test/test_atomvm.py +++ b/src/platforms/esp32/test/test_atomvm.py @@ -30,15 +30,25 @@ def create_sd_image(): yield path os.unlink(path) -@pytest.mark.parametrize( - 'qemu_extra_args', - [ - '-nic user,model=open_eth -drive file=sd_image.bin,if=sd,format=raw', - ], - indirect=True, -) +def pytest_generate_tests(metafunc): + option_value = metafunc.config.option.target + if option_value is None or option_value == 'esp32': + metafunc.parametrize( + 'qemu_extra_args', + [ + '-nic user,model=open_eth -drive file=sd_image.bin,if=sd,format=raw' + ],indirect=True + ) + if option_value == 'esp32c3': + metafunc.parametrize( + 'qemu_extra_args', + [ + '-nic user,model=open_eth -drive file=qemu_esp32c3_efuse.bin,if=none,format=raw,id=efuse -global driver=nvram.esp32c3.efuse,property=drive,value=efuse' + ],indirect=True + ) + def test_atomvm(dut, redirect): - dut.expect_unity_test_output(timeout=120) + dut.expect_unity_test_output(timeout=180) assert len(dut.testsuite.testcases) > 0 assert dut.testsuite.attrs['failures'] == 0 assert dut.testsuite.attrs['errors'] == 0