mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'espressif:master' into master
This commit is contained in:
commit
191914690f
@ -18,6 +18,7 @@ workflow:
|
||||
# Place the default settings in `.gitlab/ci/common.yml` instead
|
||||
|
||||
include:
|
||||
- '.gitlab/ci/danger.yml'
|
||||
- '.gitlab/ci/common.yml'
|
||||
- '.gitlab/ci/rules.yml'
|
||||
- '.gitlab/ci/upload_cache.yml'
|
||||
|
@ -52,7 +52,6 @@
|
||||
/.github/workflows/ @esp-idf-codeowners/ci
|
||||
/.gitlab-ci.yml @esp-idf-codeowners/ci
|
||||
/.gitlab/ci/ @esp-idf-codeowners/ci
|
||||
/.gitlab/dangerjs/ @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
/.pre-commit-config.yaml @esp-idf-codeowners/ci
|
||||
/.readthedocs.yml @esp-idf-codeowners/docs
|
||||
/.vale.ini @esp-idf-codeowners/docs
|
||||
|
@ -550,6 +550,38 @@ pytest_build_system_macos:
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
|
||||
.test_build_system_template_win:
|
||||
stage: host_test
|
||||
variables:
|
||||
# Enable ccache for all build jobs. See configure_ci_environment.sh for more ccache related settings.
|
||||
IDF_CCACHE_ENABLE: "1"
|
||||
PYTHONPATH: "$PYTHONPATH;$IDF_PATH\\tools;$IDF_PATH\\tools\\esp_app_trace;$IDF_PATH\\components\\partition_table;$IDF_PATH\\tools\\ci\\python_packages"
|
||||
before_script: []
|
||||
after_script: []
|
||||
timeout: 4 hours
|
||||
script:
|
||||
- .\install.ps1 --enable-ci --enable-pytest
|
||||
- . .\export.ps1
|
||||
- python "${SUBMODULE_FETCH_TOOL}" -s "all"
|
||||
- cd ${IDF_PATH}\tools\test_build_system
|
||||
- pytest --junitxml=${CI_PROJECT_DIR}\XUNIT_RESULT.xml
|
||||
|
||||
pytest_build_system_win:
|
||||
extends:
|
||||
- .test_build_system_template_win
|
||||
- .rules:test:windows_pytest_build_system
|
||||
needs: []
|
||||
tags:
|
||||
- windows-target
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
- test_build_system
|
||||
when: always
|
||||
expire_in: 2 days
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
|
||||
build_docker:
|
||||
extends:
|
||||
- .before_script:minimal
|
||||
|
@ -51,7 +51,6 @@ variables:
|
||||
# Docker images
|
||||
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v5.3:1"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v5.3:1-1"
|
||||
QEMU_IMAGE: "${CI_DOCKER_REGISTRY}/qemu-v5.3:1-20230522"
|
||||
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v5.3:1"
|
||||
SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:5"
|
||||
PRE_COMMIT_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-pre-commit:1"
|
||||
@ -140,6 +139,11 @@ variables:
|
||||
$IDF_PATH/tools/idf_tools.py --non-interactive install esp-clang
|
||||
fi
|
||||
|
||||
# Install QEMU if necessary
|
||||
if [[ ! -z "$INSTALL_QEMU" ]]; then
|
||||
$IDF_PATH/tools/idf_tools.py --non-interactive install qemu-xtensa qemu-riscv32
|
||||
fi
|
||||
|
||||
source ./export.sh
|
||||
|
||||
# Custom clang
|
||||
@ -172,10 +176,9 @@ variables:
|
||||
test "$CI_CCACHE_STATS" == 1 && test -n "$(which ccache)" && ccache --show-stats || true
|
||||
|
||||
.upload_failed_job_log_artifacts: &upload_failed_job_log_artifacts |
|
||||
- |
|
||||
if [ $CI_JOB_STATUS = "failed" ]; then
|
||||
python tools/ci/artifacts_handler.py upload --type logs
|
||||
fi
|
||||
if [ $CI_JOB_STATUS = "failed" ]; then
|
||||
python tools/ci/artifacts_handler.py upload --type logs
|
||||
fi
|
||||
|
||||
.before_script:minimal:
|
||||
before_script:
|
||||
|
18
.gitlab/ci/danger.yml
Normal file
18
.gitlab/ci/danger.yml
Normal file
@ -0,0 +1,18 @@
|
||||
# Extenal DangerJS
|
||||
include:
|
||||
- project: espressif/shared-ci-dangerjs
|
||||
ref: master
|
||||
file: danger.yaml
|
||||
|
||||
run-danger-mr-linter:
|
||||
stage: pre_check
|
||||
variables:
|
||||
GIT_STRATEGY: none # no repo checkout
|
||||
ENABLE_CHECK_AREA_LABELS: 'true'
|
||||
ENABLE_CHECK_DOCS_TRANSLATION: 'true'
|
||||
ENABLE_CHECK_RELEASE_NOTES_DESCRIPTION: 'true'
|
||||
ENABLE_CHECK_UPDATED_CHANGELOG: 'false'
|
||||
before_script: []
|
||||
cache: []
|
||||
tags:
|
||||
- dangerjs
|
@ -175,6 +175,12 @@
|
||||
patterns:
|
||||
- submodule
|
||||
|
||||
"test:windows_pytest_build_system":
|
||||
labels:
|
||||
- windows
|
||||
specific_rules:
|
||||
- if-schedule-test-build-system-windows
|
||||
|
||||
#################################
|
||||
# Triggered Only By Labels Jobs #
|
||||
#################################
|
||||
|
@ -99,18 +99,9 @@ test_gdbstub_on_host:
|
||||
- cd components/esp_gdbstub/test_gdbstub_host
|
||||
- make test
|
||||
|
||||
test_idf_py:
|
||||
extends: .host_test_template
|
||||
variables:
|
||||
LC_ALL: C.UTF-8
|
||||
script:
|
||||
- cd ${IDF_PATH}/tools/test_idf_py
|
||||
- ./test_idf_py.py
|
||||
- ./test_hints.py
|
||||
|
||||
# Test for create virtualenv. It must be invoked from Python, not from virtualenv.
|
||||
# Use docker image system python without any extra dependencies
|
||||
test_idf_tools:
|
||||
test_cli_installer:
|
||||
extends:
|
||||
- .host_test_template
|
||||
- .before_script:minimal
|
||||
@ -199,45 +190,41 @@ test_sysviewtrace_proc:
|
||||
- cd ${IDF_PATH}/tools/esp_app_trace/test/sysview
|
||||
- ./test.sh
|
||||
|
||||
test_mkdfu:
|
||||
extends: .host_test_template
|
||||
variables:
|
||||
LC_ALL: C.UTF-8
|
||||
script:
|
||||
- cd ${IDF_PATH}/tools/test_mkdfu
|
||||
- ./test_mkdfu.py
|
||||
|
||||
test_sbom:
|
||||
extends:
|
||||
- .host_test_template
|
||||
- .rules:patterns:sbom
|
||||
script:
|
||||
- cd ${IDF_PATH}/tools/test_sbom
|
||||
- pytest
|
||||
|
||||
test_autocomplete:
|
||||
test_tools:
|
||||
extends:
|
||||
- .host_test_template
|
||||
artifacts:
|
||||
when: on_failure
|
||||
when: always
|
||||
paths:
|
||||
- ${IDF_PATH}/*.out
|
||||
- ${IDF_PATH}/XUNIT_*.xml
|
||||
reports:
|
||||
junit: ${IDF_PATH}/XUNIT_*.xml
|
||||
expire_in: 1 week
|
||||
variables:
|
||||
LC_ALL: C.UTF-8
|
||||
INSTALL_QEMU: 1 # for test_idf_qemu.py
|
||||
script:
|
||||
- ${IDF_PATH}/tools/ci/test_autocomplete.py
|
||||
|
||||
test_detect_python:
|
||||
extends:
|
||||
- .host_test_template
|
||||
script:
|
||||
- stat=0
|
||||
- cd ${IDF_PATH}/tools/ci/test_autocomplete
|
||||
- pytest --noconftest test_autocomplete.py --junitxml=${IDF_PATH}/XUNIT_AUTOCOMP.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_idf_py
|
||||
- pytest --noconftest test_idf_py.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY.xml || stat=1
|
||||
- pytest --noconftest test_hints.py --junitxml=${IDF_PATH}/XUNIT_HINTS.xml || stat=1
|
||||
- pytest --noconftest test_idf_qemu.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY_QEMU.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_mkdfu
|
||||
- pytest --noconftest test_mkdfu.py --junitxml=${IDF_PATH}/XUNIT_MKDFU.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_sbom
|
||||
- pytest --junitxml=${IDF_PATH}/XUNIT_SBOM.xml || stat=1
|
||||
- cd ${IDF_PATH}
|
||||
- shellcheck -s sh tools/detect_python.sh
|
||||
- shellcheck -s bash tools/detect_python.sh
|
||||
- shellcheck -s dash tools/detect_python.sh
|
||||
- shellcheck -s sh tools/detect_python.sh || stat=1
|
||||
- shellcheck -s bash tools/detect_python.sh || stat=1
|
||||
- shellcheck -s dash tools/detect_python.sh || stat=1
|
||||
- "bash -c '. tools/detect_python.sh && echo Our Python: ${ESP_PYTHON?Python is not set}'"
|
||||
- "dash -c '. tools/detect_python.sh && echo Our Python: ${ESP_PYTHON?Python is not set}'"
|
||||
- "zsh -c '. tools/detect_python.sh && echo Our Python: ${ESP_PYTHON?Python is not set}'"
|
||||
- "fish -c 'source tools/detect_python.fish && echo Our Python: $ESP_PYTHON'"
|
||||
- exit "$stat"
|
||||
|
||||
test_split_path_by_spaces:
|
||||
extends: .host_test_template
|
||||
@ -294,7 +281,6 @@ test_pytest_qemu:
|
||||
extends:
|
||||
- .host_test_template
|
||||
- .before_script:build
|
||||
image: $QEMU_IMAGE
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
@ -307,6 +293,8 @@ test_pytest_qemu:
|
||||
parallel:
|
||||
matrix:
|
||||
- IDF_TARGET: [esp32, esp32c3]
|
||||
variables:
|
||||
INSTALL_QEMU: 1
|
||||
script:
|
||||
- run_cmd python tools/ci/ci_build_apps.py . -vv
|
||||
--target $IDF_TARGET
|
||||
|
@ -16,33 +16,6 @@ check_pre_commit:
|
||||
- fetch_submodules
|
||||
- pre-commit run --files $MODIFIED_FILES
|
||||
|
||||
check_MR_style_dangerjs:
|
||||
extends:
|
||||
- .pre_check_template
|
||||
image: node:18.15.0-alpine3.16
|
||||
variables:
|
||||
DANGER_GITLAB_API_TOKEN: ${ESPCI_TOKEN}
|
||||
DANGER_GITLAB_HOST: ${GITLAB_HTTP_SERVER}
|
||||
DANGER_GITLAB_API_BASE_URL: ${GITLAB_HTTP_SERVER}/api/v4
|
||||
DANGER_JIRA_USER: ${DANGER_JIRA_USER}
|
||||
DANGER_JIRA_PASSWORD: ${DANGER_JIRA_PASSWORD}
|
||||
cache:
|
||||
# pull only for most of the use cases since it's cache dir.
|
||||
# Only set "push" policy for "upload_cache" stage jobs
|
||||
key:
|
||||
files:
|
||||
- .gitlab/dangerjs/package-lock.json
|
||||
paths:
|
||||
- .gitlab/dangerjs/node_modules/
|
||||
policy: pull
|
||||
before_script:
|
||||
- cd .gitlab/dangerjs
|
||||
- npm install --no-progress --no-update-notifier # Install danger dependencies
|
||||
script:
|
||||
- npx danger ci --failOnErrors -v
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
|
||||
check_version:
|
||||
# Don't run this for feature/bugfix branches, so that it is possible to modify
|
||||
# esp_idf_version.h in a branch before tagging the next version.
|
||||
|
@ -67,9 +67,6 @@
|
||||
- "tools/ci/ci_build_apps.py"
|
||||
- "tools/test_build_system/**/*"
|
||||
|
||||
.patterns-sbom: &patterns-sbom
|
||||
- "tools/test_sbom/*"
|
||||
|
||||
.patterns-custom_test: &patterns-custom_test
|
||||
- "tools/ci/idf_pytest/**/*"
|
||||
- "tools/ci/python_packages/gitlab_api.py"
|
||||
@ -129,7 +126,7 @@
|
||||
|
||||
- "components/**/*"
|
||||
|
||||
- "tools/ci/test_autocomplete.py"
|
||||
- "tools/ci/test_autocomplete/*"
|
||||
|
||||
- "tools/mass_mfg/**/*"
|
||||
|
||||
@ -150,6 +147,8 @@
|
||||
- "tools/test_idf_tools/**/*"
|
||||
- "tools/install_util.py"
|
||||
|
||||
- "tools/test_sbom/*"
|
||||
|
||||
- "tools/requirements/*"
|
||||
- "tools/requirements.json"
|
||||
- "tools/requirements_schema.json"
|
||||
@ -197,6 +196,7 @@
|
||||
- "components/unity/unity"
|
||||
- "components/heap/tlsf"
|
||||
- "components/bt/controller/lib_esp32c6/esp32c6-bt-lib"
|
||||
- "components/bt/esp_ble_mesh/lib/lib"
|
||||
- ".gitmodules"
|
||||
|
||||
.patterns-danger-npm: &patterns-danger-npm
|
||||
@ -351,6 +351,9 @@
|
||||
.if-schedule: &if-schedule
|
||||
if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||
|
||||
.if-schedule-test-build-system-windows: &if-schedule-test-build-system-windows
|
||||
if: '$CI_PIPELINE_SOURCE == "schedule" && $SCHEDULED_BUILD_SYSTEM_TEST_WIN == "true"'
|
||||
|
||||
.if-trigger: &if-trigger
|
||||
if: '$CI_PIPELINE_SOURCE == "trigger"'
|
||||
|
||||
@ -445,14 +448,6 @@
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-sonarqube-files
|
||||
|
||||
.rules:patterns:sbom:
|
||||
rules:
|
||||
- <<: *if-protected
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-sbom
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-submodule
|
||||
|
||||
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
# DO NOT place comments or maintain any code from this line
|
||||
#
|
||||
@ -570,6 +565,9 @@
|
||||
.if-label-target_test: &if-label-target_test
|
||||
if: '$BOT_LABEL_TARGET_TEST || $CI_MERGE_REQUEST_LABELS =~ /^(?:[^,\n\r]+,)*target_test(?:,[^,\n\r]+)*$/i'
|
||||
|
||||
.if-label-windows: &if-label-windows
|
||||
if: '$BOT_LABEL_WINDOWS || $CI_MERGE_REQUEST_LABELS =~ /^(?:[^,\n\r]+,)*windows(?:,[^,\n\r]+)*$/i'
|
||||
|
||||
.rules:build:
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
@ -2583,3 +2581,13 @@
|
||||
- <<: *if-label-submodule
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-submodule
|
||||
|
||||
.rules:test:windows_pytest_build_system:
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build-only
|
||||
when: never
|
||||
- <<: *if-schedule-test-build-system-windows
|
||||
- <<: *if-label-windows
|
||||
|
@ -229,6 +229,15 @@ pytest_examples_esp32c6_generic:
|
||||
artifacts: false
|
||||
tags: [ esp32c6, generic ]
|
||||
|
||||
pytest_examples_esp32c6_usj_device:
|
||||
extends:
|
||||
- .pytest_examples_dir_template
|
||||
- .rules:test:example_test-esp32c6
|
||||
needs:
|
||||
- job: build_pytest_examples_esp32c6
|
||||
artifacts: false
|
||||
tags: [ esp32c6, usj_device ]
|
||||
|
||||
pytest_examples_esp32h2_generic:
|
||||
extends:
|
||||
- .pytest_examples_dir_template
|
||||
@ -715,6 +724,24 @@ pytest_components_esp32_adc:
|
||||
artifacts: false
|
||||
tags: [ esp32, adc ]
|
||||
|
||||
pytest_components_esp32_sdmmc:
|
||||
extends:
|
||||
- .pytest_components_dir_template
|
||||
- .rules:test:component_ut-esp32
|
||||
needs:
|
||||
- job: build_pytest_components_esp32
|
||||
artifacts: false
|
||||
tags: [ esp32, sdcard ]
|
||||
|
||||
pytest_components_esp32s3_sdmmc:
|
||||
extends:
|
||||
- .pytest_components_dir_template
|
||||
- .rules:test:component_ut-esp32s3
|
||||
needs:
|
||||
- job: build_pytest_components_esp32s3
|
||||
artifacts: false
|
||||
tags: [ esp32s3, sdcard ]
|
||||
|
||||
pytest_components_esp32_sdio:
|
||||
extends:
|
||||
- .pytest_components_dir_template
|
||||
@ -1171,15 +1198,6 @@ pytest_components_esp32c3_flash_multi:
|
||||
artifacts: false
|
||||
tags: [ esp32c3, flash_multi ]
|
||||
|
||||
pytest_components_esp32_sdmmc:
|
||||
extends:
|
||||
- .pytest_components_dir_template
|
||||
- .rules:test:component_ut-esp32
|
||||
needs:
|
||||
- job: build_pytest_components_esp32
|
||||
artifacts: false
|
||||
tags: [ esp32, sdcard_sdmode ]
|
||||
|
||||
pytest_components_esp32_sdspi:
|
||||
extends:
|
||||
- .pytest_components_dir_template
|
||||
|
@ -48,27 +48,3 @@ upload-submodules-cache:
|
||||
parallel:
|
||||
matrix:
|
||||
- GEO: [ 'shiny', 'brew' ]
|
||||
|
||||
upload-danger-npm-cache:
|
||||
stage: upload_cache
|
||||
image: node:18.15.0-alpine3.16
|
||||
extends:
|
||||
- .rules:patterns:dangerjs
|
||||
tags:
|
||||
- $GEO
|
||||
- cache
|
||||
cache:
|
||||
key:
|
||||
files:
|
||||
- .gitlab/dangerjs/package-lock.json
|
||||
paths:
|
||||
- .gitlab/dangerjs/node_modules/
|
||||
policy: push
|
||||
before_script:
|
||||
- echo "Skip before scripts ...."
|
||||
script:
|
||||
- cd .gitlab/dangerjs
|
||||
- npm install --no-progress --no-update-notifier
|
||||
parallel:
|
||||
matrix:
|
||||
- GEO: [ 'shiny', 'brew' ]
|
||||
|
@ -1,172 +0,0 @@
|
||||
const {
|
||||
minimumSummaryChars,
|
||||
maximumSummaryChars,
|
||||
maximumBodyLineChars,
|
||||
allowedTypes,
|
||||
} = require("./mrCommitsConstants.js");
|
||||
const { gptStandardModelTokens } = require("./mrCommitsConstants.js");
|
||||
|
||||
const { ChatPromptTemplate } = require("langchain/prompts");
|
||||
const { SystemMessagePromptTemplate } = require("langchain/prompts");
|
||||
const { LLMChain } = require("langchain/chains");
|
||||
const { ChatOpenAI } = require("langchain/chat_models/openai");
|
||||
const openAiTokenCount = require("openai-gpt-token-counter");
|
||||
|
||||
module.exports = async function () {
|
||||
let outputDangerMessage = `\n\nPerhaps you could use an AI-generated suggestion for your commit message. Here is one `;
|
||||
|
||||
let mrDiff = await getMrGitDiff(danger.git.modified_files);
|
||||
const mrCommitMessages = getCommitMessages(danger.gitlab.commits);
|
||||
const inputPrompt = getInputPrompt();
|
||||
const inputLlmTokens = getInputLlmTokens(
|
||||
inputPrompt,
|
||||
mrDiff,
|
||||
mrCommitMessages
|
||||
);
|
||||
console.log(`Input tokens for LLM: ${inputLlmTokens}`);
|
||||
|
||||
if (inputLlmTokens >= gptStandardModelTokens) {
|
||||
mrDiff = ""; // If the input mrDiff is larger than 16k model, don't use mrDiff, use only current commit messages
|
||||
outputDangerMessage += `(based only on your current commit messages, git-diff of this MR is too big (${inputLlmTokens} tokens) for the AI models):\n\n`;
|
||||
} else {
|
||||
outputDangerMessage += `(based on your MR git-diff and your current commit messages):\n\n`;
|
||||
}
|
||||
|
||||
// Generate AI commit message
|
||||
let generatedCommitMessage = "";
|
||||
try {
|
||||
const rawCommitMessage = await createAiGitMessage(
|
||||
inputPrompt,
|
||||
mrDiff,
|
||||
mrCommitMessages
|
||||
);
|
||||
generatedCommitMessage = postProcessCommitMessage(rawCommitMessage);
|
||||
} catch (error) {
|
||||
console.error("Error in generating AI commit message: ", error);
|
||||
outputDangerMessage +=
|
||||
"\nCould not generate commit message due to an error.\n";
|
||||
}
|
||||
|
||||
// Append closing statements ("Closes https://github.com/espressif/esp-idf/issues/XXX") to the generated commit message
|
||||
let closingStatements = extractClosingStatements(mrCommitMessages);
|
||||
if (closingStatements.length > 0) {
|
||||
generatedCommitMessage += "\n\n" + closingStatements;
|
||||
}
|
||||
|
||||
// Add the generated git message, format to the markdown code block
|
||||
outputDangerMessage += `\n\`\`\`\n${generatedCommitMessage}\n\`\`\`\n`;
|
||||
outputDangerMessage +=
|
||||
"\n**NOTE: AI-generated suggestions may not always be correct, please review the suggestion before using it.**"; // Add disclaimer
|
||||
return outputDangerMessage;
|
||||
};
|
||||
|
||||
async function getMrGitDiff(mrModifiedFiles) {
|
||||
const fileDiffs = await Promise.all(
|
||||
mrModifiedFiles.map((file) => danger.git.diffForFile(file))
|
||||
);
|
||||
return fileDiffs.map((fileDiff) => fileDiff.diff.trim()).join(" ");
|
||||
}
|
||||
|
||||
function getCommitMessages(mrCommits) {
|
||||
return mrCommits.map((commit) => commit.message);
|
||||
}
|
||||
|
||||
function getInputPrompt() {
|
||||
return `You are a helpful assistant that creates suggestions for single git commit message, that user can use to describe all the changes in their merge request.
|
||||
Use git diff: {mrDiff} and users current commit messages: {mrCommitMessages} to get the changes made in the commit.
|
||||
|
||||
Output should be git commit message following the conventional commit format.
|
||||
|
||||
Output only git commit message in desired format, without comments and other text.
|
||||
|
||||
Do not include the closing statements ("Closes https://....") in the output.
|
||||
|
||||
Here are the strict rules you must follow:
|
||||
|
||||
- Avoid mentioning any JIRA tickets (e.g., "Closes JIRA-123").
|
||||
- Be specific. Don't use vague terms (e.g., "some checks", "add new ones", "few changes").
|
||||
- The commit message structure should be: <type><(scope/component)>: <summary>
|
||||
- Types allowed: ${allowedTypes.join(", ")}
|
||||
- If 'scope/component' is used, it must start with a lowercase letter.
|
||||
- The 'summary' must NOT end with a period.
|
||||
- The 'summary' must be between ${minimumSummaryChars} and ${maximumSummaryChars} characters long.
|
||||
|
||||
If a 'body' of commit message is used:
|
||||
|
||||
- Each line must be no longer than ${maximumBodyLineChars} characters.
|
||||
- It must be separated from the 'summary' by a blank line.
|
||||
|
||||
Examples of correct commit messages:
|
||||
|
||||
- With scope and body:
|
||||
fix(freertos): Fix startup timeout issue
|
||||
|
||||
This is a text of commit message body...
|
||||
- adds support for wifi6
|
||||
- adds validations for logging script
|
||||
|
||||
- Without scope and body:
|
||||
ci: added target test job for ESP32-Wifi6`;
|
||||
}
|
||||
|
||||
function getInputLlmTokens(inputPrompt, mrDiff, mrCommitMessages) {
|
||||
const mrCommitMessagesTokens = openAiTokenCount(mrCommitMessages.join(" "));
|
||||
const gitDiffTokens = openAiTokenCount(mrDiff);
|
||||
const promptTokens = openAiTokenCount(inputPrompt);
|
||||
return mrCommitMessagesTokens + gitDiffTokens + promptTokens;
|
||||
}
|
||||
|
||||
async function createAiGitMessage(inputPrompt, mrDiff, mrCommitMessages) {
|
||||
const chat = new ChatOpenAI({ engine: "gpt-3.5-turbo", temperature: 0 });
|
||||
const chatPrompt = ChatPromptTemplate.fromPromptMessages([
|
||||
SystemMessagePromptTemplate.fromTemplate(inputPrompt),
|
||||
]);
|
||||
const chain = new LLMChain({ prompt: chatPrompt, llm: chat });
|
||||
|
||||
const response = await chain.call({
|
||||
mrDiff: mrDiff,
|
||||
mrCommitMessages: mrCommitMessages,
|
||||
});
|
||||
return response.text;
|
||||
}
|
||||
|
||||
function postProcessCommitMessage(rawCommitMessage) {
|
||||
// Split the result into lines
|
||||
let lines = rawCommitMessage.split("\n");
|
||||
|
||||
// Format each line
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i].trim();
|
||||
|
||||
// If the line is longer than maximumBodyLineChars, split it into multiple lines
|
||||
if (line.length > maximumBodyLineChars) {
|
||||
let newLines = [];
|
||||
while (line.length > maximumBodyLineChars) {
|
||||
let lastSpaceIndex = line.lastIndexOf(
|
||||
" ",
|
||||
maximumBodyLineChars
|
||||
);
|
||||
newLines.push(line.substring(0, lastSpaceIndex));
|
||||
line = line.substring(lastSpaceIndex + 1);
|
||||
}
|
||||
newLines.push(line);
|
||||
lines[i] = newLines.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Join the lines back into a single string with a newline between each one
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
function extractClosingStatements(mrCommitMessages) {
|
||||
let closingStatements = [];
|
||||
mrCommitMessages.forEach((message) => {
|
||||
const lines = message.split("\n");
|
||||
lines.forEach((line) => {
|
||||
if (line.startsWith("Closes")) {
|
||||
closingStatements.push(line);
|
||||
}
|
||||
});
|
||||
});
|
||||
return closingStatements.join("\n");
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
let outputStatuses = [];
|
||||
|
||||
/**
|
||||
* Logs the status of a rule with padded formatting and stores it in the `outputStatuses` array.
|
||||
* If the rule already exists in the array, its status is updated.
|
||||
* @param message The name of the rule
|
||||
* @param status The output (exit) status of the rule
|
||||
*/
|
||||
function recordRuleExitStatus(message, status) {
|
||||
// Check if the rule already exists in the array
|
||||
const existingRecord = outputStatuses.find(
|
||||
(rule) => rule.message === message
|
||||
);
|
||||
|
||||
if (existingRecord) {
|
||||
// Update the status of the existing rule
|
||||
existingRecord.status = status;
|
||||
} else {
|
||||
// If the rule doesn't exist, add it to the array
|
||||
outputStatuses.push({ message, status });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays all the rule output statuses stored in the `outputStatuses` array.
|
||||
* Filters out any empty lines, sorts them alphabetically, and prints the statuses
|
||||
* with a header and separator.
|
||||
* These statuses are later displayed in CI job tracelog.
|
||||
*/
|
||||
function displayAllOutputStatuses() {
|
||||
const lineLength = 100;
|
||||
const sortedStatuses = outputStatuses.sort((a, b) =>
|
||||
a.message.localeCompare(b.message)
|
||||
);
|
||||
|
||||
const formattedLines = sortedStatuses.map((statusObj) => {
|
||||
const paddingLength =
|
||||
lineLength - statusObj.message.length - statusObj.status.length;
|
||||
const paddedMessage = statusObj.message.padEnd(
|
||||
statusObj.message.length + paddingLength,
|
||||
"."
|
||||
);
|
||||
return `${paddedMessage} ${statusObj.status}`;
|
||||
});
|
||||
|
||||
console.log(
|
||||
"DangerJS checks (rules) output states:\n" + "=".repeat(lineLength + 2)
|
||||
);
|
||||
console.log(formattedLines.join("\n"));
|
||||
console.log("=".repeat(lineLength + 2));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
displayAllOutputStatuses,
|
||||
recordRuleExitStatus,
|
||||
};
|
@ -1,51 +0,0 @@
|
||||
const { displayAllOutputStatuses } = require("./configParameters.js");
|
||||
|
||||
/*
|
||||
* Modules with checks are stored in ".gitlab/dangerjs/<module_name>". To import them, use path relative to "dangerfile.js"
|
||||
*/
|
||||
async function runChecks() {
|
||||
// Checks for merge request title
|
||||
require("./mrTitleNoDraftOrWip.js")();
|
||||
|
||||
// Checks for merge request description
|
||||
require("./mrDescriptionLongEnough.js")();
|
||||
require("./mrDescriptionReleaseNotes.js")();
|
||||
await require("./mrDescriptionJiraLinks.js")();
|
||||
|
||||
// Checks for documentation
|
||||
await require("./mrDocsTranslation.js")();
|
||||
|
||||
// Checks for MR commits
|
||||
require("./mrCommitsTooManyCommits.js")();
|
||||
await require("./mrCommitsCommitMessage.js")();
|
||||
require("./mrCommitsEmail.js")();
|
||||
|
||||
// Checks for MR code
|
||||
require("./mrSizeTooLarge.js")();
|
||||
|
||||
// Checks for MR area labels
|
||||
await require("./mrAreaLabels.js")();
|
||||
|
||||
// Checks for Source branch name
|
||||
require("./mrSourceBranchName.js")();
|
||||
|
||||
// Show DangerJS individual checks statuses - visible in CI job tracelog
|
||||
displayAllOutputStatuses();
|
||||
|
||||
// Add success log if no issues
|
||||
if (
|
||||
results.fails.length === 0 &&
|
||||
results.warnings.length === 0 &&
|
||||
results.messages.length === 0
|
||||
) {
|
||||
return message("🎉 Good Job! All checks are passing!");
|
||||
}
|
||||
}
|
||||
|
||||
runChecks();
|
||||
|
||||
// Add retry link
|
||||
const retryLink = `${process.env.DANGER_GITLAB_HOST}/${process.env.CI_PROJECT_PATH}/-/jobs/${process.env.CI_JOB_ID}`;
|
||||
markdown(
|
||||
`***\n#### :repeat: You can enforce automatic MR checks by retrying the [DangerJS job](${retryLink})\n***`
|
||||
);
|
@ -1,27 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Check if MR has area labels (light blue labels)
|
||||
*
|
||||
* @dangerjs WARN
|
||||
*/
|
||||
module.exports = async function () {
|
||||
const ruleName = "Merge request area labels";
|
||||
const projectId = 103; // ESP-IDF
|
||||
const areaLabelColor = /^#d2ebfa$/i; // match color code (case-insensitive)
|
||||
const projectLabels = await danger.gitlab.api.Labels.all(projectId); // Get all project labels
|
||||
const areaLabels = projectLabels
|
||||
.filter((label) => areaLabelColor.test(label.color))
|
||||
.map((label) => label.name); // Filter only area labels
|
||||
const mrLabels = danger.gitlab.mr.labels; // Get MR labels
|
||||
|
||||
if (!mrLabels.some((label) => areaLabels.includes(label))) {
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(
|
||||
`Please add some [area labels](${process.env.DANGER_GITLAB_HOST}/espressif/esp-idf/-/labels) to this MR.`
|
||||
);
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, "Passed");
|
||||
};
|
@ -1,165 +0,0 @@
|
||||
const {
|
||||
minimumSummaryChars,
|
||||
maximumSummaryChars,
|
||||
maximumBodyLineChars,
|
||||
allowedTypes,
|
||||
} = require("./mrCommitsConstants.js");
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Check that commit messages are based on the Espressif ESP-IDF project's rules for git commit messages.
|
||||
*
|
||||
* @dangerjs WARN
|
||||
*/
|
||||
module.exports = async function () {
|
||||
const ruleName = "Commit messages style";
|
||||
const mrCommits = danger.gitlab.commits;
|
||||
const lint = require("@commitlint/lint").default;
|
||||
|
||||
const lintingRules = {
|
||||
// rule definition: [(0-1 = off/on), (always/never = must be/mustn't be), (value)]
|
||||
"body-max-line-length": [1, "always", maximumBodyLineChars], // Max length of the body line
|
||||
"footer-leading-blank": [1, "always"], // Always have a blank line before the footer section
|
||||
"footer-max-line-length": [1, "always", maximumBodyLineChars], // Max length of the footer line
|
||||
"subject-max-length": [1, "always", maximumSummaryChars], // Max length of the "Summary"
|
||||
"subject-min-length": [1, "always", minimumSummaryChars], // Min length of the "Summary"
|
||||
"scope-case": [1, "always", "lower-case"], // "scope/component" must start with lower-case
|
||||
"subject-full-stop": [1, "never", "."], // "Summary" must not end with a full stop (period)
|
||||
"subject-empty": [1, "never"], // "Summary" is mandatory
|
||||
"type-case": [1, "always", "lower-case"], // "type/action" must start with lower-case
|
||||
"type-empty": [1, "never"], // "type/action" is mandatory
|
||||
"type-enum": [1, "always", allowedTypes], // "type/action" must be one of the allowed types
|
||||
"body-leading-blank": [1, "always"], // Always have a blank line before the body section
|
||||
};
|
||||
|
||||
// Switcher for AI suggestions (for poor messages)
|
||||
let generateAISuggestion = false;
|
||||
|
||||
// Search for the messages in each commit
|
||||
let issuesAllCommitMessages = [];
|
||||
|
||||
for (const commit of mrCommits) {
|
||||
const commitMessage = commit.message;
|
||||
const commitMessageTitle = commit.title;
|
||||
|
||||
let issuesSingleCommitMessage = [];
|
||||
let reportSingleCommitMessage = "";
|
||||
|
||||
// Check if the commit message contains any Jira ticket references
|
||||
const jiraTicketRegex = /[A-Z0-9]+-[0-9]+/g;
|
||||
const jiraTicketMatches = commitMessage.match(jiraTicketRegex);
|
||||
if (jiraTicketMatches) {
|
||||
const jiraTicketNames = jiraTicketMatches.join(", ");
|
||||
issuesSingleCommitMessage.push(
|
||||
`- probably contains Jira ticket reference (\`${jiraTicketNames}\`). Please remove Jira tickets from commit messages.`
|
||||
);
|
||||
}
|
||||
|
||||
// Lint commit messages with @commitlint (Conventional Commits style)
|
||||
const result = await lint(commit.message, lintingRules);
|
||||
|
||||
for (const warning of result.warnings) {
|
||||
// Custom messages for each rule with terminology used by Espressif conventional commits guide
|
||||
switch (warning.name) {
|
||||
case "subject-max-length":
|
||||
issuesSingleCommitMessage.push(
|
||||
`- *summary* appears to be too long`
|
||||
);
|
||||
break;
|
||||
case "type-empty":
|
||||
issuesSingleCommitMessage.push(
|
||||
`- *type/action* looks empty`
|
||||
);
|
||||
break;
|
||||
case "type-case":
|
||||
issuesSingleCommitMessage.push(
|
||||
`- *type/action* should start with a lowercase letter`
|
||||
);
|
||||
|
||||
break;
|
||||
case "scope-empty":
|
||||
issuesSingleCommitMessage.push(
|
||||
`- *scope/component* looks empty`
|
||||
);
|
||||
break;
|
||||
case "scope-case":
|
||||
issuesSingleCommitMessage.push(
|
||||
`- *scope/component* should be lowercase without whitespace, allowed special characters are \`_\` \`/\` \`.\` \`,\` \`*\` \`-\` \`.\``
|
||||
);
|
||||
break;
|
||||
case "subject-empty":
|
||||
issuesSingleCommitMessage.push(`- *summary* looks empty`);
|
||||
generateAISuggestion = true;
|
||||
break;
|
||||
case "subject-min-length":
|
||||
issuesSingleCommitMessage.push(
|
||||
`- *summary* looks too short`
|
||||
);
|
||||
generateAISuggestion = true;
|
||||
break;
|
||||
case "subject-case":
|
||||
issuesSingleCommitMessage.push(
|
||||
`- *summary* should start with a capital letter`
|
||||
);
|
||||
break;
|
||||
case "subject-full-stop":
|
||||
issuesSingleCommitMessage.push(
|
||||
`- *summary* should not end with a period (full stop)`
|
||||
);
|
||||
break;
|
||||
case "type-enum":
|
||||
issuesSingleCommitMessage.push(
|
||||
`- *type/action* should be one of [${allowedTypes
|
||||
.map((type) => `\`${type}\``)
|
||||
.join(", ")}]`
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
issuesSingleCommitMessage.push(`- ${warning.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (issuesSingleCommitMessage.length) {
|
||||
reportSingleCommitMessage = `- the commit message \`"${commitMessageTitle}"\`:\n${issuesSingleCommitMessage
|
||||
.map((message) => ` ${message}`) // Indent each issue by 2 spaces
|
||||
.join("\n")}`;
|
||||
issuesAllCommitMessages.push(reportSingleCommitMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// Create report
|
||||
if (issuesAllCommitMessages.length) {
|
||||
issuesAllCommitMessages.sort();
|
||||
const basicTips = [
|
||||
`- correct format of commit message should be: \`<type/action>(<scope/component>): <summary>\`, for example \`fix(esp32): Fixed startup timeout issue\``,
|
||||
`- allowed types are: \`${allowedTypes}\``,
|
||||
`- sufficiently descriptive message summary should be between ${minimumSummaryChars} to ${maximumSummaryChars} characters and start with upper case letter`,
|
||||
`- avoid Jira references in commit messages (unavailable/irrelevant for our customers)`,
|
||||
`- follow this [commit messages guide](${process.env.DANGER_GITLAB_HOST}/espressif/esp-idf/-/wikis/dev-proc/Commit-messages)`,
|
||||
];
|
||||
let dangerMessage = `\n**Some issues found for the commit messages in this MR:**\n${issuesAllCommitMessages.join(
|
||||
"\n"
|
||||
)}
|
||||
\n***
|
||||
\n**Please consider updating these commit messages** - here are some basic tips:\n${basicTips.join(
|
||||
"\n"
|
||||
)}
|
||||
\n \`TIP:\` You can install commit-msg pre-commit hook (\`pre-commit install -t pre-commit -t commit-msg\`) to run this check when committing.
|
||||
\n***
|
||||
`;
|
||||
|
||||
if (generateAISuggestion) {
|
||||
// Create AI generated suggestion for git commit message based of gitDiff and current commit messages
|
||||
const AImessageSuggestion =
|
||||
await require("./aiGenerateGitMessage.js")();
|
||||
dangerMessage += AImessageSuggestion;
|
||||
}
|
||||
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(dangerMessage);
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, "Passed");
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
module.exports = {
|
||||
gptStandardModelTokens: 4096,
|
||||
minimumSummaryChars: 20,
|
||||
maximumSummaryChars: 72,
|
||||
maximumBodyLineChars: 100,
|
||||
allowedTypes: [
|
||||
"change",
|
||||
"ci",
|
||||
"docs",
|
||||
"feat",
|
||||
"fix",
|
||||
"refactor",
|
||||
"remove",
|
||||
"revert",
|
||||
],
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Check if the author is accidentally making a commit using a personal email
|
||||
*
|
||||
* @dangerjs INFO
|
||||
*/
|
||||
module.exports = function () {
|
||||
const ruleName = 'Commits from outside Espressif';
|
||||
const mrCommitAuthorEmails = danger.gitlab.commits.map(commit => commit.author_email);
|
||||
const mrCommitCommitterEmails = danger.gitlab.commits.map(commit => commit.committer_email);
|
||||
const emailPattern = /.*@espressif\.com/;
|
||||
const filteredEmails = [...mrCommitAuthorEmails, ...mrCommitCommitterEmails].filter((email) => !emailPattern.test(email));
|
||||
if (filteredEmails.length) {
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return message(
|
||||
`Some of the commits were authored or committed by developers outside Espressif: ${filteredEmails.join(', ')}. Please check if this is expected.`
|
||||
);
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, 'Passed');
|
||||
};
|
@ -1,22 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Check if MR has not an excessive numbers of commits (if squashed)
|
||||
*
|
||||
* @dangerjs INFO
|
||||
*/
|
||||
module.exports = function () {
|
||||
const ruleName = 'Number of commits in merge request';
|
||||
const tooManyCommitThreshold = 2; // above this number of commits, squash commits is suggested
|
||||
const mrCommits = danger.gitlab.commits;
|
||||
|
||||
if (mrCommits.length > tooManyCommitThreshold) {
|
||||
recordRuleExitStatus(ruleName, "Passed (with suggestions)");
|
||||
return message(
|
||||
`You might consider squashing your ${mrCommits.length} commits (simplifying branch history).`
|
||||
);
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, 'Passed');
|
||||
};
|
@ -1,238 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/** Check that there are valid JIRA links in MR description.
|
||||
*
|
||||
* This check extracts the "Related" section from the MR description and
|
||||
* searches for JIRA ticket references in the format "Closes [JIRA ticket key]".
|
||||
*
|
||||
* It then extracts the closing GitHub links from the corresponding JIRA tickets and
|
||||
* checks if the linked GitHub issues are still in open state.
|
||||
*
|
||||
* Finally, it checks if the required GitHub closing links are present in the MR's commit messages.
|
||||
*
|
||||
*/
|
||||
module.exports = async function () {
|
||||
const ruleName = 'Jira ticket references';
|
||||
const axios = require("axios");
|
||||
const mrDescription = danger.gitlab.mr.description;
|
||||
const mrCommitMessages = danger.gitlab.commits.map(
|
||||
(commit) => commit.message
|
||||
);
|
||||
const jiraTicketRegex = /[A-Z0-9]+-[0-9]+/;
|
||||
|
||||
let partMessages = []; // Create a blank field for future records of individual issues
|
||||
|
||||
// Parse section "Related" from MR Description
|
||||
const sectionRelated = extractSectionRelated(mrDescription);
|
||||
|
||||
if (
|
||||
!sectionRelated.header || // No section Related in MR description or ...
|
||||
!jiraTicketRegex.test(sectionRelated.content) // no Jira links in section Related
|
||||
) {
|
||||
recordRuleExitStatus(ruleName, 'Passed (with suggestions)');
|
||||
return message(
|
||||
"Please consider adding references to JIRA issues in the `Related` section of the MR description."
|
||||
);
|
||||
}
|
||||
|
||||
// Get closing (only) JIRA tickets
|
||||
const jiraTickets = findClosingJiraTickets(sectionRelated.content);
|
||||
|
||||
for (const ticket of jiraTickets) {
|
||||
ticket.jiraUIUrl = `https://jira.espressif.com:8443/browse/${ticket.ticketName}`;
|
||||
|
||||
if (!ticket.correctFormat) {
|
||||
partMessages.push(
|
||||
`- closing ticket \`${ticket.record}\` seems to be in the wrong format (or inaccessible to Jira DangerBot).. The correct format is for example \`- Closes JIRA-123\`.`
|
||||
);
|
||||
}
|
||||
|
||||
// Get closing GitHub issue links from JIRA tickets
|
||||
const closingGithubLink = await getGitHubClosingLink(ticket.ticketName);
|
||||
if (closingGithubLink) {
|
||||
ticket.closingGithubLink = closingGithubLink;
|
||||
} else if (closingGithubLink === null) {
|
||||
partMessages.push(
|
||||
`- the Jira issue number [\`${ticket.ticketName}\`](${ticket.jiraUIUrl}) seems to be invalid (please check if the ticket number is correct)`
|
||||
);
|
||||
continue; // Handle unreachable JIRA tickets; skip the following checks
|
||||
} else {
|
||||
continue; // Jira ticket have no GitHub closing link; skip the following checks
|
||||
}
|
||||
|
||||
// Get still open GitHub issues
|
||||
const githubIssueStatusOpen = await isGithubIssueOpen(
|
||||
ticket.closingGithubLink
|
||||
);
|
||||
ticket.isOpen = githubIssueStatusOpen;
|
||||
if (githubIssueStatusOpen === null) {
|
||||
// Handle unreachable GitHub issues
|
||||
partMessages.push(
|
||||
`- the GitHub issue [\`${ticket.closingGithubLink}\`](${ticket.closingGithubLink}) does not seem to exist on GitHub (referenced from JIRA ticket [\`${ticket.ticketName}\`](${ticket.jiraUIUrl}) )`
|
||||
);
|
||||
continue; // skip the following checks
|
||||
}
|
||||
|
||||
// Search in commit message if there are all GitHub closing links (from Related section) for still open GH issues
|
||||
if (ticket.isOpen) {
|
||||
if (
|
||||
!mrCommitMessages.some((item) =>
|
||||
item.includes(`Closes ${ticket.closingGithubLink}`)
|
||||
)
|
||||
) {
|
||||
partMessages.push(
|
||||
`- please add \`Closes ${ticket.closingGithubLink}\` to the commit message`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create report / DangerJS check feedback if issues with Jira links found
|
||||
if (partMessages.length) {
|
||||
createReport();
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, 'Passed');
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This function takes in a string mrDescription which contains a Markdown-formatted text
|
||||
* related to a Merge Request (MR) in a GitLab repository. It searches for a section titled "Related"
|
||||
* and extracts the content of that section. If the section is not found, it returns an object
|
||||
* indicating that the header and content are null. If the section is found but empty, it returns
|
||||
* an object indicating that the header is present but the content is null. If the section is found
|
||||
* with content, it returns an object indicating that the header is present and the content of the
|
||||
* "Related" section.
|
||||
*
|
||||
* @param {string} mrDescription - The Markdown-formatted text related to the Merge Request.
|
||||
* @returns {{
|
||||
* header: string | boolean | null,
|
||||
* content: string | null
|
||||
* }} - An object containing the header and content of the "Related" section, if present.
|
||||
*/
|
||||
|
||||
function extractSectionRelated(mrDescription) {
|
||||
const regexSectionRelated = /## Related([\s\S]*?)(?=## |$)/;
|
||||
const sectionRelated = mrDescription.match(regexSectionRelated);
|
||||
if (!sectionRelated) {
|
||||
return { header: null, content: null }; // Section "Related" is missing
|
||||
}
|
||||
|
||||
const content = sectionRelated[1].replace(/(\r\n|\n|\r)/gm, ""); // Remove empty lines
|
||||
if (!content.length) {
|
||||
return { header: true, content: null }; // Section "Related" is present, but empty
|
||||
}
|
||||
|
||||
return { header: true, content: sectionRelated[1] }; // Found section "Related" with content
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all JIRA tickets that are being closed in the given sectionRelatedcontent.
|
||||
* The function searches for lines that start with - Closes and have the format Closes [uppercase letters]-[numbers].
|
||||
* @param {string} sectionRelatedcontent - A string that contains lines with mentions of JIRA tickets
|
||||
* @returns {Array} An array of objects with ticketName property that has the correct format
|
||||
*/
|
||||
|
||||
function findClosingJiraTickets(sectionRelatedcontent) {
|
||||
let closingTickets = [];
|
||||
const lines = sectionRelatedcontent.split("\n");
|
||||
for (const line of lines) {
|
||||
if (!line.startsWith("- Closes")) {
|
||||
continue; // Not closing-type ticket, skip
|
||||
}
|
||||
|
||||
const correctJiraClosingLinkFormat = new RegExp(
|
||||
`^- Closes ${jiraTicketRegex.source}$`
|
||||
);
|
||||
const matchedJiraTicket = line.match(jiraTicketRegex);
|
||||
if (matchedJiraTicket) {
|
||||
if (!correctJiraClosingLinkFormat.test(line)) {
|
||||
closingTickets.push({
|
||||
record: line,
|
||||
ticketName: matchedJiraTicket[0],
|
||||
correctFormat: false,
|
||||
});
|
||||
} else {
|
||||
closingTickets.push({
|
||||
record: line,
|
||||
ticketName: matchedJiraTicket[0],
|
||||
correctFormat: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return closingTickets;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function takes a JIRA issue key and retrieves the description from JIRA's API.
|
||||
* It then searches the description for a GitHub closing link in the format "Closes https://github.com/owner/repo/issues/123".
|
||||
* If a GitHub closing link is found, it is returned. If no GitHub closing link is found, it returns null.
|
||||
* @param {string} jiraIssueKey - The key of the JIRA issue to search for the GitHub closing link.
|
||||
* @returns {Promise<string|null>} - A promise that resolves to a string containing the GitHub closing link if found,
|
||||
* or null if not found.
|
||||
*/
|
||||
async function getGitHubClosingLink(jiraIssueKey) {
|
||||
let jiraDescription = "";
|
||||
|
||||
// Get JIRA ticket description content
|
||||
try {
|
||||
const response = await axios({
|
||||
url: `https://jira.espressif.com:8443/rest/api/latest/issue/${jiraIssueKey}`,
|
||||
auth: {
|
||||
username: process.env.DANGER_JIRA_USER,
|
||||
password: process.env.DANGER_JIRA_PASSWORD,
|
||||
},
|
||||
});
|
||||
jiraDescription = response.data.fields.description
|
||||
? response.data.fields.description
|
||||
: ""; // if the Jira ticket has an unfilled Description, the ".description" property is missing in API response - in that case set "jiraDescription" to an empty string
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find GitHub closing link in description
|
||||
const regexClosingGhLink =
|
||||
/Closes\s+(https:\/\/github.com\/\S+\/\S+\/issues\/\d+)/;
|
||||
const closingGithubLink = jiraDescription.match(regexClosingGhLink);
|
||||
|
||||
if (closingGithubLink) {
|
||||
return closingGithubLink[1];
|
||||
} else {
|
||||
return false; // Jira issue has no GitHub closing link in description
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a GitHub issue linked in a merge request is still open.
|
||||
*
|
||||
* @param {string} link - The link to the GitHub issue.
|
||||
* @returns {Promise<boolean>} A promise that resolves to a boolean indicating if the issue is open.
|
||||
* @throws {Error} If the link is invalid or if there was an error fetching the issue.
|
||||
*/
|
||||
async function isGithubIssueOpen(link) {
|
||||
const parsedUrl = new URL(link);
|
||||
const [owner, repo] = parsedUrl.pathname.split("/").slice(1, 3);
|
||||
const issueNumber = parsedUrl.pathname.split("/").slice(-1)[0];
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}`
|
||||
);
|
||||
return response.data.state === "open"; // return True if GitHub issue is open
|
||||
} catch (error) {
|
||||
return null; // GET request to issue fails
|
||||
}
|
||||
}
|
||||
|
||||
function createReport() {
|
||||
partMessages.sort();
|
||||
let dangerMessage = `Some issues found for the related JIRA tickets in this MR:\n${partMessages.join(
|
||||
"\n"
|
||||
)}`;
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(dangerMessage);
|
||||
}
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Check if MR Description has accurate description".
|
||||
*
|
||||
* @dangerjs WARN
|
||||
*/
|
||||
module.exports = function () {
|
||||
const ruleName = "Merge request sufficient description";
|
||||
const mrDescription = danger.gitlab.mr.description;
|
||||
const descriptionChunk = mrDescription.match(/^([^#]*)/)[1].trim(); // Extract all text before the first section header (i.e., the text before the "## Release notes")
|
||||
|
||||
const shortMrDescriptionThreshold = 50; // Description is considered too short below this number of characters
|
||||
|
||||
if (descriptionChunk.length < shortMrDescriptionThreshold) {
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(
|
||||
"The MR description looks very brief, please check if more details can be added."
|
||||
);
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, "Passed");
|
||||
};
|
@ -1,103 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Check if MR Description contains mandatory section "Release notes"
|
||||
*
|
||||
* Extracts the content of the "Release notes" section from the GitLab merge request description.
|
||||
*
|
||||
* @dangerjs WARN (if section missing, is empty or wrong markdown format)
|
||||
*/
|
||||
module.exports = function () {
|
||||
const ruleName = 'Merge request Release Notes section';
|
||||
const mrDescription = danger.gitlab.mr.description;
|
||||
const wiki_link = `${process.env.DANGER_GITLAB_HOST}/espressif/esp-idf/-/wikis/rfc/How-to-write-release-notes-properly`;
|
||||
|
||||
const regexSectionReleaseNotes = /## Release notes([\s\S]*?)(?=## |$)/;
|
||||
const regexValidEntry = /^\s*[-*+]\s+.+/;
|
||||
const regexNoReleaseNotes = /no release note/i;
|
||||
|
||||
const sectionReleaseNotes = mrDescription.match(regexSectionReleaseNotes);
|
||||
if (!sectionReleaseNotes) {
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(`The \`Release Notes\` section seems to be missing. Please check if the section header in MR description is present and in the correct markdown format ("## Release Notes").\n\nSee [Release Notes Format Rules](${wiki_link}).`);
|
||||
}
|
||||
|
||||
const releaseNotesLines = sectionReleaseNotes[1].replace(/<!--[\s\S]*?-->/g, '')
|
||||
|
||||
const lines = releaseNotesLines.split("\n").filter(s => s.trim().length > 0);
|
||||
let valid_entries_found = 0;
|
||||
let no_release_notes_found = false;
|
||||
let violations = [];
|
||||
|
||||
lines.forEach((line) => {
|
||||
if (line.match(regexValidEntry)) {
|
||||
valid_entries_found++;
|
||||
const error_msg = check_entry(line);
|
||||
if (error_msg) {
|
||||
violations.push(error_msg);
|
||||
}
|
||||
} else if (line.match(regexNoReleaseNotes)) {
|
||||
no_release_notes_found = true;
|
||||
}
|
||||
});
|
||||
|
||||
let error_output = [];
|
||||
if (violations.length > 0) {
|
||||
error_output = [...error_output, 'Invalid release note entries:', violations.join('\n')];
|
||||
}
|
||||
if (no_release_notes_found) {
|
||||
if (valid_entries_found > 0) {
|
||||
error_output.push('`No release notes` comment shows up when there is valid entry. Remove bullets before comments in release notes section.');
|
||||
}
|
||||
} else {
|
||||
if (!valid_entries_found) {
|
||||
error_output.push('The `Release Notes` section seems to have no valid entries. Add bullets before valid entries, or add `No release notes` comment to suppress this error if you mean to have no release notes.');
|
||||
}
|
||||
}
|
||||
|
||||
if (error_output.length > 0) {
|
||||
// Paragraphs joined by double `\n`s.
|
||||
error_output = [...error_output, `See [Release Notes Format Guide](${wiki_link}).`].join('\n\n');
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(error_output);
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, 'Passed');
|
||||
};
|
||||
|
||||
function check_entry(entry) {
|
||||
const entry_str = `- \`${entry}\``;
|
||||
const indent = " ";
|
||||
|
||||
if (entry.match(/no\s+release\s+note/i)) {
|
||||
return [entry_str, `${indent}- \`No release notes\` comment shouldn't start with bullet.`].join('\n');
|
||||
}
|
||||
|
||||
// Remove a leading escaping backslash of the special characters, https://www.markdownguide.org/basic-syntax/#characters-you-can-escape
|
||||
const escapeCharRegex = /\\([\\`*_{}[\]<>()+#-.!|])/g;
|
||||
entry = entry.replace(escapeCharRegex, '$1');
|
||||
|
||||
const regex = /^(\s*)[-*+]\s+\[([^\]]+)\]\s+(.*)$/;
|
||||
const match = regex.exec(entry);
|
||||
if (!match) {
|
||||
return [entry_str, `${indent}- Please specify the [area] to which the change belongs (see guide). If this line is just a comment, remove the bullet.`].join('\n');
|
||||
}
|
||||
|
||||
// area is in match[2]
|
||||
const description = match[3].trim();
|
||||
let violations = [];
|
||||
|
||||
if (match[1]) {
|
||||
violations.push(`${indent}- Release note entry should start from the beginning of line. (Nested release note not allowed.)`);
|
||||
}
|
||||
|
||||
if (!/^[A-Z0-9]/.test(description)) {
|
||||
violations.push(`${indent}- Release note statement should start with a capital letter or digit.`);
|
||||
}
|
||||
|
||||
if (violations.length > 0) {
|
||||
return [entry_str, ...violations].join('\n');
|
||||
}
|
||||
return null;
|
||||
}
|
@ -1,280 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Check the documentation files in this MR.
|
||||
*
|
||||
* Generate an object with all docs/ files found in this MR with paths to their EN/CN versions.
|
||||
*
|
||||
* For common files (both language versions exist in this MR), compare the lines of both files.
|
||||
* Ignore if the CN file is only a single line file with an "include" reference to the EN version.
|
||||
*
|
||||
* For files that only have a CN version in this MR, add a message to the message that an EN file also needs to be created.
|
||||
*
|
||||
* For a file that only has an EN version in this MR, try loading its CN version from the target Gitlab branch.
|
||||
* If its CN version doesn't exist in the repository or it does exist,
|
||||
* but its contents are larger than just an "include" link to the EN version (it's a full-size file),
|
||||
* add a message to the report
|
||||
*
|
||||
* Create a compiled report with the docs/ files issues found and set its severity (WARN/INFO).
|
||||
* Severity is based on the presence of "needs translation: ??" labels in this MR
|
||||
*
|
||||
* @dangerjs WARN (if docs translation issues in the MR)
|
||||
* @dangerjs INFO (if docs translation issues in the MR and the user has already added translation labels).
|
||||
* Adding translation labels "needs translation: XX" automatically notifies the Documentation team
|
||||
*
|
||||
* @dangerjs WARN (if there are no docs issues in MR, but translation labels have been added anyway)
|
||||
*
|
||||
*/
|
||||
module.exports = async function () {
|
||||
const ruleName = 'Documentation translation';
|
||||
let partMessages = []; // Create a blank field for future records of individual issues
|
||||
const pathProject = "espressif/esp-idf";
|
||||
const regexIncludeLink = /\.\.\sinclude::\s((\.\.\/)+)en\//;
|
||||
const allMrFiles = [
|
||||
...danger.git.modified_files,
|
||||
...danger.git.created_files,
|
||||
...danger.git.deleted_files,
|
||||
];
|
||||
|
||||
const docsFilesMR = parseMrDocsFiles(allMrFiles); // Create single object of all doc files in MR with names, paths and groups
|
||||
|
||||
// Both versions (EN and CN) of document found changed in this MR
|
||||
for (const file of docsFilesMR.bothFilesInMr) {
|
||||
file.contentEn = await getContentFileInMR(file.fileEnPath); // Get content of English file
|
||||
file.linesEn = file.contentEn.split("\n").length; // Get number of lines of English file
|
||||
|
||||
file.contentCn = await getContentFileInMR(file.fileCnPath); // Get content of Chinese file
|
||||
file.linesCn = file.contentCn.split("\n").length; // Get number of lines of English file
|
||||
|
||||
// Compare number of lines in both versions
|
||||
if (file.linesEn !== file.linesCn) {
|
||||
// Check if CN file is only link to EN file
|
||||
if (!regexIncludeLink.test(file.contentCn)) {
|
||||
// if not just a link ...
|
||||
partMessages.push(
|
||||
`- please synchronize the EN and CN version of \`${file.fileName}\`. [\`${file.fileEnPath}\`](${file.fileUrlRepoEN}) has ${file.linesEn} lines; [\`${file.fileCnPath}\`](${file.fileUrlRepoCN}) has ${file.linesCn} lines.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only Chinese version of document found changed in this MR
|
||||
for (const file of docsFilesMR.onlyCnFilesInMr) {
|
||||
partMessages.push(
|
||||
`- file \`${file.fileEnPath}\` doesn't exist in this MR or in the GitLab repo. Please add \`${file.fileEnPath}\` into this MR.`
|
||||
);
|
||||
}
|
||||
|
||||
// Only English version of document found in this MR
|
||||
for (const file of docsFilesMR.onlyEnFilesInMr) {
|
||||
const targetBranch = danger.gitlab.mr.target_branch;
|
||||
file.contentCn = await getContentFileInGitlab(
|
||||
file.fileCnPath,
|
||||
targetBranch
|
||||
); // Try to fetch CN file from target branch of Gitlab repository and store content
|
||||
|
||||
if (file.contentCn) {
|
||||
// File found on target branch in Gitlab repository
|
||||
if (!regexIncludeLink.test(file.contentCn)) {
|
||||
// File on Gitlab master is NOT just an ..include:: link to ENG version
|
||||
file.fileUrlRepoMasterCN = `${process.env.DANGER_GITLAB_HOST}/${pathProject}/-/blob/${targetBranch}/${file.fileCnPath}`;
|
||||
partMessages.push(
|
||||
`- file \`${file.fileCnPath}\` was not updated in this MR, but found unchanged full document (not just link to EN) in target branch of Gitlab repository [\`${file.fileCnPath}\`](${file.fileUrlRepoMasterCN}). Please update \`${file.fileCnPath}\` into this MR.`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// File failed to fetch, probably does not exist in the target branch
|
||||
partMessages.push(
|
||||
`- file \`${file.fileCnPath}\` probably doesn't exist in this MR or in the GitLab repo. Please add \`${file.fileCnPath}\` into this MR.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a report with found issues with documents in MR
|
||||
createReport();
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, 'Passed');
|
||||
|
||||
/**
|
||||
* Generates an object that represents the relationships between files in two different languages found in this MR.
|
||||
*
|
||||
* @param {string[]} docsFilesEN - An array of file paths for documents in English.
|
||||
* @param {string[]} docsFilesCN - An array of file paths for documents in Chinese.
|
||||
* @returns {Object} An object with the following properties:
|
||||
* - bothFilesInMr: An array of objects that represent files that found in MR in both languages. Each object has the following properties:
|
||||
* - fileName: The name of the file.
|
||||
* - fileEnPath: The path to the file in English.
|
||||
* - fileCnPath: The path to the file in Chinese.
|
||||
* - fileUrlRepoEN: The URL link to MR branch path to the file in English.
|
||||
* - fileUrlRepoCN: The URL link to MR branch path to the file in Chinese.
|
||||
* - onlyCnFilesInMr: An array of objects that represent files that only found in MR in English. Each object has the following properties:
|
||||
* - fileName: The name of the file.
|
||||
* - fileEnPath: The path to the file in English.
|
||||
* - fileCnPath: The FUTURE path to the file in Chinese.
|
||||
* - fileUrlRepoEN: The URL link to MR branch path to the file in English.
|
||||
* - fileUrlRepoCN: The URL link to MR branch path to the file in Chinese.
|
||||
* - onlyEnFilesInMr: An array of objects that represent files that only found in MR in Chinese. Each object has the following properties:
|
||||
* - fileName: The name of the file.
|
||||
* - fileEnPath: The FUTURE path to the file in English.
|
||||
* - fileCnPath: The path to the file in Chinese.
|
||||
* - fileUrlRepoEN: The URL link to MR branch path to the file in English.
|
||||
* - fileUrlRepoCN: The URL link to MR branch path to the file in Chinese.
|
||||
*/
|
||||
function parseMrDocsFiles(allMrFiles) {
|
||||
const path = require("path");
|
||||
const mrBranch = danger.gitlab.mr.source_branch;
|
||||
|
||||
const docsEnFilesMrPath = allMrFiles.filter((file) =>
|
||||
file.startsWith("docs/en")
|
||||
); // Filter all English doc files in MR
|
||||
const docsCnFilesMrPath = allMrFiles.filter((file) =>
|
||||
file.startsWith("docs/zh_CN")
|
||||
); // Filter all Chinese doc files in MR
|
||||
|
||||
const docsEnFileNames = docsEnFilesMrPath.map((filePath) =>
|
||||
path.basename(filePath)
|
||||
); // Get (base) file names for English docs
|
||||
const docsCnFileNames = docsCnFilesMrPath.map((filePath) =>
|
||||
path.basename(filePath)
|
||||
); // Get (base) file names for Chinese docs
|
||||
|
||||
const bothFileNames = docsEnFileNames.filter((fileName) =>
|
||||
docsCnFileNames.includes(fileName)
|
||||
); // Get file names that are common to both English and Chinese docs
|
||||
const onlyEnFileNames = docsEnFileNames.filter(
|
||||
(fileName) => !docsCnFileNames.includes(fileName)
|
||||
); // Get file names that are only present in English version
|
||||
const onlyCnFileNames = docsCnFileNames.filter(
|
||||
(fileName) => !docsEnFileNames.includes(fileName)
|
||||
); // Get file names that are only present in Chinese version
|
||||
|
||||
return {
|
||||
bothFilesInMr: bothFileNames.map((fileName) => {
|
||||
const fileEnPath =
|
||||
docsEnFilesMrPath[docsEnFileNames.indexOf(fileName)];
|
||||
const fileCnPath =
|
||||
docsCnFilesMrPath[docsCnFileNames.indexOf(fileName)];
|
||||
|
||||
return {
|
||||
fileName,
|
||||
fileEnPath,
|
||||
fileCnPath,
|
||||
fileUrlRepoEN: `${process.env.DANGER_GITLAB_HOST}/${pathProject}/-/blob/${mrBranch}/${fileEnPath}`,
|
||||
fileUrlRepoCN: `${process.env.DANGER_GITLAB_HOST}/${pathProject}/-/blob/${mrBranch}/${fileCnPath}`,
|
||||
};
|
||||
}),
|
||||
onlyEnFilesInMr: onlyEnFileNames.map((fileName) => {
|
||||
const fileEnPath =
|
||||
docsEnFilesMrPath[docsEnFileNames.indexOf(fileName)];
|
||||
const fileCnPath = fileEnPath.replace("en", "zh_CN"); // Generate future CN file path
|
||||
|
||||
return {
|
||||
fileName,
|
||||
fileEnPath,
|
||||
fileCnPath,
|
||||
fileUrlRepoEN: `${process.env.DANGER_GITLAB_HOST}/${pathProject}/-/blob/${mrBranch}/${fileEnPath}`,
|
||||
fileUrlRepoCN: `${process.env.DANGER_GITLAB_HOST}/${pathProject}/-/blob/${mrBranch}/${fileCnPath}`,
|
||||
};
|
||||
}),
|
||||
onlyCnFilesInMr: onlyCnFileNames.map((fileName) => {
|
||||
const fileCnPath =
|
||||
docsCnFilesMrPath[docsCnFileNames.indexOf(fileName)];
|
||||
const fileEnPath = fileCnPath.replace("zh_CN", "en"); // Generate future EN file path
|
||||
|
||||
return {
|
||||
fileName,
|
||||
fileEnPath,
|
||||
fileCnPath,
|
||||
fileUrlRepoEN: `${process.env.DANGER_GITLAB_HOST}/${pathProject}/-/blob/${mrBranch}/${fileEnPath}`,
|
||||
fileUrlRepoCN: `${process.env.DANGER_GITLAB_HOST}/${pathProject}/-/blob/${mrBranch}/${fileCnPath}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the contents of a file from GitLab using the GitLab API.
|
||||
*
|
||||
* @param {string} filePath - The path of the file to retrieve.
|
||||
* @param {string} branch - The branch where the file is located.
|
||||
* @returns {string|null} - The contents of the file, with any trailing new lines trimmed, or null if the file cannot be retrieved.
|
||||
*/
|
||||
async function getContentFileInGitlab(filePath, branch) {
|
||||
const axios = require("axios");
|
||||
|
||||
const encFilePath = encodeURIComponent(filePath);
|
||||
const encBranch = encodeURIComponent(branch);
|
||||
const urlApi = `${process.env.DANGER_GITLAB_API_BASE_URL}/projects/${danger.gitlab.mr.project_id}/repository/files/${encFilePath}/raw?ref=${encBranch}`;
|
||||
|
||||
try {
|
||||
const response = await axios.get(urlApi, {
|
||||
headers: {
|
||||
"Private-Token": process.env.DANGER_GITLAB_API_TOKEN,
|
||||
},
|
||||
});
|
||||
return response.data.trim(); // Trim trailing new line
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the contents of a file in a DangerJS merge request object.
|
||||
*
|
||||
* @param {string} filePath - The path of the file to retrieve.
|
||||
* @returns {string|null} - The contents of the file, with any trailing new lines trimmed, or null if the file cannot be retrieved.
|
||||
*/
|
||||
async function getContentFileInMR(filePath) {
|
||||
try {
|
||||
const content = await danger.git.diffForFile(filePath);
|
||||
const fileContentAfter = content.after.trim(); // Trim trailing new lines
|
||||
return fileContentAfter;
|
||||
} catch (error) {
|
||||
console.error(`Error while getting file content MR: ${error}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a compiled report for found documentation issues in the current MR and alerts the Documentation team if there are any "needs translation" labels present.
|
||||
*
|
||||
* Report if documentation labels have been added by mistake.
|
||||
*/
|
||||
function createReport() {
|
||||
const mrLabels = danger.gitlab.mr.labels; // Get MR labels
|
||||
const regexTranslationLabel = /needs translation:/i;
|
||||
|
||||
const translationLabelsPresent = mrLabels.some((label) =>
|
||||
regexTranslationLabel.test(label)
|
||||
); // Check if any of MR labels are "needs translation: XX"
|
||||
|
||||
// No docs issues found in MR, but translation labels have been added anyway
|
||||
if (!partMessages.length && translationLabelsPresent) {
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(
|
||||
`Please remove the \`needs translation: XX\` labels. For documents that need to translate from scratch, Doc team will translate them in the future. For the current stage, we only focus on updating exiting EN and CN translation to make them in sync.`
|
||||
);
|
||||
}
|
||||
|
||||
// Docs issues found in this MR
|
||||
partMessages.sort();
|
||||
let dangerMessage = `Some of the documentation files in this MR seem to have translations issues:\n${partMessages.join(
|
||||
"\n"
|
||||
)}\n`;
|
||||
|
||||
if (partMessages.length) {
|
||||
if (!translationLabelsPresent) {
|
||||
dangerMessage += `
|
||||
\nWhen synchronizing the EN and CN versions, please follow the [Documentation Code](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/contribute/documenting-code.html#standardize-document-format). The total number of lines of EN and CN should be same.\n
|
||||
\nIf you have difficulty in providing translation, you can contact Documentation team by adding <kbd>needs translation: CN</kbd> or <kbd>needs translation: EN</kbd> labels into this MR and retrying Danger CI job. The documentation team will be automatically notified and will help you with the translations before the merge.\n`;
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(dangerMessage); // no "needs translation: XX" labels in MR; report issues as warn
|
||||
} else {
|
||||
dangerMessage += `\nTranslation labels <kbd>needs translation: CN</kbd> or <kbd>needs translation: EN</kbd> were added - this will automatically notify the Documentation team to help you with translation issues.`;
|
||||
recordRuleExitStatus(ruleName, 'Passed (with suggestions)');
|
||||
return message(dangerMessage); // "needs translation: XX" labels were found in MR and Docs team was notified; report issues as info
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -1,22 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Check if MR is too large (more than 1000 lines of changes)
|
||||
*
|
||||
* @dangerjs INFO
|
||||
*/
|
||||
module.exports = async function () {
|
||||
const ruleName = "Merge request size (number of changed lines)";
|
||||
const bigMrLinesOfCodeThreshold = 1000;
|
||||
const totalLines = await danger.git.linesOfCode();
|
||||
|
||||
if (totalLines > bigMrLinesOfCodeThreshold) {
|
||||
recordRuleExitStatus(ruleName, "Passed (with suggestions)");
|
||||
return message(
|
||||
`This MR seems to be quite large (total lines of code: ${totalLines}), you might consider splitting it into smaller MRs`
|
||||
);
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, "Passed");
|
||||
};
|
@ -1,31 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Throw Danger WARN if branch name contains more than one slash or uppercase letters
|
||||
*
|
||||
* @dangerjs INFO
|
||||
*/
|
||||
module.exports = function () {
|
||||
const ruleName = "Source branch name";
|
||||
const sourceBranch = danger.gitlab.mr.source_branch;
|
||||
|
||||
// Check if the source branch name contains more than one slash
|
||||
const slashCount = (sourceBranch.match(/\//g) || []).length;
|
||||
if (slashCount > 1) {
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(
|
||||
`The source branch name \`${sourceBranch}\` contains more than one slash. This can cause troubles with git sync. Please rename the branch.`
|
||||
);
|
||||
}
|
||||
|
||||
// Check if the source branch name contains any uppercase letters
|
||||
if (sourceBranch !== sourceBranch.toLowerCase()) {
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(
|
||||
`The source branch name \`${sourceBranch}\` contains uppercase letters. This can cause troubles on case-insensitive file systems (macOS). Please use only lowercase letters.`
|
||||
);
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, "Passed");
|
||||
};
|
@ -1,31 +0,0 @@
|
||||
const { recordRuleExitStatus } = require("./configParameters.js");
|
||||
|
||||
/**
|
||||
* Check if MR Title contains prefix "WIP: ...".
|
||||
*
|
||||
* @dangerjs WARN
|
||||
*/
|
||||
module.exports = function () {
|
||||
const ruleName = 'Merge request not in Draft or WIP state';
|
||||
const mrTitle = danger.gitlab.mr.title;
|
||||
const regexes = [
|
||||
{ prefix: "WIP", regex: /^WIP:/i },
|
||||
{ prefix: "W.I.P", regex: /^W\.I\.P/i },
|
||||
{ prefix: "[WIP]", regex: /^\[WIP/i },
|
||||
{ prefix: "[W.I.P]", regex: /^\[W\.I\.P/i },
|
||||
{ prefix: "(WIP)", regex: /^\(WIP/i },
|
||||
{ prefix: "(W.I.P)", regex: /^\(W\.I\.P/i },
|
||||
];
|
||||
|
||||
for (const item of regexes) {
|
||||
if (item.regex.test(mrTitle)) {
|
||||
recordRuleExitStatus(ruleName, "Failed");
|
||||
return warn(
|
||||
`Please remove the \`${item.prefix}\` prefix from the MR name before merging this MR.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, the rule has passed
|
||||
recordRuleExitStatus(ruleName, "Passed");
|
||||
};
|
2745
.gitlab/dangerjs/package-lock.json
generated
2745
.gitlab/dangerjs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "dangerjs-esp-idf",
|
||||
"description": "Merge request automatic linter",
|
||||
"main": "dangerfile.js",
|
||||
"dependencies": {
|
||||
"danger": "^11.2.3",
|
||||
"axios": "^1.3.3",
|
||||
"langchain": "^0.0.53",
|
||||
"openai-gpt-token-counter": "^1.0.3",
|
||||
"@commitlint/lint": "^13.1.0"
|
||||
}
|
||||
}
|
@ -42,7 +42,7 @@ _For other small/non-public changes, which are not expected to be in the release
|
||||
|
||||
_Don't touch the subsection titles below, they will be parsed by scripts._
|
||||
|
||||
## Release notes (Mandatory)
|
||||
## Release notes <!-- Mandatory -->
|
||||
|
||||
_Changes made in this MR that should go into the **Release Notes** should be listed here. Please use **past tense** and *specify the area (see maintainers page of IDF internal wiki)*. If there is a subscope, include it and separate with slash (`/`). Minor changes can go to the descriptions above without a release notes entry._
|
||||
|
||||
|
8
.gitmodules
vendored
8
.gitmodules
vendored
@ -81,11 +81,11 @@
|
||||
[submodule "components/unity/unity"]
|
||||
path = components/unity/unity
|
||||
url = ../../ThrowTheSwitch/Unity.git
|
||||
sbom-version = v2.4.3-51-g7d2bf62b7e6a
|
||||
sbom-version = v2.6.0-RC1
|
||||
sbom-supplier = Organization: ThrowTheSwitch community <http://www.throwtheswitch.org>
|
||||
sbom-url = https://github.com/ThrowTheSwitch/Unity
|
||||
sbom-description = Simple Unit Testing for C
|
||||
sbom-hash = 7d2bf62b7e6afaf38153041a9d53c21aeeca9a25
|
||||
sbom-hash = bf560290f6020737eafaa8b5cbd2177c3956c03f
|
||||
|
||||
[submodule "components/bt/host/nimble/nimble"]
|
||||
path = components/bt/host/nimble/nimble
|
||||
@ -143,3 +143,7 @@
|
||||
[submodule "components/esp_coex/lib"]
|
||||
path = components/esp_coex/lib
|
||||
url = ../../espressif/esp-coex-lib.git
|
||||
|
||||
[submodule "components/bt/esp_ble_mesh/lib/lib"]
|
||||
path = components/bt/esp_ble_mesh/lib/lib
|
||||
url = ../../espressif/esp-ble-mesh-lib.git
|
||||
|
@ -200,7 +200,7 @@ repos:
|
||||
- id: check-copyright
|
||||
args: ['--ignore', 'tools/ci/check_copyright_ignore.txt', '--config', 'tools/ci/check_copyright_config.yaml']
|
||||
- repo: https://github.com/espressif/conventional-precommit-linter
|
||||
rev: v1.2.1
|
||||
rev: v1.3.0
|
||||
hooks:
|
||||
- id: conventional-precommit-linter
|
||||
stages: [commit-msg]
|
||||
|
8
Kconfig
8
Kconfig
@ -114,6 +114,13 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
|
||||
config IDF_TARGET_ESP32C5
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32c5"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
select IDF_ENV_BRINGUP
|
||||
|
||||
config IDF_TARGET_ESP32P4
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32p4"
|
||||
@ -139,6 +146,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default 0x000D if IDF_TARGET_ESP32C6
|
||||
default 0x0010 if IDF_TARGET_ESP32H2
|
||||
default 0x0012 if IDF_TARGET_ESP32P4
|
||||
default 0x0013 if IDF_TARGET_ESP32C5
|
||||
default 0xFFFF
|
||||
|
||||
|
||||
|
@ -231,7 +231,7 @@ menu "Application Level Tracing"
|
||||
|
||||
choice APPTRACE_SV_CPU
|
||||
prompt "CPU to trace"
|
||||
depends on APPTRACE_SV_DEST_UART && !FREERTOS_UNICORE
|
||||
depends on APPTRACE_SV_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
default APPTRACE_SV_DEST_CPU_0
|
||||
help
|
||||
Define the CPU to trace by SystemView.
|
||||
@ -252,8 +252,8 @@ menu "Application Level Tracing"
|
||||
choice APPTRACE_SV_TS_SOURCE
|
||||
prompt "Timer to use as timestamp source"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default APPTRACE_SV_TS_SOURCE_CCOUNT if FREERTOS_UNICORE && !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
default APPTRACE_SV_TS_SOURCE_GPTIMER if !FREERTOS_UNICORE && !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
default APPTRACE_SV_TS_SOURCE_CCOUNT if ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
default APPTRACE_SV_TS_SOURCE_GPTIMER if !ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
default APPTRACE_SV_TS_SOURCE_ESP_TIMER if PM_ENABLE || IDF_TARGET_ESP32C3
|
||||
help
|
||||
SystemView needs to use a hardware timer as the source of timestamps
|
||||
@ -261,7 +261,7 @@ menu "Application Level Tracing"
|
||||
|
||||
config APPTRACE_SV_TS_SOURCE_CCOUNT
|
||||
bool "CPU cycle counter (CCOUNT)"
|
||||
depends on FREERTOS_UNICORE && !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
depends on ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
|
||||
config APPTRACE_SV_TS_SOURCE_GPTIMER
|
||||
bool "General Purpose Timer (Timer Group)"
|
||||
|
@ -77,7 +77,7 @@ esp_err_t esp_apptrace_init(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_SYSTEM_INIT_FN(esp_apptrace_init, ESP_SYSTEM_INIT_ALL_CORES, 115)
|
||||
ESP_SYSTEM_INIT_FN(esp_apptrace_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 115)
|
||||
{
|
||||
return esp_apptrace_init();
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ static inline void esp_apptrace_trax_memory_enable(void)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Enable trace memory on PRO CPU */
|
||||
DPORT_WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, DPORT_PRO_TRACEMEM_ENA_M);
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE == 0
|
||||
/* Enable trace memory on APP CPU */
|
||||
DPORT_WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, DPORT_APP_TRACEMEM_ENA_M);
|
||||
#endif
|
||||
|
@ -35,7 +35,7 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
|
||||
#if CONFIG_APPTRACE_SV_DEST_UART
|
||||
|
||||
#define ESP_APPTRACE_DEST_SYSVIEW ESP_APPTRACE_DEST_UART
|
||||
#if CONFIG_APPTRACE_SV_DEST_CPU_0 || CONFIG_FREERTOS_UNICORE
|
||||
#if CONFIG_APPTRACE_SV_DEST_CPU_0 || CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
#define APPTRACE_SV_DEST_CPU 0
|
||||
#else
|
||||
#define APPTRACE_SV_DEST_CPU 1
|
||||
@ -296,7 +296,7 @@ int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* p
|
||||
* linked whenever SystemView is used.
|
||||
*/
|
||||
|
||||
ESP_SYSTEM_INIT_FN(sysview_init, BIT(0), 120)
|
||||
ESP_SYSTEM_INIT_FN(sysview_init, SECONDARY, BIT(0), 120)
|
||||
{
|
||||
SEGGER_SYSVIEW_Conf();
|
||||
return ESP_OK;
|
||||
|
@ -105,7 +105,6 @@ menu "Bootloader config"
|
||||
config BOOTLOADER_FLASH_XMC_SUPPORT
|
||||
bool "Enable the support for flash chips of XMC (READ DOCS FIRST)"
|
||||
default y
|
||||
depends on !IDF_ENV_BRINGUP
|
||||
help
|
||||
Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow.
|
||||
XMC chips will be forbidden to be used, when this option is disabled.
|
||||
|
@ -39,7 +39,7 @@ inline static bool esp_dram_match_iram(void) {
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
inline static bool esp_ptr_in_iram(const void *p) {
|
||||
#if CONFIG_IDF_TARGET_ESP32 && CONFIG_FREERTOS_UNICORE
|
||||
#if CONFIG_IDF_TARGET_ESP32 && CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
return ((intptr_t)p >= SOC_CACHE_APP_LOW && (intptr_t)p < SOC_IRAM_HIGH);
|
||||
#else
|
||||
return ((intptr_t)p >= SOC_IRAM_LOW && (intptr_t)p < SOC_IRAM_HIGH);
|
||||
|
@ -21,6 +21,7 @@ typedef enum {
|
||||
ESP_CHIP_ID_ESP32C6 = 0x000D, /*!< chip ID: ESP32-C6 */
|
||||
ESP_CHIP_ID_ESP32H2 = 0x0010, /*!< chip ID: ESP32-H2 */
|
||||
ESP_CHIP_ID_ESP32P4 = 0x0012, /*!< chip ID: ESP32-P4 */
|
||||
ESP_CHIP_ID_ESP32C5 = 0x0013, /*!< chip ID: ESP32-C5 */
|
||||
ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */
|
||||
} __attribute__((packed)) esp_chip_id_t;
|
||||
|
||||
|
@ -103,7 +103,7 @@ void bootloader_print_banner(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
#if (SOC_CPU_CORES_NUM > 1)
|
||||
ESP_EARLY_LOGW(TAG, "Unicore bootloader");
|
||||
#endif
|
||||
|
@ -884,7 +884,7 @@ static void set_cache_and_start_app(
|
||||
bus_mask = cache_ll_l1_get_bus(0, irom_load_addr_aligned, irom_size);
|
||||
cache_ll_l1_enable_bus(0, bus_mask);
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
bus_mask = cache_ll_l1_get_bus(1, drom_load_addr_aligned, drom_size);
|
||||
cache_ll_l1_enable_bus(1, bus_mask);
|
||||
bus_mask = cache_ll_l1_get_bus(1, irom_load_addr_aligned, irom_size);
|
||||
|
@ -44,15 +44,15 @@ static void bootloader_reset_mmu(void)
|
||||
{
|
||||
/* completely reset MMU in case serial bootloader was running */
|
||||
Cache_Read_Disable(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
Cache_Read_Disable(1);
|
||||
#endif
|
||||
Cache_Flush(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
Cache_Flush(1);
|
||||
#endif
|
||||
mmu_init(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
/* The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
|
||||
necessary to work around a hardware bug. */
|
||||
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
@ -63,7 +63,7 @@ static void bootloader_reset_mmu(void)
|
||||
/* normal ROM boot exits with DROM0 cache unmasked,
|
||||
but serial bootloader exits with it masked. */
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
|
||||
#endif
|
||||
}
|
||||
@ -104,7 +104,7 @@ static void wdt_reset_info_dump(int cpu)
|
||||
lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
} else {
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
|
||||
@ -154,7 +154,7 @@ static void bootloader_check_wdt_reset(void)
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
wdt_reset_info_dump(1);
|
||||
#endif
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ static void bootloader_check_wdt_reset(void)
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
wdt_reset_info_dump(1);
|
||||
#endif
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ static void wdt_reset_info_dump(int cpu)
|
||||
lsaddr = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGLS0DATA_REG);
|
||||
} else {
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
inst = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGINST_REG);
|
||||
dstat = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGSTATUS_REG);
|
||||
data = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGDATA_REG);
|
||||
@ -115,7 +115,7 @@ static void bootloader_check_wdt_reset(void)
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
wdt_reset_info_dump(1);
|
||||
#endif
|
||||
}
|
||||
|
@ -4,7 +4,3 @@ components/bootloader_support/test_apps/rtc_custom_section:
|
||||
enable:
|
||||
- if: SOC_RTC_MEM_SUPPORTED == 1
|
||||
reason: this feature is supported on chips that have RTC memory
|
||||
disable:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
reason: this feature on esp32p4 isn't supported yet # TODO: IDF-8069
|
||||
|
@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
@ -45,10 +45,10 @@ set(ble_mesh_include_dirs
|
||||
"esp_ble_mesh/api/core/include"
|
||||
"esp_ble_mesh/api/models/include"
|
||||
"esp_ble_mesh/api"
|
||||
"esp_ble_mesh/lib/include"
|
||||
"esp_ble_mesh/v1.1/api/core/include"
|
||||
"esp_ble_mesh/v1.1/api/models/include"
|
||||
"esp_ble_mesh/v1.1/btc/include"
|
||||
"esp_ble_mesh/v1.1/include"
|
||||
)
|
||||
|
||||
set(bluedroid_include_dirs host/bluedroid/api/include/api)
|
||||
@ -550,7 +550,7 @@ if(CONFIG_BT_ENABLED)
|
||||
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c"
|
||||
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c"
|
||||
"esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c"
|
||||
"esp_ble_mesh/v1.1/ext.c")
|
||||
"esp_ble_mesh/lib/ext.c")
|
||||
|
||||
if(CONFIG_BLE_MESH_SAR_ENHANCEMENT)
|
||||
list(APPEND srcs "esp_ble_mesh/core/transport.enh.c")
|
||||
@ -826,20 +826,20 @@ endif()
|
||||
|
||||
if(CONFIG_BLE_MESH)
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
add_prebuilt_library(mesh_v11 "esp_ble_mesh/v1.1/lib/esp32/libmesh_v1.1.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE mesh_v11)
|
||||
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32/libble_mesh.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
add_prebuilt_library(mesh_v11 "esp_ble_mesh/v1.1/lib/esp32s3/libmesh_v1.1.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE mesh_v11)
|
||||
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C3)
|
||||
add_prebuilt_library(mesh_v11 "esp_ble_mesh/v1.1/lib/esp32c3/libmesh_v1.1.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE mesh_v11)
|
||||
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C6)
|
||||
add_prebuilt_library(mesh_v11 "esp_ble_mesh/v1.1/lib/esp32c6/libmesh_v1.1.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE mesh_v11)
|
||||
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32H2)
|
||||
add_prebuilt_library(mesh_v11 "esp_ble_mesh/v1.1/lib/esp32h2/libmesh_v1.1.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE mesh_v11)
|
||||
add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -16,8 +16,8 @@
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "xtensa_api.h" // Replace with interrupt allocator API (IDF-3891)
|
||||
#include "xtensa/core-macros.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_mac.h"
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <xtensa/coreasm.h>
|
||||
#include <xtensa/corebits.h>
|
||||
#include <xtensa/config/system.h>
|
||||
#include "freertos/xtensa_context.h"
|
||||
#include "xtensa_context.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
|
@ -43,8 +43,6 @@
|
||||
#include "riscv/interrupt.h"
|
||||
#include "esp32c3/rom/rom_layout.h"
|
||||
#else //CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "xtensa/core-macros.h"
|
||||
#include "esp32s3/rom/rom_layout.h"
|
||||
#endif
|
||||
#if CONFIG_BT_ENABLED
|
||||
|
0
components/bt/controller/esp32c5/Kconfig.in
Normal file
0
components/bt/controller/esp32c5/Kconfig.in
Normal file
@ -1 +1 @@
|
||||
Subproject commit cddb921d20418cef04de83ddfe3543463dfbc2bc
|
||||
Subproject commit 06ad44e581b3141929850cd705c735d0bd3207b0
|
@ -1 +1 @@
|
||||
Subproject commit 1e8bbd6f1af71b90a2e8130e77ed49dc799031fe
|
||||
Subproject commit 5dc39aabee570806cbdaed1886d07bd91451cd60
|
@ -1 +1 @@
|
||||
Subproject commit cecbe387799b41346c0affab41f339306a33e518
|
||||
Subproject commit f103dfec019fdd5bf9255abcaeaf20c707b26dc6
|
@ -1 +1 @@
|
||||
Subproject commit e70c4abbd5666afac3b7b3cea1c3d9c59ee33ce9
|
||||
Subproject commit 0caa942705eb9876a82d5ab609413eccbc712a42
|
@ -1 +1 @@
|
||||
Subproject commit 66303b4a8cc8e889a0c9bdd7301582ba2cb8b0eb
|
||||
Subproject commit acf295055730cc2acba07dadfc55716cf65faacd
|
@ -14,6 +14,7 @@ if BLE_MESH
|
||||
select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32C3
|
||||
select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32C6
|
||||
select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32H2
|
||||
select BT_NIMBLE_VS_SUPPORT if BT_NIMBLE_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable this option to allow using specific duplicate scan filter
|
||||
|
@ -1940,10 +1940,6 @@ int bt_mesh_update_exceptional_list(uint8_t sub_code, uint32_t type, void *info)
|
||||
uint8_t value[6] = {0};
|
||||
int rc = 0;
|
||||
|
||||
#if MYNEWT_VAL(BLE_HCI_VS)
|
||||
struct ble_hci_vs_duplicate_exception_list_cp cmd;
|
||||
#endif
|
||||
|
||||
if ((sub_code > BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN) ||
|
||||
(sub_code < BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN &&
|
||||
type > BLE_MESH_EXCEP_LIST_TYPE_MESH_PROXY_ADV) ||
|
||||
@ -1974,12 +1970,7 @@ int bt_mesh_update_exceptional_list(uint8_t sub_code, uint32_t type, void *info)
|
||||
BT_DBG("%s exceptional list, type 0x%08x", sub_code ? "Remove" : "Add", type);
|
||||
|
||||
#if MYNEWT_VAL(BLE_HCI_VS)
|
||||
cmd.operation = sub_code;
|
||||
cmd.type = htole32(type);
|
||||
memcpy(&cmd.device_info, value, 6);
|
||||
|
||||
rc = ble_hs_hci_send_vs_cmd(BLE_HCI_OCF_VS_DUPLICATE_EXCEPTION_LIST,
|
||||
&cmd, sizeof(cmd), NULL, 0);
|
||||
rc = ble_gap_duplicate_exception_list(sub_code, type, value, NULL);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
|
1
components/bt/esp_ble_mesh/lib/lib
Submodule
1
components/bt/esp_ble_mesh/lib/lib
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 73b3b96db91d170d96e0f3e901a47f51e749e75b
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1051,7 +1051,7 @@ config BT_ACL_CONNECTIONS
|
||||
|
||||
config BT_MULTI_CONNECTION_ENBALE
|
||||
bool "Enable BLE multi-conections"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
depends on BT_BLE_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable this option if there are multiple connections
|
||||
@ -1072,7 +1072,7 @@ config BT_BLE_DYNAMIC_ENV_MEMORY
|
||||
|
||||
config BT_BLE_HOST_QUEUE_CONG_CHECK
|
||||
bool "BLE queue congestion check"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
depends on BT_BLE_ENABLED
|
||||
default n
|
||||
help
|
||||
When scanning and scan duplicate is not enabled, if there are a lot of adv packets around
|
||||
@ -1097,7 +1097,7 @@ config BT_BLE_ACT_SCAN_REP_ADV_SCAN
|
||||
|
||||
config BT_BLE_ESTAB_LINK_CONN_TOUT
|
||||
int "Timeout of BLE connection establishment"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
depends on BT_BLE_ENABLED
|
||||
range 1 60
|
||||
default 30
|
||||
help
|
||||
@ -1133,7 +1133,7 @@ config BT_BLE_RPA_SUPPORTED
|
||||
|
||||
config BT_BLE_RPA_TIMEOUT
|
||||
int "Timeout of resolvable private address"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
depends on BT_BLE_ENABLED
|
||||
range 1 3600
|
||||
default 900
|
||||
help
|
||||
@ -1142,14 +1142,14 @@ config BT_BLE_RPA_TIMEOUT
|
||||
|
||||
config BT_BLE_50_FEATURES_SUPPORTED
|
||||
bool "Enable BLE 5.0 features"
|
||||
depends on (BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_50_SUPPORTED) || BT_CONTROLLER_DISABLED))
|
||||
depends on (BT_BLE_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_50_SUPPORTED) || BT_CONTROLLER_DISABLED))
|
||||
default y
|
||||
help
|
||||
This enables BLE 5.0 features, this option only support esp32c3/esp32s3 chip
|
||||
Enabling this option activates BLE 5.0 features. This option is universally supported in chips that support BLE, except for ESP32.
|
||||
|
||||
config BT_BLE_42_FEATURES_SUPPORTED
|
||||
bool "Enable BLE 4.2 features"
|
||||
depends on (BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_SUPPORTED) || BT_CONTROLLER_DISABLED))
|
||||
depends on (BT_BLE_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_SUPPORTED) || BT_CONTROLLER_DISABLED))
|
||||
default n
|
||||
help
|
||||
This enables BLE 4.2 features.
|
||||
@ -1168,9 +1168,16 @@ config BT_BLE_FEAT_PERIODIC_ADV_ENH
|
||||
help
|
||||
Enable the periodic advertising enhancements
|
||||
|
||||
config BT_BLE_FEAT_CREATE_SYNC_ENH
|
||||
bool "Enable create sync enhancements(reporting disable and duplicate filtering enable support)"
|
||||
depends on (BT_BLUEDROID_ENABLED && BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_ESP_NIMBLE_CONTROLLER) || BT_CONTROLLER_DISABLED))
|
||||
default n
|
||||
help
|
||||
Enable the create sync enhancements
|
||||
|
||||
config BT_BLE_HIGH_DUTY_ADV_INTERVAL
|
||||
bool "Enable BLE high duty advertising interval feature"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
depends on BT_BLE_ENABLED
|
||||
default n
|
||||
help
|
||||
This enable BLE high duty advertising interval feature
|
||||
|
@ -904,12 +904,22 @@ typedef struct {
|
||||
* @brief periodic adv sync parameters
|
||||
*/
|
||||
typedef struct {
|
||||
esp_ble_gap_sync_t filter_policy; /*!< periodic advertising sync filter policy */
|
||||
uint8_t sid; /*!< periodic advertising sid */
|
||||
esp_ble_addr_type_t addr_type; /*!< periodic advertising address type */
|
||||
esp_bd_addr_t addr; /*!< periodic advertising address */
|
||||
uint16_t skip; /*!< the maximum number of periodic advertising events that can be skipped */
|
||||
uint16_t sync_timeout; /*!< synchronization timeout */
|
||||
esp_ble_gap_sync_t filter_policy; /*!< Configures the filter policy for periodic advertising sync:
|
||||
0: Use Advertising SID, Advertiser Address Type, and Advertiser Address parameters to determine the advertiser to listen to.
|
||||
1: Use the Periodic Advertiser List to determine the advertiser to listen to. */
|
||||
#if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH)
|
||||
esp_ble_gap_sync_t reports_disabled; /*!< Supported only by esp32c2, esp32c6, and esp32h2; can be set by menuconfig:
|
||||
0: Reporting initially enabled.
|
||||
1: Reporting initially disabled. */
|
||||
esp_ble_gap_sync_t filter_duplicates; /*!< Supported only by esp32c2, esp32c6, and esp32h2; can be set by menuconfig:
|
||||
0: Duplicate filtering initially disabled.
|
||||
1: Duplicate filtering initially enabled. */
|
||||
#endif
|
||||
uint8_t sid; /*!< SID of the periodic advertising */
|
||||
esp_ble_addr_type_t addr_type; /*!< Address type of the periodic advertising */
|
||||
esp_bd_addr_t addr; /*!< Address of the periodic advertising */
|
||||
uint16_t skip; /*!< Maximum number of periodic advertising events that can be skipped */
|
||||
uint16_t sync_timeout; /*!< Synchronization timeout */
|
||||
} esp_ble_gap_periodic_adv_sync_params_t;
|
||||
|
||||
/**
|
||||
|
@ -1539,6 +1539,10 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
UINT8 filter_policy;
|
||||
#if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH)
|
||||
UINT8 reports_disabled;
|
||||
UINT8 filter_duplicates;
|
||||
#endif
|
||||
UINT8 sid;
|
||||
tBLE_ADDR_TYPE addr_type;
|
||||
BD_ADDR addr;
|
||||
|
@ -2076,6 +2076,10 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
|
||||
params.addr_type = arg_5->periodic_adv_create_sync.params.addr_type;
|
||||
params.skip = arg_5->periodic_adv_create_sync.params.skip;
|
||||
params.sync_timeout = arg_5->periodic_adv_create_sync.params.sync_timeout;
|
||||
#if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH)
|
||||
params.reports_disabled = arg_5->periodic_adv_create_sync.params.reports_disabled;
|
||||
params.filter_duplicates = arg_5->periodic_adv_create_sync.params.filter_duplicates;
|
||||
#endif
|
||||
|
||||
memcpy(params.addr, arg_5->periodic_adv_create_sync.params.addr, sizeof(BD_ADDR));
|
||||
BTC_TRACE_DEBUG("BTC_GAP_BLE_PERIODIC_ADV_CREATE_SYNC");
|
||||
|
@ -272,15 +272,17 @@ static void close_timeout_handler(void *arg)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
bt_status_t status;
|
||||
l2cap_slot_t *slot = (l2cap_slot_t *)arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_L2CAP;
|
||||
msg.act = BTA_JV_L2CAP_CLOSE_EVT;
|
||||
|
||||
status = btc_transfer_context(&msg, arg, sizeof(tBTA_JV), NULL, NULL);
|
||||
status = btc_transfer_context(&msg, slot->alarm_arg, sizeof(tBTA_JV), NULL, NULL);
|
||||
|
||||
if (arg) {
|
||||
free(arg);
|
||||
if (slot->alarm_arg) {
|
||||
free(slot->alarm_arg);
|
||||
slot->alarm_arg = NULL;
|
||||
}
|
||||
|
||||
if (status != BT_STATUS_SUCCESS) {
|
||||
@ -837,9 +839,11 @@ void btc_l2cap_cb_handler(btc_msg_t *msg)
|
||||
break;
|
||||
}
|
||||
memcpy(p_arg, p_data, sizeof(tBTA_JV));
|
||||
slot->alarm_arg = (void *)p_arg;
|
||||
if ((slot->close_alarm =
|
||||
osi_alarm_new("slot", close_timeout_handler, (void *)p_arg, VFS_CLOSE_TIMEOUT)) == NULL) {
|
||||
osi_alarm_new("slot", close_timeout_handler, (void *)slot, VFS_CLOSE_TIMEOUT)) == NULL) {
|
||||
free(p_arg);
|
||||
slot->alarm_arg = NULL;
|
||||
param.close.status = ESP_BT_L2CAP_NO_RESOURCE;
|
||||
osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex);
|
||||
BTC_TRACE_ERROR("%s unable to malloc slot close_alarm!", __func__);
|
||||
@ -847,6 +851,7 @@ void btc_l2cap_cb_handler(btc_msg_t *msg)
|
||||
}
|
||||
if (osi_alarm_set(slot->close_alarm, VFS_CLOSE_TIMEOUT) != OSI_ALARM_ERR_PASS) {
|
||||
free(p_arg);
|
||||
slot->alarm_arg = NULL;
|
||||
osi_alarm_free(slot->close_alarm);
|
||||
param.close.status = ESP_BT_L2CAP_BUSY;
|
||||
osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex);
|
||||
@ -855,7 +860,6 @@ void btc_l2cap_cb_handler(btc_msg_t *msg)
|
||||
}
|
||||
BTC_TRACE_WARNING("%s slot rx data will be discard in %d milliseconds!",
|
||||
__func__, VFS_CLOSE_TIMEOUT);
|
||||
slot->alarm_arg = (void *)p_arg;
|
||||
slot->connected = false;
|
||||
need_call = false;
|
||||
}
|
||||
|
@ -254,15 +254,17 @@ static void close_timeout_handler(void *arg)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
bt_status_t status;
|
||||
spp_slot_t *slot = (spp_slot_t *)arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_SPP;
|
||||
msg.act = BTA_JV_RFCOMM_CLOSE_EVT;
|
||||
|
||||
status = btc_transfer_context(&msg, arg, sizeof(tBTA_JV), NULL, NULL);
|
||||
status = btc_transfer_context(&msg, slot->alarm_arg, sizeof(tBTA_JV), NULL, NULL);
|
||||
|
||||
if (arg) {
|
||||
osi_free(arg);
|
||||
if (slot->alarm_arg) {
|
||||
osi_free(slot->alarm_arg);
|
||||
slot->alarm_arg = NULL;
|
||||
}
|
||||
|
||||
if (status != BT_STATUS_SUCCESS) {
|
||||
@ -1211,9 +1213,11 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
break;
|
||||
}
|
||||
memcpy(p_arg, p_data, sizeof(tBTA_JV));
|
||||
slot->alarm_arg = (void *)p_arg;
|
||||
if ((slot->close_alarm =
|
||||
osi_alarm_new("slot", close_timeout_handler, (void *)p_arg, VFS_CLOSE_TIMEOUT)) == NULL) {
|
||||
osi_alarm_new("slot", close_timeout_handler, (void *)slot, VFS_CLOSE_TIMEOUT)) == NULL) {
|
||||
free(p_arg);
|
||||
slot->alarm_arg = NULL;
|
||||
param.close.status = ESP_SPP_NO_RESOURCE;
|
||||
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
||||
BTC_TRACE_ERROR("%s unable to malloc slot close_alarm!", __func__);
|
||||
@ -1221,6 +1225,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
}
|
||||
if (osi_alarm_set(slot->close_alarm, VFS_CLOSE_TIMEOUT) != OSI_ALARM_ERR_PASS) {
|
||||
free(p_arg);
|
||||
slot->alarm_arg = NULL;
|
||||
osi_alarm_free(slot->close_alarm);
|
||||
param.close.status = ESP_SPP_BUSY;
|
||||
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
||||
@ -1229,7 +1234,6 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
}
|
||||
BTC_TRACE_WARNING("%s slot rx data will be discard in %d milliseconds!",
|
||||
__func__, VFS_CLOSE_TIMEOUT);
|
||||
slot->alarm_arg = (void *)p_arg;
|
||||
slot->connected = false;
|
||||
need_call = false;
|
||||
}
|
||||
|
@ -136,6 +136,12 @@
|
||||
#define UC_BT_BLE_FEAT_PERIODIC_ADV_ENH FALSE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH
|
||||
#define UC_BT_BLE_FEAT_CREATE_SYNC_ENH CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH
|
||||
#else
|
||||
#define UC_BT_BLE_FEAT_CREATE_SYNC_ENH FALSE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL
|
||||
#define UC_BT_BLE_HIGH_DUTY_ADV_INTERVAL CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL
|
||||
#else
|
||||
|
@ -213,6 +213,12 @@
|
||||
#define BLE_FEAT_PERIODIC_ADV_ENH FALSE
|
||||
#endif
|
||||
|
||||
#if (UC_BT_BLE_FEAT_CREATE_SYNC_ENH == TRUE)
|
||||
#define BLE_FEAT_CREATE_SYNC_ENH TRUE
|
||||
#else
|
||||
#define BLE_FEAT_CREATE_SYNC_ENH FALSE
|
||||
#endif
|
||||
|
||||
#if (UC_BT_BLE_HIGH_DUTY_ADV_INTERVAL == TRUE)
|
||||
#define BLE_HIGH_DUTY_ADV_INTERVAL TRUE
|
||||
#else
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <string.h>
|
||||
#include "l2c_int.h"
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
#define SET_BIT(t, n) (t |= 1UL << (n))
|
||||
tBTM_BLE_EXTENDED_CB extend_adv_cb;
|
||||
|
||||
tBTM_BLE_5_HCI_CBACK ble_5_hci_cb;
|
||||
@ -788,14 +789,32 @@ tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params)
|
||||
}
|
||||
|
||||
if ((params->sync_timeout < 0x0a || params->sync_timeout > 0x4000)
|
||||
|| (params->filter_policy > 0x01) || (params->addr_type > 0x01) ||
|
||||
|| (params->filter_policy > 0x01)
|
||||
#if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH)
|
||||
|| (params->reports_disabled > 0x01)
|
||||
|| (params->filter_duplicates > 0x01)
|
||||
#endif
|
||||
|| (params->addr_type > 0x01) ||
|
||||
(params->sid > 0xf) || (params->skip > 0x01F3)) {
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
BTM_TRACE_ERROR("%s, The sync parameters is invalid.", __func__);
|
||||
goto end;
|
||||
}
|
||||
uint8_t option = 0x00;
|
||||
if (params->filter_policy) {
|
||||
SET_BIT(option, 0);
|
||||
}
|
||||
|
||||
if (!btsnd_hcic_ble_periodic_adv_create_sync(params->filter_policy, params->sid, params->addr_type,
|
||||
#if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH)
|
||||
if (params->reports_disabled) {
|
||||
SET_BIT(option, 1);
|
||||
}
|
||||
if (params->filter_duplicates) {
|
||||
SET_BIT(option, 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!btsnd_hcic_ble_periodic_adv_create_sync(option, params->sid, params->addr_type,
|
||||
params->addr, params->sync_timeout, 0)) {
|
||||
BTM_TRACE_ERROR("LE PA CreateSync cmd failed");
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
|
@ -298,7 +298,7 @@ BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_
|
||||
addr_type = p_dev_rec->ble.static_addr_type;
|
||||
}
|
||||
|
||||
// white list must be public address or static random address
|
||||
// The device to be added to white list must be public address or random address
|
||||
if(addr_type == BLE_ADDR_RANDOM) {
|
||||
/*
|
||||
A static address is a 48-bit randomly generated address and shall meet the following requirements:
|
||||
@ -307,8 +307,7 @@ BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_
|
||||
• All bits of the random part of the address shall not be equal to 0
|
||||
*/
|
||||
invalid_rand_addr_b[0] = invalid_rand_addr_b[0] | BT_STATIC_RAND_ADDR_MASK;
|
||||
if((bd_addr[0] & BT_STATIC_RAND_ADDR_MASK) == BT_STATIC_RAND_ADDR_MASK
|
||||
&& memcmp(invalid_rand_addr_a, bd_addr, BD_ADDR_LEN) != 0
|
||||
if(memcmp(invalid_rand_addr_a, bd_addr, BD_ADDR_LEN) != 0
|
||||
&& memcmp(invalid_rand_addr_b, bd_addr, BD_ADDR_LEN) != 0){
|
||||
// do nothing
|
||||
} else {
|
||||
|
@ -1627,14 +1627,14 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn)
|
||||
|
||||
}
|
||||
|
||||
BOOLEAN btsnd_hcic_ble_periodic_adv_create_sync(UINT8 filter_policy, UINT8 adv_sid,
|
||||
BOOLEAN btsnd_hcic_ble_periodic_adv_create_sync(UINT8 option, UINT8 adv_sid,
|
||||
UINT8 adv_addr_type, BD_ADDR adv_addr,
|
||||
UINT16 sync_timeout, UINT8 unused)
|
||||
{
|
||||
BT_HDR *p;
|
||||
UINT8 *pp;
|
||||
HCI_TRACE_EVENT("%s, filter_policy = %d, adv_sid = %d, adv_addr_type = %d, sync_timeout = %d, unused = %d",
|
||||
__func__, filter_policy, adv_sid, adv_addr_type, sync_timeout, unused);
|
||||
HCI_TRACE_EVENT("%s, option = %d, adv_sid = %d, adv_addr_type = %d, sync_timeout = %d, unused = %d",
|
||||
__func__, option, adv_sid, adv_addr_type, sync_timeout, unused);
|
||||
|
||||
HCI_TRACE_EVENT("addr %02x %02x %02x %02x %02x %02x", adv_addr[0], adv_addr[1], adv_addr[2], adv_addr[3], adv_addr[4], adv_addr[5]);
|
||||
uint16_t skip = 0;
|
||||
@ -1642,7 +1642,7 @@ BOOLEAN btsnd_hcic_ble_periodic_adv_create_sync(UINT8 filter_policy, UINT8 adv_s
|
||||
|
||||
UINT16_TO_STREAM(pp, HCI_BLE_PERIOD_ADV_CREATE_SYNC);
|
||||
UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_PERIODIC_ADV_CREATE_SYNC + 2);
|
||||
UINT8_TO_STREAM(pp, filter_policy);
|
||||
UINT8_TO_STREAM(pp, option);
|
||||
UINT8_TO_STREAM(pp, adv_sid);
|
||||
UINT8_TO_STREAM(pp, adv_addr_type);
|
||||
BDADDR_TO_STREAM(pp, adv_addr);
|
||||
|
@ -809,6 +809,10 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
UINT8 filter_policy;
|
||||
#if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH)
|
||||
UINT8 reports_disabled;
|
||||
UINT8 filter_duplicates;
|
||||
#endif
|
||||
UINT8 sid;
|
||||
tBLE_ADDR_TYPE addr_type;
|
||||
BD_ADDR addr;
|
||||
|
@ -125,7 +125,7 @@ BOOLEAN SMP_Register (tSMP_CALLBACK *p_cback)
|
||||
SMP_TRACE_EVENT ("SMP_Register state=%d", smp_cb.state);
|
||||
|
||||
if (smp_cb.p_callback != NULL) {
|
||||
SMP_TRACE_ERROR ("SMP_Register: duplicate registration, overwrite it");
|
||||
SMP_TRACE_WARNING ("SMP_Register: duplicate registration, overwrite it");
|
||||
}
|
||||
smp_cb.p_callback = p_cback;
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit c256dbdab5e9b353363715bb9b39655b0dc01711
|
||||
Subproject commit cafd9eed805e12d134d45c9be91c6d5e46fc3ceb
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "nimble/nimble_npl.h"
|
||||
#include "../../../../controller/esp32c2/esp_bt_cfg.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
|
||||
#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
|
||||
#include "driver/uart.h"
|
||||
@ -165,7 +166,7 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po
|
||||
*/
|
||||
uint8_t esp_ble_get_chip_rev_version(void);
|
||||
|
||||
#define CONFIG_VERSION 0x20230629
|
||||
#define CONFIG_VERSION 0x20231124
|
||||
#define CONFIG_MAGIC 0x5A5AA5A5
|
||||
|
||||
/**
|
||||
@ -222,7 +223,7 @@ typedef struct {
|
||||
uint8_t cca_drop_mode; /*!< CCA drop mode */
|
||||
int8_t cca_low_tx_pwr; /*!< Low TX power setting for CCA */
|
||||
uint8_t main_xtal_freq; /*!< Main crystal frequency */
|
||||
uint8_t version_num; /*!< Version number */
|
||||
uint32_t version_num; /*!< Version number */
|
||||
uint8_t ignore_wl_for_direct_adv; /*!< Ignore the white list for directed advertising */
|
||||
uint32_t config_magic; /*!< Configuration magic value */
|
||||
} esp_bt_controller_config_t;
|
||||
@ -274,7 +275,7 @@ typedef struct {
|
||||
.dis_scan_backoff = NIMBLE_DISABLE_SCAN_BACKOFF, \
|
||||
.ble_scan_classify_filter_enable = 0, \
|
||||
.main_xtal_freq = CONFIG_XTAL_FREQ, \
|
||||
.version_num = esp_ble_get_chip_rev_version(), \
|
||||
.version_num = efuse_hal_chip_revision(), \
|
||||
.ignore_wl_for_direct_adv = 0, \
|
||||
.config_magic = CONFIG_MAGIC, \
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type
|
||||
*/
|
||||
esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle);
|
||||
|
||||
#define CONFIG_VERSION 0x20230113
|
||||
#define CONFIG_VERSION 0x20231124
|
||||
#define CONFIG_MAGIC 0x5A5AA5A5
|
||||
|
||||
/**
|
||||
@ -212,7 +212,7 @@ typedef struct {
|
||||
uint8_t cca_drop_mode; /*!< CCA drop mode */
|
||||
int8_t cca_low_tx_pwr; /*!< CCA low transmit power */
|
||||
uint8_t main_xtal_freq; /*!< Main crystal frequency */
|
||||
uint8_t version_num; /*!< Controller configuration version number */
|
||||
uint32_t version_num; /*!< Controller configuration version number */
|
||||
uint8_t cpu_freq_mhz; /*!< CPU frequency in megahertz (MHz) */
|
||||
uint8_t ignore_wl_for_direct_adv; /*!< Ignore the whitelist for direct advertising */
|
||||
uint8_t enable_pcl; /*!< Enable power control */
|
||||
|
@ -160,7 +160,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type
|
||||
*/
|
||||
esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle);
|
||||
|
||||
#define CONFIG_VERSION 0x20230113
|
||||
#define CONFIG_VERSION 0x20231124
|
||||
#define CONFIG_MAGIC 0x5A5AA5A5
|
||||
|
||||
/**
|
||||
|
@ -1149,8 +1149,10 @@ struct ble_hci_vs_duplicate_exception_list_cp {
|
||||
uint8_t device_info[6];
|
||||
} __attribute__((packed));
|
||||
|
||||
#if SOC_BLE_POWER_CONTROL_SUPPORTED && MYNEWT_VAL(BLE_HCI_VS)
|
||||
#define BLE_HCI_OCF_VS_PCL_SET_RSSI (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0111))
|
||||
#define BLE_HCI_OCF_VS_LEGACY_ADV_CLEAR (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x010C))
|
||||
|
||||
#if SOC_BLE_POWER_CONTROL_SUPPORTED
|
||||
#define BLE_HCI_OCF_VS_PCL_SET_RSSI (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0111))
|
||||
#endif
|
||||
|
||||
/* Command Specific Definitions */
|
||||
|
@ -8,21 +8,17 @@ endif()
|
||||
set(srcs)
|
||||
|
||||
# Always included headers
|
||||
set(includes "include"
|
||||
"deprecated"
|
||||
set(includes "deprecated"
|
||||
"i2c/include"
|
||||
"ledc/include"
|
||||
"parlio/include"
|
||||
"rmt/include"
|
||||
"sigma_delta/include"
|
||||
"temperature_sensor/include"
|
||||
"touch_sensor/include"
|
||||
"twai/include"
|
||||
"uart/include"
|
||||
"usb_serial_jtag/include")
|
||||
|
||||
# Always included linker fragments
|
||||
set(ldfragments "linker.lf")
|
||||
set(ldfragments "")
|
||||
|
||||
# ADC related source files (dprecated)
|
||||
if(CONFIG_SOC_ADC_SUPPORTED)
|
||||
@ -84,26 +80,19 @@ if(CONFIG_SOC_PCNT_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/pcnt_legacy.c")
|
||||
endif()
|
||||
|
||||
# RMT related source files
|
||||
# RMT legacy driver
|
||||
if(CONFIG_SOC_RMT_SUPPORTED)
|
||||
list(APPEND srcs "rmt/rmt_common.c"
|
||||
"rmt/rmt_encoder.c"
|
||||
"rmt/rmt_rx.c"
|
||||
"rmt/rmt_tx.c"
|
||||
"deprecated/rmt_legacy.c")
|
||||
list(APPEND ldfragments "rmt/linker.lf")
|
||||
list(APPEND srcs "deprecated/rmt_legacy.c")
|
||||
endif()
|
||||
|
||||
# Sigma-Delta Modulation related source files
|
||||
# Sigma-Delta Modulation legacy driver
|
||||
if(CONFIG_SOC_SDM_SUPPORTED)
|
||||
list(APPEND srcs "sigma_delta/sdm.c"
|
||||
"deprecated/sigma_delta_legacy.c")
|
||||
list(APPEND srcs "deprecated/sigma_delta_legacy.c")
|
||||
endif()
|
||||
|
||||
# Temperature Sensor related source files
|
||||
if(CONFIG_SOC_TEMP_SENSOR_SUPPORTED)
|
||||
list(APPEND srcs "temperature_sensor/temperature_sensor.c"
|
||||
"deprecated/rtc_temperature_legacy.c")
|
||||
list(APPEND srcs "deprecated/rtc_temperature_legacy.c")
|
||||
endif()
|
||||
|
||||
# Touch Sensor related source files
|
||||
@ -153,7 +142,7 @@ else()
|
||||
# have a public dependency on other "esp_driver_foo" components
|
||||
esp_driver_gpio esp_driver_pcnt esp_driver_gptimer esp_driver_spi esp_driver_mcpwm
|
||||
esp_driver_ana_cmpr esp_driver_i2s esp_driver_sdmmc esp_driver_sdspi esp_driver_sdio
|
||||
esp_driver_dac
|
||||
esp_driver_dac esp_driver_rmt esp_driver_tsens esp_driver_sdm
|
||||
LDFRAGMENTS ${ldfragments}
|
||||
)
|
||||
endif()
|
||||
|
@ -64,64 +64,8 @@ menu "Driver Configurations"
|
||||
|
||||
orsource "./twai/Kconfig.twai"
|
||||
|
||||
menu "Temperature sensor Configuration"
|
||||
depends on SOC_TEMP_SENSOR_SUPPORTED
|
||||
|
||||
config TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
Wether to suppress the deprecation warnings when using legacy temperature sensor driver
|
||||
(driver/temp_sensor.h). If you want to continue using the legacy driver,
|
||||
and don't want to see related deprecation warnings, you can enable this option.
|
||||
|
||||
config TEMP_SENSOR_ENABLE_DEBUG_LOG
|
||||
bool "Enable debug log"
|
||||
default n
|
||||
help
|
||||
Wether to enable the debug log message for temperature sensor driver.
|
||||
Note that, this option only controls the temperature sensor driver log, won't affect other drivers.
|
||||
|
||||
config TEMP_SENSOR_ISR_IRAM_SAFE
|
||||
depends on SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
|
||||
bool "Temperature sensor ISR IRAM-Safe"
|
||||
default n
|
||||
help
|
||||
Ensure the Temperature Sensor interrupt is IRAM-Safe by allowing the interrupt handler to be
|
||||
executable when the cache is disabled (e.g. SPI Flash write).
|
||||
|
||||
endmenu # TEMP_SENSOR Configuration
|
||||
|
||||
orsource "./uart/Kconfig.uart"
|
||||
|
||||
menu "Sigma Delta Modulator Configuration"
|
||||
depends on SOC_SDM_SUPPORTED
|
||||
config SDM_CTRL_FUNC_IN_IRAM
|
||||
bool "Place SDM control functions into IRAM"
|
||||
default n
|
||||
help
|
||||
Place SDM control functions (like set_duty) into IRAM,
|
||||
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
|
||||
Enabling this option can improve driver performance as well.
|
||||
|
||||
config SDM_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
Wether to suppress the deprecation warnings when using legacy sigma delta driver.
|
||||
If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
|
||||
you can enable this option.
|
||||
|
||||
config SDM_ENABLE_DEBUG_LOG
|
||||
bool "Enable debug log"
|
||||
default n
|
||||
help
|
||||
Wether to enable the debug log message for SDM driver.
|
||||
Note that, this option only controls the SDM driver log, won't affect other drivers.
|
||||
endmenu # Sigma Delta Modulator Configuration
|
||||
|
||||
orsource "./rmt/Kconfig.rmt"
|
||||
|
||||
menu "USB Serial/JTAG Configuration"
|
||||
depends on SOC_USB_SERIAL_JTAG_SUPPORTED
|
||||
config USJ_NO_AUTO_LS_ON_CONNECTION
|
||||
|
@ -51,6 +51,8 @@ components/driver/test_apps/legacy_pcnt_driver:
|
||||
components/driver/test_apps/legacy_rmt_driver:
|
||||
disable:
|
||||
- if: SOC_RMT_SUPPORTED != 1
|
||||
depends_filepatterns:
|
||||
- components/driver/deprecated/**/*rmt*
|
||||
|
||||
components/driver/test_apps/legacy_rtc_temp_driver:
|
||||
disable:
|
||||
@ -60,7 +62,7 @@ components/driver/test_apps/legacy_sigma_delta_driver:
|
||||
disable:
|
||||
- if: SOC_SDM_SUPPORTED != 1
|
||||
depends_filepatterns:
|
||||
- components/driver/deprecated/**/*
|
||||
- components/driver/deprecated/**/*sigma*
|
||||
depends_components:
|
||||
- esp_driver_gpio
|
||||
|
||||
@ -78,10 +80,6 @@ components/driver/test_apps/parlio:
|
||||
temporary: true
|
||||
reason: lack of runner
|
||||
|
||||
components/driver/test_apps/rmt:
|
||||
disable:
|
||||
- if: SOC_RMT_SUPPORTED != 1
|
||||
|
||||
components/driver/test_apps/rs485:
|
||||
disable:
|
||||
- if: SOC_UART_SUPPORTED != 1
|
||||
@ -90,18 +88,6 @@ components/driver/test_apps/rs485:
|
||||
temporary: true
|
||||
reason: lack of runners
|
||||
|
||||
components/driver/test_apps/sigma_delta:
|
||||
disable:
|
||||
- if: SOC_SDM_SUPPORTED != 1
|
||||
depends_filepatterns:
|
||||
- components/driver/sigma_delta/**/*
|
||||
depends_components:
|
||||
- esp_driver_gpio
|
||||
|
||||
components/driver/test_apps/temperature_sensor:
|
||||
disable:
|
||||
- if: SOC_TEMP_SENSOR_SUPPORTED != 1
|
||||
|
||||
components/driver/test_apps/touch_sensor_v1:
|
||||
disable:
|
||||
- if: SOC_TOUCH_SENSOR_VERSION != 1
|
||||
|
@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "sys/lock.h"
|
||||
#include "soc/soc_pins.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "sys/lock.h"
|
||||
#include "soc/soc_pins.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
@ -120,9 +120,6 @@ typedef struct {
|
||||
int rx_buffered_len; /*!< UART cached data length */
|
||||
int rx_buf_size; /*!< RX ring buffer size */
|
||||
bool rx_buffer_full_flg; /*!< RX ring buffer full flag. */
|
||||
uint32_t rx_cur_remain; /*!< Data number that waiting to be read out in ring buffer item*/
|
||||
uint8_t *rx_ptr; /*!< pointer to the current data in ring buffer*/
|
||||
uint8_t *rx_head_ptr; /*!< pointer to the head of RX item*/
|
||||
uint8_t *rx_data_buf; /*!< Data buffer to stash FIFO data*/
|
||||
uint8_t rx_stash_len; /*!< stashed data length.(When using flow control, after reading out FIFO data, if we fail to push to buffer, we can just stash them.) */
|
||||
uint32_t rx_int_usr_mask; /*!< RX interrupt status. Valid at any time, regardless of RX buffer status. */
|
||||
@ -1400,53 +1397,35 @@ int uart_read_bytes(uart_port_t uart_num, void *buf, uint32_t length, TickType_t
|
||||
ESP_RETURN_ON_FALSE((buf), (-1), UART_TAG, "uart data null");
|
||||
ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), (-1), UART_TAG, "uart driver error");
|
||||
uint8_t *data = NULL;
|
||||
size_t size;
|
||||
size_t size = 0;
|
||||
size_t copy_len = 0;
|
||||
int len_tmp;
|
||||
if (xSemaphoreTake(p_uart_obj[uart_num]->rx_mux, (TickType_t)ticks_to_wait) != pdTRUE) {
|
||||
return -1;
|
||||
}
|
||||
while (length) {
|
||||
if (p_uart_obj[uart_num]->rx_cur_remain == 0) {
|
||||
data = (uint8_t *) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (TickType_t) ticks_to_wait);
|
||||
if (data) {
|
||||
p_uart_obj[uart_num]->rx_head_ptr = data;
|
||||
p_uart_obj[uart_num]->rx_ptr = data;
|
||||
p_uart_obj[uart_num]->rx_cur_remain = size;
|
||||
data = (uint8_t *) xRingbufferReceiveUpTo(p_uart_obj[uart_num]->rx_ring_buf, &size, (TickType_t) ticks_to_wait, length);
|
||||
if (!data) {
|
||||
// When using dual cores, `rx_buffer_full_flg` may read and write on different cores at same time,
|
||||
// which may lose synchronization. So we also need to call `uart_check_buf_full` once when ringbuffer is empty
|
||||
// to solve the possible asynchronous issues.
|
||||
if (uart_check_buf_full(uart_num)) {
|
||||
// This condition will never be true if `uart_read_bytes`
|
||||
// and `uart_rx_intr_handler_default` are scheduled on the same core.
|
||||
continue;
|
||||
} else {
|
||||
//When using dual cores, `rx_buffer_full_flg` may read and write on different cores at same time,
|
||||
//which may lose synchronization. So we also need to call `uart_check_buf_full` once when ringbuffer is empty
|
||||
//to solve the possible asynchronous issues.
|
||||
if (uart_check_buf_full(uart_num)) {
|
||||
//This condition will never be true if `uart_read_bytes`
|
||||
//and `uart_rx_intr_handler_default` are scheduled on the same core.
|
||||
continue;
|
||||
} else {
|
||||
xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
|
||||
return copy_len;
|
||||
}
|
||||
// Timeout while not fetched all requested length
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p_uart_obj[uart_num]->rx_cur_remain > length) {
|
||||
len_tmp = length;
|
||||
} else {
|
||||
len_tmp = p_uart_obj[uart_num]->rx_cur_remain;
|
||||
}
|
||||
memcpy((uint8_t *)buf + copy_len, p_uart_obj[uart_num]->rx_ptr, len_tmp);
|
||||
memcpy((uint8_t *)buf + copy_len, data, size);
|
||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
p_uart_obj[uart_num]->rx_buffered_len -= len_tmp;
|
||||
uart_pattern_queue_update(uart_num, len_tmp);
|
||||
p_uart_obj[uart_num]->rx_ptr += len_tmp;
|
||||
p_uart_obj[uart_num]->rx_buffered_len -= size;
|
||||
uart_pattern_queue_update(uart_num, size);
|
||||
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
p_uart_obj[uart_num]->rx_cur_remain -= len_tmp;
|
||||
copy_len += len_tmp;
|
||||
length -= len_tmp;
|
||||
if (p_uart_obj[uart_num]->rx_cur_remain == 0) {
|
||||
vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr);
|
||||
p_uart_obj[uart_num]->rx_head_ptr = NULL;
|
||||
p_uart_obj[uart_num]->rx_ptr = NULL;
|
||||
uart_check_buf_full(uart_num);
|
||||
}
|
||||
copy_len += size;
|
||||
length -= size;
|
||||
vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, data);
|
||||
uart_check_buf_full(uart_num);
|
||||
}
|
||||
|
||||
xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
|
||||
@ -1488,25 +1467,15 @@ esp_err_t uart_flush_input(uart_port_t uart_num)
|
||||
uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT);
|
||||
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
while (true) {
|
||||
if (p_uart->rx_head_ptr) {
|
||||
vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr);
|
||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
p_uart_obj[uart_num]->rx_buffered_len -= p_uart->rx_cur_remain;
|
||||
uart_pattern_queue_update(uart_num, p_uart->rx_cur_remain);
|
||||
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
p_uart->rx_ptr = NULL;
|
||||
p_uart->rx_cur_remain = 0;
|
||||
p_uart->rx_head_ptr = NULL;
|
||||
}
|
||||
data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (TickType_t) 0);
|
||||
if(data == NULL) {
|
||||
data = (uint8_t *) xRingbufferReceive(p_uart->rx_ring_buf, &size, (TickType_t) 0);
|
||||
if (data == NULL) {
|
||||
bool error = false;
|
||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
if( p_uart_obj[uart_num]->rx_buffered_len != 0 ) {
|
||||
if (p_uart_obj[uart_num]->rx_buffered_len != 0) {
|
||||
p_uart_obj[uart_num]->rx_buffered_len = 0;
|
||||
error = true;
|
||||
}
|
||||
//We also need to clear the `rx_buffer_full_flg` here.
|
||||
// We also need to clear the `rx_buffer_full_flg` here.
|
||||
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
|
||||
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
if (error) {
|
||||
@ -1530,9 +1499,6 @@ esp_err_t uart_flush_input(uart_port_t uart_num)
|
||||
}
|
||||
}
|
||||
}
|
||||
p_uart->rx_ptr = NULL;
|
||||
p_uart->rx_cur_remain = 0;
|
||||
p_uart->rx_head_ptr = NULL;
|
||||
uart_hal_rxfifo_rst(&(uart_context[uart_num].hal));
|
||||
/* Only re-enable UART_INTR_RXFIFO_TOUT or UART_INTR_RXFIFO_FULL if they
|
||||
* were explicitly enabled by the user. */
|
||||
@ -1653,10 +1619,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
|
||||
p_uart_obj[uart_num]->rx_buffered_len = 0;
|
||||
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
|
||||
p_uart_obj[uart_num]->tx_waiting_fifo = false;
|
||||
p_uart_obj[uart_num]->rx_ptr = NULL;
|
||||
p_uart_obj[uart_num]->rx_cur_remain = 0;
|
||||
p_uart_obj[uart_num]->rx_int_usr_mask = UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT;
|
||||
p_uart_obj[uart_num]->rx_head_ptr = NULL;
|
||||
p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size;
|
||||
p_uart_obj[uart_num]->uart_select_notif_callback = NULL;
|
||||
xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem);
|
||||
@ -1850,7 +1813,9 @@ esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int *out_wakeup_thresh
|
||||
esp_err_t uart_wait_tx_idle_polling(uart_port_t uart_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error");
|
||||
while (!uart_hal_is_tx_idle(&(uart_context[uart_num].hal)));
|
||||
if (uart_ll_is_enabled(uart_num)) {
|
||||
while (!uart_hal_is_tx_idle(&(uart_context[uart_num].hal)));
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdatomic.h>
|
||||
#include "esp_log.h"
|
||||
#include "hal/usb_serial_jtag_ll.h"
|
||||
#include "hal/usb_phy_ll.h"
|
||||
@ -25,12 +26,19 @@
|
||||
#define USJ_RCC_ATOMIC()
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
FIFO_IDLE = 0, /*!< Indicates the fifo is in idle state */
|
||||
FIFO_BUSY = 1, /*!< Indicates the fifo is in busy state */
|
||||
} fifo_status_t;
|
||||
|
||||
// The hardware buffer max size is 64
|
||||
#define USB_SER_JTAG_ENDP_SIZE (64)
|
||||
#define USB_SER_JTAG_RX_MAX_SIZE (64)
|
||||
|
||||
typedef struct{
|
||||
intr_handle_t intr_handle; /*!< USB-SERIAL-JTAG interrupt handler */
|
||||
portMUX_TYPE spinlock; /*!< Spinlock for usb_serial_jtag */
|
||||
_Atomic fifo_status_t fifo_status; /*!< Record the status of fifo */
|
||||
|
||||
// RX parameters
|
||||
RingbufHandle_t rx_ring_buf; /*!< RX ring buffer handler */
|
||||
@ -67,7 +75,7 @@ static void usb_serial_jtag_isr_handler_default(void *arg) {
|
||||
// If the hardware fifo is available, write in it. Otherwise, do nothing.
|
||||
if (usb_serial_jtag_ll_txfifo_writable() == 1) {
|
||||
// We disable the interrupt here so that the interrupt won't be triggered if there is no data to send.
|
||||
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
|
||||
size_t queued_size;
|
||||
uint8_t *queued_buff = NULL;
|
||||
bool is_stashed_data = false;
|
||||
@ -91,10 +99,13 @@ static void usb_serial_jtag_isr_handler_default(void *arg) {
|
||||
|
||||
// On ringbuffer wrap-around the size can be 0 even though the buffer returned is not NULL
|
||||
if (queued_size > 0) {
|
||||
portENTER_CRITICAL_ISR(&p_usb_serial_jtag_obj->spinlock);
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_BUSY);
|
||||
uint32_t sent_size = usb_serial_jtag_write_and_flush(queued_buff, queued_size);
|
||||
portEXIT_CRITICAL_ISR(&p_usb_serial_jtag_obj->spinlock);
|
||||
|
||||
if (sent_size < queued_size) {
|
||||
// Not all bytes could be sent at once, stash the unwritten bytes in a tx buffer
|
||||
// Not all bytes could be sent at once; stash the unwritten bytes in a tx buffer
|
||||
// stash_size will not larger than USB_SER_JTAG_ENDP_SIZE because queued_size is got from xRingbufferReceiveUpToFromISR
|
||||
size_t stash_size = queued_size - sent_size;
|
||||
memcpy(p_usb_serial_jtag_obj->tx_data_buf, &queued_buff[sent_size], stash_size);
|
||||
@ -108,9 +119,17 @@ static void usb_serial_jtag_isr_handler_default(void *arg) {
|
||||
if (is_stashed_data == false) {
|
||||
vRingbufferReturnItemFromISR(p_usb_serial_jtag_obj->tx_ring_buf, queued_buff, &xTaskWoken);
|
||||
}
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
} else {
|
||||
// The last transmit may have sent a full EP worth of data. The host will interpret
|
||||
// this as a transaction that hasn't finished yet and keep the data in its internal
|
||||
// buffers rather than releasing it to the program listening on the CDC serial port.
|
||||
// We need to flush again in order to send a 0-byte packet that ends the transaction.
|
||||
usb_serial_jtag_ll_txfifo_flush();
|
||||
// Note that since this doesn't re-enable USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY, the
|
||||
// flush will not by itself cause this ISR to be called again.
|
||||
}
|
||||
} else {
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_IDLE);
|
||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
}
|
||||
}
|
||||
@ -139,6 +158,7 @@ esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_se
|
||||
p_usb_serial_jtag_obj->rx_buf_size = usb_serial_jtag_config->rx_buffer_size;
|
||||
p_usb_serial_jtag_obj->tx_buf_size = usb_serial_jtag_config->tx_buffer_size;
|
||||
p_usb_serial_jtag_obj->tx_stash_cnt = 0;
|
||||
p_usb_serial_jtag_obj->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
if (p_usb_serial_jtag_obj == NULL) {
|
||||
ESP_LOGE(USB_SERIAL_JTAG_TAG, "memory allocate error");
|
||||
err = ESP_ERR_NO_MEM;
|
||||
@ -163,6 +183,7 @@ esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_se
|
||||
USJ_RCC_ATOMIC() {
|
||||
usb_serial_jtag_ll_enable_bus_clock(true);
|
||||
}
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_IDLE);
|
||||
|
||||
// Configure PHY
|
||||
usb_phy_ll_int_jtag_enable(&USB_SERIAL_JTAG);
|
||||
@ -212,10 +233,22 @@ int usb_serial_jtag_write_bytes(const void* src, size_t size, TickType_t ticks_t
|
||||
ESP_RETURN_ON_FALSE(src != NULL, ESP_ERR_INVALID_ARG, USB_SERIAL_JTAG_TAG, "Invalid buffer pointer.");
|
||||
ESP_RETURN_ON_FALSE(p_usb_serial_jtag_obj != NULL, ESP_ERR_INVALID_ARG, USB_SERIAL_JTAG_TAG, "The driver hasn't been initialized");
|
||||
|
||||
size_t sent_data = 0;
|
||||
BaseType_t result = pdTRUE;
|
||||
const uint8_t *buff = (const uint8_t *)src;
|
||||
if (p_usb_serial_jtag_obj->fifo_status == FIFO_IDLE) {
|
||||
portENTER_CRITICAL(&p_usb_serial_jtag_obj->spinlock);
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_BUSY);
|
||||
sent_data = usb_serial_jtag_write_and_flush(src, size);
|
||||
portEXIT_CRITICAL(&p_usb_serial_jtag_obj->spinlock);
|
||||
}
|
||||
|
||||
// Blocking method, Sending data to ringbuffer, and handle the data in ISR.
|
||||
BaseType_t result = xRingbufferSend(p_usb_serial_jtag_obj->tx_ring_buf, (void*) (buff), size, ticks_to_wait);
|
||||
// Now trigger the ISR to read data from the ring buffer.
|
||||
if (size - sent_data > 0) {
|
||||
result = xRingbufferSend(p_usb_serial_jtag_obj->tx_ring_buf, (void*) (buff+sent_data), size-sent_data, ticks_to_wait);
|
||||
} else {
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_IDLE);
|
||||
}
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
return (result == pdFALSE) ? 0 : size;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void)
|
||||
}
|
||||
}
|
||||
|
||||
ESP_SYSTEM_INIT_FN(usb_serial_jtag_conn_status_init, BIT(0), 230)
|
||||
ESP_SYSTEM_INIT_FN(usb_serial_jtag_conn_status_init, SECONDARY, BIT(0), 230)
|
||||
{
|
||||
#if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "usb_serial_jtag", &s_usb_serial_jtag_pm_lock),
|
||||
|
@ -10,8 +10,12 @@
|
||||
#include "esp_err.h"
|
||||
#ifdef CONFIG_ESP_TLS_USING_MBEDTLS
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#elif CONFIG_ESP_TLS_USING_WOLFSSL
|
||||
#include "wolfssl/wolfcrypt/settings.h"
|
||||
#include "wolfssl/ssl.h"
|
||||
#endif
|
||||
/* For wolfSSL, errors are included through ssl.h which is included by default by esp_tls.h */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -359,6 +359,9 @@ esp_err_t adc_continuous_start(adc_continuous_handle_t handle)
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver isn't initialised");
|
||||
ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, ADC_TAG, "ADC continuous mode isn't in the init state, it's started already");
|
||||
|
||||
//reset ADC digital part to reset ADC sampling EOF counter
|
||||
periph_module_reset(PERIPH_SARADC_MODULE);
|
||||
|
||||
if (handle->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(handle->pm_lock), ADC_TAG, "acquire pm_lock failed");
|
||||
}
|
||||
|
0
components/esp_adc/esp32c5/include/.gitkeep
Normal file
0
components/esp_adc/esp32c5/include/.gitkeep
Normal file
@ -264,6 +264,57 @@ TEST_CASE("ADC continuous flush internal pool", "[adc_continuous][mannual][ignor
|
||||
TEST_ESP_OK(adc_continuous_deinit(handle));
|
||||
}
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3 //TODO: DIG-270
|
||||
|
||||
#define ADC_RESTART_TEST_SIZE 4096
|
||||
#define ADC_READ_TEST_COUNT 10
|
||||
|
||||
TEST_CASE("ADC continuous test after restarting", "[adc_continuous]")
|
||||
{
|
||||
adc_continuous_handle_t handle = NULL;
|
||||
adc_continuous_handle_cfg_t adc_config = {
|
||||
.max_store_buf_size = ADC_RESTART_TEST_SIZE,
|
||||
.conv_frame_size = ADC_RESTART_TEST_SIZE,
|
||||
};
|
||||
TEST_ESP_OK(adc_continuous_new_handle(&adc_config, &handle));
|
||||
|
||||
adc_continuous_config_t dig_cfg = {
|
||||
.sample_freq_hz = 50 * 1000,
|
||||
.conv_mode = ADC_CONV_SINGLE_UNIT_1,
|
||||
.format = ADC_DRIVER_TEST_OUTPUT_TYPE,
|
||||
};
|
||||
adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0};
|
||||
adc_pattern[0].atten = ADC_ATTEN_DB_12;
|
||||
adc_pattern[0].channel = ADC1_TEST_CHAN0;
|
||||
adc_pattern[0].unit = ADC_UNIT_1;
|
||||
adc_pattern[0].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;
|
||||
dig_cfg.adc_pattern = adc_pattern;
|
||||
dig_cfg.pattern_num = 1;
|
||||
TEST_ESP_OK(adc_continuous_config(handle, &dig_cfg));
|
||||
|
||||
uint8_t* result = malloc(ADC_RESTART_TEST_SIZE);
|
||||
TEST_ASSERT(result);
|
||||
|
||||
test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 0);
|
||||
|
||||
for (int i = 0; i < ADC_READ_TEST_COUNT; i++) {
|
||||
uint32_t ret_num = 0;
|
||||
TEST_ESP_OK(adc_continuous_start(handle));
|
||||
TEST_ESP_OK(adc_continuous_read(handle, result, ADC_RESTART_TEST_SIZE, &ret_num, ADC_MAX_DELAY));
|
||||
TEST_ASSERT_EQUAL(ADC_RESTART_TEST_SIZE, ret_num);
|
||||
for (int i = 0; i < ret_num; i += SOC_ADC_DIGI_RESULT_BYTES) {
|
||||
adc_digi_output_data_t *p = (void*)&result[i];
|
||||
uint32_t chan_num = ADC_DRIVER_TEST_GET_CHANNEL(p);
|
||||
TEST_ASSERT(chan_num < SOC_ADC_CHANNEL_NUM(ADC_UNIT_1));
|
||||
}
|
||||
TEST_ESP_OK(adc_continuous_stop(handle));
|
||||
}
|
||||
|
||||
TEST_ESP_OK(adc_continuous_deinit(handle));
|
||||
free(result);
|
||||
}
|
||||
#endif //!CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED
|
||||
TEST_CASE("ADC filter exhausted allocation", "[adc_continuous]")
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user