mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
freemodbus: remove component files from esp-idf (backport v4.4)
This commit is contained in:
parent
56efeb2c76
commit
ea646a9c22
4
.flake8
4
.flake8
@ -153,6 +153,7 @@ exclude =
|
|||||||
components/tinyusb,
|
components/tinyusb,
|
||||||
components/unity/unity,
|
components/unity/unity,
|
||||||
components/spiffs/spiffs,
|
components/spiffs/spiffs,
|
||||||
|
components/freemodbus,
|
||||||
examples/build_system/cmake/import_lib/main/lib/tinyxml2,
|
examples/build_system/cmake/import_lib/main/lib/tinyxml2,
|
||||||
examples/peripherals/secure_element/atecc608_ecdsa/components/esp-cryptoauthlib,
|
examples/peripherals/secure_element/atecc608_ecdsa/components/esp-cryptoauthlib,
|
||||||
# autogenerated scripts
|
# autogenerated scripts
|
||||||
@ -168,4 +169,5 @@ exclude =
|
|||||||
|
|
||||||
per-file-ignores =
|
per-file-ignores =
|
||||||
# Sphinx conf.py files use star imports to setup config variables
|
# Sphinx conf.py files use star imports to setup config variables
|
||||||
docs/conf_common.py: F405
|
docs/conf_common.py: F405,
|
||||||
|
components/freemodbus/docs/conf_common.py: F405
|
||||||
|
20
components/freemodbus/.github/workflows/issue_comment.yml
vendored
Normal file
20
components/freemodbus/.github/workflows/issue_comment.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: Sync issue comments to JIRA
|
||||||
|
|
||||||
|
# This workflow will be triggered when new issue comment is created (including PR comments)
|
||||||
|
on: issue_comment
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync_issue_comments_to_jira:
|
||||||
|
name: Sync Issue Comments to Jira
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- name: Sync issue comments to JIRA
|
||||||
|
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||||
|
JIRA_PROJECT: IDFGH
|
||||||
|
JIRA_COMPONENT: modbus
|
||||||
|
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||||
|
JIRA_USER: ${{ secrets.JIRA_USER }}
|
20
components/freemodbus/.github/workflows/new_issues.yml
vendored
Normal file
20
components/freemodbus/.github/workflows/new_issues.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: Sync issues to Jira
|
||||||
|
|
||||||
|
# This workflow will be triggered when a new issue is opened
|
||||||
|
on: issues
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync_issues_to_jira:
|
||||||
|
name: Sync issues to Jira
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- name: Sync GitHub issues to Jira project
|
||||||
|
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||||
|
JIRA_PROJECT: IDFGH
|
||||||
|
JIRA_COMPONENT: modbus
|
||||||
|
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||||
|
JIRA_USER: ${{ secrets.JIRA_USER }}
|
25
components/freemodbus/.github/workflows/new_prs.yml
vendored
Normal file
25
components/freemodbus/.github/workflows/new_prs.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
name: Sync remain PRs to Jira
|
||||||
|
|
||||||
|
# This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero comment) to Jira project
|
||||||
|
# Note that, PRs can also get synced when new PR comment is created
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 * * * *"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync_prs_to_jira:
|
||||||
|
name: Sync PRs to Jira
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- name: Sync PRs to Jira project
|
||||||
|
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||||
|
with:
|
||||||
|
cron_job: true
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||||
|
JIRA_PROJECT: IDFGH
|
||||||
|
JIRA_COMPONENT: modbus
|
||||||
|
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||||
|
JIRA_USER: ${{ secrets.JIRA_USER }}
|
49
components/freemodbus/.gitignore
vendored
Normal file
49
components/freemodbus/.gitignore
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
.config
|
||||||
|
*.o
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# gtags
|
||||||
|
GTAGS
|
||||||
|
GRTAGS
|
||||||
|
GPATH
|
||||||
|
|
||||||
|
# emacs
|
||||||
|
.dir-locals.el
|
||||||
|
|
||||||
|
# emacs temp file suffixes
|
||||||
|
*~
|
||||||
|
.#*
|
||||||
|
\#*#
|
||||||
|
|
||||||
|
# eclipse setting
|
||||||
|
.settings
|
||||||
|
|
||||||
|
# MacOS directory files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Test files
|
||||||
|
test/build
|
||||||
|
test/sdkconfig
|
||||||
|
test/sdkconfig.old
|
||||||
|
|
||||||
|
# Doc build artifacts
|
||||||
|
docs/_build/
|
||||||
|
docs/doxygen-warning-log.txt
|
||||||
|
docs/sphinx-warning-log.txt
|
||||||
|
docs/sphinx-warning-log-sanitized.txt
|
||||||
|
docs/xml/
|
||||||
|
docs/xml_in/
|
||||||
|
docs/man/
|
||||||
|
docs/doxygen_sqlite3.db
|
||||||
|
|
||||||
|
TEST_LOGS
|
||||||
|
|
||||||
|
|
||||||
|
# gcov coverage reports
|
||||||
|
*.gcda
|
||||||
|
*.gcno
|
||||||
|
coverage.info
|
||||||
|
coverage_report/
|
||||||
|
|
||||||
|
# VS Code Settings
|
||||||
|
.vscode/
|
161
components/freemodbus/.gitlab-ci.yml
Normal file
161
components/freemodbus/.gitlab-ci.yml
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
stages:
|
||||||
|
- build
|
||||||
|
- deploy
|
||||||
|
|
||||||
|
variables:
|
||||||
|
# System environment
|
||||||
|
ESP_DOCS_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env-v5.0:2-2"
|
||||||
|
ESP_DOCS_PATH: "$CI_PROJECT_DIR"
|
||||||
|
|
||||||
|
# GitLab-CI environment
|
||||||
|
GET_SOURCES_ATTEMPTS: "10"
|
||||||
|
ARTIFACT_DOWNLOAD_ATTEMPTS: "10"
|
||||||
|
GIT_SUBMODULE_STRATEGY: none
|
||||||
|
|
||||||
|
.setup_idf_tools: &setup_idf_tools |
|
||||||
|
tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1
|
||||||
|
|
||||||
|
.add_gh_key_remote: &add_gh_key_remote |
|
||||||
|
command -v ssh-agent >/dev/null || exit 1
|
||||||
|
eval $(ssh-agent -s)
|
||||||
|
printf '%s\n' "${GH_PUSH_KEY}" | tr -d '\r' | ssh-add - > /dev/null
|
||||||
|
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
||||||
|
[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config || ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
|
||||||
|
git remote remove github || true
|
||||||
|
git remote add github ${GH_PUSH_REPO}
|
||||||
|
|
||||||
|
after_script:
|
||||||
|
# Just for cleaning space, no other causes
|
||||||
|
- git clean -ffdx
|
||||||
|
|
||||||
|
|
||||||
|
# This template gets expanded multiple times, once for every IDF version.
|
||||||
|
# IDF version is specified by setting the espressif/idf image tag.
|
||||||
|
#
|
||||||
|
# EXAMPLE_TARGETS sets the list of IDF_TARGET values to build examples for.
|
||||||
|
# It should be equal to the list of targets supported by the specific IDF version.
|
||||||
|
#
|
||||||
|
# TEST_TARGETS sets the list of IDF_TARGET values to build the test_app for.
|
||||||
|
# It should contain only the targets with optimized assembly implementations.
|
||||||
|
#
|
||||||
|
.build_template:
|
||||||
|
stage: build
|
||||||
|
tags:
|
||||||
|
- build
|
||||||
|
- internet
|
||||||
|
script:
|
||||||
|
- pip install idf-component-manager --upgrade
|
||||||
|
- ./build_all.sh
|
||||||
|
variables:
|
||||||
|
EXAMPLE_TARGETS: "esp32"
|
||||||
|
TEST_TARGETS: "esp32"
|
||||||
|
|
||||||
|
build_idf_v4.1:
|
||||||
|
extends: .build_template
|
||||||
|
image: espressif/idf:release-v4.1
|
||||||
|
|
||||||
|
build_idf_v4.2:
|
||||||
|
extends: .build_template
|
||||||
|
image: espressif/idf:release-v4.2
|
||||||
|
variables:
|
||||||
|
EXAMPLE_TARGETS: "esp32 esp32s2"
|
||||||
|
|
||||||
|
build_idf_v4.3:
|
||||||
|
extends: .build_template
|
||||||
|
image: espressif/idf:release-v4.3
|
||||||
|
variables:
|
||||||
|
EXAMPLE_TARGETS: "esp32 esp32s2 esp32c3"
|
||||||
|
|
||||||
|
build_idf_v4.4:
|
||||||
|
extends: .build_template
|
||||||
|
image: espressif/idf:release-v4.4
|
||||||
|
variables:
|
||||||
|
EXAMPLE_TARGETS: "esp32 esp32s2 esp32s3 esp32c3"
|
||||||
|
TEST_TARGETS: "esp32 esp32s3"
|
||||||
|
|
||||||
|
build_idf_latest:
|
||||||
|
extends: .build_template
|
||||||
|
image: espressif/idf:latest
|
||||||
|
variables:
|
||||||
|
EXAMPLE_TARGETS: "esp32 esp32s2 esp32s3 esp32c3"
|
||||||
|
TEST_TARGETS: "esp32 esp32s3"
|
||||||
|
# GNU Make based build system is not supported starting from IDF v5.0
|
||||||
|
SKIP_GNU_MAKE_BUILD: 1
|
||||||
|
|
||||||
|
build_docs:
|
||||||
|
stage: build
|
||||||
|
image: $ESP_DOCS_ENV_IMAGE
|
||||||
|
tags:
|
||||||
|
- build_docs
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- docs/_build/*/*/*.txt
|
||||||
|
- docs/_build/*/*/html/*
|
||||||
|
expire_in: 4 days
|
||||||
|
# No cleaning when the artifacts
|
||||||
|
after_script: []
|
||||||
|
script:
|
||||||
|
- cd docs
|
||||||
|
- pip install -r requirements.txt
|
||||||
|
- build-docs -l en -t esp32
|
||||||
|
|
||||||
|
.deploy_docs_template:
|
||||||
|
stage: deploy
|
||||||
|
image: $ESP_DOCS_ENV_IMAGE
|
||||||
|
tags:
|
||||||
|
- deploy_docs
|
||||||
|
needs:
|
||||||
|
- build_docs
|
||||||
|
only:
|
||||||
|
changes:
|
||||||
|
- "docs/**/*"
|
||||||
|
script:
|
||||||
|
- source ${CI_PROJECT_DIR}/docs/utils.sh
|
||||||
|
- add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER
|
||||||
|
- export GIT_VER=$(git describe --always)
|
||||||
|
- pip install -r ${CI_PROJECT_DIR}/docs/requirements.txt
|
||||||
|
- deploy-docs
|
||||||
|
|
||||||
|
deploy_docs_preview:
|
||||||
|
extends:
|
||||||
|
- .deploy_docs_template
|
||||||
|
except:
|
||||||
|
refs:
|
||||||
|
- master
|
||||||
|
variables:
|
||||||
|
TYPE: "preview"
|
||||||
|
DOCS_BUILD_DIR: "${CI_PROJECT_DIR}/docs/_build/"
|
||||||
|
DOCS_DEPLOY_PRIVATEKEY: "$DOCS_DEPLOY_KEY"
|
||||||
|
DOCS_DEPLOY_SERVER: "$DOCS_SERVER"
|
||||||
|
DOCS_DEPLOY_SERVER_USER: "$DOCS_SERVER_USER"
|
||||||
|
DOCS_DEPLOY_PATH: "$DOCS_PATH"
|
||||||
|
DOCS_DEPLOY_URL_BASE: "https://$DOCS_PREVIEW_SERVER_URL/docs/esp-modbus"
|
||||||
|
|
||||||
|
deploy_docs_production:
|
||||||
|
extends:
|
||||||
|
- .deploy_docs_template
|
||||||
|
only:
|
||||||
|
refs:
|
||||||
|
- master
|
||||||
|
variables:
|
||||||
|
TYPE: "production"
|
||||||
|
DOCS_BUILD_DIR: "${CI_PROJECT_DIR}/docs/_build/"
|
||||||
|
DOCS_DEPLOY_PRIVATEKEY: "$DOCS_PROD_DEPLOY_KEY"
|
||||||
|
DOCS_DEPLOY_SERVER: "$DOCS_PROD_SERVER"
|
||||||
|
DOCS_DEPLOY_SERVER_USER: "$DOCS_PROD_SERVER_USER"
|
||||||
|
DOCS_DEPLOY_PATH: "$DOCS_PROD_PATH"
|
||||||
|
DOCS_DEPLOY_URL_BASE: "https://docs.espressif.com/projects/esp-modbus"
|
||||||
|
|
||||||
|
upload_to_component_manager:
|
||||||
|
stage: deploy
|
||||||
|
image: python:3.10-alpine
|
||||||
|
tags:
|
||||||
|
- deploy
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH == "master"'
|
||||||
|
- if: '$FORCE_PUSH_COMPONENT == "1"'
|
||||||
|
script:
|
||||||
|
- pip install idf-component-manager
|
||||||
|
- export IDF_COMPONENT_API_TOKEN=${ESP_MODBUS_API_KEY}
|
||||||
|
- python -m idf_component_manager upload-component --allow-existing --name=esp-modbus --namespace=espressif
|
12
components/freemodbus/.gitrepo
Normal file
12
components/freemodbus/.gitrepo
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
; DO NOT EDIT (unless you know what you are doing)
|
||||||
|
;
|
||||||
|
; This subdirectory is a git "subrepo", and this file is maintained by the
|
||||||
|
; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
|
||||||
|
;
|
||||||
|
[subrepo]
|
||||||
|
remote = https://github.com/espressif/esp-modbus.git
|
||||||
|
branch = master
|
||||||
|
commit = 0e1fe58fbf775edc5a7b6dcd46cc07d477120cf6
|
||||||
|
parent = 24e597928cca93c926ffcae0ecaf0c99463a397f
|
||||||
|
method = merge
|
||||||
|
cmdver = 0.4.5
|
@ -1,3 +1,5 @@
|
|||||||
|
# The following five lines of boilerplate have to be in your project's
|
||||||
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
set(srcs
|
set(srcs
|
||||||
"common/esp_modbus_master.c"
|
"common/esp_modbus_master.c"
|
||||||
"common/esp_modbus_slave.c"
|
"common/esp_modbus_slave.c"
|
||||||
@ -44,14 +46,29 @@ set(srcs
|
|||||||
set(include_dirs common/include)
|
set(include_dirs common/include)
|
||||||
|
|
||||||
set(priv_include_dirs common port modbus modbus/ascii modbus/functions
|
set(priv_include_dirs common port modbus modbus/ascii modbus/functions
|
||||||
modbus/rtu modbus/tcp modbus/include)
|
modbus/rtu modbus/tcp modbus/include)
|
||||||
|
|
||||||
list(APPEND priv_include_dirs serial_slave/port serial_slave/modbus_controller
|
list(APPEND priv_include_dirs serial_slave/port serial_slave/modbus_controller
|
||||||
serial_master/port serial_master/modbus_controller
|
serial_master/port serial_master/modbus_controller
|
||||||
tcp_slave/port tcp_slave/modbus_controller
|
tcp_slave/port tcp_slave/modbus_controller
|
||||||
tcp_master/port tcp_master/modbus_controller)
|
tcp_master/port tcp_master/modbus_controller)
|
||||||
|
|
||||||
|
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/freemodbus/" ${srcs})
|
||||||
|
add_prefix(include_dirs "${CMAKE_CURRENT_LIST_DIR}/freemodbus/" ${include_dirs})
|
||||||
|
add_prefix(priv_include_dirs "${CMAKE_CURRENT_LIST_DIR}/freemodbus/" ${priv_include_dirs})
|
||||||
|
|
||||||
|
message(STATUS "DEBUG: Use esp-modbus component folder: ${CMAKE_CURRENT_LIST_DIR}.")
|
||||||
|
|
||||||
|
set(requires driver lwip)
|
||||||
|
|
||||||
|
# esp_timer component was introduced in v4.2
|
||||||
|
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.1")
|
||||||
|
list(APPEND requires esp_timer)
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
INCLUDE_DIRS "${include_dirs}"
|
INCLUDE_DIRS "${include_dirs}"
|
||||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||||
REQUIRES driver)
|
REQUIRES ${requires}
|
||||||
|
PRIV_REQUIRES esp_netif)
|
||||||
|
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||||
|
@ -193,44 +193,14 @@ menu "Modbus configuration"
|
|||||||
If this option is set the Modbus stack uses timer for T3.5 time measurement.
|
If this option is set the Modbus stack uses timer for T3.5 time measurement.
|
||||||
Else the internal UART TOUT timeout is used for 3.5T symbol time measurement.
|
Else the internal UART TOUT timeout is used for 3.5T symbol time measurement.
|
||||||
|
|
||||||
config FMB_TIMER_GROUP
|
config FMB_TIMER_USE_ISR_DISPATCH_METHOD
|
||||||
int "Slave Timer group number"
|
bool "Modbus timer uses ISR dispatch method"
|
||||||
range 0 1
|
|
||||||
default 0
|
|
||||||
help
|
|
||||||
Modbus slave Timer group number that is used for timeout measurement.
|
|
||||||
|
|
||||||
config FMB_TIMER_INDEX
|
|
||||||
int "Slave Timer index in the group"
|
|
||||||
range 0 1
|
|
||||||
default 0
|
|
||||||
help
|
|
||||||
Modbus slave Timer Index in the group that is used for timeout measurement.
|
|
||||||
|
|
||||||
config FMB_MASTER_TIMER_GROUP
|
|
||||||
int "Master Timer group number"
|
|
||||||
range 0 1
|
|
||||||
default FMB_TIMER_GROUP
|
|
||||||
help
|
|
||||||
Modbus master Timer group number that is used for timeout measurement.
|
|
||||||
|
|
||||||
config FMB_MASTER_TIMER_INDEX
|
|
||||||
int "Master Timer index"
|
|
||||||
range 0 1
|
|
||||||
default FMB_TIMER_INDEX
|
|
||||||
help
|
|
||||||
Modbus master Timer Index in the group that is used for timeout measurement.
|
|
||||||
Note: Modbus master and slave should have different timer index to be able to work simultaneously.
|
|
||||||
|
|
||||||
config FMB_TIMER_ISR_IN_IRAM
|
|
||||||
bool "Place timer interrupt handler into IRAM"
|
|
||||||
default n
|
default n
|
||||||
|
select ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
||||||
select UART_ISR_IN_IRAM
|
select UART_ISR_IN_IRAM
|
||||||
help
|
help
|
||||||
This option places Modbus timer IRQ handler into IRAM.
|
If this option is set the Modbus stack uses ISR dispatch method
|
||||||
This allows to avoid delays related to processing of non-IRAM-safe interrupts
|
to send timeout events from the callback function called from ISR.
|
||||||
during a flash write operation (NVS updating a value, or some other
|
|
||||||
flash API which has to perform an read/write operation and disable CPU cache).
|
|
||||||
This option has dependency with the UART_ISR_IN_IRAM option which places UART interrupt
|
This option has dependency with the UART_ISR_IN_IRAM option which places UART interrupt
|
||||||
handler into IRAM to prevent delays related to processing of UART events.
|
handler into IRAM to prevent delays related to processing of UART events.
|
||||||
|
|
||||||
|
202
components/freemodbus/LICENSE
Normal file
202
components/freemodbus/LICENSE
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
63
components/freemodbus/README.md
Normal file
63
components/freemodbus/README.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# ESP-Modbus Library
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
An Espressif ESP-Modbus Library (esp-modbus) is a library to support Modbus communication in the networks based on RS485, WiFi, Ethernet interfaces. The Modbus is a data communications protocol originally published by Modicon (now Schneider Electric) in 1979 for use with its programmable logic controllers (PLCs).
|
||||||
|
|
||||||
|
* [ESP-Modbus component on GitHub](https://www.github.com/espressif/esp-modbus)
|
||||||
|
|
||||||
|
This library is to be used with Espressif’s IoT Development Framework, [ESP_IDF](https://github.com/espressif/esp-idf). The packages from this repository are uploaded to Espressif’s component repository.
|
||||||
|
|
||||||
|
* [esp-modbus component in component repository](https://components.espressif.com/component/espressif/esp-modbus)
|
||||||
|
|
||||||
|
You can add the component to your project via `idf.py add-dependency`. More information about idf-component-manager can be found in [Espressif API guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html) or [PyPi registry](https://pypi.org/project/idf-component-manager).
|
||||||
|
|
||||||
|
The ESP-Modbus library can be used with ESP-IDF v4.1 and later. ESP-IDF v4.x releases include an earlier version of ESP-Modbus library inside freemodbus component. To use ESP-Modbus with these releases, users need to exclude the built-in freemodbus component from the build process, and update application components to depend on esp-modbus component instead. To exclude freemodbus component from compilation, add the following line to the project CMakeLists.txt file:
|
||||||
|
|
||||||
|
```
|
||||||
|
set(EXCLUDE_COMPONENTS freemodbus)
|
||||||
|
```
|
||||||
|
|
||||||
|
ESP-IDF v5.x and later releases do not include freemodbus component, so no extra steps are necessary when adding esp-modbus component.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The documentation can be found on the link below:
|
||||||
|
|
||||||
|
* [ESP-Modbus documentation (English)](https://docs.espressif.com/projects/esp-modbus)
|
||||||
|
|
||||||
|
## Application Examples
|
||||||
|
|
||||||
|
The examples below demonstrate the ESP-Modbus library of serial, TCP ports for slave and master implementations accordingly.
|
||||||
|
|
||||||
|
- [Modbus serial slave example](https://github.com/espressif/esp-idf/tree/master/examples/protocols/modbus/serial/mb_slave)
|
||||||
|
|
||||||
|
- [Modbus serial master example](https://github.com/espressif/esp-idf/tree/master/examples/protocols/modbus/serial/mb_master)
|
||||||
|
|
||||||
|
- [Modbus TCP master example](https://github.com/espressif/esp-idf/tree/master/examples/protocols/modbus/tcp/mb_tcp_master)
|
||||||
|
|
||||||
|
- [Modbus TCP slave example](https://github.com/espressif/esp-idf/tree/master/examples/protocols/modbus/tcp/mb_tcp_slave)
|
||||||
|
|
||||||
|
Please refer to the specific example README.md for details.
|
||||||
|
|
||||||
|
## Protocol References
|
||||||
|
|
||||||
|
- [Modbus Organization with protocol specifications](https://modbus.org/specs.php)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
We welcome contributions to this project in the form of bug reports, feature requests and pull requests.
|
||||||
|
|
||||||
|
Issue reports and feature requests can be submitted using Github Issues: https://github.com/espressif/esp-modbus/issues. Please check if the issue has already been reported before opening a new one.
|
||||||
|
|
||||||
|
Contributions in the form of pull requests should follow ESP-IDF project's [contribution guidelines](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/contribute/index.html). We kindly ask developers to start a discussion on an issue before proposing large changes to the project.
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
|
||||||
|
ESP-Modbus project is based on [FreeMODBUS library](https://github.com/cwalter-at/freemodbus), Copyright (c) 2006 Christian Walter and licensed under the BSD 3-clause license.
|
||||||
|
|
||||||
|
Modbus Master related code is Copyright (c) 2013 Armink and licensed under BSD 3-clause license.
|
||||||
|
|
||||||
|
All original code in this repository is Copyright (c) 2016-2022 Espressif Systems (Shanghai) Co. Ltd.
|
||||||
|
|
||||||
|
The project is distributed under Apache 2.0 license. See the accompanying [LICENSE file](https://github.com/espressif/esp-modbus/blob/master/LICENSE) for a copy.
|
91
components/freemodbus/build_all.sh
Executable file
91
components/freemodbus/build_all.sh
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Build the test app and all examples from the examples directory.
|
||||||
|
# Expects TEST_TARGETS environment variables to be set.
|
||||||
|
# Each variable is the list of IDF_TARGET values to build the examples and
|
||||||
|
# the test app for, respectively.
|
||||||
|
#
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Safety settings (see https://gist.github.com/ilg-ul/383869cbb01f61a51c4d).
|
||||||
|
|
||||||
|
if [[ -n "${DEBUG_SHELL}" ]]
|
||||||
|
then
|
||||||
|
set -x # Activate the expand mode if DEBUG is anything but empty.
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${EXAMPLE_TARGETS}" || -z "${TEST_TARGETS}" ]]
|
||||||
|
then
|
||||||
|
echo "EXAMPLE_TARGETS and TEST_TARGETS environment variables must be set before calling this script"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${SKIP_GNU_MAKE_BUILD}" ]]
|
||||||
|
then
|
||||||
|
echo "SKIP_GNU_MAKE_BUILD not set, will build with GNU Make based build system as well."
|
||||||
|
export SKIP_GNU_MAKE_BUILD=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -o errexit # Exit if command failed.
|
||||||
|
set -o pipefail # Exit if pipe failed.
|
||||||
|
set -o nounset # Exit if variable not set.
|
||||||
|
|
||||||
|
|
||||||
|
STARS='***************************************************'
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
die() {
|
||||||
|
echo "${1:-"Unknown Error"}" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# build_for_targets <target list>
|
||||||
|
# call this in the project directory
|
||||||
|
function build_for_targets
|
||||||
|
{
|
||||||
|
target_list="$1"
|
||||||
|
for IDF_TARGET in ${target_list}
|
||||||
|
do
|
||||||
|
export IDF_TARGET
|
||||||
|
if [[ "${IDF_TARGET}" = "esp32" ]] && [[ "${SKIP_GNU_MAKE_BUILD}" = "0" ]]
|
||||||
|
then
|
||||||
|
echo "${STARS}"
|
||||||
|
echo "Building in $PWD with Make"
|
||||||
|
# -j option will be set via MAKEFLAGS in .gitlab-ci.yml
|
||||||
|
# shellcheck disable=SC2015
|
||||||
|
make defconfig && make || die "Make build in ${PWD} has failed"
|
||||||
|
rm -rf build
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${STARS}"
|
||||||
|
echo "Building in $PWD with CMake for ${IDF_TARGET}"
|
||||||
|
if [[ ${IDF_TARGET} != "esp32" ]]
|
||||||
|
then
|
||||||
|
# IDF 4.0 doesn't support idf.py set-target, and only supports esp32.
|
||||||
|
idf.py set-target "${IDF_TARGET}"
|
||||||
|
fi
|
||||||
|
idf.py build || die "CMake build in ${PWD} has failed for ${IDF_TARGET}"
|
||||||
|
idf.py fullclean
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_folders
|
||||||
|
{
|
||||||
|
pushd "$1"
|
||||||
|
EXAMPLES=$(find . -maxdepth 1 -mindepth 1 -type d | cut -d '/' -f 2)
|
||||||
|
for NAME in ${EXAMPLES}
|
||||||
|
do
|
||||||
|
cd "${NAME}"
|
||||||
|
build_for_targets "$2"
|
||||||
|
cd ..
|
||||||
|
done
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "${STARS}"
|
||||||
|
# Build the tests
|
||||||
|
build_folders test/serial "${TEST_TARGETS}"
|
||||||
|
echo "${STARS}"
|
||||||
|
# Build the tests
|
||||||
|
build_folders test/tcp "${TEST_TARGETS}"
|
||||||
|
echo "${STARS}"
|
@ -1,29 +0,0 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Stack callback functions prototypes
|
|
||||||
|
|
||||||
#ifndef _ESP_MODBUS_CALLBACKS_H_
|
|
||||||
#define _ESP_MODBUS_CALLBACKS_H_
|
|
||||||
|
|
||||||
#include "mb.h"
|
|
||||||
#include "mb_m.h"
|
|
||||||
|
|
||||||
typedef eMBErrorCode (*reg_input_cb)(UCHAR*, USHORT, USHORT);
|
|
||||||
typedef eMBErrorCode (*reg_holding_cb)(UCHAR*, USHORT, USHORT, eMBRegisterMode);
|
|
||||||
typedef eMBErrorCode (*reg_coils_cb)(UCHAR*, USHORT, USHORT, eMBRegisterMode);
|
|
||||||
typedef eMBErrorCode (*reg_discrete_cb)(UCHAR*, USHORT, USHORT);
|
|
||||||
|
|
||||||
#endif /* _ESP_MODBUS_CALLBACKS_H_ */
|
|
@ -1,33 +0,0 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "esp_err.h" // for esp_err_t
|
|
||||||
#include "esp_modbus_master.h" // for public interface defines
|
|
||||||
#include "mbc_tcp_master.h" // for public interface defines
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialization of Modbus TCP Master controller interface
|
|
||||||
*/
|
|
||||||
esp_err_t mbc_master_init_tcp(void** handler)
|
|
||||||
{
|
|
||||||
void* port_handler = NULL;
|
|
||||||
esp_err_t error = mbc_tcp_master_create(&port_handler);
|
|
||||||
|
|
||||||
if ((port_handler != NULL) && (error == ESP_OK)) {
|
|
||||||
mbc_master_init_iface(port_handler);
|
|
||||||
*handler = port_handler;
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "esp_err.h" // for esp_err_t
|
|
||||||
#include "esp_modbus_slave.h" // for public slave defines
|
|
||||||
#include "mbc_tcp_slave.h" // for public interface defines
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialization of Modbus TCP Slave controller
|
|
||||||
*/
|
|
||||||
esp_err_t mbc_slave_init_tcp(void** handler)
|
|
||||||
{
|
|
||||||
void* port_handler = NULL;
|
|
||||||
esp_err_t error = mbc_tcp_slave_create(&port_handler);
|
|
||||||
|
|
||||||
if ((port_handler != NULL) && (error == ESP_OK)) {
|
|
||||||
mbc_slave_init_iface(port_handler);
|
|
||||||
*handler = port_handler;
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
@ -1,14 +1,26 @@
|
|||||||
COMPONENT_ADD_INCLUDEDIRS := common/include
|
INCLUDEDIRS := common/include
|
||||||
COMPONENT_PRIV_INCLUDEDIRS := common port modbus modbus/ascii modbus/functions
|
PRIV_INCLUDEDIRS := common port modbus modbus/ascii modbus/functions
|
||||||
COMPONENT_PRIV_INCLUDEDIRS += modbus/rtu modbus/tcp modbus/include
|
PRIV_INCLUDEDIRS += modbus/rtu modbus/tcp modbus/include
|
||||||
COMPONENT_PRIV_INCLUDEDIRS += serial_slave/port serial_slave/modbus_controller
|
PRIV_INCLUDEDIRS += serial_slave/port serial_slave/modbus_controller
|
||||||
COMPONENT_PRIV_INCLUDEDIRS += serial_master/port serial_master/modbus_controller
|
PRIV_INCLUDEDIRS += serial_master/port serial_master/modbus_controller
|
||||||
COMPONENT_PRIV_INCLUDEDIRS += tcp_slave/port tcp_slave/modbus_controller
|
PRIV_INCLUDEDIRS += tcp_slave/port tcp_slave/modbus_controller
|
||||||
COMPONENT_PRIV_INCLUDEDIRS += tcp_master/port tcp_master/modbus_controller
|
PRIV_INCLUDEDIRS += tcp_master/port tcp_master/modbus_controller
|
||||||
COMPONENT_SRCDIRS := common
|
SRCDIRS := common
|
||||||
COMPONENT_SRCDIRS += modbus modbus/ascii modbus/functions modbus/rtu modbus/tcp
|
SRCDIRS += modbus modbus/ascii modbus/functions modbus/rtu modbus/tcp
|
||||||
COMPONENT_SRCDIRS += serial_slave/port serial_slave/modbus_controller
|
SRCDIRS += serial_slave/port serial_slave/modbus_controller
|
||||||
COMPONENT_SRCDIRS += serial_master/port serial_master/modbus_controller
|
SRCDIRS += serial_master/port serial_master/modbus_controller
|
||||||
COMPONENT_SRCDIRS += tcp_slave/port tcp_slave/modbus_controller
|
SRCDIRS += tcp_slave/port tcp_slave/modbus_controller
|
||||||
COMPONENT_SRCDIRS += tcp_master/port tcp_master/modbus_controller
|
SRCDIRS += tcp_master/port tcp_master/modbus_controller
|
||||||
COMPONENT_SRCDIRS += port
|
SRCDIRS += port
|
||||||
|
|
||||||
|
COMPONENT_PRIV_INCLUDEDIRS = $(addprefix freemodbus/, \
|
||||||
|
$(PRIV_INCLUDEDIRS) \
|
||||||
|
)
|
||||||
|
|
||||||
|
COMPONENT_SRCDIRS = $(addprefix freemodbus/, \
|
||||||
|
$(SRCDIRS) \
|
||||||
|
)
|
||||||
|
|
||||||
|
COMPONENT_ADD_INCLUDEDIRS = $(addprefix freemodbus/, \
|
||||||
|
$(INCLUDEDIRS) \
|
||||||
|
)
|
||||||
|
57
components/freemodbus/docs/Doxyfile
Normal file
57
components/freemodbus/docs/Doxyfile
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# This is Doxygen configuration file
|
||||||
|
#
|
||||||
|
# Doxygen provides over 260 configuration statements
|
||||||
|
# To make this file easier to follow,
|
||||||
|
# it contains only statements that are non-default
|
||||||
|
#
|
||||||
|
# NOTE:
|
||||||
|
# It is recommended not to change defaults unless specifically required
|
||||||
|
# Test any changes how they affect generated documentation
|
||||||
|
# Make sure that correct warnings are generated to flag issues with documented code
|
||||||
|
#
|
||||||
|
# For the complete list of configuration statements see:
|
||||||
|
# http://doxygen.nl/manual/config.html
|
||||||
|
|
||||||
|
|
||||||
|
PROJECT_NAME = "IDF Programming Guide"
|
||||||
|
|
||||||
|
## The 'INPUT' statement below is used as input by script 'gen-df-input.py'
|
||||||
|
## to automatically generate API reference list files heder_file.inc
|
||||||
|
## These files are placed in '_inc' directory
|
||||||
|
## and used to include in API reference documentation
|
||||||
|
|
||||||
|
INPUT = \
|
||||||
|
$(PROJECT_PATH)/freemodbus/common/include/esp_modbus_common.h \
|
||||||
|
$(PROJECT_PATH)/freemodbus/common/include/esp_modbus_slave.h \
|
||||||
|
$(PROJECT_PATH)/freemodbus/common/include/esp_modbus_master.h \
|
||||||
|
|
||||||
|
## Get warnings for functions that have no documentation for their parameters or return value
|
||||||
|
##
|
||||||
|
WARN_NO_PARAMDOC = YES
|
||||||
|
|
||||||
|
## Enable preprocessing and remove __attribute__(...) expressions from the INPUT files
|
||||||
|
##
|
||||||
|
ENABLE_PREPROCESSING = YES
|
||||||
|
MACRO_EXPANSION = YES
|
||||||
|
EXPAND_ONLY_PREDEF = YES
|
||||||
|
PREDEFINED = \
|
||||||
|
$(ENV_DOXYGEN_DEFINES) \
|
||||||
|
|
||||||
|
## Do not complain about not having dot
|
||||||
|
##
|
||||||
|
HAVE_DOT = NO
|
||||||
|
|
||||||
|
## Generate XML that is required for Breathe
|
||||||
|
##
|
||||||
|
GENERATE_XML = YES
|
||||||
|
XML_OUTPUT = xml
|
||||||
|
|
||||||
|
GENERATE_HTML = NO
|
||||||
|
HAVE_DOT = NO
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
GENERATE_MAN = YES
|
||||||
|
GENERATE_RTF = NO
|
||||||
|
|
||||||
|
## Skip distracting progress messages
|
||||||
|
##
|
||||||
|
QUIET = YES
|
11
components/freemodbus/docs/README.md
Normal file
11
components/freemodbus/docs/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# ESP-Modbus Library
|
||||||
|
|
||||||
|
This folder represents the official documentation for the ESP-Modbus library (**esp-modbus component documentation**). The Modbus is a data communications protocol originally published by Modicon (now Schneider Electric) in 1979 for use with its programmable logic controllers (PLCs). The Modbus has become a de facto standard communication protocol and is now a commonly available means of connecting industrial electronic devices. This library supports Modbus communication in the networks that are based on RS485 or Ethernet interfaces.
|
||||||
|
|
||||||
|
# Hosted Documentation
|
||||||
|
|
||||||
|
* English: https://docs.espressif.com/projects/esp-modbus/
|
||||||
|
|
||||||
|
# Building Documentation
|
||||||
|
|
||||||
|
The documentation is built using the python package `esp-docs`, which can be installed by running `pip install esp-docs`. Running `build-docs --help` will give a summary of available options. For more information see the `esp-docs` documentation at https://github.com/espressif/esp-docs/blob/master/README.md
|
260
components/freemodbus/docs/_static/404-page__en.svg
vendored
Normal file
260
components/freemodbus/docs/_static/404-page__en.svg
vendored
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1"
|
||||||
|
id="图层_1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 580"
|
||||||
|
style="enable-background:new 0 0 1000 580;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#FFFFFF;}
|
||||||
|
.st1{fill:url(#polygon12_1_);}
|
||||||
|
.st2{fill:url(#polygon21_1_);}
|
||||||
|
.st3{opacity:0.27;fill:url(#circle42_1_);enable-background:new ;}
|
||||||
|
.st4{fill:url(#polygon58_1_);}
|
||||||
|
.st5{fill:#444444;stroke:#FFFFFF;stroke-width:0.834;stroke-miterlimit:10;}
|
||||||
|
.st6{fill:none;stroke:#FFFFFF;stroke-width:1.1033;stroke-miterlimit:10;}
|
||||||
|
.st7{fill:none;stroke:#353535;stroke-width:1.1033;stroke-miterlimit:10;}
|
||||||
|
.st8{fill:#FFFFFF;stroke:#444444;stroke-width:0.834;stroke-miterlimit:10;}
|
||||||
|
.st9{fill:#444444;stroke:#FFFFFF;stroke-width:0.8485;stroke-miterlimit:10;}
|
||||||
|
.st10{fill:none;stroke:#FFFFFF;stroke-width:1.1226;stroke-miterlimit:10;}
|
||||||
|
.st11{fill:none;stroke:#353535;stroke-width:1.1226;stroke-miterlimit:10;}
|
||||||
|
.st12{fill:#FFFFFF;stroke:#444444;stroke-width:0.8485;stroke-miterlimit:10;}
|
||||||
|
.st13{fill:#353535;}
|
||||||
|
.st14{fill:#444444;stroke:#FFFFFF;stroke-width:0.9321;stroke-miterlimit:10;}
|
||||||
|
.st15{fill:none;stroke:#FFFFFF;stroke-width:1.046;stroke-miterlimit:10;}
|
||||||
|
.st16{fill:none;stroke:#353535;stroke-width:1.046;stroke-miterlimit:10;}
|
||||||
|
.st17{fill:#FFFFFF;stroke:#444444;stroke-width:0.7906;stroke-miterlimit:10;}
|
||||||
|
.st18{opacity:0.59;fill:#E0E0E0;enable-background:new ;}
|
||||||
|
.st19{fill:#FFFFFF;stroke:#444444;stroke-width:2;stroke-miterlimit:10;}
|
||||||
|
.st20{fill:none;stroke:#444444;stroke-width:2;stroke-miterlimit:10;}
|
||||||
|
.st21{fill:none;stroke:#444444;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st22{enable-background:new ;}
|
||||||
|
.st23{fill:#4D4D4D;}
|
||||||
|
</style>
|
||||||
|
<rect id="BG_2_" x="-1" y="-9.5" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476" class="st0" width="1012.9" height="600.4">
|
||||||
|
</rect>
|
||||||
|
<linearGradient id="polygon12_1_" gradientUnits="userSpaceOnUse" x1="1014.7582" y1="90.2012" x2="1077.5918" y2="356.7023" gradientTransform="matrix(0.9556 0.295 -0.2974 0.9605 -400.3649 -336.724)">
|
||||||
|
<stop offset="4.835800e-02" style="stop-color:#9FA0A0"/>
|
||||||
|
<stop offset="0.5227" style="stop-color:#D7D8D8;stop-opacity:0.4381"/>
|
||||||
|
<stop offset="0.8926" style="stop-color:#FFFFFF;stop-opacity:0"/>
|
||||||
|
</linearGradient>
|
||||||
|
<polygon id="polygon12" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476" class="st1" points="608.7,371.9
|
||||||
|
511.9,134.7 490.9,134.1 430.7,377.1 ">
|
||||||
|
</polygon>
|
||||||
|
<linearGradient id="polygon21_1_" gradientUnits="userSpaceOnUse" x1="197.9478" y1="434.8972" x2="282.0578" y2="791.6389" gradientTransform="matrix(0.9983 -5.887031e-02 5.887031e-02 0.9983 28.0536 -430.7623)">
|
||||||
|
<stop offset="4.835800e-02" style="stop-color:#898989"/>
|
||||||
|
<stop offset="0.5874" style="stop-color:#D7D7D7;stop-opacity:0.3616"/>
|
||||||
|
<stop offset="0.8926" style="stop-color:#FFFFFF;stop-opacity:0"/>
|
||||||
|
</linearGradient>
|
||||||
|
<polygon id="polygon21" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476" class="st2" points="325.4,155.1
|
||||||
|
289.2,163.9 291.9,437 480.9,450.4 ">
|
||||||
|
</polygon>
|
||||||
|
<radialGradient id="circle42_1_" cx="836.3" cy="506.5986" r="65.7125" gradientTransform="matrix(1 0 0 1 12 -19.0997)" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0" style="stop-color:#FFFFFF"/>
|
||||||
|
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<circle id="circle42" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476" class="st3" cx="848.3" cy="487.5" r="68.3">
|
||||||
|
</circle>
|
||||||
|
<linearGradient id="polygon58_1_" gradientUnits="userSpaceOnUse" x1="1863.538" y1="415.4688" x2="1929.7196" y2="696.1702" gradientTransform="matrix(0.8607 0.5092 -0.5092 0.8607 -635.7186 -1225.6498)">
|
||||||
|
<stop offset="4.835800e-02" style="stop-color:#898989"/>
|
||||||
|
<stop offset="0.5874" style="stop-color:#D7D7D7;stop-opacity:0.3616"/>
|
||||||
|
<stop offset="0.8926" style="stop-color:#FFFFFF;stop-opacity:0"/>
|
||||||
|
</linearGradient>
|
||||||
|
<polygon id="polygon58" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476" class="st4" points="547.4,383
|
||||||
|
763.1,428.2 713.7,163.4 683.8,156 ">
|
||||||
|
</polygon>
|
||||||
|
<g id="g94" transform="rotate(9.0573675,796.06564,263.99283)" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476">
|
||||||
|
<path id="path60" inkscape:connector-curvature="0" class="st5" d="M520,160.2l-75.8,10.4c-5.6,0.8-10.8-3.2-11.5-8.7l0,0
|
||||||
|
c-0.8-5.6,3.2-10.8,8.7-11.5l75.8-10.4c5.6-0.8,10.8,3.2,11.5,8.7l0,0C529.5,154.3,525.6,159.4,520,160.2L520,160.2z"/>
|
||||||
|
|
||||||
|
<ellipse id="circle62" transform="matrix(0.1574 -0.9875 0.9875 0.1574 220.2397 577.3303)" class="st6" cx="448.4" cy="159.6" rx="5.6" ry="5.6"/>
|
||||||
|
|
||||||
|
<ellipse id="circle64" transform="matrix(0.1574 -0.9875 0.9875 0.1574 241.8959 596.7076)" class="st6" cx="470.6" cy="156.6" rx="5.6" ry="5.6"/>
|
||||||
|
|
||||||
|
<ellipse id="circle66" transform="matrix(0.1574 -0.9875 0.9875 0.1574 304.0202 547.2599)" class="st7" cx="472.7" cy="95.5" rx="3.9" ry="3.9"/>
|
||||||
|
|
||||||
|
<ellipse id="circle68" transform="matrix(0.1574 -0.9875 0.9875 0.1574 263.9857 616.4264)" class="st6" cx="493.2" cy="153.5" rx="5.6" ry="5.6"/>
|
||||||
|
|
||||||
|
<ellipse id="circle70" transform="matrix(0.1574 -0.9875 0.9875 0.1574 285.6079 635.2634)" class="st6" cx="515.1" cy="150.3" rx="5.6" ry="5.6"/>
|
||||||
|
<path id="path72" inkscape:connector-curvature="0" class="st8" d="M510,139.5l-61.3,8.4l-0.4-2.8c-0.2-1.5,0.8-2.9,2.3-3.1
|
||||||
|
l55.7-7.7c1.5-0.2,2.9,0.8,3.1,2.3L510,139.5z"/>
|
||||||
|
<path id="path74" inkscape:connector-curvature="0" class="st8" d="M519.9,161.7L444.9,172l0.3,2.4c0.3,1.7,1.8,2.8,3.4,2.6
|
||||||
|
l69.1-9.5c1.7-0.3,2.8-1.8,2.6-3.4L519.9,161.7z"/>
|
||||||
|
<path id="path76" inkscape:connector-curvature="0" class="st7" d="M508.2,170.4l-50.5,6.9l0.4,3c0.2,1.3,1.5,2.3,2.8,2.2l45.5-6.3
|
||||||
|
c1.3-0.2,2.3-1.5,2.2-2.8L508.2,170.4z"/>
|
||||||
|
<path id="path78" inkscape:connector-curvature="0" class="st7" d="M499.5,133.7l-43.7,6l-1.8-13.2c-1-7.3,4.1-14,11.3-15l17.3-2.4
|
||||||
|
c7.3-1,14,4.1,15,11.3L499.5,133.7z"/>
|
||||||
|
<line id="line80" class="st7" x1="473.5" y1="100.6" x2="474.6" y2="109.1"/>
|
||||||
|
<line id="line82" class="st7" x1="471.6" y1="119.4" x2="464.5" y2="131.7"/>
|
||||||
|
<line id="line84" class="st7" x1="485.9" y1="117.9" x2="478.7" y2="130.2"/>
|
||||||
|
<path id="path86" inkscape:connector-curvature="0" class="st8" d="M470.7,182.8L467,193c-0.2,0.5,0.5,0.9,0.8,0.5l10.5-11.3
|
||||||
|
c0.3-0.3,0-0.9-0.4-0.8l-6.8,1C471,182.5,470.8,182.6,470.7,182.8z"/>
|
||||||
|
<path id="path88" inkscape:connector-curvature="0" class="st8" d="M460.7,184l-6.3,9.2c-0.3,0.5,0.3,1,0.8,0.7l12.8-10.1
|
||||||
|
c0.4-0.3,0.2-0.9-0.4-0.9l-6.6,0.9C460.9,183.9,460.8,184,460.7,184L460.7,184z"/>
|
||||||
|
<path id="path90" inkscape:connector-curvature="0" class="st8" d="M496.6,179l6.3,8.8c0.3,0.4-0.2,1-0.7,0.8l-13.2-8
|
||||||
|
c-0.4-0.3-0.3-0.8,0.2-0.9l6.8-0.8C496.3,178.8,496.5,178.9,496.6,179L496.6,179z"/>
|
||||||
|
<path id="path92" inkscape:connector-curvature="0" class="st8" d="M506.7,177.5l8.5,7.2c0.4,0.3,0,1.1-0.5,0.8l-15.1-6.3
|
||||||
|
c-0.5-0.2-0.4-0.9,0.1-0.9l6.6-0.9C506.4,177.4,506.5,177.4,506.7,177.5L506.7,177.5z"/>
|
||||||
|
</g>
|
||||||
|
<g id="g130" transform="translate(-131.09867,-443.26745)" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476">
|
||||||
|
<path id="path96" inkscape:connector-curvature="0" class="st9" d="M875,594.1l-76.7-13.2c-5.6-0.9-9.4-6.4-8.5-12l0,0
|
||||||
|
c0.9-5.6,6.4-9.4,12-8.5l76.7,13.2c5.6,0.9,9.4,6.4,8.5,12l0,0C885.9,591.3,880.6,595.1,875,594.1z"/>
|
||||||
|
<circle id="circle98" class="st10" cx="805.6" cy="571.5" r="5.7"/>
|
||||||
|
<circle id="circle100" class="st10" cx="828.2" cy="575.4" r="5.7"/>
|
||||||
|
<circle id="circle102" class="st11" cx="849" cy="516.8" r="4"/>
|
||||||
|
<circle id="circle104" class="st10" cx="851" cy="579.3" r="5.7"/>
|
||||||
|
<circle id="circle106" class="st10" cx="873.2" cy="583" r="5.7"/>
|
||||||
|
<path id="path108" inkscape:connector-curvature="0" class="st12" d="M871.6,570.9l-61.9-10.7l0.5-2.8c0.3-1.5,1.7-2.5,3.2-2.3
|
||||||
|
l56.4,9.8c1.5,0.3,2.5,1.7,2.3,3.2L871.6,570.9z"/>
|
||||||
|
<path id="path110" inkscape:connector-curvature="0" class="st12" d="M874.4,595.5l-76-13.2l-0.4,2.5c-0.3,1.7,0.8,3.3,2.5,3.6
|
||||||
|
l69.8,12c1.7,0.3,3.3-0.8,3.6-2.5L874.4,595.5z"/>
|
||||||
|
<path id="path112" inkscape:connector-curvature="0" class="st13" d="M860.3,600.3l-51.1-8.8l-0.5,3.1c-0.3,1.4,0.7,2.7,2.1,3l46,8
|
||||||
|
c1.4,0.3,2.7-0.7,3-2.1L860.3,600.3z"/>
|
||||||
|
<path id="path114" inkscape:connector-curvature="0" class="st11" d="M863.2,562.2l-44.2-7.6l2.3-13.3c1.3-7.3,8.3-12.3,15.6-11
|
||||||
|
l17.5,3.1c7.3,1.3,12.3,8.3,11,15.6L863.2,562.2z"/>
|
||||||
|
<line id="line116" class="st11" x1="848.1" y1="522.1" x2="846.6" y2="530.6"/>
|
||||||
|
<line id="line118" class="st11" x1="840.5" y1="539.7" x2="829.8" y2="549.5"/>
|
||||||
|
<line id="line120" class="st11" x1="854.8" y1="542.6" x2="844.2" y2="552.3"/>
|
||||||
|
<path id="path122" inkscape:connector-curvature="0" class="st12" d="M820.1,600.8l-6.8,8.7c-0.3,0.4,0.2,1,0.7,0.8l13.7-7.6
|
||||||
|
c0.4-0.3,0.3-0.8-0.2-0.9l-7-1.1C820.5,600.6,820.3,600.7,820.1,600.8L820.1,600.8z"/>
|
||||||
|
<path id="path124" inkscape:connector-curvature="0" class="st12" d="M810,599l-8.9,7c-0.4,0.3-0.1,1.1,0.5,0.8l15.5-5.9
|
||||||
|
c0.5-0.2,0.4-0.8-0.1-1l-6.6-1.2C810.3,598.8,810.1,598.9,810,599L810,599z"/>
|
||||||
|
<path id="path126" inkscape:connector-curvature="0" class="st12" d="M846.4,605.1l3.5,10.5c0.2,0.5-0.5,0.9-0.8,0.5l-10.4-11.8
|
||||||
|
c-0.3-0.3,0-0.9,0.5-0.8l6.9,1.3C846.3,604.9,846.4,605,846.4,605.1L846.4,605.1z"/>
|
||||||
|
<path id="path128" inkscape:connector-curvature="0" class="st12" d="M856.6,606.8l6,9.6c0.3,0.5-0.3,1-0.8,0.7l-12.7-10.7
|
||||||
|
c-0.4-0.3-0.1-1,0.4-0.8l6.6,1.2C856.4,606.6,856.5,606.7,856.6,606.8L856.6,606.8z"/>
|
||||||
|
</g>
|
||||||
|
<g id="g166" transform="translate(6.564267,-535.67492)" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476">
|
||||||
|
<path id="path132" inkscape:connector-curvature="0" class="st14" d="M331.5,670.9l-70.2,18.3c-5.1,1.3-10.4-1.8-11.7-6.9l0,0
|
||||||
|
c-1.3-5.1,1.8-10.4,6.9-11.7l70.2-18.3c5.1-1.3,10.4,1.8,11.7,6.9l0,0C339.7,664.2,336.7,669.6,331.5,670.9z"/>
|
||||||
|
<circle id="circle134" class="st15" cx="264.1" cy="678.3" r="5.3"/>
|
||||||
|
<circle id="circle136" class="st15" cx="284.7" cy="673" r="5.3"/>
|
||||||
|
<circle id="circle138" class="st16" cx="279.7" cy="615.2" r="3.7"/>
|
||||||
|
<circle id="circle140" class="st15" cx="305.5" cy="667.5" r="5.3"/>
|
||||||
|
<circle id="circle142" class="st15" cx="325.8" cy="662.1" r="5.3"/>
|
||||||
|
<path id="path144" inkscape:connector-curvature="0" class="st17" d="M319.7,652.5L263,667.3l-0.7-2.5c-0.4-1.4,0.5-2.8,1.9-3.2
|
||||||
|
l51.6-13.4c1.4-0.4,2.8,0.5,3.2,1.9L319.7,652.5z"/>
|
||||||
|
<path id="path146" inkscape:connector-curvature="0" class="st17" d="M331.5,672.3L262,690.4l0.6,2.2c0.4,1.6,2,2.5,3.5,2.1
|
||||||
|
l63.9-16.7c1.6-0.4,2.5-2,2.1-3.5L331.5,672.3z"/>
|
||||||
|
<path id="path148" inkscape:connector-curvature="0" class="st13" d="M321.5,681.8L274.8,694l0.7,2.8c0.4,1.3,1.7,2.1,2.9,1.7
|
||||||
|
l42.1-11c1.3-0.4,2.1-1.7,1.7-2.9L321.5,681.8z"/>
|
||||||
|
<path id="path150" inkscape:connector-curvature="0" class="st16" d="M309.3,648.2l-40.5,10.5l-3.2-12.2c-1.8-6.7,2.3-13.6,9-15.4
|
||||||
|
l16-4.2c6.7-1.8,13.6,2.3,15.4,9L309.3,648.2z"/>
|
||||||
|
<line id="line152" class="st16" x1="281" y1="620.1" x2="283.1" y2="627.9"/>
|
||||||
|
<line id="line154" class="st16" x1="281.4" y1="637.9" x2="276.1" y2="650.3"/>
|
||||||
|
<line id="line156" class="st16" x1="294.6" y1="634.9" x2="289.3" y2="647.3"/>
|
||||||
|
<path id="path158" inkscape:connector-curvature="0" class="st17" d="M287.6,697.6l-2.3,10.1c-0.1,0.5,0.6,0.8,0.8,0.4l8.7-11.7
|
||||||
|
c0.3-0.4-0.1-0.8-0.5-0.7l-6.3,1.8C287.8,697.3,287.6,697.4,287.6,697.6L287.6,697.6z"/>
|
||||||
|
<path id="path160" inkscape:connector-curvature="0" class="st17" d="M278.3,699.9l-4.8,9.3c-0.3,0.5,0.4,0.9,0.7,0.6l10.9-10.9
|
||||||
|
c0.4-0.4,0-0.9-0.5-0.8l-6.1,1.6C278.5,699.8,278.4,699.8,278.3,699.9L278.3,699.9z"/>
|
||||||
|
<path id="path162" inkscape:connector-curvature="0" class="st17" d="M311.6,691.2l7,7.6c0.4,0.4-0.1,0.9-0.6,0.7l-13.3-6.1
|
||||||
|
c-0.4-0.2-0.4-0.7,0.1-0.9l6.3-1.6C311.3,691,311.5,691.1,311.6,691.2z"/>
|
||||||
|
<path id="path164" inkscape:connector-curvature="0" class="st17" d="M320.8,688.7l8.8,5.8c0.5,0.3,0.1,1-0.4,0.8l-14.9-4.2
|
||||||
|
c-0.5-0.1-0.5-0.8,0-0.9l6.1-1.6C320.6,688.6,320.7,688.6,320.8,688.7z"/>
|
||||||
|
</g>
|
||||||
|
<path id="path168" inkscape:connector-curvature="0" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476" class="st18" d="
|
||||||
|
M241.1,524.1h-1c0.4-1.2,0.6-2.4,0.6-3.7c0-7-5.7-12.7-12.7-12.7h-3.3c-2.7,0-5.2,0.9-7.2,2.3c-1.2-0.8-2.7-1.3-4.3-1.3
|
||||||
|
c-0.7,0-1.4,0.1-2.1,0.3c-0.1-3.9-3.3-7.1-7.2-7.1h-0.3c-2.2,0-4.1,1-5.4,2.5l0,0c2.7-3.8,4.4-8.5,4.4-13.6
|
||||||
|
c0-13-10.6-23.5-23.5-23.5c-13,0-23.5,10.6-23.5,23.5c0,0.7,0,1.3,0.1,1.9c-2.9,0.3-5.7,1.3-8,2.9c-3.2-4.3-8.2-7.1-13.9-7.1l0,0
|
||||||
|
c-9.5,0-17.3,7.8-17.3,17.3c0,0.1,0,0.3,0,0.4c-1.8-0.9-3.7-1.5-5.9-1.5c-6.9,0-12.6,5.7-12.6,12.6c0,0.7,0.1,1.5,0.2,2.2H92
|
||||||
|
c-3,0-5.5,1.9-6.5,4.5h-9.9c-2.5,0-4.5,2-4.5,4.5s2,4.5,4.5,4.5h149.2h3.3h13.1c2.5,0,4.5-2,4.5-4.5
|
||||||
|
C245.6,526.1,243.6,524.1,241.1,524.1L241.1,524.1z"/>
|
||||||
|
<path id="path170" inkscape:connector-curvature="0" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476" class="st18" d="
|
||||||
|
M898.4,516.3h-0.9c0.3-1,0.5-2.1,0.5-3.3c0-6.2-5.1-11.3-11.3-11.3h-2.9c-2.4,0-4.6,0.8-6.4,2c-1.1-0.7-2.4-1.1-3.8-1.1
|
||||||
|
c-0.6,0-1.2,0.1-1.8,0.3c-0.1-3.5-2.9-6.3-6.4-6.3H865c-1.9,0-3.6,0.9-4.8,2.2l0,0c2.4-3.4,3.9-7.6,3.9-12
|
||||||
|
c0-11.5-9.4-20.9-20.9-20.9s-20.9,9.4-20.9,20.9c0,0.6,0,1.2,0.1,1.7c-2.6,0.2-5,1.2-7.1,2.6c-2.8-3.8-7.3-6.3-12.3-6.3l0,0
|
||||||
|
c-8.5,0-15.4,6.9-15.4,15.4c0,0.1,0,0.2,0,0.4c-1.6-0.8-3.3-1.4-5.2-1.4c-6.2,0-11.2,5-11.2,11.2c0,0.7,0.1,1.3,0.2,1.9h-5.5
|
||||||
|
c-2.6,0-4.9,1.7-5.8,4h-8.8c-2.2,0-4,1.8-4,4s1.8,4,4,4h132.5h2.9h11.6c2.2,0,4-1.8,4-4C902.4,518.1,900.6,516.3,898.4,516.3
|
||||||
|
L898.4,516.3z"/>
|
||||||
|
<g id="g184" transform="translate(10.641067,-115.56078)" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476">
|
||||||
|
<g id="g178">
|
||||||
|
<path id="path172" inkscape:connector-curvature="0" class="st19" d="M149.5,586c2.4,4.6,6.2,8.3,10.8,10.8c3.6,1.9,7.6,3,11.9,3
|
||||||
|
c14.2,0,25.7-11.5,25.7-25.7c0-4.3-1.1-8.4-3-11.9c-2.4-4.6-6.2-8.3-10.8-10.8c-3.6-1.9-7.6-3-11.9-3c-14.2,0-25.7,11.5-25.7,25.7
|
||||||
|
C146.6,578.4,147.7,582.4,149.5,586z"/>
|
||||||
|
<path id="path174" inkscape:connector-curvature="0" class="st18" d="M194.1,562.5c-2.3-4.4-6-8.1-10.4-10.4
|
||||||
|
c-3.4-1.8-7.4-2.9-11.5-2.9c-9.5,0-17.7,5.3-21.8,13.1c4-2.8,8.9-4.4,14.1-4.4c4.2,0,8.1,1,11.5,2.9c4.4,2.3,8.1,6,10.4,10.4
|
||||||
|
c1.8,3.4,2.9,7.4,2.9,11.5c0,4.2-1.1,8.2-2.9,11.7c6.4-4.5,10.6-11.9,10.6-20.3C197,569.8,196,565.9,194.1,562.5L194.1,562.5z"/>
|
||||||
|
<path id="path176" inkscape:connector-curvature="0" class="st20" d="M149.5,586c-7.7,10-11.6,17.8-9.3,20.1s10.1-1.6,20.1-9.3
|
||||||
|
c5.6-4.4,12-9.9,18.3-16.3c6.4-6.4,11.9-12.7,16.3-18.3c7.7-10,11.6-17.8,9.3-20.1s-10.1,1.6-20.1,9.3"/>
|
||||||
|
</g>
|
||||||
|
<path id="path180" inkscape:connector-curvature="0" class="st21" d="M154,566.3c0.5-1.2,1.1-2.3,1.8-3.4c0.7-1.1,1.5-2,2.4-2.9
|
||||||
|
s1.9-1.7,2.9-2.4c1.1-0.7,2.2-1.3,3.4-1.8s2.4-0.9,3.7-1.2s2.6-0.4,4-0.4"/>
|
||||||
|
<path id="path182" inkscape:connector-curvature="0" class="st21" d="M152.4,574.1c0-1.4,0.1-2.7,0.4-4"/>
|
||||||
|
</g>
|
||||||
|
<g id="g192" transform="translate(-0.2304,235.22748)" inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476">
|
||||||
|
<polygon id="polygon186" class="st19" points="843.4,216.1 850,204.1 856.6,216.1 868.7,222.7 856.6,229.3 850,241.4 843.4,229.3
|
||||||
|
831.4,222.7 "/>
|
||||||
|
<polygon id="polygon188" class="st19" points="868.4,248.1 873.4,239.1 878.3,248.1 887.4,253.1 878.3,258 873.4,267.1 868.4,258
|
||||||
|
859.4,253.1 "/>
|
||||||
|
<polygon id="polygon190" class="st19" points="884.1,207.8 887.4,201.7 890.7,207.8 896.7,211.1 890.7,214.4 887.4,220.4
|
||||||
|
884.1,214.4 878,211.1 "/>
|
||||||
|
</g>
|
||||||
|
<g inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476" class="st22">
|
||||||
|
<path class="st23" d="M332.8,346.5l65.5-89.9h24.1v89.6h17.5v20.8h-17.5v28.8h-27.9v-28.8h-61.7V346.5z M358.9,346.1h35.6v-34.4
|
||||||
|
c0-5.9,0.2-11.6,0.8-17h-0.9c-4.9,7.8-8,12.7-9.4,14.6L358.9,346.1z"/>
|
||||||
|
<path class="st23" d="M450.4,326.2c0-11.1,1.1-21,3.2-29.6c2.1-8.6,4.9-15.5,8.2-20.7c3.3-5.2,7.3-9.4,11.9-12.8
|
||||||
|
c4.6-3.3,9.1-5.6,13.5-6.8c4.4-1.2,9-1.8,13.7-1.8c16.3,0,28.8,6.4,37.5,19.1c8.7,12.7,13.1,30.3,13.1,52.6
|
||||||
|
c0,22.1-4.4,39.6-13.1,52.4c-8.7,12.8-21.2,19.2-37.4,19.2c-4.5,0-8.9-0.6-13.2-1.7c-4.3-1.1-8.7-3.3-13.4-6.6
|
||||||
|
c-4.6-3.2-8.7-7.4-12.1-12.5c-3.5-5.1-6.3-12-8.6-20.8C451.5,347.6,450.4,337.6,450.4,326.2z M479.4,326.2
|
||||||
|
c0,33.8,7.2,50.7,21.6,50.7c14.2,0,21.3-16.9,21.3-50.7c0-33.8-7.2-50.7-21.5-50.7C486.5,275.5,479.4,292.4,479.4,326.2z"/>
|
||||||
|
<path class="st23" d="M562.4,346.5l65.5-89.9h24.1v89.6h17.5v20.8h-17.5v28.8h-27.8v-28.8h-61.7V346.5z M588.5,346.1h35.6v-34.4
|
||||||
|
c0-5.9,0.2-11.6,0.8-17h-0.9c-4.9,7.8-8,12.7-9.4,14.6L588.5,346.1z"/>
|
||||||
|
</g>
|
||||||
|
<g inkscape:export-xdpi="96.009476" inkscape:export-ydpi="96.009476">
|
||||||
|
<path class="st23" d="M435.8,197.2c0-6.4,1.6-11.6,4.9-15.5c3.2-3.9,7.5-5.9,12.8-5.9c5.3,0,9.6,2,12.8,5.9
|
||||||
|
c3.2,3.9,4.8,9.1,4.8,15.5c0,6.4-1.6,11.6-4.8,15.4c-3.2,3.9-7.5,5.8-12.8,5.8c-5.3,0-9.6-1.9-12.8-5.8
|
||||||
|
C437.5,208.8,435.8,203.6,435.8,197.2z M443.6,197.2c0,4.6,0.9,8.2,2.6,10.8c1.7,2.7,4.2,4,7.3,4c3.1,0,5.5-1.3,7.2-4
|
||||||
|
c1.7-2.7,2.6-6.3,2.6-10.9c0-4.6-0.9-8.2-2.6-10.8c-1.7-2.7-4.1-4-7.2-4c-3.1,0-5.5,1.3-7.2,4C444.5,189,443.6,192.7,443.6,197.2z"
|
||||||
|
/>
|
||||||
|
<path class="st23" d="M474.8,202.7c0-4.4,1.2-8.2,3.5-11.2c2.3-3.1,5.8-4.6,10.4-4.6c3.1,0,5.7,0.8,7.9,2.3
|
||||||
|
c2.2,1.6,3.7,3.5,4.6,5.8c0.9,2.3,1.4,4.9,1.4,7.7c0,1.4-0.1,2.7-0.4,4c-0.2,1.3-0.7,2.7-1.3,4.2c-0.7,1.5-1.5,2.7-2.5,3.8
|
||||||
|
c-1,1.1-2.3,2-4,2.7c-1.7,0.7-3.6,1.1-5.7,1.1c-2.1,0-4-0.3-5.6-1c-1.7-0.7-3-1.5-4-2.6c-1-1.1-1.8-2.3-2.5-3.7
|
||||||
|
c-0.7-1.4-1.1-2.8-1.4-4.2C475,205.6,474.8,204.1,474.8,202.7z M482.3,202.7c0,3.4,0.6,5.8,1.9,7.3c1.3,1.5,2.8,2.3,4.5,2.3
|
||||||
|
c1.7,0,3.1-0.8,4.5-2.3c1.3-1.5,2-4,2-7.3c0-3.4-0.7-5.8-2-7.4c-1.3-1.5-2.8-2.3-4.5-2.3c-1.7,0-3.2,0.8-4.5,2.3
|
||||||
|
C482.9,196.8,482.3,199.3,482.3,202.7z"/>
|
||||||
|
<path class="st23" d="M507.9,229.5v-41.8h6.9v3.3c1.9-2.8,4.3-4.3,7.4-4.3c3.6,0,6.7,1.4,9.1,4.3c2.4,2.8,3.6,6.7,3.6,11.5
|
||||||
|
c0,2.8-0.4,5.2-1.2,7.3c-0.8,2.1-1.8,3.8-3.1,5c-1.3,1.2-2.6,2.1-4.1,2.7c-1.4,0.6-2.9,0.9-4.4,0.9c-1.8,0-3.3-0.4-4.5-1.2
|
||||||
|
c-1.2-0.8-2.1-1.7-2.7-2.7v14.9H507.9z M515,202.6c0,3,0.5,5.3,1.6,7.1c1.1,1.7,2.6,2.6,4.6,2.6c1.9,0,3.4-0.8,4.6-2.5
|
||||||
|
c1.1-1.7,1.7-4.1,1.7-7.2c0-3-0.6-5.3-1.7-7c-1.1-1.7-2.7-2.6-4.6-2.6c-2,0-3.5,0.9-4.6,2.7C515.6,197.4,515,199.8,515,202.6z"/>
|
||||||
|
<path class="st23" d="M537.8,211.3l5.1-3c2,3,4.6,4.5,7.9,4.5c1.5,0,2.6-0.3,3.4-0.9c0.8-0.6,1.2-1.4,1.2-2.3c0-0.3,0-0.6-0.1-0.8
|
||||||
|
c-0.1-0.3-0.2-0.5-0.4-0.7c-0.2-0.2-0.4-0.4-0.6-0.6c-0.2-0.2-0.4-0.4-0.8-0.6c-0.4-0.2-0.7-0.4-0.9-0.5c-0.2-0.1-0.6-0.3-1.1-0.5
|
||||||
|
c-0.5-0.2-0.9-0.3-1.2-0.4c-0.3-0.1-0.7-0.2-1.3-0.4c-0.6-0.2-1-0.3-1.3-0.4c-2.6-0.8-4.6-1.9-6.2-3.2c-1.6-1.3-2.3-3.2-2.3-5.7
|
||||||
|
c0-2.7,1.1-4.8,3.4-6.4c2.3-1.6,5-2.4,8.3-2.4c2.5,0,4.8,0.6,7,1.9c2.2,1.3,3.8,3,4.9,5l-4.8,2.9c-2.1-2.7-4.5-4-7.1-4
|
||||||
|
c-1.4,0-2.5,0.3-3.2,0.8c-0.8,0.6-1.1,1.3-1.1,2.2c0,0.3,0,0.6,0.1,0.9c0.1,0.3,0.2,0.5,0.4,0.8c0.2,0.2,0.4,0.4,0.6,0.6
|
||||||
|
c0.2,0.2,0.5,0.4,0.8,0.6c0.4,0.2,0.7,0.4,0.9,0.5c0.3,0.1,0.6,0.3,1.1,0.4c0.5,0.2,0.8,0.3,1.1,0.4c0.3,0.1,0.7,0.2,1.2,0.4
|
||||||
|
c0.5,0.2,0.9,0.3,1.2,0.4c5.9,2,8.9,4.9,8.9,8.9c0,2.5-1,4.6-3.1,6.4c-2.1,1.7-5,2.6-8.8,2.6c-2.9,0-5.6-0.7-7.9-2
|
||||||
|
S539.1,213.4,537.8,211.3z"/>
|
||||||
|
<path class="st23" d="M568.2,217.7v-8.3h9.3v8.3H568.2z M576.4,205.9h-7l-0.5-29.4h8L576.4,205.9z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st23" d="M333.4,464.8v-27.1h12c3.2,0,5.7,0.8,7.5,2.3c1.8,1.5,2.7,3.6,2.7,6.1c0,2.6-0.9,4.6-2.8,6.1
|
||||||
|
s-4.3,2.2-7.4,2.2H339v10.3H333.4z M339,450.2h5.7c1.6,0,2.9-0.4,3.8-1.1c0.9-0.7,1.4-1.7,1.4-3c0-1.3-0.4-2.3-1.3-3
|
||||||
|
c-0.9-0.7-2.2-1.1-3.8-1.1H339V450.2z"/>
|
||||||
|
<path class="st23" d="M354.1,464.8l10.8-27.1h6l10.8,27.1h-5.9l-2.3-6.4h-11.2l-2.3,6.4H354.1z M363.7,454.4h8.3l-2.2-6.4
|
||||||
|
c-0.5-1.5-1.1-3.3-1.8-5.5h-0.2c-0.2,0.7-0.5,1.6-0.9,2.8c-0.4,1.2-0.7,2.1-0.9,2.6L363.7,454.4z"/>
|
||||||
|
<path class="st23" d="M383,451.2c0-4.1,1.3-7.5,3.8-10.2c2.5-2.6,5.9-4,10-4c1.3,0,2.5,0.2,3.7,0.5c1.2,0.3,2.1,0.7,2.9,1.2
|
||||||
|
c0.8,0.5,1.5,1,2.2,1.7c0.7,0.6,1.2,1.2,1.5,1.7c0.4,0.5,0.7,1,0.9,1.5l-4.8,1.4c-0.4-0.5-0.8-1-1.1-1.3c-0.3-0.3-0.7-0.7-1.2-1.2
|
||||||
|
s-1.1-0.8-1.8-1s-1.4-0.3-2.3-0.3c-2.5,0-4.5,0.9-5.9,2.7c-1.4,1.8-2.1,4.2-2.1,7.2c0,3,0.7,5.4,2.2,7.2c1.5,1.8,3.3,2.7,5.6,2.7
|
||||||
|
c2,0,3.5-0.5,4.6-1.4c1.1-1,1.8-2.2,2-3.8c0.1-1.3,0.2-2,0.2-2.1h-7.1v-4.3h12.5v15.3H405l-0.5-2.4c-1.7,2-4.4,3-8,3
|
||||||
|
c-3.8,0-7-1.3-9.6-3.8C384.3,459,383,455.5,383,451.2z"/>
|
||||||
|
<path class="st23" d="M413.9,464.8v-27.1H434v4.3h-14.6v6.7h13.1v4.2h-13.1v7.6h14.9v4.3H413.9z"/>
|
||||||
|
<path class="st23" d="M448.1,464.8v-27.1h5.8l8.5,14.1l3.3,5.5h0.2c-0.4-2.6-0.6-5.2-0.6-7.9v-11.7h5.6v27.1h-5.8l-8.5-13.8
|
||||||
|
l-3.3-5.7h-0.2c0.4,2.5,0.6,5.1,0.6,7.9v11.6H448.1z"/>
|
||||||
|
<path class="st23" d="M475.4,451.3c0-4.3,1.2-7.7,3.6-10.3c2.4-2.6,5.6-3.9,9.5-3.9c4,0,7.1,1.3,9.5,3.9c2.4,2.6,3.6,6,3.6,10.3
|
||||||
|
c0,4.3-1.2,7.7-3.6,10.3c-2.4,2.6-5.6,3.9-9.5,3.9s-7.1-1.3-9.5-3.9C476.6,458.9,475.4,455.5,475.4,451.3z M481.2,451.3
|
||||||
|
c0,3,0.6,5.4,1.9,7.2c1.3,1.8,3.1,2.7,5.4,2.7c2.3,0,4.1-0.9,5.4-2.6c1.3-1.8,1.9-4.2,1.9-7.2c0-3-0.6-5.4-1.9-7.2
|
||||||
|
c-1.3-1.8-3.1-2.7-5.4-2.7c-2.3,0-4.1,0.9-5.4,2.7C481.9,445.8,481.2,448.2,481.2,451.3z"/>
|
||||||
|
<path class="st23" d="M502.7,442v-4.3h22.7v4.3h-8.6v22.8h-5.6V442H502.7z"/>
|
||||||
|
<path class="st23" d="M538.3,464.8v-27.1h19.6v4.3h-13.9v7.1h12.5v4.2h-12.5v11.4H538.3z"/>
|
||||||
|
<path class="st23" d="M559.9,451.3c0-4.3,1.2-7.7,3.6-10.3c2.4-2.6,5.6-3.9,9.5-3.9c4,0,7.1,1.3,9.5,3.9c2.4,2.6,3.6,6,3.6,10.3
|
||||||
|
c0,4.3-1.2,7.7-3.6,10.3c-2.4,2.6-5.6,3.9-9.5,3.9c-4,0-7.1-1.3-9.5-3.9C561.1,458.9,559.9,455.5,559.9,451.3z M565.7,451.3
|
||||||
|
c0,3,0.6,5.4,1.9,7.2c1.3,1.8,3.1,2.7,5.4,2.7c2.3,0,4.1-0.9,5.4-2.6c1.3-1.8,1.9-4.2,1.9-7.2c0-3-0.6-5.4-1.9-7.2
|
||||||
|
c-1.3-1.8-3.1-2.7-5.4-2.7c-2.3,0-4.1,0.9-5.4,2.7C566.3,445.8,565.7,448.2,565.7,451.3z"/>
|
||||||
|
<path class="st23" d="M590.5,454.6v-16.9h5.6v16.9c0,4.4,1.9,6.5,5.7,6.5c3.8,0,5.7-2.2,5.7-6.5v-16.9h5.6v16.9
|
||||||
|
c0,3.5-0.9,6.2-2.8,8c-1.9,1.9-4.7,2.8-8.5,2.8c-3.6,0-6.4-0.9-8.4-2.7S590.5,458.2,590.5,454.6z"/>
|
||||||
|
<path class="st23" d="M619.3,464.8v-27.1h5.8l8.5,14.1l3.3,5.5h0.2c-0.4-2.6-0.6-5.2-0.6-7.9v-11.7h5.6v27.1h-5.8l-8.5-13.8
|
||||||
|
l-3.3-5.7h-0.2c0.4,2.5,0.6,5.1,0.6,7.9v11.6H619.3z"/>
|
||||||
|
<path class="st23" d="M648.3,464.8v-27.1h9.2c4.6,0,8.2,1.2,10.7,3.5s3.7,5.7,3.7,10c0,1.4-0.1,2.8-0.4,4c-0.3,1.3-0.8,2.5-1.4,3.7
|
||||||
|
c-0.7,1.2-1.6,2.2-2.6,3c-1.1,0.8-2.4,1.5-4.1,2c-1.7,0.5-3.6,0.8-5.8,0.8H648.3z M653.9,460.5h3c3,0,5.3-0.7,6.8-2.2
|
||||||
|
c1.5-1.5,2.3-3.8,2.3-7.1c0-3.3-0.8-5.7-2.4-7.2s-3.8-2.1-6.7-2.1h-3.1V460.5z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 22 KiB |
BIN
components/freemodbus/docs/_static/modbus-data-mapping.png
vendored
Normal file
BIN
components/freemodbus/docs/_static/modbus-data-mapping.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
BIN
components/freemodbus/docs/_static/modbus-segment.png
vendored
Normal file
BIN
components/freemodbus/docs/_static/modbus-segment.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
16
components/freemodbus/docs/_static/modbus_docs_versions.js
vendored
Normal file
16
components/freemodbus/docs/_static/modbus_docs_versions.js
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
var DOCUMENTATION_VERSIONS = {
|
||||||
|
DEFAULTS: { has_targets: true,
|
||||||
|
supported_targets: [ "esp32", "esp32s2", "esp32s3", "esp32c3" ]
|
||||||
|
},
|
||||||
|
VERSIONS: [
|
||||||
|
{ name: "latest" },
|
||||||
|
{ name: "v1.0.1", old:false },
|
||||||
|
{ name: "v1.0.0", old:true }
|
||||||
|
],
|
||||||
|
IDF_TARGETS: [
|
||||||
|
{ text: "ESP32", value: "esp32"},
|
||||||
|
{ text: "ESP32-S2", value: "esp32s2"},
|
||||||
|
{ text: "ESP32-S3", value: "esp32s3"},
|
||||||
|
{ text: "ESP32-C3", value: "esp32c3"}
|
||||||
|
]
|
||||||
|
};
|
33
components/freemodbus/docs/conf_common.py
Normal file
33
components/freemodbus/docs/conf_common.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Common (non-language-specific) configuration for Sphinx
|
||||||
|
#
|
||||||
|
|
||||||
|
# type: ignore
|
||||||
|
# pylint: disable=wildcard-import
|
||||||
|
# pylint: disable=undefined-variable
|
||||||
|
|
||||||
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
|
from esp_docs.conf_docs import * # noqa: F403,F401
|
||||||
|
|
||||||
|
extensions += ['sphinx_copybutton',
|
||||||
|
# Needed as a trigger for running doxygen
|
||||||
|
'esp_docs.esp_extensions.dummy_build_system',
|
||||||
|
'esp_docs.esp_extensions.run_doxygen'
|
||||||
|
]
|
||||||
|
|
||||||
|
# link roles config
|
||||||
|
github_repo = 'espressif/esp-modbus'
|
||||||
|
|
||||||
|
# context used by sphinx_idf_theme
|
||||||
|
html_context['github_user'] = 'espressif'
|
||||||
|
html_context['github_repo'] = 'esp-modbus'
|
||||||
|
html_static_path = ['../_static']
|
||||||
|
|
||||||
|
# Extra options required by sphinx_idf_theme
|
||||||
|
project_slug = 'esp-modbus'
|
||||||
|
versions_url = './_static/modbus_docs_versions.js'
|
||||||
|
|
||||||
|
idf_targets = ['esp32', 'esp32s2', 'esp32c3']
|
||||||
|
languages = ['en']
|
@ -0,0 +1,72 @@
|
|||||||
|
Possible Communication Issues And Solutions
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
If the examples do not work as expected and slave and master boards are not able to communicate correctly, it is possible to find the reason for errors. The most important errors are described in master example output and formatted as below:
|
||||||
|
|
||||||
|
.. highlight:: none
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
E (1692332) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x107) (ESP_ERR_TIMEOUT).
|
||||||
|
|
||||||
|
|
||||||
|
.. list-table:: Table 5 Modbus error codes and troubleshooting
|
||||||
|
:widths: 5 30 65
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Error
|
||||||
|
- Description
|
||||||
|
- Possible solution
|
||||||
|
* - 0x106
|
||||||
|
- ``ESP_ERR_NOT_SUPPORTED`` - Invalid register request - slave returned an exception because the requested register is not supported.
|
||||||
|
- Refer to slave register map. Check the master data dictionary for correctness.
|
||||||
|
* - 0x107
|
||||||
|
- ``ESP_ERR_TIMEOUT`` - Slave response timeout - Modbus slave did not send response during configured slave response timeout.
|
||||||
|
- Measure and increase the maximum slave response timeout `idf.py menuconfig`, option ``CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND``.
|
||||||
|
Check physical connection or network configuration and make sure that the slave response can reach the master side.
|
||||||
|
If the application has some high performance tasks with higher priority than ``CONFIG_FMB_PORT_TASK_PRIO`` it is recommended to place Modbus tasks on the other core using an option ``CONFIG_FMB_PORT_TASK_AFFINITY``.
|
||||||
|
Configure the Modbus task's priority ``CONFIG_FMB_PORT_TASK_PRIO`` to ensure that the task gets sufficient processing time to handle Modbus stack events.
|
||||||
|
* - 0x108
|
||||||
|
- ``ESP_ERR_INVALID_RESPONSE`` - Received unsupported response from slave or frame check failure. Master can not execute command handler because the command is either not supported or is incorrect.
|
||||||
|
- Check the physical connection then refer to register map of your slave to configure the master data dictionary properly.
|
||||||
|
* - 0x103
|
||||||
|
- ``ESP_ERR_INVALID_STATE`` - Critical failure or FSM sequence failure or master FSM is busy processing previous request.
|
||||||
|
- Make sure your physical connection is working properly. Increase task stack size and check Modbus initialization sequence.
|
||||||
|
|
||||||
|
Application Example
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The examples below use the FreeModbus library port for serial TCP slave and master implementations accordingly. The selection of stack is performed through KConfig menu option "Enable Modbus stack support ..." for appropriate communication mode and related configuration keys.
|
||||||
|
|
||||||
|
.. _example_mb_slave:
|
||||||
|
|
||||||
|
- `Modbus serial slave example <https://github.com/espressif/esp-idf/tree/master/examples/protocols/modbus/serial/mb_slave>`__
|
||||||
|
|
||||||
|
.. _example_mb_master:
|
||||||
|
|
||||||
|
- `Modbus serial master example <https://github.com/espressif/esp-idf/tree/master/examples/protocols/modbus/serial/mb_master>`__
|
||||||
|
|
||||||
|
.. _example_mb_tcp_master:
|
||||||
|
|
||||||
|
- `Modbus TCP master example <https://github.com/espressif/esp-idf/tree/master/examples/protocols/modbus/tcp/mb_tcp_master>`__
|
||||||
|
|
||||||
|
.. _example_mb_tcp_slave:
|
||||||
|
|
||||||
|
- `Modbus TCP slave example <https://github.com/espressif/esp-idf/tree/master/examples/protocols/modbus/tcp/mb_tcp_slave>`__
|
||||||
|
|
||||||
|
Please refer to the specific example README.md for details.
|
||||||
|
|
||||||
|
.. _modbus_organization:
|
||||||
|
|
||||||
|
Protocol References
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- `Modbus Organization with protocol specifications <https://modbus.org/specs.php>`__
|
||||||
|
|
||||||
|
API Reference
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. include-build-file:: inc/esp_modbus_common.inc
|
||||||
|
.. include-build-file:: inc/esp_modbus_master.inc
|
||||||
|
.. include-build-file:: inc/esp_modbus_slave.inc
|
||||||
|
|
27
components/freemodbus/docs/en/conf.py
Normal file
27
components/freemodbus/docs/en/conf.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# English Language RTD & Sphinx config file
|
||||||
|
#
|
||||||
|
# Uses ../conf_common.py for most non-language-specific settings.
|
||||||
|
|
||||||
|
# Importing conf_common adds all the non-language-specific
|
||||||
|
# parts to this conf module
|
||||||
|
try:
|
||||||
|
from conf_common import * # noqa: F403,F401
|
||||||
|
except ImportError:
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.path.abspath('../'))
|
||||||
|
from conf_common import * # noqa: F403,F401
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
current_year = datetime.datetime.now().year
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'ESP-Modbus Programming Guide'
|
||||||
|
copyright = u'2019 - {}, Espressif Systems (Shanghai) Co., Ltd'.format(current_year)
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
language = 'en'
|
14
components/freemodbus/docs/en/index.rst
Normal file
14
components/freemodbus/docs/en/index.rst
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
ESP-Modbus Library
|
||||||
|
==================
|
||||||
|
|
||||||
|
An Espressif ESP-Modbus Library (esp-modbus) is a library to support Modbus communication in the networks based on RS485 or Ethernet interfaces.
|
||||||
|
The Modbus is a data communications protocol originally published by Modicon (now Schneider Electric) in 1979 for use with its programmable logic controllers (PLCs).
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
The Overview, Messaging Model And Data Mapping <overview_messaging_and_mapping>
|
||||||
|
Modbus Port Initialization <port_initialization>
|
||||||
|
Modbus Master API <master_api_overview>
|
||||||
|
Modbus Slave API <slave_api_overview>
|
||||||
|
Applications and References <applications_and_references>
|
300
components/freemodbus/docs/en/master_api_overview.rst
Normal file
300
components/freemodbus/docs/en/master_api_overview.rst
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
.. _modbus_api_master_overview:
|
||||||
|
|
||||||
|
Modbus Master API Overview
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
The following overview describes how to setup Modbus master communication. The overview reflects a typical programming workflow and is broken down into the sections provided below:
|
||||||
|
|
||||||
|
1. :ref:`modbus_api_port_initialization` - Initialization of Modbus controller interface for the selected port.
|
||||||
|
2. :ref:`modbus_api_master_configure_descriptor` - Configure data descriptors to access slave parameters.
|
||||||
|
3. :ref:`modbus_api_master_setup_communication_options` - Allows to setup communication options for selected port.
|
||||||
|
4. :ref:`modbus_api_master_start_communication` - Start stack and sending / receiving data.
|
||||||
|
5. :ref:`modbus_api_master_destroy` - Destroy Modbus controller and its resources.
|
||||||
|
|
||||||
|
.. _modbus_api_master_configure_descriptor:
|
||||||
|
|
||||||
|
Configuring Master Data Access
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The architectural approach of ESP_Modbus includes one level above standard Modbus IO driver.
|
||||||
|
The additional layer is called Modbus controller and its goal is to add an abstraction such as CID - characteristic identifier.
|
||||||
|
The CID is linked to a corresponding Modbus registers through the table called Data Dictionary and represents device physical parameter (such as temperature, humidity, etc.) in specific Modbus slave device.
|
||||||
|
This approach allows the upper layer (e.g., MESH or MQTT) to be isolated from Modbus specifics thus simplify Modbus integration with other protocols/networks.
|
||||||
|
|
||||||
|
The Data Dictionary is the list in the Modbus master which shall be defined by user to link each CID to its corresponding Modbus registers representation using Register Mapping table of the Modbus slave being used.
|
||||||
|
Each element in this data dictionary is of type :cpp:type:`mb_parameter_descriptor_t` and represents the description of one physical characteristic:
|
||||||
|
|
||||||
|
.. list-table:: Table 1 Modbus master Data Dictionary description
|
||||||
|
:widths: 8 10 82
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Field
|
||||||
|
- Description
|
||||||
|
- Detailed information
|
||||||
|
* - ``cid``
|
||||||
|
- Characteristic ID
|
||||||
|
- The identifier of characteristic (must be unique).
|
||||||
|
* - ``param_key``
|
||||||
|
- Characteristic Name
|
||||||
|
- String description of the characteristic.
|
||||||
|
* - ``param_units``
|
||||||
|
- Characteristic Units
|
||||||
|
- Physical Units of the characteristic.
|
||||||
|
* - ``mb_slave_addr``
|
||||||
|
- Modbus Slave Address
|
||||||
|
- The short address of the device with correspond parameter UID.
|
||||||
|
* - ``mb_param_type``
|
||||||
|
- Modbus Register Type
|
||||||
|
- Type of Modbus register area.
|
||||||
|
:cpp:enumerator:`MB_PARAM_INPUT`, :cpp:enumerator:`MB_PARAM_HOLDING`, :cpp:enumerator:`MB_PARAM_COIL`, :cpp:enumerator:`MB_PARAM_DISCRETE` - represents Input , Holding, Coil and Discrete input register area accordingly;
|
||||||
|
* - ``mb_reg_start``
|
||||||
|
- Modbus Register Start
|
||||||
|
- Relative register address of the characteristic in the register area.
|
||||||
|
* - ``mb_size``
|
||||||
|
- Modbus Register Size
|
||||||
|
- Length of characteristic in registers.
|
||||||
|
* - ``param_offset``
|
||||||
|
- Instance Offset
|
||||||
|
- Offset to instance of the characteristic in bytes. It is used to calculate the absolute address to the characteristic in the storage structure.
|
||||||
|
It is optional field and can be set to zero if the parameter is not used in the application.
|
||||||
|
* - ``param_type``
|
||||||
|
- Data Type
|
||||||
|
- Specifies type of the characteristic.
|
||||||
|
:cpp:enumerator:`PARAM_TYPE_U8`, :cpp:enumerator:`PARAM_TYPE_U16`, :cpp:enumerator:`PARAM_TYPE_U32` - Unsigned integer 8/16/32 bit type;
|
||||||
|
:cpp:enumerator:`PARAM_TYPE_FLOAT` - IEEE754 floating point format;
|
||||||
|
:cpp:enumerator:`PARAM_TYPE_ASCII` - ASCII string or binary data;
|
||||||
|
* - ``param_size``
|
||||||
|
- Data Size
|
||||||
|
- The storage size of the characteristic (bytes).
|
||||||
|
* - ``param_opts``
|
||||||
|
- Parameter Options
|
||||||
|
- Limits, options of characteristic used during processing of alarm in user application (optional)
|
||||||
|
* - ``access``
|
||||||
|
- Parameter access type
|
||||||
|
- Can be used in user application to define the behavior of the characteristic during processing of data in user application;
|
||||||
|
:cpp:enumerator:`PAR_PERMS_READ_WRITE_TRIGGER`, :cpp:enumerator:`PAR_PERMS_READ`, :cpp:enumerator:`PAR_PERMS_READ_WRITE_TRIGGER`;
|
||||||
|
|
||||||
|
.. note:: The ``cid`` and ``param_key`` have to be unique. Please use the prefix to the parameter key if you have several similar parameters in your register map table.
|
||||||
|
|
||||||
|
.. list-table:: Table 2 Example Register mapping table of Modbus slave
|
||||||
|
:widths: 5 5 2 10 5 5 68
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - CID
|
||||||
|
- Register
|
||||||
|
- Length
|
||||||
|
- Range
|
||||||
|
- Type
|
||||||
|
- Units
|
||||||
|
- Description
|
||||||
|
* - 0
|
||||||
|
- 30000
|
||||||
|
- 4
|
||||||
|
- MAX_UINT
|
||||||
|
- U32
|
||||||
|
- Not defined
|
||||||
|
- Serial number of device (4 bytes) read-only
|
||||||
|
* - 1
|
||||||
|
- 30002
|
||||||
|
- 2
|
||||||
|
- MAX_UINT
|
||||||
|
- U16
|
||||||
|
- Not defined
|
||||||
|
- Software version (4 bytes) read-only
|
||||||
|
* - 2
|
||||||
|
- 40000
|
||||||
|
- 4
|
||||||
|
- -20..40
|
||||||
|
- FLOAT
|
||||||
|
- DegC
|
||||||
|
- Room temperature in DegC. Writing a temperature value to this register for single point calibration.
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
// Enumeration of modbus slave addresses accessed by master device
|
||||||
|
enum {
|
||||||
|
MB_DEVICE_ADDR1 = 1,
|
||||||
|
MB_DEVICE_ADDR2,
|
||||||
|
MB_SLAVE_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
// Enumeration of all supported CIDs for device
|
||||||
|
enum {
|
||||||
|
CID_SER_NUM1 = 0,
|
||||||
|
CID_SW_VER1,
|
||||||
|
CID_TEMP_DATA_1,
|
||||||
|
CID_SER_NUM2,
|
||||||
|
CID_SW_VER2,
|
||||||
|
CID_TEMP_DATA_2
|
||||||
|
};
|
||||||
|
|
||||||
|
// Example Data Dictionary for Modbus parameters in 2 slaves in the segment
|
||||||
|
mb_parameter_descriptor_t device_parameters[] = {
|
||||||
|
// CID, Name, Units, Modbus addr, register type, Modbus Reg Start Addr, Modbus Reg read length,
|
||||||
|
// Instance offset (NA), Instance type, Instance length (bytes), Options (NA), Permissions
|
||||||
|
{ CID_SER_NUM1, STR("Serial_number_1"), STR("--"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
|
||||||
|
0, PARAM_TYPE_U32, 4, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER },
|
||||||
|
{ CID_SW_VER1, STR("Software_version_1"), STR("--"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 1,
|
||||||
|
0, PARAM_TYPE_U16, 2, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER },
|
||||||
|
{ CID_TEMP_DATA_1, STR("Temperature_1"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0, 2,
|
||||||
|
0, PARAM_TYPE_FLOAT, 4, OPTS( 16, 30, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
|
||||||
|
{ CID_SER_NUM2, STR("Serial_number_2"), STR("--"), MB_DEVICE_ADDR2, MB_PARAM_INPUT, 0, 2,
|
||||||
|
0, PARAM_TYPE_U32, 4, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER },
|
||||||
|
{ CID_SW_VER2, STR("Software_version_2"), STR("--"), MB_DEVICE_ADDR2, MB_PARAM_INPUT, 2, 1,
|
||||||
|
0, PARAM_TYPE_U16, 2, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER },
|
||||||
|
{ CID_TEMP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR2, MB_PARAM_HOLDING, 0, 2,
|
||||||
|
0, PARAM_TYPE_FLOAT, 4, OPTS( 20, 30, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
|
||||||
|
};
|
||||||
|
// Calculate number of parameters in the table
|
||||||
|
uint16_t num_device_parameters = (sizeof(device_parameters) / sizeof(device_parameters[0]));
|
||||||
|
|
||||||
|
During initialization of the Modbus stack, a pointer to the Data Dictionary (called descriptor) must be provided as the parameter of the function below.
|
||||||
|
|
||||||
|
:cpp:func:`mbc_master_set_descriptor`: Initialization of master descriptor.
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(mbc_master_set_descriptor(&device_parameters[0], num_device_parameters));
|
||||||
|
|
||||||
|
The Data Dictionary can be initialized from SD card, MQTT or other source before start of stack. Once the initialization and setup is done, the Modbus controller allows the reading of complex parameters from any slave included in descriptor table using its CID.
|
||||||
|
|
||||||
|
.. _modbus_api_master_setup_communication_options:
|
||||||
|
|
||||||
|
Master Communication Options
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Calling the setup function allows for specific communication options to be defined for port.
|
||||||
|
|
||||||
|
:cpp:func:`mbc_master_setup`
|
||||||
|
|
||||||
|
The communication structure provided as a parameter is different for serial and TCP communication mode.
|
||||||
|
|
||||||
|
Example setup for serial port:
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
mb_communication_info_t comm_info = {
|
||||||
|
.port = MB_PORT_NUM, // Serial port number
|
||||||
|
.mode = MB_MODE_RTU, // Modbus mode of communication (MB_MODE_RTU or MB_MODE_ASCII)
|
||||||
|
.baudrate = 9600, // Modbus communication baud rate
|
||||||
|
.parity = MB_PARITY_NONE // parity option for serial port
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(mbc_master_setup((void*)&comm_info));
|
||||||
|
|
||||||
|
Modbus master TCP port requires additional definition of IP address table where number of addresses should be equal to number of unique slave addresses in master Modbus Data Dictionary:
|
||||||
|
|
||||||
|
The order of IP address string corresponds to short slave address in the Data Dictionary.
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
#define MB_SLAVE_COUNT 2 // Number of slaves in the segment being accessed (as defined in Data Dictionary)
|
||||||
|
|
||||||
|
char* slave_ip_address_table[MB_SLAVE_COUNT] = {
|
||||||
|
"192.168.1.2", // Address corresponds to UID1 and set to predefined value by user
|
||||||
|
"192.168.1.3", // corresponds to UID2 in the segment
|
||||||
|
NULL // end of table
|
||||||
|
};
|
||||||
|
|
||||||
|
mb_communication_info_t comm_info = {
|
||||||
|
.ip_port = MB_TCP_PORT, // Modbus TCP port number (default = 502)
|
||||||
|
.ip_addr_type = MB_IPV4, // version of IP protocol
|
||||||
|
.ip_mode = MB_MODE_TCP, // Port communication mode
|
||||||
|
.ip_addr = (void*)slave_ip_address_table, // assign table of IP addresses
|
||||||
|
.ip_netif_ptr = esp_netif_ptr // esp_netif_ptr pointer to the corresponding network interface
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(mbc_master_setup((void*)&comm_info));
|
||||||
|
|
||||||
|
.. note:: Refer to `esp_netif component <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_netif.html>`__ for more information about network interface initialization.
|
||||||
|
|
||||||
|
The slave IP addresses in the table can be assigned automatically using mDNS service as described in the example.
|
||||||
|
Refer to :ref:`example TCP master <example_mb_tcp_master>` for more information.
|
||||||
|
|
||||||
|
.. note:: RS485 communication requires call to UART specific APIs to setup communication mode and pins. Refer to the `UART communication section <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/uart.html#uart-api-running-uart-communication>`__ in documentation.
|
||||||
|
|
||||||
|
|
||||||
|
.. _modbus_api_master_start_communication:
|
||||||
|
|
||||||
|
Master Communication
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The starting of the Modbus controller is the final step in enabling communication. This is performed using function below:
|
||||||
|
|
||||||
|
:cpp:func:`mbc_master_start`
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
esp_err_t err = mbc_master_start();
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "mb controller start fail, err=%x.", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
The list of functions below are used by the Modbus master stack from a user's application:
|
||||||
|
|
||||||
|
:cpp:func:`mbc_master_send_request`: This function executes a blocking Modbus request. The master sends a data request (as defined in parameter request structure :cpp:type:`mb_param_request_t`) and then blocks until a response from corresponding slave and returns the status of command execution. This function provides a standard way for read/write access to Modbus devices in the network.
|
||||||
|
|
||||||
|
:cpp:func:`mbc_master_get_cid_info`: The function gets information about each characteristic supported in the data dictionary and returns the characteristic's description in the form of the :cpp:type:`mb_parameter_descriptor_t` structure. Each characteristic is accessed using its CID.
|
||||||
|
|
||||||
|
:cpp:func:`mbc_master_get_parameter`: The function reads the data of a characteristic defined in the parameters of a Modbus slave device. The additional data for request is taken from parameter description table.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
const mb_parameter_descriptor_t* param_descriptor = NULL;
|
||||||
|
uint8_t temp_data[4] = {0}; // temporary buffer to hold maximum CID size
|
||||||
|
uint8_t type = 0;
|
||||||
|
....
|
||||||
|
|
||||||
|
// Get the information for characteristic cid from data dictionary
|
||||||
|
esp_err_t err = mbc_master_get_cid_info(cid, ¶m_descriptor);
|
||||||
|
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
|
||||||
|
err = mbc_master_get_parameter(param_descriptor->cid, (char*)param_descriptor->param_key, (uint8_t*)temp_data, &type);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.",
|
||||||
|
param_descriptor->cid,
|
||||||
|
(char*)param_descriptor->param_key,
|
||||||
|
(char*)param_descriptor->param_units,
|
||||||
|
*(uint32_t*)temp_data);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).",
|
||||||
|
param_descriptor->cid,
|
||||||
|
(char*)param_descriptor->param_key,
|
||||||
|
(int)err,
|
||||||
|
(char*)esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Could not get information for characteristic %d.", cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
:cpp:func:`mbc_master_set_parameter`
|
||||||
|
|
||||||
|
The function writes characteristic's value defined as a name and cid parameter in corresponded slave device. The additional data for parameter request is taken from master parameter description table.
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
uint8_t type = 0; // Type of parameter
|
||||||
|
uint8_t temp_data[4] = {0}; // temporary buffer
|
||||||
|
|
||||||
|
esp_err_t err = mbc_master_set_parameter(CID_TEMP_DATA_2, "Temperature_2", (uint8_t*)temp_data, &type);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
ESP_LOGI(TAG, "Set parameter data successfully.");
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Set data fail, err = 0x%x (%s).", (int)err, (char*)esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.. _modbus_api_master_destroy:
|
||||||
|
|
||||||
|
Modbus Master Teardown
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This function stops Modbus communication stack and destroys controller interface and free all used active objects.
|
||||||
|
|
||||||
|
:cpp:func:`mbc_master_destroy`
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(mbc_master_destroy());
|
@ -0,0 +1,47 @@
|
|||||||
|
ESP-Modbus
|
||||||
|
==========
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
The Modbus serial communication protocol is de facto standard protocol widely used to connect industrial electronic devices. Modbus allows communication among many devices connected to the same network, for example, a system that measures temperature and humidity and communicates the results to a computer. The Modbus protocol uses several types of data: Holding Registers, Input Registers, Coils (single bit output), Discrete Inputs. Versions of the Modbus protocol exist for serial port and for Ethernet and other protocols that support the Internet protocol suite. There are many variants of Modbus protocols, some of them are:
|
||||||
|
|
||||||
|
* ``Modbus RTU`` — This is used in serial communication and makes use of a compact, binary representation of the data for protocol communication. The RTU format follows the commands/data with a cyclic redundancy check checksum as an error check mechanism to ensure the reliability of data. Modbus RTU is the most common implementation available for Modbus. A Modbus RTU message must be transmitted continuously without inter-character hesitations. Modbus messages are framed (separated) by idle (silent) periods. The RS-485 interface communication is usually used for this type.
|
||||||
|
* ``Modbus ASCII`` — This is used in serial communication and makes use of ASCII characters for protocol communication. The ASCII format uses a longitudinal redundancy check checksum. Modbus ASCII messages are framed by leading colon (":") and trailing newline (CR/LF).
|
||||||
|
* ``Modbus TCP/IP or Modbus TCP`` — This is a Modbus variant used for communications over TCP/IP networks, connecting over port 502. It does not require a checksum calculation, as lower layers already provide checksum protection.
|
||||||
|
|
||||||
|
.. note:: This documentation (and included code snippets) requires some familiarity with the Modbus protocol. Refer to the Modbus Organization's with protocol specifications for specifics :ref:`modbus_organization`.
|
||||||
|
|
||||||
|
Messaging Model And Data Mapping
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Modbus is an application protocol that defines rules for messaging structure and data organization that are independent of the data transmission medium. Traditional serial Modbus is a register-based protocol that defines message transactions that occur between master(s) and slave devices (multiple masters are allowed on using Modbus TCP/IP). The slave devices listen for communication from the master and simply respond as instructed. The master(s) always controls communication and may communicate directly to one slave, or all connected slaves, but the slaves cannot communicate directly with each other.
|
||||||
|
|
||||||
|
.. figure:: ../_static/modbus-segment.png
|
||||||
|
:align: center
|
||||||
|
:scale: 80%
|
||||||
|
:alt: Modbus segment diagram
|
||||||
|
:figclass: align-center
|
||||||
|
|
||||||
|
Modbus segment diagram
|
||||||
|
|
||||||
|
.. note:: It is assumed that the number of slaves and their register maps are known by the Modbus master before the start of stack.
|
||||||
|
|
||||||
|
The register map of each slave device is usually part of its device manual. A Slave device usually permits configuration of its short slave address and communication options that are used within the device's network segment.
|
||||||
|
|
||||||
|
The Modbus protocol allows devices to map data to four types of registers (Holding, Input, Discrete, Coil). The figure below illustrates an example mapping of a device's data to the four types of registers.
|
||||||
|
|
||||||
|
.. figure:: ../_static/modbus-data-mapping.png
|
||||||
|
:align: center
|
||||||
|
:scale: 80%
|
||||||
|
:alt: Modbus data mapping
|
||||||
|
:figclass: align-center
|
||||||
|
|
||||||
|
Modbus data mapping
|
||||||
|
|
||||||
|
The following sections give an overview of how to use the ESP_Modbus component found under `components/freemodbus`. The sections cover initialization of a Modbus port, and the setup a master or slave device accordingly:
|
||||||
|
|
||||||
|
- :ref:`modbus_api_port_initialization`
|
||||||
|
- :ref:`modbus_api_slave_overview`
|
||||||
|
- :ref:`modbus_api_master_overview`
|
||||||
|
|
35
components/freemodbus/docs/en/port_initialization.rst
Normal file
35
components/freemodbus/docs/en/port_initialization.rst
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
.. _modbus_api_port_initialization:
|
||||||
|
|
||||||
|
Modbus Port Initialization
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The ESP_Modbus supports Modbus SERIAL and TCP ports and a port must be initialized before calling any other Modbus API. The functions below are used to create and then initialize Modbus controller interface (either master or slave) over a particular transmission medium (either Serial or TCP/IP):
|
||||||
|
|
||||||
|
- :cpp:func:`mbc_slave_init`
|
||||||
|
- :cpp:func:`mbc_master_init`
|
||||||
|
- :cpp:func:`mbc_slave_init_tcp`
|
||||||
|
- :cpp:func:`mbc_master_init_tcp`
|
||||||
|
|
||||||
|
The API call uses the first parameter to recognize the type of port being initialized. Supported enumeration for different ports: :cpp:enumerator:`MB_PORT_SERIAL_MASTER`, :cpp:enumerator:`MB_PORT_SERIAL_SLAVE` accordingly.
|
||||||
|
The parameters :cpp:enumerator:`MB_PORT_TCP_MASTER`, :cpp:enumerator:`MB_PORT_TCP_SLAVE` are reserved for internal usage.
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
void* master_handler = NULL; // Pointer to allocate interface structure
|
||||||
|
// Initialization of Modbus master for serial port
|
||||||
|
esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler);
|
||||||
|
if (master_handler == NULL || err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "mb controller initialization fail.");
|
||||||
|
}
|
||||||
|
|
||||||
|
This example code to initialize slave port:
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
void* slave_handler = NULL; // Pointer to allocate interface structure
|
||||||
|
// Initialization of Modbus slave for TCP
|
||||||
|
esp_err_t err = mbc_slave_init_tcp(&slave_handler);
|
||||||
|
if (slave_handler == NULL || err != ESP_OK) {
|
||||||
|
// Error handling is performed here
|
||||||
|
ESP_LOGE(TAG, "mb controller initialization fail.");
|
||||||
|
}
|
215
components/freemodbus/docs/en/slave_api_overview.rst
Normal file
215
components/freemodbus/docs/en/slave_api_overview.rst
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
.. _modbus_api_slave_overview:
|
||||||
|
|
||||||
|
Modbus Slave API Overview
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
The sections below represent typical programming workflow for the slave API which should be called in following order:
|
||||||
|
|
||||||
|
1. :ref:`modbus_api_port_initialization` - Initialization of Modbus controller interface for the selected port.
|
||||||
|
2. :ref:`modbus_api_slave_configure_descriptor` - Configure data descriptors to access slave parameters.
|
||||||
|
3. :ref:`modbus_api_slave_setup_communication_options` - Allows to setup communication options for selected port.
|
||||||
|
4. :ref:`modbus_api_slave_communication` - Start stack and sending / receiving data. Filter events when master accesses the register areas.
|
||||||
|
5. :ref:`modbus_api_slave_destroy` - Destroy Modbus controller and its resources.
|
||||||
|
|
||||||
|
.. _modbus_api_slave_configure_descriptor:
|
||||||
|
|
||||||
|
Configuring Slave Data Access
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The following functions must be called when the Modbus controller slave port is already initialized. Refer to :ref:`modbus_api_port_initialization`.
|
||||||
|
|
||||||
|
The slave stack requires the user to define structures (memory storage areas) that store the Modbus parameters accessed by stack. These structures should be prepared by the user and be assigned to the Modbus controller interface using :cpp:func:`mbc_slave_set_descriptor` API call before the start of communication. The slave task can call the :cpp:func:`mbc_slave_check_event` function which will block until the Modbus master access the slave. The slave task can then get information about the data being accessed.
|
||||||
|
|
||||||
|
.. note:: One slave can define several area descriptors per each type of Modbus register area with different start_offset.
|
||||||
|
|
||||||
|
Register area is defined by using the :cpp:type:`mb_register_area_descriptor_t` structure.
|
||||||
|
|
||||||
|
.. list-table:: Table 3 Modbus register area descriptor
|
||||||
|
:widths: 8 92
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Field
|
||||||
|
- Description
|
||||||
|
* - ``start_offset``
|
||||||
|
- Zero based register relative offset for defined register area. Example: register address = 40002 ( 4x register area - Function 3 - holding register ), start_offset = 2
|
||||||
|
* - ``type``
|
||||||
|
- Type of the Modbus register area. Refer to :cpp:type:`mb_param_type_t` for more information.
|
||||||
|
* - ``address``
|
||||||
|
- A pointer to the memory area which is used to store the register data for this area descriptor.
|
||||||
|
* - ``size``
|
||||||
|
- The size of the memory area in bytes which is used to store register data.
|
||||||
|
|
||||||
|
:cpp:func:`mbc_slave_set_descriptor`
|
||||||
|
|
||||||
|
The function initializes Modbus communication descriptors for each type of Modbus register area (Holding Registers, Input Registers, Coils (single bit output), Discrete Inputs). Once areas are initialized and the :cpp:func:`mbc_slave_start()` API is called the Modbus stack can access the data in user data structures by request from master.
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
#define MB_REG_INPUT_START_AREA0 (0)
|
||||||
|
#define MB_REG_HOLDING_START_AREA0 (0)
|
||||||
|
#define MB_REG_HOLD_CNT (100)
|
||||||
|
#define MB_REG_INPUT_CNT (100)
|
||||||
|
|
||||||
|
mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure
|
||||||
|
unit16_t holding_reg_area[MB_REG_HOLD_CNT] = {0}; // storage area for holding registers
|
||||||
|
unit16_t input_reg_area[MB_REG_INPUT_CNT] = {0}; // storage area for input registers
|
||||||
|
|
||||||
|
reg_area.type = MB_PARAM_HOLDING; // Set type of register area
|
||||||
|
reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol
|
||||||
|
reg_area.address = (void*)&holding_reg_area[0]; // Set pointer to storage instance
|
||||||
|
reg_area.size = sizeof(holding_reg_area) << 1; // Set the size of register storage area in bytes
|
||||||
|
ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
|
||||||
|
|
||||||
|
reg_area.type = MB_PARAM_INPUT;
|
||||||
|
reg_area.start_offset = MB_REG_INPUT_START_AREA0;
|
||||||
|
reg_area.address = (void*)&input_reg_area[0];
|
||||||
|
reg_area.size = sizeof(input_reg_area) << 1;
|
||||||
|
ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
|
||||||
|
|
||||||
|
|
||||||
|
At least one area descriptor per each Modbus register type must be set in order to provide register access to its area. If the master tries to access an undefined area, the stack will generate a Modbus exception.
|
||||||
|
|
||||||
|
Direct access to register area from user application must be protected by critical section:
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
portENTER_CRITICAL(¶m_lock);
|
||||||
|
holding_reg_area[2] += 10;
|
||||||
|
portEXIT_CRITICAL(¶m_lock);
|
||||||
|
|
||||||
|
|
||||||
|
.. _modbus_api_slave_setup_communication_options:
|
||||||
|
|
||||||
|
Slave Communication Options
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The function initializes the Modbus controller interface and its active context (tasks, RTOS objects and other resources).
|
||||||
|
|
||||||
|
:cpp:func:`mbc_slave_setup`
|
||||||
|
|
||||||
|
The function is used to setup communication parameters of the Modbus stack.
|
||||||
|
|
||||||
|
Example initialization of Modbus TCP communication:
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
esp_netif_init();
|
||||||
|
...
|
||||||
|
|
||||||
|
mb_communication_info_t comm_info = {
|
||||||
|
.ip_port = MB_TCP_PORT, // Modbus TCP port number (default = 502)
|
||||||
|
.ip_addr_type = MB_IPV4, // version of IP protocol
|
||||||
|
.ip_mode = MB_MODE_TCP, // Port communication mode
|
||||||
|
.ip_addr = NULL, // This field keeps the client IP address to bind, NULL - bind to any client
|
||||||
|
.ip_netif_ptr = esp_netif_ptr // esp_netif_ptr - pointer to the corresponding network interface
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup communication parameters and start stack
|
||||||
|
ESP_ERROR_CHECK(mbc_slave_setup((void*)&comm_info));
|
||||||
|
|
||||||
|
Example initialization of Modbus serial communication:
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
#define MB_SLAVE_DEV_SPEED 9600
|
||||||
|
#define MB_SLAVE_ADDR 1
|
||||||
|
#define MB_SLAVE_PORT_NUM 2
|
||||||
|
...
|
||||||
|
|
||||||
|
// Setup communication parameters and start stack
|
||||||
|
mb_communication_info_t comm_info = {
|
||||||
|
.mode = MB_MODE_RTU, // Communication type
|
||||||
|
.slave_addr = MB_SLAVE_ADDR, // Short address of the slave
|
||||||
|
.port = MB_SLAVE_PORT_NUM, // UART physical port number
|
||||||
|
.baudrate = MB_SLAVE_DEV_SPEED, // Baud rate for communication
|
||||||
|
.parity = MB_PARITY_NONE // Parity option
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(mbc_slave_setup((void*)&comm_info));
|
||||||
|
|
||||||
|
.. _modbus_api_slave_communication:
|
||||||
|
|
||||||
|
Slave Communication
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The function below is used to start Modbus controller interface and allows communication.
|
||||||
|
|
||||||
|
:cpp:func:`mbc_slave_start`
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(mbc_slave_start());
|
||||||
|
|
||||||
|
:cpp:func:`mbc_slave_check_event`
|
||||||
|
|
||||||
|
The blocking call to function waits for a event specified (represented as an event mask parameter). Once the master accesses the parameter and the event mask matches the parameter type, the application task will be unblocked and function will return the corresponding event :cpp:type:`mb_event_group_t` which describes the type of register access being done.
|
||||||
|
|
||||||
|
:cpp:func:`mbc_slave_get_param_info`
|
||||||
|
|
||||||
|
The function gets information about accessed parameters from the Modbus controller event queue. The KConfig ``CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE`` key can be used to configure the notification queue size. The timeout parameter allows a timeout to be specified when waiting for a notification. The :cpp:type:`mb_param_info_t` structure contains information about accessed parameter.
|
||||||
|
|
||||||
|
.. list-table:: Table 4 Description of the register info structure: :cpp:type:`mb_param_info_t`
|
||||||
|
:widths: 10 90
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Field
|
||||||
|
- Description
|
||||||
|
* - ``time_stamp``
|
||||||
|
- the time stamp of the event when defined parameter is accessed
|
||||||
|
* - ``mb_offset``
|
||||||
|
- start Modbus register accessed by master
|
||||||
|
* - ``type``
|
||||||
|
- type of the Modbus register area being accessed (See the :cpp:type:`mb_event_group_t` for more information)
|
||||||
|
* - ``address``
|
||||||
|
- memory address that corresponds to accessed register in defined area descriptor
|
||||||
|
* - ``size``
|
||||||
|
- number of registers being accessed by master
|
||||||
|
|
||||||
|
Example to get event when holding or input registers accessed in the slave:
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
#define MB_READ_MASK (MB_EVENT_INPUT_REG_RD | MB_EVENT_HOLDING_REG_RD)
|
||||||
|
#define MB_WRITE_MASK (MB_EVENT_HOLDING_REG_WR)
|
||||||
|
#define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK)
|
||||||
|
#define MB_PAR_INFO_GET_TOUT (10 / portTICK_RATE_MS)
|
||||||
|
....
|
||||||
|
|
||||||
|
// The function blocks while waiting for register access
|
||||||
|
mb_event_group_t event = mbc_slave_check_event(MB_READ_WRITE_MASK);
|
||||||
|
|
||||||
|
// Get information about data accessed from master
|
||||||
|
ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT));
|
||||||
|
const char* rw_str = (event & MB_READ_MASK) ? "READ" : "WRITE";
|
||||||
|
|
||||||
|
// Filter events and process them accordingly
|
||||||
|
if (event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) {
|
||||||
|
ESP_LOGI(TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u",
|
||||||
|
rw_str,
|
||||||
|
(uint32_t)reg_info.time_stamp,
|
||||||
|
(uint32_t)reg_info.mb_offset,
|
||||||
|
(uint32_t)reg_info.type,
|
||||||
|
(uint32_t)reg_info.address,
|
||||||
|
(uint32_t)reg_info.size);
|
||||||
|
} else if (event & (MB_EVENT_INPUT_REG_RD)) {
|
||||||
|
ESP_LOGI(TAG, "INPUT %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u",
|
||||||
|
rw_str,
|
||||||
|
(uint32_t)reg_info.time_stamp,
|
||||||
|
(uint32_t)reg_info.mb_offset,
|
||||||
|
(uint32_t)reg_info.type,
|
||||||
|
(uint32_t)reg_info.address,
|
||||||
|
(uint32_t)reg_info.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.. _modbus_api_slave_destroy:
|
||||||
|
|
||||||
|
Modbus Slave Teardown
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This function stops the Modbus communication stack, destroys the controller interface, and frees all used active objects allocated for the slave.
|
||||||
|
|
||||||
|
:cpp:func:`mbc_slave_destroy`
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(mbc_slave_destroy());
|
1
components/freemodbus/docs/requirements.txt
Normal file
1
components/freemodbus/docs/requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
esp-docs==0.2.4
|
18
components/freemodbus/docs/utils.sh
Normal file
18
components/freemodbus/docs/utils.sh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Bash helper functions for adding SSH keys
|
||||||
|
|
||||||
|
function add_ssh_keys() {
|
||||||
|
local key_string="${1}"
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
chmod 700 ~/.ssh
|
||||||
|
echo -n "${key_string}" >~/.ssh/id_rsa_base64
|
||||||
|
base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 >~/.ssh/id_rsa
|
||||||
|
chmod 600 ~/.ssh/id_rsa
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_doc_server_ssh_keys() {
|
||||||
|
local key_string="${1}"
|
||||||
|
local server_url="${2}"
|
||||||
|
local server_user="${3}"
|
||||||
|
add_ssh_keys "${key_string}"
|
||||||
|
echo -e "Host ${server_url}\n\tStrictHostKeyChecking no\n\tUser ${server_user}\n" >>~/.ssh/config
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Stack callback functions prototypes
|
||||||
|
|
||||||
|
#ifndef _ESP_MODBUS_CALLBACKS_H_
|
||||||
|
#define _ESP_MODBUS_CALLBACKS_H_
|
||||||
|
|
||||||
|
#include "mb.h"
|
||||||
|
#include "mb_m.h"
|
||||||
|
|
||||||
|
typedef eMBErrorCode (*reg_input_cb)(UCHAR*, USHORT, USHORT);
|
||||||
|
typedef eMBErrorCode (*reg_holding_cb)(UCHAR*, USHORT, USHORT, eMBRegisterMode);
|
||||||
|
typedef eMBErrorCode (*reg_coils_cb)(UCHAR*, USHORT, USHORT, eMBRegisterMode);
|
||||||
|
typedef eMBErrorCode (*reg_discrete_cb)(UCHAR*, USHORT, USHORT);
|
||||||
|
|
||||||
|
#endif /* _ESP_MODBUS_CALLBACKS_H_ */
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "esp_err.h" // for esp_err_t
|
#include "esp_err.h" // for esp_err_t
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "esp_err.h" // for esp_err_t
|
#include "esp_err.h" // for esp_err_t
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "esp_err.h" // for esp_err_t
|
||||||
|
#include "esp_modbus_master.h" // for public interface defines
|
||||||
|
#include "mbc_tcp_master.h" // for public interface defines
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization of Modbus TCP Master controller interface
|
||||||
|
*/
|
||||||
|
esp_err_t mbc_master_init_tcp(void** handler)
|
||||||
|
{
|
||||||
|
void* port_handler = NULL;
|
||||||
|
esp_err_t error = mbc_tcp_master_create(&port_handler);
|
||||||
|
|
||||||
|
if ((port_handler != NULL) && (error == ESP_OK)) {
|
||||||
|
mbc_master_init_iface(port_handler);
|
||||||
|
*handler = port_handler;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "esp_err.h" // for esp_err_t
|
#include "esp_err.h" // for esp_err_t
|
||||||
@ -78,7 +69,7 @@ static void mbc_slave_free_descriptors(void) {
|
|||||||
mb_slave_options_t* mbs_opts = &slave_interface_ptr->opts;
|
mb_slave_options_t* mbs_opts = &slave_interface_ptr->opts;
|
||||||
|
|
||||||
for (int descr_type = 0; descr_type < MB_PARAM_COUNT; descr_type++) {
|
for (int descr_type = 0; descr_type < MB_PARAM_COUNT; descr_type++) {
|
||||||
for (it = LIST_FIRST(&mbs_opts->mbs_area_descriptors[descr_type]); it != NULL; it = LIST_NEXT(it, entries)) {
|
while ((it = LIST_FIRST(&mbs_opts->mbs_area_descriptors[descr_type]))) {
|
||||||
LIST_REMOVE(it, entries);
|
LIST_REMOVE(it, entries);
|
||||||
free(it);
|
free(it);
|
||||||
}
|
}
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "esp_err.h" // for esp_err_t
|
#include "esp_err.h" // for esp_err_t
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "esp_err.h" // for esp_err_t
|
||||||
|
#include "esp_modbus_slave.h" // for public slave defines
|
||||||
|
#include "mbc_tcp_slave.h" // for public interface defines
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization of Modbus TCP Slave controller
|
||||||
|
*/
|
||||||
|
esp_err_t mbc_slave_init_tcp(void** handler)
|
||||||
|
{
|
||||||
|
void* port_handler = NULL;
|
||||||
|
esp_err_t error = mbc_tcp_slave_create(&port_handler);
|
||||||
|
|
||||||
|
if ((port_handler != NULL) && (error == ESP_OK)) {
|
||||||
|
mbc_slave_init_iface(port_handler);
|
||||||
|
*handler = port_handler;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MB_IFACE_COMMON_H
|
#ifndef _MB_IFACE_COMMON_H
|
||||||
@ -24,6 +15,7 @@ extern "C" {
|
|||||||
|
|
||||||
#if __has_include("esp_check.h")
|
#if __has_include("esp_check.h")
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
#define MB_RETURN_ON_FALSE(a, err_code, tag, format, ...) ESP_RETURN_ON_FALSE(a, err_code, tag, format __VA_OPT__(,) __VA_ARGS__)
|
#define MB_RETURN_ON_FALSE(a, err_code, tag, format, ...) ESP_RETURN_ON_FALSE(a, err_code, tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||||
|
|
||||||
@ -44,10 +36,10 @@ extern "C" {
|
|||||||
#define MB_CONTROLLER_PRIORITY (CONFIG_FMB_PORT_TASK_PRIO - 1) // priority of MB controller task
|
#define MB_CONTROLLER_PRIORITY (CONFIG_FMB_PORT_TASK_PRIO - 1) // priority of MB controller task
|
||||||
|
|
||||||
// Default port defines
|
// Default port defines
|
||||||
#define MB_DEVICE_ADDRESS (1) // Default slave device address in Modbus
|
#define MB_DEVICE_ADDRESS (1) // Default slave device address in Modbus
|
||||||
#define MB_DEVICE_SPEED (115200) // Default Modbus speed for now hard defined
|
#define MB_DEVICE_SPEED (115200) // Default Modbus speed for now hard defined
|
||||||
#define MB_UART_PORT (UART_NUM_MAX - 1) // Default UART port number
|
#define MB_UART_PORT (UART_NUM_MAX - 1) // Default UART port number
|
||||||
#define MB_PAR_INFO_TOUT (10) // Timeout for get parameter info
|
#define MB_PAR_INFO_TOUT (10) // Timeout for get parameter info
|
||||||
#define MB_PARITY_NONE (UART_PARITY_DISABLE)
|
#define MB_PARITY_NONE (UART_PARITY_DISABLE)
|
||||||
|
|
||||||
// The Macros below handle the endianness while transfer N byte data into buffer
|
// The Macros below handle the endianness while transfer N byte data into buffer
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ESP_MB_MASTER_INTERFACE_H
|
#ifndef _ESP_MB_MASTER_INTERFACE_H
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ESP_MB_SLAVE_INTERFACE_H
|
#ifndef _ESP_MB_SLAVE_INTERFACE_H
|
@ -1,17 +1,8 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
*/
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
// mbcontroller.h
|
// mbcontroller.h
|
||||||
// mbcontroller - common Modbus controller header file
|
// mbcontroller - common Modbus controller header file
|
||||||
|
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MB_CONTROLLER_MASTER_H
|
#ifndef _MB_CONTROLLER_MASTER_H
|
@ -1,17 +1,9 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MB_CONTROLLER_SLAVE_H
|
#ifndef _MB_CONTROLLER_SLAVE_H
|
||||||
#define _MB_CONTROLLER_SLAVE_H
|
#define _MB_CONTROLLER_SLAVE_H
|
||||||
|
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
||||||
@ -144,26 +151,33 @@ eMBErrorCode
|
|||||||
eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
||||||
{
|
{
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
UCHAR *pucMBASCIIFrame = ( UCHAR* ) ucASCIIBuf;
|
||||||
|
USHORT usFrameLength = usRcvBufferPos;
|
||||||
|
|
||||||
|
if( xMBPortSerialGetRequest( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
||||||
|
{
|
||||||
|
return MB_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
ENTER_CRITICAL_SECTION( );
|
ENTER_CRITICAL_SECTION( );
|
||||||
assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
|
assert( usFrameLength < MB_SER_PDU_SIZE_MAX );
|
||||||
|
|
||||||
/* Length and CRC check */
|
/* Length and CRC check */
|
||||||
if( ( usRcvBufferPos >= MB_ASCII_SER_PDU_SIZE_MIN )
|
if( ( usFrameLength >= MB_ASCII_SER_PDU_SIZE_MIN )
|
||||||
&& ( prvucMBLRC( ( UCHAR * ) ucASCIIBuf, usRcvBufferPos ) == 0 ) )
|
&& ( prvucMBLRC( ( UCHAR * ) pucMBASCIIFrame, usFrameLength ) == 0 ) )
|
||||||
{
|
{
|
||||||
/* Save the address field. All frames are passed to the upper layed
|
/* Save the address field. All frames are passed to the upper layed
|
||||||
* and the decision if a frame is used is done there.
|
* and the decision if a frame is used is done there.
|
||||||
*/
|
*/
|
||||||
*pucRcvAddress = ucASCIIBuf[MB_SER_PDU_ADDR_OFF];
|
*pucRcvAddress = pucMBASCIIFrame[MB_SER_PDU_ADDR_OFF];
|
||||||
|
|
||||||
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
|
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
|
||||||
* size of address field and CRC checksum.
|
* size of address field and CRC checksum.
|
||||||
*/
|
*/
|
||||||
*pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
|
*pusLength = ( USHORT )( usFrameLength - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
|
||||||
|
|
||||||
/* Return the start of the Modbus PDU to the caller. */
|
/* Return the start of the Modbus PDU to the caller. */
|
||||||
*pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF];
|
*pucFrame = ( UCHAR * ) & pucMBASCIIFrame[MB_SER_PDU_PDU_OFF];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -179,13 +193,14 @@ eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
|
|||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
UCHAR usLRC;
|
UCHAR usLRC;
|
||||||
|
|
||||||
ENTER_CRITICAL_SECTION( );
|
|
||||||
/* Check if the receiver is still in idle state. If not we where too
|
/* Check if the receiver is still in idle state. If not we where too
|
||||||
* slow with processing the received frame and the master sent another
|
* slow with processing the received frame and the master sent another
|
||||||
* frame on the network. We have to abort sending the frame.
|
* frame on the network. We have to abort sending the frame.
|
||||||
*/
|
*/
|
||||||
if( eRcvState == STATE_RX_IDLE )
|
if( eRcvState == STATE_RX_IDLE )
|
||||||
{
|
{
|
||||||
|
ENTER_CRITICAL_SECTION( );
|
||||||
/* First byte before the Modbus-PDU is the slave address. */
|
/* First byte before the Modbus-PDU is the slave address. */
|
||||||
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
|
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
|
||||||
usSndBufferCount = 1;
|
usSndBufferCount = 1;
|
||||||
@ -200,6 +215,13 @@ eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
|
|||||||
|
|
||||||
/* Activate the transmitter. */
|
/* Activate the transmitter. */
|
||||||
eSndState = STATE_TX_START;
|
eSndState = STATE_TX_START;
|
||||||
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
|
||||||
|
if ( xMBPortSerialSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
||||||
|
{
|
||||||
|
eStatus = MB_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
vMBPortSerialEnable( FALSE, TRUE );
|
vMBPortSerialEnable( FALSE, TRUE );
|
||||||
}
|
}
|
||||||
else
|
else
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
||||||
@ -149,30 +154,35 @@ eMBErrorCode
|
|||||||
eMBMasterASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
eMBMasterASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
||||||
{
|
{
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
UCHAR *pucMBASCIIFrame = ( UCHAR* ) ucMasterASCIIRcvBuf;
|
||||||
|
USHORT usFrameLength = usMasterRcvBufferPos;
|
||||||
|
|
||||||
|
if( xMBMasterPortSerialGetResponse( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
||||||
|
{
|
||||||
|
return MB_EIO;
|
||||||
|
}
|
||||||
ENTER_CRITICAL_SECTION( );
|
ENTER_CRITICAL_SECTION( );
|
||||||
assert( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX );
|
assert( usFrameLength < MB_SER_PDU_SIZE_MAX );
|
||||||
|
|
||||||
|
assert( pucMBASCIIFrame );
|
||||||
/* Length and CRC check */
|
/* Length and CRC check */
|
||||||
if( ( usMasterRcvBufferPos >= MB_ASCII_SER_PDU_SIZE_MIN )
|
if( ( usFrameLength >= MB_ASCII_SER_PDU_SIZE_MIN )
|
||||||
&& ( prvucMBLRC( ( UCHAR * ) ucMasterASCIIRcvBuf, usMasterRcvBufferPos ) == 0 ) )
|
&& ( prvucMBLRC( ( UCHAR * ) pucMBASCIIFrame, usFrameLength ) == 0 ) )
|
||||||
{
|
{
|
||||||
/* Save the address field. All frames are passed to the upper layed
|
/* Save the address field. All frames are passed to the upper layed
|
||||||
* and the decision if a frame is used is done there.
|
* and the decision if a frame is used is done there.
|
||||||
*/
|
*/
|
||||||
*pucRcvAddress = ucMasterASCIIRcvBuf[MB_SER_PDU_ADDR_OFF];
|
*pucRcvAddress = pucMBASCIIFrame[MB_SER_PDU_ADDR_OFF];
|
||||||
|
|
||||||
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
|
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
|
||||||
* size of address field and CRC checksum.
|
* size of address field and CRC checksum.
|
||||||
*/
|
*/
|
||||||
*pusLength = ( USHORT )( usMasterRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
|
*pusLength = ( USHORT )( usFrameLength - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
|
||||||
|
|
||||||
/* Return the start of the Modbus PDU to the caller. */
|
/* Return the start of the Modbus PDU to the caller. */
|
||||||
*pucFrame = ( UCHAR * ) & ucMasterASCIIRcvBuf[MB_SER_PDU_PDU_OFF];
|
*pucFrame = ( UCHAR * ) & pucMBASCIIFrame[MB_SER_PDU_PDU_OFF];
|
||||||
}
|
} else {
|
||||||
else
|
eStatus = MB_EIO;
|
||||||
{
|
|
||||||
eStatus = MB_EIO;
|
|
||||||
}
|
}
|
||||||
EXIT_CRITICAL_SECTION( );
|
EXIT_CRITICAL_SECTION( );
|
||||||
return eStatus;
|
return eStatus;
|
||||||
@ -186,13 +196,13 @@ eMBMasterASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLengt
|
|||||||
|
|
||||||
if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL;
|
if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL;
|
||||||
|
|
||||||
ENTER_CRITICAL_SECTION( );
|
|
||||||
/* Check if the receiver is still in idle state. If not we where too
|
/* Check if the receiver is still in idle state. If not we where too
|
||||||
* slow with processing the received frame and the master sent another
|
* slow with processing the received frame and the master sent another
|
||||||
* frame on the network. We have to abort sending the frame.
|
* frame on the network. We have to abort sending the frame.
|
||||||
*/
|
*/
|
||||||
if(eRcvState == STATE_M_RX_IDLE)
|
if(eRcvState == STATE_M_RX_IDLE)
|
||||||
{
|
{
|
||||||
|
ENTER_CRITICAL_SECTION( );
|
||||||
/* First byte before the Modbus-PDU is the slave address. */
|
/* First byte before the Modbus-PDU is the slave address. */
|
||||||
pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1;
|
pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1;
|
||||||
usMasterSndBufferCount = 1;
|
usMasterSndBufferCount = 1;
|
||||||
@ -203,17 +213,22 @@ eMBMasterASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLengt
|
|||||||
|
|
||||||
/* Calculate LRC checksum for Modbus-Serial-Line-PDU. */
|
/* Calculate LRC checksum for Modbus-Serial-Line-PDU. */
|
||||||
usLRC = prvucMBLRC( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount );
|
usLRC = prvucMBLRC( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount );
|
||||||
ucMasterASCIISndBuf[usMasterSndBufferCount++] = usLRC;
|
pucMasterSndBufferCur[usMasterSndBufferCount++] = usLRC;
|
||||||
|
|
||||||
/* Activate the transmitter. */
|
/* Activate the transmitter. */
|
||||||
eSndState = STATE_M_TX_START;
|
eSndState = STATE_M_TX_START;
|
||||||
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
|
||||||
|
if ( xMBMasterPortSerialSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
||||||
|
{
|
||||||
|
eStatus = MB_EIO;
|
||||||
|
}
|
||||||
vMBMasterPortSerialEnable( FALSE, TRUE );
|
vMBMasterPortSerialEnable( FALSE, TRUE );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
eStatus = MB_EIO;
|
eStatus = MB_EIO;
|
||||||
}
|
}
|
||||||
EXIT_CRITICAL_SECTION( );
|
|
||||||
return eStatus;
|
return eStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +437,8 @@ xMBMasterASCIITransmitFSM( void )
|
|||||||
/* Notify the task which called eMBMasterASCIISend that the frame has
|
/* Notify the task which called eMBMasterASCIISend that the frame has
|
||||||
* been sent. */
|
* been sent. */
|
||||||
case STATE_M_TX_NOTIFY:
|
case STATE_M_TX_NOTIFY:
|
||||||
xFrameIsBroadcast = ( ucMasterASCIISndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE;
|
xFrameIsBroadcast = ( ucMasterASCIISndBuf[MB_SEND_BUF_PDU_OFF - MB_SER_PDU_PDU_OFF]
|
||||||
|
== MB_ADDRESS_BROADCAST ) ? TRUE : FALSE;
|
||||||
vMBMasterRequestSetType( xFrameIsBroadcast );
|
vMBMasterRequestSetType( xFrameIsBroadcast );
|
||||||
eSndState = STATE_M_TX_XFWR;
|
eSndState = STATE_M_TX_XFWR;
|
||||||
/* If the frame is broadcast ,master will enable timer of convert delay,
|
/* If the frame is broadcast ,master will enable timer of convert delay,
|
||||||
@ -442,7 +458,7 @@ xMBMasterASCIITransmitFSM( void )
|
|||||||
return xNeedPoll;
|
return xNeedPoll;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL MB_PORT_ISR_ATTR
|
||||||
xMBMasterASCIITimerT1SExpired( void )
|
xMBMasterASCIITimerT1SExpired( void )
|
||||||
{
|
{
|
||||||
BOOL xNeedPoll = FALSE;
|
BOOL xNeedPoll = FALSE;
|
||||||
@ -452,7 +468,6 @@ xMBMasterASCIITimerT1SExpired( void )
|
|||||||
/* Timer t35 expired. Startup phase is finished. */
|
/* Timer t35 expired. Startup phase is finished. */
|
||||||
case STATE_M_RX_INIT:
|
case STATE_M_RX_INIT:
|
||||||
xNeedPoll = xMBMasterPortEventPost(EV_MASTER_READY);
|
xNeedPoll = xMBMasterPortEventPost(EV_MASTER_READY);
|
||||||
ESP_EARLY_LOGI("xMBMasterASCIITimerT1SExpired", "RX_INIT_EXPIRED");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Start of message is not received during respond timeout.
|
/* Start of message is not received during respond timeout.
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2013 Armink
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2013 Armink
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
@ -28,8 +35,6 @@
|
|||||||
* File: $Id: mbfuncdisc_m.c,v 1.60 2013/10/15 8:48:20 Armink Add Master Functions Exp $
|
* File: $Id: mbfuncdisc_m.c,v 1.60 2013/10/15 8:48:20 Armink Add Master Functions Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------- System includes ----------------------------------*/
|
/* ----------------------- System includes ----------------------------------*/
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2013 Armink
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2013 Armink
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2013 Armink
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
@ -401,6 +408,7 @@ BOOL xMBMasterRequestIsBroadcast( void );
|
|||||||
eMBMasterErrorEventType eMBMasterGetErrorType( void );
|
eMBMasterErrorEventType eMBMasterGetErrorType( void );
|
||||||
void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
|
void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
|
||||||
eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );
|
eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );
|
||||||
|
eMBMode ucMBMasterGetCommMode( void );
|
||||||
|
|
||||||
/* ----------------------- Callback -----------------------------------------*/
|
/* ----------------------- Callback -----------------------------------------*/
|
||||||
|
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
||||||
@ -34,6 +41,10 @@
|
|||||||
|
|
||||||
#include "sdkconfig.h" // for KConfig options
|
#include "sdkconfig.h" // for KConfig options
|
||||||
|
|
||||||
|
#if __has_include("esp_idf_version.h")
|
||||||
|
#include "esp_idf_version.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
PR_BEGIN_EXTERN_C
|
PR_BEGIN_EXTERN_C
|
||||||
#endif
|
#endif
|
||||||
@ -66,6 +77,15 @@ PR_BEGIN_EXTERN_C
|
|||||||
#error "None of Modbus communication mode is enabled. Please enable one of (ASCII, RTU, TCP) mode in Kconfig."
|
#error "None of Modbus communication mode is enabled. Please enable one of (ASCII, RTU, TCP) mode in Kconfig."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ESP_IDF_VERSION
|
||||||
|
|
||||||
|
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0))
|
||||||
|
// Features supported from 4.4
|
||||||
|
#define MB_TIMER_SUPPORTS_ISR_DISPATCH_METHOD 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! \brief This option defines the number of data bits per ASCII character.
|
/*! \brief This option defines the number of data bits per ASCII character.
|
||||||
*
|
*
|
||||||
* A parity bit is added before the stop bit which keeps the actual byte size at 10 bits.
|
* A parity bit is added before the stop bit which keeps the actual byte size at 10 bits.
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
||||||
@ -80,6 +87,12 @@ PR_BEGIN_EXTERN_C
|
|||||||
#define MB_TCP_UID 6
|
#define MB_TCP_UID 6
|
||||||
#define MB_TCP_FUNC 7
|
#define MB_TCP_FUNC 7
|
||||||
|
|
||||||
|
#if MB_MASTER_TCP_ENABLED
|
||||||
|
#define MB_SEND_BUF_PDU_OFF MB_TCP_FUNC
|
||||||
|
#else
|
||||||
|
#define MB_SEND_BUF_PDU_OFF MB_SER_PDU_PDU_OFF
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MB_TCP_PSEUDO_ADDRESS 255
|
#define MB_TCP_PSEUDO_ADDRESS 255
|
||||||
|
|
||||||
/* ----------------------- Prototypes 0-------------------------------------*/
|
/* ----------------------- Prototypes 0-------------------------------------*/
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
||||||
@ -138,6 +145,10 @@ BOOL xMBPortSerialGetByte( CHAR * pucByte );
|
|||||||
|
|
||||||
BOOL xMBPortSerialPutByte( CHAR ucByte );
|
BOOL xMBPortSerialPutByte( CHAR ucByte );
|
||||||
|
|
||||||
|
BOOL xMBPortSerialGetRequest( UCHAR **ppucMBSerialFrame, USHORT * pusSerialLength ) __attribute__ ((weak));
|
||||||
|
|
||||||
|
BOOL xMBPortSerialSendResponse( UCHAR *pucMBSerialFrame, USHORT usSerialLength ) __attribute__ ((weak));
|
||||||
|
|
||||||
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED
|
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED
|
||||||
BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
|
BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
|
||||||
UCHAR ucDataBits, eMBParity eParity );
|
UCHAR ucDataBits, eMBParity eParity );
|
||||||
@ -151,6 +162,13 @@ void vMBMasterPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable );
|
|||||||
BOOL xMBMasterPortSerialGetByte( CHAR * pucByte );
|
BOOL xMBMasterPortSerialGetByte( CHAR * pucByte );
|
||||||
|
|
||||||
BOOL xMBMasterPortSerialPutByte( CHAR ucByte );
|
BOOL xMBMasterPortSerialPutByte( CHAR ucByte );
|
||||||
|
|
||||||
|
BOOL xMBMasterPortSerialGetResponse( UCHAR **ppucMBSerialFrame, USHORT * usSerialLength );
|
||||||
|
|
||||||
|
BOOL xMBMasterPortSerialSendRequest( UCHAR *pucMBSerialFrame, USHORT usSerialLength );
|
||||||
|
|
||||||
|
void vMBMasterRxFlush( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ----------------------- Timers functions ---------------------------------*/
|
/* ----------------------- Timers functions ---------------------------------*/
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2013 Armink
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
@ -63,18 +70,18 @@
|
|||||||
|
|
||||||
/* ----------------------- Static variables ---------------------------------*/
|
/* ----------------------- Static variables ---------------------------------*/
|
||||||
|
|
||||||
static UCHAR ucMBMasterDestAddress;
|
static UCHAR ucMBMasterDestAddress;
|
||||||
static BOOL xMBRunInMasterMode = FALSE;
|
static BOOL xMBRunInMasterMode = FALSE;
|
||||||
static volatile eMBMasterErrorEventType eMBMasterCurErrorType;
|
static volatile eMBMasterErrorEventType eMBMasterCurErrorType;
|
||||||
static volatile USHORT usMasterSendPDULength;
|
static volatile USHORT usMasterSendPDULength;
|
||||||
static volatile eMBMode eMBMasterCurrentMode;
|
static volatile eMBMode eMBMasterCurrentMode;
|
||||||
|
|
||||||
/*------------------------ Shared variables ---------------------------------*/
|
/*------------------------ Shared variables ---------------------------------*/
|
||||||
|
|
||||||
volatile UCHAR ucMasterSndBuf[MB_SERIAL_BUF_SIZE];
|
volatile UCHAR ucMasterSndBuf[MB_SERIAL_BUF_SIZE];
|
||||||
volatile UCHAR ucMasterRcvBuf[MB_SERIAL_BUF_SIZE];
|
volatile UCHAR ucMasterRcvBuf[MB_SERIAL_BUF_SIZE];
|
||||||
volatile eMBMasterTimerMode eMasterCurTimerMode;
|
volatile eMBMasterTimerMode eMasterCurTimerMode;
|
||||||
volatile BOOL xFrameIsBroadcast = FALSE;
|
volatile BOOL xFrameIsBroadcast = FALSE;
|
||||||
|
|
||||||
static enum
|
static enum
|
||||||
{
|
{
|
||||||
@ -145,7 +152,7 @@ static xMBFunctionHandler xMasterFuncHandlers[MB_FUNC_HANDLERS_MAX] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* ----------------------- Start implementation -----------------------------*/
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
#if MB_MASTER_TCP_ENABLED > 0
|
#if MB_MASTER_TCP_ENABLED
|
||||||
eMBErrorCode
|
eMBErrorCode
|
||||||
eMBMasterTCPInit( USHORT ucTCPPort )
|
eMBMasterTCPInit( USHORT ucTCPPort )
|
||||||
{
|
{
|
||||||
@ -303,11 +310,13 @@ eMBMasterDisable( void )
|
|||||||
eMBErrorCode
|
eMBErrorCode
|
||||||
eMBMasterPoll( void )
|
eMBMasterPoll( void )
|
||||||
{
|
{
|
||||||
static UCHAR *ucMBFrame = NULL;
|
static UCHAR *ucMBSendFrame = NULL;
|
||||||
|
static UCHAR *ucMBRcvFrame = NULL;
|
||||||
static UCHAR ucRcvAddress;
|
static UCHAR ucRcvAddress;
|
||||||
static UCHAR ucFunctionCode;
|
static UCHAR ucFunctionCode;
|
||||||
static USHORT usLength;
|
static USHORT usLength;
|
||||||
static eMBException eException;
|
static eMBException eException;
|
||||||
|
static BOOL xTransactionIsActive = FALSE;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
@ -333,49 +342,61 @@ eMBMasterPoll( void )
|
|||||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) {
|
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) {
|
||||||
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_FRAME_TRANSMIT", __func__);
|
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_FRAME_TRANSMIT", __func__);
|
||||||
/* Master is busy now. */
|
/* Master is busy now. */
|
||||||
vMBMasterGetPDUSndBuf( &ucMBFrame );
|
vMBMasterGetPDUSndBuf( &ucMBSendFrame );
|
||||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
||||||
eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() );
|
eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBSendFrame, usMBMasterGetPDUSndLength() );
|
||||||
if (eStatus != MB_ENOERR)
|
if (eStatus != MB_ENOERR)
|
||||||
{
|
{
|
||||||
|
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
|
||||||
|
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
|
||||||
ESP_LOGE( MB_PORT_TAG, "%s:Frame send error. %d", __func__, eStatus );
|
ESP_LOGE( MB_PORT_TAG, "%s:Frame send error. %d", __func__, eStatus );
|
||||||
}
|
}
|
||||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT );
|
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT );
|
||||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_SENT ) ) {
|
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_SENT ) ) {
|
||||||
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_SENT", __func__ );
|
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_SENT", __func__ );
|
||||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
||||||
|
xTransactionIsActive = TRUE;
|
||||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_SENT );
|
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_SENT );
|
||||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ) ) {
|
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ) ) {
|
||||||
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength);
|
if (xTransactionIsActive) {
|
||||||
|
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBRcvFrame, &usLength);
|
||||||
|
MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "Receive buffer initialization fail.");
|
||||||
|
MB_PORT_CHECK(ucMBSendFrame, MB_EILLSTATE, "Send buffer initialization fail.");
|
||||||
|
// Check if the frame is for us. If not ,send an error process event.
|
||||||
|
if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() )
|
||||||
|
|| ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS) ) ) {
|
||||||
|
if ( ( ucMBRcvFrame[MB_PDU_FUNC_OFF] & ~MB_FUNC_ERROR ) == ( ucMBSendFrame[MB_PDU_FUNC_OFF] ) ) {
|
||||||
|
ESP_LOGD(MB_PORT_TAG, "%s: Packet data received successfully (%u).", __func__, eStatus);
|
||||||
|
ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBRcvFrame, (uint16_t)usLength, ESP_LOG_DEBUG);
|
||||||
|
|
||||||
// Check if the frame is for us. If not ,send an error process event.
|
( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
|
||||||
if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() )
|
} else {
|
||||||
|| ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS ) ) )
|
ESP_LOGE( MB_PORT_TAG, "Drop incorrect frame, receive_func(%u) != send_func(%u)",
|
||||||
{
|
ucMBRcvFrame[MB_PDU_FUNC_OFF], ucMBSendFrame[MB_PDU_FUNC_OFF]);
|
||||||
( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
|
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
|
||||||
ESP_LOGD(MB_PORT_TAG, "%s: Packet data received successfully (%u).", __func__, eStatus);
|
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
|
||||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBFrame, (uint16_t)usLength, ESP_LOG_DEBUG);
|
}
|
||||||
}
|
} else {
|
||||||
else
|
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
|
||||||
{
|
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
|
||||||
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
|
ESP_LOGD( MB_PORT_TAG, "%s: Packet data receive failed (addr=%u)(%u).",
|
||||||
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
|
__func__, ucRcvAddress, eStatus);
|
||||||
ESP_LOGD( MB_PORT_TAG, "%s: Packet data receive failed (addr=%u)(%u).",
|
}
|
||||||
__func__, ucRcvAddress, eStatus);
|
} else {
|
||||||
|
// Ignore the `EV_MASTER_FRAME_RECEIVED` event because the respond timeout occurred
|
||||||
|
// and this is likely respond to previous transaction
|
||||||
|
ESP_LOGE( MB_PORT_TAG, "Drop data received outside of transaction.");
|
||||||
}
|
}
|
||||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED );
|
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED );
|
||||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) {
|
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) {
|
||||||
if ( !ucMBFrame )
|
MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "receive buffer initialization fail.");
|
||||||
{
|
|
||||||
return MB_EILLSTATE;
|
|
||||||
}
|
|
||||||
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_EXECUTE", __func__);
|
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_EXECUTE", __func__);
|
||||||
ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
|
ucFunctionCode = ucMBRcvFrame[MB_PDU_FUNC_OFF];
|
||||||
eException = MB_EX_ILLEGAL_FUNCTION;
|
eException = MB_EX_ILLEGAL_FUNCTION;
|
||||||
/* If receive frame has exception. The receive function code highest bit is 1.*/
|
/* If receive frame has exception. The receive function code highest bit is 1.*/
|
||||||
if (ucFunctionCode & MB_FUNC_ERROR)
|
if (ucFunctionCode & MB_FUNC_ERROR)
|
||||||
{
|
{
|
||||||
eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
|
eException = (eMBException)ucMBRcvFrame[MB_PDU_DATA_OFF];
|
||||||
} else {
|
} else {
|
||||||
for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
|
for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
|
||||||
{
|
{
|
||||||
@ -396,12 +417,12 @@ eMBMasterPoll( void )
|
|||||||
for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++)
|
for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++)
|
||||||
{
|
{
|
||||||
vMBMasterSetDestAddress(j);
|
vMBMasterSetDestAddress(j);
|
||||||
eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength);
|
eException = xMasterFuncHandlers[i].pxHandler(ucMBRcvFrame, &usLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
|
eException = xMasterFuncHandlers[i].pxHandler( ucMBRcvFrame, &usLength );
|
||||||
}
|
}
|
||||||
vMBMasterSetCBRunInMasterMode( FALSE );
|
vMBMasterSetCBRunInMasterMode( FALSE );
|
||||||
break;
|
break;
|
||||||
@ -427,20 +448,20 @@ eMBMasterPoll( void )
|
|||||||
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_ERROR_PROCESS", __func__ );
|
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_ERROR_PROCESS", __func__ );
|
||||||
/* Execute specified error process callback function. */
|
/* Execute specified error process callback function. */
|
||||||
errorType = eMBMasterGetErrorType( );
|
errorType = eMBMasterGetErrorType( );
|
||||||
vMBMasterGetPDUSndBuf( &ucMBFrame );
|
vMBMasterGetPDUSndBuf( &ucMBSendFrame );
|
||||||
switch ( errorType )
|
switch ( errorType )
|
||||||
{
|
{
|
||||||
case EV_ERROR_RESPOND_TIMEOUT:
|
case EV_ERROR_RESPOND_TIMEOUT:
|
||||||
vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ),
|
vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ),
|
||||||
ucMBFrame, usMBMasterGetPDUSndLength( ) );
|
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||||
break;
|
break;
|
||||||
case EV_ERROR_RECEIVE_DATA:
|
case EV_ERROR_RECEIVE_DATA:
|
||||||
vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ),
|
vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ),
|
||||||
ucMBFrame, usMBMasterGetPDUSndLength( ) );
|
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||||
break;
|
break;
|
||||||
case EV_ERROR_EXECUTE_FUNCTION:
|
case EV_ERROR_EXECUTE_FUNCTION:
|
||||||
vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
|
vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
|
||||||
ucMBFrame, usMBMasterGetPDUSndLength( ) );
|
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||||
break;
|
break;
|
||||||
case EV_ERROR_OK:
|
case EV_ERROR_OK:
|
||||||
vMBMasterCBRequestSuccess( );
|
vMBMasterCBRequestSuccess( );
|
||||||
@ -449,6 +470,7 @@ eMBMasterPoll( void )
|
|||||||
ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %d.", __func__, errorType);
|
ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %d.", __func__, errorType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
vMBMasterPortTimersDisable( );
|
||||||
vMBMasterSetErrorType( EV_ERROR_INIT );
|
vMBMasterSetErrorType( EV_ERROR_INIT );
|
||||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS );
|
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS );
|
||||||
vMBMasterRunResRelease( );
|
vMBMasterRunResRelease( );
|
||||||
@ -501,7 +523,7 @@ void IRAM_ATTR vMBMasterSetErrorType( eMBMasterErrorEventType errorType )
|
|||||||
/* Get Modbus Master send PDU's buffer address pointer.*/
|
/* Get Modbus Master send PDU's buffer address pointer.*/
|
||||||
void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame )
|
void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame )
|
||||||
{
|
{
|
||||||
*pucFrame = ( UCHAR * ) &ucMasterSndBuf[MB_SER_PDU_PDU_OFF];
|
*pucFrame = ( UCHAR * ) &ucMasterSndBuf[MB_SEND_BUF_PDU_OFF];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set Modbus Master send PDU's buffer length.*/
|
/* Set Modbus Master send PDU's buffer length.*/
|
||||||
@ -535,8 +557,15 @@ BOOL MB_PORT_ISR_ATTR xMBMasterRequestIsBroadcast( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The master request is broadcast? */
|
/* The master request is broadcast? */
|
||||||
void vMBMasterRequestSetType( BOOL xIsBroadcast ){
|
void vMBMasterRequestSetType( BOOL xIsBroadcast )
|
||||||
|
{
|
||||||
xFrameIsBroadcast = xIsBroadcast;
|
xFrameIsBroadcast = xIsBroadcast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Modbus Master communication mode.
|
||||||
|
eMBMode ucMBMasterGetCommMode(void)
|
||||||
|
{
|
||||||
|
return eMBMasterCurrentMode;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
|
#endif // MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
||||||
@ -32,7 +39,7 @@
|
|||||||
#include "port.h"
|
#include "port.h"
|
||||||
#include "mbconfig.h"
|
#include "mbconfig.h"
|
||||||
|
|
||||||
#if MB_MASTER_RTU_ENABLED || MB_SLAVE_RTU_ENABLED
|
#if (MB_MASTER_RTU_ENABLED || MB_SLAVE_RTU_ENABLED || CONFIG_MB_UTEST)
|
||||||
|
|
||||||
static const UCHAR aucCRCHi[] = {
|
static const UCHAR aucCRCHi[] = {
|
||||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
||||||
@ -148,26 +155,33 @@ eMBErrorCode
|
|||||||
eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
||||||
{
|
{
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
UCHAR *pucMBRTUFrame = ( UCHAR* ) ucRTUBuf;
|
||||||
|
USHORT usFrameLength = usRcvBufferPos;
|
||||||
|
|
||||||
|
if( xMBPortSerialGetRequest( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
||||||
|
{
|
||||||
|
return MB_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
ENTER_CRITICAL_SECTION( );
|
ENTER_CRITICAL_SECTION( );
|
||||||
assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
|
assert( usFrameLength < MB_SER_PDU_SIZE_MAX );
|
||||||
|
|
||||||
/* Length and CRC check */
|
/* Length and CRC check */
|
||||||
if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
|
if( ( usFrameLength >= MB_SER_PDU_SIZE_MIN )
|
||||||
&& ( usMBCRC16( ( UCHAR * ) ucRTUBuf, usRcvBufferPos ) == 0 ) )
|
&& ( usMBCRC16( ( UCHAR * ) pucMBRTUFrame, usFrameLength ) == 0 ) )
|
||||||
{
|
{
|
||||||
/* Save the address field. All frames are passed to the upper layed
|
/* Save the address field. All frames are passed to the upper layed
|
||||||
* and the decision if a frame is used is done there.
|
* and the decision if a frame is used is done there.
|
||||||
*/
|
*/
|
||||||
*pucRcvAddress = ucRTUBuf[MB_SER_PDU_ADDR_OFF];
|
*pucRcvAddress = pucMBRTUFrame[MB_SER_PDU_ADDR_OFF];
|
||||||
|
|
||||||
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
|
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
|
||||||
* size of address field and CRC checksum.
|
* size of address field and CRC checksum.
|
||||||
*/
|
*/
|
||||||
*pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );
|
*pusLength = ( USHORT )( usFrameLength - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );
|
||||||
|
|
||||||
/* Return the start of the Modbus PDU to the caller. */
|
/* Return the start of the Modbus PDU to the caller. */
|
||||||
*pucFrame = ( UCHAR * ) & ucRTUBuf[MB_SER_PDU_PDU_OFF];
|
*pucFrame = ( UCHAR * ) & pucMBRTUFrame[MB_SER_PDU_PDU_OFF];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -184,14 +198,13 @@ eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
|
|||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
USHORT usCRC16;
|
USHORT usCRC16;
|
||||||
|
|
||||||
ENTER_CRITICAL_SECTION( );
|
|
||||||
|
|
||||||
/* Check if the receiver is still in idle state. If not we where to
|
/* Check if the receiver is still in idle state. If not we where to
|
||||||
* slow with processing the received frame and the master sent another
|
* slow with processing the received frame and the master sent another
|
||||||
* frame on the network. We have to abort sending the frame.
|
* frame on the network. We have to abort sending the frame.
|
||||||
*/
|
*/
|
||||||
if( eRcvState == STATE_RX_IDLE )
|
if( eRcvState == STATE_RX_IDLE )
|
||||||
{
|
{
|
||||||
|
ENTER_CRITICAL_SECTION( );
|
||||||
/* First byte before the Modbus-PDU is the slave address. */
|
/* First byte before the Modbus-PDU is the slave address. */
|
||||||
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
|
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
|
||||||
usSndBufferCount = 1;
|
usSndBufferCount = 1;
|
||||||
@ -207,13 +220,19 @@ eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
|
|||||||
|
|
||||||
/* Activate the transmitter. */
|
/* Activate the transmitter. */
|
||||||
eSndState = STATE_TX_XMIT;
|
eSndState = STATE_TX_XMIT;
|
||||||
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
|
||||||
|
if( xMBPortSerialSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
||||||
|
{
|
||||||
|
eStatus = MB_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
vMBPortSerialEnable( FALSE, TRUE );
|
vMBPortSerialEnable( FALSE, TRUE );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
eStatus = MB_EIO;
|
eStatus = MB_EIO;
|
||||||
}
|
}
|
||||||
EXIT_CRITICAL_SECTION( );
|
|
||||||
return eStatus;
|
return eStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +284,7 @@ xMBRTUReceiveFSM( void )
|
|||||||
case STATE_RX_RCV:
|
case STATE_RX_RCV:
|
||||||
if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
|
if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
|
||||||
{
|
{
|
||||||
if ( xStatus ) {
|
if( xStatus ) {
|
||||||
ucRTUBuf[usRcvBufferPos++] = ucByte;
|
ucRTUBuf[usRcvBufferPos++] = ucByte;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2013 Armink
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2013 China Beijing Armink <armink.ztl@gmail.com>
|
* Copyright (c) 2013 China Beijing Armink <armink.ztl@gmail.com>
|
||||||
@ -154,26 +161,34 @@ eMBErrorCode
|
|||||||
eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
||||||
{
|
{
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
UCHAR *pucMBRTUFrame = ( UCHAR* ) ucMasterRTURcvBuf;
|
||||||
|
USHORT usFrameLength = usMasterRcvBufferPos;
|
||||||
|
|
||||||
|
if( xMBMasterPortSerialGetResponse( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
||||||
|
{
|
||||||
|
return MB_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
ENTER_CRITICAL_SECTION( );
|
ENTER_CRITICAL_SECTION( );
|
||||||
assert( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX );
|
assert( usFrameLength < MB_SER_PDU_SIZE_MAX );
|
||||||
|
assert( pucMBRTUFrame );
|
||||||
|
|
||||||
/* Length and CRC check */
|
/* Length and CRC check */
|
||||||
if( ( usMasterRcvBufferPos >= MB_RTU_SER_PDU_SIZE_MIN )
|
if( ( usFrameLength >= MB_RTU_SER_PDU_SIZE_MIN )
|
||||||
&& ( usMBCRC16( ( UCHAR * ) ucMasterRTURcvBuf, usMasterRcvBufferPos ) == 0 ) )
|
&& ( usMBCRC16( ( UCHAR * ) pucMBRTUFrame, usFrameLength ) == 0 ) )
|
||||||
{
|
{
|
||||||
/* Save the address field. All frames are passed to the upper layed
|
/* Save the address field. All frames are passed to the upper layer
|
||||||
* and the decision if a frame is used is done there.
|
* and the decision if a frame is used is done there.
|
||||||
*/
|
*/
|
||||||
*pucRcvAddress = ucMasterRTURcvBuf[MB_SER_PDU_ADDR_OFF];
|
*pucRcvAddress = pucMBRTUFrame[MB_SER_PDU_ADDR_OFF];
|
||||||
|
|
||||||
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
|
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
|
||||||
* size of address field and CRC checksum.
|
* size of address field and CRC checksum.
|
||||||
*/
|
*/
|
||||||
*pusLength = ( USHORT )( usMasterRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );
|
*pusLength = ( USHORT )( usFrameLength - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );
|
||||||
|
|
||||||
/* Return the start of the Modbus PDU to the caller. */
|
/* Return the start of the Modbus PDU to the caller. */
|
||||||
*pucFrame = ( UCHAR * ) & ucMasterRTURcvBuf[MB_SER_PDU_PDU_OFF];
|
*pucFrame = ( UCHAR * ) & pucMBRTUFrame[MB_SER_PDU_PDU_OFF];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -192,14 +207,13 @@ eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength
|
|||||||
|
|
||||||
if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL;
|
if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL;
|
||||||
|
|
||||||
ENTER_CRITICAL_SECTION( );
|
|
||||||
|
|
||||||
/* Check if the receiver is still in idle state. If not we where to
|
/* Check if the receiver is still in idle state. If not we where to
|
||||||
* slow with processing the received frame and the master sent another
|
* slow with processing the received frame and the master sent another
|
||||||
* frame on the network. We have to abort sending the frame.
|
* frame on the network. We have to abort sending the frame.
|
||||||
*/
|
*/
|
||||||
if( eRcvState == STATE_M_RX_IDLE )
|
if( eRcvState == STATE_M_RX_IDLE )
|
||||||
{
|
{
|
||||||
|
ENTER_CRITICAL_SECTION( );
|
||||||
/* First byte before the Modbus-PDU is the slave address. */
|
/* First byte before the Modbus-PDU is the slave address. */
|
||||||
pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1;
|
pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1;
|
||||||
usMasterSndBufferCount = 1;
|
usMasterSndBufferCount = 1;
|
||||||
@ -210,11 +224,18 @@ eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength
|
|||||||
|
|
||||||
/* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
|
/* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
|
||||||
usCRC16 = usMBCRC16( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount );
|
usCRC16 = usMBCRC16( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount );
|
||||||
ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
|
pucMasterSndBufferCur[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
|
||||||
ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );
|
pucMasterSndBufferCur[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );
|
||||||
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
|
||||||
/* Activate the transmitter. */
|
/* Activate the transmitter. */
|
||||||
eSndState = STATE_M_TX_XMIT;
|
eSndState = STATE_M_TX_XMIT;
|
||||||
|
|
||||||
|
if ( xMBMasterPortSerialSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
||||||
|
{
|
||||||
|
eStatus = MB_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
// The place to enable RS485 driver
|
// The place to enable RS485 driver
|
||||||
vMBMasterPortSerialEnable( FALSE, TRUE );
|
vMBMasterPortSerialEnable( FALSE, TRUE );
|
||||||
}
|
}
|
||||||
@ -222,7 +243,6 @@ eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength
|
|||||||
{
|
{
|
||||||
eStatus = MB_EIO;
|
eStatus = MB_EIO;
|
||||||
}
|
}
|
||||||
EXIT_CRITICAL_SECTION( );
|
|
||||||
return eStatus;
|
return eStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,11 +286,15 @@ xMBMasterRTUReceiveFSM( void )
|
|||||||
eSndState = STATE_M_TX_IDLE;
|
eSndState = STATE_M_TX_IDLE;
|
||||||
|
|
||||||
usMasterRcvBufferPos = 0;
|
usMasterRcvBufferPos = 0;
|
||||||
ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte;
|
if( xStatus && ucByte ) {
|
||||||
eRcvState = STATE_M_RX_RCV;
|
ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte;
|
||||||
|
eRcvState = STATE_M_RX_RCV;
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable t3.5 timers. */
|
/* Enable t3.5 timers. */
|
||||||
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
vMBMasterPortTimersT35Enable( );
|
vMBMasterPortTimersT35Enable( );
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* We are currently receiving a frame. Reset the timer after
|
/* We are currently receiving a frame. Reset the timer after
|
||||||
@ -289,7 +313,9 @@ xMBMasterRTUReceiveFSM( void )
|
|||||||
{
|
{
|
||||||
eRcvState = STATE_M_RX_ERROR;
|
eRcvState = STATE_M_RX_ERROR;
|
||||||
}
|
}
|
||||||
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
vMBMasterPortTimersT35Enable( );
|
vMBMasterPortTimersT35Enable( );
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return xStatus;
|
return xStatus;
|
||||||
@ -324,7 +350,8 @@ xMBMasterRTUTransmitFSM( void )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE;
|
xFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SEND_BUF_PDU_OFF - MB_SER_PDU_PDU_OFF]
|
||||||
|
== MB_ADDRESS_BROADCAST ) ? TRUE : FALSE;
|
||||||
vMBMasterRequestSetType( xFrameIsBroadcast );
|
vMBMasterRequestSetType( xFrameIsBroadcast );
|
||||||
eSndState = STATE_M_TX_XFWR;
|
eSndState = STATE_M_TX_XFWR;
|
||||||
/* If the frame is broadcast ,master will enable timer of convert delay,
|
/* If the frame is broadcast ,master will enable timer of convert delay,
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
|
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
/* ----------------------- Modbus includes ----------------------------------*/
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
#include "sys/lock.h"
|
#include "sys/lock.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
|
||||||
@ -72,6 +73,61 @@ vMBPortSetMode( UCHAR ucMode )
|
|||||||
EXIT_CRITICAL_SECTION();
|
EXIT_CRITICAL_SECTION();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_SLAVE_RTU_ENABLED || MB_SLAVE_ASCII_ENABLED
|
||||||
|
|
||||||
|
BOOL xMBPortSerialWaitEvent(QueueHandle_t xMbUartQueue, uart_event_t* pxEvent, ULONG xTimeout)
|
||||||
|
{
|
||||||
|
BOOL xResult = (BaseType_t)xQueueReceive(xMbUartQueue, (void*)pxEvent, (TickType_t) xTimeout);
|
||||||
|
ESP_LOGD(MB_PORT_TAG, "%s, UART event: %d ", __func__, pxEvent->type);
|
||||||
|
return xResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function is called from ASCII/RTU module to get processed data buffer. Sets the
|
||||||
|
* received buffer and its length using parameters.
|
||||||
|
*/
|
||||||
|
__attribute__ ((weak))
|
||||||
|
BOOL xMBMasterPortSerialGetResponse( UCHAR **ppucMBSerialFrame, USHORT * usSerialLength )
|
||||||
|
{
|
||||||
|
ESP_LOGD(MB_PORT_TAG, " %s default", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function is called from ASCII/RTU module to set processed data buffer
|
||||||
|
* to be sent in transmitter state machine.
|
||||||
|
*/
|
||||||
|
__attribute__ ((weak))
|
||||||
|
BOOL xMBMasterPortSerialSendRequest( UCHAR *pucMBSerialFrame, USHORT usSerialLength )
|
||||||
|
{
|
||||||
|
ESP_LOGD(MB_PORT_TAG, "%s default", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MB_SLAVE_RTU_ENABLED || MB_SLAVE_ASCII_ENABLED
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
BOOL xMBPortSerialGetRequest( UCHAR **ppucMBSerialFrame, USHORT * usSerialLength )
|
||||||
|
{
|
||||||
|
ESP_LOGD(MB_PORT_TAG, "%s default", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
BOOL xMBPortSerialSendResponse( UCHAR *pucMBSerialFrame, USHORT usSerialLength )
|
||||||
|
{
|
||||||
|
ESP_LOGD(MB_PORT_TAG, "%s default", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MB_TCP_DEBUG
|
#if MB_TCP_DEBUG
|
||||||
|
|
||||||
// This function is kept to realize legacy freemodbus frame logging functionality
|
// This function is kept to realize legacy freemodbus frame logging functionality
|
@ -38,7 +38,18 @@
|
|||||||
#define PORT_COMMON_H_
|
#define PORT_COMMON_H_
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/queue.h" // for queue
|
||||||
|
|
||||||
#include "esp_log.h" // for ESP_LOGE macro
|
#include "esp_log.h" // for ESP_LOGE macro
|
||||||
|
#include "esp_timer.h"
|
||||||
|
#include "driver/uart.h" // for uart_event_t
|
||||||
|
|
||||||
|
#if __has_include("driver/gptimer.h")
|
||||||
|
#include "driver/gptimer.h"
|
||||||
|
#else
|
||||||
|
#include "driver/timer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "mbconfig.h"
|
#include "mbconfig.h"
|
||||||
|
|
||||||
#define INLINE inline
|
#define INLINE inline
|
||||||
@ -86,6 +97,7 @@
|
|||||||
|
|
||||||
// Define number of timer reloads per 1 mS
|
// Define number of timer reloads per 1 mS
|
||||||
#define MB_TIMER_TICS_PER_MS (20UL)
|
#define MB_TIMER_TICS_PER_MS (20UL)
|
||||||
|
#define MB_TIMER_TICK_TIME_US (1000 / MB_TIMER_TICS_PER_MS) // 50uS = one discreet for timer
|
||||||
|
|
||||||
#define MB_TCP_DEBUG (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) // Enable legacy debug output in TCP module.
|
#define MB_TCP_DEBUG (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) // Enable legacy debug output in TCP module.
|
||||||
|
|
||||||
@ -141,6 +153,12 @@ typedef enum {
|
|||||||
MB_PORT_IPV6 = 1 /*!< TCP IPV6 addressing */
|
MB_PORT_IPV6 = 1 /*!< TCP IPV6 addressing */
|
||||||
} eMBPortIpVer;
|
} eMBPortIpVer;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
esp_timer_handle_t xTimerIntHandle;
|
||||||
|
USHORT usT35Ticks;
|
||||||
|
BOOL xTimerState;
|
||||||
|
} xTimerContext_t;
|
||||||
|
|
||||||
void vMBPortEnterCritical(void);
|
void vMBPortEnterCritical(void);
|
||||||
void vMBPortExitCritical(void);
|
void vMBPortExitCritical(void);
|
||||||
|
|
||||||
@ -166,6 +184,8 @@ void prvvMBTCPLogFrame( const CHAR * pucMsg, UCHAR * pucFrame, USHORT usFrameLen
|
|||||||
void vMBPortSetMode( UCHAR ucMode );
|
void vMBPortSetMode( UCHAR ucMode );
|
||||||
UCHAR ucMBPortGetMode( void );
|
UCHAR ucMBPortGetMode( void );
|
||||||
|
|
||||||
|
BOOL xMBPortSerialWaitEvent(QueueHandle_t xMbUartQueue, uart_event_t* pxEvent, ULONG xTimeout);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
PR_END_EXTERN_C
|
PR_END_EXTERN_C
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
@ -1,16 +1,9 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010 Christian Walter
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: ESP32 Port Demo Application
|
* FreeModbus Libary: ESP32 Port Demo Application
|
||||||
@ -54,7 +47,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "port_serial_slave.h"
|
#include "port_serial_slave.h"
|
||||||
/* ----------------------- Variables ----------------------------------------*/
|
/* ----------------------- Variables ----------------------------------------*/
|
||||||
static xQueueHandle xQueueHdl;
|
static QueueHandle_t xQueueHdl;
|
||||||
|
|
||||||
#define MB_EVENT_QUEUE_SIZE (6)
|
#define MB_EVENT_QUEUE_SIZE (6)
|
||||||
#define MB_EVENT_QUEUE_TIMEOUT (pdMS_TO_TICKS(CONFIG_FMB_EVENT_QUEUE_TIMEOUT))
|
#define MB_EVENT_QUEUE_TIMEOUT (pdMS_TO_TICKS(CONFIG_FMB_EVENT_QUEUE_TIMEOUT))
|
||||||
@ -120,7 +113,7 @@ xMBPortEventGet(eMBEventType * peEvent)
|
|||||||
return xEventHappened;
|
return xEventHappened;
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueueHandle
|
QueueHandle_t
|
||||||
xMBPortEventGetHandle(void)
|
xMBPortEventGetHandle(void)
|
||||||
{
|
{
|
||||||
if(xQueueHdl != NULL)
|
if(xQueueHdl != NULL)
|
@ -187,13 +187,16 @@ BOOL xMBMasterRunResTake( LONG lTimeOut )
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is release Modbus Master running resource.
|
* This function is release Modbus Master running resource.
|
||||||
* Note:The resource is define by Operating System.If you not use OS this function can be empty.
|
* Note:The resource is define by Operating System. If you not use OS this function can be empty.
|
||||||
*/
|
*/
|
||||||
void vMBMasterRunResRelease( void )
|
void vMBMasterRunResRelease( void )
|
||||||
{
|
{
|
||||||
EventBits_t uxBits = xEventGroupSetBits( xResourceMasterHdl, MB_EVENT_RESOURCE );
|
EventBits_t uxBits = xEventGroupSetBits( xResourceMasterHdl, MB_EVENT_RESOURCE );
|
||||||
MB_PORT_CHECK((uxBits == MB_EVENT_RESOURCE), ; , "Resource release failure.");
|
if (uxBits != MB_EVENT_RESOURCE) {
|
||||||
ESP_LOGD(MB_PORT_TAG,"%s: Release resource (%x).", __func__, uxBits);
|
// The returned resource mask may be = 0, if the task waiting for it is unblocked.
|
||||||
|
// This is not an error but expected behavior.
|
||||||
|
ESP_LOGD(MB_PORT_TAG,"%s: Release resource (%x) fail.", __func__, uxBits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@ -1,16 +1,9 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010 Christian Walter
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: ESP32 Demo Application
|
* FreeModbus Libary: ESP32 Demo Application
|
@ -1,16 +1,9 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2006 Christian Walter
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: ESP32 Demo Application
|
* FreeModbus Libary: ESP32 Demo Application
|
@ -1,16 +1,9 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010 Christian Walter
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: ESP32 Port
|
* FreeModbus Libary: ESP32 Port
|
||||||
@ -40,6 +33,8 @@
|
|||||||
*
|
*
|
||||||
* File: $Id: portother.c,v 1.1 2010/06/06 13:07:20 wolti Exp $
|
* File: $Id: portother.c,v 1.1 2010/06/06 13:07:20 wolti Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "driver/uart.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
#include "freertos/queue.h" // for queue support
|
#include "freertos/queue.h" // for queue support
|
||||||
@ -92,15 +87,14 @@ static USHORT usMBPortSerialRxPoll(size_t xEventSize)
|
|||||||
|
|
||||||
if (bRxStateEnabled) {
|
if (bRxStateEnabled) {
|
||||||
// Get received packet into Rx buffer
|
// Get received packet into Rx buffer
|
||||||
while(xReadStatus && (usCnt++ <= MB_SERIAL_BUF_SIZE)) {
|
while(xReadStatus && (usCnt++ <= xEventSize)) {
|
||||||
// Call the Modbus stack callback function and let it fill the buffers.
|
// Call the Modbus stack callback function and let it fill the buffers.
|
||||||
xReadStatus = pxMBFrameCBByteReceived(); // callback to execute receive FSM
|
xReadStatus = pxMBFrameCBByteReceived(); // callback to execute receive FSM
|
||||||
}
|
}
|
||||||
uart_flush_input(ucUartNumber);
|
uart_flush_input(ucUartNumber);
|
||||||
// Send event EV_FRAME_RECEIVED to allow stack process packet
|
// Send event EV_FRAME_RECEIVED to allow stack process packet
|
||||||
#if !CONFIG_FMB_TIMER_PORT_ENABLED
|
#if !CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
// Let the stack know that T3.5 time is expired and data is received
|
pxMBPortCBTimerExpired();
|
||||||
(void)pxMBPortCBTimerExpired(); // calls callback xMBRTUTimerT35Expired();
|
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGD(TAG, "RX: %d bytes\n", usCnt);
|
ESP_LOGD(TAG, "RX: %d bytes\n", usCnt);
|
||||||
}
|
}
|
||||||
@ -133,7 +127,7 @@ static void vUartTask(void *pvParameters)
|
|||||||
uart_event_t xEvent;
|
uart_event_t xEvent;
|
||||||
USHORT usResult = 0;
|
USHORT usResult = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (xQueueReceive(xMbUartQueue, (void*)&xEvent, portMAX_DELAY) == pdTRUE) {
|
if (xMBPortSerialWaitEvent(xMbUartQueue, (void*)&xEvent, portMAX_DELAY)) {
|
||||||
ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
|
ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
|
||||||
switch(xEvent.type) {
|
switch(xEvent.type) {
|
||||||
//Event of UART receving data
|
//Event of UART receving data
|
||||||
@ -142,6 +136,8 @@ static void vUartTask(void *pvParameters)
|
|||||||
// This flag set in the event means that no more
|
// This flag set in the event means that no more
|
||||||
// data received during configured timeout and UART TOUT feature is triggered
|
// data received during configured timeout and UART TOUT feature is triggered
|
||||||
if (xEvent.timeout_flag) {
|
if (xEvent.timeout_flag) {
|
||||||
|
// Get buffered data length
|
||||||
|
ESP_ERROR_CHECK(uart_get_buffered_data_len(ucUartNumber, &xEvent.size));
|
||||||
// Read received data and send it to modbus stack
|
// Read received data and send it to modbus stack
|
||||||
usResult = usMBPortSerialRxPoll(xEvent.size);
|
usResult = usMBPortSerialRxPoll(xEvent.size);
|
||||||
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
|
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
|
||||||
@ -226,7 +222,7 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate,
|
|||||||
.stop_bits = UART_STOP_BITS_1,
|
.stop_bits = UART_STOP_BITS_1,
|
||||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||||
.rx_flow_ctrl_thresh = 2,
|
.rx_flow_ctrl_thresh = 2,
|
||||||
.source_clk = UART_SCLK_APB,
|
.source_clk = UART_SCLK_APB
|
||||||
};
|
};
|
||||||
// Set UART config
|
// Set UART config
|
||||||
xErr = uart_param_config(ucUartNumber, &xUartConfig);
|
xErr = uart_param_config(ucUartNumber, &xUartConfig);
|
@ -52,6 +52,9 @@
|
|||||||
#include "port_serial_master.h"
|
#include "port_serial_master.h"
|
||||||
|
|
||||||
/* ----------------------- Defines ------------------------------------------*/
|
/* ----------------------- Defines ------------------------------------------*/
|
||||||
|
#define MB_SERIAL_RX_SEMA_TOUT_MS (1000)
|
||||||
|
#define MB_SERIAL_RX_SEMA_TOUT (pdMS_TO_TICKS(MB_SERIAL_RX_SEMA_TOUT_MS))
|
||||||
|
#define MB_SERIAL_RX_FLUSH_RETRY (2)
|
||||||
|
|
||||||
/* ----------------------- Static variables ---------------------------------*/
|
/* ----------------------- Static variables ---------------------------------*/
|
||||||
static const CHAR *TAG = "MB_MASTER_SERIAL";
|
static const CHAR *TAG = "MB_MASTER_SERIAL";
|
||||||
@ -66,16 +69,67 @@ static UCHAR ucUartNumber = UART_NUM_MAX - 1;
|
|||||||
static BOOL bRxStateEnabled = FALSE; // Receiver enabled flag
|
static BOOL bRxStateEnabled = FALSE; // Receiver enabled flag
|
||||||
static BOOL bTxStateEnabled = FALSE; // Transmitter enabled flag
|
static BOOL bTxStateEnabled = FALSE; // Transmitter enabled flag
|
||||||
|
|
||||||
|
static SemaphoreHandle_t xMasterSemaRxHandle; // Rx blocking semaphore handle
|
||||||
|
|
||||||
|
static BOOL xMBMasterPortRxSemaInit( void )
|
||||||
|
{
|
||||||
|
xMasterSemaRxHandle = xSemaphoreCreateBinary();
|
||||||
|
MB_PORT_CHECK((xMasterSemaRxHandle != NULL), FALSE , "%s: RX semaphore create failure.", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL xMBMasterPortRxSemaTake( LONG lTimeOut )
|
||||||
|
{
|
||||||
|
BaseType_t xStatus = pdTRUE;
|
||||||
|
xStatus = xSemaphoreTake(xMasterSemaRxHandle, lTimeOut );
|
||||||
|
MB_PORT_CHECK((xStatus == pdTRUE), FALSE , "%s: RX semaphore take failure.", __func__);
|
||||||
|
ESP_LOGV(MB_PORT_TAG,"%s:Take RX semaphore (%lu ticks).", __func__, lTimeOut);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vMBMasterRxSemaRelease( void )
|
||||||
|
{
|
||||||
|
BaseType_t xStatus = pdFALSE;
|
||||||
|
xStatus = xSemaphoreGive(xMasterSemaRxHandle);
|
||||||
|
if (xStatus != pdTRUE) {
|
||||||
|
ESP_LOGD(MB_PORT_TAG,"%s:RX semaphore is free.", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL vMBMasterRxSemaIsBusy( void )
|
||||||
|
{
|
||||||
|
BaseType_t xStatus = pdFALSE;
|
||||||
|
xStatus = (uxSemaphoreGetCount(xMasterSemaRxHandle) == 0) ? TRUE : FALSE;
|
||||||
|
return xStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vMBMasterRxFlush( void )
|
||||||
|
{
|
||||||
|
size_t xSize = 1;
|
||||||
|
esp_err_t xErr = ESP_OK;
|
||||||
|
for (int xCount = 0; (xCount < MB_SERIAL_RX_FLUSH_RETRY) && xSize; xCount++) {
|
||||||
|
xErr = uart_get_buffered_data_len(ucUartNumber, &xSize);
|
||||||
|
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
|
||||||
|
BaseType_t xStatus = xQueueReset(xMbUartQueue);
|
||||||
|
if (xStatus) {
|
||||||
|
xErr = uart_flush_input(ucUartNumber);
|
||||||
|
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void vMBMasterPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
|
void vMBMasterPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
|
||||||
{
|
{
|
||||||
// This function can be called from xMBRTUTransmitFSM() of different task
|
// This function can be called from xMBRTUTransmitFSM() of different task
|
||||||
if (bTxEnable) {
|
if (bTxEnable) {
|
||||||
|
vMBMasterRxFlush();
|
||||||
bTxStateEnabled = TRUE;
|
bTxStateEnabled = TRUE;
|
||||||
} else {
|
} else {
|
||||||
bTxStateEnabled = FALSE;
|
bTxStateEnabled = FALSE;
|
||||||
}
|
}
|
||||||
if (bRxEnable) {
|
if (bRxEnable) {
|
||||||
bRxStateEnabled = TRUE;
|
bRxStateEnabled = TRUE;
|
||||||
|
vMBMasterRxSemaRelease();
|
||||||
vTaskResume(xMbTaskHandle); // Resume receiver task
|
vTaskResume(xMbTaskHandle); // Resume receiver task
|
||||||
} else {
|
} else {
|
||||||
vTaskSuspend(xMbTaskHandle); // Block receiver task
|
vTaskSuspend(xMbTaskHandle); // Block receiver task
|
||||||
@ -85,17 +139,26 @@ void vMBMasterPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
|
|||||||
|
|
||||||
static USHORT usMBMasterPortSerialRxPoll(size_t xEventSize)
|
static USHORT usMBMasterPortSerialRxPoll(size_t xEventSize)
|
||||||
{
|
{
|
||||||
BOOL xReadStatus = TRUE;
|
BOOL xStatus = TRUE;
|
||||||
USHORT usCnt = 0;
|
USHORT usCnt = 0;
|
||||||
|
|
||||||
if (bRxStateEnabled) {
|
xStatus = xMBMasterPortRxSemaTake(MB_SERIAL_RX_SEMA_TOUT);
|
||||||
while(xReadStatus && (usCnt++ <= MB_SERIAL_BUF_SIZE)) {
|
if (xStatus) {
|
||||||
|
while(xStatus && (usCnt++ <= xEventSize)) {
|
||||||
// Call the Modbus stack callback function and let it fill the stack buffers.
|
// Call the Modbus stack callback function and let it fill the stack buffers.
|
||||||
xReadStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
|
xStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
|
||||||
}
|
}
|
||||||
// The buffer is transferred into Modbus stack and is not needed here any more
|
// The buffer is transferred into Modbus stack and is not needed here any more
|
||||||
uart_flush_input(ucUartNumber);
|
uart_flush_input(ucUartNumber);
|
||||||
ESP_LOGD(TAG, "Received data: %d(bytes in buffer)\n", (uint32_t)usCnt);
|
ESP_LOGD(TAG, "Received data: %d(bytes in buffer)\n", (uint32_t)usCnt);
|
||||||
|
#if !CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
vMBMasterSetCurTimerMode(MB_TMODE_T35);
|
||||||
|
xStatus = pxMBMasterPortCBTimerExpired();
|
||||||
|
if (!xStatus) {
|
||||||
|
xMBMasterPortEventPost(EV_MASTER_FRAME_RECEIVED);
|
||||||
|
ESP_LOGD(TAG, "Send additional RX ready event.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "%s: bRxState disabled but junk data (%d bytes) received. ", __func__, xEventSize);
|
ESP_LOGE(TAG, "%s: bRxState disabled but junk data (%d bytes) received. ", __func__, xEventSize);
|
||||||
}
|
}
|
||||||
@ -129,7 +192,7 @@ static void vUartTask(void* pvParameters)
|
|||||||
uart_event_t xEvent;
|
uart_event_t xEvent;
|
||||||
USHORT usResult = 0;
|
USHORT usResult = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (xQueueReceive(xMbUartQueue, (void*)&xEvent, portMAX_DELAY) == pdTRUE) {
|
if (xMBPortSerialWaitEvent(xMbUartQueue, (void*)&xEvent, portMAX_DELAY)) {
|
||||||
ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
|
ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
|
||||||
switch(xEvent.type) {
|
switch(xEvent.type) {
|
||||||
//Event of UART receiving data
|
//Event of UART receiving data
|
||||||
@ -138,11 +201,17 @@ static void vUartTask(void* pvParameters)
|
|||||||
// This flag set in the event means that no more
|
// This flag set in the event means that no more
|
||||||
// data received during configured timeout and UART TOUT feature is triggered
|
// data received during configured timeout and UART TOUT feature is triggered
|
||||||
if (xEvent.timeout_flag) {
|
if (xEvent.timeout_flag) {
|
||||||
|
// Response is received but previous packet processing is pending
|
||||||
|
// Do not wait completion of processing and just discard received data as incorrect
|
||||||
|
if (vMBMasterRxSemaIsBusy()) {
|
||||||
|
vMBMasterRxFlush();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Get buffered data length
|
||||||
|
ESP_ERROR_CHECK(uart_get_buffered_data_len(ucUartNumber, &xEvent.size));
|
||||||
// Read received data and send it to modbus stack
|
// Read received data and send it to modbus stack
|
||||||
usResult = usMBMasterPortSerialRxPoll(xEvent.size);
|
usResult = usMBMasterPortSerialRxPoll(xEvent.size);
|
||||||
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
|
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
|
||||||
// Block receiver task until data is not processed
|
|
||||||
vTaskSuspend(NULL);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
//Event of HW FIFO overflow detected
|
//Event of HW FIFO overflow detected
|
||||||
@ -242,7 +311,8 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
|
|||||||
|
|
||||||
// Set always timeout flag to trigger timeout interrupt even after rx fifo full
|
// Set always timeout flag to trigger timeout interrupt even after rx fifo full
|
||||||
uart_set_always_rx_timeout(ucUartNumber, true);
|
uart_set_always_rx_timeout(ucUartNumber, true);
|
||||||
|
MB_PORT_CHECK((xMBMasterPortRxSemaInit()), FALSE,
|
||||||
|
"mb serial RX semaphore create fail.");
|
||||||
// Create a task to handle UART events
|
// Create a task to handle UART events
|
||||||
BaseType_t xStatus = xTaskCreatePinnedToCore(vUartTask, "uart_queue_task",
|
BaseType_t xStatus = xTaskCreatePinnedToCore(vUartTask, "uart_queue_task",
|
||||||
MB_SERIAL_TASK_STACK_SIZE,
|
MB_SERIAL_TASK_STACK_SIZE,
|
127
components/freemodbus/freemodbus/port/porttimer.c
Normal file
127
components/freemodbus/freemodbus/port/porttimer.c
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010 Christian Walter
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* FreeModbus Libary: ESP32 Port Demo Application
|
||||||
|
* Copyright (C) 2010 Christian Walter <cwalter@embedded-solutions.at>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* IF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* File: $Id: portother.c,v 1.1 2010/06/06 13:07:20 wolti Exp $
|
||||||
|
*/
|
||||||
|
/* ----------------------- Platform includes --------------------------------*/
|
||||||
|
#include "port.h"
|
||||||
|
|
||||||
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
|
#include "mb.h"
|
||||||
|
#include "mbport.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
|
||||||
|
static const char *TAG = "MBS_TIMER";
|
||||||
|
|
||||||
|
static xTimerContext_t* pxTimerContext = NULL;
|
||||||
|
|
||||||
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
|
static void IRAM_ATTR vTimerAlarmCBHandler(void *param)
|
||||||
|
{
|
||||||
|
pxMBPortCBTimerExpired(); // Timer expired callback function
|
||||||
|
pxTimerContext->xTimerState = TRUE;
|
||||||
|
ESP_EARLY_LOGD(TAG, "Slave timeout triggered.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BOOL xMBPortTimersInit(USHORT usTimeOut50us)
|
||||||
|
{
|
||||||
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
MB_PORT_CHECK((usTimeOut50us > 0), FALSE,
|
||||||
|
"Modbus timeout discreet is incorrect.");
|
||||||
|
MB_PORT_CHECK(!pxTimerContext, FALSE,
|
||||||
|
"Modbus timer is already created.");
|
||||||
|
pxTimerContext = calloc(1, sizeof(xTimerContext_t));
|
||||||
|
if (!pxTimerContext) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
pxTimerContext->xTimerIntHandle = NULL;
|
||||||
|
// Save timer reload value for Modbus T35 period
|
||||||
|
pxTimerContext->usT35Ticks = usTimeOut50us;
|
||||||
|
esp_timer_create_args_t xTimerConf = {
|
||||||
|
.callback = vTimerAlarmCBHandler,
|
||||||
|
.arg = NULL,
|
||||||
|
#if (MB_TIMER_SUPPORTS_ISR_DISPATCH_METHOD && CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD)
|
||||||
|
.dispatch_method = ESP_TIMER_ISR,
|
||||||
|
#else
|
||||||
|
.dispatch_method = ESP_TIMER_TASK,
|
||||||
|
#endif
|
||||||
|
.name = "MBS_T35timer"
|
||||||
|
};
|
||||||
|
// Create Modbus timer
|
||||||
|
esp_err_t xErr = esp_timer_create(&xTimerConf, &(pxTimerContext->xTimerIntHandle));
|
||||||
|
if (xErr) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vMBPortTimersEnable(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
MB_PORT_CHECK((pxTimerContext && pxTimerContext->xTimerIntHandle), ; ,
|
||||||
|
"timer is not initialized.");
|
||||||
|
uint64_t xToutUs = (pxTimerContext->usT35Ticks * MB_TIMER_TICK_TIME_US);
|
||||||
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
|
esp_timer_start_once(pxTimerContext->xTimerIntHandle, xToutUs);
|
||||||
|
pxTimerContext->xTimerState = FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MB_PORT_ISR_ATTR
|
||||||
|
vMBPortTimersDisable(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
// Disable timer alarm
|
||||||
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void vMBPortTimerClose(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
// Delete active timer
|
||||||
|
if (pxTimerContext) {
|
||||||
|
if (pxTimerContext->xTimerIntHandle) {
|
||||||
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
|
esp_timer_delete(pxTimerContext->xTimerIntHandle);
|
||||||
|
}
|
||||||
|
free(pxTimerContext);
|
||||||
|
pxTimerContext = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
152
components/freemodbus/freemodbus/port/porttimer_m.c
Normal file
152
components/freemodbus/freemodbus/port/porttimer_m.c
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2013 Armink
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* FreeModbus Libary: ESP32 Port
|
||||||
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* IF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* File: $Id: porttimer_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------- Platform includes --------------------------------*/
|
||||||
|
#include "port.h"
|
||||||
|
|
||||||
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
|
#include "mb_m.h"
|
||||||
|
#include "mbport.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
static const char *TAG = "MBM_TIMER";
|
||||||
|
|
||||||
|
/* ----------------------- Variables ----------------------------------------*/
|
||||||
|
static xTimerContext_t* pxTimerContext = NULL;
|
||||||
|
|
||||||
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
|
static void IRAM_ATTR vTimerAlarmCBHandler(void *param)
|
||||||
|
{
|
||||||
|
pxMBMasterPortCBTimerExpired(); // Timer expired callback function
|
||||||
|
pxTimerContext->xTimerState = TRUE;
|
||||||
|
ESP_EARLY_LOGD(TAG, "Timer mode: (%d) triggered", xMBMasterGetCurTimerMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
|
||||||
|
{
|
||||||
|
MB_PORT_CHECK((usTimeOut50us > 0), FALSE,
|
||||||
|
"Modbus timeout discreet is incorrect.");
|
||||||
|
MB_PORT_CHECK(!pxTimerContext, FALSE,
|
||||||
|
"Modbus timer is already created.");
|
||||||
|
pxTimerContext = calloc(1, sizeof(xTimerContext_t));
|
||||||
|
if (!pxTimerContext) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
pxTimerContext->xTimerIntHandle = NULL;
|
||||||
|
// Save timer reload value for Modbus T35 period
|
||||||
|
pxTimerContext->usT35Ticks = usTimeOut50us;
|
||||||
|
esp_timer_create_args_t xTimerConf = {
|
||||||
|
.callback = vTimerAlarmCBHandler,
|
||||||
|
.arg = NULL,
|
||||||
|
#if (MB_TIMER_SUPPORTS_ISR_DISPATCH_METHOD && CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD)
|
||||||
|
.dispatch_method = ESP_TIMER_ISR,
|
||||||
|
#else
|
||||||
|
.dispatch_method = ESP_TIMER_TASK,
|
||||||
|
#endif
|
||||||
|
.name = "MBM_T35timer"
|
||||||
|
};
|
||||||
|
// Create Modbus timer
|
||||||
|
esp_err_t xErr = esp_timer_create(&xTimerConf, &(pxTimerContext->xTimerIntHandle));
|
||||||
|
if (xErr) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set timer alarm value
|
||||||
|
static BOOL xMBMasterPortTimersEnable(uint64_t xToutUs)
|
||||||
|
{
|
||||||
|
MB_PORT_CHECK(pxTimerContext && (pxTimerContext->xTimerIntHandle), FALSE,
|
||||||
|
"timer is not initialized.");
|
||||||
|
MB_PORT_CHECK((xToutUs > 0), FALSE,
|
||||||
|
"incorrect tick value for timer = (0x%llu).", xToutUs);
|
||||||
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
|
esp_timer_start_once(pxTimerContext->xTimerIntHandle, xToutUs);
|
||||||
|
pxTimerContext->xTimerState = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vMBMasterPortTimersT35Enable(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_FMB_TIMER_PORT_ENABLED
|
||||||
|
uint64_t xToutUs = (pxTimerContext->usT35Ticks * MB_TIMER_TICK_TIME_US);
|
||||||
|
|
||||||
|
// Set current timer mode, don't change it.
|
||||||
|
vMBMasterSetCurTimerMode(MB_TMODE_T35);
|
||||||
|
// Set timer alarm
|
||||||
|
(void)xMBMasterPortTimersEnable(xToutUs);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void vMBMasterPortTimersConvertDelayEnable(void)
|
||||||
|
{
|
||||||
|
// Covert time in milliseconds into ticks
|
||||||
|
uint64_t xToutUs = (MB_MASTER_DELAY_MS_CONVERT * 1000);
|
||||||
|
|
||||||
|
// Set current timer mode
|
||||||
|
vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
|
||||||
|
ESP_LOGD(MB_PORT_TAG,"%s Convert delay enable.", __func__);
|
||||||
|
(void)xMBMasterPortTimersEnable(xToutUs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vMBMasterPortTimersRespondTimeoutEnable(void)
|
||||||
|
{
|
||||||
|
uint64_t xToutUs = (MB_MASTER_TIMEOUT_MS_RESPOND * 1000);
|
||||||
|
|
||||||
|
vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
|
||||||
|
ESP_LOGD(MB_PORT_TAG,"%s Respond enable timeout.", __func__);
|
||||||
|
(void)xMBMasterPortTimersEnable(xToutUs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MB_PORT_ISR_ATTR
|
||||||
|
vMBMasterPortTimersDisable()
|
||||||
|
{
|
||||||
|
// Disable timer alarm
|
||||||
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vMBMasterPortTimerClose(void)
|
||||||
|
{
|
||||||
|
// Delete active timer
|
||||||
|
if (pxTimerContext) {
|
||||||
|
if (pxTimerContext->xTimerIntHandle) {
|
||||||
|
esp_timer_stop(pxTimerContext->xTimerIntHandle);
|
||||||
|
esp_timer_delete(pxTimerContext->xTimerIntHandle);
|
||||||
|
}
|
||||||
|
free(pxTimerContext);
|
||||||
|
pxTimerContext = NULL;
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// mbc_serial_master.c
|
// mbc_serial_master.c
|
||||||
@ -39,7 +30,7 @@ extern BOOL xMBMasterPortSerialTxPoll(void);
|
|||||||
#define MB_RESPONSE_TICS pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND + 10)
|
#define MB_RESPONSE_TICS pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND + 10)
|
||||||
|
|
||||||
|
|
||||||
static mb_master_interface_t* mbm_interface_ptr = NULL; //&default_interface_inst;
|
static mb_master_interface_t* mbm_interface_ptr = NULL;
|
||||||
static const char *TAG = "MB_CONTROLLER_MASTER";
|
static const char *TAG = "MB_CONTROLLER_MASTER";
|
||||||
|
|
||||||
// Modbus event processing task
|
// Modbus event processing task
|
||||||
@ -110,7 +101,7 @@ static esp_err_t mbc_serial_master_start(void)
|
|||||||
"mb stack initialization failure, eMBInit() returns (0x%x).", status);
|
"mb stack initialization failure, eMBInit() returns (0x%x).", status);
|
||||||
status = eMBMasterEnable();
|
status = eMBMasterEnable();
|
||||||
MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
||||||
"mb stack set slave ID failure, eMBEnable() returned (0x%x).", (uint32_t)status);
|
"mb stack set slave ID failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status);
|
||||||
// Set the mbcontroller start flag
|
// Set the mbcontroller start flag
|
||||||
EventBits_t flag = xEventGroupSetBits(mbm_opts->mbm_event_group,
|
EventBits_t flag = xEventGroupSetBits(mbm_opts->mbm_event_group,
|
||||||
(EventBits_t)MB_EVENT_STACK_STARTED);
|
(EventBits_t)MB_EVENT_STACK_STARTED);
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// mbc_serial_master.h Modbus controller serial master implementation header file
|
// mbc_serial_master.h Modbus controller serial master implementation header file
|
@ -1,16 +1,9 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010 Christian Walter
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: ESP32 Port Demo Application
|
* FreeModbus Libary: ESP32 Port Demo Application
|
||||||
@ -46,7 +39,6 @@
|
|||||||
|
|
||||||
/* ----------------------- Platform includes --------------------------------*/
|
/* ----------------------- Platform includes --------------------------------*/
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
#include "driver/timer.h"
|
|
||||||
#include "esp_log.h" // for ESP_LOGE macro
|
#include "esp_log.h" // for ESP_LOGE macro
|
||||||
#include "mb_m.h"
|
#include "mb_m.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
@ -1,18 +1,8 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// mbc_serial_slave.c
|
// mbc_serial_slave.c
|
||||||
// Implementation of the Modbus controller serial slave
|
// Implementation of the Modbus controller serial slave
|
||||||
|
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// mbc_serial_slave.h Modbus controller serial slave implementation header file
|
// mbc_serial_slave.h Modbus controller serial slave implementation header file
|
@ -1,16 +1,9 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010 Christian Walter
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: ESP32 Port Demo Application
|
* FreeModbus Libary: ESP32 Port Demo Application
|
||||||
@ -47,7 +40,6 @@
|
|||||||
/* ----------------------- Platform includes --------------------------------*/
|
/* ----------------------- Platform includes --------------------------------*/
|
||||||
|
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
#include "driver/timer.h"
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
|
@ -1,16 +1,7 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// mbc_tcp_master.c
|
// mbc_tcp_master.c
|
||||||
@ -90,7 +81,7 @@ static void mbc_tcp_master_free_slave_list(void)
|
|||||||
// Initialize interface properties
|
// Initialize interface properties
|
||||||
mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts;
|
mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts;
|
||||||
|
|
||||||
LIST_FOREACH(it, &mbm_opts->mbm_slave_list, entries) {
|
while ((it = LIST_FIRST(&mbm_opts->mbm_slave_list))) {
|
||||||
LIST_REMOVE(it, entries);
|
LIST_REMOVE(it, entries);
|
||||||
mbm_opts->mbm_slave_list_count--;
|
mbm_opts->mbm_slave_list_count--;
|
||||||
free(it);
|
free(it);
|
||||||
@ -168,7 +159,7 @@ static esp_err_t mbc_tcp_master_start(void)
|
|||||||
|
|
||||||
status = eMBMasterEnable();
|
status = eMBMasterEnable();
|
||||||
MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
||||||
"mb stack set slave ID failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status);
|
"mb stack enable failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status);
|
||||||
|
|
||||||
// Add slave IP address for each slave to initialize connection
|
// Add slave IP address for each slave to initialize connection
|
||||||
mb_slave_addr_entry_t *p_slave_info;
|
mb_slave_addr_entry_t *p_slave_info;
|
||||||
@ -181,13 +172,12 @@ static esp_err_t mbc_tcp_master_start(void)
|
|||||||
// Add end of list condition
|
// Add end of list condition
|
||||||
(void)xMBTCPPortMasterAddSlaveIp(0xFF, NULL, 0xFF);
|
(void)xMBTCPPortMasterAddSlaveIp(0xFF, NULL, 0xFF);
|
||||||
|
|
||||||
|
|
||||||
// Wait for connection done event
|
// Wait for connection done event
|
||||||
bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group,
|
bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group,
|
||||||
(EventBits_t)MB_EVENT_STACK_STARTED, MB_TCP_CONNECTION_TOUT);
|
(EventBits_t)MB_EVENT_STACK_STARTED, MB_TCP_CONNECTION_TOUT);
|
||||||
MB_MASTER_CHECK((start), ESP_ERR_INVALID_STATE,
|
MB_MASTER_CHECK((start), ESP_ERR_INVALID_STATE,
|
||||||
"mb stack could not connect to slaves for %d seconds.",
|
"mb stack could not connect to slaves for %d seconds.",
|
||||||
CONFIG_FMB_TCP_CONNECTION_TOUT_SEC);
|
CONFIG_FMB_TCP_CONNECTION_TOUT_SEC);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,8 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
*/
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// mbc_tcp_master.h Modbus controller TCP master implementation header file
|
// mbc_tcp_master.h Modbus controller TCP master implementation header file
|
||||||
|
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*
|
*
|
||||||
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: ESP32 TCP Port
|
* FreeModbus Libary: ESP32 TCP Port
|
||||||
@ -281,23 +281,27 @@ static int vMBTCPPortMasterRxCheck(int xSd, fd_set* pxFdSet, int xTimeMs)
|
|||||||
return xRes;
|
return xRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xMBTCPPortMasterGetBuf(MbSlaveInfo_t* pxInfo, UCHAR* pucDstBuf, USHORT usLength)
|
static int xMBTCPPortMasterGetBuf(MbSlaveInfo_t* pxInfo, UCHAR* pucDstBuf, USHORT usLength, uint16_t xTimeMs)
|
||||||
{
|
{
|
||||||
int xLength = 0;
|
int xLength = 0;
|
||||||
UCHAR* pucBuf = pucDstBuf;
|
UCHAR* pucBuf = pucDstBuf;
|
||||||
USHORT usBytesLeft = usLength;
|
USHORT usBytesLeft = usLength;
|
||||||
|
struct timeval xTime;
|
||||||
|
|
||||||
MB_PORT_CHECK((pxInfo && pxInfo->xSockId > -1), -1, "Try to read incorrect socket = #%d.", pxInfo->xSockId);
|
MB_PORT_CHECK((pxInfo && pxInfo->xSockId > -1), -1, "Try to read incorrect socket = #%d.", pxInfo->xSockId);
|
||||||
|
|
||||||
|
// Set receive timeout for socket <= slave respond time
|
||||||
|
xTime.tv_sec = xTimeMs / 1000;
|
||||||
|
xTime.tv_usec = (xTimeMs % 1000) * 1000;
|
||||||
|
setsockopt(pxInfo->xSockId, SOL_SOCKET, SO_RCVTIMEO, &xTime, sizeof(xTime));
|
||||||
|
|
||||||
// Receive data from connected client
|
// Receive data from connected client
|
||||||
while (usBytesLeft > 0) {
|
while (usBytesLeft > 0) {
|
||||||
xMBTCPPortMasterCheckShutdown();
|
xMBTCPPortMasterCheckShutdown();
|
||||||
// none blocking read from socket with timeout
|
xLength = recv(pxInfo->xSockId, pucBuf, usBytesLeft, 0);
|
||||||
xLength = recv(pxInfo->xSockId, pucBuf, usBytesLeft, MSG_DONTWAIT);
|
|
||||||
if (xLength < 0) {
|
if (xLength < 0) {
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
// Read timeout occurred, continue reading
|
// Read timeout occurred, check the timeout and return
|
||||||
continue;
|
|
||||||
} else if (errno == ENOTCONN) {
|
} else if (errno == ENOTCONN) {
|
||||||
// Socket connection closed
|
// Socket connection closed
|
||||||
ESP_LOGE(TAG, "Socket(#%d)(%s) connection closed.",
|
ESP_LOGE(TAG, "Socket(#%d)(%s) connection closed.",
|
||||||
@ -316,7 +320,6 @@ static int xMBTCPPortMasterGetBuf(MbSlaveInfo_t* pxInfo, UCHAR* pucDstBuf, USHOR
|
|||||||
if (xMBTCPPortMasterGetRespTimeLeft(pxInfo) == 0) {
|
if (xMBTCPPortMasterGetRespTimeLeft(pxInfo) == 0) {
|
||||||
return ERR_TIMEOUT;
|
return ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
vTaskDelay(1);
|
|
||||||
}
|
}
|
||||||
return usLength;
|
return usLength;
|
||||||
}
|
}
|
||||||
@ -331,7 +334,8 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo)
|
|||||||
if (pxInfo) {
|
if (pxInfo) {
|
||||||
MB_PORT_CHECK((pxInfo->xSockId > 0), -1, "Try to read incorrect socket = #%d.", pxInfo->xSockId);
|
MB_PORT_CHECK((pxInfo->xSockId > 0), -1, "Try to read incorrect socket = #%d.", pxInfo->xSockId);
|
||||||
// Read packet header
|
// Read packet header
|
||||||
xRet = xMBTCPPortMasterGetBuf(pxInfo, &pxInfo->pucRcvBuf[0], MB_TCP_UID);
|
xRet = xMBTCPPortMasterGetBuf(pxInfo, &pxInfo->pucRcvBuf[0],
|
||||||
|
MB_TCP_UID, xMBTCPPortMasterGetRespTimeLeft(pxInfo));
|
||||||
if (xRet < 0) {
|
if (xRet < 0) {
|
||||||
pxInfo->xRcvErr = xRet;
|
pxInfo->xRcvErr = xRet;
|
||||||
return xRet;
|
return xRet;
|
||||||
@ -344,7 +348,8 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo)
|
|||||||
// If we have received the MBAP header we can analyze it and calculate
|
// If we have received the MBAP header we can analyze it and calculate
|
||||||
// the number of bytes left to complete the current request.
|
// the number of bytes left to complete the current request.
|
||||||
xLength = (int)MB_TCP_GET_FIELD(pxInfo->pucRcvBuf, MB_TCP_LEN);
|
xLength = (int)MB_TCP_GET_FIELD(pxInfo->pucRcvBuf, MB_TCP_LEN);
|
||||||
xRet = xMBTCPPortMasterGetBuf(pxInfo, &pxInfo->pucRcvBuf[MB_TCP_UID], xLength);
|
xRet = xMBTCPPortMasterGetBuf(pxInfo, &pxInfo->pucRcvBuf[MB_TCP_UID],
|
||||||
|
xLength, xMBTCPPortMasterGetRespTimeLeft(pxInfo));
|
||||||
if (xRet < 0) {
|
if (xRet < 0) {
|
||||||
pxInfo->xRcvErr = xRet;
|
pxInfo->xRcvErr = xRet;
|
||||||
return xRet;
|
return xRet;
|
||||||
@ -847,12 +852,13 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
|||||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
||||||
} else if ((xRet == ERR_TIMEOUT) || (xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo) == 0)) {
|
} else if ((xRet == ERR_TIMEOUT) || (xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo) == 0)) {
|
||||||
// Timeout occurred when receiving frame, process respond timeout
|
// Timeout occurred when receiving frame, process respond timeout
|
||||||
|
xMBTCPPortMasterFsmSetError(EV_ERROR_RESPOND_TIMEOUT, EV_MASTER_ERROR_PROCESS);
|
||||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", frame read timeout."),
|
ESP_LOGD(TAG, MB_SLAVE_FMT(", frame read timeout."),
|
||||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
||||||
} else if (xRet == ERR_BUF) {
|
} else if (xRet == ERR_BUF) {
|
||||||
// After retries a response with incorrect TID received, process failure.
|
// After retries a response with incorrect TID received, process failure.
|
||||||
xMBTCPPortMasterFsmSetError(EV_ERROR_RECEIVE_DATA, EV_MASTER_ERROR_PROCESS);
|
xMBTCPPortMasterFsmSetError(EV_ERROR_RECEIVE_DATA, EV_MASTER_ERROR_PROCESS);
|
||||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", frame error."),
|
ESP_LOGW(TAG, MB_SLAVE_FMT(", frame error."),
|
||||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, MB_SLAVE_FMT(", critical error=%d."),
|
ESP_LOGE(TAG, MB_SLAVE_FMT(", critical error=%d."),
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*
|
*
|
||||||
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeModbus Libary: ESP32 TCP Port
|
* FreeModbus Libary: ESP32 TCP Port
|
@ -1,17 +1,8 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
*/
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// mbc_tcp_slave.c
|
// mbc_tcp_slave.c
|
||||||
// Implementation of the Modbus controller TCP slave
|
// Implementation of the Modbus controller TCP slave
|
@ -1,17 +1,8 @@
|
|||||||
/* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* you may not use this file except in compliance with the License.
|
*/
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// mbc_tcp_slave.h Modbus controller TCP slave implementation header file
|
// mbc_tcp_slave.h Modbus controller TCP slave implementation header file
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user