Merge branch 'espressif:master' into master

This commit is contained in:
Jorgen Bilander 2023-12-07 18:50:58 +01:00 committed by GitHub
commit 191914690f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
750 changed files with 130199 additions and 7250 deletions

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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
View 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

View File

@ -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 #
#################################

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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' ]

View File

@ -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");
}

View File

@ -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,
};

View File

@ -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***`
);

View File

@ -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");
};

View File

@ -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");
};

View File

@ -1,16 +0,0 @@
module.exports = {
gptStandardModelTokens: 4096,
minimumSummaryChars: 20,
maximumSummaryChars: 72,
maximumBodyLineChars: 100,
allowedTypes: [
"change",
"ci",
"docs",
"feat",
"fix",
"refactor",
"remove",
"revert",
],
};

View File

@ -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');
};

View File

@ -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');
};

View File

@ -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);
}
};

View File

@ -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");
};

View File

@ -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;
}

View File

@ -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
}
}
}
};

View File

@ -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");
};

View File

@ -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");
};

View File

@ -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");
};

File diff suppressed because it is too large Load Diff

View File

@ -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"
}
}

View File

@ -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
View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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)"

View File

@ -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();
}

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -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()

View File

@ -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"

View File

@ -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"

View File

@ -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

@ -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

View File

@ -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

View File

@ -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;

@ -0,0 +1 @@
Subproject commit 73b3b96db91d170d96e0f3e901a47f51e749e75b

View File

@ -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

View File

@ -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;
/**

View File

@ -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;

View File

@ -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");

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 {

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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, \
}

View File

@ -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 */

View File

@ -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
/**

View File

@ -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 */

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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),

View File

@ -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" {

View File

@ -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");
}

View 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