Browse Source

Merge branch 'FB4S_WIFI' into FBG5_WIFI

FBG5_WIFI
andrey1s 2 years ago
parent
commit
c27323055c
  1. 6
      .editorconfig
  2. 3
      .github/FUNDING.yml
  3. 157
      .github/ISSUE_TEMPLATE/bug_report.yml
  4. 20
      .github/ISSUE_TEMPLATE/config.yml
  5. 44
      .github/ISSUE_TEMPLATE/feature_request.yml
  6. 46
      .github/code_of_conduct.md
  7. 143
      .github/contributing.md
  8. 35
      .github/issue_template.md
  9. 40
      .github/lock.yml
  10. 33
      .github/pull_request_template.md
  11. 35
      .github/workflows/bump-date.yml
  12. 32
      .github/workflows/check-pr.yml
  13. 39
      .github/workflows/clean-closed.yml
  14. 28
      .github/workflows/close-stale.yml
  15. 32
      .github/workflows/lock-closed.yml
  16. 142
      .github/workflows/test-builds.yml
  17. 22
      .github/workflows/unlock-reopened.yml
  18. 30
      .gitignore
  19. 8
      .vscode/extensions.json
  20. 986
      Marlin/Configuration.h
  21. 1556
      Marlin/Configuration_adv.h
  22. 150
      Marlin/Makefile
  23. 4
      Marlin/Version.h
  24. 211
      Marlin/config.ini
  25. 110
      Marlin/src/HAL/AVR/HAL.cpp
  26. 208
      Marlin/src/HAL/AVR/HAL.h
  27. 25
      Marlin/src/HAL/AVR/HAL_SPI.cpp
  28. 7
      Marlin/src/HAL/AVR/MarlinSPI.h
  29. 4
      Marlin/src/HAL/AVR/MarlinSerial.cpp
  30. 8
      Marlin/src/HAL/AVR/MarlinSerial.h
  31. 202
      Marlin/src/HAL/AVR/Servo.cpp
  32. 46
      Marlin/src/HAL/AVR/endstop_interrupts.h
  33. 332
      Marlin/src/HAL/AVR/fast_pwm.cpp
  34. 16
      Marlin/src/HAL/AVR/fastio.cpp
  35. 67
      Marlin/src/HAL/AVR/fastio.h
  36. 54
      Marlin/src/HAL/AVR/inc/SanityCheck.h
  37. 4
      Marlin/src/HAL/AVR/math.h
  38. 65
      Marlin/src/HAL/AVR/pinsDebug.h
  39. 3
      Marlin/src/HAL/AVR/pinsDebug_Teensyduino.h
  40. 3
      Marlin/src/HAL/AVR/pinsDebug_plus_70.h
  41. 44
      Marlin/src/HAL/AVR/timers.h
  42. 4
      Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp
  43. 70
      Marlin/src/HAL/AVR/watchdog.cpp
  44. 143
      Marlin/src/HAL/DUE/HAL.cpp
  45. 141
      Marlin/src/HAL/DUE/HAL.h
  46. 20
      Marlin/src/HAL/DUE/HAL_SPI.cpp
  47. 7
      Marlin/src/HAL/DUE/MarlinSPI.h
  48. 4
      Marlin/src/HAL/DUE/MarlinSerial.cpp
  49. 2
      Marlin/src/HAL/DUE/MarlinSerial.h
  50. 2
      Marlin/src/HAL/DUE/MarlinSerialUSB.cpp
  51. 2
      Marlin/src/HAL/DUE/MinSerial.cpp
  52. 138
      Marlin/src/HAL/DUE/Servo.cpp
  53. 2
      Marlin/src/HAL/DUE/ServoTimers.h
  54. 8
      Marlin/src/HAL/DUE/Tone.cpp
  55. 1
      Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
  56. 4
      Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp
  57. 4
      Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
  58. 46
      Marlin/src/HAL/DUE/eeprom_flash.cpp
  59. 6
      Marlin/src/HAL/DUE/endstop_interrupts.h
  60. 2
      Marlin/src/HAL/DUE/fastio/G2_PWM.cpp
  61. 28
      Marlin/src/HAL/DUE/inc/SanityCheck.h
  62. 11
      Marlin/src/HAL/DUE/pinsDebug.h
  63. 27
      Marlin/src/HAL/DUE/timers.cpp
  64. 53
      Marlin/src/HAL/DUE/timers.h
  65. 19
      Marlin/src/HAL/DUE/upload_extra_script.py
  66. 2
      Marlin/src/HAL/DUE/usb/arduino_due_x.h
  67. 2
      Marlin/src/HAL/DUE/usb/compiler.h
  68. 2
      Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp
  69. 4
      Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.h
  70. 8
      Marlin/src/HAL/DUE/usb/udd.h
  71. 4
      Marlin/src/HAL/DUE/usb/udi_cdc.c
  72. 2
      Marlin/src/HAL/DUE/usb/udi_cdc_conf.h
  73. 10
      Marlin/src/HAL/DUE/usb/udi_msc.c
  74. 46
      Marlin/src/HAL/DUE/usb/uotghs_device_due.c
  75. 2
      Marlin/src/HAL/DUE/usb/usb_protocol_msc.h
  76. 114
      Marlin/src/HAL/DUE/watchdog.cpp
  77. 240
      Marlin/src/HAL/ESP32/HAL.cpp
  78. 178
      Marlin/src/HAL/ESP32/HAL.h
  79. 6
      Marlin/src/HAL/ESP32/HAL_SPI.cpp
  80. 8
      Marlin/src/HAL/ESP32/MarlinSPI.h
  81. 18
      Marlin/src/HAL/ESP32/Servo.cpp
  82. 3
      Marlin/src/HAL/ESP32/Servo.h
  83. 8
      Marlin/src/HAL/ESP32/Tone.cpp
  84. 6
      Marlin/src/HAL/ESP32/endstop_interrupts.h
  85. 6
      Marlin/src/HAL/ESP32/esp32.csv
  86. 20
      Marlin/src/HAL/ESP32/fastio.h
  87. 53
      Marlin/src/HAL/ESP32/i2s.cpp
  88. 7
      Marlin/src/HAL/ESP32/inc/Conditionals_adv.h
  89. 20
      Marlin/src/HAL/ESP32/inc/SanityCheck.h
  90. 3
      Marlin/src/HAL/ESP32/spi_pins.h
  91. 20
      Marlin/src/HAL/ESP32/timers.cpp
  92. 38
      Marlin/src/HAL/ESP32/timers.h
  93. 106
      Marlin/src/HAL/ESP32/u8g_esp32_spi.cpp
  94. 2
      Marlin/src/HAL/ESP32/wifi.cpp
  95. 5
      Marlin/src/HAL/HAL.h
  96. 37
      Marlin/src/HAL/LINUX/HAL.cpp
  97. 158
      Marlin/src/HAL/LINUX/HAL.h
  98. 10
      Marlin/src/HAL/LINUX/MarlinSPI.h
  99. 4
      Marlin/src/HAL/LINUX/arduino.cpp
  100. 16
      Marlin/src/HAL/LINUX/eeprom.cpp

6
.editorconfig

@ -14,6 +14,10 @@ end_of_line = lf
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
[{*.py,*.conf,*.sublime-project}] [{*.py}]
indent_style = space
indent_size = 4
[{*.conf,*.sublime-project}]
indent_style = tab indent_style = tab
indent_size = 4 indent_size = 4

3
.github/FUNDING.yml

@ -1,3 +0,0 @@
github: [thinkyhead]
patreon: thinkyhead
custom: ["https://www.thinkyhead.com/donate-to-marlin"]

157
.github/ISSUE_TEMPLATE/bug_report.yml

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

20
.github/ISSUE_TEMPLATE/config.yml

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

44
.github/ISSUE_TEMPLATE/feature_request.yml

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

46
.github/code_of_conduct.md

@ -1,46 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [marlinfirmware@github.com](mailto:marlinfirmware@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/

143
.github/contributing.md

@ -1,143 +0,0 @@
# Contributing to Marlin
Thanks for your interest in contributing to Marlin Firmware!
The following is a set of guidelines for contributing to Marlin, hosted by the [MarlinFirmware Organization](https://github.com/MarlinFirmware) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a Pull Request.
#### Table Of Contents
[Code of Conduct](#code-of-conduct)
[I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question)
[How Can I Contribute?](#how-can-i-contribute)
* [Reporting Bugs](#reporting-bugs)
* [Suggesting Features or Changes](#suggesting-features-or-changes)
* [Your First Code Contribution](#your-first-code-contribution)
* [Pull Requests](#pull-requests)
[Styleguides](#styleguides)
* [Git Commit Messages](#git-commit-messages)
* [C++ Coding Standards](#c++-coding-standards)
* [Documentation Styleguide](#documentation)
[Additional Notes](#additional-notes)
* [Issue and Pull Request Labels](#issue-and-pull-request-labels)
## Code of Conduct
This project and everyone participating in it is governed by the [Marlin Code of Conduct](code_of_conduct.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [marlinfirmware@github.com](mailto:marlinfirmware@github.com).
## I don't want to read this whole thing I just have a question!!!
> **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below.
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
* [Marlin RepRap forum](https://reprap.org/forum/list.php?415)
* [MarlinFirmware on Facebook](https://www.facebook.com/groups/1049718498464482/)
If chat is more your speed, you can join the MarlinFirmware Discord server:
* Use the link https://discord.gg/n5NJ59y to join up as a General User.
* Even though our Discord is pretty active, it may take a while for community members to respond — please be patient!
* Use the `#general` channel for general questions or discussion about Marlin.
* Other channels exist for certain topics or are limited to Patrons. Check the channel list.
## How Can I Contribute?
### Reporting Bugs
This section guides you through submitting a Bug Report for Marlin. Following these guidelines helps maintainers and the community understand your report, reproduce the behavior, and find related reports.
Before creating a Bug Report, please test the "nightly" development branch, as you might find out that you don't need to create one. When you are creating a Bug Report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](issue_template.md), the information it asks for helps us resolve issues faster.
> **Note:** Regressions can happen. If you find a **Closed** issue that seems like your issue, go ahead and open a new issue and include a link to the original issue in the body of your new one. All you need to create a link is the issue number, preceded by #. For example, #8888.
#### How Do I Submit A (Good) Bug Report?
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Use the New Issue button to create an issue and provide the following information by filling in [the template](issue_template.md).
Explain the problem and include additional details to help maintainers reproduce the problem:
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started Marlin, e.g. which command exactly you used in the terminal, or how you started Marlin otherwise. When listing steps, **don't just say what you did, but explain how you did it**. For example, if you moved the cursor to the end of a line, explain if you used the mouse, or a keyboard shortcut or an Marlin command, and if so which one?
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets or log output in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
* **Include detailed log output** especially for probing and leveling. See below for usage of `DEBUG_LEVELING_FEATURE`.
* **Include screenshots, links to videos, etc.** which clearly demonstrate the problem.
* **Include G-code** (if relevant) that reliably causes the problem to show itself.
* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.
Provide more context:
* **Can you reproduce the problem with a minimum of options enabled?**
* **Did the problem start happening recently** (e.g. after updating to a new version of Marlin) or was this always a problem?
* If the problem started happening recently, **can you reproduce the problem in an older version of Marlin?** What's the most recent version in which the problem doesn't happen? You can download older versions of Marlin from [the releases page](https://github.com/MarlinFirmware/Marlin/releases).
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
Include details about your configuration and environment:
* **Which version of Marlin are you using?** Marlin's exact version and build date can be seen in the startup message when a host connects to Marlin, or in the LCD Info menu (if enabled).
* **What kind of 3D Printer and electronics are you using**?
* **What kind of add-ons (probe, filament sensor) do you have**?
* **Include your Configuration files.** Make a ZIP file containing `Configuration.h` and `Configuration_adv.h` and drop it on your reply.
### Suggesting Features or Changes
This section guides you through submitting a suggestion for Marlin, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion and find related suggestions.
Before creating a suggestion, please check [this list](#before-submitting-a-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](issue_template.md), including the steps that you imagine you would take if the feature you're requesting existed.
#### Before Submitting a Feature Request
* **Check the [Marlin website](https://marlinfw.org/)** for tips — you might discover that the feature is already included. Most importantly, check if you're using [the latest version of Marlin](https://github.com/MarlinFirmware/Marlin/releases) and if you can get the desired behavior by changing [Marlin's config settings](https://marlinfw.org/docs/configuration/configuration.html).
* **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aissue)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Feature Request?
Feature Requests are tracked as [GitHub issues](https://guides.github.com/features/issues/). Please follow these guidelines in your request:
* **Use a clear and descriptive title** for the issue to identify the suggestion.
* **Provide a step-by-step description of the requested feature** in as much detail as possible.
* **Provide specific examples to demonstrate the steps**.
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
* **Include screenshots and links to videos** which demonstrate the feature or point out the part of Marlin to which the request is related.
* **Explain why this feature would be useful** to most Marlin users.
* **Name other firmwares that have this feature, if any.**
### Your First Code Contribution
Unsure where to begin contributing to Marlin? You can start by looking through these `good-first-issue` and `help-wanted` issues:
* [Beginner issues][good-first-issue] - issues which should only require a few lines of code, and a test or two.
* [Help Wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues.
### Pull Requests
Pull Requests should always be targeted to working branches (e.g., `bugfix-1.1.x` and/or `bugfix-2.0.x`) and never to release branches (e.g., `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
* Fill in [the required template](pull_request_template.md).
* Don't include issue numbers in the PR title.
* Include pictures, diagrams, and links to videos in your Pull Request to demonstrate your changes, if needed.
* Follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website.
* Document new code with clear and concise comments.
* End all files with a newline.
## Styleguides
### Git Commit Messages
* Use the present tense ("Add feature" not "Added feature").
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...").
* Limit the first line to 72 characters or fewer.
* Reference issues and Pull Requests liberally after the first line.
### C++ Coding Standards
* Please read and follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests.
### Documentation
* Guidelines for documentation are still under development. In-general, be clear, concise, and to-the-point.

35
.github/issue_template.md

@ -1,35 +0,0 @@
<!--
Have you read Marlin's Code of Conduct? By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/MarlinFirmware/Marlin/blob/bugfix-2.0.x/.github/code_of_conduct.md
Do you want to ask a question? Are you looking for support? Please don't post here. Instead use one of the following options:
- The Marlin Firmware forum at https://reprap.org/forum/list.php?415
- The MarlinFirmware Facebook Group at https://www.facebook.com/groups/1049718498464482/
- The MarlinFirmware Discord Server at https://discord.gg/n5NJ59y.
Before filing an issue be sure to test the latest "bugfix" branch to see whether the issue is already addressed.
-->
### Description
<!-- Description of the bug or requested feature -->
### Steps to Reproduce
<!-- If this is a Bug Report, please describe the steps needed to reproduce the issue -->
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.

40
.github/lock.yml

@ -1,40 +0,0 @@
#
# Configuration for Lock Threads - https://github.com/dessant/lock-threads-app
#
# Number of days of inactivity before a closed issue or pull request is locked
daysUntilLock: 60
# Skip issues and pull requests created before a given timestamp. Timestamp must
# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
skipCreatedBefore: false
# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
exemptLabels: [ 'no-locking' ]
# Label to add before locking, such as `outdated`. Set to `false` to disable
lockLabel: false
# Comment to post before locking. Set to `false` to disable
lockComment: >
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.
# Assign `resolved` as the reason for locking. Set to `false` to disable
setLockReason: true
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings just for `issues` or `pulls`
# issues:
# exemptLabels:
# - help-wanted
# lockLabel: outdated
# pulls:
# daysUntilLock: 30
# Repository to extend settings from
# _extends: repo

33
.github/pull_request_template.md

@ -1,33 +0,0 @@
<!--
Submitting a Pull Request
- Please fill out all sections of this form. You can delete the helpful comments.
- Pull Requests without clear information will take longer and may even be rejected.
- We get a high volume of submissions so please be patient during review.
-->
### Description
<!--
Clearly describe the submitted changes with lots of details. Include images where helpful. Initial reviewers may not be familiar with the subject, so be as thorough as possible. You can use MarkDown syntax to improve readability with bullet lists, code blocks, and so on. PREVIEW and fix up formatting before submitting.
-->
### Requirements
<!-- Does this PR require a specific board, LCD, etc.? -->
### Benefits
<!-- What does this PR fix or improve? -->
### Configurations
<!-- Attach Configurations ZIP and any other files needed to test this PR. -->
### Related Issues
<!-- Does this PR fix a bug or fulfill a Feature Request? Link related Issues here. -->

35
.github/workflows/bump-date.yml

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

32
.github/workflows/check-pr.yml

@ -1,32 +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: superbrothers/close-pull-request@v3
with:
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.

39
.github/workflows/clean-closed.yml

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

28
.github/workflows/close-stale.yml

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

32
.github/workflows/lock-closed.yml

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

142
.github/workflows/test-builds.yml

@ -1,142 +0,0 @@
#
# test-builds.yml
# Do test builds to catch compile errors
#
name: CI
on:
pull_request:
branches:
- bugfix-2.0.x
paths-ignore:
- config/**
- data/**
- docs/**
- '**/*.md'
push:
branches:
- bugfix-2.0.x
paths-ignore:
- config/**
- data/**
- docs/**
- '**/*.md'
jobs:
test_builds:
name: Run All Tests
if: github.repository == 'MarlinFirmware/Marlin'
runs-on: ubuntu-latest
strategy:
matrix:
test-platform:
# Base Environments
- DUE
- DUE_archim
- esp32
- linux_native
- mega2560
- at90usb1286_dfu
- teensy31
- teensy35
- teensy41
- SAMD51_grandcentral_m4
# Extended AVR Environments
- FYSETC_F6
- mega1280
- rambo
- sanguino1284p
- sanguino644p
# STM32F1 (Maple) Environments
#- STM32F103RC_btt_maple
- STM32F103RC_btt_USB_maple
- STM32F103RC_fysetc
- STM32F103RC_meeb
- jgaurora_a5s_a1
- STM32F103VE_longer
#- mks_robin_maple
- mks_robin_lite
- mks_robin_pro
#- mks_robin_nano35_maple
#- STM32F103RET6_creality_maple
# STM32 (ST) Environments
- STM32F103RC_btt
#- STM32F103RC_btt_USB
- STM32F103RE_btt
- STM32F103RE_btt_USB
- STM32F103RET6_creality
- STM32F407VE_black
- STM32F401VE_STEVAL
- BIGTREE_BTT002
- BIGTREE_SKR_PRO
- BIGTREE_GTR_V1_0
- mks_robin
- ARMED
- FYSETC_S6
- STM32F070CB_malyan
- STM32F070RB_malyan
- malyan_M300
- FLYF407ZG
- rumba32
- LERDGEX
- LERDGEK
- mks_robin_nano35
- NUCLEO_F767ZI
- REMRAM_V1
- BTT_SKR_SE_BX
- chitu_f103
# Put lengthy tests last
- LPC1768
- LPC1769
# Non-working environment tests
#- at90usb1286_cdc
#- STM32F103CB_malyan
#- STM32F103RE
#- mks_robin_mini
steps:
- name: Check out the PR
uses: actions/checkout@v2
- name: Cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache PlatformIO
uses: actions/cache@v2
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Select Python 3.7
uses: actions/setup-python@v2
with:
python-version: '3.7' # Version range or exact version of a Python version to use, using semvers version range syntax.
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- name: Install PlatformIO
run: |
pip install -U https://github.com/platformio/platformio-core/archive/develop.zip
platformio update
- name: Run ${{ matrix.test-platform }} Tests
run: |
make tests-single-ci TEST_TARGET=${{ matrix.test-platform }}

22
.github/workflows/unlock-reopened.yml

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

30
.gitignore

@ -22,12 +22,16 @@
# Generated files # Generated files
_Version.h _Version.h
bdf2u8g bdf2u8g
marlin_config.json
mczip.h
*.gen
*.sublime-workspace
# #
# OS # OS
# #
applet/ applet/
*.DS_Store .DS_Store
# #
# Misc # Misc
@ -37,7 +41,6 @@ applet/
*.rej *.rej
*.bak *.bak
*.idea *.idea
*.s
*.i *.i
*.ii *.ii
*.swp *.swp
@ -137,16 +140,19 @@ __vm/
vc-fileutils.settings vc-fileutils.settings
# Visual Studio Code # Visual Studio Code
.vscode .vscode/*
.vscode/.browse.c_cpp.db* !.vscode/extensions.json
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/*.db
# cmake #Simulation
imgui.ini
eeprom.dat
spi_flash.bin
#cmake
CMakeLists.txt CMakeLists.txt
src/CMakeLists.txt src/CMakeLists.txt
CMakeListsPrivate.txt CMakeListsPrivate.txt
build/
# CLion # CLion
cmake-build-* cmake-build-*
@ -163,11 +169,3 @@ __pycache__
# IOLogger logs # IOLogger logs
*_log.csv *_log.csv
# Simulation / Native
eeprom.dat
imgui.ini
#Ozone
ozone.jdebug
ozone.jdebug.user

8
.vscode/extensions.json

@ -0,0 +1,8 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"marlinfirmware.auto-build",
"platformio.platformio-ide"
]
}

986
Marlin/Configuration.h

File diff suppressed because it is too large

1556
Marlin/Configuration_adv.h

File diff suppressed because it is too large

150
Marlin/Makefile

@ -109,8 +109,8 @@ LIQUID_TWI2 ?= 0
# This defines if Wire is needed # This defines if Wire is needed
WIRE ?= 0 WIRE ?= 0
# This defines if Tone is needed (i.e SPEAKER is defined in Configuration.h) # This defines if Tone is needed (i.e., SPEAKER is defined in Configuration.h)
# Disabling this (and SPEAKER) saves approximatively 350 bytes of memory. # Disabling this (and SPEAKER) saves approximately 350 bytes of memory.
TONE ?= 1 TONE ?= 1
# This defines if U8GLIB is needed (may require RELOC_WORKAROUND) # This defines if U8GLIB is needed (may require RELOC_WORKAROUND)
@ -132,7 +132,7 @@ CC_MIN:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_MINOR__ | cut -f3 -d\ )
CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | cut -f3 -d\ ) CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | cut -f3 -d\ )
CC_VER:=$(shell echo $$(( $(CC_MAJ) * 10000 + $(CC_MIN) * 100 + $(CC_PATCHLEVEL) ))) CC_VER:=$(shell echo $$(( $(CC_MAJ) * 10000 + $(CC_MIN) * 100 + $(CC_PATCHLEVEL) )))
ifeq ($(shell test $(CC_VER) -lt 40901 && echo 1),1) ifeq ($(shell test $(CC_VER) -lt 40901 && echo 1),1)
@echo This version of GCC is likely broken. Enabling relocation workaround. $(warning This GCC version $(CC_VER) is likely broken. Enabling relocation workaround.)
RELOC_WORKAROUND = 1 RELOC_WORKAROUND = 1
endif endif
@ -207,11 +207,11 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1105)
else ifeq ($(HARDWARE_MOTHERBOARD),1106) else ifeq ($(HARDWARE_MOTHERBOARD),1106)
# MKS BASE v1.0 # MKS BASE v1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1107) else ifeq ($(HARDWARE_MOTHERBOARD),1107)
# MKS v1.4 with A4982 stepper drivers # MKS BASE v1.4 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1108) else ifeq ($(HARDWARE_MOTHERBOARD),1108)
# MKS v1.5 with Allegro A4982 stepper drivers # MKS BASE v1.5 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1109) else ifeq ($(HARDWARE_MOTHERBOARD),1109)
# MKS v1.6 with Allegro A4982 stepper drivers # MKS BASE v1.6 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1110) else ifeq ($(HARDWARE_MOTHERBOARD),1110)
# MKS BASE 1.0 with Heroic HR4982 stepper drivers # MKS BASE 1.0 with Heroic HR4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1111) else ifeq ($(HARDWARE_MOTHERBOARD),1111)
@ -219,93 +219,108 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1111)
else ifeq ($(HARDWARE_MOTHERBOARD),1112) else ifeq ($(HARDWARE_MOTHERBOARD),1112)
# MKS GEN L # MKS GEN L
else ifeq ($(HARDWARE_MOTHERBOARD),1113) else ifeq ($(HARDWARE_MOTHERBOARD),1113)
# zrib V2.0 control board (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1114)
# BigTreeTech or BIQU KFB2.0 # BigTreeTech or BIQU KFB2.0
else ifeq ($(HARDWARE_MOTHERBOARD),1114)
# zrib V2.0 (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1115) else ifeq ($(HARDWARE_MOTHERBOARD),1115)
# Felix 2.0+ Electronics Board (RAMPS like) # zrib V5.2 (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1116) else ifeq ($(HARDWARE_MOTHERBOARD),1116)
# Invent-A-Part RigidBoard # Felix 2.0+ Electronics Board (RAMPS like)
else ifeq ($(HARDWARE_MOTHERBOARD),1117) else ifeq ($(HARDWARE_MOTHERBOARD),1117)
# Invent-A-Part RigidBoard V2 # Invent-A-Part RigidBoard
else ifeq ($(HARDWARE_MOTHERBOARD),1118) else ifeq ($(HARDWARE_MOTHERBOARD),1118)
# Sainsmart 2-in-1 board # Invent-A-Part RigidBoard V2
else ifeq ($(HARDWARE_MOTHERBOARD),1119) else ifeq ($(HARDWARE_MOTHERBOARD),1119)
# Ultimaker # Sainsmart 2-in-1 board
else ifeq ($(HARDWARE_MOTHERBOARD),1120) else ifeq ($(HARDWARE_MOTHERBOARD),1120)
# Ultimaker (Older electronics. Pre 1.5.4. This is rare) # Ultimaker
else ifeq ($(HARDWARE_MOTHERBOARD),1121) else ifeq ($(HARDWARE_MOTHERBOARD),1121)
# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
else ifeq ($(HARDWARE_MOTHERBOARD),1122)
MCU ?= atmega1280 MCU ?= atmega1280
PROG_MCU ?= m1280 PROG_MCU ?= m1280
# Azteeg X3 # Azteeg X3
else ifeq ($(HARDWARE_MOTHERBOARD),1122)
# Azteeg X3 Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1123) else ifeq ($(HARDWARE_MOTHERBOARD),1123)
# Ultimainboard 2.x (Uses TEMP_SENSOR 20) # Azteeg X3 Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1124) else ifeq ($(HARDWARE_MOTHERBOARD),1124)
# Rumba # Ultimainboard 2.x (Uses TEMP_SENSOR 20)
else ifeq ($(HARDWARE_MOTHERBOARD),1125) else ifeq ($(HARDWARE_MOTHERBOARD),1125)
# Raise3D Rumba # Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1126) else ifeq ($(HARDWARE_MOTHERBOARD),1126)
# Rapide Lite RL200 Rumba # Raise3D N series Rumba derivative
else ifeq ($(HARDWARE_MOTHERBOARD),1127) else ifeq ($(HARDWARE_MOTHERBOARD),1127)
# Formbot T-Rex 2 Plus # Rapide Lite 200 (v1, low-cost RUMBA clone with drv)
else ifeq ($(HARDWARE_MOTHERBOARD),1128) else ifeq ($(HARDWARE_MOTHERBOARD),1128)
# Formbot T-Rex 3 # Formbot T-Rex 2 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1129) else ifeq ($(HARDWARE_MOTHERBOARD),1129)
# Formbot Raptor # Formbot T-Rex 3
else ifeq ($(HARDWARE_MOTHERBOARD),1130) else ifeq ($(HARDWARE_MOTHERBOARD),1130)
# Formbot Raptor 2 # Formbot Raptor
else ifeq ($(HARDWARE_MOTHERBOARD),1131) else ifeq ($(HARDWARE_MOTHERBOARD),1131)
# bq ZUM Mega 3D # Formbot Raptor 2
else ifeq ($(HARDWARE_MOTHERBOARD),1132) else ifeq ($(HARDWARE_MOTHERBOARD),1132)
# MakeBoard Mini v2.1.2 is a control board sold by MicroMake # bq ZUM Mega 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1133) else ifeq ($(HARDWARE_MOTHERBOARD),1133)
# TriGorilla Anycubic version 1.3 based on RAMPS EFB # MakeBoard Mini v2.1.2 by MicroMake
else ifeq ($(HARDWARE_MOTHERBOARD),1134) else ifeq ($(HARDWARE_MOTHERBOARD),1134)
# TriGorilla Anycubic version 1.4 based on RAMPS EFB # TriGorilla Anycubic version 1.3-based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),1135) else ifeq ($(HARDWARE_MOTHERBOARD),1135)
# TriGorilla Anycubic version 1.4 Rev 1.1 # ... Ver 1.4
else ifeq ($(HARDWARE_MOTHERBOARD),1136) else ifeq ($(HARDWARE_MOTHERBOARD),1136)
# Creality: Ender-4, CR-8 # ... Rev 1.1 (new servo pin order)
else ifeq ($(HARDWARE_MOTHERBOARD),1137) else ifeq ($(HARDWARE_MOTHERBOARD),1137)
# Creality: CR10S, CR20, CR-X # Creality: Ender-4, CR-8
else ifeq ($(HARDWARE_MOTHERBOARD),1138) else ifeq ($(HARDWARE_MOTHERBOARD),1138)
# Dagoma F5 # Creality: CR10S, CR20, CR-X
else ifeq ($(HARDWARE_MOTHERBOARD),1139) else ifeq ($(HARDWARE_MOTHERBOARD),1139)
# FYSETC F6 1.3 # Dagoma F5
else ifeq ($(HARDWARE_MOTHERBOARD),1140) else ifeq ($(HARDWARE_MOTHERBOARD),1140)
# FYSETC F6 1.5 # FYSETC F6 1.3
else ifeq ($(HARDWARE_MOTHERBOARD),1141) else ifeq ($(HARDWARE_MOTHERBOARD),1141)
# Duplicator i3 Plus # FYSETC F6 1.4
else ifeq ($(HARDWARE_MOTHERBOARD),1142) else ifeq ($(HARDWARE_MOTHERBOARD),1142)
# VORON # Wanhao Duplicator i3 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1143) else ifeq ($(HARDWARE_MOTHERBOARD),1143)
# TRONXY V3 1.0 # VORON Design
else ifeq ($(HARDWARE_MOTHERBOARD),1144) else ifeq ($(HARDWARE_MOTHERBOARD),1144)
# Z-Bolt X Series # Tronxy TRONXY-V3-1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1145) else ifeq ($(HARDWARE_MOTHERBOARD),1145)
# TT OSCAR # Z-Bolt X Series
else ifeq ($(HARDWARE_MOTHERBOARD),1146) else ifeq ($(HARDWARE_MOTHERBOARD),1146)
# Overlord/Overlord Pro # TT OSCAR
else ifeq ($(HARDWARE_MOTHERBOARD),1147) else ifeq ($(HARDWARE_MOTHERBOARD),1147)
# ADIMLab Gantry v1 # Overlord/Overlord Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1148) else ifeq ($(HARDWARE_MOTHERBOARD),1148)
# ADIMLab Gantry v2 # ADIMLab Gantry v1
else ifeq ($(HARDWARE_MOTHERBOARD),1149) else ifeq ($(HARDWARE_MOTHERBOARD),1149)
# BIQU Tango V1 # ADIMLab Gantry v2
else ifeq ($(HARDWARE_MOTHERBOARD),1150) else ifeq ($(HARDWARE_MOTHERBOARD),1150)
# MKS GEN L V2 # BIQU Tango V1
else ifeq ($(HARDWARE_MOTHERBOARD),1151) else ifeq ($(HARDWARE_MOTHERBOARD),1151)
# MKS GEN L V2.1 # MKS GEN L V2
else ifeq ($(HARDWARE_MOTHERBOARD),1152) else ifeq ($(HARDWARE_MOTHERBOARD),1152)
# Copymaster 3D # MKS GEN L V2.1
else ifeq ($(HARDWARE_MOTHERBOARD),1153) else ifeq ($(HARDWARE_MOTHERBOARD),1153)
# Ortur 4 # Copymaster 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1154) else ifeq ($(HARDWARE_MOTHERBOARD),1154)
# Tenlog D3 Hero # Ortur 4
else ifeq ($(HARDWARE_MOTHERBOARD),1155) else ifeq ($(HARDWARE_MOTHERBOARD),1155)
# Tenlog D3 Hero IDEX printer
else ifeq ($(HARDWARE_MOTHERBOARD),1156)
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Fan, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),1157)
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Hotend2, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),1158)
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend, Fan0, Fan1, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),1159)
# Longer LK1 PRO / Alfawise U20 Pro (PRO version)
else ifeq ($(HARDWARE_MOTHERBOARD),1160)
# Longer LKx PRO / Alfawise Uxx Pro (PRO version)
else ifeq ($(HARDWARE_MOTHERBOARD),1161)
# Zonestar zrib V5.3 (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1162)
# Pxmalion Core I3
else ifeq ($(HARDWARE_MOTHERBOARD),1163)
# #
# RAMBo and derivatives # RAMBo and derivatives
@ -358,20 +373,38 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1311)
else ifeq ($(HARDWARE_MOTHERBOARD),1312) else ifeq ($(HARDWARE_MOTHERBOARD),1312)
# Mega controller # Mega controller
else ifeq ($(HARDWARE_MOTHERBOARD),1313) else ifeq ($(HARDWARE_MOTHERBOARD),1313)
# Geeetech GT2560 Rev B for Mecreator2 # Geeetech GT2560 Rev A
else ifeq ($(HARDWARE_MOTHERBOARD),1314) else ifeq ($(HARDWARE_MOTHERBOARD),1314)
# Geeetech GT2560 Rev. A # Geeetech GT2560 Rev A+ (with auto level probe)
else ifeq ($(HARDWARE_MOTHERBOARD),1315) else ifeq ($(HARDWARE_MOTHERBOARD),1315)
# Geeetech GT2560 Rev. A+ (with auto level probe) # Geeetech GT2560 Rev B
else ifeq ($(HARDWARE_MOTHERBOARD),1316) else ifeq ($(HARDWARE_MOTHERBOARD),1316)
# Geeetech GT2560 Rev B for A10(M/D) # Geeetech GT2560 Rev B for A10(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1317) else ifeq ($(HARDWARE_MOTHERBOARD),1317)
# Geeetech GT2560 Rev B for A20(M/D) # Geeetech GT2560 Rev B for A10(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1318) else ifeq ($(HARDWARE_MOTHERBOARD),1318)
# Einstart retrofit # Geeetech GT2560 Rev B for Mecreator2
else ifeq ($(HARDWARE_MOTHERBOARD),1319) else ifeq ($(HARDWARE_MOTHERBOARD),1319)
# Wanhao 0ne+ i3 Mini # Geeetech GT2560 Rev B for A20(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1320) else ifeq ($(HARDWARE_MOTHERBOARD),1320)
# Einstart retrofit
else ifeq ($(HARDWARE_MOTHERBOARD),1321)
# Wanhao 0ne+ i3 Mini
else ifeq ($(HARDWARE_MOTHERBOARD),1322)
# Leapfrog Xeed 2015
else ifeq ($(HARDWARE_MOTHERBOARD),1323)
# PICA Shield (original version)
else ifeq ($(HARDWARE_MOTHERBOARD),1324)
# PICA Shield (rev C or later)
else ifeq ($(HARDWARE_MOTHERBOARD),1325)
# Intamsys 4.0 (Funmat HT)
else ifeq ($(HARDWARE_MOTHERBOARD),1326)
# Malyan M180 Mainboard Version 2 (no display function, direct G-code only)
else ifeq ($(HARDWARE_MOTHERBOARD),1327)
# Geeetech GT2560 Rev B for A20(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1328)
# Mega controller & Protoneer CNC Shield V3.00
else ifeq ($(HARDWARE_MOTHERBOARD),1329)
# #
# ATmega1281, ATmega2561 # ATmega1281, ATmega2561
@ -445,6 +478,11 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1510)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p MCU ?= atmega1284p
PROG_MCU ?= m1284p PROG_MCU ?= m1284p
# ZoneStar ZMIB V2
else ifeq ($(HARDWARE_MOTHERBOARD),1511)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
PROG_MCU ?= m1284p
# #
# Other ATmega644P, ATmega644, ATmega1284P # Other ATmega644P, ATmega644, ATmega1284P

4
Marlin/Version.h

@ -28,7 +28,7 @@
/** /**
* Marlin release version identifier * Marlin release version identifier
*/ */
//#define SHORT_BUILD_VERSION "2.0.9.1" //#define SHORT_BUILD_VERSION "2.1.1"
/** /**
* Verbose version identifier which should contain a reference to the location * Verbose version identifier which should contain a reference to the location
@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release * here we define this default string as the date where the latest release
* version was tagged. * version was tagged.
*/ */
//#define STRING_DISTRIBUTION_DATE "2021-06-27" //#define STRING_DISTRIBUTION_DATE "2022-08-06"
/** /**
* Defines a generic printer name to be output to the LCD after booting Marlin. * Defines a generic printer name to be output to the LCD after booting Marlin.

211
Marlin/config.ini

@ -0,0 +1,211 @@
#
# Marlin Firmware
# config.ini - Options to apply before the build
#
[config:base]
ini_use_config = none
# Load all config: sections in this file
;ini_use_config = all
# Load config file relative to Marlin/
;ini_use_config = another.ini
# Download configurations from GitHub
;ini_use_config = example/Creality/Ender-5 Plus @ bugfix-2.1.x
# Download configurations from your server
;ini_use_config = https://me.myserver.com/path/to/configs
# Evaluate config:base and do a config dump
;ini_use_config = base
;config_export = 2
[config:minimal]
motherboard = BOARD_RAMPS_14_EFB
serial_port = 0
baudrate = 250000
use_watchdog = on
thermal_protection_hotends = on
thermal_protection_hysteresis = 4
thermal_protection_period = 40
bufsize = 4
block_buffer_size = 16
max_cmd_size = 96
extruders = 1
temp_sensor_0 = 1
temp_hysteresis = 3
heater_0_mintemp = 5
heater_0_maxtemp = 275
preheat_1_temp_hotend = 180
bang_max = 255
pidtemp = on
pid_k1 = 0.95
pid_max = BANG_MAX
pid_functional_range = 10
default_kp = 22.20
default_ki = 1.08
default_kd = 114.00
x_driver_type = A4988
y_driver_type = A4988
z_driver_type = A4988
e0_driver_type = A4988
x_bed_size = 200
x_min_pos = 0
x_max_pos = X_BED_SIZE
y_bed_size = 200
y_min_pos = 0
y_max_pos = Y_BED_SIZE
z_min_pos = 0
z_max_pos = 200
x_home_dir = -1
y_home_dir = -1
z_home_dir = -1
use_xmin_plug = on
use_ymin_plug = on
use_zmin_plug = on
x_min_endstop_inverting = false
y_min_endstop_inverting = false
z_min_endstop_inverting = false
default_axis_steps_per_unit = { 80, 80, 400, 500 }
axis_relative_modes = { false, false, false, false }
default_max_feedrate = { 300, 300, 5, 25 }
default_max_acceleration = { 3000, 3000, 100, 10000 }
homing_feedrate_mm_m = { (50*60), (50*60), (4*60) }
homing_bump_divisor = { 2, 2, 4 }
x_enable_on = 0
y_enable_on = 0
z_enable_on = 0
e_enable_on = 0
invert_x_dir = false
invert_y_dir = true
invert_z_dir = false
invert_e0_dir = false
invert_e_step_pin = false
invert_x_step_pin = false
invert_y_step_pin = false
invert_z_step_pin = false
disable_x = false
disable_y = false
disable_z = false
disable_e = false
proportional_font_ratio = 1.0
default_nominal_filament_dia = 1.75
junction_deviation_mm = 0.013
default_acceleration = 3000
default_travel_acceleration = 3000
default_retract_acceleration = 3000
default_minimumfeedrate = 0.0
default_mintravelfeedrate = 0.0
minimum_planner_speed = 0.05
min_steps_per_segment = 6
default_minsegmenttime = 20000
[config:basic]
bed_overshoot = 10
busy_while_heating = on
default_ejerk = 5.0
default_keepalive_interval = 2
default_leveling_fade_height = 0.0
disable_inactive_extruder = on
display_charset_hd44780 = JAPANESE
eeprom_boot_silent = on
eeprom_chitchat = on
endstoppullups = on
extrude_maxlength = 200
extrude_mintemp = 170
host_keepalive_feature = on
hotend_overshoot = 15
jd_handle_small_segments = on
lcd_info_screen_style = 0
lcd_language = en
max_bed_power = 255
mesh_inset = 0
min_software_endstops = on
max_software_endstops = on
min_software_endstop_x = on
min_software_endstop_y = on
min_software_endstop_z = on
max_software_endstop_x = on
max_software_endstop_y = on
max_software_endstop_z = on
preheat_1_fan_speed = 0
preheat_1_label = "PLA"
preheat_1_temp_bed = 70
prevent_cold_extrusion = on
prevent_lengthy_extrude = on
printjob_timer_autostart = on
probing_margin = 10
show_bootscreen = on
soft_pwm_scale = 0
string_config_h_author = "(none, default config)"
temp_bed_hysteresis = 3
temp_bed_residency_time = 10
temp_bed_window = 1
temp_residency_time = 10
temp_window = 1
validate_homing_endstops = on
xy_probe_feedrate = (133*60)
z_clearance_between_probes = 5
z_clearance_deploy_probe = 10
z_clearance_multi_probe = 5
[config:advanced]
arc_support = on
auto_report_temperatures = on
autotemp = on
autotemp_oldweight = 0.98
bed_check_interval = 5000
default_stepper_deactive_time = 120
default_volumetric_extruder_limit = 0.00
disable_inactive_e = true
disable_inactive_x = true
disable_inactive_y = true
disable_inactive_z = true
e0_auto_fan_pin = -1
encoder_100x_steps_per_sec = 80
encoder_10x_steps_per_sec = 30
encoder_rate_multiplier = on
extended_capabilities_report = on
extruder_auto_fan_speed = 255
extruder_auto_fan_temperature = 50
fanmux0_pin = -1
fanmux1_pin = -1
fanmux2_pin = -1
faster_gcode_parser = on
homing_bump_mm = { 5, 5, 2 }
max_arc_segment_mm = 1.0
min_arc_segment_mm = 0.1
min_circle_segments = 72
n_arc_correction = 25
serial_overrun_protection = on
slowdown = on
slowdown_divisor = 2
temp_sensor_bed = 0
thermal_protection_bed_hysteresis = 2
thermocouple_max_errors = 15
tx_buffer_size = 0
watch_bed_temp_increase = 2
watch_bed_temp_period = 60
watch_temp_increase = 2
watch_temp_period = 20

110
Marlin/src/HAL/AVR/HAL.cpp

@ -23,6 +23,7 @@
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "HAL.h" #include "HAL.h"
#include <avr/wdt.h>
#ifdef USBCON #ifdef USBCON
DefaultSerial1 MSerial0(false, Serial); DefaultSerial1 MSerial0(false, Serial);
@ -35,13 +36,32 @@
// Public Variables // Public Variables
// ------------------------ // ------------------------
//uint8_t MCUSR; // Don't initialize/override variable (which would happen in .init4)
uint8_t MarlinHAL::reset_reason __attribute__((section(".noinit")));
// ------------------------ // ------------------------
// Public functions // Public functions
// ------------------------ // ------------------------
void HAL_init() { __attribute__((naked)) // Don't output function pro- and epilogue
__attribute__((used)) // Output the function, even if "not used"
__attribute__((section(".init3"))) // Put in an early user definable section
void save_reset_reason() {
#if ENABLED(OPTIBOOT_RESET_REASON)
__asm__ __volatile__(
A("STS %0, r2")
: "=m"(hal.reset_reason)
);
#else
hal.reset_reason = MCUSR;
#endif
// Clear within 16ms since WDRF bit enables a 16ms watchdog timer -> Boot loop
hal.clear_reset_source();
wdt_disable();
}
void MarlinHAL::init() {
// Init Servo Pins // Init Servo Pins
#define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW) #define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW)
#if HAS_SERVO_0 #if HAS_SERVO_0
@ -56,9 +76,11 @@ void HAL_init() {
#if HAS_SERVO_3 #if HAS_SERVO_3
INIT_SERVO(3); INIT_SERVO(3);
#endif #endif
init_pwm_timers(); // Init user timers to default frequency - 1000HZ
} }
void HAL_reboot() { void MarlinHAL::reboot() {
#if ENABLED(USE_WATCHDOG) #if ENABLED(USE_WATCHDOG)
while (1) { /* run out the watchdog */ } while (1) { /* run out the watchdog */ }
#else #else
@ -67,6 +89,62 @@ void HAL_reboot() {
#endif #endif
} }
// ------------------------
// Watchdog Timer
// ------------------------
#if ENABLED(USE_WATCHDOG)
#include <avr/wdt.h>
#include "../../MarlinCore.h"
// Initialize watchdog with 8s timeout, if possible. Otherwise, make it 4s.
void MarlinHAL::watchdog_init() {
#if ENABLED(WATCHDOG_DURATION_8S) && defined(WDTO_8S)
#define WDTO_NS WDTO_8S
#else
#define WDTO_NS WDTO_4S
#endif
#if ENABLED(WATCHDOG_RESET_MANUAL)
// Enable the watchdog timer, but only for the interrupt.
// Take care, as this requires the correct order of operation, with interrupts disabled.
// See the datasheet of any AVR chip for details.
wdt_reset();
cli();
_WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE);
_WD_CONTROL_REG = _BV(WDIE) | (WDTO_NS & 0x07) | ((WDTO_NS & 0x08) << 2); // WDTO_NS directly does not work. bit 0-2 are consecutive in the register but the highest value bit is at bit 5
// So worked for up to WDTO_2S
sei();
wdt_reset();
#else
wdt_enable(WDTO_NS); // The function handles the upper bit correct.
#endif
//delay(10000); // test it!
}
//===========================================================================
//=================================== ISR ===================================
//===========================================================================
// Watchdog timer interrupt, called if main program blocks >4sec and manual reset is enabled.
#if ENABLED(WATCHDOG_RESET_MANUAL)
ISR(WDT_vect) {
sei(); // With the interrupt driven serial we need to allow interrupts.
SERIAL_ERROR_MSG(STR_WATCHDOG_FIRED);
minkill(); // interrupt-safe final kill and infinite loop
}
#endif
// Reset watchdog. MUST be called at least every 4 seconds after the
// first watchdog_init or AVR will go into emergency procedures.
void MarlinHAL::watchdog_refresh() { wdt_reset(); }
#endif // USE_WATCHDOG
// ------------------------
// Free Memory Accessor
// ------------------------
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
#include "../../sd/SdFatUtil.h" #include "../../sd/SdFatUtil.h"
@ -74,20 +152,20 @@ void HAL_reboot() {
#else // !SDSUPPORT #else // !SDSUPPORT
extern "C" { extern "C" {
extern char __bss_end; extern char __bss_end;
extern char __heap_start; extern char __heap_start;
extern void* __brkval; extern void* __brkval;
int freeMemory() { int freeMemory() {
int free_memory; int free_memory;
if ((int)__brkval == 0) if ((int)__brkval == 0)
free_memory = ((int)&free_memory) - ((int)&__bss_end); free_memory = ((int)&free_memory) - ((int)&__bss_end);
else else
free_memory = ((int)&free_memory) - ((int)__brkval); free_memory = ((int)&free_memory) - ((int)__brkval);
return free_memory; return free_memory;
}
} }
}
#endif // !SDSUPPORT #endif // !SDSUPPORT

208
Marlin/src/HAL/AVR/HAL.h

@ -19,16 +19,18 @@
*/ */
#pragma once #pragma once
/**
* HAL for Arduino AVR
*/
#include "../shared/Marduino.h" #include "../shared/Marduino.h"
#include "../shared/HAL_SPI.h" #include "../shared/HAL_SPI.h"
#include "fastio.h" #include "fastio.h"
#include "watchdog.h"
#include "math.h" #include "math.h"
#ifdef USBCON #ifdef USBCON
#include <HardwareSerial.h> #include <HardwareSerial.h>
#else #else
#define HardwareSerial_h // Hack to prevent HardwareSerial.h header inclusion
#include "MarlinSerial.h" #include "MarlinSerial.h"
#endif #endif
@ -39,6 +41,19 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <avr/io.h> #include <avr/io.h>
//
// Default graphical display delays
//
#if F_CPU >= 20000000
#define CPU_ST7920_DELAY_1 150
#define CPU_ST7920_DELAY_2 0
#define CPU_ST7920_DELAY_3 150
#elif F_CPU == 16000000
#define CPU_ST7920_DELAY_1 125
#define CPU_ST7920_DELAY_2 0
#define CPU_ST7920_DELAY_3 188
#endif
#ifndef pgm_read_ptr #ifndef pgm_read_ptr
// Compatibility for avr-libc 1.8.0-4.1 included with Ubuntu for // Compatibility for avr-libc 1.8.0-4.1 included with Ubuntu for
// Windows Subsystem for Linux on Windows 10 as of 10/18/2019 // Windows Subsystem for Linux on Windows 10 as of 10/18/2019
@ -61,9 +76,9 @@
#define CRITICAL_SECTION_START() unsigned char _sreg = SREG; cli() #define CRITICAL_SECTION_START() unsigned char _sreg = SREG; cli()
#define CRITICAL_SECTION_END() SREG = _sreg #define CRITICAL_SECTION_END() SREG = _sreg
#endif #endif
#define ISRS_ENABLED() TEST(SREG, SREG_I)
#define ENABLE_ISRS() sei() #define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
#define DISABLE_ISRS() cli() #define PWM_FREQUENCY 1000 // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
// ------------------------ // ------------------------
// Types // Types
@ -71,16 +86,15 @@
typedef int8_t pin_t; typedef int8_t pin_t;
#define SHARED_SERVOS HAS_SERVOS #define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
#define HAL_SERVO_LIB Servo
class Servo;
typedef Servo hal_servo_t;
// ------------------------ // ------------------------
// Public Variables // Serial ports
// ------------------------ // ------------------------
//extern uint8_t MCUSR;
// Serial ports
#ifdef USBCON #ifdef USBCON
#include "../../core/serial_hook.h" #include "../../core/serial_hook.h"
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1; typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
@ -129,89 +143,135 @@ typedef int8_t pin_t;
#endif #endif
#endif #endif
// ------------------------ //
// Public functions // ADC
// ------------------------ //
#define HAL_ADC_VREF 5.0
#define HAL_ADC_RESOLUTION 10
void HAL_init(); //
// Pin Mapping for M42, M43, M226
//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
//void cli(); #define HAL_SENSITIVE_PINS 0, 1,
//void _delay_ms(const int delay); #ifdef __AVR_AT90USB1286__
#define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)
#endif
inline void HAL_clear_reset_source() { MCUSR = 0; } // AVR compatibility
inline uint8_t HAL_get_reset_source() { return MCUSR; } #define strtof strtod
void HAL_reboot(); // ------------------------
// Free Memory Accessor
// ------------------------
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000 #if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-function"
#endif #endif
extern "C" int freeMemory(); extern "C" int freeMemory();
#if GCC_VERSION <= 50000 #pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif
// ADC // ------------------------
#ifdef DIDR2 // MarlinHAL Class
#define HAL_ANALOG_SELECT(ind) do{ if (ind < 8) SBI(DIDR0, ind); else SBI(DIDR2, ind & 0x07); }while(0) // ------------------------
#else
#define HAL_ANALOG_SELECT(ind) SBI(DIDR0, ind);
#endif
inline void HAL_adc_init() { class MarlinHAL {
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07; public:
DIDR0 = 0;
#ifdef DIDR2
DIDR2 = 0;
#endif
}
#define SET_ADMUX_ADCSRA(ch) ADMUX = _BV(REFS0) | (ch & 0x07); SBI(ADCSRA, ADSC) // Earliest possible init, before setup()
#ifdef MUX5 MarlinHAL() {}
#define HAL_START_ADC(ch) if (ch > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
#else
#define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
#endif
#define HAL_ADC_VREF 5.0 // Watchdog
#define HAL_ADC_RESOLUTION 10 static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
#define HAL_READ_ADC() ADC static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
#define GET_PIN_MAP_PIN(index) index static void init(); // Called early in setup()
#define GET_PIN_MAP_INDEX(pin) pin static void init_board() {} // Called less early in setup()
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) static void reboot(); // Restart the firmware from 0x0
#define HAL_SENSITIVE_PINS 0, 1, // Interrupts
static bool isr_state() { return TEST(SREG, SREG_I); }
static void isr_on() { sei(); }
static void isr_off() { cli(); }
#ifdef __AVR_AT90USB1286__ static void delay_ms(const int ms) { _delay_ms(ms); }
#define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)
#endif
// AVR compatibility // Tasks, called from idle()
#define strtof strtod static void idletask() {}
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment // Reset
static uint8_t reset_reason;
static uint8_t get_reset_source() { return reset_reason; }
static void clear_reset_source() { MCUSR = 0; }
/** // Free SRAM
* set_pwm_frequency static int freeMemory() { return ::freeMemory(); }
* Sets the frequency of the timer corresponding to the provided pin
* as close as possible to the provided desired frequency. Internally
* calculates the required waveform generation mode, prescaler and
* resolution values required and sets the timer registers accordingly.
* NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
* NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST FAN PWM Settings)
*/
void set_pwm_frequency(const pin_t pin, int f_desired);
/** //
* set_pwm_duty // ADC Methods
* Sets 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] // Called by Temperature::init once at startup
*/ static void adc_init() {
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false); ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
DIDR0 = 0;
#ifdef DIDR2
DIDR2 = 0;
#endif
}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t ch) {
#ifdef DIDR2
if (ch > 7) { SBI(DIDR2, ch & 0x07); return; }
#endif
SBI(DIDR0, ch);
}
// Begin ADC sampling on the given channel. Called from Temperature::isr!
static void adc_start(const uint8_t ch) {
#ifdef MUX5
ADCSRB = ch > 7 ? _BV(MUX5) : 0;
#else
ADCSRB = 0;
#endif
ADMUX = _BV(REFS0) | (ch & 0x07);
SBI(ADCSRA, ADSC);
}
// Is the ADC ready for reading?
static bool adc_ready() { return !TEST(ADCSRA, ADSC); }
// The current value of the ADC register
static __typeof__(ADC) adc_value() { return ADC; }
/**
* init_pwm_timers
* Set the default frequency for timers 2-5 to 1000HZ
*/
static void init_pwm_timers();
/**
* Set the PWM duty cycle for the pin to the given value.
* Optionally invert the duty cycle [default = false]
* Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
/**
* Set the frequency of the timer for the given pin as close as
* possible to the provided desired frequency. Internally calculate
* the required waveform generation mode, prescaler, and resolution
* values and set timer registers accordingly.
* NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
* NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST_PWM_FAN Settings)
*/
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
};

25
Marlin/src/HAL/AVR/HAL_SPI.cpp

@ -34,21 +34,21 @@
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
void spiBegin() { void spiBegin() {
OUT_WRITE(SD_SS_PIN, HIGH); #if PIN_EXISTS(SD_SS)
// Do not init HIGH for boards with pin 4 used as Fans or Heaters or otherwise, not likely to have multiple SPI devices anyway.
#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)
// SS must be in output mode even it is not chip select
SET_OUTPUT(SD_SS_PIN);
#else
// set SS high - may be chip select for another SPI device
OUT_WRITE(SD_SS_PIN, HIGH);
#endif
#endif
SET_OUTPUT(SD_SCK_PIN); SET_OUTPUT(SD_SCK_PIN);
SET_INPUT(SD_MISO_PIN); SET_INPUT(SD_MISO_PIN);
SET_OUTPUT(SD_MOSI_PIN); SET_OUTPUT(SD_MOSI_PIN);
#if DISABLED(SOFTWARE_SPI) IF_DISABLED(SOFTWARE_SPI, spiInit(SPI_HALF_SPEED));
// SS must be in output mode even it is not chip select
//SET_OUTPUT(SD_SS_PIN);
// set SS high - may be chip select for another SPI device
//#if SET_SPI_SS_HIGH
//WRITE(SD_SS_PIN, HIGH);
//#endif
// set a default rate
spiInit(1);
#endif
} }
#if NONE(SOFTWARE_SPI, FORCE_SOFT_SPI) #if NONE(SOFTWARE_SPI, FORCE_SOFT_SPI)
@ -74,7 +74,8 @@ void spiBegin() {
#elif defined(PRR0) #elif defined(PRR0)
PRR0 PRR0
#endif #endif
, PRSPI); , PRSPI
);
SPCR = _BV(SPE) | _BV(MSTR) | (spiRate >> 1); SPCR = _BV(SPE) | _BV(MSTR) | (spiRate >> 1);
SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X); SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X);

7
Marlin/src/HAL/STM32/watchdog.h → Marlin/src/HAL/AVR/MarlinSPI.h

@ -1,6 +1,6 @@
/** /**
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* *
* Based on Sprinter and grbl. * Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
@ -21,5 +21,6 @@
*/ */
#pragma once #pragma once
void watchdog_init(); #include <SPI.h>
void HAL_watchdog_refresh();
using MarlinSPI = SPIClass;

4
Marlin/src/HAL/AVR/MarlinSerial.cpp

@ -486,7 +486,7 @@ void MarlinSerial<Cfg>::write(const uint8_t c) {
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1); const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
// If global interrupts are disabled (as the result of being called from an ISR)... // If global interrupts are disabled (as the result of being called from an ISR)...
if (!ISRS_ENABLED()) { if (!hal.isr_state()) {
// Make room by polling if it is possible to transmit, and do so! // Make room by polling if it is possible to transmit, and do so!
while (i == tx_buffer.tail) { while (i == tx_buffer.tail) {
@ -534,7 +534,7 @@ void MarlinSerial<Cfg>::flushTX() {
if (!_written) return; if (!_written) return;
// If global interrupts are disabled (as the result of being called from an ISR)... // If global interrupts are disabled (as the result of being called from an ISR)...
if (!ISRS_ENABLED()) { if (!hal.isr_state()) {
// Wait until everything was transmitted - We must do polling, as interrupts are disabled // Wait until everything was transmitted - We must do polling, as interrupts are disabled
while (tx_buffer.head != tx_buffer.tail || !B_TXC) { while (tx_buffer.head != tx_buffer.tail || !B_TXC) {

8
Marlin/src/HAL/AVR/MarlinSerial.h

@ -191,13 +191,13 @@
rx_framing_errors; rx_framing_errors;
static ring_buffer_pos_t rx_max_enqueued; static ring_buffer_pos_t rx_max_enqueued;
static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head(); FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_head();
static volatile bool rx_tail_value_not_stable; static volatile bool rx_tail_value_not_stable;
static volatile uint16_t rx_tail_value_backup; static volatile uint16_t rx_tail_value_backup;
static FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value); FORCE_INLINE static void atomic_set_rx_tail(ring_buffer_pos_t value);
static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail(); FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_tail();
public: public:
FORCE_INLINE static void store_rxd_char(); FORCE_INLINE static void store_rxd_char();
@ -217,7 +217,7 @@
#endif #endif
enum { HasEmergencyParser = Cfg::EMERGENCYPARSER }; enum { HasEmergencyParser = Cfg::EMERGENCYPARSER };
static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; } static 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 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 buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }

202
Marlin/src/HAL/AVR/Servo.cpp

@ -66,27 +66,26 @@ static volatile int8_t Channel[_Nbr_16timers]; // counter for the s
/************ static functions common to all instances ***********************/ /************ static functions common to all instances ***********************/
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) { static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
if (Channel[timer] < 0) int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer if (cho < 0) // Channel -1 indicates the refresh interval completed...
else { *TCNTn = 0; // ...so reset the timer
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive) else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
}
Channel[timer] = ++cho; // Handle the next channel (or 0)
Channel[timer]++; // increment to the next channel if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) { *OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration
*OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks; if (SERVO(timer, cho).Pin.isActive) // activated?
if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
} }
else { else {
// finished all channels so wait for the refresh period to expire before starting over // finished all channels so wait for the refresh period to expire before starting over
if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL); ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
else *OCRnA = max(cval, ival);
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel Channel[timer] = -1; // reset the timer counter to 0 on the next call
} }
} }
@ -123,91 +122,102 @@ static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t
/****************** end of static functions ******************************/ /****************** end of static functions ******************************/
void initISR(timer16_Sequence_t timer) { void initISR(const timer16_Sequence_t timer_index) {
#ifdef _useTimer1 switch (timer_index) {
if (timer == _timer1) { default: break;
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8 #ifdef _useTimer1
TCNT1 = 0; // clear the timer count case _timer1:
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) TCCR1A = 0; // normal counting mode
SBI(TIFR, OCF1A); // clear any pending interrupts; TCCR1B = _BV(CS11); // set prescaler of 8
SBI(TIMSK, OCIE1A); // enable the output compare interrupt TCNT1 = 0; // clear the timer count
#else #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
// here if not ATmega8 or ATmega128 SBI(TIFR, OCF1A); // clear any pending interrupts;
SBI(TIFR1, OCF1A); // clear any pending interrupts; SBI(TIMSK, OCIE1A); // enable the output compare interrupt
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
}
#endif
#ifdef _useTimer3
if (timer == _timer3) {
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#ifdef __AVR_ATmega128__
SBI(TIFR, OCF3A); // clear any pending interrupts;
SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
#else
SBI(TIFR3, OCF3A); // clear any pending interrupts;
SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif
}
#endif
#ifdef _useTimer4
if (timer == _timer4) {
TCCR4A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8
TCNT4 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
}
#endif
#ifdef _useTimer5
if (timer == _timer5) {
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
}
#endif
}
void finISR(timer16_Sequence_t timer) {
// Disable use of the given timer
#ifdef WIRING
if (timer == _timer1) {
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK1
#else #else
TIMSK // here if not ATmega8 or ATmega128
SBI(TIFR1, OCF1A); // clear any pending interrupts;
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
#endif #endif
, OCIE1A); // disable timer 1 output compare interrupt #ifdef WIRING
timerDetach(TIMER1OUTCOMPAREA_INT); timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
} #endif
else if (timer == _timer3) { break;
CBI( #endif
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK3 #ifdef _useTimer3
case _timer3:
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#ifdef __AVR_ATmega128__
SBI(TIFR, OCF3A); // clear any pending interrupts;
SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
#else #else
ETIMSK SBI(TIFR3, OCF3A); // clear any pending interrupts;
SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif #endif
, OCIE3A); // disable the timer3 output compare A interrupt break;
timerDetach(TIMER3OUTCOMPAREA_INT); #endif
#ifdef _useTimer4
case _timer4:
TCCR4A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8
TCNT4 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
break;
#endif
#ifdef _useTimer5
case _timer5:
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
break;
#endif
}
}
void finISR(const timer16_Sequence_t timer_index) {
// Disable use of the given timer
#ifdef WIRING
switch (timer_index) {
default: break;
case _timer1:
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK1
#else
TIMSK
#endif
, OCIE1A // disable timer 1 output compare interrupt
);
timerDetach(TIMER1OUTCOMPAREA_INT);
break;
case _timer3:
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK3
#else
ETIMSK
#endif
, OCIE3A // disable the timer3 output compare A interrupt
);
timerDetach(TIMER3OUTCOMPAREA_INT);
break;
} }
#else // !WIRING #else // !WIRING
// For arduino - in future: call here to a currently undefined function to reset the timer // For arduino - in future: call here to a currently undefined function to reset the timer
UNUSED(timer); UNUSED(timer_index);
#endif #endif
} }

46
Marlin/src/HAL/AVR/endstop_interrupts.h

@ -213,6 +213,51 @@ void setup_endstop_interrupts() {
pciSetup(K_MIN_PIN); pciSetup(K_MIN_PIN);
#endif #endif
#endif #endif
#if HAS_U_MAX
#if (digitalPinToInterrupt(U_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(U_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(U_MAX_PIN), "U_MAX_PIN is not interrupt-capable");
pciSetup(U_MAX_PIN);
#endif
#elif HAS_U_MIN
#if (digitalPinToInterrupt(U_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(U_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(U_MIN_PIN), "U_MIN_PIN is not interrupt-capable");
pciSetup(U_MIN_PIN);
#endif
#endif
#if HAS_V_MAX
#if (digitalPinToInterrupt(V_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(V_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(V_MAX_PIN), "V_MAX_PIN is not interrupt-capable");
pciSetup(V_MAX_PIN);
#endif
#elif HAS_V_MIN
#if (digitalPinToInterrupt(V_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(V_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(V_MIN_PIN), "V_MIN_PIN is not interrupt-capable");
pciSetup(V_MIN_PIN);
#endif
#endif
#if HAS_W_MAX
#if (digitalPinToInterrupt(W_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(W_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(W_MAX_PIN), "W_MAX_PIN is not interrupt-capable");
pciSetup(W_MAX_PIN);
#endif
#elif HAS_W_MIN
#if (digitalPinToInterrupt(W_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(W_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(W_MIN_PIN), "W_MIN_PIN is not interrupt-capable");
pciSetup(W_MIN_PIN);
#endif
#endif
#if HAS_X2_MAX #if HAS_X2_MAX
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MAX_PIN); _ATTACH(X2_MAX_PIN);
@ -301,5 +346,6 @@ void setup_endstop_interrupts() {
pciSetup(Z_MIN_PROBE_PIN); pciSetup(Z_MIN_PROBE_PIN);
#endif #endif
#endif #endif
// If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI. // If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI.
} }

332
Marlin/src/HAL/AVR/fast_pwm.cpp

@ -21,11 +21,7 @@
*/ */
#ifdef __AVR__ #ifdef __AVR__
#include "../../inc/MarlinConfigPre.h" #include "../../inc/MarlinConfig.h"
#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM
#include "HAL.h"
struct Timer { struct Timer {
volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer
@ -33,250 +29,194 @@ struct Timer {
volatile uint16_t* ICRn; // max 1 ICR register per timer volatile uint16_t* ICRn; // max 1 ICR register per timer
uint8_t n; // the timer number [0->5] uint8_t n; // the timer number [0->5]
uint8_t q; // the timer output [0->2] (A->C) uint8_t q; // the timer output [0->2] (A->C)
bool isPWM; // True if pin is a "hardware timer"
bool isProtected; // True if timer is protected
}; };
// Macros for the Timer structure
#define _SET_WGMnQ(T, V) do{ \
*(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
*(T.TCCRnQ)[1] = (*(T.TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
}while(0)
// Set TCCR CS bits
#define _SET_CSn(T, V) (*(T.TCCRnQ)[1] = (*(T.TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0))
// Set TCCR COM bits
#define _SET_COMnQ(T, Q, V) (*(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q))))
// Set OCRnQ register
#define _SET_OCRnQ(T, Q, V) (*(T.OCRnQ)[Q] = int(V) & 0xFFFF)
// Set ICRn register (one per timer)
#define _SET_ICRn(T, V) (*(T.ICRn) = int(V) & 0xFFFF)
/** /**
* get_pwm_timer * Return a Timer struct describing a pin's timer.
* Get the timer information and register of the provided pin.
* Return a Timer struct containing this information.
* Used by set_pwm_frequency, set_pwm_duty
*/ */
Timer get_pwm_timer(const pin_t pin) { const Timer get_pwm_timer(const pin_t pin) {
uint8_t q = 0; uint8_t q = 0;
switch (digitalPinToTimer(pin)) { switch (digitalPinToTimer(pin)) {
// Protect reserved timers (TIMER0 & TIMER1)
#ifdef TCCR0A #ifdef TCCR0A
#if !AVR_AT90USB1286_FAMILY IF_DISABLED(AVR_AT90USB1286_FAMILY, case TIMER0A:)
case TIMER0A:
#endif
case TIMER0B:
#endif #endif
#ifdef TCCR1A #ifdef TCCR1A
case TIMER1A: case TIMER1B: case TIMER1A: case TIMER1B:
#endif #endif
break;
#if defined(TCCR2) || defined(TCCR2A) break; // Protect reserved timers (TIMER0 & TIMER1)
#ifdef TCCR2
case TIMER2: { #ifdef TCCR0A
Timer timer = { case TIMER0B: // Protected timer, but allow setting the duty cycle on OCR0B for pin D4 only
/*TCCRnQ*/ { &TCCR2, nullptr, nullptr }, return Timer({ { &TCCR0A, nullptr, nullptr }, { (uint16_t*)&OCR0A, (uint16_t*)&OCR0B, nullptr }, nullptr, 0, 1, true, true });
/*OCRnQ*/ { (uint16_t*)&OCR2, nullptr, nullptr }, #endif
/*ICRn*/ nullptr,
/*n, q*/ 2, 0 #if HAS_TCCR2
}; case TIMER2:
} return Timer({ { &TCCR2, nullptr, nullptr }, { (uint16_t*)&OCR2, nullptr, nullptr }, nullptr, 2, 0, true, false });
#elif defined(TCCR2A) #elif ENABLED(USE_OCR2A_AS_TOP)
#if ENABLED(USE_OCR2A_AS_TOP) case TIMER2A: break; // Protect TIMER2A since its OCR is used by TIMER2B
case TIMER2A: break; // protect TIMER2A case TIMER2B:
case TIMER2B: { return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, 1, true, false });
Timer timer = { #elif defined(TCCR2A)
/*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr }, case TIMER2B: ++q; case TIMER2A:
/*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, q, true, false });
/*ICRn*/ nullptr,
/*n, q*/ 2, 1
};
return timer;
}
#else
case TIMER2B: ++q;
case TIMER2A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr },
/*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
/*ICRn*/ nullptr,
2, q
};
return timer;
}
#endif
#endif
#endif #endif
#ifdef OCR3C #ifdef OCR3C
case TIMER3C: ++q; case TIMER3C: ++q; case TIMER3B: ++q; case TIMER3A:
case TIMER3B: ++q; return Timer({ { &TCCR3A, &TCCR3B, &TCCR3C }, { &OCR3A, &OCR3B, &OCR3C }, &ICR3, 3, q, true, false });
case TIMER3A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR3A, &TCCR3B, &TCCR3C },
/*OCRnQ*/ { &OCR3A, &OCR3B, &OCR3C },
/*ICRn*/ &ICR3,
/*n, q*/ 3, q
};
return timer;
}
#elif defined(OCR3B) #elif defined(OCR3B)
case TIMER3B: ++q; case TIMER3B: ++q; case TIMER3A:
case TIMER3A: { return Timer({ { &TCCR3A, &TCCR3B, nullptr }, { &OCR3A, &OCR3B, nullptr }, &ICR3, 3, q, true, false });
Timer timer = {
/*TCCRnQ*/ { &TCCR3A, &TCCR3B, nullptr },
/*OCRnQ*/ { &OCR3A, &OCR3B, nullptr },
/*ICRn*/ &ICR3,
/*n, q*/ 3, q
};
return timer;
}
#endif #endif
#ifdef TCCR4A #ifdef TCCR4A
case TIMER4C: ++q; case TIMER4C: ++q; case TIMER4B: ++q; case TIMER4A:
case TIMER4B: ++q; return Timer({ { &TCCR4A, &TCCR4B, &TCCR4C }, { &OCR4A, &OCR4B, &OCR4C }, &ICR4, 4, q, true, false });
case TIMER4A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR4A, &TCCR4B, &TCCR4C },
/*OCRnQ*/ { &OCR4A, &OCR4B, &OCR4C },
/*ICRn*/ &ICR4,
/*n, q*/ 4, q
};
return timer;
}
#endif #endif
#ifdef TCCR5A #ifdef TCCR5A
case TIMER5C: ++q; case TIMER5C: ++q; case TIMER5B: ++q; case TIMER5A:
case TIMER5B: ++q; return Timer({ { &TCCR5A, &TCCR5B, &TCCR5C }, { &OCR5A, &OCR5B, &OCR5C }, &ICR5, 5, q, true, false });
case TIMER5A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR5A, &TCCR5B, &TCCR5C },
/*OCRnQ*/ { &OCR5A, &OCR5B, &OCR5C },
/*ICRn*/ &ICR5,
/*n, q*/ 5, q
};
return timer;
}
#endif #endif
} }
Timer timer = {
/*TCCRnQ*/ { nullptr, nullptr, nullptr }, return Timer();
/*OCRnQ*/ { nullptr, nullptr, nullptr },
/*ICRn*/ nullptr,
0, 0
};
return timer;
} }
void set_pwm_frequency(const pin_t pin, int f_desired) { void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
Timer timer = get_pwm_timer(pin); const Timer timer = get_pwm_timer(pin);
if (timer.n == 0) return; // Don't proceed if protected timer or not recognised if (timer.isProtected || !timer.isPWM) return; // Don't proceed if protected timer or not recognized
uint16_t size;
if (timer.n == 2) size = 255; else size = 65535; const bool is_timer2 = timer.n == 2;
const uint16_t maxtop = is_timer2 ? 0xFF : 0xFFFF;
uint16_t res = 255; // resolution (TOP value) uint16_t res = 0xFF; // resolution (TOP value)
uint8_t j = 0; // prescaler index uint8_t j = CS_NONE; // prescaler index
uint8_t wgm = 1; // waveform generation mode uint8_t wgm = WGM_PWM_PC_8; // waveform generation mode
// Calculating the prescaler and resolution to use to achieve closest frequency // Calculating the prescaler and resolution to use to achieve closest frequency
if (f_desired != 0) { if (f_desired != 0) {
int f = (F_CPU) / (2 * 1024 * size) + 1; // Initialize frequency as lowest (non-zero) achievable constexpr uint16_t prescaler[] = { 1, 8, (32), 64, (128), 256, 1024 }; // (*) are Timer 2 only
uint16_t prescaler[] = { 0, 1, 8, /*TIMER2 ONLY*/32, 64, /*TIMER2 ONLY*/128, 256, 1024 }; uint16_t f = (F_CPU) / (2 * 1024 * maxtop) + 1; // Start with the lowest non-zero frequency achievable (1 or 31)
// loop over prescaler values LOOP_L_N(i, COUNT(prescaler)) { // Loop through all prescaler values
LOOP_S_L_N(i, 1, 8) { const uint16_t p = prescaler[i];
uint16_t res_temp_fast = 255, res_temp_phase_correct = 255; uint16_t res_fast_temp, res_pc_temp;
if (timer.n == 2) { if (is_timer2) {
// No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP #if ENABLED(USE_OCR2A_AS_TOP) // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
#if ENABLED(USE_OCR2A_AS_TOP) const uint16_t rft = (F_CPU) / (p * f_desired);
const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired); res_fast_temp = rft - 1;
res_temp_fast = rtf - 1; res_pc_temp = rft / 2;
res_temp_phase_correct = rtf / 2; #else
res_fast_temp = res_pc_temp = maxtop;
#endif #endif
} }
else { else {
// Skip TIMER2 specific prescalers when not TIMER2 if (p == 32 || p == 128) continue; // Skip TIMER2 specific prescalers when not TIMER2
if (i == 3 || i == 5) continue; const uint16_t rft = (F_CPU) / (p * f_desired);
const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired); res_fast_temp = rft - 1;
res_temp_fast = rtf - 1; res_pc_temp = rft / 2;
res_temp_phase_correct = rtf / 2;
} }
LIMIT(res_temp_fast, 1U, size); LIMIT(res_fast_temp, 1U, maxtop);
LIMIT(res_temp_phase_correct, 1U, size); LIMIT(res_pc_temp, 1U, maxtop);
// Calculate frequencies of test prescaler and resolution values // Calculate frequencies of test prescaler and resolution values
const int f_temp_fast = (F_CPU) / (prescaler[i] * (1 + res_temp_fast)), const uint32_t f_diff = _MAX(f, f_desired) - _MIN(f, f_desired),
f_temp_phase_correct = (F_CPU) / (2 * prescaler[i] * res_temp_phase_correct), f_fast_temp = (F_CPU) / (p * (1 + res_fast_temp)),
f_diff = ABS(f - f_desired), f_fast_diff = _MAX(f_fast_temp, f_desired) - _MIN(f_fast_temp, f_desired),
f_fast_diff = ABS(f_temp_fast - f_desired), f_pc_temp = (F_CPU) / (2 * p * res_pc_temp),
f_phase_diff = ABS(f_temp_phase_correct - f_desired); f_pc_diff = _MAX(f_pc_temp, f_desired) - _MIN(f_pc_temp, f_desired);
// If FAST values are closest to desired f if (f_fast_diff < f_diff && f_fast_diff <= f_pc_diff) { // FAST values are closest to desired f
if (f_fast_diff < f_diff && f_fast_diff <= f_phase_diff) {
// Remember this combination
f = f_temp_fast;
res = res_temp_fast;
j = i;
// Set the Wave Generation Mode to FAST PWM // Set the Wave Generation Mode to FAST PWM
if (timer.n == 2) { wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM)) : uint8_t(WGM_FAST_PWM_ICRn);
wgm = ( // Remember this combination
#if ENABLED(USE_OCR2A_AS_TOP) f = f_fast_temp; res = res_fast_temp; j = i + 1;
WGM2_FAST_PWM_OCR2A
#else
WGM2_FAST_PWM
#endif
);
}
else wgm = WGM_FAST_PWM_ICRn;
} }
// If PHASE CORRECT values are closes to desired f else if (f_pc_diff < f_diff) { // PHASE CORRECT values are closes to desired f
else if (f_phase_diff < f_diff) {
f = f_temp_phase_correct;
res = res_temp_phase_correct;
j = i;
// Set the Wave Generation Mode to PWM PHASE CORRECT // Set the Wave Generation Mode to PWM PHASE CORRECT
if (timer.n == 2) { wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_PWM_PC_OCR2A, WGM2_PWM_PC)) : uint8_t(WGM_PWM_PC_ICRn);
wgm = ( f = f_pc_temp; res = res_pc_temp; j = i + 1;
#if ENABLED(USE_OCR2A_AS_TOP)
WGM2_PWM_PC_OCR2A
#else
WGM2_PWM_PC
#endif
);
}
else wgm = WGM_PWM_PC_ICRn;
} }
} }
} }
_SET_WGMnQ(timer.TCCRnQ, wgm);
_SET_CSn(timer.TCCRnQ, j);
if (timer.n == 2) { _SET_WGMnQ(timer, wgm);
#if ENABLED(USE_OCR2A_AS_TOP) _SET_CSn(timer, j);
_SET_OCRnQ(timer.OCRnQ, 0, res); // Set OCR2A value (TOP) = res
#endif if (is_timer2) {
TERN_(USE_OCR2A_AS_TOP, _SET_OCRnQ(timer, 0, res)); // Set OCR2A value (TOP) = res
} }
else else
_SET_ICRn(timer.ICRn, res); // Set ICRn value (TOP) = res _SET_ICRn(timer, res); // Set ICRn value (TOP) = res
} }
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
// If v is 0 or v_size (max), digitalWrite to LOW or HIGH. // If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
// Note that digitalWrite also disables pwm output for us (sets COM bit to 0) // Note that digitalWrite also disables PWM output for us (sets COM bit to 0)
if (v == 0) if (v == 0)
digitalWrite(pin, invert); digitalWrite(pin, invert);
else if (v == v_size) else if (v == v_size)
digitalWrite(pin, !invert); digitalWrite(pin, !invert);
else { else {
Timer timer = get_pwm_timer(pin); const Timer timer = get_pwm_timer(pin);
if (timer.n == 0) return; // Don't proceed if protected timer or not recognised if (timer.isPWM) {
// Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted) if (timer.n == 0) {
_SET_COMnQ(timer.TCCRnQ, (timer.q _SET_COMnQ(timer, timer.q, COM_CLEAR_SET); // Only allow a TIMER0B select...
#ifdef TCCR2 _SET_OCRnQ(timer, timer.q, v); // ...and OCR0B duty update. For output pin D4 no frequency changes are permitted.
+ (timer.q == 2) // COM20 is on bit 4 of TCCR2, thus requires q + 1 in the macro }
#endif else if (!timer.isProtected) {
), COM_CLEAR_SET + invert const uint16_t top = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn;
); _SET_COMnQ(timer, SUM_TERN(HAS_TCCR2, timer.q, timer.q == 2), COM_CLEAR_SET + invert); // COM20 is on bit 4 of TCCR2, so +1 for q==2
_SET_OCRnQ(timer, timer.q, uint16_t(uint32_t(v) * top / v_size)); // Scale 8/16-bit v to top value
uint16_t top; }
if (timer.n == 2) { // if TIMER2
top = (
#if ENABLED(USE_OCR2A_AS_TOP)
*timer.OCRnQ[0] // top = OCR2A
#else
255 // top = 0xFF (max)
#endif
);
} }
else else
top = *timer.ICRn; // top = ICRn digitalWrite(pin, v < v_size / 2 ? LOW : HIGH);
_SET_OCRnQ(timer.OCRnQ, timer.q, v * float(top) / float(v_size)); // Scale 8/16-bit v to top value
} }
} }
#endif // NEEDS_HARDWARE_PWM void MarlinHAL::init_pwm_timers() {
// Init some timer frequencies to a default 1KHz
const pin_t pwm_pin[] = {
#ifdef __AVR_ATmega2560__
10, 5, 6, 46
#elif defined(__AVR_ATmega1280__)
12, 31
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284__)
15, 6
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_mega64) || defined(__AVR_mega128)
16, 24
#endif
};
LOOP_L_N(i, COUNT(pwm_pin))
set_pwm_frequency(pwm_pin[i], 1000);
}
#endif // __AVR__ #endif // __AVR__

16
Marlin/src/HAL/AVR/fastio.cpp

@ -245,7 +245,7 @@ uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb
float count = 0; float count = 0;
if (hz > 0 && (dca || dcb || dcc)) { if (hz > 0 && (dca || dcb || dcc)) {
count = float(F_CPU) / hz; // 1x prescaler, TOP for 16MHz base freq. count = float(F_CPU) / hz; // 1x prescaler, TOP for 16MHz base freq.
uint16_t prescaler; // Range of 30.5Hz (65535) 64.5KHz (>31) uint16_t prescaler; // Range of 30.5Hz (65535) 64.5kHz (>31)
if (count >= 255. * 256.) { prescaler = 1024; SET_CS(5, PRESCALER_1024); } if (count >= 255. * 256.) { prescaler = 1024; SET_CS(5, PRESCALER_1024); }
else if (count >= 255. * 64.) { prescaler = 256; SET_CS(5, PRESCALER_256); } else if (count >= 255. * 64.) { prescaler = 256; SET_CS(5, PRESCALER_256); }
@ -257,7 +257,7 @@ uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb
const float pwm_top = round(count); // Get the rounded count const float pwm_top = round(count); // Get the rounded count
ICR5 = (uint16_t)pwm_top - 1; // Subtract 1 for TOP ICR5 = (uint16_t)pwm_top - 1; // Subtract 1 for TOP
OCR5A = pwm_top * ABS(dca); // Update and scale DCs OCR5A = pwm_top * ABS(dca); // Update and scale DCs
OCR5B = pwm_top * ABS(dcb); OCR5B = pwm_top * ABS(dcb);
OCR5C = pwm_top * ABS(dcc); OCR5C = pwm_top * ABS(dcc);
_SET_COM(5, A, dca ? (dca < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL); // Set compare modes _SET_COM(5, A, dca ? (dca < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL); // Set compare modes
@ -267,17 +267,17 @@ uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb
SET_WGM(5, FAST_PWM_ICRn); // Fast PWM with ICR5 as TOP SET_WGM(5, FAST_PWM_ICRn); // Fast PWM with ICR5 as TOP
//SERIAL_ECHOLNPGM("Timer 5 Settings:"); //SERIAL_ECHOLNPGM("Timer 5 Settings:");
//SERIAL_ECHOLNPAIR(" Prescaler=", prescaler); //SERIAL_ECHOLNPGM(" Prescaler=", prescaler);
//SERIAL_ECHOLNPAIR(" TOP=", ICR5); //SERIAL_ECHOLNPGM(" TOP=", ICR5);
//SERIAL_ECHOLNPAIR(" OCR5A=", OCR5A); //SERIAL_ECHOLNPGM(" OCR5A=", OCR5A);
//SERIAL_ECHOLNPAIR(" OCR5B=", OCR5B); //SERIAL_ECHOLNPGM(" OCR5B=", OCR5B);
//SERIAL_ECHOLNPAIR(" OCR5C=", OCR5C); //SERIAL_ECHOLNPGM(" OCR5C=", OCR5C);
} }
else { else {
// Restore the default for Timer 5 // Restore the default for Timer 5
SET_WGM(5, PWM_PC_8); // PWM 8-bit (Phase Correct) SET_WGM(5, PWM_PC_8); // PWM 8-bit (Phase Correct)
SET_COMS(5, NORMAL, NORMAL, NORMAL); // Do nothing SET_COMS(5, NORMAL, NORMAL, NORMAL); // Do nothing
SET_CS(5, PRESCALER_64); // 16MHz / 64 = 250KHz SET_CS(5, PRESCALER_64); // 16MHz / 64 = 250kHz
OCR5A = OCR5B = OCR5C = 0; OCR5A = OCR5B = OCR5C = 0;
} }
return round(count); return round(count);

67
Marlin/src/HAL/AVR/fastio.h

@ -118,7 +118,7 @@
*/ */
// Waveform Generation Modes // Waveform Generation Modes
enum WaveGenMode : char { enum WaveGenMode : uint8_t {
WGM_NORMAL, // 0 WGM_NORMAL, // 0
WGM_PWM_PC_8, // 1 WGM_PWM_PC_8, // 1
WGM_PWM_PC_9, // 2 WGM_PWM_PC_9, // 2
@ -138,19 +138,19 @@ enum WaveGenMode : char {
}; };
// Wavefore Generation Modes (Timer 2 only) // Wavefore Generation Modes (Timer 2 only)
enum WaveGenMode2 : char { enum WaveGenMode2 : uint8_t {
WGM2_NORMAL, // 0 WGM2_NORMAL, // 0
WGM2_PWM_PC, // 1 WGM2_PWM_PC, // 1
WGM2_CTC_OCR2A, // 2 WGM2_CTC_OCR2A, // 2
WGM2_FAST_PWM, // 3 WGM2_FAST_PWM, // 3
WGM2_reserved_1, // 4 WGM2_reserved_1, // 4
WGM2_PWM_PC_OCR2A, // 5 WGM2_PWM_PC_OCR2A, // 5
WGM2_reserved_2, // 6 WGM2_reserved_2, // 6
WGM2_FAST_PWM_OCR2A, // 7 WGM2_FAST_PWM_OCR2A, // 7
}; };
// Compare Modes // Compare Modes
enum CompareMode : char { enum CompareMode : uint8_t {
COM_NORMAL, // 0 COM_NORMAL, // 0
COM_TOGGLE, // 1 Non-PWM: OCnx ... Both PWM (WGM 9,11,14,15): OCnA only ... else NORMAL COM_TOGGLE, // 1 Non-PWM: OCnx ... Both PWM (WGM 9,11,14,15): OCnA only ... else NORMAL
COM_CLEAR_SET, // 2 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down COM_CLEAR_SET, // 2 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
@ -158,7 +158,7 @@ enum CompareMode : char {
}; };
// Clock Sources // Clock Sources
enum ClockSource : char { enum ClockSource : uint8_t {
CS_NONE, // 0 CS_NONE, // 0
CS_PRESCALER_1, // 1 CS_PRESCALER_1, // 1
CS_PRESCALER_8, // 2 CS_PRESCALER_8, // 2
@ -170,7 +170,7 @@ enum ClockSource : char {
}; };
// Clock Sources (Timer 2 only) // Clock Sources (Timer 2 only)
enum ClockSource2 : char { enum ClockSource2 : uint8_t {
CS2_NONE, // 0 CS2_NONE, // 0
CS2_PRESCALER_1, // 1 CS2_PRESCALER_1, // 1
CS2_PRESCALER_8, // 2 CS2_PRESCALER_8, // 2
@ -203,40 +203,33 @@ enum ClockSource2 : char {
TCCR##T##B = (TCCR##T##B & ~(0x3 << WGM##T##2)) | (((int(V) >> 2) & 0x3) << WGM##T##2); \ TCCR##T##B = (TCCR##T##B & ~(0x3 << WGM##T##2)) | (((int(V) >> 2) & 0x3) << WGM##T##2); \
}while(0) }while(0)
#define SET_WGM(T,V) _SET_WGM(T,WGM_##V) #define SET_WGM(T,V) _SET_WGM(T,WGM_##V)
// Runtime (see set_pwm_frequency):
#define _SET_WGMnQ(TCCRnQ, V) do{ \
*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
*(TCCRnQ)[1] = (*(TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
}while(0)
// Set Clock Select bits // Set Clock Select bits
// Ex: SET_CS3(PRESCALER_64); // Ex: SET_CS3(PRESCALER_64);
#ifdef TCCR2
#define HAS_TCCR2 1
#endif
#define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0)) #define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0))
#define _SET_CS0(V) _SET_CS(0,V) #define _SET_CS0(V) _SET_CS(0,V)
#define _SET_CS1(V) _SET_CS(1,V) #define _SET_CS1(V) _SET_CS(1,V)
#ifdef TCCR2
#define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
#else
#define _SET_CS2(V) _SET_CS(2,V)
#endif
#define _SET_CS3(V) _SET_CS(3,V) #define _SET_CS3(V) _SET_CS(3,V)
#define _SET_CS4(V) _SET_CS(4,V) #define _SET_CS4(V) _SET_CS(4,V)
#define _SET_CS5(V) _SET_CS(5,V) #define _SET_CS5(V) _SET_CS(5,V)
#define SET_CS0(V) _SET_CS0(CS_##V) #define SET_CS0(V) _SET_CS0(CS_##V)
#define SET_CS1(V) _SET_CS1(CS_##V) #define SET_CS1(V) _SET_CS1(CS_##V)
#ifdef TCCR2
#if HAS_TCCR2
#define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
#define SET_CS2(V) _SET_CS2(CS2_##V) #define SET_CS2(V) _SET_CS2(CS2_##V)
#else #else
#define _SET_CS2(V) _SET_CS(2,V)
#define SET_CS2(V) _SET_CS2(CS_##V) #define SET_CS2(V) _SET_CS2(CS_##V)
#endif #endif
#define SET_CS3(V) _SET_CS3(CS_##V) #define SET_CS3(V) _SET_CS3(CS_##V)
#define SET_CS4(V) _SET_CS4(CS_##V) #define SET_CS4(V) _SET_CS4(CS_##V)
#define SET_CS5(V) _SET_CS5(CS_##V) #define SET_CS5(V) _SET_CS5(CS_##V)
#define SET_CS(T,V) SET_CS##T(V) #define SET_CS(T,V) SET_CS##T(V)
// Runtime (see set_pwm_frequency)
#define _SET_CSn(TCCRnQ, V) do{ \
(*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0)); \
}while(0)
// Set Compare Mode bits // Set Compare Mode bits
// Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET); // Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET);
@ -246,22 +239,6 @@ enum ClockSource2 : char {
#define SET_COMB(T,V) SET_COM(T,B,V) #define SET_COMB(T,V) SET_COM(T,B,V)
#define SET_COMC(T,V) SET_COM(T,C,V) #define SET_COMC(T,V) SET_COM(T,C,V)
#define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0) #define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0)
// Runtime (see set_pwm_duty)
#define _SET_COMnQ(TCCRnQ, Q, V) do{ \
(*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q)))); \
}while(0)
// Set OCRnQ register
// Runtime (see set_pwm_duty):
#define _SET_OCRnQ(OCRnQ, Q, V) do{ \
(*(OCRnQ)[(Q)] = (0x0000) | (int(V) & 0xFFFF)); \
}while(0)
// Set ICRn register (one per timer)
// Runtime (see set_pwm_frequency)
#define _SET_ICRn(ICRn, V) do{ \
(*(ICRn) = (0x0000) | (int(V) & 0xFFFF)); \
}while(0)
// Set Noise Canceler bit // Set Noise Canceler bit
// Ex: SET_ICNC(2,1) // Ex: SET_ICNC(2,1)
@ -284,7 +261,7 @@ enum ClockSource2 : char {
* PWM availability macros * PWM availability macros
*/ */
// Determine which harware PWMs are already in use // Determine which hardware 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 || P == COOLER_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) #if PIN_EXISTS(CONTROLLER_FAN)
#define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN) #define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN)

54
Marlin/src/HAL/AVR/inc/SanityCheck.h

@ -25,25 +25,65 @@
* Test AVR-specific configuration values for errors at compile-time. * Test AVR-specific configuration values for errors at compile-time.
*/ */
/**
* Check for common serial pin conflicts
*/
#define CHECK_SERIAL_PIN(N) ( \
X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \
|| X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \
|| X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \
|| X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \
|| X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \
|| X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \
|| BTN_EN1 == N || BTN_EN2 == N \
)
#if CONF_SERIAL_IS(0)
// D0-D1. No known conflicts.
#endif
#if NOT_TARGET(__AVR_ATmega644P__, __AVR_ATmega1284P__)
#if CONF_SERIAL_IS(1) && (CHECK_SERIAL_PIN(18) || CHECK_SERIAL_PIN(19))
#error "Serial Port 1 pin D18 and/or D19 conflicts with another pin on the board."
#endif
#else
#if CONF_SERIAL_IS(1) && (CHECK_SERIAL_PIN(10) || CHECK_SERIAL_PIN(11))
#error "Serial Port 1 pin D10 and/or D11 conflicts with another pin on the board."
#endif
#endif
#if CONF_SERIAL_IS(2) && (CHECK_SERIAL_PIN(16) || CHECK_SERIAL_PIN(17))
#error "Serial Port 2 pin D16 and/or D17 conflicts with another pin on the board."
#endif
#if CONF_SERIAL_IS(3) && (CHECK_SERIAL_PIN(14) || CHECK_SERIAL_PIN(15))
#error "Serial Port 3 pin D14 and/or D15 conflicts with another pin on the board."
#endif
#undef CHECK_SERIAL_PIN
/** /**
* Checks for FAST PWM * Checks for FAST PWM
*/ */
#if ENABLED(FAST_PWM_FAN) && (ENABLED(USE_OCR2A_AS_TOP) && defined(TCCR2)) #if ALL(FAST_PWM_FAN, USE_OCR2A_AS_TOP, HAS_TCCR2)
#error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2" #error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2."
#endif
/**
* Checks for SOFT PWM
*/
#if HAS_FAN0 && FAN_PIN == 9 && DISABLED(FAN_SOFT_PWM) && ENABLED(SPEAKER)
#error "FAN_PIN 9 Hardware PWM uses Timer 2 which conflicts with Arduino AVR Tone Timer (for SPEAKER)."
#error "Disable SPEAKER or enable FAN_SOFT_PWM."
#endif #endif
/** /**
* Sanity checks for Spindle / Laser PWM * Sanity checks for Spindle / Laser PWM
*/ */
#if ENABLED(SPINDLE_LASER_PWM) #if ENABLED(SPINDLE_LASER_USE_PWM)
#include "../ServoTimers.h" // Needed to check timer availability (_useTimer3) #include "../ServoTimers.h" // Needed to check timer availability (_useTimer3)
#if SPINDLE_LASER_PWM_PIN == 4 || WITHIN(SPINDLE_LASER_PWM_PIN, 11, 13) #if SPINDLE_LASER_PWM_PIN == 4 || WITHIN(SPINDLE_LASER_PWM_PIN, 11, 13)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by a system interrupt." #error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by a system interrupt."
#elif NUM_SERVOS > 0 && defined(_useTimer3) && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5) #elif NUM_SERVOS > 0 && defined(_useTimer3) && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by the servo system." #error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by the servo system."
#endif #endif
#elif defined(SPINDLE_LASER_FREQUENCY) #elif SPINDLE_LASER_FREQUENCY
#error "SPINDLE_LASER_FREQUENCY requires SPINDLE_LASER_PWM." #error "SPINDLE_LASER_FREQUENCY requires SPINDLE_LASER_USE_PWM."
#endif #endif
/** /**
@ -63,3 +103,7 @@
#if ENABLED(POSTMORTEM_DEBUGGING) #if ENABLED(POSTMORTEM_DEBUGGING)
#error "POSTMORTEM_DEBUGGING is not supported on AVR boards." #error "POSTMORTEM_DEBUGGING is not supported on AVR boards."
#endif #endif
#if USING_PULLDOWNS
#error "PULLDOWN pin mode is not available on AVR boards."
#endif

4
Marlin/src/HAL/AVR/math.h

@ -35,7 +35,7 @@
// C B A is longIn1 // C B A is longIn1
// D C B A is longIn2 // D C B A is longIn2
// //
static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) { FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
uint8_t tmp1; uint8_t tmp1;
uint8_t tmp2; uint8_t tmp2;
uint16_t intRes; uint16_t intRes;
@ -89,7 +89,7 @@ static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
// uses: // uses:
// r26 to store 0 // r26 to store 0
// r27 to store the byte 1 of the 24 bit result // r27 to store the byte 1 of the 24 bit result
static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) { FORCE_INLINE static uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
uint8_t tmp; uint8_t tmp;
uint16_t intRes; uint16_t intRes;
__asm__ __volatile__ ( __asm__ __volatile__ (

65
Marlin/src/HAL/AVR/pinsDebug.h

@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
@ -71,7 +74,7 @@
#define MULTI_NAME_PAD 26 // space needed to be pretty if not first name assigned to a pin #define MULTI_NAME_PAD 26 // space needed to be pretty if not first name assigned to a pin
void PRINT_ARRAY_NAME(uint8_t x) { void PRINT_ARRAY_NAME(uint8_t x) {
char *name_mem_pointer = (char*)pgm_read_ptr(&pin_array[x].name); PGM_P const name_mem_pointer = (PGM_P)pgm_read_ptr(&pin_array[x].name);
LOOP_L_N(y, MAX_NAME_LENGTH) { LOOP_L_N(y, MAX_NAME_LENGTH) {
char temp_char = pgm_read_byte(name_mem_pointer + y); char temp_char = pgm_read_byte(name_mem_pointer + y);
if (temp_char != 0) if (temp_char != 0)
@ -99,7 +102,7 @@ void PRINT_ARRAY_NAME(uint8_t x) {
return true; \ return true; \
} else return false } else return false
#define ABTEST(N) defined(TCCR##N##A) && defined(COM##N##A1)
/** /**
* Print a pin's PWM status. * Print a pin's PWM status.
@ -110,7 +113,7 @@ static bool pwm_status(uint8_t pin) {
switch (digitalPinToTimer_DEBUG(pin)) { switch (digitalPinToTimer_DEBUG(pin)) {
#if defined(TCCR0A) && defined(COM0A1) #if ABTEST(0)
#ifdef TIMER0A #ifdef TIMER0A
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs #if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
PWM_CASE(0, A); PWM_CASE(0, A);
@ -119,20 +122,20 @@ static bool pwm_status(uint8_t pin) {
PWM_CASE(0, B); PWM_CASE(0, B);
#endif #endif
#if defined(TCCR1A) && defined(COM1A1) #if ABTEST(1)
PWM_CASE(1, A); PWM_CASE(1, A);
PWM_CASE(1, B); PWM_CASE(1, B);
#if defined(COM1C1) && defined(TIMER1C) #if defined(COM1C1) && defined(TIMER1C)
PWM_CASE(1, C); PWM_CASE(1, C);
#endif #endif
#endif #endif
#if defined(TCCR2A) && defined(COM2A1) #if ABTEST(2)
PWM_CASE(2, A); PWM_CASE(2, A);
PWM_CASE(2, B); PWM_CASE(2, B);
#endif #endif
#if defined(TCCR3A) && defined(COM3A1) #if ABTEST(3)
PWM_CASE(3, A); PWM_CASE(3, A);
PWM_CASE(3, B); PWM_CASE(3, B);
#ifdef COM3C1 #ifdef COM3C1
@ -146,7 +149,7 @@ static bool pwm_status(uint8_t pin) {
PWM_CASE(4, C); PWM_CASE(4, C);
#endif #endif
#if defined(TCCR5A) && defined(COM5A1) #if ABTEST(5)
PWM_CASE(5, A); PWM_CASE(5, A);
PWM_CASE(5, B); PWM_CASE(5, B);
PWM_CASE(5, C); PWM_CASE(5, C);
@ -163,16 +166,16 @@ static bool pwm_status(uint8_t pin) {
const volatile uint8_t* const PWM_other[][3] PROGMEM = { const volatile uint8_t* const PWM_other[][3] PROGMEM = {
{ &TCCR0A, &TCCR0B, &TIMSK0 }, { &TCCR0A, &TCCR0B, &TIMSK0 },
{ &TCCR1A, &TCCR1B, &TIMSK1 }, { &TCCR1A, &TCCR1B, &TIMSK1 },
#if defined(TCCR2A) && defined(COM2A1) #if ABTEST(2)
{ &TCCR2A, &TCCR2B, &TIMSK2 }, { &TCCR2A, &TCCR2B, &TIMSK2 },
#endif #endif
#if defined(TCCR3A) && defined(COM3A1) #if ABTEST(3)
{ &TCCR3A, &TCCR3B, &TIMSK3 }, { &TCCR3A, &TCCR3B, &TIMSK3 },
#endif #endif
#ifdef TCCR4A #ifdef TCCR4A
{ &TCCR4A, &TCCR4B, &TIMSK4 }, { &TCCR4A, &TCCR4B, &TIMSK4 },
#endif #endif
#if defined(TCCR5A) && defined(COM5A1) #if ABTEST(5)
{ &TCCR5A, &TCCR5B, &TIMSK5 }, { &TCCR5A, &TCCR5B, &TIMSK5 },
#endif #endif
}; };
@ -192,11 +195,11 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
{ (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 }, { (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 },
#endif #endif
#if defined(TCCR2A) && defined(COM2A1) #if ABTEST(2)
{ &OCR2A, &OCR2B, 0 }, { &OCR2A, &OCR2B, 0 },
#endif #endif
#if defined(TCCR3A) && defined(COM3A1) #if ABTEST(3)
#ifdef COM3C1 #ifdef COM3C1
{ (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C }, { (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C },
#else #else
@ -208,7 +211,7 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
{ (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C }, { (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C },
#endif #endif
#if defined(TCCR5A) && defined(COM5A1) #if ABTEST(5)
{ (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C }, { (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C },
#endif #endif
}; };
@ -235,9 +238,9 @@ 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) { inline void com_print(const uint8_t N, const uint8_t Z) {
const uint8_t *TCCRA = (uint8_t*)TCCR_A(N); const uint8_t *TCCRA = (uint8_t*)TCCR_A(N);
SERIAL_ECHOPAIR(" COM", AS_CHAR('0' + N)); SERIAL_ECHOPGM(" COM", AS_DIGIT(N));
SERIAL_CHAR(Z); SERIAL_CHAR(Z);
SERIAL_ECHOPAIR(": ", int((*TCCRA >> (6 - Z * 2)) & 0x03)); SERIAL_ECHOPGM(": ", int((*TCCRA >> (6 - Z * 2)) & 0x03));
} }
void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N - WGM bit layout void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N - WGM bit layout
@ -247,7 +250,7 @@ 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)))); uint8_t WGM = (((*TCCRB & _BV(WGM_2)) >> 1) | (*TCCRA & (_BV(WGM_0) | _BV(WGM_1))));
if (N == 4) WGM |= ((*TCCRB & _BV(WGM_3)) >> 1); if (N == 4) WGM |= ((*TCCRB & _BV(WGM_3)) >> 1);
SERIAL_ECHOPAIR(" TIMER", AS_CHAR(T + '0')); SERIAL_ECHOPGM(" TIMER", AS_DIGIT(T));
SERIAL_CHAR(L); SERIAL_CHAR(L);
SERIAL_ECHO_SP(3); SERIAL_ECHO_SP(3);
@ -259,14 +262,14 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
const uint16_t *OCRVAL16 = (uint16_t*)OCR_VAL(T, L - 'A'); const uint16_t *OCRVAL16 = (uint16_t*)OCR_VAL(T, L - 'A');
PWM_PRINT(*OCRVAL16); PWM_PRINT(*OCRVAL16);
} }
SERIAL_ECHOPAIR(" WGM: ", WGM); SERIAL_ECHOPGM(" WGM: ", WGM);
com_print(T,L); com_print(T,L);
SERIAL_ECHOPAIR(" CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) )); SERIAL_ECHOPGM(" CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) ));
SERIAL_ECHOPAIR(" TCCR", AS_CHAR(T + '0'), "A: ", *TCCRA); SERIAL_ECHOPGM(" TCCR", AS_DIGIT(T), "A: ", *TCCRA);
SERIAL_ECHOPAIR(" TCCR", AS_CHAR(T + '0'), "B: ", *TCCRB); SERIAL_ECHOPGM(" TCCR", AS_DIGIT(T), "B: ", *TCCRB);
const uint8_t *TMSK = (uint8_t*)TIMSK(T); const uint8_t *TMSK = (uint8_t*)TIMSK(T);
SERIAL_ECHOPAIR(" TIMSK", AS_CHAR(T + '0'), ": ", *TMSK); SERIAL_ECHOPGM(" TIMSK", AS_DIGIT(T), ": ", *TMSK);
const uint8_t OCIE = L - 'A' + 1; const uint8_t OCIE = L - 'A' + 1;
if (N == 3) { if (WGM == 0 || WGM == 2 || WGM == 4 || WGM == 6) err_is_counter(); } if (N == 3) { if (WGM == 0 || WGM == 2 || WGM == 4 || WGM == 6) err_is_counter(); }
@ -278,7 +281,7 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
static void pwm_details(uint8_t pin) { static void pwm_details(uint8_t pin) {
switch (digitalPinToTimer_DEBUG(pin)) { switch (digitalPinToTimer_DEBUG(pin)) {
#if defined(TCCR0A) && defined(COM0A1) #if ABTEST(0)
#ifdef TIMER0A #ifdef TIMER0A
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs #if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
case TIMER0A: timer_prefix(0, 'A', 3); break; case TIMER0A: timer_prefix(0, 'A', 3); break;
@ -287,7 +290,7 @@ static void pwm_details(uint8_t pin) {
case TIMER0B: timer_prefix(0, 'B', 3); break; case TIMER0B: timer_prefix(0, 'B', 3); break;
#endif #endif
#if defined(TCCR1A) && defined(COM1A1) #if ABTEST(1)
case TIMER1A: timer_prefix(1, 'A', 4); break; case TIMER1A: timer_prefix(1, 'A', 4); break;
case TIMER1B: timer_prefix(1, 'B', 4); break; case TIMER1B: timer_prefix(1, 'B', 4); break;
#if defined(COM1C1) && defined(TIMER1C) #if defined(COM1C1) && defined(TIMER1C)
@ -295,12 +298,12 @@ static void pwm_details(uint8_t pin) {
#endif #endif
#endif #endif
#if defined(TCCR2A) && defined(COM2A1) #if ABTEST(2)
case TIMER2A: timer_prefix(2, 'A', 3); break; case TIMER2A: timer_prefix(2, 'A', 3); break;
case TIMER2B: timer_prefix(2, 'B', 3); break; case TIMER2B: timer_prefix(2, 'B', 3); break;
#endif #endif
#if defined(TCCR3A) && defined(COM3A1) #if ABTEST(3)
case TIMER3A: timer_prefix(3, 'A', 4); break; case TIMER3A: timer_prefix(3, 'A', 4); break;
case TIMER3B: timer_prefix(3, 'B', 4); break; case TIMER3B: timer_prefix(3, 'B', 4); break;
#ifdef COM3C1 #ifdef COM3C1
@ -314,7 +317,7 @@ static void pwm_details(uint8_t pin) {
case TIMER4C: timer_prefix(4, 'C', 4); break; case TIMER4C: timer_prefix(4, 'C', 4); break;
#endif #endif
#if defined(TCCR5A) && defined(COM5A1) #if ABTEST(5)
case TIMER5A: timer_prefix(5, 'A', 4); break; case TIMER5A: timer_prefix(5, 'A', 4); break;
case TIMER5B: timer_prefix(5, 'B', 4); break; case TIMER5B: timer_prefix(5, 'B', 4); break;
case TIMER5C: timer_prefix(5, 'C', 4); break; case TIMER5C: timer_prefix(5, 'C', 4); break;
@ -348,7 +351,6 @@ static void pwm_details(uint8_t pin) {
#endif #endif
} // pwm_details } // pwm_details
#ifndef digitalRead_mod // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs #ifndef digitalRead_mod // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs
int digitalRead_mod(const int8_t pin) { // same as digitalRead except the PWM stop section has been removed int digitalRead_mod(const int8_t pin) { // same as digitalRead except the PWM stop section has been removed
const uint8_t port = digitalPinToPort_DEBUG(pin); const uint8_t port = digitalPinToPort_DEBUG(pin);
@ -393,3 +395,6 @@ static void pwm_details(uint8_t pin) {
#endif #endif
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0) #define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#undef ABTEST

3
Marlin/src/HAL/AVR/pinsDebug_Teensyduino.h

@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or

3
Marlin/src/HAL/AVR/pinsDebug_plus_70.h

@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or

44
Marlin/src/HAL/AVR/timers.h

@ -34,14 +34,14 @@ typedef uint16_t hal_timer_t;
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz #define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
#ifndef STEP_TIMER_NUM #ifndef MF_TIMER_STEP
#define STEP_TIMER_NUM 1 #define MF_TIMER_STEP 1
#endif #endif
#ifndef PULSE_TIMER_NUM #ifndef MF_TIMER_PULSE
#define PULSE_TIMER_NUM STEP_TIMER_NUM #define MF_TIMER_PULSE MF_TIMER_STEP
#endif #endif
#ifndef TEMP_TIMER_NUM #ifndef MF_TIMER_TEMP
#define TEMP_TIMER_NUM 0 #define MF_TIMER_TEMP 0
#endif #endif
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0) #define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
@ -58,13 +58,13 @@ typedef uint16_t hal_timer_t;
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A) #define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A) #define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0B) #define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0A)
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0B) #define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0A)
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0B) #define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0A)
FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) { FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
switch (timer_num) { switch (timer_num) {
case STEP_TIMER_NUM: case MF_TIMER_STEP:
// waveform generation = 0100 = CTC // waveform generation = 0100 = CTC
SET_WGM(1, CTC_OCRnA); SET_WGM(1, CTC_OCRnA);
@ -84,10 +84,10 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
TCNT1 = 0; TCNT1 = 0;
break; break;
case TEMP_TIMER_NUM: case MF_TIMER_TEMP:
// Use timer0 for temperature measurement // Use timer0 for temperature measurement
// Interleave temperature interrupt with millies interrupt // Interleave temperature interrupt with millies interrupt
OCR0B = 128; OCR0A = 128;
break; break;
} }
} }
@ -109,12 +109,12 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
* (otherwise, characters will be lost due to UART overflow). * (otherwise, characters will be lost due to UART overflow).
* Then: Stepper, Endstops, Temperature, and -finally- all others. * Then: Stepper, Endstops, Temperature, and -finally- all others.
*/ */
#define HAL_timer_isr_prologue(TIMER_NUM) #define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(TIMER_NUM) #define HAL_timer_isr_epilogue(T) NOOP
/* 18 cycles maximum latency */
#ifndef HAL_STEP_TIMER_ISR #ifndef HAL_STEP_TIMER_ISR
/* 18 cycles maximum latency */
#define HAL_STEP_TIMER_ISR() \ #define HAL_STEP_TIMER_ISR() \
extern "C" void TIMER1_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \ extern "C" void TIMER1_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER1_COMPA_vect_bottom() asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \ extern "C" void TIMER1_COMPA_vect_bottom() asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
@ -180,7 +180,7 @@ void TIMER1_COMPA_vect() { \
: \ : \
: [timsk0] "i" ((uint16_t)&TIMSK0), \ : [timsk0] "i" ((uint16_t)&TIMSK0), \
[timsk1] "i" ((uint16_t)&TIMSK1), \ [timsk1] "i" ((uint16_t)&TIMSK1), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)),\ [msk0] "M" ((uint8_t)(1<<OCIE0A)),\
[msk1] "M" ((uint8_t)(1<<OCIE1A)) \ [msk1] "M" ((uint8_t)(1<<OCIE1A)) \
: \ : \
); \ ); \
@ -193,9 +193,9 @@ void TIMER1_COMPA_vect_bottom()
/* 14 cycles maximum latency */ /* 14 cycles maximum latency */
#define HAL_TEMP_TIMER_ISR() \ #define HAL_TEMP_TIMER_ISR() \
extern "C" void TIMER0_COMPB_vect() __attribute__ ((signal, naked, used, externally_visible)); \ extern "C" void TIMER0_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER0_COMPB_vect_bottom() asm ("TIMER0_COMPB_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \ extern "C" void TIMER0_COMPA_vect_bottom() asm ("TIMER0_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER0_COMPB_vect() { \ void TIMER0_COMPA_vect() { \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \ A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \ A("in r16, __SREG__") /* 1 Get SREG */ \
@ -223,7 +223,7 @@ void TIMER0_COMPB_vect() { \
A("push r30") \ A("push r30") \
A("push r31") \ A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \ A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER0_COMPB_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \ A("call TIMER0_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \ A("pop r31") \
A("pop r30") \ A("pop r30") \
A("pop r27") \ A("pop r27") \
@ -251,10 +251,10 @@ void TIMER0_COMPB_vect() { \
A("reti") /* 4 Return from interrupt */ \ A("reti") /* 4 Return from interrupt */ \
: \ : \
: [timsk0] "i"((uint16_t)&TIMSK0), \ : [timsk0] "i"((uint16_t)&TIMSK0), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)) \ [msk0] "M" ((uint8_t)(1<<OCIE0A)) \
: \ : \
); \ ); \
} \ } \
void TIMER0_COMPB_vect_bottom() void TIMER0_COMPA_vect_bottom()
#endif // HAL_TEMP_TIMER_ISR #endif // HAL_TEMP_TIMER_ISR

4
Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp

@ -64,8 +64,8 @@
#include <U8glib-HAL.h> #include <U8glib-HAL.h>
uint8_t u8g_bitData, u8g_bitNotData, u8g_bitClock, u8g_bitNotClock; static uint8_t u8g_bitData, u8g_bitNotData, u8g_bitClock, u8g_bitNotClock;
volatile uint8_t *u8g_outData, *u8g_outClock; static volatile uint8_t *u8g_outData, *u8g_outClock;
static void u8g_com_arduino_init_shift_out(uint8_t dataPin, uint8_t clockPin) { static void u8g_com_arduino_init_shift_out(uint8_t dataPin, uint8_t clockPin) {
u8g_outData = portOutputRegister(digitalPinToPort(dataPin)); u8g_outData = portOutputRegister(digitalPinToPort(dataPin));

70
Marlin/src/HAL/AVR/watchdog.cpp

@ -1,70 +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 <https://www.gnu.org/licenses/>.
*
*/
#ifdef __AVR__
#include "../../inc/MarlinConfig.h"
#if ENABLED(USE_WATCHDOG)
#include "watchdog.h"
#include "../../MarlinCore.h"
// Initialize watchdog with 8s timeout, if possible. Otherwise, make it 4s.
void watchdog_init() {
#if ENABLED(WATCHDOG_DURATION_8S) && defined(WDTO_8S)
#define WDTO_NS WDTO_8S
#else
#define WDTO_NS WDTO_4S
#endif
#if ENABLED(WATCHDOG_RESET_MANUAL)
// Enable the watchdog timer, but only for the interrupt.
// Take care, as this requires the correct order of operation, with interrupts disabled.
// See the datasheet of any AVR chip for details.
wdt_reset();
cli();
_WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE);
_WD_CONTROL_REG = _BV(WDIE) | (WDTO_NS & 0x07) | ((WDTO_NS & 0x08) << 2); // WDTO_NS directly does not work. bit 0-2 are consecutive in the register but the highest value bit is at bit 5
// So worked for up to WDTO_2S
sei();
wdt_reset();
#else
wdt_enable(WDTO_NS); // The function handles the upper bit correct.
#endif
//delay(10000); // test it!
}
//===========================================================================
//=================================== ISR ===================================
//===========================================================================
// Watchdog timer interrupt, called if main program blocks >4sec and manual reset is enabled.
#if ENABLED(WATCHDOG_RESET_MANUAL)
ISR(WDT_vect) {
sei(); // With the interrupt driven serial we need to allow interrupts.
SERIAL_ERROR_MSG(STR_WATCHDOG_FIRED);
minkill(); // interrupt-safe final kill and infinite loop
}
#endif
#endif // USE_WATCHDOG
#endif // __AVR__

143
Marlin/src/HAL/DUE/HAL.cpp

@ -25,7 +25,7 @@
#ifdef ARDUINO_ARCH_SAM #ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "HAL.h" #include "../../MarlinCore.h"
#include <Wire.h> #include <Wire.h>
#include "usb/usb_task.h" #include "usb/usb_task.h"
@ -34,39 +34,33 @@
// Public Variables // Public Variables
// ------------------------ // ------------------------
uint16_t HAL_adc_result; uint16_t MarlinHAL::adc_result;
// ------------------------ // ------------------------
// Public functions // Public functions
// ------------------------ // ------------------------
TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial()); #if ENABLED(POSTMORTEM_DEBUGGING)
extern void install_min_serial();
#endif
// HAL initialization task void MarlinHAL::init() {
void HAL_init() {
// Initialize the USB stack
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
#endif #endif
usb_task_init(); usb_task_init(); // Initialize the USB stack
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
} }
// HAL idle task void MarlinHAL::init_board() {
void HAL_idletask() { #ifdef BOARD_INIT
// Perform USB stack housekeeping BOARD_INIT();
usb_task_idle(); #endif
} }
// Disable interrupts void MarlinHAL::idletask() { usb_task_idle(); } // Perform USB stack housekeeping
void cli() { noInterrupts(); }
// Enable interrupts
void sei() { interrupts(); }
void HAL_clear_reset_source() { } uint8_t MarlinHAL::get_reset_source() {
uint8_t HAL_get_reset_source() {
switch ((RSTC->RSTC_SR >> 8) & 0x07) { switch ((RSTC->RSTC_SR >> 8) & 0x07) {
case 0: return RST_POWER_ON; case 0: return RST_POWER_ON;
case 1: return RST_BACKUP; case 1: return RST_BACKUP;
@ -77,13 +71,105 @@ uint8_t HAL_get_reset_source() {
} }
} }
void HAL_reboot() { rstc_start_software_reset(RSTC); } void MarlinHAL::reboot() { rstc_start_software_reset(RSTC); }
// ------------------------
// Watchdog Timer
// ------------------------
#if ENABLED(USE_WATCHDOG)
// Initialize watchdog - On SAM3X, Watchdog was already configured
// and enabled or disabled at startup, so no need to reconfigure it
// here.
void MarlinHAL::watchdog_init() { WDT_Restart(WDT); } // Reset watchdog to start clean
// Reset watchdog. MUST be called at least every 4 seconds after the
// first watchdog_init or AVR will go into emergency procedures.
void MarlinHAL::watchdog_refresh() { watchdogReset(); }
#endif
// Override Arduino runtime to either config or disable the watchdog
//
// We need to configure the watchdog as soon as possible in the boot
// process, because watchdog initialization at hardware reset on SAM3X8E
// is unreliable, and there is risk of unintended resets if we delay
// that initialization to a later time.
void watchdogSetup() {
#if ENABLED(USE_WATCHDOG)
// 4 seconds timeout
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
// frequency is therefore 32768 / 128 = 256 Hz
timeout = (timeout << 8) / 1000;
if (timeout == 0)
timeout = 1;
else if (timeout > 0xFFF)
timeout = 0xFFF;
// We want to enable the watchdog with the specified timeout
uint32_t value =
WDT_MR_WDV(timeout) | // With the specified timeout
WDT_MR_WDD(timeout) | // and no invalid write window
#if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
WDT_MR_WDRPROC | // WDT fault resets processor only - We want
// to keep PIO controller state
#endif
WDT_MR_WDDBGHLT | // WDT stops in debug state.
WDT_MR_WDIDLEHLT; // WDT stops in idle state.
#if ENABLED(WATCHDOG_RESET_MANUAL)
// We enable the watchdog timer, but only for the interrupt.
// Configure WDT to only trigger an interrupt
value |= WDT_MR_WDFIEN; // Enable WDT fault interrupt.
void _delay_ms(const int delay_ms) { // Disable WDT interrupt (just in case, to avoid triggering it!)
// Todo: port for Due? NVIC_DisableIRQ(WDT_IRQn);
delay(delay_ms);
// 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();
// Initialize WDT with the given parameters
WDT_Enable(WDT, value);
// Configure and enable WDT interrupt.
NVIC_ClearPendingIRQ(WDT_IRQn);
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
NVIC_EnableIRQ(WDT_IRQn);
#else
// a WDT fault triggers a reset
value |= WDT_MR_WDRSTEN;
// Initialize WDT with the given parameters
WDT_Enable(WDT, value);
#endif
// Reset the watchdog
WDT_Restart(WDT);
#else
// Make sure to completely disable the Watchdog
WDT_Disable(WDT);
#endif
} }
// ------------------------
// Free Memory Accessor
// ------------------------
extern "C" { extern "C" {
extern unsigned int _ebss; // end of bss section extern unsigned int _ebss; // end of bss section
} }
@ -95,18 +181,9 @@ int freeMemory() {
} }
// ------------------------ // ------------------------
// ADC // Serial Ports
// ------------------------ // ------------------------
void HAL_adc_start_conversion(const uint8_t ch) {
HAL_adc_result = analogRead(ch);
}
uint16_t HAL_adc_get_result() {
// nop
return HAL_adc_result;
}
// Forward the default serial ports // Forward the default serial ports
#if USING_HW_SERIAL0 #if USING_HW_SERIAL0
DefaultSerial1 MSerial0(false, Serial); DefaultSerial1 MSerial0(false, Serial);

141
Marlin/src/HAL/DUE/HAL.h

@ -32,12 +32,15 @@
#include "../shared/math_32bit.h" #include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h" #include "../shared/HAL_SPI.h"
#include "fastio.h" #include "fastio.h"
#include "watchdog.h"
#include <stdint.h> #include <stdint.h>
#include "../../core/serial_hook.h" #include "../../core/serial_hook.h"
// ------------------------
// Serial ports
// ------------------------
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1; typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2; typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3; typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
@ -97,55 +100,38 @@ extern DefaultSerial4 MSerial3;
#include "MarlinSerial.h" #include "MarlinSerial.h"
#include "MarlinSerialUSB.h" #include "MarlinSerialUSB.h"
// On AVR this is in math.h? // ------------------------
#define square(x) ((x)*(x)) // Types
// ------------------------
typedef int8_t pin_t; typedef int8_t pin_t;
#define SHARED_SERVOS HAS_SERVOS #define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
#define HAL_SERVO_LIB Servo
class Servo;
typedef Servo hal_servo_t;
// //
// Interrupts // Interrupts
// //
#define CRITICAL_SECTION_START() uint32_t primask = __get_PRIMASK(); __disable_irq() #define sei() interrupts()
#define CRITICAL_SECTION_END() if (!primask) __enable_irq() #define cli() noInterrupts()
#define ISRS_ENABLED() (!__get_PRIMASK())
#define ENABLE_ISRS() __enable_irq()
#define DISABLE_ISRS() __disable_irq()
void cli(); // Disable interrupts
void sei(); // Enable interrupts
void HAL_clear_reset_source(); // clear reset reason #define CRITICAL_SECTION_START() const bool _irqon = hal.isr_state(); hal.isr_off()
uint8_t HAL_get_reset_source(); // get reset reason #define CRITICAL_SECTION_END() if (_irqon) hal.isr_on()
void HAL_reboot();
// //
// ADC // ADC
// //
extern uint16_t HAL_adc_result; // result of last ADC conversion #define HAL_ADC_VREF 3.3
#define HAL_ADC_RESOLUTION 10
#ifndef analogInputToDigitalPin #ifndef analogInputToDigitalPin
#define analogInputToDigitalPin(p) ((p < 12U) ? (p) + 54U : -1) #define analogInputToDigitalPin(p) ((p < 12U) ? (p) + 54U : -1)
#endif #endif
#define HAL_ANALOG_SELECT(ch)
inline void HAL_adc_init() {}//todo
#define HAL_ADC_VREF 3.3
#define HAL_ADC_RESOLUTION 10
#define HAL_START_ADC(ch) HAL_adc_start_conversion(ch)
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
void HAL_adc_start_conversion(const uint8_t ch);
uint16_t HAL_adc_get_result();
// //
// Pin Map // Pin Mapping for M42, M43, M226
// //
#define GET_PIN_MAP_PIN(index) index #define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin #define GET_PIN_MAP_INDEX(pin) pin
@ -154,30 +140,19 @@ uint16_t HAL_adc_get_result();
// //
// Tone // Tone
// //
void toneInit();
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0); void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
void noTone(const pin_t _pin); void noTone(const pin_t _pin);
// Enable hooks into idle and setup for HAL // ------------------------
#define HAL_IDLETASK 1 // Class Utilities
void HAL_idletask(); // ------------------------
void HAL_init();
//
// Utility functions
//
void _delay_ms(const int delay);
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000 #if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-function"
#endif #endif
int freeMemory(); #pragma GCC diagnostic pop
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -186,3 +161,73 @@ char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
// Return free RAM between end of heap (or end bss) and whatever is current
int freeMemory();
// ------------------------
// MarlinHAL Class
// ------------------------
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init(); // Called early in setup()
static void init_board(); // Called less early in setup()
static void reboot(); // Restart the firmware
// Interrupts
static bool isr_state() { return !__get_PRIMASK(); }
static void isr_on() { __enable_irq(); }
static void isr_off() { __disable_irq(); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask();
// Reset
static uint8_t get_reset_source();
static void clear_reset_source() {}
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
static uint16_t adc_result;
// Called by Temperature::init once at startup
static void adc_init() {}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t ch) {}
// Begin ADC sampling on the given channel. Called from Temperature::isr!
static void adc_start(const uint8_t ch) { adc_result = analogRead(ch); }
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value() { return adc_result; }
/**
* Set the PWM duty cycle for the pin to the given value.
* No inverting the duty cycle in this HAL.
* No changing the maximum size of the provided value to enable finer PWM duty control in this HAL.
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
analogWrite(pin, v);
}
};

20
Marlin/src/HAL/DUE/HAL_SPI.cpp

@ -31,8 +31,6 @@
/** /**
* HAL for Arduino Due and compatible (SAM3X8E) * HAL for Arduino Due and compatible (SAM3X8E)
*
* For ARDUINO_ARCH_SAM
*/ */
#ifdef ARDUINO_ARCH_SAM #ifdef ARDUINO_ARCH_SAM
@ -437,7 +435,7 @@
} while (--todo); } while (--todo);
} }
// Pointers to generic functions for block tranfers // Pointers to generic functions for block transfers
static pfnSpiTxBlock spiTxBlock = (pfnSpiTxBlock)spiTxBlockX; static pfnSpiTxBlock spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
static pfnSpiRxBlock spiRxBlock = (pfnSpiRxBlock)spiRxBlockX; static pfnSpiRxBlock spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
@ -594,18 +592,14 @@
SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS); SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
SPI_Enable(SPI0); SPI_Enable(SPI0);
SET_OUTPUT(DAC0_SYNC); SET_OUTPUT(DAC0_SYNC_PIN);
#if HAS_MULTI_EXTRUDER #if HAS_MULTI_EXTRUDER
SET_OUTPUT(DAC1_SYNC); OUT_WRITE(DAC1_SYNC_PIN, HIGH);
WRITE(DAC1_SYNC, HIGH);
#endif #endif
SET_OUTPUT(SPI_EEPROM1_CS); WRITE(DAC0_SYNC_PIN, HIGH);
SET_OUTPUT(SPI_EEPROM2_CS); OUT_WRITE(SPI_EEPROM1_CS_PIN, HIGH);
SET_OUTPUT(SPI_FLASH_CS); OUT_WRITE(SPI_EEPROM2_CS_PIN, HIGH);
WRITE(DAC0_SYNC, HIGH); OUT_WRITE(SPI_FLASH_CS_PIN, HIGH);
WRITE(SPI_EEPROM1_CS, HIGH);
WRITE(SPI_EEPROM2_CS, HIGH);
WRITE(SPI_FLASH_CS, HIGH);
WRITE(SD_SS_PIN, HIGH); WRITE(SD_SS_PIN, HIGH);
OUT_WRITE(SDSS, LOW); OUT_WRITE(SDSS, LOW);

7
Marlin/src/HAL/LINUX/watchdog.h → Marlin/src/HAL/DUE/MarlinSPI.h

@ -1,6 +1,6 @@
/** /**
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* *
* Based on Sprinter and grbl. * Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
@ -21,5 +21,6 @@
*/ */
#pragma once #pragma once
void watchdog_init(); #include <SPI.h>
void HAL_watchdog_refresh();
using MarlinSPI = SPIClass;

4
Marlin/src/HAL/DUE/MarlinSerial.cpp

@ -406,7 +406,7 @@ size_t MarlinSerial<Cfg>::write(const uint8_t c) {
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1); const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
// If global interrupts are disabled (as the result of being called from an ISR)... // If global interrupts are disabled (as the result of being called from an ISR)...
if (!ISRS_ENABLED()) { if (!hal.isr_state()) {
// Make room by polling if it is possible to transmit, and do so! // Make room by polling if it is possible to transmit, and do so!
while (i == tx_buffer.tail) { while (i == tx_buffer.tail) {
@ -454,7 +454,7 @@ void MarlinSerial<Cfg>::flushTX() {
if (!_written) return; if (!_written) return;
// If global interrupts are disabled (as the result of being called from an ISR)... // If global interrupts are disabled (as the result of being called from an ISR)...
if (!ISRS_ENABLED()) { if (!hal.isr_state()) {
// Wait until everything was transmitted - We must do polling, as interrupts are disabled // Wait until everything was transmitted - We must do polling, as interrupts are disabled
while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) { while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {

2
Marlin/src/HAL/DUE/MarlinSerial.h

@ -118,7 +118,7 @@ public:
static size_t write(const uint8_t c); static size_t write(const uint8_t c);
static void flushTX(); static void flushTX();
static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; } static 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 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 buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }

2
Marlin/src/HAL/DUE/MarlinSerialUSB.cpp

@ -41,7 +41,7 @@ extern "C" {
int udi_cdc_getc(); int udi_cdc_getc();
bool udi_cdc_is_tx_ready(); bool udi_cdc_is_tx_ready();
int udi_cdc_putc(int value); int udi_cdc_putc(int value);
}; }
// Pending character // Pending character
static int pending_char = -1; static int pending_char = -1;

2
Marlin/src/HAL/DUE/HAL_MinSerial.cpp → Marlin/src/HAL/DUE/MinSerial.cpp

@ -25,7 +25,7 @@
#if ENABLED(POSTMORTEM_DEBUGGING) #if ENABLED(POSTMORTEM_DEBUGGING)
#include "../shared/HAL_MinSerial.h" #include "../shared/MinSerial.h"
#include <stdarg.h> #include <stdarg.h>

138
Marlin/src/HAL/DUE/Servo.cpp

@ -47,12 +47,12 @@
#include "../shared/servo.h" #include "../shared/servo.h"
#include "../shared/servo_private.h" #include "../shared/servo_private.h"
static volatile int8_t Channel[_Nbr_16timers]; // counter for the servo being pulsed for each timer (or -1 if refresh interval) static Flags<_Nbr_16timers> DisablePending; // ISR should disable the timer at the next timer reset
// ------------------------ // ------------------------
/// Interrupt handler for the TC0 channel 1. /// Interrupt handler for the TC0 channel 1.
// ------------------------ // ------------------------
void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel); void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
#ifdef _useTimer1 #ifdef _useTimer1
void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); } void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
@ -70,88 +70,92 @@ void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); } void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
#endif #endif
void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) { void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) {
// clear interrupt static int8_t Channel[_Nbr_16timers]; // Servo counters to pulse (or -1 for refresh interval)
tc->TC_CHANNEL[channel].TC_SR; int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
if (Channel[timer] < 0) if (cho < 0) { // Channel -1 indicates the refresh interval completed...
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // ...so reset the timer
else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive) if (DisablePending[timer]) {
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated // Disabling only after the full servo period expires prevents
// pulses being too close together if immediately re-enabled.
Channel[timer]++; // increment to the next channel DisablePending.clear(timer);
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) { TC_Stop(tc, channel);
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks; tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
if (SERVO(timer,Channel[timer]).Pin.isActive) // check if activated return;
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high }
}
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
Channel[timer] = ++cho; // go to the next channel (or 0)
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer, cho).ticks;
if (SERVO(timer, cho).Pin.isActive) // activated?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
} }
else { else {
// finished all channels so wait for the refresh period to expire before starting over // finished all channels so wait for the refresh period to expire before starting over
tc->TC_CHANNEL[channel].TC_RA = const unsigned int cval = tc->TC_CHANNEL[channel].TC_CV + 128 / (SERVO_TIMER_PRESCALER), // allow 128 cycles to ensure the next CV not missed
tc->TC_CHANNEL[channel].TC_CV < usToTicks(REFRESH_INTERVAL) - 4 ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
? (unsigned int)usToTicks(REFRESH_INTERVAL) // allow a few ticks to ensure the next OCR1A not missed tc->TC_CHANNEL[channel].TC_RA = max(cval, ival);
: tc->TC_CHANNEL[channel].TC_CV + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel Channel[timer] = -1; // reset the timer CCR on the next call
} }
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
} }
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) { static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
pmc_enable_periph_clk(id); pmc_enable_periph_clk(id);
TC_Configure(tc, channel, TC_Configure(tc, channel,
TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32 TC_CMR_WAVE // Waveform mode
TC_CMR_WAVE | // Waveform mode | TC_CMR_WAVSEL_UP_RC // Counter running up and reset when equal to RC
TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC | (SERVO_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0) // MCK/2
| (SERVO_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0) // MCK/8
/* 84MHz, MCK/32, for 1.5ms: 3937 */ | (SERVO_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0) // MCK/32
TC_SetRA(tc, channel, 2625); // 1ms | (SERVO_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0) // MCK/128
);
/* Configure and enable interrupt */
// Wait 1ms before the first ISR
TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms
// Configure and enable interrupt
NVIC_EnableIRQ(irqn); NVIC_EnableIRQ(irqn);
// TC_IER_CPAS: RA Compare tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // TC_IER_CPAS: RA Compare
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS;
// Enables the timer clock and performs a software reset to start the counting // Enables the timer clock and performs a software reset to start the counting
TC_Start(tc, channel); TC_Start(tc, channel);
} }
void initISR(timer16_Sequence_t timer) { void initISR(const timer16_Sequence_t timer_index) {
#ifdef _useTimer1 CRITICAL_SECTION_START();
if (timer == _timer1) const bool disable_soon = DisablePending[timer_index];
_initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1); DisablePending.clear(timer_index);
#endif CRITICAL_SECTION_END();
#ifdef _useTimer2
if (timer == _timer2) if (!disable_soon) switch (timer_index) {
_initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2); default: break;
#endif #ifdef _useTimer1
#ifdef _useTimer3 case _timer1: return _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
if (timer == _timer3) #endif
_initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3); #ifdef _useTimer2
#endif case _timer2: return _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
#ifdef _useTimer4 #endif
if (timer == _timer4) #ifdef _useTimer3
_initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4); case _timer3: return _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
#endif #endif
#ifdef _useTimer5 #ifdef _useTimer4
if (timer == _timer5) case _timer4: return _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
_initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5); #endif
#endif #ifdef _useTimer5
case _timer5: return _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
#endif
}
} }
void finISR(timer16_Sequence_t) { void finISR(const timer16_Sequence_t timer_index) {
#ifdef _useTimer1 // Timer is disabled from the ISR, to ensure proper final pulse length.
TC_Stop(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); DisablePending.set(timer_index);
#endif
#ifdef _useTimer2
TC_Stop(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
#endif
#ifdef _useTimer3
TC_Stop(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
#endif
#ifdef _useTimer4
TC_Stop(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
#endif
#ifdef _useTimer5
TC_Stop(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
#endif
} }
#endif // HAS_SERVOS #endif // HAS_SERVOS

2
Marlin/src/HAL/DUE/ServoTimers.h

@ -37,7 +37,7 @@
#define _useTimer5 #define _useTimer5
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays #define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
#define SERVO_TIMER_PRESCALER 32 // timer prescaler #define SERVO_TIMER_PRESCALER 2 // timer prescaler
/* /*
TC0, chan 0 => TC0_Handler TC0, chan 0 => TC0_Handler

8
Marlin/src/HAL/DUE/Tone.cpp

@ -35,20 +35,20 @@
static pin_t tone_pin; static pin_t tone_pin;
volatile static int32_t toggles; volatile static int32_t toggles;
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) { void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration/*=0*/) {
tone_pin = _pin; tone_pin = _pin;
toggles = 2 * frequency * duration / 1000; toggles = 2 * frequency * duration / 1000;
HAL_timer_start(TONE_TIMER_NUM, 2 * frequency); HAL_timer_start(MF_TIMER_TONE, 2 * frequency);
} }
void noTone(const pin_t _pin) { void noTone(const pin_t _pin) {
HAL_timer_disable_interrupt(TONE_TIMER_NUM); HAL_timer_disable_interrupt(MF_TIMER_TONE);
extDigitalWrite(_pin, LOW); extDigitalWrite(_pin, LOW);
} }
HAL_TONE_TIMER_ISR() { HAL_TONE_TIMER_ISR() {
static uint8_t pin_state = 0; static uint8_t pin_state = 0;
HAL_timer_isr_prologue(TONE_TIMER_NUM); HAL_timer_isr_prologue(MF_TIMER_TONE);
if (toggles) { if (toggles) {
toggles--; toggles--;

1
Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp

@ -20,7 +20,6 @@
* *
*/ */
/** /**
* Based on u8g_com_msp430_hw_spi.c * Based on u8g_com_msp430_hw_spi.c
* *

4
Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp

@ -57,7 +57,7 @@
#include "../../../inc/MarlinConfigPre.h" #include "../../../inc/MarlinConfigPre.h"
#if ENABLED(U8GLIB_ST7920) #if IS_U8GLIB_ST7920
#include "../../../inc/MarlinConfig.h" #include "../../../inc/MarlinConfig.h"
#include "../../shared/Delay.h" #include "../../shared/Delay.h"
@ -182,5 +182,5 @@ uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
} }
#endif // LIGHTWEIGHT_UI #endif // LIGHTWEIGHT_UI
#endif // U8GLIB_ST7920 #endif // IS_U8GLIB_ST7920
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_SAM

4
Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp

@ -57,7 +57,7 @@
#include "../../../inc/MarlinConfigPre.h" #include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920) #if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
#include "u8g_com_HAL_DUE_sw_spi_shared.h" #include "u8g_com_HAL_DUE_sw_spi_shared.h"
@ -141,5 +141,5 @@ uint8_t u8g_com_HAL_DUE_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
return 1; return 1;
} }
#endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920 #endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_SAM

46
Marlin/src/HAL/DUE/eeprom_flash.cpp

@ -199,10 +199,9 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
for (i = 0; i <PageSize >> 2; i++) for (i = 0; i <PageSize >> 2; i++)
pageContents[i] = (((uint32_t*)data)[i]) | (~(pageContents[i] ^ ((uint32_t*)data)[i])); pageContents[i] = (((uint32_t*)data)[i]) | (~(pageContents[i] ^ ((uint32_t*)data)[i]));
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM PageWrite ", page);
DEBUG_ECHOLNPAIR("EEPROM PageWrite ", page); DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash);
DEBUG_ECHOLNPAIR(" in FLASH address ", (uint32_t)addrflash); DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0));
DEBUG_ECHOLNPAIR(" base address ", (uint32_t)getFlashStorage(0));
DEBUG_FLUSH(); DEBUG_FLUSH();
// Get the page relative to the start of the EFC controller, and the EFC controller to use // Get the page relative to the start of the EFC controller, and the EFC controller to use
@ -245,8 +244,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
// Reenable interrupts // Reenable interrupts
__enable_irq(); __enable_irq();
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Unlock failure for page ", page);
DEBUG_ECHOLNPAIR("EEPROM Unlock failure for page ", page);
return false; return false;
} }
@ -270,8 +268,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
// Reenable interrupts // Reenable interrupts
__enable_irq(); __enable_irq();
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Write failure for page ", page);
DEBUG_ECHOLNPAIR("EEPROM Write failure for page ", page);
return false; return false;
} }
@ -286,8 +283,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
if (memcmp(getFlashStorage(page),data,PageSize)) { if (memcmp(getFlashStorage(page),data,PageSize)) {
#ifdef EE_EMU_DEBUG #ifdef EE_EMU_DEBUG
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Verify Write failure for page ", page);
DEBUG_ECHOLNPAIR("EEPROM Verify Write failure for page ", page);
ee_Dump( page, (uint32_t *)addrflash); ee_Dump( page, (uint32_t *)addrflash);
ee_Dump(-page, data); ee_Dump(-page, data);
@ -306,7 +302,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
} }
} }
} }
DEBUG_ECHOLNPAIR("--> Differing bits: ", count); DEBUG_ECHOLNPGM("--> Differing bits: ", count);
#endif #endif
return false; return false;
@ -325,10 +321,9 @@ static bool ee_PageErase(uint16_t page) {
uint16_t i; uint16_t i;
uint32_t addrflash = uint32_t(getFlashStorage(page)); uint32_t addrflash = uint32_t(getFlashStorage(page));
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM PageErase ", page);
DEBUG_ECHOLNPAIR("EEPROM PageErase ", page); DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash);
DEBUG_ECHOLNPAIR(" in FLASH address ", (uint32_t)addrflash); DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0));
DEBUG_ECHOLNPAIR(" base address ", (uint32_t)getFlashStorage(0));
DEBUG_FLUSH(); DEBUG_FLUSH();
// Get the page relative to the start of the EFC controller, and the EFC controller to use // Get the page relative to the start of the EFC controller, and the EFC controller to use
@ -370,8 +365,7 @@ static bool ee_PageErase(uint16_t page) {
// Reenable interrupts // Reenable interrupts
__enable_irq(); __enable_irq();
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Unlock failure for page ",page);
DEBUG_ECHOLNPAIR("EEPROM Unlock failure for page ",page);
return false; return false;
} }
@ -394,8 +388,7 @@ static bool ee_PageErase(uint16_t page) {
// Reenable interrupts // Reenable interrupts
__enable_irq(); __enable_irq();
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Erase failure for page ",page);
DEBUG_ECHOLNPAIR("EEPROM Erase failure for page ",page);
return false; return false;
} }
@ -410,8 +403,7 @@ static bool ee_PageErase(uint16_t page) {
uint32_t * aligned_src = (uint32_t *) addrflash; uint32_t * aligned_src = (uint32_t *) addrflash;
for (i = 0; i < PageSize >> 2; i++) { for (i = 0; i < PageSize >> 2; i++) {
if (*aligned_src++ != 0xFFFFFFFF) { if (*aligned_src++ != 0xFFFFFFFF) {
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Verify Erase failure for page ",page);
DEBUG_ECHOLNPAIR("EEPROM Verify Erase failure for page ",page);
ee_Dump(page, (uint32_t *)addrflash); ee_Dump(page, (uint32_t *)addrflash);
return false; return false;
} }
@ -921,8 +913,7 @@ static void ee_Init() {
// If all groups seem to be used, default to first group // If all groups seem to be used, default to first group
if (curGroup >= GroupCount) curGroup = 0; if (curGroup >= GroupCount) curGroup = 0;
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Current Group: ",curGroup);
DEBUG_ECHOLNPAIR("EEPROM Current Group: ",curGroup);
DEBUG_FLUSH(); DEBUG_FLUSH();
// Now, validate that all the other group pages are empty // Now, validate that all the other group pages are empty
@ -931,8 +922,7 @@ static void ee_Init() {
for (int page = 0; page < PagesPerGroup; page++) { for (int page = 0; page < PagesPerGroup; page++) {
if (!ee_IsPageClean(grp * PagesPerGroup + page)) { if (!ee_IsPageClean(grp * PagesPerGroup + page)) {
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on group ", grp);
DEBUG_ECHOLNPAIR("EEPROM Page ", page, " not clean on group ", grp);
DEBUG_FLUSH(); DEBUG_FLUSH();
ee_PageErase(grp * PagesPerGroup + page); ee_PageErase(grp * PagesPerGroup + page);
} }
@ -948,15 +938,13 @@ static void ee_Init() {
} }
} }
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Active page: ", curPage);
DEBUG_ECHOLNPAIR("EEPROM Active page: ", curPage);
DEBUG_FLUSH(); DEBUG_FLUSH();
// Make sure the pages following the first clean one are also clean // Make sure the pages following the first clean one are also clean
for (int page = curPage + 1; page < PagesPerGroup; page++) { for (int page = curPage + 1; page < PagesPerGroup; page++) {
if (!ee_IsPageClean(curGroup * PagesPerGroup + page)) { if (!ee_IsPageClean(curGroup * PagesPerGroup + page)) {
DEBUG_ECHO_START(); DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on active group ", curGroup);
DEBUG_ECHOLNPAIR("EEPROM Page ", page, " not clean on active group ", curGroup);
DEBUG_FLUSH(); DEBUG_FLUSH();
ee_Dump(curGroup * PagesPerGroup + page, getFlashStorage(curGroup * PagesPerGroup + page)); ee_Dump(curGroup * PagesPerGroup + page, getFlashStorage(curGroup * PagesPerGroup + page));
ee_PageErase(curGroup * PagesPerGroup + page); ee_PageErase(curGroup * PagesPerGroup + page);

6
Marlin/src/HAL/DUE/endstop_interrupts.h

@ -70,4 +70,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN));
TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN));
TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN));
TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN));
TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN));
TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN));
} }

2
Marlin/src/HAL/DUE/fastio/G2_PWM.cpp

@ -25,7 +25,7 @@
* is NOT used to directly toggle pins. The ISR writes to the pin assigned to * is NOT used to directly toggle pins. The ISR writes to the pin assigned to
* that interrupt. * that interrupt.
* *
* All PWMs use the same repetition rate. The G2 needs about 10KHz min in order to * All PWMs use the same repetition rate. The G2 needs about 10kHz min in order to
* not have obvious ripple on the Vref signals. * not have obvious ripple on the Vref signals.
* *
* The data structures are setup to minimize the computation done by the ISR which * The data structures are setup to minimize the computation done by the ISR which

28
Marlin/src/HAL/DUE/inc/SanityCheck.h

@ -25,6 +25,30 @@
* Test Arduino Due specific configuration values for errors at compile-time. * Test Arduino Due specific configuration values for errors at compile-time.
*/ */
/**
* Check for common serial pin conflicts
*/
#define CHECK_SERIAL_PIN(N) ( \
X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \
|| X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \
|| X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \
|| X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \
|| X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \
|| X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \
)
#if CONF_SERIAL_IS(0) // D0-D1. No known conflicts.
#endif
#if CONF_SERIAL_IS(1) && (CHECK_SERIAL_PIN(18) || CHECK_SERIAL_PIN(19))
#error "Serial Port 1 pin D18 and/or D19 conflicts with another pin on the board."
#endif
#if CONF_SERIAL_IS(2) && (CHECK_SERIAL_PIN(16) || CHECK_SERIAL_PIN(17))
#error "Serial Port 2 pin D16 and/or D17 conflicts with another pin on the board."
#endif
#if CONF_SERIAL_IS(3) && (CHECK_SERIAL_PIN(14) || CHECK_SERIAL_PIN(15))
#error "Serial Port 3 pin D14 and/or D15 conflicts with another pin on the board."
#endif
#undef CHECK_SERIAL_PIN
/** /**
* HARDWARE VS. SOFTWARE SPI COMPATIBILITY * HARDWARE VS. SOFTWARE SPI COMPATIBILITY
* *
@ -59,3 +83,7 @@
#if HAS_TMC_SW_SERIAL #if HAS_TMC_SW_SERIAL
#error "TMC220x Software Serial is not supported on the DUE platform." #error "TMC220x Software Serial is not supported on the DUE platform."
#endif #endif
#if USING_PULLDOWNS
#error "PULLDOWN pin mode is not available on DUE boards."
#endif

11
Marlin/src/HAL/DUE/pinsDebug.h

@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
@ -50,7 +53,7 @@
* The net result is that both the g_pinStatus[pin] array and the PIO_OSR register * The net result is that both the g_pinStatus[pin] array and the PIO_OSR register
* needs to be looked at when determining if a pin is an input or an output. * needs to be looked at when determining if a pin is an input or an output.
* *
* b) Due has only pins 6, 7, 8 & 9 enabled for PWMs. FYI - they run at 1KHz * b) Due has only pins 6, 7, 8 & 9 enabled for PWMs. FYI - they run at 1kHz
* *
* c) NUM_DIGITAL_PINS does not include the analog pins * c) NUM_DIGITAL_PINS does not include the analog pins
* *
@ -64,9 +67,10 @@
#define PRINT_PORT(p) #define 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 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("%02d"), p); SERIAL_ECHO(buffer); }while(0) #define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%02d"), p); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#define GET_ARRAY_PIN(p) pin_array[p].pin #define GET_ARRAY_PIN(p) pin_array[p].pin
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital #define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL ? 1 : 0) #define VALID_PIN(pin) (pin >= 0 && pin < int8_t(NUMBER_PINS_TOTAL))
#define DIGITAL_PIN_TO_ANALOG_PIN(p) int(p - analogInputToDigitalPin(0)) #define DIGITAL_PIN_TO_ANALOG_PIN(p) int(p - analogInputToDigitalPin(0))
#define IS_ANALOG(P) WITHIN(P, char(analogInputToDigitalPin(0)), char(analogInputToDigitalPin(NUM_ANALOG_INPUTS - 1))) #define IS_ANALOG(P) WITHIN(P, char(analogInputToDigitalPin(0)), char(analogInputToDigitalPin(NUM_ANALOG_INPUTS - 1)))
#define pwm_status(pin) (((g_pinStatus[pin] & 0xF) == PIN_STATUS_PWM) && \ #define pwm_status(pin) (((g_pinStatus[pin] & 0xF) == PIN_STATUS_PWM) && \
@ -82,11 +86,10 @@ bool GET_PINMODE(int8_t pin) { // 1: output, 0: input
|| pwm_status(pin)); || pwm_status(pin));
} }
void pwm_details(int32_t pin) { void pwm_details(int32_t pin) {
if (pwm_status(pin)) { if (pwm_status(pin)) {
uint32_t chan = g_APinDescription[pin].ulPWMChannel; uint32_t chan = g_APinDescription[pin].ulPWMChannel;
SERIAL_ECHOPAIR("PWM = ", PWM_INTERFACE->PWM_CH_NUM[chan].PWM_CDTY); SERIAL_ECHOPGM("PWM = ", PWM_INTERFACE->PWM_CH_NUM[chan].PWM_CDTY);
} }
} }

27
Marlin/src/HAL/DUE/timers.cpp

@ -42,7 +42,7 @@
// Private Variables // Private Variables
// ------------------------ // ------------------------
const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = { const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
{ TC0, 0, TC0_IRQn, 3}, // 0 - [servo timer5] { TC0, 0, TC0_IRQn, 3}, // 0 - [servo timer5]
{ TC0, 1, TC1_IRQn, 0}, // 1 { TC0, 1, TC1_IRQn, 0}, // 1
{ TC0, 2, TC2_IRQn, 2}, // 2 - stepper { TC0, 2, TC2_IRQn, 2}, // 2 - stepper
@ -66,9 +66,9 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
*/ */
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
Tc *tc = TimerConfig[timer_num].pTimerRegs; Tc *tc = timer_config[timer_num].pTimerRegs;
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; IRQn_Type irq = timer_config[timer_num].IRQ_Id;
uint32_t channel = TimerConfig[timer_num].channel; uint32_t channel = timer_config[timer_num].channel;
// Disable interrupt, just in case it was already enabled // Disable interrupt, just in case it was already enabled
NVIC_DisableIRQ(irq); NVIC_DisableIRQ(irq);
@ -86,13 +86,20 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
pmc_set_writeprotect(false); pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq); pmc_enable_periph_clk((uint32_t)irq);
NVIC_SetPriority(irq, TimerConfig [timer_num].priority); NVIC_SetPriority(irq, timer_config[timer_num].priority);
// wave mode, reset counter on match with RC, // wave mode, reset counter on match with RC,
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); TC_Configure(tc, channel,
TC_CMR_WAVE
| TC_CMR_WAVSEL_UP_RC
| (HAL_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0)
| (HAL_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0)
| (HAL_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0)
| (HAL_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0)
);
// Set compare value // Set compare value
TC_SetRC(tc, channel, VARIANT_MCK / 2 / frequency); TC_SetRC(tc, channel, VARIANT_MCK / (HAL_TIMER_PRESCALER) / frequency);
// And start timer // And start timer
TC_Start(tc, channel); TC_Start(tc, channel);
@ -105,12 +112,12 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
} }
void HAL_timer_enable_interrupt(const uint8_t timer_num) { void HAL_timer_enable_interrupt(const uint8_t timer_num) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; IRQn_Type irq = timer_config[timer_num].IRQ_Id;
NVIC_EnableIRQ(irq); NVIC_EnableIRQ(irq);
} }
void HAL_timer_disable_interrupt(const uint8_t timer_num) { void HAL_timer_disable_interrupt(const uint8_t timer_num) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; IRQn_Type irq = timer_config[timer_num].IRQ_Id;
NVIC_DisableIRQ(irq); NVIC_DisableIRQ(irq);
// We NEED memory barriers to ensure Interrupts are actually disabled! // We NEED memory barriers to ensure Interrupts are actually disabled!
@ -125,7 +132,7 @@ static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
} }
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id; IRQn_Type irq = timer_config[timer_num].IRQ_Id;
return NVIC_GetEnabledIRQ(irq); return NVIC_GetEnabledIRQ(irq);
} }

53
Marlin/src/HAL/DUE/timers.h

@ -35,37 +35,38 @@
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF #define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals #define HAL_TIMER_PRESCALER 2
#define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals
#ifndef STEP_TIMER_NUM #ifndef MF_TIMER_STEP
#define STEP_TIMER_NUM 2 // Timer Index for Stepper #define MF_TIMER_STEP 2 // Timer Index for Stepper
#endif #endif
#ifndef PULSE_TIMER_NUM #ifndef MF_TIMER_PULSE
#define PULSE_TIMER_NUM STEP_TIMER_NUM #define MF_TIMER_PULSE MF_TIMER_STEP
#endif #endif
#ifndef TEMP_TIMER_NUM #ifndef MF_TIMER_TEMP
#define TEMP_TIMER_NUM 4 // Timer Index for Temperature #define MF_TIMER_TEMP 4 // Timer Index for Temperature
#endif #endif
#ifndef TONE_TIMER_NUM #ifndef MF_TIMER_TONE
#define TONE_TIMER_NUM 6 // index of timer to use for beeper tones #define MF_TIMER_TONE 6 // index of timer to use for beeper tones
#endif #endif
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency #define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) #define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) #define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) #define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) #define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_STEP_TIMER_ISR #ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() void TC2_Handler() #define HAL_STEP_TIMER_ISR() void TC2_Handler()
@ -92,7 +93,7 @@ typedef struct {
// Public Variables // Public Variables
// ------------------------ // ------------------------
extern const tTimerConfig TimerConfig[]; extern const tTimerConfig timer_config[];
// ------------------------ // ------------------------
// Public functions // Public functions
@ -101,17 +102,17 @@ extern const tTimerConfig TimerConfig[];
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency); void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) { FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
const tTimerConfig * const pConfig = &TimerConfig[timer_num]; const tTimerConfig * const pConfig = &timer_config[timer_num];
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC = compare; pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC = compare;
} }
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
const tTimerConfig * const pConfig = &TimerConfig[timer_num]; const tTimerConfig * const pConfig = &timer_config[timer_num];
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC; return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC;
} }
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
const tTimerConfig * const pConfig = &TimerConfig[timer_num]; const tTimerConfig * const pConfig = &timer_config[timer_num];
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV; return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV;
} }
@ -120,9 +121,9 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) { FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
const tTimerConfig * const pConfig = &TimerConfig[timer_num]; const tTimerConfig * const pConfig = &timer_config[timer_num];
// Reading the status register clears the interrupt flag // Reading the status register clears the interrupt flag
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR; pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR;
} }
#define HAL_timer_isr_epilogue(TIMER_NUM) #define HAL_timer_isr_epilogue(T) NOOP

19
Marlin/src/HAL/DUE/upload_extra_script.py

@ -4,15 +4,16 @@
# Windows: bossac.exe # Windows: bossac.exe
# Other: leave unchanged # Other: leave unchanged
# #
import pioutil
if pioutil.is_pio_build():
import platform
current_OS = platform.system()
import platform if current_OS == 'Windows':
current_OS = platform.system()
if current_OS == 'Windows': Import("env")
Import("env") # Use bossac.exe on Windows
env.Replace(
# Use bossac.exe on Windows UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
env.Replace( )
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
)

2
Marlin/src/HAL/DUE/usb/arduino_due_x.h

@ -71,7 +71,7 @@
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/** /**
* \page arduino_due_x_board_info "Arduino Due/X - Board informations" * \page arduino_due_x_board_info "Arduino Due/X - Board information"
* This page lists several definition related to the board description. * This page lists several definition related to the board description.
* *
*/ */

2
Marlin/src/HAL/DUE/usb/compiler.h

@ -1059,7 +1059,7 @@ static inline void convert_64_bit_to_byte_array(uint64_t value, uint8_t *data)
while (val_index < 8) while (val_index < 8)
{ {
data[val_index++] = value & 0xFF; data[val_index++] = value & 0xFF;
value = value >> 8; value >>= 8;
} }
} }

2
Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp

@ -10,7 +10,7 @@
#include "../../../sd/cardreader.h" #include "../../../sd/cardreader.h"
extern "C" { extern "C" {
#include "sd_mmc_spi_mem.h" #include "sd_mmc_spi_mem.h"
} }
#define SD_MMC_BLOCK_SIZE 512 #define SD_MMC_BLOCK_SIZE 512

4
Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.h

@ -74,7 +74,7 @@
#define SD_MMC_REMOVING 2 #define SD_MMC_REMOVING 2
//---- CONTROL FONCTIONS ---- //---- CONTROL FUNCTIONS ----
//! //!
//! @brief This function initializes the hw/sw resources required to drive the SD_MMC_SPI. //! @brief This function initializes the hw/sw resources required to drive the SD_MMC_SPI.
//!/ //!/
@ -134,7 +134,7 @@ extern bool sd_mmc_spi_wr_protect(void);
extern bool sd_mmc_spi_removal(void); extern bool sd_mmc_spi_removal(void);
//---- ACCESS DATA FONCTIONS ---- //---- ACCESS DATA FUNCTIONS ----
#if ACCESS_USB == true #if ACCESS_USB == true
// Standard functions for open in read/write mode the device // Standard functions for open in read/write mode the device

8
Marlin/src/HAL/DUE/usb/udd.h

@ -90,7 +90,7 @@ typedef struct {
//! This buffer must be word align for DATA IN phase (use prefix COMPILER_WORD_ALIGNED for buffer) //! This buffer must be word align for DATA IN phase (use prefix COMPILER_WORD_ALIGNED for buffer)
uint8_t *payload; uint8_t *payload;
//! Size of buffer to send or fill, and content the number of byte transfered //! Size of buffer to send or fill, and content the number of byte transferred
uint16_t payload_size; uint16_t payload_size;
//! Callback called after reception of ZLP from setup request //! Callback called after reception of ZLP from setup request
@ -132,10 +132,10 @@ typedef void (*udd_callback_halt_cleared_t)(void);
* *
* \param status UDD_EP_TRANSFER_OK, if transfer is complete * \param status UDD_EP_TRANSFER_OK, if transfer is complete
* \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted * \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
* \param n number of data transfered * \param n number of data transferred
*/ */
typedef void (*udd_callback_trans_t) (udd_ep_status_t status, typedef void (*udd_callback_trans_t) (udd_ep_status_t status,
iram_size_t nb_transfered, udd_ep_id_t ep); iram_size_t nb_transferred, udd_ep_id_t ep);
/** /**
* \brief Authorizes the VBUS event * \brief Authorizes the VBUS event
@ -303,7 +303,7 @@ bool udd_ep_wait_stall_clear(udd_ep_id_t ep,
* The driver uses a specific DMA USB to transfer data * The driver uses a specific DMA USB to transfer data
* from internal RAM to endpoint, if this one is available. * from internal RAM to endpoint, if this one is available.
* When the transfer is finished or aborted (stall, reset, ...), the \a callback is called. * When the transfer is finished or aborted (stall, reset, ...), the \a callback is called.
* The \a callback returns the transfer status and eventually the number of byte transfered. * The \a callback returns the transfer status and eventually the number of byte transferred.
* Note: The control endpoint is not authorized. * Note: The control endpoint is not authorized.
* *
* \param ep The ID of the endpoint to use * \param ep The ID of the endpoint to use

4
Marlin/src/HAL/DUE/usb/udi_cdc.c

@ -162,7 +162,7 @@ static void udi_cdc_ctrl_state_notify(uint8_t port, udd_ep_id_t ep);
* *
* \param status UDD_EP_TRANSFER_OK, if transfer finished * \param status UDD_EP_TRANSFER_OK, if transfer finished
* \param status UDD_EP_TRANSFER_ABORT, if transfer aborted * \param status UDD_EP_TRANSFER_ABORT, if transfer aborted
* \param n number of data transfered * \param n number of data transferred
*/ */
static void udi_cdc_serial_state_msg_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep); static void udi_cdc_serial_state_msg_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep);
@ -200,7 +200,7 @@ static void udi_cdc_data_received(udd_ep_status_t status, iram_size_t n, udd_ep_
* *
* \param status UDD_EP_TRANSFER_OK, if transfer finished * \param status UDD_EP_TRANSFER_OK, if transfer finished
* \param status UDD_EP_TRANSFER_ABORT, if transfer aborted * \param status UDD_EP_TRANSFER_ABORT, if transfer aborted
* \param n number of data transfered * \param n number of data transferred
*/ */
static void udi_cdc_data_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep); static void udi_cdc_data_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep);

2
Marlin/src/HAL/DUE/usb/udi_cdc_conf.h

@ -106,7 +106,7 @@ extern "C" {
*/ */
//@{ //@{
# if UDI_CDC_PORT_NB > 2 # if UDI_CDC_PORT_NB > 2
# error USBB, UDP, UDPHS and UOTGHS interfaces have not enought endpoints. # error USBB, UDP, UDPHS and UOTGHS interfaces have not enough endpoints.
# endif # endif
#define UDI_CDC_DATA_EP_IN_0 (1 | USB_EP_DIR_IN) // TX #define UDI_CDC_DATA_EP_IN_0 (1 | USB_EP_DIR_IN) // TX
#define UDI_CDC_DATA_EP_OUT_0 (2 | USB_EP_DIR_OUT) // RX #define UDI_CDC_DATA_EP_OUT_0 (2 | USB_EP_DIR_OUT) // RX

10
Marlin/src/HAL/DUE/usb/udi_msc.c

@ -173,7 +173,7 @@ static void udi_msc_cbw_wait(void);
* *
* \param status UDD_EP_TRANSFER_OK, if transfer is finished * \param status UDD_EP_TRANSFER_OK, if transfer is finished
* \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted * \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
* \param nb_received number of data transfered * \param nb_received number of data transferred
*/ */
static void udi_msc_cbw_received(udd_ep_status_t status, static void udi_msc_cbw_received(udd_ep_status_t status,
iram_size_t nb_received, udd_ep_id_t ep); iram_size_t nb_received, udd_ep_id_t ep);
@ -211,7 +211,7 @@ static void udi_msc_data_send(uint8_t * buffer, uint8_t buf_size);
* *
* \param status UDD_EP_TRANSFER_OK, if transfer finish * \param status UDD_EP_TRANSFER_OK, if transfer finish
* \param status UDD_EP_TRANSFER_ABORT, if transfer aborted * \param status UDD_EP_TRANSFER_ABORT, if transfer aborted
* \param nb_sent number of data transfered * \param nb_sent number of data transferred
*/ */
static void udi_msc_data_sent(udd_ep_status_t status, iram_size_t nb_sent, static void udi_msc_data_sent(udd_ep_status_t status, iram_size_t nb_sent,
udd_ep_id_t ep); udd_ep_id_t ep);
@ -244,7 +244,7 @@ void udi_msc_csw_send(void);
* *
* \param status UDD_EP_TRANSFER_OK, if transfer is finished * \param status UDD_EP_TRANSFER_OK, if transfer is finished
* \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted * \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
* \param nb_sent number of data transfered * \param nb_sent number of data transferred
*/ */
static void udi_msc_csw_sent(udd_ep_status_t status, iram_size_t nb_sent, static void udi_msc_csw_sent(udd_ep_status_t status, iram_size_t nb_sent,
udd_ep_id_t ep); udd_ep_id_t ep);
@ -463,7 +463,7 @@ uint8_t udi_msc_getsetting(void)
static void udi_msc_cbw_invalid(void) static void udi_msc_cbw_invalid(void)
{ {
if (!udi_msc_b_cbw_invalid) if (!udi_msc_b_cbw_invalid)
return; // Don't re-stall endpoint if error reseted by setup return; // Don't re-stall endpoint if error reset by setup
udd_ep_set_halt(UDI_MSC_EP_OUT); udd_ep_set_halt(UDI_MSC_EP_OUT);
// If stall cleared then re-stall it. Only Setup MSC Reset can clear it // If stall cleared then re-stall it. Only Setup MSC Reset can clear it
udd_ep_wait_stall_clear(UDI_MSC_EP_OUT, udi_msc_cbw_invalid); udd_ep_wait_stall_clear(UDI_MSC_EP_OUT, udi_msc_cbw_invalid);
@ -472,7 +472,7 @@ static void udi_msc_cbw_invalid(void)
static void udi_msc_csw_invalid(void) static void udi_msc_csw_invalid(void)
{ {
if (!udi_msc_b_cbw_invalid) if (!udi_msc_b_cbw_invalid)
return; // Don't re-stall endpoint if error reseted by setup return; // Don't re-stall endpoint if error reset by setup
udd_ep_set_halt(UDI_MSC_EP_IN); udd_ep_set_halt(UDI_MSC_EP_IN);
// If stall cleared then re-stall it. Only Setup MSC Reset can clear it // If stall cleared then re-stall it. Only Setup MSC Reset can clear it
udd_ep_wait_stall_clear(UDI_MSC_EP_IN, udi_msc_csw_invalid); udd_ep_wait_stall_clear(UDI_MSC_EP_IN, udi_msc_csw_invalid);

46
Marlin/src/HAL/DUE/usb/uotghs_device_due.c

@ -325,7 +325,7 @@ static void udd_sleep_mode(bool b_idle)
/** /**
* \name Control endpoint low level management routine. * \name Control endpoint low level management routine.
* *
* This function performs control endpoint mangement. * This function performs control endpoint management.
* It handle the SETUP/DATA/HANDSHAKE phases of a control transaction. * It handle the SETUP/DATA/HANDSHAKE phases of a control transaction.
*/ */
//@{ //@{
@ -397,9 +397,9 @@ static void udd_ctrl_endofrequest(void);
/** /**
* \brief Main interrupt routine for control endpoint * \brief Main interrupt routine for control endpoint
* *
* This switchs control endpoint events to correct sub function. * This switches control endpoint events to correct sub function.
* *
* \return \c 1 if an event about control endpoint is occured, otherwise \c 0. * \return \c 1 if an event about control endpoint is occurred, otherwise \c 0.
*/ */
static bool udd_ctrl_interrupt(void); static bool udd_ctrl_interrupt(void);
@ -410,7 +410,7 @@ static bool udd_ctrl_interrupt(void);
* \name Management of bulk/interrupt/isochronous endpoints * \name Management of bulk/interrupt/isochronous endpoints
* *
* The UDD manages the data transfer on endpoints: * The UDD manages the data transfer on endpoints:
* - Start data tranfer on endpoint with USB Device DMA * - Start data transfer on endpoint with USB Device DMA
* - Send a ZLP packet if requested * - Send a ZLP packet if requested
* - Call callback registered to signal end of transfer * - Call callback registered to signal end of transfer
* The transfer abort and stall feature are supported. * The transfer abort and stall feature are supported.
@ -431,7 +431,7 @@ typedef struct {
uint8_t *buf; uint8_t *buf;
//! Size of buffer to send or fill //! Size of buffer to send or fill
iram_size_t buf_size; iram_size_t buf_size;
//!< Size of data transfered //!< Size of data transferred
iram_size_t buf_cnt; iram_size_t buf_cnt;
//!< Size of data loaded (or prepared for DMA) last time //!< Size of data loaded (or prepared for DMA) last time
iram_size_t buf_load; iram_size_t buf_load;
@ -486,7 +486,7 @@ static void udd_ep_finish_job(udd_ep_job_t * ptr_job, bool b_abort, uint8_t ep_n
#ifdef UDD_EP_DMA_SUPPORTED #ifdef UDD_EP_DMA_SUPPORTED
/** /**
* \brief Start the next transfer if necessary or complet the job associated. * \brief Start the next transfer if necessary or complete the job associated.
* *
* \param ep endpoint number without direction flag * \param ep endpoint number without direction flag
*/ */
@ -496,9 +496,9 @@ static void udd_ep_finish_job(udd_ep_job_t * ptr_job, bool b_abort, uint8_t ep_n
/** /**
* \brief Main interrupt routine for bulk/interrupt/isochronous endpoints * \brief Main interrupt routine for bulk/interrupt/isochronous endpoints
* *
* This switchs endpoint events to correct sub function. * This switches endpoint events to correct sub function.
* *
* \return \c 1 if an event about bulk/interrupt/isochronous endpoints has occured, otherwise \c 0. * \return \c 1 if an event about bulk/interrupt/isochronous endpoints has occurred, otherwise \c 0.
*/ */
static bool udd_ep_interrupt(void); static bool udd_ep_interrupt(void);
@ -520,7 +520,7 @@ static bool udd_ep_interrupt(void);
* *
* Note: * Note:
* Here, the global interrupt mask is not clear when an USB interrupt is enabled * Here, the global interrupt mask is not clear when an USB interrupt is enabled
* because this one can not be occured during the USB ISR (=during INTX is masked). * because this one can not be occurred during the USB ISR (=during INTX is masked).
* See Technical reference $3.8.3 Masking interrupt requests in peripheral modules. * See Technical reference $3.8.3 Masking interrupt requests in peripheral modules.
*/ */
#ifdef UHD_ENABLE #ifdef UHD_ENABLE
@ -787,7 +787,7 @@ void udd_attach(void)
udd_sleep_mode(true); udd_sleep_mode(true);
otg_unfreeze_clock(); otg_unfreeze_clock();
// This section of clock check can be improved with a chek of // This section of clock check can be improved with a check of
// USB clock source via sysclk() // USB clock source via sysclk()
// Check USB clock because the source can be a PLL // Check USB clock because the source can be a PLL
while (!Is_otg_clock_usable()); while (!Is_otg_clock_usable());
@ -803,7 +803,7 @@ void udd_attach(void)
#ifdef USB_DEVICE_HS_SUPPORT #ifdef USB_DEVICE_HS_SUPPORT
udd_enable_msof_interrupt(); udd_enable_msof_interrupt();
#endif #endif
// Reset following interupts flag // Reset following interrupts flag
udd_ack_reset(); udd_ack_reset();
udd_ack_sof(); udd_ack_sof();
udd_ack_msof(); udd_ack_msof();
@ -902,7 +902,7 @@ bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes,
} }
dbg_print("alloc(%x, %d) ", ep, MaxEndpointSize); dbg_print("alloc(%x, %d) ", ep, MaxEndpointSize);
// Bank choise // Bank choice
switch (bmAttributes & USB_EP_TYPE_MASK) { switch (bmAttributes & USB_EP_TYPE_MASK) {
case USB_EP_TYPE_ISOCHRONOUS: case USB_EP_TYPE_ISOCHRONOUS:
nb_bank = UDD_ISOCHRONOUS_NB_BANK(ep); nb_bank = UDD_ISOCHRONOUS_NB_BANK(ep);
@ -1228,7 +1228,7 @@ bool udd_ep_wait_stall_clear(udd_ep_id_t ep,
if (Is_udd_endpoint_stall_requested(ep) if (Is_udd_endpoint_stall_requested(ep)
|| ptr_job->stall_requested) { || ptr_job->stall_requested) {
// Endpoint halted then registes the callback // Endpoint halted then registers the callback
ptr_job->busy = true; ptr_job->busy = true;
ptr_job->call_nohalt = callback; ptr_job->call_nohalt = callback;
} else { } else {
@ -1386,7 +1386,7 @@ static void udd_ctrl_setup_received(void)
// Decode setup request // Decode setup request
if (udc_process_setup() == false) { if (udc_process_setup() == false) {
// Setup request unknow then stall it // Setup request unknown then stall it
udd_ctrl_stall_data(); udd_ctrl_stall_data();
udd_ack_setup_received(0); udd_ack_setup_received(0);
return; return;
@ -1447,7 +1447,7 @@ static void udd_ctrl_in_sent(void)
udd_ctrl_prev_payload_buf_cnt += udd_ctrl_payload_buf_cnt; udd_ctrl_prev_payload_buf_cnt += udd_ctrl_payload_buf_cnt;
if ((udd_g_ctrlreq.req.wLength == udd_ctrl_prev_payload_buf_cnt) if ((udd_g_ctrlreq.req.wLength == udd_ctrl_prev_payload_buf_cnt)
|| b_shortpacket) { || b_shortpacket) {
// All data requested are transfered or a short packet has been sent // All data requested are transferred or a short packet has been sent
// then it is the end of data phase. // then it is the end of data phase.
// Generate an OUT ZLP for handshake phase. // Generate an OUT ZLP for handshake phase.
udd_ctrl_send_zlp_out(); udd_ctrl_send_zlp_out();
@ -1516,7 +1516,7 @@ static void udd_ctrl_out_received(void)
// End of SETUP request: // End of SETUP request:
// - Data IN Phase aborted, // - Data IN Phase aborted,
// - or last Data IN Phase hidden by ZLP OUT sending quiclky, // - or last Data IN Phase hidden by ZLP OUT sending quiclky,
// - or ZLP OUT received normaly. // - or ZLP OUT received normally.
udd_ctrl_endofrequest(); udd_ctrl_endofrequest();
} else { } else {
// Protocol error during SETUP request // Protocol error during SETUP request
@ -1544,7 +1544,7 @@ static void udd_ctrl_out_received(void)
(udd_ctrl_prev_payload_buf_cnt + (udd_ctrl_prev_payload_buf_cnt +
udd_ctrl_payload_buf_cnt))) { udd_ctrl_payload_buf_cnt))) {
// End of reception because it is a short packet // End of reception because it is a short packet
// Before send ZLP, call intermediat calback // Before send ZLP, call intermediate callback
// in case of data receiv generate a stall // in case of data receiv generate a stall
udd_g_ctrlreq.payload_size = udd_ctrl_payload_buf_cnt; udd_g_ctrlreq.payload_size = udd_ctrl_payload_buf_cnt;
if (NULL != udd_g_ctrlreq.over_under_run) { if (NULL != udd_g_ctrlreq.over_under_run) {
@ -1565,7 +1565,7 @@ static void udd_ctrl_out_received(void)
if (udd_g_ctrlreq.payload_size == udd_ctrl_payload_buf_cnt) { if (udd_g_ctrlreq.payload_size == udd_ctrl_payload_buf_cnt) {
// Overrun then request a new payload buffer // Overrun then request a new payload buffer
if (!udd_g_ctrlreq.over_under_run) { if (!udd_g_ctrlreq.over_under_run) {
// No callback availabled to request a new payload buffer // No callback available to request a new payload buffer
udd_ctrl_stall_data(); udd_ctrl_stall_data();
// Ack reception of OUT to replace NAK by a STALL // Ack reception of OUT to replace NAK by a STALL
udd_ack_out_received(0); udd_ack_out_received(0);
@ -1805,7 +1805,7 @@ static void udd_ep_trans_done(udd_ep_id_t ep)
// transfer size of UDD_ENDPOINT_MAX_TRANS Bytes // transfer size of UDD_ENDPOINT_MAX_TRANS Bytes
next_trans = UDD_ENDPOINT_MAX_TRANS; next_trans = UDD_ENDPOINT_MAX_TRANS;
// Set 0 to tranfer the maximum // Set 0 to transfer the maximum
udd_dma_ctrl = UOTGHS_DEVDMACONTROL_BUFF_LENGTH(0); udd_dma_ctrl = UOTGHS_DEVDMACONTROL_BUFF_LENGTH(0);
} else { } else {
udd_dma_ctrl = UOTGHS_DEVDMACONTROL_BUFF_LENGTH(next_trans); udd_dma_ctrl = UOTGHS_DEVDMACONTROL_BUFF_LENGTH(next_trans);
@ -1850,7 +1850,7 @@ static void udd_ep_trans_done(udd_ep_id_t ep)
} }
cpu_irq_restore(flags); cpu_irq_restore(flags);
// Here a ZLP has been recieved // Here a ZLP has been received
// and the DMA transfer must be not started. // and the DMA transfer must be not started.
// It is the end of transfer // It is the end of transfer
ptr_job->buf_size = ptr_job->buf_cnt; ptr_job->buf_size = ptr_job->buf_cnt;
@ -1991,13 +1991,13 @@ static bool udd_ep_interrupt(void)
} }
dbg_print("dma%x: ", ep); dbg_print("dma%x: ", ep);
udd_disable_endpoint_dma_interrupt(ep); udd_disable_endpoint_dma_interrupt(ep);
// Save number of data no transfered // Save number of data no transferred
nb_remaining = (udd_endpoint_dma_get_status(ep) & nb_remaining = (udd_endpoint_dma_get_status(ep) &
UOTGHS_DEVDMASTATUS_BUFF_COUNT_Msk) UOTGHS_DEVDMASTATUS_BUFF_COUNT_Msk)
>> UOTGHS_DEVDMASTATUS_BUFF_COUNT_Pos; >> UOTGHS_DEVDMASTATUS_BUFF_COUNT_Pos;
if (nb_remaining) { if (nb_remaining) {
// Transfer no complete (short packet or ZLP) then: // Transfer no complete (short packet or ZLP) then:
// Update number of data transfered // Update number of data transferred
ptr_job->buf_cnt -= nb_remaining; ptr_job->buf_cnt -= nb_remaining;
// Set transfer complete to stop the transfer // Set transfer complete to stop the transfer
ptr_job->buf_size = ptr_job->buf_cnt; ptr_job->buf_size = ptr_job->buf_cnt;
@ -2056,7 +2056,7 @@ static bool udd_ep_interrupt(void)
udd_disable_endpoint_interrupt(ep); udd_disable_endpoint_interrupt(ep);
Assert(ptr_job->stall_requested); Assert(ptr_job->stall_requested);
// A stall has been requested during backgound transfer // A stall has been requested during background transfer
ptr_job->stall_requested = false; ptr_job->stall_requested = false;
udd_disable_endpoint_bank_autoswitch(ep); udd_disable_endpoint_bank_autoswitch(ep);
udd_enable_stall_handshake(ep); udd_enable_stall_handshake(ep);

2
Marlin/src/HAL/DUE/usb/usb_protocol_msc.h

@ -130,7 +130,7 @@ struct usb_msc_cbw {
struct usb_msc_csw { struct usb_msc_csw {
le32_t dCSWSignature; //!< Must contain 'USBS' le32_t dCSWSignature; //!< Must contain 'USBS'
le32_t dCSWTag; //!< Same as dCBWTag le32_t dCSWTag; //!< Same as dCBWTag
le32_t dCSWDataResidue; //!< Number of bytes not transfered le32_t dCSWDataResidue; //!< Number of bytes not transferred
uint8_t bCSWStatus; //!< Status code uint8_t bCSWStatus; //!< Status code
}; };

114
Marlin/src/HAL/DUE/watchdog.cpp

@ -1,114 +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 <https://www.gnu.org/licenses/>.
*
*/
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
#include "../../MarlinCore.h"
#include "watchdog.h"
// Override Arduino runtime to either config or disable the watchdog
//
// We need to configure the watchdog as soon as possible in the boot
// process, because watchdog initialization at hardware reset on SAM3X8E
// is unreliable, and there is risk of unintended resets if we delay
// that initialization to a later time.
void watchdogSetup() {
#if ENABLED(USE_WATCHDOG)
// 4 seconds timeout
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
// frequency is therefore 32768 / 128 = 256 Hz
timeout = (timeout << 8) / 1000;
if (timeout == 0)
timeout = 1;
else if (timeout > 0xFFF)
timeout = 0xFFF;
// We want to enable the watchdog with the specified timeout
uint32_t value =
WDT_MR_WDV(timeout) | // With the specified timeout
WDT_MR_WDD(timeout) | // and no invalid write window
#if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
WDT_MR_WDRPROC | // WDT fault resets processor only - We want
// to keep PIO controller state
#endif
WDT_MR_WDDBGHLT | // WDT stops in debug state.
WDT_MR_WDIDLEHLT; // WDT stops in idle state.
#if ENABLED(WATCHDOG_RESET_MANUAL)
// We enable the watchdog timer, but only for the interrupt.
// Configure WDT to only trigger an interrupt
value |= WDT_MR_WDFIEN; // Enable WDT fault interrupt.
// Disable WDT interrupt (just in case, to avoid triggering it!)
NVIC_DisableIRQ(WDT_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();
// Initialize WDT with the given parameters
WDT_Enable(WDT, value);
// Configure and enable WDT interrupt.
NVIC_ClearPendingIRQ(WDT_IRQn);
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
NVIC_EnableIRQ(WDT_IRQn);
#else
// a WDT fault triggers a reset
value |= WDT_MR_WDRSTEN;
// Initialize WDT with the given parameters
WDT_Enable(WDT, value);
#endif
// Reset the watchdog
WDT_Restart(WDT);
#else
// Make sure to completely disable the Watchdog
WDT_Disable(WDT);
#endif
}
#if ENABLED(USE_WATCHDOG)
// Initialize watchdog - On SAM3X, Watchdog was already configured
// and enabled or disabled at startup, so no need to reconfigure it
// here.
void watchdog_init() {
// Reset watchdog to start clean
WDT_Restart(WDT);
}
#endif // USE_WATCHDOG
#endif

240
Marlin/src/HAL/ESP32/HAL.cpp

@ -28,6 +28,10 @@
#include <esp_adc_cal.h> #include <esp_adc_cal.h>
#include <HardwareSerial.h> #include <HardwareSerial.h>
#if ENABLED(USE_ESP32_TASK_WDT)
#include <esp_task_wdt.h>
#endif
#if ENABLED(WIFISUPPORT) #if ENABLED(WIFISUPPORT)
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
#include "wifi.h" #include "wifi.h"
@ -48,7 +52,7 @@
// Externs // Externs
// ------------------------ // ------------------------
portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; portMUX_TYPE MarlinHAL::spinlock = portMUX_INITIALIZER_UNLOCKED;
// ------------------------ // ------------------------
// Local defines // Local defines
@ -60,7 +64,8 @@ portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
// Public Variables // Public Variables
// ------------------------ // ------------------------
uint16_t HAL_adc_result; uint16_t MarlinHAL::adc_result;
pwm_pin_t MarlinHAL::pwm_pin_data[MAX_EXPANDER_BITS];
// ------------------------ // ------------------------
// Private Variables // Private Variables
@ -69,9 +74,16 @@ uint16_t HAL_adc_result;
esp_adc_cal_characteristics_t characteristics[ADC_ATTEN_MAX]; esp_adc_cal_characteristics_t characteristics[ADC_ATTEN_MAX];
adc_atten_t attenuations[ADC1_CHANNEL_MAX] = {}; adc_atten_t attenuations[ADC1_CHANNEL_MAX] = {};
uint32_t thresholds[ADC_ATTEN_MAX]; uint32_t thresholds[ADC_ATTEN_MAX];
volatile int numPWMUsed = 0,
pwmPins[MAX_PWM_PINS], volatile int numPWMUsed = 0;
pwmValues[MAX_PWM_PINS]; volatile struct { pin_t pin; int value; } pwmState[MAX_PWM_PINS];
pin_t chan_pin[CHANNEL_MAX_NUM + 1] = { 0 }; // PWM capable IOpins - not 0 or >33 on ESP32
struct {
uint32_t freq; // ledcReadFreq doesn't work if a duty hasn't been set yet!
uint16_t res;
} pwmInfo[(CHANNEL_MAX_NUM + 1) / 2];
// ------------------------ // ------------------------
// Public functions // Public functions
@ -90,8 +102,26 @@ volatile int numPWMUsed = 0,
#endif #endif
void HAL_init_board() { #if ENABLED(USE_ESP32_EXIO)
HardwareSerial YSerial2(2);
void Write_EXIO(uint8_t IO, uint8_t v) {
if (hal.isr_state()) {
hal.isr_off();
YSerial2.write(0x80 | (((char)v) << 5) | (IO - 100));
hal.isr_on();
}
else
YSerial2.write(0x80 | (((char)v) << 5) | (IO - 100));
}
#endif
void MarlinHAL::init_board() {
#if ENABLED(USE_ESP32_TASK_WDT)
esp_task_wdt_init(10, true);
#endif
#if ENABLED(ESP3D_WIFISUPPORT) #if ENABLED(ESP3D_WIFISUPPORT)
esp3dlib.init(); esp3dlib.init();
#elif ENABLED(WIFISUPPORT) #elif ENABLED(WIFISUPPORT)
@ -127,30 +157,58 @@ void HAL_init_board() {
// Initialize the i2s peripheral only if the I2S stepper stream is enabled. // Initialize the i2s peripheral only if the I2S stepper stream is enabled.
// The following initialization is performed after Serial1 and Serial2 are defined as // 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. // their native pins might conflict with the i2s stream even when they are remapped.
TERN_(I2S_STEPPER_STREAM, i2s_init()); #if ENABLED(USE_ESP32_EXIO)
YSerial2.begin(460800 * 3, SERIAL_8N1, 16, 17);
#elif ENABLED(I2S_STEPPER_STREAM)
i2s_init();
#endif
} }
void HAL_idletask() { void MarlinHAL::idletask() {
#if BOTH(WIFISUPPORT, OTASUPPORT) #if BOTH(WIFISUPPORT, OTASUPPORT)
OTA_handle(); OTA_handle();
#endif #endif
TERN_(ESP3D_WIFISUPPORT, esp3dlib.idletask()); TERN_(ESP3D_WIFISUPPORT, esp3dlib.idletask());
} }
void HAL_clear_reset_source() { } uint8_t MarlinHAL::get_reset_source() { return rtc_get_reset_reason(1); }
uint8_t HAL_get_reset_source() { return rtc_get_reset_reason(1); }
void HAL_reboot() { ESP.restart(); } void MarlinHAL::reboot() { ESP.restart(); }
void _delay_ms(int delay_ms) { delay(delay_ms); } void _delay_ms(int delay_ms) { delay(delay_ms); }
// return free memory between end of heap (or end bss) and whatever is current // return free memory between end of heap (or end bss) and whatever is current
int freeMemory() { return ESP.getFreeHeap(); } int MarlinHAL::freeMemory() { return ESP.getFreeHeap(); }
// ------------------------
// Watchdog Timer
// ------------------------
#if ENABLED(USE_WATCHDOG)
#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
extern "C" {
esp_err_t esp_task_wdt_reset();
}
void watchdogSetup() {
// do whatever. don't remove this function.
}
void MarlinHAL::watchdog_init() {
// TODO
}
// Reset watchdog.
void MarlinHAL::watchdog_refresh() { esp_task_wdt_reset(); }
#endif
// ------------------------ // ------------------------
// ADC // ADC
// ------------------------ // ------------------------
#define ADC1_CHANNEL(pin) ADC1_GPIO ## pin ## _CHANNEL #define ADC1_CHANNEL(pin) ADC1_GPIO ## pin ## _CHANNEL
adc1_channel_t get_channel(int pin) { adc1_channel_t get_channel(int pin) {
@ -172,22 +230,24 @@ void adc1_set_attenuation(adc1_channel_t chan, adc_atten_t atten) {
} }
} }
void HAL_adc_init() { void MarlinHAL::adc_init() {
// Configure ADC // Configure ADC
adc1_config_width(ADC_WIDTH_12Bit); adc1_config_width(ADC_WIDTH_12Bit);
// Configure channels only if used as (re-)configuring a pin for ADC that is used elsewhere might have adverse effects // Configure channels only if used as (re-)configuring a pin for ADC that is used elsewhere might have adverse effects
TERN_(HAS_TEMP_ADC_0, adc1_set_attenuation(get_channel(TEMP_0_PIN), ADC_ATTEN_11db)); TERN_(HAS_TEMP_ADC_0, adc1_set_attenuation(get_channel(TEMP_0_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_1, adc1_set_attenuation(get_channel(TEMP_1_PIN), ADC_ATTEN_11db)); TERN_(HAS_TEMP_ADC_1, adc1_set_attenuation(get_channel(TEMP_1_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_2, adc1_set_attenuation(get_channel(TEMP_2_PIN), ADC_ATTEN_11db)); TERN_(HAS_TEMP_ADC_2, adc1_set_attenuation(get_channel(TEMP_2_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_3, adc1_set_attenuation(get_channel(TEMP_3_PIN), ADC_ATTEN_11db)); TERN_(HAS_TEMP_ADC_3, adc1_set_attenuation(get_channel(TEMP_3_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_4, adc1_set_attenuation(get_channel(TEMP_4_PIN), ADC_ATTEN_11db)); TERN_(HAS_TEMP_ADC_4, adc1_set_attenuation(get_channel(TEMP_4_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_5, adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db)); TERN_(HAS_TEMP_ADC_5, adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_6, adc2_set_attenuation(get_channel(TEMP_6_PIN), ADC_ATTEN_11db)); TERN_(HAS_TEMP_ADC_6, adc2_set_attenuation(get_channel(TEMP_6_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db)); 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_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_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_(HAS_TEMP_PROBE, adc1_set_attenuation(get_channel(TEMP_PROBE_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_BOARD, adc1_set_attenuation(get_channel(TEMP_BOARD_PIN), ADC_ATTEN_11db));
TERN_(FILAMENT_WIDTH_SENSOR, adc1_set_attenuation(get_channel(FILWIDTH_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. // Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail.
@ -202,11 +262,16 @@ void HAL_adc_init() {
} }
} }
void HAL_adc_start_conversion(const uint8_t adc_pin) { #ifndef ADC_REFERENCE_VOLTAGE
const adc1_channel_t chan = get_channel(adc_pin); #define ADC_REFERENCE_VOLTAGE 3.3
#endif
void MarlinHAL::adc_start(const pin_t pin) {
const adc1_channel_t chan = get_channel(pin);
uint32_t mv; uint32_t mv;
esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv);
HAL_adc_result = mv * 1023.0 / 3300.0;
adc_result = mv * isr_float_t(1023) / isr_float_t(ADC_REFERENCE_VOLTAGE) / isr_float_t(1000);
// Change the attenuation level based on the new reading // Change the attenuation level based on the new reading
adc_atten_t atten; adc_atten_t atten;
@ -223,25 +288,106 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
adc1_set_attenuation(chan, atten); adc1_set_attenuation(chan, atten);
} }
void analogWrite(pin_t pin, int value) { // ------------------------
// Use ledc hardware for internal pins // PWM
if (pin < 34) { // ------------------------
static int cnt_channel = 1, pin_to_channel[40] = { 0 };
if (pin_to_channel[pin] == 0) { int8_t channel_for_pin(const uint8_t pin) {
ledcAttachPin(pin, cnt_channel); for (int i = 0; i <= CHANNEL_MAX_NUM; i++)
ledcSetup(cnt_channel, 490, 8); if (chan_pin[i] == pin) return i;
ledcWrite(cnt_channel, value); return -1;
pin_to_channel[pin] = cnt_channel++; }
// get PWM channel for pin - if none then attach a new one
// return -1 if fail or invalid pin#, channel # (0-15) if success
int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) {
if (!WITHIN(pin, 1, MAX_PWM_IOPIN)) return -1; // Not a hardware PWM pin!
int8_t cid = channel_for_pin(pin);
if (cid >= 0) return cid;
// Find an empty adjacent channel (same timer & freq/res)
for (int i = 0; i <= CHANNEL_MAX_NUM; i++) {
if (chan_pin[i] == 0) {
if (chan_pin[i ^ 0x1] != 0) {
if (pwmInfo[i / 2].freq == freq && pwmInfo[i / 2].res == res) {
chan_pin[i] = pin; // Allocate PWM to this channel
ledcAttachPin(pin, i);
return i;
}
}
else if (cid == -1) // Pair of empty channels?
cid = i & 0xFE; // Save lower channel number
}
}
// not attached, is an empty timer slot avail?
if (cid >= 0) {
chan_pin[cid] = pin;
pwmInfo[cid / 2].freq = freq;
pwmInfo[cid / 2].res = res;
ledcSetup(cid, freq, res);
ledcAttachPin(pin, cid);
}
return cid; // -1 if no channel avail
}
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) {
#if ENABLED(I2S_STEPPER_STREAM)
if (pin > 127) {
const uint8_t pinlo = pin & 0x7F;
pwm_pin_t &pindata = pwm_pin_data[pinlo];
const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, pindata.pwm_cycle_ticks);
if (duty == 0 || duty == pindata.pwm_cycle_ticks) { // max or min (i.e., on/off)
pindata.pwm_duty_ticks = 0; // turn off PWM for this pin
duty ? SBI32(i2s_port_data, pinlo) : CBI32(i2s_port_data, pinlo); // set pin level
}
else
pindata.pwm_duty_ticks = duty; // PWM duty count = # of 4µs ticks per full PWM cycle
} }
ledcWrite(pin_to_channel[pin], value); else
#endif
{
const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION);
if (cid >= 0) {
const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1);
ledcWrite(cid, duty);
}
}
}
int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) {
#if ENABLED(I2S_STEPPER_STREAM)
if (pin > 127) {
pwm_pin_data[pin & 0x7F].pwm_cycle_ticks = 1000000UL / f_desired / 4; // # of 4µs ticks per full PWM cycle
return 0;
}
else
#endif
{
const int8_t cid = channel_for_pin(pin);
if (cid >= 0) {
if (f_desired == ledcReadFreq(cid)) return cid; // no freq change
ledcDetachPin(chan_pin[cid]);
chan_pin[cid] = 0; // remove old freq channel
}
return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one
}
}
// use hardware PWM if avail, if not then ISR
void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PWM_FREQUENCY*/, const uint16_t res/*=8*/) { // always 8 bit resolution!
// Use ledc hardware for internal pins
const int8_t cid = get_pwm_channel(pin, freq, res);
if (cid >= 0) {
ledcWrite(cid, value); // set duty value
return; return;
} }
// not a hardware PWM pin OR no PWM channels available
int idx = -1; int idx = -1;
// Search Pin // Search Pin
for (int i = 0; i < numPWMUsed; ++i) for (int i = 0; i < numPWMUsed; ++i)
if (pwmPins[i] == pin) { idx = i; break; } if (pwmState[i].pin == pin) { idx = i; break; }
// not found ? // not found ?
if (idx < 0) { if (idx < 0) {
@ -250,34 +396,34 @@ void analogWrite(pin_t pin, int value) {
// Take new slot for pin // Take new slot for pin
idx = numPWMUsed; idx = numPWMUsed;
pwmPins[idx] = pin; pwmState[idx].pin = pin;
// Start timer on first use // Start timer on first use
if (idx == 0) HAL_timer_start(PWM_TIMER_NUM, PWM_TIMER_FREQUENCY); if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY);
++numPWMUsed; ++numPWMUsed;
} }
// Use 7bit internal value - add 1 to have 100% high at 255 // Use 7bit internal value - add 1 to have 100% high at 255
pwmValues[idx] = (value + 1) / 2; pwmState[idx].value = (value + 1) / 2;
} }
// Handle PWM timer interrupt // Handle PWM timer interrupt
HAL_PWM_TIMER_ISR() { HAL_PWM_TIMER_ISR() {
HAL_timer_isr_prologue(PWM_TIMER_NUM); HAL_timer_isr_prologue(MF_TIMER_PWM);
static uint8_t count = 0; static uint8_t count = 0;
for (int i = 0; i < numPWMUsed; ++i) { for (int i = 0; i < numPWMUsed; ++i) {
if (count == 0) // Start of interval if (count == 0) // Start of interval
WRITE(pwmPins[i], pwmValues[i] ? HIGH : LOW); digitalWrite(pwmState[i].pin, pwmState[i].value ? HIGH : LOW);
else if (pwmValues[i] == count) // End of duration else if (pwmState[i].value == count) // End of duration
WRITE(pwmPins[i], LOW); digitalWrite(pwmState[i].pin, LOW);
} }
// 128 for 7 Bit resolution // 128 for 7 Bit resolution
count = (count + 1) & 0x7F; count = (count + 1) & 0x7F;
HAL_timer_isr_epilogue(PWM_TIMER_NUM); HAL_timer_isr_epilogue(MF_TIMER_PWM);
} }
#endif // ARDUINO_ARCH_ESP32 #endif // ARDUINO_ARCH_ESP32

178
Marlin/src/HAL/ESP32/HAL.h

@ -32,7 +32,6 @@
#include "../shared/HAL_SPI.h" #include "../shared/HAL_SPI.h"
#include "fastio.h" #include "fastio.h"
#include "watchdog.h"
#include "i2s.h" #include "i2s.h"
#if ENABLED(WIFISUPPORT) #if ENABLED(WIFISUPPORT)
@ -49,8 +48,6 @@
// Defines // Defines
// ------------------------ // ------------------------
extern portMUX_TYPE spinlock;
#define MYSERIAL1 flushableSerial #define MYSERIAL1 flushableSerial
#if EITHER(WIFISUPPORT, ESP3D_WIFISUPPORT) #if EITHER(WIFISUPPORT, ESP3D_WIFISUPPORT)
@ -63,26 +60,33 @@ extern portMUX_TYPE spinlock;
#endif #endif
#endif #endif
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock) #define CRITICAL_SECTION_START() portENTER_CRITICAL(&hal.spinlock)
#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock) #define CRITICAL_SECTION_END() portEXIT_CRITICAL(&hal.spinlock)
#define ISRS_ENABLED() (spinlock.owner == portMUX_FREE_VAL)
#define ENABLE_ISRS() if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock) #define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
#define DISABLE_ISRS() portENTER_CRITICAL(&spinlock) #define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
#define PWM_RESOLUTION 10u // Default PWM bit resolution
#define CHANNEL_MAX_NUM 15u // max PWM channel # to allocate (7 to only use low speed, 15 to use low & high)
#define MAX_PWM_IOPIN 33u // hardware pwm pins < 34
#ifndef MAX_EXPANDER_BITS
#define MAX_EXPANDER_BITS 32 // I2S expander bit width (max 32)
#endif
// ------------------------ // ------------------------
// Types // Types
// ------------------------ // ------------------------
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef int16_t pin_t; typedef int16_t pin_t;
#define HAL_SERVO_LIB Servo typedef struct pwm_pin {
uint32_t pwm_cycle_ticks = 1000000UL / (PWM_FREQUENCY) / 4; // # ticks per pwm cycle
uint32_t pwm_tick_count = 0; // current tick count
uint32_t pwm_duty_ticks = 0; // # of ticks for current duty cycle
} pwm_pin_t;
// ------------------------ class Servo;
// Public Variables typedef Servo hal_servo_t;
// ------------------------
/** result of last ADC conversion */
extern uint16_t HAL_adc_result;
// ------------------------ // ------------------------
// Public functions // Public functions
@ -91,56 +95,21 @@ extern uint16_t HAL_adc_result;
// //
// Tone // Tone
// //
void toneInit();
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0); void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
void noTone(const pin_t _pin); void noTone(const pin_t _pin);
int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res);
void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq=PWM_FREQUENCY, const uint16_t res=8);
// clear reset reason //
void HAL_clear_reset_source(); // Pin Mapping for M42, M43, M226
//
// reset reason
uint8_t HAL_get_reset_source();
void HAL_reboot();
void _delay_ms(int delay);
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic pop
#endif
void analogWrite(pin_t pin, int value);
// ADC
#define HAL_ANALOG_SELECT(pin)
void HAL_adc_init();
#define HAL_ADC_VREF 3.3
#define HAL_ADC_RESOLUTION 10
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
void HAL_adc_start_conversion(const uint8_t adc_pin);
#define GET_PIN_MAP_PIN(index) index #define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin #define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
// Enable hooks into idle and setup for HAL #if ENABLED(USE_ESP32_EXIO)
#define HAL_IDLETASK 1 void Write_EXIO(uint8_t IO, uint8_t v);
#define BOARD_INIT() HAL_init_board(); #endif
void HAL_idletask();
inline void HAL_init() {}
void HAL_init_board();
// //
// Delay in cycles (used by DELAY_NS / DELAY_US) // Delay in cycles (used by DELAY_NS / DELAY_US)
@ -182,3 +151,96 @@ FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
} }
} }
// ------------------------
// Class Utilities
// ------------------------
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#pragma GCC diagnostic pop
void _delay_ms(const int ms);
// ------------------------
// MarlinHAL Class
// ------------------------
#define HAL_ADC_VREF 3.3
#define HAL_ADC_RESOLUTION 10
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init() {} // Called early in setup()
static void init_board(); // Called less early in setup()
static void reboot(); // Restart the firmware
// Interrupts
static portMUX_TYPE spinlock;
static bool isr_state() { return spinlock.owner == portMUX_FREE_VAL; }
static void isr_on() { if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock); }
static void isr_off() { portENTER_CRITICAL(&spinlock); }
static void delay_ms(const int ms) { _delay_ms(ms); }
// Tasks, called from idle()
static void idletask();
// Reset
static uint8_t get_reset_source();
static void clear_reset_source() {}
// Free SRAM
static int freeMemory();
static pwm_pin_t pwm_pin_data[MAX_EXPANDER_BITS];
//
// ADC Methods
//
static uint16_t adc_result;
// Called by Temperature::init once at startup
static void adc_init();
// Called by Temperature::init for each sensor at startup
static void adc_enable(const pin_t pin) {}
// Begin ADC sampling on the given pin. Called from Temperature::isr!
static void adc_start(const pin_t pin);
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value() { return adc_result; }
/**
* If not already allocated, allocate a hardware PWM channel
* to the pin and set the duty cycle..
* Optionally invert the duty cycle [default = false]
* Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
/**
* Allocate and set the frequency of a hardware PWM pin
* Returns -1 if no pin available.
*/
static int8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired);
};

6
Marlin/src/HAL/ESP32/HAL_SPI.cpp

@ -53,11 +53,9 @@ static SPISettings spiConfig;
// ------------------------ // ------------------------
void spiBegin() { void spiBegin() {
#if !PIN_EXISTS(SD_SS) #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_SS)
#error "SD_SS_PIN not defined!" OUT_WRITE(SD_SS_PIN, HIGH);
#endif #endif
OUT_WRITE(SD_SS_PIN, HIGH);
} }
void spiInit(uint8_t spiRate) { void spiInit(uint8_t spiRate) {

8
Marlin/src/HAL/LPC1768/watchdog.h → Marlin/src/HAL/ESP32/MarlinSPI.h

@ -1,6 +1,6 @@
/** /**
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* *
* Based on Sprinter and grbl. * Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
@ -21,8 +21,6 @@
*/ */
#pragma once #pragma once
void watchdog_init(); #include <SPI.h>
void HAL_watchdog_refresh();
bool watchdog_timed_out(); using MarlinSPI = SPIClass;
void watchdog_clear_timeout_flag();

18
Marlin/src/HAL/ESP32/Servo.cpp

@ -31,20 +31,18 @@
// so we only allocate servo channels up high to avoid side effects with regards to analogWrite (fans, leds, laser pwm etc.) // so we only allocate servo channels up high to avoid side effects with regards to analogWrite (fans, leds, laser pwm etc.)
int Servo::channel_next_free = 12; int Servo::channel_next_free = 12;
Servo::Servo() { Servo::Servo() {}
channel = channel_next_free++;
}
int8_t Servo::attach(const int inPin) { int8_t Servo::attach(const int inPin) {
if (channel >= CHANNEL_MAX_NUM) return -1;
if (inPin > 0) pin = inPin; if (inPin > 0) pin = inPin;
channel = get_pwm_channel(pin, 50u, 16u);
ledcSetup(channel, 50, 16); // channel X, 50 Hz, 16-bit depth return channel; // -1 if no PWM avail.
ledcAttachPin(pin, channel);
return true;
} }
void Servo::detach() { ledcDetachPin(pin); } // leave channel connected to servo - set duty to zero
void Servo::detach() {
if (channel >= 0) ledcWrite(channel, 0);
}
int Servo::read() { return degrees; } int Servo::read() { return degrees; }
@ -52,7 +50,7 @@ void Servo::write(int inDegrees) {
degrees = constrain(inDegrees, MIN_ANGLE, MAX_ANGLE); degrees = constrain(inDegrees, MIN_ANGLE, MAX_ANGLE);
int us = map(degrees, MIN_ANGLE, MAX_ANGLE, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); int us = map(degrees, MIN_ANGLE, MAX_ANGLE, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
int duty = map(us, 0, TAU_USEC, 0, MAX_COMPARE); int duty = map(us, 0, TAU_USEC, 0, MAX_COMPARE);
ledcWrite(channel, duty); if (channel >= 0) ledcWrite(channel, duty); // don't save duty for servos!
} }
void Servo::move(const int value) { void Servo::move(const int value) {

3
Marlin/src/HAL/ESP32/Servo.h

@ -30,8 +30,7 @@ class Servo {
MAX_PULSE_WIDTH = 2400, // Longest pulse sent to a servo MAX_PULSE_WIDTH = 2400, // Longest pulse sent to a servo
TAU_MSEC = 20, TAU_MSEC = 20,
TAU_USEC = (TAU_MSEC * 1000), TAU_USEC = (TAU_MSEC * 1000),
MAX_COMPARE = _BV(16) - 1, // 65535 MAX_COMPARE = _BV(16) - 1; // 65535
CHANNEL_MAX_NUM = 16;
public: public:
Servo(); Servo();

8
Marlin/src/HAL/ESP32/Tone.cpp

@ -35,19 +35,19 @@
static pin_t tone_pin; static pin_t tone_pin;
volatile static int32_t toggles; volatile static int32_t toggles;
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) { void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration/*=0*/) {
tone_pin = _pin; tone_pin = _pin;
toggles = 2 * frequency * duration / 1000; toggles = 2 * frequency * duration / 1000;
HAL_timer_start(TONE_TIMER_NUM, 2 * frequency); HAL_timer_start(MF_TIMER_TONE, 2 * frequency);
} }
void noTone(const pin_t _pin) { void noTone(const pin_t _pin) {
HAL_timer_disable_interrupt(TONE_TIMER_NUM); HAL_timer_disable_interrupt(MF_TIMER_TONE);
WRITE(_pin, LOW); WRITE(_pin, LOW);
} }
HAL_TONE_TIMER_ISR() { HAL_TONE_TIMER_ISR() {
HAL_timer_isr_prologue(TONE_TIMER_NUM); HAL_timer_isr_prologue(MF_TIMER_TONE);
if (toggles) { if (toggles) {
toggles--; toggles--;

6
Marlin/src/HAL/ESP32/endstop_interrupts.h

@ -65,4 +65,10 @@ void setup_endstop_interrupts() {
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN));
TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN));
TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN));
TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN));
TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN));
TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN));
} }

6
Marlin/src/HAL/ESP32/esp32.csv

@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x180000,
app1, app, ota_1, 0x190000, 0x180000,
spiffs, data, spiffs, 0x310000, 0xF0000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 0x10000 0x180000
5 app1 app ota_1 0x190000 0x180000
6 spiffs data spiffs 0x310000 0xF0000

20
Marlin/src/HAL/ESP32/fastio.h

@ -40,13 +40,19 @@
// Set pin as input with pullup mode // Set pin as input with pullup mode
#define _PULLUP(IO, v) pinMode(IO, v ? INPUT_PULLUP : INPUT) #define _PULLUP(IO, v) pinMode(IO, v ? INPUT_PULLUP : INPUT)
// Read a pin wrapper #if ENABLED(USE_ESP32_EXIO)
#define READ(IO) (IS_I2S_EXPANDER_PIN(IO) ? i2s_state(I2S_EXPANDER_PIN_INDEX(IO)) : digitalRead(IO)) // Read a pin wrapper
#define READ(IO) digitalRead(IO)
// Write to a pin wrapper // Write to a pin wrapper
#define WRITE(IO, v) (IS_I2S_EXPANDER_PIN(IO) ? i2s_write(I2S_EXPANDER_PIN_INDEX(IO), v) : digitalWrite(IO, v)) #define WRITE(IO, v) (IO >= 100 ? Write_EXIO(IO, v) : digitalWrite(IO, v))
#else
// Set pin as input wrapper // Read a pin wrapper
#define READ(IO) (IS_I2S_EXPANDER_PIN(IO) ? i2s_state(I2S_EXPANDER_PIN_INDEX(IO)) : digitalRead(IO))
// Write to a pin wrapper
#define WRITE(IO, v) (IS_I2S_EXPANDER_PIN(IO) ? i2s_write(I2S_EXPANDER_PIN_INDEX(IO), v) : digitalWrite(IO, v))
#endif
// Set pin as input wrapper (0x80 | (v << 5) | (IO - 100))
#define SET_INPUT(IO) _SET_INPUT(IO) #define SET_INPUT(IO) _SET_INPUT(IO)
// Set pin as input with pullup wrapper // Set pin as input with pullup wrapper

53
Marlin/src/HAL/ESP32/i2s.cpp

@ -23,6 +23,8 @@
#include "../../inc/MarlinConfigPre.h" #include "../../inc/MarlinConfigPre.h"
#if DISABLED(USE_ESP32_EXIO)
#include "i2s.h" #include "i2s.h"
#include "../shared/Marduino.h" #include "../shared/Marduino.h"
@ -62,12 +64,9 @@ uint32_t i2s_port_data = 0;
#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) #define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
static inline void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) { static inline void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) {
//if pin = -1, do not need to configure PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
if (gpio != -1) { gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv);
gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv);
}
} }
static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num) { static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num) {
@ -254,13 +253,7 @@ int i2s_init() {
I2S0.fifo_conf.dscr_en = 0; I2S0.fifo_conf.dscr_en = 0;
I2S0.conf_chan.tx_chan_mod = ( I2S0.conf_chan.tx_chan_mod = TERN(I2S_STEPPER_SPLIT_STREAM, 4, 0);
#if ENABLED(I2S_STEPPER_SPLIT_STREAM)
4
#else
0
#endif
);
I2S0.fifo_conf.tx_fifo_mod = 0; I2S0.fifo_conf.tx_fifo_mod = 0;
I2S0.conf.tx_mono = 0; I2S0.conf.tx_mono = 0;
@ -311,9 +304,16 @@ int i2s_init() {
xTaskCreatePinnedToCore(stepperTask, "StepperTask", 10000, nullptr, 1, nullptr, CONFIG_ARDUINO_RUNNING_CORE); // run I2S stepper task on same core as rest of Marlin xTaskCreatePinnedToCore(stepperTask, "StepperTask", 10000, nullptr, 1, nullptr, CONFIG_ARDUINO_RUNNING_CORE); // run I2S stepper task on same core as rest of Marlin
// Route the i2s pins to the appropriate GPIO // Route the i2s pins to the appropriate GPIO
gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0); // If a pin is not defined, no need to configure
gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0); #if defined(I2S_DATA) && I2S_DATA >= 0
gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0); gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0);
#endif
#if defined(I2S_BCK) && I2S_BCK >= 0
gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0);
#endif
#if defined(I2S_WS) && I2S_WS >= 0
gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0);
#endif
// Start the I2S peripheral // Start the I2S peripheral
return i2s_start(I2S_NUM_0); return i2s_start(I2S_NUM_0);
@ -337,7 +337,28 @@ uint8_t i2s_state(uint8_t pin) {
} }
void i2s_push_sample() { void i2s_push_sample() {
// Every 4µs (when space in DMA buffer) toggle each expander PWM output using
// the current duty cycle/frequency so they sync with any steps (once
// through the DMA/FIFO buffers). PWM signal inversion handled by other functions
LOOP_L_N(p, MAX_EXPANDER_BITS) {
if (hal.pwm_pin_data[p].pwm_duty_ticks > 0) { // pin has active pwm?
if (hal.pwm_pin_data[p].pwm_tick_count == 0) {
if (TEST32(i2s_port_data, p)) { // hi->lo
CBI32(i2s_port_data, p);
hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_cycle_ticks - hal.pwm_pin_data[p].pwm_duty_ticks;
}
else { // lo->hi
SBI32(i2s_port_data, p);
hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_duty_ticks;
}
}
else
hal.pwm_pin_data[p].pwm_tick_count--;
}
}
dma.current[dma.rw_pos++] = i2s_port_data; dma.current[dma.rw_pos++] = i2s_port_data;
} }
#endif // !USE_ESP32_EXIO
#endif // ARDUINO_ARCH_ESP32 #endif // ARDUINO_ARCH_ESP32

7
Marlin/src/HAL/ESP32/inc/Conditionals_adv.h

@ -20,3 +20,10 @@
* *
*/ */
#pragma once #pragma once
//
// Board-specific options need to be defined before HAL.h
//
#if MB(MKS_TINYBEE)
#define MAX_EXPANDER_BITS 24 // TinyBee has 3 x HC595
#endif

20
Marlin/src/HAL/ESP32/inc/SanityCheck.h

@ -25,8 +25,8 @@
#error "EMERGENCY_PARSER is not yet implemented for ESP32. Disable EMERGENCY_PARSER to continue." #error "EMERGENCY_PARSER is not yet implemented for ESP32. Disable EMERGENCY_PARSER to continue."
#endif #endif
#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY #if (ENABLED(SPINDLE_LASER_USE_PWM) && SPINDLE_LASER_FREQUENCY > 78125) || (ENABLED(FAST_PWM_FAN_FREQUENCY) && FAST_PWM_FAN_FREQUENCY > 78125)
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on ESP32." #error "SPINDLE_LASER_FREQUENCY and FAST_PWM_FREQUENCY maximum value is 78125Hz for ESP32."
#endif #endif
#if HAS_TMC_SW_SERIAL #if HAS_TMC_SW_SERIAL
@ -40,3 +40,19 @@
#if ENABLED(POSTMORTEM_DEBUGGING) #if ENABLED(POSTMORTEM_DEBUGGING)
#error "POSTMORTEM_DEBUGGING is not yet supported on ESP32." #error "POSTMORTEM_DEBUGGING is not yet supported on ESP32."
#endif #endif
#if MB(MKS_TINYBEE) && ENABLED(FAST_PWM_FAN)
#error "FAST_PWM_FAN is not available on TinyBee."
#endif
#if BOTH(I2S_STEPPER_STREAM, BABYSTEPPING) && DISABLED(INTEGRATED_BABYSTEPPING)
#error "BABYSTEPPING on I2S stream requires INTEGRATED_BABYSTEPPING."
#endif
#if USING_PULLDOWNS
#error "PULLDOWN pin mode is not available on ESP32 boards."
#endif
#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE)
#error "I2S stream is currently incompatible with LIN_ADVANCE."
#endif

3
Marlin/src/HAL/ESP32/spi_pins.h

@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or

20
Marlin/src/HAL/ESP32/timers.cpp

@ -41,7 +41,7 @@
static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1}; static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};
const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = { const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
{ TIMER_GROUP_0, TIMER_0, STEPPER_TIMER_PRESCALE, stepTC_Handler }, // 0 - Stepper { 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_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_0, PWM_TIMER_PRESCALE, pwmTC_Handler }, // 2 - PWM
@ -53,7 +53,7 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
// ------------------------ // ------------------------
void IRAM_ATTR timer_isr(void *para) { void IRAM_ATTR timer_isr(void *para) {
const tTimerConfig& timer = TimerConfig[(int)para]; const tTimerConfig& timer = timer_config[(int)para];
// Retrieve the interrupt status and the counter value // Retrieve the interrupt status and the counter value
// from the timer that reported the interrupt // from the timer that reported the interrupt
@ -81,8 +81,8 @@ void IRAM_ATTR timer_isr(void *para) {
* @param timer_num timer number to initialize * @param timer_num timer number to initialize
* @param frequency frequency of the timer * @param frequency frequency of the timer
*/ */
void HAL_timer_start(const uint8_t timer_num, uint32_t frequency) { void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
const tTimerConfig timer = TimerConfig[timer_num]; const tTimerConfig timer = timer_config[timer_num];
timer_config_t config; timer_config_t config;
config.divider = timer.divider; config.divider = timer.divider;
@ -115,7 +115,7 @@ void HAL_timer_start(const uint8_t timer_num, uint32_t frequency) {
* @param count threshold at which the interrupt is triggered * @param count threshold at which the interrupt is triggered
*/ */
void HAL_timer_set_compare(const uint8_t timer_num, hal_timer_t count) { void HAL_timer_set_compare(const uint8_t timer_num, hal_timer_t count) {
const tTimerConfig timer = TimerConfig[timer_num]; const tTimerConfig timer = timer_config[timer_num];
timer_set_alarm_value(timer.group, timer.idx, count); timer_set_alarm_value(timer.group, timer.idx, count);
} }
@ -125,7 +125,7 @@ void HAL_timer_set_compare(const uint8_t timer_num, hal_timer_t count) {
* @return the timer current threshold for the alarm to be triggered * @return the timer current threshold for the alarm to be triggered
*/ */
hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
const tTimerConfig timer = TimerConfig[timer_num]; const tTimerConfig timer = timer_config[timer_num];
uint64_t alarm_value; uint64_t alarm_value;
timer_get_alarm_value(timer.group, timer.idx, &alarm_value); timer_get_alarm_value(timer.group, timer.idx, &alarm_value);
@ -139,7 +139,7 @@ hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
* @return the current counter of the alarm * @return the current counter of the alarm
*/ */
hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
const tTimerConfig timer = TimerConfig[timer_num]; const tTimerConfig timer = timer_config[timer_num];
uint64_t counter_value; uint64_t counter_value;
timer_get_counter_value(timer.group, timer.idx, &counter_value); timer_get_counter_value(timer.group, timer.idx, &counter_value);
return counter_value; return counter_value;
@ -150,7 +150,7 @@ hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
* @param timer_num timer number to enable interrupts on * @param timer_num timer number to enable interrupts on
*/ */
void HAL_timer_enable_interrupt(const uint8_t timer_num) { void HAL_timer_enable_interrupt(const uint8_t timer_num) {
//const tTimerConfig timer = TimerConfig[timer_num]; //const tTimerConfig timer = timer_config[timer_num];
//timer_enable_intr(timer.group, timer.idx); //timer_enable_intr(timer.group, timer.idx);
} }
@ -159,12 +159,12 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num) {
* @param timer_num timer number to disable interrupts on * @param timer_num timer number to disable interrupts on
*/ */
void HAL_timer_disable_interrupt(const uint8_t timer_num) { void HAL_timer_disable_interrupt(const uint8_t timer_num) {
//const tTimerConfig timer = TimerConfig[timer_num]; //const tTimerConfig timer = timer_config[timer_num];
//timer_disable_intr(timer.group, timer.idx); //timer_disable_intr(timer.group, timer.idx);
} }
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
const tTimerConfig timer = TimerConfig[timer_num]; const tTimerConfig timer = timer_config[timer_num];
return TG[timer.group]->int_ena.val | BIT(timer_num); return TG[timer.group]->int_ena.val | BIT(timer_num);
} }

38
Marlin/src/HAL/ESP32/timers.h

@ -32,20 +32,20 @@
typedef uint64_t hal_timer_t; typedef uint64_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFFFFFFFFFULL #define HAL_TIMER_TYPE_MAX 0xFFFFFFFFFFFFFFFFULL
#ifndef STEP_TIMER_NUM #ifndef MF_TIMER_STEP
#define STEP_TIMER_NUM 0 // Timer Index for Stepper #define MF_TIMER_STEP 0 // Timer Index for Stepper
#endif #endif
#ifndef PULSE_TIMER_NUM #ifndef MF_TIMER_PULSE
#define PULSE_TIMER_NUM STEP_TIMER_NUM #define MF_TIMER_PULSE MF_TIMER_STEP
#endif #endif
#ifndef TEMP_TIMER_NUM #ifndef MF_TIMER_TEMP
#define TEMP_TIMER_NUM 1 // Timer Index for Temperature #define MF_TIMER_TEMP 1 // Timer Index for Temperature
#endif #endif
#ifndef PWM_TIMER_NUM #ifndef MF_TIMER_PWM
#define PWM_TIMER_NUM 2 // index of timer to use for PWM outputs #define MF_TIMER_PWM 2 // index of timer to use for PWM outputs
#endif #endif
#ifndef TONE_TIMER_NUM #ifndef MF_TIMER_TONE
#define TONE_TIMER_NUM 3 // index of timer for beeper tones #define MF_TIMER_TONE 3 // index of timer for beeper tones
#endif #endif
#define HAL_TIMER_RATE APB_CLK_FREQ // frequency of timer peripherals #define HAL_TIMER_RATE APB_CLK_FREQ // frequency of timer peripherals
@ -79,12 +79,12 @@ typedef uint64_t hal_timer_t;
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM) #define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM) #define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM) #define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM) #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_TEMP_TIMER_ISR #ifndef HAL_TEMP_TIMER_ISR
#define HAL_TEMP_TIMER_ISR() extern "C" void tempTC_Handler() #define HAL_TEMP_TIMER_ISR() extern "C" void tempTC_Handler()
@ -121,13 +121,13 @@ typedef struct {
// Public Variables // Public Variables
// ------------------------ // ------------------------
extern const tTimerConfig TimerConfig[]; extern const tTimerConfig timer_config[];
// ------------------------ // ------------------------
// Public functions // Public functions
// ------------------------ // ------------------------
void HAL_timer_start (const uint8_t timer_num, uint32_t frequency); void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t count); void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t count);
hal_timer_t HAL_timer_get_compare(const uint8_t timer_num); hal_timer_t HAL_timer_get_compare(const uint8_t timer_num);
hal_timer_t HAL_timer_get_count(const uint8_t timer_num); hal_timer_t HAL_timer_get_count(const uint8_t timer_num);
@ -136,5 +136,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num); void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
#define HAL_timer_isr_prologue(TIMER_NUM) #define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(TIMER_NUM) #define HAL_timer_isr_epilogue(T) NOOP

106
Marlin/src/HAL/ESP32/u8g_esp32_spi.cpp

@ -0,0 +1,106 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* 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
* (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 <https://www.gnu.org/licenses/>.
*
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfig.h"
#if EITHER(MKS_MINI_12864, FYSETC_MINI_12864_2_1)
#include <U8glib-HAL.h>
#include "../shared/HAL_SPI.h"
#include "HAL.h"
#include "SPI.h"
#if ENABLED(SDSUPPORT)
#include "../../sd/cardreader.h"
#if ENABLED(ESP3D_WIFISUPPORT)
#include "sd_ESP32.h"
#endif
#endif
static SPISettings spiConfig;
#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_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
static uint8_t msgInitCount = 2; // Ignore all messages until 2nd U8G_COM_MSG_INIT
#if ENABLED(PAUSE_LCD_FOR_BUSY_SD)
if (card.flag.saving || card.flag.logging || TERN0(ESP3D_WIFISUPPORT, sd_busy_lock == true)) return 0;
#endif
if (msgInitCount) {
if (msg == U8G_COM_MSG_INIT) msgInitCount--;
if (msgInitCount) return -1;
}
switch (msg) {
case U8G_COM_MSG_STOP: break;
case U8G_COM_MSG_INIT:
OUT_WRITE(DOGLCD_CS, HIGH);
OUT_WRITE(DOGLCD_A0, HIGH);
OUT_WRITE(LCD_RESET_PIN, HIGH);
u8g_Delay(5);
spiBegin();
spiInit(LCD_SPI_SPEED);
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
WRITE(DOGLCD_A0, arg_val ? HIGH : LOW);
break;
case U8G_COM_MSG_CHIP_SELECT: /* arg_val == 0 means HIGH level of U8G_PI_CS */
WRITE(DOGLCD_CS, arg_val ? LOW : HIGH);
break;
case U8G_COM_MSG_RESET:
WRITE(LCD_RESET_PIN, arg_val);
break;
case U8G_COM_MSG_WRITE_BYTE:
spiSend((uint8_t)arg_val);
break;
case U8G_COM_MSG_WRITE_SEQ:
uint8_t *ptr = (uint8_t*) arg_ptr;
while (arg_val > 0) {
spiSend(*ptr++);
arg_val--;
}
break;
}
return 1;
}
#endif // EITHER(MKS_MINI_12864, FYSETC_MINI_12864_2_1)
#endif // ARDUINO_ARCH_ESP32

2
Marlin/src/HAL/ESP32/wifi.cpp

@ -59,7 +59,7 @@ void wifi_init() {
MDNS.addService("http", "tcp", 80); MDNS.addService("http", "tcp", 80);
SERIAL_ECHOLNPAIR("Successfully connected to WiFi with SSID '" WIFI_SSID "', hostname: '" WIFI_HOSTNAME "', IP address: ", WiFi.localIP().toString().c_str()); SERIAL_ECHOLNPGM("Successfully connected to WiFi with SSID '" WIFI_SSID "', hostname: '" WIFI_HOSTNAME "', IP address: ", WiFi.localIP().toString().c_str());
} }
#endif // WIFISUPPORT #endif // WIFISUPPORT

5
Marlin/src/HAL/HAL.h

@ -28,6 +28,7 @@
#endif #endif
#include HAL_PATH(.,HAL.h) #include HAL_PATH(.,HAL.h)
extern MarlinHAL hal;
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION) #define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
@ -44,7 +45,3 @@
#ifndef PGMSTR #ifndef PGMSTR
#define PGMSTR(NAM,STR) const char NAM[] = STR #define PGMSTR(NAM,STR) const char NAM[] = STR
#endif #endif
inline void watchdog_refresh() {
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
}

37
Marlin/src/HAL/LINUX/HAL.cpp

@ -24,6 +24,10 @@
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h" #include "../shared/Delay.h"
// ------------------------
// Serial ports
// ------------------------
MSerialT usb_serial(TERN0(EMERGENCY_PARSER, true)); MSerialT usb_serial(TERN0(EMERGENCY_PARSER, true));
// U8glib required functions // U8glib required functions
@ -37,42 +41,21 @@ extern "C" {
//************************// //************************//
// return free heap space // return free heap space
int freeMemory() { int freeMemory() { return 0; }
return 0;
}
// ------------------------ // ------------------------
// ADC // ADC
// ------------------------ // ------------------------
void HAL_adc_init() { uint8_t MarlinHAL::active_ch = 0;
}
void HAL_adc_enable_channel(const uint8_t ch) {
}
uint8_t active_ch = 0;
void HAL_adc_start_conversion(const uint8_t ch) {
active_ch = ch;
}
bool HAL_adc_finished() {
return true;
}
uint16_t HAL_adc_get_result() { uint16_t MarlinHAL::adc_value() {
pin_t pin = analogInputToDigitalPin(active_ch); const pin_t pin = analogInputToDigitalPin(active_ch);
if (!VALID_PIN(pin)) return 0; if (!VALID_PIN(pin)) return 0;
uint16_t data = ((Gpio::get(pin) >> 2) & 0x3FF); const uint16_t data = ((Gpio::get(pin) >> 2) & 0x3FF);
return data; // return 10bit value as Marlin expects return data; // return 10bit value as Marlin expects
} }
void HAL_pwm_init() { void MarlinHAL::reboot() { /* Reset the application state and GPIO */ }
}
void HAL_reboot() { /* Reset the application state and GPIO */ }
#endif // __PLAT_LINUX__ #endif // __PLAT_LINUX__

158
Marlin/src/HAL/LINUX/HAL.h

@ -21,25 +21,42 @@
*/ */
#pragma once #pragma once
#define CPU_32_BIT #include "../../inc/MarlinConfigPre.h"
#define F_CPU 100000000UL
#define SystemCoreClock F_CPU
#include <iostream> #include <iostream>
#include <stdint.h> #include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#undef min #undef min
#undef max #undef max
#include <algorithm> #include <algorithm>
void _printf (const char *format, ...); #include "hardware/Clock.h"
#include "../shared/Marduino.h"
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "serial.h"
// ------------------------
// Defines
// ------------------------
#define CPU_32_BIT
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
#define F_CPU 100000000UL
#define SystemCoreClock F_CPU
#define DELAY_CYCLES(x) Clock::delayCycles(x)
#define CPU_ST7920_DELAY_1 600
#define CPU_ST7920_DELAY_2 750
#define CPU_ST7920_DELAY_3 750
void _printf(const char *format, ...);
void _putc(uint8_t c); void _putc(uint8_t c);
uint8_t _getc(); uint8_t _getc();
//extern "C" volatile uint32_t _millis;
//arduino: Print.h //arduino: Print.h
#define DEC 10 #define DEC 10
#define HEX 16 #define HEX 16
@ -49,67 +66,100 @@ uint8_t _getc();
#define B01 1 #define B01 1
#define B10 2 #define B10 2
#include "hardware/Clock.h" // ------------------------
// Serial ports
#include "../shared/Marduino.h" // ------------------------
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "watchdog.h"
#include "serial.h"
#define SHARED_SERVOS HAS_SERVOS
extern MSerialT usb_serial; extern MSerialT usb_serial;
#define MYSERIAL1 usb_serial #define MYSERIAL1 usb_serial
#define ST7920_DELAY_1 DELAY_NS(600)
#define ST7920_DELAY_2 DELAY_NS(750)
#define ST7920_DELAY_3 DELAY_NS(750)
// //
// Interrupts // Interrupts
// //
#define CRITICAL_SECTION_START() #define CRITICAL_SECTION_START()
#define CRITICAL_SECTION_END() #define CRITICAL_SECTION_END()
#define ISRS_ENABLED()
#define ENABLE_ISRS()
#define DISABLE_ISRS()
inline void HAL_init() {} // ADC
#define HAL_ADC_VREF 5.0
#define HAL_ADC_RESOLUTION 10
// Utility functions // ------------------------
// Class Utilities
// ------------------------
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000 #if GCC_VERSION <= 50000
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-function"
#endif #endif
int freeMemory(); int freeMemory();
#if GCC_VERSION <= 50000 #pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif
// ADC // ------------------------
#define HAL_ADC_VREF 5.0 // MarlinHAL Class
#define HAL_ADC_RESOLUTION 10 // ------------------------
#define HAL_ANALOG_SELECT(ch) HAL_adc_enable_channel(ch)
#define HAL_START_ADC(ch) HAL_adc_start_conversion(ch) class MarlinHAL {
#define HAL_READ_ADC() HAL_adc_get_result() public:
#define HAL_ADC_READY() true
// Earliest possible init, before setup()
void HAL_adc_init(); MarlinHAL() {}
void HAL_adc_enable_channel(const uint8_t ch);
void HAL_adc_start_conversion(const uint8_t ch); // Watchdog
uint16_t HAL_adc_get_result(); static void watchdog_init() {}
static void watchdog_refresh() {}
// Reset source
inline void HAL_clear_reset_source(void) {} static void init() {} // Called early in setup()
inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; } static void init_board() {} // Called less early in setup()
static void reboot(); // Reset the application state and GPIO
void HAL_reboot(); // Reset the application state and GPIO
// Interrupts
/* ---------------- Delay in cycles */ static bool isr_state() { return true; }
FORCE_INLINE static void DELAY_CYCLES(uint64_t x) { static void isr_on() {}
Clock::delayCycles(x); static void isr_off() {}
}
static void delay_ms(const int ms) { _delay_ms(ms); }
// Tasks, called from idle()
static void idletask() {}
// Reset
static constexpr uint8_t reset_reason = RST_POWER_ON;
static uint8_t get_reset_source() { return reset_reason; }
static void clear_reset_source() {}
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
static uint8_t active_ch;
// Called by Temperature::init once at startup
static void adc_init() {}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t) {}
// Begin ADC sampling on the given channel
static void adc_start(const uint8_t ch) { active_ch = ch; }
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value();
/**
* Set the PWM duty cycle for the pin to the given value.
* No option to change the resolution or invert the duty cycle.
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
analogWrite(pin, v);
}
static void set_pwm_frequency(const pin_t, int) {}
};

10
Marlin/src/HAL/TEENSY40_41/watchdog.h → Marlin/src/HAL/LINUX/MarlinSPI.h

@ -1,6 +1,6 @@
/** /**
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* *
* Based on Sprinter and grbl. * Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
@ -21,10 +21,6 @@
*/ */
#pragma once #pragma once
/** #include <SPI.h>
* HAL Watchdog for Teensy 4.0 (IMXRT1062DVL6A) / 4.1 (IMXRT1062DVJ6A)
*/
void watchdog_init();
void HAL_watchdog_refresh(); using MarlinSPI = SPIClass;

4
Marlin/src/HAL/LINUX/arduino.cpp

@ -31,9 +31,7 @@ void cli() { } // Disable
void sei() { } // Enable void sei() { } // Enable
// Time functions // Time functions
void _delay_ms(const int delay_ms) { void _delay_ms(const int ms) { delay(ms); }
delay(delay_ms);
}
uint32_t millis() { uint32_t millis() {
return (uint32_t)Clock::millis(); return (uint32_t)Clock::millis();

16
Marlin/src/HAL/LINUX/eeprom.cpp

@ -69,12 +69,12 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
std::size_t bytes_written = 0; std::size_t bytes_written = 0;
for (std::size_t i = 0; i < size; i++) { for (std::size_t i = 0; i < size; i++) {
buffer[pos+i] = value[i]; buffer[pos + i] = value[i];
bytes_written ++; bytes_written++;
} }
crc16(crc, value, size); crc16(crc, value, size);
pos = pos + size; pos += size;
return (bytes_written != size); // return true for any error return (bytes_written != size); // return true for any error
} }
@ -82,21 +82,21 @@ bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uin
std::size_t bytes_read = 0; std::size_t bytes_read = 0;
if (writing) { if (writing) {
for (std::size_t i = 0; i < size; i++) { for (std::size_t i = 0; i < size; i++) {
value[i] = buffer[pos+i]; value[i] = buffer[pos + i];
bytes_read ++; bytes_read++;
} }
crc16(crc, value, size); crc16(crc, value, size);
} }
else { else {
uint8_t temp[size]; uint8_t temp[size];
for (std::size_t i = 0; i < size; i++) { for (std::size_t i = 0; i < size; i++) {
temp[i] = buffer[pos+i]; temp[i] = buffer[pos + i];
bytes_read ++; bytes_read++;
} }
crc16(crc, temp, size); crc16(crc, temp, size);
} }
pos = pos + size; pos += size;
return bytes_read != size; // return true for any error return bytes_read != size; // return true for any error
} }

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save