mirror of https://github.com/mriscoc/Ender3V2S1
## What's new in NEW YEAR 2023 release ##
- Support for Input Shaping in the Special Configuration repository - Add MPC as default for precompiled version if program memory space allows it - TMC Trinamic driver current editor menu when it is supported (not for standalone) - Menu item for enable/disable Adaptive Step Smoothing when it is supported - Reset Print stats confirmation - Show message when is not possible to park head on pause - Preheat hotend menu for Prepare/Filament management menu - Mesh Leveling progress viewer - Added PETG Preheat in precompiled versions (Current source supports 10 material preheats) - And many improvements and fixes From Marlin 2.1.2 - More SCURVE cycles on unoptimized cortex-m0 (#24955) - Fix G-code resend race condition - G30 move to logical XY (#24953) - and many more fixes from latest bugfix 2.1.xpull/668/head 20221222
parent
8f2d09c334
commit
72b6093669
@ -0,0 +1,23 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[{*.patch,syntax_test_*}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{*.c,*.cpp,*.h,*.ino}]
|
||||
charset = utf-8
|
||||
|
||||
[{*.c,*.cpp,*.h,*.ino,Makefile}]
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[{*.py}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[{*.conf,*.sublime-project}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
@ -0,0 +1,21 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Files with Unix line endings
|
||||
*.c text eol=lf
|
||||
*.cpp text eol=lf
|
||||
*.h text eol=lf
|
||||
*.ino text eol=lf
|
||||
*.py text eol=lf
|
||||
*.sh text eol=lf
|
||||
*.scad text eol=lf
|
||||
|
||||
# Files with native line endings
|
||||
# *.sln text
|
||||
|
||||
# Binary files
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.fon binary
|
||||
*.bin binary
|
||||
*.woff binary
|
@ -0,0 +1,14 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📖 Professional Firmware Documentation
|
||||
url: https://github.com/mriscoc/Ender3V2S1/wiki
|
||||
about: Lots of documentation about firmware settings and features.
|
||||
- name: 📖 Marlin Documentation
|
||||
url: https://marlinfw.org/
|
||||
about: Lots of documentation on installing and using Marlin.
|
||||
- name: 👤 Professional Firmware Facebook group
|
||||
url: https://www.facebook.com/groups/513889302986197
|
||||
about: Please ask and answer questions here.
|
||||
- name: 💸 Want to donate?
|
||||
url: https://www.paypal.com/paypalme/mriscoc
|
||||
about: Your contribution to this project is always welcome!
|
@ -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.
|
@ -1,23 +1,33 @@
|
||||
### Requirements
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
* Filling out this template is required. Pull Requests without a clear description may be closed at the maintainers' discretion.
|
||||
-->
|
||||
|
||||
### Description
|
||||
|
||||
<!--
|
||||
|
||||
We must be able to understand your proposed change from this description. If we can't understand what the code will do from this description, the Pull Request may be closed at the maintainers' discretion. Keep in mind that the maintainer reviewing this PR may not be familiar with or have worked with the code recently, so please walk us through the concepts.
|
||||
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 fix or improve? -->
|
||||
<!-- What does this PR fix or improve? -->
|
||||
|
||||
### Configurations
|
||||
|
||||
<!-- Attach any Configuration.h, Configuration_adv.h, or platformio.ini files needed to compile/test your Pull Request. -->
|
||||
<!-- Attach Configurations ZIP and any other files needed to test this PR. -->
|
||||
|
||||
### Related Issues
|
||||
|
||||
<!-- Whether this fixes a bug or fulfills a feature request, please list any related Issues here. -->
|
||||
<!-- Does this PR fix a bug or fulfill a Feature Request? Link related Issues here. -->
|
||||
|
@ -0,0 +1,59 @@
|
||||
#
|
||||
# bump-date.yml
|
||||
# Bump the distribution date once per day
|
||||
#
|
||||
|
||||
name: Bump Distribution Date
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 */6 * * *'
|
||||
|
||||
jobs:
|
||||
bump_date:
|
||||
name: Bump Distribution Date
|
||||
if: github.repository == 'MarlinFirmware/Marlin'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out bugfix-2.1.x
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: bugfix-2.1.x
|
||||
|
||||
- name: Bump Date (bugfix-2.0.x)
|
||||
run: |
|
||||
# Inline Bump Script
|
||||
if [[ ! "$( git log -1 --pretty=%B )" =~ ^\[cron\] ]]; then
|
||||
DIST=$( date +"%Y-%m-%d" )
|
||||
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/src/inc/Version.h" && \
|
||||
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/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
|
||||
fi
|
||||
exit 0
|
||||
|
||||
- name: Check out bugfix-2.1.x
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: bugfix-2.1.x
|
||||
|
||||
- name: Bump Date (bugfix-2.1.x)
|
||||
run: |
|
||||
# Inline Bump Script
|
||||
if [[ ! "$( git log -1 --pretty=%B )" =~ ^\[cron\] ]]; then
|
||||
DIST=$( date +"%Y-%m-%d" )
|
||||
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/src/inc/Version.h" && \
|
||||
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/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
|
||||
fi
|
||||
exit 0
|
@ -0,0 +1,34 @@
|
||||
#
|
||||
# check-pr.yml
|
||||
# Close PRs directed at release branches
|
||||
#
|
||||
|
||||
name: PR Bad Target
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
branches:
|
||||
- 1.0.x
|
||||
- 1.1.x
|
||||
- 2.0.x
|
||||
- 2.1.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.1.x` branch and be careful to target `bugfix-2.1.x` when resubmitting the PR. Patches may also target `bugfix-2.0.x` if they are specifically for 2.0.9.x.
|
||||
|
||||
It may help to set your fork's default branch to `bugfix-2.1.x`.
|
||||
|
||||
See [this page](https://marlinfw.org/docs/development/getting_started_pull_requests.html) for full instructions.
|
@ -0,0 +1,39 @@
|
||||
#
|
||||
# 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 }}
|
@ -0,0 +1,28 @@
|
||||
#
|
||||
# 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: More Data,Needs: Discussion,Needs: Documentation,Needs: Patch,Needs: Work,Needs: Testing,help wanted,no-locking'
|
@ -0,0 +1,32 @@
|
||||
#
|
||||
# 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: ''
|
||||
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: ''
|
@ -0,0 +1,22 @@
|
||||
#
|
||||
# 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 }}"
|
@ -0,0 +1,172 @@
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
# Generated files
|
||||
_Version.h
|
||||
bdf2u8g
|
||||
marlin_config.json
|
||||
mczip.h
|
||||
*.gen
|
||||
*.sublime-workspace
|
||||
|
||||
#
|
||||
# OS
|
||||
#
|
||||
applet/
|
||||
.DS_Store
|
||||
|
||||
#
|
||||
# Misc
|
||||
#
|
||||
*~
|
||||
*.orig
|
||||
*.rej
|
||||
*.bak
|
||||
*.idea
|
||||
*.i
|
||||
*.ii
|
||||
*.swp
|
||||
tags
|
||||
|
||||
#
|
||||
# C++
|
||||
#
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
*.ino.cpp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
#
|
||||
# C
|
||||
#
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
|
||||
# PlatformIO files/dirs
|
||||
.pio*
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
/lib/
|
||||
|
||||
# Secure Credentials
|
||||
Configuration_Secure.h
|
||||
|
||||
# Visual Studio
|
||||
*.sln
|
||||
*.vcxproj
|
||||
*.vcxproj.user
|
||||
*.vcxproj.filters
|
||||
Release/
|
||||
Debug/
|
||||
__vm/
|
||||
.vs/
|
||||
vc-fileutils.settings
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
|
||||
#Simulation
|
||||
imgui.ini
|
||||
eeprom.dat
|
||||
spi_flash.bin
|
||||
fs.img
|
||||
|
||||
#cmake
|
||||
CMakeLists.txt
|
||||
src/CMakeLists.txt
|
||||
CMakeListsPrivate.txt
|
||||
build/
|
||||
|
||||
# CLion
|
||||
cmake-build-*
|
||||
|
||||
# Eclipse
|
||||
.project
|
||||
.cproject
|
||||
.pydevproject
|
||||
.settings
|
||||
.classpath
|
||||
|
||||
# Python
|
||||
__pycache__
|
||||
|
||||
# IOLogger logs
|
||||
*_log.csv
|
@ -0,0 +1,52 @@
|
||||
help:
|
||||
@echo "Tasks for local development:"
|
||||
@echo "* tests-single-ci: Run a single test from inside the CI"
|
||||
@echo "* tests-single-local: Run a single test locally"
|
||||
@echo "* tests-single-local-docker: Run a single test locally, using docker-compose"
|
||||
@echo "* tests-all-local: Run all tests locally"
|
||||
@echo "* tests-all-local-docker: Run all tests locally, using docker-compose"
|
||||
@echo "* setup-local-docker: Setup local docker-compose"
|
||||
@echo ""
|
||||
@echo "Options for testing:"
|
||||
@echo " TEST_TARGET Set when running tests-single-*, to select the"
|
||||
@echo " test. If you set it to ALL it will run all "
|
||||
@echo " tests, but some of them are broken: use "
|
||||
@echo " tests-all-* instead to run only the ones that "
|
||||
@echo " run on GitHub CI"
|
||||
@echo " ONLY_TEST Limit tests to only those that contain this, or"
|
||||
@echo " the index of the test (1-based)"
|
||||
@echo " VERBOSE_PLATFORMIO If you want the full PIO output, set any value"
|
||||
@echo " GIT_RESET_HARD Used by CI: reset all local changes. WARNING:"
|
||||
@echo " THIS WILL UNDO ANY CHANGES YOU'VE MADE!"
|
||||
.PHONY: help
|
||||
|
||||
tests-single-ci:
|
||||
export GIT_RESET_HARD=true
|
||||
$(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET)
|
||||
.PHONY: tests-single-ci
|
||||
|
||||
tests-single-local:
|
||||
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local" ; return 1; fi
|
||||
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
|
||||
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
|
||||
&& run_tests . $(TEST_TARGET) "$(ONLY_TEST)"
|
||||
.PHONY: tests-single-local
|
||||
|
||||
tests-single-local-docker:
|
||||
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local-docker" ; return 1; fi
|
||||
docker-compose run --rm marlin $(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET) VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) ONLY_TEST="$(ONLY_TEST)"
|
||||
.PHONY: tests-single-local-docker
|
||||
|
||||
tests-all-local:
|
||||
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
|
||||
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
|
||||
&& for TEST_TARGET in $$(./get_test_targets.py) ; do echo "Running tests for $$TEST_TARGET" ; run_tests . $$TEST_TARGET ; done
|
||||
.PHONY: tests-all-local
|
||||
|
||||
tests-all-local-docker:
|
||||
docker-compose run --rm marlin $(MAKE) tests-all-local VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD)
|
||||
.PHONY: tests-all-local-docker
|
||||
|
||||
setup-local-docker:
|
||||
docker-compose build
|
||||
.PHONY: setup-local-docker
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,57 @@
|
||||
/*==============================================================================
|
||||
|
||||
Marlin Firmware
|
||||
|
||||
(c) 2011-2020 MarlinFirmware
|
||||
Portions of Marlin are (c) by their respective authors.
|
||||
All code complies with GPLv2 and/or GPLv3
|
||||
|
||||
================================================================================
|
||||
|
||||
Greetings! Thank you for choosing Marlin 2 as your 3D printer firmware.
|
||||
|
||||
To configure Marlin you must edit Configuration.h and Configuration_adv.h
|
||||
located in the root 'Marlin' folder. Check our Configurations repository to
|
||||
see if there's a more suitable starting-point for your specific hardware.
|
||||
|
||||
Before diving in, we recommend the following essential links:
|
||||
|
||||
Marlin Firmware Official Website
|
||||
|
||||
- https://marlinfw.org/
|
||||
The official Marlin Firmware website contains the most up-to-date
|
||||
documentation. Contributions are always welcome!
|
||||
|
||||
Configuration
|
||||
|
||||
- https://github.com/MarlinFirmware/Configurations
|
||||
Example configurations for several printer models.
|
||||
|
||||
- https://www.youtube.com/watch?v=3gwWVFtdg-4
|
||||
A good 20-minute overview of Marlin configuration by Tom Sanladerer.
|
||||
(Applies to Marlin 1.0.x, so Jerk and Acceleration should be halved.)
|
||||
Also... https://www.google.com/search?tbs=vid%3A1&q=configure+marlin
|
||||
|
||||
- https://marlinfw.org/docs/configuration/configuration.html
|
||||
Marlin's configuration options are explained in more detail here.
|
||||
|
||||
Getting Help
|
||||
|
||||
- https://reprap.org/forum/list.php?415
|
||||
The Marlin Discussion Forum is a great place to get help from other Marlin
|
||||
users who may have experienced similar issues to your own.
|
||||
|
||||
- https://github.com/MarlinFirmware/Marlin/issues
|
||||
With a free GitHub account you can provide us with feedback, bug reports,
|
||||
and feature requests via the Marlin Issue Queue.
|
||||
|
||||
Contributing
|
||||
|
||||
- https://marlinfw.org/docs/development/contributing.html
|
||||
If you'd like to contribute to Marlin, read this first!
|
||||
|
||||
- https://marlinfw.org/docs/development/coding_standards.html
|
||||
Before submitting code get to know the Coding Standards.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------*/
|
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
////////////////////////////
|
||||
// VENDOR VERSION EXAMPLE //
|
||||
////////////////////////////
|
||||
|
||||
/**
|
||||
* Marlin release version identifier
|
||||
*/
|
||||
#define SHORT_BUILD_VERSION "2.1.3 MRiscoC"
|
||||
|
||||
/**
|
||||
* Verbose version identifier which should contain a reference to the location
|
||||
* from where the binary was downloaded or the source code was compiled.
|
||||
*/
|
||||
#define DETAILED_BUILD_VERSION SHORT_BUILD_VERSION " Ender3V2-422-MM, based on bugfix-2.1.x"
|
||||
|
||||
/**
|
||||
* The STRING_DISTRIBUTION_DATE represents when the binary file was built,
|
||||
* here we define this default string as the date where the latest release
|
||||
* version was tagged.
|
||||
*/
|
||||
//#define STRING_DISTRIBUTION_DATE "2022-12-14"
|
||||
|
||||
#define STRING_DISTRIBUTION_DATE __DATE__
|
||||
#define STRING_DISTRIBUTION_TIME __TIME__
|
||||
|
||||
/**
|
||||
* Defines a generic printer name to be output to the LCD after booting Marlin.
|
||||
*/
|
||||
#define MACHINE_NAME "Ender 3V2"
|
||||
|
||||
/**
|
||||
* The SOURCE_CODE_URL is the location where users will find the Marlin Source
|
||||
* Code which is installed on the device. In most cases —unless the manufacturer
|
||||
* has a distinct Github fork— the Source Code URL should just be the main
|
||||
* Marlin repository.
|
||||
*/
|
||||
#define SOURCE_CODE_URL "github.com/mriscoc/Ender3V2S1"
|
||||
|
||||
/**
|
||||
* Default generic printer UUID.
|
||||
*/
|
||||
//#define DEFAULT_MACHINE_UUID "cede2a2f-41a2-4748-9b12-c55c62f367ff"
|
||||
|
||||
/**
|
||||
* The WEBSITE_URL is the location where users can get more information such as
|
||||
* documentation about a specific Marlin release.
|
||||
*/
|
||||
#define WEBSITE_URL "github.com/mriscoc/Ender3V2S1/wiki"
|
||||
|
||||
/**
|
||||
* Set the vendor info the serial USB interface, if changable
|
||||
* Currently only supported by DUE platform
|
||||
*/
|
||||
//#define USB_DEVICE_VENDOR_ID 0x0000
|
||||
//#define USB_DEVICE_PRODUCT_ID 0x0000
|
||||
//#define USB_DEVICE_MANUFACTURE_NAME WEBSITE_URL
|
@ -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
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,36 @@
|
||||
|
||||
This directory is intended for the project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link to executable file.
|
||||
|
||||
The source code of each library should be placed in separate directory, like
|
||||
"lib/private_lib/[here are source files]".
|
||||
|
||||
For example, see how can be organized `Foo` and `Bar` libraries:
|
||||
|
||||
|--lib
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |- readme.txt --> THIS FILE
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
Then in `src/main.c` you should use:
|
||||
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
// rest H/C/CPP code
|
||||
|
||||
PlatformIO will find your libraries automatically, configure preprocessor's
|
||||
include paths and build them.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "platforms.h"
|
||||
|
||||
#ifndef GCC_VERSION
|
||||
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#endif
|
||||
|
||||
#include HAL_PATH(.,HAL.h)
|
||||
extern MarlinHAL hal;
|
||||
|
||||
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
|
||||
|
||||
#ifndef I2C_ADDRESS
|
||||
#define I2C_ADDRESS(A) uint8_t(A)
|
||||
#endif
|
||||
|
||||
// Needed for AVR sprintf_P PROGMEM extension
|
||||
#ifndef S_FMT
|
||||
#define S_FMT "%s"
|
||||
#endif
|
||||
|
||||
// String helper
|
||||
#ifndef PGMSTR
|
||||
#define PGMSTR(NAM,STR) const char NAM[] = STR
|
||||
#endif
|
@ -0,0 +1,212 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#include <wiring_private.h>
|
||||
|
||||
#if USING_HW_SERIALUSB
|
||||
DefaultSerial1 MSerialUSB(false, SerialUSB);
|
||||
#endif
|
||||
#if USING_HW_SERIAL0
|
||||
DefaultSerial2 MSerial1(false, Serial1);
|
||||
#endif
|
||||
#if USING_HW_SERIAL1
|
||||
DefaultSerial3 MSerial2(false, Serial2);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define WDT_CONFIG_PER_7_Val 0x9u
|
||||
#define WDT_CONFIG_PER_Pos 0
|
||||
#define WDT_CONFIG_PER_7 (WDT_CONFIG_PER_7_Val << WDT_CONFIG_PER_Pos)
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
#define WDT_TIMEOUT_REG TERN(WATCHDOG_DURATION_8S, WDT_CONFIG_PER_CYC8192, WDT_CONFIG_PER_CYC4096) // 4 or 8 second timeout
|
||||
|
||||
void MarlinHAL::watchdog_init() {
|
||||
// Set up the generic clock (GCLK2) used to clock the watchdog timer at 1.024kHz
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_DIV(4) | // Divide the 32.768kHz clock source by divisor 32, where 2^(4 + 1): 32.768kHz/32=1.024kHz
|
||||
GCLK_GENDIV_ID(2); // Select Generic Clock (GCLK) 2
|
||||
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
|
||||
REG_GCLK_GENCTRL = GCLK_GENCTRL_DIVSEL | // Set to divide by 2^(GCLK_GENDIV_DIV(4) + 1)
|
||||
GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
|
||||
GCLK_GENCTRL_GENEN | // Enable GCLK2
|
||||
GCLK_GENCTRL_SRC_OSCULP32K | // Set the clock source to the ultra low power oscillator (OSCULP32K)
|
||||
GCLK_GENCTRL_ID(2); // Select GCLK2
|
||||
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
|
||||
// Feed GCLK2 to WDT (Watchdog Timer)
|
||||
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK2 to the WDT
|
||||
GCLK_CLKCTRL_GEN_GCLK2 | // Select GCLK2
|
||||
GCLK_CLKCTRL_ID_WDT; // Feed the GCLK2 to the WDT
|
||||
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
|
||||
WDT->CONFIG.bit.PER = WDT_CONFIG_PER_7; // Set the WDT reset timeout to 4 seconds
|
||||
while (WDT->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
REG_WDT_CTRL = WDT_CTRL_ENABLE; // Enable the WDT in normal mode
|
||||
while (WDT->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
}
|
||||
|
||||
// Reset watchdog. MUST be called at least every 4 seconds after the
|
||||
// first watchdog_init or SAMD will go into emergency procedures.
|
||||
void MarlinHAL::watchdog_refresh() {
|
||||
WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;
|
||||
while (WDT->STATUS.bit.SYNCBUSY);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
// Types
|
||||
// ------------------------
|
||||
|
||||
// ------------------------
|
||||
// Private Variables
|
||||
// ------------------------
|
||||
|
||||
// ------------------------
|
||||
// Private functions
|
||||
// ------------------------
|
||||
|
||||
void MarlinHAL::dma_init() {}
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
// HAL initialization task
|
||||
void MarlinHAL::init() {
|
||||
TERN_(DMA_IS_REQUIRED, dma_init());
|
||||
#if ENABLED(SDSUPPORT)
|
||||
#if HAS_SD_DETECT && SD_CONNECTION_IS(ONBOARD)
|
||||
SET_INPUT_PULLUP(SD_DETECT_PIN);
|
||||
#endif
|
||||
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma push_macro("WDT")
|
||||
#undef WDT // Required to be able to use '.bit.WDT'. Compiler wrongly replace struct field with WDT define
|
||||
uint8_t MarlinHAL::get_reset_source() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
#pragma pop_macro("WDT")
|
||||
|
||||
void MarlinHAL::reboot() { NVIC_SystemReset(); }
|
||||
|
||||
extern "C" {
|
||||
void * _sbrk(int incr);
|
||||
extern unsigned int __bss_end__; // end of bss section
|
||||
}
|
||||
|
||||
// Return free memory between end of heap (or end bss) and whatever is current
|
||||
int freeMemory() {
|
||||
int free_memory, heap_end = (int)_sbrk(0);
|
||||
return (int)&free_memory - (heap_end ?: (int)&__bss_end__);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// ADC
|
||||
// ------------------------
|
||||
|
||||
uint16_t MarlinHAL::adc_result;
|
||||
|
||||
void MarlinHAL::adc_init() {
|
||||
/* thanks to https://www.eevblog.com/forum/microcontrollers/samd21g18-adc-with-resrdy-interrupts-only-reads-once-or-twice/ */
|
||||
|
||||
ADC->CTRLA.bit.ENABLE = false;
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
// load chip corrections
|
||||
uint32_t bias = (*((uint32_t *) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;
|
||||
uint32_t linearity = (*((uint32_t *) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
|
||||
linearity |= ((*((uint32_t *) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
|
||||
|
||||
/* Wait for bus synchronization. */
|
||||
while (ADC->STATUS.bit.SYNCBUSY) {};
|
||||
|
||||
ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity);
|
||||
|
||||
/* Wait for bus synchronization. */
|
||||
while (ADC->STATUS.bit.SYNCBUSY) {};
|
||||
|
||||
ADC->CTRLA.bit.SWRST = true;
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
ADC->REFCTRL.reg = ADC_REFCTRL_REFSEL_INTVCC1;
|
||||
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_32| ADC_AVGCTRL_ADJRES(4);;
|
||||
|
||||
|
||||
ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV128 |
|
||||
ADC_CTRLB_RESSEL_16BIT |
|
||||
ADC_CTRLB_FREERUN;
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
ADC->SAMPCTRL.bit.SAMPLEN = 0x00;
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
ADC->INPUTCTRL.reg = ADC_INPUTCTRL_INPUTSCAN(HAL_ADC_AIN_LEN) // scan (INPUTSCAN + NUM_EXTUDERS - 1) pins
|
||||
| ADC_INPUTCTRL_GAIN_DIV2 |ADC_INPUTCTRL_MUXNEG_GND| HAL_ADC_AIN_START ; /* set to first AIN */
|
||||
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
ADC->INTENSET.reg |= ADC_INTENSET_RESRDY; // enable Result Ready ADC interrupts
|
||||
while (ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
NVIC_EnableIRQ(ADC_IRQn); // enable ADC interrupts
|
||||
|
||||
NVIC_SetPriority(ADC_IRQn, 3);
|
||||
|
||||
ADC->CTRLA.bit.ENABLE = true;
|
||||
}
|
||||
|
||||
volatile uint32_t adc_results[HAL_ADC_AIN_NUM_SENSORS];
|
||||
|
||||
void ADC_Handler() {
|
||||
while(ADC->STATUS.bit.SYNCBUSY == 1);
|
||||
int pos = ADC->INPUTCTRL.bit.INPUTOFFSET;
|
||||
|
||||
adc_results[pos] = ADC->RESULT.reg; /* Read the value. */
|
||||
ADC->INTFLAG.reg = ADC_INTENSET_RESRDY; /* Clear the data ready flag. */
|
||||
}
|
||||
|
||||
void MarlinHAL::adc_start(const pin_t pin) {
|
||||
/* due to the way INPUTOFFSET works, the last sensor is the first position in the array
|
||||
and we want the ADC_handler interrupt to be as simple possible, so we do the calculation here.
|
||||
*/
|
||||
unsigned int pos = PIN_TO_INPUTCTRL(pin) - HAL_ADC_AIN_START + 1;
|
||||
if (pos == HAL_ADC_AIN_NUM_SENSORS) pos = 0;
|
||||
adc_result = adc_results[pos]; // 16-bit resolution
|
||||
//adc_result = 0xFFFF;
|
||||
}
|
||||
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,223 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#define CPU_32_BIT
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
#include "../shared/math_32bit.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
|
||||
// ------------------------
|
||||
// Serial ports
|
||||
// ------------------------
|
||||
#include "../../core/serial_hook.h"
|
||||
typedef ForwardSerial1Class< decltype(SerialUSB) > DefaultSerial1;
|
||||
extern DefaultSerial1 MSerialUSB;
|
||||
|
||||
// Serial ports
|
||||
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
|
||||
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
|
||||
|
||||
extern DefaultSerial2 MSerial0;
|
||||
extern DefaultSerial3 MSerial1;
|
||||
|
||||
|
||||
#define __MSERIAL(X) MSerial##X
|
||||
#define _MSERIAL(X) __MSERIAL(X)
|
||||
#define MSERIAL(X) _MSERIAL(INCREMENT(X))
|
||||
|
||||
#if WITHIN(SERIAL_PORT, 0, 1)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#elif SERIAL_PORT == -1
|
||||
#define MYSERIAL1 MSerialUSB
|
||||
#else
|
||||
#error "SERIAL_PORT must be -1 (Native USB only)."
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if WITHIN(SERIAL_PORT_2, 0, 1)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT)
|
||||
#elif SERIAL_PORT_2 == -1
|
||||
#define MYSERIAL2 MSerialUSB
|
||||
#else
|
||||
#error "SERIAL_PORT_2 must be -1 (Native USB only)."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MMU2_SERIAL_PORT
|
||||
#if WITHIN(MMU2_SERIAL_PORT, 0, 1)
|
||||
#define MMU2_SERIAL MSERIAL(SERIAL_PORT)
|
||||
#elif MMU2_SERIAL_PORT == -1
|
||||
#define MMU2_SERIAL MSerialUSB
|
||||
#else
|
||||
#error "MMU2_SERIAL_PORT must be -1 (Native USB only)."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LCD_SERIAL_PORT
|
||||
#if WITHIN(LCD_SERIAL_PORT, 0, 1)
|
||||
#define LCD_SERIAL MSERIAL(SERIAL_PORT)
|
||||
#elif LCD_SERIAL_PORT == -1
|
||||
#define LCD_SERIAL MSerialUSB
|
||||
#else
|
||||
#error "LCD_SERIAL_PORT must be -1 (Native USB only)."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef int8_t pin_t;
|
||||
|
||||
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
|
||||
|
||||
class Servo;
|
||||
typedef Servo hal_servo_t;
|
||||
|
||||
//
|
||||
// Interrupts
|
||||
//
|
||||
#define CRITICAL_SECTION_START() const bool irqon = !__get_PRIMASK(); __disable_irq()
|
||||
#define CRITICAL_SECTION_END() if (irqon) __enable_irq()
|
||||
|
||||
#define cli() __disable_irq() // Disable interrupts
|
||||
#define sei() __enable_irq() // Enable interrupts
|
||||
|
||||
//
|
||||
// ADC
|
||||
//
|
||||
|
||||
#define HAL_ADC_FILTERED 1 // Disable Marlin's oversampling. The HAL filters ADC values.
|
||||
#define HAL_ADC_VREF 3.3
|
||||
#define HAL_ADC_RESOLUTION 12
|
||||
#define HAL_ADC_AIN_START ADC_INPUTCTRL_MUXPOS_PIN3
|
||||
#define HAL_ADC_AIN_NUM_SENSORS 3
|
||||
#define HAL_ADC_AIN_LEN HAL_ADC_AIN_NUM_SENSORS-1
|
||||
|
||||
//
|
||||
// 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)
|
||||
|
||||
//
|
||||
// Tone
|
||||
//
|
||||
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
|
||||
void noTone(const pin_t _pin);
|
||||
|
||||
// ------------------------
|
||||
// Class Utilities
|
||||
// ------------------------
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s);
|
||||
|
||||
extern "C" int freeMemory();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// ------------------------
|
||||
// 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 from 0x0
|
||||
|
||||
// Interrupts
|
||||
static bool isr_state() { return !__get_PRIMASK(); }
|
||||
static void isr_on() { sei(); }
|
||||
static void isr_off() { cli(); }
|
||||
|
||||
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 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; }
|
||||
|
||||
/**
|
||||
* Set the PWM duty cycle for the pin to the given value.
|
||||
* No option to invert the duty cycle [default = false]
|
||||
* No option to 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=255, const bool=false) {
|
||||
analogWrite(pin, v);
|
||||
}
|
||||
|
||||
private:
|
||||
static void dma_init();
|
||||
};
|
@ -0,0 +1,148 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Hardware and software SPI implementations are included in this file.
|
||||
*
|
||||
* Control of the slave select pin(s) is handled by the calling routines and
|
||||
* SAMD21 let hardware SPI handling to remove SS from its logic.
|
||||
*/
|
||||
|
||||
#ifdef __SAMD21__
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include <SPI.h>
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if EITHER(SOFTWARE_SPI, FORCE_SOFT_SPI)
|
||||
|
||||
// ------------------------
|
||||
// Software SPI
|
||||
// ------------------------
|
||||
#error "Software SPI not supported for SAMD21. Use Hardware SPI."
|
||||
|
||||
#else // !SOFTWARE_SPI
|
||||
|
||||
static SPISettings spiConfig;
|
||||
|
||||
// ------------------------
|
||||
// Hardware SPI
|
||||
// ------------------------
|
||||
void spiBegin() {
|
||||
spiInit(SPI_HALF_SPEED);
|
||||
}
|
||||
|
||||
void spiInit(uint8_t spiRate) {
|
||||
// Use datarates Marlin uses
|
||||
uint32_t clock;
|
||||
switch (spiRate) {
|
||||
case SPI_FULL_SPEED: clock = 8000000; break;
|
||||
case SPI_HALF_SPEED: clock = 4000000; break;
|
||||
case SPI_QUARTER_SPEED: clock = 2000000; break;
|
||||
case SPI_EIGHTH_SPEED: clock = 1000000; break;
|
||||
case SPI_SIXTEENTH_SPEED: clock = 500000; break;
|
||||
case SPI_SPEED_5: clock = 250000; break;
|
||||
case SPI_SPEED_6: clock = 125000; break;
|
||||
default: clock = 4000000; break; // Default from the SPI library
|
||||
}
|
||||
spiConfig = SPISettings(clock, MSBFIRST, SPI_MODE0);
|
||||
SPI.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives a single byte from the SPI port.
|
||||
*
|
||||
* @return Byte received
|
||||
*
|
||||
* @details
|
||||
*/
|
||||
uint8_t spiRec() {
|
||||
SPI.beginTransaction(spiConfig);
|
||||
uint8_t returnByte = SPI.transfer(0xFF);
|
||||
SPI.endTransaction();
|
||||
return returnByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives a number of bytes from the SPI port to a buffer
|
||||
*
|
||||
* @param buf Pointer to starting address of buffer to write to.
|
||||
* @param nbyte Number of bytes to receive.
|
||||
* @return Nothing
|
||||
*/
|
||||
void spiRead(uint8_t *buf, uint16_t nbyte) {
|
||||
if (nbyte == 0) return;
|
||||
memset(buf, 0xFF, nbyte);
|
||||
|
||||
SPI.beginTransaction(spiConfig);
|
||||
SPI.transfer(buf, nbyte);
|
||||
SPI.endTransaction();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a single byte on SPI port
|
||||
*
|
||||
* @param b Byte to send
|
||||
*
|
||||
* @details
|
||||
*/
|
||||
void spiSend(uint8_t b) {
|
||||
SPI.beginTransaction(spiConfig);
|
||||
SPI.transfer(b);
|
||||
SPI.endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write token and then write from 512 byte buffer to SPI (for SD card)
|
||||
*
|
||||
* @param buf Pointer with buffer start address
|
||||
* @return Nothing
|
||||
*
|
||||
* @details Uses DMA
|
||||
*/
|
||||
void spiSendBlock(uint8_t token, const uint8_t *buf) {
|
||||
SPI.beginTransaction(spiConfig);
|
||||
SPI.transfer(token);
|
||||
SPI.transfer((uint8_t*)buf, 512);
|
||||
SPI.endTransaction();
|
||||
}
|
||||
|
||||
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
||||
spiConfig = SPISettings(spiClock, (BitOrder)bitOrder, dataMode);
|
||||
SPI.beginTransaction(spiConfig);
|
||||
}
|
||||
#endif // !SOFTWARE_SPI
|
||||
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
using MarlinSPI = SPIClass;
|
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(QSPI_EEPROM)
|
||||
|
||||
#include "QSPIFlash.h"
|
||||
|
||||
#define INVALID_ADDR 0xFFFFFFFF
|
||||
#define SECTOR_OF(a) (a & ~(SFLASH_SECTOR_SIZE - 1))
|
||||
#define OFFSET_OF(a) (a & (SFLASH_SECTOR_SIZE - 1))
|
||||
|
||||
Adafruit_SPIFlashBase * QSPIFlash::_flashBase = nullptr;
|
||||
uint8_t QSPIFlash::_buf[SFLASH_SECTOR_SIZE];
|
||||
uint32_t QSPIFlash::_addr = INVALID_ADDR;
|
||||
|
||||
void QSPIFlash::begin() {
|
||||
if (_flashBase) return;
|
||||
|
||||
_flashBase = new Adafruit_SPIFlashBase(new Adafruit_FlashTransport_QSPI());
|
||||
_flashBase->begin(nullptr);
|
||||
}
|
||||
|
||||
size_t QSPIFlash::size() {
|
||||
return _flashBase->size();
|
||||
}
|
||||
|
||||
uint8_t QSPIFlash::readByte(const uint32_t address) {
|
||||
if (SECTOR_OF(address) == _addr) return _buf[OFFSET_OF(address)];
|
||||
|
||||
return _flashBase->read8(address);
|
||||
}
|
||||
|
||||
void QSPIFlash::writeByte(const uint32_t address, const uint8_t value) {
|
||||
uint32_t const sector_addr = SECTOR_OF(address);
|
||||
|
||||
// Page changes, flush old and update new cache
|
||||
if (sector_addr != _addr) {
|
||||
flush();
|
||||
_addr = sector_addr;
|
||||
|
||||
// read a whole page from flash
|
||||
_flashBase->readBuffer(sector_addr, _buf, SFLASH_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
_buf[OFFSET_OF(address)] = value;
|
||||
}
|
||||
|
||||
void QSPIFlash::flush() {
|
||||
if (_addr == INVALID_ADDR) return;
|
||||
|
||||
_flashBase->eraseSector(_addr / SFLASH_SECTOR_SIZE);
|
||||
_flashBase->writeBuffer(_addr, _buf, SFLASH_SECTOR_SIZE);
|
||||
|
||||
_addr = INVALID_ADDR;
|
||||
}
|
||||
|
||||
#endif // QSPI_EEPROM
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file QSPIFlash.h
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach and Dean Miller for Adafruit Industries LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Derived from Adafruit_SPIFlash class with no SdFat references
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Adafruit_SPIFlashBase.h>
|
||||
|
||||
// This class extends Adafruit_SPIFlashBase by adding caching support.
|
||||
//
|
||||
// This class will use 4096 Bytes of RAM as a block cache.
|
||||
class QSPIFlash {
|
||||
public:
|
||||
static void begin();
|
||||
static size_t size();
|
||||
static uint8_t readByte(const uint32_t address);
|
||||
static void writeByte(const uint32_t address, const uint8_t v);
|
||||
static void flush();
|
||||
|
||||
private:
|
||||
static Adafruit_SPIFlashBase * _flashBase;
|
||||
static uint8_t _buf[SFLASH_SECTOR_SIZE];
|
||||
static uint32_t _addr;
|
||||
};
|
||||
|
||||
extern QSPIFlash qspi;
|
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#define SYNC(sc) while (sc) { \
|
||||
asm(""); \
|
||||
}
|
||||
|
||||
// Get SAMD port/pin from specified arduino pin
|
||||
#define GET_SAMD_PORT(P) _GET_SAMD_PORT(PIN_TO_SAMD_PIN(P))
|
||||
#define GET_SAMD_PIN(P) _GET_SAMD_PIN(PIN_TO_SAMD_PIN(P))
|
||||
|
||||
// Get external interrupt line associated to specified arduino pin
|
||||
#define PIN_TO_EILINE(P) _SAMDPORTPIN_TO_EILINE(GET_SAMD_PORT(P), GET_SAMD_PIN(P))
|
||||
|
||||
// Get adc/ain associated to specified arduino pin
|
||||
#define PIN_TO_ADC(P) (ANAPIN_TO_ADCAIN(P) >> 8)
|
||||
|
||||
// Private defines
|
||||
#define PIN_TO_SAMD_PIN(P) DIO##P##_PIN
|
||||
|
||||
#define _GET_SAMD_PORT(P) ((P) >> 5)
|
||||
#define _GET_SAMD_PIN(P) ((P) & 0x1F)
|
||||
|
||||
// Get external interrupt line
|
||||
#define _SAMDPORTPIN_TO_EILINE(P,B) ((P == 0 && WITHIN(B, 0, 31) && B != 26 && B != 28 && B != 29) ? (B) & 0xF \
|
||||
: (P == 1 && (WITHIN(B, 0, 25) || WITHIN(B, 30, 31))) ? (B) & 0xF \
|
||||
: (P == 1 && WITHIN(B, 26, 29)) ? 12 + (B) - 26 \
|
||||
: (P == 2 && (WITHIN(B, 0, 6) || WITHIN(B, 10, 31)) && B != 29) ? (B) & 0xF \
|
||||
: (P == 2 && B == 7) ? 9 \
|
||||
: (P == 3 && WITHIN(B, 0, 1)) ? (B) \
|
||||
: (P == 3 && WITHIN(B, 8, 12)) ? 3 + (B) - 8 \
|
||||
: (P == 3 && WITHIN(B, 20, 21)) ? 10 + (B) - 20 \
|
||||
: -1)
|
||||
|
||||
|
||||
|
||||
#define A2_AIN 3
|
||||
#define A3_AIN 4
|
||||
#define A4_AIN 5
|
||||
#define PIN_TO_AIN(P) A##P##_AIN
|
||||
#define AIN_TO_RESULT(P) ( (P - HAL_ADC_AIN_START == HAL_ADC_AIN_NUM_SENSORS-1) ? 0 : (P - HAL_ADC_AIN_START + 1) )
|
@ -0,0 +1,220 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* This comes from Arduino library which at the moment is buggy and uncompilable
|
||||
*/
|
||||
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_SERVOS
|
||||
|
||||
#include "../shared/servo.h"
|
||||
#include "../shared/servo_private.h"
|
||||
#include "SAMD21.h"
|
||||
|
||||
#define __TC_GCLK_ID(t) TC##t##_GCLK_ID
|
||||
#define _TC_GCLK_ID(t) __TC_GCLK_ID(t)
|
||||
#define TC_GCLK_ID _TC_GCLK_ID(SERVO_TC)
|
||||
|
||||
#define _TC_PRESCALER(d) TC_CTRLA_PRESCALER_DIV##d##_Val
|
||||
#define TC_PRESCALER(d) _TC_PRESCALER(d)
|
||||
|
||||
#define __SERVO_IRQn(t) TC##t##_IRQn
|
||||
#define _SERVO_IRQn(t) __SERVO_IRQn(t)
|
||||
#define SERVO_IRQn _SERVO_IRQn(SERVO_TC)
|
||||
|
||||
#define HAL_SERVO_TIMER_ISR() TC_HANDLER(SERVO_TC)
|
||||
|
||||
#define TIMER_TCCHANNEL(t) ((t) & 1)
|
||||
#define TC_COUNTER_START_VAL 0xFFFF
|
||||
|
||||
|
||||
static volatile int8_t currentServoIndex[_Nbr_16timers]; // index for the servo being pulsed for each timer (or -1 if refresh interval)
|
||||
|
||||
FORCE_INLINE static uint16_t getTimerCount() {
|
||||
Tcc * const tc = timer_config[SERVO_TC].pTcc;
|
||||
|
||||
tc->CTRLBSET.reg = TCC_CTRLBCLR_CMD_READSYNC;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
|
||||
return tc->COUNT.bit.COUNT;
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
// Interrupt handler for the TC
|
||||
// ----------------------------
|
||||
HAL_SERVO_TIMER_ISR() {
|
||||
Tcc * const tc = timer_config[SERVO_TC].pTcc;
|
||||
const timer16_Sequence_t timer =
|
||||
#ifndef _useTimer1
|
||||
_timer2
|
||||
#elif !defined(_useTimer2)
|
||||
_timer1
|
||||
#else
|
||||
(tc->INTFLAG.reg & tc->INTENSET.reg & TC_INTFLAG_MC0) ? _timer1 : _timer2
|
||||
#endif
|
||||
;
|
||||
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
|
||||
|
||||
int8_t cho = currentServoIndex[timer]; // Handle the prior servo first
|
||||
if (cho < 0) { // Servo -1 indicates the refresh interval completed...
|
||||
#if defined(_useTimer1) && defined(_useTimer2)
|
||||
if (currentServoIndex[timer ^ 1] >= 0) {
|
||||
// Wait for both channels
|
||||
// Clear the interrupt
|
||||
tc->INTFLAG.reg = (tcChannel == 0) ? TC_INTFLAG_MC0 : TC_INTFLAG_MC1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
tc->COUNT.reg = TC_COUNTER_START_VAL; // ...so reset the timer
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
}
|
||||
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
|
||||
digitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
|
||||
|
||||
currentServoIndex[timer] = ++cho; // go to the next channel (or 0)
|
||||
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
|
||||
if (SERVO(timer, cho).Pin.isActive) // activated?
|
||||
digitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
|
||||
|
||||
tc->CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, cho).ticks;
|
||||
}
|
||||
else {
|
||||
// finished all channels so wait for the refresh period to expire before starting over
|
||||
currentServoIndex[timer] = -1; // reset the timer COUNT.reg on the next call
|
||||
const uint16_t cval = getTimerCount() - 256 / (SERVO_TIMER_PRESCALER), // allow 256 cycles to ensure the next CV not missed
|
||||
ival = (TC_COUNTER_START_VAL) - (uint16_t)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
|
||||
tc->CC[tcChannel].reg = min(cval, ival);
|
||||
}
|
||||
if (tcChannel == 0) {
|
||||
SYNC(tc->SYNCBUSY.bit.CC0);
|
||||
tc->INTFLAG.reg = TC_INTFLAG_MC0; // Clear the interrupt
|
||||
}
|
||||
else {
|
||||
SYNC(tc->SYNCBUSY.bit.CC1);
|
||||
tc->INTFLAG.reg = TC_INTFLAG_MC1; // Clear the interrupt
|
||||
}
|
||||
}
|
||||
|
||||
void initISR(const timer16_Sequence_t timer) {
|
||||
Tcc * const tc = timer_config[SERVO_TC].pTcc;
|
||||
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
|
||||
|
||||
static bool initialized = false; // Servo TC has been initialized
|
||||
if (!initialized) {
|
||||
NVIC_DisableIRQ(SERVO_IRQn);
|
||||
|
||||
// Disable the timer
|
||||
tc->CTRLA.bit.ENABLE = false;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
|
||||
// Select GCLK0 as timer/counter input clock source
|
||||
GCLK->CLKCTRL.reg =(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(TCC0_GCLK_ID));
|
||||
SYNC (GCLK->STATUS.bit.SYNCBUSY);
|
||||
|
||||
// Reset the timer
|
||||
tc->CTRLA.bit.SWRST = true;
|
||||
SYNC(tc->CTRLA.bit.SWRST);
|
||||
|
||||
// Set timer counter mode to 16 bits
|
||||
tc->CTRLA.reg = TC_CTRLA_MODE_COUNT16;
|
||||
|
||||
// Set timer counter mode as normal PWM
|
||||
tc->WAVE.bit.WAVEGEN = TCC_WAVE_WAVEGEN_NPWM_Val;
|
||||
|
||||
// Set the prescaler factor
|
||||
tc->CTRLA.bit.PRESCALER = TC_PRESCALER(SERVO_TIMER_PRESCALER);
|
||||
|
||||
// Count down
|
||||
tc->CTRLBSET.reg = TCC_CTRLBCLR_DIR;
|
||||
SYNC(tc->SYNCBUSY.bit.CTRLB);
|
||||
|
||||
// Reset all servo indexes
|
||||
memset((void *)currentServoIndex, 0xFF, sizeof(currentServoIndex));
|
||||
|
||||
// Configure interrupt request
|
||||
NVIC_ClearPendingIRQ(SERVO_IRQn);
|
||||
NVIC_SetPriority(SERVO_IRQn, 5);
|
||||
NVIC_EnableIRQ(SERVO_IRQn);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
if (!tc->CTRLA.bit.ENABLE) {
|
||||
// Reset the timer counter
|
||||
tc->COUNT.reg = TC_COUNTER_START_VAL;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
|
||||
// Enable the timer and start it
|
||||
tc->CTRLA.bit.ENABLE = true;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
}
|
||||
// First interrupt request after 1 ms
|
||||
tc->CC[tcChannel].reg = getTimerCount() - (uint16_t)usToTicks(1000UL);
|
||||
|
||||
if (tcChannel == 0 ) {
|
||||
SYNC(tc->SYNCBUSY.bit.CC0);
|
||||
|
||||
// Clear pending match interrupt
|
||||
tc->INTFLAG.reg = TC_INTENSET_MC0;
|
||||
// Enable the match channel interrupt request
|
||||
tc->INTENSET.reg = TC_INTENSET_MC0;
|
||||
}
|
||||
else {
|
||||
SYNC(tc->SYNCBUSY.bit.CC1);
|
||||
|
||||
// Clear pending match interrupt
|
||||
tc->INTFLAG.reg = TC_INTENSET_MC1;
|
||||
// Enable the match channel interrupt request
|
||||
tc->INTENSET.reg = TC_INTENSET_MC1;
|
||||
}
|
||||
}
|
||||
|
||||
void finISR(const timer16_Sequence_t timer_index) {
|
||||
Tcc * const tc = timer_config[SERVO_TC].pTcc;
|
||||
const uint8_t tcChannel = TIMER_TCCHANNEL(timer_index);
|
||||
|
||||
// Disable the match channel interrupt request
|
||||
tc->INTENCLR.reg = (tcChannel == 0) ? TC_INTENCLR_MC0 : TC_INTENCLR_MC1;
|
||||
|
||||
if (true
|
||||
#if defined(_useTimer1) && defined(_useTimer2)
|
||||
&& (tc->INTENCLR.reg & (TC_INTENCLR_MC0|TC_INTENCLR_MC1)) == 0
|
||||
#endif
|
||||
) {
|
||||
// Disable the timer if not used
|
||||
tc->CTRLA.bit.ENABLE = false;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_SERVOS
|
||||
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#define _useTimer1
|
||||
#define _useTimer2
|
||||
|
||||
#define TRIM_DURATION 5 // compensation ticks to trim adjust for digitalWrite delays
|
||||
#define SERVO_TIMER_PRESCALER 64 // timer prescaler factor to 64 (avoid overflowing 16-bit clock counter, at 120MHz this is 1831 ticks per millisecond
|
||||
|
||||
#define SERVO_TC 3
|
||||
|
||||
typedef enum {
|
||||
#ifdef _useTimer1
|
||||
_timer1,
|
||||
#endif
|
||||
#ifdef _useTimer2
|
||||
_timer2,
|
||||
#endif
|
||||
_Nbr_16timers
|
||||
} timer16_Sequence_t;
|
@ -0,0 +1,141 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(FLASH_EEPROM_EMULATION)
|
||||
|
||||
#define TOTAL_FLASH_SIZE (MARLIN_EEPROM_SIZE+255)/256*256
|
||||
|
||||
/* reserve flash memory */
|
||||
static const uint8_t flashdata[TOTAL_FLASH_SIZE] __attribute__((__aligned__(256))) { }; \
|
||||
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
size_t PersistentStore::capacity() {
|
||||
return MARLIN_EEPROM_SIZE;
|
||||
/* const uint8_t psz = NVMCTRL->SEESTAT.bit.PSZ,
|
||||
sblk = NVMCTRL->SEESTAT.bit.SBLK;
|
||||
|
||||
return (!psz && !sblk) ? 0
|
||||
: (psz <= 2) ? (0x200 << psz)
|
||||
: (sblk == 1 || psz == 3) ? 4096
|
||||
: (sblk == 2 || psz == 4) ? 8192
|
||||
: (sblk <= 4 || psz == 5) ? 16384
|
||||
: (sblk >= 9 && psz == 7) ? 65536
|
||||
: 32768;*/
|
||||
}
|
||||
|
||||
uint32_t PAGE_SIZE;
|
||||
uint32_t ROW_SIZE;
|
||||
bool hasWritten = false;
|
||||
uint8_t * buffer;
|
||||
|
||||
void _erase(const volatile void *flash_ptr) {
|
||||
NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2;
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
|
||||
while (!NVMCTRL->INTFLAG.bit.READY) { }
|
||||
|
||||
}
|
||||
|
||||
void erase(const volatile void *flash_ptr, uint32_t size) {
|
||||
const uint8_t *ptr = (const uint8_t *)flash_ptr;
|
||||
while (size > ROW_SIZE) {
|
||||
_erase(ptr);
|
||||
ptr += ROW_SIZE;
|
||||
size -= ROW_SIZE;
|
||||
}
|
||||
_erase(ptr);
|
||||
}
|
||||
|
||||
bool PersistentStore::access_start() {
|
||||
/* clear page buffer*/
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
|
||||
PAGE_SIZE = pow(2,3 + NVMCTRL->PARAM.bit.PSZ);
|
||||
ROW_SIZE= PAGE_SIZE * 4;
|
||||
/*NVMCTRL->SEECFG.reg = NVMCTRL_SEECFG_WMODE_BUFFERED; // Buffered mode and segment reallocation active
|
||||
if (NVMCTRL->SEESTAT.bit.RLOCK)
|
||||
NVMCTRL_CMD(NVMCTRL_CTRLB_CMD_USEE); */ // Unlock E2P data write access
|
||||
// erase(&flashdata[0], TOTAL_FLASH_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::access_finish() {
|
||||
if (hasWritten) {
|
||||
erase(&flashdata[0], TOTAL_FLASH_SIZE);
|
||||
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
|
||||
NVMCTRL->CTRLB.bit.MANW = 0;
|
||||
|
||||
volatile uint32_t *dst_addr = (volatile uint32_t *) &flashdata;
|
||||
|
||||
uint32_t *pointer = (uint32_t *) buffer;
|
||||
for (uint32_t i = 0; i < TOTAL_FLASH_SIZE; i+=4) {
|
||||
|
||||
*dst_addr = (uint32_t) *pointer;
|
||||
pointer++;
|
||||
dst_addr ++;
|
||||
}
|
||||
|
||||
// Execute "WP" Write Page
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
|
||||
free(buffer);
|
||||
hasWritten = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
if (!hasWritten) {
|
||||
// init temp buffer
|
||||
buffer = (uint8_t *) malloc(MARLIN_EEPROM_SIZE);
|
||||
hasWritten=true;
|
||||
}
|
||||
|
||||
memcpy(buffer+pos,value,size);
|
||||
pos += size;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
volatile uint8_t *dst_addr = (volatile uint8_t *) &flashdata;
|
||||
dst_addr += pos;
|
||||
|
||||
memcpy(value,(const void *) dst_addr,size);
|
||||
pos += size;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // FLASH_EEPROM_EMULATION
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(QSPI_EEPROM)
|
||||
|
||||
#error "QSPI_EEPROM emulation Not implemented on SAMD21"
|
||||
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#include "QSPIFlash.h"
|
||||
|
||||
static bool initialized;
|
||||
|
||||
size_t PersistentStore::capacity() { return qspi.size(); }
|
||||
|
||||
bool PersistentStore::access_start() {
|
||||
if (!initialized) {
|
||||
qspi.begin();
|
||||
initialized = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::access_finish() {
|
||||
qspi.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
while (size--) {
|
||||
const uint8_t v = *value;
|
||||
qspi.writeByte(pos, v);
|
||||
crc16(crc, &v, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
while (size--) {
|
||||
uint8_t c = qspi.readByte(pos);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // QSPI_EEPROM
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if USE_WIRED_EEPROM
|
||||
|
||||
#error "USE_WIRED_EEPROM emulation Not implemented on SAMD21"
|
||||
/**
|
||||
* PersistentStore for Arduino-style EEPROM interface
|
||||
* with simple implementations supplied by Marlin.
|
||||
*/
|
||||
|
||||
#include "../shared/eeprom_if.h"
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM."
|
||||
#endif
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
|
||||
bool PersistentStore::access_start() { eeprom_init(); return true; }
|
||||
bool PersistentStore::access_finish() { return true; }
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
uint16_t written = 0;
|
||||
while (size--) {
|
||||
const uint8_t v = *value;
|
||||
uint8_t * const p = (uint8_t * const)pos;
|
||||
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
|
||||
eeprom_write_byte(p, v);
|
||||
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
|
||||
if (eeprom_read_byte(p) != v) {
|
||||
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
crc16(crc, &v, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
while (size--) {
|
||||
uint8_t c = eeprom_read_byte((uint8_t*)pos);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // USE_WIRED_EEPROM
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,216 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fast IO functions for SAMD21
|
||||
*/
|
||||
|
||||
#include "SAMD21.h"
|
||||
|
||||
/**
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
#ifndef MASK
|
||||
#define MASK(PIN) _BV(PIN)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Magic I/O routines
|
||||
*
|
||||
* Now you can simply SET_OUTPUT(IO); WRITE(IO, HIGH); WRITE(IO, LOW);
|
||||
*/
|
||||
|
||||
// Read a pin
|
||||
#define READ(IO) ((PORT->Group[(EPortType)GET_SAMD_PORT(IO)].IN.reg & MASK(GET_SAMD_PIN(IO))) != 0)
|
||||
|
||||
// Write to a pin
|
||||
#define WRITE(IO,V) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t mask = MASK(GET_SAMD_PIN(IO)); \
|
||||
\
|
||||
if (V) PORT->Group[port].OUTSET.reg = mask; \
|
||||
else PORT->Group[port].OUTCLR.reg = mask; \
|
||||
}while(0)
|
||||
|
||||
// Toggle a pin
|
||||
#define TOGGLE(IO) PORT->Group[(EPortType)GET_SAMD_PORT(IO)].OUTTGL.reg = MASK(GET_SAMD_PIN(IO));
|
||||
|
||||
// Set pin as input
|
||||
#define SET_INPUT(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
\
|
||||
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN); \
|
||||
PORT->Group[port].DIRCLR.reg = MASK(pin); \
|
||||
}while(0)
|
||||
// Set pin as input with pullup
|
||||
#define SET_INPUT_PULLUP(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
const uint32_t mask = MASK(pin); \
|
||||
\
|
||||
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PULLEN); \
|
||||
PORT->Group[port].DIRCLR.reg = mask; \
|
||||
PORT->Group[port].OUTSET.reg = mask; \
|
||||
}while(0)
|
||||
// Set pin as input with pulldown
|
||||
#define SET_INPUT_PULLDOWN(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
const uint32_t mask = MASK(pin); \
|
||||
\
|
||||
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PULLEN); \
|
||||
PORT->Group[port].DIRCLR.reg = mask; \
|
||||
PORT->Group[port].OUTCLR.reg = mask; \
|
||||
}while(0)
|
||||
// Set pin as output (push pull)
|
||||
#define SET_OUTPUT(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
\
|
||||
PORT->Group[port].DIRSET.reg = MASK(pin); \
|
||||
PORT->Group[port].PINCFG[pin].reg = 0; \
|
||||
}while(0)
|
||||
// Set pin as output (open drain)
|
||||
#define SET_OUTPUT_OD(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
\
|
||||
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_PULLEN); \
|
||||
PORT->Group[port].DIRCLR.reg = MASK(pin); \
|
||||
}while(0)
|
||||
// Set pin as PWM (push pull)
|
||||
#define SET_PWM SET_OUTPUT
|
||||
// Set pin as PWM (open drain)
|
||||
#define SET_PWM_OD SET_OUTPUT_OD
|
||||
|
||||
// check if pin is an output
|
||||
#define IS_OUTPUT(IO) ((PORT->Group[(EPortType)GET_SAMD_PORT(IO)].DIR.reg & MASK(GET_SAMD_PIN(IO))) \
|
||||
|| (PORT->Group[(EPortType)GET_SAMD_PORT(IO)].PINCFG[GET_SAMD_PIN(IO)].reg & (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)) == PORT_PINCFG_PULLEN)
|
||||
// check if pin is an input
|
||||
#define IS_INPUT(IO) !IS_OUTPUT(IO)
|
||||
|
||||
// Shorthand
|
||||
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
|
||||
#define OUT_WRITE_OD(IO,V) do{ SET_OUTPUT_OD(IO); WRITE(IO,V); }while(0)
|
||||
|
||||
// digitalRead/Write wrappers
|
||||
#define extDigitalRead(IO) digitalRead(IO)
|
||||
#define extDigitalWrite(IO,V) digitalWrite(IO,V)
|
||||
|
||||
/**
|
||||
* Ports and functions
|
||||
* Added as necessary or if I feel like it- not a comprehensive list!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some of these share the same source and so can't be used in the same time
|
||||
*/
|
||||
#define PWM_PIN(P) (WITHIN(P, 2, 13) || WITHIN(P, 22, 23) || WITHIN(P, 44, 45) || P == 48)
|
||||
|
||||
// Return fulfilled ADCx->INPUTCTRL.reg
|
||||
#define PIN_TO_INPUTCTRL(P) ( (P == 0) ? ADC_INPUTCTRL_MUXPOS_PIN0 \
|
||||
: ((P) == 1) ? ADC_INPUTCTRL_MUXPOS_PIN1 \
|
||||
: ((P) == 2) ? ADC_INPUTCTRL_MUXPOS_PIN3 \
|
||||
: ((P) == 3) ? ADC_INPUTCTRL_MUXPOS_PIN4 \
|
||||
: ((P) == 4) ? ADC_INPUTCTRL_MUXPOS_PIN5 \
|
||||
: ((P) == 5) ? ADC_INPUTCTRL_MUXPOS_PIN5 \
|
||||
: ((P) == 6) ? ADC_INPUTCTRL_MUXPOS_PIN6 \
|
||||
: ((P) == 7) ? ADC_INPUTCTRL_MUXPOS_PIN7 \
|
||||
: ((P) == 8) ? ADC_INPUTCTRL_MUXPOS_PIN8 \
|
||||
: ((P) == 9) ? ADC_INPUTCTRL_MUXPOS_PIN9 \
|
||||
: ((P) == 10) ? ADC_INPUTCTRL_MUXPOS_PIN10 \
|
||||
: ((P) == 11) ? ADC_INPUTCTRL_MUXPOS_PIN11 \
|
||||
: ((P) == 12) ? ADC_INPUTCTRL_MUXPOS_PIN12 \
|
||||
: ((P) == 13) ? ADC_INPUTCTRL_MUXPOS_PIN13 \
|
||||
: ((P) == 14) ? ADC_INPUTCTRL_MUXPOS_PIN14 \
|
||||
: ADC_INPUTCTRL_MUXPOS_PIN15)
|
||||
|
||||
#define digitalPinToAnalogInput(P) (WITHIN(P, 67, 74) ? (P) - 67 : WITHIN(P, 54, 61) ? 8 + (P) - 54 : WITHIN(P, 12, 13) ? 16 + (P) - 12 : P == 9 ? 18 : -1)
|
||||
|
||||
/**
|
||||
* pins
|
||||
*/
|
||||
|
||||
// PORTA
|
||||
#define DIO28_PIN PIN_PA02 // A0
|
||||
#define DIO56_PIN PIN_PA03 // A13
|
||||
#define DIO31_PIN PIN_PA04 // A13
|
||||
#define DIO32_PIN PIN_PA05 // A1
|
||||
#define DIO8_PIN PIN_PA06 // A14
|
||||
#define DIO9_PIN PIN_PA07 // A15
|
||||
#define DIO4_PIN PIN_PA08 // A15
|
||||
#define DIO3_PIN PIN_PA09 // A15
|
||||
#define DIO1_PIN PIN_PA10
|
||||
#define DIO0_PIN PIN_PA11
|
||||
#define DIO18_PIN PIN_PA12
|
||||
#define DIO52_PIN PIN_PA13
|
||||
#define DIO2_PIN PIN_PA14
|
||||
#define DIO5_PIN PIN_PA15
|
||||
#define DIO11_PIN PIN_PA16
|
||||
#define DIO13_PIN PIN_PA17
|
||||
#define DIO10_PIN PIN_PA18
|
||||
#define DIO12_PIN PIN_PA19
|
||||
#define DIO6_PIN PIN_PA20
|
||||
#define DIO07_PIN PIN_PA21
|
||||
#define DIO34_PIN PIN_PA22
|
||||
#define DIO35_PIN PIN_PA23
|
||||
#define DIO42_PIN PIN_PA24
|
||||
#define DIO43_PIN PIN_PA25
|
||||
|
||||
#define DIO40_PIN PIN_PA27
|
||||
|
||||
#define DIO26_PIN PIN_PB00
|
||||
#define DIO27_PIN PIN_PB01 // A0
|
||||
#define DIO33_PIN PIN_PB02
|
||||
#define DIO39_PIN PIN_PB03
|
||||
#define DIO14_PIN PIN_PB04
|
||||
#define DIO15_PIN PIN_PB05
|
||||
#define DIO16_PIN PIN_PB06
|
||||
#define DIO17_PIN PIN_PB07
|
||||
#define DIO29_PIN PIN_PB08
|
||||
#define DIO30_PIN PIN_PB09
|
||||
#define DIO37_PIN PIN_PB10
|
||||
#define DIO38_PIN PIN_PB11
|
||||
#define DIO36_PIN PIN_PB12
|
||||
#define DIO19_PIN PIN_PB13
|
||||
#define DIO20_PIN PIN_PB14
|
||||
#define DIO21_PIN PIN_PB15
|
||||
#define DIO22_PIN PIN_PB16
|
||||
#define DIO23_PIN PIN_PB17
|
||||
|
||||
#define DIO44_PIN PIN_PB22
|
||||
#define DIO45_PIN PIN_PB23
|
||||
#define DIO24_PIN PIN_PB30
|
||||
#define DIO25_PIN PIN_PB31
|
||||
|
||||
#define DIO53_PIN PIN_PA21
|
||||
#define DIO54_PIN PIN_PA06
|
||||
#define DIO55_PIN PIN_PA07
|
||||
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if HAS_SPI_TFT || HAS_FSMC_TFT
|
||||
#error "Sorry! TFT displays are not available for HAL/SAMD21."
|
||||
#endif
|
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if USE_FALLBACK_EEPROM
|
||||
#define FLASH_EEPROM_EMULATION
|
||||
#elif EITHER(I2C_EEPROM, SPI_EEPROM)
|
||||
#define USE_SHARED_EEPROM 1
|
||||
#endif
|
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test SAMD21 specific configuration values for errors at compile-time.
|
||||
*/
|
||||
|
||||
#if SERVO_TC == MF_TIMER_RTC
|
||||
#error "Servos can't use RTC timer"
|
||||
#endif
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#error "EMERGENCY_PARSER is not yet implemented for SAMD21. Disable EMERGENCY_PARSER to continue."
|
||||
#endif
|
||||
|
||||
#if ENABLED(SDIO_SUPPORT)
|
||||
#error "SDIO_SUPPORT is not supported on SAMD21."
|
||||
#endif
|
||||
|
||||
#if ENABLED(FAST_PWM_FAN)
|
||||
#error "Features requiring Hardware PWM (FAST_PWM_FAN) are not yet supported on SAMD21."
|
||||
#endif
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not yet supported on SAMD21."
|
||||
#endif
|
@ -0,0 +1,160 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#define NUMBER_PINS_TOTAL PINS_COUNT
|
||||
|
||||
#define digitalRead_mod(p) extDigitalRead(p)
|
||||
#define PRINT_PORT(p) do{ SERIAL_ECHOPGM(" Port: "); sprintf_P(buffer, PSTR("%c%02ld"), 'A' + g_APinDescription[p].ulPort, g_APinDescription[p].ulPin); 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("%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)
|
||||
#define GET_ARRAY_PIN(p) pin_array[p].pin
|
||||
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
|
||||
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL)
|
||||
#define DIGITAL_PIN_TO_ANALOG_PIN(p) digitalPinToAnalogInput(p)
|
||||
#define IS_ANALOG(P) (DIGITAL_PIN_TO_ANALOG_PIN(P)!=-1)
|
||||
#define pwm_status(pin) digitalPinHasPWM(pin)
|
||||
#define MULTI_NAME_PAD 27 // space needed to be pretty if not first name assigned to a pin
|
||||
|
||||
// pins that will cause hang/reset/disconnect in M43 Toggle and Watch utilities
|
||||
// uses pin index
|
||||
#define M43_NEVER_TOUCH(Q) ((Q) >= 75)
|
||||
|
||||
bool GET_PINMODE(int8_t pin) { // 1: output, 0: input
|
||||
const EPortType samdport = g_APinDescription[pin].ulPort;
|
||||
const uint32_t samdpin = g_APinDescription[pin].ulPin;
|
||||
return PORT->Group[samdport].DIR.reg & MASK(samdpin) || (PORT->Group[samdport].PINCFG[samdpin].reg & (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)) == PORT_PINCFG_PULLEN;
|
||||
}
|
||||
|
||||
void pwm_details(int32_t pin) {
|
||||
if (pwm_status(pin)) {
|
||||
//uint32_t chan = g_APinDescription[pin].ulPWMChannel TODO when fast pwm is operative;
|
||||
//SERIAL_ECHOPGM("PWM = ", duty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SAMD21 Board pin| PORT | Label
|
||||
* ----------------+--------+-------
|
||||
* 0 | PB25 | "RX0"
|
||||
* 1 | PB24 | "TX0"
|
||||
* 2 | PC18 |
|
||||
* 3 | PC19 |
|
||||
* 4 | PC20 |
|
||||
* 5 | PC21 |
|
||||
* 6 | PD20 |
|
||||
* 7 | PD21 |
|
||||
* 8 | PB18 |
|
||||
* 9 | PB2 |
|
||||
* 10 | PB22 |
|
||||
* 11 | PB23 |
|
||||
* 12 | PB0 | "A16"
|
||||
* 13 | PB1 | LED AMBER "L" / "A17"
|
||||
* 14 | PB16 | "TX3"
|
||||
* 15 | PB17 | "RX3"
|
||||
* 16 | PC22 | "TX2"
|
||||
* 17 | PC23 | "RX2"
|
||||
* 18 | PB12 | "TX1" / "A18"
|
||||
* 19 | PB13 | "RX1"
|
||||
* 20 | PB20 | "SDA"
|
||||
* 21 | PB21 | "SCL"
|
||||
* 22 | PD12 |
|
||||
* 23 | PA15 |
|
||||
* 24 | PC17 |
|
||||
* 25 | PC16 |
|
||||
* 26 | PA12 |
|
||||
* 27 | PA13 |
|
||||
* 28 | PA14 |
|
||||
* 29 | PB19 |
|
||||
* 30 | PA23 |
|
||||
* 31 | PA22 |
|
||||
* 32 | PA21 |
|
||||
* 33 | PA20 |
|
||||
* 34 | PA19 |
|
||||
* 35 | PA18 |
|
||||
* 36 | PA17 |
|
||||
* 37 | PA16 |
|
||||
* 38 | PB15 |
|
||||
* 39 | PB14 |
|
||||
* 40 | PC13 |
|
||||
* 41 | PC12 |
|
||||
* 42 | PC15 |
|
||||
* 43 | PC14 |
|
||||
* 44 | PC11 |
|
||||
* 45 | PC10 |
|
||||
* 46 | PC6 |
|
||||
* 47 | PC7 |
|
||||
* 48 | PC4 |
|
||||
* 49 | PC5 |
|
||||
* 50 | PD11 |
|
||||
* 51 | PD8 |
|
||||
* 52 | PD9 |
|
||||
* 53 | PD10 |
|
||||
* 54 | PB5 | "A8"
|
||||
* 55 | PB6 | "A9"
|
||||
* 56 | PB7 | "A10"
|
||||
* 57 | PB8 | "A11"
|
||||
* 58 | PB9 | "A12"
|
||||
* 69 | PA4 | "A13"
|
||||
* 60 | PA6 | "A14"
|
||||
* 61 | PA7 | "A15"
|
||||
* 62 | PB17 |
|
||||
* 63 | PB20 |
|
||||
* 64 | PD11 |
|
||||
* 65 | PD8 |
|
||||
* 66 | PD9 |
|
||||
* 67 | PA2 | "A0" / "DAC0"
|
||||
* 68 | PA5 | "A1" / "DAC1"
|
||||
* 69 | PB3 | "A2"
|
||||
* 70 | PC0 | "A3"
|
||||
* 71 | PC1 | "A4"
|
||||
* 72 | PC2 | "A5"
|
||||
* 73 | PC3 | "A6"
|
||||
* 74 | PB4 | "A7"
|
||||
* 75 | PC31 | LED GREEN "RX"
|
||||
* 76 | PC30 | LED GREEN "TX"
|
||||
* 77 | PA27 | USB: Host enable
|
||||
* 78 | PA24 | USB: D-
|
||||
* 79 | PA25 | USB: D+
|
||||
* 80 | PB29 | SD: MISO
|
||||
* 81 | PB27 | SD: SCK
|
||||
* 82 | PB26 | SD: MOSI
|
||||
* 83 | PB28 | SD: CS
|
||||
* 84 | PA3 | AREF
|
||||
* 85 | PA2 | DAC0 (Duplicate)
|
||||
* 86 | PA5 | DAC1 (Duplicate)
|
||||
* 87 | PB1 | LED AMBER "L" (Duplicate)
|
||||
* 88 | PC24 | NeoPixel
|
||||
* 89 | PB10 | QSPI: SCK
|
||||
* 90 | PB11 | QSPI: CS
|
||||
* 91 | PA8 | QSPI: IO0
|
||||
* 92 | PA9 | QSPI: IO1
|
||||
* 93 | PA10 | QSPI: IO2
|
||||
* 94 | PA11 | QSPI: IO3
|
||||
* 95 | PB31 | SD: DETECT
|
||||
*/
|
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 Default SPI Pins
|
||||
*
|
||||
* SS SCK MISO MOSI
|
||||
* +-------------------------+
|
||||
* SPI | 53 52 50 51 |
|
||||
* SPI1 | 83 81 80 82 |
|
||||
* +-------------------------+
|
||||
* Any pin can be used for Chip Select (SD_SS_PIN)
|
||||
*/
|
||||
#ifndef SD_SCK_PIN
|
||||
#define SD_SCK_PIN 38
|
||||
#endif
|
||||
#ifndef SD_MISO_PIN
|
||||
#define SD_MISO_PIN 36
|
||||
#endif
|
||||
#ifndef SD_MOSI_PIN
|
||||
#define SD_MOSI_PIN 37
|
||||
#endif
|
||||
#ifndef SDSS
|
||||
#define SDSS 18
|
||||
#endif
|
||||
|
||||
#ifndef SD_SS_PIN
|
||||
#define SD_SS_PIN SDSS
|
||||
#endif
|
@ -0,0 +1,217 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "ServoTimers.h" // for SERVO_TC
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Local defines
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#define NUM_HARDWARE_TIMERS 9
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Private Variables
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
|
||||
{ {.pTcc=TCC0}, TimerType::tcc, TCC0_IRQn, TC_PRIORITY(0) }, // 0 - stepper (assigned priority 2)
|
||||
{ {.pTcc=TCC1}, TimerType::tcc, TCC1_IRQn, TC_PRIORITY(1) }, // 1 - stepper (needed by 32 bit timers)
|
||||
{ {.pTcc=TCC2}, TimerType::tcc, TCC2_IRQn, 5 }, // 2 - tone (reserved by framework and fixed assigned priority 5)
|
||||
{ {.pTc=TC3}, TimerType::tc, TC3_IRQn, TC_PRIORITY(3) }, // 3 - servo (assigned priority 1)
|
||||
{ {.pTc=TC4}, TimerType::tc, TC4_IRQn, TC_PRIORITY(4) }, // 4 - software serial (no interrupts used)
|
||||
{ {.pTc=TC5}, TimerType::tc, TC5_IRQn, TC_PRIORITY(5) },
|
||||
{ {.pTc=TC6}, TimerType::tc, TC6_IRQn, TC_PRIORITY(6) },
|
||||
{ {.pTc=TC7}, TimerType::tc, TC7_IRQn, TC_PRIORITY(7) },
|
||||
{ {.pRtc=RTC}, TimerType::rtc, RTC_IRQn, TC_PRIORITY(8) } // 8 - temperature (assigned priority 6)
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Private functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
FORCE_INLINE void Disable_Irq(IRQn_Type irq) {
|
||||
NVIC_DisableIRQ(irq);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
static bool tcIsSyncing(Tc * tc) {
|
||||
return tc->COUNT32.STATUS.reg & TC_STATUS_SYNCBUSY;
|
||||
}
|
||||
|
||||
static void tcReset( Tc * tc) {
|
||||
tc->COUNT32.CTRLA.reg = TC_CTRLA_SWRST;
|
||||
while (tcIsSyncing(tc)) {}
|
||||
while (tc->COUNT32.CTRLA.bit.SWRST) {}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
||||
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
|
||||
// Disable interrupt, just in case it was already enabled
|
||||
NVIC_DisableIRQ(irq);
|
||||
NVIC_ClearPendingIRQ(irq);
|
||||
|
||||
if (timer_num == MF_TIMER_RTC) {
|
||||
|
||||
// https://github.com/arduino-libraries/RTCZero
|
||||
Rtc * const rtc = timer_config[timer_num].pRtc;
|
||||
PM->APBAMASK.reg |= PM_APBAMASK_RTC;
|
||||
|
||||
GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK4 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {}
|
||||
|
||||
GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(4) | GCLK_GENCTRL_DIVSEL );
|
||||
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
|
||||
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_ID(4);
|
||||
GCLK->GENDIV.bit.DIV=4;
|
||||
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
|
||||
|
||||
// Disable timer interrupt
|
||||
rtc->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0;
|
||||
SYNC(rtc->MODE0.STATUS.bit.SYNCBUSY);
|
||||
|
||||
while(rtc->MODE0.STATUS.bit.SYNCBUSY) {}
|
||||
|
||||
// Stop timer, just in case, to be able to reconfigure it
|
||||
rtc->MODE0.CTRL.reg =
|
||||
RTC_MODE0_CTRL_MODE_COUNT32 | // Mode 0 = 32-bits counter
|
||||
RTC_MODE0_CTRL_PRESCALER_DIV1024; // Divisor = 1024
|
||||
|
||||
while(rtc->MODE0.STATUS.bit.SYNCBUSY) {}
|
||||
|
||||
// Mode, reset counter on match
|
||||
rtc->MODE0.CTRL.reg = RTC_MODE0_CTRL_MODE_COUNT32 | RTC_MODE0_CTRL_MATCHCLR;
|
||||
|
||||
// Set compare value
|
||||
rtc->MODE0.COMP[0].reg = (32768 + frequency / 2) / frequency;
|
||||
SYNC(rtc->MODE0.STATUS.bit.SYNCBUSY);
|
||||
|
||||
// Enable interrupt on compare
|
||||
rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0; // reset pending interrupt
|
||||
rtc->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0; // enable compare 0 interrupt
|
||||
|
||||
// And start timer
|
||||
rtc->MODE0.CTRL.bit.ENABLE = true;
|
||||
SYNC(rtc->MODE0.STATUS.bit.SYNCBUSY);
|
||||
|
||||
}
|
||||
else if (timer_config[timer_num].type==TimerType::tcc) {
|
||||
|
||||
Tcc * const tc = timer_config[timer_num].pTcc;
|
||||
|
||||
PM->APBCMASK.reg |= PM_APBCMASK_TCC0;
|
||||
GCLK->CLKCTRL.reg =(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(TCC0_GCLK_ID));
|
||||
SYNC (GCLK->STATUS.bit.SYNCBUSY);
|
||||
|
||||
tc->CTRLA.reg = TCC_CTRLA_SWRST;
|
||||
SYNC (tc->SYNCBUSY.reg & TCC_SYNCBUSY_SWRST) {}
|
||||
|
||||
SYNC (tc->CTRLA.bit.SWRST);
|
||||
|
||||
tc->CTRLA.reg &= ~(TCC_CTRLA_ENABLE); // disable TC module
|
||||
|
||||
tc->CTRLA.reg |= TCC_WAVE_WAVEGEN_MFRQ;
|
||||
tc->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV2;
|
||||
tc->CC[0].reg = (HAL_TIMER_RATE) / frequency;
|
||||
tc->INTENSET.reg = TCC_INTFLAG_MC0;
|
||||
tc->CTRLA.reg |= TCC_CTRLA_ENABLE;
|
||||
tc->INTFLAG.reg = 0xFF;
|
||||
SYNC ( tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
|
||||
}
|
||||
else {
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
|
||||
// Disable timer interrupt
|
||||
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
|
||||
|
||||
// TCn clock setup
|
||||
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)) ;
|
||||
SYNC (GCLK->STATUS.bit.SYNCBUSY);
|
||||
|
||||
tcReset(tc); // reset TC
|
||||
|
||||
// Set Timer counter 5 Mode to 16 bits, it will become a 16bit counter ('mode1' in the datasheet)
|
||||
tc->COUNT32.CTRLA.reg |= TC_CTRLA_MODE_COUNT32;
|
||||
// Set TC waveform generation mode to 'match frequency'
|
||||
tc->COUNT32.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
|
||||
//set prescaler
|
||||
//the clock normally counts at the GCLK_TC frequency, but we can set it to divide that frequency to slow it down
|
||||
//you can use different prescaler divisons here like TC_CTRLA_PRESCALER_DIV1 to get a different range
|
||||
tc->COUNT32.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1 | TC_CTRLA_ENABLE; //it will divide GCLK_TC frequency by 1024
|
||||
//set the compare-capture register.
|
||||
//The counter will count up to this value (it's a 16bit counter so we use uint16_t)
|
||||
//this is how we fine-tune the frequency, make it count to a lower or higher value
|
||||
//system clock should be 1MHz (8MHz/8) at Reset by default
|
||||
tc->COUNT32.CC[0].reg = (uint16_t) (HAL_TIMER_RATE / frequency);
|
||||
while (tcIsSyncing(tc)) {}
|
||||
|
||||
// Enable the TC interrupt request
|
||||
tc->COUNT32.INTENSET.bit.MC0 = 1;
|
||||
while (tcIsSyncing(tc)) {}
|
||||
}
|
||||
|
||||
NVIC_SetPriority(irq, timer_config[timer_num].priority);
|
||||
NVIC_EnableIRQ(irq);
|
||||
}
|
||||
|
||||
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
|
||||
const IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
NVIC_EnableIRQ(irq);
|
||||
}
|
||||
|
||||
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
|
||||
const IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
Disable_Irq(irq);
|
||||
}
|
||||
|
||||
// missing from CMSIS: Check if interrupt is enabled or not
|
||||
static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
|
||||
return TEST(NVIC->ISER[uint32_t(IRQn) >> 5], uint32_t(IRQn) & 0x1F);
|
||||
}
|
||||
|
||||
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
|
||||
const IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
return NVIC_GetEnabledIRQ(irq);
|
||||
}
|
||||
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,160 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Defines
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
typedef uint32_t hal_timer_t;
|
||||
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
|
||||
|
||||
#define HAL_TIMER_RATE F_CPU // frequency of timers peripherals
|
||||
|
||||
#define MF_TIMER_RTC 8 // This is not a TC but a RTC
|
||||
|
||||
#ifndef MF_TIMER_STEP
|
||||
#define MF_TIMER_STEP 4 // Timer Index for Stepper
|
||||
#endif
|
||||
#ifndef MF_TIMER_PULSE
|
||||
#define MF_TIMER_PULSE MF_TIMER_STEP
|
||||
#endif
|
||||
#ifndef MF_TIMER_TEMP
|
||||
#define MF_TIMER_TEMP MF_TIMER_RTC // Timer Index for Temperature
|
||||
#endif
|
||||
|
||||
#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_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 PULSE_TIMER_RATE STEPPER_TIMER_RATE
|
||||
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
|
||||
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
|
||||
|
||||
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
|
||||
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
|
||||
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
|
||||
|
||||
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
|
||||
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
|
||||
|
||||
#define TC_PRIORITY(t) ( t == SERVO_TC ? 1 \
|
||||
: (t == MF_TIMER_STEP || t == MF_TIMER_PULSE) ? 2 \
|
||||
: (t == MF_TIMER_TEMP) ? 6 : 7 )
|
||||
|
||||
#define _TC_HANDLER(t) void TC##t##_Handler()
|
||||
#define TC_HANDLER(t) _TC_HANDLER(t)
|
||||
#ifndef HAL_STEP_TIMER_ISR
|
||||
#define HAL_STEP_TIMER_ISR() TC_HANDLER(MF_TIMER_STEP)
|
||||
#endif
|
||||
#if MF_TIMER_STEP != MF_TIMER_PULSE
|
||||
#define HAL_PULSE_TIMER_ISR() TC_HANDLER(MF_TIMER_PULSE)
|
||||
#endif
|
||||
#if MF_TIMER_TEMP == MF_TIMER_RTC
|
||||
#define HAL_TEMP_TIMER_ISR() void RTC_Handler()
|
||||
#else
|
||||
#define HAL_TEMP_TIMER_ISR() TC_HANDLER(MF_TIMER_TEMP)
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Types
|
||||
// --------------------------------------------------------------------------
|
||||
typedef enum { tcc, tc, rtc } TimerType;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
Tc *pTc;
|
||||
Tcc *pTcc;
|
||||
Rtc *pRtc;
|
||||
};
|
||||
TimerType type;
|
||||
IRQn_Type IRQ_Id;
|
||||
uint8_t priority;
|
||||
} tTimerConfig;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public Variables
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
extern const tTimerConfig timer_config[];
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
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) {
|
||||
// Should never be called with timer MF_TIMER_RTC
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
tc->COUNT32.CC[0].reg = compare;
|
||||
}
|
||||
|
||||
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
|
||||
// Should never be called with timer MF_TIMER_RTC
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
return (hal_timer_t)tc->COUNT32.CC[0].reg;
|
||||
}
|
||||
|
||||
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
|
||||
// Should never be called with timer MF_TIMER_RTC
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
tc->COUNT32.READREQ.reg = TC_READREQ_RREQ;
|
||||
// Request a read synchronization
|
||||
SYNC (tc->COUNT32.STATUS.bit.SYNCBUSY);
|
||||
//SYNC(tc->COUNT32.STATUS.bit.SYNCBUSY );
|
||||
return tc->COUNT32.COUNT.reg;
|
||||
}
|
||||
|
||||
void HAL_timer_enable_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);
|
||||
|
||||
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
|
||||
if (timer_num == MF_TIMER_RTC) {
|
||||
Rtc * const rtc = timer_config[timer_num].pRtc;
|
||||
// Clear interrupt flag
|
||||
rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0| RTC_MODE0_INTFLAG_OVF;
|
||||
|
||||
}
|
||||
else if (timer_config[timer_num].type == TimerType::tcc){
|
||||
Tcc * const tc = timer_config[timer_num].pTcc;
|
||||
// Clear interrupt flag
|
||||
tc->INTFLAG.reg = TCC_INTFLAG_OVF;
|
||||
}
|
||||
else {
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
// Clear interrupt flag
|
||||
tc->COUNT32.INTFLAG.bit.MC0 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define HAL_timer_isr_epilogue(timer_num)
|
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
// adapted from I2C/master/master.c example
|
||||
// https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
|
||||
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SAMD21 LCD-specific defines
|
||||
*/
|
||||
|
||||
// The following are optional depending on the platform.
|
||||
|
||||
// definitions of HAL specific com and device drivers.
|
||||
uint8_t u8g_com_samd21_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
|
||||
uint8_t u8g_com_samd21_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
|
||||
|
||||
// connect U8g com generic com names to the desired driver
|
||||
#define U8G_COM_HW_SPI u8g_com_samd21_st7920_hw_spi_fn // use SAMD21 specific hardware SPI routine
|
||||
#define U8G_COM_ST7920_HW_SPI u8g_com_samd21_st7920_hw_spi_fn
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Low level pin manipulation routines - used by all the drivers.
|
||||
*
|
||||
* These are based on the SAMD51 pinMode, digitalRead & digitalWrite routines.
|
||||
*
|
||||
* Couldn't just call exact copies because the overhead killed the LCD update speed
|
||||
* With an intermediate level the softspi was running in the 10-20kHz range which
|
||||
* resulted in using about about 25% of the CPU's time.
|
||||
*/
|
||||
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Low level pin manipulation routines - used by all the drivers.
|
||||
*
|
||||
* These are based on the SAMD51 pinMode, digitalRead & digitalWrite routines.
|
||||
*
|
||||
* Couldn't just call exact copies because the overhead killed the LCD update speed
|
||||
* With an intermediate level the softspi was running in the 10-20kHz range which
|
||||
* resulted in using about about 25% of the CPU's time.
|
||||
*/
|
||||
|
||||
void u8g_SetPinOutput(uint8_t internal_pin_number);
|
||||
void u8g_SetPinInput(uint8_t internal_pin_number);
|
||||
void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status);
|
||||
uint8_t u8g_GetPinLevel(uint8_t pin);
|
@ -0,0 +1,154 @@
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on u8g_com_msp430_hw_spi.c
|
||||
*
|
||||
* Universal 8bit Graphics Library
|
||||
*
|
||||
* Copyright (c) 2012, olikraus@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include <U8glib-HAL.h>
|
||||
#include "SPI.h"
|
||||
|
||||
#include "../../shared/HAL_SPI.h"
|
||||
|
||||
#ifndef LCD_SPI_SPEED
|
||||
#define LCD_SPI_SPEED SPI_QUARTER_SPEED
|
||||
#endif
|
||||
|
||||
void u8g_SetPIOutput(u8g_t *u8g, uint8_t pin_index) {
|
||||
if (u8g->pin_list[pin_index]!= U8G_PIN_NONE)
|
||||
pinMode(u8g->pin_list[pin_index],OUTPUT);
|
||||
}
|
||||
|
||||
void u8g_SetPILevel(u8g_t *u8g, uint8_t pin_index, uint8_t level) {
|
||||
if (u8g->pin_list[pin_index]!= U8G_PIN_NONE)
|
||||
digitalWrite(u8g->pin_list[pin_index],level);
|
||||
}
|
||||
|
||||
uint8_t u8g_com_samd21_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
|
||||
|
||||
static SPISettings lcdSPIConfig;
|
||||
|
||||
switch (msg) {
|
||||
case U8G_COM_MSG_STOP:
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_INIT:
|
||||
u8g_SetPIOutput(u8g, U8G_PI_CS);
|
||||
u8g_SetPIOutput(u8g, U8G_PI_A0);
|
||||
u8g_SetPIOutput(u8g, U8G_PI_RESET);
|
||||
|
||||
u8g_SetPILevel(u8g, U8G_PI_CS, LOW);
|
||||
|
||||
spiBegin();
|
||||
lcdSPIConfig = SPISettings(900000, MSBFIRST, SPI_MODE0);
|
||||
u8g->pin_list[U8G_PI_A0_STATE] = 0;
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_ADDRESS: // define cmd (arg_val = 0) or data mode (arg_val = 1)
|
||||
u8g_SetPILevel(u8g, U8G_PI_A0, arg_val);
|
||||
u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_CHIP_SELECT: // arg_val == 1 means chip selected, but ST7920 is active high, so needs inverting
|
||||
u8g_SetPILevel(u8g, U8G_PI_CS, arg_val ? HIGH : LOW);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_RESET:
|
||||
u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_BYTE:
|
||||
SPI.beginTransaction(lcdSPIConfig);
|
||||
|
||||
if (u8g->pin_list[U8G_PI_A0_STATE] == 0) { // command
|
||||
SPI.transfer(0x0f8); u8g->pin_list[U8G_PI_A0_STATE] = 2;
|
||||
}
|
||||
else if (u8g->pin_list[U8G_PI_A0_STATE] == 1) { // data
|
||||
SPI.transfer(0x0fa); u8g->pin_list[U8G_PI_A0_STATE] = 2;
|
||||
}
|
||||
|
||||
SPI.transfer(arg_val & 0x0f0);
|
||||
SPI.transfer(arg_val << 4);
|
||||
SPI.endTransaction();
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_SEQ:
|
||||
SPI.beginTransaction(lcdSPIConfig);
|
||||
|
||||
if (u8g->pin_list[U8G_PI_A0_STATE] == 0 ) { // command
|
||||
SPI.transfer(0x0f8); u8g->pin_list[U8G_PI_A0_STATE] = 2;
|
||||
}
|
||||
else if (u8g->pin_list[U8G_PI_A0_STATE] == 1) { // data
|
||||
SPI.transfer(0x0fa); u8g->pin_list[U8G_PI_A0_STATE] = 2;
|
||||
}
|
||||
|
||||
uint8_t *ptr = (uint8_t*)arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
SPI.transfer((*ptr) & 0x0f0);
|
||||
SPI.transfer((*ptr) << 4);
|
||||
ptr++;
|
||||
arg_val--;
|
||||
}
|
||||
|
||||
SPI.endTransaction();
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // __SAMD21__
|
@ -0,0 +1,182 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
*
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
|
||||
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "../shared/Delay.h"
|
||||
|
||||
#include "usb_serial.h"
|
||||
|
||||
#ifdef USBCON
|
||||
DefaultSerial1 MSerialUSB(false, SerialUSB);
|
||||
#endif
|
||||
|
||||
#if ENABLED(SRAM_EEPROM_EMULATION)
|
||||
#if STM32F7xx
|
||||
#include <stm32f7xx_ll_pwr.h>
|
||||
#elif STM32F4xx
|
||||
#include <stm32f4xx_ll_pwr.h>
|
||||
#else
|
||||
#error "SRAM_EEPROM_EMULATION is currently only supported for STM32F4xx and STM32F7xx"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_SD_HOST_DRIVE
|
||||
#include "msc_sd.h"
|
||||
#include "usbd_cdc_if.h"
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
// Public Variables
|
||||
// ------------------------
|
||||
|
||||
uint16_t MarlinHAL::adc_result;
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
extern void install_min_serial();
|
||||
#endif
|
||||
|
||||
// HAL initialization task
|
||||
void MarlinHAL::init() {
|
||||
// Ensure F_CPU is a constant expression.
|
||||
// If the compiler breaks here, it means that delay code that should compute at compile time will not work.
|
||||
// So better safe than sorry here.
|
||||
constexpr int cpuFreq = F_CPU;
|
||||
UNUSED(cpuFreq);
|
||||
|
||||
#if ENABLED(SDSUPPORT) && DISABLED(SDIO_SUPPORT) && (defined(SDSS) && SDSS != -1)
|
||||
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
|
||||
#endif
|
||||
|
||||
#if PIN_EXISTS(LED)
|
||||
OUT_WRITE(LED_PIN, LOW);
|
||||
#endif
|
||||
|
||||
#if ENABLED(SRAM_EEPROM_EMULATION)
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
HAL_PWR_EnableBkUpAccess(); // Enable access to backup SRAM
|
||||
__HAL_RCC_BKPSRAM_CLK_ENABLE();
|
||||
LL_PWR_EnableBkUpRegulator(); // Enable backup regulator
|
||||
while (!LL_PWR_IsActiveFlag_BRR()); // Wait until backup regulator is initialized
|
||||
#endif
|
||||
|
||||
SetTimerInterruptPriorities();
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER) && (USBD_USE_CDC || USBD_USE_CDC_MSC)
|
||||
USB_Hook_init();
|
||||
#endif
|
||||
|
||||
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
|
||||
|
||||
TERN_(HAS_SD_HOST_DRIVE, MSC_SD_init()); // Enable USB SD card access
|
||||
|
||||
#if PIN_EXISTS(USB_CONNECT)
|
||||
OUT_WRITE(USB_CONNECT_PIN, !USB_CONNECT_INVERTING); // USB clear connection
|
||||
delay(1000); // Give OS time to notice
|
||||
WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING);
|
||||
#endif
|
||||
}
|
||||
|
||||
// HAL idle task
|
||||
void MarlinHAL::idletask() {
|
||||
#if HAS_SHARED_MEDIA
|
||||
// Stm32duino currently doesn't have a "loop/idle" method
|
||||
CDC_resume_receive();
|
||||
CDC_continue_transmit();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MarlinHAL::reboot() { NVIC_SystemReset(); }
|
||||
|
||||
uint8_t MarlinHAL::get_reset_source() {
|
||||
return
|
||||
#ifdef RCC_FLAG_IWDGRST // Some sources may not exist...
|
||||
RESET != __HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) ? RST_WATCHDOG :
|
||||
#endif
|
||||
#ifdef RCC_FLAG_IWDG1RST
|
||||
RESET != __HAL_RCC_GET_FLAG(RCC_FLAG_IWDG1RST) ? RST_WATCHDOG :
|
||||
#endif
|
||||
#ifdef RCC_FLAG_IWDG2RST
|
||||
RESET != __HAL_RCC_GET_FLAG(RCC_FLAG_IWDG2RST) ? RST_WATCHDOG :
|
||||
#endif
|
||||
#ifdef RCC_FLAG_SFTRST
|
||||
RESET != __HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST) ? RST_SOFTWARE :
|
||||
#endif
|
||||
#ifdef RCC_FLAG_PINRST
|
||||
RESET != __HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) ? RST_EXTERNAL :
|
||||
#endif
|
||||
#ifdef RCC_FLAG_PORRST
|
||||
RESET != __HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) ? RST_POWER_ON :
|
||||
#endif
|
||||
0
|
||||
;
|
||||
}
|
||||
|
||||
void MarlinHAL::clear_reset_source() { __HAL_RCC_CLEAR_RESET_FLAGS(); }
|
||||
|
||||
// ------------------------
|
||||
// Watchdog Timer
|
||||
// ------------------------
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
|
||||
|
||||
#include <IWatchdog.h>
|
||||
|
||||
void MarlinHAL::watchdog_init() {
|
||||
IF_DISABLED(DISABLE_WATCHDOG_INIT, IWatchdog.begin(WDT_TIMEOUT_US));
|
||||
}
|
||||
|
||||
void MarlinHAL::watchdog_refresh() {
|
||||
IWatchdog.reload();
|
||||
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
|
||||
TOGGLE(LED_PIN); // heartbeat indicator
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
extern unsigned int _ebss; // end of bss section
|
||||
}
|
||||
|
||||
// Reset the system to initiate a firmware flash
|
||||
WEAK void flashFirmware(const int16_t) { hal.reboot(); }
|
||||
|
||||
// Maple Compatibility
|
||||
volatile uint32_t systick_uptime_millis = 0;
|
||||
systickCallback_t systick_user_callback;
|
||||
void systick_attach_callback(systickCallback_t cb) { systick_user_callback = cb; }
|
||||
void HAL_SYSTICK_Callback() {
|
||||
systick_uptime_millis++;
|
||||
if (systick_user_callback) systick_user_callback();
|
||||
}
|
||||
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,281 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
*
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
|
||||
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define CPU_32_BIT
|
||||
|
||||
#include "../../core/macros.h"
|
||||
#include "../shared/Marduino.h"
|
||||
#include "../shared/math_32bit.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
#include "Servo.h"
|
||||
#include "MarlinSerial.h"
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//
|
||||
// Default graphical display delays
|
||||
//
|
||||
#define CPU_ST7920_DELAY_1 300
|
||||
#define CPU_ST7920_DELAY_2 40
|
||||
#define CPU_ST7920_DELAY_3 340
|
||||
|
||||
// ------------------------
|
||||
// Serial ports
|
||||
// ------------------------
|
||||
#ifdef USBCON
|
||||
#include <USBSerial.h>
|
||||
#include "../../core/serial_hook.h"
|
||||
typedef ForwardSerial1Class< decltype(SerialUSB) > DefaultSerial1;
|
||||
extern DefaultSerial1 MSerialUSB;
|
||||
#endif
|
||||
|
||||
#define _MSERIAL(X) MSerial##X
|
||||
#define MSERIAL(X) _MSERIAL(X)
|
||||
|
||||
#if WITHIN(SERIAL_PORT, 1, 6)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#elif !defined(USBCON)
|
||||
#error "SERIAL_PORT must be from 1 to 6."
|
||||
#elif SERIAL_PORT == -1
|
||||
#define MYSERIAL1 MSerialUSB
|
||||
#else
|
||||
#error "SERIAL_PORT must be from 1 to 6, or -1 for Native USB."
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if WITHIN(SERIAL_PORT_2, 1, 6)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
|
||||
#elif !defined(USBCON)
|
||||
#error "SERIAL_PORT must be from 1 to 6."
|
||||
#elif SERIAL_PORT_2 == -1
|
||||
#define MYSERIAL2 MSerialUSB
|
||||
#else
|
||||
#error "SERIAL_PORT_2 must be from 1 to 6, or -1 for Native USB."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_3
|
||||
#if WITHIN(SERIAL_PORT_3, 1, 6)
|
||||
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
|
||||
#elif !defined(USBCON)
|
||||
#error "SERIAL_PORT must be from 1 to 6."
|
||||
#elif SERIAL_PORT_3 == -1
|
||||
#define MYSERIAL3 MSerialUSB
|
||||
#else
|
||||
#error "SERIAL_PORT_3 must be from 1 to 6, or -1 for Native USB."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MMU2_SERIAL_PORT
|
||||
#if WITHIN(MMU2_SERIAL_PORT, 1, 6)
|
||||
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
|
||||
#elif !defined(USBCON)
|
||||
#error "SERIAL_PORT must be from 1 to 6."
|
||||
#elif MMU2_SERIAL_PORT == -1
|
||||
#define MMU2_SERIAL MSerialUSB
|
||||
#else
|
||||
#error "MMU2_SERIAL_PORT must be from 1 to 6, or -1 for Native USB."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LCD_SERIAL_PORT
|
||||
#if WITHIN(LCD_SERIAL_PORT, 1, 6)
|
||||
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
|
||||
#elif !defined(USBCON)
|
||||
#error "SERIAL_PORT must be from 1 to 6."
|
||||
#elif LCD_SERIAL_PORT == -1
|
||||
#define LCD_SERIAL MSerialUSB
|
||||
#else
|
||||
#error "LCD_SERIAL_PORT must be from 1 to 6, or -1 for Native USB."
|
||||
#endif
|
||||
#if HAS_DGUS_LCD
|
||||
#define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TODO: review this to return 1 for pins that are not analog input
|
||||
*/
|
||||
#ifndef analogInputToDigitalPin
|
||||
#define analogInputToDigitalPin(p) (p)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Interrupts
|
||||
//
|
||||
#define CRITICAL_SECTION_START() const bool irqon = !__get_PRIMASK(); __disable_irq()
|
||||
#define CRITICAL_SECTION_END() if (irqon) __enable_irq()
|
||||
#define cli() __disable_irq()
|
||||
#define sei() __enable_irq()
|
||||
|
||||
// ------------------------
|
||||
// Types
|
||||
// ------------------------
|
||||
|
||||
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
|
||||
|
||||
#ifdef STM32G0B1xx
|
||||
typedef int32_t pin_t;
|
||||
#else
|
||||
typedef int16_t pin_t;
|
||||
#endif
|
||||
|
||||
class libServo;
|
||||
typedef libServo hal_servo_t;
|
||||
#define PAUSE_SERVO_OUTPUT() libServo::pause_all_servos()
|
||||
#define RESUME_SERVO_OUTPUT() libServo::resume_all_servos()
|
||||
|
||||
// ------------------------
|
||||
// ADC
|
||||
// ------------------------
|
||||
|
||||
#ifdef ADC_RESOLUTION
|
||||
#define HAL_ADC_RESOLUTION ADC_RESOLUTION
|
||||
#else
|
||||
#define HAL_ADC_RESOLUTION 12
|
||||
#endif
|
||||
|
||||
#define HAL_ADC_VREF 3.3
|
||||
|
||||
//
|
||||
// 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)
|
||||
|
||||
#ifdef STM32F1xx
|
||||
#define JTAG_DISABLE() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_JTAGDISABLE)
|
||||
#define JTAGSWD_DISABLE() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_DISABLE)
|
||||
#define JTAGSWD_RESET() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_RESET); // Reset: FULL SWD+JTAG
|
||||
#endif
|
||||
|
||||
#define PLATFORM_M997_SUPPORT
|
||||
void flashFirmware(const int16_t);
|
||||
|
||||
// Maple Compatibility
|
||||
typedef void (*systickCallback_t)(void);
|
||||
void systick_attach_callback(systickCallback_t cb);
|
||||
void HAL_SYSTICK_Callback();
|
||||
|
||||
extern volatile uint32_t systick_uptime_millis;
|
||||
|
||||
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
|
||||
|
||||
// ------------------------
|
||||
// Class Utilities
|
||||
// ------------------------
|
||||
|
||||
// Memory related
|
||||
#define __bss_end __bss_end__
|
||||
|
||||
extern "C" char* _sbrk(int incr);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
static inline int freeMemory() {
|
||||
volatile char top;
|
||||
return &top - reinterpret_cast<char*>(_sbrk(0));
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// ------------------------
|
||||
// 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 from 0x0
|
||||
|
||||
// Interrupts
|
||||
static bool isr_state() { return !__get_PRIMASK(); }
|
||||
static void isr_on() { sei(); }
|
||||
static void isr_off() { cli(); }
|
||||
|
||||
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() {
|
||||
analogReadResolution(HAL_ADC_RESOLUTION);
|
||||
}
|
||||
|
||||
// Called by Temperature::init for each sensor at startup
|
||||
static void adc_enable(const pin_t pin) { pinMode(pin, INPUT); }
|
||||
|
||||
// Begin ADC sampling on the given pin. Called from Temperature::isr!
|
||||
static void adc_start(const pin_t pin) { adc_result = analogRead(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; }
|
||||
|
||||
/**
|
||||
* Set the PWM duty cycle for the pin to the given value.
|
||||
* Optionally invert the duty cycle [default = false]
|
||||
* Optionally change the maximum size 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.
|
||||
* All Timer PWM pins run at the same frequency.
|
||||
*/
|
||||
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
|
||||
|
||||
};
|
@ -0,0 +1,231 @@
|
||||
/**
|
||||
* 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
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
// ------------------------
|
||||
// Public Variables
|
||||
// ------------------------
|
||||
|
||||
static SPISettings spiConfig;
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
#if ENABLED(SOFTWARE_SPI)
|
||||
|
||||
// ------------------------
|
||||
// Software SPI
|
||||
// ------------------------
|
||||
|
||||
#include "../shared/Delay.h"
|
||||
|
||||
void spiBegin(void) {
|
||||
#if PIN_EXISTS(SD_SS)
|
||||
OUT_WRITE(SD_SS_PIN, HIGH);
|
||||
#endif
|
||||
OUT_WRITE(SD_SCK_PIN, HIGH);
|
||||
SET_INPUT(SD_MISO_PIN);
|
||||
OUT_WRITE(SD_MOSI_PIN, HIGH);
|
||||
}
|
||||
|
||||
// Use function with compile-time value so we can actually reach the desired frequency
|
||||
// Need to adjust this a little bit: on a 72MHz clock, we have 14ns/clock
|
||||
// and we'll use ~3 cycles to jump to the method and going back, so it'll take ~40ns from the given clock here
|
||||
#define CALLING_COST_NS (3U * 1000000000U) / (F_CPU)
|
||||
void (*delaySPIFunc)();
|
||||
void delaySPI_125() { DELAY_NS(125 - CALLING_COST_NS); }
|
||||
void delaySPI_250() { DELAY_NS(250 - CALLING_COST_NS); }
|
||||
void delaySPI_500() { DELAY_NS(500 - CALLING_COST_NS); }
|
||||
void delaySPI_1000() { DELAY_NS(1000 - CALLING_COST_NS); }
|
||||
void delaySPI_2000() { DELAY_NS(2000 - CALLING_COST_NS); }
|
||||
void delaySPI_4000() { DELAY_NS(4000 - CALLING_COST_NS); }
|
||||
|
||||
void spiInit(uint8_t spiRate) {
|
||||
// Use datarates Marlin uses
|
||||
switch (spiRate) {
|
||||
case SPI_FULL_SPEED: delaySPIFunc = &delaySPI_125; break; // desired: 8,000,000 actual: ~1.1M
|
||||
case SPI_HALF_SPEED: delaySPIFunc = &delaySPI_125; break; // desired: 4,000,000 actual: ~1.1M
|
||||
case SPI_QUARTER_SPEED:delaySPIFunc = &delaySPI_250; break; // desired: 2,000,000 actual: ~890K
|
||||
case SPI_EIGHTH_SPEED: delaySPIFunc = &delaySPI_500; break; // desired: 1,000,000 actual: ~590K
|
||||
case SPI_SPEED_5: delaySPIFunc = &delaySPI_1000; break; // desired: 500,000 actual: ~360K
|
||||
case SPI_SPEED_6: delaySPIFunc = &delaySPI_2000; break; // desired: 250,000 actual: ~210K
|
||||
default: delaySPIFunc = &delaySPI_4000; break; // desired: 125,000 actual: ~123K
|
||||
}
|
||||
SPI.begin();
|
||||
}
|
||||
|
||||
// Begin SPI transaction, set clock, bit order, data mode
|
||||
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) { /* do nothing */ }
|
||||
|
||||
uint8_t HAL_SPI_STM32_SpiTransfer_Mode_3(uint8_t b) { // using Mode 3
|
||||
for (uint8_t bits = 8; bits--;) {
|
||||
WRITE(SD_SCK_PIN, LOW);
|
||||
WRITE(SD_MOSI_PIN, b & 0x80);
|
||||
|
||||
delaySPIFunc();
|
||||
WRITE(SD_SCK_PIN, HIGH);
|
||||
delaySPIFunc();
|
||||
|
||||
b <<= 1; // little setup time
|
||||
b |= (READ(SD_MISO_PIN) != 0);
|
||||
}
|
||||
DELAY_NS(125);
|
||||
return b;
|
||||
}
|
||||
|
||||
// Soft SPI receive byte
|
||||
uint8_t spiRec() {
|
||||
hal.isr_off(); // No interrupts during byte receive
|
||||
const uint8_t data = HAL_SPI_STM32_SpiTransfer_Mode_3(0xFF);
|
||||
hal.isr_on(); // Enable interrupts
|
||||
return data;
|
||||
}
|
||||
|
||||
// Soft SPI read data
|
||||
void spiRead(uint8_t *buf, uint16_t nbyte) {
|
||||
for (uint16_t i = 0; i < nbyte; i++)
|
||||
buf[i] = spiRec();
|
||||
}
|
||||
|
||||
// Soft SPI send byte
|
||||
void spiSend(uint8_t data) {
|
||||
hal.isr_off(); // No interrupts during byte send
|
||||
HAL_SPI_STM32_SpiTransfer_Mode_3(data); // Don't care what is received
|
||||
hal.isr_on(); // Enable interrupts
|
||||
}
|
||||
|
||||
// Soft SPI send block
|
||||
void spiSendBlock(uint8_t token, const uint8_t *buf) {
|
||||
spiSend(token);
|
||||
for (uint16_t i = 0; i < 512; i++)
|
||||
spiSend(buf[i]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// ------------------------
|
||||
// Hardware SPI
|
||||
// ------------------------
|
||||
|
||||
/**
|
||||
* VGPV SPI speed start and PCLK2/2, by default 108/2 = 54Mhz
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Begin SPI port setup
|
||||
*
|
||||
* @return Nothing
|
||||
*
|
||||
* @details Only configures SS pin since stm32duino creates and initialize the SPI object
|
||||
*/
|
||||
void spiBegin() {
|
||||
#if PIN_EXISTS(SD_SS)
|
||||
OUT_WRITE(SD_SS_PIN, HIGH);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Configure SPI for specified SPI speed
|
||||
void spiInit(uint8_t spiRate) {
|
||||
// Use datarates Marlin uses
|
||||
uint32_t clock;
|
||||
switch (spiRate) {
|
||||
case SPI_FULL_SPEED: clock = 20000000; break; // 13.9mhz=20000000 6.75mhz=10000000 3.38mhz=5000000 .833mhz=1000000
|
||||
case SPI_HALF_SPEED: clock = 5000000; break;
|
||||
case SPI_QUARTER_SPEED: clock = 2500000; break;
|
||||
case SPI_EIGHTH_SPEED: clock = 1250000; break;
|
||||
case SPI_SPEED_5: clock = 625000; break;
|
||||
case SPI_SPEED_6: clock = 300000; break;
|
||||
default:
|
||||
clock = 4000000; // Default from the SPI library
|
||||
}
|
||||
spiConfig = SPISettings(clock, MSBFIRST, SPI_MODE0);
|
||||
|
||||
SPI.setMISO(SD_MISO_PIN);
|
||||
SPI.setMOSI(SD_MOSI_PIN);
|
||||
SPI.setSCLK(SD_SCK_PIN);
|
||||
|
||||
SPI.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives a single byte from the SPI port.
|
||||
*
|
||||
* @return Byte received
|
||||
*
|
||||
* @details
|
||||
*/
|
||||
uint8_t spiRec() {
|
||||
uint8_t returnByte = SPI.transfer(0xFF);
|
||||
return returnByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive a number of bytes from the SPI port to a buffer
|
||||
*
|
||||
* @param buf Pointer to starting address of buffer to write to.
|
||||
* @param nbyte Number of bytes to receive.
|
||||
* @return Nothing
|
||||
*
|
||||
* @details Uses DMA
|
||||
*/
|
||||
void spiRead(uint8_t *buf, uint16_t nbyte) {
|
||||
if (nbyte == 0) return;
|
||||
memset(buf, 0xFF, nbyte);
|
||||
SPI.transfer(buf, nbyte);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a single byte on SPI port
|
||||
*
|
||||
* @param b Byte to send
|
||||
*
|
||||
* @details
|
||||
*/
|
||||
void spiSend(uint8_t b) {
|
||||
SPI.transfer(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write token and then write from 512 byte buffer to SPI (for SD card)
|
||||
*
|
||||
* @param buf Pointer with buffer start address
|
||||
* @return Nothing
|
||||
*
|
||||
* @details Use DMA
|
||||
*/
|
||||
void spiSendBlock(uint8_t token, const uint8_t *buf) {
|
||||
uint8_t rxBuf[512];
|
||||
SPI.transfer(token);
|
||||
SPI.transfer((uint8_t*)buf, &rxBuf, 512);
|
||||
}
|
||||
|
||||
#endif // SOFTWARE_SPI
|
||||
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,174 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../platforms.h"
|
||||
|
||||
#if defined(HAL_STM32) && !defined(STM32H7xx)
|
||||
|
||||
#include "MarlinSPI.h"
|
||||
|
||||
static void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb, uint32_t dataSize) {
|
||||
spi_init(obj, speed, mode, msb);
|
||||
// spi_init set 8bit always
|
||||
// TODO: copy the code from spi_init and handle data size, to avoid double init always!!
|
||||
if (dataSize != SPI_DATASIZE_8BIT) {
|
||||
obj->handle.Init.DataSize = dataSize;
|
||||
HAL_SPI_Init(&obj->handle);
|
||||
__HAL_SPI_ENABLE(&obj->handle);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSPI::setClockDivider(uint8_t _div) {
|
||||
_speed = spi_getClkFreq(&_spi);// / _div;
|
||||
_clockDivider = _div;
|
||||
}
|
||||
|
||||
void MarlinSPI::begin(void) {
|
||||
//TODO: only call spi_init if any parameter changed!!
|
||||
spi_init(&_spi, _speed, _dataMode, _bitOrder, _dataSize);
|
||||
}
|
||||
|
||||
void MarlinSPI::setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc) {
|
||||
_dmaHandle.Init.Direction = direction;
|
||||
_dmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
_dmaHandle.Init.Mode = DMA_NORMAL;
|
||||
_dmaHandle.Init.Priority = DMA_PRIORITY_LOW;
|
||||
_dmaHandle.Init.MemInc = minc ? DMA_MINC_ENABLE : DMA_MINC_DISABLE;
|
||||
|
||||
if (_dataSize == DATA_SIZE_8BIT) {
|
||||
_dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
_dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
}
|
||||
else {
|
||||
_dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
|
||||
_dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
|
||||
}
|
||||
#ifdef STM32F4xx
|
||||
_dmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
|
||||
#endif
|
||||
|
||||
// start DMA hardware
|
||||
// TODO: check if hardware is already enabled
|
||||
#ifdef SPI1_BASE
|
||||
if (_spiHandle.Instance == SPI1) {
|
||||
#ifdef STM32F1xx
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
_dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel3 : DMA1_Channel2;
|
||||
#elif defined(STM32F4xx)
|
||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||
_dmaHandle.Init.Channel = DMA_CHANNEL_3;
|
||||
_dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA2_Stream3 : DMA2_Stream0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef SPI2_BASE
|
||||
if (_spiHandle.Instance == SPI2) {
|
||||
#ifdef STM32F1xx
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
_dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel5 : DMA1_Channel4;
|
||||
#elif defined(STM32F4xx)
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
_dmaHandle.Init.Channel = DMA_CHANNEL_0;
|
||||
_dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Stream4 : DMA1_Stream3;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef SPI3_BASE
|
||||
if (_spiHandle.Instance == SPI3) {
|
||||
#ifdef STM32F1xx
|
||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||
_dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA2_Channel2 : DMA2_Channel1;
|
||||
#elif defined(STM32F4xx)
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
_dmaHandle.Init.Channel = DMA_CHANNEL_0;
|
||||
_dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Stream5 : DMA1_Stream2;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
HAL_DMA_Init(&_dmaHandle);
|
||||
}
|
||||
|
||||
byte MarlinSPI::transfer(uint8_t _data) {
|
||||
uint8_t rxData = 0xFF;
|
||||
HAL_SPI_TransmitReceive(&_spi.handle, &_data, &rxData, 1, HAL_MAX_DELAY);
|
||||
return rxData;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); }
|
||||
__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); }
|
||||
|
||||
uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) {
|
||||
const uint8_t ff = 0xFF;
|
||||
|
||||
//if (!LL_SPI_IsEnabled(_spi.handle)) // only enable if disabled
|
||||
__HAL_SPI_ENABLE(&_spi.handle);
|
||||
|
||||
if (receiveBuf) {
|
||||
setupDma(_spi.handle, _dmaRx, DMA_PERIPH_TO_MEMORY, true);
|
||||
HAL_DMA_Start(&_dmaRx, (uint32_t)&(_spi.handle.Instance->DR), (uint32_t)receiveBuf, length);
|
||||
LL_SPI_EnableDMAReq_RX(_spi.handle.Instance); // Enable Rx DMA Request
|
||||
}
|
||||
|
||||
// check for 2 lines transfer
|
||||
bool mincTransmit = true;
|
||||
if (transmitBuf == nullptr && _spi.handle.Init.Direction == SPI_DIRECTION_2LINES && _spi.handle.Init.Mode == SPI_MODE_MASTER) {
|
||||
transmitBuf = &ff;
|
||||
mincTransmit = false;
|
||||
}
|
||||
|
||||
if (transmitBuf) {
|
||||
setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, mincTransmit);
|
||||
HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
|
||||
LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request
|
||||
}
|
||||
|
||||
if (transmitBuf) {
|
||||
HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
|
||||
HAL_DMA_Abort(&_dmaTx);
|
||||
HAL_DMA_DeInit(&_dmaTx);
|
||||
}
|
||||
|
||||
// while ((_spi.handle.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
|
||||
|
||||
if (receiveBuf) {
|
||||
HAL_DMA_PollForTransfer(&_dmaRx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
|
||||
HAL_DMA_Abort(&_dmaRx);
|
||||
HAL_DMA_DeInit(&_dmaRx);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t MarlinSPI::dmaSend(const void * transmitBuf, uint16_t length, bool minc) {
|
||||
setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, minc);
|
||||
HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
|
||||
__HAL_SPI_ENABLE(&_spi.handle);
|
||||
LL_SPI_EnableDMAReq_TX(_spi.handle.Instance); // Enable Tx DMA Request
|
||||
HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
|
||||
HAL_DMA_Abort(&_dmaTx);
|
||||
// DeInit objects
|
||||
HAL_DMA_DeInit(&_dmaTx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // HAL_STM32 && !STM32H7xx
|
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "HAL.h"
|
||||
#include <SPI.h>
|
||||
|
||||
extern "C" {
|
||||
#include <utility/spi_com.h>
|
||||
}
|
||||
|
||||
/**
|
||||
* Marlin currently requires 3 SPI classes:
|
||||
*
|
||||
* SPIClass:
|
||||
* This class is normally provided by frameworks and has a semi-default interface.
|
||||
* This is needed because some libraries reference it globally.
|
||||
*
|
||||
* SPISettings:
|
||||
* Container for SPI configs for SPIClass. As above, libraries may reference it globally.
|
||||
*
|
||||
* These two classes are often provided by frameworks so we cannot extend them to add
|
||||
* useful methods for Marlin.
|
||||
*
|
||||
* MarlinSPI:
|
||||
* Provides the default SPIClass interface plus some Marlin goodies such as a simplified
|
||||
* interface for SPI DMA transfer.
|
||||
*
|
||||
*/
|
||||
|
||||
#define DATA_SIZE_8BIT SPI_DATASIZE_8BIT
|
||||
#define DATA_SIZE_16BIT SPI_DATASIZE_16BIT
|
||||
|
||||
class MarlinSPI {
|
||||
public:
|
||||
MarlinSPI() : MarlinSPI(NC, NC, NC, NC) {}
|
||||
|
||||
MarlinSPI(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel = (pin_t)NC) : _mosiPin(mosi), _misoPin(miso), _sckPin(sclk), _ssPin(ssel) {
|
||||
_spi.pin_miso = digitalPinToPinName(_misoPin);
|
||||
_spi.pin_mosi = digitalPinToPinName(_mosiPin);
|
||||
_spi.pin_sclk = digitalPinToPinName(_sckPin);
|
||||
_spi.pin_ssel = digitalPinToPinName(_ssPin);
|
||||
_dataSize = DATA_SIZE_8BIT;
|
||||
_bitOrder = MSBFIRST;
|
||||
_dataMode = SPI_MODE_0;
|
||||
_spi.handle.State = HAL_SPI_STATE_RESET;
|
||||
setClockDivider(SPI_SPEED_CLOCK_DIV2_MHZ);
|
||||
}
|
||||
|
||||
void begin(void);
|
||||
void end(void) {}
|
||||
|
||||
byte transfer(uint8_t _data);
|
||||
uint8_t dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length);
|
||||
uint8_t dmaSend(const void * transmitBuf, uint16_t length, bool minc = true);
|
||||
|
||||
/* These methods are deprecated and kept for compatibility.
|
||||
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
|
||||
*/
|
||||
void setBitOrder(BitOrder _order) { _bitOrder = _order; }
|
||||
|
||||
void setDataMode(uint8_t _mode) {
|
||||
switch (_mode) {
|
||||
case SPI_MODE0: _dataMode = SPI_MODE_0; break;
|
||||
case SPI_MODE1: _dataMode = SPI_MODE_1; break;
|
||||
case SPI_MODE2: _dataMode = SPI_MODE_2; break;
|
||||
case SPI_MODE3: _dataMode = SPI_MODE_3; break;
|
||||
}
|
||||
}
|
||||
|
||||
void setClockDivider(uint8_t _div);
|
||||
|
||||
private:
|
||||
void setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc = false);
|
||||
|
||||
spi_t _spi;
|
||||
DMA_HandleTypeDef _dmaTx;
|
||||
DMA_HandleTypeDef _dmaRx;
|
||||
BitOrder _bitOrder;
|
||||
spi_mode_e _dataMode;
|
||||
uint8_t _clockDivider;
|
||||
uint32_t _speed;
|
||||
uint32_t _dataSize;
|
||||
pin_t _mosiPin;
|
||||
pin_t _misoPin;
|
||||
pin_t _sckPin;
|
||||
pin_t _ssPin;
|
||||
};
|
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "MarlinSerial.h"
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#include "../../feature/e_parser.h"
|
||||
#endif
|
||||
|
||||
#ifndef USART4
|
||||
#define USART4 UART4
|
||||
#endif
|
||||
#ifndef USART5
|
||||
#define USART5 UART5
|
||||
#endif
|
||||
|
||||
#define DECLARE_SERIAL_PORT(ser_num) \
|
||||
void _rx_complete_irq_ ## ser_num (serial_t * obj); \
|
||||
MSerialT MSerial ## ser_num (true, USART ## ser_num, &_rx_complete_irq_ ## ser_num); \
|
||||
void _rx_complete_irq_ ## ser_num (serial_t * obj) { MSerial ## ser_num ._rx_complete_irq(obj); }
|
||||
|
||||
#if USING_HW_SERIAL1
|
||||
DECLARE_SERIAL_PORT(1)
|
||||
#endif
|
||||
#if USING_HW_SERIAL2
|
||||
DECLARE_SERIAL_PORT(2)
|
||||
#endif
|
||||
#if USING_HW_SERIAL3
|
||||
DECLARE_SERIAL_PORT(3)
|
||||
#endif
|
||||
#if USING_HW_SERIAL4
|
||||
DECLARE_SERIAL_PORT(4)
|
||||
#endif
|
||||
#if USING_HW_SERIAL5
|
||||
DECLARE_SERIAL_PORT(5)
|
||||
#endif
|
||||
#if USING_HW_SERIAL6
|
||||
DECLARE_SERIAL_PORT(6)
|
||||
#endif
|
||||
#if USING_HW_SERIAL7
|
||||
DECLARE_SERIAL_PORT(7)
|
||||
#endif
|
||||
#if USING_HW_SERIAL8
|
||||
DECLARE_SERIAL_PORT(8)
|
||||
#endif
|
||||
#if USING_HW_SERIAL9
|
||||
DECLARE_SERIAL_PORT(9)
|
||||
#endif
|
||||
#if USING_HW_SERIAL10
|
||||
DECLARE_SERIAL_PORT(10)
|
||||
#endif
|
||||
#if USING_HW_SERIALLP1
|
||||
DECLARE_SERIAL_PORT(LP1)
|
||||
#endif
|
||||
|
||||
void MarlinSerial::begin(unsigned long baud, uint8_t config) {
|
||||
HardwareSerial::begin(baud, config);
|
||||
// Replace the IRQ callback with the one we have defined
|
||||
TERN_(EMERGENCY_PARSER, _serial.rx_callback = _rx_callback);
|
||||
}
|
||||
|
||||
// This function is Copyright (c) 2006 Nicholas Zambetti.
|
||||
void MarlinSerial::_rx_complete_irq(serial_t *obj) {
|
||||
// No Parity error, read byte and store it in the buffer if there is room
|
||||
unsigned char c;
|
||||
|
||||
if (uart_getc(obj, &c) == 0) {
|
||||
|
||||
rx_buffer_index_t i = (unsigned int)(obj->rx_head + 1) % SERIAL_RX_BUFFER_SIZE;
|
||||
|
||||
// if we should be storing the received character into the location
|
||||
// just before the tail (meaning that the head would advance to the
|
||||
// current location of the tail), we're about to overflow the buffer
|
||||
// and so we don't write the character or advance the head.
|
||||
if (i != obj->rx_tail) {
|
||||
obj->rx_buff[obj->rx_head] = c;
|
||||
obj->rx_head = i;
|
||||
}
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
emergency_parser.update(static_cast<MSerialT*>(this)->emergency_state, c);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#include "../../feature/e_parser.h"
|
||||
#endif
|
||||
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
typedef void (*usart_rx_callback_t)(serial_t * obj);
|
||||
|
||||
struct MarlinSerial : public HardwareSerial {
|
||||
MarlinSerial(void *peripheral, usart_rx_callback_t rx_callback) :
|
||||
HardwareSerial(peripheral), _rx_callback(rx_callback)
|
||||
{ }
|
||||
|
||||
void begin(unsigned long baud, uint8_t config);
|
||||
inline void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
|
||||
|
||||
void _rx_complete_irq(serial_t *obj);
|
||||
|
||||
protected:
|
||||
usart_rx_callback_t _rx_callback;
|
||||
};
|
||||
|
||||
typedef Serial1Class<MarlinSerial> MSerialT;
|
||||
extern MSerialT MSerial1;
|
||||
extern MSerialT MSerial2;
|
||||
extern MSerialT MSerial3;
|
||||
extern MSerialT MSerial4;
|
||||
extern MSerialT MSerial5;
|
||||
extern MSerialT MSerial6;
|
||||
extern MSerialT MSerial7;
|
||||
extern MSerialT MSerial8;
|
||||
extern MSerialT MSerial9;
|
||||
extern MSerialT MSerial10;
|
||||
extern MSerialT MSerialLP1;
|
@ -0,0 +1,153 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
|
||||
#include "../shared/MinSerial.h"
|
||||
|
||||
/* Instruction Synchronization Barrier */
|
||||
#define isb() __asm__ __volatile__ ("isb" : : : "memory")
|
||||
|
||||
/* Data Synchronization Barrier */
|
||||
#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
|
||||
|
||||
// Dumb mapping over the registers of a USART device on STM32
|
||||
struct USARTMin {
|
||||
volatile uint32_t SR;
|
||||
volatile uint32_t DR;
|
||||
volatile uint32_t BRR;
|
||||
volatile uint32_t CR1;
|
||||
volatile uint32_t CR2;
|
||||
};
|
||||
|
||||
#if WITHIN(SERIAL_PORT, 1, 6)
|
||||
// Depending on the CPU, the serial port is different for USART1
|
||||
static const uintptr_t regsAddr[] = {
|
||||
TERN(STM32F1xx, 0x40013800, 0x40011000), // USART1
|
||||
0x40004400, // USART2
|
||||
0x40004800, // USART3
|
||||
0x40004C00, // UART4_BASE
|
||||
0x40005000, // UART5_BASE
|
||||
0x40011400 // USART6
|
||||
};
|
||||
static USARTMin * regs = (USARTMin*)regsAddr[SERIAL_PORT - 1];
|
||||
#endif
|
||||
|
||||
static void TXBegin() {
|
||||
#if !WITHIN(SERIAL_PORT, 1, 6)
|
||||
#warning "Using POSTMORTEM_DEBUGGING requires a physical U(S)ART hardware in case of severe error."
|
||||
#warning "Disabling the severe error reporting feature currently because the used serial port is not a HW port."
|
||||
#else
|
||||
// This is common between STM32F1/STM32F2 and STM32F4
|
||||
const int nvicUART[] = { /* NVIC_USART1 */ 37, /* NVIC_USART2 */ 38, /* NVIC_USART3 */ 39, /* NVIC_UART4 */ 52, /* NVIC_UART5 */ 53, /* NVIC_USART6 */ 71 };
|
||||
int nvicIndex = nvicUART[SERIAL_PORT - 1];
|
||||
|
||||
struct NVICMin {
|
||||
volatile uint32_t ISER[32];
|
||||
volatile uint32_t ICER[32];
|
||||
};
|
||||
|
||||
NVICMin *nvicBase = (NVICMin*)0xE000E100;
|
||||
SBI32(nvicBase->ICER[nvicIndex >> 5], nvicIndex & 0x1F);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
dsb();
|
||||
isb();
|
||||
|
||||
// Example for USART1 disable: (RCC->APB2ENR &= ~(RCC_APB2ENR_USART1EN))
|
||||
// Too difficult to reimplement here, let's query the STM32duino macro here
|
||||
#if SERIAL_PORT == 1
|
||||
__HAL_RCC_USART1_CLK_DISABLE();
|
||||
__HAL_RCC_USART1_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 2
|
||||
__HAL_RCC_USART2_CLK_DISABLE();
|
||||
__HAL_RCC_USART2_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 3
|
||||
__HAL_RCC_USART3_CLK_DISABLE();
|
||||
__HAL_RCC_USART3_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 4
|
||||
__HAL_RCC_UART4_CLK_DISABLE(); // BEWARE: UART4 and not USART4 here
|
||||
__HAL_RCC_UART4_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 5
|
||||
__HAL_RCC_UART5_CLK_DISABLE(); // BEWARE: UART5 and not USART5 here
|
||||
__HAL_RCC_UART5_CLK_ENABLE();
|
||||
#elif SERIAL_PORT == 6
|
||||
__HAL_RCC_USART6_CLK_DISABLE();
|
||||
__HAL_RCC_USART6_CLK_ENABLE();
|
||||
#endif
|
||||
|
||||
uint32_t brr = regs->BRR;
|
||||
regs->CR1 = 0; // Reset the USART
|
||||
regs->CR2 = 0; // 1 stop bit
|
||||
|
||||
// If we don't touch the BRR (baudrate register), we don't need to recompute.
|
||||
regs->BRR = brr;
|
||||
|
||||
regs->CR1 = _BV(3) | _BV(13); // 8 bits, no parity, 1 stop bit (TE | UE)
|
||||
#endif
|
||||
}
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() __asm__ volatile("": : :"memory");
|
||||
static void TX(char c) {
|
||||
#if WITHIN(SERIAL_PORT, 1, 6)
|
||||
constexpr uint32_t usart_sr_txe = _BV(7);
|
||||
while (!(regs->SR & usart_sr_txe)) {
|
||||
hal.watchdog_refresh();
|
||||
sw_barrier();
|
||||
}
|
||||
regs->DR = c;
|
||||
#else
|
||||
// Let's hope a mystical guru will fix this, one day by writing interrupt-free USB CDC ACM code (or, at least, by polling the registers since interrupt will be queued but will never trigger)
|
||||
// For now, it's completely lost to oblivion.
|
||||
#endif
|
||||
}
|
||||
|
||||
void install_min_serial() {
|
||||
HAL_min_serial_init = &TXBegin;
|
||||
HAL_min_serial_out = &TX;
|
||||
}
|
||||
|
||||
#if NONE(DYNAMIC_VECTORTABLE, STM32F0xx, STM32G0xx) // Cortex M0 can't jump to a symbol that's too far from the current function, so we work around this in exception_arm.cpp
|
||||
extern "C" {
|
||||
__attribute__((naked)) void JumpHandler_ASM() {
|
||||
__asm__ __volatile__ (
|
||||
"b CommonHandler_ASM\n"
|
||||
);
|
||||
}
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) HardFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) BusFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) UsageFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) MemManage_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) NMI_Handler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // POSTMORTEM_DEBUGGING
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,11 @@
|
||||
# Generic STM32 HAL based on the stm32duino core
|
||||
|
||||
This HAL is intended to act as the generic STM32 HAL for all STM32 chips (The whole F, H and L family).
|
||||
|
||||
Currently it supports:
|
||||
* STM32F0xx
|
||||
* STM32F1xx
|
||||
* STM32F4xx
|
||||
* STM32F7xx
|
||||
|
||||
Targeting the official [Arduino STM32 Core](https://github.com/stm32duino/Arduino_Core_STM32).
|
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 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
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_SERVOS
|
||||
|
||||
#include "Servo.h"
|
||||
|
||||
static uint_fast8_t servoCount = 0;
|
||||
static libServo *servos[NUM_SERVOS] = {0};
|
||||
constexpr millis_t servoDelay[] = SERVO_DELAY;
|
||||
static_assert(COUNT(servoDelay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
|
||||
|
||||
// Initialize to the default timer priority. This will be overridden by a call from timers.cpp.
|
||||
// This allows all timer interrupt priorities to be managed from a single location in the HAL.
|
||||
static uint32_t servo_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), TIM_IRQ_PRIO, TIM_IRQ_SUBPRIO);
|
||||
|
||||
// This must be called after the STM32 Servo class has initialized the timer.
|
||||
// It may only be needed after the first call to attach(), but it is possible
|
||||
// that is is necessary after every detach() call. To be safe this is currently
|
||||
// called after every call to attach().
|
||||
static void fixServoTimerInterruptPriority() {
|
||||
NVIC_SetPriority(getTimerUpIrq(TIMER_SERVO), servo_interrupt_priority);
|
||||
}
|
||||
|
||||
libServo::libServo()
|
||||
: delay(servoDelay[servoCount]),
|
||||
was_attached_before_pause(false),
|
||||
value_before_pause(0)
|
||||
{
|
||||
servos[servoCount++] = this;
|
||||
}
|
||||
|
||||
int8_t libServo::attach(const int pin) {
|
||||
if (servoCount >= MAX_SERVOS) return -1;
|
||||
if (pin > 0) servo_pin = pin;
|
||||
auto result = stm32_servo.attach(servo_pin);
|
||||
fixServoTimerInterruptPriority();
|
||||
return result;
|
||||
}
|
||||
|
||||
int8_t libServo::attach(const int pin, const int min, const int max) {
|
||||
if (servoCount >= MAX_SERVOS) return -1;
|
||||
if (pin > 0) servo_pin = pin;
|
||||
auto result = stm32_servo.attach(servo_pin, min, max);
|
||||
fixServoTimerInterruptPriority();
|
||||
return result;
|
||||
}
|
||||
|
||||
void libServo::move(const int value) {
|
||||
if (attach(0) >= 0) {
|
||||
stm32_servo.write(value);
|
||||
safe_delay(delay);
|
||||
TERN_(DEACTIVATE_SERVOS_AFTER_MOVE, detach());
|
||||
}
|
||||
}
|
||||
|
||||
void libServo::pause() {
|
||||
was_attached_before_pause = stm32_servo.attached();
|
||||
if (was_attached_before_pause) {
|
||||
value_before_pause = stm32_servo.read();
|
||||
stm32_servo.detach();
|
||||
}
|
||||
}
|
||||
|
||||
void libServo::resume() {
|
||||
if (was_attached_before_pause) {
|
||||
attach();
|
||||
move(value_before_pause);
|
||||
}
|
||||
}
|
||||
|
||||
void libServo::pause_all_servos() {
|
||||
for (auto& servo : servos)
|
||||
if (servo) servo->pause();
|
||||
}
|
||||
|
||||
void libServo::resume_all_servos() {
|
||||
for (auto& servo : servos)
|
||||
if (servo) servo->resume();
|
||||
}
|
||||
|
||||
void libServo::setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority) {
|
||||
servo_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), preemptPriority, subPriority);
|
||||
}
|
||||
|
||||
#endif // HAS_SERVOS
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Servo.h>
|
||||
|
||||
#include "../../core/millis_t.h"
|
||||
|
||||
// Inherit and expand on the official library
|
||||
class libServo {
|
||||
public:
|
||||
libServo();
|
||||
int8_t attach(const int pin = 0); // pin == 0 uses value from previous call
|
||||
int8_t attach(const int pin, const int min, const int max);
|
||||
void detach() { stm32_servo.detach(); }
|
||||
int read() { return stm32_servo.read(); }
|
||||
void move(const int value);
|
||||
|
||||
void pause();
|
||||
void resume();
|
||||
|
||||
static void pause_all_servos();
|
||||
static void resume_all_servos();
|
||||
static void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority);
|
||||
|
||||
private:
|
||||
Servo stm32_servo;
|
||||
|
||||
int servo_pin = 0;
|
||||
millis_t delay = 0;
|
||||
|
||||
bool was_attached_before_pause;
|
||||
int value_before_pause;
|
||||
};
|
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
/**
|
||||
* PersistentStore for Arduino-style EEPROM interface
|
||||
* with simple implementations supplied by Marlin.
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(IIC_BL24CXX_EEPROM)
|
||||
|
||||
#include "../shared/eeprom_if.h"
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
//
|
||||
// PersistentStore
|
||||
//
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#error "MARLIN_EEPROM_SIZE is required for IIC_BL24CXX_EEPROM."
|
||||
#endif
|
||||
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
|
||||
bool PersistentStore::access_start() { eeprom_init(); return true; }
|
||||
bool PersistentStore::access_finish() { return true; }
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
uint16_t written = 0;
|
||||
while (size--) {
|
||||
uint8_t v = *value;
|
||||
uint8_t * const p = (uint8_t * const)pos;
|
||||
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
|
||||
eeprom_write_byte(p, v);
|
||||
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
|
||||
if (eeprom_read_byte(p) != v) {
|
||||
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
crc16(crc, &v, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
do {
|
||||
uint8_t * const p = (uint8_t * const)pos;
|
||||
uint8_t c = eeprom_read_byte(p);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
} while (--size);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // IIC_BL24CXX_EEPROM
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,279 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
*
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
|
||||
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
|
||||
* Copyright (c) 2016 Victor Perez victor_pv@hotmail.com
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(FLASH_EEPROM_EMULATION)
|
||||
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
// Better: "utility/stm32_eeprom.h", but only after updating stm32duino to 2.0.0
|
||||
// Use EEPROM.h for compatibility, for now.
|
||||
#include <EEPROM.h>
|
||||
|
||||
/**
|
||||
* The STM32 HAL supports chips that deal with "pages" and some with "sectors" and some that
|
||||
* even have multiple "banks" of flash.
|
||||
*
|
||||
* This code is a bit of a mashup of
|
||||
* framework-arduinoststm32/cores/arduino/stm32/stm32_eeprom.c
|
||||
* hal/hal_lpc1768/persistent_store_flash.cpp
|
||||
*
|
||||
* This has only be written against those that use a single "sector" design.
|
||||
*
|
||||
* Those that deal with "pages" could be made to work. Looking at the STM32F07 for example, there are
|
||||
* 128 "pages", each 2kB in size. If we continued with our EEPROM being 4Kb, we'd always need to operate
|
||||
* on 2 of these pages. Each write, we'd use 2 different pages from a pool of pages until we are done.
|
||||
*/
|
||||
|
||||
#if ENABLED(FLASH_EEPROM_LEVELING)
|
||||
|
||||
#include "stm32_def.h"
|
||||
|
||||
#define DEBUG_OUT ENABLED(EEPROM_CHITCHAT)
|
||||
#include "../../core/debug_out.h"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_SECTOR
|
||||
#define FLASH_SECTOR (FLASH_SECTOR_TOTAL - 1)
|
||||
#endif
|
||||
#ifndef FLASH_UNIT_SIZE
|
||||
#define FLASH_UNIT_SIZE 0x20000 // 128kB
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_ADDRESS_START
|
||||
#define FLASH_ADDRESS_START (FLASH_END - ((FLASH_SECTOR_TOTAL - (FLASH_SECTOR)) * (FLASH_UNIT_SIZE)) + 1)
|
||||
#endif
|
||||
#define FLASH_ADDRESS_END (FLASH_ADDRESS_START + FLASH_UNIT_SIZE - 1)
|
||||
|
||||
#define EEPROM_SLOTS ((FLASH_UNIT_SIZE) / (MARLIN_EEPROM_SIZE))
|
||||
#define SLOT_ADDRESS(slot) (FLASH_ADDRESS_START + (slot * (MARLIN_EEPROM_SIZE)))
|
||||
|
||||
#define UNLOCK_FLASH() if (!flash_unlocked) { \
|
||||
HAL_FLASH_Unlock(); \
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
|
||||
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); \
|
||||
flash_unlocked = true; \
|
||||
}
|
||||
#define LOCK_FLASH() if (flash_unlocked) { HAL_FLASH_Lock(); flash_unlocked = false; }
|
||||
|
||||
#define EMPTY_UINT32 ((uint32_t)-1)
|
||||
#define EMPTY_UINT8 ((uint8_t)-1)
|
||||
|
||||
static uint8_t ram_eeprom[MARLIN_EEPROM_SIZE] __attribute__((aligned(4))) = {0};
|
||||
static int current_slot = -1;
|
||||
|
||||
static_assert(0 == MARLIN_EEPROM_SIZE % 4, "MARLIN_EEPROM_SIZE must be a multiple of 4"); // Ensure copying as uint32_t is safe
|
||||
static_assert(0 == FLASH_UNIT_SIZE % MARLIN_EEPROM_SIZE, "MARLIN_EEPROM_SIZE must divide evenly into your FLASH_UNIT_SIZE");
|
||||
static_assert(FLASH_UNIT_SIZE >= MARLIN_EEPROM_SIZE, "FLASH_UNIT_SIZE must be greater than or equal to your MARLIN_EEPROM_SIZE");
|
||||
static_assert(IS_FLASH_SECTOR(FLASH_SECTOR), "FLASH_SECTOR is invalid");
|
||||
static_assert(IS_POWER_OF_2(FLASH_UNIT_SIZE), "FLASH_UNIT_SIZE should be a power of 2, please check your chip's spec sheet");
|
||||
|
||||
#endif // FLASH_EEPROM_LEVELING
|
||||
|
||||
static bool eeprom_data_written = false;
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#define MARLIN_EEPROM_SIZE size_t(E2END + 1)
|
||||
#endif
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
|
||||
bool PersistentStore::access_start() {
|
||||
|
||||
EEPROM.begin(); // Avoid STM32 EEPROM.h warning (do nothing)
|
||||
|
||||
#if ENABLED(FLASH_EEPROM_LEVELING)
|
||||
|
||||
if (current_slot == -1 || eeprom_data_written) {
|
||||
// This must be the first time since power on that we have accessed the storage, or someone
|
||||
// loaded and called write_data and never called access_finish.
|
||||
// Lets go looking for the slot that holds our configuration.
|
||||
if (eeprom_data_written) DEBUG_ECHOLNPGM("Dangling EEPROM write_data");
|
||||
uint32_t address = FLASH_ADDRESS_START;
|
||||
while (address <= FLASH_ADDRESS_END) {
|
||||
uint32_t address_value = (*(__IO uint32_t*)address);
|
||||
if (address_value != EMPTY_UINT32) {
|
||||
current_slot = (address - (FLASH_ADDRESS_START)) / (MARLIN_EEPROM_SIZE);
|
||||
break;
|
||||
}
|
||||
address += sizeof(uint32_t);
|
||||
}
|
||||
if (current_slot == -1) {
|
||||
// We didn't find anything, so we'll just initialize to empty
|
||||
for (int i = 0; i < MARLIN_EEPROM_SIZE; i++) ram_eeprom[i] = EMPTY_UINT8;
|
||||
current_slot = EEPROM_SLOTS;
|
||||
}
|
||||
else {
|
||||
// load current settings
|
||||
uint8_t *eeprom_data = (uint8_t *)SLOT_ADDRESS(current_slot);
|
||||
for (int i = 0; i < MARLIN_EEPROM_SIZE; i++) ram_eeprom[i] = eeprom_data[i];
|
||||
DEBUG_ECHOLNPGM("EEPROM loaded from slot ", current_slot, ".");
|
||||
}
|
||||
eeprom_data_written = false;
|
||||
}
|
||||
|
||||
#else
|
||||
eeprom_buffer_fill();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::access_finish() {
|
||||
|
||||
if (eeprom_data_written) {
|
||||
#ifdef STM32F4xx
|
||||
// MCU may come up with flash error bits which prevent some flash operations.
|
||||
// Clear flags prior to flash operations to prevent errors.
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
||||
#endif
|
||||
|
||||
#if ENABLED(FLASH_EEPROM_LEVELING)
|
||||
|
||||
HAL_StatusTypeDef status = HAL_ERROR;
|
||||
bool flash_unlocked = false;
|
||||
|
||||
if (--current_slot < 0) {
|
||||
// all slots have been used, erase everything and start again
|
||||
|
||||
FLASH_EraseInitTypeDef EraseInitStruct;
|
||||
uint32_t SectorError = 0;
|
||||
|
||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||||
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
||||
EraseInitStruct.Sector = FLASH_SECTOR;
|
||||
EraseInitStruct.NbSectors = 1;
|
||||
|
||||
current_slot = EEPROM_SLOTS - 1;
|
||||
UNLOCK_FLASH();
|
||||
|
||||
TERN_(HAS_PAUSE_SERVO_OUTPUT, PAUSE_SERVO_OUTPUT());
|
||||
hal.isr_off();
|
||||
status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
|
||||
hal.isr_on();
|
||||
TERN_(HAS_PAUSE_SERVO_OUTPUT, RESUME_SERVO_OUTPUT());
|
||||
if (status != HAL_OK) {
|
||||
DEBUG_ECHOLNPGM("HAL_FLASHEx_Erase=", status);
|
||||
DEBUG_ECHOLNPGM("GetError=", HAL_FLASH_GetError());
|
||||
DEBUG_ECHOLNPGM("SectorError=", SectorError);
|
||||
LOCK_FLASH();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK_FLASH();
|
||||
|
||||
uint32_t offset = 0,
|
||||
address = SLOT_ADDRESS(current_slot),
|
||||
address_end = address + MARLIN_EEPROM_SIZE,
|
||||
data = 0;
|
||||
|
||||
bool success = true;
|
||||
|
||||
while (address < address_end) {
|
||||
memcpy(&data, ram_eeprom + offset, sizeof(data));
|
||||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data);
|
||||
if (status == HAL_OK) {
|
||||
address += sizeof(uint32_t);
|
||||
offset += sizeof(uint32_t);
|
||||
}
|
||||
else {
|
||||
DEBUG_ECHOLNPGM("HAL_FLASH_Program=", status);
|
||||
DEBUG_ECHOLNPGM("GetError=", HAL_FLASH_GetError());
|
||||
DEBUG_ECHOLNPGM("address=", address);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LOCK_FLASH();
|
||||
|
||||
if (success) {
|
||||
eeprom_data_written = false;
|
||||
DEBUG_ECHOLNPGM("EEPROM saved to slot ", current_slot, ".");
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
#else // !FLASH_EEPROM_LEVELING
|
||||
|
||||
// The following was written for the STM32F4 but may work with other MCUs as well.
|
||||
// Most STM32F4 flash does not allow reading from flash during erase operations.
|
||||
// This takes about a second on a STM32F407 with a 128kB sector used as EEPROM.
|
||||
// Interrupts during this time can have unpredictable results, such as killing Servo
|
||||
// output. Servo output still glitches with interrupts disabled, but recovers after the
|
||||
// erase.
|
||||
TERN_(HAS_PAUSE_SERVO_OUTPUT, PAUSE_SERVO_OUTPUT());
|
||||
hal.isr_off();
|
||||
eeprom_buffer_flush();
|
||||
hal.isr_on();
|
||||
TERN_(HAS_PAUSE_SERVO_OUTPUT, RESUME_SERVO_OUTPUT());
|
||||
|
||||
eeprom_data_written = false;
|
||||
|
||||
#endif // !FLASH_EEPROM_LEVELING
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
while (size--) {
|
||||
uint8_t v = *value;
|
||||
#if ENABLED(FLASH_EEPROM_LEVELING)
|
||||
if (v != ram_eeprom[pos]) {
|
||||
ram_eeprom[pos] = v;
|
||||
eeprom_data_written = true;
|
||||
}
|
||||
#else
|
||||
if (v != eeprom_buffered_read_byte(pos)) {
|
||||
eeprom_buffered_write_byte(pos, v);
|
||||
eeprom_data_written = true;
|
||||
}
|
||||
#endif
|
||||
crc16(crc, &v, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
do {
|
||||
const uint8_t c = TERN(FLASH_EEPROM_LEVELING, ram_eeprom[pos], eeprom_buffered_read_byte(pos));
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
} while (--size);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // FLASH_EEPROM_EMULATION
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
/**
|
||||
* Platform-independent Arduino functions for I2C EEPROM.
|
||||
* Enable USE_SHARED_EEPROM if not supplied by the framework.
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(IIC_BL24CXX_EEPROM)
|
||||
|
||||
#include "../../libs/BL24CXX.h"
|
||||
#include "../shared/eeprom_if.h"
|
||||
|
||||
void eeprom_init() { BL24CXX::init(); }
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
void eeprom_write_byte(uint8_t *pos, uint8_t value) {
|
||||
const unsigned eeprom_address = (unsigned)pos;
|
||||
return BL24CXX::writeOneByte(eeprom_address, value);
|
||||
}
|
||||
|
||||
uint8_t eeprom_read_byte(uint8_t *pos) {
|
||||
const unsigned eeprom_address = (unsigned)pos;
|
||||
return BL24CXX::readOneByte(eeprom_address);
|
||||
}
|
||||
|
||||
#endif // IIC_BL24CXX_EEPROM
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
/**
|
||||
* Implementation of EEPROM settings in SD Card
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(SDCARD_EEPROM_EMULATION)
|
||||
|
||||
#include "../shared/eeprom_api.h"
|
||||
#include "../../sd/cardreader.h"
|
||||
|
||||
#define EEPROM_FILENAME "eeprom.dat"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
|
||||
#endif
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
|
||||
#define _ALIGN(x) __attribute__ ((aligned(x)))
|
||||
static char _ALIGN(4) HAL_eeprom_data[MARLIN_EEPROM_SIZE];
|
||||
|
||||
bool PersistentStore::access_start() {
|
||||
if (!card.isMounted()) return false;
|
||||
|
||||
SdFile file, root = card.getroot();
|
||||
if (!file.open(&root, EEPROM_FILENAME, O_RDONLY))
|
||||
return true;
|
||||
|
||||
int bytes_read = file.read(HAL_eeprom_data, MARLIN_EEPROM_SIZE);
|
||||
if (bytes_read < 0) return false;
|
||||
for (; bytes_read < MARLIN_EEPROM_SIZE; bytes_read++)
|
||||
HAL_eeprom_data[bytes_read] = 0xFF;
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::access_finish() {
|
||||
if (!card.isMounted()) return false;
|
||||
|
||||
SdFile file, root = card.getroot();
|
||||
int bytes_written = 0;
|
||||
if (file.open(&root, EEPROM_FILENAME, O_CREAT | O_WRITE | O_TRUNC)) {
|
||||
bytes_written = file.write(HAL_eeprom_data, MARLIN_EEPROM_SIZE);
|
||||
file.close();
|
||||
}
|
||||
return (bytes_written == MARLIN_EEPROM_SIZE);
|
||||
}
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
for (size_t i = 0; i < size; i++)
|
||||
HAL_eeprom_data[pos + i] = value[i];
|
||||
crc16(crc, value, size);
|
||||
pos += size;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
uint8_t c = HAL_eeprom_data[pos + i];
|
||||
if (writing) value[i] = c;
|
||||
crc16(crc, &c, 1);
|
||||
}
|
||||
pos += size;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // SDCARD_EEPROM_EMULATION
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
*
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
|
||||
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
|
||||
* Copyright (c) 2016 Victor Perez victor_pv@hotmail.com
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(SRAM_EEPROM_EMULATION)
|
||||
|
||||
#include "../shared/eeprom_if.h"
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
|
||||
#endif
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
|
||||
bool PersistentStore::access_start() { return true; }
|
||||
bool PersistentStore::access_finish() { return true; }
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
while (size--) {
|
||||
uint8_t v = *value;
|
||||
|
||||
// Save to Backup SRAM
|
||||
*(__IO uint8_t *)(BKPSRAM_BASE + (uint8_t * const)pos) = v;
|
||||
|
||||
crc16(crc, &v, 1);
|
||||
pos++;
|
||||
value++;
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
do {
|
||||
// Read from either external EEPROM, program flash or Backup SRAM
|
||||
const uint8_t c = ( *(__IO uint8_t *)(BKPSRAM_BASE + ((uint8_t*)pos)) );
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
} while (--size);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // SRAM_EEPROM_EMULATION
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
*
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
|
||||
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
|
||||
* Copyright (c) 2016 Victor Perez victor_pv@hotmail.com
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if USE_WIRED_EEPROM
|
||||
|
||||
/**
|
||||
* PersistentStore for Arduino-style EEPROM interface
|
||||
* with simple implementations supplied by Marlin.
|
||||
*/
|
||||
|
||||
#include "../shared/eeprom_if.h"
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#define MARLIN_EEPROM_SIZE size_t(E2END + 1)
|
||||
#endif
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
|
||||
bool PersistentStore::access_start() { eeprom_init(); return true; }
|
||||
bool PersistentStore::access_finish() { return true; }
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
uint16_t written = 0;
|
||||
while (size--) {
|
||||
uint8_t v = *value;
|
||||
uint8_t * const p = (uint8_t * const)pos;
|
||||
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
|
||||
eeprom_write_byte(p, v);
|
||||
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
|
||||
if (eeprom_read_byte(p) != v) {
|
||||
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
crc16(crc, &v, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
do {
|
||||
// Read from either external EEPROM, program flash or Backup SRAM
|
||||
const uint8_t c = eeprom_read_byte((uint8_t*)pos);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
} while (--size);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // USE_WIRED_EEPROM
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../module/endstops.h"
|
||||
|
||||
// One ISR for all EXT-Interrupts
|
||||
void endstop_ISR() { endstops.update(); }
|
||||
|
||||
void setup_endstop_interrupts() {
|
||||
#define _ATTACH(P) attachInterrupt(P, endstop_ISR, CHANGE)
|
||||
TERN_(HAS_X_MAX, _ATTACH(X_MAX_PIN));
|
||||
TERN_(HAS_X_MIN, _ATTACH(X_MIN_PIN));
|
||||
TERN_(HAS_Y_MAX, _ATTACH(Y_MAX_PIN));
|
||||
TERN_(HAS_Y_MIN, _ATTACH(Y_MIN_PIN));
|
||||
TERN_(HAS_Z_MAX, _ATTACH(Z_MAX_PIN));
|
||||
TERN_(HAS_Z_MIN, _ATTACH(Z_MIN_PIN));
|
||||
TERN_(HAS_X2_MAX, _ATTACH(X2_MAX_PIN));
|
||||
TERN_(HAS_X2_MIN, _ATTACH(X2_MIN_PIN));
|
||||
TERN_(HAS_Y2_MAX, _ATTACH(Y2_MAX_PIN));
|
||||
TERN_(HAS_Y2_MIN, _ATTACH(Y2_MIN_PIN));
|
||||
TERN_(HAS_Z2_MAX, _ATTACH(Z2_MAX_PIN));
|
||||
TERN_(HAS_Z2_MIN, _ATTACH(Z2_MIN_PIN));
|
||||
TERN_(HAS_Z3_MAX, _ATTACH(Z3_MAX_PIN));
|
||||
TERN_(HAS_Z3_MIN, _ATTACH(Z3_MIN_PIN));
|
||||
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
|
||||
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
|
||||
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
|
||||
TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
|
||||
TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
|
||||
TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
|
||||
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
|
||||
TERN_(HAS_K_MAX, _ATTACH(K_MAX_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));
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
// Array to support sticky frequency sets per timer
|
||||
static uint16_t timer_freq[TIMER_NUM];
|
||||
|
||||
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
|
||||
const uint16_t duty = invert ? v_size - v : v;
|
||||
if (PWM_PIN(pin)) {
|
||||
const PinName pin_name = digitalPinToPinName(pin);
|
||||
TIM_TypeDef * const Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM);
|
||||
|
||||
const timer_index_t index = get_timer_index(Instance);
|
||||
const bool needs_freq = (HardwareTimer_Handle[index] == nullptr);
|
||||
if (needs_freq) // A new instance must be set to the default frequency of PWM_FREQUENCY
|
||||
HardwareTimer_Handle[index]->__this = new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM));
|
||||
|
||||
HardwareTimer * const HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
|
||||
const uint32_t channel = STM_PIN_CHANNEL(pinmap_function(pin_name, PinMap_PWM));
|
||||
const TimerModes_t previousMode = HT->getMode(channel);
|
||||
if (previousMode != TIMER_OUTPUT_COMPARE_PWM1)
|
||||
HT->setMode(channel, TIMER_OUTPUT_COMPARE_PWM1, pin);
|
||||
|
||||
if (needs_freq && timer_freq[index] == 0) // If the timer is unconfigured and no freq is set then default PWM_FREQUENCY
|
||||
set_pwm_frequency(pin_name, PWM_FREQUENCY); // Set the frequency and save the value to the assigned index no.
|
||||
|
||||
// Note the resolution is sticky here, the input can be upto 16 bits and that would require RESOLUTION_16B_COMPARE_FORMAT (16)
|
||||
// If such a need were to manifest then we would need to calc the resolution based on the v_size parameter and add code for it.
|
||||
HT->setCaptureCompare(channel, duty, RESOLUTION_8B_COMPARE_FORMAT); // Set the duty, the calc is done in the library :)
|
||||
pinmap_pinout(pin_name, PinMap_PWM); // Make sure the pin output state is set.
|
||||
if (previousMode != TIMER_OUTPUT_COMPARE_PWM1) HT->resume();
|
||||
}
|
||||
else {
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, duty < v_size / 2 ? LOW : HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
|
||||
if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer
|
||||
const PinName pin_name = digitalPinToPinName(pin);
|
||||
TIM_TypeDef * const Instance = (TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM); // Get HAL timer instance
|
||||
const timer_index_t index = get_timer_index(Instance);
|
||||
|
||||
// Protect used timers.
|
||||
#ifdef STEP_TIMER
|
||||
if (index == TIMER_INDEX(STEP_TIMER)) return;
|
||||
#endif
|
||||
#ifdef TEMP_TIMER
|
||||
if (index == TIMER_INDEX(TEMP_TIMER)) return;
|
||||
#endif
|
||||
#if defined(PULSE_TIMER) && MF_TIMER_PULSE != MF_TIMER_STEP
|
||||
if (index == TIMER_INDEX(PULSE_TIMER)) return;
|
||||
#endif
|
||||
|
||||
if (HardwareTimer_Handle[index] == nullptr) // If frequency is set before duty we need to create a handle here.
|
||||
HardwareTimer_Handle[index]->__this = new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin_name, PinMap_PWM));
|
||||
HardwareTimer * const HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
|
||||
HT->setOverflow(f_desired, HERTZ_FORMAT);
|
||||
timer_freq[index] = f_desired; // Save the last frequency so duty will not set the default for this timer number.
|
||||
}
|
||||
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
GPIO_TypeDef* FastIOPortMap[LastPort + 1] = { 0 };
|
||||
|
||||
void FastIO_init() {
|
||||
LOOP_L_N(i, NUM_DIGITAL_PINS)
|
||||
FastIOPortMap[STM_PORT(digitalPin[i])] = get_GPIO_Port(STM_PORT(digitalPin[i]));
|
||||
}
|
||||
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 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
|
||||
* Copyright (c) 2017 Victor Perez
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Fast I/O interfaces for STM32
|
||||
* These use GPIO register access for fast port manipulation.
|
||||
*/
|
||||
|
||||
// ------------------------
|
||||
// Public Variables
|
||||
// ------------------------
|
||||
|
||||
extern GPIO_TypeDef * FastIOPortMap[];
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
void FastIO_init(); // Must be called before using fast io macros
|
||||
#define FASTIO_INIT() FastIO_init()
|
||||
|
||||
// ------------------------
|
||||
// Defines
|
||||
// ------------------------
|
||||
|
||||
#define _BV32(b) (1UL << (b))
|
||||
|
||||
#ifndef PWM
|
||||
#define PWM OUTPUT
|
||||
#endif
|
||||
|
||||
#if defined(STM32F0xx) || defined(STM32F1xx) || defined(STM32F3xx) || defined(STM32L0xx) || defined(STM32L4xx)
|
||||
#define _WRITE(IO, V) do { \
|
||||
if (V) FastIOPortMap[STM_PORT(digitalPinToPinName(IO))]->BSRR = _BV32(STM_PIN(digitalPinToPinName(IO))) ; \
|
||||
else FastIOPortMap[STM_PORT(digitalPinToPinName(IO))]->BRR = _BV32(STM_PIN(digitalPinToPinName(IO))) ; \
|
||||
}while(0)
|
||||
#else
|
||||
#define _WRITE(IO, V) (FastIOPortMap[STM_PORT(digitalPinToPinName(IO))]->BSRR = _BV32(STM_PIN(digitalPinToPinName(IO)) + ((V) ? 0 : 16)))
|
||||
#endif
|
||||
|
||||
#define _READ(IO) bool(READ_BIT(FastIOPortMap[STM_PORT(digitalPinToPinName(IO))]->IDR, _BV32(STM_PIN(digitalPinToPinName(IO)))))
|
||||
#define _TOGGLE(IO) TBI32(FastIOPortMap[STM_PORT(digitalPinToPinName(IO))]->ODR, STM_PIN(digitalPinToPinName(IO)))
|
||||
|
||||
#define _GET_MODE(IO)
|
||||
#define _SET_MODE(IO,M) pinMode(IO, M)
|
||||
#define _SET_OUTPUT(IO) pinMode(IO, OUTPUT) //!< Output Push Pull Mode & GPIO_NOPULL
|
||||
#define _SET_OUTPUT_OD(IO) pinMode(IO, OUTPUT_OPEN_DRAIN)
|
||||
|
||||
#define WRITE(IO,V) _WRITE(IO,V)
|
||||
#define READ(IO) _READ(IO)
|
||||
#define TOGGLE(IO) _TOGGLE(IO)
|
||||
|
||||
#define OUT_WRITE(IO,V) do{ _SET_OUTPUT(IO); WRITE(IO,V); }while(0)
|
||||
#define OUT_WRITE_OD(IO,V) do{ _SET_OUTPUT_OD(IO); WRITE(IO,V); }while(0)
|
||||
|
||||
#define SET_INPUT(IO) _SET_MODE(IO, INPUT) //!< Input Floating Mode
|
||||
#define SET_INPUT_PULLUP(IO) _SET_MODE(IO, INPUT_PULLUP) //!< Input with Pull-up activation
|
||||
#define SET_INPUT_PULLDOWN(IO) _SET_MODE(IO, INPUT_PULLDOWN) //!< Input with Pull-down activation
|
||||
#define SET_OUTPUT(IO) OUT_WRITE(IO, LOW)
|
||||
#define SET_PWM(IO) _SET_MODE(IO, PWM)
|
||||
|
||||
#define IS_INPUT(IO)
|
||||
#define IS_OUTPUT(IO)
|
||||
|
||||
#define PWM_PIN(P) digitalPinHasPWM(P)
|
||||
#define NO_COMPILE_TIME_PWM
|
||||
|
||||
// digitalRead/Write wrappers
|
||||
#define extDigitalRead(IO) digitalRead(IO)
|
||||
#define extDigitalWrite(IO,V) digitalWrite(IO,V)
|
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if BOTH(SDSUPPORT, USBD_USE_CDC_MSC) && DISABLED(NO_SD_HOST_DRIVE)
|
||||
#define HAS_SD_HOST_DRIVE 1
|
||||
#endif
|
||||
|
||||
// Fix F_CPU not being a compile-time constant in STSTM32 framework
|
||||
#ifdef BOARD_F_CPU
|
||||
#undef F_CPU
|
||||
#define F_CPU BOARD_F_CPU
|
||||
#endif
|
||||
|
||||
// The Sensitive Pins array is not optimizable
|
||||
#define RUNTIME_ONLY_ANALOG_TO_DIGITAL
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// If no real or emulated EEPROM selected, fall back to SD emulation
|
||||
#if USE_FALLBACK_EEPROM
|
||||
#define SDCARD_EEPROM_EMULATION
|
||||
#elif EITHER(I2C_EEPROM, SPI_EEPROM)
|
||||
#define USE_SHARED_EEPROM 1
|
||||
#endif
|
||||
|
||||
// Some STM32F4 boards may lose steps when saving to EEPROM during print (PR #17946)
|
||||
#if defined(STM32F4xx) && ENABLED(FLASH_EEPROM_EMULATION) && PRINTCOUNTER_SAVE_INTERVAL > 0
|
||||
#define PRINTCOUNTER_SYNC 1
|
||||
#endif
|
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Test STM32-specific configuration values for errors at compile-time.
|
||||
*/
|
||||
//#if ENABLED(SPINDLE_LASER_USE_PWM) && !(SPINDLE_LASER_PWM_PIN == 4 || SPINDLE_LASER_PWM_PIN == 6 || SPINDLE_LASER_PWM_PIN == 11)
|
||||
// #error "SPINDLE_LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
|
||||
//#endif
|
||||
|
||||
|
||||
#if ENABLED(SDCARD_EEPROM_EMULATION) && DISABLED(SDSUPPORT)
|
||||
#undef SDCARD_EEPROM_EMULATION // Avoid additional error noise
|
||||
#if USE_FALLBACK_EEPROM
|
||||
#warning "EEPROM type not specified. Fallback is SDCARD_EEPROM_EMULATION."
|
||||
#endif
|
||||
#error "SDCARD_EEPROM_EMULATION requires SDSUPPORT. Enable SDSUPPORT or choose another EEPROM emulation."
|
||||
#endif
|
||||
|
||||
#if !defined(STM32F4xx) && ENABLED(FLASH_EEPROM_LEVELING)
|
||||
#error "FLASH_EEPROM_LEVELING is currently only supported on STM32F4 hardware."
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
#error "SERIAL_STATS_MAX_RX_QUEUED is not supported on STM32."
|
||||
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
#error "SERIAL_STATS_DROPPED_RX is not supported on STM32."
|
||||
#endif
|
||||
|
||||
#if ANY(TFT_COLOR_UI, TFT_LVGL_UI, TFT_CLASSIC_UI) && NOT_TARGET(STM32H7xx, STM32F4xx, STM32F1xx)
|
||||
#error "TFT_COLOR_UI, TFT_LVGL_UI and TFT_CLASSIC_UI are currently only supported on STM32H7, STM32F4 and STM32F1 hardware."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check for common serial pin conflicts
|
||||
*/
|
||||
#define _CHECK_SERIAL_PIN(N) (( \
|
||||
BTN_EN1 == N || DOGLCD_CS == N || HEATER_BED_PIN == N || FAN_PIN == N || \
|
||||
SDIO_D2_PIN == N || SDIO_D3_PIN == N || SDIO_CK_PIN == N || SDIO_CMD_PIN == N \
|
||||
))
|
||||
#define CHECK_SERIAL_PIN(T,N) defined(UART##N##_##T##_PIN) && _CHECK_SERIAL_PIN(UART##N##_##T##_PIN)
|
||||
#if SERIAL_IN_USE(1)
|
||||
#if CHECK_SERIAL_PIN(TX,1)
|
||||
#error "Serial Port 1 TX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#if CHECK_SERIAL_PIN(RX,1)
|
||||
#error "Serial Port 1 RX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#endif
|
||||
#if SERIAL_IN_USE(2)
|
||||
#if CHECK_SERIAL_PIN(TX,2)
|
||||
#error "Serial Port 2 TX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#if CHECK_SERIAL_PIN(RX,2)
|
||||
#error "Serial Port 2 RX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#endif
|
||||
#if SERIAL_IN_USE(3)
|
||||
#if CHECK_SERIAL_PIN(TX,3)
|
||||
#error "Serial Port 3 TX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#if CHECK_SERIAL_PIN(RX,3)
|
||||
#error "Serial Port 3 RX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#endif
|
||||
#if SERIAL_IN_USE(4)
|
||||
#if CHECK_SERIAL_PIN(TX,4)
|
||||
#error "Serial Port 4 TX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#if CHECK_SERIAL_PIN(RX,4)
|
||||
#error "Serial Port 4 RX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#endif
|
||||
#if SERIAL_IN_USE(5)
|
||||
#if CHECK_SERIAL_PIN(TX,5)
|
||||
#error "Serial Port 5 TX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#if CHECK_SERIAL_PIN(RX,5)
|
||||
#error "Serial Port 5 RX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#endif
|
||||
#if SERIAL_IN_USE(6)
|
||||
#if CHECK_SERIAL_PIN(TX,6)
|
||||
#error "Serial Port 6 TX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#if CHECK_SERIAL_PIN(RX,6)
|
||||
#error "Serial Port 6 RX IO pins conflict with another pin on the board."
|
||||
#endif
|
||||
#endif
|
||||
#undef CHECK_SERIAL_PIN
|
||||
#undef _CHECK_SERIAL_PIN
|
@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
*
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech]
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if HAS_SD_HOST_DRIVE
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
#include "msc_sd.h"
|
||||
#include "usbd_core.h"
|
||||
|
||||
#include "../../sd/cardreader.h"
|
||||
|
||||
#include <USB.h>
|
||||
#include <USBMscHandler.h>
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
#define PRODUCT_ID 0x29
|
||||
|
||||
class Sd2CardUSBMscHandler : public USBMscHandler {
|
||||
public:
|
||||
DiskIODriver* diskIODriver() {
|
||||
#if ENABLED(MULTI_VOLUME)
|
||||
#if SHARED_VOLUME_IS(SD_ONBOARD)
|
||||
return &card.media_driver_sdcard;
|
||||
#elif SHARED_VOLUME_IS(USB_FLASH_DRIVE)
|
||||
return &card.media_driver_usbFlash;
|
||||
#endif
|
||||
#else
|
||||
return card.diskIODriver();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GetCapacity(uint32_t *pBlockNum, uint16_t *pBlockSize) {
|
||||
*pBlockNum = diskIODriver()->cardSize();
|
||||
*pBlockSize = BLOCK_SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Write(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
|
||||
auto sd2card = diskIODriver();
|
||||
// single block
|
||||
if (blkLen == 1) {
|
||||
hal.watchdog_refresh();
|
||||
sd2card->writeBlock(blkAddr, pBuf);
|
||||
return true;
|
||||
}
|
||||
|
||||
// multi block optimization
|
||||
sd2card->writeStart(blkAddr, blkLen);
|
||||
while (blkLen--) {
|
||||
hal.watchdog_refresh();
|
||||
sd2card->writeData(pBuf);
|
||||
pBuf += BLOCK_SIZE;
|
||||
}
|
||||
sd2card->writeStop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Read(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
|
||||
auto sd2card = diskIODriver();
|
||||
// single block
|
||||
if (blkLen == 1) {
|
||||
hal.watchdog_refresh();
|
||||
sd2card->readBlock(blkAddr, pBuf);
|
||||
return true;
|
||||
}
|
||||
|
||||
// multi block optimization
|
||||
sd2card->readStart(blkAddr);
|
||||
while (blkLen--) {
|
||||
hal.watchdog_refresh();
|
||||
sd2card->readData(pBuf);
|
||||
pBuf += BLOCK_SIZE;
|
||||
}
|
||||
sd2card->readStop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsReady() {
|
||||
return diskIODriver()->isReady();
|
||||
}
|
||||
};
|
||||
|
||||
Sd2CardUSBMscHandler usbMscHandler;
|
||||
|
||||
/* USB Mass storage Standard Inquiry Data */
|
||||
uint8_t Marlin_STORAGE_Inquirydata[] = { /* 36 */
|
||||
/* LUN 0 */
|
||||
0x00,
|
||||
0x80,
|
||||
0x02,
|
||||
0x02,
|
||||
(STANDARD_INQUIRY_DATA_LEN - 5),
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
'M', 'A', 'R', 'L', 'I', 'N', ' ', ' ', /* Manufacturer : 8 bytes */
|
||||
'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
|
||||
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
|
||||
'0', '.', '0', '1', /* Version : 4 Bytes */
|
||||
};
|
||||
|
||||
USBMscHandler *pSingleMscHandler = &usbMscHandler;
|
||||
|
||||
void MSC_SD_init() {
|
||||
USBDevice.end();
|
||||
delay(200);
|
||||
USBDevice.registerMscHandlers(1, &pSingleMscHandler, Marlin_STORAGE_Inquirydata);
|
||||
USBDevice.begin();
|
||||
}
|
||||
|
||||
#endif // HAS_SD_HOST_DRIVE
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
*
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech]
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
void MSC_SD_init();
|
@ -0,0 +1,287 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifndef NUM_DIGITAL_PINS
|
||||
// Only in ST's Arduino core (STM32duino, STM32Core)
|
||||
#error "Expected NUM_DIGITAL_PINS not found"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Life gets complicated if you want an easy to use 'M43 I' output (in port/pin order)
|
||||
* because the variants in this platform do not always define all the I/O port/pins
|
||||
* that a CPU has.
|
||||
*
|
||||
* VARIABLES:
|
||||
* Ard_num - Arduino pin number - defined by the platform. It is used by digitalRead and
|
||||
* digitalWrite commands and by M42.
|
||||
* - does not contain port/pin info
|
||||
* - is not in port/pin order
|
||||
* - typically a variant will only assign Ard_num to port/pins that are actually used
|
||||
* Index - M43 counter - only used to get Ard_num
|
||||
* x - a parameter/argument used to search the pin_array to try to find a signal name
|
||||
* associated with a Ard_num
|
||||
* Port_pin - port number and pin number for use with CPU registers and printing reports
|
||||
*
|
||||
* Since M43 uses digitalRead and digitalWrite commands, only the Port_pins with an Ard_num
|
||||
* are accessed and/or displayed.
|
||||
*
|
||||
* Three arrays are used.
|
||||
*
|
||||
* digitalPin[] is provided by the platform. It consists of the Port_pin numbers in
|
||||
* Arduino pin number order.
|
||||
*
|
||||
* pin_array is a structure generated by the pins/pinsDebug.h header file. It is generated by
|
||||
* the preprocessor. Only the signals associated with enabled options are in this table.
|
||||
* It contains:
|
||||
* - name of the signal
|
||||
* - the Ard_num assigned by the pins_YOUR_BOARD.h file using the platform defines.
|
||||
* EXAMPLE: "#define KILL_PIN PB1" results in Ard_num of 57. 57 is then used as the
|
||||
* argument to digitalPinToPinName(IO) to get the Port_pin number
|
||||
* - if it is a digital or analog signal. PWMs are considered digital here.
|
||||
*
|
||||
* pin_xref is a structure generated by this header file. It is generated by the
|
||||
* preprocessor. It is in port/pin order. It contains just the port/pin numbers defined by the
|
||||
* platform for this variant.
|
||||
* - Ard_num
|
||||
* - printable version of Port_pin
|
||||
*
|
||||
* Routines with an "x" as a parameter/argument are used to search the pin_array to try to
|
||||
* find a signal name associated with a port/pin.
|
||||
*
|
||||
* NOTE - the Arduino pin number is what is used by the M42 command, NOT the port/pin for that
|
||||
* signal. The Arduino pin number is listed by the M43 I command.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// make a list of the Arduino pin numbers in the Port/Pin order
|
||||
//
|
||||
|
||||
#define _PIN_ADD(NAME_ALPHA, ARDUINO_NUM) { NAME_ALPHA, ARDUINO_NUM },
|
||||
#define PIN_ADD(NAME) _PIN_ADD(#NAME, NAME)
|
||||
|
||||
typedef struct {
|
||||
char Port_pin_alpha[5];
|
||||
pin_t Ard_num;
|
||||
} XrefInfo;
|
||||
|
||||
const XrefInfo pin_xref[] PROGMEM = {
|
||||
#include "pins_Xref.h"
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#define MODE_PIN_INPUT 0 // Input mode (reset state)
|
||||
#define MODE_PIN_OUTPUT 1 // General purpose output mode
|
||||
#define MODE_PIN_ALT 2 // Alternate function mode
|
||||
#define MODE_PIN_ANALOG 3 // Analog mode
|
||||
|
||||
#define PIN_NUM(P) (P & 0x000F)
|
||||
#define PIN_NUM_ALPHA_LEFT(P) (((P & 0x000F) < 10) ? ('0' + (P & 0x000F)) : '1')
|
||||
#define PIN_NUM_ALPHA_RIGHT(P) (((P & 0x000F) > 9) ? ('0' + (P & 0x000F) - 10) : 0 )
|
||||
#define PORT_NUM(P) ((P >> 4) & 0x0007)
|
||||
#define PORT_ALPHA(P) ('A' + (P >> 4))
|
||||
|
||||
/**
|
||||
* Translation of routines & variables used by pinsDebug.h
|
||||
*/
|
||||
|
||||
#if NUM_ANALOG_FIRST >= NUM_DIGITAL_PINS
|
||||
#define HAS_HIGH_ANALOG_PINS 1
|
||||
#endif
|
||||
#define NUM_ANALOG_LAST ((NUM_ANALOG_FIRST) + (NUM_ANALOG_INPUTS) - 1)
|
||||
#define NUMBER_PINS_TOTAL ((NUM_DIGITAL_PINS) + TERN0(HAS_HIGH_ANALOG_PINS, NUM_ANALOG_INPUTS))
|
||||
#define VALID_PIN(P) (WITHIN(P, 0, (NUM_DIGITAL_PINS) - 1) || TERN0(HAS_HIGH_ANALOG_PINS, WITHIN(P, NUM_ANALOG_FIRST, NUM_ANALOG_LAST)))
|
||||
#define digitalRead_mod(Ard_num) extDigitalRead(Ard_num) // must use Arduino pin numbers when doing reads
|
||||
#define PRINT_PIN(Q)
|
||||
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
|
||||
#define PRINT_PORT(ANUM) port_print(ANUM)
|
||||
#define DIGITAL_PIN_TO_ANALOG_PIN(ANUM) -1 // will report analog pin number in the print port routine
|
||||
|
||||
// x is a variable used to search pin_array
|
||||
#define GET_ARRAY_IS_DIGITAL(x) ((bool) pin_array[x].is_digital)
|
||||
#define GET_ARRAY_PIN(x) ((pin_t) pin_array[x].pin)
|
||||
#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
|
||||
#define MULTI_NAME_PAD 33 // space needed to be pretty if not first name assigned to a pin
|
||||
|
||||
//
|
||||
// Pin Mapping for M43
|
||||
//
|
||||
#define GET_PIN_MAP_PIN_M43(Index) pin_xref[Index].Ard_num
|
||||
|
||||
#ifndef M43_NEVER_TOUCH
|
||||
#define _M43_NEVER_TOUCH(Index) (Index >= 9 && Index <= 12) // SERIAL/USB pins: PA9(TX) PA10(RX) PA11(USB_DM) PA12(USB_DP)
|
||||
#ifdef KILL_PIN
|
||||
#define M43_NEVER_TOUCH(Index) m43_never_touch(Index)
|
||||
|
||||
bool m43_never_touch(const pin_t Index) {
|
||||
static pin_t M43_kill_index = -1;
|
||||
if (M43_kill_index < 0)
|
||||
for (M43_kill_index = 0; M43_kill_index < NUMBER_PINS_TOTAL; M43_kill_index++)
|
||||
if (KILL_PIN == GET_PIN_MAP_PIN_M43(M43_kill_index)) break;
|
||||
return _M43_NEVER_TOUCH(Index) || Index == M43_kill_index; // KILL_PIN and SERIAL/USB
|
||||
}
|
||||
#else
|
||||
#define M43_NEVER_TOUCH(Index) _M43_NEVER_TOUCH(Index)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint8_t get_pin_mode(const pin_t Ard_num) {
|
||||
const PinName dp = digitalPinToPinName(Ard_num);
|
||||
uint32_t ll_pin = STM_LL_GPIO_PIN(dp);
|
||||
GPIO_TypeDef *port = get_GPIO_Port(STM_PORT(dp));
|
||||
uint32_t mode = LL_GPIO_GetPinMode(port, ll_pin);
|
||||
switch (mode) {
|
||||
case LL_GPIO_MODE_ANALOG: return MODE_PIN_ANALOG;
|
||||
case LL_GPIO_MODE_INPUT: return MODE_PIN_INPUT;
|
||||
case LL_GPIO_MODE_OUTPUT: return MODE_PIN_OUTPUT;
|
||||
case LL_GPIO_MODE_ALTERNATE: return MODE_PIN_ALT;
|
||||
TERN_(STM32F1xx, case LL_GPIO_MODE_FLOATING:)
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool GET_PINMODE(const pin_t Ard_num) {
|
||||
const uint8_t pin_mode = get_pin_mode(Ard_num);
|
||||
return pin_mode == MODE_PIN_OUTPUT || pin_mode == MODE_PIN_ALT; // assume all alt definitions are PWM
|
||||
}
|
||||
|
||||
int8_t digital_pin_to_analog_pin(const pin_t Ard_num) {
|
||||
if (WITHIN(Ard_num, NUM_ANALOG_FIRST, NUM_ANALOG_LAST))
|
||||
return Ard_num - NUM_ANALOG_FIRST;
|
||||
|
||||
const uint32_t ind = digitalPinToAnalogInput(Ard_num);
|
||||
return (ind < NUM_ANALOG_INPUTS) ? ind : -1;
|
||||
}
|
||||
|
||||
bool IS_ANALOG(const pin_t Ard_num) {
|
||||
return get_pin_mode(Ard_num) == MODE_PIN_ANALOG;
|
||||
}
|
||||
|
||||
bool is_digital(const pin_t Ard_num) {
|
||||
const uint8_t pin_mode = get_pin_mode(pin_array[Ard_num].pin);
|
||||
return pin_mode == MODE_PIN_INPUT || pin_mode == MODE_PIN_OUTPUT;
|
||||
}
|
||||
|
||||
void port_print(const pin_t Ard_num) {
|
||||
char buffer[16];
|
||||
pin_t Index;
|
||||
for (Index = 0; Index < NUMBER_PINS_TOTAL; Index++)
|
||||
if (Ard_num == GET_PIN_MAP_PIN_M43(Index)) break;
|
||||
|
||||
const char * ppa = pin_xref[Index].Port_pin_alpha;
|
||||
sprintf_P(buffer, PSTR("%s"), ppa);
|
||||
SERIAL_ECHO(buffer);
|
||||
if (ppa[3] == '\0') SERIAL_CHAR(' ');
|
||||
|
||||
// print analog pin number
|
||||
const int8_t Port_pin = digital_pin_to_analog_pin(Ard_num);
|
||||
if (Port_pin >= 0) {
|
||||
sprintf_P(buffer, PSTR(" (A%d) "), Port_pin);
|
||||
SERIAL_ECHO(buffer);
|
||||
if (Port_pin < 10) SERIAL_CHAR(' ');
|
||||
}
|
||||
else
|
||||
SERIAL_ECHO_SP(7);
|
||||
|
||||
// Print number to be used with M42
|
||||
int calc_p = Ard_num;
|
||||
if (Ard_num > NUM_DIGITAL_PINS) {
|
||||
calc_p -= NUM_ANALOG_FIRST;
|
||||
if (calc_p > 7) calc_p += 8;
|
||||
}
|
||||
SERIAL_ECHOPGM(" M42 P", calc_p);
|
||||
SERIAL_CHAR(' ');
|
||||
if (calc_p < 100) {
|
||||
SERIAL_CHAR(' ');
|
||||
if (calc_p < 10)
|
||||
SERIAL_CHAR(' ');
|
||||
}
|
||||
}
|
||||
|
||||
bool pwm_status(const pin_t Ard_num) {
|
||||
return get_pin_mode(Ard_num) == MODE_PIN_ALT;
|
||||
}
|
||||
|
||||
void pwm_details(const pin_t Ard_num) {
|
||||
#ifndef STM32F1xx
|
||||
if (pwm_status(Ard_num)) {
|
||||
uint32_t alt_all = 0;
|
||||
const PinName dp = digitalPinToPinName(Ard_num);
|
||||
pin_t pin_number = uint8_t(PIN_NUM(dp));
|
||||
const bool over_7 = pin_number >= 8;
|
||||
const uint8_t ind = over_7 ? 1 : 0;
|
||||
switch (PORT_ALPHA(dp)) { // get alt function
|
||||
case 'A' : alt_all = GPIOA->AFR[ind]; break;
|
||||
case 'B' : alt_all = GPIOB->AFR[ind]; break;
|
||||
case 'C' : alt_all = GPIOC->AFR[ind]; break;
|
||||
case 'D' : alt_all = GPIOD->AFR[ind]; break;
|
||||
#ifdef PE_0
|
||||
case 'E' : alt_all = GPIOE->AFR[ind]; break;
|
||||
#elif defined(PF_0)
|
||||
case 'F' : alt_all = GPIOF->AFR[ind]; break;
|
||||
#elif defined(PG_0)
|
||||
case 'G' : alt_all = GPIOG->AFR[ind]; break;
|
||||
#elif defined(PH_0)
|
||||
case 'H' : alt_all = GPIOH->AFR[ind]; break;
|
||||
#elif defined(PI_0)
|
||||
case 'I' : alt_all = GPIOI->AFR[ind]; break;
|
||||
#elif defined(PJ_0)
|
||||
case 'J' : alt_all = GPIOJ->AFR[ind]; break;
|
||||
#elif defined(PK_0)
|
||||
case 'K' : alt_all = GPIOK->AFR[ind]; break;
|
||||
#elif defined(PL_0)
|
||||
case 'L' : alt_all = GPIOL->AFR[ind]; break;
|
||||
#endif
|
||||
}
|
||||
if (over_7) pin_number -= 8;
|
||||
|
||||
uint8_t alt_func = (alt_all >> (4 * pin_number)) & 0x0F;
|
||||
SERIAL_ECHOPGM("Alt Function: ", alt_func);
|
||||
if (alt_func < 10) SERIAL_CHAR(' ');
|
||||
SERIAL_ECHOPGM(" - ");
|
||||
switch (alt_func) {
|
||||
case 0 : SERIAL_ECHOPGM("system (misc. I/O)"); break;
|
||||
case 1 : SERIAL_ECHOPGM("TIM1/TIM2 (probably PWM)"); break;
|
||||
case 2 : SERIAL_ECHOPGM("TIM3..5 (probably PWM)"); break;
|
||||
case 3 : SERIAL_ECHOPGM("TIM8..11 (probably PWM)"); break;
|
||||
case 4 : SERIAL_ECHOPGM("I2C1..3"); break;
|
||||
case 5 : SERIAL_ECHOPGM("SPI1/SPI2"); break;
|
||||
case 6 : SERIAL_ECHOPGM("SPI3"); break;
|
||||
case 7 : SERIAL_ECHOPGM("USART1..3"); break;
|
||||
case 8 : SERIAL_ECHOPGM("USART4..6"); break;
|
||||
case 9 : SERIAL_ECHOPGM("CAN1/CAN2, TIM12..14 (probably PWM)"); break;
|
||||
case 10 : SERIAL_ECHOPGM("OTG"); break;
|
||||
case 11 : SERIAL_ECHOPGM("ETH"); break;
|
||||
case 12 : SERIAL_ECHOPGM("FSMC, SDIO, OTG"); break;
|
||||
case 13 : SERIAL_ECHOPGM("DCMI"); break;
|
||||
case 14 : SERIAL_ECHOPGM("unused (shouldn't see this)"); break;
|
||||
case 15 : SERIAL_ECHOPGM("EVENTOUT"); break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// TODO: F1 doesn't support changing pins function, so we need to check the function of the PIN and if it's enabled
|
||||
#endif
|
||||
} // pwm_details
|
@ -0,0 +1,612 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// make a list of the Arduino pin numbers in the Port/Pin order
|
||||
//
|
||||
#ifdef PA0
|
||||
PIN_ADD(PA0)
|
||||
#endif
|
||||
#ifdef PA1
|
||||
PIN_ADD(PA1)
|
||||
#endif
|
||||
#ifdef PA2
|
||||
PIN_ADD(PA2)
|
||||
#endif
|
||||
#ifdef PA3
|
||||
PIN_ADD(PA3)
|
||||
#endif
|
||||
#ifdef PA4
|
||||
PIN_ADD(PA4)
|
||||
#endif
|
||||
#ifdef PA5
|
||||
PIN_ADD(PA5)
|
||||
#endif
|
||||
#ifdef PA6
|
||||
PIN_ADD(PA6)
|
||||
#endif
|
||||
#ifdef PA7
|
||||
PIN_ADD(PA7)
|
||||
#endif
|
||||
#ifdef PA8
|
||||
PIN_ADD(PA8)
|
||||
#endif
|
||||
#ifdef PA9
|
||||
PIN_ADD(PA9)
|
||||
#endif
|
||||
#ifdef PA10
|
||||
PIN_ADD(PA10)
|
||||
#endif
|
||||
#ifdef PA11
|
||||
PIN_ADD(PA11)
|
||||
#endif
|
||||
#ifdef PA12
|
||||
PIN_ADD(PA12)
|
||||
#endif
|
||||
#ifdef PA13
|
||||
PIN_ADD(PA13)
|
||||
#endif
|
||||
#ifdef PA14
|
||||
PIN_ADD(PA14)
|
||||
#endif
|
||||
#ifdef PA15
|
||||
PIN_ADD(PA15)
|
||||
#endif
|
||||
|
||||
#ifdef PB0
|
||||
PIN_ADD(PB0)
|
||||
#endif
|
||||
#ifdef PB1
|
||||
PIN_ADD(PB1)
|
||||
#endif
|
||||
#ifdef PB2
|
||||
PIN_ADD(PB2)
|
||||
#endif
|
||||
#ifdef PB3
|
||||
PIN_ADD(PB3)
|
||||
#endif
|
||||
#ifdef PB4
|
||||
PIN_ADD(PB4)
|
||||
#endif
|
||||
#ifdef PB5
|
||||
PIN_ADD(PB5)
|
||||
#endif
|
||||
#ifdef PB6
|
||||
PIN_ADD(PB6)
|
||||
#endif
|
||||
#ifdef PB7
|
||||
PIN_ADD(PB7)
|
||||
#endif
|
||||
#ifdef PB8
|
||||
PIN_ADD(PB8)
|
||||
#endif
|
||||
#ifdef PB9
|
||||
PIN_ADD(PB9)
|
||||
#endif
|
||||
#ifdef PB10
|
||||
PIN_ADD(PB10)
|
||||
#endif
|
||||
#ifdef PB11
|
||||
PIN_ADD(PB11)
|
||||
#endif
|
||||
#ifdef PB12
|
||||
PIN_ADD(PB12)
|
||||
#endif
|
||||
#ifdef PB13
|
||||
PIN_ADD(PB13)
|
||||
#endif
|
||||
#ifdef PB14
|
||||
PIN_ADD(PB14)
|
||||
#endif
|
||||
#ifdef PB15
|
||||
PIN_ADD(PB15)
|
||||
#endif
|
||||
|
||||
#ifdef PC0
|
||||
PIN_ADD(PC0)
|
||||
#endif
|
||||
#ifdef PC1
|
||||
PIN_ADD(PC1)
|
||||
#endif
|
||||
#ifdef PC2
|
||||
PIN_ADD(PC2)
|
||||
#endif
|
||||
#ifdef PC3
|
||||
PIN_ADD(PC3)
|
||||
#endif
|
||||
#ifdef PC4
|
||||
PIN_ADD(PC4)
|
||||
#endif
|
||||
#ifdef PC5
|
||||
PIN_ADD(PC5)
|
||||
#endif
|
||||
#ifdef PC6
|
||||
PIN_ADD(PC6)
|
||||
#endif
|
||||
#ifdef PC7
|
||||
PIN_ADD(PC7)
|
||||
#endif
|
||||
#ifdef PC8
|
||||
PIN_ADD(PC8)
|
||||
#endif
|
||||
#ifdef PC9
|
||||
PIN_ADD(PC9)
|
||||
#endif
|
||||
#ifdef PC10
|
||||
PIN_ADD(PC10)
|
||||
#endif
|
||||
#ifdef PC11
|
||||
PIN_ADD(PC11)
|
||||
#endif
|
||||
#ifdef PC12
|
||||
PIN_ADD(PC12)
|
||||
#endif
|
||||
#ifdef PC13
|
||||
PIN_ADD(PC13)
|
||||
#endif
|
||||
#ifdef PC14
|
||||
PIN_ADD(PC14)
|
||||
#endif
|
||||
#ifdef PC15
|
||||
PIN_ADD(PC15)
|
||||
#endif
|
||||
|
||||
#ifdef PD0
|
||||
PIN_ADD(PD0)
|
||||
#endif
|
||||
#ifdef PD1
|
||||
PIN_ADD(PD1)
|
||||
#endif
|
||||
#ifdef PD2
|
||||
PIN_ADD(PD2)
|
||||
#endif
|
||||
#ifdef PD3
|
||||
PIN_ADD(PD3)
|
||||
#endif
|
||||
#ifdef PD4
|
||||
PIN_ADD(PD4)
|
||||
#endif
|
||||
#ifdef PD5
|
||||
PIN_ADD(PD5)
|
||||
#endif
|
||||
#ifdef PD6
|
||||
PIN_ADD(PD6)
|
||||
#endif
|
||||
#ifdef PD7
|
||||
PIN_ADD(PD7)
|
||||
#endif
|
||||
#ifdef PD8
|
||||
PIN_ADD(PD8)
|
||||
#endif
|
||||
#ifdef PD9
|
||||
PIN_ADD(PD9)
|
||||
#endif
|
||||
#ifdef PD10
|
||||
PIN_ADD(PD10)
|
||||
#endif
|
||||
#ifdef PD11
|
||||
PIN_ADD(PD11)
|
||||
#endif
|
||||
#ifdef PD12
|
||||
PIN_ADD(PD12)
|
||||
#endif
|
||||
#ifdef PD13
|
||||
PIN_ADD(PD13)
|
||||
#endif
|
||||
#ifdef PD14
|
||||
PIN_ADD(PD14)
|
||||
#endif
|
||||
#ifdef PD15
|
||||
PIN_ADD(PD15)
|
||||
#endif
|
||||
|
||||
#ifdef PE0
|
||||
PIN_ADD(PE0)
|
||||
#endif
|
||||
#ifdef PE1
|
||||
PIN_ADD(PE1)
|
||||
#endif
|
||||
#ifdef PE2
|
||||
PIN_ADD(PE2)
|
||||
#endif
|
||||
#ifdef PE3
|
||||
PIN_ADD(PE3)
|
||||
#endif
|
||||
#ifdef PE4
|
||||
PIN_ADD(PE4)
|
||||
#endif
|
||||
#ifdef PE5
|
||||
PIN_ADD(PE5)
|
||||
#endif
|
||||
#ifdef PE6
|
||||
PIN_ADD(PE6)
|
||||
#endif
|
||||
#ifdef PE7
|
||||
PIN_ADD(PE7)
|
||||
#endif
|
||||
#ifdef PE8
|
||||
PIN_ADD(PE8)
|
||||
#endif
|
||||
#ifdef PE9
|
||||
PIN_ADD(PE9)
|
||||
#endif
|
||||
#ifdef PE10
|
||||
PIN_ADD(PE10)
|
||||
#endif
|
||||
#ifdef PE11
|
||||
PIN_ADD(PE11)
|
||||
#endif
|
||||
#ifdef PE12
|
||||
PIN_ADD(PE12)
|
||||
#endif
|
||||
#ifdef PE13
|
||||
PIN_ADD(PE13)
|
||||
#endif
|
||||
#ifdef PE14
|
||||
PIN_ADD(PE14)
|
||||
#endif
|
||||
#ifdef PE15
|
||||
PIN_ADD(PE15)
|
||||
#endif
|
||||
|
||||
#ifdef PF0
|
||||
PIN_ADD(PF0)
|
||||
#endif
|
||||
#ifdef PF1
|
||||
PIN_ADD(PF1)
|
||||
#endif
|
||||
#ifdef PF2
|
||||
PIN_ADD(PF2)
|
||||
#endif
|
||||
#ifdef PF3
|
||||
PIN_ADD(PF3)
|
||||
#endif
|
||||
#ifdef PF4
|
||||
PIN_ADD(PF4)
|
||||
#endif
|
||||
#ifdef PF5
|
||||
PIN_ADD(PF5)
|
||||
#endif
|
||||
#ifdef PF6
|
||||
PIN_ADD(PF6)
|
||||
#endif
|
||||
#ifdef PF7
|
||||
PIN_ADD(PF7)
|
||||
#endif
|
||||
#ifdef PF8
|
||||
PIN_ADD(PF8)
|
||||
#endif
|
||||
#ifdef PF9
|
||||
PIN_ADD(PF9)
|
||||
#endif
|
||||
#ifdef PF10
|
||||
PIN_ADD(PF10)
|
||||
#endif
|
||||
#ifdef PF11
|
||||
PIN_ADD(PF11)
|
||||
#endif
|
||||
#ifdef PF12
|
||||
PIN_ADD(PF12)
|
||||
#endif
|
||||
#ifdef PF13
|
||||
PIN_ADD(PF13)
|
||||
#endif
|
||||
#ifdef PF14
|
||||
PIN_ADD(PF14)
|
||||
#endif
|
||||
#ifdef PF15
|
||||
PIN_ADD(PF15)
|
||||
#endif
|
||||
|
||||
#ifdef PG0
|
||||
PIN_ADD(PG0)
|
||||
#endif
|
||||
#ifdef PG1
|
||||
PIN_ADD(PG1)
|
||||
#endif
|
||||
#ifdef PG2
|
||||
PIN_ADD(PG2)
|
||||
#endif
|
||||
#ifdef PG3
|
||||
PIN_ADD(PG3)
|
||||
#endif
|
||||
#ifdef PG4
|
||||
PIN_ADD(PG4)
|
||||
#endif
|
||||
#ifdef PG5
|
||||
PIN_ADD(PG5)
|
||||
#endif
|
||||
#ifdef PG6
|
||||
PIN_ADD(PG6)
|
||||
#endif
|
||||
#ifdef PG7
|
||||
PIN_ADD(PG7)
|
||||
#endif
|
||||
#ifdef PG8
|
||||
PIN_ADD(PG8)
|
||||
#endif
|
||||
#ifdef PG9
|
||||
PIN_ADD(PG9)
|
||||
#endif
|
||||
#ifdef PG10
|
||||
PIN_ADD(PG10)
|
||||
#endif
|
||||
#ifdef PG11
|
||||
PIN_ADD(PG11)
|
||||
#endif
|
||||
#ifdef PG12
|
||||
PIN_ADD(PG12)
|
||||
#endif
|
||||
#ifdef PG13
|
||||
PIN_ADD(PG13)
|
||||
#endif
|
||||
#ifdef PG14
|
||||
PIN_ADD(PG14)
|
||||
#endif
|
||||
#ifdef PG15
|
||||
PIN_ADD(PG15)
|
||||
#endif
|
||||
|
||||
#ifdef PH0
|
||||
PIN_ADD(PH0)
|
||||
#endif
|
||||
#ifdef PH1
|
||||
PIN_ADD(PH1)
|
||||
#endif
|
||||
#ifdef PH2
|
||||
PIN_ADD(PH2)
|
||||
#endif
|
||||
#ifdef PH3
|
||||
PIN_ADD(PH3)
|
||||
#endif
|
||||
#ifdef PH4
|
||||
PIN_ADD(PH4)
|
||||
#endif
|
||||
#ifdef PH5
|
||||
PIN_ADD(PH5)
|
||||
#endif
|
||||
#ifdef PH6
|
||||
PIN_ADD(PH6)
|
||||
#endif
|
||||
#ifdef PH7
|
||||
PIN_ADD(PH7)
|
||||
#endif
|
||||
#ifdef PH8
|
||||
PIN_ADD(PH8)
|
||||
#endif
|
||||
#ifdef PH9
|
||||
PIN_ADD(PH9)
|
||||
#endif
|
||||
#ifdef PH10
|
||||
PIN_ADD(PH10)
|
||||
#endif
|
||||
#ifdef PH11
|
||||
PIN_ADD(PH11)
|
||||
#endif
|
||||
#ifdef PH12
|
||||
PIN_ADD(PH12)
|
||||
#endif
|
||||
#ifdef PH13
|
||||
PIN_ADD(PH13)
|
||||
#endif
|
||||
#ifdef PH14
|
||||
PIN_ADD(PH14)
|
||||
#endif
|
||||
#ifdef PH15
|
||||
PIN_ADD(PH15)
|
||||
#endif
|
||||
|
||||
#ifdef PI0
|
||||
PIN_ADD(PI0)
|
||||
#endif
|
||||
#ifdef PI1
|
||||
PIN_ADD(PI1)
|
||||
#endif
|
||||
#ifdef PI2
|
||||
PIN_ADD(PI2)
|
||||
#endif
|
||||
#ifdef PI3
|
||||
PIN_ADD(PI3)
|
||||
#endif
|
||||
#ifdef PI4
|
||||
PIN_ADD(PI4)
|
||||
#endif
|
||||
#ifdef PI5
|
||||
PIN_ADD(PI5)
|
||||
#endif
|
||||
#ifdef PI6
|
||||
PIN_ADD(PI6)
|
||||
#endif
|
||||
#ifdef PI7
|
||||
PIN_ADD(PI7)
|
||||
#endif
|
||||
#ifdef PI8
|
||||
PIN_ADD(PI8)
|
||||
#endif
|
||||
#ifdef PI9
|
||||
PIN_ADD(PI9)
|
||||
#endif
|
||||
#ifdef PI10
|
||||
PIN_ADD(PI10)
|
||||
#endif
|
||||
#ifdef PI11
|
||||
PIN_ADD(PI11)
|
||||
#endif
|
||||
#ifdef PI12
|
||||
PIN_ADD(PI12)
|
||||
#endif
|
||||
#ifdef PI13
|
||||
PIN_ADD(PI13)
|
||||
#endif
|
||||
#ifdef PI14
|
||||
PIN_ADD(PI14)
|
||||
#endif
|
||||
#ifdef PI15
|
||||
PIN_ADD(PI15)
|
||||
#endif
|
||||
|
||||
#ifdef PJ0
|
||||
PIN_ADD(PJ0)
|
||||
#endif
|
||||
#ifdef PJ1
|
||||
PIN_ADD(PJ1)
|
||||
#endif
|
||||
#ifdef PJ2
|
||||
PIN_ADD(PJ2)
|
||||
#endif
|
||||
#ifdef PJ3
|
||||
PIN_ADD(PJ3)
|
||||
#endif
|
||||
#ifdef PJ4
|
||||
PIN_ADD(PJ4)
|
||||
#endif
|
||||
#ifdef PJ5
|
||||
PIN_ADD(PJ5)
|
||||
#endif
|
||||
#ifdef PJ6
|
||||
PIN_ADD(PJ6)
|
||||
#endif
|
||||
#ifdef PJ7
|
||||
PIN_ADD(PJ7)
|
||||
#endif
|
||||
#ifdef PJ8
|
||||
PIN_ADD(PJ8)
|
||||
#endif
|
||||
#ifdef PJ9
|
||||
PIN_ADD(PJ9)
|
||||
#endif
|
||||
#ifdef PJ10
|
||||
PIN_ADD(PJ10)
|
||||
#endif
|
||||
#ifdef PJ11
|
||||
PIN_ADD(PJ11)
|
||||
#endif
|
||||
#ifdef PJ12
|
||||
PIN_ADD(PJ12)
|
||||
#endif
|
||||
#ifdef PJ13
|
||||
PIN_ADD(PJ13)
|
||||
#endif
|
||||
#ifdef PJ14
|
||||
PIN_ADD(PJ14)
|
||||
#endif
|
||||
#ifdef PJ15
|
||||
PIN_ADD(PJ15)
|
||||
#endif
|
||||
|
||||
#ifdef PK0
|
||||
PIN_ADD(PK0)
|
||||
#endif
|
||||
#ifdef PK1
|
||||
PIN_ADD(PK1)
|
||||
#endif
|
||||
#ifdef PK2
|
||||
PIN_ADD(PK2)
|
||||
#endif
|
||||
#ifdef PK3
|
||||
PIN_ADD(PK3)
|
||||
#endif
|
||||
#ifdef PK4
|
||||
PIN_ADD(PK4)
|
||||
#endif
|
||||
#ifdef PK5
|
||||
PIN_ADD(PK5)
|
||||
#endif
|
||||
#ifdef PK6
|
||||
PIN_ADD(PK6)
|
||||
#endif
|
||||
#ifdef PK7
|
||||
PIN_ADD(PK7)
|
||||
#endif
|
||||
#ifdef PK8
|
||||
PIN_ADD(PK8)
|
||||
#endif
|
||||
#ifdef PK9
|
||||
PIN_ADD(PK9)
|
||||
#endif
|
||||
#ifdef PK10
|
||||
PIN_ADD(PK10)
|
||||
#endif
|
||||
#ifdef PK11
|
||||
PIN_ADD(PK11)
|
||||
#endif
|
||||
#ifdef PK12
|
||||
PIN_ADD(PK12)
|
||||
#endif
|
||||
#ifdef PK13
|
||||
PIN_ADD(PK13)
|
||||
#endif
|
||||
#ifdef PK14
|
||||
PIN_ADD(PK14)
|
||||
#endif
|
||||
#ifdef PK15
|
||||
PIN_ADD(PK15)
|
||||
#endif
|
||||
|
||||
#ifdef PL0
|
||||
PIN_ADD(PL0)
|
||||
#endif
|
||||
#ifdef PL1
|
||||
PIN_ADD(PL1)
|
||||
#endif
|
||||
#ifdef PL2
|
||||
PIN_ADD(PL2)
|
||||
#endif
|
||||
#ifdef PL3
|
||||
PIN_ADD(PL3)
|
||||
#endif
|
||||
#ifdef PL4
|
||||
PIN_ADD(PL4)
|
||||
#endif
|
||||
#ifdef PL5
|
||||
PIN_ADD(PL5)
|
||||
#endif
|
||||
#ifdef PL6
|
||||
PIN_ADD(PL6)
|
||||
#endif
|
||||
#ifdef PL7
|
||||
PIN_ADD(PL7)
|
||||
#endif
|
||||
#ifdef PL8
|
||||
PIN_ADD(PL8)
|
||||
#endif
|
||||
#ifdef PL9
|
||||
PIN_ADD(PL9)
|
||||
#endif
|
||||
#ifdef PL10
|
||||
PIN_ADD(PL10)
|
||||
#endif
|
||||
#ifdef PL11
|
||||
PIN_ADD(PL11)
|
||||
#endif
|
||||
#ifdef PL12
|
||||
PIN_ADD(PL12)
|
||||
#endif
|
||||
#ifdef PL13
|
||||
PIN_ADD(PL13)
|
||||
#endif
|
||||
#ifdef PL14
|
||||
PIN_ADD(PL14)
|
||||
#endif
|
||||
#ifdef PL15
|
||||
PIN_ADD(PL15)
|
||||
#endif
|
@ -0,0 +1,451 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(SDIO_SUPPORT)
|
||||
|
||||
#include "sdio.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(STM32F103xE) || defined(STM32F103xG)
|
||||
#include <stm32f1xx_hal_rcc_ex.h>
|
||||
#include <stm32f1xx_hal_sd.h>
|
||||
#elif defined(STM32F4xx)
|
||||
#include <stm32f4xx_hal_rcc.h>
|
||||
#include <stm32f4xx_hal_dma.h>
|
||||
#include <stm32f4xx_hal_gpio.h>
|
||||
#include <stm32f4xx_hal_sd.h>
|
||||
#elif defined(STM32F7xx)
|
||||
#include <stm32f7xx_hal_rcc.h>
|
||||
#include <stm32f7xx_hal_dma.h>
|
||||
#include <stm32f7xx_hal_gpio.h>
|
||||
#include <stm32f7xx_hal_sd.h>
|
||||
#elif defined(STM32H7xx)
|
||||
#define SDIO_FOR_STM32H7
|
||||
#include <stm32h7xx_hal_rcc.h>
|
||||
#include <stm32h7xx_hal_dma.h>
|
||||
#include <stm32h7xx_hal_gpio.h>
|
||||
#include <stm32h7xx_hal_sd.h>
|
||||
#else
|
||||
#error "SDIO is only supported with STM32F103xE, STM32F103xG, STM32F4xx, STM32F7xx, and STM32H7xx."
|
||||
#endif
|
||||
|
||||
// SDIO Max Clock (naming from STM Manual, don't change)
|
||||
#define SDIOCLK 48000000
|
||||
|
||||
// Target Clock, configurable. Default is 18MHz, from STM32F1
|
||||
#ifndef SDIO_CLOCK
|
||||
#define SDIO_CLOCK 18000000 // 18 MHz
|
||||
#endif
|
||||
|
||||
SD_HandleTypeDef hsd; // SDIO structure
|
||||
|
||||
static uint32_t clock_to_divider(uint32_t clk) {
|
||||
#ifdef SDIO_FOR_STM32H7
|
||||
// SDMMC_CK frequency = sdmmc_ker_ck / [2 * CLKDIV].
|
||||
uint32_t sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
|
||||
return sdmmc_clk / (2U * SDIO_CLOCK) + (sdmmc_clk % (2U * SDIO_CLOCK) != 0);
|
||||
#else
|
||||
// limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals
|
||||
// Also limited to no more than 48Mhz (SDIOCLK).
|
||||
const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq();
|
||||
clk = min(clk, (uint32_t)(pclk2 * 8 / 3));
|
||||
clk = min(clk, (uint32_t)SDIOCLK);
|
||||
// Round up divider, so we don't run the card over the speed supported,
|
||||
// and subtract by 2, because STM32 will add 2, as written in the manual:
|
||||
// SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
|
||||
return pclk2 / clk + (pclk2 % clk != 0) - 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Start the SDIO clock
|
||||
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
|
||||
UNUSED(hsd);
|
||||
#ifdef SDIO_FOR_STM32H7
|
||||
pinmap_pinout(PC_12, PinMap_SD);
|
||||
pinmap_pinout(PD_2, PinMap_SD);
|
||||
pinmap_pinout(PC_8, PinMap_SD);
|
||||
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // Define D1-D3 only for 4-bit wide SDIO bus
|
||||
pinmap_pinout(PC_9, PinMap_SD);
|
||||
pinmap_pinout(PC_10, PinMap_SD);
|
||||
pinmap_pinout(PC_11, PinMap_SD);
|
||||
#endif
|
||||
__HAL_RCC_SDMMC1_CLK_ENABLE();
|
||||
HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
|
||||
#else
|
||||
__HAL_RCC_SDIO_CLK_ENABLE();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SDIO_FOR_STM32H7
|
||||
|
||||
#define SD_TIMEOUT 1000 // ms
|
||||
|
||||
extern "C" void SDMMC1_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
|
||||
|
||||
uint8_t waitingRxCplt = 0, waitingTxCplt = 0;
|
||||
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsdio) { waitingTxCplt = 0; }
|
||||
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsdio) { waitingRxCplt = 0; }
|
||||
|
||||
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) {
|
||||
__HAL_RCC_SDMMC1_FORCE_RESET(); delay(10);
|
||||
__HAL_RCC_SDMMC1_RELEASE_RESET(); delay(10);
|
||||
}
|
||||
|
||||
bool SDIO_Init() {
|
||||
HAL_StatusTypeDef sd_state = HAL_OK;
|
||||
if (hsd.Instance == SDMMC1) HAL_SD_DeInit(&hsd);
|
||||
|
||||
// HAL SD initialization
|
||||
hsd.Instance = SDMMC1;
|
||||
hsd.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
|
||||
hsd.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
|
||||
hsd.Init.BusWide = SDMMC_BUS_WIDE_1B;
|
||||
hsd.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
|
||||
hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
|
||||
sd_state = HAL_SD_Init(&hsd);
|
||||
|
||||
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3)
|
||||
if (sd_state == HAL_OK)
|
||||
sd_state = HAL_SD_ConfigWideBusOperation(&hsd, SDMMC_BUS_WIDE_4B);
|
||||
#endif
|
||||
|
||||
return (sd_state == HAL_OK);
|
||||
}
|
||||
|
||||
#else // !SDIO_FOR_STM32H7
|
||||
|
||||
#define SD_TIMEOUT 500 // ms
|
||||
|
||||
// SDIO retries, configurable. Default is 3, from STM32F1
|
||||
#ifndef SDIO_READ_RETRIES
|
||||
#define SDIO_READ_RETRIES 3
|
||||
#endif
|
||||
|
||||
// F4 supports one DMA for RX and another for TX, but Marlin will never
|
||||
// do read and write at same time, so we use the same DMA for both.
|
||||
DMA_HandleTypeDef hdma_sdio;
|
||||
|
||||
#ifdef STM32F1xx
|
||||
#define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler
|
||||
#elif defined(STM32F4xx)
|
||||
#define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler
|
||||
#else
|
||||
#error "Unknown STM32 architecture."
|
||||
#endif
|
||||
|
||||
extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
|
||||
extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); }
|
||||
|
||||
/*
|
||||
SDIO_INIT_CLK_DIV is 118
|
||||
SDIO clock frequency is 48MHz / (TRANSFER_CLOCK_DIV + 2)
|
||||
SDIO init clock frequency should not exceed 400kHz = 48MHz / (118 + 2)
|
||||
|
||||
Default TRANSFER_CLOCK_DIV is 2 (118 / 40)
|
||||
Default SDIO clock frequency is 48MHz / (2 + 2) = 12 MHz
|
||||
This might be too fast for stable SDIO operations
|
||||
|
||||
MKS Robin SDIO seems stable with BusWide 1bit and ClockDiv 8 (i.e., 4.8MHz SDIO clock frequency)
|
||||
More testing is required as there are clearly some 4bit init problems.
|
||||
*/
|
||||
|
||||
void go_to_transfer_speed() {
|
||||
/* Default SDIO peripheral configuration for SD card initialization */
|
||||
hsd.Init.ClockEdge = hsd.Init.ClockEdge;
|
||||
hsd.Init.ClockBypass = hsd.Init.ClockBypass;
|
||||
hsd.Init.ClockPowerSave = hsd.Init.ClockPowerSave;
|
||||
hsd.Init.BusWide = hsd.Init.BusWide;
|
||||
hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl;
|
||||
hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
|
||||
|
||||
/* Initialize SDIO peripheral interface with default configuration */
|
||||
SDIO_Init(hsd.Instance, hsd.Init);
|
||||
}
|
||||
|
||||
void SD_LowLevel_Init() {
|
||||
uint32_t tempreg;
|
||||
|
||||
// Enable GPIO clocks
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = 1; // GPIO_NOPULL
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
|
||||
#if DISABLED(STM32F1xx)
|
||||
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
|
||||
#endif
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // define D1-D3 only if have a four bit wide SDIO bus
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; // D1-D3
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
#endif
|
||||
|
||||
// Configure PD.02 CMD line
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_2;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||
|
||||
// Setup DMA
|
||||
#ifdef STM32F1xx
|
||||
hdma_sdio.Init.Mode = DMA_NORMAL;
|
||||
hdma_sdio.Instance = DMA2_Channel4;
|
||||
HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
|
||||
#elif defined(STM32F4xx)
|
||||
hdma_sdio.Init.Mode = DMA_PFCTRL;
|
||||
hdma_sdio.Instance = DMA2_Stream3;
|
||||
hdma_sdio.Init.Channel = DMA_CHANNEL_4;
|
||||
hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
||||
hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
||||
hdma_sdio.Init.MemBurst = DMA_MBURST_INC4;
|
||||
hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4;
|
||||
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
|
||||
#endif
|
||||
HAL_NVIC_EnableIRQ(SDIO_IRQn);
|
||||
hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
|
||||
hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
||||
hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
|
||||
__HAL_LINKDMA(&hsd, hdmarx, hdma_sdio);
|
||||
__HAL_LINKDMA(&hsd, hdmatx, hdma_sdio);
|
||||
|
||||
#ifdef STM32F1xx
|
||||
__HAL_RCC_SDIO_CLK_ENABLE();
|
||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||
#else
|
||||
__HAL_RCC_SDIO_FORCE_RESET(); delay(2);
|
||||
__HAL_RCC_SDIO_RELEASE_RESET(); delay(2);
|
||||
__HAL_RCC_SDIO_CLK_ENABLE();
|
||||
|
||||
__HAL_RCC_DMA2_FORCE_RESET(); delay(2);
|
||||
__HAL_RCC_DMA2_RELEASE_RESET(); delay(2);
|
||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||
#endif
|
||||
|
||||
// Initialize the SDIO (with initial <400Khz Clock)
|
||||
tempreg = 0 // Reset value
|
||||
| SDIO_CLKCR_CLKEN // Clock enabled
|
||||
| SDIO_INIT_CLK_DIV; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz
|
||||
// Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable
|
||||
SDIO->CLKCR = tempreg;
|
||||
|
||||
// Power up the SDIO
|
||||
SDIO_PowerState_ON(SDIO);
|
||||
hsd.Instance = SDIO;
|
||||
}
|
||||
|
||||
bool SDIO_Init() {
|
||||
uint8_t retryCnt = SDIO_READ_RETRIES;
|
||||
|
||||
bool status;
|
||||
hsd.Instance = SDIO;
|
||||
hsd.State = HAL_SD_STATE_RESET;
|
||||
|
||||
SD_LowLevel_Init();
|
||||
|
||||
uint8_t retry_Cnt = retryCnt;
|
||||
for (;;) {
|
||||
hal.watchdog_refresh();
|
||||
status = (bool) HAL_SD_Init(&hsd);
|
||||
if (!status) break;
|
||||
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
|
||||
}
|
||||
|
||||
go_to_transfer_speed();
|
||||
|
||||
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined
|
||||
retry_Cnt = retryCnt;
|
||||
for (;;) {
|
||||
hal.watchdog_refresh();
|
||||
if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) break; // some cards are only 1 bit wide so a pass here is not required
|
||||
if (!--retry_Cnt) break;
|
||||
}
|
||||
if (!retry_Cnt) { // wide bus failed, go back to one bit wide mode
|
||||
hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET
|
||||
SD_LowLevel_Init();
|
||||
retry_Cnt = retryCnt;
|
||||
for (;;) {
|
||||
hal.watchdog_refresh();
|
||||
status = (bool) HAL_SD_Init(&hsd);
|
||||
if (!status) break;
|
||||
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
|
||||
}
|
||||
go_to_transfer_speed();
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read or Write a block
|
||||
* @details Read or Write a block with SDIO
|
||||
*
|
||||
* @param block The block index
|
||||
* @param src The data buffer source for a write
|
||||
* @param dst The data buffer destination for a read
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) {
|
||||
if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false;
|
||||
|
||||
hal.watchdog_refresh();
|
||||
|
||||
HAL_StatusTypeDef ret;
|
||||
if (src) {
|
||||
hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
HAL_DMA_Init(&hdma_sdio);
|
||||
ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*)src, block, 1);
|
||||
}
|
||||
else {
|
||||
hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
HAL_DMA_Init(&hdma_sdio);
|
||||
ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1);
|
||||
}
|
||||
|
||||
if (ret != HAL_OK) {
|
||||
HAL_DMA_Abort_IT(&hdma_sdio);
|
||||
HAL_DMA_DeInit(&hdma_sdio);
|
||||
return false;
|
||||
}
|
||||
|
||||
millis_t timeout = millis() + SD_TIMEOUT;
|
||||
// Wait the transfer
|
||||
while (hsd.State != HAL_SD_STATE_READY) {
|
||||
if (ELAPSED(millis(), timeout)) {
|
||||
HAL_DMA_Abort_IT(&hdma_sdio);
|
||||
HAL_DMA_DeInit(&hdma_sdio);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0
|
||||
|| __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ }
|
||||
|
||||
HAL_DMA_Abort_IT(&hdma_sdio);
|
||||
HAL_DMA_DeInit(&hdma_sdio);
|
||||
|
||||
timeout = millis() + SD_TIMEOUT;
|
||||
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // !SDIO_FOR_STM32H7
|
||||
|
||||
/**
|
||||
* @brief Read a block
|
||||
* @details Read a block from media with SDIO
|
||||
*
|
||||
* @param block The block index
|
||||
* @param src The block buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
|
||||
#ifdef SDIO_FOR_STM32H7
|
||||
|
||||
uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
|
||||
|
||||
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
|
||||
if (HAL_GetTick() >= timeout) return false;
|
||||
|
||||
waitingRxCplt = 1;
|
||||
if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1) != HAL_OK)
|
||||
return false;
|
||||
|
||||
timeout = HAL_GetTick() + SD_TIMEOUT;
|
||||
while (waitingRxCplt)
|
||||
if (HAL_GetTick() >= timeout) return false;
|
||||
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
uint8_t retries = SDIO_READ_RETRIES;
|
||||
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, nullptr, dst)) return true;
|
||||
return false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a block
|
||||
* @details Write a block to media with SDIO
|
||||
*
|
||||
* @param block The block index
|
||||
* @param src The block data
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
|
||||
#ifdef SDIO_FOR_STM32H7
|
||||
|
||||
uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
|
||||
|
||||
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
|
||||
if (HAL_GetTick() >= timeout) return false;
|
||||
|
||||
waitingTxCplt = 1;
|
||||
if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*)src, block, 1) != HAL_OK)
|
||||
return false;
|
||||
|
||||
timeout = HAL_GetTick() + SD_TIMEOUT;
|
||||
while (waitingTxCplt)
|
||||
if (HAL_GetTick() >= timeout) return false;
|
||||
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
uint8_t retries = SDIO_READ_RETRIES;
|
||||
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, nullptr)) return true;
|
||||
return false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SDIO_IsReady() {
|
||||
return hsd.State == HAL_SD_STATE_READY;
|
||||
}
|
||||
|
||||
uint32_t SDIO_GetCardSize() {
|
||||
return (uint32_t)(hsd.SdCard.BlockNbr) * (hsd.SdCard.BlockSize);
|
||||
}
|
||||
|
||||
#endif // SDIO_SUPPORT
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define SDIO_D0_PIN PC8
|
||||
#define SDIO_D1_PIN PC9
|
||||
#define SDIO_D2_PIN PC10
|
||||
#define SDIO_D3_PIN PC11
|
||||
#define SDIO_CK_PIN PC12
|
||||
#define SDIO_CMD_PIN PD2
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Define SPI Pins: SCK, MISO, MOSI, SS
|
||||
*/
|
||||
#ifndef SD_SCK_PIN
|
||||
#define SD_SCK_PIN PIN_SPI_SCK
|
||||
#endif
|
||||
#ifndef SD_MISO_PIN
|
||||
#define SD_MISO_PIN PIN_SPI_MISO
|
||||
#endif
|
||||
#ifndef SD_MOSI_PIN
|
||||
#define SD_MOSI_PIN PIN_SPI_MOSI
|
||||
#endif
|
||||
#ifndef SD_SS_PIN
|
||||
#define SD_SS_PIN PIN_SPI_SS
|
||||
#endif
|
@ -0,0 +1,208 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "../../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(TFT_TOUCH_DEVICE_GT911)
|
||||
|
||||
#include "gt911.h"
|
||||
#include "pinconfig.h"
|
||||
|
||||
SW_IIC::SW_IIC(uint16_t sda, uint16_t scl) {
|
||||
scl_pin = scl;
|
||||
sda_pin = sda;
|
||||
}
|
||||
|
||||
// Software I2C hardware io init
|
||||
void SW_IIC::init() {
|
||||
OUT_WRITE(scl_pin, HIGH);
|
||||
OUT_WRITE(sda_pin, HIGH);
|
||||
}
|
||||
|
||||
// Software I2C start signal
|
||||
void SW_IIC::start() {
|
||||
write_sda(HIGH); // SDA = 1
|
||||
write_scl(HIGH); // SCL = 1
|
||||
iic_delay(2);
|
||||
write_sda(LOW); // SDA = 0
|
||||
iic_delay(1);
|
||||
write_scl(LOW); // SCL = 0 // keep SCL low, avoid false stop caused by level jump caused by SDA switching IN/OUT
|
||||
}
|
||||
|
||||
// Software I2C stop signal
|
||||
void SW_IIC::stop() {
|
||||
write_scl(LOW); // SCL = 0
|
||||
iic_delay(2);
|
||||
write_sda(LOW); // SDA = 0
|
||||
iic_delay(2);
|
||||
write_scl(HIGH); // SCL = 1
|
||||
iic_delay(2);
|
||||
write_sda(HIGH); // SDA = 1
|
||||
}
|
||||
|
||||
// Software I2C sends ACK or NACK signal
|
||||
void SW_IIC::send_ack(bool ack) {
|
||||
write_sda(ack ? LOW : HIGH); // SDA = !ack
|
||||
iic_delay(2);
|
||||
write_scl(HIGH); // SCL = 1
|
||||
iic_delay(2);
|
||||
write_scl(LOW); // SCL = 0
|
||||
}
|
||||
|
||||
// Software I2C read ACK or NACK signal
|
||||
bool SW_IIC::read_ack() {
|
||||
bool error = 0;
|
||||
set_sda_in();
|
||||
|
||||
iic_delay(2);
|
||||
|
||||
write_scl(HIGH); // SCL = 1
|
||||
error = read_sda();
|
||||
|
||||
iic_delay(2);
|
||||
|
||||
write_scl(LOW); // SCL = 0
|
||||
|
||||
set_sda_out();
|
||||
return error;
|
||||
}
|
||||
|
||||
void SW_IIC::send_byte(uint8_t txd) {
|
||||
LOOP_L_N(i, 8) {
|
||||
write_sda(txd & 0x80); // write data bit
|
||||
txd <<= 1;
|
||||
iic_delay(1);
|
||||
write_scl(HIGH); // SCL = 1
|
||||
iic_delay(2);
|
||||
write_scl(LOW); // SCL = 0
|
||||
iic_delay(1);
|
||||
}
|
||||
|
||||
read_ack(); // wait ack
|
||||
}
|
||||
|
||||
uint8_t SW_IIC::read_byte(bool ack) {
|
||||
uint8_t data = 0;
|
||||
|
||||
set_sda_in();
|
||||
LOOP_L_N(i, 8) {
|
||||
write_scl(HIGH); // SCL = 1
|
||||
iic_delay(1);
|
||||
data <<= 1;
|
||||
if (read_sda()) data++;
|
||||
write_scl(LOW); // SCL = 0
|
||||
iic_delay(2);
|
||||
}
|
||||
set_sda_out();
|
||||
|
||||
send_ack(ack);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
GT911_REG_MAP GT911::reg;
|
||||
SW_IIC GT911::sw_iic = SW_IIC(GT911_SW_I2C_SDA_PIN, GT911_SW_I2C_SCL_PIN);
|
||||
|
||||
void GT911::write_reg(uint16_t reg, uint8_t reg_len, uint8_t* w_data, uint8_t w_len) {
|
||||
sw_iic.start();
|
||||
sw_iic.send_byte(gt911_slave_address); // Set IIC Slave address
|
||||
LOOP_L_N(i, reg_len) { // Set reg address
|
||||
uint8_t r = (reg >> (8 * (reg_len - 1 - i))) & 0xFF;
|
||||
sw_iic.send_byte(r);
|
||||
}
|
||||
|
||||
LOOP_L_N(i, w_len) { // Write data to reg
|
||||
sw_iic.send_byte(w_data[i]);
|
||||
}
|
||||
sw_iic.stop();
|
||||
}
|
||||
|
||||
void GT911::read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_len) {
|
||||
sw_iic.start();
|
||||
sw_iic.send_byte(gt911_slave_address); // Set IIC Slave address
|
||||
LOOP_L_N(i, reg_len) { // Set reg address
|
||||
uint8_t r = (reg >> (8 * (reg_len - 1 - i))) & 0xFF;
|
||||
sw_iic.send_byte(r);
|
||||
}
|
||||
|
||||
sw_iic.start();
|
||||
sw_iic.send_byte(gt911_slave_address + 1); // Set read mode
|
||||
|
||||
LOOP_L_N(i, r_len)
|
||||
r_data[i] = sw_iic.read_byte(1); // Read data from reg
|
||||
|
||||
sw_iic.stop();
|
||||
}
|
||||
|
||||
void GT911::Init() {
|
||||
OUT_WRITE(GT911_RST_PIN, LOW);
|
||||
OUT_WRITE(GT911_INT_PIN, LOW);
|
||||
delay(11);
|
||||
WRITE(GT911_INT_PIN, HIGH);
|
||||
delayMicroseconds(110);
|
||||
WRITE(GT911_RST_PIN, HIGH);
|
||||
delay(6);
|
||||
WRITE(GT911_INT_PIN, LOW);
|
||||
delay(55);
|
||||
SET_INPUT(GT911_INT_PIN);
|
||||
|
||||
sw_iic.init();
|
||||
|
||||
uint8_t clear_reg = 0x00;
|
||||
write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start
|
||||
}
|
||||
|
||||
bool GT911::getFirstTouchPoint(int16_t *x, int16_t *y) {
|
||||
read_reg(0x814E, 2, ®.REG.status, 1);
|
||||
|
||||
if (reg.REG.status >= 0x80 && reg.REG.status <= 0x85) {
|
||||
read_reg(0x8150, 2, reg.map + 2, 38);
|
||||
uint8_t clear_reg = 0x00;
|
||||
write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start
|
||||
// First touch point
|
||||
*x = ((reg.REG.point[0].xh & 0x0F) << 8) | reg.REG.point[0].xl;
|
||||
*y = ((reg.REG.point[0].yh & 0x0F) << 8) | reg.REG.point[0].yl;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GT911::getPoint(int16_t *x, int16_t *y) {
|
||||
static bool touched = 0;
|
||||
static int16_t read_x = 0, read_y = 0;
|
||||
static millis_t next_time = 0;
|
||||
|
||||
if (ELAPSED(millis(), next_time)) {
|
||||
touched = getFirstTouchPoint(&read_x, &read_y);
|
||||
next_time = millis() + 20;
|
||||
}
|
||||
|
||||
*x = read_x;
|
||||
*y = read_y;
|
||||
return touched;
|
||||
}
|
||||
|
||||
#endif // TFT_TOUCH_DEVICE_GT911
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#define GT911_SLAVE_ADDRESS 0x28
|
||||
|
||||
#if !PIN_EXISTS(GT911_RST)
|
||||
#error "GT911_RST_PIN is not defined."
|
||||
#elif !PIN_EXISTS(GT911_INT)
|
||||
#error "GT911_INT_PIN is not defined."
|
||||
#elif !PIN_EXISTS(GT911_SW_I2C_SCL)
|
||||
#error "GT911_SW_I2C_SCL_PIN is not defined."
|
||||
#elif !PIN_EXISTS(GT911_SW_I2C_SDA)
|
||||
#error "GT911_SW_I2C_SDA_PIN is not defined."
|
||||
#endif
|
||||
|
||||
class SW_IIC {
|
||||
private:
|
||||
uint16_t scl_pin;
|
||||
uint16_t sda_pin;
|
||||
void write_scl(bool level) { WRITE(scl_pin, level); }
|
||||
void write_sda(bool level) { WRITE(sda_pin, level); }
|
||||
bool read_sda() { return READ(sda_pin); }
|
||||
void set_sda_out() { SET_OUTPUT(sda_pin); }
|
||||
void set_sda_in() { SET_INPUT_PULLUP(sda_pin); }
|
||||
static void iic_delay(uint8_t t) { delayMicroseconds(t); }
|
||||
|
||||
public:
|
||||
SW_IIC(uint16_t sda, uint16_t scl);
|
||||
// setSCL/SDA have to be called before begin()
|
||||
void setSCL(uint16_t scl) { scl_pin = scl; }
|
||||
void setSDA(uint16_t sda) { sda_pin = sda; }
|
||||
void init(); // Initialize the IO port of IIC
|
||||
void start(); // Send IIC start signal
|
||||
void stop(); // Send IIC stop signal
|
||||
void send_byte(uint8_t txd); // IIC sends a byte
|
||||
uint8_t read_byte(bool ack); // IIC reads a byte
|
||||
void send_ack(bool ack); // IIC sends ACK or NACK signal
|
||||
bool read_ack();
|
||||
};
|
||||
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
uint8_t xl;
|
||||
uint8_t xh;
|
||||
uint8_t yl;
|
||||
uint8_t yh;
|
||||
uint8_t sizel;
|
||||
uint8_t sizeh;
|
||||
uint8_t reserved;
|
||||
uint8_t track_id;
|
||||
} GT911_POINT;
|
||||
|
||||
typedef union __attribute__((__packed__)) {
|
||||
uint8_t map[42];
|
||||
struct {
|
||||
uint8_t status; // 0x814E
|
||||
uint8_t track_id; // 0x814F
|
||||
|
||||
GT911_POINT point[5]; // [0]:0x8150 - 0x8157 / [1]:0x8158 - 0x815F / [2]:0x8160 - 0x8167 / [3]:0x8168 - 0x816F / [4]:0x8170 - 0x8177
|
||||
} REG;
|
||||
} GT911_REG_MAP;
|
||||
|
||||
class GT911 {
|
||||
private:
|
||||
static const uint8_t gt911_slave_address = GT911_SLAVE_ADDRESS;
|
||||
static GT911_REG_MAP reg;
|
||||
static SW_IIC sw_iic;
|
||||
static void write_reg(uint16_t reg, uint8_t reg_len, uint8_t* w_data, uint8_t w_len);
|
||||
static void read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_len);
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static bool getFirstTouchPoint(int16_t *x, int16_t *y);
|
||||
static bool getPoint(int16_t *x, int16_t *y);
|
||||
};
|
@ -0,0 +1,189 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_FSMC_TFT
|
||||
|
||||
#include "tft_fsmc.h"
|
||||
#include "pinconfig.h"
|
||||
|
||||
SRAM_HandleTypeDef TFT_FSMC::SRAMx;
|
||||
DMA_HandleTypeDef TFT_FSMC::DMAtx;
|
||||
LCD_CONTROLLER_TypeDef *TFT_FSMC::LCD;
|
||||
|
||||
void TFT_FSMC::Init() {
|
||||
uint32_t controllerAddress;
|
||||
FSMC_NORSRAM_TimingTypeDef Timing, ExtTiming;
|
||||
|
||||
uint32_t NSBank = (uint32_t)pinmap_peripheral(digitalPinToPinName(TFT_CS_PIN), PinMap_FSMC_CS);
|
||||
|
||||
// Perform the SRAM1 memory initialization sequence
|
||||
SRAMx.Instance = FSMC_NORSRAM_DEVICE;
|
||||
SRAMx.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
|
||||
// SRAMx.Init
|
||||
SRAMx.Init.NSBank = NSBank;
|
||||
SRAMx.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
|
||||
SRAMx.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
|
||||
SRAMx.Init.MemoryDataWidth = TERN(TFT_INTERFACE_FSMC_8BIT, FSMC_NORSRAM_MEM_BUS_WIDTH_8, FSMC_NORSRAM_MEM_BUS_WIDTH_16);
|
||||
SRAMx.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
|
||||
SRAMx.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
|
||||
SRAMx.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
|
||||
SRAMx.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
|
||||
SRAMx.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
|
||||
SRAMx.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
|
||||
SRAMx.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE;
|
||||
SRAMx.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
|
||||
SRAMx.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
|
||||
#ifdef STM32F4xx
|
||||
SRAMx.Init.PageSize = FSMC_PAGE_SIZE_NONE;
|
||||
#endif
|
||||
// Read Timing - relatively slow to ensure ID information is correctly read from TFT controller
|
||||
// Can be decreases from 15-15-24 to 4-4-8 with risk of stability loss
|
||||
Timing.AddressSetupTime = 15;
|
||||
Timing.AddressHoldTime = 15;
|
||||
Timing.DataSetupTime = 24;
|
||||
Timing.BusTurnAroundDuration = 0;
|
||||
Timing.CLKDivision = 16;
|
||||
Timing.DataLatency = 17;
|
||||
Timing.AccessMode = FSMC_ACCESS_MODE_A;
|
||||
// Write Timing
|
||||
// Can be decreases from 8-15-8 to 0-0-1 with risk of stability loss
|
||||
ExtTiming.AddressSetupTime = 8;
|
||||
ExtTiming.AddressHoldTime = 15;
|
||||
ExtTiming.DataSetupTime = 8;
|
||||
ExtTiming.BusTurnAroundDuration = 0;
|
||||
ExtTiming.CLKDivision = 16;
|
||||
ExtTiming.DataLatency = 17;
|
||||
ExtTiming.AccessMode = FSMC_ACCESS_MODE_A;
|
||||
|
||||
__HAL_RCC_FSMC_CLK_ENABLE();
|
||||
|
||||
for (uint16_t i = 0; PinMap_FSMC[i].pin != NC; i++)
|
||||
pinmap_pinout(PinMap_FSMC[i].pin, PinMap_FSMC);
|
||||
pinmap_pinout(digitalPinToPinName(TFT_CS_PIN), PinMap_FSMC_CS);
|
||||
pinmap_pinout(digitalPinToPinName(TFT_RS_PIN), PinMap_FSMC_RS);
|
||||
|
||||
controllerAddress = FSMC_BANK1_1;
|
||||
#ifdef PF0
|
||||
switch (NSBank) {
|
||||
case FSMC_NORSRAM_BANK2: controllerAddress = FSMC_BANK1_2 ; break;
|
||||
case FSMC_NORSRAM_BANK3: controllerAddress = FSMC_BANK1_3 ; break;
|
||||
case FSMC_NORSRAM_BANK4: controllerAddress = FSMC_BANK1_4 ; break;
|
||||
}
|
||||
#endif
|
||||
|
||||
controllerAddress |= (uint32_t)pinmap_peripheral(digitalPinToPinName(TFT_RS_PIN), PinMap_FSMC_RS);
|
||||
|
||||
HAL_SRAM_Init(&SRAMx, &Timing, &ExtTiming);
|
||||
|
||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||
|
||||
#ifdef STM32F1xx
|
||||
DMAtx.Instance = DMA2_Channel1;
|
||||
#elif defined(STM32F4xx)
|
||||
DMAtx.Instance = DMA2_Stream0;
|
||||
DMAtx.Init.Channel = DMA_CHANNEL_0;
|
||||
DMAtx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
||||
DMAtx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
||||
DMAtx.Init.MemBurst = DMA_MBURST_SINGLE;
|
||||
DMAtx.Init.PeriphBurst = DMA_PBURST_SINGLE;
|
||||
#endif
|
||||
|
||||
DMAtx.Init.Direction = DMA_MEMORY_TO_MEMORY;
|
||||
DMAtx.Init.MemInc = DMA_MINC_DISABLE;
|
||||
DMAtx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
|
||||
DMAtx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
|
||||
DMAtx.Init.Mode = DMA_NORMAL;
|
||||
DMAtx.Init.Priority = DMA_PRIORITY_HIGH;
|
||||
|
||||
LCD = (LCD_CONTROLLER_TypeDef *)controllerAddress;
|
||||
}
|
||||
|
||||
uint32_t TFT_FSMC::GetID() {
|
||||
uint32_t id;
|
||||
WriteReg(0);
|
||||
id = LCD->RAM;
|
||||
|
||||
if (id == 0)
|
||||
id = ReadID(LCD_READ_ID);
|
||||
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
|
||||
id = ReadID(LCD_READ_ID4);
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t TFT_FSMC::ReadID(tft_data_t Reg) {
|
||||
uint32_t id;
|
||||
WriteReg(Reg);
|
||||
id = LCD->RAM; // dummy read
|
||||
id = Reg << 24;
|
||||
id |= (LCD->RAM & 0x00FF) << 16;
|
||||
id |= (LCD->RAM & 0x00FF) << 8;
|
||||
id |= LCD->RAM & 0x00FF;
|
||||
return id;
|
||||
}
|
||||
|
||||
bool TFT_FSMC::isBusy() {
|
||||
#ifdef STM32F1xx
|
||||
#define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CCR & DMA_CCR_EN)
|
||||
#define __IS_DMA_CONFIGURED(__HANDLE__) ((__HANDLE__)->Instance->CPAR != 0)
|
||||
#elif defined(STM32F4xx)
|
||||
#define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CR & DMA_SxCR_EN)
|
||||
#define __IS_DMA_CONFIGURED(__HANDLE__) ((__HANDLE__)->Instance->PAR != 0)
|
||||
#endif
|
||||
|
||||
if (!__IS_DMA_CONFIGURED(&DMAtx)) return false;
|
||||
|
||||
// Check if DMA transfer error or transfer complete flags are set
|
||||
if ((__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx)) == 0) && (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx)) == 0)) return true;
|
||||
|
||||
__DSB();
|
||||
Abort();
|
||||
return false;
|
||||
}
|
||||
|
||||
void TFT_FSMC::Abort() {
|
||||
HAL_DMA_Abort(&DMAtx); // Abort DMA transfer if any
|
||||
HAL_DMA_DeInit(&DMAtx); // Deconfigure DMA
|
||||
}
|
||||
|
||||
void TFT_FSMC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
|
||||
DMAtx.Init.PeriphInc = MemoryIncrease;
|
||||
HAL_DMA_Init(&DMAtx);
|
||||
HAL_DMA_Start(&DMAtx, (uint32_t)Data, (uint32_t)&(LCD->RAM), Count);
|
||||
}
|
||||
|
||||
void TFT_FSMC::Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
|
||||
DMAtx.Init.PeriphInc = MemoryIncrease;
|
||||
HAL_DMA_Init(&DMAtx);
|
||||
DataTransferBegin();
|
||||
HAL_DMA_Start(&DMAtx, (uint32_t)Data, (uint32_t)&(LCD->RAM), Count);
|
||||
HAL_DMA_PollForTransfer(&DMAtx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
|
||||
Abort();
|
||||
}
|
||||
|
||||
#endif // HAS_FSMC_TFT
|
||||
#endif // HAL_STM32
|
@ -0,0 +1,174 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#ifdef STM32F1xx
|
||||
#include "stm32f1xx_hal.h"
|
||||
#elif defined(STM32F4xx)
|
||||
#include "stm32f4xx_hal.h"
|
||||
#else
|
||||
#error "FSMC TFT is currently only supported on STM32F1 and STM32F4 hardware."
|
||||
#endif
|
||||
|
||||
#ifndef LCD_READ_ID
|
||||
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
|
||||
#endif
|
||||
#ifndef LCD_READ_ID4
|
||||
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
|
||||
#endif
|
||||
|
||||
#define DATASIZE_8BIT SPI_DATASIZE_8BIT
|
||||
#define DATASIZE_16BIT SPI_DATASIZE_16BIT
|
||||
#define TFT_IO_DRIVER TFT_FSMC
|
||||
#define DMA_MAX_SIZE 0xFFFF
|
||||
|
||||
#define TFT_DATASIZE TERN(TFT_INTERFACE_FSMC_8BIT, DATASIZE_8BIT, DATASIZE_16BIT)
|
||||
typedef TERN(TFT_INTERFACE_FSMC_8BIT, uint8_t, uint16_t) tft_data_t;
|
||||
|
||||
typedef struct {
|
||||
__IO tft_data_t REG;
|
||||
__IO tft_data_t RAM;
|
||||
} LCD_CONTROLLER_TypeDef;
|
||||
|
||||
class TFT_FSMC {
|
||||
private:
|
||||
static SRAM_HandleTypeDef SRAMx;
|
||||
static DMA_HandleTypeDef DMAtx;
|
||||
|
||||
static LCD_CONTROLLER_TypeDef *LCD;
|
||||
|
||||
static uint32_t ReadID(tft_data_t Reg);
|
||||
static void Transmit(tft_data_t Data) { LCD->RAM = Data; __DSB(); }
|
||||
static void Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
|
||||
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static uint32_t GetID();
|
||||
static bool isBusy();
|
||||
static void Abort();
|
||||
|
||||
static void DataTransferBegin(uint16_t DataWidth = TFT_DATASIZE) {}
|
||||
static void DataTransferEnd() {};
|
||||
|
||||
static void WriteData(uint16_t Data) { Transmit(tft_data_t(Data)); }
|
||||
static void WriteReg(uint16_t Reg) { LCD->REG = tft_data_t(Reg); __DSB(); }
|
||||
|
||||
static void WriteSequence_DMA(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_ENABLE, Data, Count); }
|
||||
static void WriteMultiple_DMA(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_PINC_DISABLE, &Data, Count); }
|
||||
|
||||
static void WriteSequence(uint16_t *Data, uint16_t Count) { Transmit(DMA_PINC_ENABLE, Data, Count); }
|
||||
static void WriteMultiple(uint16_t Color, uint32_t Count) {
|
||||
while (Count > 0) {
|
||||
Transmit(DMA_MINC_DISABLE, &Color, Count > DMA_MAX_SIZE ? DMA_MAX_SIZE : Count);
|
||||
Count = Count > DMA_MAX_SIZE ? Count - DMA_MAX_SIZE : 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef STM32F1xx
|
||||
#define FSMC_PIN_DATA STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, AFIO_NONE)
|
||||
#elif defined(STM32F4xx)
|
||||
#define FSMC_PIN_DATA STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_FSMC)
|
||||
#define FSMC_BANK1_1 0x60000000U
|
||||
#define FSMC_BANK1_2 0x64000000U
|
||||
#define FSMC_BANK1_3 0x68000000U
|
||||
#define FSMC_BANK1_4 0x6C000000U
|
||||
#else
|
||||
#error No configuration for this MCU
|
||||
#endif
|
||||
|
||||
const PinMap PinMap_FSMC[] = {
|
||||
{PD_14, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D00
|
||||
{PD_15, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D01
|
||||
{PD_0, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D02
|
||||
{PD_1, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D03
|
||||
{PE_7, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D04
|
||||
{PE_8, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D05
|
||||
{PE_9, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D06
|
||||
{PE_10, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D07
|
||||
#if DISABLED(TFT_INTERFACE_FSMC_8BIT)
|
||||
{PE_11, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D08
|
||||
{PE_12, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D09
|
||||
{PE_13, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D10
|
||||
{PE_14, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D11
|
||||
{PE_15, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D12
|
||||
{PD_8, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D13
|
||||
{PD_9, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D14
|
||||
{PD_10, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D15
|
||||
#endif
|
||||
{PD_4, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_NOE
|
||||
{PD_5, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_NWE
|
||||
{NC, NP, 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_FSMC_CS[] = {
|
||||
{PD_7, (void *)FSMC_NORSRAM_BANK1, FSMC_PIN_DATA}, // FSMC_NE1
|
||||
#ifdef PF0
|
||||
{PG_9, (void *)FSMC_NORSRAM_BANK2, FSMC_PIN_DATA}, // FSMC_NE2
|
||||
{PG_10, (void *)FSMC_NORSRAM_BANK3, FSMC_PIN_DATA}, // FSMC_NE3
|
||||
{PG_12, (void *)FSMC_NORSRAM_BANK4, FSMC_PIN_DATA}, // FSMC_NE4
|
||||
#endif
|
||||
{NC, NP, 0}
|
||||
};
|
||||
|
||||
#if ENABLED(TFT_INTERFACE_FSMC_8BIT)
|
||||
#define FSMC_RS(A) (void *)((2 << (A-1)) - 1)
|
||||
#else
|
||||
#define FSMC_RS(A) (void *)((2 << A) - 2)
|
||||
#endif
|
||||
|
||||
const PinMap PinMap_FSMC_RS[] = {
|
||||
#ifdef PF0
|
||||
{PF_0, FSMC_RS( 0), FSMC_PIN_DATA}, // FSMC_A0
|
||||
{PF_1, FSMC_RS( 1), FSMC_PIN_DATA}, // FSMC_A1
|
||||
{PF_2, FSMC_RS( 2), FSMC_PIN_DATA}, // FSMC_A2
|
||||
{PF_3, FSMC_RS( 3), FSMC_PIN_DATA}, // FSMC_A3
|
||||
{PF_4, FSMC_RS( 4), FSMC_PIN_DATA}, // FSMC_A4
|
||||
{PF_5, FSMC_RS( 5), FSMC_PIN_DATA}, // FSMC_A5
|
||||
{PF_12, FSMC_RS( 6), FSMC_PIN_DATA}, // FSMC_A6
|
||||
{PF_13, FSMC_RS( 7), FSMC_PIN_DATA}, // FSMC_A7
|
||||
{PF_14, FSMC_RS( 8), FSMC_PIN_DATA}, // FSMC_A8
|
||||
{PF_15, FSMC_RS( 9), FSMC_PIN_DATA}, // FSMC_A9
|
||||
{PG_0, FSMC_RS(10), FSMC_PIN_DATA}, // FSMC_A10
|
||||
{PG_1, FSMC_RS(11), FSMC_PIN_DATA}, // FSMC_A11
|
||||
{PG_2, FSMC_RS(12), FSMC_PIN_DATA}, // FSMC_A12
|
||||
{PG_3, FSMC_RS(13), FSMC_PIN_DATA}, // FSMC_A13
|
||||
{PG_4, FSMC_RS(14), FSMC_PIN_DATA}, // FSMC_A14
|
||||
{PG_5, FSMC_RS(15), FSMC_PIN_DATA}, // FSMC_A15
|
||||
#endif
|
||||
{PD_11, FSMC_RS(16), FSMC_PIN_DATA}, // FSMC_A16
|
||||
{PD_12, FSMC_RS(17), FSMC_PIN_DATA}, // FSMC_A17
|
||||
{PD_13, FSMC_RS(18), FSMC_PIN_DATA}, // FSMC_A18
|
||||
{PE_3, FSMC_RS(19), FSMC_PIN_DATA}, // FSMC_A19
|
||||
{PE_4, FSMC_RS(20), FSMC_PIN_DATA}, // FSMC_A20
|
||||
{PE_5, FSMC_RS(21), FSMC_PIN_DATA}, // FSMC_A21
|
||||
{PE_6, FSMC_RS(22), FSMC_PIN_DATA}, // FSMC_A22
|
||||
{PE_2, FSMC_RS(23), FSMC_PIN_DATA}, // FSMC_A23
|
||||
#ifdef PF0
|
||||
{PG_13, FSMC_RS(24), FSMC_PIN_DATA}, // FSMC_A24
|
||||
{PG_14, FSMC_RS(25), FSMC_PIN_DATA}, // FSMC_A25
|
||||
#endif
|
||||
{NC, NP, 0}
|
||||
};
|
@ -0,0 +1,389 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "../../platforms.h"
|
||||
|
||||
#ifdef HAL_STM32
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_LTDC_TFT
|
||||
|
||||
#include "tft_ltdc.h"
|
||||
#include "pinconfig.h"
|
||||
|
||||
#define FRAME_BUFFER_ADDRESS 0XC0000000 // SDRAM address
|
||||
|
||||
#define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
|
||||
#define REFRESH_COUNT ((uint32_t)0x02A5) // SDRAM refresh counter
|
||||
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
|
||||
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
|
||||
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
|
||||
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
|
||||
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
|
||||
|
||||
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command) {
|
||||
|
||||
__IO uint32_t tmpmrd =0;
|
||||
/* Step 1: Configure a clock configuration enable command */
|
||||
Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
|
||||
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
|
||||
Command->AutoRefreshNumber = 1;
|
||||
Command->ModeRegisterDefinition = 0;
|
||||
/* Send the command */
|
||||
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
|
||||
|
||||
/* Step 2: Insert 100 us minimum delay */
|
||||
/* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
|
||||
HAL_Delay(1);
|
||||
|
||||
/* Step 3: Configure a PALL (precharge all) command */
|
||||
Command->CommandMode = FMC_SDRAM_CMD_PALL;
|
||||
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
|
||||
Command->AutoRefreshNumber = 1;
|
||||
Command->ModeRegisterDefinition = 0;
|
||||
/* Send the command */
|
||||
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
|
||||
|
||||
/* Step 4 : Configure a Auto-Refresh command */
|
||||
Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
|
||||
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
|
||||
Command->AutoRefreshNumber = 8;
|
||||
Command->ModeRegisterDefinition = 0;
|
||||
/* Send the command */
|
||||
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
|
||||
|
||||
/* Step 5: Program the external memory mode register */
|
||||
tmpmrd = (uint32_t)(SDRAM_MODEREG_BURST_LENGTH_1 |
|
||||
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
|
||||
SDRAM_MODEREG_CAS_LATENCY_2 |
|
||||
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
|
||||
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE);
|
||||
|
||||
Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
|
||||
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
|
||||
Command->AutoRefreshNumber = 1;
|
||||
Command->ModeRegisterDefinition = tmpmrd;
|
||||
/* Send the command */
|
||||
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
|
||||
|
||||
/* Step 6: Set the refresh rate counter */
|
||||
/* Set the device refresh rate */
|
||||
HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
|
||||
}
|
||||
|
||||
void SDRAM_Config() {
|
||||
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
__HAL_RCC_FMC_CLK_ENABLE();
|
||||
|
||||
SDRAM_HandleTypeDef hsdram;
|
||||
FMC_SDRAM_TimingTypeDef SDRAM_Timing;
|
||||
FMC_SDRAM_CommandTypeDef command;
|
||||
|
||||
/* Configure the SDRAM device */
|
||||
hsdram.Instance = FMC_SDRAM_DEVICE;
|
||||
hsdram.Init.SDBank = FMC_SDRAM_BANK1;
|
||||
hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
|
||||
hsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
|
||||
hsdram.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
|
||||
hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
|
||||
hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
|
||||
hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
|
||||
hsdram.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
|
||||
hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
|
||||
hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
|
||||
|
||||
/* Timing configuration for 100Mhz as SDRAM clock frequency (System clock is up to 200Mhz) */
|
||||
SDRAM_Timing.LoadToActiveDelay = 2;
|
||||
SDRAM_Timing.ExitSelfRefreshDelay = 8;
|
||||
SDRAM_Timing.SelfRefreshTime = 6;
|
||||
SDRAM_Timing.RowCycleDelay = 6;
|
||||
SDRAM_Timing.WriteRecoveryTime = 2;
|
||||
SDRAM_Timing.RPDelay = 2;
|
||||
SDRAM_Timing.RCDDelay = 2;
|
||||
|
||||
/* Initialize the SDRAM controller */
|
||||
if (HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
|
||||
{
|
||||
/* Initialization Error */
|
||||
}
|
||||
|
||||
/* Program the SDRAM external device */
|
||||
SDRAM_Initialization_Sequence(&hsdram, &command);
|
||||
}
|
||||
|
||||
void LTDC_Config() {
|
||||
|
||||
__HAL_RCC_LTDC_CLK_ENABLE();
|
||||
__HAL_RCC_DMA2D_CLK_ENABLE();
|
||||
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
|
||||
|
||||
/* The PLL3R is configured to provide the LTDC PCLK clock */
|
||||
/* PLL3_VCO Input = HSE_VALUE / PLL3M = 25Mhz / 5 = 5 Mhz */
|
||||
/* PLL3_VCO Output = PLL3_VCO Input * PLL3N = 5Mhz * 160 = 800 Mhz */
|
||||
/* PLLLCDCLK = PLL3_VCO Output/PLL3R = 800Mhz / 16 = 50Mhz */
|
||||
/* LTDC clock frequency = PLLLCDCLK = 50 Mhz */
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
|
||||
PeriphClkInitStruct.PLL3.PLL3M = 5;
|
||||
PeriphClkInitStruct.PLL3.PLL3N = 160;
|
||||
PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
|
||||
PeriphClkInitStruct.PLL3.PLL3P = 2;
|
||||
PeriphClkInitStruct.PLL3.PLL3Q = 2;
|
||||
PeriphClkInitStruct.PLL3.PLL3R = (800 / LTDC_LCD_CLK);
|
||||
PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
|
||||
PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
|
||||
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
||||
|
||||
LTDC_HandleTypeDef hltdc_F;
|
||||
LTDC_LayerCfgTypeDef pLayerCfg;
|
||||
|
||||
/* LTDC Initialization -------------------------------------------------------*/
|
||||
|
||||
/* Polarity configuration */
|
||||
/* Initialize the horizontal synchronization polarity as active low */
|
||||
hltdc_F.Init.HSPolarity = LTDC_HSPOLARITY_AL;
|
||||
/* Initialize the vertical synchronization polarity as active low */
|
||||
hltdc_F.Init.VSPolarity = LTDC_VSPOLARITY_AL;
|
||||
/* Initialize the data enable polarity as active low */
|
||||
hltdc_F.Init.DEPolarity = LTDC_DEPOLARITY_AL;
|
||||
/* Initialize the pixel clock polarity as input pixel clock */
|
||||
hltdc_F.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
|
||||
|
||||
/* Timing configuration */
|
||||
hltdc_F.Init.HorizontalSync = (LTDC_LCD_HSYNC - 1);
|
||||
hltdc_F.Init.VerticalSync = (LTDC_LCD_VSYNC - 1);
|
||||
hltdc_F.Init.AccumulatedHBP = (LTDC_LCD_HSYNC + LTDC_LCD_HBP - 1);
|
||||
hltdc_F.Init.AccumulatedVBP = (LTDC_LCD_VSYNC + LTDC_LCD_VBP - 1);
|
||||
hltdc_F.Init.AccumulatedActiveH = (TFT_HEIGHT + LTDC_LCD_VSYNC + LTDC_LCD_VBP - 1);
|
||||
hltdc_F.Init.AccumulatedActiveW = (TFT_WIDTH + LTDC_LCD_HSYNC + LTDC_LCD_HBP - 1);
|
||||
hltdc_F.Init.TotalHeigh = (TFT_HEIGHT + LTDC_LCD_VSYNC + LTDC_LCD_VBP + LTDC_LCD_VFP - 1);
|
||||
hltdc_F.Init.TotalWidth = (TFT_WIDTH + LTDC_LCD_HSYNC + LTDC_LCD_HBP + LTDC_LCD_HFP - 1);
|
||||
|
||||
/* Configure R,G,B component values for LCD background color : all black background */
|
||||
hltdc_F.Init.Backcolor.Blue = 0;
|
||||
hltdc_F.Init.Backcolor.Green = 0;
|
||||
hltdc_F.Init.Backcolor.Red = 0;
|
||||
|
||||
hltdc_F.Instance = LTDC;
|
||||
|
||||
/* Layer0 Configuration ------------------------------------------------------*/
|
||||
|
||||
/* Windowing configuration */
|
||||
pLayerCfg.WindowX0 = 0;
|
||||
pLayerCfg.WindowX1 = TFT_WIDTH;
|
||||
pLayerCfg.WindowY0 = 0;
|
||||
pLayerCfg.WindowY1 = TFT_HEIGHT;
|
||||
|
||||
/* Pixel Format configuration*/
|
||||
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
|
||||
|
||||
/* Start Address configuration : frame buffer is located at SDRAM memory */
|
||||
pLayerCfg.FBStartAdress = (uint32_t)(FRAME_BUFFER_ADDRESS);
|
||||
|
||||
/* Alpha constant (255 == totally opaque) */
|
||||
pLayerCfg.Alpha = 255;
|
||||
|
||||
/* Default Color configuration (configure A,R,G,B component values) : no background color */
|
||||
pLayerCfg.Alpha0 = 0; /* fully transparent */
|
||||
pLayerCfg.Backcolor.Blue = 0;
|
||||
pLayerCfg.Backcolor.Green = 0;
|
||||
pLayerCfg.Backcolor.Red = 0;
|
||||
|
||||
/* Configure blending factors */
|
||||
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
|
||||
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
|
||||
|
||||
/* Configure the number of lines and number of pixels per line */
|
||||
pLayerCfg.ImageWidth = TFT_WIDTH;
|
||||
pLayerCfg.ImageHeight = TFT_HEIGHT;
|
||||
|
||||
/* Configure the LTDC */
|
||||
if (HAL_LTDC_Init(&hltdc_F) != HAL_OK)
|
||||
{
|
||||
/* Initialization Error */
|
||||
}
|
||||
|
||||
/* Configure the Layer*/
|
||||
if (HAL_LTDC_ConfigLayer(&hltdc_F, &pLayerCfg, 0) != HAL_OK)
|
||||
{
|
||||
/* Initialization Error */
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t TFT_LTDC::x_min = 0;
|
||||
uint16_t TFT_LTDC::x_max = 0;
|
||||
uint16_t TFT_LTDC::y_min = 0;
|
||||
uint16_t TFT_LTDC::y_max = 0;
|
||||
uint16_t TFT_LTDC::x_cur = 0;
|
||||
uint16_t TFT_LTDC::y_cur = 0;
|
||||
uint8_t TFT_LTDC::reg = 0;
|
||||
volatile uint16_t* TFT_LTDC::framebuffer = (volatile uint16_t* )FRAME_BUFFER_ADDRESS;
|
||||
|
||||
void TFT_LTDC::Init() {
|
||||
|
||||
// SDRAM pins init
|
||||
for (uint16_t i = 0; PinMap_SDRAM[i].pin != NC; i++)
|
||||
pinmap_pinout(PinMap_SDRAM[i].pin, PinMap_SDRAM);
|
||||
|
||||
// SDRAM peripheral config
|
||||
SDRAM_Config();
|
||||
|
||||
// LTDC pins init
|
||||
for (uint16_t i = 0; PinMap_LTDC[i].pin != NC; i++)
|
||||
pinmap_pinout(PinMap_LTDC[i].pin, PinMap_LTDC);
|
||||
|
||||
// LTDC peripheral config
|
||||
LTDC_Config();
|
||||
}
|
||||
|
||||
uint32_t TFT_LTDC::GetID() {
|
||||
return 0xABAB;
|
||||
}
|
||||
|
||||
uint32_t TFT_LTDC::ReadID(tft_data_t Reg) {
|
||||
return 0xABAB;
|
||||
}
|
||||
|
||||
bool TFT_LTDC::isBusy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t TFT_LTDC::ReadPoint(uint16_t x, uint16_t y) {
|
||||
return framebuffer[(TFT_WIDTH * y) + x];
|
||||
}
|
||||
|
||||
void TFT_LTDC::DrawPoint(uint16_t x, uint16_t y, uint16_t color) {
|
||||
framebuffer[(TFT_WIDTH * y) + x] = color;
|
||||
}
|
||||
|
||||
void TFT_LTDC::DrawRect(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color) {
|
||||
|
||||
if (sx == ex || sy == ey) return;
|
||||
|
||||
uint16_t offline = TFT_WIDTH - (ex - sx);
|
||||
uint32_t addr = (uint32_t)&framebuffer[(TFT_WIDTH * sy) + sx];
|
||||
|
||||
CBI(DMA2D->CR, 0);
|
||||
DMA2D->CR = 3 << 16;
|
||||
DMA2D->OPFCCR = 0X02;
|
||||
DMA2D->OOR = offline;
|
||||
DMA2D->OMAR = addr;
|
||||
DMA2D->NLR = (ey - sy) | ((ex - sx) << 16);
|
||||
DMA2D->OCOLR = color;
|
||||
SBI(DMA2D->CR, 0);
|
||||
|
||||
uint32_t timeout = 0;
|
||||
while (!TEST(DMA2D->ISR, 1)) {
|
||||
timeout++;
|
||||
if (timeout > 0x1FFFFF) break;
|
||||
}
|
||||
SBI(DMA2D->IFCR, 1);
|
||||
}
|
||||
|
||||
void TFT_LTDC::DrawImage(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *colors) {
|
||||
|
||||
if (sx == ex || sy == ey) return;
|
||||
|
||||
uint16_t offline = TFT_WIDTH - (ex - sx);
|
||||
uint32_t addr = (uint32_t)&framebuffer[(TFT_WIDTH * sy) + sx];
|
||||
|
||||
CBI(DMA2D->CR, 0);
|
||||
DMA2D->CR = 0 << 16;
|
||||
DMA2D->FGPFCCR = 0X02;
|
||||
DMA2D->FGOR = 0;
|
||||
DMA2D->OOR = offline;
|
||||
DMA2D->FGMAR = (uint32_t)colors;
|
||||
DMA2D->OMAR = addr;
|
||||
DMA2D->NLR = (ey - sy) | ((ex - sx) << 16);
|
||||
SBI(DMA2D->CR, 0);
|
||||
|
||||
uint32_t timeout = 0;
|
||||
while (!TEST(DMA2D->ISR, 1)) {
|
||||
timeout++;
|
||||
if (timeout > 0x1FFFFF) break;
|
||||
}
|
||||
SBI(DMA2D->IFCR, 1);
|
||||
}
|
||||
|
||||
void TFT_LTDC::WriteData(uint16_t data) {
|
||||
switch (reg) {
|
||||
case 0x01: x_cur = x_min = data; return;
|
||||
case 0x02: x_max = data; return;
|
||||
case 0x03: y_cur = y_min = data; return;
|
||||
case 0x04: y_max = data; return;
|
||||
}
|
||||
Transmit(data);
|
||||
}
|
||||
|
||||
void TFT_LTDC::Transmit(tft_data_t Data) {
|
||||
DrawPoint(x_cur, y_cur, Data);
|
||||
x_cur++;
|
||||
if (x_cur > x_max) {
|
||||
x_cur = x_min;
|
||||
y_cur++;
|
||||
if (y_cur > y_max) y_cur = y_min;
|
||||
}
|
||||
}
|
||||
|
||||
void TFT_LTDC::WriteReg(uint16_t Reg) {
|
||||
reg = Reg;
|
||||
}
|
||||
|
||||
void TFT_LTDC::Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
|
||||
|
||||
while (x_cur != x_min && Count) {
|
||||
Transmit(*Data);
|
||||
if (MemoryIncrease == DMA_PINC_ENABLE) Data++;
|
||||
Count--;
|
||||
}
|
||||
|
||||
uint16_t width = x_max - x_min + 1;
|
||||
uint16_t height = Count / width;
|
||||
uint16_t x_end_cnt = Count - (width * height);
|
||||
|
||||
if (height) {
|
||||
if (MemoryIncrease == DMA_PINC_ENABLE) {
|
||||
DrawImage(x_min, y_cur, x_min + width, y_cur + height, Data);
|
||||
Data += width * height;
|
||||
}
|
||||
else
|
||||
DrawRect(x_min, y_cur, x_min + width, y_cur + height, *Data);
|
||||
y_cur += height;
|
||||
}
|
||||
|
||||
while (x_end_cnt) {
|
||||
Transmit(*Data);
|
||||
if (MemoryIncrease == DMA_PINC_ENABLE) Data++;
|
||||
x_end_cnt--;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_LTDC_TFT
|
||||
#endif // HAL_STM32
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue