diff --git a/.github/workflows/package_core.yml b/.github/workflows/package_core.yml index 0dc5cd6aa..97deb7e2d 100644 --- a/.github/workflows/package_core.yml +++ b/.github/workflows/package_core.yml @@ -407,11 +407,13 @@ jobs: pattern: "*-report-*" merge-multiple: true - - run: | + - name: Generate workflow summary + run: | # gather the array of job metadata (especially name and ID) for the current workflow run export WORKFLOW_JOBS=$(gh run view ${{ github.run_id }} --attempt ${{ github.run_attempt }} --json jobs --jq '.jobs') # Run the log inspection script extra/ci_inspect_logs.py result summary full_log + cat result # Display the summary and full log in the step summary cat summary >> $GITHUB_STEP_SUMMARY @@ -431,6 +433,12 @@ jobs: tar jchf size-reports-${{ needs.build-env.outputs.CORE_HASH }}.tar.bz2 arduino-*.json fi + - name: Compute code size changes + if: ${{ github.event_name == 'pull_request' }} + run: | + export GITHUB_BASE_SHA=$(git describe --always origin/${GITHUB_BASE_REF}) + extra/ci_calc_size_reports.py ${GITHUB_BASE_SHA} sketches-reports/ + # upload comment request artifact (will be retrieved by leave_pr_comment.yml) - name: Archive comment information uses: actions/upload-artifact@v4 @@ -440,6 +448,15 @@ jobs: path: comment-request/ retention-days: 1 + # upload size delta report artifact (will be retrieved by report_size_deltas.yml) + - name: Archive size deltas report information + uses: actions/upload-artifact@v4 + if: ${{ github.event_name == 'pull_request' }} + with: + name: sketches-reports + path: sketches-reports/ + retention-days: 1 + # upload new official test size artifact (for AWS storage) - name: Archive sketch report information uses: actions/upload-artifact@v4 diff --git a/.github/workflows/report_size_deltas.yml b/.github/workflows/report_size_deltas.yml new file mode 100644 index 000000000..adc4abf13 --- /dev/null +++ b/.github/workflows/report_size_deltas.yml @@ -0,0 +1,20 @@ +# Copyright (c) Arduino s.r.l. and/or its affiliated companies +# SPDX-License-Identifier: Apache-2.0 + +name: Report size deltas + +on: + workflow_run: + workflows: ["Package, test and upload core"] + types: + - completed + +permissions: + contents: read + pull-requests: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: arduino/report-size-deltas@v1.1.0 diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 9c57441db..9b0fb402e 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -7,6 +7,21 @@ #include #include "zephyrInternal.h" +#ifdef CONFIG_PINCTRL_DYNAMIC +// create an array of arduino_pins with functions to reinitialize pins if needed +static const struct device *pinmux_array[DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios)] = { + nullptr}; + +void _reinit_peripheral_if_needed(pin_size_t pin, const struct device *dev) { + if (pinmux_array[pin] != dev) { + pinmux_array[pin] = dev; + if (dev != NULL) { + dev->ops.init(dev); + } + } +} +#endif + static const struct gpio_dt_spec arduino_pins[] = { DT_FOREACH_PROP_ELEM_SEP( DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))}; @@ -209,6 +224,9 @@ void yield(void) { * A high physical level will be interpreted as value 1 */ void pinMode(pin_size_t pinNumber, PinMode pinMode) { +#ifdef CONFIG_PINCTRL_DYNAMIC + _reinit_peripheral_if_needed(pinNumber, NULL); +#endif if (pinMode == INPUT) { // input mode gpio_pin_configure_dt(&arduino_pins[pinNumber], GPIO_INPUT | GPIO_ACTIVE_HIGH); } else if (pinMode == INPUT_PULLUP) { // input with internal pull-up @@ -312,6 +330,9 @@ void analogWrite(pin_size_t pinNumber, int value) { return; } +#ifdef CONFIG_PINCTRL_DYNAMIC + _reinit_peripheral_if_needed(pinNumber, arduino_pwm[idx].dev); +#endif value = map(value, 0, 1 << _analog_write_resolution, 0, arduino_pwm[idx].period); if (((uint32_t)value) > arduino_pwm[idx].period) { @@ -335,6 +356,11 @@ void analogWrite(enum dacPins dacName, int value) { return; } + // TODO: add reverse map to find pin name from DAC* define + // In the meantime, consider A0 == DAC0 +#ifdef CONFIG_PINCTRL_DYNAMIC + _reinit_peripheral_if_needed((pin_size_t)(dacName + A0), dac_dev); +#endif dac_channel_setup(dac_dev, &dac_ch_cfg[dacName]); const int max_dac_value = 1U << dac_ch_cfg[dacName].resolution; @@ -385,6 +411,9 @@ int analogRead(pin_size_t pinNumber) { return -ENOTSUP; } +#ifdef CONFIG_PINCTRL_DYNAMIC + _reinit_peripheral_if_needed(pinNumber, arduino_adc[idx].dev); +#endif err = adc_channel_setup(arduino_adc[idx].dev, &arduino_adc[idx].channel_cfg); if (err < 0) { return err; diff --git a/cores/arduino/zephyrInternal.h b/cores/arduino/zephyrInternal.h index b07e1bd9c..30ae255fd 100644 --- a/cores/arduino/zephyrInternal.h +++ b/cores/arduino/zephyrInternal.h @@ -14,6 +14,9 @@ extern "C" { void enableInterrupt(pin_size_t); void disableInterrupt(pin_size_t); +#ifdef CONFIG_PINCTRL_DYNAMIC +void _reinit_peripheral_if_needed(pin_size_t pin, const struct device *dev); +#endif #ifdef __cplusplus } // extern "C" diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index f493047fa..63f86a171 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -59,6 +59,10 @@ void arduino::ZephyrSerial::begin(unsigned long baud, uint16_t conf) { .flow_ctrl = UART_CFG_FLOW_CTRL_NONE, }; +#ifdef CONFIG_PINCTRL_DYNAMIC + uart->ops.init(uart); +#endif + uart_configure(uart, &config); uart_irq_callback_user_data_set(uart, arduino::ZephyrSerial::IrqDispatch, this); k_sem_take(&rx.sem, K_FOREVER); diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index 5e1d15fe7..0f8ba1cd4 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -75,6 +75,11 @@ class ZephyrSerial : public HardwareSerial { void flush(); void end() { +#ifdef CONFIG_DEVICE_DEINIT_SUPPORT + if (uart->ops.deinit) { + uart->ops.deinit(uart); + } +#endif } size_t write(const uint8_t *buffer, size_t size); diff --git a/extra/artifacts/zephyr_unoq.test_setup.sh b/extra/artifacts/zephyr_unoq.test_setup.sh index 7527e2051..064b14ad1 100644 --- a/extra/artifacts/zephyr_unoq.test_setup.sh +++ b/extra/artifacts/zephyr_unoq.test_setup.sh @@ -13,4 +13,9 @@ # copy artifacts under the provided paths. # ArduinoBLE -get_branch_tip libraries arduino-libraries/ArduinoBLE master +get_branch_tip libraries arduino-libraries/ArduinoBLE master \ + examples/Central/LedControl \ + examples/Central/Scan \ + examples/Peripheral/Advertising/EnhancedAdvertising \ + examples/Peripheral/ButtonLED \ + diff --git a/extra/ci_calc_size_reports.py b/extra/ci_calc_size_reports.py new file mode 100755 index 000000000..8bb71e8cc --- /dev/null +++ b/extra/ci_calc_size_reports.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python3 + +# Copyright (c) Arduino s.r.l. and/or its affiliated companies +# SPDX-License-Identifier: Apache-2.0 + +# Script to analyze CI test logs, download previously generated size reports, +# and calculate size deltas in the official JSON report format. +# +# This scripts expects the following arguments: +# - : SHA of the base report to get, used for delta calculation +# - : directory to populate with the delta reports +# +# The script performs the following actions: +# - downloads the previous report archive from AWS +# - extracts it in the output folder +# - for each JSON report file in the output folder: +# - calculates the delta with the corresponding report in the +# current directory (if it exists and both reports are valid) +# - updates the output report file with the delta information. + +from collections import defaultdict +import copy +import json +import os +from pathlib import Path +import requests +import re +import sys +import tarfile + +def extract_url(url, file_pattern, sha, local_path): + """ + Download and extract a tar.bz2 archive from a URL, trying with truncated + versions of the SHA until a match is found. The archive is expected to + contain size reports in JSON format. The extracted files will be placed in + the specified local path. If no archive is found for the given SHA, a + FileNotFoundError is raised. + """ + + session = requests.Session() + + # try with the input SHA, then with truncated versions + # until we find a match or run out of characters + while len(sha) > 6: + file = file_pattern.format(sha) + archive_url = f"{url}/{file}" + archive_path = Path(local_path) / file + try: + os.makedirs(local_path, exist_ok=True) + response = session.get(archive_url) + if response.status_code == 404: + sha = sha[:-1] + continue + # raise other errors + response.raise_for_status() + with open(archive_path, 'wb') as f: + f.write(response.content) + print(f"Downloaded {archive_url}") + break + except Exception as e: + print(f"Error downloading {url}: {e}") + raise + + if not archive_path.exists(): + raise FileNotFoundError(f"Could not find size archive for SHA {sha}") + + try: + with tarfile.open(archive_path, 'r:bz2') as tar: + tar.extractall(path=local_path) + print(f"Extracted {archive_path} to {local_path}") + except Exception as e: + print(f"Error extracting {archive_path}: {e}") + raise + + os.remove(archive_path) + +def update_final_deltas(final, abs_max, delta): + """ + Update the final delta values for a given entry (e.g. "flash" or "RAM for + global variables") based on a new delta calculation from a sketch. + """ + + if not "maximum" in final: + final["maximum"] = abs_max + final["delta"] = {} + for key in delta: # rel/abs + val = delta[key] + final["delta"][key] = { + "minimum": val, + "maximum": val + } + else: + final["maximum"] = max(final["maximum"], abs_max) + for key in delta: # rel/abs + val = delta[key] + final["delta"][key]["minimum"] = min(final["delta"][key]["minimum"], val) + final["delta"][key]["maximum"] = max(final["delta"][key]["maximum"], val) + +def range_str(delta): + """ + Format a delta value (with "absolute" and "relative" keys) as a string for + display in the summary table. + """ + + if not delta: + return "N/A" + + dmin = delta['absolute']['minimum'] + dmax = delta['absolute']['maximum'] + if not dmin and not dmax: + return "===" + + dmin_str = f"{int(dmin)}" if dmin <= 0 else f"+{int(dmin)}" + dmax_str = f"{int(dmax)}" if dmax <= 0 else f"+{int(dmax)}" + if dmin == dmax: + return dmin_str + else: + return f"{dmin_str}..{dmax_str}" + +if not len(sys.argv) == 3: + print("Usage: ci_size_reports.py ") + sys.exit(1) + +prev_sha = sys.argv[1] +output_folder = sys.argv[2] + +headers = [ "Package", "Board", "Options", "Flash", " RAM ", "Tests", f"vs {prev_sha}" ] +formats = [ "{{:<{}}}", "{{:<{}}}", "{{:<{}}}", "{{:^{}}}", "{{:^{}}}", "{{:>{}}}", "{{:<{}}}" ] +data_lines = [] +col_widths = [ len(header) for header in headers ] + +name_regexp = re.compile(r'(libraries|examples)/([^/]+)/(examples/|extras/)?(.*)') + +# get the previous data to the output folder +extract_url("https://downloads.arduino.cc/cores/zephyr/size-reports", + "size-reports-{}.tar.bz2", prev_sha, output_folder) + +# find every JSON file in the output folder +old_jsons = [] +max_package_len = 0 +max_board_len = 0 +max_mode_len = 0 +for dirent in os.scandir(output_folder): + if dirent.is_file() and dirent.name.endswith(".json"): + package, board, opts = dirent.name[:-5].split('-')[1:4] + old_jsons.append(( package, board, opts, dirent )) + +# calculate deltas and update output files +for package, board, opts, dirent in sorted(old_jsons): + with open(dirent.path, 'r') as f: + old_report_data = json.load(f) + # test if the current file exists + if not os.path.exists(dirent.name): + # no: remove the old report to prevent confusion + os.remove(dirent.path) + continue + with open(dirent.name, 'r') as f: + new_report_data = json.load(f) + + # the output file will be a copy of the new data, plus some fields + output_report_data = copy.deepcopy(new_report_data) + sketch_now_missing = 0 + sketch_was_missing = 0 + updated_sketches = 0 + finals = defaultdict(dict) + + output_sketches = output_report_data['boards'][0]['sketches'] + + group_lines = [] + + for sketch in sorted(output_sketches, key=lambda s: s['name']): + match = name_regexp.search(sketch['name']) + display_name = f"{match.group(2)} {match.group(4)}" if match else sketch['name'] + + sketch_ok = sketch['compilation_success'] + old_sketch = next((s for s in old_report_data['boards'][0]['sketches'] if s['name'] == sketch['name']), None) + old_sketch_ok = old_sketch and old_sketch['compilation_success'] + + if not sketch_ok: + # compile time issue in the new data, skip + if old_sketch_ok: + group_lines.append(( display_name, "-- compile failed" )) + sketch_now_missing += 1 + continue + if not old_sketch_ok: + # compile time issue or missing old data, skip + group_lines.append(( display_name, "-- old data missing" )) + sketch_was_missing += 1 + continue + deltas = {} + for entry in sketch['sizes']: # list, name is "flash" or "RAM for global variables" + key = entry['name'] + old_match = next((e for e in old_sketch['sizes'] if e['name'] == entry['name']), None) + if not old_match: + # major group missing in old data, skip + group_lines.append(( display_name, f"-- old group mismatch" )) + continue + # add "previous" data from the old report + entry['previous'] = old_match['current'] + curr_abs = entry['current']['absolute'] + prev_abs = entry['previous']['absolute'] + if isinstance(curr_abs, str) or isinstance(prev_abs, str): + # "N/A", ignore delta for this entry + continue + deltas[key] = entry['delta'] = { + 'absolute': curr_abs - prev_abs, + 'relative': ((curr_abs - prev_abs) * 100 // prev_abs) / 100 if prev_abs > 0 else "N/A" + } + update_final_deltas(finals[key], entry['maximum'], entry['delta']) + + # update display name in output file + sketch['name'] = display_name + + if not deltas: + group_lines.append(( display_name, "-- no matches" )) + else: + updated_sketches += 1 + ram_delta = deltas["RAM for global variables"]['absolute'] if "RAM for global variables" in deltas else "N/A" + flash_delta = deltas["flash"]['absolute'] if "flash" in deltas else "N/A" + group_lines.append(( display_name, f"{flash_delta:6} {ram_delta:6}" )) + + if group_lines: + print(f"::group::{package} {board} {opts}") + max_name_len = max(len(display_name) for display_name, _ in group_lines) + for display_name, text in group_lines: + print(f"{package} {board} {opts} {display_name:{max_name_len}} {text}") + print(f"::endgroup::") + + # update the board-specific 'sizes' list with the new deltas + output_report_data['boards'][0]['sizes'] = [] + for entry_name, final_values in finals.items(): + output_report_data['boards'][0]['sizes'].append({ + "name": entry_name, + **final_values + }) + + # overwite old file with new data + valid deltas + with open(dirent.path, 'w') as f: + json.dump(output_report_data, f, indent=2) + + # generate a line for the summary table + changes = f"{sketch_now_missing} lost" if sketch_now_missing else "" + changes += ", " if sketch_now_missing and sketch_was_missing else "" + changes += f"{sketch_was_missing} new" if sketch_was_missing else "" + data_line = [ package, board, opts, + range_str(finals["flash"].get('delta')), + range_str(finals["RAM for global variables"].get('delta')), + updated_sketches or '-', + changes ] + + col_widths = [ max(len(str(data_line[i])), col_widths[i]) for i in range(len(data_line)) ] + data_lines.append(data_line) + +# format and output table +format_string = "| " + " | ".join([ formats[i].format(col_widths[i]) for i in range(len(col_widths)) ]) + " |" +spacer_string = "+-" + "-+-".join([ "-"*col_widths[i] for i in range(len(col_widths)) ]) + "-+" + +print(spacer_string) +print(format_string.format(*headers)) + +last_package = None +for data_line in data_lines: + if data_line[0] != last_package: + last_package = data_line[0] + print(spacer_string) + else: + data_line[0] = "" + print(format_string.format(*data_line)) + +print(spacer_string) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index 6434dd93d..947c09b08 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -115,9 +115,17 @@ void arduino::ZephyrSPI::detachInterrupt() { } void arduino::ZephyrSPI::begin() { +#ifdef CONFIG_PINCTRL_DYNAMIC + spi_dev->ops.init(spi_dev); +#endif } void arduino::ZephyrSPI::end() { +#ifdef CONFIG_DEVICE_DEINIT_SUPPORT + if (spi_dev->ops.deinit) { + spi_dev->ops.deinit(spi_dev); + } +#endif } #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), spis) diff --git a/libraries/SocketWrapper/SocketHelpers.cpp b/libraries/SocketWrapper/SocketHelpers.cpp index 30a8f7b75..d6e1f0c84 100644 --- a/libraries/SocketWrapper/SocketHelpers.cpp +++ b/libraries/SocketWrapper/SocketHelpers.cpp @@ -154,9 +154,12 @@ void NetworkInterface::setMACAddress(const uint8_t *mac) { int NetworkInterface::begin(bool blocking, uint64_t additional_event_mask) { dhcp(); + // FIXME: additional_event_mask cannot be ORed here due to how Zephyr // events are handled internally. Must be reworked to wait on a sem // and register multiple event masks with event_handler instead. + ARG_UNUSED(additional_event_mask); + int ret = net_mgmt_event_wait_on_iface(netif, NET_EVENT_IPV4_ADDR_ADD, NULL, NULL, NULL, blocking ? K_FOREVER : K_SECONDS(1)); return (ret == 0) ? 1 : 0; diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index c7d97587f..f5f0ff944 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -57,6 +57,9 @@ arduino::ZephyrI2C::ZephyrI2C(const struct device *i2c) : i2c_cfg({0}), i2c_dev( } void arduino::ZephyrI2C::begin() { +#ifdef CONFIG_PINCTRL_DYNAMIC + i2c_dev->ops.init(i2c_dev); +#endif } void arduino::ZephyrI2C::begin(uint8_t slaveAddr) { @@ -73,6 +76,11 @@ void arduino::ZephyrI2C::end() { i2c_target_unregister(i2c_dev, &i2c_cfg); memset(&i2c_cfg, 0, sizeof(i2c_cfg)); } +#ifdef CONFIG_DEVICE_DEINIT_SUPPORT + if (i2c_dev->ops.deinit) { + i2c_dev->ops.deinit(i2c_dev); + } +#endif } void arduino::ZephyrI2C::setClock(uint32_t freq) { diff --git a/loader/prj.conf b/loader/prj.conf index 023da8fd3..7c9d7eec1 100644 --- a/loader/prj.conf +++ b/loader/prj.conf @@ -27,6 +27,8 @@ CONFIG_LLEXT_EDK_FORMAT_TAR_ZSTD=y CONFIG_GPIO=y CONFIG_GPIO_GET_DIRECTION=y CONFIG_PINCTRL=y +CONFIG_PINCTRL_DYNAMIC=y +CONFIG_DEVICE_DEINIT_SUPPORT=y CONFIG_I2C=y CONFIG_SPI=y diff --git a/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay b/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay index e9b892c6f..64495f0ae 100644 --- a/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay +++ b/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay @@ -28,6 +28,13 @@ */ }; +&i2c3 { + status = "okay"; + pinctrl-0 = <&i2c3_scl_pc0 &i2c3_sda_pc1>; + pinctrl-names = "default"; + clock-frequency = ; +}; + /* clock from HSI48 */ &mco1 { status = "okay"; @@ -96,15 +103,13 @@ status = "okay"; /* tim1_etr_pa12 is not available for PWM */ /* Currently only the pins marked with ~ on the pin headers are enabled */ - /* pinctrl-0 = <&tim1_ch4_pa11 &tim1_ch3n_pb15 &tim1_ch1n_pb13 &tim1_ch2n_pb14>; */ - pinctrl-0 = <&tim1_ch4_pa11>; + pinctrl-0 = <&tim1_ch4_pa11 &tim1_ch3n_pb15 &tim1_ch1n_pb13 &tim1_ch2n_pb14>; pinctrl-names = "default"; }; }; /* Currently only the pins marked with ~ on the pin headers are enabled */ /* PB10 and PB11 conflict with I2C configuation */ -/* &timers2 { status = "okay"; st,prescaler = <4>; @@ -115,7 +120,6 @@ pinctrl-names = "default"; }; }; -*/ &timers3 { status = "okay"; @@ -124,8 +128,7 @@ pwm3: pwm { status = "okay"; /* Currently only the pins marked with ~ on the pin headers are enabled */ - /* pinctrl-0 = <&tim3_ch3_pb0 &tim3_ch4_pb1 &tim3_ch1_pb4>; */ - pinctrl-0 = <&tim3_ch3_pb0 &tim3_ch4_pb1>; + pinctrl-0 = <&tim3_ch3_pb0 &tim3_ch4_pb1 &tim3_ch1_pb4>; pinctrl-names = "default"; }; }; @@ -138,8 +141,7 @@ status = "okay"; /* PB6 PB7 not usable for PWM until dynamic pin muxing works */ /* Currently only the pins marked with ~ on the pin headers are enabled */ - /* pinctrl-0 = <&tim4_ch3_pb8 &tim4_ch4_pb9 &tim4_ch1_pb6 &tim4_ch2_pb7>; */ - pinctrl-0 = <&tim4_ch3_pb8 &tim4_ch4_pb9>; + pinctrl-0 = <&tim4_ch3_pb8 &tim4_ch4_pb9 /*&tim4_ch1_pb6 &tim4_ch2_pb7*/>; pinctrl-names = "default"; }; }; @@ -156,7 +158,6 @@ }; /* Currently only the pins marked with ~ on the pin headers are enabled */ -/* &timers8 { status = "okay"; st,prescaler = <4>; @@ -167,7 +168,6 @@ pinctrl-names = "default"; }; }; -*/ &timers16 { status = "okay"; @@ -287,25 +287,25 @@ /* PWM pin mapping - Digital pins with their timer channels */ /* Currently only the pins marked with ~ on the pin headers are enabled */ - pwm-pin-gpios = - /* <&gpiob 6 0>, */ /* D1/PB6 - TIM4_CH1 */ - /* <&gpiob 3 0>, */ /* D2/PB3 - TIM2_CH2 */ - /* <&gpiob 3 0>, */ /* D2/PB3 - TIM2_CH2 */ - <&gpiob 0 0>, /* D3/PB0 - TIM3_CH3 */ - <&gpioa 11 0>, /* D5/PA11 - TIM1_CH4 */ - <&gpiob 1 0>, /* D6/PB1 - TIM3_CH4 */ - /* <&gpiob 2 0>, */ /* D7/PB2 - TIM8_CH4N */ - /* <&gpiob 4 0>, */ /* D8/PB4 - TIM3_CH1 */ - <&gpiob 8 0>, /* D9/PB8 - TIM4_CH3 */ - <&gpiob 9 0>, /* D10/PB9 - TIM4_CH4 */ - /* <&gpiob 15 0>, */ /* D11/PB15 - TIM1_CH3N */ - /* <&gpiob 14 0>, */ /* D12/PB14 - TIM1_CH2N */ - /* <&gpiob 13 0>, */ /* D13/PB13 - TIM1_CH1N */ - /* <&gpiob 11 0>, */ /* D20/PB11 - TIM2_CH4 */ - /* <&gpiob 10 0>; */ /* D21/PB10 - TIM2_CH3 */ - <&gpioh 10 0>, /* LED3_R - TIM5_CH1 */ - <&gpioh 11 0>, /* LED3_G - TIM5_CH2 */ - <&gpioh 12 0>; /* LED3_B - TIM5_CH3 */ + pwm-pin-gpios = + /*<&gpiob 7 0>,*/ /* D0/PB6 - TIM4_CH2 */ + /*<&gpiob 6 0>,*/ /* D1/PB6 - TIM4_CH1 */ + <&gpiob 3 0>, /* D2/PB3 - TIM2_CH2 */ + <&gpiob 0 0>, /* D3/PB0 - TIM3_CH3 */ + <&gpioa 11 0>, /* D5/PA11 - TIM1_CH4 */ + <&gpiob 1 0>, /* D6/PB1 - TIM3_CH4 */ + <&gpiob 2 0>, /* D7/PB2 - TIM8_CH4N */ + <&gpiob 4 0>, /* D8/PB4 - TIM3_CH1 */ + <&gpiob 8 0>, /* D9/PB8 - TIM4_CH3 */ + <&gpiob 9 0>, /* D10/PB9 - TIM4_CH4 */ + <&gpiob 15 0>, /* D11/PB15 - TIM1_CH3N */ + <&gpiob 14 0>, /* D12/PB14 - TIM1_CH2N */ + <&gpiob 13 0>, /* D13/PB13 - TIM1_CH1N */ + <&gpiob 11 0>, /* D20/PB11 - TIM2_CH4 */ + <&gpiob 10 0>, /* D21/PB10 - TIM2_CH3 */ + <&gpioh 10 0>, /* LED3_R - TIM5_CH1 */ + <&gpioh 11 0>, /* LED3_G - TIM5_CH2 */ + <&gpioh 12 0>; /* LED3_B - TIM5_CH3 */ adc-pin-gpios = <&gpioa 4 0>, <&gpioa 5 0>, @@ -315,26 +315,26 @@ <&gpioc 0 0>; serials = <&usart1>, <&lpuart1>; - i2cs = <&i2c2>, <&i2c4>; + i2cs = <&i2c2>, <&i2c4>, <&i2c3>; spis = <&spi2>, <&spi3>; /* PWM mapping for the digital pins */ /* Currently only the pins marked with ~ on the pin headers are enabled */ - pwms = - /* <&pwm4 2 PWM_HZ(500) PWM_POLARITY_NORMAL>, */ /* D0/PB7 → TIM4_CH2 */ - /* <&pwm4 1 PWM_HZ(500) PWM_POLARITY_NORMAL>, */ /* D1/PB6 → TIM4_CH1 */ - /* <&pwm2 2 PWM_HZ(500) PWM_POLARITY_NORMAL>, */ /* D2/PB3 → TIM2_CH2 */ + pwms = + /*<&pwm4 2 PWM_HZ(500) PWM_POLARITY_NORMAL>,*/ /* D0/PB7 → TIM4_CH2 */ + /*<&pwm4 1 PWM_HZ(500) PWM_POLARITY_NORMAL>,*/ /* D1/PB6 → TIM4_CH1 */ + <&pwm2 2 PWM_HZ(500) PWM_POLARITY_NORMAL>, /* D2/PB3 → TIM2_CH2 */ <&pwm3 3 PWM_HZ(500) PWM_POLARITY_NORMAL>, /* D3/PB0 → TIM3_CH3 */ <&pwm1 4 PWM_HZ(500) PWM_POLARITY_NORMAL>, /* D5/PA11 → TIM1_CH4 */ <&pwm3 4 PWM_HZ(500) PWM_POLARITY_NORMAL>, /* D6/PB1 → TIM3_CH4 */ - /* <&pwm8 4 PWM_HZ(500) PWM_POLARITY_INVERTED>, */ /* D7/PB2 → TIM8_CH4N */ - /* <&pwm3 1 PWM_HZ(500) PWM_POLARITY_NORMAL>, */ /* D8/PB4 → TIM3_CH1 */ + <&pwm8 4 PWM_HZ(500) PWM_POLARITY_INVERTED>, /* D7/PB2 → TIM8_CH4N */ + <&pwm3 1 PWM_HZ(500) PWM_POLARITY_NORMAL>, /* D8/PB4 → TIM3_CH1 */ <&pwm4 3 PWM_HZ(500) PWM_POLARITY_NORMAL>, /* D9/PB8 → TIM4_CH3 */ <&pwm4 4 PWM_HZ(500) PWM_POLARITY_NORMAL>, /* D10/PB9 → TIM4_CH4 */ - /* <&pwm1 3 PWM_HZ(500) PWM_POLARITY_INVERTED>, */ /* D11/PB15 → TIM1_CH3N */ - /* <&pwm1 2 PWM_HZ(500) PWM_POLARITY_INVERTED>, */ /* D12/PB14 → TIM1_CH2N */ - /* <&pwm1 1 PWM_HZ(500) PWM_POLARITY_INVERTED>, */ /* D13/PB13 → TIM1_CH1N */ - /* <&pwm2 4 PWM_HZ(500) PWM_POLARITY_NORMAL>, */ /* D20/PB11 → TIM2_CH4 */ - /* <&pwm2 3 PWM_HZ(500) PWM_POLARITY_NORMAL>; */ /* D21/PB10 → TIM2_CH3 */ + <&pwm1 3 PWM_HZ(500) PWM_POLARITY_INVERTED>, /* D11/PB15 → TIM1_CH3N */ + <&pwm1 2 PWM_HZ(500) PWM_POLARITY_INVERTED>, /* D12/PB14 → TIM1_CH2N */ + <&pwm1 1 PWM_HZ(500) PWM_POLARITY_INVERTED>, /* D13/PB13 → TIM1_CH1N */ + <&pwm2 4 PWM_HZ(500) PWM_POLARITY_NORMAL>, /* D20/PB11 → TIM2_CH4 */ + <&pwm2 3 PWM_HZ(500) PWM_POLARITY_NORMAL>, /* D21/PB10 → TIM2_CH3 */ <&pwm5 1 PWM_HZ(500) PWM_POLARITY_INVERTED>, /* LED3_R/PH10 → TIM5_CH1 */ <&pwm5 2 PWM_HZ(500) PWM_POLARITY_INVERTED>, /* LED3_G/PH11 → TIM5_CH2 */ <&pwm5 3 PWM_HZ(500) PWM_POLARITY_INVERTED>; /* LED3_B/PH12 → TIM5_CH3 */ @@ -349,6 +349,9 @@ <&adc1 2>, /* A4 - PC1 */ <&adc1 1>; /* A5 - PC0 */ + dac-pin-gpios = <&gpioa 4 0>, + <&gpioa 5 0>; + dac = <&dac1>; dac-channels = <1>, <2>; dac-resolution = <12>; diff --git a/variants/arduino_uno_q_stm32u585xx/skip_these_examples.txt b/variants/arduino_uno_q_stm32u585xx/skip_these_examples.txt index 22e511274..1ccad6243 100644 --- a/variants/arduino_uno_q_stm32u585xx/skip_these_examples.txt +++ b/variants/arduino_uno_q_stm32u585xx/skip_these_examples.txt @@ -8,5 +8,4 @@ # Each line in this file should contain the path to an example to exclude, # relative to the root of the repository. -libraries/ArduinoBLE libraries/Arduino_RPClite/extras/integration_test