Skip to content

Commit 5cd1b77

Browse files
authored
Merge branch 'master' into fix/ledc-attach-duty-check
2 parents b9664f4 + 4db2edd commit 5cd1b77

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+468
-2392
lines changed

.github/scripts/on-push.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
6060
BUILD_PIO=1
6161
fi
6262

63-
if [ "$BUILD_LOG" -le 0 ]; then
63+
if [ -z "$BUILD_LOG" ] || [ "$BUILD_LOG" -le 0 ]; then
6464
BUILD_LOG=0
6565
fi
6666

.github/scripts/sketch_utils.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [ex
7878

7979
# Default FQBN options if none were passed in the command line.
8080

81-
esp32_opts="PSRAM=enabled,PartitionScheme=huge_app"
81+
esp32_opts="FlashMode=dio,PSRAM=enabled,PartitionScheme=huge_app"
8282
esp32s2_opts="PSRAM=enabled,PartitionScheme=huge_app"
8383
esp32s3_opts="PSRAM=opi,USBMode=default,PartitionScheme=huge_app"
84-
esp32c3_opts="PartitionScheme=huge_app"
84+
esp32c3_opts="FlashMode=dio,PartitionScheme=huge_app"
8585
esp32c6_opts="PartitionScheme=huge_app"
8686
esp32h2_opts="PartitionScheme=huge_app"
8787

.github/scripts/tests_run.sh

+25-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function run_test() {
88
local sketchdir=$(dirname $sketch)
99
local sketchname=$(basename $sketchdir)
1010

11-
if [[ -f "$sketchdir/.skip.$platform" ]]; then
11+
if [[ -f "$sketchdir/.skip.$platform" ]] || [[ -f "$sketchdir/.skip.$target" ]] || [[ -f "$sketchdir/.skip.$platform.$target" ]]; then
1212
echo "Skipping $sketchname test for $target, platform: $platform"
1313
skipfile="$sketchdir/.test_skipped"
1414
touch $skipfile
@@ -45,11 +45,24 @@ function run_test() {
4545
if [[ -f "$sketchdir/scenario.yaml" ]]; then
4646
extra_args+=" --wokwi-scenario $sketchdir/scenario.yaml"
4747
fi
48+
elif [ $platform == "qemu" ]; then
49+
PATH=$HOME/qemu/bin:$PATH
50+
extra_args="--embedded-services qemu --qemu-image-path $build_dir/$sketchname.ino.merged.bin"
51+
52+
if [ $target == "esp32" ] || [ $target == "esp32s3" ]; then
53+
extra_args+=" --qemu-prog-path qemu-system-xtensa --qemu-cli-args=\"-machine $target -m 4M -nographic\""
54+
elif [ $target == "esp32c3" ]; then
55+
extra_args+=" --qemu-prog-path qemu-system-riscv32 --qemu-cli-args=\"-machine $target -icount 3 -nographic\""
56+
else
57+
echo "Unsupported QEMU target: $target"
58+
exit 1
59+
fi
4860
else
4961
extra_args="--embedded-services esp,arduino"
5062
fi
5163

52-
pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args
64+
echo "pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args"
65+
bash -c "pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args"
5366
result=$?
5467
if [ $result -ne 0 ]; then
5568
return $result
@@ -71,6 +84,13 @@ while [ ! -z "$1" ]; do
7184
-c )
7285
chunk_run=1
7386
;;
87+
-q )
88+
if [ ! -d $QEMU_PATH ]; then
89+
echo "QEMU path $QEMU_PATH does not exist"
90+
exit 1
91+
fi
92+
platform="qemu"
93+
;;
7494
-w )
7595
shift
7696
wokwi_timeout=$1
@@ -113,7 +133,9 @@ while [ ! -z "$1" ]; do
113133
shift
114134
done
115135

116-
source ${SCRIPTS_DIR}/install-arduino-ide.sh
136+
if [ ! $platform == "qemu" ]; then
137+
source ${SCRIPTS_DIR}/install-arduino-ide.sh
138+
fi
117139

118140
# If sketch is provided and test type is not, test type is inferred from the sketch path
119141
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then

.github/workflows/hil.yml

+79-8
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,83 @@ jobs:
8686
~/.arduino/tests/**/build*.tmp/*.elf
8787
~/.arduino/tests/**/build*.tmp/*.json
8888
89+
qemu-test:
90+
needs: [gen_chunks, build]
91+
name: ${{matrix.chip}}-QEMU_Test#${{matrix.chunks}}
92+
if: ${{ false }}
93+
strategy:
94+
fail-fast: false
95+
matrix:
96+
chip: ['esp32', 'esp32c3'] # Currently only ESP32 and ESP32-C3 are supported by QEMU
97+
chunks: ${{fromJson(needs.gen_chunks.outputs.chunks)}}
98+
runs-on: ubuntu-latest
99+
env:
100+
QEMU_INSTALL_PATH: "$HOME"
101+
steps:
102+
- name: Checkout repository
103+
uses: actions/checkout@v4
104+
105+
- name: Get QEMU version
106+
uses: pozetroninc/[email protected]
107+
id: get-qemu-version
108+
with:
109+
token: ${{secrets.GITHUB_TOKEN}}
110+
owner: espressif
111+
repo: qemu
112+
excludes: prerelease, draft
113+
114+
- name: Cache tools
115+
id: cache-linux
116+
uses: actions/cache@v4
117+
with:
118+
path: |
119+
~/qemu
120+
~/.cache/pip
121+
key: qemu-${{ steps.get-qemu-version.outputs.release }}-${{ hashFiles('.github/workflows/hil.yml') }}
122+
123+
- name: Install dependencies
124+
run: |
125+
pip install -U pip
126+
pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi
127+
sudo apt update && sudo apt install libpixman-1-0 libnuma1 libglib2.0-0 libslirp0 libsdl2-2.0-0
128+
129+
- name: Download QEMU
130+
if: steps.cache-linux.outputs.cache-hit != 'true'
131+
run: |
132+
cd ${{ env.QEMU_INSTALL_PATH }}
133+
underscore_release=$(echo ${{ steps.get-qemu-version.outputs.release }} | sed 's/\-/_/g')
134+
curl -L https://github.com/espressif/qemu/releases/download/${{ steps.get-qemu-version.outputs.release }}/qemu-riscv32-softmmu-${underscore_release}-x86_64-linux-gnu.tar.xz > qemu-riscv32.tar.xz
135+
curl -L https://github.com/espressif/qemu/releases/download/${{ steps.get-qemu-version.outputs.release }}/qemu-xtensa-softmmu-${underscore_release}-x86_64-linux-gnu.tar.xz > qemu-xtensa.tar.xz
136+
tar -xf qemu-riscv32.tar.xz
137+
tar -xf qemu-xtensa.tar.xz
138+
rm qemu-*
139+
echo "QEMU_PATH=${{ env.QEMU_INSTALL_PATH }}/qemu" >> $GITHUB_ENV
140+
141+
- name: Download ${{matrix.chip}}-${{matrix.chunks}} artifacts
142+
uses: actions/download-artifact@v4
143+
with:
144+
name: ${{matrix.chip}}-${{matrix.chunks}}.artifacts
145+
path: ~/
146+
147+
- name: Run Tests
148+
run: QEMU_PATH="${{env.QEMU_PATH}}" bash .github/scripts/tests_run.sh -c -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}} -q
149+
150+
- name: Check if tests were skipped
151+
id: check-test-skipped
152+
run: |
153+
if [ $(find "tests" -name ".test_skipped") ]; then
154+
echo "skipped=true" >> $GITHUB_OUTPUT
155+
else
156+
echo "skipped=false" >> $GITHUB_OUTPUT
157+
fi
158+
159+
- name: Upload test result artifacts
160+
uses: actions/upload-artifact@v4
161+
if: ${{ always() && steps.check-test-skipped.outputs.skipped == 'false' }}
162+
with:
163+
name: qemu_results-${{matrix.chip}}-${{matrix.chunks}}
164+
path: tests/*/*.xml
165+
89166
wokwi-test:
90167
needs: [gen_chunks, build]
91168
if: github.event_name == 'schedule'
@@ -105,7 +182,7 @@ jobs:
105182
with:
106183
name: ${{matrix.chip}}-${{matrix.chunks}}.artifacts
107184
path: ~/
108-
185+
109186
- name: Install Wokwi CLI
110187
run: curl -L https://wokwi.com/ci/install.sh | sh
111188

@@ -193,16 +270,10 @@ jobs:
193270
194271
event_file:
195272
name: "Event File"
196-
if: |
197-
contains(github.event.pull_request.labels.*.name, 'hil_test') ||
198-
contains(github.event.pull_request.labels.*.name, 'perf_test') ||
199-
github.event_name == 'schedule'
200-
needs: hardware-test
201273
runs-on: ubuntu-latest
202274
steps:
203275
- name: Upload
204276
uses: actions/upload-artifact@v4
205277
with:
206-
name: Event File
278+
name: event_file
207279
path: ${{github.event_path}}
208-

.github/workflows/publish.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ jobs:
3333
uses: EnricoMi/publish-unit-test-result-action@v1
3434
with:
3535
commit: ${{ github.event.workflow_run.head_sha }}
36-
event_file: artifacts/Event File/event.json
36+
event_file: artifacts/event_file/event.json
3737
event_name: ${{ github.event.workflow_run.event }}
3838
files: "artifacts/**/*.xml"

.github/workflows/wokwi.yml

+33-7
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,37 @@ env:
1515
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
1616
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1717

18-
concurrency:
19-
group: wokwi-${{github.event.pull_request.number || github.ref}}
20-
cancel-in-progress: true
21-
2218
jobs:
19+
get_event_file:
20+
name: Get event file
21+
runs-on: ubuntu-latest
22+
outputs:
23+
ref: ${{ steps.get-ref.outputs.ref }}
24+
steps:
25+
- name: Download event file
26+
uses: actions/download-artifact@v4
27+
with:
28+
run-id: ${{github.event.workflow_run.id}}
29+
github-token: ${{env.GITHUB_TOKEN}}
30+
name: event_file
31+
32+
- name: Get ref
33+
id: get-ref
34+
run: |
35+
PR_NUMBER=$(jq -r '.number' event.json)
36+
echo "PR_NUMBER = $PR_NUMBER"
37+
echo "ref=$PR_NUMBER" >> $GITHUB_OUTPUT
38+
2339
gen_chunks:
2440
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
2541
name: Generate Chunks matrix
2642
runs-on: ubuntu-latest
43+
needs: get_event_file
2744
outputs:
2845
chunks: ${{ steps.gen-chunks.outputs.chunks }}
46+
concurrency:
47+
group: wokwi-${{ needs.get_event_file.outputs.ref || github.ref }}
48+
cancel-in-progress: true
2949
steps:
3050
- name: Checkout Repository
3151
uses: actions/checkout@v4
@@ -47,8 +67,11 @@ jobs:
4767
echo "chunks=${CHUNKS}" >>$GITHUB_OUTPUT
4868
4969
wokwi-test:
50-
needs: [gen_chunks]
70+
needs: [get_event_file, gen_chunks]
5171
name: ${{matrix.chip}}-Wokwi_Test#${{matrix.chunks}}
72+
concurrency:
73+
group: wokwi-${{ needs.get_event_file.outputs.ref || github.ref }}-${{matrix.chip}}-${{matrix.chunks}}
74+
cancel-in-progress: true
5275
strategy:
5376
fail-fast: false
5477
matrix:
@@ -101,7 +124,10 @@ jobs:
101124
report-result:
102125
name: Report wokwi test result
103126
runs-on: ubuntu-latest
104-
needs: wokwi-test
127+
needs: [get_event_file, wokwi-test]
128+
concurrency:
129+
group: wokwi-${{ needs.get_event_file.outputs.ref || github.ref }}
130+
cancel-in-progress: true
105131
if: always() && github.event.workflow_run.event == 'pull_request'
106132
steps:
107133
- name: Report result
@@ -127,4 +153,4 @@ jobs:
127153
target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
128154
})).data;
129155
core.info(`${name} is ${state}`);
130-
156+

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@ libraries/Insights/examples/*/*.ino.zip
5050
!.vale/styles/Vocab/
5151
.vale/styles/Vocab/*
5252
!.vale/styles/Vocab/Espressif/
53+
54+
# Ignore Lib Builder Docker run scripts
55+
/run.sh
56+
/run.ps1

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ set(includedirs variants/${CONFIG_ARDUINO_VARIANT}/ cores/esp32/ ${ARDUINO_LIBRA
288288
set(srcs ${CORE_SRCS} ${ARDUINO_LIBRARIES_SRCS})
289289
set(priv_includes cores/esp32/libb64)
290290
set(requires spi_flash esp_partition mbedtls wifi_provisioning wpa_supplicant esp_adc esp_eth http_parser)
291-
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid ${ARDUINO_LIBRARIES_REQUIRES})
291+
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support bt esp_hid usb ${ARDUINO_LIBRARIES_REQUIRES})
292292

293293
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
294294

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ Here are the ESP32 series supported by the Arduino-ESP32 project:
6060
| ESP32-C6 | No | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) |
6161
| ESP32-H2 | No | Yes | [ESP32-H2](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) |
6262

63+
> [!NOTE]
64+
> ESP32-C2 is also supported by Arduino-ESP32 but requires rebuilding the static libraries. This is not trivial and requires a good understanding of the ESP-IDF
65+
> build system. For more information, see the [Lib Builder documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/lib_builder.html).
66+
6367
For more details visit the [supported chips](https://docs.espressif.com/projects/arduino-esp32/en/latest/getting_started.html#supported-soc-s) documentation page.
6468

6569
### Decoding exceptions

cores/esp32/USBMSC.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ extern "C" uint16_t tusb_msc_load_descriptor(uint8_t *dst, uint8_t *itf) {
3333

3434
typedef struct {
3535
bool media_present;
36+
bool is_writable;
3637
uint8_t vendor_id[8];
3738
uint8_t product_id[16];
3839
uint8_t product_rev[4];
@@ -179,11 +180,17 @@ int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, u
179180
return resplen;
180181
}
181182

183+
bool tud_msc_is_writable_cb(uint8_t lun) {
184+
log_v("[%u]: %u", lun, msc_luns[lun].is_writable);
185+
return msc_luns[lun].is_writable; // RAM disk is always ready
186+
}
187+
182188
USBMSC::USBMSC() {
183189
if (MSC_ACTIVE_LUN < MSC_MAX_LUN) {
184190
_lun = MSC_ACTIVE_LUN;
185191
MSC_ACTIVE_LUN++;
186192
msc_luns[_lun].media_present = false;
193+
msc_luns[_lun].is_writable = true;
187194
msc_luns[_lun].vendor_id[0] = 0;
188195
msc_luns[_lun].product_id[0] = 0;
189196
msc_luns[_lun].product_rev[0] = 0;
@@ -213,6 +220,7 @@ bool USBMSC::begin(uint32_t block_count, uint16_t block_size) {
213220

214221
void USBMSC::end() {
215222
msc_luns[_lun].media_present = false;
223+
msc_luns[_lun].is_writable = false;
216224
msc_luns[_lun].vendor_id[0] = 0;
217225
msc_luns[_lun].product_id[0] = 0;
218226
msc_luns[_lun].product_rev[0] = 0;
@@ -247,6 +255,10 @@ void USBMSC::onWrite(msc_write_cb cb) {
247255
msc_luns[_lun].write = cb;
248256
}
249257

258+
void USBMSC::isWritable(bool is_writable) {
259+
msc_luns[_lun].is_writable = is_writable;
260+
}
261+
250262
void USBMSC::mediaPresent(bool media_present) {
251263
msc_luns[_lun].media_present = media_present;
252264
}

cores/esp32/USBMSC.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class USBMSC {
4444
void productID(const char *pid); //max 16 chars
4545
void productRevision(const char *ver); //max 4 chars
4646
void mediaPresent(bool media_present);
47+
void isWritable(bool is_writable);
4748
void onStartStop(msc_start_stop_cb cb);
4849
void onRead(msc_read_cb cb);
4950
void onWrite(msc_write_cb cb);

0 commit comments

Comments
 (0)