diff --git a/.editorconfig b/.editorconfig
index a0fa3eff1..b8f6ef7f8 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -4,10 +4,10 @@ root = true
[{*.patch,syntax_test_*}]
trim_trailing_whitespace = false
-[{*.c,*.cpp,*.h}]
+[{*.c,*.cpp,*.h,*.ino}]
charset = utf-8
-[{*.c,*.cpp,*.h,Makefile}]
+[{*.c,*.cpp,*.h,*.ino,Makefile}]
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
diff --git a/.gitattributes b/.gitattributes
index 2588229e0..83897cba6 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -17,3 +17,5 @@
*.png binary
*.jpg binary
*.fon binary
+*.bin binary
+*.woff binary
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
deleted file mode 100644
index d1eb86105..000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ /dev/null
@@ -1,157 +0,0 @@
-name: 🪲 Report a bug
-description: Create a bug report to help improve Marlin Firmware
-title: "[BUG] (bug summary)"
-body:
- - type: markdown
- attributes:
- value: >
- Do you want to ask a question? Are you looking for support? Please use one of the [support links](https://github.com/MarlinFirmware/Marlin/issues/new/choose).
-
- - type: markdown
- attributes:
- value: |
- **Thank you for reporting a bug in Marlin Firmware!**
-
- ## Before Reporting a Bug
-
- - Read and understand Marlin's [Code of Conduct](https://github.com/MarlinFirmware/Marlin/blob/master/.github/code_of_conduct.md). You are expected to comply with it, including treating everyone with respect.
-
- - Test with the [`bugfix-2.0.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.0.x.zip) to see whether the issue still exists.
-
- ## Instructions
-
- Please follow the instructions below. Failure to do so may result in your issue being closed. See [Contributing to Marlin](https://github.com/MarlinFirmware/Marlin/blob/2.0.x/.github/contributing.md) for additional guidelines.
-
- 1. Provide a good title starting with [BUG].
- 2. Fill out all sections of this bug report form.
- 3. Always attach configuration files so we can build and test your setup.
-
- - type: dropdown
- attributes:
- label: Did you test the latest `bugfix-2.0.x` code?
- description: >-
- Always try the latest code to make sure the issue you are reporting is not already fixed. To download
- the latest code just [click this link](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.0.x.zip).
- options:
- - Yes, and the problem still exists.
- - No, but I will test it now!
- validations:
- required: true
-
- - type: markdown
- attributes:
- value: |
- # Bug Details
-
- - type: textarea
- attributes:
- label: Bug Description
- description: >-
- Describe the bug in this section. Tell us what you were trying to do and what
- happened that you did not expect. Provide a clear and concise description of the
- problem and include as many details as possible.
- placeholder: |
- Marlin doesn't work.
- validations:
- required: true
-
- - type: input
- attributes:
- label: Bug Timeline
- description: Is this a new bug or an old issue? When did it first start?
-
- - type: textarea
- attributes:
- label: Expected behavior
- description: >-
- What did you expect to happen?
- placeholder: I expected it to move left.
-
- - type: textarea
- attributes:
- label: Actual behavior
- description: What actually happened instead?
- placeholder: It moved right instead of left.
-
- - type: textarea
- attributes:
- label: Steps to Reproduce
- description: >-
- Please describe the steps needed to reproduce the issue.
- placeholder: |
- 1. [First Step] ...
- 2. [Second Step] ...
- 3. [and so on] ...
-
- - type: markdown
- attributes:
- value: |
- # Your Setup
-
- - type: input
- attributes:
- label: Version of Marlin Firmware
- description: "See the About Menu on the LCD or the output of `M115`. NOTE: For older releases we only patch critical bugs."
- validations:
- required: true
-
- - type: input
- attributes:
- label: Printer model
- description: Creality Ender 3, Prusa mini, or Kossel Delta?
-
- - type: input
- attributes:
- label: Electronics
- description: Stock electronics, upgrade board, or something else?
-
- - type: input
- attributes:
- label: Add-ons
- description: Please list any hardware add-ons that could be involved.
-
- - type: dropdown
- attributes:
- label: Your Slicer
- description: Do you use Slic3r, Prusa Slicer, Simplify3D, IdeaMaker...?
- options:
- - Slic3r
- - Simplify3D
- - Prusa Slicer
- - IdeaMaker
- - Cura
- - Other (explain below)
-
- - type: dropdown
- attributes:
- label: Host Software
- description: Do you use OctoPrint, Repetier Host, Pronterface...?
- options:
- - SD Card (headless)
- - Repetier Host
- - OctoPrint
- - Pronterface
- - Cura
- - Same as my slicer
- - Other (explain below)
-
- - type: markdown
- attributes:
- value: >-
- ## Other things to include
-
- Please also be sure to include these items to help with troubleshooting:
-
- * **A ZIP file** containing your `Configuration.h` and `Configuration_adv.h`.
- (Please don't paste lengthy configuration text here.)
- * **Log output** from the host. (`M111 S247` for maximum logging.)
- * **Images or videos** demonstrating the problem, if it helps to make it clear.
- * **A G-Code file** that exposes the problem, if not affecting _all_ G-code.
-
- If you've made any other modifications to the firmware, please describe them in detail in the space provided.
-
- When pasting formatted text into the box below don't forget to put ` ``` ` (on its own line) before and after to make it readable.
-
- - type: textarea
- attributes:
- label: Additional information & file uploads
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
deleted file mode 100644
index 3f5d6fe55..000000000
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-blank_issues_enabled: false
-contact_links:
- - name: 📖 Marlin Documentation
- url: http://marlinfw.org/
- about: Lots of documentation on installing and using Marlin.
- - name: 👤 MarlinFirmware Facebook group
- url: https://www.facebook.com/groups/1049718498464482
- about: Please ask and answer questions here.
- - name: 🕹 Marlin on Discord
- url: https://discord.gg/n5NJ59y
- about: Join the Discord server for support and discussion.
- - name: 🔗 Marlin Discussion Forum
- url: http://forums.reprap.org/list.php?415
- about: A searchable web forum hosted by RepRap dot org.
- - name: 📺 Marlin Videos on YouTube
- url: https://www.youtube.com/results?search_query=marlin+firmware
- about: Tutorials and more from Marlin users all around the world. Great for new users!
- - name: 💸 Want to donate?
- url: https://www.thinkyhead.com/donate-to-marlin
- about: Please take a look at the various options to support Marlin Firmware's development financially!
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
deleted file mode 100644
index df1938ccd..000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: ✨ Request a feature
-description: Request a new Marlin Firmware feature
-title: "[FR] (feature summary)"
-labels: 'T: Feature Request'
-body:
- - type: markdown
- attributes:
- value: >
- Do you want to ask a question? Are you looking for support? Please use one of the [support links](https://github.com/MarlinFirmware/Marlin/issues/new/choose).
-
- - type: markdown
- attributes:
- value: >
- **Thank you for requesting a new Marlin Firmware feature!**
-
- ## Before Requesting a Feature
-
- - Read and understand Marlin's [Code of Conduct](https://github.com/MarlinFirmware/Marlin/blob/master/.github/code_of_conduct.md). You are expected to comply with it, including treating everyone with respect.
-
- - Check the latest [`bugfix-2.0.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.0.x.zip) to see if the feature already exists.
-
- - Before you proceed with your request, please consider if it is necessary to make it into a firmware feature, or if it may be better suited for a slicer or host feature.
-
- - type: textarea
- attributes:
- label: Is your feature request related to a problem? Please describe.
- description: A clear description of the problem (e.g., "I need X but Marlin can't do it [...]").
-
- - type: textarea
- attributes:
- label: Are you looking for hardware support?
- description: Tell us the printer, board, or peripheral that needs support.
-
- - type: textarea
- attributes:
- label: Describe the feature you want
- description: A clear description of the feature and how you think it should work.
- validations:
- required: true
-
- - type: textarea
- attributes:
- label: Additional context
- description: Add any other context or screenshots about the feature request here.
diff --git a/.github/issue_template.md b/.github/issue_template.md
index a211ca5e2..6cb34b8f5 100644
--- a/.github/issue_template.md
+++ b/.github/issue_template.md
@@ -1,11 +1,35 @@
-# NO SUPPORT REQUESTS PLEASE
+
+
+### Description
+
+
+
+### Steps to Reproduce
+
+
+
+1. [First Step]
+2. [Second Step]
+3. [and so on...]
+
+**Expected behavior:** [What you expect to happen]
+
+**Actual behavior:** [What actually happens]
+
+#### Additional Information
+
+* Include a ZIP file containing your `Configuration.h` and `Configuration_adv.h` files.
+* Provide pictures or links to videos that clearly demonstrate the issue.
+* See [How Can I Contribute](#how-can-i-contribute) for additional guidelines.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index cd5158b3c..d82fb0f9e 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,33 +1,23 @@
-
+* Filling out this template is required. Pull Requests without a clear description may be closed at the maintainers' discretion.
### Description
-### Requirements
-
-
-
### Benefits
-
+
### Configurations
-
+
### Related Issues
-
+
diff --git a/.github/workflows/bump-date.yml b/.github/workflows/bump-date.yml
deleted file mode 100644
index 54902da8c..000000000
--- a/.github/workflows/bump-date.yml
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# bump-date.yml
-# Bump the distribution date once per day
-#
-
-name: Bump Distribution Date
-
-on:
- schedule:
- - cron: '0 0 * * *'
-
-jobs:
- bump_date:
- name: Bump Distribution Date
- if: github.repository == 'MarlinFirmware/Marlin'
-
- runs-on: ubuntu-latest
-
- steps:
-
- - name: Check out bugfix-2.0.x
- uses: actions/checkout@v2
- with:
- ref: bugfix-2.0.x
-
- - name: Bump Distribution Date
- run: |
- # Inline Bump Script
- DIST=$( date +"%Y-%m-%d" )
- eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/src/inc/Version.h" && \
- git config user.name "${GITHUB_ACTOR}" && \
- git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" && \
- git add . && \
- git commit -m "[cron] Bump distribution date ($DIST)" && \
- git push
diff --git a/.github/workflows/check-pr.yml b/.github/workflows/check-pr.yml
deleted file mode 100644
index aa4a2c59c..000000000
--- a/.github/workflows/check-pr.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# check-pr.yml
-# Close PRs directed at release branches
-#
-
-name: PR Bad Target
-
-on:
- pull_request:
- branches:
- - 1.0.x
- - 1.1.x
- - 2.0.x
-
-jobs:
- bad_target:
- name: PR Bad Target
- if: github.repository == 'MarlinFirmware/Marlin'
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: peter-evans/close-pull@v1
- with:
- delete-branch: false
- comment: >
- Thanks for your contribution! Unfortunately we can't accept PRs directed at release branches. We make patches to the bugfix branches and only later do we push them out as releases.
-
- Please redo this PR starting with the `bugfix-2.0.x` branch and be careful to target `bugfix-2.0.x` when resubmitting the PR.
-
- It may help to set your fork's default branch to `bugfix-2.0.x`.
-
- See [this page](http://marlinfw.org/docs/development/getting_started_pull_requests.html) for full instructions.
diff --git a/.github/workflows/clean-closed.yml b/.github/workflows/clean-closed.yml
deleted file mode 100644
index befec4498..000000000
--- a/.github/workflows/clean-closed.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# clean-closed.yml
-# Remove obsolete labels when an Issue or PR is closed
-#
-
-name: Clean Closed
-
-on:
- pull_request:
- types: [closed]
- issues:
- types: [closed]
-
-jobs:
- remove_label:
- runs-on: ubuntu-latest
-
- strategy:
- matrix:
- label:
- - "S: Don't Merge"
- - "S: Hold for 2.1"
- - "S: Please Merge"
- - "S: Please Test"
- - "help wanted"
- - "Needs: Discussion"
- - "Needs: Documentation"
- - "Needs: More Data"
- - "Needs: Patch"
- - "Needs: Testing"
- - "Needs: Work"
-
- steps:
- - uses: actions/checkout@v2
- - name: Remove Labels
- uses: actions-ecosystem/action-remove-labels@v1
- with:
- github_token: ${{ github.token }}
- labels: ${{ matrix.label }}
diff --git a/.github/workflows/close-stale.yml b/.github/workflows/close-stale.yml
deleted file mode 100644
index f017907d2..000000000
--- a/.github/workflows/close-stale.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# close-stale.yml
-# Close open issues after a period of inactivity
-#
-
-name: Close Stale Issues
-
-on:
- schedule:
- - cron: "22 1 * * *"
-
-jobs:
- stale:
- name: Close Stale Issues
- if: github.repository == 'MarlinFirmware/Marlin'
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/stale@v3
- with:
- repo-token: ${{ secrets.GITHUB_TOKEN }}
- stale-issue-message: 'This issue has had no activity in the last 60 days. Please add a reply if you want to keep this issue active, otherwise it will be automatically closed within 10 days.'
- days-before-stale: 60
- days-before-close: 10
- stale-issue-label: 'stale-closing-soon'
- exempt-all-assignees: true
- exempt-issue-labels: 'Bug: Confirmed !,T: Feature Request,Needs: Discussion,Needs: Documentation,Needs: More Data,Needs: Patch,Needs: Work,Needs: Testing,help wanted,no-locking'
diff --git a/.github/workflows/lock-closed.yml b/.github/workflows/lock-closed.yml
deleted file mode 100644
index 811456882..000000000
--- a/.github/workflows/lock-closed.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# lock-closed.yml
-# Lock closed issues after a period of inactivity
-#
-
-name: Lock Closed Issues
-
-on:
- schedule:
- - cron: '0 1/13 * * *'
-
-jobs:
- lock:
- name: Lock Closed Issues
- if: github.repository == 'MarlinFirmware/Marlin'
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: dessant/lock-threads@v2
- with:
- github-token: ${{ github.token }}
- process-only: 'issues'
- issue-lock-inactive-days: '60'
- issue-exclude-created-before: '2017-07-01T00:00:00Z'
- issue-exclude-labels: 'no-locking'
- issue-lock-labels: ''
- issue-lock-comment: >
- This issue has been automatically locked since there
- has not been any recent activity after it was closed.
- Please open a new issue for related bugs.
- issue-lock-reason: ''
diff --git a/.github/workflows/test-builds.yml b/.github/workflows/test-builds.yml
index b22878379..93bda9726 100644
--- a/.github/workflows/test-builds.yml
+++ b/.github/workflows/test-builds.yml
@@ -36,9 +36,11 @@ jobs:
# Base Environments
- DUE
+ - DUE_archim
- esp32
- linux_native
- mega2560
+ - at90usb1286_dfu
- teensy31
- teensy35
- teensy41
@@ -46,13 +48,13 @@ jobs:
# Extended AVR Environments
- - FYSETC_F6_13
+ - FYSETC_F6
- mega1280
- rambo
- sanguino1284p
- sanguino644p
- # Extended STM32 Environments
+ # STM32F1 (Maple) Environments
- STM32F103RC_btt
- STM32F103RC_btt_USB
@@ -62,40 +64,43 @@ jobs:
- STM32F103RC_meeb
- jgaurora_a5s_a1
- STM32F103VE_longer
+ - mks_robin
+ - mks_robin_lite
+ - mks_robin_pro
+ - STM32F103RET6_creality
+ - mks_robin_nano35
+
+ # STM32 (ST) Environments
+
- STM32F407VE_black
- STM32F401VE_STEVAL
- BIGTREE_BTT002
- BIGTREE_SKR_PRO
- BIGTREE_GTR_V1_0
- - mks_robin
- mks_robin_stm32
- ARMED
- FYSETC_S6
- STM32F070CB_malyan
- STM32F070RB_malyan
- malyan_M300
- - mks_robin_lite
- FLYF407ZG
- rumba32
- - mks_robin_pro
- - STM32F103RET6_creality
- LERDGEX
- - mks_robin_nano35
+ - mks_robin_nano35_stm32
+ - NUCLEO_F767ZI
+ - REMRAM_V1
+ - BTT_SKR_SE_BX
+ - chitu_f103
# Put lengthy tests last
- LPC1768
- LPC1769
- # STM32 with non-STM framework. both broken for now. they should use HAL_STM32 which is working.
-
- #- STM32F4
- #- STM32F7
-
# Non-working environment tests
#- at90usb1286_cdc
- #- at90usb1286_dfu
#- STM32F103CB_malyan
+ #- STM32F103RE
#- mks_robin_mini
steps:
@@ -116,8 +121,4 @@ jobs:
- name: Run ${{ matrix.test-platform }} Tests
run: |
- # Inline tests script
- chmod +x buildroot/bin/*
- chmod +x buildroot/tests/*
- export PATH=./buildroot/bin/:./buildroot/tests/:${PATH}
- run_tests . ${{ matrix.test-platform }}
+ make tests-single-ci TEST_TARGET=${{ matrix.test-platform }}
diff --git a/.github/workflows/unlock-reopened.yml b/.github/workflows/unlock-reopened.yml
deleted file mode 100644
index 614ef3fab..000000000
--- a/.github/workflows/unlock-reopened.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# unlock-reopened.yml
-# Unlock an issue whenever it is re-opened
-#
-
-name: "Unlock reopened issue"
-
-on:
- issues:
- types: [reopened]
-
-jobs:
- unlock:
- name: Unlock Reopened
- if: github.repository == 'MarlinFirmware/Marlin'
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: OSDKDev/unlock-issues@v1.1
- with:
- repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.gitignore b/.gitignore
index c163d339d..ac2c9b559 100755
--- a/.gitignore
+++ b/.gitignore
@@ -19,9 +19,9 @@
# along with this program. If not, see .
#
-# Our automatic versioning scheme generates the following file
-# NEVER put it in the repository
+# Generated files
_Version.h
+bdf2u8g
#
# OS
@@ -77,7 +77,6 @@ tags
*.out
*.app
-
#
# C
#
@@ -123,33 +122,10 @@ tags
.gcc-flags.json
/lib/
-# Workaround for Deviot+platformio quirks
-Marlin/lib
-Marlin/platformio.ini
-Marlin/*/platformio.ini
-Marlin/*/*/platformio.ini
-Marlin/*/*/*/platformio.ini
-Marlin/*/*/*/*/platformio.ini
-Marlin/.travis.yml
-Marlin/*/.travis.yml
-Marlin/*/*/.travis.yml
-Marlin/*/*/*/.travis.yml
-Marlin/*/*/*/*/.travis.yml
-Marlin/.gitignore
-Marlin/*/.gitignore
-Marlin/*/*/.gitignore
-Marlin/*/*/*/.gitignore
-Marlin/*/*/*/*/.gitignore
-Marlin/readme.txt
-Marlin/*/readme.txt
-Marlin/*/*/readme.txt
-Marlin/*/*/*/readme.txt
-Marlin/*/*/*/*/readme.txt
-
# Secure Credentials
Configuration_Secure.h
-#Visual Studio
+# Visual Studio
*.sln
*.vcxproj
*.vcxproj.user
@@ -160,27 +136,34 @@ __vm/
.vs/
vc-fileutils.settings
-#Visual Studio Code
+# Visual Studio Code
.vscode
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/*.db
-#cmake
+# cmake
CMakeLists.txt
src/CMakeLists.txt
CMakeListsPrivate.txt
-#CLion
+# CLion
cmake-build-*
-#Eclipse
+# Eclipse
.project
.cproject
.pydevproject
.settings
.classpath
-#Python
+# Python
__pycache__
+
+# IOLogger logs
+*_log.csv
+
+# Simulation / Native
+eeprom.dat
+imgui.ini
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..ebcdf25e2
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,52 @@
+help:
+ @echo "Tasks for local development:"
+ @echo "* tests-single-ci: Run a single test from inside the CI"
+ @echo "* tests-single-local: Run a single test locally"
+ @echo "* tests-single-local-docker: Run a single test locally, using docker-compose"
+ @echo "* tests-all-local: Run all tests locally"
+ @echo "* tests-all-local-docker: Run all tests locally, using docker-compose"
+ @echo "* setup-local-docker: Setup local docker-compose"
+ @echo ""
+ @echo "Options for testing:"
+ @echo " TEST_TARGET Set when running tests-single-*, to select the"
+ @echo " test. If you set it to ALL it will run all "
+ @echo " tests, but some of them are broken: use "
+ @echo " tests-all-* instead to run only the ones that "
+ @echo " run on GitHub CI"
+ @echo " ONLY_TEST Limit tests to only those that contain this, or"
+ @echo " the index of the test (1-based)"
+ @echo " VERBOSE_PLATFORMIO If you want the full PIO output, set any value"
+ @echo " GIT_RESET_HARD Used by CI: reset all local changes. WARNING:"
+ @echo " THIS WILL UNDO ANY CHANGES YOU'VE MADE!"
+.PHONY: help
+
+tests-single-ci:
+ export GIT_RESET_HARD=true
+ $(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET)
+.PHONY: tests-single-ci
+
+tests-single-local:
+ @if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET= or use make tests-all-local" ; return 1; fi
+ export PATH=./buildroot/bin/:./buildroot/tests/:${PATH} \
+ && export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
+ && run_tests . $(TEST_TARGET) "$(ONLY_TEST)"
+.PHONY: tests-single-local
+
+tests-single-local-docker:
+ @if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET= or use make tests-all-local-docker" ; return 1; fi
+ docker-compose run --rm marlin $(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET) VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) ONLY_TEST="$(ONLY_TEST)"
+.PHONY: tests-single-local-docker
+
+tests-all-local:
+ export PATH=./buildroot/bin/:./buildroot/tests/:${PATH} \
+ && export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
+ && for TEST_TARGET in $$(./get_test_targets.py) ; do echo "Running tests for $$TEST_TARGET" ; run_tests . $$TEST_TARGET ; done
+.PHONY: tests-all-local
+
+tests-all-local-docker:
+ docker-compose run --rm marlin $(MAKE) tests-all-local VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD)
+.PHONY: tests-all-local-docker
+
+setup-local-docker:
+ docker-compose build
+.PHONY: setup-local-docker
diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index db266b524..442f502c3 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -35,37 +35,36 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
-#define CONFIGURATION_H_VERSION 020007
+#define CONFIGURATION_H_VERSION 020008
//===========================================================================
//============================= Getting Started =============================
//===========================================================================
/**
- * Here are some standard links for getting your machine calibrated:
+ * Here are some useful links to help get your machine configured and calibrated:
*
- * https://reprap.org/wiki/Calibration
- * https://youtu.be/wAL9d7FgInk
- * http://calculator.josefprusa.cz
- * https://reprap.org/wiki/Triffid_Hunter%27s_Calibration_Guide
- * https://www.thingiverse.com/thing:5573
- * https://sites.google.com/site/repraplogphase/calibration-of-your-reprap
- * https://www.thingiverse.com/thing:298812
+ * Example Configs: https://github.com/MarlinFirmware/Configurations/branches/all
+ *
+ * Průša Calculator: https://blog.prusaprinters.org/calculator_3416/
+ *
+ * Calibration Guides: https://reprap.org/wiki/Calibration
+ * https://reprap.org/wiki/Triffid_Hunter%27s_Calibration_Guide
+ * https://sites.google.com/site/repraplogphase/calibration-of-your-reprap
+ * https://youtu.be/wAL9d7FgInk
+ *
+ * Calibration Objects: https://www.thingiverse.com/thing:5573
+ * https://www.thingiverse.com/thing:1278865
*/
//===========================================================================
-//============================= DELTA Printer ===============================
+//========================== DELTA / SCARA / TPARA ==========================
//===========================================================================
-// For a Delta printer start with one of the configuration files in the
-// config/examples/delta directory and customize for your machine.
//
-
-//===========================================================================
-//============================= SCARA Printer ===============================
-//===========================================================================
-// For a SCARA printer start with the configuration files in
-// config/examples/SCARA and customize for your machine.
+// Download configurations from the link above and customize for your machine.
+// Examples are located in config/examples/delta, .../SCARA, and .../TPARA.
//
+//===========================================================================
// @section info
@@ -107,7 +106,8 @@
/**
* Select a secondary serial port on the board to use for communication with the host.
- * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+ * Currently Ethernet (-2) is only supported on Teensy 4.1 boards.
+ * :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_2 -1
@@ -157,33 +157,19 @@
#endif
/**
- * Průša MK2 Single Nozzle Multi-Material Multiplexer, and variants.
+ * Multi-Material Unit
+ * Set to one of these predefined models:
*
- * This device allows one stepper driver on a control board to drive
- * two to eight stepper motors, one at a time, in a manner suitable
- * for extruders.
- *
- * This option only allows the multiplexer to switch on tool-change.
- * Additional options to configure custom E moves are pending.
- */
-//#define MK2_MULTIPLEXER
-#if ENABLED(MK2_MULTIPLEXER)
- // Override the default DIO selector pins here, if needed.
- // Some pins files may provide defaults for these pins.
- //#define E_MUX0_PIN 40 // Always Required
- //#define E_MUX1_PIN 42 // Needed for 3 to 8 inputs
- //#define E_MUX2_PIN 44 // Needed for 5 to 8 inputs
-#endif
-
-/**
- * Průša Multi-Material Unit v2
+ * PRUSA_MMU1 : Průša MMU1 (The "multiplexer" version)
+ * PRUSA_MMU2 : Průša MMU2
+ * PRUSA_MMU2S : Průša MMU2S (Requires MK3S extruder with motion sensor, EXTRUDERS = 5)
+ * EXTENDABLE_EMU_MMU2 : MMU with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware)
+ * EXTENDABLE_EMU_MMU2S : MMUS with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware)
*
* Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
- * Requires EXTRUDERS = 5
- *
- * For additional configuration see Configuration_adv.h
+ * See additional options in Configuration_adv.h.
*/
-//#define PRUSA_MMU2
+//#define MMU_MODEL PRUSA_MMU2
// A dual extruder that uses a single stepper motor
//#define SWITCHING_EXTRUDER
@@ -334,15 +320,21 @@
//#define PSU_DEFAULT_OFF // Keep power off until enabled directly with M80
//#define PSU_POWERUP_DELAY 250 // (ms) Delay for the PSU to warm up to full power
+ //#define PSU_POWERUP_GCODE "M355 S1" // G-code to run after power-on (e.g., case light on)
+ //#define PSU_POWEROFF_GCODE "M355 S0" // G-code to run before power-off (e.g., case light off)
+
//#define AUTO_POWER_CONTROL // Enable automatic control of the PS_ON pin
#if ENABLED(AUTO_POWER_CONTROL)
#define AUTO_POWER_FANS // Turn on PSU if fans need power
#define AUTO_POWER_E_FANS
#define AUTO_POWER_CONTROLLERFAN
#define AUTO_POWER_CHAMBER_FAN
- //#define AUTO_POWER_E_TEMP 50 // (°C) Turn on PSU over this temperature
- //#define AUTO_POWER_CHAMBER_TEMP 30 // (°C) Turn on PSU over this temperature
- #define POWER_TIMEOUT 30
+ #define AUTO_POWER_COOLER_FAN
+ //#define AUTO_POWER_E_TEMP 50 // (°C) Turn on PSU if any extruder is over this temperature
+ //#define AUTO_POWER_CHAMBER_TEMP 30 // (°C) Turn on PSU if the chamber is over this temperature
+ //#define AUTO_POWER_COOLER_TEMP 26 // (°C) Turn on PSU if the cooler is over this temperature
+ #define POWER_TIMEOUT 30 // (s) Turn off power if the machine is idle for this duration
+ //#define POWER_OFF_DELAY 60 // (s) Delay of poweroff after M81 command. Useful to let fans run for extra time.
#endif
#endif
@@ -384,8 +376,10 @@
* 13 : 100k Hisens 3950 1% up to 300°C for hotend "Simple ONE " & "Hotend "All In ONE"
* 15 : 100k thermistor calibration for JGAurora A5 hotend
* 18 : ATC Semitec 204GT-2 (4.7k pullup) Dagoma.Fr - MKS_Base_DKU001327
- * 20 : Pt100 with circuit in the Ultimainboard V2.x with 5v excitation (AVR)
- * 21 : Pt100 with circuit in the Ultimainboard V2.x with 3.3v excitation (STM32 \ LPC176x....)
+ * 20 : Pt100 with circuit in the Ultimainboard V2.x with mainboard ADC reference voltage = INA826 amplifier-board supply voltage.
+ * NOTES: (1) Must use an ADC input with no pullup. (2) Some INA826 amplifiers are unreliable at 3.3V so consider using sensor 147, 110, or 21.
+ * 21 : Pt100 with circuit in the Ultimainboard V2.x with 3.3v ADC reference voltage (STM32, LPC176x....) and 5V INA826 amplifier board supply.
+ * NOTE: ADC pins are not 5V tolerant. Not recommended because it's possible to damage the CPU by going over 500°C.
* 22 : 100k (hotend) with 4.7k pullup to 3.3V and 220R to analog input (as in GTM32 Pro vB)
* 23 : 100k (bed) with 4.7k pullup to 3.3v and 220R to analog input (as in GTM32 Pro vB)
* 30 : Kis3d Silicone heating mat 200W/300W with 6mm precision cast plate (EN AW 5083) NTC100K / B3950 (4.7k pullup)
@@ -426,29 +420,34 @@
#define TEMP_SENSOR_BED 0
#define TEMP_SENSOR_PROBE 0
#define TEMP_SENSOR_CHAMBER 0
+#define TEMP_SENSOR_COOLER 0
// Dummy thermistor constant temperature readings, for use with 998 and 999
-#define DUMMY_THERMISTOR_998_VALUE 25
+#define DUMMY_THERMISTOR_998_VALUE 25
#define DUMMY_THERMISTOR_999_VALUE 100
-// Resistor values when using a MAX31865 (sensor -5)
-// Sensor value is typically 100 (PT100) or 1000 (PT1000)
-// Calibration value is typically 430 ohm for AdaFruit PT100 modules and 4300 ohm for AdaFruit PT1000 modules.
-//#define MAX31865_SENSOR_OHMS 100
-//#define MAX31865_CALIBRATION_OHMS 430
+// Resistor values when using MAX31865 sensors (-5) on TEMP_SENSOR_0 / 1
+//#define MAX31865_SENSOR_OHMS_0 100 // (Ω) Typically 100 or 1000 (PT100 or PT1000)
+//#define MAX31865_CALIBRATION_OHMS_0 430 // (Ω) Typically 430 for AdaFruit PT100; 4300 for AdaFruit PT1000
+//#define MAX31865_SENSOR_OHMS_1 100
+//#define MAX31865_CALIBRATION_OHMS_1 430
// Use temp sensor 1 as a redundant sensor with sensor 0. If the readings
// from the two sensors differ too much the print will be aborted.
//#define TEMP_SENSOR_1_AS_REDUNDANT
#define MAX_REDUNDANT_TEMP_SENSOR_DIFF 10
-#define TEMP_RESIDENCY_TIME 10 // (seconds) Time to wait for hotend to "settle" in M109
-#define TEMP_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
-#define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
+#define TEMP_RESIDENCY_TIME 10 // (seconds) Time to wait for hotend to "settle" in M109
+#define TEMP_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
+#define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
-#define TEMP_BED_RESIDENCY_TIME 10 // (seconds) Time to wait for bed to "settle" in M190
-#define TEMP_BED_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
-#define TEMP_BED_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
+#define TEMP_BED_RESIDENCY_TIME 10 // (seconds) Time to wait for bed to "settle" in M190
+#define TEMP_BED_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
+#define TEMP_BED_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
+
+#define TEMP_CHAMBER_RESIDENCY_TIME 10 // (seconds) Time to wait for chamber to "settle" in M191
+#define TEMP_CHAMBER_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
+#define TEMP_CHAMBER_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
// Below this temperature the heater will be switched off
// because it probably indicates a broken thermistor wire.
@@ -461,6 +460,7 @@
#define HEATER_6_MINTEMP 5
#define HEATER_7_MINTEMP 5
#define BED_MINTEMP 5
+#define CHAMBER_MINTEMP 5
// Above this temperature the heater will be switched off.
// This can protect components from overheating, but NOT from shorts and failures.
@@ -474,6 +474,17 @@
#define HEATER_6_MAXTEMP 275
#define HEATER_7_MAXTEMP 275
#define BED_MAXTEMP 150
+#define CHAMBER_MAXTEMP 60
+
+/**
+ * Thermal Overshoot
+ * During heatup (and printing) the temperature can often "overshoot" the target by many degrees
+ * (especially before PID tuning). Setting the target temperature too close to MAXTEMP guarantees
+ * a MAXTEMP shutdown! Use these values to forbid temperatures being set too close to MAXTEMP.
+ */
+#define HOTEND_OVERSHOOT 15 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
+#define BED_OVERSHOOT 10 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
+#define COOLER_OVERSHOOT 2 // (°C) Forbid temperatures closer than OVERSHOOT
//===========================================================================
//============================= PID Settings ================================
@@ -547,7 +558,51 @@
// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
#endif // PIDTEMPBED
-#if EITHER(PIDTEMP, PIDTEMPBED)
+//===========================================================================
+//==================== PID > Chamber Temperature Control ====================
+//===========================================================================
+
+/**
+ * PID Chamber Heating
+ *
+ * If this option is enabled set PID constants below.
+ * If this option is disabled, bang-bang will be used and CHAMBER_LIMIT_SWITCHING will enable
+ * hysteresis.
+ *
+ * The PID frequency will be the same as the extruder PWM.
+ * If PID_dT is the default, and correct for the hardware/configuration, that means 7.689Hz,
+ * which is fine for driving a square wave into a resistive load and does not significantly
+ * impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 200W
+ * heater. If your configuration is significantly different than this and you don't understand
+ * the issues involved, don't use chamber PID until someone else verifies that your hardware works.
+ */
+//#define PIDTEMPCHAMBER
+//#define CHAMBER_LIMIT_SWITCHING
+
+/**
+ * Max Chamber Power
+ * Applies to all forms of chamber control (PID, bang-bang, and bang-bang with hysteresis).
+ * When set to any value below 255, enables a form of PWM to the chamber heater that acts like a divider
+ * so don't use it unless you are OK with PWM on your heater. (See the comment on enabling PIDTEMPCHAMBER)
+ */
+#define MAX_CHAMBER_POWER 255 // limits duty cycle to chamber heater; 255=full current
+
+#if ENABLED(PIDTEMPCHAMBER)
+ #define MIN_CHAMBER_POWER 0
+ //#define PID_CHAMBER_DEBUG // Sends debug data to the serial port.
+
+ // Lasko "MyHeat Personal Heater" (200w) modified with a Fotek SSR-10DA to control only the heating element
+ // and placed inside the small Creality printer enclosure tent.
+ //
+ #define DEFAULT_chamberKp 37.04
+ #define DEFAULT_chamberKi 1.40
+ #define DEFAULT_chamberKd 655.17
+ // M309 P37.04 I1.04 D655.17
+
+ // FIND YOUR OWN: "M303 E-2 C8 S50" to run autotune on the chamber at 50 degreesC for 8 cycles.
+#endif // PIDTEMPCHAMBER
+
+#if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER)
//#define PID_DEBUG // Sends debug data to the serial port. Use 'M303 D' to toggle activation.
//#define PID_OPENLOOP // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
//#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay
@@ -594,6 +649,7 @@
#define THERMAL_PROTECTION_HOTENDS // Enable thermal protection for all extruders
#define THERMAL_PROTECTION_BED // Enable thermal protection for the heated bed
#define THERMAL_PROTECTION_CHAMBER // Enable thermal protection for the heated chamber
+#define THERMAL_PROTECTION_COOLER // Enable thermal protection for the laser cooling
//===========================================================================
//============================= Mechanical Settings =========================
@@ -670,6 +726,8 @@
*
* A4988 is assumed for unspecified drivers.
*
+ * Use TMC2208/TMC2208_STANDALONE for TMC2225 drivers and TMC2209/TMC2209_STANDALONE for TMC2226 drivers.
+ *
* Options: A4988, A5984, DRV8825, LV8729, L6470, L6474, POWERSTEP01,
* TB6560, TB6600, TMC2100,
* TMC2130, TMC2130_STANDALONE, TMC2160, TMC2160_STANDALONE,
@@ -678,15 +736,15 @@
* TMC5130, TMC5130_STANDALONE, TMC5160, TMC5160_STANDALONE
* :['A4988', 'A5984', 'DRV8825', 'LV8729', 'L6470', 'L6474', 'POWERSTEP01', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC26X', 'TMC26X_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
*/
-//#define X_DRIVER_TYPE A4988
-//#define Y_DRIVER_TYPE A4988
-//#define Z_DRIVER_TYPE A4988
+#define X_DRIVER_TYPE A4988
+#define Y_DRIVER_TYPE A4988
+#define Z_DRIVER_TYPE A4988
//#define X2_DRIVER_TYPE A4988
//#define Y2_DRIVER_TYPE A4988
//#define Z2_DRIVER_TYPE A4988
//#define Z3_DRIVER_TYPE A4988
//#define Z4_DRIVER_TYPE A4988
-//#define E0_DRIVER_TYPE A4988
+#define E0_DRIVER_TYPE A4988
//#define E1_DRIVER_TYPE A4988
//#define E2_DRIVER_TYPE A4988
//#define E3_DRIVER_TYPE A4988
@@ -741,7 +799,7 @@
* Override with M92
* X, Y, Z, E0 [, E1[, E2...]]
*/
-#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 4000, 500 }
+#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 500 }
/**
* Default Max Feed Rate (mm/s)
@@ -876,7 +934,6 @@
* or (with LCD_BED_LEVELING) the LCD controller.
*/
//#define PROBE_MANUALLY
-//#define MANUAL_PROBE_START_Z 0.2
/**
* A Fix-Mounted Probe either doesn't deploy or needs manual deployment.
@@ -901,11 +958,6 @@
*/
//#define BLTOUCH
-/**
- * Pressure sensor with a BLTouch-like interface
- */
-//#define CREALITY_TOUCH
-
/**
* Touch-MI Probe by hotends.fr
*
@@ -959,10 +1011,20 @@
/**
* Nozzle-to-Probe offsets { X, Y, Z }
*
- * - Use a caliper or ruler to measure the distance from the tip of
+ * X and Y offset
+ * Use a caliper or ruler to measure the distance from the tip of
* the Nozzle to the center-point of the Probe in the X and Y axes.
+ *
+ * Z offset
* - For the Z offset use your best known value and adjust at runtime.
- * - Probe Offsets can be tuned at runtime with 'M851', LCD menus, babystepping, etc.
+ * - Common probes trigger below the nozzle and have negative values for Z offset.
+ * - Probes triggering above the nozzle height are uncommon but do exist. When using
+ * probes such as this, carefully set Z_CLEARANCE_DEPLOY_PROBE and Z_CLEARANCE_BETWEEN_PROBES
+ * to avoid collisions during probing.
+ *
+ * Tune and Adjust
+ * - Probe Offsets can be tuned at runtime with 'M851', LCD menus, babystepping, etc.
+ * - PROBE_OFFSET_WIZARD (configuration_adv.h) can be used for setting the Z offset.
*
* Assuming the typical work area orientation:
* - Probe to RIGHT of the Nozzle has a Positive X offset
@@ -993,13 +1055,40 @@
#define PROBING_MARGIN 10
// X and Y axis travel speed (mm/min) between probes
-#define XY_PROBE_SPEED (133*60)
+#define XY_PROBE_FEEDRATE (133*60)
// Feedrate (mm/min) for the first approach when double-probing (MULTIPLE_PROBING == 2)
-#define Z_PROBE_SPEED_FAST HOMING_FEEDRATE_Z
+#define Z_PROBE_FEEDRATE_FAST (4*60)
// Feedrate (mm/min) for the "accurate" probe of each point
-#define Z_PROBE_SPEED_SLOW (Z_PROBE_SPEED_FAST / 2)
+#define Z_PROBE_FEEDRATE_SLOW (Z_PROBE_FEEDRATE_FAST / 2)
+
+/**
+ * Probe Activation Switch
+ * A switch indicating proper deployment, or an optical
+ * switch triggered when the carriage is near the bed.
+ */
+//#define PROBE_ACTIVATION_SWITCH
+#if ENABLED(PROBE_ACTIVATION_SWITCH)
+ #define PROBE_ACTIVATION_SWITCH_STATE LOW // State indicating probe is active
+ //#define PROBE_ACTIVATION_SWITCH_PIN PC6 // Override default pin
+#endif
+
+/**
+ * Tare Probe (determine zero-point) prior to each probe.
+ * Useful for a strain gauge or piezo sensor that needs to factor out
+ * elements such as cables pulling on the carriage.
+ */
+//#define PROBE_TARE
+#if ENABLED(PROBE_TARE)
+ #define PROBE_TARE_TIME 200 // (ms) Time to hold tare pin
+ #define PROBE_TARE_DELAY 200 // (ms) Delay after tare before
+ #define PROBE_TARE_STATE HIGH // State to write pin for tare
+ //#define PROBE_TARE_PIN PA5 // Override default pin
+ #if ENABLED(PROBE_ACTIVATION_SWITCH)
+ //#define PROBE_TARE_ONLY_WHILE_INACTIVE // Fail to tare/probe if PROBE_ACTIVATION_SWITCH is active
+ #endif
+#endif
/**
* Multiple Probing
@@ -1057,11 +1146,19 @@
//#define PROBING_HEATERS_OFF // Turn heaters off when probing
#if ENABLED(PROBING_HEATERS_OFF)
//#define WAIT_FOR_BED_HEATER // Wait for bed to heat back up between probes (to improve accuracy)
+ //#define WAIT_FOR_HOTEND // Wait for hotend to heat back up between probes (to improve accuracy & prevent cold extrude)
#endif
//#define PROBING_FANS_OFF // Turn fans off when probing
//#define PROBING_STEPPERS_OFF // Turn steppers off (unless needed to hold position) when probing
//#define DELAY_BEFORE_PROBING 200 // (ms) To prevent vibrations from triggering piezo sensors
+// Require minimum nozzle and/or bed temperature for probing
+//#define PREHEAT_BEFORE_PROBING
+#if ENABLED(PREHEAT_BEFORE_PROBING)
+ #define PROBING_NOZZLE_TEMP 120 // (°C) Only applies to E0 at this time
+ #define PROBING_BED_TEMP 50
+#endif
+
// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
// :{ 0:'Low', 1:'High' }
#define X_ENABLE_ON 0
@@ -1104,9 +1201,15 @@
// @section homing
-//#define NO_MOTION_BEFORE_HOMING // Inhibit movement until all axes have been homed
+//#define NO_MOTION_BEFORE_HOMING // Inhibit movement until all axes have been homed. Also enable HOME_AFTER_DEACTIVATE for extra safety.
+//#define HOME_AFTER_DEACTIVATE // Require rehoming after steppers are deactivated. Also enable NO_MOTION_BEFORE_HOMING for extra safety.
-//#define UNKNOWN_Z_NO_RAISE // Don't raise Z (lower the bed) if Z is "unknown." For beds that fall when Z is powered off.
+/**
+ * Set Z_IDLE_HEIGHT if the Z-Axis moves on its own when steppers are disabled.
+ * - Use a low value (i.e., Z_MIN_POS) if the nozzle falls down to the bed.
+ * - Use a large value (i.e., Z_MAX_POS) if the bed falls down, away from the nozzle.
+ */
+//#define Z_IDLE_HEIGHT Z_HOME_POS
//#define Z_HOMING_HEIGHT 4 // (mm) Minimal Z height before homing (G28) for Z clearance above the bed, clamps, ...
// Be sure to have this much clearance over your Z_MAX_POS to prevent grinding.
@@ -1121,7 +1224,7 @@
// @section machine
-// The size of the print bed
+// The size of the printable area
#define X_BED_SIZE 200
#define Y_BED_SIZE 200
@@ -1166,6 +1269,12 @@
* Filament Runout Sensors
* Mechanical or opto endstops are used to check for the presence of filament.
*
+ * IMPORTANT: Runout will only trigger if Marlin is aware that a print job is running.
+ * Marlin knows a print job is running when:
+ * 1. Running a print job from media started with M24.
+ * 2. The Print Job Timer has been started with M75.
+ * 3. The heaters were turned on and PRINTJOB_TIMER_AUTOSTART is enabled.
+ *
* RAMPS-based boards use SERVO3_PIN for the first runout sensor.
* For other boards you may need to define FIL_RUNOUT_PIN, FIL_RUNOUT2_PIN, etc.
*/
@@ -1173,12 +1282,49 @@
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#define FIL_RUNOUT_ENABLED_DEFAULT true // Enable the sensor on startup. Override with M412 followed by M500.
#define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each.
+
#define FIL_RUNOUT_STATE LOW // Pin state indicating that filament is NOT present.
#define FIL_RUNOUT_PULLUP // Use internal pullup for filament runout pins.
//#define FIL_RUNOUT_PULLDOWN // Use internal pulldown for filament runout pins.
+ //#define WATCH_ALL_RUNOUT_SENSORS // Execute runout script on any triggering sensor, not only for the active extruder.
+ // This is automatically enabled for MIXING_EXTRUDERs.
- // Set one or more commands to execute on filament runout.
- // (After 'M412 H' Marlin will ask the host to handle the process.)
+ // Override individually if the runout sensors vary
+ //#define FIL_RUNOUT1_STATE LOW
+ //#define FIL_RUNOUT1_PULLUP
+ //#define FIL_RUNOUT1_PULLDOWN
+
+ //#define FIL_RUNOUT2_STATE LOW
+ //#define FIL_RUNOUT2_PULLUP
+ //#define FIL_RUNOUT2_PULLDOWN
+
+ //#define FIL_RUNOUT3_STATE LOW
+ //#define FIL_RUNOUT3_PULLUP
+ //#define FIL_RUNOUT3_PULLDOWN
+
+ //#define FIL_RUNOUT4_STATE LOW
+ //#define FIL_RUNOUT4_PULLUP
+ //#define FIL_RUNOUT4_PULLDOWN
+
+ //#define FIL_RUNOUT5_STATE LOW
+ //#define FIL_RUNOUT5_PULLUP
+ //#define FIL_RUNOUT5_PULLDOWN
+
+ //#define FIL_RUNOUT6_STATE LOW
+ //#define FIL_RUNOUT6_PULLUP
+ //#define FIL_RUNOUT6_PULLDOWN
+
+ //#define FIL_RUNOUT7_STATE LOW
+ //#define FIL_RUNOUT7_PULLUP
+ //#define FIL_RUNOUT7_PULLDOWN
+
+ //#define FIL_RUNOUT8_STATE LOW
+ //#define FIL_RUNOUT8_PULLUP
+ //#define FIL_RUNOUT8_PULLDOWN
+
+ // Commands to execute on filament runout.
+ // With multiple runout sensors use the %c placeholder for the current tool in commands (e.g., "M600 T%c")
+ // NOTE: After 'M412 H1' the host handles filament runout and this script does not apply.
#define FILAMENT_RUNOUT_SCRIPT "M600"
// After a runout is detected, continue printing this length of filament
@@ -1239,10 +1385,21 @@
//#define MESH_BED_LEVELING
/**
- * Normally G28 leaves leveling disabled on completion. Enable
- * this option to have G28 restore the prior leveling state.
+ * Normally G28 leaves leveling disabled on completion. Enable one of
+ * these options to restore the prior leveling state or to always enable
+ * leveling immediately after G28.
*/
//#define RESTORE_LEVELING_AFTER_G28
+//#define ENABLE_LEVELING_AFTER_G28
+
+/**
+ * Auto-leveling needs preheating
+ */
+//#define PREHEAT_BEFORE_LEVELING
+#if ENABLED(PREHEAT_BEFORE_LEVELING)
+ #define LEVELING_NOZZLE_TEMP 120 // (°C) Only applies to E0 at this time
+ #define LEVELING_BED_TEMP 50
+#endif
/**
* Enable detailed logging of G28, G29, M48, etc.
@@ -1251,11 +1408,19 @@
*/
//#define DEBUG_LEVELING_FEATURE
+#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL, PROBE_MANUALLY)
+ // Set a height for the start of manual adjustment
+ #define MANUAL_PROBE_START_Z 0.2 // (mm) Comment out to use the last-measured height
+#endif
+
#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_UBL)
// Gradually reduce leveling correction until a set height is reached,
// at which point movement will be level to the machine's XY plane.
// The height can be set with M420 Z
#define ENABLE_LEVELING_FADE_HEIGHT
+ #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
+ #define DEFAULT_LEVELING_FADE_HEIGHT 10.0 // (mm) Default fade height.
+ #endif
// For Cartesian machines, instead of dividing moves on mesh boundaries,
// split up moves into short segments like a Delta. This follows the
@@ -1269,10 +1434,11 @@
//#define G26_MESH_VALIDATION
#if ENABLED(G26_MESH_VALIDATION)
#define MESH_TEST_NOZZLE_SIZE 0.4 // (mm) Diameter of primary nozzle.
- #define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for the G26 Mesh Validation Tool.
- #define MESH_TEST_HOTEND_TEMP 205 // (°C) Default nozzle temperature for the G26 Mesh Validation Tool.
- #define MESH_TEST_BED_TEMP 60 // (°C) Default bed temperature for the G26 Mesh Validation Tool.
- #define G26_XY_FEEDRATE 20 // (mm/s) Feedrate for XY Moves for the G26 Mesh Validation Tool.
+ #define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for G26.
+ #define MESH_TEST_HOTEND_TEMP 205 // (°C) Default nozzle temperature for G26.
+ #define MESH_TEST_BED_TEMP 60 // (°C) Default bed temperature for G26.
+ #define G26_XY_FEEDRATE 20 // (mm/s) Feedrate for G26 XY moves.
+ #define G26_XY_FEEDRATE_TRAVEL 100 // (mm/s) Feedrate for G26 XY travel moves.
#define G26_RETRACT_MULTIPLIER 1.0 // G26 Q (retraction) used by default between mesh test elements.
#endif
@@ -1317,6 +1483,8 @@
#define GRID_MAX_POINTS_X 10 // Don't use more than 15 points per axis, implementation limited.
#define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
+ //#define UBL_HILBERT_CURVE // Use Hilbert distribution for less travel when probing multiple points
+
#define UBL_MESH_EDIT_MOVES_Z // Sophisticated users prefer no movement of nozzle
#define UBL_SAVE_ACTIVE_ON_M500 // Save the currently active mesh in the current slot on M500
@@ -1357,6 +1525,31 @@
#define LEVEL_CORNERS_HEIGHT 0.0 // (mm) Z height of nozzle at leveling points
#define LEVEL_CORNERS_Z_HOP 4.0 // (mm) Z height of nozzle between leveling points
//#define LEVEL_CENTER_TOO // Move to the center after the last corner
+ //#define LEVEL_CORNERS_USE_PROBE
+ #if ENABLED(LEVEL_CORNERS_USE_PROBE)
+ #define LEVEL_CORNERS_PROBE_TOLERANCE 0.1
+ #define LEVEL_CORNERS_VERIFY_RAISED // After adjustment triggers the probe, re-probe to verify
+ //#define LEVEL_CORNERS_AUDIO_FEEDBACK
+ #endif
+
+ /**
+ * Corner Leveling Order
+ *
+ * Set 2 or 4 points. When 2 points are given, the 3rd is the center of the opposite edge.
+ *
+ * LF Left-Front RF Right-Front
+ * LB Left-Back RB Right-Back
+ *
+ * Examples:
+ *
+ * Default {LF,RB,LB,RF} {LF,RF} {LB,LF}
+ * LB --------- RB LB --------- RB LB --------- RB LB --------- RB
+ * | 4 3 | | 3 2 | | <3> | | 1 |
+ * | | | | | | | <3>|
+ * | 1 2 | | 1 4 | | 1 2 | | 2 |
+ * LF --------- RF LF --------- RF LF --------- RF LF --------- RF
+ */
+ #define LEVEL_CORNERS_LEVELING_ORDER { LF, RF, RB, LB }
#endif
/**
@@ -1393,8 +1586,7 @@
#endif
// Homing speeds (mm/min)
-#define HOMING_FEEDRATE_XY (50*60)
-#define HOMING_FEEDRATE_Z (4*60)
+#define HOMING_FEEDRATE_MM_M { (50*60), (50*60), (4*60) }
// Validate that endstops are triggered on homing moves
#define VALIDATE_HOMING_ENDSTOPS
@@ -1501,15 +1693,19 @@
// @section temperature
-// Preheat Constants
+//
+// Preheat Constants - Up to 5 are supported without changes
+//
#define PREHEAT_1_LABEL "PLA"
#define PREHEAT_1_TEMP_HOTEND 180
#define PREHEAT_1_TEMP_BED 70
+#define PREHEAT_1_TEMP_CHAMBER 35
#define PREHEAT_1_FAN_SPEED 0 // Value from 0 to 255
#define PREHEAT_2_LABEL "ABS"
#define PREHEAT_2_TEMP_HOTEND 240
#define PREHEAT_2_TEMP_BED 110
+#define PREHEAT_2_TEMP_CHAMBER 35
#define PREHEAT_2_FAN_SPEED 0 // Value from 0 to 255
/**
@@ -1602,6 +1798,10 @@
// For a purge/clean station mounted on the X axis
//#define NOZZLE_CLEAN_NO_Y
+ // Require a minimum hotend temperature for cleaning
+ #define NOZZLE_CLEAN_MIN_TEMP 170
+ //#define NOZZLE_CLEAN_HEATUP // Heat up the nozzle instead of skipping wipe
+
// Explicit wipe G-code script applies to a G12 with no arguments.
//#define WIPE_SEQUENCE_COMMANDS "G1 X-17 Y25 Z10 F4000\nG1 Z1\nM114\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 Z15\nM400\nG0 X-10.0 Y-9.0"
@@ -1637,6 +1837,9 @@
* View the current statistics with M78.
*/
//#define PRINTCOUNTER
+#if ENABLED(PRINTCOUNTER)
+ #define PRINTCOUNTER_SAVE_INTERVAL 60 // (minutes) EEPROM save interval during print
+#endif
/**
* Password
@@ -1681,9 +1884,9 @@
* Select the language to display on the LCD. These languages are available:
*
* en, an, bg, ca, cz, da, de, el, el_gr, es, eu, fi, fr, gl, hr, hu, it,
- * jp_kana, ko_KR, nl, pl, pt, pt_br, ro, ru, sk, tr, uk, vi, zh_CN, zh_TW, test
+ * jp_kana, ko_KR, nl, pl, pt, pt_br, ro, ru, sk, sv, tr, uk, vi, zh_CN, zh_TW
*
- * :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek', 'el_gr':'Greek (Greece)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hr':'Croatian', 'hu':'Hungarian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ro':'Romanian', 'ru':'Russian', 'sk':'Slovak', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)', 'test':'TEST' }
+ * :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek', 'el_gr':'Greek (Greece)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hr':'Croatian', 'hu':'Hungarian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ro':'Romanian', 'ru':'Russian', 'sk':'Slovak', 'sv':'Swedish', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)' }
*/
#define LCD_LANGUAGE en
@@ -1726,16 +1929,6 @@
*/
//#define SDSUPPORT
-/**
- * SD CARD: SPI SPEED
- *
- * Enable one of the following items for a slower SPI transfer speed.
- * This may be required to resolve "volume init" errors.
- */
-//#define SPI_SPEED SPI_HALF_SPEED
-//#define SPI_SPEED SPI_QUARTER_SPEED
-//#define SPI_SPEED SPI_EIGHTH_SPEED
-
/**
* SD CARD: ENABLE CRC
*
@@ -1837,6 +2030,14 @@
//
//#define REPRAP_DISCOUNT_SMART_CONTROLLER
+//
+// GT2560 (YHCB2004) LCD Display
+//
+// Requires Testato, Koepel softwarewire library and
+// Andriy Golovnya's LiquidCrystal_AIP31068 library.
+//
+//#define YHCB2004
+
//
// Original RADDS LCD Display+Encoder+SDCardReader
// http://doku.radds.org/dokumentation/lcd-display/
@@ -1987,6 +2188,11 @@
//
//#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+//
+// K.3D Full Graphic Smart Controller
+//
+//#define K3D_FULL_GRAPHIC_SMART_CONTROLLER
+
//
// ReprapWorld Graphical LCD
// https://reprapworld.com/?products_details&products_id/1218
@@ -2083,9 +2289,10 @@
//
// Anet 128x64 full graphics lcd with rotary encoder as used on Anet A6
// A clone of the RepRapDiscount full graphics display but with
-// different pins/wiring (see pins_ANET_10.h).
+// different pins/wiring (see pins_ANET_10.h). Enable one of these.
//
//#define ANET_FULL_GRAPHICS_LCD
+//#define ANET_FULL_GRAPHICS_LCD_ALT_WIRING
//
// AZSMZ 12864 LCD with SD
@@ -2123,7 +2330,7 @@
//#define OLED_PANEL_TINYBOY2
//
-// MKS OLED 1.3" 128×64 FULL GRAPHICS CONTROLLER
+// MKS OLED 1.3" 128×64 Full Graphics Controller
// https://reprap.org/wiki/MKS_12864OLED
//
// Tiny, but very sharp OLED display
@@ -2132,7 +2339,7 @@
//#define MKS_12864OLED_SSD1306 // Uses the SSD1306 controller
//
-// Zonestar OLED 128×64 FULL GRAPHICS CONTROLLER
+// Zonestar OLED 128×64 Full Graphics Controller
//
//#define ZONESTAR_12864LCD // Graphical (DOGM) with ST7920 controller
//#define ZONESTAR_12864OLED // 1.3" OLED with SH1106 controller (default)
@@ -2149,10 +2356,15 @@
//#define OVERLORD_OLED
//
-// FYSETC OLED 2.42" 128×64 FULL GRAPHICS CONTROLLER with WS2812 RGB
+// FYSETC OLED 2.42" 128×64 Full Graphics Controller with WS2812 RGB
// Where to find : https://www.aliexpress.com/item/4000345255731.html
//#define FYSETC_242_OLED_12864 // Uses the SSD1309 controller
+//
+// K.3D SSD1309 OLED 2.42" 128×64 Full Graphics Controller
+//
+//#define K3D_242_OLED_CONTROLLER // Software SPI
+
//=============================================================================
//========================== Extensible UI Displays ===========================
//=============================================================================
@@ -2166,6 +2378,11 @@
//#define DGUS_LCD_UI_FYSETC
//#define DGUS_LCD_UI_HIPRECY
+//#define DGUS_LCD_UI_MKS
+#if ENABLED(DGUS_LCD_UI_MKS)
+ #define USE_MKS_GREEN_UI
+#endif
+
//
// Touch-screen LCD for Malyan M200/M300 printers
//
@@ -2190,9 +2407,17 @@
//#define ANYCUBIC_LCD_DEBUG
#endif
+//
+// 320x240 Nextion 2.8" serial TFT Resistive Touch Screen NX3224T028
+//
+//#define NEXTION_TFT
+#if ENABLED(NEXTION_TFT)
+ #define LCD_SERIAL_PORT 1 // Default is 1 for Nextion
+#endif
+
//
// Third-party or vendor-customized controller interfaces.
-// Sources should be installed in 'src/lcd/extensible_ui'.
+// Sources should be installed in 'src/lcd/extui'.
//
//#define EXTENSIBLE_UI
@@ -2205,22 +2430,98 @@
//=============================================================================
/**
- * TFT Type - Select your Display type
- *
- * Available options are:
- * MKS_TS35_V2_0,
- * MKS_ROBIN_TFT24, MKS_ROBIN_TFT28, MKS_ROBIN_TFT32, MKS_ROBIN_TFT35,
- * MKS_ROBIN_TFT43, MKS_ROBIN_TFT_V1_1R
- * TFT_TRONXY_X5SA, ANYCUBIC_TFT35, LONGER_LK_TFT28
- * TFT_GENERIC
- *
- * For TFT_GENERIC, you need to configure these 3 options:
- * Driver: TFT_DRIVER
- * Current Drivers are: AUTO, ST7735, ST7789, ST7796, R61505, ILI9328, ILI9341, ILI9488
- * Resolution: TFT_WIDTH and TFT_HEIGHT
- * Interface: TFT_INTERFACE_FSMC or TFT_INTERFACE_SPI
+ * Specific TFT Model Presets. Enable one of the following options
+ * or enable TFT_GENERIC and set sub-options.
*/
+
+//
+// 480x320, 3.5", SPI Display From MKS
+// Normally used in MKS Robin Nano V2
+//
+//#define MKS_TS35_V2_0
+
+//
+// 320x240, 2.4", FSMC Display From MKS
+// Normally used in MKS Robin Nano V1.2
+//
+//#define MKS_ROBIN_TFT24
+
+//
+// 320x240, 2.8", FSMC Display From MKS
+// Normally used in MKS Robin Nano V1.2
+//
+//#define MKS_ROBIN_TFT28
+
+//
+// 320x240, 3.2", FSMC Display From MKS
+// Normally used in MKS Robin Nano V1.2
+//
+//#define MKS_ROBIN_TFT32
+
+//
+// 480x320, 3.5", FSMC Display From MKS
+// Normally used in MKS Robin Nano V1.2
+//
+//#define MKS_ROBIN_TFT35
+
+//
+// 480x272, 4.3", FSMC Display From MKS
+//
+//#define MKS_ROBIN_TFT43
+
+//
+// 320x240, 3.2", FSMC Display From MKS
+// Normally used in MKS Robin
+//
+//#define MKS_ROBIN_TFT_V1_1R
+
+//
+// 480x320, 3.5", FSMC Stock Display from TronxXY
+//
+//#define TFT_TRONXY_X5SA
+
+//
+// 480x320, 3.5", FSMC Stock Display from AnyCubic
+//
+//#define ANYCUBIC_TFT35
+
+//
+// 320x240, 2.8", FSMC Stock Display from Longer/Alfawise
+//
+//#define LONGER_LK_TFT28
+
+//
+// 320x240, 2.8", FSMC Stock Display from ET4
+//
+//#define ANET_ET4_TFT28
+
+//
+// 480x320, 3.5", FSMC Stock Display from ET5
+//
+//#define ANET_ET5_TFT35
+
+//
+// 1024x600, 7", RGB Stock Display from BIQU-BX
+//
+//#define BIQU_BX_TFT70
+
+//
+// Generic TFT with detailed options
+//
//#define TFT_GENERIC
+#if ENABLED(TFT_GENERIC)
+ // :[ 'AUTO', 'ST7735', 'ST7789', 'ST7796', 'R61505', 'ILI9328', 'ILI9341', 'ILI9488' ]
+ #define TFT_DRIVER AUTO
+
+ // Interface. Enable one of the following options:
+ //#define TFT_INTERFACE_FSMC
+ //#define TFT_INTERFACE_SPI
+
+ // TFT Resolution. Enable one of the following options:
+ //#define TFT_RES_320x240
+ //#define TFT_RES_480x272
+ //#define TFT_RES_480x320
+#endif
/**
* TFT UI - User Interface Selection. Enable one of the following options:
@@ -2236,6 +2537,10 @@
//#define TFT_COLOR_UI
//#define TFT_LVGL_UI
+#if ENABLED(TFT_LVGL_UI)
+ //#define MKS_WIFI_MODULE // MKS WiFi module
+#endif
+
/**
* TFT Rotation. Set to one of the following values:
*
@@ -2265,10 +2570,19 @@
#define TOUCH_SCREEN_CALIBRATION
- //#define XPT2046_X_CALIBRATION 12316
- //#define XPT2046_Y_CALIBRATION -8981
- //#define XPT2046_X_OFFSET -43
- //#define XPT2046_Y_OFFSET 257
+ //#define TOUCH_CALIBRATION_X 12316
+ //#define TOUCH_CALIBRATION_Y -8981
+ //#define TOUCH_OFFSET_X -43
+ //#define TOUCH_OFFSET_Y 257
+ //#define TOUCH_ORIENTATION TOUCH_LANDSCAPE
+
+ #if BOTH(TOUCH_SCREEN_CALIBRATION, EEPROM_SETTINGS)
+ #define TOUCH_CALIBRATION_AUTO_SAVE // Auto save successful calibration values to EEPROM
+ #endif
+
+ #if ENABLED(TFT_COLOR_UI)
+ //#define SINGLE_TOUCH_NAVIGATION
+ #endif
#endif
//
@@ -2382,6 +2696,7 @@
// Use a single NeoPixel LED for static (background) lighting
//#define NEOPIXEL_BKGD_LED_INDEX 0 // Index of the LED to use
//#define NEOPIXEL_BKGD_COLOR { 255, 255, 255, 0 } // R, G, B, W
+ //#define NEOPIXEL_BKGD_ALWAYS_ON // Keep the backlight on when other NeoPixels are off
#endif
/**
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index bcacddd20..149ac610f 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -30,7 +30,7 @@
*
* Basic settings can be found in Configuration.h
*/
-#define CONFIGURATION_ADV_H_VERSION 020007
+#define CONFIGURATION_ADV_H_VERSION 020008
//===========================================================================
//============================= Thermal Settings ============================
@@ -113,6 +113,18 @@
#define CHAMBER_BETA 3950 // Beta value
#endif
+#if TEMP_SENSOR_COOLER == 1000
+ #define COOLER_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define COOLER_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define COOLER_BETA 3950 // Beta value
+#endif
+
+#if TEMP_SENSOR_PROBE == 1000
+ #define PROBE_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define PROBE_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define PROBE_BETA 3950 // Beta value
+#endif
+
//
// Hephestos 2 24V heated bed upgrade kit.
// https://store.bq.com/en/heated-bed-kit-hephestos2
@@ -137,17 +149,21 @@
//
// Heated Chamber options
//
+#if DISABLED(PIDTEMPCHAMBER)
+ #define CHAMBER_CHECK_INTERVAL 5000 // (ms) Interval between checks in bang-bang control
+ #if ENABLED(CHAMBER_LIMIT_SWITCHING)
+ #define CHAMBER_HYSTERESIS 2 // (°C) Only set the relevant heater state when ABS(T-target) > CHAMBER_HYSTERESIS
+ #endif
+#endif
+
#if TEMP_SENSOR_CHAMBER
- #define CHAMBER_MINTEMP 5
- #define CHAMBER_MAXTEMP 60
- #define TEMP_CHAMBER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
- //#define CHAMBER_LIMIT_SWITCHING
- //#define HEATER_CHAMBER_PIN 44 // Chamber heater on/off pin
+ //#define HEATER_CHAMBER_PIN P2_04 // Required heater on/off pin (example: SKR 1.4 Turbo HE1 plug)
//#define HEATER_CHAMBER_INVERTING false
+ //#define FAN1_PIN -1 // Remove the fan signal on pin P2_04 (example: SKR 1.4 Turbo HE1 plug)
//#define CHAMBER_FAN // Enable a fan on the chamber
#if ENABLED(CHAMBER_FAN)
- #define CHAMBER_FAN_MODE 2 // Fan control mode: 0=Static; 1=Linear increase when temp is higher than target; 2=V-shaped curve.
+ #define CHAMBER_FAN_MODE 2 // Fan control mode: 0=Static; 1=Linear increase when temp is higher than target; 2=V-shaped curve; 3=similar to 1 but fan is always on.
#if CHAMBER_FAN_MODE == 0
#define CHAMBER_FAN_BASE 255 // Chamber fan PWM (0-255)
#elif CHAMBER_FAN_MODE == 1
@@ -156,6 +172,9 @@
#elif CHAMBER_FAN_MODE == 2
#define CHAMBER_FAN_BASE 128 // Minimum chamber fan PWM (0-255)
#define CHAMBER_FAN_FACTOR 25 // PWM increase per °C difference from target
+ #elif CHAMBER_FAN_MODE == 3
+ #define CHAMBER_FAN_BASE 128 // Base chamber fan PWM (0-255)
+ #define CHAMBER_FAN_FACTOR 25 // PWM increase per °C above target
#endif
#endif
@@ -163,12 +182,45 @@
#if ENABLED(CHAMBER_VENT)
#define CHAMBER_VENT_SERVO_NR 1 // Index of the vent servo
#define HIGH_EXCESS_HEAT_LIMIT 5 // How much above target temp to consider there is excess heat in the chamber
- #define LOW_EXCESS_HEAT_LIMIT 3
+ #define LOW_EXCESS_HEAT_LIMIT 3
#define MIN_COOLING_SLOPE_TIME_CHAMBER_VENT 20
#define MIN_COOLING_SLOPE_DEG_CHAMBER_VENT 1.5
#endif
#endif
+//
+// Laser Cooler options
+//
+#if TEMP_SENSOR_COOLER
+ #define COOLER_MINTEMP 8 // (°C)
+ #define COOLER_MAXTEMP 26 // (°C)
+ #define COOLER_DEFAULT_TEMP 16 // (°C)
+ #define TEMP_COOLER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
+ #define COOLER_PIN 8 // Laser cooler on/off pin used to control power to the cooling element e.g. TEC, External chiller via relay
+ #define COOLER_INVERTING false
+ #define TEMP_COOLER_PIN 15 // Laser/Cooler temperature sensor pin. ADC is required.
+ #define COOLER_FAN // Enable a fan on the cooler, Fan# 0,1,2,3 etc.
+ #define COOLER_FAN_INDEX 0 // FAN number 0, 1, 2 etc. e.g.
+ #if ENABLED(COOLER_FAN)
+ #define COOLER_FAN_BASE 100 // Base Cooler fan PWM (0-255); turns on when Cooler temperature is above the target
+ #define COOLER_FAN_FACTOR 25 // PWM increase per °C above target
+ #endif
+#endif
+
+//
+// Laser Coolant Flow Meter
+//
+//#define LASER_COOLANT_FLOW_METER
+#if ENABLED(LASER_COOLANT_FLOW_METER)
+ #define FLOWMETER_PIN 20 // Requires an external interrupt-enabled pin (e.g., RAMPS 2,3,18,19,20,21)
+ #define FLOWMETER_PPL 5880 // (pulses/liter) Flow meter pulses-per-liter on the input pin
+ #define FLOWMETER_INTERVAL 1000 // (ms) Flow rate calculation interval in milliseconds
+ #define FLOWMETER_SAFETY // Prevent running the laser without the minimum flow rate set below
+ #if ENABLED(FLOWMETER_SAFETY)
+ #define FLOWMETER_MIN_LITERS_PER_MINUTE 1.5 // (liters/min) Minimum flow required when enabled
+ #endif
+#endif
+
/**
* Thermal Protection provides additional protection to your printer from damage
* and fire. Marlin always includes safe min and max temperature ranges which
@@ -206,7 +258,7 @@
* and/or decrease WATCH_TEMP_INCREASE. WATCH_TEMP_INCREASE should not be set
* below 2.
*/
- #define WATCH_TEMP_PERIOD 20 // Seconds
+ #define WATCH_TEMP_PERIOD 20 // Seconds
#define WATCH_TEMP_INCREASE 2 // Degrees Celsius
#endif
@@ -238,6 +290,20 @@
#define WATCH_CHAMBER_TEMP_INCREASE 2 // Degrees Celsius
#endif
+/**
+ * Thermal Protection parameters for the laser cooler.
+ */
+#if ENABLED(THERMAL_PROTECTION_COOLER)
+ #define THERMAL_PROTECTION_COOLER_PERIOD 10 // Seconds
+ #define THERMAL_PROTECTION_COOLER_HYSTERESIS 3 // Degrees Celsius
+
+ /**
+ * Laser cooling watch settings (M143/M193).
+ */
+ #define WATCH_COOLER_TEMP_PERIOD 60 // Seconds
+ #define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius
+#endif
+
#if ENABLED(PIDTEMP)
// Add an experimental additional term to the heater power, proportional to the extrusion speed.
// A well-chosen Kc value should add just enough power to melt the increased material volume.
@@ -284,8 +350,8 @@
// DEFAULT_Kf and PID_FAN_SCALING_LIN_FACTOR are calculated accordingly.
#define PID_FAN_SCALING_AT_FULL_SPEED 13.0 //=PID_FAN_SCALING_LIN_FACTOR*255+DEFAULT_Kf
- #define PID_FAN_SCALING_AT_MIN_SPEED 6.0 //=PID_FAN_SCALING_LIN_FACTOR*PID_FAN_SCALING_MIN_SPEED+DEFAULT_Kf
- #define PID_FAN_SCALING_MIN_SPEED 10.0 // Minimum fan speed at which to enable PID_FAN_SCALING
+ #define PID_FAN_SCALING_AT_MIN_SPEED 6.0 //=PID_FAN_SCALING_LIN_FACTOR*PID_FAN_SCALING_MIN_SPEED+DEFAULT_Kf
+ #define PID_FAN_SCALING_MIN_SPEED 10.0 // Minimum fan speed at which to enable PID_FAN_SCALING
#define DEFAULT_Kf (255.0*PID_FAN_SCALING_AT_MIN_SPEED-PID_FAN_SCALING_AT_FULL_SPEED*PID_FAN_SCALING_MIN_SPEED)/(255.0-PID_FAN_SCALING_MIN_SPEED)
#define PID_FAN_SCALING_LIN_FACTOR (PID_FAN_SCALING_AT_FULL_SPEED-DEFAULT_Kf)/255.0
@@ -331,7 +397,7 @@
* High Temperature Thermistor Support
*
* Thermistors able to support high temperature tend to have a hard time getting
- * good readings at room and lower temperatures. This means HEATER_X_RAW_LO_TEMP
+ * good readings at room and lower temperatures. This means TEMP_SENSOR_X_RAW_LO_TEMP
* will probably be caught when the heating element first turns on during the
* preheating process, which will trigger a min_temp_error as a safety measure
* and force stop everything.
@@ -483,11 +549,15 @@
#define E6_AUTO_FAN_PIN -1
#define E7_AUTO_FAN_PIN -1
#define CHAMBER_AUTO_FAN_PIN -1
+#define COOLER_AUTO_FAN_PIN -1
+#define COOLER_FAN_PIN -1
#define EXTRUDER_AUTO_FAN_TEMPERATURE 50
#define EXTRUDER_AUTO_FAN_SPEED 255 // 255 == full speed
#define CHAMBER_AUTO_FAN_TEMPERATURE 30
#define CHAMBER_AUTO_FAN_SPEED 255
+#define COOLER_AUTO_FAN_TEMPERATURE 18
+#define COOLER_AUTO_FAN_SPEED 255
/**
* Part-Cooling Fan Multiplexer
@@ -509,12 +579,17 @@
#define INVERT_CASE_LIGHT false // Set true if Case Light is ON when pin is LOW
#define CASE_LIGHT_DEFAULT_ON true // Set default power-up state on
#define CASE_LIGHT_DEFAULT_BRIGHTNESS 105 // Set default power-up brightness (0-255, requires PWM pin)
- //#define CASE_LIGHT_MAX_PWM 128 // Limit pwm
- //#define CASE_LIGHT_MENU // Add Case Light options to the LCD menu
//#define CASE_LIGHT_NO_BRIGHTNESS // Disable brightness control. Enable for non-PWM lighting.
- //#define CASE_LIGHT_USE_NEOPIXEL // Use NeoPixel LED as case light, requires NEOPIXEL_LED.
- #if ENABLED(CASE_LIGHT_USE_NEOPIXEL)
- #define CASE_LIGHT_NEOPIXEL_COLOR { 255, 255, 255, 255 } // { Red, Green, Blue, White }
+ //#define CASE_LIGHT_MAX_PWM 128 // Limit PWM duty cycle (0-255)
+ //#define CASE_LIGHT_MENU // Add Case Light options to the LCD menu
+ #if ENABLED(NEOPIXEL_LED)
+ //#define CASE_LIGHT_USE_NEOPIXEL // Use NeoPixel LED as case light
+ #endif
+ #if EITHER(RGB_LED, RGBW_LED)
+ //#define CASE_LIGHT_USE_RGB_LED // Use RGB / RGBW LED as case light
+ #endif
+ #if EITHER(CASE_LIGHT_USE_NEOPIXEL, CASE_LIGHT_USE_RGB_LED)
+ #define CASE_LIGHT_DEFAULT_COLOR { 255, 255, 255, 255 } // { Red, Green, Blue, White }
#endif
#endif
@@ -552,7 +627,7 @@
//#define X_DUAL_STEPPER_DRIVERS
#if ENABLED(X_DUAL_STEPPER_DRIVERS)
- #define INVERT_X2_VS_X_DIR true // Set 'true' if X motors should rotate in opposite directions
+ //#define INVERT_X2_VS_X_DIR // Enable if X2 direction signal is opposite to X
//#define X_DUAL_ENDSTOPS
#if ENABLED(X_DUAL_ENDSTOPS)
#define X2_USE_ENDSTOP _XMAX_
@@ -562,7 +637,7 @@
//#define Y_DUAL_STEPPER_DRIVERS
#if ENABLED(Y_DUAL_STEPPER_DRIVERS)
- #define INVERT_Y2_VS_Y_DIR true // Set 'true' if Y motors should rotate in opposite directions
+ //#define INVERT_Y2_VS_Y_DIR // Enable if Y2 direction signal is opposite to Y
//#define Y_DUAL_ENDSTOPS
#if ENABLED(Y_DUAL_ENDSTOPS)
#define Y2_USE_ENDSTOP _YMAX_
@@ -576,6 +651,11 @@
#define NUM_Z_STEPPER_DRIVERS 1 // (1-4) Z options change based on how many
#if NUM_Z_STEPPER_DRIVERS > 1
+ // Enable if Z motor direction signals are the opposite of Z1
+ //#define INVERT_Z2_VS_Z_DIR
+ //#define INVERT_Z3_VS_Z_DIR
+ //#define INVERT_Z4_VS_Z_DIR
+
//#define Z_MULTI_ENDSTOPS
#if ENABLED(Z_MULTI_ENDSTOPS)
#define Z2_USE_ENDSTOP _XMAX_
@@ -637,6 +717,9 @@
// Default x offset in duplication mode (typically set to half print bed width)
#define DEFAULT_DUPLICATION_X_OFFSET 100
+
+ // Default action to execute following M605 mode change commands. Typically G28X to apply new mode.
+ //#define EVENT_GCODE_IDEX_AFTER_MODECHANGE "G28X"
#endif
// Activate a solenoid on the active extruder with M380. Disable all with M381.
@@ -660,6 +743,7 @@
//#define QUICK_HOME // If G28 contains XY do a diagonal move first
//#define HOME_Y_BEFORE_X // If G28 contains XY home Y before X
+//#define HOME_Z_FIRST // Home Z first. Requires a Z-MIN endstop (not a probe).
//#define CODEPENDENT_XY_HOMING // If X/Y can't home without homing Y/X first
// @section bltouch
@@ -721,8 +805,8 @@
/**
* Use "HIGH SPEED" mode for probing.
* Danger: Disable if your probe sometimes fails. Only suitable for stable well-adjusted systems.
- * This feature was designed for Delta's with very fast Z moves however higher speed cartesians may function
- * If the machine cannot raise the probe fast enough after a trigger, it may enter a fault state.
+ * This feature was designed for Deltabots with very fast Z moves; however, higher speed Cartesians
+ * might be able to use it. If the machine can't raise Z fast enough the BLTouch may go into ALARM.
*/
//#define BLTOUCH_HS_MODE
@@ -797,10 +881,10 @@
//#define ASSISTED_TRAMMING
#if ENABLED(ASSISTED_TRAMMING)
- // Define positions for probing points, use the hotend as reference not the sensor.
- #define TRAMMING_POINT_XY { { 20, 20 }, { 200, 20 }, { 200, 200 }, { 20, 200 } }
+ // Define positions for probe points.
+ #define TRAMMING_POINT_XY { { 20, 20 }, { 180, 20 }, { 180, 180 }, { 20, 180 } }
- // Define positions names for probing points.
+ // Define position names for probe points.
#define TRAMMING_POINT_NAME_1 "Front-Left"
#define TRAMMING_POINT_NAME_2 "Front-Right"
#define TRAMMING_POINT_NAME_3 "Back-Right"
@@ -808,7 +892,10 @@
#define RESTORE_LEVELING_AFTER_G35 // Enable to restore leveling setup after operation
//#define REPORT_TRAMMING_MM // Report Z deviation (mm) for each point relative to the first
- //#define ASSISTED_TRAMMING_MENU_ITEM // Add a menu item for Assisted Tramming
+
+ //#define ASSISTED_TRAMMING_WIZARD // Add a Tramming Wizard to the LCD menu
+
+ //#define ASSISTED_TRAMMING_WAIT_POSITION { X_CENTER, Y_CENTER, 30 } // Move the nozzle out of the way for adjustment
/**
* Screw thread:
@@ -844,11 +931,6 @@
#define DISABLE_INACTIVE_Z true // Set 'false' if the nozzle could fall onto your printed part!
#define DISABLE_INACTIVE_E true
-// If the Nozzle or Bed falls when the Z stepper is disabled, set its resting position here.
-//#define Z_AFTER_DEACTIVATE Z_HOME_POS
-
-//#define HOME_AFTER_DEACTIVATE // Require rehoming after steppers are deactivated
-
// Default Minimum Feedrates for printing and travel moves
#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s) Minimum feedrate. Set with M205 S.
#define DEFAULT_MINTRAVELFEEDRATE 0.0 // (mm/s) Minimum travel feedrate. Set with M205 T.
@@ -890,6 +972,9 @@
#define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (mm)
#define BACKLASH_CORRECTION 0.0 // 0.0 = no correction; 1.0 = full correction
+ // Add steps for motor direction changes on CORE kinematics
+ //#define CORE_BACKLASH
+
// Set BACKLASH_SMOOTHING_MM to spread backlash correction over multiple segments
// to reduce print artifacts. (Enabling this is costly in memory and computation!)
//#define BACKLASH_SMOOTHING_MM 3 // (mm)
@@ -907,7 +992,7 @@
// increments while checking for the contact to be broken.
#define BACKLASH_MEASUREMENT_LIMIT 0.5 // (mm)
#define BACKLASH_MEASUREMENT_RESOLUTION 0.005 // (mm)
- #define BACKLASH_MEASUREMENT_FEEDRATE Z_PROBE_SPEED_SLOW // (mm/min)
+ #define BACKLASH_MEASUREMENT_FEEDRATE Z_PROBE_FEEDRATE_SLOW // (mm/min)
#endif
#endif
#endif
@@ -1017,7 +1102,7 @@
/**
* I2C-based DIGIPOTs (e.g., Azteeg X3 Pro)
*/
-//#define DIGIPOT_MCP4018 // Requires https://github.com/stawel/SlowSoftI2CMaster
+//#define DIGIPOT_MCP4018 // Requires https://github.com/felias-fogg/SlowSoftI2CMaster
//#define DIGIPOT_MCP4451
#if EITHER(DIGIPOT_MCP4018, DIGIPOT_MCP4451)
#define DIGIPOT_I2C_NUM_CHANNELS 8 // 5DPRINT:4 AZTEEG_X3_PRO:8 MKS_SBASE:5 MIGHTYBOARD_REVE:5
@@ -1048,10 +1133,10 @@
// @section lcd
-#if EITHER(ULTIPANEL, EXTENSIBLE_UI)
+#if EITHER(IS_ULTIPANEL, EXTENSIBLE_UI)
#define MANUAL_FEEDRATE { 50*60, 50*60, 4*60, 2*60 } // (mm/min) Feedrates for manual moves along X, Y, Z, E from panel
- #define SHORT_MANUAL_Z_MOVE 0.025 // (mm) Smallest manual Z move (< 0.1mm)
- #if ENABLED(ULTIPANEL)
+ #define FINE_MANUAL_MOVE 0.025 // (mm) Smallest manual move (< 0.1mm) applying to Z on most machines
+ #if IS_ULTIPANEL
#define MANUAL_E_MOVES_RELATIVE // Display extruder move distance rather than "position"
#define ULTIPANEL_FEEDMULTIPLY // Encoder sets the feedrate multiplier on the Status Screen
#endif
@@ -1077,7 +1162,15 @@
#if HAS_BED_PROBE
//#define PROBE_OFFSET_WIZARD
#if ENABLED(PROBE_OFFSET_WIZARD)
- #define PROBE_OFFSET_START -4.0 // Estimated nozzle-to-probe Z offset, plus a little extra
+ //
+ // Enable to init the Probe Z-Offset when starting the Wizard.
+ // Use a height slightly above the estimated nozzle-to-probe Z offset.
+ // For example, with an offset of -5, consider a starting height of -4.
+ //
+ //#define PROBE_OFFSET_WIZARD_START_Z -4.0
+
+ // Set a convenient position to do the calibration (probing point and nozzle/bed-distance)
+ //#define PROBE_OFFSET_WIZARD_XY_POS { X_CENTER, Y_CENTER }
#endif
#endif
@@ -1090,6 +1183,9 @@
// BACK menu items keep the highlight at the top
//#define TURBO_BACK_MENU_ITEM
+ // Add a mute option to the LCD menu
+ //#define SOUND_MENU_ITEM
+
/**
* LED Control Menu
* Add LED Control to the LCD menu
@@ -1116,35 +1212,43 @@
#endif
#endif
+ // Insert a menu for preheating at the top level to allow for quick access
+ //#define PREHEAT_SHORTCUT_MENU_ITEM
+
#endif // HAS_LCD_MENU
-// Scroll a longer status message into view
-//#define STATUS_MESSAGE_SCROLLING
+#if HAS_DISPLAY
+ // The timeout (in ms) to return to the status screen from sub-menus
+ //#define LCD_TIMEOUT_TO_STATUS 15000
-// On the Info Screen, display XY with one decimal place when possible
-//#define LCD_DECIMAL_SMALL_XY
+ #if ENABLED(SHOW_BOOTSCREEN)
+ #define BOOTSCREEN_TIMEOUT 4000 // (ms) Total Duration to display the boot screen(s)
+ #if EITHER(HAS_MARLINUI_U8GLIB, TFT_COLOR_UI)
+ #define BOOT_MARLIN_LOGO_SMALL // Show a smaller Marlin logo on the Boot Screen (saving lots of flash)
+ #endif
+ #endif
-// The timeout (in ms) to return to the status screen from sub-menus
-//#define LCD_TIMEOUT_TO_STATUS 15000
+ // Scroll a longer status message into view
+ //#define STATUS_MESSAGE_SCROLLING
-// Add an 'M73' G-code to set the current percentage
-//#define LCD_SET_PROGRESS_MANUALLY
+ // On the Info Screen, display XY with one decimal place when possible
+ //#define LCD_DECIMAL_SMALL_XY
-// Show the E position (filament used) during printing
-//#define LCD_SHOW_E_TOTAL
+ // Add an 'M73' G-code to set the current percentage
+ //#define LCD_SET_PROGRESS_MANUALLY
-#if ENABLED(SHOW_BOOTSCREEN)
- #define BOOTSCREEN_TIMEOUT 4000 // (ms) Total Duration to display the boot screen(s)
+ // Show the E position (filament used) during printing
+ //#define LCD_SHOW_E_TOTAL
#endif
-#if EITHER(SDSUPPORT, LCD_SET_PROGRESS_MANUALLY) && ANY(HAS_MARLINUI_U8GLIB, HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL)
+#if EITHER(SDSUPPORT, LCD_SET_PROGRESS_MANUALLY) && ANY(HAS_MARLINUI_U8GLIB, HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL, EXTENSIBLE_UI)
//#define SHOW_REMAINING_TIME // Display estimated time to completion
#if ENABLED(SHOW_REMAINING_TIME)
//#define USE_M73_REMAINING_TIME // Use remaining time from M73 command instead of estimation
//#define ROTATE_PROGRESS_DISPLAY // Display (P)rogress, (E)lapsed, and (R)emaining time
#endif
- #if HAS_MARLINUI_U8GLIB
+ #if EITHER(HAS_MARLINUI_U8GLIB, EXTENSIBLE_UI)
//#define PRINT_PROGRESS_SHOW_DECIMALS // Show progress with decimal digits
#endif
@@ -1161,13 +1265,26 @@
#endif
#if ENABLED(SDSUPPORT)
+ /**
+ * SD Card SPI Speed
+ * May be required to resolve "volume init" errors.
+ *
+ * Enable and set to SPI_HALF_SPEED, SPI_QUARTER_SPEED, or SPI_EIGHTH_SPEED
+ * otherwise full speed will be applied.
+ *
+ * :['SPI_HALF_SPEED', 'SPI_QUARTER_SPEED', 'SPI_EIGHTH_SPEED']
+ */
+ //#define SD_SPI_SPEED SPI_HALF_SPEED
// The standard SD detect circuit reads LOW when media is inserted and HIGH when empty.
// Enable this option and set to HIGH if your SD cards are incorrectly detected.
//#define SD_DETECT_STATE HIGH
+ //#define SD_IGNORE_AT_STARTUP // Don't mount the SD card when starting up
//#define SDCARD_READONLY // Read-only SD card (to save over 2K of flash)
+ //#define GCODE_REPEAT_MARKERS // Enable G-code M808 to set repeat markers and do looping
+
#define SD_PROCEDURE_DEPTH 1 // Increase if you need more nested M32 calls
#define SD_FINISHED_STEPPERRELEASE true // Disable steppers when SD Print is finished
@@ -1179,8 +1296,11 @@
#define SD_MENU_CONFIRM_START // Confirm the selected SD file before printing
+ //#define NO_SD_AUTOSTART // Remove auto#.g file support completely to save some Flash, SRAM
//#define MENU_ADDAUTOSTART // Add a menu option to run auto#.g files
+ //#define BROWSE_MEDIA_ON_INSERT // Open the file browser when media is inserted
+
#define EVENT_GCODE_SD_ABORT "G28XY" // G-code to run on SD Abort Print (e.g., "G28XY" or "G27")
#if ENABLED(PRINTER_EVENT_LEDS)
@@ -1199,17 +1319,23 @@
#if ENABLED(POWER_LOSS_RECOVERY)
#define PLR_ENABLED_DEFAULT false // Power Loss Recovery enabled by default. (Set with 'M413 Sn' & M500)
//#define BACKUP_POWER_SUPPLY // Backup power / UPS to move the steppers on power loss
- //#define POWER_LOSS_RECOVER_ZHOME // Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
//#define POWER_LOSS_ZRAISE 2 // (mm) Z axis raise on resume (on power loss with UPS)
//#define POWER_LOSS_PIN 44 // Pin to detect power loss. Set to -1 to disable default pin on boards without module.
//#define POWER_LOSS_STATE HIGH // State of pin indicating power loss
- //#define POWER_LOSS_PULL // Set pullup / pulldown as appropriate
+ //#define POWER_LOSS_PULLUP // Set pullup / pulldown as appropriate for your sensor
+ //#define POWER_LOSS_PULLDOWN
//#define POWER_LOSS_PURGE_LEN 20 // (mm) Length of filament to purge on resume
//#define POWER_LOSS_RETRACT_LEN 10 // (mm) Length of filament to retract on fail. Requires backup power.
// Without a POWER_LOSS_PIN the following option helps reduce wear on the SD card,
// especially with "vase mode" printing. Set too high and vases cannot be continued.
#define POWER_LOSS_MIN_Z_CHANGE 0.05 // (mm) Minimum Z change before saving power-loss data
+
+ // Enable if Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
+ //#define POWER_LOSS_RECOVER_ZHOME
+ #if ENABLED(POWER_LOSS_RECOVER_ZHOME)
+ //#define POWER_LOSS_ZHOME_POS { 0, 0 } // Safe XY position to home Z while avoiding objects on the bed
+ #endif
#endif
/**
@@ -1250,6 +1376,10 @@
// Note: Only affects SCROLL_LONG_FILENAMES with SDSORT_CACHE_NAMES but not SDSORT_DYNAMIC_RAM.
#endif
+ // Allow international symbols in long filenames. To display correctly, the
+ // LCD's font must contain the characters. Check your selected LCD language.
+ //#define UTF_FILENAME_SUPPORT
+
// This allows hosts to request long names for files and folders with M33
//#define LONG_FILENAME_HOST_SUPPORT
@@ -1294,9 +1424,6 @@
*/
//#define USB_FLASH_DRIVE_SUPPORT
#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
- #define USB_CS_PIN SDSS
- #define USB_INTR_PIN SD_DETECT_PIN
-
/**
* USB Host Shield Library
*
@@ -1307,7 +1434,18 @@
* is less tested and is known to interfere with Servos.
* [1] This requires USB_INTR_PIN to be interrupt-capable.
*/
+ //#define USE_UHS2_USB
//#define USE_UHS3_USB
+
+ /**
+ * Native USB Host supported by some boards (USB OTG)
+ */
+ //#define USE_OTG_USB_HOST
+
+ #if DISABLED(USE_OTG_USB_HOST)
+ #define USB_CS_PIN SDSS
+ #define USB_INTR_PIN SD_DETECT_PIN
+ #endif
#endif
/**
@@ -1333,13 +1471,25 @@
* Set this option to one of the following (or the board's defaults apply):
*
* LCD - Use the SD drive in the external LCD controller.
- * ONBOARD - Use the SD drive on the control board. (No SD_DETECT_PIN. M21 to init.)
+ * ONBOARD - Use the SD drive on the control board.
* CUSTOM_CABLE - Use a custom cable to access the SD (as defined in a pins file).
*
* :[ 'LCD', 'ONBOARD', 'CUSTOM_CABLE' ]
*/
//#define SDCARD_CONNECTION LCD
+ // Enable if SD detect is rendered useless (e.g., by using an SD extender)
+ //#define NO_SD_DETECT
+
+ // Multiple volume support - EXPERIMENTAL.
+ //#define MULTI_VOLUME
+ #if ENABLED(MULTI_VOLUME)
+ #define VOLUME_SD_ONBOARD
+ #define VOLUME_USB_FLASH_DRIVE
+ #define DEFAULT_VOLUME SD_ONBOARD
+ #define DEFAULT_SHARED_VOLUME USB_FLASH_DRIVE
+ #endif
+
#endif // SDSUPPORT
/**
@@ -1417,11 +1567,12 @@
#define STATUS_BED_ANIM // Use a second bitmap to indicate bed heating
#define STATUS_CHAMBER_ANIM // Use a second bitmap to indicate chamber heating
//#define STATUS_CUTTER_ANIM // Use a second bitmap to indicate spindle / laser active
+ //#define STATUS_COOLER_ANIM // Use a second bitmap to indicate laser cooling
+ //#define STATUS_FLOWMETER_ANIM // Use multiple bitmaps to indicate coolant flow
//#define STATUS_ALT_BED_BITMAP // Use the alternative bed bitmap
//#define STATUS_ALT_FAN_BITMAP // Use the alternative fan bitmap
//#define STATUS_FAN_FRAMES 3 // :[0,1,2,3,4] Number of fan animation frames
//#define STATUS_HEAT_PERCENT // Show heating in a progress bar
- //#define BOOT_MARLIN_LOGO_SMALL // Show a smaller Marlin logo on the Boot Screen (saving 399 bytes of flash)
//#define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~3260 (or ~940) bytes of PROGMEM.
// Frivolous Game Options
@@ -1445,12 +1596,12 @@
#define DGUS_UPDATE_INTERVAL_MS 500 // (ms) Interval between automatic screen updates
- #if EITHER(DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_HIPRECY)
+ #if ANY(DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_MKS, DGUS_LCD_UI_HIPRECY)
#define DGUS_PRINT_FILENAME // Display the filename during printing
#define DGUS_PREHEAT_UI // Display a preheat screen during heatup
- #if ENABLED(DGUS_LCD_UI_FYSETC)
- //#define DGUS_UI_MOVE_DIS_OPTION // Disabled by default for UI_FYSETC
+ #if EITHER(DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_MKS)
+ //#define DGUS_UI_MOVE_DIS_OPTION // Disabled by default for FYSETC and MKS
#else
#define DGUS_UI_MOVE_DIS_OPTION // Enabled by default for UI_HIPRECY
#endif
@@ -1469,6 +1620,44 @@
#endif
#endif // HAS_DGUS_LCD
+//
+// Additional options for AnyCubic Chiron TFT displays
+//
+#if ENABLED(ANYCUBIC_LCD_CHIRON)
+ // By default the type of panel is automatically detected.
+ // Enable one of these options if you know the panel type.
+ //#define CHIRON_TFT_STANDARD
+ //#define CHIRON_TFT_NEW
+
+ // Enable the longer Anycubic powerup startup tune
+ //#define AC_DEFAULT_STARTUP_TUNE
+
+ /**
+ * Display Folders
+ * By default the file browser lists all G-code files (including those in subfolders) in a flat list.
+ * Enable this option to display a hierarchical file browser.
+ *
+ * NOTES:
+ * - Without this option it helps to enable SDCARD_SORT_ALPHA so files are sorted before/after folders.
+ * - When used with the "new" panel, folder names will also have '.gcode' appended to their names.
+ * This hack is currently required to force the panel to show folders.
+ */
+ #define AC_SD_FOLDER_VIEW
+#endif
+
+//
+// Specify additional languages for the UI. Default specified by LCD_LANGUAGE.
+//
+#if ANY(DOGLCD, TFT_COLOR_UI, TOUCH_UI_FTDI_EVE)
+ //#define LCD_LANGUAGE_2 fr
+ //#define LCD_LANGUAGE_3 de
+ //#define LCD_LANGUAGE_4 es
+ //#define LCD_LANGUAGE_5 it
+ #ifdef LCD_LANGUAGE_2
+ //#define LCD_LANGUAGE_AUTO_SAVE // Automatically save language to EEPROM on change
+ #endif
+#endif
+
//
// Touch UI for the FTDI Embedded Video Engine (EVE)
//
@@ -1480,6 +1669,8 @@
//#define LCD_HAOYU_FT810CB // Haoyu with 5" (800x480)
//#define LCD_ALEPHOBJECTS_CLCD_UI // Aleph Objects Color LCD UI
//#define LCD_FYSETC_TFT81050 // FYSETC with 5" (800x480)
+ //#define LCD_EVE3_50G // Matrix Orbital 5.0", 800x480, BT815
+ //#define LCD_EVE2_50G // Matrix Orbital 5.0", 800x480, FT813
// Correct the resolution if not using the stock TFT panel.
//#define TOUCH_UI_320x240
@@ -1536,18 +1727,14 @@
//#define TOUCH_UI_UTF8_FRACTIONS // ¼ ½ ¾
//#define TOUCH_UI_UTF8_SYMBOLS // µ ¶ ¦ § ¬
#endif
+
+ // Cyrillic character set, costs about 27KiB of flash
+ //#define TOUCH_UI_UTF8_CYRILLIC_CHARSET
#endif
// Use a smaller font when labels don't fit buttons
#define TOUCH_UI_FIT_TEXT
- // Allow language selection from menu at run-time (otherwise use LCD_LANGUAGE)
- //#define LCD_LANGUAGE_1 en
- //#define LCD_LANGUAGE_2 fr
- //#define LCD_LANGUAGE_3 de
- //#define LCD_LANGUAGE_4 es
- //#define LCD_LANGUAGE_5 it
-
// Use a numeric passcode for "Screen lock" keypad.
// (recommended for smaller displays)
//#define TOUCH_UI_PASSCODE
@@ -1707,6 +1894,10 @@
//#define MESH_MAX_Y Y_BED_SIZE - (MESH_INSET)
#endif
+#if BOTH(AUTO_BED_LEVELING_UBL, EEPROM_SETTINGS)
+ //#define OPTIMIZED_MESH_STORAGE // Store mesh with less precision to save EEPROM space
+#endif
+
/**
* Repeatedly attempt G29 leveling until it succeeds.
* Stop after G29_MAX_RETRIES attempts.
@@ -1936,6 +2127,12 @@
//#define SERIAL_STATS_DROPPED_RX
#endif
+// Monitor RX buffer usage
+// Dump an error to the serial port if the serial receive buffer overflows.
+// If you see these errors, increase the RX_BUFFER_SIZE value.
+// Not supported on all platforms.
+//#define RX_BUFFER_MONITOR
+
/**
* Emergency Command Parser
*
@@ -1946,6 +2143,26 @@
*/
//#define EMERGENCY_PARSER
+/**
+ * Realtime Reporting (requires EMERGENCY_PARSER)
+ *
+ * - Report position and state of the machine (like Grbl).
+ * - Auto-report position during long moves.
+ * - Useful for CNC/LASER.
+ *
+ * Adds support for commands:
+ * S000 : Report State and Position while moving.
+ * P000 : Instant Pause / Hold while moving.
+ * R000 : Resume from Pause / Hold.
+ *
+ * - During Hold all Emergency Parser commands are available, as usual.
+ * - Enable NANODLP_Z_SYNC and NANODLP_ALL_AXIS for move command end-state reports.
+ */
+//#define REALTIME_REPORTING_COMMANDS
+#if ENABLED(REALTIME_REPORTING_COMMANDS)
+ //#define FULL_REPORT_TO_HOST_FEATURE // Auto-report the machine status like Grbl CNC
+#endif
+
// Bad Serial-connections can miss a received command by sending an 'ok'
// Therefore some clients abort after 30 seconds in a timeout.
// Some other clients start sending commands while receiving a 'wait'.
@@ -1989,21 +2206,21 @@
*/
//#define FWRETRACT
#if ENABLED(FWRETRACT)
- #define FWRETRACT_AUTORETRACT // Override slicer retractions
+ #define FWRETRACT_AUTORETRACT // Override slicer retractions
#if ENABLED(FWRETRACT_AUTORETRACT)
- #define MIN_AUTORETRACT 0.1 // (mm) Don't convert E moves under this length
- #define MAX_AUTORETRACT 10.0 // (mm) Don't convert E moves over this length
+ #define MIN_AUTORETRACT 0.1 // (mm) Don't convert E moves under this length
+ #define MAX_AUTORETRACT 10.0 // (mm) Don't convert E moves over this length
#endif
- #define RETRACT_LENGTH 3 // (mm) Default retract length (positive value)
- #define RETRACT_LENGTH_SWAP 13 // (mm) Default swap retract length (positive value)
- #define RETRACT_FEEDRATE 45 // (mm/s) Default feedrate for retracting
- #define RETRACT_ZRAISE 0 // (mm) Default retract Z-raise
- #define RETRACT_RECOVER_LENGTH 0 // (mm) Default additional recover length (added to retract length on recover)
- #define RETRACT_RECOVER_LENGTH_SWAP 0 // (mm) Default additional swap recover length (added to retract length on recover from toolchange)
- #define RETRACT_RECOVER_FEEDRATE 8 // (mm/s) Default feedrate for recovering from retraction
- #define RETRACT_RECOVER_FEEDRATE_SWAP 8 // (mm/s) Default feedrate for recovering from swap retraction
+ #define RETRACT_LENGTH 3 // (mm) Default retract length (positive value)
+ #define RETRACT_LENGTH_SWAP 13 // (mm) Default swap retract length (positive value)
+ #define RETRACT_FEEDRATE 45 // (mm/s) Default feedrate for retracting
+ #define RETRACT_ZRAISE 0 // (mm) Default retract Z-raise
+ #define RETRACT_RECOVER_LENGTH 0 // (mm) Default additional recover length (added to retract length on recover)
+ #define RETRACT_RECOVER_LENGTH_SWAP 0 // (mm) Default additional swap recover length (added to retract length on recover from toolchange)
+ #define RETRACT_RECOVER_FEEDRATE 8 // (mm/s) Default feedrate for recovering from retraction
+ #define RETRACT_RECOVER_FEEDRATE_SWAP 8 // (mm/s) Default feedrate for recovering from swap retraction
#if ENABLED(MIXING_EXTRUDER)
- //#define RETRACT_SYNC_MIXING // Retract and restore all mixing steppers simultaneously
+ //#define RETRACT_SYNC_MIXING // Retract and restore all mixing steppers simultaneously
#endif
#endif
@@ -2020,6 +2237,12 @@
//#define EVENT_GCODE_AFTER_TOOLCHANGE "G12X" // Extra G-code to run after tool-change
#endif
+ /**
+ * Tool Sensors detect when tools have been picked up or dropped.
+ * Requires the pins TOOL_SENSOR1_PIN, TOOL_SENSOR2_PIN, etc.
+ */
+ //#define TOOL_SENSOR
+
/**
* Retract and prime filament on tool-change to reduce
* ooze and stringing and to get cleaner transitions.
@@ -2151,7 +2374,7 @@
#if AXIS_DRIVER_TYPE_X2(TMC26X)
#define X2_MAX_CURRENT 1000
#define X2_SENSE_RESISTOR 91
- #define X2_MICROSTEPS 16
+ #define X2_MICROSTEPS X_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_Y(TMC26X)
@@ -2163,7 +2386,7 @@
#if AXIS_DRIVER_TYPE_Y2(TMC26X)
#define Y2_MAX_CURRENT 1000
#define Y2_SENSE_RESISTOR 91
- #define Y2_MICROSTEPS 16
+ #define Y2_MICROSTEPS Y_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_Z(TMC26X)
@@ -2175,19 +2398,19 @@
#if AXIS_DRIVER_TYPE_Z2(TMC26X)
#define Z2_MAX_CURRENT 1000
#define Z2_SENSE_RESISTOR 91
- #define Z2_MICROSTEPS 16
+ #define Z2_MICROSTEPS Z_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_Z3(TMC26X)
#define Z3_MAX_CURRENT 1000
#define Z3_SENSE_RESISTOR 91
- #define Z3_MICROSTEPS 16
+ #define Z3_MICROSTEPS Z_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_Z4(TMC26X)
#define Z4_MAX_CURRENT 1000
#define Z4_SENSE_RESISTOR 91
- #define Z4_MICROSTEPS 16
+ #define Z4_MICROSTEPS Z_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X)
@@ -2199,43 +2422,43 @@
#if AXIS_DRIVER_TYPE_E1(TMC26X)
#define E1_MAX_CURRENT 1000
#define E1_SENSE_RESISTOR 91
- #define E1_MICROSTEPS 16
+ #define E1_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E2(TMC26X)
#define E2_MAX_CURRENT 1000
#define E2_SENSE_RESISTOR 91
- #define E2_MICROSTEPS 16
+ #define E2_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E3(TMC26X)
#define E3_MAX_CURRENT 1000
#define E3_SENSE_RESISTOR 91
- #define E3_MICROSTEPS 16
+ #define E3_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E4(TMC26X)
#define E4_MAX_CURRENT 1000
#define E4_SENSE_RESISTOR 91
- #define E4_MICROSTEPS 16
+ #define E4_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E5(TMC26X)
#define E5_MAX_CURRENT 1000
#define E5_SENSE_RESISTOR 91
- #define E5_MICROSTEPS 16
+ #define E5_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E6(TMC26X)
#define E6_MAX_CURRENT 1000
#define E6_SENSE_RESISTOR 91
- #define E6_MICROSTEPS 16
+ #define E6_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E7(TMC26X)
#define E7_MAX_CURRENT 1000
#define E7_SENSE_RESISTOR 91
- #define E7_MICROSTEPS 16
+ #define E7_MICROSTEPS E0_MICROSTEPS
#endif
#endif // TMC26X
@@ -2261,22 +2484,29 @@
#if HAS_TRINAMIC_CONFIG
#define HOLD_MULTIPLIER 0.5 // Scales down the holding current from run current
- #define INTERPOLATE true // Interpolate X/Y/Z_MICROSTEPS to 256
+
+ /**
+ * Interpolate microsteps to 256
+ * Override for each driver with _INTERPOLATE settings below
+ */
+ #define INTERPOLATE true
#if AXIS_IS_TMC(X)
#define X_CURRENT 800 // (mA) RMS current. Multiply by 1.414 for peak current.
#define X_CURRENT_HOME X_CURRENT // (mA) RMS current for sensorless homing
- #define X_MICROSTEPS 16 // 0..256
+ #define X_MICROSTEPS 16 // 0..256
#define X_RSENSE 0.11
- #define X_CHAIN_POS -1 // <=0 : Not chained. 1 : MCU MOSI connected. 2 : Next in chain, ...
+ #define X_CHAIN_POS -1 // -1..0: Not chained. 1: MCU MOSI connected. 2: Next in chain, ...
+ //#define X_INTERPOLATE true // Enable to override 'INTERPOLATE' for the X axis
#endif
#if AXIS_IS_TMC(X2)
#define X2_CURRENT 800
#define X2_CURRENT_HOME X2_CURRENT
- #define X2_MICROSTEPS 16
+ #define X2_MICROSTEPS X_MICROSTEPS
#define X2_RSENSE 0.11
#define X2_CHAIN_POS -1
+ //#define X2_INTERPOLATE true
#endif
#if AXIS_IS_TMC(Y)
@@ -2285,14 +2515,16 @@
#define Y_MICROSTEPS 16
#define Y_RSENSE 0.11
#define Y_CHAIN_POS -1
+ //#define Y_INTERPOLATE true
#endif
#if AXIS_IS_TMC(Y2)
#define Y2_CURRENT 800
#define Y2_CURRENT_HOME Y2_CURRENT
- #define Y2_MICROSTEPS 16
+ #define Y2_MICROSTEPS Y_MICROSTEPS
#define Y2_RSENSE 0.11
#define Y2_CHAIN_POS -1
+ //#define Y2_INTERPOLATE true
#endif
#if AXIS_IS_TMC(Z)
@@ -2301,30 +2533,34 @@
#define Z_MICROSTEPS 16
#define Z_RSENSE 0.11
#define Z_CHAIN_POS -1
+ //#define Z_INTERPOLATE true
#endif
#if AXIS_IS_TMC(Z2)
#define Z2_CURRENT 800
#define Z2_CURRENT_HOME Z2_CURRENT
- #define Z2_MICROSTEPS 16
+ #define Z2_MICROSTEPS Z_MICROSTEPS
#define Z2_RSENSE 0.11
#define Z2_CHAIN_POS -1
+ //#define Z2_INTERPOLATE true
#endif
#if AXIS_IS_TMC(Z3)
#define Z3_CURRENT 800
#define Z3_CURRENT_HOME Z3_CURRENT
- #define Z3_MICROSTEPS 16
+ #define Z3_MICROSTEPS Z_MICROSTEPS
#define Z3_RSENSE 0.11
#define Z3_CHAIN_POS -1
+ //#define Z3_INTERPOLATE true
#endif
#if AXIS_IS_TMC(Z4)
#define Z4_CURRENT 800
#define Z4_CURRENT_HOME Z4_CURRENT
- #define Z4_MICROSTEPS 16
+ #define Z4_MICROSTEPS Z_MICROSTEPS
#define Z4_RSENSE 0.11
#define Z4_CHAIN_POS -1
+ //#define Z4_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E0)
@@ -2332,55 +2568,63 @@
#define E0_MICROSTEPS 16
#define E0_RSENSE 0.11
#define E0_CHAIN_POS -1
+ //#define E0_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E1)
#define E1_CURRENT 800
- #define E1_MICROSTEPS 16
+ #define E1_MICROSTEPS E0_MICROSTEPS
#define E1_RSENSE 0.11
#define E1_CHAIN_POS -1
+ //#define E1_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E2)
#define E2_CURRENT 800
- #define E2_MICROSTEPS 16
+ #define E2_MICROSTEPS E0_MICROSTEPS
#define E2_RSENSE 0.11
#define E2_CHAIN_POS -1
+ //#define E2_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E3)
#define E3_CURRENT 800
- #define E3_MICROSTEPS 16
+ #define E3_MICROSTEPS E0_MICROSTEPS
#define E3_RSENSE 0.11
#define E3_CHAIN_POS -1
+ //#define E3_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E4)
#define E4_CURRENT 800
- #define E4_MICROSTEPS 16
+ #define E4_MICROSTEPS E0_MICROSTEPS
#define E4_RSENSE 0.11
#define E4_CHAIN_POS -1
+ //#define E4_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E5)
#define E5_CURRENT 800
- #define E5_MICROSTEPS 16
+ #define E5_MICROSTEPS E0_MICROSTEPS
#define E5_RSENSE 0.11
#define E5_CHAIN_POS -1
+ //#define E5_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E6)
#define E6_CURRENT 800
- #define E6_MICROSTEPS 16
+ #define E6_MICROSTEPS E0_MICROSTEPS
#define E6_RSENSE 0.11
#define E6_CHAIN_POS -1
+ //#define E6_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E7)
#define E7_CURRENT 800
- #define E7_MICROSTEPS 16
+ #define E7_MICROSTEPS E0_MICROSTEPS
#define E7_RSENSE 0.11
#define E7_CHAIN_POS -1
+ //#define E7_INTERPOLATE true
#endif
/**
@@ -2425,22 +2669,22 @@
* Set *_SERIAL_TX_PIN and *_SERIAL_RX_PIN to match for all drivers
* on the same serial port, either here or in your board's pins file.
*/
- #define X_SLAVE_ADDRESS 0
- #define Y_SLAVE_ADDRESS 0
- #define Z_SLAVE_ADDRESS 0
- #define X2_SLAVE_ADDRESS 0
- #define Y2_SLAVE_ADDRESS 0
- #define Z2_SLAVE_ADDRESS 0
- #define Z3_SLAVE_ADDRESS 0
- #define Z4_SLAVE_ADDRESS 0
- #define E0_SLAVE_ADDRESS 0
- #define E1_SLAVE_ADDRESS 0
- #define E2_SLAVE_ADDRESS 0
- #define E3_SLAVE_ADDRESS 0
- #define E4_SLAVE_ADDRESS 0
- #define E5_SLAVE_ADDRESS 0
- #define E6_SLAVE_ADDRESS 0
- #define E7_SLAVE_ADDRESS 0
+ //#define X_SLAVE_ADDRESS 0
+ //#define Y_SLAVE_ADDRESS 0
+ //#define Z_SLAVE_ADDRESS 0
+ //#define X2_SLAVE_ADDRESS 0
+ //#define Y2_SLAVE_ADDRESS 0
+ //#define Z2_SLAVE_ADDRESS 0
+ //#define Z3_SLAVE_ADDRESS 0
+ //#define Z4_SLAVE_ADDRESS 0
+ //#define E0_SLAVE_ADDRESS 0
+ //#define E1_SLAVE_ADDRESS 0
+ //#define E2_SLAVE_ADDRESS 0
+ //#define E3_SLAVE_ADDRESS 0
+ //#define E4_SLAVE_ADDRESS 0
+ //#define E5_SLAVE_ADDRESS 0
+ //#define E6_SLAVE_ADDRESS 0
+ //#define E7_SLAVE_ADDRESS 0
/**
* Software enable
@@ -2471,10 +2715,26 @@
* CHOPPER_PRUSAMK3_24V // Imported parameters from the official Průša firmware for MK3 (24V)
* CHOPPER_MARLIN_119 // Old defaults from Marlin v1.1.9
*
- * Define you own with
+ * Define your own with:
* { , , hysteresis_start[1..8] }
*/
- #define CHOPPER_TIMING CHOPPER_DEFAULT_12V
+ #define CHOPPER_TIMING CHOPPER_DEFAULT_12V // All axes (override below)
+ //#define CHOPPER_TIMING_X CHOPPER_TIMING // For X Axes (override below)
+ //#define CHOPPER_TIMING_X2 CHOPPER_TIMING_X
+ //#define CHOPPER_TIMING_Y CHOPPER_TIMING // For Y Axes (override below)
+ //#define CHOPPER_TIMING_Y2 CHOPPER_TIMING_Y
+ //#define CHOPPER_TIMING_Z CHOPPER_TIMING // For Z Axes (override below)
+ //#define CHOPPER_TIMING_Z2 CHOPPER_TIMING_Z
+ //#define CHOPPER_TIMING_Z3 CHOPPER_TIMING_Z
+ //#define CHOPPER_TIMING_Z4 CHOPPER_TIMING_Z
+ //#define CHOPPER_TIMING_E CHOPPER_TIMING // For Extruders (override below)
+ //#define CHOPPER_TIMING_E1 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E2 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E3 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E4 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E5 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E6 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E7 CHOPPER_TIMING_E
/**
* Monitor Trinamic drivers
@@ -2582,7 +2842,7 @@
/**
* Enable M122 debugging command for TMC stepper drivers.
- * M122 S0/1 will enable continous reporting.
+ * M122 S0/1 will enable continuous reporting.
*/
//#define TMC_DEBUG
@@ -2636,138 +2896,138 @@
#endif
#if AXIS_IS_L64XX(X2)
- #define X2_MICROSTEPS 128
- #define X2_OVERCURRENT 2000
- #define X2_STALLCURRENT 1500
- #define X2_MAX_VOLTAGE 127
- #define X2_CHAIN_POS -1
- #define X2_SLEW_RATE 1
+ #define X2_MICROSTEPS X_MICROSTEPS
+ #define X2_OVERCURRENT 2000
+ #define X2_STALLCURRENT 1500
+ #define X2_MAX_VOLTAGE 127
+ #define X2_CHAIN_POS -1
+ #define X2_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(Y)
- #define Y_MICROSTEPS 128
- #define Y_OVERCURRENT 2000
- #define Y_STALLCURRENT 1500
- #define Y_MAX_VOLTAGE 127
- #define Y_CHAIN_POS -1
- #define Y_SLEW_RATE 1
+ #define Y_MICROSTEPS 128
+ #define Y_OVERCURRENT 2000
+ #define Y_STALLCURRENT 1500
+ #define Y_MAX_VOLTAGE 127
+ #define Y_CHAIN_POS -1
+ #define Y_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(Y2)
- #define Y2_MICROSTEPS 128
- #define Y2_OVERCURRENT 2000
- #define Y2_STALLCURRENT 1500
- #define Y2_MAX_VOLTAGE 127
- #define Y2_CHAIN_POS -1
- #define Y2_SLEW_RATE 1
+ #define Y2_MICROSTEPS Y_MICROSTEPS
+ #define Y2_OVERCURRENT 2000
+ #define Y2_STALLCURRENT 1500
+ #define Y2_MAX_VOLTAGE 127
+ #define Y2_CHAIN_POS -1
+ #define Y2_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(Z)
- #define Z_MICROSTEPS 128
- #define Z_OVERCURRENT 2000
- #define Z_STALLCURRENT 1500
- #define Z_MAX_VOLTAGE 127
- #define Z_CHAIN_POS -1
- #define Z_SLEW_RATE 1
+ #define Z_MICROSTEPS 128
+ #define Z_OVERCURRENT 2000
+ #define Z_STALLCURRENT 1500
+ #define Z_MAX_VOLTAGE 127
+ #define Z_CHAIN_POS -1
+ #define Z_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(Z2)
- #define Z2_MICROSTEPS 128
- #define Z2_OVERCURRENT 2000
- #define Z2_STALLCURRENT 1500
- #define Z2_MAX_VOLTAGE 127
- #define Z2_CHAIN_POS -1
- #define Z2_SLEW_RATE 1
+ #define Z2_MICROSTEPS Z_MICROSTEPS
+ #define Z2_OVERCURRENT 2000
+ #define Z2_STALLCURRENT 1500
+ #define Z2_MAX_VOLTAGE 127
+ #define Z2_CHAIN_POS -1
+ #define Z2_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(Z3)
- #define Z3_MICROSTEPS 128
- #define Z3_OVERCURRENT 2000
- #define Z3_STALLCURRENT 1500
- #define Z3_MAX_VOLTAGE 127
- #define Z3_CHAIN_POS -1
- #define Z3_SLEW_RATE 1
+ #define Z3_MICROSTEPS Z_MICROSTEPS
+ #define Z3_OVERCURRENT 2000
+ #define Z3_STALLCURRENT 1500
+ #define Z3_MAX_VOLTAGE 127
+ #define Z3_CHAIN_POS -1
+ #define Z3_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(Z4)
- #define Z4_MICROSTEPS 128
- #define Z4_OVERCURRENT 2000
- #define Z4_STALLCURRENT 1500
- #define Z4_MAX_VOLTAGE 127
- #define Z4_CHAIN_POS -1
- #define Z4_SLEW_RATE 1
+ #define Z4_MICROSTEPS Z_MICROSTEPS
+ #define Z4_OVERCURRENT 2000
+ #define Z4_STALLCURRENT 1500
+ #define Z4_MAX_VOLTAGE 127
+ #define Z4_CHAIN_POS -1
+ #define Z4_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E0)
- #define E0_MICROSTEPS 128
- #define E0_OVERCURRENT 2000
- #define E0_STALLCURRENT 1500
- #define E0_MAX_VOLTAGE 127
- #define E0_CHAIN_POS -1
- #define E0_SLEW_RATE 1
+ #define E0_MICROSTEPS 128
+ #define E0_OVERCURRENT 2000
+ #define E0_STALLCURRENT 1500
+ #define E0_MAX_VOLTAGE 127
+ #define E0_CHAIN_POS -1
+ #define E0_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E1)
- #define E1_MICROSTEPS 128
- #define E1_OVERCURRENT 2000
- #define E1_STALLCURRENT 1500
- #define E1_MAX_VOLTAGE 127
- #define E1_CHAIN_POS -1
- #define E1_SLEW_RATE 1
+ #define E1_MICROSTEPS E0_MICROSTEPS
+ #define E1_OVERCURRENT 2000
+ #define E1_STALLCURRENT 1500
+ #define E1_MAX_VOLTAGE 127
+ #define E1_CHAIN_POS -1
+ #define E1_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E2)
- #define E2_MICROSTEPS 128
- #define E2_OVERCURRENT 2000
- #define E2_STALLCURRENT 1500
- #define E2_MAX_VOLTAGE 127
- #define E2_CHAIN_POS -1
- #define E2_SLEW_RATE 1
+ #define E2_MICROSTEPS E0_MICROSTEPS
+ #define E2_OVERCURRENT 2000
+ #define E2_STALLCURRENT 1500
+ #define E2_MAX_VOLTAGE 127
+ #define E2_CHAIN_POS -1
+ #define E2_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E3)
- #define E3_MICROSTEPS 128
- #define E3_OVERCURRENT 2000
- #define E3_STALLCURRENT 1500
- #define E3_MAX_VOLTAGE 127
- #define E3_CHAIN_POS -1
- #define E3_SLEW_RATE 1
+ #define E3_MICROSTEPS E0_MICROSTEPS
+ #define E3_OVERCURRENT 2000
+ #define E3_STALLCURRENT 1500
+ #define E3_MAX_VOLTAGE 127
+ #define E3_CHAIN_POS -1
+ #define E3_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E4)
- #define E4_MICROSTEPS 128
- #define E4_OVERCURRENT 2000
- #define E4_STALLCURRENT 1500
- #define E4_MAX_VOLTAGE 127
- #define E4_CHAIN_POS -1
- #define E4_SLEW_RATE 1
+ #define E4_MICROSTEPS E0_MICROSTEPS
+ #define E4_OVERCURRENT 2000
+ #define E4_STALLCURRENT 1500
+ #define E4_MAX_VOLTAGE 127
+ #define E4_CHAIN_POS -1
+ #define E4_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E5)
- #define E5_MICROSTEPS 128
- #define E5_OVERCURRENT 2000
- #define E5_STALLCURRENT 1500
- #define E5_MAX_VOLTAGE 127
- #define E5_CHAIN_POS -1
- #define E5_SLEW_RATE 1
+ #define E5_MICROSTEPS E0_MICROSTEPS
+ #define E5_OVERCURRENT 2000
+ #define E5_STALLCURRENT 1500
+ #define E5_MAX_VOLTAGE 127
+ #define E5_CHAIN_POS -1
+ #define E5_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E6)
- #define E6_MICROSTEPS 128
- #define E6_OVERCURRENT 2000
- #define E6_STALLCURRENT 1500
- #define E6_MAX_VOLTAGE 127
- #define E6_CHAIN_POS -1
- #define E6_SLEW_RATE 1
+ #define E6_MICROSTEPS E0_MICROSTEPS
+ #define E6_OVERCURRENT 2000
+ #define E6_STALLCURRENT 1500
+ #define E6_MAX_VOLTAGE 127
+ #define E6_CHAIN_POS -1
+ #define E6_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E7)
- #define E7_MICROSTEPS 128
- #define E7_OVERCURRENT 2000
- #define E7_STALLCURRENT 1500
- #define E7_MAX_VOLTAGE 127
- #define E7_CHAIN_POS -1
- #define E7_SLEW_RATE 1
+ #define E7_MICROSTEPS E0_MICROSTEPS
+ #define E7_OVERCURRENT 2000
+ #define E7_STALLCURRENT 1500
+ #define E7_MAX_VOLTAGE 127
+ #define E7_CHAIN_POS -1
+ #define E7_SLEW_RATE 1
#endif
/**
@@ -2903,11 +3163,24 @@
#define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR and LPC)
+ //#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
+ #if ENABLED(AIR_EVACUATION)
+ #define AIR_EVACUATION_ACTIVE LOW // Set to "HIGH" if the on/off function is active HIGH
+ #define AIR_EVACUATION_PIN 42 // Override the default Cutter Vacuum or Laser Blower pin
+ #endif
+
+ //#define SPINDLE_SERVO // A servo converting an angle to spindle power
+ #ifdef SPINDLE_SERVO
+ #define SPINDLE_SERVO_NR 0 // Index of servo used for spindle control
+ #define SPINDLE_SERVO_MIN 10 // Minimum angle for servo spindle
+ #endif
+
/**
* Speed / Power can be set ('M3 S') and displayed in terms of:
* - PWM255 (S0 - S255)
* - PERCENT (S0 - S100)
* - RPM (S0 - S50000) Best for use with a spindle
+ * - SERVO (S0 - S180)
*/
#define CUTTER_POWER_UNIT PWM255
@@ -2950,6 +3223,10 @@
#define SPEED_POWER_MAX 100 // (%) 0-100
#define SPEED_POWER_STARTUP 80 // (%) M3/M4 speed/power default (with no arguments)
+ // Define the minimum and maximum test pulse time values for a laser test fire function
+ #define LASER_TEST_PULSE_MIN 1 // Used with Laser Control Menu
+ #define LASER_TEST_PULSE_MAX 999 // Caution: Menu may not show more than 3 characters
+
/**
* Enable inline laser power to be handled in the planner / stepper routines.
* Inline power is specified by the I (inline) flag in an M3 command (e.g., M3 S20 I)
@@ -2958,7 +3235,7 @@
* This allows the laser to keep in perfect sync with the planner and removes
* the powerup/down delay since lasers require negligible time.
*/
- #define LASER_POWER_INLINE
+ //#define LASER_POWER_INLINE
#if ENABLED(LASER_POWER_INLINE)
/**
@@ -3027,6 +3304,18 @@
#endif
#endif
+/**
+ * Synchronous Laser Control with M106/M107
+ *
+ * Marlin normally applies M106/M107 fan speeds at a time "soon after" processing
+ * a planner block. This is too inaccurate for a PWM/TTL laser attached to the fan
+ * header (as with some add-on laser kits). Enable this option to set fan/laser
+ * speeds with much more exact timing for improved print fidelity.
+ *
+ * NOTE: This option sacrifices some cooling fan speed options.
+ */
+//#define LASER_SYNCHRONOUS_M106_M107
+
/**
* Coolant Control
*
@@ -3086,13 +3375,27 @@
*/
//#define POWER_MONITOR_CURRENT // Monitor the system current
//#define POWER_MONITOR_VOLTAGE // Monitor the system voltage
-#if EITHER(POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE)
- #define POWER_MONITOR_VOLTS_PER_AMP 0.05000 // Input voltage to the MCU analog pin per amp - DO NOT apply more than ADC_VREF!
- #define POWER_MONITOR_CURRENT_OFFSET -1 // Offset value for current sensors with linear function output
- #define POWER_MONITOR_VOLTS_PER_VOLT 0.11786 // Input voltage to the MCU analog pin per volt - DO NOT apply more than ADC_VREF!
+
+#if ENABLED(POWER_MONITOR_CURRENT)
+ #define POWER_MONITOR_VOLTS_PER_AMP 0.05000 // Input voltage to the MCU analog pin per amp - DO NOT apply more than ADC_VREF!
+ #define POWER_MONITOR_CURRENT_OFFSET 0 // Offset (in amps) applied to the calculated current
#define POWER_MONITOR_FIXED_VOLTAGE 13.6 // Voltage for a current sensor with no voltage sensor (for power display)
#endif
+#if ENABLED(POWER_MONITOR_VOLTAGE)
+ #define POWER_MONITOR_VOLTS_PER_VOLT 0.077933 // Input voltage to the MCU analog pin per volt - DO NOT apply more than ADC_VREF!
+ #define POWER_MONITOR_VOLTAGE_OFFSET 0 // Offset (in volts) applied to the calculated voltage
+#endif
+
+/**
+ * Stepper Driver Anti-SNAFU Protection
+ *
+ * If the SAFE_POWER_PIN is defined for your board, Marlin will check
+ * that stepper drivers are properly plugged in before applying power.
+ * Disable protection if your stepper drivers don't support the feature.
+ */
+//#define DISABLE_DRIVER_SAFE_POWER_PROTECT
+
/**
* CNC Coordinate Systems
*
@@ -3183,6 +3486,10 @@
//#define GCODE_QUOTED_STRINGS // Support for quoted string parameters
#endif
+// Support for MeatPack G-code compression (https://github.com/scottmudge/OctoPrint-MeatPack)
+//#define MEATPACK_ON_SERIAL_PORT_1
+//#define MEATPACK_ON_SERIAL_PORT_2
+
//#define GCODE_CASE_INSENSITIVE // Accept G-code sent to the firmware in lowercase
//#define REPETIER_GCODE_M360 // Add commands originally from Repetier FW
@@ -3222,29 +3529,99 @@
#endif
/**
- * User-defined menu items that execute custom GCode
+ * User-defined menu items to run custom G-code.
+ * Up to 25 may be defined, but the actual number is LCD-dependent.
*/
-//#define CUSTOM_USER_MENUS
-#if ENABLED(CUSTOM_USER_MENUS)
- //#define CUSTOM_USER_MENU_TITLE "Custom Commands"
- #define USER_SCRIPT_DONE "M117 User Script Done"
- #define USER_SCRIPT_AUDIBLE_FEEDBACK
- //#define USER_SCRIPT_RETURN // Return to status screen after a script
- #define USER_DESC_1 "Home & UBL Info"
- #define USER_GCODE_1 "G28\nG29 W"
+// Custom Menu: Main Menu
+//#define CUSTOM_MENU_MAIN
+#if ENABLED(CUSTOM_MENU_MAIN)
+ //#define CUSTOM_MENU_MAIN_TITLE "Custom Commands"
+ #define CUSTOM_MENU_MAIN_SCRIPT_DONE "M117 User Script Done"
+ #define CUSTOM_MENU_MAIN_SCRIPT_AUDIBLE_FEEDBACK
+ //#define CUSTOM_MENU_MAIN_SCRIPT_RETURN // Return to status screen after a script
+ #define CUSTOM_MENU_MAIN_ONLY_IDLE // Only show custom menu when the machine is idle
- #define USER_DESC_2 "Preheat for " PREHEAT_1_LABEL
- #define USER_GCODE_2 "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
+ #define MAIN_MENU_ITEM_1_DESC "Home & UBL Info"
+ #define MAIN_MENU_ITEM_1_GCODE "G28\nG29 W"
+ //#define MAIN_MENU_ITEM_1_CONFIRM // Show a confirmation dialog before this action
- #define USER_DESC_3 "Preheat for " PREHEAT_2_LABEL
- #define USER_GCODE_3 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
+ #define MAIN_MENU_ITEM_2_DESC "Preheat for " PREHEAT_1_LABEL
+ #define MAIN_MENU_ITEM_2_GCODE "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
+ //#define MAIN_MENU_ITEM_2_CONFIRM
- #define USER_DESC_4 "Heat Bed/Home/Level"
- #define USER_GCODE_4 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29"
+ //#define MAIN_MENU_ITEM_3_DESC "Preheat for " PREHEAT_2_LABEL
+ //#define MAIN_MENU_ITEM_3_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
+ //#define MAIN_MENU_ITEM_3_CONFIRM
- #define USER_DESC_5 "Home & Info"
- #define USER_GCODE_5 "G28\nM503"
+ //#define MAIN_MENU_ITEM_4_DESC "Heat Bed/Home/Level"
+ //#define MAIN_MENU_ITEM_4_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29"
+ //#define MAIN_MENU_ITEM_4_CONFIRM
+
+ //#define MAIN_MENU_ITEM_5_DESC "Home & Info"
+ //#define MAIN_MENU_ITEM_5_GCODE "G28\nM503"
+ //#define MAIN_MENU_ITEM_5_CONFIRM
+#endif
+
+// Custom Menu: Configuration Menu
+//#define CUSTOM_MENU_CONFIG
+#if ENABLED(CUSTOM_MENU_CONFIG)
+ //#define CUSTOM_MENU_CONFIG_TITLE "Custom Commands"
+ #define CUSTOM_MENU_CONFIG_SCRIPT_DONE "M117 Wireless Script Done"
+ #define CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK
+ //#define CUSTOM_MENU_CONFIG_SCRIPT_RETURN // Return to status screen after a script
+ #define CUSTOM_MENU_CONFIG_ONLY_IDLE // Only show custom menu when the machine is idle
+
+ #define CONFIG_MENU_ITEM_1_DESC "Wifi ON"
+ #define CONFIG_MENU_ITEM_1_GCODE "M118 [ESP110] WIFI-STA pwd=12345678"
+ //#define CONFIG_MENU_ITEM_1_CONFIRM // Show a confirmation dialog before this action
+
+ #define CONFIG_MENU_ITEM_2_DESC "Bluetooth ON"
+ #define CONFIG_MENU_ITEM_2_GCODE "M118 [ESP110] BT pwd=12345678"
+ //#define CONFIG_MENU_ITEM_2_CONFIRM
+
+ //#define CONFIG_MENU_ITEM_3_DESC "Radio OFF"
+ //#define CONFIG_MENU_ITEM_3_GCODE "M118 [ESP110] OFF pwd=12345678"
+ //#define CONFIG_MENU_ITEM_3_CONFIRM
+
+ //#define CONFIG_MENU_ITEM_4_DESC "Wifi ????"
+ //#define CONFIG_MENU_ITEM_4_GCODE "M118 ????"
+ //#define CONFIG_MENU_ITEM_4_CONFIRM
+
+ //#define CONFIG_MENU_ITEM_5_DESC "Wifi ????"
+ //#define CONFIG_MENU_ITEM_5_GCODE "M118 ????"
+ //#define CONFIG_MENU_ITEM_5_CONFIRM
+#endif
+
+/**
+ * User-defined buttons to run custom G-code.
+ * Up to 25 may be defined.
+ */
+//#define CUSTOM_USER_BUTTONS
+#if ENABLED(CUSTOM_USER_BUTTONS)
+ //#define BUTTON1_PIN -1
+ #if PIN_EXISTS(BUTTON1)
+ #define BUTTON1_HIT_STATE LOW // State of the triggered button. NC=LOW. NO=HIGH.
+ #define BUTTON1_WHEN_PRINTING false // Button allowed to trigger during printing?
+ #define BUTTON1_GCODE "G28"
+ #define BUTTON1_DESC "Homing" // Optional string to set the LCD status
+ #endif
+
+ //#define BUTTON2_PIN -1
+ #if PIN_EXISTS(BUTTON2)
+ #define BUTTON2_HIT_STATE LOW
+ #define BUTTON2_WHEN_PRINTING false
+ #define BUTTON2_GCODE "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
+ #define BUTTON2_DESC "Preheat for " PREHEAT_1_LABEL
+ #endif
+
+ //#define BUTTON3_PIN -1
+ #if PIN_EXISTS(BUTTON3)
+ #define BUTTON3_HIT_STATE LOW
+ #define BUTTON3_WHEN_PRINTING false
+ #define BUTTON3_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
+ #define BUTTON3_DESC "Preheat for " PREHEAT_2_LABEL
+ #endif
#endif
/**
@@ -3273,6 +3650,9 @@
* Implement M486 to allow Marlin to skip objects
*/
//#define CANCEL_OBJECTS
+#if ENABLED(CANCEL_OBJECTS)
+ #define CANCEL_OBJECTS_REPORTING // Emit the current object as a status message
+#endif
/**
* I2C position encoders for closed loop control.
@@ -3388,7 +3768,7 @@
#define GANTRY_CALIBRATION_FEEDRATE 500 // Feedrate for correction move
//#define GANTRY_CALIBRATION_TO_MIN // Enable to calibrate Z in the MIN direction
- //#define GANTRY_CALIBRATION_SAFE_POSITION { X_CENTER, Y_CENTER } // Safe position for nozzle
+ //#define GANTRY_CALIBRATION_SAFE_POSITION XY_CENTER // Safe position for nozzle
//#define GANTRY_CALIBRATION_XY_PARK_FEEDRATE 3000 // XY Park Feedrate - MMM
//#define GANTRY_CALIBRATION_COMMANDS_PRE ""
#define GANTRY_CALIBRATION_COMMANDS_POST "G28" // G28 highly recommended to ensure an accurate position
@@ -3430,14 +3810,20 @@
/**
* NanoDLP Sync support
*
- * Add support for Synchronized Z moves when using with NanoDLP. G0/G1 axis moves will output "Z_move_comp"
- * string to enable synchronization with DLP projector exposure. This change will allow to use
- * [[WaitForDoneMessage]] instead of populating your gcode with M400 commands
+ * Support for Synchronized Z moves when used with NanoDLP. G0/G1 axis moves will
+ * output a "Z_move_comp" string to enable synchronization with DLP projector exposure.
+ * This feature allows you to use [[WaitForDoneMessage]] instead of M400 commands.
*/
//#define NANODLP_Z_SYNC
#if ENABLED(NANODLP_Z_SYNC)
- //#define NANODLP_ALL_AXIS // Enables "Z_move_comp" output on any axis move.
- // Default behavior is limited to Z axis only.
+ //#define NANODLP_ALL_AXIS // Send a "Z_move_comp" report for any axis move (not just Z).
+#endif
+
+/**
+ * Ethernet. Use M552 to enable and set the IP address.
+ */
+#if HAS_ETHERNET
+ #define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D } // A MAC address unique to your network
#endif
/**
@@ -3463,16 +3849,26 @@
#endif
/**
- * Průša Multi-Material Unit v2
+ * Průša Multi-Material Unit (MMU)
* Enable in Configuration.h
+ *
+ * These devices allow a single stepper driver on the board to drive
+ * multi-material feeders with any number of stepper motors.
*/
-#if ENABLED(PRUSA_MMU2)
-
+#if HAS_PRUSA_MMU1
+ /**
+ * This option only allows the multiplexer to switch on tool-change.
+ * Additional options to configure custom E moves are pending.
+ *
+ * Override the default DIO selector pins here, if needed.
+ * Some pins files may provide defaults for these pins.
+ */
+ //#define E_MUX0_PIN 40 // Always Required
+ //#define E_MUX1_PIN 42 // Needed for 3 to 8 inputs
+ //#define E_MUX2_PIN 44 // Needed for 5 to 8 inputs
+#elif HAS_PRUSA_MMU2
// Serial port used for communication with MMU2.
- // For AVR enable the UART port used for the MMU. (e.g., mmuSerial)
- // For 32-bit boards check your HAL for available serial ports. (e.g., Serial2)
#define MMU2_SERIAL_PORT 2
- #define MMU2_SERIAL mmuSerial
// Use hardware reset for MMU if a pin is defined for it
//#define MMU2_RST_PIN 23
@@ -3485,7 +3881,7 @@
// Add an LCD menu for MMU2
//#define MMU2_MENUS
- #if ENABLED(MMU2_MENUS)
+ #if EITHER(MMU2_MENUS, HAS_PRUSA_MMU2S)
// Settings for filament load / unload from the LCD menu.
// This is for Průša MK3-style extruders. Customize for your hardware.
#define MMU2_FILAMENTCHANGE_EJECT_FEED 80.0
@@ -3510,29 +3906,12 @@
{ -50.0, 2000 }
#endif
- /**
- * MMU Extruder Sensor
- *
- * Support for a Průša (or other) IR Sensor to detect filament near the extruder
- * and make loading more reliable. Suitable for an extruder equipped with a filament
- * sensor less than 38mm from the gears.
- *
- * During loading the extruder will stop when the sensor is triggered, then do a last
- * move up to the gears. If no filament is detected, the MMU2 can make some more attempts.
- * If all attempts fail, a filament runout will be triggered.
- */
- //#define MMU_EXTRUDER_SENSOR
- #if ENABLED(MMU_EXTRUDER_SENSOR)
- #define MMU_LOADING_ATTEMPTS_NR 5 // max. number of attempts to load filament if first load fail
- #endif
-
/**
* Using a sensor like the MMU2S
* This mode requires a MK3S extruder with a sensor at the extruder idler, like the MMU2S.
* See https://help.prusa3d.com/en/guide/3b-mk3s-mk2-5s-extruder-upgrade_41560, step 11
*/
- //#define PRUSA_MMU2_S_MODE
- #if ENABLED(PRUSA_MMU2_S_MODE)
+ #if HAS_PRUSA_MMU2S
#define MMU2_C0_RETRY 5 // Number of retries (total time = timeout*retries)
#define MMU2_CAN_LOAD_FEEDRATE 800 // (mm/min)
@@ -3548,11 +3927,29 @@
#define MMU2_CAN_LOAD_INCREMENT_SEQUENCE \
{ -MMU2_CAN_LOAD_INCREMENT, MMU2_CAN_LOAD_FEEDRATE }
+ #else
+
+ /**
+ * MMU1 Extruder Sensor
+ *
+ * Support for a Průša (or other) IR Sensor to detect filament near the extruder
+ * and make loading more reliable. Suitable for an extruder equipped with a filament
+ * sensor less than 38mm from the gears.
+ *
+ * During loading the extruder will stop when the sensor is triggered, then do a last
+ * move up to the gears. If no filament is detected, the MMU2 can make some more attempts.
+ * If all attempts fail, a filament runout will be triggered.
+ */
+ //#define MMU_EXTRUDER_SENSOR
+ #if ENABLED(MMU_EXTRUDER_SENSOR)
+ #define MMU_LOADING_ATTEMPTS_NR 5 // max. number of attempts to load filament if first load fail
+ #endif
+
#endif
//#define MMU2_DEBUG // Write debug info to serial output
-#endif // PRUSA_MMU2
+#endif // HAS_PRUSA_MMU2
/**
* Advanced Print Counter settings
@@ -3587,3 +3984,16 @@
// Enable Marlin dev mode which adds some special commands
//#define MARLIN_DEV_MODE
+
+/**
+ * Postmortem Debugging captures misbehavior and outputs the CPU status and backtrace to serial.
+ * When running in the debugger it will break for debugging. This is useful to help understand
+ * a crash from a remote location. Requires ~400 bytes of SRAM and 5Kb of flash.
+ */
+//#define POSTMORTEM_DEBUGGING
+
+/**
+ * Software Reset options
+ */
+//#define SOFT_RESET_VIA_SERIAL // 'KILL' and '^X' commands will soft-reset the controller
+//#define SOFT_RESET_ON_KILL // Use a digital button to soft-reset the controller after KILL
diff --git a/Marlin/Makefile b/Marlin/Makefile
index 49cb960b9..5ff183082 100644
--- a/Marlin/Makefile
+++ b/Marlin/Makefile
@@ -219,7 +219,7 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1111)
else ifeq ($(HARDWARE_MOTHERBOARD),1112)
# MKS GEN L
else ifeq ($(HARDWARE_MOTHERBOARD),1113)
-# zrib V2.0 control board (Chinese knock off RAMPS replica)
+# zrib V2.0 control board (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1114)
# BigTreeTech or BIQU KFB2.0
else ifeq ($(HARDWARE_MOTHERBOARD),1115)
@@ -323,6 +323,8 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1203)
else ifeq ($(HARDWARE_MOTHERBOARD),1204)
# abee Scoovo X9H
else ifeq ($(HARDWARE_MOTHERBOARD),1205)
+# Rambo ThinkerV2
+else ifeq ($(HARDWARE_MOTHERBOARD),1206)
#
# Other ATmega1280, ATmega2560
@@ -991,5 +993,5 @@ clean:
.PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
-# Automaticaly include the dependency files created by gcc
+# Automatically include the dependency files created by gcc
-include ${patsubst %.o, %.d, ${OBJ}}
diff --git a/Marlin/Version.h b/Marlin/Version.h
index 60e068ba3..629904995 100644
--- a/Marlin/Version.h
+++ b/Marlin/Version.h
@@ -54,7 +54,7 @@
* has a distinct Github fork— the Source Code URL should just be the main
* Marlin repository.
*/
-//#define SOURCE_CODE_URL "https://github.com/MarlinFirmware/Marlin"
+//#define SOURCE_CODE_URL "github.com/MarlinFirmware/Marlin"
/**
* Default generic printer UUID.
@@ -65,7 +65,7 @@
* The WEBSITE_URL is the location where users can get more information such as
* documentation about a specific Marlin release.
*/
-//#define WEBSITE_URL "https://marlinfw.org"
+//#define WEBSITE_URL "marlinfw.org"
/**
* Set the vendor info the serial USB interface, if changable
diff --git a/Marlin/src/HAL/AVR/HAL.cpp b/Marlin/src/HAL/AVR/HAL.cpp
index 58d57c8ee..708583b26 100644
--- a/Marlin/src/HAL/AVR/HAL.cpp
+++ b/Marlin/src/HAL/AVR/HAL.cpp
@@ -24,6 +24,13 @@
#include "../../inc/MarlinConfig.h"
#include "HAL.h"
+#ifdef USBCON
+ DefaultSerial1 MSerial0(false, Serial);
+ #ifdef BLUETOOTH
+ BTSerial btSerial(false, bluetoothSerial);
+ #endif
+#endif
+
// ------------------------
// Public Variables
// ------------------------
@@ -51,6 +58,15 @@ void HAL_init() {
#endif
}
+void HAL_reboot() {
+ #if ENABLED(USE_WATCHDOG)
+ while (1) { /* run out the watchdog */ }
+ #else
+ void (*resetFunc)() = 0; // Declare resetFunc() at address 0
+ resetFunc(); // Jump to address 0
+ #endif
+}
+
#if ENABLED(SDSUPPORT)
#include "../../sd/SdFatUtil.h"
diff --git a/Marlin/src/HAL/AVR/HAL.h b/Marlin/src/HAL/AVR/HAL.h
index 6e0afa8f1..7adf1aad4 100644
--- a/Marlin/src/HAL/AVR/HAL.h
+++ b/Marlin/src/HAL/AVR/HAL.h
@@ -25,7 +25,7 @@
#include "watchdog.h"
#include "math.h"
-#ifdef IS_AT90USB
+#ifdef USBCON
#include
#else
#define HardwareSerial_h // Hack to prevent HardwareSerial.h header inclusion
@@ -81,25 +81,40 @@ typedef int8_t pin_t;
//extern uint8_t MCUSR;
// Serial ports
-#ifdef IS_AT90USB
- #define MYSERIAL0 TERN(BLUETOOTH, bluetoothSerial, Serial)
+#ifdef USBCON
+ #include "../../core/serial_hook.h"
+ typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
+ extern DefaultSerial1 MSerial0;
+ #ifdef BLUETOOTH
+ typedef ForwardSerial1Class< decltype(bluetoothSerial) > BTSerial;
+ extern BTSerial btSerial;
+ #endif
+
+ #define MYSERIAL1 TERN(BLUETOOTH, btSerial, MSerial0)
#else
#if !WITHIN(SERIAL_PORT, -1, 3)
- #error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
- #define MYSERIAL0 customizedSerial1
+ #define MYSERIAL1 customizedSerial1
#ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 3)
- #error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
- #define MYSERIAL1 customizedSerial2
+ #define MYSERIAL2 customizedSerial2
#endif
#endif
+#ifdef MMU2_SERIAL_PORT
+ #if !WITHIN(MMU2_SERIAL_PORT, -1, 3)
+ #error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+ #define MMU2_SERIAL mmuSerial
+#endif
+
#ifdef LCD_SERIAL_PORT
#if !WITHIN(LCD_SERIAL_PORT, -1, 3)
- #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#define LCD_SERIAL lcdSerial
#if HAS_DGUS_LCD
@@ -120,14 +135,18 @@ void HAL_init();
inline void HAL_clear_reset_source() { MCUSR = 0; }
inline uint8_t HAL_get_reset_source() { return MCUSR; }
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+void HAL_reboot();
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-extern "C" {
- int freeMemory();
-}
-#pragma GCC diagnostic pop
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+extern "C" int freeMemory();
+
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic pop
+#endif
// ADC
#ifdef DIDR2
diff --git a/Marlin/src/HAL/AVR/HAL_SPI.cpp b/Marlin/src/HAL/AVR/HAL_SPI.cpp
index 31e589746..1a1b98b3d 100644
--- a/Marlin/src/HAL/AVR/HAL_SPI.cpp
+++ b/Marlin/src/HAL/AVR/HAL_SPI.cpp
@@ -34,17 +34,17 @@
#include "../../inc/MarlinConfig.h"
void spiBegin() {
- OUT_WRITE(SS_PIN, HIGH);
- SET_OUTPUT(SCK_PIN);
- SET_INPUT(MISO_PIN);
- SET_OUTPUT(MOSI_PIN);
+ OUT_WRITE(SD_SS_PIN, HIGH);
+ SET_OUTPUT(SD_SCK_PIN);
+ SET_INPUT(SD_MISO_PIN);
+ SET_OUTPUT(SD_MOSI_PIN);
#if DISABLED(SOFTWARE_SPI)
// SS must be in output mode even it is not chip select
- //SET_OUTPUT(SS_PIN);
+ //SET_OUTPUT(SD_SS_PIN);
// set SS high - may be chip select for another SPI device
//#if SET_SPI_SS_HIGH
- //WRITE(SS_PIN, HIGH);
+ //WRITE(SD_SS_PIN, HIGH);
//#endif
// set a default rate
spiInit(1);
@@ -88,7 +88,7 @@ void spiBegin() {
}
/** SPI read data */
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
if (nbyte-- == 0) return;
SPDR = 0xFF;
for (uint16_t i = 0; i < nbyte; i++) {
@@ -107,7 +107,7 @@ void spiBegin() {
}
/** SPI send block */
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
SPDR = token;
for (uint16_t i = 0; i < 512; i += 2) {
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
@@ -195,19 +195,19 @@ void spiBegin() {
// no interrupts during byte receive - about 8µs
cli();
// output pin high - like sending 0xFF
- WRITE(MOSI_PIN, HIGH);
+ WRITE(SD_MOSI_PIN, HIGH);
LOOP_L_N(i, 8) {
- WRITE(SCK_PIN, HIGH);
+ WRITE(SD_SCK_PIN, HIGH);
nop; // adjust so SCK is nice
nop;
data <<= 1;
- if (READ(MISO_PIN)) data |= 1;
+ if (READ(SD_MISO_PIN)) data |= 1;
- WRITE(SCK_PIN, LOW);
+ WRITE(SD_SCK_PIN, LOW);
}
sei();
@@ -215,7 +215,7 @@ void spiBegin() {
}
// Soft SPI read data
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++)
buf[i] = spiRec();
}
@@ -225,10 +225,10 @@ void spiBegin() {
// no interrupts during byte send - about 8µs
cli();
LOOP_L_N(i, 8) {
- WRITE(SCK_PIN, LOW);
- WRITE(MOSI_PIN, data & 0x80);
+ WRITE(SD_SCK_PIN, LOW);
+ WRITE(SD_MOSI_PIN, data & 0x80);
data <<= 1;
- WRITE(SCK_PIN, HIGH);
+ WRITE(SD_SCK_PIN, HIGH);
}
nop; // hold SCK high for a few ns
@@ -236,13 +236,13 @@ void spiBegin() {
nop;
nop;
- WRITE(SCK_PIN, LOW);
+ WRITE(SD_SCK_PIN, LOW);
sei();
}
// Soft SPI send block
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
spiSend(token);
for (uint16_t i = 0; i < 512; i++)
spiSend(buf[i]);
diff --git a/Marlin/src/HAL/AVR/MarlinSerial.cpp b/Marlin/src/HAL/AVR/MarlinSerial.cpp
index 8feac32aa..7cd444698 100644
--- a/Marlin/src/HAL/AVR/MarlinSerial.cpp
+++ b/Marlin/src/HAL/AVR/MarlinSerial.cpp
@@ -38,7 +38,7 @@
#include "../../inc/MarlinConfig.h"
-#if !IS_AT90USB && (defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H))
+#if !defined(USBCON) && (defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H))
#include "MarlinSerial.h"
#include "../../MarlinCore.h"
@@ -556,161 +556,6 @@ void MarlinSerial::flushTX() {
}
}
-/**
- * Imports from print.h
- */
-
-template
-void MarlinSerial::print(char c, int base) {
- print((long)c, base);
-}
-
-template
-void MarlinSerial::print(unsigned char b, int base) {
- print((unsigned long)b, base);
-}
-
-template
-void MarlinSerial::print(int n, int base) {
- print((long)n, base);
-}
-
-template
-void MarlinSerial::print(unsigned int n, int base) {
- print((unsigned long)n, base);
-}
-
-template
-void MarlinSerial::print(long n, int base) {
- if (base == 0) write(n);
- else if (base == 10) {
- if (n < 0) { print('-'); n = -n; }
- printNumber(n, 10);
- }
- else
- printNumber(n, base);
-}
-
-template
-void MarlinSerial::print(unsigned long n, int base) {
- if (base == 0) write(n);
- else printNumber(n, base);
-}
-
-template
-void MarlinSerial::print(double n, int digits) {
- printFloat(n, digits);
-}
-
-template
-void MarlinSerial::println() {
- print('\r');
- print('\n');
-}
-
-template
-void MarlinSerial::println(const String& s) {
- print(s);
- println();
-}
-
-template
-void MarlinSerial::println(const char c[]) {
- print(c);
- println();
-}
-
-template
-void MarlinSerial::println(char c, int base) {
- print(c, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned char b, int base) {
- print(b, base);
- println();
-}
-
-template
-void MarlinSerial::println(int n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned int n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(long n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned long n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(double n, int digits) {
- print(n, digits);
- println();
-}
-
-// Private Methods
-
-template
-void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
- if (n) {
- unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
- int8_t i = 0;
- while (n) {
- buf[i++] = n % base;
- n /= base;
- }
- while (i--)
- print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
- }
- else
- print('0');
-}
-
-template
-void MarlinSerial::printFloat(double number, uint8_t digits) {
- // Handle negative numbers
- if (number < 0.0) {
- print('-');
- number = -number;
- }
-
- // Round correctly so that print(1.999, 2) prints as "2.00"
- double rounding = 0.5;
- LOOP_L_N(i, digits) rounding *= 0.1;
- number += rounding;
-
- // Extract the integer part of the number and print it
- unsigned long int_part = (unsigned long)number;
- double remainder = number - (double)int_part;
- print(int_part);
-
- // Print the decimal point, but only if there are digits beyond
- if (digits) {
- print('.');
- // Extract digits from the remainder one at a time
- while (digits--) {
- remainder *= 10.0;
- int toPrint = int(remainder);
- print(toPrint);
- remainder -= toPrint;
- }
- }
-}
-
// Hookup ISR handlers
ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _RX_vect)) {
MarlinSerial>::store_rxd_char();
@@ -720,11 +565,9 @@ ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _UDRE_vect)) {
MarlinSerial>::_tx_udr_empty_irq();
}
-// Preinstantiate
-template class MarlinSerial>;
-
-// Instantiate
-MarlinSerial> customizedSerial1;
+// Because of the template definition above, it's required to instantiate the template to have all methods generated
+template class MarlinSerial< MarlinSerialCfg >;
+MSerialT customizedSerial1(MSerialT::HasEmergencyParser);
#ifdef SERIAL_PORT_2
@@ -737,12 +580,8 @@ MarlinSerial> customizedSerial1;
MarlinSerial>::_tx_udr_empty_irq();
}
- // Preinstantiate
- template class MarlinSerial>;
-
- // Instantiate
- MarlinSerial> customizedSerial2;
-
+ template class MarlinSerial< MarlinSerialCfg >;
+ MSerialT2 customizedSerial2(MSerialT2::HasEmergencyParser);
#endif
#ifdef MMU2_SERIAL_PORT
@@ -755,12 +594,8 @@ MarlinSerial> customizedSerial1;
MarlinSerial>::_tx_udr_empty_irq();
}
- // Preinstantiate
- template class MarlinSerial>;
-
- // Instantiate
- MarlinSerial> mmuSerial;
-
+ template class MarlinSerial< MMU2SerialCfg >;
+ MSerialT3 mmuSerial(MSerialT3::HasEmergencyParser);
#endif
#ifdef LCD_SERIAL_PORT
@@ -773,11 +608,8 @@ MarlinSerial> customizedSerial1;
MarlinSerial>::_tx_udr_empty_irq();
}
- // Preinstantiate
- template class MarlinSerial>;
-
- // Instantiate
- MarlinSerial> lcdSerial;
+ template class MarlinSerial< LCDSerialCfg >;
+ MSerialT4 lcdSerial(MSerialT4::HasEmergencyParser);
#if HAS_DGUS_LCD
template
@@ -792,11 +624,11 @@ MarlinSerial> customizedSerial1;
#endif
-#endif // !IS_AT90USB && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
+#endif // !USBCON && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
// For AT90USB targets use the UART for BT interfacing
-#if BOTH(IS_AT90USB, BLUETOOTH)
- HardwareSerial bluetoothSerial;
+#if defined(USBCON) && ENABLED(BLUETOOTH)
+ MSerialT5 bluetoothSerial(false);
#endif
#endif // __AVR__
diff --git a/Marlin/src/HAL/AVR/MarlinSerial.h b/Marlin/src/HAL/AVR/MarlinSerial.h
index 3850e2a47..355ecd41f 100644
--- a/Marlin/src/HAL/AVR/MarlinSerial.h
+++ b/Marlin/src/HAL/AVR/MarlinSerial.h
@@ -34,6 +34,7 @@
#include
#include "../../inc/MarlinConfigPre.h"
+#include "../../core/serial_hook.h"
#ifndef SERIAL_PORT
#define SERIAL_PORT 0
@@ -135,10 +136,6 @@
UART_DECL(3);
#endif
- #define DEC 10
- #define HEX 16
- #define OCT 8
- #define BIN 2
#define BYTE 0
// Templated type selector
@@ -202,60 +199,30 @@
static FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value);
static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail();
- public:
-
+ public:
FORCE_INLINE static void store_rxd_char();
FORCE_INLINE static void _tx_udr_empty_irq();
- public:
- MarlinSerial() {};
- static void begin(const long);
- static void end();
- static int peek();
- static int read();
- static void flush();
- static ring_buffer_pos_t available();
- static void write(const uint8_t c);
- static void flushTX();
- #if HAS_DGUS_LCD
- static ring_buffer_pos_t get_tx_buffer_free();
- #endif
+ public:
+ static void begin(const long);
+ static void end();
+ static int peek();
+ static int read();
+ static void flush();
+ static ring_buffer_pos_t available();
+ static void write(const uint8_t c);
+ static void flushTX();
+ #if HAS_DGUS_LCD
+ static ring_buffer_pos_t get_tx_buffer_free();
+ #endif
- static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
+ enum { HasEmergencyParser = Cfg::EMERGENCYPARSER };
+ static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
- FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
- FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
- FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
- FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
-
- FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
- FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
- FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
- FORCE_INLINE static void print(const char* str) { write(str); }
-
- static void print(char, int = BYTE);
- static void print(unsigned char, int = BYTE);
- static void print(int, int = DEC);
- static void print(unsigned int, int = DEC);
- static void print(long, int = DEC);
- static void print(unsigned long, int = DEC);
- static void print(double, int = 2);
-
- static void println(const String& s);
- static void println(const char[]);
- static void println(char, int = BYTE);
- static void println(unsigned char, int = BYTE);
- static void println(int, int = DEC);
- static void println(unsigned int, int = DEC);
- static void println(long, int = DEC);
- static void println(unsigned long, int = DEC);
- static void println(double, int = 2);
- static void println();
- operator bool() { return true; }
-
- private:
- static void printNumber(unsigned long, const uint8_t);
- static void printFloat(double, uint8_t);
+ FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
+ FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
+ FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
+ FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
};
template
@@ -270,12 +237,13 @@
static constexpr bool RX_FRAMING_ERRORS = ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS);
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
};
- extern MarlinSerial> customizedSerial1;
+
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT;
+ extern MSerialT customizedSerial1;
#ifdef SERIAL_PORT_2
-
- extern MarlinSerial> customizedSerial2;
-
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT2;
+ extern MSerialT2 customizedSerial2;
#endif
#endif // !USBCON
@@ -284,49 +252,41 @@
template
struct MMU2SerialCfg {
static constexpr int PORT = serial;
+ static constexpr unsigned int RX_SIZE = 32;
+ static constexpr unsigned int TX_SIZE = 32;
static constexpr bool XONOFF = false;
static constexpr bool EMERGENCYPARSER = false;
static constexpr bool DROPPED_RX = false;
static constexpr bool RX_FRAMING_ERRORS = false;
static constexpr bool MAX_RX_QUEUED = false;
- static constexpr unsigned int RX_SIZE = 32;
- static constexpr unsigned int TX_SIZE = 32;
static constexpr bool RX_OVERRUNS = false;
};
- extern MarlinSerial> mmuSerial;
+ typedef Serial1Class< MarlinSerial< MMU2SerialCfg > > MSerialT3;
+ extern MSerialT3 mmuSerial;
#endif
#ifdef LCD_SERIAL_PORT
template
struct LCDSerialCfg {
- static constexpr int PORT = serial;
- static constexpr bool XONOFF = false;
- static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
- static constexpr bool DROPPED_RX = false;
- static constexpr bool RX_FRAMING_ERRORS = false;
- static constexpr bool MAX_RX_QUEUED = false;
- #if HAS_DGUS_LCD
- static constexpr unsigned int RX_SIZE = DGUS_RX_BUFFER_SIZE;
- static constexpr unsigned int TX_SIZE = DGUS_TX_BUFFER_SIZE;
- static constexpr bool RX_OVERRUNS = ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS);
- #elif EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
- static constexpr unsigned int RX_SIZE = 64;
- static constexpr unsigned int TX_SIZE = 128;
- static constexpr bool RX_OVERRUNS = false;
- #else
- static constexpr unsigned int RX_SIZE = 64;
- static constexpr unsigned int TX_SIZE = 128;
- static constexpr bool RX_OVERRUNS = false
- #endif
+ static constexpr int PORT = serial;
+ static constexpr unsigned int RX_SIZE = TERN(HAS_DGUS_LCD, DGUS_RX_BUFFER_SIZE, 64);
+ static constexpr unsigned int TX_SIZE = TERN(HAS_DGUS_LCD, DGUS_TX_BUFFER_SIZE, 128);
+ static constexpr bool XONOFF = false;
+ static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
+ static constexpr bool DROPPED_RX = false;
+ static constexpr bool RX_FRAMING_ERRORS = false;
+ static constexpr bool MAX_RX_QUEUED = false;
+ static constexpr bool RX_OVERRUNS = BOTH(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS);
};
- extern MarlinSerial> lcdSerial;
-
+ typedef Serial1Class< MarlinSerial< LCDSerialCfg > > MSerialT4;
+ extern MSerialT4 lcdSerial;
#endif
// Use the UART for Bluetooth in AT90USB configurations
-#if BOTH(IS_AT90USB, BLUETOOTH)
- extern HardwareSerial bluetoothSerial;
+#if defined(USBCON) && ENABLED(BLUETOOTH)
+ typedef Serial1Class MSerialT5;
+ extern MSerialT5 bluetoothSerial;
#endif
diff --git a/Marlin/src/HAL/AVR/eeprom.cpp b/Marlin/src/HAL/AVR/eeprom.cpp
index c7906985e..8d084dec7 100644
--- a/Marlin/src/HAL/AVR/eeprom.cpp
+++ b/Marlin/src/HAL/AVR/eeprom.cpp
@@ -40,13 +40,13 @@ bool PersistentStore::access_start() { return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
- if (v != eeprom_read_byte(p)) {
+ if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -59,7 +59,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c;
diff --git a/Marlin/src/HAL/AVR/endstop_interrupts.h b/Marlin/src/HAL/AVR/endstop_interrupts.h
index ae9a605ac..9fd9c38b8 100644
--- a/Marlin/src/HAL/AVR/endstop_interrupts.h
+++ b/Marlin/src/HAL/AVR/endstop_interrupts.h
@@ -124,7 +124,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(X_MAX_PIN), "X_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(X_MAX_PIN), "X_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(X_MAX_PIN);
#endif
#endif
@@ -132,7 +132,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(X_MIN_PIN), "X_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(X_MIN_PIN), "X_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(X_MIN_PIN);
#endif
#endif
@@ -140,7 +140,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Y_MAX_PIN), "Y_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Y_MAX_PIN), "Y_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Y_MAX_PIN);
#endif
#endif
@@ -148,7 +148,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Y_MIN_PIN), "Y_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Y_MIN_PIN), "Y_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Y_MIN_PIN);
#endif
#endif
@@ -156,7 +156,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Z_MAX_PIN), "Z_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z_MAX_PIN), "Z_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z_MAX_PIN);
#endif
#endif
@@ -164,7 +164,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Z_MIN_PIN), "Z_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z_MIN_PIN), "Z_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z_MIN_PIN);
#endif
#endif
@@ -172,7 +172,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(X2_MAX_PIN), "X2_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(X2_MAX_PIN), "X2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(X2_MAX_PIN);
#endif
#endif
@@ -180,7 +180,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(X2_MIN_PIN), "X2_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(X2_MIN_PIN), "X2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(X2_MIN_PIN);
#endif
#endif
@@ -188,7 +188,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y2_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Y2_MAX_PIN), "Y2_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Y2_MAX_PIN), "Y2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Y2_MAX_PIN);
#endif
#endif
@@ -196,7 +196,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y2_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Y2_MIN_PIN), "Y2_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Y2_MIN_PIN), "Y2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Y2_MIN_PIN);
#endif
#endif
@@ -204,7 +204,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z2_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Z2_MAX_PIN), "Z2_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z2_MAX_PIN), "Z2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z2_MAX_PIN);
#endif
#endif
@@ -212,7 +212,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z2_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Z2_MIN_PIN), "Z2_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z2_MIN_PIN), "Z2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z2_MIN_PIN);
#endif
#endif
@@ -220,7 +220,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z3_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z3_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Z3_MAX_PIN), "Z3_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z3_MAX_PIN), "Z3_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z3_MAX_PIN);
#endif
#endif
@@ -228,7 +228,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z3_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z3_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Z3_MIN_PIN), "Z3_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z3_MIN_PIN), "Z3_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z3_MIN_PIN);
#endif
#endif
@@ -236,7 +236,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z4_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z4_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Z4_MAX_PIN), "Z4_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z4_MAX_PIN), "Z4_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z4_MAX_PIN);
#endif
#endif
@@ -244,7 +244,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z4_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z4_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Z4_MIN_PIN), "Z4_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z4_MIN_PIN), "Z4_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z4_MIN_PIN);
#endif
#endif
@@ -252,7 +252,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MIN_PROBE_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MIN_PROBE_PIN);
#else
- static_assert(digitalPinHasPCICR(Z_MIN_PROBE_PIN), "Z_MIN_PROBE_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z_MIN_PROBE_PIN), "Z_MIN_PROBE_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z_MIN_PROBE_PIN);
#endif
#endif
diff --git a/Marlin/src/HAL/AVR/fastio.cpp b/Marlin/src/HAL/AVR/fastio.cpp
index b51d7f976..70132e71e 100644
--- a/Marlin/src/HAL/AVR/fastio.cpp
+++ b/Marlin/src/HAL/AVR/fastio.cpp
@@ -241,7 +241,7 @@ uint8_t extDigitalRead(const int8_t pin) {
*
* DC values -1.0 to 1.0. Negative duty cycle inverts the pulse.
*/
-uint16_t set_pwm_frequency_hz(const float &hz, const float dca, const float dcb, const float dcc) {
+uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb, const float dcc) {
float count = 0;
if (hz > 0 && (dca || dcb || dcc)) {
count = float(F_CPU) / hz; // 1x prescaler, TOP for 16MHz base freq.
diff --git a/Marlin/src/HAL/AVR/fastio.h b/Marlin/src/HAL/AVR/fastio.h
index dd0163466..cf704179c 100644
--- a/Marlin/src/HAL/AVR/fastio.h
+++ b/Marlin/src/HAL/AVR/fastio.h
@@ -285,7 +285,7 @@ enum ClockSource2 : char {
*/
// Determine which harware PWMs are already in use
-#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN)
+#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN || P == COOLER_AUTO_FAN_PIN)
#if PIN_EXISTS(CONTROLLER_FAN)
#define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN)
#else
diff --git a/Marlin/src/HAL/AVR/inc/SanityCheck.h b/Marlin/src/HAL/AVR/inc/SanityCheck.h
index 731cf9286..51ba24795 100644
--- a/Marlin/src/HAL/AVR/inc/SanityCheck.h
+++ b/Marlin/src/HAL/AVR/inc/SanityCheck.h
@@ -56,3 +56,10 @@
#if BOTH(HAS_TMC_SW_SERIAL, MONITOR_DRIVER_STATUS)
#error "MONITOR_DRIVER_STATUS causes performance issues when used with SoftwareSerial-connected drivers. Disable MONITOR_DRIVER_STATUS or use hardware serial to continue."
#endif
+
+/**
+ * Postmortem debugging
+ */
+#if ENABLED(POSTMORTEM_DEBUGGING)
+ #error "POSTMORTEM_DEBUGGING is not supported on AVR boards."
+#endif
diff --git a/Marlin/src/HAL/AVR/pinsDebug.h b/Marlin/src/HAL/AVR/pinsDebug.h
index dac6b1b15..6bf9f33a0 100644
--- a/Marlin/src/HAL/AVR/pinsDebug.h
+++ b/Marlin/src/HAL/AVR/pinsDebug.h
@@ -235,8 +235,8 @@ static void print_is_also_tied() { SERIAL_ECHOPGM(" is also tied to this pin");
inline void com_print(const uint8_t N, const uint8_t Z) {
const uint8_t *TCCRA = (uint8_t*)TCCR_A(N);
- SERIAL_ECHOPGM(" COM");
- SERIAL_CHAR('0' + N, Z);
+ SERIAL_ECHOPAIR(" COM", AS_CHAR('0' + N));
+ SERIAL_CHAR(Z);
SERIAL_ECHOPAIR(": ", int((*TCCRA >> (6 - Z * 2)) & 0x03));
}
@@ -247,8 +247,8 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
uint8_t WGM = (((*TCCRB & _BV(WGM_2)) >> 1) | (*TCCRA & (_BV(WGM_0) | _BV(WGM_1))));
if (N == 4) WGM |= ((*TCCRB & _BV(WGM_3)) >> 1);
- SERIAL_ECHOPGM(" TIMER");
- SERIAL_CHAR(T + '0', L);
+ SERIAL_ECHOPAIR(" TIMER", AS_CHAR(T + '0'));
+ SERIAL_CHAR(L);
SERIAL_ECHO_SP(3);
if (N == 3) {
@@ -262,19 +262,11 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
SERIAL_ECHOPAIR(" WGM: ", WGM);
com_print(T,L);
SERIAL_ECHOPAIR(" CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) ));
-
- SERIAL_ECHOPGM(" TCCR");
- SERIAL_CHAR(T + '0');
- SERIAL_ECHOPAIR("A: ", *TCCRA);
-
- SERIAL_ECHOPGM(" TCCR");
- SERIAL_CHAR(T + '0');
- SERIAL_ECHOPAIR("B: ", *TCCRB);
+ SERIAL_ECHOPAIR(" TCCR", AS_CHAR(T + '0'), "A: ", *TCCRA);
+ SERIAL_ECHOPAIR(" TCCR", AS_CHAR(T + '0'), "B: ", *TCCRB);
const uint8_t *TMSK = (uint8_t*)TIMSK(T);
- SERIAL_ECHOPGM(" TIMSK");
- SERIAL_CHAR(T + '0');
- SERIAL_ECHOPAIR(": ", *TMSK);
+ SERIAL_ECHOPAIR(" TIMSK", AS_CHAR(T + '0'), ": ", *TMSK);
const uint8_t OCIE = L - 'A' + 1;
if (N == 3) { if (WGM == 0 || WGM == 2 || WGM == 4 || WGM == 6) err_is_counter(); }
diff --git a/Marlin/src/HAL/AVR/spi_pins.h b/Marlin/src/HAL/AVR/spi_pins.h
index f3fa78e2b..831972938 100644
--- a/Marlin/src/HAL/AVR/spi_pins.h
+++ b/Marlin/src/HAL/AVR/spi_pins.h
@@ -51,15 +51,15 @@
#define AVR_SS_PIN 16
#endif
-#ifndef SCK_PIN
- #define SCK_PIN AVR_SCK_PIN
+#ifndef SD_SCK_PIN
+ #define SD_SCK_PIN AVR_SCK_PIN
#endif
-#ifndef MISO_PIN
- #define MISO_PIN AVR_MISO_PIN
+#ifndef SD_MISO_PIN
+ #define SD_MISO_PIN AVR_MISO_PIN
#endif
-#ifndef MOSI_PIN
- #define MOSI_PIN AVR_MOSI_PIN
+#ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN AVR_MOSI_PIN
#endif
-#ifndef SS_PIN
- #define SS_PIN AVR_SS_PIN
+#ifndef SD_SS_PIN
+ #define SD_SS_PIN AVR_SS_PIN
#endif
diff --git a/Marlin/src/HAL/DUE/DebugMonitor.cpp b/Marlin/src/HAL/DUE/DebugMonitor.cpp
deleted file mode 100644
index 79759151d..000000000
--- a/Marlin/src/HAL/DUE/DebugMonitor.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#ifdef ARDUINO_ARCH_SAM
-
-#include "../../core/macros.h"
-#include "../../core/serial.h"
-
-#include "../shared/backtrace/unwinder.h"
-#include "../shared/backtrace/unwmemaccess.h"
-
-#include
-
-// Debug monitor that dumps to the Programming port all status when
-// an exception or WDT timeout happens - And then resets the board
-
-// All the Monitor routines must run with interrupts disabled and
-// under an ISR execution context. That is why we cannot reuse the
-// Serial interrupt routines or any C runtime, as we don't know the
-// state we are when running them
-
-// A SW memory barrier, to ensure GCC does not overoptimize loops
-#define sw_barrier() __asm__ volatile("": : :"memory");
-
-// (re)initialize UART0 as a monitor output to 250000,n,8,1
-static void TXBegin() {
-
- // Disable UART interrupt in NVIC
- NVIC_DisableIRQ( UART_IRQn );
-
- // We NEED memory barriers to ensure Interrupts are actually disabled!
- // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
- __DSB();
- __ISB();
-
- // Disable clock
- pmc_disable_periph_clk( ID_UART );
-
- // Configure PMC
- pmc_enable_periph_clk( ID_UART );
-
- // Disable PDC channel
- UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
-
- // Reset and disable receiver and transmitter
- UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
-
- // Configure mode: 8bit, No parity, 1 bit stop
- UART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
-
- // Configure baudrate (asynchronous, no oversampling) to BAUDRATE bauds
- UART->UART_BRGR = (SystemCoreClock / (BAUDRATE << 4));
-
- // Enable receiver and transmitter
- UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
-}
-
-// Send character through UART with no interrupts
-static void TX(char c) {
- while (!(UART->UART_SR & UART_SR_TXRDY)) { WDT_Restart(WDT); sw_barrier(); };
- UART->UART_THR = c;
-}
-
-// Send String through UART
-static void TX(const char* s) {
- while (*s) TX(*s++);
-}
-
-static void TXDigit(uint32_t d) {
- if (d < 10) TX((char)(d+'0'));
- else if (d < 16) TX((char)(d+'A'-10));
- else TX('?');
-}
-
-// Send Hex number thru UART
-static void TXHex(uint32_t v) {
- TX("0x");
- for (uint8_t i = 0; i < 8; i++, v <<= 4)
- TXDigit((v >> 28) & 0xF);
-}
-
-// Send Decimal number thru UART
-static void TXDec(uint32_t v) {
- if (!v) {
- TX('0');
- return;
- }
-
- char nbrs[14];
- char *p = &nbrs[0];
- while (v != 0) {
- *p++ = '0' + (v % 10);
- v /= 10;
- }
- do {
- p--;
- TX(*p);
- } while (p != &nbrs[0]);
-}
-
-// Dump a backtrace entry
-static bool UnwReportOut(void* ctx, const UnwReport* bte) {
- int* p = (int*)ctx;
-
- (*p)++;
- TX('#'); TXDec(*p); TX(" : ");
- TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
- TX('+'); TXDec(bte->address - bte->function);
- TX(" PC:");TXHex(bte->address); TX('\n');
- return true;
-}
-
-#ifdef UNW_DEBUG
- void UnwPrintf(const char* format, ...) {
- char dest[256];
- va_list argptr;
- va_start(argptr, format);
- vsprintf(dest, format, argptr);
- va_end(argptr);
- TX(&dest[0]);
- }
-#endif
-
-/* Table of function pointers for passing to the unwinder */
-static const UnwindCallbacks UnwCallbacks = {
- UnwReportOut,
- UnwReadW,
- UnwReadH,
- UnwReadB
- #ifdef UNW_DEBUG
- , UnwPrintf
- #endif
-};
-
-/**
- * HardFaultHandler_C:
- * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
- * as the parameter. We can then read the values from the stack and place them
- * into local variables for ease of reading.
- * We then read the various Fault Status and Address Registers to help decode
- * cause of the fault.
- * The function ends with a BKPT instruction to force control back into the debugger
- */
-extern "C"
-void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
-
- static const char* causestr[] = {
- "NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
- };
-
- UnwindFrame btf;
-
- // Dump report to the Programming port (interrupts are DISABLED)
- TXBegin();
- TX("\n\n## Software Fault detected ##\n");
- TX("Cause: "); TX(causestr[cause]); TX('\n');
-
- TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
- TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
- TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
- TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
- TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
- TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
- TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
- TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
-
- // Configurable Fault Status Register
- // Consists of MMSR, BFSR and UFSR
- TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
-
- // Hard Fault Status Register
- TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
-
- // Debug Fault Status Register
- TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
-
- // Auxiliary Fault Status Register
- TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
-
- // Read the Fault Address Registers. These may not contain valid values.
- // Check BFARVALID/MMARVALID to see if they are valid values
- // MemManage Fault Address Register
- TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
-
- // Bus Fault Address Register
- TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
-
- TX("ExcLR: "); TXHex(lr); TX('\n');
- TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
-
- btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
- btf.fp = btf.sp;
- btf.lr = ((unsigned long)sp[5]);
- btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
-
- // Perform a backtrace
- TX("\nBacktrace:\n\n");
- int ctr = 0;
- UnwindStart(&btf, &UnwCallbacks, &ctr);
-
- // Disable all NVIC interrupts
- NVIC->ICER[0] = 0xFFFFFFFF;
- NVIC->ICER[1] = 0xFFFFFFFF;
-
- // Relocate VTOR table to default position
- SCB->VTOR = 0;
-
- // Disable USB
- otg_disable();
-
- // Restart watchdog
- WDT_Restart(WDT);
-
- // Reset controller
- NVIC_SystemReset();
- for (;;) WDT_Restart(WDT);
-}
-
-__attribute__((naked)) void NMI_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#0")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void HardFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#1")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void MemManage_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#2")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void BusFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#3")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void UsageFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#4")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void DebugMon_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#5")
- A("b HardFault_HandlerC")
- );
-}
-
-/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
-__attribute__((naked)) void WDT_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#6")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void RSTC_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#7")
- A("b HardFault_HandlerC")
- );
-}
-
-#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/HAL.cpp b/Marlin/src/HAL/DUE/HAL.cpp
index 6ce85a464..a3985652e 100644
--- a/Marlin/src/HAL/DUE/HAL.cpp
+++ b/Marlin/src/HAL/DUE/HAL.cpp
@@ -40,6 +40,8 @@ uint16_t HAL_adc_result;
// Public functions
// ------------------------
+TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
+
// HAL initialization task
void HAL_init() {
// Initialize the USB stack
@@ -47,6 +49,7 @@ void HAL_init() {
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
#endif
usb_task_init();
+ TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
}
// HAL idle task
@@ -74,6 +77,8 @@ uint8_t HAL_get_reset_source() {
}
}
+void HAL_reboot() { rstc_start_software_reset(RSTC); }
+
void _delay_ms(const int delay_ms) {
// Todo: port for Due?
delay(delay_ms);
@@ -102,4 +107,18 @@ uint16_t HAL_adc_get_result() {
return HAL_adc_result;
}
+// Forward the default serial ports
+#if USING_HW_SERIAL0
+ DefaultSerial1 MSerial0(false, Serial);
+#endif
+#if USING_HW_SERIAL1
+ DefaultSerial2 MSerial1(false, Serial1);
+#endif
+#if USING_HW_SERIAL2
+ DefaultSerial3 MSerial2(false, Serial2);
+#endif
+#if USING_HW_SERIAL3
+ DefaultSerial4 MSerial3(false, Serial3);
+#endif
+
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/HAL.h b/Marlin/src/HAL/DUE/HAL.h
index 88ace5957..1bc3bf741 100644
--- a/Marlin/src/HAL/DUE/HAL.h
+++ b/Marlin/src/HAL/DUE/HAL.h
@@ -36,26 +36,44 @@
#include
-#define _MSERIAL(X) Serial##X
-#define MSERIAL(X) _MSERIAL(X)
-#define Serial0 Serial
+#include "../../core/serial_hook.h"
-// Define MYSERIAL0/1 before MarlinSerial includes!
+typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
+typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
+typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
+typedef ForwardSerial1Class< decltype(Serial3) > DefaultSerial4;
+extern DefaultSerial1 MSerial0;
+extern DefaultSerial2 MSerial1;
+extern DefaultSerial3 MSerial2;
+extern DefaultSerial4 MSerial3;
+
+#define _MSERIAL(X) MSerial##X
+#define MSERIAL(X) _MSERIAL(X)
+
+// Define MYSERIAL1/2 before MarlinSerial includes!
#if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER)
- #define MYSERIAL0 customizedSerial1
+ #define MYSERIAL1 customizedSerial1
#elif WITHIN(SERIAL_PORT, 0, 3)
- #define MYSERIAL0 MSERIAL(SERIAL_PORT)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
- #error "The required SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "The required SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1 || ENABLED(EMERGENCY_PARSER)
- #define MYSERIAL1 customizedSerial2
+ #define MYSERIAL2 customizedSerial2
#elif WITHIN(SERIAL_PORT_2, 0, 3)
- #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
+ #define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
- #error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+#endif
+
+#ifdef MMU2_SERIAL_PORT
+ #if WITHIN(MMU2_SERIAL_PORT, 0, 3)
+ #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
+ #else
+ #error "MMU2_SERIAL_PORT must be from 0 to 3."
#endif
#endif
@@ -65,7 +83,7 @@
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
@@ -75,16 +93,6 @@
// On AVR this is in math.h?
#define square(x) ((x)*(x))
-#ifndef strncpy_P
- #define strncpy_P(dest, src, num) strncpy((dest), (src), (num))
-#endif
-
-// Fix bug in pgm_read_ptr
-#undef pgm_read_ptr
-#define pgm_read_ptr(addr) (*((void**)(addr)))
-#undef pgm_read_word
-#define pgm_read_word(addr) (*((uint16_t*)(addr)))
-
typedef int8_t pin_t;
#define SHARED_SERVOS HAS_SERVOS
@@ -105,7 +113,7 @@ void sei(); // Enable interrupts
void HAL_clear_reset_source(); // clear reset reason
uint8_t HAL_get_reset_source(); // get reset reason
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+void HAL_reboot();
//
// ADC
@@ -153,10 +161,16 @@ void HAL_init();
//
void _delay_ms(const int delay);
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
int freeMemory();
-#pragma GCC diagnostic pop
+
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic pop
+#endif
#ifdef __cplusplus
extern "C" {
diff --git a/Marlin/src/HAL/DUE/HAL_MinSerial.cpp b/Marlin/src/HAL/DUE/HAL_MinSerial.cpp
new file mode 100644
index 000000000..93c4ed67d
--- /dev/null
+++ b/Marlin/src/HAL/DUE/HAL_MinSerial.cpp
@@ -0,0 +1,91 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef ARDUINO_ARCH_SAM
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+
+#include "../shared/HAL_MinSerial.h"
+
+#include
+
+static void TXBegin() {
+ // Disable UART interrupt in NVIC
+ NVIC_DisableIRQ( UART_IRQn );
+
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ __DSB();
+ __ISB();
+
+ // Disable clock
+ pmc_disable_periph_clk( ID_UART );
+
+ // Configure PMC
+ pmc_enable_periph_clk( ID_UART );
+
+ // Disable PDC channel
+ UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
+
+ // Reset and disable receiver and transmitter
+ UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
+
+ // Configure mode: 8bit, No parity, 1 bit stop
+ UART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
+
+ // Configure baudrate (asynchronous, no oversampling) to BAUDRATE bauds
+ UART->UART_BRGR = (SystemCoreClock / (BAUDRATE << 4));
+
+ // Enable receiver and transmitter
+ UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
+}
+
+// A SW memory barrier, to ensure GCC does not overoptimize loops
+#define sw_barrier() __asm__ volatile("": : :"memory");
+static void TX(char c) {
+ while (!(UART->UART_SR & UART_SR_TXRDY)) { WDT_Restart(WDT); sw_barrier(); };
+ UART->UART_THR = c;
+}
+
+void install_min_serial() {
+ HAL_min_serial_init = &TXBegin;
+ HAL_min_serial_out = &TX;
+}
+
+#if DISABLED(DYNAMIC_VECTORTABLE)
+extern "C" {
+ __attribute__((naked)) void JumpHandler_ASM() {
+ __asm__ __volatile__ (
+ "b CommonHandler_ASM\n"
+ );
+ }
+ void __attribute__((naked, alias("JumpHandler_ASM"))) HardFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) BusFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) UsageFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) MemManage_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) NMI_Handler();
+}
+#endif
+
+#endif // POSTMORTEM_DEBUGGING
+#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/HAL_SPI.cpp b/Marlin/src/HAL/DUE/HAL_SPI.cpp
index 0451d8bcc..f42e8a980 100644
--- a/Marlin/src/HAL/DUE/HAL_SPI.cpp
+++ b/Marlin/src/HAL/DUE/HAL_SPI.cpp
@@ -56,8 +56,8 @@
#pragma GCC optimize (3)
typedef uint8_t (*pfnSpiTransfer)(uint8_t b);
- typedef void (*pfnSpiRxBlock)(uint8_t* buf, uint32_t nbyte);
- typedef void (*pfnSpiTxBlock)(const uint8_t* buf, uint32_t nbyte);
+ typedef void (*pfnSpiRxBlock)(uint8_t *buf, uint32_t nbyte);
+ typedef void (*pfnSpiTxBlock)(const uint8_t *buf, uint32_t nbyte);
/* ---------------- Macros to be able to access definitions from asm */
#define _PORT(IO) DIO ## IO ## _WPORT
@@ -69,10 +69,10 @@
// run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
static uint8_t spiTransferTx0(uint8_t bout) { // using Mode 0
- uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
- uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
- uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; /* SODR of port */
+ uint32_t MOSI_MASK = PIN_MASK(SD_MOSI_PIN);
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
uint32_t idx = 0;
/* Negate bout, as the assembler requires a negated value */
@@ -154,9 +154,9 @@
static uint8_t spiTransferRx0(uint8_t) { // using Mode 0
uint32_t bin = 0;
uint32_t work = 0;
- uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
- uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
/* The software SPI routine */
__asm__ __volatile__(
@@ -225,36 +225,36 @@
static uint8_t spiTransfer1(uint8_t b) { // using Mode 0
int bits = 8;
do {
- WRITE(MOSI_PIN, b & 0x80);
+ WRITE(SD_MOSI_PIN, b & 0x80);
b <<= 1; // little setup time
- WRITE(SCK_PIN, HIGH);
+ WRITE(SD_SCK_PIN, HIGH);
DELAY_NS(125); // 10 cycles @ 84mhz
- b |= (READ(MISO_PIN) != 0);
+ b |= (READ(SD_MISO_PIN) != 0);
- WRITE(SCK_PIN, LOW);
+ WRITE(SD_SCK_PIN, LOW);
DELAY_NS(125); // 10 cycles @ 84mhz
} while (--bits);
return b;
}
// all the others
- static uint32_t spiDelayCyclesX4 = (F_CPU) / 1000000; // 4µs => 125khz
+ static uint32_t spiDelayCyclesX4 = 4 * (F_CPU) / 1000000; // 4µs => 125khz
static uint8_t spiTransferX(uint8_t b) { // using Mode 0
int bits = 8;
do {
- WRITE(MOSI_PIN, b & 0x80);
+ WRITE(SD_MOSI_PIN, b & 0x80);
b <<= 1; // little setup time
- WRITE(SCK_PIN, HIGH);
- __delay_4cycles(spiDelayCyclesX4);
+ WRITE(SD_SCK_PIN, HIGH);
+ DELAY_CYCLES(spiDelayCyclesX4);
- b |= (READ(MISO_PIN) != 0);
+ b |= (READ(SD_MISO_PIN) != 0);
- WRITE(SCK_PIN, LOW);
- __delay_4cycles(spiDelayCyclesX4);
+ WRITE(SD_SCK_PIN, LOW);
+ DELAY_CYCLES(spiDelayCyclesX4);
} while (--bits);
return b;
}
@@ -270,11 +270,11 @@
static pfnSpiTransfer spiTransferTx = (pfnSpiTransfer)spiTransferX;
// Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
- static void spiTxBlock0(const uint8_t* ptr, uint32_t todo) {
- uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
- uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
- uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ static void spiTxBlock0(const uint8_t *ptr, uint32_t todo) {
+ uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; /* SODR of port */
+ uint32_t MOSI_MASK = PIN_MASK(SD_MOSI_PIN);
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
uint32_t work = 0;
uint32_t txval = 0;
@@ -349,12 +349,12 @@
);
}
- static void spiRxBlock0(uint8_t* ptr, uint32_t todo) {
+ static void spiRxBlock0(uint8_t *ptr, uint32_t todo) {
uint32_t bin = 0;
uint32_t work = 0;
- uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
- uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
/* The software SPI routine */
__asm__ __volatile__(
@@ -425,13 +425,13 @@
);
}
- static void spiTxBlockX(const uint8_t* buf, uint32_t todo) {
+ static void spiTxBlockX(const uint8_t *buf, uint32_t todo) {
do {
(void)spiTransferTx(*buf++);
} while (--todo);
}
- static void spiRxBlockX(uint8_t* buf, uint32_t todo) {
+ static void spiRxBlockX(uint8_t *buf, uint32_t todo) {
do {
*buf++ = spiTransferRx(0xFF);
} while (--todo);
@@ -442,31 +442,31 @@
static pfnSpiRxBlock spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
#if MB(ALLIGATOR)
- #define _SS_WRITE(S) WRITE(SS_PIN, S)
+ #define _SS_WRITE(S) WRITE(SD_SS_PIN, S)
#else
#define _SS_WRITE(S) NOOP
#endif
void spiBegin() {
- SET_OUTPUT(SS_PIN);
+ SET_OUTPUT(SD_SS_PIN);
_SS_WRITE(HIGH);
- SET_OUTPUT(SCK_PIN);
- SET_INPUT(MISO_PIN);
- SET_OUTPUT(MOSI_PIN);
+ SET_OUTPUT(SD_SCK_PIN);
+ SET_INPUT(SD_MISO_PIN);
+ SET_OUTPUT(SD_MOSI_PIN);
}
uint8_t spiRec() {
_SS_WRITE(LOW);
- WRITE(MOSI_PIN, HIGH); // Output 1s 1
+ WRITE(SD_MOSI_PIN, HIGH); // Output 1s 1
uint8_t b = spiTransferRx(0xFF);
_SS_WRITE(HIGH);
return b;
}
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
if (nbyte) {
_SS_WRITE(LOW);
- WRITE(MOSI_PIN, HIGH); // Output 1s 1
+ WRITE(SD_MOSI_PIN, HIGH); // Output 1s 1
spiRxBlock(buf, nbyte);
_SS_WRITE(HIGH);
}
@@ -478,7 +478,7 @@
_SS_WRITE(HIGH);
}
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
_SS_WRITE(LOW);
(void)spiTransferTx(token);
spiTxBlock(buf, 512);
@@ -510,7 +510,7 @@
spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
break;
default:
- spiDelayCyclesX4 = ((F_CPU) / 1000000) >> (6 - spiRate);
+ spiDelayCyclesX4 = ((F_CPU) / 1000000) >> (6 - spiRate) << 2; // spiRate of 2 gives the maximum error with current CPU
spiTransferTx = (pfnSpiTransfer)spiTransferX;
spiTransferRx = (pfnSpiTransfer)spiTransferX;
spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
@@ -519,8 +519,8 @@
}
_SS_WRITE(HIGH);
- WRITE(MOSI_PIN, HIGH);
- WRITE(SCK_PIN, LOW);
+ WRITE(SD_MOSI_PIN, HIGH);
+ WRITE(SD_SCK_PIN, LOW);
}
/** Begin SPI transaction, set clock, bit order, data mode */
@@ -575,20 +575,20 @@
// Configure SPI pins
PIO_Configure(
- g_APinDescription[SCK_PIN].pPort,
- g_APinDescription[SCK_PIN].ulPinType,
- g_APinDescription[SCK_PIN].ulPin,
- g_APinDescription[SCK_PIN].ulPinConfiguration);
+ g_APinDescription[SD_SCK_PIN].pPort,
+ g_APinDescription[SD_SCK_PIN].ulPinType,
+ g_APinDescription[SD_SCK_PIN].ulPin,
+ g_APinDescription[SD_SCK_PIN].ulPinConfiguration);
PIO_Configure(
- g_APinDescription[MOSI_PIN].pPort,
- g_APinDescription[MOSI_PIN].ulPinType,
- g_APinDescription[MOSI_PIN].ulPin,
- g_APinDescription[MOSI_PIN].ulPinConfiguration);
+ g_APinDescription[SD_MOSI_PIN].pPort,
+ g_APinDescription[SD_MOSI_PIN].ulPinType,
+ g_APinDescription[SD_MOSI_PIN].ulPin,
+ g_APinDescription[SD_MOSI_PIN].ulPinConfiguration);
PIO_Configure(
- g_APinDescription[MISO_PIN].pPort,
- g_APinDescription[MISO_PIN].ulPinType,
- g_APinDescription[MISO_PIN].ulPin,
- g_APinDescription[MISO_PIN].ulPinConfiguration);
+ g_APinDescription[SD_MISO_PIN].pPort,
+ g_APinDescription[SD_MISO_PIN].ulPinType,
+ g_APinDescription[SD_MISO_PIN].ulPin,
+ g_APinDescription[SD_MISO_PIN].ulPinConfiguration);
// set master mode, peripheral select, fault detection
SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
@@ -606,7 +606,7 @@
WRITE(SPI_EEPROM1_CS, HIGH);
WRITE(SPI_EEPROM2_CS, HIGH);
WRITE(SPI_FLASH_CS, HIGH);
- WRITE(SS_PIN, HIGH);
+ WRITE(SD_SS_PIN, HIGH);
OUT_WRITE(SDSS, LOW);
@@ -645,7 +645,7 @@
}
// Read from SPI into buffer
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
if (!nbyte) return;
--nbyte;
for (int i = 0; i < nbyte; i++) {
@@ -668,7 +668,7 @@
//DELAY_US(1U);
}
- void spiSend(const uint8_t* buf, size_t nbyte) {
+ void spiSend(const uint8_t *buf, size_t nbyte) {
if (!nbyte) return;
--nbyte;
for (size_t i = 0; i < nbyte; i++) {
@@ -689,7 +689,7 @@
FLUSH_RX();
}
- void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {
+ void spiSend(uint32_t chan, const uint8_t *buf, size_t nbyte) {
if (!nbyte) return;
--nbyte;
for (size_t i = 0; i < nbyte; i++) {
@@ -702,7 +702,7 @@
}
// Write from buffer to SPI
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
SPI0->SPI_TDR = (uint32_t)token | SPI_PCS(SPI_CHAN);
WHILE_TX(0);
//WHILE_RX(0);
@@ -801,19 +801,19 @@
uint8_t spiRec() { return (uint8_t)spiTransfer(0xFF); }
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
for (int i = 0; i < nbyte; i++)
buf[i] = spiTransfer(0xFF);
}
void spiSend(uint8_t data) { spiTransfer(data); }
- void spiSend(const uint8_t* buf, size_t nbyte) {
+ void spiSend(const uint8_t *buf, size_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++)
spiTransfer(buf[i]);
}
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
spiTransfer(token);
for (uint16_t i = 0; i < 512; i++)
spiTransfer(buf[i]);
diff --git a/Marlin/src/HAL/DUE/MarlinSerial.cpp b/Marlin/src/HAL/DUE/MarlinSerial.cpp
index c9a372eeb..5b333fbeb 100644
--- a/Marlin/src/HAL/DUE/MarlinSerial.cpp
+++ b/Marlin/src/HAL/DUE/MarlinSerial.cpp
@@ -382,7 +382,7 @@ void MarlinSerial::flush() {
}
template
-void MarlinSerial::write(const uint8_t c) {
+size_t MarlinSerial::write(const uint8_t c) {
_written = true;
if (Cfg::TX_SIZE == 0) {
@@ -400,7 +400,7 @@ void MarlinSerial::write(const uint8_t c) {
// XOFF char at the RX isr, but it is properly handled there
if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
HWUART->UART_THR = c;
- return;
+ return 1;
}
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
@@ -428,6 +428,7 @@ void MarlinSerial::write(const uint8_t c) {
// Enable TX isr - Non atomic, but it will eventually enable TX isr
HWUART->UART_IER = UART_IER_TXRDY;
}
+ return 1;
}
template
@@ -473,169 +474,16 @@ void MarlinSerial::flushTX() {
}
}
-/**
- * Imports from print.h
- */
-
-template
-void MarlinSerial::print(char c, int base) {
- print((long)c, base);
-}
-
-template
-void MarlinSerial::print(unsigned char b, int base) {
- print((unsigned long)b, base);
-}
-
-template
-void MarlinSerial::print(int n, int base) {
- print((long)n, base);
-}
-
-template
-void MarlinSerial::print(unsigned int n, int base) {
- print((unsigned long)n, base);
-}
-
-template
-void MarlinSerial::print(long n, int base) {
- if (base == 0) write(n);
- else if (base == 10) {
- if (n < 0) { print('-'); n = -n; }
- printNumber(n, 10);
- }
- else
- printNumber(n, base);
-}
-
-template
-void MarlinSerial::print(unsigned long n, int base) {
- if (base == 0) write(n);
- else printNumber(n, base);
-}
-
-template
-void MarlinSerial::print(double n, int digits) {
- printFloat(n, digits);
-}
-
-template
-void MarlinSerial::println() {
- print('\r');
- print('\n');
-}
-
-template
-void MarlinSerial::println(const String& s) {
- print(s);
- println();
-}
-
-template
-void MarlinSerial::println(const char c[]) {
- print(c);
- println();
-}
-
-template
-void MarlinSerial::println(char c, int base) {
- print(c, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned char b, int base) {
- print(b, base);
- println();
-}
-
-template
-void MarlinSerial::println(int n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned int n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(long n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned long n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(double n, int digits) {
- print(n, digits);
- println();
-}
-
-// Private Methods
-template
-void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
- if (n) {
- unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
- int8_t i = 0;
- while (n) {
- buf[i++] = n % base;
- n /= base;
- }
- while (i--)
- print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
- }
- else
- print('0');
-}
-
-template
-void MarlinSerial::printFloat(double number, uint8_t digits) {
- // Handle negative numbers
- if (number < 0.0) {
- print('-');
- number = -number;
- }
-
- // Round correctly so that print(1.999, 2) prints as "2.00"
- double rounding = 0.5;
- LOOP_L_N(i, digits) rounding *= 0.1;
- number += rounding;
-
- // Extract the integer part of the number and print it
- unsigned long int_part = (unsigned long)number;
- double remainder = number - (double)int_part;
- print(int_part);
-
- // Print the decimal point, but only if there are digits beyond
- if (digits) {
- print('.');
- // Extract digits from the remainder one at a time
- while (digits--) {
- remainder *= 10.0;
- int toPrint = int(remainder);
- print(toPrint);
- remainder -= toPrint;
- }
- }
-}
// If not using the USB port as serial port
-#if SERIAL_PORT >= 0
- template class MarlinSerial>; // Define
- MarlinSerial> customizedSerial1; // Instantiate
+#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
+ template class MarlinSerial< MarlinSerialCfg >;
+ MSerialT customizedSerial1(MarlinSerialCfg::EMERGENCYPARSER);
#endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
- template class MarlinSerial>; // Define
- MarlinSerial> customizedSerial2; // Instantiate
+ template class MarlinSerial< MarlinSerialCfg >;
+ MSerialT2 customizedSerial2(MarlinSerialCfg::EMERGENCYPARSER);
#endif
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/MarlinSerial.h b/Marlin/src/HAL/DUE/MarlinSerial.h
index a194eba2f..0fb15cf8a 100644
--- a/Marlin/src/HAL/DUE/MarlinSerial.h
+++ b/Marlin/src/HAL/DUE/MarlinSerial.h
@@ -30,11 +30,7 @@
#include
#include "../../inc/MarlinConfigPre.h"
-
-#define DEC 10
-#define HEX 16
-#define OCT 8
-#define BIN 2
+#include "../../core/serial_hook.h"
// Define constants and variables for buffering incoming serial data. We're
// using a ring buffer (I think), in which rx_buffer_head is the index of the
@@ -119,7 +115,7 @@ public:
static int read();
static void flush();
static ring_buffer_pos_t available();
- static void write(const uint8_t c);
+ static size_t write(const uint8_t c);
static void flushTX();
static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
@@ -128,35 +124,6 @@ public:
FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
-
- FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
- FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
- FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
- FORCE_INLINE static void print(const char* str) { write(str); }
-
- static void print(char, int = 0);
- static void print(unsigned char, int = 0);
- static void print(int, int = DEC);
- static void print(unsigned int, int = DEC);
- static void print(long, int = DEC);
- static void print(unsigned long, int = DEC);
- static void print(double, int = 2);
-
- static void println(const String& s);
- static void println(const char[]);
- static void println(char, int = 0);
- static void println(unsigned char, int = 0);
- static void println(int, int = DEC);
- static void println(unsigned int, int = DEC);
- static void println(long, int = DEC);
- static void println(unsigned long, int = DEC);
- static void println(double, int = 2);
- static void println();
- operator bool() { return true; }
-
-private:
- static void printNumber(unsigned long, const uint8_t);
- static void printFloat(double, uint8_t);
};
// Serial port configuration
@@ -173,10 +140,12 @@ struct MarlinSerialCfg {
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
};
-#if SERIAL_PORT >= 0
- extern MarlinSerial> customizedSerial1;
+#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT;
+ extern MSerialT customizedSerial1;
#endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
- extern MarlinSerial> customizedSerial2;
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT2;
+ extern MSerialT2 customizedSerial2;
#endif
diff --git a/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp b/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp
index a41dbfeb7..fca677c79 100644
--- a/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp
+++ b/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp
@@ -33,10 +33,6 @@
#include "MarlinSerialUSB.h"
-#if ENABLED(EMERGENCY_PARSER)
- #include "../../feature/e_parser.h"
-#endif
-
// Imports from Atmel USB Stack/CDC implementation
extern "C" {
bool usb_task_cdc_isenabled();
@@ -50,10 +46,6 @@ extern "C" {
// Pending character
static int pending_char = -1;
-#if ENABLED(EMERGENCY_PARSER)
- static EmergencyParser::State emergency_state; // = EP_RESET
-#endif
-
// Public Methods
void MarlinSerialUSB::begin(const long) {}
@@ -73,7 +65,7 @@ int MarlinSerialUSB::peek() {
pending_char = udi_cdc_getc();
- TERN_(EMERGENCY_PARSER, emergency_parser.update(emergency_state, (char)pending_char));
+ TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast(this)->emergency_state, (char)pending_char));
return pending_char;
}
@@ -95,29 +87,27 @@ int MarlinSerialUSB::read() {
int c = udi_cdc_getc();
- TERN_(EMERGENCY_PARSER, emergency_parser.update(emergency_state, (char)c));
+ TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast(this)->emergency_state, (char)c));
return c;
}
-bool MarlinSerialUSB::available() {
- /* If Pending chars */
- return pending_char >= 0 ||
- /* or USB CDC enumerated and configured on the PC side and some
- bytes where sent to us */
- (usb_task_cdc_isenabled() && udi_cdc_is_rx_ready());
+int MarlinSerialUSB::available() {
+ if (pending_char > 0) return pending_char;
+ return pending_char == 0 ||
+ // or USB CDC enumerated and configured on the PC side and some bytes where sent to us */
+ (usb_task_cdc_isenabled() && udi_cdc_is_rx_ready());
}
void MarlinSerialUSB::flush() { }
-void MarlinSerialUSB::flushTX() { }
-void MarlinSerialUSB::write(const uint8_t c) {
+size_t MarlinSerialUSB::write(const uint8_t c) {
/* Do not even bother sending anything if USB CDC is not enumerated
or not configured on the PC side or there is no program on the PC
listening to our messages */
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
- return;
+ return 0;
/* Wait until the PC has read the pending to be sent data */
while (usb_task_cdc_isenabled() &&
@@ -129,161 +119,20 @@ void MarlinSerialUSB::write(const uint8_t c) {
or not configured on the PC side or there is no program on the PC
listening to our messages at this point */
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
- return;
+ return 0;
// Fifo full
// udi_cdc_signal_overrun();
udi_cdc_putc(c);
-}
-
-/**
- * Imports from print.h
- */
-
-void MarlinSerialUSB::print(char c, int base) {
- print((long)c, base);
-}
-
-void MarlinSerialUSB::print(unsigned char b, int base) {
- print((unsigned long)b, base);
-}
-
-void MarlinSerialUSB::print(int n, int base) {
- print((long)n, base);
-}
-
-void MarlinSerialUSB::print(unsigned int n, int base) {
- print((unsigned long)n, base);
-}
-
-void MarlinSerialUSB::print(long n, int base) {
- if (base == 0)
- write(n);
- else if (base == 10) {
- if (n < 0) {
- print('-');
- n = -n;
- }
- printNumber(n, 10);
- }
- else
- printNumber(n, base);
-}
-
-void MarlinSerialUSB::print(unsigned long n, int base) {
- if (base == 0) write(n);
- else printNumber(n, base);
-}
-
-void MarlinSerialUSB::print(double n, int digits) {
- printFloat(n, digits);
-}
-
-void MarlinSerialUSB::println() {
- print('\r');
- print('\n');
-}
-
-void MarlinSerialUSB::println(const String& s) {
- print(s);
- println();
-}
-
-void MarlinSerialUSB::println(const char c[]) {
- print(c);
- println();
-}
-
-void MarlinSerialUSB::println(char c, int base) {
- print(c, base);
- println();
-}
-
-void MarlinSerialUSB::println(unsigned char b, int base) {
- print(b, base);
- println();
-}
-
-void MarlinSerialUSB::println(int n, int base) {
- print(n, base);
- println();
-}
-
-void MarlinSerialUSB::println(unsigned int n, int base) {
- print(n, base);
- println();
-}
-
-void MarlinSerialUSB::println(long n, int base) {
- print(n, base);
- println();
-}
-
-void MarlinSerialUSB::println(unsigned long n, int base) {
- print(n, base);
- println();
-}
-
-void MarlinSerialUSB::println(double n, int digits) {
- print(n, digits);
- println();
-}
-
-// Private Methods
-
-void MarlinSerialUSB::printNumber(unsigned long n, uint8_t base) {
- if (n) {
- unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
- int8_t i = 0;
- while (n) {
- buf[i++] = n % base;
- n /= base;
- }
- while (i--)
- print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
- }
- else
- print('0');
-}
-
-void MarlinSerialUSB::printFloat(double number, uint8_t digits) {
- // Handle negative numbers
- if (number < 0.0) {
- print('-');
- number = -number;
- }
-
- // Round correctly so that print(1.999, 2) prints as "2.00"
- double rounding = 0.5;
- LOOP_L_N(i, digits)
- rounding *= 0.1;
-
- number += rounding;
-
- // Extract the integer part of the number and print it
- unsigned long int_part = (unsigned long)number;
- double remainder = number - (double)int_part;
- print(int_part);
-
- // Print the decimal point, but only if there are digits beyond
- if (digits) {
- print('.');
- // Extract digits from the remainder one at a time
- while (digits--) {
- remainder *= 10.0;
- int toPrint = int(remainder);
- print(toPrint);
- remainder -= toPrint;
- }
- }
+ return 1;
}
// Preinstantiate
#if SERIAL_PORT == -1
- MarlinSerialUSB customizedSerial1;
+ MSerialT customizedSerial1(TERN0(EMERGENCY_PARSER, true));
#endif
#if SERIAL_PORT_2 == -1
- MarlinSerialUSB customizedSerial2;
+ MSerialT customizedSerial2(TERN0(EMERGENCY_PARSER, true));
#endif
#endif // HAS_USB_SERIAL
diff --git a/Marlin/src/HAL/DUE/MarlinSerialUSB.h b/Marlin/src/HAL/DUE/MarlinSerialUSB.h
index 2e3622e55..4c299dced 100644
--- a/Marlin/src/HAL/DUE/MarlinSerialUSB.h
+++ b/Marlin/src/HAL/DUE/MarlinSerialUSB.h
@@ -27,73 +27,37 @@
*/
#include "../../inc/MarlinConfig.h"
-
#if HAS_USB_SERIAL
#include
+#include "../../core/serial_hook.h"
-#define DEC 10
-#define HEX 16
-#define OCT 8
-#define BIN 2
-class MarlinSerialUSB {
-
-public:
- MarlinSerialUSB() {};
- static void begin(const long);
- static void end();
- static int peek();
- static int read();
- static void flush();
- static void flushTX();
- static bool available();
- static void write(const uint8_t c);
+struct MarlinSerialUSB {
+ void begin(const long);
+ void end();
+ int peek();
+ int read();
+ void flush();
+ int available();
+ size_t write(const uint8_t c);
#if ENABLED(SERIAL_STATS_DROPPED_RX)
- FORCE_INLINE static uint32_t dropped() { return 0; }
+ FORCE_INLINE uint32_t dropped() { return 0; }
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- FORCE_INLINE static int rxMaxEnqueued() { return 0; }
+ FORCE_INLINE int rxMaxEnqueued() { return 0; }
#endif
-
- FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
- FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
- FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
- FORCE_INLINE static void print(const char* str) { write(str); }
-
- static void print(char, int = 0);
- static void print(unsigned char, int = 0);
- static void print(int, int = DEC);
- static void print(unsigned int, int = DEC);
- static void print(long, int = DEC);
- static void print(unsigned long, int = DEC);
- static void print(double, int = 2);
-
- static void println(const String& s);
- static void println(const char[]);
- static void println(char, int = 0);
- static void println(unsigned char, int = 0);
- static void println(int, int = DEC);
- static void println(unsigned int, int = DEC);
- static void println(long, int = DEC);
- static void println(unsigned long, int = DEC);
- static void println(double, int = 2);
- static void println();
- operator bool() { return true; }
-
-private:
- static void printNumber(unsigned long, const uint8_t);
- static void printFloat(double, uint8_t);
};
+typedef Serial1Class MSerialT;
#if SERIAL_PORT == -1
- extern MarlinSerialUSB customizedSerial1;
+ extern MSerialT customizedSerial1;
#endif
#if SERIAL_PORT_2 == -1
- extern MarlinSerialUSB customizedSerial2;
+ extern MSerialT customizedSerial2;
#endif
#endif // HAS_USB_SERIAL
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
index be4b49c0f..d07da15ad 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
@@ -64,12 +64,11 @@
#include "../../../MarlinCore.h"
-void spiBegin();
-void spiInit(uint8_t spiRate);
-void spiSend(uint8_t b);
-void spiSend(const uint8_t* buf, size_t n);
+#ifndef LCD_SPI_SPEED
+ #define LCD_SPI_SPEED SPI_QUARTER_SPEED
+#endif
-#include "../../shared/Marduino.h"
+#include "../../shared/HAL_SPI.h"
#include "../fastio.h"
void u8g_SetPIOutput_DUE_hw_spi(u8g_t *u8g, uint8_t pin_index) {
@@ -100,11 +99,7 @@ uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
spiBegin();
- #ifndef SPI_SPEED
- #define SPI_SPEED SPI_FULL_SPEED // use same SPI speed as SD card
- #endif
- spiInit(2);
-
+ spiInit(LCD_SPI_SPEED);
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp
index 47060d6a5..d01cd4dd6 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp
@@ -59,6 +59,7 @@
#if ENABLED(U8GLIB_ST7920)
+#include "../../../inc/MarlinConfig.h"
#include "../../shared/Delay.h"
#include
@@ -145,7 +146,7 @@ uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
}
#if ENABLED(LIGHTWEIGHT_UI)
- #include "../../../lcd/ultralcd.h"
+ #include "../../../lcd/marlinui.h"
#include "../../shared/HAL_ST7920.h"
#define ST7920_CS_PIN LCD_PINS_RS
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
index ea7204fa3..890546af5 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
@@ -59,9 +59,6 @@
#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920)
-#undef SPI_SPEED
-#define SPI_SPEED 2 // About 2 MHz
-
#include "u8g_com_HAL_DUE_sw_spi_shared.h"
#include "../../shared/Marduino.h"
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp
index 615a386c3..4fb7a6e2c 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp
@@ -59,6 +59,7 @@
#if HAS_MARLINUI_U8GLIB
+#include "../../../inc/MarlinConfig.h"
#include "../../shared/Delay.h"
#include
diff --git a/Marlin/src/HAL/DUE/eeprom_flash.cpp b/Marlin/src/HAL/DUE/eeprom_flash.cpp
index 6f38da096..b4cb9912b 100644
--- a/Marlin/src/HAL/DUE/eeprom_flash.cpp
+++ b/Marlin/src/HAL/DUE/eeprom_flash.cpp
@@ -135,11 +135,11 @@ static uint8_t buffer[256] = {0}, // The RAM buffer to accumulate writes
#define DEBUG_OUT ENABLED(EE_EMU_DEBUG)
#include "../../core/debug_out.h"
-static void ee_Dump(const int page, const void* data) {
+static void ee_Dump(const int page, const void *data) {
#ifdef EE_EMU_DEBUG
- const uint8_t* c = (const uint8_t*) data;
+ const uint8_t *c = (const uint8_t*) data;
char buffer[80];
sprintf_P(buffer, PSTR("Page: %d (0x%04x)\n"), page, page);
@@ -181,7 +181,7 @@ static void ee_Dump(const int page, const void* data) {
* @param data (pointer to the data buffer)
*/
__attribute__ ((long_call, section (".ramfunc")))
-static bool ee_PageWrite(uint16_t page, const void* data) {
+static bool ee_PageWrite(uint16_t page, const void *data) {
uint16_t i;
uint32_t addrflash = uint32_t(getFlashStorage(page));
@@ -293,8 +293,8 @@ static bool ee_PageWrite(uint16_t page, const void* data) {
ee_Dump(-page, data);
// Calculate count of changed bits
- uint32_t* p1 = (uint32_t*)addrflash;
- uint32_t* p2 = (uint32_t*)data;
+ uint32_t *p1 = (uint32_t*)addrflash;
+ uint32_t *p2 = (uint32_t*)data;
int count = 0;
for (i =0; i> 2; i++) {
if (p1[i] != p2[i]) {
@@ -470,7 +470,7 @@ static uint8_t ee_Read(uint32_t address, bool excludeRAMBuffer=false) {
for (int page = curPage - 1; page >= 0; --page) {
// Get a pointer to the flash page
- uint8_t* pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
+ uint8_t *pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
uint16_t i = 0;
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
@@ -550,7 +550,7 @@ static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer=false) {
for (int page = curPage - 1; page >= 0; --page) {
// Get a pointer to the flash page
- uint8_t* pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
+ uint8_t *pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
uint16_t i = 0;
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
@@ -589,7 +589,7 @@ static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer=false) {
}
static bool ee_IsPageClean(int page) {
- uint32_t* pflash = (uint32_t*) getFlashStorage(page);
+ uint32_t *pflash = (uint32_t*) getFlashStorage(page);
for (uint16_t i = 0; i < (PageSize >> 2); ++i)
if (*pflash++ != 0xFFFFFFFF) return false;
return true;
@@ -599,7 +599,7 @@ static bool ee_Flush(uint32_t overrideAddress = 0xFFFFFFFF, uint8_t overrideData
// Check if RAM buffer has something to be written
bool isEmpty = true;
- uint32_t* p = (uint32_t*) &buffer[0];
+ uint32_t *p = (uint32_t*) &buffer[0];
for (uint16_t j = 0; j < (PageSize >> 2); j++) {
if (*p++ != 0xFFFFFFFF) {
isEmpty = false;
@@ -976,14 +976,13 @@ bool PersistentStore::access_start() { ee_Init(); return true; }
bool PersistentStore::access_finish() { ee_Flush(); return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
- if (v != ee_Read(uint32_t(p))) {
+ if (v != ee_Read(uint32_t(p))) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
ee_Write(uint32_t(p), v);
- delay(2);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (ee_Read(uint32_t(p)) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -996,7 +995,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
uint8_t c = ee_Read(uint32_t(pos));
if (writing) *value = c;
diff --git a/Marlin/src/HAL/DUE/eeprom_wired.cpp b/Marlin/src/HAL/DUE/eeprom_wired.cpp
index 4599d6a7c..557a2f2cf 100644
--- a/Marlin/src/HAL/DUE/eeprom_wired.cpp
+++ b/Marlin/src/HAL/DUE/eeprom_wired.cpp
@@ -42,14 +42,13 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
- if (v != eeprom_read_byte(p)) {
+ if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
- delay(2);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -62,7 +61,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c;
diff --git a/Marlin/src/HAL/DUE/fastio.h b/Marlin/src/HAL/DUE/fastio.h
index 286319302..f375cb6b2 100644
--- a/Marlin/src/HAL/DUE/fastio.h
+++ b/Marlin/src/HAL/DUE/fastio.h
@@ -50,7 +50,7 @@
#define PWM_PIN(P) WITHIN(P, 2, 13)
#ifndef MASK
- #define MASK(PIN) (1 << PIN)
+ #define MASK(PIN) _BV(PIN)
#endif
/**
@@ -163,6 +163,9 @@
#define SET_INPUT(IO) _SET_INPUT(IO)
// Set pin as input with pullup (wrapper)
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0)
+// Set pin as input with pulldown (substitution)
+#define SET_INPUT_PULLDOWN SET_INPUT
+
// Set pin as output (wrapper) - reads the pin and sets the output to that value
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
// Set pin as PWM
@@ -477,7 +480,7 @@
#define DIO91_PIN 15
#define DIO91_WPORT PIOB
-#if ARDUINO_SAM_ARCHIM
+#ifdef ARDUINO_SAM_ARCHIM
#define DIO92_PIN 11
#define DIO92_WPORT PIOC
diff --git a/Marlin/src/HAL/DUE/inc/SanityCheck.h b/Marlin/src/HAL/DUE/inc/SanityCheck.h
index 688069650..87b09cf29 100644
--- a/Marlin/src/HAL/DUE/inc/SanityCheck.h
+++ b/Marlin/src/HAL/DUE/inc/SanityCheck.h
@@ -40,7 +40,7 @@
* Usually the hardware SPI pins are only available to the LCD. This makes the DUE hard SPI used at the same time
* as the TMC2130 soft SPI the most common setup.
*/
-#define _IS_HW_SPI(P) (defined(TMC_SW_##P) && (TMC_SW_##P == MOSI_PIN || TMC_SW_##P == MISO_PIN || TMC_SW_##P == SCK_PIN))
+#define _IS_HW_SPI(P) (defined(TMC_SW_##P) && (TMC_SW_##P == SD_MOSI_PIN || TMC_SW_##P == SD_MISO_PIN || TMC_SW_##P == SD_SCK_PIN))
#if ENABLED(SDSUPPORT) && HAS_DRIVER(TMC2130)
#if ENABLED(TMC_USE_SW_SPI)
@@ -57,5 +57,5 @@
#endif
#if HAS_TMC_SW_SERIAL
- #error "TMC220x Software Serial is not supported on this platform."
+ #error "TMC220x Software Serial is not supported on the DUE platform."
#endif
diff --git a/Marlin/src/HAL/DUE/spi_pins.h b/Marlin/src/HAL/DUE/spi_pins.h
index e28eaf827..cec22c2c3 100644
--- a/Marlin/src/HAL/DUE/spi_pins.h
+++ b/Marlin/src/HAL/DUE/spi_pins.h
@@ -43,22 +43,22 @@
#define SPI_PIN 87
#define SPI_CHAN 1
#endif
- #define SCK_PIN 76
- #define MISO_PIN 74
- #define MOSI_PIN 75
+ #define SD_SCK_PIN 76
+ #define SD_MISO_PIN 74
+ #define SD_MOSI_PIN 75
#else
// defaults
#define DUE_SOFTWARE_SPI
- #ifndef SCK_PIN
- #define SCK_PIN 52
+ #ifndef SD_SCK_PIN
+ #define SD_SCK_PIN 52
#endif
- #ifndef MISO_PIN
- #define MISO_PIN 50
+ #ifndef SD_MISO_PIN
+ #define SD_MISO_PIN 50
#endif
- #ifndef MOSI_PIN
- #define MOSI_PIN 51
+ #ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN 51
#endif
#endif
/* A.28, A.29, B.21, C.26, C.29 */
-#define SS_PIN SDSS
+#define SD_SS_PIN SDSS
diff --git a/Marlin/src/HAL/DUE/timers.cpp b/Marlin/src/HAL/DUE/timers.cpp
index 9b937d1a7..65073c510 100644
--- a/Marlin/src/HAL/DUE/timers.cpp
+++ b/Marlin/src/HAL/DUE/timers.cpp
@@ -121,7 +121,7 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num) {
// missing from CMSIS: Check if interrupt is enabled or not
static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
- return (NVIC->ISER[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) != 0;
+ return TEST(NVIC->ISER[uint32_t(IRQn) >> 5], uint32_t(IRQn) & 0x1F);
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
diff --git a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp
index ea2936359..3dcbbaecd 100644
--- a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp
+++ b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp
@@ -32,7 +32,7 @@ Ctrl_status sd_mmc_spi_test_unit_ready() {
Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector) {
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
return CTRL_NO_PRESENT;
- *nb_sector = card.getSd2Card().cardSize() - 1;
+ *nb_sector = card.diskIODriver()->cardSize() - 1;
return CTRL_GOOD;
}
@@ -68,30 +68,30 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
{
char buffer[80];
sprintf_P(buffer, PSTR("SDRD: %d @ 0x%08x\n"), nb_sector, addr);
- PORT_REDIRECT(0);
+ PORT_REDIRECT(SERIAL_PORTMASK(0));
SERIAL_ECHO(buffer);
}
#endif
// Start reading
- if (!card.getSd2Card().readStart(addr))
+ if (!card.diskIODriver()->readStart(addr))
return CTRL_FAIL;
// For each specified sector
while (nb_sector--) {
// Read a sector
- card.getSd2Card().readData(sector_buf);
+ card.diskIODriver()->readData(sector_buf);
// RAM -> USB
- if (!udi_msc_trans_block(true, sector_buf, SD_MMC_BLOCK_SIZE, NULL)) {
- card.getSd2Card().readStop();
+ if (!udi_msc_trans_block(true, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) {
+ card.diskIODriver()->readStop();
return CTRL_FAIL;
}
}
// Stop reading
- card.getSd2Card().readStop();
+ card.diskIODriver()->readStop();
// Done
return CTRL_GOOD;
@@ -108,29 +108,29 @@ Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
{
char buffer[80];
sprintf_P(buffer, PSTR("SDWR: %d @ 0x%08x\n"), nb_sector, addr);
- PORT_REDIRECT(0);
+ PORT_REDIRECT(SERIAL_PORTMASK(0));
SERIAL_ECHO(buffer);
}
#endif
- if (!card.getSd2Card().writeStart(addr, nb_sector))
+ if (!card.diskIODriver()->writeStart(addr, nb_sector))
return CTRL_FAIL;
// For each specified sector
while (nb_sector--) {
// USB -> RAM
- if (!udi_msc_trans_block(false, sector_buf, SD_MMC_BLOCK_SIZE, NULL)) {
- card.getSd2Card().writeStop();
+ if (!udi_msc_trans_block(false, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) {
+ card.diskIODriver()->writeStop();
return CTRL_FAIL;
}
// Write a sector
- card.getSd2Card().writeData(sector_buf);
+ card.diskIODriver()->writeData(sector_buf);
}
// Stop writing
- card.getSd2Card().writeStop();
+ card.diskIODriver()->writeStop();
// Done
return CTRL_GOOD;
diff --git a/Marlin/src/HAL/DUE/usb/udi_cdc.h b/Marlin/src/HAL/DUE/usb/udi_cdc.h
index 0ecf7bb00..b61845011 100644
--- a/Marlin/src/HAL/DUE/usb/udi_cdc.h
+++ b/Marlin/src/HAL/DUE/usb/udi_cdc.h
@@ -675,11 +675,11 @@ iram_size_t udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t s
* - \code // Waits and gets a value on CDC line
int udi_cdc_getc(void);
// Reads a RAM buffer on CDC line
- iram_size_t udi_cdc_read_buf(int* buf, iram_size_t size);
+ iram_size_t udi_cdc_read_buf(int *buf, iram_size_t size);
// Puts a byte on CDC line
int udi_cdc_putc(int value);
// Writes a RAM buffer on CDC line
- iram_size_t udi_cdc_write_buf(const int* buf, iram_size_t size); \endcode
+ iram_size_t udi_cdc_write_buf(const int *buf, iram_size_t size); \endcode
*
* \section udi_cdc_use_cases Advanced use cases
* For more advanced use of the UDI CDC module, see the following use cases:
diff --git a/Marlin/src/HAL/DUE/usb/usb_task.c b/Marlin/src/HAL/DUE/usb/usb_task.c
index 66bdb265d..54a808d7f 100644
--- a/Marlin/src/HAL/DUE/usb/usb_task.c
+++ b/Marlin/src/HAL/DUE/usb/usb_task.c
@@ -264,7 +264,7 @@ bool usb_task_extra_string(void) {
** Handle device requests that the ASF stack doesn't
*/
bool usb_task_other_requests(void) {
- uint8_t* ptr = 0;
+ uint8_t *ptr = 0;
uint16_t size = 0;
if (Udd_setup_type() == USB_REQ_TYPE_VENDOR) {
@@ -322,7 +322,7 @@ void usb_task_init(void) {
char *sptr;
// Patch in the filament diameter
- sprintf_P(diam, PSTR("%d"), (int)((DEFAULT_NOMINAL_FILAMENT_DIA) * 1000.0));
+ itoa((int)((DEFAULT_NOMINAL_FILAMENT_DIA) * 1000), diam, 10);
// And copy it to the proper place, expanding it to unicode
sptr = &diam[0];
diff --git a/Marlin/src/HAL/DUE/watchdog.cpp b/Marlin/src/HAL/DUE/watchdog.cpp
index 0f4697183..e144db829 100644
--- a/Marlin/src/HAL/DUE/watchdog.cpp
+++ b/Marlin/src/HAL/DUE/watchdog.cpp
@@ -36,7 +36,7 @@ void watchdogSetup() {
#if ENABLED(USE_WATCHDOG)
// 4 seconds timeout
- uint32_t timeout = 4000;
+ uint32_t timeout = TERN(WATCHDOG_DURATION_8S, 8000, 4000);
// Calculate timeout value in WDT counter ticks: This assumes
// the slow clock is running at 32.768 kHz watchdog
diff --git a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp
index d4b2f42c5..145662215 100644
--- a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp
+++ b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp
@@ -20,14 +20,10 @@
*
*/
-#include "FlushableHardwareSerial.h"
-
#ifdef ARDUINO_ARCH_ESP32
-FlushableHardwareSerial::FlushableHardwareSerial(int uart_nr)
- : HardwareSerial(uart_nr)
-{}
+#include "FlushableHardwareSerial.h"
-FlushableHardwareSerial flushableSerial(0);
+Serial1Class flushableSerial(false, 0);
-#endif // ARDUINO_ARCH_ESP32
+#endif
diff --git a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h
index b43caea13..012dda862 100644
--- a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h
+++ b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h
@@ -21,17 +21,14 @@
*/
#pragma once
-#ifdef ARDUINO_ARCH_ESP32
-
#include
+#include "../shared/Marduino.h"
+#include "../../core/serial_hook.h"
+
class FlushableHardwareSerial : public HardwareSerial {
public:
- FlushableHardwareSerial(int uart_nr);
-
- inline void flushTX() { /* No need to flush the hardware serial, but defined here for compatibility. */ }
+ FlushableHardwareSerial(int uart_nr) : HardwareSerial(uart_nr) {}
};
-extern FlushableHardwareSerial flushableSerial;
-
-#endif // ARDUINO_ARCH_ESP32
+extern Serial1Class flushableSerial;
diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp
index 1e00df517..7818dbdd8 100644
--- a/Marlin/src/HAL/ESP32/HAL.cpp
+++ b/Marlin/src/HAL/ESP32/HAL.cpp
@@ -40,6 +40,10 @@
#endif
#endif
+#if ENABLED(ESP3D_WIFISUPPORT)
+ DefaultSerial1 MSerial0(false, Serial2Socket);
+#endif
+
// ------------------------
// Externs
// ------------------------
@@ -86,8 +90,6 @@ volatile int numPWMUsed = 0,
#endif
-void HAL_init() { i2s_init(); }
-
void HAL_init_board() {
#if ENABLED(ESP3D_WIFISUPPORT)
@@ -122,6 +124,10 @@ void HAL_init_board() {
#endif
#endif
+ // Initialize the i2s peripheral only if the I2S stepper stream is enabled.
+ // The following initialization is performed after Serial1 and Serial2 are defined as
+ // their native pins might conflict with the i2s stream even when they are remapped.
+ TERN_(I2S_STEPPER_STREAM, i2s_init());
}
void HAL_idletask() {
@@ -135,6 +141,8 @@ void HAL_clear_reset_source() { }
uint8_t HAL_get_reset_source() { return rtc_get_reset_reason(1); }
+void HAL_reboot() { ESP.restart(); }
+
void _delay_ms(int delay_ms) { delay(delay_ms); }
// return free memory between end of heap (or end bss) and whatever is current
@@ -179,6 +187,7 @@ void HAL_adc_init() {
TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(FILAMENT_WIDTH_SENSOR, adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db));
// Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail.
diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h
index ebc16c952..0f9205203 100644
--- a/Marlin/src/HAL/ESP32/HAL.h
+++ b/Marlin/src/HAL/ESP32/HAL.h
@@ -51,13 +51,15 @@
extern portMUX_TYPE spinlock;
-#define MYSERIAL0 flushableSerial
+#define MYSERIAL1 flushableSerial
#if EITHER(WIFISUPPORT, ESP3D_WIFISUPPORT)
#if ENABLED(ESP3D_WIFISUPPORT)
- #define MYSERIAL1 Serial2Socket
+ typedef ForwardSerial1Class< decltype(Serial2Socket) > DefaultSerial1;
+ extern DefaultSerial1 MSerial0;
+ #define MYSERIAL2 MSerial0
#else
- #define MYSERIAL1 webSocketSerial
+ #define MYSERIAL2 webSocketSerial
#endif
#endif
@@ -67,10 +69,6 @@ extern portMUX_TYPE spinlock;
#define ENABLE_ISRS() if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock)
#define DISABLE_ISRS() portENTER_CRITICAL(&spinlock)
-// Fix bug in pgm_read_ptr
-#undef pgm_read_ptr
-#define pgm_read_ptr(addr) (*(addr))
-
// ------------------------
// Types
// ------------------------
@@ -90,20 +88,33 @@ extern uint16_t HAL_adc_result;
// Public functions
// ------------------------
+//
+// Tone
+//
+void toneInit();
+void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
+void noTone(const pin_t _pin);
+
// clear reset reason
void HAL_clear_reset_source();
// reset reason
uint8_t HAL_get_reset_source();
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+void HAL_reboot();
void _delay_ms(int delay);
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
int freeMemory();
-#pragma GCC diagnostic pop
+
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic pop
+#endif
void analogWrite(pin_t pin, int value);
@@ -128,7 +139,7 @@ void HAL_adc_start_conversion(const uint8_t adc_pin);
#define HAL_IDLETASK 1
#define BOARD_INIT() HAL_init_board();
void HAL_idletask();
-void HAL_init();
+inline void HAL_init() {}
void HAL_init_board();
//
diff --git a/Marlin/src/HAL/ESP32/HAL_SPI.cpp b/Marlin/src/HAL/ESP32/HAL_SPI.cpp
index 8e5875fc3..8743ac5be 100644
--- a/Marlin/src/HAL/ESP32/HAL_SPI.cpp
+++ b/Marlin/src/HAL/ESP32/HAL_SPI.cpp
@@ -53,11 +53,11 @@ static SPISettings spiConfig;
// ------------------------
void spiBegin() {
- #if !PIN_EXISTS(SS)
- #error "SS_PIN not defined!"
+ #if !PIN_EXISTS(SD_SS)
+ #error "SD_SS_PIN not defined!"
#endif
- OUT_WRITE(SS_PIN, HIGH);
+ OUT_WRITE(SD_SS_PIN, HIGH);
}
void spiInit(uint8_t spiRate) {
@@ -85,7 +85,7 @@ uint8_t spiRec() {
return returnByte;
}
-void spiRead(uint8_t* buf, uint16_t nbyte) {
+void spiRead(uint8_t *buf, uint16_t nbyte) {
SPI.beginTransaction(spiConfig);
SPI.transferBytes(0, buf, nbyte);
SPI.endTransaction();
@@ -97,7 +97,7 @@ void spiSend(uint8_t b) {
SPI.endTransaction();
}
-void spiSendBlock(uint8_t token, const uint8_t* buf) {
+void spiSendBlock(uint8_t token, const uint8_t *buf) {
SPI.beginTransaction(spiConfig);
SPI.transfer(token);
SPI.writeBytes(const_cast(buf), 512);
diff --git a/Marlin/src/HAL/ESP32/Servo.h b/Marlin/src/HAL/ESP32/Servo.h
index b0d929452..8542092d6 100644
--- a/Marlin/src/HAL/ESP32/Servo.h
+++ b/Marlin/src/HAL/ESP32/Servo.h
@@ -30,7 +30,7 @@ class Servo {
MAX_PULSE_WIDTH = 2400, // Longest pulse sent to a servo
TAU_MSEC = 20,
TAU_USEC = (TAU_MSEC * 1000),
- MAX_COMPARE = ((1 << 16) - 1), // 65535
+ MAX_COMPARE = _BV(16) - 1, // 65535
CHANNEL_MAX_NUM = 16;
public:
diff --git a/Marlin/src/HAL/STM32_F4_F7/watchdog.cpp b/Marlin/src/HAL/ESP32/Tone.cpp
similarity index 52%
rename from Marlin/src/HAL/STM32_F4_F7/watchdog.cpp
rename to Marlin/src/HAL/ESP32/Tone.cpp
index cb12ec7aa..376c0f32e 100644
--- a/Marlin/src/HAL/STM32_F4_F7/watchdog.cpp
+++ b/Marlin/src/HAL/ESP32/Tone.cpp
@@ -5,6 +5,8 @@
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
+ * Copypaste of SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -19,37 +21,39 @@
* along with this program. If not, see .
*
*/
-#if defined(STM32GENERIC) && (defined(STM32F4) || defined(STM32F7))
+
+/**
+ * Description: Tone function for ESP32
+ * Derived from https://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
+ */
+
+#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfig.h"
+#include "HAL.h"
-#if ENABLED(USE_WATCHDOG)
+static pin_t tone_pin;
+volatile static int32_t toggles;
- #include "watchdog.h"
+void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) {
+ tone_pin = _pin;
+ toggles = 2 * frequency * duration / 1000;
+ HAL_timer_start(TONE_TIMER_NUM, 2 * frequency);
+}
- IWDG_HandleTypeDef hiwdg;
+void noTone(const pin_t _pin) {
+ HAL_timer_disable_interrupt(TONE_TIMER_NUM);
+ WRITE(_pin, LOW);
+}
- void watchdog_init() {
- hiwdg.Instance = IWDG;
- hiwdg.Init.Prescaler = IWDG_PRESCALER_32; //32kHz LSI clock and 32x prescalar = 1024Hz IWDG clock
- hiwdg.Init.Reload = 4095; //4095 counts = 4 seconds at 1024Hz
- if (HAL_IWDG_Init(&hiwdg) != HAL_OK) {
- //Error_Handler();
- }
- else {
- #if PIN_EXISTS(LED) && DISABLED(PINS_DEBUGGING)
- TOGGLE(LED_PIN); // heartbeat indicator
- #endif
- }
+HAL_TONE_TIMER_ISR() {
+ HAL_timer_isr_prologue(TONE_TIMER_NUM);
+
+ if (toggles) {
+ toggles--;
+ TOGGLE(tone_pin);
}
+ else noTone(tone_pin); // turn off interrupt
+}
- void HAL_watchdog_refresh() {
- /* Refresh IWDG: reload counter */
- if (HAL_IWDG_Refresh(&hiwdg) != HAL_OK) {
- /* Refresh Error */
- //Error_Handler();
- }
- }
-
-#endif // USE_WATCHDOG
-#endif // STM32GENERIC && (STM32F4 || STM32F7)
+#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/ESP32/WebSocketSerial.cpp b/Marlin/src/HAL/ESP32/WebSocketSerial.cpp
index ca7f47a1f..96769f261 100644
--- a/Marlin/src/HAL/ESP32/WebSocketSerial.cpp
+++ b/Marlin/src/HAL/ESP32/WebSocketSerial.cpp
@@ -29,7 +29,7 @@
#include "wifi.h"
#include
-WebSocketSerial webSocketSerial;
+MSerialT webSocketSerial(false);
AsyncWebSocket ws("/ws"); // TODO Move inside the class.
// RingBuffer impl
@@ -137,16 +137,12 @@ size_t WebSocketSerial::write(const uint8_t c) {
return ret;
}
-size_t WebSocketSerial::write(const uint8_t* buffer, size_t size) {
+size_t WebSocketSerial::write(const uint8_t *buffer, size_t size) {
size_t written = 0;
for (size_t i = 0; i < size; i++)
written += write(buffer[i]);
return written;
}
-void WebSocketSerial::flushTX() {
- // No need to do anything as there's no benefit to sending partial lines over the websocket connection.
-}
-
#endif // WIFISUPPORT
#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/ESP32/WebSocketSerial.h b/Marlin/src/HAL/ESP32/WebSocketSerial.h
index 7a25c6dc5..574f7b10f 100644
--- a/Marlin/src/HAL/ESP32/WebSocketSerial.h
+++ b/Marlin/src/HAL/ESP32/WebSocketSerial.h
@@ -22,6 +22,7 @@
#pragma once
#include "../../inc/MarlinConfig.h"
+#include "../../core/serial_hook.h"
#include
@@ -53,7 +54,7 @@ public:
ring_buffer_pos_t read(uint8_t *buffer);
void flush();
ring_buffer_pos_t write(const uint8_t c);
- ring_buffer_pos_t write(const uint8_t* buffer, ring_buffer_pos_t size);
+ ring_buffer_pos_t write(const uint8_t *buffer, ring_buffer_pos_t size);
};
class WebSocketSerial: public Stream {
@@ -68,11 +69,8 @@ public:
int peek();
int read();
void flush();
- void flushTX();
size_t write(const uint8_t c);
- size_t write(const uint8_t* buffer, size_t size);
-
- operator bool() { return true; }
+ size_t write(const uint8_t *buffer, size_t size);
#if ENABLED(SERIAL_STATS_DROPPED_RX)
FORCE_INLINE uint32_t dropped() { return 0; }
@@ -83,4 +81,5 @@ public:
#endif
};
-extern WebSocketSerial webSocketSerial;
+typedef Serial1Class MSerialT;
+extern MSerialT webSocketSerial;
diff --git a/Marlin/src/HAL/ESP32/eeprom.cpp b/Marlin/src/HAL/ESP32/eeprom.cpp
index 1bf687c6f..cb5f88128 100644
--- a/Marlin/src/HAL/ESP32/eeprom.cpp
+++ b/Marlin/src/HAL/ESP32/eeprom.cpp
@@ -44,7 +44,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
for (size_t i = 0; i < size; i++) {
uint8_t c = EEPROM.read(pos++);
if (writing) value[i] = c;
diff --git a/Marlin/src/HAL/ESP32/fastio.h b/Marlin/src/HAL/ESP32/fastio.h
index 2ded3a5f6..8db89dca1 100644
--- a/Marlin/src/HAL/ESP32/fastio.h
+++ b/Marlin/src/HAL/ESP32/fastio.h
@@ -52,6 +52,9 @@
// Set pin as input with pullup wrapper
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0)
+// Set pin as input with pulldown (substitution)
+#define SET_INPUT_PULLDOWN SET_INPUT
+
// Set pin as output wrapper
#define SET_OUTPUT(IO) do{ _SET_OUTPUT(IO); }while(0)
diff --git a/Marlin/src/HAL/ESP32/i2s.cpp b/Marlin/src/HAL/ESP32/i2s.cpp
index 99b2f755e..c28c00879 100644
--- a/Marlin/src/HAL/ESP32/i2s.cpp
+++ b/Marlin/src/HAL/ESP32/i2s.cpp
@@ -139,7 +139,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) {
I2S0.int_clr.val = I2S0.int_st.val; //clear pending interrupt
}
-void stepperTask(void* parameter) {
+void stepperTask(void *parameter) {
uint32_t remaining = 0;
while (1) {
@@ -184,7 +184,7 @@ int i2s_init() {
// Allocate the array of pointers to the buffers
dma.buffers = (uint32_t **)malloc(sizeof(uint32_t*) * DMA_BUF_COUNT);
- if (dma.buffers == nullptr) return -1;
+ if (!dma.buffers) return -1;
// Allocate each buffer that can be used by the DMA controller
for (int buf_idx = 0; buf_idx < DMA_BUF_COUNT; buf_idx++) {
@@ -194,7 +194,7 @@ int i2s_init() {
// Allocate the array of DMA descriptors
dma.desc = (lldesc_t**) malloc(sizeof(lldesc_t*) * DMA_BUF_COUNT);
- if (dma.desc == nullptr) return -1;
+ if (!dma.desc) return -1;
// Allocate each DMA descriptor that will be used by the DMA controller
for (int buf_idx = 0; buf_idx < DMA_BUF_COUNT; buf_idx++) {
diff --git a/Marlin/src/HAL/ESP32/inc/SanityCheck.h b/Marlin/src/HAL/ESP32/inc/SanityCheck.h
index f57a6c591..8bbc68d87 100644
--- a/Marlin/src/HAL/ESP32/inc/SanityCheck.h
+++ b/Marlin/src/HAL/ESP32/inc/SanityCheck.h
@@ -30,9 +30,13 @@
#endif
#if HAS_TMC_SW_SERIAL
- #error "TMC220x Software Serial is not supported on this platform."
+ #error "TMC220x Software Serial is not supported on ESP32."
#endif
#if BOTH(WIFISUPPORT, ESP3D_WIFISUPPORT)
#error "Only enable one WiFi option, either WIFISUPPORT or ESP3D_WIFISUPPORT."
#endif
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+ #error "POSTMORTEM_DEBUGGING is not yet supported on ESP32."
+#endif
diff --git a/Marlin/src/HAL/ESP32/spi_pins.h b/Marlin/src/HAL/ESP32/spi_pins.h
index 15f8f2ab6..cfe71eee4 100644
--- a/Marlin/src/HAL/ESP32/spi_pins.h
+++ b/Marlin/src/HAL/ESP32/spi_pins.h
@@ -18,7 +18,7 @@
*/
#pragma once
-#define SS_PIN SDSS
-#define SCK_PIN 18
-#define MISO_PIN 19
-#define MOSI_PIN 23
+#define SD_SS_PIN SDSS
+#define SD_SCK_PIN 18
+#define SD_MISO_PIN 19
+#define SD_MOSI_PIN 23
diff --git a/Marlin/src/HAL/ESP32/timers.cpp b/Marlin/src/HAL/ESP32/timers.cpp
index 3300aea8a..57662a665 100644
--- a/Marlin/src/HAL/ESP32/timers.cpp
+++ b/Marlin/src/HAL/ESP32/timers.cpp
@@ -45,7 +45,7 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
{ TIMER_GROUP_0, TIMER_0, STEPPER_TIMER_PRESCALE, stepTC_Handler }, // 0 - Stepper
{ TIMER_GROUP_0, TIMER_1, TEMP_TIMER_PRESCALE, tempTC_Handler }, // 1 - Temperature
{ TIMER_GROUP_1, TIMER_0, PWM_TIMER_PRESCALE, pwmTC_Handler }, // 2 - PWM
- { TIMER_GROUP_1, TIMER_1, 1, nullptr }, // 3
+ { TIMER_GROUP_1, TIMER_1, TONE_TIMER_PRESCALE, toneTC_Handler }, // 3 - Tone
};
// ------------------------
diff --git a/Marlin/src/HAL/ESP32/timers.h b/Marlin/src/HAL/ESP32/timers.h
index d722670f3..a47697113 100644
--- a/Marlin/src/HAL/ESP32/timers.h
+++ b/Marlin/src/HAL/ESP32/timers.h
@@ -24,15 +24,9 @@
#include
#include
-// Includes needed to get I2S_STEPPER_STREAM. Note that pins.h
-// is included in case this header is being included early.
-#include "../../inc/MarlinConfig.h"
-#include "../../pins/pins.h"
-
// ------------------------
// Defines
// ------------------------
-//
#define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint64_t hal_timer_t;
@@ -50,6 +44,9 @@ typedef uint64_t hal_timer_t;
#ifndef PWM_TIMER_NUM
#define PWM_TIMER_NUM 2 // index of timer to use for PWM outputs
#endif
+#ifndef TONE_TIMER_NUM
+ #define TONE_TIMER_NUM 3 // index of timer for beeper tones
+#endif
#define HAL_TIMER_RATE APB_CLK_FREQ // frequency of timer peripherals
@@ -65,6 +62,8 @@ typedef uint64_t hal_timer_t;
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
+#define TONE_TIMER_PRESCALE 1000 // Arbitrary value, no idea what i'm doing here
+
#define TEMP_TIMER_PRESCALE 1000 // prescaler for setting Temp timer, 72Khz
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
@@ -96,10 +95,16 @@ typedef uint64_t hal_timer_t;
#ifndef HAL_PWM_TIMER_ISR
#define HAL_PWM_TIMER_ISR() extern "C" void pwmTC_Handler()
#endif
+#ifndef HAL_TONE_TIMER_ISR
+ #define HAL_TONE_TIMER_ISR() extern "C" void toneTC_Handler()
+#endif
-extern "C" void tempTC_Handler();
-extern "C" void stepTC_Handler();
-extern "C" void pwmTC_Handler();
+extern "C" {
+ void tempTC_Handler();
+ void stepTC_Handler();
+ void pwmTC_Handler();
+ void toneTC_Handler();
+}
// ------------------------
// Types
diff --git a/Marlin/src/HAL/ESP32/watchdog.cpp b/Marlin/src/HAL/ESP32/watchdog.cpp
index f6fcfa318..5ec03c460 100644
--- a/Marlin/src/HAL/ESP32/watchdog.cpp
+++ b/Marlin/src/HAL/ESP32/watchdog.cpp
@@ -25,6 +25,8 @@
#if ENABLED(USE_WATCHDOG)
+#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
+
#include "watchdog.h"
void watchdogSetup() {
diff --git a/Marlin/src/HAL/HAL.h b/Marlin/src/HAL/HAL.h
index 5eca2f7ea..0cd836af2 100644
--- a/Marlin/src/HAL/HAL.h
+++ b/Marlin/src/HAL/HAL.h
@@ -23,14 +23,12 @@
#include "platforms.h"
-#include HAL_PATH(.,HAL.h)
-
-#ifdef SERIAL_PORT_2
- #define NUM_SERIAL 2
-#else
- #define NUM_SERIAL 1
+#ifndef GCC_VERSION
+ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
+#include HAL_PATH(.,HAL.h)
+
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
#ifndef I2C_ADDRESS
diff --git a/Marlin/src/HAL/LINUX/HAL.cpp b/Marlin/src/HAL/LINUX/HAL.cpp
index d7d7c2d2b..0b679170e 100644
--- a/Marlin/src/HAL/LINUX/HAL.cpp
+++ b/Marlin/src/HAL/LINUX/HAL.cpp
@@ -24,21 +24,16 @@
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
-HalSerial usb_serial;
+MSerialT usb_serial(TERN0(EMERGENCY_PARSER, true));
// U8glib required functions
-extern "C" void u8g_xMicroDelay(uint16_t val) {
- DELAY_US(val);
-}
-extern "C" void u8g_MicroDelay() {
- u8g_xMicroDelay(1);
-}
-extern "C" void u8g_10MicroDelay() {
- u8g_xMicroDelay(10);
-}
-extern "C" void u8g_Delay(uint16_t val) {
- delay(val);
+extern "C" {
+ void u8g_xMicroDelay(uint16_t val) { DELAY_US(val); }
+ void u8g_MicroDelay() { u8g_xMicroDelay(1); }
+ void u8g_10MicroDelay() { u8g_xMicroDelay(10); }
+ void u8g_Delay(uint16_t val) { delay(val); }
}
+
//************************//
// return free heap space
@@ -78,4 +73,6 @@ void HAL_pwm_init() {
}
+void HAL_reboot() { /* Reset the application state and GPIO */ }
+
#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/HAL.h b/Marlin/src/HAL/LINUX/HAL.h
index 2e545e03d..36906bffc 100644
--- a/Marlin/src/HAL/LINUX/HAL.h
+++ b/Marlin/src/HAL/LINUX/HAL.h
@@ -23,7 +23,7 @@
#define CPU_32_BIT
-#define F_CPU 100000000
+#define F_CPU 100000000UL
#define SystemCoreClock F_CPU
#include
#include
@@ -60,8 +60,8 @@ uint8_t _getc();
#define SHARED_SERVOS HAS_SERVOS
-extern HalSerial usb_serial;
-#define MYSERIAL0 usb_serial
+extern MSerialT usb_serial;
+#define MYSERIAL1 usb_serial
#define ST7920_DELAY_1 DELAY_NS(600)
#define ST7920_DELAY_2 DELAY_NS(750)
@@ -79,10 +79,16 @@ extern HalSerial usb_serial;
inline void HAL_init() {}
// Utility functions
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
int freeMemory();
-#pragma GCC diagnostic pop
+
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic pop
+#endif
// ADC
#define HAL_ADC_VREF 5.0
@@ -101,14 +107,9 @@ uint16_t HAL_adc_get_result();
inline void HAL_clear_reset_source(void) {}
inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; }
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+void HAL_reboot(); // Reset the application state and GPIO
/* ---------------- Delay in cycles */
FORCE_INLINE static void DELAY_CYCLES(uint64_t x) {
Clock::delayCycles(x);
}
-
-// Add strcmp_P if missing
-#ifndef strcmp_P
- #define strcmp_P(a, b) strcmp((a), (b))
-#endif
diff --git a/Marlin/src/HAL/LINUX/eeprom.cpp b/Marlin/src/HAL/LINUX/eeprom.cpp
index 967ca851a..532f323c6 100644
--- a/Marlin/src/HAL/LINUX/eeprom.cpp
+++ b/Marlin/src/HAL/LINUX/eeprom.cpp
@@ -40,7 +40,7 @@ size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
bool PersistentStore::access_start() {
const char eeprom_erase_value = 0xFF;
FILE * eeprom_file = fopen(filename, "rb");
- if (eeprom_file == nullptr) return false;
+ if (!eeprom_file) return false;
fseek(eeprom_file, 0L, SEEK_END);
std::size_t file_size = ftell(eeprom_file);
@@ -59,7 +59,7 @@ bool PersistentStore::access_start() {
bool PersistentStore::access_finish() {
FILE * eeprom_file = fopen(filename, "wb");
- if (eeprom_file == nullptr) return false;
+ if (!eeprom_file) return false;
fwrite(buffer, sizeof(uint8_t), sizeof(buffer), eeprom_file);
fclose(eeprom_file);
return true;
@@ -78,7 +78,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return (bytes_written != size); // return true for any error
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
std::size_t bytes_read = 0;
if (writing) {
for (std::size_t i = 0; i < size; i++) {
diff --git a/Marlin/src/HAL/LINUX/hardware/Gpio.h b/Marlin/src/HAL/LINUX/hardware/Gpio.h
index 9255ec1df..2d9b1f29e 100644
--- a/Marlin/src/HAL/LINUX/hardware/Gpio.h
+++ b/Marlin/src/HAL/LINUX/hardware/Gpio.h
@@ -86,10 +86,10 @@ public:
GpioEvent::Type evt_type = value > 1 ? GpioEvent::SET_VALUE : value > pin_map[pin].value ? GpioEvent::RISE : value < pin_map[pin].value ? GpioEvent::FALL : GpioEvent::NOP;
pin_map[pin].value = value;
GpioEvent evt(Clock::nanos(), pin, evt_type);
- if (pin_map[pin].cb != nullptr) {
+ if (pin_map[pin].cb) {
pin_map[pin].cb->interrupt(evt);
}
- if (Gpio::logger != nullptr) Gpio::logger->log(evt);
+ if (Gpio::logger) Gpio::logger->log(evt);
}
static uint16_t get(pin_type pin) {
@@ -105,8 +105,8 @@ public:
if (!valid_pin(pin)) return;
pin_map[pin].mode = value;
GpioEvent evt(Clock::nanos(), pin, GpioEvent::Type::SETM);
- if (pin_map[pin].cb != nullptr) pin_map[pin].cb->interrupt(evt);
- if (Gpio::logger != nullptr) Gpio::logger->log(evt);
+ if (pin_map[pin].cb) pin_map[pin].cb->interrupt(evt);
+ if (Gpio::logger) Gpio::logger->log(evt);
}
static uint8_t getMode(pin_type pin) {
@@ -118,8 +118,8 @@ public:
if (!valid_pin(pin)) return;
pin_map[pin].dir = value;
GpioEvent evt(Clock::nanos(), pin, GpioEvent::Type::SETD);
- if (pin_map[pin].cb != nullptr) pin_map[pin].cb->interrupt(evt);
- if (Gpio::logger != nullptr) Gpio::logger->log(evt);
+ if (pin_map[pin].cb) pin_map[pin].cb->interrupt(evt);
+ if (Gpio::logger) Gpio::logger->log(evt);
}
static uint8_t getDir(pin_type pin) {
diff --git a/Marlin/src/HAL/LINUX/inc/SanityCheck.h b/Marlin/src/HAL/LINUX/inc/SanityCheck.h
index 84167c97a..45bb2662a 100644
--- a/Marlin/src/HAL/LINUX/inc/SanityCheck.h
+++ b/Marlin/src/HAL/LINUX/inc/SanityCheck.h
@@ -35,5 +35,9 @@
#endif
#if HAS_TMC_SW_SERIAL
- #error "TMC220x Software Serial is not supported on this platform."
+ #error "TMC220x Software Serial is not supported on LINUX."
+#endif
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+ #error "POSTMORTEM_DEBUGGING is not yet supported on LINUX."
#endif
diff --git a/Marlin/src/HAL/LINUX/include/Arduino.h b/Marlin/src/HAL/LINUX/include/Arduino.h
index e28b474ed..d4086e259 100644
--- a/Marlin/src/HAL/LINUX/include/Arduino.h
+++ b/Marlin/src/HAL/LINUX/include/Arduino.h
@@ -67,34 +67,14 @@ void cli(); // Disable
void sei(); // Enable
void attachInterrupt(uint32_t pin, void (*callback)(), uint32_t mode);
void detachInterrupt(uint32_t pin);
-extern "C" void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
-extern "C" void GpioDisableInt(uint32_t port, uint32_t pin);
-// Program Memory
-#define pgm_read_ptr(addr) (*((void**)(addr)))
-#define pgm_read_byte_near(addr) (*((uint8_t*)(addr)))
-#define pgm_read_float_near(addr) (*((float*)(addr)))
-#define pgm_read_word_near(addr) (*((uint16_t*)(addr)))
-#define pgm_read_dword_near(addr) (*((uint32_t*)(addr)))
-#define pgm_read_byte(addr) pgm_read_byte_near(addr)
-#define pgm_read_float(addr) pgm_read_float_near(addr)
-#define pgm_read_word(addr) pgm_read_word_near(addr)
-#define pgm_read_dword(addr) pgm_read_dword_near(addr)
-
-using std::memcpy;
-#define memcpy_P memcpy
-#define sprintf_P sprintf
-#define strstr_P strstr
-#define strncpy_P strncpy
-#define vsnprintf_P vsnprintf
-#define strcpy_P strcpy
-#define snprintf_P snprintf
-#define strlen_P strlen
+extern "C" {
+ void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
+ void GpioDisableInt(uint32_t port, uint32_t pin);
+}
// Time functions
-extern "C" {
- void delay(const int milis);
-}
+extern "C" void delay(const int milis);
void _delay_ms(const int delay);
void delayMicroseconds(unsigned long);
uint32_t millis();
diff --git a/Marlin/src/HAL/LINUX/include/serial.h b/Marlin/src/HAL/LINUX/include/serial.h
index e91624938..ebae066c3 100644
--- a/Marlin/src/HAL/LINUX/include/serial.h
+++ b/Marlin/src/HAL/LINUX/include/serial.h
@@ -25,6 +25,7 @@
#if ENABLED(EMERGENCY_PARSER)
#include "../../../feature/e_parser.h"
#endif
+#include "../../../core/serial_hook.h"
#include
#include
@@ -73,19 +74,11 @@ private:
volatile uint32_t index_read;
};
-class HalSerial {
-public:
-
- #if ENABLED(EMERGENCY_PARSER)
- EmergencyParser::State emergency_state;
- static inline bool emergency_parser_enabled() { return true; }
- #endif
-
+struct HalSerial {
HalSerial() { host_connected = true; }
void begin(int32_t) {}
-
- void end() {}
+ void end() {}
int peek() {
uint8_t value;
@@ -100,7 +93,7 @@ public:
return transmit_buffer.write(c);
}
- operator bool() { return host_connected; }
+ bool connected() { return host_connected; }
uint16_t available() {
return (uint16_t)receive_buffer.available();
@@ -117,92 +110,9 @@ public:
while (transmit_buffer.available()) { /* nada */ }
}
- void printf(const char *format, ...) {
- static char buffer[256];
- va_list vArgs;
- va_start(vArgs, format);
- int length = vsnprintf((char *) buffer, 256, (char const *) format, vArgs);
- va_end(vArgs);
- if (length > 0 && length < 256) {
- if (host_connected) {
- for (int i = 0; i < length;) {
- if (transmit_buffer.write(buffer[i])) {
- ++i;
- }
- }
- }
- }
- }
-
- #define DEC 10
- #define HEX 16
- #define OCT 8
- #define BIN 2
-
- void print_bin(uint32_t value, uint8_t num_digits) {
- uint32_t mask = 1 << (num_digits -1);
- for (uint8_t i = 0; i < num_digits; i++) {
- if (!(i % 4) && i) write(' ');
- if (!(i % 16) && i) write(' ');
- if (value & mask) write('1');
- else write('0');
- value <<= 1;
- }
- }
-
- void print(const char value[]) { printf("%s" , value); }
- void print(char value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 8);
- else if (nbase == OCT) printf("%3o", value);
- else if (nbase == HEX) printf("%2X", value);
- else if (nbase == DEC ) printf("%d", value);
- else printf("%c" , value);
- }
- void print(unsigned char value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 8);
- else if (nbase == OCT) printf("%3o", value);
- else if (nbase == HEX) printf("%2X", value);
- else printf("%u" , value);
- }
- void print(int value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 16);
- else if (nbase == OCT) printf("%6o", value);
- else if (nbase == HEX) printf("%4X", value);
- else printf("%d", value);
- }
- void print(unsigned int value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 16);
- else if (nbase == OCT) printf("%6o", value);
- else if (nbase == HEX) printf("%4X", value);
- else printf("%u" , value);
- }
- void print(long value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 32);
- else if (nbase == OCT) printf("%11o", value);
- else if (nbase == HEX) printf("%8X", value);
- else printf("%ld" , value);
- }
- void print(unsigned long value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 32);
- else if (nbase == OCT) printf("%11o", value);
- else if (nbase == HEX) printf("%8X", value);
- else printf("%lu" , value);
- }
- void print(float value, int round = 6) { printf("%f" , value); }
- void print(double value, int round = 6) { printf("%f" , value); }
-
- void println(const char value[]) { printf("%s\n" , value); }
- void println(char value, int nbase = 0) { print(value, nbase); println(); }
- void println(unsigned char value, int nbase = 0) { print(value, nbase); println(); }
- void println(int value, int nbase = 0) { print(value, nbase); println(); }
- void println(unsigned int value, int nbase = 0) { print(value, nbase); println(); }
- void println(long value, int nbase = 0) { print(value, nbase); println(); }
- void println(unsigned long value, int nbase = 0) { print(value, nbase); println(); }
- void println(float value, int round = 6) { printf("%f\n" , value); }
- void println(double value, int round = 6) { printf("%f\n" , value); }
- void println() { print('\n'); }
-
volatile RingBuffer receive_buffer;
volatile RingBuffer transmit_buffer;
volatile bool host_connected;
};
+
+typedef Serial1Class MSerialT;
diff --git a/Marlin/src/HAL/LINUX/main.cpp b/Marlin/src/HAL/LINUX/main.cpp
index 481f05903..31f6de98e 100644
--- a/Marlin/src/HAL/LINUX/main.cpp
+++ b/Marlin/src/HAL/LINUX/main.cpp
@@ -1,6 +1,5 @@
/**
* Marlin 3D Printer Firmware
- *
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* This program is free software: you can redistribute it and/or modify
@@ -19,22 +18,23 @@
*/
#ifdef __PLAT_LINUX__
-extern void setup();
-extern void loop();
-
-#include
-
-#include
-#include
+//#define GPIO_LOGGING // Full GPIO and Positional Logging
#include "../../inc/MarlinConfig.h"
-#include
-#include
#include "../shared/Delay.h"
#include "hardware/IOLoggerCSV.h"
#include "hardware/Heater.h"
#include "hardware/LinearAxis.h"
+#include
+#include
+#include
+#include
+#include
+
+extern void setup();
+extern void loop();
+
// simple stdout / stdin implementation for fake serial port
void write_serial_thread() {
for (;;) {
@@ -64,8 +64,6 @@ void simulation_loop() {
LinearAxis z_axis(Z_ENABLE_PIN, Z_DIR_PIN, Z_STEP_PIN, Z_MIN_PIN, Z_MAX_PIN);
LinearAxis extruder0(E0_ENABLE_PIN, E0_DIR_PIN, E0_STEP_PIN, P_NC, P_NC);
- //#define GPIO_LOGGING // Full GPIO and Positional Logging
-
#ifdef GPIO_LOGGING
IOLoggerCSV logger("all_gpio_log.csv");
Gpio::attachLogger(&logger);
@@ -88,7 +86,7 @@ void simulation_loop() {
#ifdef GPIO_LOGGING
if (x_axis.position != x || y_axis.position != y || z_axis.position != z) {
- uint64_t update = MAX3(x_axis.last_update, y_axis.last_update, z_axis.last_update);
+ uint64_t update = _MAX(x_axis.last_update, y_axis.last_update, z_axis.last_update);
position_log << update << ", " << x_axis.position << ", " << y_axis.position << ", " << z_axis.position << std::endl;
position_log.flush();
x = x_axis.position;
@@ -107,8 +105,8 @@ int main() {
std::thread write_serial (write_serial_thread);
std::thread read_serial (read_serial_thread);
- #ifdef MYSERIAL0
- MYSERIAL0.begin(BAUDRATE);
+ #ifdef MYSERIAL1
+ MYSERIAL1.begin(BAUDRATE);
SERIAL_ECHOLNPGM("x86_64 Initialized");
SERIAL_FLUSHTX();
#endif
diff --git a/Marlin/src/HAL/LINUX/pinsDebug.h b/Marlin/src/HAL/LINUX/pinsDebug.h
index a93ceddc6..8f8543ef5 100644
--- a/Marlin/src/HAL/LINUX/pinsDebug.h
+++ b/Marlin/src/HAL/LINUX/pinsDebug.h
@@ -26,15 +26,15 @@
*/
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
-#define pwm_details(pin) pin = pin // do nothing // print PWM details
-#define pwm_status(pin) false //Print a pin's PWM status. Return true if it's currently a PWM pin.
-#define IS_ANALOG(P) (DIGITAL_PIN_TO_ANALOG_PIN(P) >= 0 ? 1 : 0)
+#define pwm_details(pin) NOOP // (do nothing)
+#define pwm_status(pin) false // Print a pin's PWM status. Return true if it's currently a PWM pin.
+#define IS_ANALOG(P) (DIGITAL_PIN_TO_ANALOG_PIN(P) >= 0 ? 1 : 0)
#define digitalRead_mod(p) digitalRead(p)
#define PRINT_PORT(p)
-#define GET_ARRAY_PIN(p) pin_array[p].pin
+#define GET_ARRAY_PIN(p) pin_array[p].pin
#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
-#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
-#define MULTI_NAME_PAD 16 // space needed to be pretty if not first name assigned to a pin
+#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
+#define MULTI_NAME_PAD 16 // space needed to be pretty if not first name assigned to a pin
// active ADC function/mode/code values for PINSEL registers
constexpr int8_t ADC_pin_mode(pin_t pin) {
diff --git a/Marlin/src/HAL/LINUX/spi_pins.h b/Marlin/src/HAL/LINUX/spi_pins.h
index 01ba28e5b..33136ac9d 100644
--- a/Marlin/src/HAL/LINUX/spi_pins.h
+++ b/Marlin/src/HAL/LINUX/spi_pins.h
@@ -24,31 +24,32 @@
#include "../../core/macros.h"
#include "../../inc/MarlinConfigPre.h"
-#if BOTH(HAS_MARLINUI_U8GLIB, SDSUPPORT) && (LCD_PINS_D4 == SCK_PIN || LCD_PINS_ENABLE == MOSI_PIN || DOGLCD_SCK == SCK_PIN || DOGLCD_MOSI == MOSI_PIN)
+#if BOTH(HAS_MARLINUI_U8GLIB, SDSUPPORT) && (LCD_PINS_D4 == SD_SCK_PIN || LCD_PINS_ENABLE == SD_MOSI_PIN || DOGLCD_SCK == SD_SCK_PIN || DOGLCD_MOSI == SD_MOSI_PIN)
#define LPC_SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently
// needed due to the speed and mode required for communicating with each device being different.
// This requirement can be removed if the SPI access to these devices is updated to use
// spiBeginTransaction.
#endif
-/** onboard SD card */
-//#define SCK_PIN P0_07
-//#define MISO_PIN P0_08
-//#define MOSI_PIN P0_09
-//#define SS_PIN P0_06
-/** external */
-#ifndef SCK_PIN
- #define SCK_PIN 50
+// Onboard SD
+//#define SD_SCK_PIN P0_07
+//#define SD_MISO_PIN P0_08
+//#define SD_MOSI_PIN P0_09
+//#define SD_SS_PIN P0_06
+
+// External SD
+#ifndef SD_SCK_PIN
+ #define SD_SCK_PIN 50
#endif
-#ifndef MISO_PIN
- #define MISO_PIN 51
+#ifndef SD_MISO_PIN
+ #define SD_MISO_PIN 51
#endif
-#ifndef MOSI_PIN
- #define MOSI_PIN 52
+#ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN 52
#endif
-#ifndef SS_PIN
- #define SS_PIN 53
+#ifndef SD_SS_PIN
+ #define SD_SS_PIN 53
#endif
#ifndef SDSS
- #define SDSS SS_PIN
+ #define SDSS SD_SS_PIN
#endif
diff --git a/Marlin/src/HAL/LINUX/watchdog.cpp b/Marlin/src/HAL/LINUX/watchdog.cpp
index c15b0e311..84202e48b 100644
--- a/Marlin/src/HAL/LINUX/watchdog.cpp
+++ b/Marlin/src/HAL/LINUX/watchdog.cpp
@@ -27,6 +27,8 @@
#include "watchdog.h"
+#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
+
void watchdog_init() {}
void HAL_watchdog_refresh() {}
diff --git a/Marlin/src/HAL/LINUX/watchdog.h b/Marlin/src/HAL/LINUX/watchdog.h
index 472624cc7..49a0d9c63 100644
--- a/Marlin/src/HAL/LINUX/watchdog.h
+++ b/Marlin/src/HAL/LINUX/watchdog.h
@@ -21,7 +21,5 @@
*/
#pragma once
-#define WDT_TIMEOUT 4000000 // 4 second timeout
-
void watchdog_init();
void HAL_watchdog_refresh();
diff --git a/Marlin/src/HAL/LPC1768/DebugMonitor.cpp b/Marlin/src/HAL/LPC1768/DebugMonitor.cpp
deleted file mode 100644
index 783b10cfa..000000000
--- a/Marlin/src/HAL/LPC1768/DebugMonitor.cpp
+++ /dev/null
@@ -1,322 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#ifdef TARGET_LPC1768
-
-#include "../../core/macros.h"
-#include "../../core/serial.h"
-#include
-
-#include "../shared/backtrace/unwinder.h"
-#include "../shared/backtrace/unwmemaccess.h"
-#include "watchdog.h"
-#include
-
-
-// Debug monitor that dumps to the Programming port all status when
-// an exception or WDT timeout happens - And then resets the board
-
-// All the Monitor routines must run with interrupts disabled and
-// under an ISR execution context. That is why we cannot reuse the
-// Serial interrupt routines or any C runtime, as we don't know the
-// state we are when running them
-
-// A SW memory barrier, to ensure GCC does not overoptimize loops
-#define sw_barrier() __asm__ volatile("": : :"memory");
-
-// (re)initialize UART0 as a monitor output to 250000,n,8,1
-static void TXBegin() {
-}
-
-// Send character through UART with no interrupts
-static void TX(char c) {
- _DBC(c);
-}
-
-// Send String through UART
-static void TX(const char* s) {
- while (*s) TX(*s++);
-}
-
-static void TXDigit(uint32_t d) {
- if (d < 10) TX((char)(d+'0'));
- else if (d < 16) TX((char)(d+'A'-10));
- else TX('?');
-}
-
-// Send Hex number thru UART
-static void TXHex(uint32_t v) {
- TX("0x");
- for (uint8_t i = 0; i < 8; i++, v <<= 4)
- TXDigit((v >> 28) & 0xF);
-}
-
-// Send Decimal number thru UART
-static void TXDec(uint32_t v) {
- if (!v) {
- TX('0');
- return;
- }
-
- char nbrs[14];
- char *p = &nbrs[0];
- while (v != 0) {
- *p++ = '0' + (v % 10);
- v /= 10;
- }
- do {
- p--;
- TX(*p);
- } while (p != &nbrs[0]);
-}
-
-// Dump a backtrace entry
-static bool UnwReportOut(void* ctx, const UnwReport* bte) {
- int* p = (int*)ctx;
-
- (*p)++;
- TX('#'); TXDec(*p); TX(" : ");
- TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
- TX('+'); TXDec(bte->address - bte->function);
- TX(" PC:");TXHex(bte->address); TX('\n');
- return true;
-}
-
-#ifdef UNW_DEBUG
- void UnwPrintf(const char* format, ...) {
- char dest[256];
- va_list argptr;
- va_start(argptr, format);
- vsprintf(dest, format, argptr);
- va_end(argptr);
- TX(&dest[0]);
- }
-#endif
-
-/* Table of function pointers for passing to the unwinder */
-static const UnwindCallbacks UnwCallbacks = {
- UnwReportOut,
- UnwReadW,
- UnwReadH,
- UnwReadB
- #ifdef UNW_DEBUG
- ,UnwPrintf
- #endif
-};
-
-
-/**
- * HardFaultHandler_C:
- * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
- * as the parameter. We can then read the values from the stack and place them
- * into local variables for ease of reading.
- * We then read the various Fault Status and Address Registers to help decode
- * cause of the fault.
- * The function ends with a BKPT instruction to force control back into the debugger
- */
-extern "C"
-void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
-
- static const char* causestr[] = {
- "NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
- };
-
- UnwindFrame btf;
-
- // Dump report to the Programming port (interrupts are DISABLED)
- TXBegin();
- TX("\n\n## Software Fault detected ##\n");
- TX("Cause: "); TX(causestr[cause]); TX('\n');
-
- TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
- TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
- TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
- TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
- TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
- TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
- TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
- TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
-
- // Configurable Fault Status Register
- // Consists of MMSR, BFSR and UFSR
- TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
-
- // Hard Fault Status Register
- TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
-
- // Debug Fault Status Register
- TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
-
- // Auxiliary Fault Status Register
- TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
-
- // Read the Fault Address Registers. These may not contain valid values.
- // Check BFARVALID/MMARVALID to see if they are valid values
- // MemManage Fault Address Register
- TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
-
- // Bus Fault Address Register
- TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
-
- TX("ExcLR: "); TXHex(lr); TX('\n');
- TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
-
- btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
- btf.fp = btf.sp;
- btf.lr = ((unsigned long)sp[5]);
- btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
-
- // Perform a backtrace
- TX("\nBacktrace:\n\n");
- int ctr = 0;
- UnwindStart(&btf, &UnwCallbacks, &ctr);
-
- // Disable all NVIC interrupts
- NVIC->ICER[0] = 0xFFFFFFFF;
- NVIC->ICER[1] = 0xFFFFFFFF;
-
- // Relocate VTOR table to default position
- SCB->VTOR = 0;
-
- // Clear cause of reset to prevent entering smoothie bootstrap
- HAL_clear_reset_source();
-
- // Restart watchdog
- #if ENABLED(USE_WATCHDOG)
- //WDT_Restart(WDT);
- watchdog_init();
- #endif
-
- // Reset controller
- NVIC_SystemReset();
-
- // Nothing below here is compiled because NVIC_SystemReset loops forever
-
- for (;;) { TERN_(USE_WATCHDOG, watchdog_init()); }
-}
-
-extern "C" {
-__attribute__((naked)) void NMI_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#0")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void HardFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#1")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void MemManage_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#2")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void BusFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#3")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void UsageFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#4")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void DebugMon_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#5")
- A("b HardFault_HandlerC")
- );
-}
-
-/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
-__attribute__((naked)) void WDT_IRQHandler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#6")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void RSTC_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#7")
- A("b HardFault_HandlerC")
- );
-}
-}
-#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/HAL.cpp b/Marlin/src/HAL/LPC1768/HAL.cpp
index 939f1e8a9..cee9cfc5f 100644
--- a/Marlin/src/HAL/LPC1768/HAL.cpp
+++ b/Marlin/src/HAL/LPC1768/HAL.cpp
@@ -29,21 +29,18 @@
#include "watchdog.h"
#endif
+DefaultSerial1 USBSerial(false, UsbSerial);
+
uint32_t HAL_adc_reading = 0;
// U8glib required functions
-extern "C" void u8g_xMicroDelay(uint16_t val) {
- DELAY_US(val);
-}
-extern "C" void u8g_MicroDelay() {
- u8g_xMicroDelay(1);
-}
-extern "C" void u8g_10MicroDelay() {
- u8g_xMicroDelay(10);
-}
-extern "C" void u8g_Delay(uint16_t val) {
- delay(val);
+extern "C" {
+ void u8g_xMicroDelay(uint16_t val) { DELAY_US(val); }
+ void u8g_MicroDelay() { u8g_xMicroDelay(1); }
+ void u8g_10MicroDelay() { u8g_xMicroDelay(10); }
+ void u8g_Delay(uint16_t val) { delay(val); }
}
+
//************************//
// return free heap space
@@ -66,7 +63,12 @@ int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
return ind > -1 ? ind : dval;
}
-void flashFirmware(const int16_t) { NVIC_SystemReset(); }
+void flashFirmware(const int16_t) {
+ delay(500); // Give OS time to disconnect
+ USB_Connect(false); // USB clear connection
+ delay(1000); // Give OS time to notice
+ HAL_reboot();
+}
void HAL_clear_reset_source(void) {
TERN_(USE_WATCHDOG, watchdog_clear_timeout_flag());
@@ -79,4 +81,6 @@ uint8_t HAL_get_reset_source(void) {
return RST_POWER_ON;
}
+void HAL_reboot() { NVIC_SystemReset(); }
+
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/HAL.h b/Marlin/src/HAL/LPC1768/HAL.h
index cb637e715..bcfa6c412 100644
--- a/Marlin/src/HAL/LPC1768/HAL.h
+++ b/Marlin/src/HAL/LPC1768/HAL.h
@@ -47,9 +47,6 @@ extern "C" volatile uint32_t _millis;
#include
#include
-// i2c uses 8-bit shifted address
-#define I2C_ADDRESS(A) uint8_t((A) << 1)
-
//
// Default graphical display delays
//
@@ -63,35 +60,50 @@ extern "C" volatile uint32_t _millis;
#define ST7920_DELAY_3 DELAY_NS(750)
#endif
+typedef ForwardSerial1Class< decltype(UsbSerial) > DefaultSerial1;
+extern DefaultSerial1 USBSerial;
+
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
-#define MSerial0 MSerial
#if SERIAL_PORT == -1
- #define MYSERIAL0 UsbSerial
+ #define MYSERIAL1 USBSerial
#elif WITHIN(SERIAL_PORT, 0, 3)
- #define MYSERIAL0 MSERIAL(SERIAL_PORT)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
- #error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
- #define MYSERIAL1 UsbSerial
+ #define MYSERIAL2 USBSerial
#elif WITHIN(SERIAL_PORT_2, 0, 3)
- #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
+ #define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
- #error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+#endif
+
+#ifdef MMU2_SERIAL_PORT
+ #if MMU2_SERIAL_PORT == -1
+ #define MMU2_SERIAL USBSerial
+ #elif WITHIN(MMU2_SERIAL_PORT, 0, 3)
+ #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
+ #else
+ #error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if LCD_SERIAL_PORT == -1
- #define LCD_SERIAL UsbSerial
+ #define LCD_SERIAL USBSerial
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+ #if HAS_DGUS_LCD
+ #define SERIAL_GET_TX_BUFFER_FREE() MSerial0.available()
#endif
#endif
@@ -107,10 +119,16 @@ extern "C" volatile uint32_t _millis;
//
// Utility functions
//
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
int freeMemory();
-#pragma GCC diagnostic pop
+
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic pop
+#endif
//
// ADC API
@@ -200,9 +218,4 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255,
void HAL_clear_reset_source(void);
uint8_t HAL_get_reset_source(void);
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
-
-// Add strcmp_P if missing
-#ifndef strcmp_P
- #define strcmp_P(a, b) strcmp((a), (b))
-#endif
+void HAL_reboot();
diff --git a/Marlin/src/HAL/LPC1768/HAL_MinSerial.cpp b/Marlin/src/HAL/LPC1768/HAL_MinSerial.cpp
new file mode 100644
index 000000000..ab9af1fe0
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/HAL_MinSerial.cpp
@@ -0,0 +1,50 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef TARGET_LPC1768
+
+#include "HAL.h"
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+
+#include "../shared/HAL_MinSerial.h"
+#include
+
+static void TX(char c) { _DBC(c); }
+void install_min_serial() { HAL_min_serial_out = &TX; }
+
+#if DISABLED(DYNAMIC_VECTORTABLE)
+extern "C" {
+ __attribute__((naked)) void JumpHandler_ASM() {
+ __asm__ __volatile__ (
+ "b CommonHandler_ASM\n"
+ );
+ }
+ void __attribute__((naked, alias("JumpHandler_ASM"))) HardFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) BusFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) UsageFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) MemManage_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) NMI_Handler();
+}
+#endif
+
+#endif // POSTMORTEM_DEBUGGING
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/HAL_SPI.cpp b/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
index b3d2908ac..99db15f6e 100644
--- a/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
+++ b/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
@@ -55,27 +55,33 @@
#include
#include
+#include "../shared/HAL_SPI.h"
+
// ------------------------
// Public functions
// ------------------------
#if ENABLED(LPC_SOFTWARE_SPI)
- #include
-
// Software SPI
- static uint8_t SPI_speed = 0;
+ #include
+
+ #ifndef HAL_SPI_SPEED
+ #define HAL_SPI_SPEED SPI_FULL_SPEED
+ #endif
+
+ static uint8_t SPI_speed = HAL_SPI_SPEED;
static uint8_t spiTransfer(uint8_t b) {
- return swSpiTransfer(b, SPI_speed, SCK_PIN, MISO_PIN, MOSI_PIN);
+ return swSpiTransfer(b, SPI_speed, SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
}
void spiBegin() {
- swSpiBegin(SCK_PIN, MISO_PIN, MOSI_PIN);
+ swSpiBegin(SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
}
void spiInit(uint8_t spiRate) {
- SPI_speed = swSpiInit(spiRate, SCK_PIN, MOSI_PIN);
+ SPI_speed = swSpiInit(spiRate, SD_SCK_PIN, SD_MOSI_PIN);
}
uint8_t spiRec() { return spiTransfer(0xFF); }
@@ -87,12 +93,12 @@
void spiSend(uint8_t b) { (void)spiTransfer(b); }
- void spiSend(const uint8_t* buf, size_t nbyte) {
+ void spiSend(const uint8_t *buf, size_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++)
(void)spiTransfer(buf[i]);
}
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
(void)spiTransfer(token);
for (uint16_t i = 0; i < 512; i++)
(void)spiTransfer(buf[i]);
@@ -100,14 +106,20 @@
#else
- void spiBegin() { // setup SCK, MOSI & MISO pins for SSP0
- spiInit(SPI_SPEED);
- }
+ #ifndef HAL_SPI_SPEED
+ #ifdef SD_SPI_SPEED
+ #define HAL_SPI_SPEED SD_SPI_SPEED
+ #else
+ #define HAL_SPI_SPEED SPI_FULL_SPEED
+ #endif
+ #endif
+
+ void spiBegin() { spiInit(HAL_SPI_SPEED); } // Set up SCK, MOSI & MISO pins for SSP0
void spiInit(uint8_t spiRate) {
- #if MISO_PIN == BOARD_SPI1_MISO_PIN
+ #if SD_MISO_PIN == BOARD_SPI1_MISO_PIN
SPI.setModule(1);
- #elif MISO_PIN == BOARD_SPI2_MISO_PIN
+ #elif SD_MISO_PIN == BOARD_SPI2_MISO_PIN
SPI.setModule(2);
#endif
SPI.setDataSize(DATA_SIZE_8BIT);
@@ -123,15 +135,13 @@
void spiSend(uint8_t b) { doio(b); }
- void spiSend(const uint8_t* buf, size_t nbyte) {
+ void spiSend(const uint8_t *buf, size_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++) doio(buf[i]);
}
- void spiSend(uint32_t chan, byte b) {
- }
+ void spiSend(uint32_t chan, byte b) {}
- void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {
- }
+ void spiSend(uint32_t chan, const uint8_t *buf, size_t nbyte) {}
// Read single byte from SPI
uint8_t spiRec() { return doio(0xFF); }
@@ -143,21 +153,18 @@
for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
}
- uint8_t spiTransfer(uint8_t b) {
- return doio(b);
- }
+ uint8_t spiTransfer(uint8_t b) { return doio(b); }
// Write from buffer to SPI
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
(void)spiTransfer(token);
for (uint16_t i = 0; i < 512; i++)
(void)spiTransfer(buf[i]);
}
- /** Begin SPI transaction, set clock, bit order, data mode */
+ // Begin SPI transaction, set clock, bit order, data mode
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
- // TODO: to be implemented
-
+ // TODO: Implement this method
}
#endif // LPC_SOFTWARE_SPI
@@ -201,6 +208,15 @@ SPIClass::SPIClass(uint8_t device) {
GPDMA_Init();
}
+SPIClass::SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel) {
+ #if BOARD_NR_SPI >= 1
+ if (mosi == BOARD_SPI1_MOSI_PIN) SPIClass(1);
+ #endif
+ #if BOARD_NR_SPI >= 2
+ if (mosi == BOARD_SPI2_MOSI_PIN) SPIClass(2);
+ #endif
+}
+
void SPIClass::begin() {
// Init the SPI pins in the first begin call
if ((_currentSetting->spi_d == LPC_SSP0 && spiInitialised[0] == false) ||
@@ -263,8 +279,9 @@ uint16_t SPIClass::transfer16(const uint16_t data) {
}
void SPIClass::end() {
- // SSP_Cmd(_currentSetting->spi_d, DISABLE); // stop device or SSP_DeInit?
- SSP_DeInit(_currentSetting->spi_d);
+ // Neither is needed for Marlin
+ //SSP_Cmd(_currentSetting->spi_d, DISABLE);
+ //SSP_DeInit(_currentSetting->spi_d);
}
void SPIClass::send(uint8_t data) {
@@ -330,25 +347,15 @@ void SPIClass::read(uint8_t *buf, uint32_t len) {
for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF);
}
-void SPIClass::setClock(uint32_t clock) {
- _currentSetting->clock = clock;
-}
+void SPIClass::setClock(uint32_t clock) { _currentSetting->clock = clock; }
-void SPIClass::setModule(uint8_t device) {
- _currentSetting = &_settings[device - 1];// SPI channels are called 1 2 and 3 but the array is zero indexed
-}
+void SPIClass::setModule(uint8_t device) { _currentSetting = &_settings[device - 1]; } // SPI channels are called 1, 2, and 3 but the array is zero-indexed
-void SPIClass::setBitOrder(uint8_t bitOrder) {
- _currentSetting->bitOrder = bitOrder;
-}
+void SPIClass::setBitOrder(uint8_t bitOrder) { _currentSetting->bitOrder = bitOrder; }
-void SPIClass::setDataMode(uint8_t dataMode) {
- _currentSetting->dataMode = dataMode;
-}
+void SPIClass::setDataMode(uint8_t dataMode) { _currentSetting->dataMode = dataMode; }
-void SPIClass::setDataSize(uint32_t ds) {
- _currentSetting->dataSize = ds;
-}
+void SPIClass::setDataSize(uint32_t dataSize) { _currentSetting->dataSize = dataSize; }
/**
* Set up/tear down
@@ -356,8 +363,8 @@ void SPIClass::setDataSize(uint32_t ds) {
void SPIClass::updateSettings() {
//SSP_DeInit(_currentSetting->spi_d); //todo: need force de init?!
- // divide PCLK by 2 for SSP0
- CLKPWR_SetPCLKDiv(_currentSetting->spi_d == LPC_SSP0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
+ // Divide PCLK by 2 for SSP0
+ //CLKPWR_SetPCLKDiv(_currentSetting->spi_d == LPC_SSP0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
SSP_CFG_Type HW_SPI_init; // data structure to hold init values
SSP_ConfigStructInit(&HW_SPI_init); // set values for SPI mode
@@ -396,9 +403,9 @@ void SPIClass::updateSettings() {
SSP_Init(_currentSetting->spi_d, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
}
-#if MISO_PIN == BOARD_SPI1_MISO_PIN
+#if SD_MISO_PIN == BOARD_SPI1_MISO_PIN
SPIClass SPI(1);
-#elif MISO_PIN == BOARD_SPI2_MISO_PIN
+#elif SD_MISO_PIN == BOARD_SPI2_MISO_PIN
SPIClass SPI(2);
#endif
diff --git a/Marlin/src/HAL/STM32_F4_F7/Servo.h b/Marlin/src/HAL/LPC1768/MarlinSPI.h
similarity index 57%
rename from Marlin/src/HAL/STM32_F4_F7/Servo.h
rename to Marlin/src/HAL/LPC1768/MarlinSPI.h
index e42cc6084..fab245f90 100644
--- a/Marlin/src/HAL/STM32_F4_F7/Servo.h
+++ b/Marlin/src/HAL/LPC1768/MarlinSPI.h
@@ -4,7 +4,6 @@
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- * Copyright (c) 2017 Victor Perez
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,20 +21,25 @@
*/
#pragma once
-//#ifdef STM32F7
-// #include <../../libraries/Servo/src/Servo.h>
-//#else
- #include
-//#endif
+#include
-// Inherit and expand on the official library
-class libServo : public Servo {
- public:
- int8_t attach(const int pin);
- int8_t attach(const int pin, const int min, const int max);
- void move(const int value);
- private:
- typedef Servo super;
- uint16_t min_ticks, max_ticks;
- uint8_t servoIndex; // index into the channel data for this servo
-};
+/**
+ * Marlin currently requires 3 SPI classes:
+ *
+ * SPIClass:
+ * This class is normally provided by frameworks and has a semi-default interface.
+ * This is needed because some libraries reference it globally.
+ *
+ * SPISettings:
+ * Container for SPI configs for SPIClass. As above, libraries may reference it globally.
+ *
+ * These two classes are often provided by frameworks so we cannot extend them to add
+ * useful methods for Marlin.
+ *
+ * MarlinSPI:
+ * Provides the default SPIClass interface plus some Marlin goodies such as a simplified
+ * interface for SPI DMA transfer.
+ *
+ */
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/LPC1768/MarlinSerial.cpp b/Marlin/src/HAL/LPC1768/MarlinSerial.cpp
index 5374e005d..f35328d22 100644
--- a/Marlin/src/HAL/LPC1768/MarlinSerial.cpp
+++ b/Marlin/src/HAL/LPC1768/MarlinSerial.cpp
@@ -21,35 +21,51 @@
*/
#ifdef TARGET_LPC1768
-#include "../../inc/MarlinConfigPre.h"
#include "MarlinSerial.h"
-#if USING_SERIAL_0
- MarlinSerial MSerial(LPC_UART0);
- extern "C" void UART0_IRQHandler() {
- MSerial.IRQHandler();
- }
+#include "../../inc/MarlinConfig.h"
+
+#if USING_HW_SERIAL0
+ MarlinSerial _MSerial(LPC_UART0);
+ MSerialT MSerial0(true, _MSerial);
+ extern "C" void UART0_IRQHandler() { _MSerial.IRQHandler(); }
+#endif
+#if USING_HW_SERIAL1
+ MarlinSerial _MSerial1((LPC_UART_TypeDef *) LPC_UART1);
+ MSerialT MSerial1(true, _MSerial1);
+ extern "C" void UART1_IRQHandler() { _MSerial1.IRQHandler(); }
+#endif
+#if USING_HW_SERIAL2
+ MarlinSerial _MSerial2(LPC_UART2);
+ MSerialT MSerial2(true, _MSerial2);
+ extern "C" void UART2_IRQHandler() { _MSerial2.IRQHandler(); }
+#endif
+#if USING_HW_SERIAL3
+ MarlinSerial _MSerial3(LPC_UART3);
+ MSerialT MSerial3(true, _MSerial3);
+ extern "C" void UART3_IRQHandler() { _MSerial3.IRQHandler(); }
#endif
-#if USING_SERIAL_1
- MarlinSerial MSerial1((LPC_UART_TypeDef *) LPC_UART1);
- extern "C" void UART1_IRQHandler() {
- MSerial1.IRQHandler();
- }
-#endif
+#if ENABLED(EMERGENCY_PARSER)
-#if USING_SERIAL_2
- MarlinSerial MSerial2(LPC_UART2);
- extern "C" void UART2_IRQHandler() {
- MSerial2.IRQHandler();
+ bool MarlinSerial::recv_callback(const char c) {
+ // Need to figure out which serial port we are and react in consequence (Marlin does not have CONTAINER_OF macro)
+ if (false) {}
+ #if USING_HW_SERIAL0
+ else if (this == &_MSerial) emergency_parser.update(MSerial0.emergency_state, c);
+ #endif
+ #if USING_HW_SERIAL1
+ else if (this == &_MSerial1) emergency_parser.update(MSerial1.emergency_state, c);
+ #endif
+ #if USING_HW_SERIAL2
+ else if (this == &_MSerial2) emergency_parser.update(MSerial2.emergency_state, c);
+ #endif
+ #if USING_HW_SERIAL3
+ else if (this == &_MSerial3) emergency_parser.update(MSerial3.emergency_state, c);
+ #endif
+ return true;
}
-#endif
-#if USING_SERIAL_3
- MarlinSerial MSerial3(LPC_UART3);
- extern "C" void UART3_IRQHandler() {
- MSerial3.IRQHandler();
- }
#endif
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/MarlinSerial.h b/Marlin/src/HAL/LPC1768/MarlinSerial.h
index 8d6b64378..489bd8cc6 100644
--- a/Marlin/src/HAL/LPC1768/MarlinSerial.h
+++ b/Marlin/src/HAL/LPC1768/MarlinSerial.h
@@ -28,6 +28,7 @@
#if ENABLED(EMERGENCY_PARSER)
#include "../../feature/e_parser.h"
#endif
+#include "../../core/serial_hook.h"
#ifndef SERIAL_PORT
#define SERIAL_PORT 0
@@ -41,27 +42,26 @@
class MarlinSerial : public HardwareSerial {
public:
- MarlinSerial(LPC_UART_TypeDef *UARTx) :
- HardwareSerial(UARTx)
- #if ENABLED(EMERGENCY_PARSER)
- , emergency_state(EmergencyParser::State::EP_RESET)
- #endif
- { }
+ MarlinSerial(LPC_UART_TypeDef *UARTx) : HardwareSerial(UARTx) { }
void end() {}
#if ENABLED(EMERGENCY_PARSER)
- bool recv_callback(const char c) override {
- emergency_parser.update(emergency_state, c);
- return true; // do not discard character
- }
-
- EmergencyParser::State emergency_state;
- static inline bool emergency_parser_enabled() { return true; }
+ bool recv_callback(const char c) override;
#endif
};
-extern MarlinSerial MSerial;
-extern MarlinSerial MSerial1;
-extern MarlinSerial MSerial2;
-extern MarlinSerial MSerial3;
+// On LPC176x framework, HardwareSerial does not implement the same interface as Arduino's Serial, so overloads
+// of 'available' and 'read' method are not used in this multiple inheritance scenario.
+// Instead, use a ForwardSerial here that adapts the interface.
+typedef ForwardSerial1Class MSerialT;
+extern MSerialT MSerial0;
+extern MSerialT MSerial1;
+extern MSerialT MSerial2;
+extern MSerialT MSerial3;
+
+// Consequently, we can't use a RuntimeSerial either. The workaround would be to use a RuntimeSerial> type here
+// Right now, let's ignore this until it's actually required.
+#if ENABLED(SERIAL_RUNTIME_HOOK)
+ #error "SERIAL_RUNTIME_HOOK is not yet supported for LPC176x."
+#endif
diff --git a/Marlin/src/HAL/LPC1768/eeprom_flash.cpp b/Marlin/src/HAL/LPC1768/eeprom_flash.cpp
index 255848637..38d2705d5 100644
--- a/Marlin/src/HAL/LPC1768/eeprom_flash.cpp
+++ b/Marlin/src/HAL/LPC1768/eeprom_flash.cpp
@@ -25,7 +25,7 @@
* Emulate EEPROM storage using Flash Memory
*
* Use a single 32K flash sector to store EEPROM data. To reduce the
- * number of erase operations a simple "levelling" scheme is used that
+ * number of erase operations a simple "leveling" scheme is used that
* maintains a number of EEPROM "slots" within the larger flash sector.
* Each slot is used in turn and the entire sector is only erased when all
* slots have been used.
@@ -119,7 +119,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false; // return true for any error
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
const uint8_t * const buff = writing ? &value[0] : &ram_eeprom[pos];
if (writing) for (size_t i = 0; i < size; i++) value[i] = ram_eeprom[pos + i];
crc16(crc, buff, size);
diff --git a/Marlin/src/HAL/LPC1768/eeprom_sdcard.cpp b/Marlin/src/HAL/LPC1768/eeprom_sdcard.cpp
index 9f2475f49..70395251d 100644
--- a/Marlin/src/HAL/LPC1768/eeprom_sdcard.cpp
+++ b/Marlin/src/HAL/LPC1768/eeprom_sdcard.cpp
@@ -83,17 +83,16 @@ bool PersistentStore::access_finish() {
static void debug_rw(const bool write, int &pos, const uint8_t *value, const size_t size, const FRESULT s, const size_t total=0) {
PGM_P const rw_str = write ? PSTR("write") : PSTR("read");
SERIAL_CHAR(' ');
- serialprintPGM(rw_str);
- SERIAL_ECHOLNPAIR("_data(", pos, ",", int(value), ",", int(size), ", ...)");
+ SERIAL_ECHOPGM_P(rw_str);
+ SERIAL_ECHOLNPAIR("_data(", pos, ",", value, ",", size, ", ...)");
if (total) {
SERIAL_ECHOPGM(" f_");
- serialprintPGM(rw_str);
- SERIAL_ECHOPAIR("()=", int(s), "\n size=", int(size), "\n bytes_");
- serialprintPGM(write ? PSTR("written=") : PSTR("read="));
- SERIAL_ECHOLN(total);
+ SERIAL_ECHOPGM_P(rw_str);
+ SERIAL_ECHOPAIR("()=", s, "\n size=", size, "\n bytes_");
+ SERIAL_ECHOLNPAIR_P(write ? PSTR("written=") : PSTR("read="), total);
}
else
- SERIAL_ECHOLNPAIR(" f_lseek()=", int(s));
+ SERIAL_ECHOLNPAIR(" f_lseek()=", s);
}
// File function return codes for type FRESULT. This goes away soon, but
@@ -143,7 +142,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return bytes_written != size; // return true for any error
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
if (!eeprom_file_open) return true;
UINT bytes_read = 0;
FRESULT s;
diff --git a/Marlin/src/HAL/LPC1768/eeprom_wired.cpp b/Marlin/src/HAL/LPC1768/eeprom_wired.cpp
index 16c15eaf0..f9286a74a 100644
--- a/Marlin/src/HAL/LPC1768/eeprom_wired.cpp
+++ b/Marlin/src/HAL/LPC1768/eeprom_wired.cpp
@@ -42,33 +42,29 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t v = *value;
-
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
uint8_t * const p = (uint8_t * const)pos;
- if (v != eeprom_read_byte(p)) {
+ if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
}
}
-
crc16(crc, &v, 1);
pos++;
value++;
- };
-
+ }
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
// Read from external EEPROM
const uint8_t c = eeprom_read_byte((uint8_t*)pos);
-
if (writing) *value = c;
crc16(crc, &c, 1);
pos++;
diff --git a/Marlin/src/HAL/LPC1768/endstop_interrupts.h b/Marlin/src/HAL/LPC1768/endstop_interrupts.h
index b0d0c0ec5..126d6e7d5 100644
--- a/Marlin/src/HAL/LPC1768/endstop_interrupts.h
+++ b/Marlin/src/HAL/LPC1768/endstop_interrupts.h
@@ -46,79 +46,79 @@ void setup_endstop_interrupts() {
#if HAS_X_MAX
#if !LPC1768_PIN_INTERRUPT_M(X_MAX_PIN)
- #error "X_MAX_PIN is not INTERRUPT-capable."
+ #error "X_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(X_MAX_PIN);
#endif
#if HAS_X_MIN
#if !LPC1768_PIN_INTERRUPT_M(X_MIN_PIN)
- #error "X_MIN_PIN is not INTERRUPT-capable."
+ #error "X_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(X_MIN_PIN);
#endif
#if HAS_Y_MAX
#if !LPC1768_PIN_INTERRUPT_M(Y_MAX_PIN)
- #error "Y_MAX_PIN is not INTERRUPT-capable."
+ #error "Y_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Y_MAX_PIN);
#endif
#if HAS_Y_MIN
#if !LPC1768_PIN_INTERRUPT_M(Y_MIN_PIN)
- #error "Y_MIN_PIN is not INTERRUPT-capable."
+ #error "Y_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Y_MIN_PIN);
#endif
#if HAS_Z_MAX
#if !LPC1768_PIN_INTERRUPT_M(Z_MAX_PIN)
- #error "Z_MAX_PIN is not INTERRUPT-capable."
+ #error "Z_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z_MAX_PIN);
#endif
#if HAS_Z_MIN
#if !LPC1768_PIN_INTERRUPT_M(Z_MIN_PIN)
- #error "Z_MIN_PIN is not INTERRUPT-capable."
+ #error "Z_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z_MIN_PIN);
#endif
#if HAS_Z2_MAX
#if !LPC1768_PIN_INTERRUPT_M(Z2_MAX_PIN)
- #error "Z2_MAX_PIN is not INTERRUPT-capable."
+ #error "Z2_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z2_MAX_PIN);
#endif
#if HAS_Z2_MIN
#if !LPC1768_PIN_INTERRUPT_M(Z2_MIN_PIN)
- #error "Z2_MIN_PIN is not INTERRUPT-capable."
+ #error "Z2_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z2_MIN_PIN);
#endif
#if HAS_Z3_MAX
#if !LPC1768_PIN_INTERRUPT_M(Z3_MAX_PIN)
- #error "Z3_MIN_PIN is not INTERRUPT-capable."
+ #error "Z3_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z3_MAX_PIN);
#endif
#if HAS_Z3_MIN
#if !LPC1768_PIN_INTERRUPT_M(Z3_MIN_PIN)
- #error "Z3_MIN_PIN is not INTERRUPT-capable."
+ #error "Z3_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z3_MIN_PIN);
#endif
#if HAS_Z4_MAX
#if !LPC1768_PIN_INTERRUPT_M(Z4_MAX_PIN)
- #error "Z4_MIN_PIN is not INTERRUPT-capable."
+ #error "Z4_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z4_MAX_PIN);
#endif
#if HAS_Z4_MIN
#if !LPC1768_PIN_INTERRUPT_M(Z4_MIN_PIN)
- #error "Z4_MIN_PIN is not INTERRUPT-capable."
+ #error "Z4_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z4_MIN_PIN);
#endif
#if HAS_Z_MIN_PROBE_PIN
#if !LPC1768_PIN_INTERRUPT_M(Z_MIN_PROBE_PIN)
- #error "Z_MIN_PROBE_PIN is not INTERRUPT-capable."
+ #error "Z_MIN_PROBE_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z_MIN_PROBE_PIN);
#endif
diff --git a/Marlin/src/HAL/LPC1768/inc/Conditionals_adv.h b/Marlin/src/HAL/LPC1768/inc/Conditionals_adv.h
index 5f1c4b160..8e7cab185 100644
--- a/Marlin/src/HAL/LPC1768/inc/Conditionals_adv.h
+++ b/Marlin/src/HAL/LPC1768/inc/Conditionals_adv.h
@@ -20,3 +20,7 @@
*
*/
#pragma once
+
+#if DISABLED(NO_SD_HOST_DRIVE)
+ #define HAS_SD_HOST_DRIVE 1
+#endif
diff --git a/Marlin/src/HAL/LPC1768/inc/Conditionals_post.h b/Marlin/src/HAL/LPC1768/inc/Conditionals_post.h
index ce6d3fdde..be574a96e 100644
--- a/Marlin/src/HAL/LPC1768/inc/Conditionals_post.h
+++ b/Marlin/src/HAL/LPC1768/inc/Conditionals_post.h
@@ -26,3 +26,9 @@
#elif EITHER(I2C_EEPROM, SPI_EEPROM)
#define USE_SHARED_EEPROM 1
#endif
+
+// LPC1768 boards seem to lose steps when saving to EEPROM during print (issue #20785)
+// TODO: Which other boards are incompatible?
+#if defined(MCU_LPC1768) && PRINTCOUNTER_SAVE_INTERVAL > 0
+ #define PRINTCOUNTER_SYNC 1
+#endif
diff --git a/Marlin/src/HAL/LPC1768/inc/SanityCheck.h b/Marlin/src/HAL/LPC1768/inc/SanityCheck.h
index f5051d32a..a6286ba6f 100644
--- a/Marlin/src/HAL/LPC1768/inc/SanityCheck.h
+++ b/Marlin/src/HAL/LPC1768/inc/SanityCheck.h
@@ -24,14 +24,14 @@
#if PIO_PLATFORM_VERSION < 1001
#error "nxplpc-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries. You may need to remove the platform and let it reinstall automatically."
#endif
-#if PIO_FRAMEWORK_VERSION < 2005
+#if PIO_FRAMEWORK_VERSION < 2006
#error "framework-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries."
#endif
/**
* Detect an old pins file by checking for old ADC pins values.
*/
-#define _OLD_TEMP_PIN(P) PIN_EXISTS(P) && _CAT(P,_PIN) <= 7 && _CAT(P,_PIN) != 2 && _CAT(P,_PIN) != 3
+#define _OLD_TEMP_PIN(P) PIN_EXISTS(P) && _CAT(P,_PIN) <= 7 && !WITHIN(_CAT(P,_PIN), TERN(LPC1768_IS_SKRV1_3, 0, 2), 3) // Include P0_00 and P0_01 for SKR V1.3 board
#if _OLD_TEMP_PIN(TEMP_BED)
#error "TEMP_BED_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#elif _OLD_TEMP_PIN(TEMP_0)
@@ -72,7 +72,7 @@ static_assert(!(NUM_SERVOS && ENABLED(FAST_PWM_FAN)), "BLTOUCH and Servos are in
//#endif
#if MB(RAMPS_14_RE_ARM_EFB, RAMPS_14_RE_ARM_EEB, RAMPS_14_RE_ARM_EFF, RAMPS_14_RE_ARM_EEF, RAMPS_14_RE_ARM_SF)
- #if ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) && HAS_DRIVER(TMC2130) && DISABLED(TMC_USE_SW_SPI)
+ #if IS_RRD_FG_SC && HAS_DRIVER(TMC2130) && DISABLED(TMC_USE_SW_SPI)
#error "Re-ARM with REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER and TMC2130 requires TMC_USE_SW_SPI."
#endif
#endif
@@ -92,13 +92,13 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#define ANY_TX(N,V...) DO(IS_TX##N,||,V)
#define ANY_RX(N,V...) DO(IS_RX##N,||,V)
-#if USING_SERIAL_0
+#if USING_HW_SERIAL0
#define IS_TX0(P) (P == P0_02)
#define IS_RX0(P) (P == P0_03)
#if IS_TX0(TMC_SW_MISO) || IS_RX0(TMC_SW_MOSI)
#error "Serial port pins (0) conflict with Trinamic SPI pins!"
- #elif ENABLED(MK2_MULTIPLEXER) && (IS_TX0(E_MUX1_PIN) || IS_RX0(E_MUX0_PIN))
- #error "Serial port pins (0) conflict with MK2 multiplexer pins!"
+ #elif HAS_PRUSA_MMU1 && (IS_TX0(E_MUX1_PIN) || IS_RX0(E_MUX0_PIN))
+ #error "Serial port pins (0) conflict with Multi-Material-Unit multiplexer pins!"
#elif (AXIS_HAS_SPI(X) && IS_TX0(X_CS_PIN)) || (AXIS_HAS_SPI(Y) && IS_RX0(Y_CS_PIN))
#error "Serial port pins (0) conflict with X/Y axis SPI pins!"
#endif
@@ -106,7 +106,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#undef IS_RX0
#endif
-#if USING_SERIAL_1
+#if USING_HW_SERIAL1
#define IS_TX1(P) (P == P0_15)
#define IS_RX1(P) (P == P0_16)
#define _IS_TX1_1 IS_TX1
@@ -116,8 +116,8 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#elif HAS_WIRED_LCD
#if IS_TX1(BTN_EN2) || IS_RX1(BTN_EN1)
#error "Serial port pins (1) conflict with Encoder Buttons!"
- #elif ANY_TX(1, SCK_PIN, LCD_PINS_D4, DOGLCD_SCK, LCD_RESET_PIN, LCD_PINS_RS, SHIFT_CLK) \
- || ANY_RX(1, LCD_SDSS, LCD_PINS_RS, MISO_PIN, DOGLCD_A0, SS_PIN, LCD_SDSS, DOGLCD_CS, LCD_RESET_PIN, LCD_BACKLIGHT_PIN)
+ #elif ANY_TX(1, SD_SCK_PIN, LCD_PINS_D4, DOGLCD_SCK, LCD_RESET_PIN, LCD_PINS_RS, SHIFT_CLK_PIN) \
+ || ANY_RX(1, LCD_SDSS, LCD_PINS_RS, SD_MISO_PIN, DOGLCD_A0, SD_SS_PIN, LCD_SDSS, DOGLCD_CS, LCD_RESET_PIN, LCD_BACKLIGHT_PIN)
#error "Serial port pins (1) conflict with LCD pins!"
#endif
#endif
@@ -127,7 +127,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#undef _IS_RX1_1
#endif
-#if USING_SERIAL_2
+#if USING_HW_SERIAL2
#define IS_TX2(P) (P == P0_10)
#define IS_RX2(P) (P == P0_11)
#define _IS_TX2_1 IS_TX2
@@ -161,7 +161,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#undef _IS_RX2_1
#endif
-#if USING_SERIAL_3
+#if USING_HW_SERIAL3
#define PIN_IS_TX3(P) (PIN_EXISTS(P) && P##_PIN == P0_00)
#define PIN_IS_RX3(P) (P##_PIN == P0_01)
#if PIN_IS_TX3(X_MIN) || PIN_IS_RX3(X_MAX)
@@ -205,8 +205,8 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#error "SDA0 overlaps with BEEPER_PIN!"
#elif IS_SCL0(BTN_ENC)
#error "SCL0 overlaps with Encoder Button!"
- #elif IS_SCL0(SS_PIN)
- #error "SCL0 overlaps with SS_PIN!"
+ #elif IS_SCL0(SD_SS_PIN)
+ #error "SCL0 overlaps with SD_SS_PIN!"
#elif IS_SCL0(LCD_SDSS)
#error "SCL0 overlaps with LCD_SDSS!"
#endif
@@ -270,7 +270,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- #error "SERIAL_STATS_MAX_RX_QUEUED is not supported on this platform."
+ #error "SERIAL_STATS_MAX_RX_QUEUED is not supported on LPC176x."
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
- #error "SERIAL_STATS_DROPPED_RX is not supported on this platform."
+ #error "SERIAL_STATS_DROPPED_RX is not supported on LPX176x."
#endif
diff --git a/Marlin/src/HAL/LPC1768/include/SPI.h b/Marlin/src/HAL/LPC1768/include/SPI.h
index 9da2a3255..ecd91f6a3 100644
--- a/Marlin/src/HAL/LPC1768/include/SPI.h
+++ b/Marlin/src/HAL/LPC1768/include/SPI.h
@@ -37,13 +37,14 @@
#define DATA_SIZE_8BIT SSP_DATABIT_8
#define DATA_SIZE_16BIT SSP_DATABIT_16
-#define SPI_CLOCK_DIV2 8333333 //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
-#define SPI_CLOCK_DIV4 4166667 //(SCR: 5) desired: 4,000,000 actual: 4,166,667 +4.2% SPI_HALF_SPEED
-#define SPI_CLOCK_DIV8 2083333 //(SCR: 11) desired: 2,000,000 actual: 2,083,333 +4.2% SPI_QUARTER_SPEED
-#define SPI_CLOCK_DIV16 1000000 //(SCR: 24) desired: 1,000,000 actual: 1,000,000 SPI_EIGHTH_SPEED
-#define SPI_CLOCK_DIV32 500000 //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
-#define SPI_CLOCK_DIV64 250000 //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
-#define SPI_CLOCK_DIV128 125000 //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
+#define SPI_CLOCK_MAX_TFT 30000000UL
+#define SPI_CLOCK_DIV2 8333333 //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
+#define SPI_CLOCK_DIV4 4166667 //(SCR: 5) desired: 4,000,000 actual: 4,166,667 +4.2% SPI_HALF_SPEED
+#define SPI_CLOCK_DIV8 2083333 //(SCR: 11) desired: 2,000,000 actual: 2,083,333 +4.2% SPI_QUARTER_SPEED
+#define SPI_CLOCK_DIV16 1000000 //(SCR: 24) desired: 1,000,000 actual: 1,000,000 SPI_EIGHTH_SPEED
+#define SPI_CLOCK_DIV32 500000 //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
+#define SPI_CLOCK_DIV64 250000 //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
+#define SPI_CLOCK_DIV128 125000 //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
@@ -125,6 +126,11 @@ public:
*/
SPIClass(uint8_t spiPortNumber);
+ /**
+ * Init using pins
+ */
+ SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel = (pin_t)-1);
+
/**
* Select and configure the current selected SPI device to use
*/
diff --git a/Marlin/src/HAL/LPC1768/main.cpp b/Marlin/src/HAL/LPC1768/main.cpp
index 0b4045cb9..08fb1a1ed 100644
--- a/Marlin/src/HAL/LPC1768/main.cpp
+++ b/Marlin/src/HAL/LPC1768/main.cpp
@@ -31,20 +31,23 @@
#include
#include
-extern "C" {
- #include
-}
-
-#include "../../sd/cardreader.h"
#include "../../inc/MarlinConfig.h"
#include "../../core/millis_t.h"
+#include "../../sd/cardreader.h"
+
extern uint32_t MSC_SD_Init(uint8_t pdrv);
-extern "C" int isLPC1769();
-extern "C" void disk_timerproc();
+
+extern "C" {
+ #include
+ extern "C" int isLPC1769();
+ extern "C" void disk_timerproc();
+}
void SysTick_Callback() { disk_timerproc(); }
+TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
+
void HAL_init() {
// Init LEDs
@@ -89,11 +92,11 @@ void HAL_init() {
//debug_frmwrk_init();
//_DBG("\n\nDebug running\n");
// Initialize the SD card chip select pins as soon as possible
- #if PIN_EXISTS(SS)
- OUT_WRITE(SS_PIN, HIGH);
+ #if PIN_EXISTS(SD_SS)
+ OUT_WRITE(SD_SS_PIN, HIGH);
#endif
- #if PIN_EXISTS(ONBOARD_SD_CS) && ONBOARD_SD_CS_PIN != SS_PIN
+ #if PIN_EXISTS(ONBOARD_SD_CS) && ONBOARD_SD_CS_PIN != SD_SS_PIN
OUT_WRITE(ONBOARD_SD_CS_PIN, HIGH);
#endif
@@ -118,13 +121,11 @@ void HAL_init() {
#endif
USB_Init(); // USB Initialization
- USB_Connect(FALSE); // USB clear connection
+ USB_Connect(false); // USB clear connection
delay(1000); // Give OS time to notice
- USB_Connect(TRUE);
+ USB_Connect(true);
- #if DISABLED(NO_SD_HOST_DRIVE)
- MSC_SD_Init(0); // Enable USB SD card access
- #endif
+ TERN_(HAS_SD_HOST_DRIVE, MSC_SD_Init(0)); // Enable USB SD card access
const millis_t usb_timeout = millis() + 2000;
while (!USB_Configuration && PENDING(millis(), usb_timeout)) {
@@ -136,6 +137,8 @@ void HAL_init() {
}
HAL_timer_init();
+
+ TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
}
// HAL idle task
diff --git a/Marlin/src/HAL/LPC1768/spi_pins.h b/Marlin/src/HAL/LPC1768/spi_pins.h
index b4da5d4df..e7d774742 100644
--- a/Marlin/src/HAL/LPC1768/spi_pins.h
+++ b/Marlin/src/HAL/LPC1768/spi_pins.h
@@ -23,7 +23,7 @@
#include "../../core/macros.h"
-#if BOTH(SDSUPPORT, HAS_MARLINUI_U8GLIB) && (LCD_PINS_D4 == SCK_PIN || LCD_PINS_ENABLE == MOSI_PIN || DOGLCD_SCK == SCK_PIN || DOGLCD_MOSI == MOSI_PIN)
+#if BOTH(SDSUPPORT, HAS_MARLINUI_U8GLIB) && (LCD_PINS_D4 == SD_SCK_PIN || LCD_PINS_ENABLE == SD_MOSI_PIN || DOGLCD_SCK == SD_SCK_PIN || DOGLCD_MOSI == SD_MOSI_PIN)
#define LPC_SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently
// needed due to the speed and mode required for communicating with each device being different.
// This requirement can be removed if the SPI access to these devices is updated to use
@@ -31,24 +31,24 @@
#endif
/** onboard SD card */
-//#define SCK_PIN P0_07
-//#define MISO_PIN P0_08
-//#define MOSI_PIN P0_09
-//#define SS_PIN P0_06
+//#define SD_SCK_PIN P0_07
+//#define SD_MISO_PIN P0_08
+//#define SD_MOSI_PIN P0_09
+//#define SD_SS_PIN P0_06
/** external */
-#ifndef SCK_PIN
- #define SCK_PIN P0_15
+#ifndef SD_SCK_PIN
+ #define SD_SCK_PIN P0_15
#endif
-#ifndef MISO_PIN
- #define MISO_PIN P0_17
+#ifndef SD_MISO_PIN
+ #define SD_MISO_PIN P0_17
#endif
-#ifndef MOSI_PIN
- #define MOSI_PIN P0_18
+#ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN P0_18
#endif
-#ifndef SS_PIN
- #define SS_PIN P1_23
+#ifndef SD_SS_PIN
+ #define SD_SS_PIN P1_23
#endif
#if !defined(SDSS) || SDSS == P_NC // gets defaulted in pins.h
#undef SDSS
- #define SDSS SS_PIN
+ #define SDSS SD_SS_PIN
#endif
diff --git a/Marlin/src/HAL/LPC1768/tft/tft_spi.cpp b/Marlin/src/HAL/LPC1768/tft/tft_spi.cpp
index 84907acd0..a2cb66ab5 100644
--- a/Marlin/src/HAL/LPC1768/tft/tft_spi.cpp
+++ b/Marlin/src/HAL/LPC1768/tft/tft_spi.cpp
@@ -89,7 +89,7 @@ void TFT_SPI::Init() {
#elif TFT_MISO_PIN == BOARD_SPI2_MISO_PIN
SPIx.setModule(2);
#endif
- SPIx.setClock(SPI_CLOCK_MAX);
+ SPIx.setClock(SPI_CLOCK_MAX_TFT);
SPIx.setBitOrder(MSBFIRST);
SPIx.setDataMode(SPI_MODE0);
}
@@ -125,7 +125,7 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
}
DataTransferEnd();
- SPIx.setClock(SPI_CLOCK_MAX);
+ SPIx.setClock(SPI_CLOCK_MAX_TFT);
#endif
return data >> 7;
diff --git a/Marlin/src/HAL/LPC1768/tft/xpt2046.cpp b/Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
index 5f9663004..cf1440548 100644
--- a/Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
+++ b/Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
@@ -1,6 +1,9 @@
/**
* Marlin 3D Printer Firmware
- * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,7 +22,7 @@
#include "../../../inc/MarlinConfig.h"
-#if HAS_TFT_XPT2046 || HAS_TOUCH_XPT2046
+#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
#include "xpt2046.h"
#include
diff --git a/Marlin/src/HAL/LPC1768/tft/xpt2046.h b/Marlin/src/HAL/LPC1768/tft/xpt2046.h
index 019f75efc..65602bda0 100644
--- a/Marlin/src/HAL/LPC1768/tft/xpt2046.h
+++ b/Marlin/src/HAL/LPC1768/tft/xpt2046.h
@@ -1,6 +1,9 @@
/**
* Marlin 3D Printer Firmware
- * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,16 +28,16 @@
#endif
#ifndef TOUCH_MISO_PIN
- #define TOUCH_MISO_PIN MISO_PIN
+ #define TOUCH_MISO_PIN SD_MISO_PIN
#endif
#ifndef TOUCH_MOSI_PIN
- #define TOUCH_MOSI_PIN MOSI_PIN
+ #define TOUCH_MOSI_PIN SD_MOSI_PIN
#endif
#ifndef TOUCH_SCK_PIN
- #define TOUCH_SCK_PIN SCK_PIN
+ #define TOUCH_SCK_PIN SD_SCK_PIN
#endif
#ifndef TOUCH_CS_PIN
- #define TOUCH_CS_PIN CS_PIN
+ #define TOUCH_CS_PIN SD_SS_PIN
#endif
#ifndef TOUCH_INT_PIN
#define TOUCH_INT_PIN -1
diff --git a/Marlin/src/HAL/LPC1768/timers.h b/Marlin/src/HAL/LPC1768/timers.h
index e6744fb00..4b6385468 100644
--- a/Marlin/src/HAL/LPC1768/timers.h
+++ b/Marlin/src/HAL/LPC1768/timers.h
@@ -152,7 +152,7 @@ FORCE_INLINE static void HAL_timer_disable_interrupt(const uint8_t timer_num) {
// This function is missing from CMSIS
FORCE_INLINE static bool NVIC_GetEnableIRQ(IRQn_Type IRQn) {
- return (NVIC->ISER[((uint32_t)IRQn) >> 5] & (1 << ((uint32_t)IRQn) & 0x1F)) != 0;
+ return TEST(NVIC->ISER[uint32_t(IRQn) >> 5], uint32_t(IRQn) & 0x1F);
}
FORCE_INLINE static bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
index 057e10e0f..b1eea13d5 100644
--- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
@@ -62,10 +62,13 @@
#include
#include "../../shared/HAL_SPI.h"
-void spiBegin();
-void spiInit(uint8_t spiRate);
-void spiSend(uint8_t b);
-void spiSend(const uint8_t* buf, size_t n);
+#ifndef LCD_SPI_SPEED
+ #ifdef SD_SPI_SPEED
+ #define LCD_SPI_SPEED SD_SPI_SPEED // Assume SPI speed shared with SD
+ #else
+ #define LCD_SPI_SPEED SPI_FULL_SPEED // Use full speed if SD speed is not supplied
+ #endif
+#endif
uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch (msg) {
@@ -81,10 +84,7 @@ uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val,
u8g_SetPIOutput(u8g, U8G_PI_RESET);
u8g_Delay(5);
spiBegin();
- #ifndef SPI_SPEED
- #define SPI_SPEED SPI_FULL_SPEED // use same SPI speed as SD card
- #endif
- spiInit(SPI_SPEED);
+ spiInit(LCD_SPI_SPEED);
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
index 592e27f6c..0b0626de7 100644
--- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
@@ -66,7 +66,7 @@
void spiBegin();
void spiInit(uint8_t spiRate);
void spiSend(uint8_t b);
-void spiSend(const uint8_t* buf, size_t n);
+void spiSend(const uint8_t *buf, size_t n);
static uint8_t rs_last_state = 255;
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
index 10d849416..61211d9d8 100644
--- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
@@ -62,9 +62,11 @@
#include
#include
#include "../../shared/Delay.h"
+#include "../../shared/HAL_SPI.h"
-#undef SPI_SPEED
-#define SPI_SPEED 3 // About 1 MHz
+#ifndef LCD_SPI_SPEED
+ #define LCD_SPI_SPEED SPI_EIGHTH_SPEED // About 1 MHz
+#endif
static pin_t SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL;
static uint8_t SPI_speed = 0;
@@ -92,7 +94,7 @@ uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t ar
u8g_SetPIOutput(u8g, U8G_PI_MOSI);
u8g_Delay(5);
- SPI_speed = swSpiInit(SPI_SPEED, SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL);
+ SPI_speed = swSpiInit(LCD_SPI_SPEED, SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL);
u8g_SetPILevel(u8g, U8G_PI_CS, 0);
u8g_SetPILevel(u8g, U8G_PI_SCK, 0);
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
index ca9d6ecfb..7f38ec54a 100644
--- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
@@ -60,9 +60,11 @@
#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920)
#include
+#include "../../shared/HAL_SPI.h"
-#undef SPI_SPEED
-#define SPI_SPEED 2 // About 2 MHz
+#ifndef LCD_SPI_SPEED
+ #define LCD_SPI_SPEED SPI_QUARTER_SPEED // About 2 MHz
+#endif
#include
#include
@@ -145,7 +147,7 @@ uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val,
u8g_SetPIOutput(u8g, U8G_PI_CS);
u8g_SetPIOutput(u8g, U8G_PI_A0);
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPIOutput(u8g, U8G_PI_RESET);
- SPI_speed = swSpiInit(SPI_SPEED, u8g->pin_list[U8G_PI_SCK], u8g->pin_list[U8G_PI_MOSI]);
+ SPI_speed = swSpiInit(LCD_SPI_SPEED, u8g->pin_list[U8G_PI_SCK], u8g->pin_list[U8G_PI_MOSI]);
u8g_SetPILevel(u8g, U8G_PI_SCK, 0);
u8g_SetPILevel(u8g, U8G_PI_MOSI, 0);
break;
diff --git a/Marlin/src/HAL/LPC1768/upload_extra_script.py b/Marlin/src/HAL/LPC1768/upload_extra_script.py
index 9b0d0617a..5967a9970 100755
--- a/Marlin/src/HAL/LPC1768/upload_extra_script.py
+++ b/Marlin/src/HAL/LPC1768/upload_extra_script.py
@@ -8,9 +8,7 @@ from __future__ import print_function
target_filename = "FIRMWARE.CUR"
target_drive = "REARM"
-import os
-import getpass
-import platform
+import os,getpass,platform
current_OS = platform.system()
Import("env")
@@ -23,63 +21,49 @@ def print_error(e):
%(e, env.get('PIOENV')))
try:
+ #
+ # Find a disk for upload
+ #
+ upload_disk = 'Disk not found'
+ target_file_found = False
+ target_drive_found = False
if current_OS == 'Windows':
#
# platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:'
# Windows - doesn't care about the disk's name, only cares about the drive letter
- #
+ import subprocess,string
+ from ctypes import windll
- #
- # get all drives on this computer
- #
- import subprocess
- # typical result (string): 'Drives: C:\ D:\ E:\ F:\ G:\ H:\ I:\ J:\ K:\ L:\ M:\ Y:\ Z:\'
- driveStr = str(subprocess.check_output("fsutil fsinfo drives"))
- # typical result (string): 'C:\ D:\ E:\ F:\ G:\ H:\ I:\ J:\ K:\ L:\ M:\ Y:\ Z:\'
- # driveStr = driveStr.strip().lstrip('Drives: ') <- Doesn't work in other Languages as English. In German is "Drives:" = "Laufwerke:"
- FirstFound = driveStr.find(':',0,-1) # Find the first ":" and
- driveStr = driveStr[FirstFound + 1 : -1] # truncate to the rest
- # typical result (array of stings): ['C:\\', 'D:\\', 'E:\\', 'F:\\',
- # 'G:\\', 'H:\\', 'I:\\', 'J:\\', 'K:\\', 'L:\\', 'M:\\', 'Y:\\', 'Z:\\']
- drives = driveStr.split()
+ # getting list of drives
+ # https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
+ drives = []
+ bitmask = windll.kernel32.GetLogicalDrives()
+ for letter in string.ascii_uppercase:
+ if bitmask & 1:
+ drives.append(letter)
+ bitmask >>= 1
- upload_disk = 'Disk not found'
- target_file_found = False
- target_drive_found = False
for drive in drives:
- final_drive_name = drive.strip().rstrip('\\') # typical result (string): 'C:'
+ final_drive_name = drive + ':\\'
+ # print ('disc check: {}'.format(final_drive_name))
try:
volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
except Exception as e:
+ print ('error:{}'.format(e))
continue
else:
- if target_drive in volume_info and target_file_found == False: # set upload if not found target file yet
+ if target_drive in volume_info and not target_file_found: # set upload if not found target file yet
target_drive_found = True
upload_disk = final_drive_name
if target_filename in volume_info:
- if target_file_found == False:
+ if not target_file_found:
upload_disk = final_drive_name
target_file_found = True
- #
- # set upload_port to drive if found
- #
-
- if target_file_found == True or target_drive_found == True:
- env.Replace(
- UPLOAD_PORT=upload_disk
- )
- print('upload disk: ', upload_disk)
- else:
- print_error('Autodetect Error')
-
elif current_OS == 'Linux':
#
# platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive'
#
- upload_disk = 'Disk not found'
- target_file_found = False
- target_drive_found = False
drives = os.listdir(os.path.join(os.sep, 'media', getpass.getuser()))
if target_drive in drives: # If target drive is found, use it.
target_drive_found = True
@@ -101,22 +85,15 @@ try:
if target_file_found or target_drive_found:
env.Replace(
- UPLOAD_FLAGS="-P$UPLOAD_PORT",
- UPLOAD_PORT=upload_disk
+ UPLOAD_FLAGS="-P$UPLOAD_PORT"
)
- print('upload disk: ', upload_disk)
- else:
- print_error('Autodetect Error')
elif current_OS == 'Darwin': # MAC
#
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
#
- upload_disk = 'Disk not found'
drives = os.listdir('/Volumes') # human readable names
- target_file_found = False
- target_drive_found = False
- if target_drive in drives and target_file_found == False: # set upload if not found target file yet
+ if target_drive in drives and not target_file_found: # set upload if not found target file yet
target_drive_found = True
upload_disk = '/Volumes/' + target_drive + '/'
for drive in drives:
@@ -126,20 +103,18 @@ try:
continue
else:
if target_filename in filenames:
- if target_file_found == False:
+ if not target_file_found:
upload_disk = '/Volumes/' + drive + '/'
target_file_found = True
- #
- # set upload_port to drive if found
- #
- if target_file_found == True or target_drive_found == True:
- env.Replace(
- UPLOAD_PORT=upload_disk
- )
- print('\nupload disk: ', upload_disk, '\n')
- else:
- print_error('Autodetect Error')
+ #
+ # Set upload_port to drive if found
+ #
+ if target_file_found or target_drive_found:
+ env.Replace(UPLOAD_PORT=upload_disk)
+ print('\nUpload disk: ', upload_disk, '\n')
+ else:
+ print_error('Autodetect Error')
except Exception as e:
print_error(str(e))
diff --git a/Marlin/src/HAL/LPC1768/usb_serial.cpp b/Marlin/src/HAL/LPC1768/usb_serial.cpp
index d225ce418..3c1fce54f 100644
--- a/Marlin/src/HAL/LPC1768/usb_serial.cpp
+++ b/Marlin/src/HAL/LPC1768/usb_serial.cpp
@@ -29,8 +29,8 @@
EmergencyParser::State emergency_state;
-bool CDC_RecvCallback(const char buffer) {
- emergency_parser.update(emergency_state, buffer);
+bool CDC_RecvCallback(const char c) {
+ emergency_parser.update(emergency_state, c);
return true;
}
diff --git a/Marlin/src/HAL/LPC1768/watchdog.cpp b/Marlin/src/HAL/LPC1768/watchdog.cpp
index 3cd22d665..f23ccf5b5 100644
--- a/Marlin/src/HAL/LPC1768/watchdog.cpp
+++ b/Marlin/src/HAL/LPC1768/watchdog.cpp
@@ -28,6 +28,8 @@
#include
#include "watchdog.h"
+#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
+
void watchdog_init() {
#if ENABLED(WATCHDOG_RESET_MANUAL)
// We enable the watchdog timer, but only for the interrupt.
@@ -52,7 +54,7 @@ void watchdog_init() {
#else
WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_RESET);
#endif
- WDT_Start(WDT_TIMEOUT);
+ WDT_Start(WDT_TIMEOUT_US);
}
void HAL_watchdog_refresh() {
diff --git a/Marlin/src/HAL/LPC1768/watchdog.h b/Marlin/src/HAL/LPC1768/watchdog.h
index cc170881f..c843f0ed5 100644
--- a/Marlin/src/HAL/LPC1768/watchdog.h
+++ b/Marlin/src/HAL/LPC1768/watchdog.h
@@ -21,8 +21,6 @@
*/
#pragma once
-#define WDT_TIMEOUT 4000000 // 4 second timeout
-
void watchdog_init();
void HAL_watchdog_refresh();
diff --git a/Marlin/src/HAL/SAMD51/HAL.cpp b/Marlin/src/HAL/SAMD51/HAL.cpp
index 9f24d3007..5aa23cdae 100644
--- a/Marlin/src/HAL/SAMD51/HAL.cpp
+++ b/Marlin/src/HAL/SAMD51/HAL.cpp
@@ -24,6 +24,24 @@
#include
#include
+#ifdef ADAFRUIT_GRAND_CENTRAL_M4
+ #if USING_HW_SERIALUSB
+ DefaultSerial1 MSerial0(false, Serial);
+ #endif
+ #if USING_HW_SERIAL0
+ DefaultSerial2 MSerial1(false, Serial1);
+ #endif
+ #if USING_HW_SERIAL1
+ DefaultSerial3 MSerial2(false, Serial2);
+ #endif
+ #if USING_HW_SERIAL2
+ DefaultSerial4 MSerial3(false, Serial3);
+ #endif
+ #if USING_HW_SERIAL3
+ DefaultSerial5 MSerial4(false, Serial4);
+ #endif
+#endif
+
// ------------------------
// Local defines
// ------------------------
@@ -39,6 +57,7 @@
#define GET_PROBE_ADC() TERN(HAS_TEMP_PROBE, PIN_TO_ADC(TEMP_PROBE_PIN), -1)
#define GET_BED_ADC() TERN(HAS_TEMP_ADC_BED, PIN_TO_ADC(TEMP_BED_PIN), -1)
#define GET_CHAMBER_ADC() TERN(HAS_TEMP_ADC_CHAMBER, PIN_TO_ADC(TEMP_CHAMBER_PIN), -1)
+#define GET_COOLER_ADC() TERN(HAS_TEMP_ADC_COOLER, PIN_TO_ADC(TEMP_COOLER_PIN), -1)
#define GET_FILAMENT_WIDTH_ADC() TERN(FILAMENT_WIDTH_SENSOR, PIN_TO_ADC(FILWIDTH_PIN), -1)
#define GET_BUTTONS_ADC() TERN(HAS_ADC_BUTTONS, PIN_TO_ADC(ADC_KEYPAD_PIN), -1)
@@ -48,6 +67,7 @@
|| GET_PROBE_ADC() == n \
|| GET_BED_ADC() == n \
|| GET_CHAMBER_ADC() == n \
+ || GET_COOLER_ADC() == n \
|| GET_FILAMENT_WIDTH_ADC() == n \
|| GET_BUTTONS_ADC() == n \
)
@@ -126,6 +146,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 0
TEMP_CHAMBER_PIN,
#endif
+ #if GET_COOLER_ADC() == 0
+ TEMP_COOLER_PIN,
+ #endif
#if GET_FILAMENT_WIDTH_ADC() == 0
FILWIDTH_PIN,
#endif
@@ -166,6 +189,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 1
TEMP_CHAMBER_PIN,
#endif
+ #if GET_COOLER_ADC() == 1
+ TEMP_COOLER_PIN,
+ #endif
#if GET_FILAMENT_WIDTH_ADC() == 1
FILWIDTH_PIN,
#endif
@@ -214,6 +240,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
+ #if GET_COOLER_ADC() == 0
+ { PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
+ #endif
#if GET_FILAMENT_WIDTH_ADC() == 0
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif
@@ -263,6 +292,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
+ #if GET_COOLER_ADC() == 1
+ { PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
+ #endif
#if GET_FILAMENT_WIDTH_ADC() == 1
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif
@@ -300,7 +332,7 @@ uint16_t HAL_adc_result;
DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
DMA_STEPSEL_SRC // STEPSEL
);
- if (descriptor != nullptr)
+ if (descriptor)
descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
adc0DMAProgram.startJob();
}
@@ -337,7 +369,7 @@ uint16_t HAL_adc_result;
DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
DMA_STEPSEL_SRC // STEPSEL
);
- if (descriptor != nullptr)
+ if (descriptor)
descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
adc1DMAProgram.startJob();
}
@@ -404,6 +436,8 @@ uint8_t HAL_get_reset_source() {
}
#pragma pop_macro("WDT")
+void HAL_reboot() { NVIC_SystemReset(); }
+
extern "C" {
void * _sbrk(int incr);
diff --git a/Marlin/src/HAL/SAMD51/HAL.h b/Marlin/src/HAL/SAMD51/HAL.h
index 7cb3635bd..85ac5dd00 100644
--- a/Marlin/src/HAL/SAMD51/HAL.h
+++ b/Marlin/src/HAL/SAMD51/HAL.h
@@ -32,38 +32,58 @@
#include "MarlinSerial_AGCM4.h"
// Serial ports
+ typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
+ typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
+ typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
+ typedef ForwardSerial1Class< decltype(Serial3) > DefaultSerial4;
+ typedef ForwardSerial1Class< decltype(Serial4) > DefaultSerial5;
+ extern DefaultSerial1 MSerial0;
+ extern DefaultSerial2 MSerial1;
+ extern DefaultSerial3 MSerial2;
+ extern DefaultSerial4 MSerial3;
+ extern DefaultSerial5 MSerial4;
- // MYSERIAL0 required before MarlinSerial includes!
+ // MYSERIAL1 required before MarlinSerial includes!
- #define __MSERIAL(X) Serial##X
+ #define __MSERIAL(X) MSerial##X
#define _MSERIAL(X) __MSERIAL(X)
#define MSERIAL(X) _MSERIAL(INCREMENT(X))
#if SERIAL_PORT == -1
- #define MYSERIAL0 Serial
+ #define MYSERIAL1 MSerial0
#elif WITHIN(SERIAL_PORT, 0, 3)
- #define MYSERIAL0 MSERIAL(SERIAL_PORT)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
- #error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
- #define MYSERIAL1 Serial
+ #define MYSERIAL2 MSerial0
#elif WITHIN(SERIAL_PORT_2, 0, 3)
- #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
+ #define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
- #error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+ #endif
+
+ #ifdef MMU2_SERIAL_PORT
+ #if MMU2_SERIAL_PORT == -1
+ #define MMU2_SERIAL MSerial0
+ #elif WITHIN(MMU2_SERIAL_PORT, 0, 3)
+ #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
+ #else
+ #error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if LCD_SERIAL_PORT == -1
- #define LCD_SERIAL Serial
+ #define LCD_SERIAL MSerial0
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
@@ -89,7 +109,7 @@ typedef int8_t pin_t;
void HAL_clear_reset_source(); // clear reset reason
uint8_t HAL_get_reset_source(); // get reset reason
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+void HAL_reboot();
//
// ADC
@@ -135,10 +155,16 @@ void HAL_idletask();
//
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
int freeMemory();
-#pragma GCC diagnostic pop
+
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic pop
+#endif
#ifdef __cplusplus
extern "C" {
diff --git a/Marlin/src/HAL/SAMD51/HAL_SPI.cpp b/Marlin/src/HAL/SAMD51/HAL_SPI.cpp
index c3acd3823..77f4d5ecd 100644
--- a/Marlin/src/HAL/SAMD51/HAL_SPI.cpp
+++ b/Marlin/src/HAL/SAMD51/HAL_SPI.cpp
@@ -103,7 +103,7 @@
* @param nbyte Number of bytes to receive.
* @return Nothing
*/
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
if (nbyte == 0) return;
memset(buf, 0xFF, nbyte);
sdSPI.beginTransaction(spiConfig);
@@ -132,7 +132,7 @@
*
* @details Uses DMA
*/
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
sdSPI.beginTransaction(spiConfig);
sdSPI.transfer(token);
sdSPI.transfer((uint8_t*)buf, nullptr, 512);
diff --git a/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.cpp b/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.cpp
index abc5f3acb..a16ea2f75 100644
--- a/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.cpp
+++ b/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.cpp
@@ -21,30 +21,30 @@
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
/**
- * Framework doesn't define some serial to save sercom resources
+ * Framework doesn't define some serials to save sercom resources
* hence if these are used I need to define them
*/
#include "../../inc/MarlinConfig.h"
-#if SERIAL_PORT == 1 || SERIAL_PORT_2 == 1
- Uart Serial2(&sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX);
+#if USING_HW_SERIAL1
+ UartT Serial2(false, &sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX);
void SERCOM4_0_Handler() { Serial2.IrqHandler(); }
void SERCOM4_1_Handler() { Serial2.IrqHandler(); }
void SERCOM4_2_Handler() { Serial2.IrqHandler(); }
void SERCOM4_3_Handler() { Serial2.IrqHandler(); }
#endif
-#if SERIAL_PORT == 2 || SERIAL_PORT_2 == 2
- Uart Serial3(&sercom1, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX, PAD_SERIAL3_TX);
+#if USING_HW_SERIAL2
+ UartT Serial3(false, &sercom1, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX, PAD_SERIAL3_TX);
void SERCOM1_0_Handler() { Serial3.IrqHandler(); }
void SERCOM1_1_Handler() { Serial3.IrqHandler(); }
void SERCOM1_2_Handler() { Serial3.IrqHandler(); }
void SERCOM1_3_Handler() { Serial3.IrqHandler(); }
#endif
-#if SERIAL_PORT == 3 || SERIAL_PORT_2 == 3
- Uart Serial4(&sercom5, PIN_SERIAL4_RX, PIN_SERIAL4_TX, PAD_SERIAL4_RX, PAD_SERIAL4_TX);
+#if USING_HW_SERIAL3
+ UartT Serial4(false, &sercom5, PIN_SERIAL4_RX, PIN_SERIAL4_TX, PAD_SERIAL4_RX, PAD_SERIAL4_TX);
void SERCOM5_0_Handler() { Serial4.IrqHandler(); }
void SERCOM5_1_Handler() { Serial4.IrqHandler(); }
void SERCOM5_2_Handler() { Serial4.IrqHandler(); }
diff --git a/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.h b/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.h
index f3821d8d5..ac5a37939 100644
--- a/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.h
+++ b/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.h
@@ -20,6 +20,10 @@
*/
#pragma once
-extern Uart Serial2;
-extern Uart Serial3;
-extern Uart Serial4;
+#include "../../core/serial_hook.h"
+
+typedef Serial1Class UartT;
+
+extern UartT Serial2;
+extern UartT Serial3;
+extern UartT Serial4;
diff --git a/Marlin/src/HAL/SAMD51/QSPIFlash.cpp b/Marlin/src/HAL/SAMD51/QSPIFlash.cpp
index 307eb3fd4..fc21a1ad8 100644
--- a/Marlin/src/HAL/SAMD51/QSPIFlash.cpp
+++ b/Marlin/src/HAL/SAMD51/QSPIFlash.cpp
@@ -35,10 +35,10 @@ uint8_t QSPIFlash::_buf[SFLASH_SECTOR_SIZE];
uint32_t QSPIFlash::_addr = INVALID_ADDR;
void QSPIFlash::begin() {
- if (_flashBase != nullptr) return;
+ if (_flashBase) return;
_flashBase = new Adafruit_SPIFlashBase(new Adafruit_FlashTransport_QSPI());
- _flashBase->begin(NULL);
+ _flashBase->begin(nullptr);
}
size_t QSPIFlash::size() {
diff --git a/Marlin/src/HAL/SAMD51/eeprom_flash.cpp b/Marlin/src/HAL/SAMD51/eeprom_flash.cpp
index 429ef1c2d..871bf22b7 100644
--- a/Marlin/src/HAL/SAMD51/eeprom_flash.cpp
+++ b/Marlin/src/HAL/SAMD51/eeprom_flash.cpp
@@ -79,7 +79,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
while (size--) {
SYNC(NVMCTRL->SEESTAT.bit.BUSY);
uint8_t c = ((volatile uint8_t *)SEEPROM_ADDR)[pos];
diff --git a/Marlin/src/HAL/SAMD51/eeprom_qspi.cpp b/Marlin/src/HAL/SAMD51/eeprom_qspi.cpp
index b403f7939..faa763719 100644
--- a/Marlin/src/HAL/SAMD51/eeprom_qspi.cpp
+++ b/Marlin/src/HAL/SAMD51/eeprom_qspi.cpp
@@ -56,7 +56,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
while (size--) {
uint8_t c = qspi.readByte(pos);
if (writing) *value = c;
diff --git a/Marlin/src/HAL/SAMD51/eeprom_wired.cpp b/Marlin/src/HAL/SAMD51/eeprom_wired.cpp
index 328319589..3481fe539 100644
--- a/Marlin/src/HAL/SAMD51/eeprom_wired.cpp
+++ b/Marlin/src/HAL/SAMD51/eeprom_wired.cpp
@@ -41,12 +41,13 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
const uint8_t v = *value;
uint8_t * const p = (uint8_t * const)pos;
- if (v != eeprom_read_byte(p)) {
+ if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
- delay(2);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -59,7 +60,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
while (size--) {
uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c;
diff --git a/Marlin/src/HAL/SAMD51/fastio.h b/Marlin/src/HAL/SAMD51/fastio.h
index c456dfce3..a95b7cac0 100644
--- a/Marlin/src/HAL/SAMD51/fastio.h
+++ b/Marlin/src/HAL/SAMD51/fastio.h
@@ -31,7 +31,7 @@
*/
#ifndef MASK
- #define MASK(PIN) (1 << PIN)
+ #define MASK(PIN) _BV(PIN)
#endif
/**
diff --git a/Marlin/src/HAL/SAMD51/inc/SanityCheck.h b/Marlin/src/HAL/SAMD51/inc/SanityCheck.h
index 5d610acac..2a4bde98e 100644
--- a/Marlin/src/HAL/SAMD51/inc/SanityCheck.h
+++ b/Marlin/src/HAL/SAMD51/inc/SanityCheck.h
@@ -50,3 +50,7 @@
#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on SAMD51."
#endif
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+ #error "POSTMORTEM_DEBUGGING is not yet supported on AGCM4."
+#endif
diff --git a/Marlin/src/HAL/SAMD51/spi_pins.h b/Marlin/src/HAL/SAMD51/spi_pins.h
index 5a9b1275e..2a667bcaa 100644
--- a/Marlin/src/HAL/SAMD51/spi_pins.h
+++ b/Marlin/src/HAL/SAMD51/spi_pins.h
@@ -30,16 +30,16 @@
* SPI | 53 52 50 51 |
* SPI1 | 83 81 80 82 |
* +-------------------------+
- * Any pin can be used for Chip Select (SS_PIN)
+ * Any pin can be used for Chip Select (SD_SS_PIN)
*/
- #ifndef SCK_PIN
- #define SCK_PIN 52
+ #ifndef SD_SCK_PIN
+ #define SD_SCK_PIN 52
#endif
- #ifndef MISO_PIN
- #define MISO_PIN 50
+ #ifndef SD_MISO_PIN
+ #define SD_MISO_PIN 50
#endif
- #ifndef MOSI_PIN
- #define MOSI_PIN 51
+ #ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN 51
#endif
#ifndef SDSS
#define SDSS 53
@@ -51,4 +51,4 @@
#endif
-#define SS_PIN SDSS
+#define SD_SS_PIN SDSS
diff --git a/Marlin/src/HAL/SAMD51/timers.cpp b/Marlin/src/HAL/SAMD51/timers.cpp
index a68af2e07..5c55d3240 100644
--- a/Marlin/src/HAL/SAMD51/timers.cpp
+++ b/Marlin/src/HAL/SAMD51/timers.cpp
@@ -157,7 +157,7 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num) {
// missing from CMSIS: Check if interrupt is enabled or not
static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
- return (NVIC->ISER[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) != 0;
+ return TEST(NVIC->ISER[uint32_t(IRQn) >> 5], uint32_t(IRQn) & 0x1F);
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
diff --git a/Marlin/src/HAL/SAMD51/watchdog.cpp b/Marlin/src/HAL/SAMD51/watchdog.cpp
index ebc8dffe1..9de451836 100644
--- a/Marlin/src/HAL/SAMD51/watchdog.cpp
+++ b/Marlin/src/HAL/SAMD51/watchdog.cpp
@@ -24,28 +24,30 @@
#if ENABLED(USE_WATCHDOG)
- #include "watchdog.h"
+#include "watchdog.h"
- void watchdog_init() {
- // The low-power oscillator used by the WDT runs at 32,768 Hz with
- // a 1:32 prescale, thus 1024 Hz, though probably not super precise.
+#define WDT_TIMEOUT_REG TERN(WATCHDOG_DURATION_8S, WDT_CONFIG_PER_CYC8192, WDT_CONFIG_PER_CYC4096) // 4 or 8 second timeout
- // Setup WDT clocks
- MCLK->APBAMASK.bit.OSC32KCTRL_ = true;
- MCLK->APBAMASK.bit.WDT_ = true;
- OSC32KCTRL->OSCULP32K.bit.EN1K = true; // Enable out 1K (this is what WDT uses)
+void watchdog_init() {
+ // The low-power oscillator used by the WDT runs at 32,768 Hz with
+ // a 1:32 prescale, thus 1024 Hz, though probably not super precise.
- WDT->CTRLA.bit.ENABLE = false; // Disable watchdog for config
- SYNC(WDT->SYNCBUSY.bit.ENABLE);
+ // Setup WDT clocks
+ MCLK->APBAMASK.bit.OSC32KCTRL_ = true;
+ MCLK->APBAMASK.bit.WDT_ = true;
+ OSC32KCTRL->OSCULP32K.bit.EN1K = true; // Enable out 1K (this is what WDT uses)
- WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt
- WDT->CONFIG.reg = WDT_CONFIG_PER_CYC4096; // Set at least 4s period for chip reset
+ WDT->CTRLA.bit.ENABLE = false; // Disable watchdog for config
+ SYNC(WDT->SYNCBUSY.bit.ENABLE);
- HAL_watchdog_refresh();
+ WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt
+ WDT->CONFIG.reg = WDT_TIMEOUT_REG; // Set a 4s or 8s period for chip reset
- WDT->CTRLA.reg = WDT_CTRLA_ENABLE; // Start watchdog now in normal mode
- SYNC(WDT->SYNCBUSY.bit.ENABLE);
- }
+ HAL_watchdog_refresh();
+
+ WDT->CTRLA.reg = WDT_CTRLA_ENABLE; // Start watchdog now in normal mode
+ SYNC(WDT->SYNCBUSY.bit.ENABLE);
+}
#endif // USE_WATCHDOG
diff --git a/Marlin/src/HAL/STM32/HAL.cpp b/Marlin/src/HAL/STM32/HAL.cpp
index 83604b110..3bb12fd9e 100644
--- a/Marlin/src/HAL/STM32/HAL.cpp
+++ b/Marlin/src/HAL/STM32/HAL.cpp
@@ -28,6 +28,10 @@
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
+#ifdef USBCON
+ DefaultSerial1 MSerial0(false, SerialUSB);
+#endif
+
#if ENABLED(SRAM_EEPROM_EMULATION)
#if STM32F7xx
#include
@@ -38,6 +42,11 @@
#endif
#endif
+#if HAS_SD_HOST_DRIVE
+ #include "msc_sd.h"
+ #include "usbd_cdc_if.h"
+#endif
+
// ------------------------
// Public Variables
// ------------------------
@@ -48,21 +57,18 @@ uint16_t HAL_adc_result;
// Public functions
// ------------------------
-// Needed for DELAY_NS() / DELAY_US() on CORTEX-M7
-#if (defined(__arm__) || defined(__thumb__)) && __CORTEX_M == 7
- // HAL pre-initialization task
- // Force the preinit function to run between the premain() and main() function
- // of the STM32 arduino core
- __attribute__((constructor (102)))
- void HAL_preinit() {
- enableCycleCounter();
- }
-#endif
+TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
// HAL initialization task
void HAL_init() {
FastIO_init();
+ // Ensure F_CPU is a constant expression.
+ // If the compiler breaks here, it means that delay code that should compute at compile time will not work.
+ // So better safe than sorry here.
+ constexpr int cpuFreq = F_CPU;
+ UNUSED(cpuFreq);
+
#if ENABLED(SDSUPPORT) && DISABLED(SDIO_SUPPORT) && (defined(SDSS) && SDSS != -1)
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
#endif
@@ -81,7 +87,24 @@ void HAL_init() {
SetTimerInterruptPriorities();
- TERN_(EMERGENCY_PARSER, USB_Hook_init());
+ #if ENABLED(EMERGENCY_PARSER) && USBD_USE_CDC
+ USB_Hook_init();
+ #endif
+
+ TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
+
+ #if HAS_SD_HOST_DRIVE
+ MSC_SD_init(); // Enable USB SD card access
+ #endif
+}
+
+// HAL idle task
+void HAL_idletask() {
+ #if HAS_SHARED_MEDIA
+ // Stm32duino currently doesn't have a "loop/idle" method
+ CDC_resume_receive();
+ CDC_continue_transmit();
+ #endif
}
void HAL_clear_reset_source() { __HAL_RCC_CLEAR_RESET_FLAGS(); }
@@ -110,6 +133,8 @@ uint8_t HAL_get_reset_source() {
;
}
+void HAL_reboot() { NVIC_SystemReset(); }
+
void _delay_ms(const int delay_ms) { delay(delay_ms); }
extern "C" {
@@ -124,12 +149,16 @@ extern "C" {
void HAL_adc_start_conversion(const uint8_t adc_pin) { HAL_adc_result = analogRead(adc_pin); }
uint16_t HAL_adc_get_result() { return HAL_adc_result; }
-// Reset the system (to initiate a firmware flash)
-void flashFirmware(const int16_t) { NVIC_SystemReset(); }
+// Reset the system to initiate a firmware flash
+void flashFirmware(const int16_t) { HAL_reboot(); }
// Maple Compatibility
+volatile uint32_t systick_uptime_millis = 0;
systickCallback_t systick_user_callback;
void systick_attach_callback(systickCallback_t cb) { systick_user_callback = cb; }
-void HAL_SYSTICK_Callback() { if (systick_user_callback) systick_user_callback(); }
+void HAL_SYSTICK_Callback() {
+ systick_uptime_millis++;
+ if (systick_user_callback) systick_user_callback();
+}
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/HAL.h b/Marlin/src/HAL/STM32/HAL.h
index a1f7515d6..469d08e43 100644
--- a/Marlin/src/HAL/STM32/HAL.h
+++ b/Marlin/src/HAL/STM32/HAL.h
@@ -29,6 +29,7 @@
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
+#include "Servo.h"
#include "watchdog.h"
#include "MarlinSerial.h"
@@ -38,6 +39,9 @@
#ifdef USBCON
#include
+ #include "../../core/serial_hook.h"
+ typedef ForwardSerial1Class< decltype(SerialUSB) > DefaultSerial1;
+ extern DefaultSerial1 MSerial0;
#endif
// ------------------------
@@ -47,30 +51,40 @@
#define MSERIAL(X) _MSERIAL(X)
#if SERIAL_PORT == -1
- #define MYSERIAL0 SerialUSB
+ #define MYSERIAL1 MSerial0
#elif WITHIN(SERIAL_PORT, 1, 6)
- #define MYSERIAL0 MSERIAL(SERIAL_PORT)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
- #error "SERIAL_PORT must be -1 or from 1 to 6. Please update your configuration."
+ #error "SERIAL_PORT must be from 1 to 6. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
- #define MYSERIAL1 SerialUSB
+ #define MYSERIAL2 MSerial0
#elif WITHIN(SERIAL_PORT_2, 1, 6)
- #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
+ #define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
- #error "SERIAL_PORT_2 must be -1 or from 1 to 6. Please update your configuration."
+ #error "SERIAL_PORT_2 must be from 1 to 6. You can also use -1 if the board supports Native USB."
+ #endif
+#endif
+
+#ifdef MMU2_SERIAL_PORT
+ #if MMU2_SERIAL_PORT == -1
+ #define MMU2_SERIAL MSerial0
+ #elif WITHIN(MMU2_SERIAL_PORT, 1, 6)
+ #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
+ #else
+ #error "MMU2_SERIAL_PORT must be from 1 to 6. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if LCD_SERIAL_PORT == -1
- #define LCD_SERIAL SerialUSB
+ #define LCD_SERIAL MSerial0
#elif WITHIN(LCD_SERIAL_PORT, 1, 6)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "LCD_SERIAL_PORT must be -1 or from 1 to 6. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from 1 to 6. You can also use -1 if the board supports Native USB."
#endif
#if HAS_DGUS_LCD
#define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
@@ -95,14 +109,6 @@
// On AVR this is in math.h?
#define square(x) ((x)*(x))
-#ifndef strncpy_P
- #define strncpy_P(dest, src, num) strncpy((dest), (src), (num))
-#endif
-
-// Fix bug in pgm_read_ptr
-#undef pgm_read_ptr
-#define pgm_read_ptr(addr) (*(addr))
-
// ------------------------
// Types
// ------------------------
@@ -110,6 +116,8 @@
typedef int16_t pin_t;
#define HAL_SERVO_LIB libServo
+#define PAUSE_SERVO_OUTPUT() libServo::pause_all_servos()
+#define RESUME_SERVO_OUTPUT() libServo::resume_all_servos()
// ------------------------
// Public Variables
@@ -127,6 +135,8 @@ extern uint16_t HAL_adc_result;
// Enable hooks into setup for HAL
void HAL_init();
+#define HAL_IDLETASK 1
+void HAL_idletask();
// Clear reset reason
void HAL_clear_reset_source();
@@ -134,7 +144,7 @@ void HAL_clear_reset_source();
// Reset reason
uint8_t HAL_get_reset_source();
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+void HAL_reboot();
void _delay_ms(const int delay);
@@ -156,14 +166,14 @@ static inline int freeMemory() {
#define HAL_ANALOG_SELECT(pin) pinMode(pin, INPUT)
-inline void HAL_adc_init() {}
-
#define HAL_ADC_VREF 3.3
-#define HAL_ADC_RESOLUTION 10
+#define HAL_ADC_RESOLUTION ADC_RESOLUTION // 12
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
+inline void HAL_adc_init() { analogReadResolution(HAL_ADC_RESOLUTION); }
+
void HAL_adc_start_conversion(const uint8_t adc_pin);
uint16_t HAL_adc_get_result();
@@ -184,3 +194,22 @@ void flashFirmware(const int16_t);
typedef void (*systickCallback_t)(void);
void systick_attach_callback(systickCallback_t cb);
void HAL_SYSTICK_Callback();
+
+extern volatile uint32_t systick_uptime_millis;
+
+#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
+
+/**
+ * set_pwm_frequency
+ * Set the frequency of the timer corresponding to the provided pin
+ * All Timer PWM pins run at the same frequency
+ */
+void set_pwm_frequency(const pin_t pin, int f_desired);
+
+/**
+ * set_pwm_duty
+ * Set the PWM duty cycle of the provided pin to the provided value
+ * Optionally allows inverting the duty cycle [default = false]
+ * Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
+ */
+void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
diff --git a/Marlin/src/HAL/STM32/HAL_MinSerial.cpp b/Marlin/src/HAL/STM32/HAL_MinSerial.cpp
new file mode 100644
index 000000000..823bb6e8f
--- /dev/null
+++ b/Marlin/src/HAL/STM32/HAL_MinSerial.cpp
@@ -0,0 +1,152 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ * Copyright (c) 2017 Victor Perez
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+
+#include "../shared/HAL_MinSerial.h"
+#include "watchdog.h"
+
+/* Instruction Synchronization Barrier */
+#define isb() __asm__ __volatile__ ("isb" : : : "memory")
+
+/* Data Synchronization Barrier */
+#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
+
+// Dumb mapping over the registers of a USART device on STM32
+struct USARTMin {
+ volatile uint32_t SR;
+ volatile uint32_t DR;
+ volatile uint32_t BRR;
+ volatile uint32_t CR1;
+ volatile uint32_t CR2;
+};
+
+#if WITHIN(SERIAL_PORT, 1, 6)
+ // Depending on the CPU, the serial port is different for USART1
+ static const uintptr_t regsAddr[] = {
+ TERN(STM32F1xx, 0x40013800, 0x40011000), // USART1
+ 0x40004400, // USART2
+ 0x40004800, // USART3
+ 0x40004C00, // UART4_BASE
+ 0x40005000, // UART5_BASE
+ 0x40011400 // USART6
+ };
+ static USARTMin * regs = (USARTMin*)regsAddr[SERIAL_PORT - 1];
+#endif
+
+static void TXBegin() {
+ #if !WITHIN(SERIAL_PORT, 1, 6)
+ #warning "Using POSTMORTEM_DEBUGGING requires a physical U(S)ART hardware in case of severe error."
+ #warning "Disabling the severe error reporting feature currently because the used serial port is not a HW port."
+ #else
+ // This is common between STM32F1/STM32F2 and STM32F4
+ const int nvicUART[] = { /* NVIC_USART1 */ 37, /* NVIC_USART2 */ 38, /* NVIC_USART3 */ 39, /* NVIC_UART4 */ 52, /* NVIC_UART5 */ 53, /* NVIC_USART6 */ 71 };
+ int nvicIndex = nvicUART[SERIAL_PORT - 1];
+
+ struct NVICMin {
+ volatile uint32_t ISER[32];
+ volatile uint32_t ICER[32];
+ };
+
+ NVICMin * nvicBase = (NVICMin*)0xE000E100;
+ nvicBase->ICER[nvicIndex / 32] |= _BV32(nvicIndex % 32);
+
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ dsb();
+ isb();
+
+ // Example for USART1 disable: (RCC->APB2ENR &= ~(RCC_APB2ENR_USART1EN))
+ // Too difficult to reimplement here, let's query the STM32duino macro here
+ #if SERIAL_PORT == 1
+ __HAL_RCC_USART1_CLK_DISABLE();
+ __HAL_RCC_USART1_CLK_ENABLE();
+ #elif SERIAL_PORT == 2
+ __HAL_RCC_USART2_CLK_DISABLE();
+ __HAL_RCC_USART2_CLK_ENABLE();
+ #elif SERIAL_PORT == 3
+ __HAL_RCC_USART3_CLK_DISABLE();
+ __HAL_RCC_USART3_CLK_ENABLE();
+ #elif SERIAL_PORT == 4
+ __HAL_RCC_UART4_CLK_DISABLE(); // BEWARE: UART4 and not USART4 here
+ __HAL_RCC_UART4_CLK_ENABLE();
+ #elif SERIAL_PORT == 5
+ __HAL_RCC_UART5_CLK_DISABLE(); // BEWARE: UART5 and not USART5 here
+ __HAL_RCC_UART5_CLK_ENABLE();
+ #elif SERIAL_PORT == 6
+ __HAL_RCC_USART6_CLK_DISABLE();
+ __HAL_RCC_USART6_CLK_ENABLE();
+ #endif
+
+ uint32_t brr = regs->BRR;
+ regs->CR1 = 0; // Reset the USART
+ regs->CR2 = 0; // 1 stop bit
+
+ // If we don't touch the BRR (baudrate register), we don't need to recompute.
+ regs->BRR = brr;
+
+ regs->CR1 = _BV(3) | _BV(13); // 8 bits, no parity, 1 stop bit (TE | UE)
+ #endif
+}
+
+// A SW memory barrier, to ensure GCC does not overoptimize loops
+#define sw_barrier() __asm__ volatile("": : :"memory");
+static void TX(char c) {
+ #if WITHIN(SERIAL_PORT, 1, 6)
+ constexpr uint32_t usart_sr_txe = _BV(7);
+ while (!(regs->SR & usart_sr_txe)) {
+ TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
+ sw_barrier();
+ }
+ regs->DR = c;
+ #else
+ // Let's hope a mystical guru will fix this, one day by writting interrupt-free USB CDC ACM code (or, at least, by polling the registers since interrupt will be queued but will never trigger)
+ // For now, it's completely lost to oblivion.
+ #endif
+}
+
+void install_min_serial() {
+ HAL_min_serial_init = &TXBegin;
+ HAL_min_serial_out = &TX;
+}
+
+#if DISABLED(DYNAMIC_VECTORTABLE) && DISABLED(STM32F0xx) // Cortex M0 can't jump to a symbol that's too far from the current function, so we work around this in exception_arm.cpp
+extern "C" {
+ __attribute__((naked)) void JumpHandler_ASM() {
+ __asm__ __volatile__ (
+ "b CommonHandler_ASM\n"
+ );
+ }
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) HardFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) BusFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) UsageFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) MemManage_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) NMI_Handler();
+}
+#endif
+
+#endif // POSTMORTEM_DEBUGGING
+#endif // ARDUINO_ARCH_STM32
diff --git a/Marlin/src/HAL/STM32/HAL_SPI.cpp b/Marlin/src/HAL/STM32/HAL_SPI.cpp
index f947e6ef3..80347e115 100644
--- a/Marlin/src/HAL/STM32/HAL_SPI.cpp
+++ b/Marlin/src/HAL/STM32/HAL_SPI.cpp
@@ -45,24 +45,34 @@ static SPISettings spiConfig;
#include "../shared/Delay.h"
void spiBegin(void) {
- OUT_WRITE(SS_PIN, HIGH);
- OUT_WRITE(SCK_PIN, HIGH);
- SET_INPUT(MISO_PIN);
- OUT_WRITE(MOSI_PIN, HIGH);
+ OUT_WRITE(SD_SS_PIN, HIGH);
+ OUT_WRITE(SD_SCK_PIN, HIGH);
+ SET_INPUT(SD_MISO_PIN);
+ OUT_WRITE(SD_MOSI_PIN, HIGH);
}
- static uint16_t delay_STM32_soft_spi;
+ // Use function with compile-time value so we can actually reach the desired frequency
+ // Need to adjust this a little bit: on a 72MHz clock, we have 14ns/clock
+ // and we'll use ~3 cycles to jump to the method and going back, so it'll take ~40ns from the given clock here
+ #define CALLING_COST_NS (3U * 1000000000U) / (F_CPU)
+ void (*delaySPIFunc)();
+ void delaySPI_125() { DELAY_NS(125 - CALLING_COST_NS); }
+ void delaySPI_250() { DELAY_NS(250 - CALLING_COST_NS); }
+ void delaySPI_500() { DELAY_NS(500 - CALLING_COST_NS); }
+ void delaySPI_1000() { DELAY_NS(1000 - CALLING_COST_NS); }
+ void delaySPI_2000() { DELAY_NS(2000 - CALLING_COST_NS); }
+ void delaySPI_4000() { DELAY_NS(4000 - CALLING_COST_NS); }
void spiInit(uint8_t spiRate) {
// Use datarates Marlin uses
switch (spiRate) {
- case SPI_FULL_SPEED: delay_STM32_soft_spi = 125; break; // desired: 8,000,000 actual: ~1.1M
- case SPI_HALF_SPEED: delay_STM32_soft_spi = 125; break; // desired: 4,000,000 actual: ~1.1M
- case SPI_QUARTER_SPEED:delay_STM32_soft_spi = 250; break; // desired: 2,000,000 actual: ~890K
- case SPI_EIGHTH_SPEED: delay_STM32_soft_spi = 500; break; // desired: 1,000,000 actual: ~590K
- case SPI_SPEED_5: delay_STM32_soft_spi = 1000; break; // desired: 500,000 actual: ~360K
- case SPI_SPEED_6: delay_STM32_soft_spi = 2000; break; // desired: 250,000 actual: ~210K
- default: delay_STM32_soft_spi = 4000; break; // desired: 125,000 actual: ~123K
+ case SPI_FULL_SPEED: delaySPIFunc = &delaySPI_125; break; // desired: 8,000,000 actual: ~1.1M
+ case SPI_HALF_SPEED: delaySPIFunc = &delaySPI_125; break; // desired: 4,000,000 actual: ~1.1M
+ case SPI_QUARTER_SPEED:delaySPIFunc = &delaySPI_250; break; // desired: 2,000,000 actual: ~890K
+ case SPI_EIGHTH_SPEED: delaySPIFunc = &delaySPI_500; break; // desired: 1,000,000 actual: ~590K
+ case SPI_SPEED_5: delaySPIFunc = &delaySPI_1000; break; // desired: 500,000 actual: ~360K
+ case SPI_SPEED_6: delaySPIFunc = &delaySPI_2000; break; // desired: 250,000 actual: ~210K
+ default: delaySPIFunc = &delaySPI_4000; break; // desired: 125,000 actual: ~123K
}
SPI.begin();
}
@@ -72,15 +82,15 @@ static SPISettings spiConfig;
uint8_t HAL_SPI_STM32_SpiTransfer_Mode_3(uint8_t b) { // using Mode 3
for (uint8_t bits = 8; bits--;) {
- WRITE(SCK_PIN, LOW);
- WRITE(MOSI_PIN, b & 0x80);
+ WRITE(SD_SCK_PIN, LOW);
+ WRITE(SD_MOSI_PIN, b & 0x80);
- DELAY_NS(delay_STM32_soft_spi);
- WRITE(SCK_PIN, HIGH);
- DELAY_NS(delay_STM32_soft_spi);
+ delaySPIFunc();
+ WRITE(SD_SCK_PIN, HIGH);
+ delaySPIFunc();
b <<= 1; // little setup time
- b |= (READ(MISO_PIN) != 0);
+ b |= (READ(SD_MISO_PIN) != 0);
}
DELAY_NS(125);
return b;
@@ -132,8 +142,8 @@ static SPISettings spiConfig;
* @details Only configures SS pin since stm32duino creates and initialize the SPI object
*/
void spiBegin() {
- #if PIN_EXISTS(SS)
- OUT_WRITE(SS_PIN, HIGH);
+ #if PIN_EXISTS(SD_SS)
+ OUT_WRITE(SD_SS_PIN, HIGH);
#endif
}
@@ -154,10 +164,9 @@ static SPISettings spiConfig;
spiConfig = SPISettings(clock, MSBFIRST, SPI_MODE0);
#if ENABLED(CUSTOM_SPI_PINS)
- SPI.setMISO(MISO_PIN);
- SPI.setMOSI(MOSI_PIN);
- SPI.setSCLK(SCK_PIN);
- SPI.setSSEL(SS_PIN);
+ SPI.setMISO(SD_MISO_PIN);
+ SPI.setMOSI(SD_MOSI_PIN);
+ SPI.setSCLK(SD_SCK_PIN);
#endif
SPI.begin();
@@ -184,7 +193,7 @@ static SPISettings spiConfig;
*
* @details Uses DMA
*/
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
if (nbyte == 0) return;
memset(buf, 0xFF, nbyte);
SPI.transfer(buf, nbyte);
@@ -209,7 +218,7 @@ static SPISettings spiConfig;
*
* @details Use DMA
*/
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
uint8_t rxBuf[512];
SPI.transfer(token);
SPI.transfer((uint8_t*)buf, &rxBuf, 512);
diff --git a/Marlin/src/HAL/STM32/MarlinSPI.cpp b/Marlin/src/HAL/STM32/MarlinSPI.cpp
new file mode 100644
index 000000000..896ec1433
--- /dev/null
+++ b/Marlin/src/HAL/STM32/MarlinSPI.cpp
@@ -0,0 +1,168 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) && !defined(STM32H7xx)
+
+#include "MarlinSPI.h"
+
+static void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb, uint32_t dataSize) {
+ spi_init(obj, speed, mode, msb);
+ // spi_init set 8bit always
+ // TODO: copy the code from spi_init and handle data size, to avoid double init always!!
+ if (dataSize != SPI_DATASIZE_8BIT) {
+ obj->handle.Init.DataSize = dataSize;
+ HAL_SPI_Init(&obj->handle);
+ __HAL_SPI_ENABLE(&obj->handle);
+ }
+}
+
+void MarlinSPI::setClockDivider(uint8_t _div) {
+ _speed = spi_getClkFreq(&_spi);// / _div;
+ _clockDivider = _div;
+}
+
+void MarlinSPI::begin(void) {
+ //TODO: only call spi_init if any parameter changed!!
+ spi_init(&_spi, _speed, _dataMode, _bitOrder, _dataSize);
+}
+
+void MarlinSPI::setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc) {
+ _dmaHandle.Init.Direction = direction;
+ _dmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
+ _dmaHandle.Init.Mode = DMA_NORMAL;
+ _dmaHandle.Init.Priority = DMA_PRIORITY_LOW;
+ _dmaHandle.Init.MemInc = minc ? DMA_MINC_ENABLE : DMA_MINC_DISABLE;
+
+ if (_dataSize == DATA_SIZE_8BIT) {
+ _dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ _dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ }
+ else {
+ _dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
+ _dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
+ }
+ #ifdef STM32F4xx
+ _dmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ #endif
+
+ // start DMA hardware
+ // TODO: check if hardware is already enabled
+ #ifdef SPI1_BASE
+ if (_spiHandle.Instance == SPI1) {
+ #ifdef STM32F1xx
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel3 : DMA1_Channel2;
+ #elif defined(STM32F4xx)
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ _dmaHandle.Init.Channel = DMA_CHANNEL_3;
+ _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA2_Stream3 : DMA2_Stream0;
+ #endif
+ }
+ #endif
+ #ifdef SPI2_BASE
+ if (_spiHandle.Instance == SPI2) {
+ #ifdef STM32F1xx
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel5 : DMA1_Channel4;
+ #elif defined(STM32F4xx)
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ _dmaHandle.Init.Channel = DMA_CHANNEL_0;
+ _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Stream4 : DMA1_Stream3;
+ #endif
+ }
+ #endif
+ #ifdef SPI3_BASE
+ if (_spiHandle.Instance == SPI3) {
+ #ifdef STM32F1xx
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA2_Channel2 : DMA2_Channel1;
+ #elif defined(STM32F4xx)
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ _dmaHandle.Init.Channel = DMA_CHANNEL_0;
+ _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Stream5 : DMA1_Stream2;
+ #endif
+ }
+ #endif
+
+ HAL_DMA_Init(&_dmaHandle);
+}
+
+byte MarlinSPI::transfer(uint8_t _data) {
+ uint8_t rxData = 0xFF;
+ HAL_SPI_TransmitReceive(&_spi.handle, &_data, &rxData, 1, HAL_MAX_DELAY);
+ return rxData;
+}
+
+uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) {
+ const uint8_t ff = 0xFF;
+
+ //if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) //only enable if disabled
+ __HAL_SPI_ENABLE(&_spi.handle);
+
+ if (receiveBuf) {
+ setupDma(_spi.handle, _dmaRx, DMA_PERIPH_TO_MEMORY, true);
+ HAL_DMA_Start(&_dmaRx, (uint32_t)&(_spi.handle.Instance->DR), (uint32_t)receiveBuf, length);
+ SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_RXDMAEN); /* Enable Rx DMA Request */
+ }
+
+ // check for 2 lines transfer
+ bool mincTransmit = true;
+ if (transmitBuf == nullptr && _spi.handle.Init.Direction == SPI_DIRECTION_2LINES && _spi.handle.Init.Mode == SPI_MODE_MASTER) {
+ transmitBuf = &ff;
+ mincTransmit = false;
+ }
+
+ if (transmitBuf) {
+ setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, mincTransmit);
+ HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
+ SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */
+ }
+
+ if (transmitBuf) {
+ HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
+ HAL_DMA_Abort(&_dmaTx);
+ HAL_DMA_DeInit(&_dmaTx);
+ }
+
+ // while ((_spi.handle.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
+
+ if (receiveBuf) {
+ HAL_DMA_PollForTransfer(&_dmaRx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
+ HAL_DMA_Abort(&_dmaRx);
+ HAL_DMA_DeInit(&_dmaRx);
+ }
+
+ return 1;
+}
+
+uint8_t MarlinSPI::dmaSend(const void * transmitBuf, uint16_t length, bool minc) {
+ setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, minc);
+ HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
+ __HAL_SPI_ENABLE(&_spi.handle);
+ SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */
+ HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
+ HAL_DMA_Abort(&_dmaTx);
+ // DeInit objects
+ HAL_DMA_DeInit(&_dmaTx);
+ return 1;
+}
+
+#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/MarlinSPI.h b/Marlin/src/HAL/STM32/MarlinSPI.h
new file mode 100644
index 000000000..fbd3585ff
--- /dev/null
+++ b/Marlin/src/HAL/STM32/MarlinSPI.h
@@ -0,0 +1,107 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "HAL.h"
+#include
+
+extern "C" {
+ #include
+}
+
+/**
+ * Marlin currently requires 3 SPI classes:
+ *
+ * SPIClass:
+ * This class is normally provided by frameworks and has a semi-default interface.
+ * This is needed because some libraries reference it globally.
+ *
+ * SPISettings:
+ * Container for SPI configs for SPIClass. As above, libraries may reference it globally.
+ *
+ * These two classes are often provided by frameworks so we cannot extend them to add
+ * useful methods for Marlin.
+ *
+ * MarlinSPI:
+ * Provides the default SPIClass interface plus some Marlin goodies such as a simplified
+ * interface for SPI DMA transfer.
+ *
+ */
+
+#define DATA_SIZE_8BIT SPI_DATASIZE_8BIT
+#define DATA_SIZE_16BIT SPI_DATASIZE_16BIT
+
+class MarlinSPI {
+public:
+ MarlinSPI() : MarlinSPI(NC, NC, NC, NC) {}
+
+ MarlinSPI(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel = (pin_t)NC) : _mosiPin(mosi), _misoPin(miso), _sckPin(sclk), _ssPin(ssel) {
+ _spi.pin_miso = digitalPinToPinName(_misoPin);
+ _spi.pin_mosi = digitalPinToPinName(_mosiPin);
+ _spi.pin_sclk = digitalPinToPinName(_sckPin);
+ _spi.pin_ssel = digitalPinToPinName(_ssPin);
+ _dataSize = DATA_SIZE_8BIT;
+ _bitOrder = MSBFIRST;
+ _dataMode = SPI_MODE_0;
+ _spi.handle.State = HAL_SPI_STATE_RESET;
+ setClockDivider(SPI_SPEED_CLOCK_DIV2_MHZ);
+ }
+
+ void begin(void);
+ void end(void) {}
+
+ byte transfer(uint8_t _data);
+ uint8_t dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length);
+ uint8_t dmaSend(const void * transmitBuf, uint16_t length, bool minc = true);
+
+ /* These methods are deprecated and kept for compatibility.
+ * Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
+ */
+ void setBitOrder(BitOrder _order) { _bitOrder = _order; }
+
+ void setDataMode(uint8_t _mode) {
+ switch (_mode) {
+ case SPI_MODE0: _dataMode = SPI_MODE_0; break;
+ case SPI_MODE1: _dataMode = SPI_MODE_1; break;
+ case SPI_MODE2: _dataMode = SPI_MODE_2; break;
+ case SPI_MODE3: _dataMode = SPI_MODE_3; break;
+ }
+ }
+
+ void setClockDivider(uint8_t _div);
+
+private:
+ void setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc = false);
+
+ spi_t _spi;
+ DMA_HandleTypeDef _dmaTx;
+ DMA_HandleTypeDef _dmaRx;
+ BitOrder _bitOrder;
+ spi_mode_e _dataMode;
+ uint8_t _clockDivider;
+ uint32_t _speed;
+ uint32_t _dataSize;
+ pin_t _mosiPin;
+ pin_t _misoPin;
+ pin_t _sckPin;
+ pin_t _ssPin;
+};
diff --git a/Marlin/src/HAL/STM32/MarlinSerial.cpp b/Marlin/src/HAL/STM32/MarlinSerial.cpp
index a14666436..265e8b5ab 100644
--- a/Marlin/src/HAL/STM32/MarlinSerial.cpp
+++ b/Marlin/src/HAL/STM32/MarlinSerial.cpp
@@ -16,7 +16,6 @@
* along with this program. If not, see .
*
*/
-
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#include "../../inc/MarlinConfig.h"
@@ -29,28 +28,47 @@
#ifndef USART4
#define USART4 UART4
#endif
-
#ifndef USART5
#define USART5 UART5
#endif
#define DECLARE_SERIAL_PORT(ser_num) \
void _rx_complete_irq_ ## ser_num (serial_t * obj); \
- MarlinSerial MSerial ## ser_num (USART ## ser_num, &_rx_complete_irq_ ## ser_num); \
+ MSerialT MSerial ## ser_num (true, USART ## ser_num, &_rx_complete_irq_ ## ser_num); \
void _rx_complete_irq_ ## ser_num (serial_t * obj) { MSerial ## ser_num ._rx_complete_irq(obj); }
-#define DECLARE_SERIAL_PORT_EXP(ser_num) DECLARE_SERIAL_PORT(ser_num)
-
-#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
- DECLARE_SERIAL_PORT_EXP(SERIAL_PORT)
+#if USING_HW_SERIAL1
+ DECLARE_SERIAL_PORT(1)
#endif
-
-#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
- DECLARE_SERIAL_PORT_EXP(SERIAL_PORT_2)
+#if USING_HW_SERIAL2
+ DECLARE_SERIAL_PORT(2)
#endif
-
-#if defined(LCD_SERIAL_PORT) && LCD_SERIAL_PORT >= 0
- DECLARE_SERIAL_PORT_EXP(LCD_SERIAL_PORT)
+#if USING_HW_SERIAL3
+ DECLARE_SERIAL_PORT(3)
+#endif
+#if USING_HW_SERIAL4
+ DECLARE_SERIAL_PORT(4)
+#endif
+#if USING_HW_SERIAL5
+ DECLARE_SERIAL_PORT(5)
+#endif
+#if USING_HW_SERIAL6
+ DECLARE_SERIAL_PORT(6)
+#endif
+#if USING_HW_SERIAL7
+ DECLARE_SERIAL_PORT(7)
+#endif
+#if USING_HW_SERIAL8
+ DECLARE_SERIAL_PORT(8)
+#endif
+#if USING_HW_SERIAL9
+ DECLARE_SERIAL_PORT(9)
+#endif
+#if USING_HW_SERIAL10
+ DECLARE_SERIAL_PORT(10)
+#endif
+#if USING_HW_SERIALLP1
+ DECLARE_SERIAL_PORT(LP1)
#endif
void MarlinSerial::begin(unsigned long baud, uint8_t config) {
@@ -78,7 +96,7 @@ void MarlinSerial::_rx_complete_irq(serial_t *obj) {
}
#if ENABLED(EMERGENCY_PARSER)
- emergency_parser.update(emergency_state, c);
+ emergency_parser.update(static_cast(this)->emergency_state, c);
#endif
}
}
diff --git a/Marlin/src/HAL/STM32/MarlinSerial.h b/Marlin/src/HAL/STM32/MarlinSerial.h
index 3611cc78d..ab5c4260a 100644
--- a/Marlin/src/HAL/STM32/MarlinSerial.h
+++ b/Marlin/src/HAL/STM32/MarlinSerial.h
@@ -24,41 +24,33 @@
#include "../../feature/e_parser.h"
#endif
+#include "../../core/serial_hook.h"
+
typedef void (*usart_rx_callback_t)(serial_t * obj);
-class MarlinSerial : public HardwareSerial {
-public:
- MarlinSerial(void* peripheral, usart_rx_callback_t rx_callback) :
+struct MarlinSerial : public HardwareSerial {
+ MarlinSerial(void *peripheral, usart_rx_callback_t rx_callback) :
HardwareSerial(peripheral), _rx_callback(rx_callback)
- #if ENABLED(EMERGENCY_PARSER)
- , emergency_state(EmergencyParser::State::EP_RESET)
- #endif
{ }
- #if ENABLED(EMERGENCY_PARSER)
- static inline bool emergency_parser_enabled() { return true; }
- #endif
-
void begin(unsigned long baud, uint8_t config);
inline void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
- void _rx_complete_irq(serial_t* obj);
+ void _rx_complete_irq(serial_t *obj);
protected:
usart_rx_callback_t _rx_callback;
- #if ENABLED(EMERGENCY_PARSER)
- EmergencyParser::State emergency_state;
- #endif
};
-extern MarlinSerial MSerial1;
-extern MarlinSerial MSerial2;
-extern MarlinSerial MSerial3;
-extern MarlinSerial MSerial4;
-extern MarlinSerial MSerial5;
-extern MarlinSerial MSerial6;
-extern MarlinSerial MSerial7;
-extern MarlinSerial MSerial8;
-extern MarlinSerial MSerial9;
-extern MarlinSerial MSerial10;
-extern MarlinSerial MSerialLP1;
+typedef Serial1Class MSerialT;
+extern MSerialT MSerial1;
+extern MSerialT MSerial2;
+extern MSerialT MSerial3;
+extern MSerialT MSerial4;
+extern MSerialT MSerial5;
+extern MSerialT MSerial6;
+extern MSerialT MSerial7;
+extern MSerialT MSerial8;
+extern MSerialT MSerial9;
+extern MSerialT MSerial10;
+extern MSerialT MSerialLP1;
diff --git a/Marlin/src/HAL/STM32/Sd2Card_sdio_stm32duino.cpp b/Marlin/src/HAL/STM32/Sd2Card_sdio_stm32duino.cpp
index 6e73e87c2..3353f8c36 100644
--- a/Marlin/src/HAL/STM32/Sd2Card_sdio_stm32duino.cpp
+++ b/Marlin/src/HAL/STM32/Sd2Card_sdio_stm32duino.cpp
@@ -19,10 +19,11 @@
* along with this program. If not, see .
*
*/
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#include "../../inc/MarlinConfig.h"
-#if ENABLED(SDIO_SUPPORT) && !defined(STM32GENERIC)
+#if ENABLED(SDIO_SUPPORT)
#include
#include
@@ -31,13 +32,14 @@
#error "ERROR - Only STM32F103xE, STM32F103xG, STM32F4xx or STM32F7xx CPUs supported"
#endif
-#ifdef USBD_USE_CDC_COMPOSITE
+#if HAS_SD_HOST_DRIVE
// use USB drivers
- extern "C" { int8_t SD_MSC_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
- int8_t SD_MSC_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
- extern SD_HandleTypeDef hsd;
+ extern "C" {
+ int8_t SD_MSC_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
+ int8_t SD_MSC_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
+ extern SD_HandleTypeDef hsd;
}
bool SDIO_Init() {
@@ -74,7 +76,18 @@
#error "ERROR - Only STM32F103xE, STM32F103xG, STM32F4xx or STM32F7xx CPUs supported"
#endif
+ // Fixed
+ #define SDIO_D0_PIN PC8
+ #define SDIO_D1_PIN PC9
+ #define SDIO_D2_PIN PC10
+ #define SDIO_D3_PIN PC11
+ #define SDIO_CK_PIN PC12
+ #define SDIO_CMD_PIN PD2
+
SD_HandleTypeDef hsd; // create SDIO structure
+ // F4 supports one DMA for RX and another for TX, but Marlin will never
+ // do read and write at same time, so we use the same DMA for both.
+ DMA_HandleTypeDef hdma_sdio;
/*
SDIO_INIT_CLK_DIV is 118
@@ -87,37 +100,53 @@
MKS Robin board seems to have stable SDIO with BusWide 1bit and ClockDiv 8 i.e. 4.8MHz SDIO clock frequency
Additional testing is required as there are clearly some 4bit initialization problems
-
- Add -DTRANSFER_CLOCK_DIV=8 to build parameters to improve SDIO stability
*/
- #ifndef TRANSFER_CLOCK_DIV
- #define TRANSFER_CLOCK_DIV (uint8_t(SDIO_INIT_CLK_DIV) / 40)
- #endif
-
#ifndef USBD_OK
#define USBD_OK 0
#endif
- void go_to_transfer_speed() {
- SD_InitTypeDef Init;
+ // Target Clock, configurable. Default is 18MHz, from STM32F1
+ #ifndef SDIO_CLOCK
+ #define SDIO_CLOCK 18000000 // 18 MHz
+ #endif
+ // SDIO retries, configurable. Default is 3, from STM32F1
+ #ifndef SDIO_READ_RETRIES
+ #define SDIO_READ_RETRIES 3
+ #endif
+
+ // SDIO Max Clock (naming from STM Manual, don't change)
+ #define SDIOCLK 48000000
+
+ static uint32_t clock_to_divider(uint32_t clk) {
+ // limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals
+ // Also limited to no more than 48Mhz (SDIOCLK).
+ const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq();
+ clk = min(clk, (uint32_t)(pclk2 * 8 / 3));
+ clk = min(clk, (uint32_t)SDIOCLK);
+ // Round up divider, so we don't run the card over the speed supported,
+ // and subtract by 2, because STM32 will add 2, as written in the manual:
+ // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
+ return pclk2 / clk + (pclk2 % clk != 0) - 2;
+ }
+
+ void go_to_transfer_speed() {
/* Default SDIO peripheral configuration for SD card initialization */
- Init.ClockEdge = hsd.Init.ClockEdge;
- Init.ClockBypass = hsd.Init.ClockBypass;
- Init.ClockPowerSave = hsd.Init.ClockPowerSave;
- Init.BusWide = hsd.Init.BusWide;
- Init.HardwareFlowControl = hsd.Init.HardwareFlowControl;
- Init.ClockDiv = TRANSFER_CLOCK_DIV;
+ hsd.Init.ClockEdge = hsd.Init.ClockEdge;
+ hsd.Init.ClockBypass = hsd.Init.ClockBypass;
+ hsd.Init.ClockPowerSave = hsd.Init.ClockPowerSave;
+ hsd.Init.BusWide = hsd.Init.BusWide;
+ hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl;
+ hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
/* Initialize SDIO peripheral interface with default configuration */
- SDIO_Init(hsd.Instance, Init);
+ SDIO_Init(hsd.Instance, hsd.Init);
}
void SD_LowLevel_Init(void) {
uint32_t tempreg;
- __HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks
__HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks
@@ -143,49 +172,70 @@
GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
+ // Setup DMA
+ #if defined(STM32F1xx)
+ hdma_sdio.Init.Mode = DMA_NORMAL;
+ hdma_sdio.Instance = DMA2_Channel4;
+ HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
+ #elif defined(STM32F4xx)
+ hdma_sdio.Init.Mode = DMA_PFCTRL;
+ hdma_sdio.Instance = DMA2_Stream3;
+ hdma_sdio.Init.Channel = DMA_CHANNEL_4;
+ hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
+ hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
+ hdma_sdio.Init.MemBurst = DMA_MBURST_INC4;
+ hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4;
+ HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
+ #endif
+ HAL_NVIC_EnableIRQ(SDIO_IRQn);
+ hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
+ hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
+ hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+ hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
+ hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
+ __HAL_LINKDMA(&hsd, hdmarx, hdma_sdio);
+ __HAL_LINKDMA(&hsd, hdmatx, hdma_sdio);
- #if DISABLED(STM32F1xx)
- // TODO: use __HAL_RCC_SDIO_RELEASE_RESET() and __HAL_RCC_SDIO_CLK_ENABLE();
- RCC->APB2RSTR &= ~RCC_APB2RSTR_SDIORST_Msk; // take SDIO out of reset
- RCC->APB2ENR |= RCC_APB2RSTR_SDIORST_Msk; // enable SDIO clock
- // Enable the DMA2 Clock
+ #if defined(STM32F1xx)
+ __HAL_RCC_SDIO_CLK_ENABLE();
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ #else
+ __HAL_RCC_SDIO_FORCE_RESET();
+ delay(2);
+ __HAL_RCC_SDIO_RELEASE_RESET();
+ delay(2);
+ __HAL_RCC_SDIO_CLK_ENABLE();
+
+ __HAL_RCC_DMA2_FORCE_RESET();
+ delay(2);
+ __HAL_RCC_DMA2_RELEASE_RESET();
+ delay(2);
+ __HAL_RCC_DMA2_CLK_ENABLE();
#endif
//Initialize the SDIO (with initial <400Khz Clock)
tempreg = 0; //Reset value
tempreg |= SDIO_CLKCR_CLKEN; // Clock enabled
- tempreg |= (uint32_t)0x76; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz
+ tempreg |= SDIO_INIT_CLK_DIV; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz
// Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable
SDIO->CLKCR = tempreg;
// Power up the SDIO
- SDIO->POWER = 0x03;
+ SDIO_PowerState_ON(SDIO);
+ hsd.Instance = SDIO;
}
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { // application specific init
- UNUSED(hsd); /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd); // Prevent unused argument(s) compilation warning
__HAL_RCC_SDIO_CLK_ENABLE(); // turn on SDIO clock
}
- constexpr uint8_t SD_RETRY_COUNT = TERN(SD_CHECK_AND_RETRY, 3, 1);
-
bool SDIO_Init() {
- //init SDIO and get SD card info
-
- uint8_t retryCnt = SD_RETRY_COUNT;
+ uint8_t retryCnt = SDIO_READ_RETRIES;
bool status;
hsd.Instance = SDIO;
- hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET
-
- /*
- hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
- hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
- hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
- hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
- hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
- hsd.Init.ClockDiv = 8;
- */
+ hsd.State = HAL_SD_STATE_RESET;
SD_LowLevel_Init();
@@ -216,106 +266,81 @@
if (!status) break;
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
}
+ go_to_transfer_speed();
}
#endif
return true;
}
- /*
- void init_SDIO_pins(void) {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- // SDIO GPIO Configuration
- // PC8 ------> SDIO_D0
- // PC12 ------> SDIO_CK
- // PD2 ------> SDIO_CMD
+ static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) {
+ if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false;
- GPIO_InitStruct.Pin = GPIO_PIN_8;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+ TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
- GPIO_InitStruct.Pin = GPIO_PIN_12;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
-
- GPIO_InitStruct.Pin = GPIO_PIN_2;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
- HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
- }
- */
- //bool SDIO_init() { return (bool) (SD_SDIO_Init() ? 1 : 0);}
- //bool SDIO_Init_C() { return (bool) (SD_SDIO_Init() ? 1 : 0);}
-
- bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
- hsd.Instance = SDIO;
- uint8_t retryCnt = SD_RETRY_COUNT;
-
- bool status;
- for (;;) {
- TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
- status = (bool) HAL_SD_ReadBlocks(&hsd, (uint8_t*)dst, block, 1, 1000); // read one 512 byte block with 500mS timeout
- status |= (bool) HAL_SD_GetCardState(&hsd); // make sure all is OK
- if (!status) break; // return passing status
- if (!--retryCnt) break; // return failing status if retries are exhausted
+ HAL_StatusTypeDef ret;
+ if (src) {
+ hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH;
+ HAL_DMA_Init(&hdma_sdio);
+ ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)src, block, 1);
+ }
+ else {
+ hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ HAL_DMA_Init(&hdma_sdio);
+ ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)dst, block, 1);
}
- return status;
- /*
- return (bool) ((status_read | status_card) ? 1 : 0);
-
- if (SDIO_GetCardState() != SDIO_CARD_TRANSFER) return false;
- if (blockAddress >= SdCard.LogBlockNbr) return false;
- if ((0x03 & (uint32_t)data)) return false; // misaligned data
-
- if (SdCard.CardType != CARD_SDHC_SDXC) { blockAddress *= 512U; }
-
- if (!SDIO_CmdReadSingleBlock(blockAddress)) {
- SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS);
- dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL);
+ if (ret != HAL_OK) {
+ HAL_DMA_Abort_IT(&hdma_sdio);
+ HAL_DMA_DeInit(&hdma_sdio);
return false;
}
- while (!SDIO_GET_FLAG(SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS)) {}
-
- dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL);
-
- if (SDIO->STA & SDIO_STA_RXDAVL) {
- while (SDIO->STA & SDIO_STA_RXDAVL) (void)SDIO->FIFO;
- SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS);
- return false;
+ millis_t timeout = millis() + 500;
+ // Wait the transfer
+ while (hsd.State != HAL_SD_STATE_READY) {
+ if (ELAPSED(millis(), timeout)) {
+ HAL_DMA_Abort_IT(&hdma_sdio);
+ HAL_DMA_DeInit(&hdma_sdio);
+ return false;
+ }
}
- if (SDIO_GET_FLAG(SDIO_STA_TRX_ERROR_FLAGS)) {
- SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS);
- return false;
- }
- SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS);
- */
+ while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0
+ || __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ }
+
+ HAL_DMA_Abort_IT(&hdma_sdio);
+ HAL_DMA_DeInit(&hdma_sdio);
+
+ timeout = millis() + 500;
+ while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false;
return true;
}
- bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
- hsd.Instance = SDIO;
- uint8_t retryCnt = SD_RETRY_COUNT;
- bool status;
- for (;;) {
- status = (bool) HAL_SD_WriteBlocks(&hsd, (uint8_t*)src, block, 1, 500); // write one 512 byte block with 500mS timeout
- status |= (bool) HAL_SD_GetCardState(&hsd); // make sure all is OK
- if (!status) break; // return passing status
- if (!--retryCnt) break; // return failing status if retries are exhausted
- }
- return status;
+ bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
+ uint8_t retries = SDIO_READ_RETRIES;
+ while (retries--) if (SDIO_ReadWriteBlock_DMA(block, NULL, dst)) return true;
+ return false;
}
+ bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
+ uint8_t retries = SDIO_READ_RETRIES;
+ while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, NULL)) return true;
+ return false;
+ }
+
+ #if defined(STM32F1xx)
+ #define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler
+ #elif defined(STM32F4xx)
+ #define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler
+ #else
+ #error "Unknown STM32 architecture."
+ #endif
+
+ extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
+ extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); }
+
#endif // !USBD_USE_CDC_COMPOSITE
#endif // SDIO_SUPPORT
+#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/eeprom_flash.cpp b/Marlin/src/HAL/STM32/eeprom_flash.cpp
index 0933b9f4e..5862090f1 100644
--- a/Marlin/src/HAL/STM32/eeprom_flash.cpp
+++ b/Marlin/src/HAL/STM32/eeprom_flash.cpp
@@ -28,15 +28,6 @@
#include "../shared/eeprom_api.h"
-#if HAS_SERVOS
- #include "Servo.h"
- #define PAUSE_SERVO_OUTPUT() libServo::pause_all_servos()
- #define RESUME_SERVO_OUTPUT() libServo::resume_all_servos()
-#else
- #define PAUSE_SERVO_OUTPUT()
- #define RESUME_SERVO_OUTPUT()
-#endif
-
/**
* The STM32 HAL supports chips that deal with "pages" and some with "sectors" and some that
* even have multiple "banks" of flash.
@@ -57,7 +48,7 @@
#include "stm32_def.h"
#define DEBUG_OUT ENABLED(EEPROM_CHITCHAT)
- #include "src/core/debug_out.h"
+ #include "../../core/debug_out.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
@@ -70,7 +61,9 @@
#define FLASH_UNIT_SIZE 0x20000 // 128kB
#endif
- #define FLASH_ADDRESS_START (FLASH_END - ((FLASH_SECTOR_TOTAL - (FLASH_SECTOR)) * (FLASH_UNIT_SIZE)) + 1)
+ #ifndef FLASH_ADDRESS_START
+ #define FLASH_ADDRESS_START (FLASH_END - ((FLASH_SECTOR_TOTAL - (FLASH_SECTOR)) * (FLASH_UNIT_SIZE)) + 1)
+ #endif
#define FLASH_ADDRESS_END (FLASH_ADDRESS_START + FLASH_UNIT_SIZE - 1)
#define EEPROM_SLOTS ((FLASH_UNIT_SIZE) / (MARLIN_EEPROM_SIZE))
@@ -113,7 +106,7 @@ bool PersistentStore::access_start() {
// This must be the first time since power on that we have accessed the storage, or someone
// loaded and called write_data and never called access_finish.
// Lets go looking for the slot that holds our configuration.
- if (eeprom_data_written) DEBUG_ECHOLN("Dangling EEPROM write_data");
+ if (eeprom_data_written) DEBUG_ECHOLNPGM("Dangling EEPROM write_data");
uint32_t address = FLASH_ADDRESS_START;
while (address <= FLASH_ADDRESS_END) {
uint32_t address_value = (*(__IO uint32_t*)address);
@@ -172,11 +165,11 @@ bool PersistentStore::access_finish() {
current_slot = EEPROM_SLOTS - 1;
UNLOCK_FLASH();
- PAUSE_SERVO_OUTPUT();
+ TERN_(HAS_PAUSE_SERVO_OUTPUT, PAUSE_SERVO_OUTPUT());
DISABLE_ISRS();
status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
ENABLE_ISRS();
- RESUME_SERVO_OUTPUT();
+ TERN_(HAS_PAUSE_SERVO_OUTPUT, RESUME_SERVO_OUTPUT());
if (status != HAL_OK) {
DEBUG_ECHOLNPAIR("HAL_FLASHEx_Erase=", status);
DEBUG_ECHOLNPAIR("GetError=", HAL_FLASH_GetError());
@@ -227,11 +220,11 @@ bool PersistentStore::access_finish() {
// Interrupts during this time can have unpredictable results, such as killing Servo
// output. Servo output still glitches with interrupts disabled, but recovers after the
// erase.
- PAUSE_SERVO_OUTPUT();
+ TERN_(HAS_PAUSE_SERVO_OUTPUT, PAUSE_SERVO_OUTPUT());
DISABLE_ISRS();
eeprom_buffer_flush();
ENABLE_ISRS();
- RESUME_SERVO_OUTPUT();
+ TERN_(HAS_PAUSE_SERVO_OUTPUT, RESUME_SERVO_OUTPUT());
eeprom_data_written = false;
#endif
@@ -261,7 +254,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
const uint8_t c = TERN(FLASH_EEPROM_LEVELING, ram_eeprom[pos], eeprom_buffered_read_byte(pos));
if (writing) *value = c;
diff --git a/Marlin/src/HAL/STM32/eeprom_sdcard.cpp b/Marlin/src/HAL/STM32/eeprom_sdcard.cpp
index 711a83ed5..f811468fb 100644
--- a/Marlin/src/HAL/STM32/eeprom_sdcard.cpp
+++ b/Marlin/src/HAL/STM32/eeprom_sdcard.cpp
@@ -19,13 +19,12 @@
* along with this program. If not, see .
*
*/
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
/**
* Implementation of EEPROM settings in SD Card
*/
-#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
-
#include "../../inc/MarlinConfig.h"
#if ENABLED(SDCARD_EEPROM_EMULATION)
@@ -78,7 +77,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
for (size_t i = 0; i < size; i++) {
uint8_t c = HAL_eeprom_data[pos + i];
if (writing) value[i] = c;
@@ -89,4 +88,4 @@ bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uin
}
#endif // SDCARD_EEPROM_EMULATION
-#endif // STM32 && !STM32GENERIC
+#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/eeprom_sram.cpp b/Marlin/src/HAL/STM32/eeprom_sram.cpp
index 5f6f26f9c..135bcabde 100644
--- a/Marlin/src/HAL/STM32/eeprom_sram.cpp
+++ b/Marlin/src/HAL/STM32/eeprom_sram.cpp
@@ -52,7 +52,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
// Read from either external EEPROM, program flash or Backup SRAM
const uint8_t c = ( *(__IO uint8_t *)(BKPSRAM_BASE + ((uint8_t*)pos)) );
diff --git a/Marlin/src/HAL/STM32/eeprom_wired.cpp b/Marlin/src/HAL/STM32/eeprom_wired.cpp
index 8c46e45f0..6aa2f1d36 100644
--- a/Marlin/src/HAL/STM32/eeprom_wired.cpp
+++ b/Marlin/src/HAL/STM32/eeprom_wired.cpp
@@ -43,29 +43,26 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t v = *value;
-
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
uint8_t * const p = (uint8_t * const)pos;
- if (v != eeprom_read_byte(p)) {
+ if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
}
}
-
crc16(crc, &v, 1);
pos++;
value++;
- };
-
+ }
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
// Read from either external EEPROM, program flash or Backup SRAM
const uint8_t c = eeprom_read_byte((uint8_t*)pos);
diff --git a/Marlin/src/HAL/STM32/fast_pwm.cpp b/Marlin/src/HAL/STM32/fast_pwm.cpp
new file mode 100644
index 000000000..42eecb5e1
--- /dev/null
+++ b/Marlin/src/HAL/STM32/fast_pwm.cpp
@@ -0,0 +1,59 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if NEEDS_HARDWARE_PWM
+
+#include "HAL.h"
+#include "timers.h"
+
+void set_pwm_frequency(const pin_t pin, int f_desired) {
+ if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
+
+ PinName pin_name = digitalPinToPinName(pin);
+ TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance
+
+ LOOP_S_L_N(i, 0, NUM_HARDWARE_TIMERS) // Protect used timers
+ if (timer_instance[i] && timer_instance[i]->getHandle()->Instance == Instance)
+ return;
+
+ pwm_start(pin_name, f_desired, 0, RESOLUTION_8B_COMPARE_FORMAT);
+}
+
+void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
+ PinName pin_name = digitalPinToPinName(pin);
+ TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM);
+ uint16_t adj_val = Instance->ARR * v / v_size;
+ if (invert) adj_val = Instance->ARR - adj_val;
+
+ switch (get_pwm_channel(pin_name)) {
+ case TIM_CHANNEL_1: LL_TIM_OC_SetCompareCH1(Instance, adj_val); break;
+ case TIM_CHANNEL_2: LL_TIM_OC_SetCompareCH2(Instance, adj_val); break;
+ case TIM_CHANNEL_3: LL_TIM_OC_SetCompareCH3(Instance, adj_val); break;
+ case TIM_CHANNEL_4: LL_TIM_OC_SetCompareCH4(Instance, adj_val); break;
+ }
+}
+
+#endif // NEEDS_HARDWARE_PWM
+#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/fastio.h b/Marlin/src/HAL/STM32/fastio.h
index ea28b8f3b..17751c44d 100644
--- a/Marlin/src/HAL/STM32/fastio.h
+++ b/Marlin/src/HAL/STM32/fastio.h
@@ -59,7 +59,7 @@ void FastIO_init(); // Must be called before using fast io macros
#endif
#define _READ(IO) bool(READ_BIT(FastIOPortMap[STM_PORT(digitalPinToPinName(IO))]->IDR, _BV32(STM_PIN(digitalPinToPinName(IO)))))
-#define _TOGGLE(IO) (FastIOPortMap[STM_PORT(digitalPinToPinName(IO))]->ODR ^= _BV32(STM_PIN(digitalPinToPinName(IO))))
+#define _TOGGLE(IO) TBI32(FastIOPortMap[STM_PORT(digitalPinToPinName(IO))]->ODR, STM_PIN(digitalPinToPinName(IO)))
#define _GET_MODE(IO)
#define _SET_MODE(IO,M) pinMode(IO, M)
diff --git a/Marlin/src/HAL/STM32/inc/Conditionals_adv.h b/Marlin/src/HAL/STM32/inc/Conditionals_adv.h
index 5f1c4b160..9c9a7014c 100644
--- a/Marlin/src/HAL/STM32/inc/Conditionals_adv.h
+++ b/Marlin/src/HAL/STM32/inc/Conditionals_adv.h
@@ -20,3 +20,13 @@
*
*/
#pragma once
+
+#if defined(USBD_USE_CDC_MSC) && DISABLED(NO_SD_HOST_DRIVE)
+ #define HAS_SD_HOST_DRIVE 1
+#endif
+
+// Fix F_CPU not being a compile-time constant in STSTM32 framework
+#ifdef BOARD_F_CPU
+ #undef F_CPU
+ #define F_CPU BOARD_F_CPU
+#endif
diff --git a/Marlin/src/HAL/STM32/inc/SanityCheck.h b/Marlin/src/HAL/STM32/inc/SanityCheck.h
index 30d0750d9..12ff2abec 100644
--- a/Marlin/src/HAL/STM32/inc/SanityCheck.h
+++ b/Marlin/src/HAL/STM32/inc/SanityCheck.h
@@ -28,9 +28,6 @@
// #error "SPINDLE_LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
//#endif
-#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
- #error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on STM32."
-#endif
#if ENABLED(SDCARD_EEPROM_EMULATION) && DISABLED(SDSUPPORT)
#undef SDCARD_EEPROM_EMULATION // Avoid additional error noise
@@ -50,7 +47,11 @@
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- #error "SERIAL_STATS_MAX_RX_QUEUED is not supported on this platform."
+ #error "SERIAL_STATS_MAX_RX_QUEUED is not supported on STM32."
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
- #error "SERIAL_STATS_DROPPED_RX is not supported on this platform."
+ #error "SERIAL_STATS_DROPPED_RX is not supported on STM32."
+#endif
+
+#if ANY(TFT_COLOR_UI, TFT_LVGL_UI, TFT_CLASSIC_UI) && NOT_TARGET(STM32H7xx, STM32F4xx, STM32F1xx)
+ #error "TFT_COLOR_UI, TFT_LVGL_UI and TFT_CLASSIC_UI are currently only supported on STM32H7, STM32F4 and STM32F1 hardware."
#endif
diff --git a/Marlin/src/HAL/STM32/msc_sd.cpp b/Marlin/src/HAL/STM32/msc_sd.cpp
new file mode 100644
index 000000000..20e1ab3cf
--- /dev/null
+++ b/Marlin/src/HAL/STM32/msc_sd.cpp
@@ -0,0 +1,124 @@
+/**
+ * Marlin 3D Printer Firmware
+ *
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech]
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#include "../../inc/MarlinConfigPre.h"
+
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) && HAS_SD_HOST_DRIVE
+
+#include "msc_sd.h"
+#include "../shared/Marduino.h"
+#include "usbd_core.h"
+#include
+#include
+
+#define BLOCK_SIZE 512
+#define PRODUCT_ID 0x29
+
+#include "../../sd/cardreader.h"
+
+class Sd2CardUSBMscHandler : public USBMscHandler {
+public:
+ DiskIODriver* diskIODriver() {
+ #if ENABLED(MULTI_VOLUME)
+ #if SHARED_VOLUME_IS(SD_ONBOARD)
+ return &card.media_sd_spi;
+ #elif SHARED_VOLUME_IS(USB_FLASH_DRIVE)
+ return &card.media_usbFlashDrive;
+ #endif
+ #else
+ return diskIODriver();
+ #endif
+ }
+
+ bool GetCapacity(uint32_t *pBlockNum, uint16_t *pBlockSize) {
+ *pBlockNum = diskIODriver()->cardSize();
+ *pBlockSize = BLOCK_SIZE;
+ return true;
+ }
+
+ bool Write(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
+ auto sd2card = diskIODriver();
+ // single block
+ if (blkLen == 1) {
+ watchdog_refresh();
+ sd2card->writeBlock(blkAddr, pBuf);
+ return true;
+ }
+
+ // multi block optmization
+ sd2card->writeStart(blkAddr, blkLen);
+ while (blkLen--) {
+ watchdog_refresh();
+ sd2card->writeData(pBuf);
+ pBuf += BLOCK_SIZE;
+ }
+ sd2card->writeStop();
+ return true;
+ }
+
+ bool Read(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
+ auto sd2card = diskIODriver();
+ // single block
+ if (blkLen == 1) {
+ watchdog_refresh();
+ sd2card->readBlock(blkAddr, pBuf);
+ return true;
+ }
+
+ // multi block optmization
+ sd2card->readStart(blkAddr);
+ while (blkLen--) {
+ watchdog_refresh();
+ sd2card->readData(pBuf);
+ pBuf += BLOCK_SIZE;
+ }
+ sd2card->readStop();
+ return true;
+ }
+
+ bool IsReady() {
+ return diskIODriver()->isReady();
+ }
+};
+
+Sd2CardUSBMscHandler usbMscHandler;
+
+/* USB Mass storage Standard Inquiry Data */
+uint8_t Marlin_STORAGE_Inquirydata[] = { /* 36 */
+ /* LUN 0 */
+ 0x00,
+ 0x80,
+ 0x02,
+ 0x02,
+ (STANDARD_INQUIRY_DATA_LEN - 5),
+ 0x00,
+ 0x00,
+ 0x00,
+ 'M', 'A', 'R', 'L', 'I', 'N', ' ', ' ', /* Manufacturer : 8 bytes */
+ 'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ '0', '.', '0', '1', /* Version : 4 Bytes */
+};
+
+USBMscHandler *pSingleMscHandler = &usbMscHandler;
+
+void MSC_SD_init() {
+ USBDevice.end();
+ delay(200);
+ USBDevice.registerMscHandlers(1, &pSingleMscHandler, Marlin_STORAGE_Inquirydata);
+ USBDevice.begin();
+}
+
+#endif // __STM32F1__ && HAS_SD_HOST_DRIVE
diff --git a/Marlin/src/HAL/STM32/msc_sd.h b/Marlin/src/HAL/STM32/msc_sd.h
new file mode 100644
index 000000000..a8e5349f7
--- /dev/null
+++ b/Marlin/src/HAL/STM32/msc_sd.h
@@ -0,0 +1,18 @@
+/**
+ * Marlin 3D Printer Firmware
+ *
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech]
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+void MSC_SD_init();
diff --git a/Marlin/src/HAL/STM32/pinsDebug.h b/Marlin/src/HAL/STM32/pinsDebug.h
index ec08e3fd7..048f788e3 100644
--- a/Marlin/src/HAL/STM32/pinsDebug.h
+++ b/Marlin/src/HAL/STM32/pinsDebug.h
@@ -18,17 +18,247 @@
*/
#pragma once
-#if !(defined(NUM_DIGITAL_PINS) || defined(BOARD_NR_GPIO_PINS))
- #error "M43 not supported for this board"
+#include
+
+#ifndef NUM_DIGITAL_PINS
+ // Only in ST's Arduino core (STM32duino, STM32Core)
+ #error "Expected NUM_DIGITAL_PINS not found"
#endif
-// Strange - STM32F4 comes to HAL_STM32 rather than HAL_STM32F4 for these files
-#ifdef STM32F4
- #ifdef NUM_DIGITAL_PINS // Only in ST's Arduino core (STM32duino, STM32Core)
- #include "pinsDebug_STM32duino.h"
- #elif defined(BOARD_NR_GPIO_PINS) // Only in STM32GENERIC (Maple)
- #include "pinsDebug_STM32GENERIC.h"
+/**
+ * Life gets complicated if you want an easy to use 'M43 I' output (in port/pin order)
+ * because the variants in this platform do not always define all the I/O port/pins
+ * that a CPU has.
+ *
+ * VARIABLES:
+ * Ard_num - Arduino pin number - defined by the platform. It is used by digitalRead and
+ * digitalWrite commands and by M42.
+ * - does not contain port/pin info
+ * - is not in port/pin order
+ * - typically a variant will only assign Ard_num to port/pins that are actually used
+ * Index - M43 counter - only used to get Ard_num
+ * x - a parameter/argument used to search the pin_array to try to find a signal name
+ * associated with a Ard_num
+ * Port_pin - port number and pin number for use with CPU registers and printing reports
+ *
+ * Since M43 uses digitalRead and digitalWrite commands, only the Port_pins with an Ard_num
+ * are accessed and/or displayed.
+ *
+ * Three arrays are used.
+ *
+ * digitalPin[] is provided by the platform. It consists of the Port_pin numbers in
+ * Arduino pin number order.
+ *
+ * pin_array is a structure generated by the pins/pinsDebug.h header file. It is generated by
+ * the preprocessor. Only the signals associated with enabled options are in this table.
+ * It contains:
+ * - name of the signal
+ * - the Ard_num assigned by the pins_YOUR_BOARD.h file using the platform defines.
+ * EXAMPLE: "#define KILL_PIN PB1" results in Ard_num of 57. 57 is then used as the
+ * argument to digitalPinToPinName(IO) to get the Port_pin number
+ * - if it is a digital or analog signal. PWMs are considered digital here.
+ *
+ * pin_xref is a structure generated by this header file. It is generated by the
+ * preprocessor. It is in port/pin order. It contains just the port/pin numbers defined by the
+ * platform for this variant.
+ * - Ard_num
+ * - printable version of Port_pin
+ *
+ * Routines with an "x" as a parameter/argument are used to search the pin_array to try to
+ * find a signal name associated with a port/pin.
+ *
+ * NOTE - the Arduino pin number is what is used by the M42 command, NOT the port/pin for that
+ * signal. The Arduino pin number is listed by the M43 I command.
+ */
+
+////////////////////////////////////////////////////////
+//
+// make a list of the Arduino pin numbers in the Port/Pin order
+//
+
+#define _PIN_ADD_2(NAME_ALPHA, ARDUINO_NUM) { {NAME_ALPHA}, ARDUINO_NUM },
+#define _PIN_ADD(NAME_ALPHA, ARDUINO_NUM) { NAME_ALPHA, ARDUINO_NUM },
+#define PIN_ADD(NAME) _PIN_ADD(#NAME, NAME)
+
+typedef struct {
+ char Port_pin_alpha[5];
+ pin_t Ard_num;
+} XrefInfo;
+
+const XrefInfo pin_xref[] PROGMEM = {
+ #include "pins_Xref.h"
+};
+
+////////////////////////////////////////////////////////////
+
+#define MODE_PIN_INPUT 0 // Input mode (reset state)
+#define MODE_PIN_OUTPUT 1 // General purpose output mode
+#define MODE_PIN_ALT 2 // Alternate function mode
+#define MODE_PIN_ANALOG 3 // Analog mode
+
+#define PIN_NUM(P) (P & 0x000F)
+#define PIN_NUM_ALPHA_LEFT(P) (((P & 0x000F) < 10) ? ('0' + (P & 0x000F)) : '1')
+#define PIN_NUM_ALPHA_RIGHT(P) (((P & 0x000F) > 9) ? ('0' + (P & 0x000F) - 10) : 0 )
+#define PORT_NUM(P) ((P >> 4) & 0x0007)
+#define PORT_ALPHA(P) ('A' + (P >> 4))
+
+/**
+ * Translation of routines & variables used by pinsDebug.h
+ */
+#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
+#define VALID_PIN(ANUM) ((ANUM) >= 0 && (ANUM) < NUMBER_PINS_TOTAL)
+#define digitalRead_mod(Ard_num) extDigitalRead(Ard_num) // must use Arduino pin numbers when doing reads
+#define PRINT_PIN(Q)
+#define PRINT_PORT(ANUM) port_print(ANUM)
+#define DIGITAL_PIN_TO_ANALOG_PIN(ANUM) -1 // will report analog pin number in the print port routine
+#define GET_PIN_MAP_PIN_M43(Index) pin_xref[Index].Ard_num
+
+// x is a variable used to search pin_array
+#define GET_ARRAY_IS_DIGITAL(x) ((bool) pin_array[x].is_digital)
+#define GET_ARRAY_PIN(x) ((pin_t) pin_array[x].pin)
+#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
+#define MULTI_NAME_PAD 33 // space needed to be pretty if not first name assigned to a pin
+
+#ifndef M43_NEVER_TOUCH
+ #define _M43_NEVER_TOUCH(Index) (Index >= 9 && Index <= 12) // SERIAL/USB pins: PA9(TX) PA10(RX) PA11(USB_DM) PA12(USB_DP)
+ #ifdef KILL_PIN
+ #define M43_NEVER_TOUCH(Index) m43_never_touch(Index)
+
+ bool m43_never_touch(const pin_t Index) {
+ static pin_t M43_kill_index = -1;
+ if (M43_kill_index < 0)
+ for (M43_kill_index = 0; M43_kill_index < NUMBER_PINS_TOTAL; M43_kill_index++)
+ if (KILL_PIN == GET_PIN_MAP_PIN_M43(M43_kill_index)) break;
+ return _M43_NEVER_TOUCH(Index) || Index == M43_kill_index; // KILL_PIN and SERIAL/USB
+ }
#else
- #error "M43 not supported for this board"
+ #define M43_NEVER_TOUCH(Index) _M43_NEVER_TOUCH(Index)
#endif
#endif
+
+uint8_t get_pin_mode(const pin_t Ard_num) {
+ const PinName dp = digitalPinToPinName(Ard_num);
+ uint32_t ll_pin = STM_LL_GPIO_PIN(dp);
+ GPIO_TypeDef *port = get_GPIO_Port(STM_PORT(dp));
+ uint32_t mode = LL_GPIO_GetPinMode(port, ll_pin);
+ switch (mode) {
+ case LL_GPIO_MODE_ANALOG: return MODE_PIN_ANALOG;
+ case LL_GPIO_MODE_INPUT: return MODE_PIN_INPUT;
+ case LL_GPIO_MODE_OUTPUT: return MODE_PIN_OUTPUT;
+ case LL_GPIO_MODE_ALTERNATE: return MODE_PIN_ALT;
+ TERN_(STM32F1xx, case LL_GPIO_MODE_FLOATING:)
+ default: return 0;
+ }
+}
+
+bool GET_PINMODE(const pin_t Ard_num) {
+ const uint8_t pin_mode = get_pin_mode(Ard_num);
+ return pin_mode == MODE_PIN_OUTPUT || pin_mode == MODE_PIN_ALT; // assume all alt definitions are PWM
+}
+
+int8_t digital_pin_to_analog_pin(pin_t Ard_num) {
+ Ard_num -= NUM_ANALOG_FIRST;
+ return (Ard_num >= 0 && Ard_num < NUM_ANALOG_INPUTS) ? Ard_num : -1;
+}
+
+bool IS_ANALOG(const pin_t Ard_num) {
+ return get_pin_mode(Ard_num) == MODE_PIN_ANALOG;
+}
+
+bool is_digital(const pin_t x) {
+ const uint8_t pin_mode = get_pin_mode(pin_array[x].pin);
+ return pin_mode == MODE_PIN_INPUT || pin_mode == MODE_PIN_OUTPUT;
+}
+
+void port_print(const pin_t Ard_num) {
+ char buffer[16];
+ pin_t Index;
+ for (Index = 0; Index < NUMBER_PINS_TOTAL; Index++)
+ if (Ard_num == GET_PIN_MAP_PIN_M43(Index)) break;
+
+ const char * ppa = pin_xref[Index].Port_pin_alpha;
+ sprintf_P(buffer, PSTR("%s"), ppa);
+ SERIAL_ECHO(buffer);
+ if (ppa[3] == '\0') SERIAL_CHAR(' ');
+
+ // print analog pin number
+ const int8_t Port_pin = digital_pin_to_analog_pin(Ard_num);
+ if (Port_pin >= 0) {
+ sprintf_P(buffer, PSTR(" (A%d) "), Port_pin);
+ SERIAL_ECHO(buffer);
+ if (Port_pin < 10) SERIAL_CHAR(' ');
+ }
+ else
+ SERIAL_ECHO_SP(7);
+
+ // Print number to be used with M42
+ sprintf_P(buffer, PSTR(" M42 P%d "), Ard_num);
+ SERIAL_ECHO(buffer);
+ if (Ard_num < 10) SERIAL_CHAR(' ');
+ if (Ard_num < 100) SERIAL_CHAR(' ');
+}
+
+bool pwm_status(const pin_t Ard_num) {
+ return get_pin_mode(Ard_num) == MODE_PIN_ALT;
+}
+
+void pwm_details(const pin_t Ard_num) {
+ #ifndef STM32F1xx
+ if (pwm_status(Ard_num)) {
+ uint32_t alt_all = 0;
+ const PinName dp = digitalPinToPinName(Ard_num);
+ pin_t pin_number = uint8_t(PIN_NUM(dp));
+ const bool over_7 = pin_number >= 8;
+ const uint8_t ind = over_7 ? 1 : 0;
+ switch (PORT_ALPHA(dp)) { // get alt function
+ case 'A' : alt_all = GPIOA->AFR[ind]; break;
+ case 'B' : alt_all = GPIOB->AFR[ind]; break;
+ case 'C' : alt_all = GPIOC->AFR[ind]; break;
+ case 'D' : alt_all = GPIOD->AFR[ind]; break;
+ #ifdef PE_0
+ case 'E' : alt_all = GPIOE->AFR[ind]; break;
+ #elif defined (PF_0)
+ case 'F' : alt_all = GPIOF->AFR[ind]; break;
+ #elif defined (PG_0)
+ case 'G' : alt_all = GPIOG->AFR[ind]; break;
+ #elif defined (PH_0)
+ case 'H' : alt_all = GPIOH->AFR[ind]; break;
+ #elif defined (PI_0)
+ case 'I' : alt_all = GPIOI->AFR[ind]; break;
+ #elif defined (PJ_0)
+ case 'J' : alt_all = GPIOJ->AFR[ind]; break;
+ #elif defined (PK_0)
+ case 'K' : alt_all = GPIOK->AFR[ind]; break;
+ #elif defined (PL_0)
+ case 'L' : alt_all = GPIOL->AFR[ind]; break;
+ #endif
+ }
+ if (over_7) pin_number -= 8;
+
+ uint8_t alt_func = (alt_all >> (4 * pin_number)) & 0x0F;
+ SERIAL_ECHOPAIR("Alt Function: ", alt_func);
+ if (alt_func < 10) SERIAL_CHAR(' ');
+ SERIAL_ECHOPGM(" - ");
+ switch (alt_func) {
+ case 0 : SERIAL_ECHOPGM("system (misc. I/O)"); break;
+ case 1 : SERIAL_ECHOPGM("TIM1/TIM2 (probably PWM)"); break;
+ case 2 : SERIAL_ECHOPGM("TIM3..5 (probably PWM)"); break;
+ case 3 : SERIAL_ECHOPGM("TIM8..11 (probably PWM)"); break;
+ case 4 : SERIAL_ECHOPGM("I2C1..3"); break;
+ case 5 : SERIAL_ECHOPGM("SPI1/SPI2"); break;
+ case 6 : SERIAL_ECHOPGM("SPI3"); break;
+ case 7 : SERIAL_ECHOPGM("USART1..3"); break;
+ case 8 : SERIAL_ECHOPGM("USART4..6"); break;
+ case 9 : SERIAL_ECHOPGM("CAN1/CAN2, TIM12..14 (probably PWM)"); break;
+ case 10 : SERIAL_ECHOPGM("OTG"); break;
+ case 11 : SERIAL_ECHOPGM("ETH"); break;
+ case 12 : SERIAL_ECHOPGM("FSMC, SDIO, OTG"); break;
+ case 13 : SERIAL_ECHOPGM("DCMI"); break;
+ case 14 : SERIAL_ECHOPGM("unused (shouldn't see this)"); break;
+ case 15 : SERIAL_ECHOPGM("EVENTOUT"); break;
+ }
+ }
+ #else
+ // TODO: F1 doesn't support changing pins function, so we need to check the function of the PIN and if it's enabled
+ #endif
+} // pwm_details
diff --git a/Marlin/src/HAL/STM32/pinsDebug_STM32GENERIC.h b/Marlin/src/HAL/STM32/pinsDebug_STM32GENERIC.h
deleted file mode 100644
index 9069d9f7b..000000000
--- a/Marlin/src/HAL/STM32/pinsDebug_STM32GENERIC.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#pragma once
-
-/**
- * Support routines for STM32GENERIC (Maple)
- */
-
-/**
- * Translation of routines & variables used by pinsDebug.h
- */
-
-#ifdef BOARD_NR_GPIO_PINS // Only in STM32GENERIC (Maple)
-
-#ifdef __STM32F1__
- #include "../STM32F1/fastio.h"
-#elif defined(STM32F4) || defined(STM32F7)
- #include "../STM32_F4_F7/fastio.h"
-#else
- #include "fastio.h"
-#endif
-
-extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS];
-
-#define NUM_DIGITAL_PINS BOARD_NR_GPIO_PINS
-#define NUMBER_PINS_TOTAL BOARD_NR_GPIO_PINS
-#define VALID_PIN(pin) (pin >= 0 && pin < BOARD_NR_GPIO_PINS)
-#define GET_ARRAY_PIN(p) pin_t(pin_array[p].pin)
-#define pwm_status(pin) PWM_PIN(pin)
-#define digitalRead_mod(p) extDigitalRead(p)
-#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3hd "), int16_t(p)); SERIAL_ECHO(buffer); }while(0)
-#define PRINT_PORT(p) print_port(p)
-#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
-#define MULTI_NAME_PAD 21 // space needed to be pretty if not first name assigned to a pin
-
-// pins that will cause hang/reset/disconnect in M43 Toggle and Watch utilities
-#ifndef M43_NEVER_TOUCH
- #define M43_NEVER_TOUCH(Q) (Q >= 9 && Q <= 12) // SERIAL/USB pins PA9(TX) PA10(RX)
-#endif
-
-static inline int8_t get_pin_mode(pin_t pin) {
- return VALID_PIN(pin) ? _GET_MODE(pin) : -1;
-}
-
-static inline pin_t DIGITAL_PIN_TO_ANALOG_PIN(pin_t pin) {
- if (!VALID_PIN(pin)) return -1;
- int8_t adc_channel = int8_t(PIN_MAP[pin].adc_channel);
- #ifdef NUM_ANALOG_INPUTS
- if (adc_channel >= NUM_ANALOG_INPUTS) adc_channel = ADCx;
- #endif
- return pin_t(adc_channel);
-}
-
-static inline bool IS_ANALOG(pin_t pin) {
- if (!VALID_PIN(pin)) return false;
- if (PIN_MAP[pin].adc_channel != ADCx) {
- #ifdef NUM_ANALOG_INPUTS
- if (PIN_MAP[pin].adc_channel >= NUM_ANALOG_INPUTS) return false;
- #endif
- return _GET_MODE(pin) == GPIO_INPUT_ANALOG && !M43_NEVER_TOUCH(pin);
- }
- return false;
-}
-
-static inline bool GET_PINMODE(const pin_t pin) {
- return VALID_PIN(pin) && !IS_INPUT(pin);
-}
-
-static inline bool GET_ARRAY_IS_DIGITAL(const int16_t array_pin) {
- const pin_t pin = GET_ARRAY_PIN(array_pin);
- return (!IS_ANALOG(pin)
- #ifdef NUM_ANALOG_INPUTS
- || PIN_MAP[pin].adc_channel >= NUM_ANALOG_INPUTS
- #endif
- );
-}
-
-#include "../../inc/MarlinConfig.h" // Allow pins/pins.h to set density
-
-static inline void pwm_details(const pin_t pin) {
- if (PWM_PIN(pin)) {
- timer_dev * const tdev = PIN_MAP[pin].timer_device;
- const uint8_t channel = PIN_MAP[pin].timer_channel;
- const char num = (
- #if EITHER(STM32_HIGH_DENSITY, STM32_XL_DENSITY)
- tdev == &timer8 ? '8' :
- tdev == &timer5 ? '5' :
- #endif
- tdev == &timer4 ? '4' :
- tdev == &timer3 ? '3' :
- tdev == &timer2 ? '2' :
- tdev == &timer1 ? '1' : '?'
- );
- char buffer[10];
- sprintf_P(buffer, PSTR(" TIM%c CH%c"), num, ('0' + channel));
- SERIAL_ECHO(buffer);
- }
-}
-
-static inline void print_port(pin_t pin) {
- const char port = 'A' + char(pin >> 4); // pin div 16
- const int16_t gbit = PIN_MAP[pin].gpio_bit;
- char buffer[8];
- sprintf_P(buffer, PSTR("P%c%hd "), port, gbit);
- if (gbit < 10) SERIAL_CHAR(' ');
- SERIAL_ECHO(buffer);
-}
-
-#endif // BOARD_NR_GPIO_PINS
diff --git a/Marlin/src/HAL/STM32/pinsDebug_STM32duino.h b/Marlin/src/HAL/STM32/pinsDebug_STM32duino.h
deleted file mode 100644
index 71480153a..000000000
--- a/Marlin/src/HAL/STM32/pinsDebug_STM32duino.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#pragma once
-
-#include
-
-#ifdef NUM_DIGITAL_PINS // Only in ST's Arduino core (STM32duino, STM32Core)
-
-/**
- * Life gets complicated if you want an easy to use 'M43 I' output (in port/pin order)
- * because the variants in this platform do not always define all the I/O port/pins
- * that a CPU has.
- *
- * VARIABLES:
- * Ard_num - Arduino pin number - defined by the platform. It is used by digitalRead and
- * digitalWrite commands and by M42.
- * - does not contain port/pin info
- * - is not in port/pin order
- * - typically a variant will only assign Ard_num to port/pins that are actually used
- * Index - M43 counter - only used to get Ard_num
- * x - a parameter/argument used to search the pin_array to try to find a signal name
- * associated with a Ard_num
- * Port_pin - port number and pin number for use with CPU registers and printing reports
- *
- * Since M43 uses digitalRead and digitalWrite commands, only the Port_pins with an Ard_num
- * are accessed and/or displayed.
- *
- * Three arrays are used.
- *
- * digitalPin[] is provided by the platform. It consists of the Port_pin numbers in
- * Arduino pin number order.
- *
- * pin_array is a structure generated by the pins/pinsDebug.h header file. It is generated by
- * the preprocessor. Only the signals associated with enabled options are in this table.
- * It contains:
- * - name of the signal
- * - the Ard_num assigned by the pins_YOUR_BOARD.h file using the platform defines.
- * EXAMPLE: "#define KILL_PIN PB1" results in Ard_num of 57. 57 is then used as the
- * argument to digitalPinToPinName(IO) to get the Port_pin number
- * - if it is a digital or analog signal. PWMs are considered digital here.
- *
- * pin_xref is a structure generated by this header file. It is generated by the
- * preprocessor. It is in port/pin order. It contains just the port/pin numbers defined by the
- * platform for this variant.
- * - Ard_num
- * - printable version of Port_pin
- *
- * Routines with an "x" as a parameter/argument are used to search the pin_array to try to
- * find a signal name associated with a port/pin.
- *
- * NOTE - the Arduino pin number is what is used by the M42 command, NOT the port/pin for that
- * signal. The Arduino pin number is listed by the M43 I command.
- */
-
-////////////////////////////////////////////////////////
-//
-// make a list of the Arduino pin numbers in the Port/Pin order
-//
-
-#define _PIN_ADD_2(NAME_ALPHA, ARDUINO_NUM) { {NAME_ALPHA}, ARDUINO_NUM },
-#define _PIN_ADD(NAME_ALPHA, ARDUINO_NUM) { NAME_ALPHA, ARDUINO_NUM },
-#define PIN_ADD(NAME) _PIN_ADD(#NAME, NAME)
-
-typedef struct {
- char Port_pin_alpha[5];
- pin_t Ard_num;
-} XrefInfo;
-
-const XrefInfo pin_xref[] PROGMEM = {
- #include "pins_Xref.h"
-};
-
-////////////////////////////////////////////////////////////
-
-#define MODE_PIN_INPUT 0 // Input mode (reset state)
-#define MODE_PIN_OUTPUT 1 // General purpose output mode
-#define MODE_PIN_ALT 2 // Alternate function mode
-#define MODE_PIN_ANALOG 3 // Analog mode
-
-#define PIN_NUM(P) (P & 0x000F)
-#define PIN_NUM_ALPHA_LEFT(P) (((P & 0x000F) < 10) ? ('0' + (P & 0x000F)) : '1')
-#define PIN_NUM_ALPHA_RIGHT(P) (((P & 0x000F) > 9) ? ('0' + (P & 0x000F) - 10) : 0 )
-#define PORT_NUM(P) ((P >> 4) & 0x0007)
-#define PORT_ALPHA(P) ('A' + (P >> 4))
-
-/**
- * Translation of routines & variables used by pinsDebug.h
- */
-#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
-#define VALID_PIN(ANUM) ((ANUM) >= 0 && (ANUM) < NUMBER_PINS_TOTAL)
-#define digitalRead_mod(Ard_num) extDigitalRead(Ard_num) // must use Arduino pin numbers when doing reads
-#define PRINT_PIN(Q)
-#define PRINT_PORT(ANUM) port_print(ANUM)
-#define DIGITAL_PIN_TO_ANALOG_PIN(ANUM) -1 // will report analog pin number in the print port routine
-#define GET_PIN_MAP_PIN_M43(Index) pin_xref[Index].Ard_num
-
-// x is a variable used to search pin_array
-#define GET_ARRAY_IS_DIGITAL(x) ((bool) pin_array[x].is_digital)
-#define GET_ARRAY_PIN(x) ((pin_t) pin_array[x].pin)
-#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
-#define MULTI_NAME_PAD 33 // space needed to be pretty if not first name assigned to a pin
-
-#ifndef M43_NEVER_TOUCH
- #define _M43_NEVER_TOUCH(Index) (Index >= 9 && Index <= 12) // SERIAL/USB pins: PA9(TX) PA10(RX) PA11(USB_DM) PA12(USB_DP)
- #ifdef KILL_PIN
- #define M43_NEVER_TOUCH(Index) m43_never_touch(Index)
-
- bool m43_never_touch(const pin_t Index) {
- static pin_t M43_kill_index = -1;
- if (M43_kill_index < 0)
- for (M43_kill_index = 0; M43_kill_index < NUMBER_PINS_TOTAL; M43_kill_index++)
- if (KILL_PIN == GET_PIN_MAP_PIN_M43(M43_kill_index)) break;
- return _M43_NEVER_TOUCH(Index) || Index == M43_kill_index; // KILL_PIN and SERIAL/USB
- }
- #else
- #define M43_NEVER_TOUCH(Index) _M43_NEVER_TOUCH(Index)
- #endif
-#endif
-
-uint8_t get_pin_mode(const pin_t Ard_num) {
- uint32_t mode_all = 0;
- const PinName dp = digitalPinToPinName(Ard_num);
- switch (PORT_ALPHA(dp)) {
- case 'A' : mode_all = GPIOA->MODER; break;
- case 'B' : mode_all = GPIOB->MODER; break;
- case 'C' : mode_all = GPIOC->MODER; break;
- case 'D' : mode_all = GPIOD->MODER; break;
- #ifdef PE_0
- case 'E' : mode_all = GPIOE->MODER; break;
- #elif defined(PF_0)
- case 'F' : mode_all = GPIOF->MODER; break;
- #elif defined(PG_0)
- case 'G' : mode_all = GPIOG->MODER; break;
- #elif defined(PH_0)
- case 'H' : mode_all = GPIOH->MODER; break;
- #elif defined(PI_0)
- case 'I' : mode_all = GPIOI->MODER; break;
- #elif defined(PJ_0)
- case 'J' : mode_all = GPIOJ->MODER; break;
- #elif defined(PK_0)
- case 'K' : mode_all = GPIOK->MODER; break;
- #elif defined(PL_0)
- case 'L' : mode_all = GPIOL->MODER; break;
- #endif
- }
- return (mode_all >> (2 * uint8_t(PIN_NUM(dp)))) & 0x03;
-}
-
-bool GET_PINMODE(const pin_t Ard_num) {
- const uint8_t pin_mode = get_pin_mode(Ard_num);
- return pin_mode == MODE_PIN_OUTPUT || pin_mode == MODE_PIN_ALT; // assume all alt definitions are PWM
-}
-
-int8_t digital_pin_to_analog_pin(pin_t Ard_num) {
- Ard_num -= NUM_ANALOG_FIRST;
- return (Ard_num >= 0 && Ard_num < NUM_ANALOG_INPUTS) ? Ard_num : -1;
-}
-
-bool IS_ANALOG(const pin_t Ard_num) {
- return get_pin_mode(Ard_num) == MODE_PIN_ANALOG;
-}
-
-bool is_digital(const pin_t x) {
- const uint8_t pin_mode = get_pin_mode(pin_array[x].pin);
- return pin_mode == MODE_PIN_INPUT || pin_mode == MODE_PIN_OUTPUT;
-}
-
-void port_print(const pin_t Ard_num) {
- char buffer[16];
- pin_t Index;
- for (Index = 0; Index < NUMBER_PINS_TOTAL; Index++)
- if (Ard_num == GET_PIN_MAP_PIN_M43(Index)) break;
-
- const char * ppa = pin_xref[Index].Port_pin_alpha;
- sprintf_P(buffer, PSTR("%s"), ppa);
- SERIAL_ECHO(buffer);
- if (ppa[3] == '\0') SERIAL_CHAR(' ');
-
- // print analog pin number
- const int8_t Port_pin = digital_pin_to_analog_pin(Ard_num);
- if (Port_pin >= 0) {
- sprintf_P(buffer, PSTR(" (A%d) "), Port_pin);
- SERIAL_ECHO(buffer);
- if (Port_pin < 10) SERIAL_CHAR(' ');
- }
- else
- SERIAL_ECHO_SP(7);
-
- // Print number to be used with M42
- sprintf_P(buffer, PSTR(" M42 P%d "), Ard_num);
- SERIAL_ECHO(buffer);
- if (Ard_num < 10) SERIAL_CHAR(' ');
- if (Ard_num < 100) SERIAL_CHAR(' ');
-}
-
-bool pwm_status(const pin_t Ard_num) {
- return get_pin_mode(Ard_num) == MODE_PIN_ALT;
-}
-
-void pwm_details(const pin_t Ard_num) {
- if (pwm_status(Ard_num)) {
- uint32_t alt_all = 0;
- const PinName dp = digitalPinToPinName(Ard_num);
- pin_t pin_number = uint8_t(PIN_NUM(dp));
- const bool over_7 = pin_number >= 8;
- const uint8_t ind = over_7 ? 1 : 0;
- switch (PORT_ALPHA(dp)) { // get alt function
- case 'A' : alt_all = GPIOA->AFR[ind]; break;
- case 'B' : alt_all = GPIOB->AFR[ind]; break;
- case 'C' : alt_all = GPIOC->AFR[ind]; break;
- case 'D' : alt_all = GPIOD->AFR[ind]; break;
- #ifdef PE_0
- case 'E' : alt_all = GPIOE->AFR[ind]; break;
- #elif defined (PF_0)
- case 'F' : alt_all = GPIOF->AFR[ind]; break;
- #elif defined (PG_0)
- case 'G' : alt_all = GPIOG->AFR[ind]; break;
- #elif defined (PH_0)
- case 'H' : alt_all = GPIOH->AFR[ind]; break;
- #elif defined (PI_0)
- case 'I' : alt_all = GPIOI->AFR[ind]; break;
- #elif defined (PJ_0)
- case 'J' : alt_all = GPIOJ->AFR[ind]; break;
- #elif defined (PK_0)
- case 'K' : alt_all = GPIOK->AFR[ind]; break;
- #elif defined (PL_0)
- case 'L' : alt_all = GPIOL->AFR[ind]; break;
- #endif
- }
- if (over_7) pin_number -= 8;
-
- uint8_t alt_func = (alt_all >> (4 * pin_number)) & 0x0F;
- SERIAL_ECHOPAIR("Alt Function: ", alt_func);
- if (alt_func < 10) SERIAL_CHAR(' ');
- SERIAL_ECHOPGM(" - ");
- switch (alt_func) {
- case 0 : SERIAL_ECHOPGM("system (misc. I/O)"); break;
- case 1 : SERIAL_ECHOPGM("TIM1/TIM2 (probably PWM)"); break;
- case 2 : SERIAL_ECHOPGM("TIM3..5 (probably PWM)"); break;
- case 3 : SERIAL_ECHOPGM("TIM8..11 (probably PWM)"); break;
- case 4 : SERIAL_ECHOPGM("I2C1..3"); break;
- case 5 : SERIAL_ECHOPGM("SPI1/SPI2"); break;
- case 6 : SERIAL_ECHOPGM("SPI3"); break;
- case 7 : SERIAL_ECHOPGM("USART1..3"); break;
- case 8 : SERIAL_ECHOPGM("USART4..6"); break;
- case 9 : SERIAL_ECHOPGM("CAN1/CAN2, TIM12..14 (probably PWM)"); break;
- case 10 : SERIAL_ECHOPGM("OTG"); break;
- case 11 : SERIAL_ECHOPGM("ETH"); break;
- case 12 : SERIAL_ECHOPGM("FSMC, SDIO, OTG"); break;
- case 13 : SERIAL_ECHOPGM("DCMI"); break;
- case 14 : SERIAL_ECHOPGM("unused (shouldn't see this)"); break;
- case 15 : SERIAL_ECHOPGM("EVENTOUT"); break;
- }
- }
-} // pwm_details
-
-#endif // NUM_DIGITAL_PINS
diff --git a/Marlin/src/HAL/STM32/spi_pins.h b/Marlin/src/HAL/STM32/spi_pins.h
index 176e2a7b2..e2052c5c7 100644
--- a/Marlin/src/HAL/STM32/spi_pins.h
+++ b/Marlin/src/HAL/STM32/spi_pins.h
@@ -21,15 +21,15 @@
/**
* Define SPI Pins: SCK, MISO, MOSI, SS
*/
-#ifndef SCK_PIN
- #define SCK_PIN PIN_SPI_SCK
+#ifndef SD_SCK_PIN
+ #define SD_SCK_PIN PIN_SPI_SCK
#endif
-#ifndef MISO_PIN
- #define MISO_PIN PIN_SPI_MISO
+#ifndef SD_MISO_PIN
+ #define SD_MISO_PIN PIN_SPI_MISO
#endif
-#ifndef MOSI_PIN
- #define MOSI_PIN PIN_SPI_MOSI
+#ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN PIN_SPI_MOSI
#endif
-#ifndef SS_PIN
- #define SS_PIN PIN_SPI_SS
+#ifndef SD_SS_PIN
+ #define SD_SS_PIN PIN_SPI_SS
#endif
diff --git a/Marlin/src/HAL/STM32/tft/tft_fsmc.cpp b/Marlin/src/HAL/STM32/tft/tft_fsmc.cpp
index 3a080d5e2..87ca2dbbe 100644
--- a/Marlin/src/HAL/STM32/tft/tft_fsmc.cpp
+++ b/Marlin/src/HAL/STM32/tft/tft_fsmc.cpp
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#include "../../../inc/MarlinConfig.h"
@@ -47,13 +48,14 @@ void TFT_FSMC::Init() {
uint32_t NSBank = (uint32_t)pinmap_peripheral(digitalPinToPinName(TFT_CS_PIN), PinMap_FSMC_CS);
+ // Perform the SRAM1 memory initialization sequence
SRAMx.Instance = FSMC_NORSRAM_DEVICE;
SRAMx.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
- /* SRAMx.Init */
+ // SRAMx.Init
SRAMx.Init.NSBank = NSBank;
SRAMx.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
SRAMx.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
- SRAMx.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
+ SRAMx.Init.MemoryDataWidth = TERN(TFT_INTERFACE_FSMC_8BIT, FSMC_NORSRAM_MEM_BUS_WIDTH_8, FSMC_NORSRAM_MEM_BUS_WIDTH_16);
SRAMx.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
SRAMx.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
SRAMx.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
@@ -66,8 +68,8 @@ void TFT_FSMC::Init() {
#ifdef STM32F4xx
SRAMx.Init.PageSize = FSMC_PAGE_SIZE_NONE;
#endif
- /* Read Timing - relatively slow to ensure ID information is correctly read from TFT controller */
- /* Can be decreases from 15-15-24 to 4-4-8 with risk of stability loss */
+ // Read Timing - relatively slow to ensure ID information is correctly read from TFT controller
+ // Can be decreases from 15-15-24 to 4-4-8 with risk of stability loss
Timing.AddressSetupTime = 15;
Timing.AddressHoldTime = 15;
Timing.DataSetupTime = 24;
@@ -75,8 +77,8 @@ void TFT_FSMC::Init() {
Timing.CLKDivision = 16;
Timing.DataLatency = 17;
Timing.AccessMode = FSMC_ACCESS_MODE_A;
- /* Write Timing */
- /* Can be decreases from 8-15-8 to 0-0-1 with risk of stability loss */
+ // Write Timing
+ // Can be decreases from 8-15-8 to 0-0-1 with risk of stability loss
ExtTiming.AddressSetupTime = 8;
ExtTiming.AddressHoldTime = 15;
ExtTiming.DataSetupTime = 8;
@@ -130,7 +132,7 @@ void TFT_FSMC::Init() {
uint32_t TFT_FSMC::GetID() {
uint32_t id;
- WriteReg(0x0000);
+ WriteReg(0);
id = LCD->RAM;
if (id == 0)
@@ -140,41 +142,40 @@ uint32_t TFT_FSMC::GetID() {
return id;
}
- uint32_t TFT_FSMC::ReadID(uint16_t Reg) {
- uint32_t id;
- WriteReg(Reg);
- id = LCD->RAM; // dummy read
- id = Reg << 24;
- id |= (LCD->RAM & 0x00FF) << 16;
- id |= (LCD->RAM & 0x00FF) << 8;
- id |= LCD->RAM & 0x00FF;
- return id;
- }
+uint32_t TFT_FSMC::ReadID(tft_data_t Reg) {
+ uint32_t id;
+ WriteReg(Reg);
+ id = LCD->RAM; // dummy read
+ id = Reg << 24;
+ id |= (LCD->RAM & 0x00FF) << 16;
+ id |= (LCD->RAM & 0x00FF) << 8;
+ id |= LCD->RAM & 0x00FF;
+ return id;
+}
bool TFT_FSMC::isBusy() {
- if (__IS_DMA_ENABLED(&DMAtx))
+ #if defined(STM32F1xx)
+ volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET;
+ #elif defined(STM32F4xx)
+ volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN;
+ #endif
+ if (dmaEnabled) {
if (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx)) != 0 || __HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx)) != 0)
Abort();
- return __IS_DMA_ENABLED(&DMAtx);
+ }
+ else
+ Abort();
+ return dmaEnabled;
}
void TFT_FSMC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DMAtx.Init.PeriphInc = MemoryIncrease;
HAL_DMA_Init(&DMAtx);
-
- __HAL_DMA_CLEAR_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx));
- __HAL_DMA_CLEAR_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx));
-
- #ifdef STM32F1xx
- DMAtx.Instance->CNDTR = Count;
- DMAtx.Instance->CPAR = (uint32_t)Data;
- DMAtx.Instance->CMAR = (uint32_t)&(LCD->RAM);
- #elif defined(STM32F4xx)
- DMAtx.Instance->NDTR = Count;
- DMAtx.Instance->PAR = (uint32_t)Data;
- DMAtx.Instance->M0AR = (uint32_t)&(LCD->RAM);
- #endif
- __HAL_DMA_ENABLE(&DMAtx);
+ DataTransferBegin();
+ HAL_DMA_Start(&DMAtx, (uint32_t)Data, (uint32_t)&(LCD->RAM), Count);
+ HAL_DMA_PollForTransfer(&DMAtx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
+ Abort();
}
#endif // HAS_FSMC_TFT
+#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/tft/tft_fsmc.h b/Marlin/src/HAL/STM32/tft/tft_fsmc.h
index cbec7613e..2200abaa1 100644
--- a/Marlin/src/HAL/STM32/tft/tft_fsmc.h
+++ b/Marlin/src/HAL/STM32/tft/tft_fsmc.h
@@ -21,34 +21,33 @@
*/
#pragma once
+#include "../../../inc/MarlinConfig.h"
+
#ifdef STM32F1xx
#include "stm32f1xx_hal.h"
#elif defined(STM32F4xx)
#include "stm32f4xx_hal.h"
#else
- #error FSMC TFT is currently only supported on STM32F1 and STM32F4 hardware.
+ #error "FSMC TFT is currently only supported on STM32F1 and STM32F4 hardware."
#endif
#ifndef LCD_READ_ID
- #define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
+ #define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif
#ifndef LCD_READ_ID4
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
#endif
-#define DATASIZE_8BIT SPI_DATASIZE_8BIT
-#define DATASIZE_16BIT SPI_DATASIZE_16BIT
-#define TFT_IO_DRIVER TFT_FSMC
+#define DATASIZE_8BIT SPI_DATASIZE_8BIT
+#define DATASIZE_16BIT SPI_DATASIZE_16BIT
+#define TFT_IO_DRIVER TFT_FSMC
-#ifdef STM32F1xx
- #define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CCR & DMA_CCR_EN)
-#elif defined(STM32F4xx)
- #define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CR & DMA_SxCR_EN)
-#endif
+#define TFT_DATASIZE TERN(TFT_INTERFACE_FSMC_8BIT, DATASIZE_8BIT, DATASIZE_16BIT)
+typedef TERN(TFT_INTERFACE_FSMC_8BIT, uint8_t, uint16_t) tft_data_t;
typedef struct {
- __IO uint16_t REG;
- __IO uint16_t RAM;
+ __IO tft_data_t REG;
+ __IO tft_data_t RAM;
} LCD_CONTROLLER_TypeDef;
class TFT_FSMC {
@@ -58,8 +57,8 @@ class TFT_FSMC {
static LCD_CONTROLLER_TypeDef *LCD;
- static uint32_t ReadID(uint16_t Reg);
- static void Transmit(uint16_t Data) { LCD->RAM = Data; __DSB(); }
+ static uint32_t ReadID(tft_data_t Reg);
+ static void Transmit(tft_data_t Data) { LCD->RAM = Data; __DSB(); }
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public:
@@ -68,17 +67,23 @@ class TFT_FSMC {
static bool isBusy();
static void Abort() { __HAL_DMA_DISABLE(&DMAtx); }
- static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT) {}
+ static void DataTransferBegin(uint16_t DataWidth = TFT_DATASIZE) {}
static void DataTransferEnd() {};
- static void WriteData(uint16_t Data) { Transmit(Data); }
- static void WriteReg(uint16_t Reg) { LCD->REG = Reg; __DSB(); }
+ static void WriteData(uint16_t Data) { Transmit(tft_data_t(Data)); }
+ static void WriteReg(uint16_t Reg) { LCD->REG = tft_data_t(Reg); __DSB(); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_PINC_DISABLE, &Data, Count); }
+ static void WriteMultiple(uint16_t Color, uint32_t Count) {
+ static uint16_t Data; Data = Color;
+ while (Count > 0) {
+ TransmitDMA(DMA_MINC_DISABLE, &Data, Count > 0xFFFF ? 0xFFFF : Count);
+ Count = Count > 0xFFFF ? Count - 0xFFFF : 0;
+ }
+ }
};
-
#ifdef STM32F1xx
#define FSMC_PIN_DATA STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, AFIO_NONE)
#elif defined(STM32F4xx)
@@ -100,14 +105,16 @@ const PinMap PinMap_FSMC[] = {
{PE_8, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D05
{PE_9, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D06
{PE_10, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D07
- {PE_11, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D08
- {PE_12, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D09
- {PE_13, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D10
- {PE_14, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D11
- {PE_15, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D12
- {PD_8, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D13
- {PD_9, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D14
- {PD_10, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D15
+ #if DISABLED(TFT_INTERFACE_FSMC_8BIT)
+ {PE_11, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D08
+ {PE_12, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D09
+ {PE_13, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D10
+ {PE_14, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D11
+ {PE_15, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D12
+ {PD_8, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D13
+ {PD_9, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D14
+ {PD_10, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D15
+ #endif
{PD_4, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_NOE
{PD_5, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_NWE
{NC, NP, 0}
@@ -123,7 +130,11 @@ const PinMap PinMap_FSMC_CS[] = {
{NC, NP, 0}
};
-#define FSMC_RS(A) (void *)((2 << A) - 2)
+#if ENABLED(TFT_INTERFACE_FSMC_8BIT)
+ #define FSMC_RS(A) (void *)((2 << (A-1)) - 1)
+#else
+ #define FSMC_RS(A) (void *)((2 << A) - 2)
+#endif
const PinMap PinMap_FSMC_RS[] = {
#ifdef PF0
diff --git a/Marlin/src/HAL/STM32/tft/tft_ltdc.cpp b/Marlin/src/HAL/STM32/tft/tft_ltdc.cpp
new file mode 100644
index 000000000..6039593f4
--- /dev/null
+++ b/Marlin/src/HAL/STM32/tft/tft_ltdc.cpp
@@ -0,0 +1,390 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
+
+#include "../../../inc/MarlinConfig.h"
+
+#if HAS_LTDC_TFT
+
+#include "tft_ltdc.h"
+#include "pinconfig.h"
+
+#define FRAME_BUFFER_ADDRESS 0XC0000000 // SDRAM address
+
+#define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
+#define REFRESH_COUNT ((uint32_t)0x02A5) // SDRAM refresh counter
+
+#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
+#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
+#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
+#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
+#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
+#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
+#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
+#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
+#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
+#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
+#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
+
+
+void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command) {
+
+ __IO uint32_t tmpmrd =0;
+ /* Step 1: Configure a clock configuration enable command */
+ Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
+ Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
+ Command->AutoRefreshNumber = 1;
+ Command->ModeRegisterDefinition = 0;
+ /* Send the command */
+ HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
+
+ /* Step 2: Insert 100 us minimum delay */
+ /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
+ HAL_Delay(1);
+
+ /* Step 3: Configure a PALL (precharge all) command */
+ Command->CommandMode = FMC_SDRAM_CMD_PALL;
+ Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
+ Command->AutoRefreshNumber = 1;
+ Command->ModeRegisterDefinition = 0;
+ /* Send the command */
+ HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
+
+ /* Step 4 : Configure a Auto-Refresh command */
+ Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
+ Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
+ Command->AutoRefreshNumber = 8;
+ Command->ModeRegisterDefinition = 0;
+ /* Send the command */
+ HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
+
+ /* Step 5: Program the external memory mode register */
+ tmpmrd = (uint32_t)(SDRAM_MODEREG_BURST_LENGTH_1 |
+ SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
+ SDRAM_MODEREG_CAS_LATENCY_2 |
+ SDRAM_MODEREG_OPERATING_MODE_STANDARD |
+ SDRAM_MODEREG_WRITEBURST_MODE_SINGLE);
+
+ Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
+ Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
+ Command->AutoRefreshNumber = 1;
+ Command->ModeRegisterDefinition = tmpmrd;
+ /* Send the command */
+ HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
+
+ /* Step 6: Set the refresh rate counter */
+ /* Set the device refresh rate */
+ HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
+}
+
+void SDRAM_Config() {
+
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ __HAL_RCC_FMC_CLK_ENABLE();
+
+ SDRAM_HandleTypeDef hsdram;
+ FMC_SDRAM_TimingTypeDef SDRAM_Timing;
+ FMC_SDRAM_CommandTypeDef command;
+
+ /* Configure the SDRAM device */
+ hsdram.Instance = FMC_SDRAM_DEVICE;
+ hsdram.Init.SDBank = FMC_SDRAM_BANK1;
+ hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
+ hsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
+ hsdram.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
+ hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
+ hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
+ hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
+ hsdram.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
+ hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
+ hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
+
+ /* Timing configuration for 100Mhz as SDRAM clock frequency (System clock is up to 200Mhz) */
+ SDRAM_Timing.LoadToActiveDelay = 2;
+ SDRAM_Timing.ExitSelfRefreshDelay = 8;
+ SDRAM_Timing.SelfRefreshTime = 6;
+ SDRAM_Timing.RowCycleDelay = 6;
+ SDRAM_Timing.WriteRecoveryTime = 2;
+ SDRAM_Timing.RPDelay = 2;
+ SDRAM_Timing.RCDDelay = 2;
+
+ /* Initialize the SDRAM controller */
+ if (HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
+ {
+ /* Initialization Error */
+ }
+
+ /* Program the SDRAM external device */
+ SDRAM_Initialization_Sequence(&hsdram, &command);
+}
+
+void LTDC_Config() {
+
+ __HAL_RCC_LTDC_CLK_ENABLE();
+ __HAL_RCC_DMA2D_CLK_ENABLE();
+
+ RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
+
+ /* The PLL3R is configured to provide the LTDC PCLK clock */
+ /* PLL3_VCO Input = HSE_VALUE / PLL3M = 25Mhz / 5 = 5 Mhz */
+ /* PLL3_VCO Output = PLL3_VCO Input * PLL3N = 5Mhz * 160 = 800 Mhz */
+ /* PLLLCDCLK = PLL3_VCO Output/PLL3R = 800Mhz / 16 = 50Mhz */
+ /* LTDC clock frequency = PLLLCDCLK = 50 Mhz */
+ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
+ PeriphClkInitStruct.PLL3.PLL3M = 5;
+ PeriphClkInitStruct.PLL3.PLL3N = 160;
+ PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
+ PeriphClkInitStruct.PLL3.PLL3P = 2;
+ PeriphClkInitStruct.PLL3.PLL3Q = 2;
+ PeriphClkInitStruct.PLL3.PLL3R = (800 / LTDC_LCD_CLK);
+ PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
+ PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
+ HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
+
+ LTDC_HandleTypeDef hltdc_F;
+ LTDC_LayerCfgTypeDef pLayerCfg;
+
+ /* LTDC Initialization -------------------------------------------------------*/
+
+ /* Polarity configuration */
+ /* Initialize the horizontal synchronization polarity as active low */
+ hltdc_F.Init.HSPolarity = LTDC_HSPOLARITY_AL;
+ /* Initialize the vertical synchronization polarity as active low */
+ hltdc_F.Init.VSPolarity = LTDC_VSPOLARITY_AL;
+ /* Initialize the data enable polarity as active low */
+ hltdc_F.Init.DEPolarity = LTDC_DEPOLARITY_AL;
+ /* Initialize the pixel clock polarity as input pixel clock */
+ hltdc_F.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
+
+ /* Timing configuration */
+ hltdc_F.Init.HorizontalSync = (LTDC_LCD_HSYNC - 1);
+ hltdc_F.Init.VerticalSync = (LTDC_LCD_VSYNC - 1);
+ hltdc_F.Init.AccumulatedHBP = (LTDC_LCD_HSYNC + LTDC_LCD_HBP - 1);
+ hltdc_F.Init.AccumulatedVBP = (LTDC_LCD_VSYNC + LTDC_LCD_VBP - 1);
+ hltdc_F.Init.AccumulatedActiveH = (TFT_HEIGHT + LTDC_LCD_VSYNC + LTDC_LCD_VBP - 1);
+ hltdc_F.Init.AccumulatedActiveW = (TFT_WIDTH + LTDC_LCD_HSYNC + LTDC_LCD_HBP - 1);
+ hltdc_F.Init.TotalHeigh = (TFT_HEIGHT + LTDC_LCD_VSYNC + LTDC_LCD_VBP + LTDC_LCD_VFP - 1);
+ hltdc_F.Init.TotalWidth = (TFT_WIDTH + LTDC_LCD_HSYNC + LTDC_LCD_HBP + LTDC_LCD_HFP - 1);
+
+ /* Configure R,G,B component values for LCD background color : all black background */
+ hltdc_F.Init.Backcolor.Blue = 0;
+ hltdc_F.Init.Backcolor.Green = 0;
+ hltdc_F.Init.Backcolor.Red = 0;
+
+ hltdc_F.Instance = LTDC;
+
+/* Layer0 Configuration ------------------------------------------------------*/
+
+ /* Windowing configuration */
+ pLayerCfg.WindowX0 = 0;
+ pLayerCfg.WindowX1 = TFT_WIDTH;
+ pLayerCfg.WindowY0 = 0;
+ pLayerCfg.WindowY1 = TFT_HEIGHT;
+
+ /* Pixel Format configuration*/
+ pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
+
+ /* Start Address configuration : frame buffer is located at SDRAM memory */
+ pLayerCfg.FBStartAdress = (uint32_t)(FRAME_BUFFER_ADDRESS);
+
+ /* Alpha constant (255 == totally opaque) */
+ pLayerCfg.Alpha = 255;
+
+ /* Default Color configuration (configure A,R,G,B component values) : no background color */
+ pLayerCfg.Alpha0 = 0; /* fully transparent */
+ pLayerCfg.Backcolor.Blue = 0;
+ pLayerCfg.Backcolor.Green = 0;
+ pLayerCfg.Backcolor.Red = 0;
+
+ /* Configure blending factors */
+ pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
+ pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
+
+ /* Configure the number of lines and number of pixels per line */
+ pLayerCfg.ImageWidth = TFT_WIDTH;
+ pLayerCfg.ImageHeight = TFT_HEIGHT;
+
+ /* Configure the LTDC */
+ if (HAL_LTDC_Init(&hltdc_F) != HAL_OK)
+ {
+ /* Initialization Error */
+ }
+
+ /* Configure the Layer*/
+ if (HAL_LTDC_ConfigLayer(&hltdc_F, &pLayerCfg, 0) != HAL_OK)
+ {
+ /* Initialization Error */
+ }
+}
+
+uint16_t TFT_LTDC::x_min = 0;
+uint16_t TFT_LTDC::x_max = 0;
+uint16_t TFT_LTDC::y_min = 0;
+uint16_t TFT_LTDC::y_max = 0;
+uint16_t TFT_LTDC::x_cur = 0;
+uint16_t TFT_LTDC::y_cur = 0;
+uint8_t TFT_LTDC::reg = 0;
+volatile uint16_t* TFT_LTDC::framebuffer = (volatile uint16_t* )FRAME_BUFFER_ADDRESS;
+
+void TFT_LTDC::Init() {
+
+ // SDRAM pins init
+ for (uint16_t i = 0; PinMap_SDRAM[i].pin != NC; i++)
+ pinmap_pinout(PinMap_SDRAM[i].pin, PinMap_SDRAM);
+
+ // SDRAM peripheral config
+ SDRAM_Config();
+
+ // LTDC pins init
+ for (uint16_t i = 0; PinMap_LTDC[i].pin != NC; i++)
+ pinmap_pinout(PinMap_LTDC[i].pin, PinMap_LTDC);
+
+ // LTDC peripheral config
+ LTDC_Config();
+}
+
+uint32_t TFT_LTDC::GetID() {
+ return 0xABAB;
+}
+
+uint32_t TFT_LTDC::ReadID(tft_data_t Reg) {
+ return 0xABAB;
+}
+
+bool TFT_LTDC::isBusy() {
+ return false;
+}
+
+uint16_t TFT_LTDC::ReadPoint(uint16_t x, uint16_t y) {
+ return framebuffer[(TFT_WIDTH * y) + x];
+}
+
+void TFT_LTDC::DrawPoint(uint16_t x, uint16_t y, uint16_t color) {
+ framebuffer[(TFT_WIDTH * y) + x] = color;
+}
+
+void TFT_LTDC::DrawRect(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color) {
+
+ if (sx == ex || sy == ey) return;
+
+ uint16_t offline = TFT_WIDTH - (ex - sx);
+ uint32_t addr = (uint32_t)&framebuffer[(TFT_WIDTH * sy) + sx];
+
+ DMA2D->CR &= ~(1 << 0);
+ DMA2D->CR = 3 << 16;
+ DMA2D->OPFCCR = 0X02;
+ DMA2D->OOR = offline;
+ DMA2D->OMAR = addr;
+ DMA2D->NLR = (ey - sy) | ((ex - sx) << 16);
+ DMA2D->OCOLR = color;
+ DMA2D->CR |= 1<<0;
+
+ uint32_t timeout = 0;
+ while((DMA2D->ISR & (1<<1)) == 0)
+ {
+ timeout++;
+ if(timeout>0X1FFFFF)break;
+ }
+ DMA2D->IFCR |= 1<<1;
+}
+
+void TFT_LTDC::DrawImage(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *colors) {
+
+ if (sx == ex || sy == ey) return;
+
+ uint16_t offline = TFT_WIDTH - (ex - sx);
+ uint32_t addr = (uint32_t)&framebuffer[(TFT_WIDTH * sy) + sx];
+
+ DMA2D->CR &= ~(1 << 0);
+ DMA2D->CR = 0 << 16;
+ DMA2D->FGPFCCR = 0X02;
+ DMA2D->FGOR = 0;
+ DMA2D->OOR = offline;
+ DMA2D->FGMAR = (uint32_t)colors;
+ DMA2D->OMAR = addr;
+ DMA2D->NLR = (ey - sy) | ((ex - sx) << 16);
+ DMA2D->CR |= 1<<0;
+
+ uint32_t timeout = 0;
+ while((DMA2D->ISR & (1<<1)) == 0)
+ {
+ timeout++;
+ if(timeout>0X1FFFFF)break;
+ }
+ DMA2D->IFCR |= 1<<1;
+}
+
+void TFT_LTDC::WriteData(uint16_t data) {
+ switch (reg) {
+ case 0x01: x_cur = x_min = data; return;
+ case 0x02: x_max = data; return;
+ case 0x03: y_cur = y_min = data; return;
+ case 0x04: y_max = data; return;
+ }
+ Transmit(data);
+}
+
+void TFT_LTDC::Transmit(tft_data_t Data) {
+ DrawPoint(x_cur, y_cur, Data);
+ x_cur++;
+ if (x_cur > x_max) {
+ x_cur = x_min;
+ y_cur++;
+ if (y_cur > y_max) y_cur = y_min;
+ }
+}
+
+void TFT_LTDC::WriteReg(uint16_t Reg) {
+ reg = Reg;
+}
+
+void TFT_LTDC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
+
+ while (x_cur != x_min && Count) {
+ Transmit(*Data);
+ if (MemoryIncrease == DMA_PINC_ENABLE) Data++;
+ Count--;
+ }
+
+ uint16_t width = x_max - x_min + 1;
+ uint16_t height = Count / width;
+ uint16_t x_end_cnt = Count - (width * height);
+
+ if (height) {
+ if (MemoryIncrease == DMA_PINC_ENABLE) {
+ DrawImage(x_min, y_cur, x_min + width, y_cur + height, Data);
+ Data += width * height;
+ } else {
+ DrawRect(x_min, y_cur, x_min + width, y_cur + height, *Data);
+ }
+ y_cur += height;
+ }
+
+ while (x_end_cnt) {
+ Transmit(*Data);
+ if (MemoryIncrease == DMA_PINC_ENABLE) Data++;
+ x_end_cnt--;
+ }
+}
+
+#endif // HAS_LTDC_TFT
+#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/tft/tft_ltdc.h b/Marlin/src/HAL/STM32/tft/tft_ltdc.h
new file mode 100644
index 000000000..7b63d6929
--- /dev/null
+++ b/Marlin/src/HAL/STM32/tft/tft_ltdc.h
@@ -0,0 +1,155 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "../../../inc/MarlinConfig.h"
+
+#ifdef STM32H7xx
+ #include "stm32h7xx_hal.h"
+#else
+ #error "LTDC TFT is currently only supported on STM32H7 hardware."
+#endif
+
+#define DATASIZE_8BIT SPI_DATASIZE_8BIT
+#define DATASIZE_16BIT SPI_DATASIZE_16BIT
+#define TFT_IO_DRIVER TFT_LTDC
+
+#define TFT_DATASIZE DATASIZE_16BIT
+typedef uint16_t tft_data_t;
+
+class TFT_LTDC {
+ private:
+ static volatile uint16_t *framebuffer;
+ static uint16_t x_min, x_max, y_min, y_max, x_cur, y_cur;
+ static uint8_t reg;
+
+ static uint32_t ReadID(tft_data_t Reg);
+
+ static uint16_t ReadPoint(uint16_t x, uint16_t y);
+ static void DrawPoint(uint16_t x, uint16_t y, uint16_t color);
+ static void DrawRect(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color);
+ static void DrawImage(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *colors);
+ static void Transmit(tft_data_t Data);
+ static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
+
+ public:
+ static void Init();
+ static uint32_t GetID();
+ static bool isBusy();
+ static void Abort() { /*__HAL_DMA_DISABLE(&DMAtx);*/ }
+
+ static void DataTransferBegin(uint16_t DataWidth = TFT_DATASIZE) {}
+ static void DataTransferEnd() {};
+
+ static void WriteData(uint16_t Data);
+ static void WriteReg(uint16_t Reg);
+
+ static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_ENABLE, Data, Count); }
+ static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_PINC_DISABLE, &Data, Count); }
+ static void WriteMultiple(uint16_t Color, uint32_t Count) {
+ static uint16_t Data; Data = Color;
+ while (Count > 0) {
+ TransmitDMA(DMA_MINC_DISABLE, &Data, Count > 0xFFFF ? 0xFFFF : Count);
+ Count = Count > 0xFFFF ? Count - 0xFFFF : 0;
+ }
+ }
+};
+
+const PinMap PinMap_LTDC[] = {
+ {PF_10, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_DE
+ {PG_7, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_CLK
+ {PI_9, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_VSYNC
+ {PI_10, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_HSYNC
+
+ {PG_6, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R7
+ {PH_12, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R6
+ {PH_11, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R5
+ {PH_10, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R4
+ {PH_9, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R3
+
+ {PI_2, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G7
+ {PI_1, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G6
+ {PI_0, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G5
+ {PH_15, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G4
+ {PH_14, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G3
+ {PH_13, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G2
+
+ {PI_7, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B7
+ {PI_6, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B6
+ {PI_5, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B5
+ {PI_4, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B4
+ {PG_11, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B3
+ {NC, NP, 0}
+};
+
+const PinMap PinMap_SDRAM[] = {
+ {PC_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDNWE
+ {PC_2, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDNE0
+ {PC_3, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDCKE0
+ {PE_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_NBL0
+ {PE_1, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_NBL1
+ {PF_11, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDNRAS
+ {PG_8, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDCLK
+ {PG_15, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDNCAS
+ {PG_4, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_BA0
+ {PG_5, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_BA1
+ {PD_14, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D0
+ {PD_15, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D1
+ {PD_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D2
+ {PD_1, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D3
+ {PE_7, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D4
+ {PE_8, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D5
+ {PE_9, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D6
+ {PE_10, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D7
+ {PE_11, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D8
+ {PE_12, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D9
+ {PE_13, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D10
+ {PE_14, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D11
+ {PE_15, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D12
+ {PD_8, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D13
+ {PD_9, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D14
+ {PD_10, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D15
+ {PF_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A0
+ {PF_1, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A1
+ {PF_2, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A2
+ {PF_3, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A3
+ {PF_4, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A4
+ {PF_5, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A5
+ {PF_12, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A6
+ {PF_13, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A7
+ {PF_14, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A8
+ {PF_15, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A9
+ {PG_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A10
+ {PG_1, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A11
+ {PG_2, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A12
+ {NC, NP, 0}
+};
+
+const PinMap PinMap_QUADSPI[] = {
+ {PB_2, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_CLK
+ {PB_10, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_NCS
+ {PF_6, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3
+ {PF_7, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2
+ {PF_8, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0
+ {PF_9, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1
+ {NC, NP, 0}
+};
diff --git a/Marlin/src/HAL/STM32/tft/tft_spi.cpp b/Marlin/src/HAL/STM32/tft/tft_spi.cpp
index d3eb4ba8d..32af67d15 100644
--- a/Marlin/src/HAL/STM32/tft/tft_spi.cpp
+++ b/Marlin/src/HAL/STM32/tft/tft_spi.cpp
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#include "../../../inc/MarlinConfig.h"
@@ -33,22 +34,13 @@ DMA_HandleTypeDef TFT_SPI::DMAtx;
void TFT_SPI::Init() {
SPI_TypeDef *spiInstance;
- #if PIN_EXISTS(TFT_RESET)
- OUT_WRITE(TFT_RESET_PIN, HIGH);
- HAL_Delay(100);
- #endif
-
- #if PIN_EXISTS(TFT_BACKLIGHT)
- OUT_WRITE(TFT_BACKLIGHT_PIN, HIGH);
- #endif
-
OUT_WRITE(TFT_A0_PIN, HIGH);
OUT_WRITE(TFT_CS_PIN, HIGH);
if ((spiInstance = (SPI_TypeDef *)pinmap_peripheral(digitalPinToPinName(TFT_SCK_PIN), PinMap_SPI_SCLK)) == NP) return;
if (spiInstance != (SPI_TypeDef *)pinmap_peripheral(digitalPinToPinName(TFT_MOSI_PIN), PinMap_SPI_MOSI)) return;
- #if PIN_EXISTS(TFT_MISO) && (TFT_MISO_PIN != TFT_MOSI_PIN)
+ #if PIN_EXISTS(TFT_MISO) && TFT_MISO_PIN != TFT_MOSI_PIN
if (spiInstance != (SPI_TypeDef *)pinmap_peripheral(digitalPinToPinName(TFT_MISO_PIN), PinMap_SPI_MISO)) return;
#endif
@@ -56,12 +48,7 @@ void TFT_SPI::Init() {
SPIx.State = HAL_SPI_STATE_RESET;
SPIx.Init.NSS = SPI_NSS_SOFT;
SPIx.Init.Mode = SPI_MODE_MASTER;
- SPIx.Init.Direction =
- #if TFT_MISO_PIN == TFT_MOSI_PIN
- SPI_DIRECTION_1LINE;
- #else
- SPI_DIRECTION_2LINES;
- #endif
+ SPIx.Init.Direction = (TFT_MISO_PIN == TFT_MOSI_PIN) ? SPI_DIRECTION_1LINE : SPI_DIRECTION_2LINES;
SPIx.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
SPIx.Init.CLKPhase = SPI_PHASE_1EDGE;
SPIx.Init.CLKPolarity = SPI_POLARITY_LOW;
@@ -73,7 +60,7 @@ void TFT_SPI::Init() {
pinmap_pinout(digitalPinToPinName(TFT_SCK_PIN), PinMap_SPI_SCLK);
pinmap_pinout(digitalPinToPinName(TFT_MOSI_PIN), PinMap_SPI_MOSI);
- #if PIN_EXISTS(TFT_MISO) && (TFT_MISO_PIN != TFT_MOSI_PIN)
+ #if PIN_EXISTS(TFT_MISO) && TFT_MISO_PIN != TFT_MOSI_PIN
pinmap_pinout(digitalPinToPinName(TFT_MISO_PIN), PinMap_SPI_MISO);
#endif
pin_PullConfig(get_GPIO_Port(STM_PORT(digitalPinToPinName(TFT_SCK_PIN))), STM_LL_GPIO_PIN(digitalPinToPinName(TFT_SCK_PIN)), GPIO_PULLDOWN);
@@ -81,23 +68,41 @@ void TFT_SPI::Init() {
#ifdef SPI1_BASE
if (SPIx.Instance == SPI1) {
__HAL_RCC_SPI1_CLK_ENABLE();
- __HAL_RCC_DMA1_CLK_ENABLE();
+ #ifdef STM32F1xx
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ DMAtx.Instance = DMA1_Channel3;
+ #elif defined(STM32F4xx)
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ DMAtx.Instance = DMA2_Stream3;
+ DMAtx.Init.Channel = DMA_CHANNEL_3;
+ #endif
SPIx.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
- DMAtx.Instance = DMA1_Channel3;
}
#endif
#ifdef SPI2_BASE
if (SPIx.Instance == SPI2) {
__HAL_RCC_SPI2_CLK_ENABLE();
- __HAL_RCC_DMA1_CLK_ENABLE();
- DMAtx.Instance = DMA1_Channel5;
+ #ifdef STM32F1xx
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ DMAtx.Instance = DMA1_Channel5;
+ #elif defined(STM32F4xx)
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ DMAtx.Instance = DMA1_Stream4;
+ DMAtx.Init.Channel = DMA_CHANNEL_0;
+ #endif
}
#endif
#ifdef SPI3_BASE
if (SPIx.Instance == SPI3) {
__HAL_RCC_SPI3_CLK_ENABLE();
- __HAL_RCC_DMA2_CLK_ENABLE();
- DMAtx.Instance = DMA2_Channel2;
+ #ifdef STM32F1xx
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ DMAtx.Instance = DMA2_Channel2;
+ #elif defined(STM32F4xx)
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ DMAtx.Instance = DMA1_Stream5;
+ DMAtx.Init.Channel = DMA_CHANNEL_0;
+ #endif
}
#endif
@@ -109,6 +114,9 @@ void TFT_SPI::Init() {
DMAtx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
DMAtx.Init.Mode = DMA_NORMAL;
DMAtx.Init.Priority = DMA_PRIORITY_LOW;
+ #ifdef STM32F4xx
+ DMAtx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ #endif
}
void TFT_SPI::DataTransferBegin(uint16_t DataSize) {
@@ -127,11 +135,10 @@ uint32_t TFT_SPI::GetID() {
}
uint32_t TFT_SPI::ReadID(uint16_t Reg) {
- #if !PIN_EXISTS(TFT_MISO)
- return 0;
- #else
+ uint32_t Data = 0;
+ #if PIN_EXISTS(TFT_MISO)
uint32_t BaudRatePrescaler = SPIx.Init.BaudRatePrescaler;
- uint32_t i, Data = 0;
+ uint32_t i;
SPIx.Init.BaudRatePrescaler = SPIx.Instance == SPI1 ? SPI_BAUDRATEPRESCALER_8 : SPI_BAUDRATEPRESCALER_4;
DataTransferBegin(DATASIZE_8BIT);
@@ -155,27 +162,42 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
DataTransferEnd();
SPIx.Init.BaudRatePrescaler = BaudRatePrescaler;
-
- return Data >> 7;
#endif
+
+ return Data >> 7;
}
bool TFT_SPI::isBusy() {
- if (DMAtx.Instance->CCR & DMA_CCR_EN)
+ #if defined(STM32F1xx)
+ volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET;
+ #elif defined(STM32F4xx)
+ volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN;
+ #endif
+ if (dmaEnabled) {
if (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx)) != 0 || __HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx)) != 0)
Abort();
- return DMAtx.Instance->CCR & DMA_CCR_EN;
+ }
+ else
+ Abort();
+ return dmaEnabled;
}
void TFT_SPI::Abort() {
- __HAL_DMA_DISABLE(&DMAtx);
+ // Wait for any running spi
+ while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
+ while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {}
+ // First, abort any running dma
+ HAL_DMA_Abort(&DMAtx);
+ // DeInit objects
+ HAL_DMA_DeInit(&DMAtx);
+ HAL_SPI_DeInit(&SPIx);
+ // Deselect CS
DataTransferEnd();
}
void TFT_SPI::Transmit(uint16_t Data) {
- #if TFT_MISO_PIN == TFT_MOSI_PIN
+ if (TFT_MISO_PIN == TFT_MOSI_PIN)
SPI_1LINE_TX(&SPIx);
- #endif
__HAL_SPI_ENABLE(&SPIx);
@@ -184,29 +206,30 @@ void TFT_SPI::Transmit(uint16_t Data) {
while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {}
- #if TFT_MISO_PIN != TFT_MOSI_PIN
- __HAL_SPI_CLEAR_OVRFLAG(&SPIx); /* Clear overrun flag in 2 Lines communication mode because received is not read */
- #endif
+ if (TFT_MISO_PIN != TFT_MOSI_PIN)
+ __HAL_SPI_CLEAR_OVRFLAG(&SPIx); // Clear overrun flag in 2 Lines communication mode because received is not read
}
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
+ // Wait last dma finish, to start another
+ while (isBusy()) { /* nada */ }
+
DMAtx.Init.MemInc = MemoryIncrease;
HAL_DMA_Init(&DMAtx);
+ if (TFT_MISO_PIN == TFT_MOSI_PIN)
+ SPI_1LINE_TX(&SPIx);
+
DataTransferBegin();
- #if TFT_MISO_PIN == TFT_MOSI_PIN
- SPI_1LINE_TX(&SPIx);
- #endif
-
- DMAtx.DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << DMAtx.ChannelIndex);
- DMAtx.Instance->CNDTR = Count;
- DMAtx.Instance->CPAR = (uint32_t)&(SPIx.Instance->DR);
- DMAtx.Instance->CMAR = (uint32_t)Data;
- __HAL_DMA_ENABLE(&DMAtx);
+ HAL_DMA_Start(&DMAtx, (uint32_t)Data, (uint32_t)&(SPIx.Instance->DR), Count);
__HAL_SPI_ENABLE(&SPIx);
- SET_BIT(SPIx.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */
+ SET_BIT(SPIx.Instance->CR2, SPI_CR2_TXDMAEN); // Enable Tx DMA Request
+
+ HAL_DMA_PollForTransfer(&DMAtx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
+ Abort();
}
#endif // HAS_SPI_TFT
+#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/tft/tft_spi.h b/Marlin/src/HAL/STM32/tft/tft_spi.h
index d477b58c0..667b5f366 100644
--- a/Marlin/src/HAL/STM32/tft/tft_spi.h
+++ b/Marlin/src/HAL/STM32/tft/tft_spi.h
@@ -64,4 +64,11 @@ public:
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
+ static void WriteMultiple(uint16_t Color, uint32_t Count) {
+ static uint16_t Data; Data = Color;
+ while (Count > 0) {
+ TransmitDMA(DMA_MINC_DISABLE, &Data, Count > 0xFFFF ? 0xFFFF : Count);
+ Count = Count > 0xFFFF ? Count - 0xFFFF : 0;
+ }
+ }
};
diff --git a/Marlin/src/HAL/STM32/tft/xpt2046.cpp b/Marlin/src/HAL/STM32/tft/xpt2046.cpp
index 921e377a9..04294e669 100644
--- a/Marlin/src/HAL/STM32/tft/xpt2046.cpp
+++ b/Marlin/src/HAL/STM32/tft/xpt2046.cpp
@@ -1,6 +1,9 @@
/**
* Marlin 3D Printer Firmware
- * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +19,11 @@
* along with this program. If not, see .
*
*/
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#include "../../../inc/MarlinConfig.h"
-#if HAS_TFT_XPT2046
+#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
#include "xpt2046.h"
#include "pinconfig.h"
@@ -27,7 +31,6 @@
uint16_t delta(uint16_t a, uint16_t b) { return a > b ? a - b : b - a; }
SPI_HandleTypeDef XPT2046::SPIx;
-DMA_HandleTypeDef XPT2046::DMAtx;
void XPT2046::Init() {
SPI_TypeDef *spiInstance;
@@ -67,43 +70,24 @@ void XPT2046::Init() {
if (SPIx.Instance == SPI1) {
__HAL_RCC_SPI1_CLK_ENABLE();
SPIx.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
- #ifdef STM32F1xx
- DMAtx.Instance = DMA1_Channel3;
- #elif defined(STM32F4xx)
- DMAtx.Instance = DMA2_Stream3; // DMA2_Stream5
- #endif
- //SERIAL_ECHO_MSG(" Touch Screen on SPI1");
}
#endif
#ifdef SPI2_BASE
if (SPIx.Instance == SPI2) {
__HAL_RCC_SPI2_CLK_ENABLE();
- #ifdef STM32F1xx
- DMAtx.Instance = DMA1_Channel5;
- #elif defined(STM32F4xx)
- DMAtx.Instance = DMA1_Stream4;
- #endif
- //SERIAL_ECHO_MSG(" Touch Screen on SPI2");
}
#endif
#ifdef SPI3_BASE
if (SPIx.Instance == SPI3) {
__HAL_RCC_SPI3_CLK_ENABLE();
- #ifdef STM32F1xx
- DMAtx.Instance = DMA2_Channel2;
- #elif defined(STM32F4xx)
- DMAtx.Instance = DMA1_Stream5; // DMA1_Stream7
- #endif
- //SERIAL_ECHO_MSG(" Touch Screen on SPI3");
}
#endif
}
else {
- SPIx.Instance = NULL;
+ SPIx.Instance = nullptr;
SET_INPUT(TOUCH_MISO_PIN);
SET_OUTPUT(TOUCH_MOSI_PIN);
SET_OUTPUT(TOUCH_SCK_PIN);
- //SERIAL_ECHO_MSG(" Touch Screen on Software SPI");
}
getRawData(XPT2046_Z1);
@@ -183,3 +167,4 @@ uint16_t XPT2046::SoftwareIO(uint16_t data) {
}
#endif // HAS_TFT_XPT2046
+#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/tft/xpt2046.h b/Marlin/src/HAL/STM32/tft/xpt2046.h
index 7a6d8439c..5b8acf4b8 100644
--- a/Marlin/src/HAL/STM32/tft/xpt2046.h
+++ b/Marlin/src/HAL/STM32/tft/xpt2046.h
@@ -1,6 +1,9 @@
/**
* Marlin 3D Printer Firmware
- * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,19 +60,11 @@ enum XPTCoordinate : uint8_t {
#define XPT2046_Z1_THRESHOLD 10
#endif
-#ifdef STM32F1xx
- #define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CCR & DMA_CCR_EN)
-#elif defined(STM32F4xx)
- #define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CR & DMA_SxCR_EN)
-#endif
-
-
class XPT2046 {
private:
static SPI_HandleTypeDef SPIx;
- static DMA_HandleTypeDef DMAtx;
- static bool isBusy() { return SPIx.Instance ? __IS_DMA_ENABLED(&DMAtx) : false; }
+ static bool isBusy() { return false; }
static uint16_t getRawData(const XPTCoordinate coordinate);
static bool isTouched();
diff --git a/Marlin/src/HAL/STM32/timers.cpp b/Marlin/src/HAL/STM32/timers.cpp
index c0ba19abe..03353c2ca 100644
--- a/Marlin/src/HAL/STM32/timers.cpp
+++ b/Marlin/src/HAL/STM32/timers.cpp
@@ -27,8 +27,6 @@
// Local defines
// ------------------------
-#define NUM_HARDWARE_TIMERS 2
-
// Default timer priorities. Override by specifying alternate priorities in the board pins file.
// The TONE timer is not present here, as it currently cannot be set programmatically. It is set
// by defining TIM_IRQ_PRIO in the variant.h or platformio.ini file, which adjusts the default
@@ -68,26 +66,23 @@
#endif
#ifdef STM32F0xx
- #define MCU_TIMER_RATE (F_CPU) // Frequency of timer peripherals
#define MCU_STEP_TIMER 16
#define MCU_TEMP_TIMER 17
#elif defined(STM32F1xx)
- #define MCU_TIMER_RATE (F_CPU)
#define MCU_STEP_TIMER 4
#define MCU_TEMP_TIMER 2
#elif defined(STM32F401xC) || defined(STM32F401xE)
- #define MCU_TIMER_RATE (F_CPU / 2)
#define MCU_STEP_TIMER 9
#define MCU_TEMP_TIMER 10
-#elif defined(STM32F4xx) || defined(STM32F7xx)
- #define MCU_TIMER_RATE (F_CPU / 2)
+#elif defined(STM32F4xx) || defined(STM32F7xx) || defined(STM32H7xx)
#define MCU_STEP_TIMER 6 // STM32F401 has no TIM6, TIM7, or TIM8
#define MCU_TEMP_TIMER 14 // TIM7 is consumed by Software Serial if used.
#endif
#ifndef HAL_TIMER_RATE
- #define HAL_TIMER_RATE MCU_TIMER_RATE
+ #define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
+
#ifndef STEP_TIMER
#define STEP_TIMER MCU_STEP_TIMER
#endif
@@ -100,21 +95,23 @@
#define STEP_TIMER_DEV _TIMER_DEV(STEP_TIMER)
#define TEMP_TIMER_DEV _TIMER_DEV(TEMP_TIMER)
-#define __TIMER_IRQ_NAME(X) TIM##X##_IRQn
-#define _TIMER_IRQ_NAME(X) __TIMER_IRQ_NAME(X)
-#define STEP_TIMER_IRQ_NAME _TIMER_IRQ_NAME(STEP_TIMER)
-#define TEMP_TIMER_IRQ_NAME _TIMER_IRQ_NAME(TEMP_TIMER)
-
// ------------------------
// Private Variables
// ------------------------
-HardwareTimer *timer_instance[NUM_HARDWARE_TIMERS] = { NULL };
+HardwareTimer *timer_instance[NUM_HARDWARE_TIMERS] = { nullptr };
// ------------------------
// Public functions
// ------------------------
+uint32_t GetStepperTimerClkFreq() {
+ // Timer input clocks vary between devices, and in some cases between timers on the same device.
+ // Retrieve at runtime to ensure device compatibility. Cache result to avoid repeated overhead.
+ static uint32_t clkfreq = timer_instance[STEP_TIMER_NUM]->getTimerClkFreq();
+ return clkfreq;
+}
+
// frequency is in Hertz
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
if (!HAL_timer_initialized(timer_num)) {
@@ -194,87 +191,132 @@ void SetTimerInterruptPriorities() {
TERN_(HAS_SERVOS, libServo::setInterruptPriority(SERVO_TIMER_IRQ_PRIO, 0));
}
-// This is a terrible hack to replicate the behavior used in the framework's SoftwareSerial.cpp
-// to choose a serial timer. It will select TIM7 on most boards used by Marlin, but this is more
-// resiliant to new MCUs which may not have a TIM7. Best practice is to explicitly specify
-// TIMER_SERIAL to avoid relying on framework selections which may not be predictable.
-#if !defined(TIMER_SERIAL)
- #if defined (TIM18_BASE)
- #define TIMER_SERIAL TIM18
- #elif defined (TIM7_BASE)
- #define TIMER_SERIAL TIM7
- #elif defined (TIM6_BASE)
- #define TIMER_SERIAL TIM6
- #elif defined (TIM22_BASE)
- #define TIMER_SERIAL TIM22
- #elif defined (TIM21_BASE)
- #define TIMER_SERIAL TIM21
- #elif defined (TIM17_BASE)
- #define TIMER_SERIAL TIM17
- #elif defined (TIM16_BASE)
- #define TIMER_SERIAL TIM16
- #elif defined (TIM15_BASE)
- #define TIMER_SERIAL TIM15
- #elif defined (TIM14_BASE)
- #define TIMER_SERIAL TIM14
- #elif defined (TIM13_BASE)
- #define TIMER_SERIAL TIM13
- #elif defined (TIM11_BASE)
- #define TIMER_SERIAL TIM11
- #elif defined (TIM10_BASE)
- #define TIMER_SERIAL TIM10
- #elif defined (TIM12_BASE)
- #define TIMER_SERIAL TIM12
- #elif defined (TIM19_BASE)
- #define TIMER_SERIAL TIM19
- #elif defined (TIM9_BASE)
- #define TIMER_SERIAL TIM9
- #elif defined (TIM5_BASE)
- #define TIMER_SERIAL TIM5
- #elif defined (TIM4_BASE)
- #define TIMER_SERIAL TIM4
- #elif defined (TIM3_BASE)
- #define TIMER_SERIAL TIM3
- #elif defined (TIM2_BASE)
- #define TIMER_SERIAL TIM2
- #elif defined (TIM20_BASE)
- #define TIMER_SERIAL TIM20
- #elif defined (TIM8_BASE)
- #define TIMER_SERIAL TIM8
- #elif defined (TIM1_BASE)
- #define TIMER_SERIAL TIM1
- #else
- #error No suitable timer found for SoftwareSerial, define TIMER_SERIAL in variant.h
+// ------------------------
+// Detect timer conflicts
+// ------------------------
+
+// This list serves two purposes. Firstly, it facilitates build-time mapping between
+// variant-defined timer names (such as TIM1) and timer numbers. It also replicates
+// the order of timers used in the framework's SoftwareSerial.cpp. The first timer in
+// this list will be automatically used by SoftwareSerial if it is not already defined
+// in the board's variant or compiler options.
+static constexpr struct {uintptr_t base_address; int timer_number;} stm32_timer_map[] = {
+ #ifdef TIM18_BASE
+ { uintptr_t(TIM18), 18 },
#endif
+ #ifdef TIM7_BASE
+ { uintptr_t(TIM7), 7 },
+ #endif
+ #ifdef TIM6_BASE
+ { uintptr_t(TIM6), 6 },
+ #endif
+ #ifdef TIM22_BASE
+ { uintptr_t(TIM22), 22 },
+ #endif
+ #ifdef TIM21_BASE
+ { uintptr_t(TIM21), 21 },
+ #endif
+ #ifdef TIM17_BASE
+ { uintptr_t(TIM17), 17 },
+ #endif
+ #ifdef TIM16_BASE
+ { uintptr_t(TIM16), 16 },
+ #endif
+ #ifdef TIM15_BASE
+ { uintptr_t(TIM15), 15 },
+ #endif
+ #ifdef TIM14_BASE
+ { uintptr_t(TIM14), 14 },
+ #endif
+ #ifdef TIM13_BASE
+ { uintptr_t(TIM13), 13 },
+ #endif
+ #ifdef TIM11_BASE
+ { uintptr_t(TIM11), 11 },
+ #endif
+ #ifdef TIM10_BASE
+ { uintptr_t(TIM10), 10 },
+ #endif
+ #ifdef TIM12_BASE
+ { uintptr_t(TIM12), 12 },
+ #endif
+ #ifdef TIM19_BASE
+ { uintptr_t(TIM19), 19 },
+ #endif
+ #ifdef TIM9_BASE
+ { uintptr_t(TIM9), 9 },
+ #endif
+ #ifdef TIM5_BASE
+ { uintptr_t(TIM5), 5 },
+ #endif
+ #ifdef TIM4_BASE
+ { uintptr_t(TIM4), 4 },
+ #endif
+ #ifdef TIM3_BASE
+ { uintptr_t(TIM3), 3 },
+ #endif
+ #ifdef TIM2_BASE
+ { uintptr_t(TIM2), 2 },
+ #endif
+ #ifdef TIM20_BASE
+ { uintptr_t(TIM20), 20 },
+ #endif
+ #ifdef TIM8_BASE
+ { uintptr_t(TIM8), 8 },
+ #endif
+ #ifdef TIM1_BASE
+ { uintptr_t(TIM1), 1 }
+ #endif
+};
+
+// Convert from a timer base address to its integer timer number.
+static constexpr int get_timer_num_from_base_address(uintptr_t base_address) {
+ for (const auto &timer : stm32_timer_map)
+ if (timer.base_address == base_address) return timer.timer_number;
+ return 0;
+}
+
+// The platform's SoftwareSerial.cpp will use the first timer from stm32_timer_map.
+#if HAS_TMC_SW_SERIAL && !defined(TIMER_SERIAL)
+ #define TIMER_SERIAL (stm32_timer_map[0].base_address)
#endif
-// Place all timers used into an array, then recursively check for duplicates during compilation.
-// This does not currently account for timers used for PWM, such as for fans.
-// Timers are actually pointers. Convert to integers to simplify constexpr logic.
-static constexpr uintptr_t timers_in_use[] = {
- uintptr_t(TEMP_TIMER_DEV), // Override in pins file
- uintptr_t(STEP_TIMER_DEV), // Override in pins file
+// constexpr doesn't like using the base address pointers that timers evaluate to.
+// We can get away with casting them to uintptr_t, if we do so inside an array.
+// GCC will not currently do it directly to a uintptr_t.
+IF_ENABLED(HAS_TMC_SW_SERIAL, static constexpr uintptr_t timer_serial[] = {uintptr_t(TIMER_SERIAL)});
+IF_ENABLED(SPEAKER, static constexpr uintptr_t timer_tone[] = {uintptr_t(TIMER_TONE)});
+IF_ENABLED(HAS_SERVOS, static constexpr uintptr_t timer_servo[] = {uintptr_t(TIMER_SERVO)});
+
+enum TimerPurpose { TP_SERIAL, TP_TONE, TP_SERVO, TP_STEP, TP_TEMP };
+
+// List of timers, to enable checking for conflicts.
+// Includes the purpose of each timer to ease debugging when evaluating at build-time.
+// This cannot yet account for timers used for PWM output, such as for fans.
+static constexpr struct { TimerPurpose p; int t; } timers_in_use[] = {
#if HAS_TMC_SW_SERIAL
- uintptr_t(TIMER_SERIAL), // Set in variant.h, or as a define in platformio.h if not present in variant.h
+ {TP_SERIAL, get_timer_num_from_base_address(timer_serial[0])}, // Set in variant.h, or as a define in platformio.h if not present in variant.h
#endif
#if ENABLED(SPEAKER)
- uintptr_t(TIMER_TONE), // Set in variant.h, or as a define in platformio.h if not present in variant.h
+ {TP_TONE, get_timer_num_from_base_address(timer_tone[0])}, // Set in variant.h, or as a define in platformio.h if not present in variant.h
#endif
#if HAS_SERVOS
- uintptr_t(TIMER_SERVO), // Set in variant.h, or as a define in platformio.h if not present in variant.h
+ {TP_SERVO, get_timer_num_from_base_address(timer_servo[0])}, // Set in variant.h, or as a define in platformio.h if not present in variant.h
#endif
- };
+ {TP_STEP, STEP_TIMER},
+ {TP_TEMP, TEMP_TIMER},
+};
-static constexpr bool verify_no_duplicate_timers() {
+static constexpr bool verify_no_timer_conflicts() {
LOOP_L_N(i, COUNT(timers_in_use))
LOOP_S_L_N(j, i + 1, COUNT(timers_in_use))
- if (timers_in_use[i] == timers_in_use[j]) return false;
+ if (timers_in_use[i].t == timers_in_use[j].t) return false;
return true;
}
-// If this assertion fails at compile time, review the timers_in_use array. If default_envs is
-// defined properly in platformio.ini, VS Code can evaluate the array when hovering over it,
-// making it easy to identify the conflicting timers.
-static_assert(verify_no_duplicate_timers(), "One or more timer conflict detected");
+// If this assertion fails at compile time, review the timers_in_use array.
+// If default_envs is defined properly in platformio.ini, VS Code can evaluate the array
+// when hovering over it, making it easy to identify the conflicting timers.
+static_assert(verify_no_timer_conflicts(), "One or more timer conflict detected. Examine \"timers_in_use\" to help identify conflict.");
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/timers.h b/Marlin/src/HAL/STM32/timers.h
index 5515219ea..464982430 100644
--- a/Marlin/src/HAL/STM32/timers.h
+++ b/Marlin/src/HAL/STM32/timers.h
@@ -43,6 +43,8 @@
#define hal_timer_t uint32_t
#define HAL_TIMER_TYPE_MAX UINT16_MAX
+#define NUM_HARDWARE_TIMERS 2
+
#ifndef STEP_TIMER_NUM
#define STEP_TIMER_NUM 0 // Timer Index for Stepper
#endif
@@ -57,7 +59,8 @@
// TODO: get rid of manual rate/prescale/ticks/cycles taken for procedures in stepper.cpp
#define STEPPER_TIMER_RATE 2000000 // 2 Mhz
-#define STEPPER_TIMER_PRESCALE ((HAL_TIMER_RATE)/(STEPPER_TIMER_RATE))
+extern uint32_t GetStepperTimerClkFreq();
+#define STEPPER_TIMER_PRESCALE (GetStepperTimerClkFreq() / (STEPPER_TIMER_RATE))
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE
@@ -102,7 +105,7 @@ void SetTimerInterruptPriorities();
// FORCE_INLINE because these are used in performance-critical situations
FORCE_INLINE bool HAL_timer_initialized(const uint8_t timer_num) {
- return timer_instance[timer_num] != NULL;
+ return timer_instance[timer_num] != nullptr;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
return HAL_timer_initialized(timer_num) ? timer_instance[timer_num]->getCount() : 0;
diff --git a/Marlin/src/HAL/STM32/usb_host.cpp b/Marlin/src/HAL/STM32/usb_host.cpp
new file mode 100644
index 000000000..8fa49ccbc
--- /dev/null
+++ b/Marlin/src/HAL/STM32/usb_host.cpp
@@ -0,0 +1,117 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
+
+#include "../../inc/MarlinConfig.h"
+
+#if BOTH(USE_OTG_USB_HOST, USBHOST)
+
+#include "usb_host.h"
+#include "../shared/Marduino.h"
+#include "usbh_core.h"
+#include "usbh_msc.h"
+
+USBH_HandleTypeDef hUsbHost;
+USBHost usb;
+BulkStorage bulk(&usb);
+
+static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id) {
+ switch(id) {
+ case HOST_USER_SELECT_CONFIGURATION:
+ //SERIAL_ECHOLNPGM("APPLICATION_SELECT_CONFIGURATION");
+ break;
+ case HOST_USER_DISCONNECTION:
+ //SERIAL_ECHOLNPGM("APPLICATION_DISCONNECT");
+ //usb.setUsbTaskState(USB_STATE_RUNNING);
+ break;
+ case HOST_USER_CLASS_ACTIVE:
+ //SERIAL_ECHOLNPGM("APPLICATION_READY");
+ usb.setUsbTaskState(USB_STATE_RUNNING);
+ break;
+ case HOST_USER_CONNECTION:
+ break;
+ default:
+ break;
+ }
+}
+
+bool USBHost::start() {
+ if (USBH_Init(&hUsbHost, USBH_UserProcess, TERN(USE_USB_HS_IN_FS, HOST_HS, HOST_FS)) != USBH_OK) {
+ SERIAL_ECHOLNPGM("Error: USBH_Init");
+ return false;
+ }
+ if (USBH_RegisterClass(&hUsbHost, USBH_MSC_CLASS) != USBH_OK) {
+ SERIAL_ECHOLNPGM("Error: USBH_RegisterClass");
+ return false;
+ }
+ if (USBH_Start(&hUsbHost) != USBH_OK) {
+ SERIAL_ECHOLNPGM("Error: USBH_Start");
+ return false;
+ }
+ return true;
+}
+
+void USBHost::Task() {
+ USBH_Process(&hUsbHost);
+}
+
+uint8_t USBHost::getUsbTaskState() {
+ return usb_task_state;
+}
+
+void USBHost::setUsbTaskState(uint8_t state) {
+ usb_task_state = state;
+ if (usb_task_state == USB_STATE_RUNNING) {
+ MSC_LUNTypeDef info;
+ USBH_MSC_GetLUNInfo(&hUsbHost, usb.lun, &info);
+ capacity = info.capacity.block_nbr / 2000;
+ block_size = info.capacity.block_size;
+ block_count = info.capacity.block_nbr;
+ // SERIAL_ECHOLNPAIR("info.capacity.block_nbr : %ld\n", info.capacity.block_nbr);
+ // SERIAL_ECHOLNPAIR("info.capacity.block_size: %d\n", info.capacity.block_size);
+ // SERIAL_ECHOLNPAIR("capacity : %d MB\n", capacity);
+ }
+};
+
+bool BulkStorage::LUNIsGood(uint8_t t) {
+ return USBH_MSC_IsReady(&hUsbHost) && USBH_MSC_UnitIsReady(&hUsbHost, t);
+}
+
+uint32_t BulkStorage::GetCapacity(uint8_t lun) {
+ return usb->block_count;
+}
+
+uint16_t BulkStorage::GetSectorSize(uint8_t lun) {
+ return usb->block_size;
+}
+
+uint8_t BulkStorage::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
+ return USBH_MSC_Read(&hUsbHost, lun, addr, buf, blocks) != USBH_OK;
+}
+
+uint8_t BulkStorage::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
+ return USBH_MSC_Write(&hUsbHost, lun, addr, const_cast(buf), blocks) != USBH_OK;
+}
+
+#endif // USE_OTG_USB_HOST && USBHOST
+#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32_F4_F7/inc/SanityCheck.h b/Marlin/src/HAL/STM32/usb_host.h
similarity index 50%
rename from Marlin/src/HAL/STM32_F4_F7/inc/SanityCheck.h
rename to Marlin/src/HAL/STM32/usb_host.h
index 9bb36f3bb..c0001c0d7 100644
--- a/Marlin/src/HAL/STM32_F4_F7/inc/SanityCheck.h
+++ b/Marlin/src/HAL/STM32/usb_host.h
@@ -21,21 +21,40 @@
*/
#pragma once
-/**
- * Test STM32F4/7-specific configuration values for errors at compile-time.
- */
-//#if ENABLED(SPINDLE_LASER_PWM) && !(SPINDLE_LASER_PWM_PIN == 4 || SPINDLE_LASER_PWM_PIN == 6 || SPINDLE_LASER_PWM_PIN == 11)
-// #error "SPINDLE_LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
-//#endif
+#include
-#if ENABLED(EMERGENCY_PARSER)
- #error "EMERGENCY_PARSER is not yet implemented for STM32F4/7. Disable EMERGENCY_PARSER to continue."
-#endif
+typedef enum {
+ USB_STATE_INIT,
+ USB_STATE_ERROR,
+ USB_STATE_RUNNING,
+} usb_state_t;
-#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
- #error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on STM32F4/F7."
-#endif
+class USBHost {
+public:
+ bool start();
+ void Task();
+ uint8_t getUsbTaskState();
+ void setUsbTaskState(uint8_t state);
+ uint8_t regRd(uint8_t reg) { return 0x0; };
+ uint8_t usb_task_state = USB_STATE_INIT;
+ uint8_t lun = 0;
+ uint32_t capacity = 0;
+ uint16_t block_size = 0;
+ uint32_t block_count = 0;
+};
-#if HAS_TMC_SW_SERIAL
- #error "TMC220x Software Serial is not supported on this platform."
-#endif
+class BulkStorage {
+public:
+ BulkStorage(USBHost *usb) : usb(usb) {};
+
+ bool LUNIsGood(uint8_t t);
+ uint32_t GetCapacity(uint8_t lun);
+ uint16_t GetSectorSize(uint8_t lun);
+ uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf);
+ uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf);
+
+ USBHost *usb;
+};
+
+extern USBHost usb;
+extern BulkStorage bulk;
diff --git a/Marlin/src/HAL/STM32/usb_serial.cpp b/Marlin/src/HAL/STM32/usb_serial.cpp
index 2dd1bef12..705d649ff 100644
--- a/Marlin/src/HAL/STM32/usb_serial.cpp
+++ b/Marlin/src/HAL/STM32/usb_serial.cpp
@@ -16,12 +16,11 @@
* along with this program. If not, see .
*
*/
-
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#include "../../inc/MarlinConfigPre.h"
-#if ENABLED(EMERGENCY_PARSER)
+#if ENABLED(EMERGENCY_PARSER) && USBD_USE_CDC
#include "usb_serial.h"
#include "../../feature/e_parser.h"
@@ -51,5 +50,5 @@ void USB_Hook_init() {
USBD_CDC_fops.Receive = USBD_CDC_Receive_hook;
}
-#endif // EMERGENCY_PARSER
+#endif // EMERGENCY_PARSER && USBD_USE_CDC
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/watchdog.cpp b/Marlin/src/HAL/STM32/watchdog.cpp
index cc1855314..aad0a79a0 100644
--- a/Marlin/src/HAL/STM32/watchdog.cpp
+++ b/Marlin/src/HAL/STM32/watchdog.cpp
@@ -25,23 +25,25 @@
#if ENABLED(USE_WATCHDOG)
- #include "../../inc/MarlinConfig.h"
+#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
- #include "watchdog.h"
- #include
+#include "../../inc/MarlinConfig.h"
- void watchdog_init() {
- #if DISABLED(DISABLE_WATCHDOG_INIT)
- IWatchdog.begin(4000000); // 4 sec timeout
- #endif
- }
+#include "watchdog.h"
+#include
- void HAL_watchdog_refresh() {
- IWatchdog.reload();
- #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
- TOGGLE(LED_PIN); // heartbeat indicator
- #endif
- }
+void watchdog_init() {
+ #if DISABLED(DISABLE_WATCHDOG_INIT)
+ IWatchdog.begin(WDT_TIMEOUT_US);
+ #endif
+}
+
+void HAL_watchdog_refresh() {
+ IWatchdog.reload();
+ #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
+ TOGGLE(LED_PIN); // heartbeat indicator
+ #endif
+}
#endif // USE_WATCHDOG
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32F1/HAL.cpp b/Marlin/src/HAL/STM32F1/HAL.cpp
index cd1efc165..2efea4f00 100644
--- a/Marlin/src/HAL/STM32F1/HAL.cpp
+++ b/Marlin/src/HAL/STM32F1/HAL.cpp
@@ -82,8 +82,34 @@
// Public Variables
// ------------------------
-#if (defined(SERIAL_USB) && !defined(USE_USB_COMPOSITE))
+#if defined(SERIAL_USB) && !HAS_SD_HOST_DRIVE
USBSerial SerialUSB;
+ DefaultSerial1 MSerial0(true, SerialUSB);
+
+ #if ENABLED(EMERGENCY_PARSER)
+ #include "../libmaple/usb/stm32f1/usb_reg_map.h"
+ #include "libmaple/usb_cdcacm.h"
+ // The original callback is not called (no way to retrieve address).
+ // That callback detects a special STM32 reset sequence: this functionality is not essential
+ // as M997 achieves the same.
+ void my_rx_callback(unsigned int, void*) {
+ // max length of 16 is enough to contain all emergency commands
+ uint8 buf[16];
+
+ //rx is usbSerialPart.endpoints[2]
+ uint16 len = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP);
+ uint32 total = usb_cdcacm_data_available();
+
+ if (len == 0 || total == 0 || !WITHIN(total, len, COUNT(buf)))
+ return;
+
+ // cannot get character by character due to bug in composite_cdcacm_peek_ex
+ len = usb_cdcacm_peek(buf, total);
+
+ for (uint32 i = 0; i < len; i++)
+ emergency_parser.update(MSerial0.emergency_state, buf[i + total - len]);
+ }
+ #endif
#endif
uint16_t HAL_adc_result;
@@ -106,6 +132,9 @@ const uint8_t adc_pins[] = {
#if HAS_TEMP_CHAMBER
TEMP_CHAMBER_PIN,
#endif
+ #if HAS_TEMP_COOLER
+ TEMP_COOLER_PIN,
+ #endif
#if HAS_TEMP_ADC_1
TEMP_1_PIN,
#endif
@@ -130,7 +159,7 @@ const uint8_t adc_pins[] = {
#if ENABLED(FILAMENT_WIDTH_SENSOR)
FILWIDTH_PIN,
#endif
- #if ENABLED(ADC_KEYPAD)
+ #if HAS_ADC_BUTTONS
ADC_KEYPAD_PIN,
#endif
#if HAS_JOY_ADC_X
@@ -163,6 +192,9 @@ enum TempPinIndex : char {
#if HAS_TEMP_CHAMBER
TEMP_CHAMBER,
#endif
+ #if HAS_TEMP_COOLER
+ TEMP_COOLER_PIN,
+ #endif
#if HAS_TEMP_ADC_1
TEMP_1,
#endif
@@ -187,7 +219,7 @@ enum TempPinIndex : char {
#if ENABLED(FILAMENT_WIDTH_SENSOR)
FILWIDTH,
#endif
- #if ENABLED(ADC_KEYPAD)
+ #if HAS_ADC_BUTTONS
ADC_KEY,
#endif
#if HAS_JOY_ADC_X
@@ -246,34 +278,37 @@ static void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) {
} }
#endif
+TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
+
void HAL_init() {
NVIC_SetPriorityGrouping(0x3);
#if PIN_EXISTS(LED)
OUT_WRITE(LED_PIN, LOW);
#endif
- #ifdef USE_USB_COMPOSITE
+ #if HAS_SD_HOST_DRIVE
MSC_SD_init();
+ #elif BOTH(SERIAL_USB, EMERGENCY_PARSER)
+ usb_cdcacm_set_hooks(USB_CDCACM_HOOK_RX, my_rx_callback);
#endif
#if PIN_EXISTS(USB_CONNECT)
OUT_WRITE(USB_CONNECT_PIN, !USB_CONNECT_INVERTING); // USB clear connection
delay(1000); // Give OS time to notice
OUT_WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING);
#endif
+ TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the minimal serial handler
}
// HAL idle task
void HAL_idletask() {
- #ifdef USE_USB_COMPOSITE
- #if HAS_SHARED_MEDIA
- // If Marlin is using the SD card we need to lock it to prevent access from
- // a PC via USB.
- // Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but
- // this will not reliably detect delete operations. To be safe we will lock
- // the disk if Marlin has it mounted. Unfortunately there is currently no way
- // to unmount the disk from the LCD menu.
- // if (IS_SD_PRINTING() || IS_SD_FILE_OPEN())
- /* copy from lpc1768 framework, should be fixed later for process HAS_SHARED_MEDIA*/
- #endif
+ #if HAS_SHARED_MEDIA
+ // If Marlin is using the SD card we need to lock it to prevent access from
+ // a PC via USB.
+ // Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but
+ // this will not reliably detect delete operations. To be safe we will lock
+ // the disk if Marlin has it mounted. Unfortunately there is currently no way
+ // to unmount the disk from the LCD menu.
+ // if (IS_SD_PRINTING() || IS_SD_FILE_OPEN())
+ /* copy from lpc1768 framework, should be fixed later for process HAS_SD_HOST_DRIVE*/
// process USB mass storage device class loop
MarlinMSC.loop();
#endif
@@ -356,6 +391,9 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
#if HAS_TEMP_CHAMBER
case TEMP_CHAMBER_PIN: pin_index = TEMP_CHAMBER; break;
#endif
+ #if HAS_TEMP_COOLER
+ case TEMP_COOLER_PIN: pin_index = TEMP_COOLER; break;
+ #endif
#if HAS_TEMP_ADC_1
case TEMP_1_PIN: pin_index = TEMP_1; break;
#endif
@@ -389,7 +427,7 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
#if ENABLED(FILAMENT_WIDTH_SENSOR)
case FILWIDTH_PIN: pin_index = FILWIDTH; break;
#endif
- #if ENABLED(ADC_KEYPAD)
+ #if HAS_ADC_BUTTONS
case ADC_KEYPAD_PIN: pin_index = ADC_KEY; break;
#endif
#if ENABLED(POWER_MONITOR_CURRENT)
@@ -415,6 +453,8 @@ void analogWrite(pin_t pin, int pwm_val8) {
analogWrite(uint8_t(pin), pwm_val8);
}
-void flashFirmware(const int16_t) { nvic_sys_reset(); }
+void HAL_reboot() { nvic_sys_reset(); }
+
+void flashFirmware(const int16_t) { HAL_reboot(); }
#endif // __STM32F1__
diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h
index c10dea0ea..af4d27f43 100644
--- a/Marlin/src/HAL/STM32F1/HAL.h
+++ b/Marlin/src/HAL/STM32F1/HAL.h
@@ -42,7 +42,7 @@
#include "../../inc/MarlinConfigPre.h"
-#ifdef USE_USB_COMPOSITE
+#if HAS_SD_HOST_DRIVE
#include "msc_sd.h"
#endif
@@ -53,7 +53,7 @@
// ------------------------
#ifndef STM32_FLASH_SIZE
- #if EITHER(MCU_STM32F103RE, MCU_STM32F103VE)
+ #if ANY(MCU_STM32F103RE, MCU_STM32F103VE, MCU_STM32F103ZE)
#define STM32_FLASH_SIZE 512
#else
#define STM32_FLASH_SIZE 256
@@ -61,8 +61,11 @@
#endif
#ifdef SERIAL_USB
- #ifndef USE_USB_COMPOSITE
- #define UsbSerial Serial
+ typedef ForwardSerial1Class< USBSerial > DefaultSerial1;
+ extern DefaultSerial1 MSerial0;
+
+ #if !HAS_SD_HOST_DRIVE
+ #define UsbSerial MSerial0
#else
#define UsbSerial MarlinCompositeSerial
#endif
@@ -78,24 +81,45 @@
#endif
#if SERIAL_PORT == -1
- #define MYSERIAL0 UsbSerial
+ #define MYSERIAL1 UsbSerial
#elif WITHIN(SERIAL_PORT, 1, NUM_UARTS)
- #define MYSERIAL0 MSERIAL(SERIAL_PORT)
-#elif NUM_UARTS == 5
- #error "SERIAL_PORT must be -1 or from 1 to 5. Please update your configuration."
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
- #error "SERIAL_PORT must be -1 or from 1 to 3. Please update your configuration."
+ #define MYSERIAL1 MSERIAL(1) // dummy port
+ #if NUM_UARTS == 5
+ #error "SERIAL_PORT must be from 1 to 5. You can also use -1 if the board supports Native USB."
+ #else
+ #error "SERIAL_PORT must be from 1 to 3. You can also use -1 if the board supports Native USB."
+ #endif
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
- #define MYSERIAL1 UsbSerial
+ #define MYSERIAL2 UsbSerial
#elif WITHIN(SERIAL_PORT_2, 1, NUM_UARTS)
- #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
- #elif NUM_UARTS == 5
- #error "SERIAL_PORT_2 must be -1 or from 1 to 5. Please update your configuration."
+ #define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
- #error "SERIAL_PORT_2 must be -1 or from 1 to 3. Please update your configuration."
+ #define MYSERIAL2 MSERIAL(1) // dummy port
+ #if NUM_UARTS == 5
+ #error "SERIAL_PORT_2 must be from 1 to 5. You can also use -1 if the board supports Native USB."
+ #else
+ #error "SERIAL_PORT_2 must be from 1 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+ #endif
+#endif
+
+#ifdef MMU2_SERIAL_PORT
+ #if MMU2_SERIAL_PORT == -1
+ #define MMU2_SERIAL UsbSerial
+ #elif WITHIN(MMU2_SERIAL_PORT, 1, NUM_UARTS)
+ #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
+ #else
+ #define MMU2_SERIAL MSERIAL(1) // dummy port
+ #if NUM_UARTS == 5
+ #error "MMU2_SERIAL_PORT must be from 1 to 5. You can also use -1 if the board supports Native USB."
+ #else
+ #error "MMU2_SERIAL_PORT must be from 1 to 3. You can also use -1 if the board supports Native USB."
+ #endif
#endif
#endif
@@ -104,10 +128,16 @@
#define LCD_SERIAL UsbSerial
#elif WITHIN(LCD_SERIAL_PORT, 1, NUM_UARTS)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
- #elif NUM_UARTS == 5
- #error "LCD_SERIAL_PORT must be -1 or from 1 to 5. Please update your configuration."
#else
- #error "LCD_SERIAL_PORT must be -1 or from 1 to 3. Please update your configuration."
+ #define LCD_SERIAL MSERIAL(1) // dummy port
+ #if NUM_UARTS == 5
+ #error "LCD_SERIAL_PORT must be from 1 to 5. You can also use -1 if the board supports Native USB."
+ #else
+ #error "LCD_SERIAL_PORT must be from 1 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+ #endif
+ #if HAS_DGUS_LCD
+ #define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
#endif
#endif
@@ -124,7 +154,7 @@ void HAL_idletask();
#endif
#ifndef digitalPinHasPWM
- #define digitalPinHasPWM(P) (PIN_MAP[P].timer_device != nullptr)
+ #define digitalPinHasPWM(P) !!PIN_MAP[P].timer_device
#define NO_COMPILE_TIME_PWM
#endif
@@ -137,14 +167,6 @@ void HAL_idletask();
// On AVR this is in math.h?
#define square(x) ((x)*(x))
-#ifndef strncpy_P
- #define strncpy_P(dest, src, num) strncpy((dest), (src), (num))
-#endif
-
-// Fix bug in pgm_read_ptr
-#undef pgm_read_ptr
-#define pgm_read_ptr(addr) (*(addr))
-
#define RST_POWER_ON 1
#define RST_EXTERNAL 2
#define RST_BROWN_OUT 4
@@ -185,7 +207,7 @@ void HAL_clear_reset_source();
// Reset reason
uint8_t HAL_get_reset_source();
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+void HAL_reboot();
void _delay_ms(const int delay);
@@ -200,17 +222,9 @@ extern "C" {
extern "C" char* _sbrk(int incr);
-/*
-static int freeMemory() {
- volatile int top;
- top = (int)((char*)&top - reinterpret_cast(_sbrk(0)));
- return top;
-}
-*/
-
-static int freeMemory() {
+static inline int freeMemory() {
volatile char top;
- return &top - reinterpret_cast(_sbrk(0));
+ return &top - _sbrk(0);
}
#pragma GCC diagnostic pop
@@ -244,3 +258,20 @@ void analogWrite(pin_t pin, int pwm_val8); // PWM only! mul by 257 in maple!?
#define PLATFORM_M997_SUPPORT
void flashFirmware(const int16_t);
+
+#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
+
+/**
+ * set_pwm_frequency
+ * Set the frequency of the timer corresponding to the provided pin
+ * All Timer PWM pins run at the same frequency
+ */
+void set_pwm_frequency(const pin_t pin, int f_desired);
+
+/**
+ * set_pwm_duty
+ * Set the PWM duty cycle of the provided pin to the provided value
+ * Optionally allows inverting the duty cycle [default = false]
+ * Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
+ */
+void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
diff --git a/Marlin/src/HAL/STM32F1/HAL_MinSerial.cpp b/Marlin/src/HAL/STM32F1/HAL_MinSerial.cpp
new file mode 100644
index 000000000..2cb75bb1e
--- /dev/null
+++ b/Marlin/src/HAL/STM32F1/HAL_MinSerial.cpp
@@ -0,0 +1,118 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ * Copyright (c) 2017 Victor Perez
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef __STM32F1__
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+
+#include "../shared/HAL_MinSerial.h"
+#include "watchdog.h"
+
+#include
+#include
+#include
+
+/* Instruction Synchronization Barrier */
+#define isb() __asm__ __volatile__ ("isb" : : : "memory")
+
+/* Data Synchronization Barrier */
+#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
+
+static void TXBegin() {
+ #if !WITHIN(SERIAL_PORT, 1, 6)
+ #warning "Using POSTMORTEM_DEBUGGING requires a physical U(S)ART hardware in case of severe error."
+ #warning "Disabling the severe error reporting feature currently because the used serial port is not a HW port."
+ #else
+ // We use MYSERIAL1 here, so we need to figure out how to get the linked register
+ struct usart_dev* dev = MYSERIAL1.c_dev();
+
+ // Or use this if removing libmaple
+ // int irq = dev->irq_num;
+ // int nvicUART[] = { NVIC_USART1 /* = 37 */, NVIC_USART2 /* = 38 */, NVIC_USART3 /* = 39 */, NVIC_UART4 /* = 52 */, NVIC_UART5 /* = 53 */ };
+ // Disabling irq means setting the bit in the NVIC ICER register located at
+ // Disable UART interrupt in NVIC
+ nvic_irq_disable(dev->irq_num);
+
+ // Use this if removing libmaple
+ //NVIC_BASE->ICER[1] |= _BV(irq - 32);
+
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ dsb();
+ isb();
+
+ rcc_clk_disable(dev->clk_id);
+ rcc_clk_enable(dev->clk_id);
+
+ usart_reg_map *regs = dev->regs;
+ regs->CR1 = 0; // Reset the USART
+ regs->CR2 = 0; // 1 stop bit
+
+ // If we don't touch the BRR (baudrate register), we don't need to recompute. Else we would need to call
+ usart_set_baud_rate(dev, 0, BAUDRATE);
+
+ regs->CR1 = (USART_CR1_TE | USART_CR1_UE); // 8 bits, no parity, 1 stop bit
+ #endif
+}
+
+// A SW memory barrier, to ensure GCC does not overoptimize loops
+#define sw_barrier() __asm__ volatile("": : :"memory");
+static void TX(char c) {
+ #if WITHIN(SERIAL_PORT, 1, 6)
+ struct usart_dev* dev = MYSERIAL1.c_dev();
+ while (!(dev->regs->SR & USART_SR_TXE)) {
+ TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
+ sw_barrier();
+ }
+ dev->regs->DR = c;
+ #endif
+}
+
+void install_min_serial() {
+ HAL_min_serial_init = &TXBegin;
+ HAL_min_serial_out = &TX;
+}
+
+#if DISABLED(DYNAMIC_VECTORTABLE) && DISABLED(STM32F0xx) // Cortex M0 can't branch to a symbol that's too far, so we have a specific hack for them
+extern "C" {
+ __attribute__((naked)) void JumpHandler_ASM() {
+ __asm__ __volatile__ (
+ "b CommonHandler_ASM\n"
+ );
+ }
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_hardfault();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_busfault();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_usagefault();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_memmanage();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __exc_nmi();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception7();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception8();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception9();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception10();
+ void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) __stm32reservedexception13();
+}
+#endif
+
+#endif // POSTMORTEM_DEBUGGING
+#endif // __STM32F1__
diff --git a/Marlin/src/HAL/STM32F1/HAL_SPI.cpp b/Marlin/src/HAL/STM32F1/HAL_SPI.cpp
index 76b1c3e24..abb348d74 100644
--- a/Marlin/src/HAL/STM32F1/HAL_SPI.cpp
+++ b/Marlin/src/HAL/STM32F1/HAL_SPI.cpp
@@ -61,8 +61,8 @@
* @details Only configures SS pin since libmaple creates and initialize the SPI object
*/
void spiBegin() {
- #if PIN_EXISTS(SS)
- OUT_WRITE(SS_PIN, HIGH);
+ #if PIN_EXISTS(SD_SS)
+ OUT_WRITE(SD_SS_PIN, HIGH);
#endif
}
@@ -123,7 +123,7 @@ uint8_t spiRec() {
*
* @details Uses DMA
*/
-void spiRead(uint8_t* buf, uint16_t nbyte) {
+void spiRead(uint8_t *buf, uint16_t nbyte) {
SPI.dmaTransfer(0, const_cast(buf), nbyte);
}
@@ -146,7 +146,7 @@ void spiSend(uint8_t b) {
*
* @details Use DMA
*/
-void spiSendBlock(uint8_t token, const uint8_t* buf) {
+void spiSendBlock(uint8_t token, const uint8_t *buf) {
SPI.send(token);
SPI.dmaSend(const_cast(buf), 512);
}
@@ -160,7 +160,7 @@ uint8_t spiRec(uint32_t chan) { return SPI.transfer(0xFF); }
void spiSend(uint32_t chan, byte b) { SPI.send(b); }
// Write buffer to specified SPI channel
-void spiSend(uint32_t chan, const uint8_t* buf, size_t n) {
+void spiSend(uint32_t chan, const uint8_t *buf, size_t n) {
for (size_t p = 0; p < n; p++) spiSend(chan, buf[p]);
}
diff --git a/Marlin/src/HAL/STM32F1/MarlinSPI.h b/Marlin/src/HAL/STM32F1/MarlinSPI.h
new file mode 100644
index 000000000..fab245f90
--- /dev/null
+++ b/Marlin/src/HAL/STM32F1/MarlinSPI.h
@@ -0,0 +1,45 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include
+
+/**
+ * Marlin currently requires 3 SPI classes:
+ *
+ * SPIClass:
+ * This class is normally provided by frameworks and has a semi-default interface.
+ * This is needed because some libraries reference it globally.
+ *
+ * SPISettings:
+ * Container for SPI configs for SPIClass. As above, libraries may reference it globally.
+ *
+ * These two classes are often provided by frameworks so we cannot extend them to add
+ * useful methods for Marlin.
+ *
+ * MarlinSPI:
+ * Provides the default SPIClass interface plus some Marlin goodies such as a simplified
+ * interface for SPI DMA transfer.
+ *
+ */
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/STM32F1/MarlinSerial.cpp b/Marlin/src/HAL/STM32F1/MarlinSerial.cpp
index ebf11cb42..fa8bb7eaa 100644
--- a/Marlin/src/HAL/STM32F1/MarlinSerial.cpp
+++ b/Marlin/src/HAL/STM32F1/MarlinSerial.cpp
@@ -28,7 +28,7 @@
// Copied from ~/.platformio/packages/framework-arduinoststm32-maple/STM32F1/system/libmaple/usart_private.h
// Changed to handle Emergency Parser
-static inline __always_inline void my_usart_irq(ring_buffer *rb, ring_buffer *wb, usart_reg_map *regs, MarlinSerial &serial) {
+static inline __always_inline void my_usart_irq(ring_buffer *rb, ring_buffer *wb, usart_reg_map *regs, MSerialT &serial) {
/* Handle RXNEIE and TXEIE interrupts.
* RXNE signifies availability of a byte in DR.
*
@@ -60,7 +60,7 @@ static inline __always_inline void my_usart_irq(ring_buffer *rb, ring_buffer *wb
}
else if (srflags & USART_SR_ORE) {
// overrun and empty data, just do a dummy read to clear ORE
- // and prevent a raise condition where a continous interrupt stream (due to ORE set) occurs
+ // and prevent a raise condition where a continuous interrupt stream (due to ORE set) occurs
// (see chapter "Overrun error" ) in STM32 reference manual
regs->DR;
}
@@ -90,20 +90,20 @@ constexpr bool serial_handles_emergency(int port) {
;
}
-#define DEFINE_HWSERIAL_MARLIN(name, n) \
- MarlinSerial name(USART##n, \
- BOARD_USART##n##_TX_PIN, \
- BOARD_USART##n##_RX_PIN, \
- serial_handles_emergency(n)); \
- extern "C" void __irq_usart##n(void) { \
+#define DEFINE_HWSERIAL_MARLIN(name, n) \
+ MSerialT name(serial_handles_emergency(n),\
+ USART##n, \
+ BOARD_USART##n##_TX_PIN, \
+ BOARD_USART##n##_RX_PIN); \
+ extern "C" void __irq_usart##n(void) { \
my_usart_irq(USART##n->rb, USART##n->wb, USART##n##_BASE, MSerial##n); \
}
#define DEFINE_HWSERIAL_UART_MARLIN(name, n) \
- MarlinSerial name(UART##n, \
+ MSerialT name(serial_handles_emergency(n), \
+ UART##n, \
BOARD_USART##n##_TX_PIN, \
- BOARD_USART##n##_RX_PIN, \
- serial_handles_emergency(n)); \
+ BOARD_USART##n##_RX_PIN); \
extern "C" void __irq_usart##n(void) { \
my_usart_irq(UART##n->rb, UART##n->wb, UART##n##_BASE, MSerial##n); \
}
@@ -111,7 +111,9 @@ constexpr bool serial_handles_emergency(int port) {
// Instantiate all UARTs even if they are not needed
// This avoids a bunch of logic to figure out every serial
// port which may be in use on the system.
-DEFINE_HWSERIAL_MARLIN(MSerial1, 1);
+#if DISABLED(MKS_WIFI_MODULE)
+ DEFINE_HWSERIAL_MARLIN(MSerial1, 1);
+#endif
DEFINE_HWSERIAL_MARLIN(MSerial2, 2);
DEFINE_HWSERIAL_MARLIN(MSerial3, 3);
#if EITHER(STM32_HIGH_DENSITY, STM32_XL_DENSITY)
@@ -132,12 +134,12 @@ constexpr bool IsSerialClassAllowed(const HardwareSerial&) { return false; }
// If you encounter this error, replace SerialX with MSerialX, for example MSerial3.
// Non-TMC ports were already validated in HAL.h, so do not require verbose error messages.
-#ifdef MYSERIAL0
- CHECK_CFG_SERIAL(MYSERIAL0);
-#endif
#ifdef MYSERIAL1
CHECK_CFG_SERIAL(MYSERIAL1);
#endif
+#ifdef MYSERIAL2
+ CHECK_CFG_SERIAL(MYSERIAL2);
+#endif
#ifdef LCD_SERIAL
CHECK_CFG_SERIAL(LCD_SERIAL);
#endif
diff --git a/Marlin/src/HAL/STM32F1/MarlinSerial.h b/Marlin/src/HAL/STM32F1/MarlinSerial.h
index 6aa94b64f..dda32fe7a 100644
--- a/Marlin/src/HAL/STM32F1/MarlinSerial.h
+++ b/Marlin/src/HAL/STM32F1/MarlinSerial.h
@@ -26,28 +26,13 @@
#include
#include "../../inc/MarlinConfigPre.h"
-#if ENABLED(EMERGENCY_PARSER)
- #include "../../feature/e_parser.h"
-#endif
+#include "../../core/serial_hook.h"
// Increase priority of serial interrupts, to reduce overflow errors
#define UART_IRQ_PRIO 1
-class MarlinSerial : public HardwareSerial {
-public:
- #if ENABLED(EMERGENCY_PARSER)
- const bool ep_enabled;
- EmergencyParser::State emergency_state;
- inline bool emergency_parser_enabled() { return ep_enabled; }
- #endif
-
- MarlinSerial(struct usart_dev *usart_device, uint8 tx_pin, uint8 rx_pin, bool TERN_(EMERGENCY_PARSER, ep_capable)) :
- HardwareSerial(usart_device, tx_pin, rx_pin)
- #if ENABLED(EMERGENCY_PARSER)
- , ep_enabled(ep_capable)
- , emergency_state(EmergencyParser::State::EP_RESET)
- #endif
- { }
+struct MarlinSerial : public HardwareSerial {
+ MarlinSerial(struct usart_dev *usart_device, uint8 tx_pin, uint8 rx_pin) : HardwareSerial(usart_device, tx_pin, rx_pin) { }
#ifdef UART_IRQ_PRIO
// Shadow the parent methods to set IRQ priority after begin()
@@ -62,10 +47,12 @@ public:
#endif
};
-extern MarlinSerial MSerial1;
-extern MarlinSerial MSerial2;
-extern MarlinSerial MSerial3;
+typedef Serial1Class MSerialT;
+
+extern MSerialT MSerial1;
+extern MSerialT MSerial2;
+extern MSerialT MSerial3;
#if EITHER(STM32_HIGH_DENSITY, STM32_XL_DENSITY)
- extern MarlinSerial MSerial4;
- extern MarlinSerial MSerial5;
+ extern MSerialT MSerial4;
+ extern MSerialT MSerial5;
#endif
diff --git a/Marlin/src/HAL/STM32F1/SPI.cpp b/Marlin/src/HAL/STM32F1/SPI.cpp
index 0452cf629..c0a35b88d 100644
--- a/Marlin/src/HAL/STM32F1/SPI.cpp
+++ b/Marlin/src/HAL/STM32F1/SPI.cpp
@@ -147,6 +147,18 @@ SPIClass::SPIClass(uint32_t spi_num) {
_currentSetting->state = SPI_STATE_IDLE;
}
+SPIClass::SPIClass(int8_t mosi, int8_t miso, int8_t sclk, int8_t ssel) : SPIClass(1) {
+ #if BOARD_NR_SPI >= 1
+ if (mosi == BOARD_SPI1_MOSI_PIN) setModule(1);
+ #endif
+ #if BOARD_NR_SPI >= 2
+ if (mosi == BOARD_SPI2_MOSI_PIN) setModule(2);
+ #endif
+ #if BOARD_NR_SPI >= 3
+ if (mosi == BOARD_SPI3_MOSI_PIN) setModule(3);
+ #endif
+}
+
/**
* Set up/tear down
*/
@@ -656,7 +668,7 @@ static const spi_pins* dev_to_spi_pins(spi_dev *dev) {
#if BOARD_NR_SPI >= 3
case RCC_SPI3: return board_spi_pins + 2;
#endif
- default: return NULL;
+ default: return nullptr;
}
}
diff --git a/Marlin/src/HAL/STM32F1/SPI.h b/Marlin/src/HAL/STM32F1/SPI.h
index 0d20a4657..828644f1d 100644
--- a/Marlin/src/HAL/STM32F1/SPI.h
+++ b/Marlin/src/HAL/STM32F1/SPI.h
@@ -163,6 +163,11 @@ public:
*/
SPIClass(uint32_t spiPortNumber);
+ /**
+ * Init using pins
+ */
+ SPIClass(int8_t mosi, int8_t miso, int8_t sclk, int8_t ssel=-1);
+
/**
* @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
*/
diff --git a/Marlin/src/HAL/STM32F1/Servo.cpp b/Marlin/src/HAL/STM32F1/Servo.cpp
index e1ee83149..36f7c6d51 100644
--- a/Marlin/src/HAL/STM32F1/Servo.cpp
+++ b/Marlin/src/HAL/STM32F1/Servo.cpp
@@ -45,7 +45,7 @@ uint8_t ServoCount = 0;
*
* This uses the smallest prescaler that allows an overflow < 2^16.
*/
-#define MAX_OVERFLOW UINT16_MAX //((1 << 16) - 1)
+#define MAX_OVERFLOW UINT16_MAX // _BV(16) - 1
#define CYC_MSEC (1000 * CYCLES_PER_MICROSECOND)
#define TAU_MSEC 20
#define TAU_USEC (TAU_MSEC * 1000)
diff --git a/Marlin/src/HAL/STM32F1/SoftwareSerial.cpp b/Marlin/src/HAL/STM32F1/SoftwareSerial.cpp
deleted file mode 100644
index 993403cf7..000000000
--- a/Marlin/src/HAL/STM32F1/SoftwareSerial.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#if defined(__STM32F1__) && !defined(HAVE_SW_SERIAL)
-
-/**
- * Empty class for Software Serial implementation (Custom RX/TX pins)
- *
- * TODO: Optionally use https://github.com/FYSETC/SoftwareSerialM if TMC UART is wanted
- */
-
-#include "SoftwareSerial.h"
-
-// Constructor
-
-SoftwareSerial::SoftwareSerial(int8_t RX_pin, int8_t TX_pin) {}
-
-// Public
-
-void SoftwareSerial::begin(const uint32_t baudrate) {
-}
-
-bool SoftwareSerial::available() {
- return false;
-}
-
-uint8_t SoftwareSerial::read() {
- return 0;
-}
-
-uint16_t SoftwareSerial::write(uint8_t byte) {
- return 0;
-}
-
-void SoftwareSerial::flush() {}
-
-void SoftwareSerial::listen() {
- listening = true;
-}
-
-void SoftwareSerial::stopListening() {
- listening = false;
-}
-
-#endif // __STM32F1__
diff --git a/Marlin/src/HAL/STM32F1/SoftwareSerial.h b/Marlin/src/HAL/STM32F1/SoftwareSerial.h
deleted file mode 100644
index 1c8058665..000000000
--- a/Marlin/src/HAL/STM32F1/SoftwareSerial.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#pragma once
-
-#include
-
-#ifndef HAVE_SW_SERIAL
- #define SW_SERIAL_PLACEHOLDER 1
-#endif
-
-class SoftwareSerial {
-public:
- SoftwareSerial(int8_t RX_pin, int8_t TX_pin);
-
- void begin(const uint32_t baudrate);
-
- bool available();
-
- uint8_t read();
- uint16_t write(uint8_t byte);
- void flush();
-
- void listen();
- void stopListening();
-
-protected:
- bool listening;
-};
diff --git a/Marlin/src/HAL/STM32F1/build_flags.py b/Marlin/src/HAL/STM32F1/build_flags.py
index 98c871a1d..c51fd4fa5 100755
--- a/Marlin/src/HAL/STM32F1/build_flags.py
+++ b/Marlin/src/HAL/STM32F1/build_flags.py
@@ -3,7 +3,7 @@ import sys
#dynamic build flags for generic compile options
if __name__ == "__main__":
- args = " ".join([ "-std=gnu11",
+ args = " ".join([ "-std=gnu++14",
"-Os",
"-mcpu=cortex-m3",
"-mthumb",
diff --git a/Marlin/src/HAL/STM32F1/dogm/u8g_com_stm32duino_swspi.cpp b/Marlin/src/HAL/STM32F1/dogm/u8g_com_stm32duino_swspi.cpp
index 60596054e..784a80c29 100644
--- a/Marlin/src/HAL/STM32F1/dogm/u8g_com_stm32duino_swspi.cpp
+++ b/Marlin/src/HAL/STM32F1/dogm/u8g_com_stm32duino_swspi.cpp
@@ -23,12 +23,14 @@
#if BOTH(HAS_MARLINUI_U8GLIB, FORCE_SOFT_SPI)
#include
+#include "../../shared/HAL_SPI.h"
-#undef SPI_SPEED
-#define SPI_SPEED 0 // Fastest
-//#define SPI_SPEED 2 // Slower
+#ifndef LCD_SPI_SPEED
+ #define LCD_SPI_SPEED SPI_FULL_SPEED // Fastest
+ //#define LCD_SPI_SPEED SPI_QUARTER_SPEED // Slower
+#endif
-static uint8_t SPI_speed = SPI_SPEED;
+static uint8_t SPI_speed = LCD_SPI_SPEED;
static inline uint8_t swSpiTransfer_mode_0(uint8_t b, const uint8_t spi_speed, const pin_t miso_pin=-1) {
LOOP_L_N(i, 8) {
@@ -104,7 +106,7 @@ static uint8_t swSpiInit(const uint8_t spi_speed) {
uint8_t u8g_com_HAL_STM32F1_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch (msg) {
case U8G_COM_MSG_INIT:
- SPI_speed = swSpiInit(SPI_SPEED);
+ SPI_speed = swSpiInit(LCD_SPI_SPEED);
break;
case U8G_COM_MSG_STOP:
diff --git a/Marlin/src/HAL/STM32F1/eeprom_bl24cxx.cpp b/Marlin/src/HAL/STM32F1/eeprom_bl24cxx.cpp
index 658b7cd4a..4e25bc69d 100644
--- a/Marlin/src/HAL/STM32F1/eeprom_bl24cxx.cpp
+++ b/Marlin/src/HAL/STM32F1/eeprom_bl24cxx.cpp
@@ -19,14 +19,13 @@
* along with this program. If not, see .
*
*/
+#ifdef __STM32F1__
/**
* PersistentStore for Arduino-style EEPROM interface
* with simple implementations supplied by Marlin.
*/
-#ifdef __STM32F1__
-
#include "../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
@@ -48,14 +47,13 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t v = *value;
uint8_t * const p = (uint8_t * const)pos;
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
- if (v != eeprom_read_byte(p)) {
+ if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
- delay(2);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -68,7 +66,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
uint8_t * const p = (uint8_t * const)pos;
uint8_t c = eeprom_read_byte(p);
diff --git a/Marlin/src/HAL/STM32F1/eeprom_flash.cpp b/Marlin/src/HAL/STM32F1/eeprom_flash.cpp
index 8db8c8638..e7d9dd29e 100644
--- a/Marlin/src/HAL/STM32F1/eeprom_flash.cpp
+++ b/Marlin/src/HAL/STM32F1/eeprom_flash.cpp
@@ -48,8 +48,8 @@ static uint8_t ram_eeprom[MARLIN_EEPROM_SIZE] __attribute__((aligned(4))) = {0};
static bool eeprom_dirty = false;
bool PersistentStore::access_start() {
- const uint32_t* source = reinterpret_cast(EEPROM_PAGE0_BASE);
- uint32_t* destination = reinterpret_cast(ram_eeprom);
+ const uint32_t *source = reinterpret_cast(EEPROM_PAGE0_BASE);
+ uint32_t *destination = reinterpret_cast(ram_eeprom);
static_assert(0 == (MARLIN_EEPROM_SIZE) % 4, "MARLIN_EEPROM_SIZE is corrupted. (Must be a multiple of 4.)"); // Ensure copying as uint32_t is safe
constexpr size_t eeprom_size_u32 = (MARLIN_EEPROM_SIZE) / 4;
@@ -101,7 +101,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false; // return true for any error
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
const uint8_t * const buff = writing ? &value[0] : &ram_eeprom[pos];
if (writing) for (size_t i = 0; i < size; i++) value[i] = ram_eeprom[pos + i];
crc16(crc, buff, size);
diff --git a/Marlin/src/HAL/STM32F1/eeprom_if_iic.cpp b/Marlin/src/HAL/STM32F1/eeprom_if_iic.cpp
index ccc3fc537..78b7af0b0 100644
--- a/Marlin/src/HAL/STM32F1/eeprom_if_iic.cpp
+++ b/Marlin/src/HAL/STM32F1/eeprom_if_iic.cpp
@@ -40,7 +40,7 @@ void eeprom_init() { BL24CXX::init(); }
// Public functions
// ------------------------
-void eeprom_write_byte(uint8_t *pos, unsigned char value) {
+void eeprom_write_byte(uint8_t *pos, uint8_t value) {
const unsigned eeprom_address = (unsigned)pos;
return BL24CXX::writeOneByte(eeprom_address, value);
}
diff --git a/Marlin/src/HAL/STM32F1/eeprom_sdcard.cpp b/Marlin/src/HAL/STM32F1/eeprom_sdcard.cpp
index 11959191f..d608ccee1 100644
--- a/Marlin/src/HAL/STM32F1/eeprom_sdcard.cpp
+++ b/Marlin/src/HAL/STM32F1/eeprom_sdcard.cpp
@@ -79,7 +79,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
for (size_t i = 0; i < size; i++) {
uint8_t c = HAL_eeprom_data[pos + i];
if (writing) value[i] = c;
diff --git a/Marlin/src/HAL/STM32F1/eeprom_wired.cpp b/Marlin/src/HAL/STM32F1/eeprom_wired.cpp
index fffd6ccaf..0ad69065c 100644
--- a/Marlin/src/HAL/STM32F1/eeprom_wired.cpp
+++ b/Marlin/src/HAL/STM32F1/eeprom_wired.cpp
@@ -1,6 +1,5 @@
/**
* Marlin 3D Printer Firmware
- *
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* This program is free software: you can redistribute it and/or modify
@@ -53,13 +52,13 @@ bool PersistentStore::access_start() {
}
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
- if (v != eeprom_read_byte(p)) {
+ if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -72,7 +71,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing && value) *value = c;
diff --git a/Marlin/src/HAL/STM32F1/fast_pwm.cpp b/Marlin/src/HAL/STM32F1/fast_pwm.cpp
new file mode 100644
index 000000000..884d482af
--- /dev/null
+++ b/Marlin/src/HAL/STM32F1/fast_pwm.cpp
@@ -0,0 +1,68 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef __STM32F1__
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if NEEDS_HARDWARE_PWM
+
+#include
+#include "HAL.h"
+#include "timers.h"
+
+void set_pwm_frequency(const pin_t pin, int f_desired) {
+ if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
+
+ timer_dev *timer = PIN_MAP[pin].timer_device;
+ uint8_t channel = PIN_MAP[pin].timer_channel;
+
+ // Protect used timers
+ if (timer == get_timer_dev(TEMP_TIMER_NUM)) return;
+ if (timer == get_timer_dev(STEP_TIMER_NUM)) return;
+ #if PULSE_TIMER_NUM != STEP_TIMER_NUM
+ if (timer == get_timer_dev(PULSE_TIMER_NUM)) return;
+ #endif
+
+ if (!(timer->regs.bas->SR & TIMER_CR1_CEN)) // Ensure the timer is enabled
+ timer_init(timer);
+
+ timer_set_mode(timer, channel, TIMER_PWM);
+ uint16_t preload = 255; // Lock 255 PWM resolution for high frequencies
+ int32_t prescaler = (HAL_TIMER_RATE) / (preload + 1) / f_desired - 1;
+ if (prescaler > 65535) { // For low frequencies increase prescaler
+ prescaler = 65535;
+ preload = (HAL_TIMER_RATE) / (prescaler + 1) / f_desired - 1;
+ }
+ if (prescaler < 0) return; // Too high frequency
+ timer_set_reload(timer, preload);
+ timer_set_prescaler(timer, prescaler);
+}
+
+void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
+ timer_dev *timer = PIN_MAP[pin].timer_device;
+ uint16_t max_val = timer->regs.bas->ARR * v / v_size;
+ if (invert) max_val = v_size - max_val;
+ pwmWrite(pin, max_val);
+}
+
+#endif // NEEDS_HARDWARE_PWM
+#endif // __STM32F1__
diff --git a/Marlin/src/HAL/STM32F1/fastio.h b/Marlin/src/HAL/STM32F1/fastio.h
index e0e2e03a1..e75254d69 100644
--- a/Marlin/src/HAL/STM32F1/fastio.h
+++ b/Marlin/src/HAL/STM32F1/fastio.h
@@ -29,9 +29,9 @@
#include
-#define READ(IO) (PIN_MAP[IO].gpio_device->regs->IDR & (1U << PIN_MAP[IO].gpio_bit) ? HIGH : LOW)
-#define WRITE(IO,V) (PIN_MAP[IO].gpio_device->regs->BSRR = (1U << PIN_MAP[IO].gpio_bit) << ((V) ? 0 : 16))
-#define TOGGLE(IO) (PIN_MAP[IO].gpio_device->regs->ODR = PIN_MAP[IO].gpio_device->regs->ODR ^ (1U << PIN_MAP[IO].gpio_bit))
+#define READ(IO) (PIN_MAP[IO].gpio_device->regs->IDR & _BV32(PIN_MAP[IO].gpio_bit) ? HIGH : LOW)
+#define WRITE(IO,V) (PIN_MAP[IO].gpio_device->regs->BSRR = _BV32(PIN_MAP[IO].gpio_bit) << ((V) ? 0 : 16))
+#define TOGGLE(IO) TBI32(PIN_MAP[IO].gpio_device->regs->ODR, PIN_MAP[IO].gpio_bit)
#define _GET_MODE(IO) gpio_get_mode(PIN_MAP[IO].gpio_device, PIN_MAP[IO].gpio_bit)
#define _SET_MODE(IO,M) gpio_set_mode(PIN_MAP[IO].gpio_device, PIN_MAP[IO].gpio_bit, M)
@@ -51,7 +51,7 @@
#define IS_INPUT(IO) (_GET_MODE(IO) == GPIO_INPUT_FLOATING || _GET_MODE(IO) == GPIO_INPUT_ANALOG || _GET_MODE(IO) == GPIO_INPUT_PU || _GET_MODE(IO) == GPIO_INPUT_PD)
#define IS_OUTPUT(IO) (_GET_MODE(IO) == GPIO_OUTPUT_PP || _GET_MODE(IO) == GPIO_OUTPUT_OD)
-#define PWM_PIN(IO) (PIN_MAP[IO].timer_device != nullptr)
+#define PWM_PIN(IO) !!PIN_MAP[IO].timer_device
// digitalRead/Write wrappers
#define extDigitalRead(IO) digitalRead(IO)
diff --git a/Marlin/src/HAL/STM32F1/inc/Conditionals_LCD.h b/Marlin/src/HAL/STM32F1/inc/Conditionals_LCD.h
index f52e6fec2..5f1c4b160 100644
--- a/Marlin/src/HAL/STM32F1/inc/Conditionals_LCD.h
+++ b/Marlin/src/HAL/STM32F1/inc/Conditionals_LCD.h
@@ -20,8 +20,3 @@
*
*/
#pragma once
-
-#if ENABLED(USE_USB_COMPOSITE)
- //#warning "SD_CHECK_AND_RETRY isn't needed with USE_USB_COMPOSITE."
- #undef SD_CHECK_AND_RETRY
-#endif
diff --git a/Marlin/src/HAL/STM32F1/inc/Conditionals_adv.h b/Marlin/src/HAL/STM32F1/inc/Conditionals_adv.h
index 5f1c4b160..0fe792476 100644
--- a/Marlin/src/HAL/STM32F1/inc/Conditionals_adv.h
+++ b/Marlin/src/HAL/STM32F1/inc/Conditionals_adv.h
@@ -20,3 +20,11 @@
*
*/
#pragma once
+
+#ifdef USE_USB_COMPOSITE
+ //#warning "SD_CHECK_AND_RETRY isn't needed with USE_USB_COMPOSITE."
+ #undef SD_CHECK_AND_RETRY
+ #if DISABLED(NO_SD_HOST_DRIVE)
+ #define HAS_SD_HOST_DRIVE 1
+ #endif
+#endif
diff --git a/Marlin/src/HAL/STM32F1/inc/SanityCheck.h b/Marlin/src/HAL/STM32F1/inc/SanityCheck.h
index 9d5026fba..89ee66d64 100644
--- a/Marlin/src/HAL/STM32F1/inc/SanityCheck.h
+++ b/Marlin/src/HAL/STM32F1/inc/SanityCheck.h
@@ -25,15 +25,6 @@
* Test STM32F1-specific configuration values for errors at compile-time.
*/
-#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
- #error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on STM32F1."
-#endif
-
-#if !defined(HAVE_SW_SERIAL) && HAS_TMC_SW_SERIAL
- #warning "With TMC2208/9 consider using SoftwareSerialM with HAVE_SW_SERIAL and appropriate SS_TIMER."
- #error "Missing SoftwareSerial implementation."
-#endif
-
#if ENABLED(SDCARD_EEPROM_EMULATION) && DISABLED(SDSUPPORT)
#undef SDCARD_EEPROM_EMULATION // Avoid additional error noise
#if USE_FALLBACK_EEPROM
@@ -43,11 +34,18 @@
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- #error "SERIAL_STATS_MAX_RX_QUEUED is not supported on this platform."
+ #error "SERIAL_STATS_MAX_RX_QUEUED is not supported on the STM32F1 platform."
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
- #error "SERIAL_STATS_DROPPED_RX is not supported on this platform."
+ #error "SERIAL_STATS_DROPPED_RX is not supported on the STM32F1 platform."
#endif
#if ENABLED(NEOPIXEL_LED)
#error "NEOPIXEL_LED (Adafruit NeoPixel) is not supported for HAL/STM32F1. Comment out this line to proceed at your own risk!"
#endif
+
+// Emergency Parser needs at least one serial with HardwareSerial or USBComposite.
+// The USBSerial maple don't allow any hook to implement EMERGENCY_PARSER.
+// And copy all USBSerial code to marlin space to support EMERGENCY_PARSER, when we have another options, don't worth it.
+#if ENABLED(EMERGENCY_PARSER) && !defined(USE_USB_COMPOSITE) && ((SERIAL_PORT == -1 && !defined(SERIAL_PORT_2)) || (SERIAL_PORT_2 == -1 && !defined(SERIAL_PORT)))
+ #error "EMERGENCY_PARSER is only supported by HardwareSerial or USBComposite in HAL/STM32F1."
+#endif
diff --git a/Marlin/src/HAL/STM32F1/msc_sd.cpp b/Marlin/src/HAL/STM32F1/msc_sd.cpp
index 4f44f2ee9..7725b2c32 100644
--- a/Marlin/src/HAL/STM32F1/msc_sd.cpp
+++ b/Marlin/src/HAL/STM32F1/msc_sd.cpp
@@ -13,15 +13,18 @@
* along with this program. If not, see .
*
*/
-#if defined(__STM32F1__) && defined(USE_USB_COMPOSITE)
+#include "../../inc/MarlinConfigPre.h"
+
+#if defined(__STM32F1__) && HAS_SD_HOST_DRIVE
#include "msc_sd.h"
#include "SPI.h"
+#include "usb_reg_map.h"
#define PRODUCT_ID 0x29
USBMassStorage MarlinMSC;
-MarlinUSBCompositeSerial MarlinCompositeSerial;
+Serial1Class MarlinCompositeSerial(true);
#include "../../inc/MarlinConfig.h"
@@ -39,14 +42,28 @@ MarlinUSBCompositeSerial MarlinCompositeSerial;
#endif
#if ENABLED(EMERGENCY_PARSER)
- void (*real_rx_callback)(void);
- void my_rx_callback(void) {
- real_rx_callback();
- int len = MarlinCompositeSerial.available();
- while (len-- > 0) // >0 because available() may return a negative value
- emergency_parser.update(MarlinCompositeSerial.emergency_state, MarlinCompositeSerial.peek());
+ // The original callback is not called (no way to retrieve address).
+ // That callback detects a special STM32 reset sequence: this functionality is not essential
+ // as M997 achieves the same.
+ void my_rx_callback(unsigned int, void*) {
+ // max length of 16 is enough to contain all emergency commands
+ uint8 buf[16];
+
+ //rx is usbSerialPart.endpoints[2]
+ uint16 len = usb_get_ep_rx_count(usbSerialPart.endpoints[2].address);
+ uint32 total = composite_cdcacm_data_available();
+
+ if (len == 0 || total == 0 || !WITHIN(total, len, COUNT(buf)))
+ return;
+
+ // cannot get character by character due to bug in composite_cdcacm_peek_ex
+ len = composite_cdcacm_peek(buf, total);
+
+ for (uint32 i = 0; i < len; i++)
+ emergency_parser.update(MarlinCompositeSerial.emergency_state, buf[i+total-len]);
}
+
#endif
void MSC_SD_init() {
@@ -71,10 +88,8 @@ void MSC_SD_init() {
MarlinCompositeSerial.registerComponent();
USBComposite.begin();
#if ENABLED(EMERGENCY_PARSER)
- //rx is usbSerialPart.endpoints[2]
- real_rx_callback = usbSerialPart.endpoints[2].callback;
- usbSerialPart.endpoints[2].callback = my_rx_callback;
+ composite_cdcacm_set_hooks(USBHID_CDCACM_HOOK_RX, my_rx_callback);
#endif
}
-#endif // __STM32F1__ && USE_USB_COMPOSITE
+#endif // __STM32F1__ && HAS_SD_HOST_DRIVE
diff --git a/Marlin/src/HAL/STM32F1/msc_sd.h b/Marlin/src/HAL/STM32F1/msc_sd.h
index 1e4e4c44b..f4636bdff 100644
--- a/Marlin/src/HAL/STM32F1/msc_sd.h
+++ b/Marlin/src/HAL/STM32F1/msc_sd.h
@@ -18,25 +18,9 @@
#include
#include "../../inc/MarlinConfigPre.h"
-#if ENABLED(EMERGENCY_PARSER)
- #include "../../feature/e_parser.h"
-#endif
-
-class MarlinUSBCompositeSerial : public USBCompositeSerial {
-public:
- MarlinUSBCompositeSerial() : USBCompositeSerial()
- #if ENABLED(EMERGENCY_PARSER)
- , emergency_state(EmergencyParser::State::EP_RESET)
- #endif
- { }
-
- #if ENABLED(EMERGENCY_PARSER)
- EmergencyParser::State emergency_state;
- inline bool emergency_parser_enabled() { return true; }
- #endif
-};
+#include "../../core/serial_hook.h"
extern USBMassStorage MarlinMSC;
-extern MarlinUSBCompositeSerial MarlinCompositeSerial;
+extern Serial1Class MarlinCompositeSerial;
void MSC_SD_init();
diff --git a/Marlin/src/HAL/STM32F1/onboard_sd.cpp b/Marlin/src/HAL/STM32F1/onboard_sd.cpp
index 9c2b128dd..6092aea32 100644
--- a/Marlin/src/HAL/STM32F1/onboard_sd.cpp
+++ b/Marlin/src/HAL/STM32F1/onboard_sd.cpp
@@ -21,10 +21,11 @@
#include "SPI.h"
#include "fastio.h"
-#if HAS_SHARED_MEDIA
- #ifndef ONBOARD_SPI_DEVICE
- #define ONBOARD_SPI_DEVICE SPI_DEVICE
- #endif
+#ifndef ONBOARD_SPI_DEVICE
+ #define ONBOARD_SPI_DEVICE SPI_DEVICE
+#endif
+
+#if HAS_SD_HOST_DRIVE
#define ONBOARD_SD_SPI SPI
#else
SPIClass OnboardSPI(ONBOARD_SPI_DEVICE);
diff --git a/Marlin/src/HAL/STM32F1/onboard_sd.h b/Marlin/src/HAL/STM32F1/onboard_sd.h
index 1dc7ec5b3..1c0a1c5b8 100644
--- a/Marlin/src/HAL/STM32F1/onboard_sd.h
+++ b/Marlin/src/HAL/STM32F1/onboard_sd.h
@@ -48,7 +48,7 @@ DRESULT disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
#endif
#if _DISKIO_IOCTL
- DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buff);
+ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff);
#endif
/* Disk Status Bits (DSTATUS) */
diff --git a/Marlin/src/HAL/STM32F1/pinsDebug.h b/Marlin/src/HAL/STM32F1/pinsDebug.h
index 2d63ebd77..8e7a3d813 100644
--- a/Marlin/src/HAL/STM32F1/pinsDebug.h
+++ b/Marlin/src/HAL/STM32F1/pinsDebug.h
@@ -18,10 +18,102 @@
*/
#pragma once
-#ifdef NUM_DIGITAL_PINS // Only in ST's Arduino core (STM32duino, STM32Core)
- #include "../STM32/pinsDebug_STM32duino.h"
-#elif defined(BOARD_NR_GPIO_PINS) // Only in STM32GENERIC (Maple)
- #include "../STM32/pinsDebug_STM32GENERIC.h"
-#else
- #error "M43 not supported for this board"
+/**
+ * Support routines for STM32GENERIC (Maple)
+ */
+
+/**
+ * Translation of routines & variables used by pinsDebug.h
+ */
+
+#ifndef BOARD_NR_GPIO_PINS // Only in STM32GENERIC (Maple)
+ #error "Expected BOARD_NR_GPIO_PINS not found"
#endif
+
+#include "fastio.h"
+
+extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS];
+
+#define NUM_DIGITAL_PINS BOARD_NR_GPIO_PINS
+#define NUMBER_PINS_TOTAL BOARD_NR_GPIO_PINS
+#define VALID_PIN(pin) (pin >= 0 && pin < BOARD_NR_GPIO_PINS)
+#define GET_ARRAY_PIN(p) pin_t(pin_array[p].pin)
+#define pwm_status(pin) PWM_PIN(pin)
+#define digitalRead_mod(p) extDigitalRead(p)
+#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3hd "), int16_t(p)); SERIAL_ECHO(buffer); }while(0)
+#define PRINT_PORT(p) print_port(p)
+#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
+#define MULTI_NAME_PAD 21 // space needed to be pretty if not first name assigned to a pin
+
+// pins that will cause hang/reset/disconnect in M43 Toggle and Watch utilities
+#ifndef M43_NEVER_TOUCH
+ #define M43_NEVER_TOUCH(Q) (Q >= 9 && Q <= 12) // SERIAL/USB pins PA9(TX) PA10(RX)
+#endif
+
+static inline int8_t get_pin_mode(pin_t pin) {
+ return VALID_PIN(pin) ? _GET_MODE(pin) : -1;
+}
+
+static inline pin_t DIGITAL_PIN_TO_ANALOG_PIN(pin_t pin) {
+ if (!VALID_PIN(pin)) return -1;
+ int8_t adc_channel = int8_t(PIN_MAP[pin].adc_channel);
+ #ifdef NUM_ANALOG_INPUTS
+ if (adc_channel >= NUM_ANALOG_INPUTS) adc_channel = ADCx;
+ #endif
+ return pin_t(adc_channel);
+}
+
+static inline bool IS_ANALOG(pin_t pin) {
+ if (!VALID_PIN(pin)) return false;
+ if (PIN_MAP[pin].adc_channel != ADCx) {
+ #ifdef NUM_ANALOG_INPUTS
+ if (PIN_MAP[pin].adc_channel >= NUM_ANALOG_INPUTS) return false;
+ #endif
+ return _GET_MODE(pin) == GPIO_INPUT_ANALOG && !M43_NEVER_TOUCH(pin);
+ }
+ return false;
+}
+
+static inline bool GET_PINMODE(const pin_t pin) {
+ return VALID_PIN(pin) && !IS_INPUT(pin);
+}
+
+static inline bool GET_ARRAY_IS_DIGITAL(const int16_t array_pin) {
+ const pin_t pin = GET_ARRAY_PIN(array_pin);
+ return (!IS_ANALOG(pin)
+ #ifdef NUM_ANALOG_INPUTS
+ || PIN_MAP[pin].adc_channel >= NUM_ANALOG_INPUTS
+ #endif
+ );
+}
+
+#include "../../inc/MarlinConfig.h" // Allow pins/pins.h to set density
+
+static inline void pwm_details(const pin_t pin) {
+ if (PWM_PIN(pin)) {
+ timer_dev * const tdev = PIN_MAP[pin].timer_device;
+ const uint8_t channel = PIN_MAP[pin].timer_channel;
+ const char num = (
+ #if EITHER(STM32_HIGH_DENSITY, STM32_XL_DENSITY)
+ tdev == &timer8 ? '8' :
+ tdev == &timer5 ? '5' :
+ #endif
+ tdev == &timer4 ? '4' :
+ tdev == &timer3 ? '3' :
+ tdev == &timer2 ? '2' :
+ tdev == &timer1 ? '1' : '?'
+ );
+ char buffer[10];
+ sprintf_P(buffer, PSTR(" TIM%c CH%c"), num, ('0' + channel));
+ SERIAL_ECHO(buffer);
+ }
+}
+
+static inline void print_port(pin_t pin) {
+ const char port = 'A' + char(pin >> 4); // pin div 16
+ const int16_t gbit = PIN_MAP[pin].gpio_bit;
+ char buffer[8];
+ sprintf_P(buffer, PSTR("P%c%hd "), port, gbit);
+ if (gbit < 10) SERIAL_CHAR(' ');
+ SERIAL_ECHO(buffer);
+}
diff --git a/Marlin/src/HAL/STM32F1/spi_pins.h b/Marlin/src/HAL/STM32F1/spi_pins.h
index 8f2b324f6..7d650ffe3 100644
--- a/Marlin/src/HAL/STM32F1/spi_pins.h
+++ b/Marlin/src/HAL/STM32F1/spi_pins.h
@@ -31,28 +31,24 @@
* SPI2 | PB12 PB13 PB14 PB15 |
* SPI3 | PA15 PB3 PB4 PB5 |
* +-----------------------------+
- * Any pin can be used for Chip Select (SS_PIN)
+ * Any pin can be used for Chip Select (SD_SS_PIN)
* SPI1 is enabled by default
*/
-#ifndef SCK_PIN
- #define SCK_PIN PA5
+#ifndef SD_SCK_PIN
+ #define SD_SCK_PIN PA5
#endif
-#ifndef MISO_PIN
- #define MISO_PIN PA6
+#ifndef SD_MISO_PIN
+ #define SD_MISO_PIN PA6
#endif
-#ifndef MOSI_PIN
- #define MOSI_PIN PA7
+#ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN PA7
#endif
-#ifndef SS_PIN
- #define SS_PIN PA4
+#ifndef SD_SS_PIN
+ #define SD_SS_PIN PA4
#endif
#undef SDSS
-#define SDSS SS_PIN
+#define SDSS SD_SS_PIN
-#if ENABLED(ENABLE_SPI3)
- #define SPI_DEVICE 3
-#elif ENABLED(ENABLE_SPI2)
- #define SPI_DEVICE 2
-#else
+#ifndef SPI_DEVICE
#define SPI_DEVICE 1
#endif
diff --git a/Marlin/src/HAL/STM32F1/tft/tft_fsmc.h b/Marlin/src/HAL/STM32F1/tft/tft_fsmc.h
index 11eb1ffa8..d9ee1f4c7 100644
--- a/Marlin/src/HAL/STM32F1/tft/tft_fsmc.h
+++ b/Marlin/src/HAL/STM32F1/tft/tft_fsmc.h
@@ -22,7 +22,7 @@
#pragma once
#ifndef LCD_READ_ID
- #define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
+ #define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif
#ifndef LCD_READ_ID4
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
@@ -30,9 +30,9 @@
#include
-#define DATASIZE_8BIT DMA_SIZE_8BITS
-#define DATASIZE_16BIT DMA_SIZE_16BITS
-#define TFT_IO_DRIVER TFT_FSMC
+#define DATASIZE_8BIT DMA_SIZE_8BITS
+#define DATASIZE_16BIT DMA_SIZE_16BITS
+#define TFT_IO_DRIVER TFT_FSMC
typedef struct {
__IO uint16_t REG;
diff --git a/Marlin/src/HAL/STM32F1/tft/xpt2046.cpp b/Marlin/src/HAL/STM32F1/tft/xpt2046.cpp
index 616d05fea..98371c5ff 100644
--- a/Marlin/src/HAL/STM32F1/tft/xpt2046.cpp
+++ b/Marlin/src/HAL/STM32F1/tft/xpt2046.cpp
@@ -1,6 +1,9 @@
/**
* Marlin 3D Printer Firmware
- * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,7 +22,7 @@
#include "../../../inc/MarlinConfig.h"
-#if HAS_TFT_XPT2046 || HAS_TOUCH_XPT2046
+#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
#include "xpt2046.h"
#include
diff --git a/Marlin/src/HAL/STM32F1/tft/xpt2046.h b/Marlin/src/HAL/STM32F1/tft/xpt2046.h
index 019f75efc..65602bda0 100644
--- a/Marlin/src/HAL/STM32F1/tft/xpt2046.h
+++ b/Marlin/src/HAL/STM32F1/tft/xpt2046.h
@@ -1,6 +1,9 @@
/**
* Marlin 3D Printer Firmware
- * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,16 +28,16 @@
#endif
#ifndef TOUCH_MISO_PIN
- #define TOUCH_MISO_PIN MISO_PIN
+ #define TOUCH_MISO_PIN SD_MISO_PIN
#endif
#ifndef TOUCH_MOSI_PIN
- #define TOUCH_MOSI_PIN MOSI_PIN
+ #define TOUCH_MOSI_PIN SD_MOSI_PIN
#endif
#ifndef TOUCH_SCK_PIN
- #define TOUCH_SCK_PIN SCK_PIN
+ #define TOUCH_SCK_PIN SD_SCK_PIN
#endif
#ifndef TOUCH_CS_PIN
- #define TOUCH_CS_PIN CS_PIN
+ #define TOUCH_CS_PIN SD_SS_PIN
#endif
#ifndef TOUCH_INT_PIN
#define TOUCH_INT_PIN -1
diff --git a/Marlin/src/HAL/STM32F1/timers.h b/Marlin/src/HAL/STM32F1/timers.h
index 6f360f6bf..3e2e7775f 100644
--- a/Marlin/src/HAL/STM32F1/timers.h
+++ b/Marlin/src/HAL/STM32F1/timers.h
@@ -129,8 +129,10 @@ timer_dev* get_timer_dev(int number);
#define HAL_STEP_TIMER_ISR() extern "C" void stepTC_Handler()
#endif
-extern "C" void tempTC_Handler();
-extern "C" void stepTC_Handler();
+extern "C" {
+ void tempTC_Handler();
+ void stepTC_Handler();
+}
// ------------------------
// Public Variables
diff --git a/Marlin/src/HAL/STM32F1/watchdog.cpp b/Marlin/src/HAL/STM32F1/watchdog.cpp
index ca91a6fe4..b812a4fa6 100644
--- a/Marlin/src/HAL/STM32F1/watchdog.cpp
+++ b/Marlin/src/HAL/STM32F1/watchdog.cpp
@@ -33,6 +33,11 @@
#include
#include "watchdog.h"
+/**
+ * The watchdog clock is 40Khz. So for a 4s or 8s interval use a /256 preescaler and 625 or 1250 reload value (counts down to 0).
+ */
+#define STM32F1_WD_RELOAD TERN(WATCHDOG_DURATION_8S, 1250, 625) // 4 or 8 second timeout
+
void HAL_watchdog_refresh() {
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
TOGGLE(LED_PIN); // heartbeat indicator
@@ -49,7 +54,7 @@ void watchdogSetup() {
*
* @return No return
*
- * @details The watchdog clock is 40Khz. We need a 4 seconds interval, so use a /256 preescaler and 625 reload value (counts down to 0)
+ * @details The watchdog clock is 40Khz. So for a 4s or 8s interval use a /256 preescaler and 625 or 1250 reload value (counts down to 0).
*/
void watchdog_init() {
#if DISABLED(DISABLE_WATCHDOG_INIT)
diff --git a/Marlin/src/HAL/STM32F1/watchdog.h b/Marlin/src/HAL/STM32F1/watchdog.h
index 7185d6977..68920f8cb 100644
--- a/Marlin/src/HAL/STM32F1/watchdog.h
+++ b/Marlin/src/HAL/STM32F1/watchdog.h
@@ -27,18 +27,9 @@
#include
-/**
- * The watchdog clock is 40Khz. We need a 4 seconds interval, so use a /256 preescaler and
- * 625 reload value (counts down to 0)
- * use 1250 for 8 seconds
- */
-#define STM32F1_WD_RELOAD 625
-
-// Arduino STM32F1 core now has watchdog support
-
-// Initialize watchdog with a 4 second countdown time
+// Initialize watchdog with a 4 or 8 second countdown time
void watchdog_init();
-// Reset watchdog. MUST be called at least every 4 seconds after the
-// first watchdog_init or STM32F1 will reset.
+// Reset watchdog. MUST be called every 4 or 8 seconds after the
+// first watchdog_init or the STM32F1 will reset.
void HAL_watchdog_refresh();
diff --git a/Marlin/src/HAL/STM32_F4_F7/HAL.cpp b/Marlin/src/HAL/STM32_F4_F7/HAL.cpp
deleted file mode 100644
index b4629d2af..000000000
--- a/Marlin/src/HAL/STM32_F4_F7/HAL.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- *
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
- * Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
- * Copyright (c) 2017 Victor Perez
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#if defined(STM32GENERIC) && (defined(STM32F4) || defined(STM32F7))
-
-#include "HAL.h"
-
-//#include
-
-// ------------------------
-// Public Variables
-// ------------------------
-
-uint16_t HAL_adc_result;
-
-// ------------------------
-// Public functions
-// ------------------------
-
-/* VGPV Done with defines
-// disable interrupts
-void cli() { noInterrupts(); }
-
-// enable interrupts
-void sei() { interrupts(); }
-*/
-
-void HAL_clear_reset_source() { __HAL_RCC_CLEAR_RESET_FLAGS(); }
-
-uint8_t HAL_get_reset_source() {
- if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET) return RST_WATCHDOG;
- if (__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST) != RESET) return RST_SOFTWARE;
- if (__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET) return RST_EXTERNAL;
- if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) return RST_POWER_ON;
- return 0;
-}
-
-void _delay_ms(const int delay_ms) { delay(delay_ms); }
-
-extern "C" {
- extern unsigned int _ebss; // end of bss section
-}
-
-// return free memory between end of heap (or end bss) and whatever is current
-
-/*
-#include
-//extern caddr_t _sbrk(int incr);
-#ifndef CONFIG_HEAP_END
-extern char _lm_heap_end;
-#define CONFIG_HEAP_END ((caddr_t)&_lm_heap_end)
-#endif
-
-extern "C" {
- static int freeMemory() {
- char top = 't';
- return &top - reinterpret_cast(sbrk(0));
- }
- int freeMemory() {
- int free_memory;
- int heap_end = (int)_sbrk(0);
- free_memory = ((int)&free_memory) - ((int)heap_end);
- return free_memory;
- }
-}
-*/
-
-// ------------------------
-// ADC
-// ------------------------
-
-void HAL_adc_start_conversion(const uint8_t adc_pin) { HAL_adc_result = analogRead(adc_pin); }
-
-uint16_t HAL_adc_get_result() { return HAL_adc_result; }
-
-#endif // STM32GENERIC && (STM32F4 || STM32F7)
diff --git a/Marlin/src/HAL/STM32_F4_F7/HAL.h b/Marlin/src/HAL/STM32_F4_F7/HAL.h
deleted file mode 100644
index 00a65de79..000000000
--- a/Marlin/src/HAL/STM32_F4_F7/HAL.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- *
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
- * Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
- * Copyright (c) 2017 Victor Perez
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#pragma once
-
-#define CPU_32_BIT
-
-#include "../../inc/MarlinConfigPre.h"
-
-#include "../shared/Marduino.h"
-#include "../shared/math_32bit.h"
-#include "../shared/HAL_SPI.h"
-
-#include "fastio.h"
-#include "watchdog.h"
-
-#include
-
-#if defined(STM32F4) && USBCON
- #include
-#endif
-
-// ------------------------
-// Defines
-// ------------------------
-
-// Serial override
-//extern HalSerial usb_serial;
-
-#define _MSERIAL(X) SerialUART##X
-#define MSERIAL(X) _MSERIAL(X)
-#define SerialUART0 Serial1
-
-#if defined(STM32F4) && SERIAL_PORT == 0
- #error "SERIAL_PORT cannot be 0. (Port 0 does not exist.) Please update your configuration."
-#elif SERIAL_PORT == -1
- #define MYSERIAL0 SerialUSB
-#elif WITHIN(SERIAL_PORT, 0, 6)
- #define MYSERIAL0 MSERIAL(SERIAL_PORT)
-#else
- #error "SERIAL_PORT must be from -1 to 6. Please update your configuration."
-#endif
-
-#ifdef SERIAL_PORT_2
- #if defined(STM32F4) && SERIAL_PORT_2 == 0
- #error "SERIAL_PORT_2 cannot be 0. (Port 0 does not exist.) Please update your configuration."
- #elif SERIAL_PORT_2 == -1
- #define MYSERIAL1 SerialUSB
- #elif WITHIN(SERIAL_PORT_2, 0, 6)
- #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
- #else
- #error "SERIAL_PORT_2 must be from -1 to 6. Please update your configuration."
- #endif
-#endif
-
-#ifdef LCD_SERIAL_PORT
- #if defined(STM32F4) && LCD_SERIAL_PORT == 0
- #error "LCD_SERIAL_PORT cannot be 0. (Port 0 does not exist.) Please update your configuration."
- #elif LCD_SERIAL_PORT == -1
- #define LCD_SERIAL SerialUSB
- #elif WITHIN(LCD_SERIAL_PORT, 0, 6)
- #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
- #else
- #error "LCD_SERIAL_PORT must be from -1 to 6. Please update your configuration."
- #endif
-#endif
-
-/**
- * TODO: review this to return 1 for pins that are not analog input
- */
-#ifndef analogInputToDigitalPin
- #define analogInputToDigitalPin(p) (p)
-#endif
-
-#define CRITICAL_SECTION_START() uint32_t primask = __get_PRIMASK(); __disable_irq()
-#define CRITICAL_SECTION_END() if (!primask) __enable_irq()
-#define ISRS_ENABLED() (!__get_PRIMASK())
-#define ENABLE_ISRS() __enable_irq()
-#define DISABLE_ISRS() __disable_irq()
-#define cli() __disable_irq()
-#define sei() __enable_irq()
-
-// On AVR this is in math.h?
-#define square(x) ((x)*(x))
-
-#ifndef strncpy_P
- #define strncpy_P(dest, src, num) strncpy((dest), (src), (num))
-#endif
-
-// Fix bug in pgm_read_ptr
-#undef pgm_read_ptr
-#define pgm_read_ptr(addr) (*(addr))
-
-// ------------------------
-// Types
-// ------------------------
-
-typedef int8_t pin_t;
-
-#ifdef STM32F4
- #define HAL_SERVO_LIB libServo
-#endif
-
-// ------------------------
-// Public Variables
-// ------------------------
-
-// Result of last ADC conversion
-extern uint16_t HAL_adc_result;
-
-// ------------------------
-// Public functions
-// ------------------------
-
-// Memory related
-#define __bss_end __bss_end__
-
-inline void HAL_init() {}
-
-// Clear reset reason
-void HAL_clear_reset_source();
-
-// Reset reason
-uint8_t HAL_get_reset_source();
-
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
-
-void _delay_ms(const int delay);
-
-/*
-extern "C" {
- int freeMemory();
-}
-*/
-
-extern "C" char* _sbrk(int incr);
-
-/*
-int freeMemory() {
- volatile int top;
- top = (int)((char*)&top - reinterpret_cast(_sbrk(0)));
- return top;
-}
-*/
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-
-static inline int freeMemory() {
- volatile char top;
- return &top - reinterpret_cast