Revert "移植 IQ.Pilot panda 子系统"
This reverts commit 237816d8f9.
Reason: IQ.Pilot panda 子系统依赖 cereal::IQCarParams 和 iqState
service,在 openpilot 标准 cereal 中不存在,设备上编译失败。
回退到上一个正常编译版本。panda 固件层(F4/H7)已确认编译通过,
保留固件编译修复的成果。
This commit is contained in:
@@ -95,5 +95,3 @@ SKILL.md
|
||||
!.idea/customTargets.xml
|
||||
!.idea/tools/*
|
||||
!.run/*
|
||||
panda.bak.20260603154803/
|
||||
*.bak.*
|
||||
|
||||
@@ -37,3 +37,6 @@ tests/safety/coverage.info
|
||||
*.profraw
|
||||
*.profdata
|
||||
mull.yml
|
||||
|
||||
.claude/
|
||||
TASK.md
|
||||
|
||||
+2
-1
@@ -8,7 +8,8 @@ WORKDIR $WORKDIR
|
||||
|
||||
# deps install
|
||||
COPY pyproject.toml __init__.py setup.sh $WORKDIR
|
||||
RUN mkdir -p $WORKDIR/python/ && touch $WORKDIR/__init__.py
|
||||
RUN mkdir -p $WORKDIR/python/ $WORKDIR/board/body/ $WORKDIR/board/jungle/ && \
|
||||
touch $WORKDIR/__init__.py $WORKDIR/board/__init__.py $WORKDIR/board/body/__init__.py $WORKDIR/board/jungle/__init__.py
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends sudo && DEBIAN_FRONTEND=noninteractive $WORKDIR/setup.sh
|
||||
|
||||
# second pass for the opendbc moving tag
|
||||
|
||||
Vendored
+11
-16
@@ -6,7 +6,7 @@ def docker_run(String step_label, int timeout_mins, String cmd) {
|
||||
--volume /var/run/dbus:/var/run/dbus \
|
||||
--net host \
|
||||
${env.DOCKER_IMAGE_TAG} \
|
||||
bash -c 'scons -j8 && ${cmd}'", \
|
||||
bash -c 'scons && ${cmd}'", \
|
||||
label: step_label
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ def docker_run(String step_label, int timeout_mins, String cmd) {
|
||||
def phone(String ip, String step_label, String cmd) {
|
||||
withCredentials([file(credentialsId: 'id_rsa', variable: 'key_file')]) {
|
||||
def ssh_cmd = """
|
||||
ssh -tt -o StrictHostKeyChecking=no -i ${key_file} 'comma@${ip}' /usr/bin/bash <<'END'
|
||||
ssh -tt -o StrictHostKeyChecking=no -o ConnectTimeout=30 -o ConnectionAttempts=3 -o ServerAliveInterval=10 -o ServerAliveCountMax=3 -i ${key_file} 'comma@${ip}' /usr/bin/bash <<'END'
|
||||
|
||||
set -e
|
||||
|
||||
@@ -51,7 +51,11 @@ END"""
|
||||
def phone_steps(String device_type, steps) {
|
||||
lock(resource: "", label: device_type, inversePrecedence: true, variable: 'device_ip', quantity: 1) {
|
||||
timeout(time: 20, unit: 'MINUTES') {
|
||||
phone(device_ip, "git checkout", readFile("tests/setup_device_ci.sh"),)
|
||||
retry (3) {
|
||||
def date = sh(script: 'date', returnStdout: true).trim()
|
||||
phone(device_ip, "set time", "date -s '${date}'")
|
||||
phone(device_ip, "git checkout", readFile("tests/setup_device_ci.sh"))
|
||||
}
|
||||
steps.each { item ->
|
||||
phone(device_ip, item[0], item[1])
|
||||
}
|
||||
@@ -107,10 +111,10 @@ pipeline {
|
||||
agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } }
|
||||
steps {
|
||||
phone_steps("panda-cuatro", [
|
||||
["build", "scons -j4"],
|
||||
["build", "scons"],
|
||||
["flash", "cd scripts/ && ./reflash_internal_panda.py"],
|
||||
["flash jungle", "cd board/jungle && ./flash.py --all"],
|
||||
["test", "cd tests/hitl && pytest --durations=0 2*.py [5-9]*.py"],
|
||||
["test", "cd tests/hitl && pytest -o 'addopts=' --durations=0 2*.py [5-9]*.py"],
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -119,23 +123,14 @@ pipeline {
|
||||
agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } }
|
||||
steps {
|
||||
phone_steps("panda-tres", [
|
||||
["build", "scons -j4"],
|
||||
["build", "scons"],
|
||||
["flash", "cd scripts/ && ./reflash_internal_panda.py"],
|
||||
["flash jungle", "cd board/jungle && ./flash.py --all"],
|
||||
["test", "cd tests/hitl && pytest --durations=0 2*.py [5-9]*.py"],
|
||||
["test", "cd tests/hitl && pytest -o 'addopts=' --durations=0 2*.py [5-9]*.py"],
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
stage('bootkick tests') {
|
||||
steps {
|
||||
script {
|
||||
docker_run("test", 10, "pytest ./tests/som/test_bootkick.py")
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-88
@@ -1,98 +1,21 @@
|
||||
# IQ.Lvbs (Panda) License v0.1a
|
||||
# Custom MIT License
|
||||
|
||||
Copyright (c) 2026 IQ.Lvbs LLC, a part of Project Teal Lvbs Inc. All Rights Reserved.
|
||||
Copyright (c) 2024, Haibin Wen, SUNNYPILOT LLC
|
||||
|
||||
DEFINITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to view and modify the Software, subject to the following conditions:
|
||||
|
||||
"Software" refers to IQ.Pilot, konn3kt, and all associated source code,
|
||||
documentation, and assets owned by the Copyright Holder.
|
||||
1. **Permission Required**: Permission Required for Commercial, For-Profit, or Closed Source Use: Use of the Software, in whole or in part, for any commercial purposes, for-profit projects, or in closed source projects requires explicit written permission from the original author(s).
|
||||
|
||||
"Open Components" refers to portions of the Software explicitly marked as
|
||||
open source.
|
||||
2. **Redistribution**: Any redistribution of the Software, modified or unmodified, must retain this license notice and the following acknowledgment:
|
||||
"This software is licensed under a custom license requiring permission for use."
|
||||
|
||||
"Proprietary Components" refers to all portions of the Software not made
|
||||
available to the public in source form.
|
||||
3. **Visibility**: Any project that uses the Software must visibly mention the following acknowledgment:
|
||||
"This project uses software from Haibin Wen and SUNNYPILOT LLC and is licensed under a custom license requiring permission for use."
|
||||
|
||||
"Copyright Holder" refers to IQ.Lvbs LLC, a part of Project Teal Lvbs Inc.
|
||||
4. **No Warranty**: 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.
|
||||
|
||||
GRANT OF LICENSE
|
||||
|
||||
Subject to the terms of this license, you are granted a limited,
|
||||
non-exclusive, revocable license to:
|
||||
|
||||
1. View, study, and learn from the Open Components
|
||||
2. Modify the Open Components for personal, internal, or open-source public use
|
||||
3. Run the Software for personal, non-commercial purposes
|
||||
|
||||
RESTRICTIONS
|
||||
|
||||
You may NOT:
|
||||
|
||||
1. Claim ownership of any part of the Software, excluding your own
|
||||
modifications that do not incorporate Proprietary Components.
|
||||
|
||||
2. Reverse engineer, decompile, disassemble, or in any way attempt to
|
||||
circumvent the obfuscation of the Proprietary Components.
|
||||
|
||||
3. Use the Software or any derivative for commercial purposes without
|
||||
explicit written permission from the Copyright Holder.
|
||||
|
||||
4. Remove or alter any copyright notices or this license.
|
||||
|
||||
5. Sublicense, sell, or transfer rights to the Software.
|
||||
|
||||
6. Use the Software and/or its source code to compete with or create a
|
||||
substantially similar product.
|
||||
|
||||
7. Use the Software in closed source software not licensed by IQ.Lvbs LLC.
|
||||
|
||||
CONSEQUENCES OF VIOLATION
|
||||
|
||||
In the event any Restriction is violated, any product created using inspiration from, or source code from, IQ.Pilot or Konn3kt shall be subject to a licensing fee determined solely by the Copyright Holder. Additionally, the violating party hereby grants IQ.Lvbs LLC an exclusive, irrevocable, worldwide, royalty-free license to use any and all assets from the infringing product on IQ.Lvbs webpages, advertising materials, and in any other manner IQ.Lvbs sees fit.
|
||||
|
||||
OWNERSHIP
|
||||
|
||||
All rights, title, and interest in the Software remain exclusively with the
|
||||
Copyright Holder. Any modifications, improvements, or derivative works you
|
||||
create based on the Software are owned by the Copyright Holder. By
|
||||
contributing modifications, you irrevocably assign all rights to the
|
||||
Copyright Holder.
|
||||
|
||||
PROPRIETARY COMPONENTS
|
||||
|
||||
The Proprietary Components are provided in binary or obfuscated form only.
|
||||
Reverse engineering, decompilation, or disassembly of Proprietary Components
|
||||
is strictly prohibited. Violation of this provision entitles IQ.Lvbs LLC to
|
||||
pursue all available legal remedies to protect its intellectual property and
|
||||
trade secrets.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT
|
||||
HOLDER DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||
NON-INFRINGEMENT.
|
||||
|
||||
LIMITATION OF LIABILITY
|
||||
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES, OR
|
||||
OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE. THE USER ACCEPTS FULL
|
||||
RESPONSIBILITY FOR ANY AND ALL LIABILITIES WHEN USING IQ.LVBS SOFTWARE.
|
||||
|
||||
TERMINATION
|
||||
|
||||
This license terminates automatically if you violate any of its terms. Upon
|
||||
termination, you must destroy all copies of the Software in your possession.
|
||||
|
||||
The Copyright Holder reserves the right to revoke this license at any time
|
||||
for any reason.
|
||||
|
||||
GOVERNING LAW
|
||||
|
||||
This license shall be governed by the laws of the State of Illinois, United
|
||||
States of America. Any disputes arising under this license shall be subject
|
||||
to the exclusive jurisdiction of the courts located in Henry County, Illinois.
|
||||
Contact sunnypilot Support <support@sunnypilot.ai> for permission requests.
|
||||
|
||||
---
|
||||
|
||||
For commercial licensing inquiries, contact: support@iqlvbs.com
|
||||
Haibin Wen, SUNNYPILOT LLC
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
# Welcome to panda
|
||||
|
||||
panda speaks CAN and CAN FD, and it runs on the [STM32H725](https://www.st.com/resource/en/reference_manual/rm0468-stm32h723733-stm32h725735-and-stm32h730-value-line-advanced-armbased-32bit-mcus-stmicroelectronics.pdf).
|
||||
|
||||
## Directory structure
|
||||
|
||||
```
|
||||
.
|
||||
├── board # Code that runs on the STM32
|
||||
├── python # Python userspace library for interfacing with the panda
|
||||
├── tests # Tests for panda
|
||||
├── scripts # Miscellaneous used for panda development and debugging
|
||||
├── examples # Example scripts for using a panda in a car
|
||||
```
|
||||
|
||||
## Safety Model
|
||||
|
||||
panda is compiled with vehicle-specific safety logic provided by [opendbc](https://github.com/commaai/opendbc). See details about the car safety models, safety testing, and code rigor in that repository.
|
||||
|
||||
## Code Rigor
|
||||
|
||||
The panda firmware is written for its use in conjunction with [openpilot](https://github.com/commaai/openpilot). The panda firmware, through its safety model, provides and enforces the
|
||||
[openpilot safety](https://github.com/commaai/openpilot/blob/master/docs/SAFETY.md). Due to its critical function, it's important that the application code rigor within the `board` folder is held to high standards.
|
||||
|
||||
These are the [CI regression tests](https://github.com/commaai/panda/actions) we have in place:
|
||||
* A generic static code analysis is performed by [cppcheck](https://github.com/danmar/cppcheck/).
|
||||
* In addition, [cppcheck](https://github.com/danmar/cppcheck/) has a specific addon to check for [MISRA C:2012](https://misra.org.uk/) violations. See [current coverage](https://github.com/commaai/panda/blob/master/tests/misra/coverage_table).
|
||||
* Compiler options are strict: the flags `-Wall -Wextra -Wstrict-prototypes -Werror` are enforced.
|
||||
* The [safety logic](https://github.com/commaai/panda/tree/master/opendbc/safety) is tested and verified by [unit tests](https://github.com/commaai/panda/tree/master/opendbc/safety/tests) for each supported car variant.
|
||||
to ensure that the behavior remains unchanged.
|
||||
* A hardware-in-the-loop test verifies panda's functionalities on all active panda variants, including:
|
||||
* additional safety model checks
|
||||
* compiling and flashing the bootstub and app code
|
||||
* receiving, sending, and forwarding CAN messages on all buses
|
||||
* CAN loopback and latency tests through SPI
|
||||
|
||||
The above tests are themselves tested by:
|
||||
* a [mutation test](tests/misra/test_mutation.py) on the MISRA coverage
|
||||
* a [mutation test]([tests/misra/test_mutation.py](https://github.com/commaai/opendbc/blob/master/opendbc/safety/tests/mutation.sh)) on the vehicle-specific safety logic
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
git clone https://github.com/commaai/panda.git
|
||||
cd panda
|
||||
|
||||
# setup your environment
|
||||
./setup.sh
|
||||
|
||||
# build fw + run the tests
|
||||
./test.sh
|
||||
```
|
||||
|
||||
See [the Panda class](https://github.com/commaai/panda/blob/master/python/__init__.py) for how to interact with the panda.
|
||||
|
||||
For example, to receive CAN messages:
|
||||
``` python
|
||||
>>> from panda import Panda
|
||||
>>> panda = Panda()
|
||||
>>> panda.can_recv()
|
||||
```
|
||||
And to send one on bus 0:
|
||||
``` python
|
||||
>>> from opendbc.car.structs import CarParams
|
||||
>>> panda.set_safety_mode(CarParams.SafetyModel.allOutput)
|
||||
>>> panda.can_send(0x1aa, b'message', 0)
|
||||
```
|
||||
Note that you may have to setup [udev rules](https://github.com/commaai/panda/tree/master/drivers/linux) for Linux, such as
|
||||
``` bash
|
||||
sudo tee /etc/udev/rules.d/11-panda.rules <<EOF
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="3801", ATTRS{idProduct}=="ddcc", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="3801", ATTRS{idProduct}=="ddee", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="bbaa", ATTRS{idProduct}=="ddcc", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="bbaa", ATTRS{idProduct}=="ddee", MODE="0666"
|
||||
EOF
|
||||
sudo udevadm control --reload-rules && sudo udevadm trigger
|
||||
```
|
||||
|
||||
The panda jungle uses different udev rules. See [the repo](https://github.com/commaai/panda_jungle#udev-rules) for instructions.
|
||||
|
||||
## Licensing
|
||||
|
||||
panda software is released under the MIT license unless otherwise specified.
|
||||
+18
-28
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import hashlib
|
||||
import opendbc
|
||||
import subprocess
|
||||
|
||||
@@ -14,7 +15,7 @@ if os.getenv("RELEASE"):
|
||||
assert os.path.exists(cert_fn), 'Certificate file not found. Please specify absolute path'
|
||||
else:
|
||||
BUILD_TYPE = "DEBUG"
|
||||
cert_fn = File("./certs/debug").srcnode().relpath
|
||||
cert_fn = File("./board/certs/debug").srcnode().relpath
|
||||
common_flags += ["-DALLOW_DEBUG"]
|
||||
|
||||
if os.getenv("DEBUG"):
|
||||
@@ -26,14 +27,14 @@ def objcopy(source, target, env, for_signature):
|
||||
def get_version(builder, build_type):
|
||||
try:
|
||||
git = subprocess.check_output(["git", "rev-parse", "--short=8", "HEAD"], encoding='utf8').strip()
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
except subprocess.CalledProcessError:
|
||||
git = "unknown"
|
||||
return f"{builder}-{git}-{build_type}"
|
||||
|
||||
def get_key_header(name):
|
||||
from Crypto.PublicKey import RSA
|
||||
|
||||
public_fn = File(f'./certs/{name}.pub').srcnode().get_path()
|
||||
public_fn = File(f'./board/certs/{name}.pub').srcnode().get_path()
|
||||
with open(public_fn) as f:
|
||||
rsa = RSA.importKey(f.read())
|
||||
assert(rsa.size_in_bits() == 1024)
|
||||
@@ -90,7 +91,7 @@ def build_project(project_name, project, main, extra_flags):
|
||||
CFLAGS=flags,
|
||||
ASFLAGS=flags,
|
||||
LINKFLAGS=flags,
|
||||
CPPPATH=[Dir("./"), "./board/stm32f4/inc", "./board/stm32h7/inc", opendbc.INCLUDE_PATH],
|
||||
CPPPATH=[Dir("./"), "./board/stm32h7/inc", opendbc.INCLUDE_PATH],
|
||||
ASCOM="$AS $ASFLAGS -o $TARGET -c $SOURCES",
|
||||
BUILDERS={
|
||||
'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf')
|
||||
@@ -105,8 +106,8 @@ def build_project(project_name, project, main, extra_flags):
|
||||
bs_env.Append(CFLAGS="-DBOOTSTUB", ASFLAGS="-DBOOTSTUB", LINKFLAGS="-DBOOTSTUB")
|
||||
bs_elf = bs_env.Program(f"{project_dir}/bootstub.elf", [
|
||||
startup,
|
||||
"./crypto/rsa.c",
|
||||
"./crypto/sha.c",
|
||||
"./board/crypto/rsa.c",
|
||||
"./board/crypto/sha.c",
|
||||
"./board/bootstub.c",
|
||||
])
|
||||
bs_env.Objcopy(f"./board/obj/bootstub.{project_name}.bin", bs_elf)
|
||||
@@ -117,25 +118,11 @@ def build_project(project_name, project, main, extra_flags):
|
||||
main
|
||||
], LINKFLAGS=[f"-Wl,--section-start,.isr_vector={project['APP_START_ADDRESS']}"] + flags)
|
||||
main_bin = env.Objcopy(f"{project_dir}/main.bin", main_elf)
|
||||
sign_py = File(f"./crypto/sign.py").srcnode().relpath
|
||||
sign_py = File(f"./board/crypto/sign.py").srcnode().relpath
|
||||
env.Command(f"./board/obj/{project_name}.bin.signed", main_bin, f"SETLEN=1 {sign_py} $SOURCE $TARGET {cert_fn}")
|
||||
|
||||
|
||||
|
||||
base_project_f4 = {
|
||||
"STARTUP_FILE": "./board/stm32f4/startup_stm32f413xx.s",
|
||||
"LINKER_SCRIPT": "./board/stm32f4/stm32f4_flash.ld",
|
||||
"APP_START_ADDRESS": "0x8004000",
|
||||
"FLAGS": [
|
||||
"-mcpu=cortex-m4",
|
||||
"-mhard-float",
|
||||
"-DSTM32F4",
|
||||
"-DSTM32F413xx",
|
||||
"-Iboard/stm32f4/inc",
|
||||
"-mfpu=fpv4-sp-d16",
|
||||
],
|
||||
}
|
||||
|
||||
base_project_h7 = {
|
||||
"STARTUP_FILE": "./board/stm32h7/startup_stm32h7x5xx.s",
|
||||
"LINKER_SCRIPT": "./board/stm32h7/stm32h7x5_flash.ld",
|
||||
@@ -151,8 +138,6 @@ base_project_h7 = {
|
||||
}
|
||||
|
||||
# Common autogenerated includes
|
||||
os.makedirs("board/obj", exist_ok=True)
|
||||
|
||||
with open("board/obj/gitversion.h", "w") as f:
|
||||
version = get_version(BUILDER, BUILD_TYPE)
|
||||
f.write(f'extern const uint8_t gitversion[{len(version)+1}];\n')
|
||||
@@ -166,21 +151,26 @@ with open("board/obj/cert.h", "w") as f:
|
||||
for cert in certs:
|
||||
f.write("\n".join(cert) + "\n")
|
||||
|
||||
# Packet version defines: SHA hash of the struct header files
|
||||
def version_hash(path):
|
||||
with open(path, "rb") as f:
|
||||
# Normalize line endings on Windows
|
||||
return int.from_bytes(hashlib.sha256(f.read().replace(b'\r', b'')).digest()[:4], 'little')
|
||||
hh, ch, jh = version_hash("board/health.h"), version_hash(os.path.join(opendbc.INCLUDE_PATH, "opendbc/safety/can.h")), version_hash("board/jungle/jungle_health.h")
|
||||
common_flags += [f"-DHEALTH_PACKET_VERSION=0x{hh:08X}U", f"-DCAN_PACKET_VERSION_HASH=0x{ch:08X}U",
|
||||
f"-DJUNGLE_HEALTH_PACKET_VERSION=0x{jh:08X}U"]
|
||||
|
||||
# panda fw
|
||||
build_project("panda", base_project_f4, "./board/main.c", [])
|
||||
build_project("panda_h7", base_project_h7, "./board/main.c", [])
|
||||
|
||||
# panda jungle fw
|
||||
flags = [
|
||||
"-DPANDA_JUNGLE",
|
||||
]
|
||||
if os.getenv("FINAL_PROVISIONING"):
|
||||
flags += ["-DFINAL_PROVISIONING"]
|
||||
build_project("panda_jungle_h7", base_project_h7, "./board/jungle/main.c", flags)
|
||||
|
||||
# body fw
|
||||
build_project("body_h7", base_project_h7, "./board/body/main.c", ["-DPANDA_BODY"])
|
||||
|
||||
# test files
|
||||
if GetOption('extras'):
|
||||
SConscript('tests/libpanda/SConscript')
|
||||
SConscript('tests/libpanda/SConscript')
|
||||
|
||||
+3
-9
@@ -1,18 +1,12 @@
|
||||
AddOption('--minimal',
|
||||
action='store_false',
|
||||
dest='extras',
|
||||
default=True,
|
||||
help='the minimum build. no tests, tools, etc.')
|
||||
|
||||
AddOption('--ubsan',
|
||||
action='store_true',
|
||||
help='turn on UBSan')
|
||||
import os
|
||||
|
||||
env = Environment(
|
||||
COMPILATIONDB_USE_ABSPATH=True,
|
||||
tools=["default", "compilation_db"],
|
||||
)
|
||||
|
||||
SetOption('num_jobs', max(1, int((os.cpu_count() or 1)-1)))
|
||||
|
||||
env.CompilationDatabase("compile_commands.json")
|
||||
|
||||
# panda fw & test files
|
||||
|
||||
@@ -49,9 +49,7 @@ struct board {
|
||||
// ******************* Definitions ********************
|
||||
// These should match the enums in cereal/log.capnp and __init__.py
|
||||
#define HW_TYPE_UNKNOWN 0U
|
||||
#define HW_TYPE_DOS 6U
|
||||
#define HW_TYPE_RED_PANDA 7U
|
||||
#define HW_TYPE_RED_PANDA_V2 8U
|
||||
#define HW_TYPE_TRES 9U
|
||||
#define HW_TYPE_CUATRO 10U
|
||||
|
||||
@@ -59,7 +57,6 @@ struct board {
|
||||
#define CAN_MODE_NORMAL 0U
|
||||
#define CAN_MODE_OBD_CAN2 1U
|
||||
|
||||
extern struct board board_dos;
|
||||
extern struct board board_tres;
|
||||
extern struct board board_cuatro;
|
||||
extern struct board board_red;
|
||||
|
||||
@@ -39,6 +39,8 @@ static void cuatro_set_fan_enabled(bool enabled) {
|
||||
|
||||
static void cuatro_set_bootkick(BootState state) {
|
||||
set_gpio_output(GPIOA, 0, state != BOOT_BOOTKICK);
|
||||
// DC_IN rising edge wakes SOM from ship mode
|
||||
set_gpio_output(GPIOC, 11, state != BOOT_BOOTKICK);
|
||||
}
|
||||
|
||||
static void cuatro_set_amp_enabled(bool enabled) {
|
||||
@@ -50,7 +52,7 @@ static void cuatro_init(void) {
|
||||
|
||||
// open drain
|
||||
set_gpio_output_type(GPIOD, 3, OUTPUT_TYPE_OPEN_DRAIN); // FAN_EN
|
||||
set_gpio_output_type(GPIOC, 12, OUTPUT_TYPE_OPEN_DRAIN); // VBAT_EN
|
||||
set_gpio_output_type(GPIOC, 11, OUTPUT_TYPE_OPEN_DRAIN); // DC_IN_EN_N
|
||||
|
||||
// Power readout
|
||||
set_gpio_mode(GPIOC, 5, MODE_ANALOG);
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "board_declarations.h"
|
||||
|
||||
static void dos_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
switch (transceiver){
|
||||
case 1U:
|
||||
set_gpio_output(GPIOC, 1, !enabled);
|
||||
break;
|
||||
case 2U:
|
||||
set_gpio_output(GPIOC, 13, !enabled);
|
||||
break;
|
||||
case 3U:
|
||||
set_gpio_output(GPIOA, 0, !enabled);
|
||||
break;
|
||||
case 4U:
|
||||
set_gpio_output(GPIOB, 10, !enabled);
|
||||
break;
|
||||
default:
|
||||
print("Invalid CAN transceiver ("); puth(transceiver); print("): enabling failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dos_set_bootkick(BootState state) {
|
||||
set_gpio_output(GPIOC, 4, state != BOOT_BOOTKICK);
|
||||
}
|
||||
|
||||
static void dos_set_can_mode(uint8_t mode) {
|
||||
dos_enable_can_transceiver(2U, false);
|
||||
dos_enable_can_transceiver(4U, false);
|
||||
switch (mode) {
|
||||
case CAN_MODE_NORMAL:
|
||||
case CAN_MODE_OBD_CAN2:
|
||||
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(harness.status == HARNESS_STATUS_FLIPPED)) {
|
||||
set_gpio_mode(GPIOB, 12, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
|
||||
set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
|
||||
set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
|
||||
dos_enable_can_transceiver(2U, true);
|
||||
} else {
|
||||
set_gpio_mode(GPIOB, 5, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 6, MODE_INPUT);
|
||||
|
||||
set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2);
|
||||
set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2);
|
||||
dos_enable_can_transceiver(4U, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
print("Tried to set unsupported CAN mode: "); puth(mode); print("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dos_set_ir_power(uint8_t percentage){
|
||||
pwm_set(TIM4, 2, percentage);
|
||||
}
|
||||
|
||||
static void dos_set_fan_enabled(bool enabled){
|
||||
set_gpio_output(GPIOA, 1, enabled);
|
||||
}
|
||||
|
||||
static void dos_set_siren(bool enabled){
|
||||
set_gpio_output(GPIOC, 12, enabled);
|
||||
}
|
||||
|
||||
static uint32_t dos_read_voltage_mV(void){
|
||||
return adc_get_mV(&(const adc_signal_t) ADC_CHANNEL_DEFAULT(ADC1, 12)) * 11U;
|
||||
}
|
||||
|
||||
static bool dos_read_som_gpio(void){
|
||||
return (get_gpio_input(GPIOC, 2) != 0);
|
||||
}
|
||||
|
||||
static void dos_init(void) {
|
||||
common_init_gpio();
|
||||
|
||||
set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3);
|
||||
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
|
||||
|
||||
set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3);
|
||||
|
||||
set_gpio_mode(GPIOC, 2, MODE_INPUT);
|
||||
set_gpio_pullup(GPIOC, 2, PULL_DOWN);
|
||||
|
||||
set_gpio_alternate(GPIOB, 7, GPIO_AF2_TIM4);
|
||||
pwm_init(TIM4, 2);
|
||||
dos_set_ir_power(0U);
|
||||
|
||||
dos_set_bootkick(true);
|
||||
|
||||
clock_source_init(false);
|
||||
}
|
||||
|
||||
static harness_configuration dos_harness_config = {
|
||||
.GPIO_SBU1 = GPIOC,
|
||||
.GPIO_SBU2 = GPIOC,
|
||||
.GPIO_relay_SBU1 = GPIOC,
|
||||
.GPIO_relay_SBU2 = GPIOC,
|
||||
.pin_SBU1 = 0,
|
||||
.pin_SBU2 = 3,
|
||||
.pin_relay_SBU1 = 10,
|
||||
.pin_relay_SBU2 = 11,
|
||||
.adc_signal_SBU1 = ADC_CHANNEL_DEFAULT(ADC1, 10),
|
||||
.adc_signal_SBU2 = ADC_CHANNEL_DEFAULT(ADC1, 13),
|
||||
};
|
||||
|
||||
board board_dos = {
|
||||
.harness_config = &dos_harness_config,
|
||||
.has_spi = false,
|
||||
.has_fan = true,
|
||||
.avdd_mV = 3300U,
|
||||
.fan_enable_cooldown_time = 3U,
|
||||
.init = dos_init,
|
||||
.init_bootloader = unused_init_bootloader,
|
||||
.enable_can_transceiver = dos_enable_can_transceiver,
|
||||
.led_GPIO = {GPIOC, GPIOC, GPIOC},
|
||||
.led_pin = {9, 7, 6},
|
||||
.set_can_mode = dos_set_can_mode,
|
||||
.read_voltage_mV = dos_read_voltage_mV,
|
||||
.read_current_mA = unused_read_current,
|
||||
.set_fan_enabled = dos_set_fan_enabled,
|
||||
.set_ir_power = dos_set_ir_power,
|
||||
.set_siren = dos_set_siren,
|
||||
.set_bootkick = dos_set_bootkick,
|
||||
.read_som_gpio = dos_read_som_gpio,
|
||||
.set_amp_enabled = unused_set_amp_enabled
|
||||
};
|
||||
@@ -8,35 +8,37 @@ class PandaBody(Panda):
|
||||
MOTOR_LEFT: int = 1
|
||||
MOTOR_RIGHT: int = 2
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._rpm_left: int = 0
|
||||
self._rpm_right: int = 0
|
||||
|
||||
@property
|
||||
def rpm_left(self) -> int:
|
||||
return self._rpm_left
|
||||
|
||||
@rpm_left.setter
|
||||
def rpm_left(self, value: int) -> None:
|
||||
self._rpm_left = int(value)
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xb3, self._rpm_left, self._rpm_right, b'')
|
||||
|
||||
@property
|
||||
def rpm_right(self) -> int:
|
||||
return self._rpm_right
|
||||
|
||||
@rpm_right.setter
|
||||
def rpm_right(self, value: int) -> None:
|
||||
self._rpm_right = int(value)
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xb3, self._rpm_left, self._rpm_right, b'')
|
||||
|
||||
# ****************** Motor Control *****************
|
||||
@staticmethod
|
||||
def _ensure_valid_motor(motor: int) -> None:
|
||||
if motor not in (PandaBody.MOTOR_LEFT, PandaBody.MOTOR_RIGHT):
|
||||
raise ValueError("motor must be MOTOR_LEFT or MOTOR_RIGHT")
|
||||
|
||||
def motor_set_speed(self, motor: int, speed: int) -> None:
|
||||
self._ensure_valid_motor(motor)
|
||||
assert -100 <= speed <= 100, "speed must be between -100 and 100"
|
||||
speed_param = speed if speed >= 0 else (256 + speed)
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe0, motor, speed_param, b'')
|
||||
|
||||
def motor_set_target_rpm(self, motor: int, rpm: float) -> None:
|
||||
self._ensure_valid_motor(motor)
|
||||
target_deci_rpm = int(round(rpm * 10.0))
|
||||
assert -32768 <= target_deci_rpm <= 32767, "target rpm out of range (-3276.8 to 3276.7)"
|
||||
target_param = target_deci_rpm if target_deci_rpm >= 0 else (target_deci_rpm + (1 << 16))
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe4, motor, target_param, b'')
|
||||
|
||||
def motor_stop(self, motor: int) -> None:
|
||||
self._ensure_valid_motor(motor)
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe1, motor, 0, b'')
|
||||
|
||||
def motor_get_encoder_state(self, motor: int) -> tuple[int, float]:
|
||||
self._ensure_valid_motor(motor)
|
||||
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xe2, motor, 0, 8)
|
||||
position, rpm_milli = struct.unpack("<ii", dat)
|
||||
return position, rpm_milli / 1000.0
|
||||
|
||||
def motor_reset_encoder(self, motor: int) -> None:
|
||||
self._ensure_valid_motor(motor)
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe3, motor, 0, b'')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* File: BLDC_controller.h
|
||||
*
|
||||
* Code generated for Simulink model 'BLDC_controller'.
|
||||
*
|
||||
* Model version : 1.1297
|
||||
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
|
||||
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
|
||||
*
|
||||
* Target selection: ert.tlc
|
||||
* Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||
* Emulation hardware selection:
|
||||
* Differs from embedded hardware (MATLAB Host)
|
||||
* Code generation objectives:
|
||||
* 1. Execution efficiency
|
||||
* 2. RAM efficiency
|
||||
* Validation result: Not run
|
||||
*/
|
||||
|
||||
#ifndef RTW_HEADER_BLDC_controller_h_
|
||||
#define RTW_HEADER_BLDC_controller_h_
|
||||
#include "rtwtypes.h"
|
||||
#ifndef BLDC_controller_COMMON_INCLUDES_
|
||||
# define BLDC_controller_COMMON_INCLUDES_
|
||||
#include "rtwtypes.h"
|
||||
#endif /* BLDC_controller_COMMON_INCLUDES_ */
|
||||
|
||||
/* Macros for accessing real-time model data structure */
|
||||
|
||||
/* Forward declaration for rtModel */
|
||||
typedef struct tag_RTM RT_MODEL;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<S13>/Counter' */
|
||||
typedef struct {
|
||||
int16_T UnitDelay_DSTATE; /* '<S18>/UnitDelay' */
|
||||
} DW_Counter;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<S50>/Low_Pass_Filter' */
|
||||
typedef struct {
|
||||
int32_T UnitDelay1_DSTATE[2]; /* '<S56>/UnitDelay1' */
|
||||
} DW_Low_Pass_Filter;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<S25>/Counter' */
|
||||
typedef struct {
|
||||
uint16_T UnitDelay_DSTATE; /* '<S30>/UnitDelay' */
|
||||
} DW_Counter_b;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<S21>/either_edge' */
|
||||
typedef struct {
|
||||
boolean_T UnitDelay_DSTATE; /* '<S26>/UnitDelay' */
|
||||
} DW_either_edge;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<S20>/Debounce_Filter' */
|
||||
typedef struct {
|
||||
DW_either_edge either_edge_p; /* '<S21>/either_edge' */
|
||||
DW_Counter_b Counter_e; /* '<S24>/Counter' */
|
||||
DW_Counter_b Counter_n1; /* '<S25>/Counter' */
|
||||
boolean_T UnitDelay_DSTATE; /* '<S21>/UnitDelay' */
|
||||
} DW_Debounce_Filter;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<S83>/I_backCalc_fixdt' */
|
||||
typedef struct {
|
||||
int32_T UnitDelay_DSTATE; /* '<S88>/UnitDelay' */
|
||||
int32_T UnitDelay_DSTATE_m; /* '<S90>/UnitDelay' */
|
||||
} DW_I_backCalc_fixdt;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<S63>/PI_clamp_fixdt' */
|
||||
typedef struct {
|
||||
int32_T ResettableDelay_DSTATE; /* '<S77>/Resettable Delay' */
|
||||
uint8_T icLoad; /* '<S77>/Resettable Delay' */
|
||||
boolean_T UnitDelay1_DSTATE; /* '<S74>/UnitDelay1' */
|
||||
} DW_PI_clamp_fixdt;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<S61>/PI_clamp_fixdt' */
|
||||
typedef struct {
|
||||
int32_T ResettableDelay_DSTATE; /* '<S67>/Resettable Delay' */
|
||||
uint8_T icLoad; /* '<S67>/Resettable Delay' */
|
||||
boolean_T UnitDelay1_DSTATE; /* '<S65>/UnitDelay1' */
|
||||
} DW_PI_clamp_fixdt_m;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<S62>/PI_clamp_fixdt' */
|
||||
typedef struct {
|
||||
int16_T ResettableDelay_DSTATE; /* '<S72>/Resettable Delay' */
|
||||
uint8_T icLoad; /* '<S72>/Resettable Delay' */
|
||||
boolean_T UnitDelay1_DSTATE; /* '<S69>/UnitDelay1' */
|
||||
} DW_PI_clamp_fixdt_g;
|
||||
|
||||
/* Block signals and states (auto storage) for system '<Root>' */
|
||||
typedef struct {
|
||||
DW_PI_clamp_fixdt_g PI_clamp_fixdt_kh;/* '<S62>/PI_clamp_fixdt' */
|
||||
DW_PI_clamp_fixdt_m PI_clamp_fixdt_l4;/* '<S61>/PI_clamp_fixdt' */
|
||||
DW_PI_clamp_fixdt PI_clamp_fixdt_i; /* '<S63>/PI_clamp_fixdt' */
|
||||
DW_I_backCalc_fixdt I_backCalc_fixdt_j;/* '<S82>/I_backCalc_fixdt' */
|
||||
DW_I_backCalc_fixdt I_backCalc_fixdt1;/* '<S83>/I_backCalc_fixdt1' */
|
||||
DW_I_backCalc_fixdt I_backCalc_fixdt_i;/* '<S83>/I_backCalc_fixdt' */
|
||||
DW_either_edge either_edge_i; /* '<S20>/either_edge' */
|
||||
DW_Debounce_Filter Debounce_Filter_k;/* '<S20>/Debounce_Filter' */
|
||||
DW_Low_Pass_Filter Low_Pass_Filter_m;/* '<S50>/Low_Pass_Filter' */
|
||||
DW_Counter Counter_e; /* '<S13>/Counter' */
|
||||
int32_T Divide1; /* '<S81>/Divide1' */
|
||||
int32_T UnitDelay_DSTATE; /* '<S40>/UnitDelay' */
|
||||
int16_T Gain4_e[3]; /* '<S57>/Gain4' */
|
||||
int16_T DataTypeConversion[2]; /* '<S56>/Data Type Conversion' */
|
||||
int16_T z_counterRawPrev; /* '<S17>/z_counterRawPrev' */
|
||||
int16_T Merge; /* '<S59>/Merge' */
|
||||
int16_T Switch1; /* '<S78>/Switch1' */
|
||||
int16_T Vd_max1; /* '<S80>/Vd_max1' */
|
||||
int16_T Gain3; /* '<S80>/Gain3' */
|
||||
int16_T Vq_max_M1; /* '<S80>/Vq_max_M1' */
|
||||
int16_T Gain5; /* '<S80>/Gain5' */
|
||||
int16_T i_max; /* '<S80>/i_max' */
|
||||
int16_T Divide1_n; /* '<S80>/Divide1' */
|
||||
int16_T Gain1; /* '<S80>/Gain1' */
|
||||
int16_T Gain4; /* '<S80>/Gain4' */
|
||||
int16_T Switch2_i; /* '<S87>/Switch2' */
|
||||
int16_T Switch2_o; /* '<S93>/Switch2' */
|
||||
int16_T Switch2_a; /* '<S91>/Switch2' */
|
||||
int16_T Divide3; /* '<S42>/Divide3' */
|
||||
int16_T Merge1; /* '<S33>/Merge1' */
|
||||
int16_T Abs1; /* '<S5>/Abs1' */
|
||||
int16_T Abs5_h; /* '<S50>/Abs5' */
|
||||
int16_T Divide11; /* '<S17>/Divide11' */
|
||||
int16_T r_sin_M1; /* '<S52>/r_sin_M1' */
|
||||
int16_T r_cos_M1; /* '<S52>/r_cos_M1' */
|
||||
int16_T UnitDelay3_DSTATE; /* '<S13>/UnitDelay3' */
|
||||
int16_T UnitDelay4_DSTATE; /* '<S17>/UnitDelay4' */
|
||||
int16_T UnitDelay2_DSTATE; /* '<S17>/UnitDelay2' */
|
||||
int16_T UnitDelay3_DSTATE_o; /* '<S17>/UnitDelay3' */
|
||||
int16_T UnitDelay5_DSTATE; /* '<S17>/UnitDelay5' */
|
||||
int16_T UnitDelay4_DSTATE_e; /* '<S13>/UnitDelay4' */
|
||||
int16_T UnitDelay4_DSTATE_eu; /* '<S8>/UnitDelay4' */
|
||||
int8_T Switch2_e; /* '<S12>/Switch2' */
|
||||
int8_T UnitDelay2_DSTATE_b; /* '<S12>/UnitDelay2' */
|
||||
int8_T If1_ActiveSubsystem; /* '<S7>/If1' */
|
||||
int8_T If2_ActiveSubsystem; /* '<S7>/If2' */
|
||||
int8_T If1_ActiveSubsystem_j; /* '<S47>/If1' */
|
||||
int8_T SwitchCase_ActiveSubsystem; /* '<S59>/Switch Case' */
|
||||
int8_T If1_ActiveSubsystem_a; /* '<S59>/If1' */
|
||||
int8_T If1_ActiveSubsystem_o; /* '<S48>/If1' */
|
||||
int8_T SwitchCase_ActiveSubsystem_d; /* '<S80>/Switch Case' */
|
||||
int8_T If2_ActiveSubsystem_f; /* '<S33>/If2' */
|
||||
int8_T If2_ActiveSubsystem_a; /* '<S45>/If2' */
|
||||
uint8_T z_ctrlMod; /* '<S5>/F03_02_Control_Mode_Manager' */
|
||||
uint8_T UnitDelay3_DSTATE_fy; /* '<S10>/UnitDelay3' */
|
||||
uint8_T UnitDelay1_DSTATE; /* '<S10>/UnitDelay1' */
|
||||
uint8_T UnitDelay2_DSTATE_f; /* '<S10>/UnitDelay2' */
|
||||
uint8_T UnitDelay_DSTATE_e; /* '<S20>/UnitDelay' */
|
||||
uint8_T is_active_c1_BLDC_controller;/* '<S5>/F03_02_Control_Mode_Manager' */
|
||||
uint8_T is_c1_BLDC_controller; /* '<S5>/F03_02_Control_Mode_Manager' */
|
||||
uint8_T is_ACTIVE; /* '<S5>/F03_02_Control_Mode_Manager' */
|
||||
boolean_T Merge_p; /* '<S21>/Merge' */
|
||||
boolean_T dz_cntTrnsDet; /* '<S17>/dz_cntTrnsDet' */
|
||||
boolean_T UnitDelay2_DSTATE_c; /* '<S2>/UnitDelay2' */
|
||||
boolean_T UnitDelay5_DSTATE_m; /* '<S2>/UnitDelay5' */
|
||||
boolean_T UnitDelay6_DSTATE; /* '<S2>/UnitDelay6' */
|
||||
boolean_T UnitDelay_DSTATE_b; /* '<S39>/UnitDelay' */
|
||||
boolean_T UnitDelay1_DSTATE_n; /* '<S17>/UnitDelay1' */
|
||||
boolean_T n_commDeacv_Mode; /* '<S13>/n_commDeacv' */
|
||||
boolean_T dz_cntTrnsDet_Mode; /* '<S17>/dz_cntTrnsDet' */
|
||||
} DW;
|
||||
|
||||
/* Constant parameters (auto storage) */
|
||||
typedef struct {
|
||||
/* Computed Parameter: r_sin_M1_Table
|
||||
* Referenced by: '<S52>/r_sin_M1'
|
||||
*/
|
||||
int16_T r_sin_M1_Table[181];
|
||||
|
||||
/* Computed Parameter: r_cos_M1_Table
|
||||
* Referenced by: '<S52>/r_cos_M1'
|
||||
*/
|
||||
int16_T r_cos_M1_Table[181];
|
||||
|
||||
/* Computed Parameter: r_sin3PhaA_M1_Table
|
||||
* Referenced by: '<S96>/r_sin3PhaA_M1'
|
||||
*/
|
||||
int16_T r_sin3PhaA_M1_Table[181];
|
||||
|
||||
/* Computed Parameter: r_sin3PhaB_M1_Table
|
||||
* Referenced by: '<S96>/r_sin3PhaB_M1'
|
||||
*/
|
||||
int16_T r_sin3PhaB_M1_Table[181];
|
||||
|
||||
/* Computed Parameter: r_sin3PhaC_M1_Table
|
||||
* Referenced by: '<S96>/r_sin3PhaC_M1'
|
||||
*/
|
||||
int16_T r_sin3PhaC_M1_Table[181];
|
||||
|
||||
/* Computed Parameter: iq_maxSca_M1_Table
|
||||
* Referenced by: '<S80>/iq_maxSca_M1'
|
||||
*/
|
||||
uint16_T iq_maxSca_M1_Table[50];
|
||||
|
||||
/* Computed Parameter: z_commutMap_M1_table
|
||||
* Referenced by: '<S94>/z_commutMap_M1'
|
||||
*/
|
||||
int8_T z_commutMap_M1_table[18];
|
||||
|
||||
/* Computed Parameter: vec_hallToPos_Value
|
||||
* Referenced by: '<S11>/vec_hallToPos'
|
||||
*/
|
||||
int8_T vec_hallToPos_Value[8];
|
||||
} ConstP;
|
||||
|
||||
/* External inputs (root inport signals with auto storage) */
|
||||
typedef struct {
|
||||
boolean_T b_motEna; /* '<Root>/b_motEna' */
|
||||
uint8_T z_ctrlModReq; /* '<Root>/z_ctrlModReq' */
|
||||
int16_T r_inpTgt; /* '<Root>/r_inpTgt' */
|
||||
uint8_T b_hallA; /* '<Root>/b_hallA ' */
|
||||
uint8_T b_hallB; /* '<Root>/b_hallB' */
|
||||
uint8_T b_hallC; /* '<Root>/b_hallC' */
|
||||
int16_T i_phaAB; /* '<Root>/i_phaAB' */
|
||||
int16_T i_phaBC; /* '<Root>/i_phaBC' */
|
||||
int16_T i_DCLink; /* '<Root>/i_DCLink' */
|
||||
int16_T a_mechAngle; /* '<Root>/a_mechAngle' */
|
||||
} ExtU;
|
||||
|
||||
/* External outputs (root outports fed by signals with auto storage) */
|
||||
typedef struct {
|
||||
int16_T DC_phaA; /* '<Root>/DC_phaA' */
|
||||
int16_T DC_phaB; /* '<Root>/DC_phaB' */
|
||||
int16_T DC_phaC; /* '<Root>/DC_phaC' */
|
||||
uint8_T z_errCode; /* '<Root>/z_errCode' */
|
||||
int16_T n_mot; /* '<Root>/n_mot' */
|
||||
int16_T a_elecAngle; /* '<Root>/a_elecAngle' */
|
||||
int16_T iq; /* '<Root>/iq' */
|
||||
int16_T id; /* '<Root>/id' */
|
||||
} ExtY;
|
||||
|
||||
/* Parameters (auto storage) */
|
||||
struct P_ {
|
||||
int32_T dV_openRate; /* Variable: dV_openRate
|
||||
* Referenced by: '<S37>/dV_openRate'
|
||||
*/
|
||||
int16_T dz_cntTrnsDetHi; /* Variable: dz_cntTrnsDetHi
|
||||
* Referenced by: '<S17>/dz_cntTrnsDet'
|
||||
*/
|
||||
int16_T dz_cntTrnsDetLo; /* Variable: dz_cntTrnsDetLo
|
||||
* Referenced by: '<S17>/dz_cntTrnsDet'
|
||||
*/
|
||||
int16_T n_cruiseMotTgt; /* Variable: n_cruiseMotTgt
|
||||
* Referenced by: '<S61>/n_cruiseMotTgt'
|
||||
*/
|
||||
int16_T z_maxCntRst; /* Variable: z_maxCntRst
|
||||
* Referenced by:
|
||||
* '<S13>/Counter'
|
||||
* '<S13>/z_maxCntRst'
|
||||
* '<S13>/z_maxCntRst2'
|
||||
* '<S13>/UnitDelay3'
|
||||
* '<S17>/z_counter'
|
||||
*/
|
||||
uint16_T cf_speedCoef; /* Variable: cf_speedCoef
|
||||
* Referenced by: '<S17>/cf_speedCoef'
|
||||
*/
|
||||
uint16_T t_errDequal; /* Variable: t_errDequal
|
||||
* Referenced by: '<S20>/t_errDequal'
|
||||
*/
|
||||
uint16_T t_errQual; /* Variable: t_errQual
|
||||
* Referenced by: '<S20>/t_errQual'
|
||||
*/
|
||||
int16_T Vd_max; /* Variable: Vd_max
|
||||
* Referenced by:
|
||||
* '<S36>/Vd_max'
|
||||
* '<S80>/Vd_max1'
|
||||
*/
|
||||
int16_T Vq_max_M1[46]; /* Variable: Vq_max_M1
|
||||
* Referenced by: '<S80>/Vq_max_M1'
|
||||
*/
|
||||
int16_T Vq_max_XA[46]; /* Variable: Vq_max_XA
|
||||
* Referenced by: '<S80>/Vq_max_XA'
|
||||
*/
|
||||
int16_T a_phaAdvMax; /* Variable: a_phaAdvMax
|
||||
* Referenced by: '<S42>/a_phaAdvMax'
|
||||
*/
|
||||
int16_T i_max; /* Variable: i_max
|
||||
* Referenced by:
|
||||
* '<S36>/i_max'
|
||||
* '<S80>/i_max'
|
||||
*/
|
||||
int16_T id_fieldWeakMax; /* Variable: id_fieldWeakMax
|
||||
* Referenced by: '<S42>/id_fieldWeakMax'
|
||||
*/
|
||||
int16_T n_commAcvLo; /* Variable: n_commAcvLo
|
||||
* Referenced by: '<S13>/n_commDeacv'
|
||||
*/
|
||||
int16_T n_commDeacvHi; /* Variable: n_commDeacvHi
|
||||
* Referenced by: '<S13>/n_commDeacv'
|
||||
*/
|
||||
int16_T n_fieldWeakAuthHi; /* Variable: n_fieldWeakAuthHi
|
||||
* Referenced by: '<S42>/n_fieldWeakAuthHi'
|
||||
*/
|
||||
int16_T n_fieldWeakAuthLo; /* Variable: n_fieldWeakAuthLo
|
||||
* Referenced by: '<S42>/n_fieldWeakAuthLo'
|
||||
*/
|
||||
int16_T n_max; /* Variable: n_max
|
||||
* Referenced by:
|
||||
* '<S36>/n_max'
|
||||
* '<S80>/n_max1'
|
||||
*/
|
||||
int16_T n_stdStillDet; /* Variable: n_stdStillDet
|
||||
* Referenced by: '<S13>/n_stdStillDet'
|
||||
*/
|
||||
int16_T r_errInpTgtThres; /* Variable: r_errInpTgtThres
|
||||
* Referenced by: '<S20>/r_errInpTgtThres'
|
||||
*/
|
||||
int16_T r_fieldWeakHi; /* Variable: r_fieldWeakHi
|
||||
* Referenced by: '<S42>/r_fieldWeakHi'
|
||||
*/
|
||||
int16_T r_fieldWeakLo; /* Variable: r_fieldWeakLo
|
||||
* Referenced by: '<S42>/r_fieldWeakLo'
|
||||
*/
|
||||
uint16_T cf_KbLimProt; /* Variable: cf_KbLimProt
|
||||
* Referenced by:
|
||||
* '<S82>/cf_KbLimProt'
|
||||
* '<S83>/cf_KbLimProt'
|
||||
*/
|
||||
uint16_T cf_idKp; /* Variable: cf_idKp
|
||||
* Referenced by: '<S63>/cf_idKp1'
|
||||
*/
|
||||
uint16_T cf_iqKp; /* Variable: cf_iqKp
|
||||
* Referenced by: '<S62>/cf_iqKp'
|
||||
*/
|
||||
uint16_T cf_nKp; /* Variable: cf_nKp
|
||||
* Referenced by: '<S61>/cf_nKp'
|
||||
*/
|
||||
uint16_T cf_currFilt; /* Variable: cf_currFilt
|
||||
* Referenced by: '<S50>/cf_currFilt'
|
||||
*/
|
||||
uint16_T cf_idKi; /* Variable: cf_idKi
|
||||
* Referenced by: '<S63>/cf_idKi1'
|
||||
*/
|
||||
uint16_T cf_iqKi; /* Variable: cf_iqKi
|
||||
* Referenced by: '<S62>/cf_iqKi'
|
||||
*/
|
||||
uint16_T cf_iqKiLimProt; /* Variable: cf_iqKiLimProt
|
||||
* Referenced by:
|
||||
* '<S81>/cf_iqKiLimProt'
|
||||
* '<S83>/cf_iqKiLimProt'
|
||||
*/
|
||||
uint16_T cf_nKi; /* Variable: cf_nKi
|
||||
* Referenced by: '<S61>/cf_nKi'
|
||||
*/
|
||||
uint16_T cf_nKiLimProt; /* Variable: cf_nKiLimProt
|
||||
* Referenced by:
|
||||
* '<S82>/cf_nKiLimProt'
|
||||
* '<S83>/cf_nKiLimProt'
|
||||
*/
|
||||
uint8_T n_polePairs; /* Variable: n_polePairs
|
||||
* Referenced by: '<S15>/n_polePairs'
|
||||
*/
|
||||
uint8_T z_ctrlTypSel; /* Variable: z_ctrlTypSel
|
||||
* Referenced by: '<S1>/z_ctrlTypSel'
|
||||
*/
|
||||
uint8_T z_selPhaCurMeasABC; /* Variable: z_selPhaCurMeasABC
|
||||
* Referenced by: '<S49>/z_selPhaCurMeasABC'
|
||||
*/
|
||||
boolean_T b_angleMeasEna; /* Variable: b_angleMeasEna
|
||||
* Referenced by:
|
||||
* '<S3>/b_angleMeasEna'
|
||||
* '<S13>/b_angleMeasEna'
|
||||
*/
|
||||
boolean_T b_cruiseCtrlEna; /* Variable: b_cruiseCtrlEna
|
||||
* Referenced by: '<S1>/b_cruiseCtrlEna'
|
||||
*/
|
||||
boolean_T b_diagEna; /* Variable: b_diagEna
|
||||
* Referenced by: '<S4>/b_diagEna'
|
||||
*/
|
||||
boolean_T b_fieldWeakEna; /* Variable: b_fieldWeakEna
|
||||
* Referenced by:
|
||||
* '<S6>/b_fieldWeakEna'
|
||||
* '<S97>/b_fieldWeakEna'
|
||||
*/
|
||||
};
|
||||
|
||||
/* Parameters (auto storage) */
|
||||
typedef struct P_ P;
|
||||
|
||||
/* Real-time Model Data Structure */
|
||||
struct tag_RTM {
|
||||
P *defaultParam;
|
||||
ExtU *inputs;
|
||||
ExtY *outputs;
|
||||
DW *dwork;
|
||||
};
|
||||
|
||||
/* Constant parameters (auto storage) */
|
||||
extern const ConstP rtConstP;
|
||||
|
||||
/* Model entry point functions */
|
||||
extern void BLDC_controller_initialize(RT_MODEL *const rtM);
|
||||
extern void BLDC_controller_step(RT_MODEL *const rtM);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* File: BLDC_controller_data.c
|
||||
*
|
||||
* Code generated for Simulink model 'BLDC_controller'.
|
||||
*
|
||||
* Model version : 1.1297
|
||||
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
|
||||
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
|
||||
*
|
||||
* Target selection: ert.tlc
|
||||
* Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||
* Emulation hardware selection:
|
||||
* Differs from embedded hardware (MATLAB Host)
|
||||
* Code generation objectives:
|
||||
* 1. Execution efficiency
|
||||
* 2. RAM efficiency
|
||||
* Validation result: Not run
|
||||
*/
|
||||
|
||||
#include "BLDC_controller.h"
|
||||
|
||||
/* Constant parameters (auto storage) */
|
||||
const ConstP rtConstP = {
|
||||
/* Computed Parameter: r_sin_M1_Table
|
||||
* Referenced by: '<S52>/r_sin_M1'
|
||||
*/
|
||||
{ 8192, 8682, 9162, 9630, 10087, 10531, 10963, 11381, 11786, 12176, 12551,
|
||||
12911, 13255, 13583, 13894, 14189, 14466, 14726, 14968, 15191, 15396, 15582,
|
||||
15749, 15897, 16026, 16135, 16225, 16294, 16344, 16374, 16384, 16374, 16344,
|
||||
16294, 16225, 16135, 16026, 15897, 15749, 15582, 15396, 15191, 14968, 14726,
|
||||
14466, 14189, 13894, 13583, 13255, 12911, 12551, 12176, 11786, 11381, 10963,
|
||||
10531, 10087, 9630, 9162, 8682, 8192, 7692, 7182, 6664, 6138, 5604, 5063,
|
||||
4516, 3964, 3406, 2845, 2280, 1713, 1143, 572, 0, -572, -1143, -1713, -2280,
|
||||
-2845, -3406, -3964, -4516, -5063, -5604, -6138, -6664, -7182, -7692, -8192,
|
||||
-8682, -9162, -9630, -10087, -10531, -10963, -11381, -11786, -12176, -12551,
|
||||
-12911, -13255, -13583, -13894, -14189, -14466, -14726, -14968, -15191,
|
||||
-15396, -15582, -15749, -15897, -16026, -16135, -16225, -16294, -16344,
|
||||
-16374, -16384, -16374, -16344, -16294, -16225, -16135, -16026, -15897,
|
||||
-15749, -15582, -15396, -15191, -14968, -14726, -14466, -14189, -13894,
|
||||
-13583, -13255, -12911, -12551, -12176, -11786, -11381, -10963, -10531,
|
||||
-10087, -9630, -9162, -8682, -8192, -7692, -7182, -6664, -6138, -5604, -5063,
|
||||
-4516, -3964, -3406, -2845, -2280, -1713, -1143, -572, 0, 572, 1143, 1713,
|
||||
2280, 2845, 3406, 3964, 4516, 5063, 5604, 6138, 6664, 7182, 7692, 8192 },
|
||||
|
||||
/* Computed Parameter: r_cos_M1_Table
|
||||
* Referenced by: '<S52>/r_cos_M1'
|
||||
*/
|
||||
{ 14189, 13894, 13583, 13255, 12911, 12551, 12176, 11786, 11381, 10963, 10531,
|
||||
10087, 9630, 9162, 8682, 8192, 7692, 7182, 6664, 6138, 5604, 5063, 4516,
|
||||
3964, 3406, 2845, 2280, 1713, 1143, 572, 0, -572, -1143, -1713, -2280, -2845,
|
||||
-3406, -3964, -4516, -5063, -5604, -6138, -6664, -7182, -7692, -8192, -8682,
|
||||
-9162, -9630, -10087, -10531, -10963, -11381, -11786, -12176, -12551, -12911,
|
||||
-13255, -13583, -13894, -14189, -14466, -14726, -14968, -15191, -15396,
|
||||
-15582, -15749, -15897, -16026, -16135, -16225, -16294, -16344, -16374,
|
||||
-16384, -16374, -16344, -16294, -16225, -16135, -16026, -15897, -15749,
|
||||
-15582, -15396, -15191, -14968, -14726, -14466, -14189, -13894, -13583,
|
||||
-13255, -12911, -12551, -12176, -11786, -11381, -10963, -10531, -10087,
|
||||
-9630, -9162, -8682, -8192, -7692, -7182, -6664, -6138, -5604, -5063, -4516,
|
||||
-3964, -3406, -2845, -2280, -1713, -1143, -572, 0, 572, 1143, 1713, 2280,
|
||||
2845, 3406, 3964, 4516, 5063, 5604, 6138, 6664, 7182, 7692, 8192, 8682, 9162,
|
||||
9630, 10087, 10531, 10963, 11381, 11786, 12176, 12551, 12911, 13255, 13583,
|
||||
13894, 14189, 14466, 14726, 14968, 15191, 15396, 15582, 15749, 15897, 16026,
|
||||
16135, 16225, 16294, 16344, 16374, 16384, 16374, 16344, 16294, 16225, 16135,
|
||||
16026, 15897, 15749, 15582, 15396, 15191, 14968, 14726, 14466, 14189 },
|
||||
|
||||
/* Computed Parameter: r_sin3PhaA_M1_Table
|
||||
* Referenced by: '<S96>/r_sin3PhaA_M1'
|
||||
*/
|
||||
{ -13091, -13634, -14126, -14565, -14953, -15289, -15577, -15816, -16009,
|
||||
-16159, -16269, -16340, -16377, -16383, -16362, -16317, -16253, -16172,
|
||||
-16079, -15977, -15870, -15762, -15656, -15555, -15461, -15377, -15306,
|
||||
-15248, -15206, -15180, -15172, -15180, -15206, -15248, -15306, -15377,
|
||||
-15461, -15555, -15656, -15762, -15870, -15977, -16079, -16172, -16253,
|
||||
-16317, -16362, -16383, -16377, -16340, -16269, -16159, -16009, -15816,
|
||||
-15577, -15289, -14953, -14565, -14126, -13634, -13091, -12496, -11849,
|
||||
-11154, -10411, -9623, -8791, -7921, -7014, -6075, -5107, -4115, -3104,
|
||||
-2077, -1041, 0, 1041, 2077, 3104, 4115, 5107, 6075, 7014, 7921, 8791, 9623,
|
||||
10411, 11154, 11849, 12496, 13091, 13634, 14126, 14565, 14953, 15289, 15577,
|
||||
15816, 16009, 16159, 16269, 16340, 16377, 16383, 16362, 16317, 16253, 16172,
|
||||
16079, 15977, 15870, 15762, 15656, 15555, 15461, 15377, 15306, 15248, 15206,
|
||||
15180, 15172, 15180, 15206, 15248, 15306, 15377, 15461, 15555, 15656, 15762,
|
||||
15870, 15977, 16079, 16172, 16253, 16317, 16362, 16383, 16377, 16340, 16269,
|
||||
16159, 16009, 15816, 15577, 15289, 14953, 14565, 14126, 13634, 13091, 12496,
|
||||
11849, 11154, 10411, 9623, 8791, 7921, 7014, 6075, 5107, 4115, 3104, 2077,
|
||||
1041, 0, -1041, -2077, -3104, -4115, -5107, -6075, -7014, -7921, -8791,
|
||||
-9623, -10411, -11154, -11849, -12496, -13091 },
|
||||
|
||||
/* Computed Parameter: r_sin3PhaB_M1_Table
|
||||
* Referenced by: '<S96>/r_sin3PhaB_M1'
|
||||
*/
|
||||
{ 15172, 15180, 15206, 15248, 15306, 15377, 15461, 15555, 15656, 15762, 15870,
|
||||
15977, 16079, 16172, 16253, 16317, 16362, 16383, 16377, 16340, 16269, 16159,
|
||||
16009, 15816, 15577, 15289, 14953, 14565, 14126, 13634, 13091, 12496, 11849,
|
||||
11154, 10411, 9623, 8791, 7921, 7014, 6075, 5107, 4115, 3104, 2077, 1041, 0,
|
||||
-1041, -2077, -3104, -4115, -5107, -6075, -7014, -7921, -8791, -9623, -10411,
|
||||
-11154, -11849, -12496, -13091, -13634, -14126, -14565, -14953, -15289,
|
||||
-15577, -15816, -16009, -16159, -16269, -16340, -16377, -16383, -16362,
|
||||
-16317, -16253, -16172, -16079, -15977, -15870, -15762, -15656, -15555,
|
||||
-15461, -15377, -15306, -15248, -15206, -15180, -15172, -15180, -15206,
|
||||
-15248, -15306, -15377, -15461, -15555, -15656, -15762, -15870, -15977,
|
||||
-16079, -16172, -16253, -16317, -16362, -16383, -16377, -16340, -16269,
|
||||
-16159, -16009, -15816, -15577, -15289, -14953, -14565, -14126, -13634,
|
||||
-13091, -12496, -11849, -11154, -10411, -9623, -8791, -7921, -7014, -6075,
|
||||
-5107, -4115, -3104, -2077, -1041, 0, 1041, 2077, 3104, 4115, 5107, 6075,
|
||||
7014, 7921, 8791, 9623, 10411, 11154, 11849, 12496, 13091, 13634, 14126,
|
||||
14565, 14953, 15289, 15577, 15816, 16009, 16159, 16269, 16340, 16377, 16383,
|
||||
16362, 16317, 16253, 16172, 16079, 15977, 15870, 15762, 15656, 15555, 15461,
|
||||
15377, 15306, 15248, 15206, 15180, 15172 },
|
||||
|
||||
/* Computed Parameter: r_sin3PhaC_M1_Table
|
||||
* Referenced by: '<S96>/r_sin3PhaC_M1'
|
||||
*/
|
||||
{ -13091, -12496, -11849, -11154, -10411, -9623, -8791, -7921, -7014, -6075,
|
||||
-5107, -4115, -3104, -2077, -1041, 0, 1041, 2077, 3104, 4115, 5107, 6075,
|
||||
7014, 7921, 8791, 9623, 10411, 11154, 11849, 12496, 13091, 13634, 14126,
|
||||
14565, 14953, 15289, 15577, 15816, 16009, 16159, 16269, 16340, 16377, 16383,
|
||||
16362, 16317, 16253, 16172, 16079, 15977, 15870, 15762, 15656, 15555, 15461,
|
||||
15377, 15306, 15248, 15206, 15180, 15172, 15180, 15206, 15248, 15306, 15377,
|
||||
15461, 15555, 15656, 15762, 15870, 15977, 16079, 16172, 16253, 16317, 16362,
|
||||
16383, 16377, 16340, 16269, 16159, 16009, 15816, 15577, 15289, 14953, 14565,
|
||||
14126, 13634, 13091, 12496, 11849, 11154, 10411, 9623, 8791, 7921, 7014,
|
||||
6075, 5107, 4115, 3104, 2077, 1041, 0, -1041, -2077, -3104, -4115, -5107,
|
||||
-6075, -7014, -7921, -8791, -9623, -10411, -11154, -11849, -12496, -13091,
|
||||
-13634, -14126, -14565, -14953, -15289, -15577, -15816, -16009, -16159,
|
||||
-16269, -16340, -16377, -16383, -16362, -16317, -16253, -16172, -16079,
|
||||
-15977, -15870, -15762, -15656, -15555, -15461, -15377, -15306, -15248,
|
||||
-15206, -15180, -15172, -15180, -15206, -15248, -15306, -15377, -15461,
|
||||
-15555, -15656, -15762, -15870, -15977, -16079, -16172, -16253, -16317,
|
||||
-16362, -16383, -16377, -16340, -16269, -16159, -16009, -15816, -15577,
|
||||
-15289, -14953, -14565, -14126, -13634, -13091 },
|
||||
|
||||
/* Computed Parameter: iq_maxSca_M1_Table
|
||||
* Referenced by: '<S80>/iq_maxSca_M1'
|
||||
*/
|
||||
{ 65535U, 65523U, 65484U, 65418U, 65326U, 65207U, 65062U, 64890U, 64691U,
|
||||
64465U, 64211U, 63930U, 63620U, 63281U, 62913U, 62516U, 62088U, 61630U,
|
||||
61140U, 60618U, 60062U, 59473U, 58848U, 58187U, 57489U, 56752U, 55974U,
|
||||
55155U, 54291U, 53381U, 52422U, 51413U, 50349U, 49227U, 48043U, 46792U,
|
||||
45470U, 44069U, 42581U, 40997U, 39307U, 37494U, 35541U, 33422U, 31105U,
|
||||
28540U, 25655U, 22323U, 18304U, 12974U },
|
||||
|
||||
/* Computed Parameter: z_commutMap_M1_table
|
||||
* Referenced by: '<S94>/z_commutMap_M1'
|
||||
*/
|
||||
{ -1, 1, 0, -1, 0, 1, 0, -1, 1, 1, -1, 0, 1, 0, -1, 0, 1, -1 },
|
||||
|
||||
/* Computed Parameter: vec_hallToPos_Value
|
||||
* Referenced by: '<S11>/vec_hallToPos'
|
||||
*/
|
||||
{ 0, 2, 0, 1, 4, 3, 5, 0 }
|
||||
};
|
||||
|
||||
P rtP_Left = {
|
||||
/* Variable: dV_openRate
|
||||
* Referenced by: '<S37>/dV_openRate'
|
||||
*/
|
||||
12288,
|
||||
|
||||
/* Variable: dz_cntTrnsDetHi
|
||||
* Referenced by: '<S17>/dz_cntTrnsDet'
|
||||
*/
|
||||
40,
|
||||
|
||||
/* Variable: dz_cntTrnsDetLo
|
||||
* Referenced by: '<S17>/dz_cntTrnsDet'
|
||||
*/
|
||||
20,
|
||||
|
||||
/* Variable: n_cruiseMotTgt
|
||||
* Referenced by: '<S61>/n_cruiseMotTgt'
|
||||
*/
|
||||
0,
|
||||
|
||||
/* Variable: z_maxCntRst
|
||||
* Referenced by:
|
||||
* '<S13>/Counter'
|
||||
* '<S13>/z_maxCntRst'
|
||||
* '<S13>/z_maxCntRst2'
|
||||
* '<S13>/UnitDelay3'
|
||||
* '<S17>/z_counter'
|
||||
*/
|
||||
2000,
|
||||
|
||||
/* Variable: cf_speedCoef
|
||||
* Referenced by: '<S17>/cf_speedCoef'
|
||||
*/
|
||||
5334U,
|
||||
|
||||
/* Variable: t_errDequal
|
||||
* Referenced by: '<S20>/t_errDequal'
|
||||
*/
|
||||
9600U,
|
||||
|
||||
/* Variable: t_errQual
|
||||
* Referenced by: '<S20>/t_errQual'
|
||||
*/
|
||||
1280U,
|
||||
|
||||
/* Variable: Vd_max
|
||||
* Referenced by:
|
||||
* '<S36>/Vd_max'
|
||||
* '<S80>/Vd_max1'
|
||||
*/
|
||||
14400,
|
||||
|
||||
/* Variable: Vq_max_M1
|
||||
* Referenced by: '<S80>/Vq_max_M1'
|
||||
*/
|
||||
{ 14400, 14396, 14386, 14368, 14343, 14311, 14271, 14225, 14171, 14109, 14040,
|
||||
13963, 13879, 13786, 13685, 13576, 13459, 13333, 13198, 13053, 12900, 12736,
|
||||
12562, 12377, 12181, 11973, 11753, 11520, 11273, 11011, 10733, 10438, 10124,
|
||||
9790, 9433, 9051, 8640, 8196, 7713, 7184, 6597, 5935, 5170, 4245, 3019, 0 },
|
||||
|
||||
/* Variable: Vq_max_XA
|
||||
* Referenced by: '<S80>/Vq_max_XA'
|
||||
*/
|
||||
{ 0, 320, 640, 960, 1280, 1600, 1920, 2240, 2560, 2880, 3200, 3520, 3840, 4160,
|
||||
4480, 4800, 5120, 5440, 5760, 6080, 6400, 6720, 7040, 7360, 7680, 8000, 8320,
|
||||
8640, 8960, 9280, 9600, 9920, 10240, 10560, 10880, 11200, 11520, 11840,
|
||||
12160, 12480, 12800, 13120, 13440, 13760, 14080, 14400 },
|
||||
|
||||
/* Variable: a_phaAdvMax
|
||||
* Referenced by: '<S42>/a_phaAdvMax'
|
||||
*/
|
||||
400,
|
||||
|
||||
/* Variable: i_max
|
||||
* Referenced by:
|
||||
* '<S36>/i_max'
|
||||
* '<S80>/i_max'
|
||||
*/
|
||||
30000,
|
||||
|
||||
/* Variable: id_fieldWeakMax
|
||||
* Referenced by: '<S42>/id_fieldWeakMax'
|
||||
*/
|
||||
4000,
|
||||
|
||||
/* Variable: n_commAcvLo
|
||||
* Referenced by: '<S13>/n_commDeacv'
|
||||
*/
|
||||
240,
|
||||
|
||||
/* Variable: n_commDeacvHi
|
||||
* Referenced by: '<S13>/n_commDeacv'
|
||||
*/
|
||||
480,
|
||||
|
||||
/* Variable: n_fieldWeakAuthHi
|
||||
* Referenced by: '<S42>/n_fieldWeakAuthHi'
|
||||
*/
|
||||
6400,
|
||||
|
||||
/* Variable: n_fieldWeakAuthLo
|
||||
* Referenced by: '<S42>/n_fieldWeakAuthLo'
|
||||
*/
|
||||
4800,
|
||||
|
||||
/* Variable: n_max
|
||||
* Referenced by:
|
||||
* '<S36>/n_max'
|
||||
* '<S80>/n_max1'
|
||||
*/
|
||||
32000,
|
||||
|
||||
/* Variable: n_stdStillDet
|
||||
* Referenced by: '<S13>/n_stdStillDet'
|
||||
*/
|
||||
48,
|
||||
|
||||
/* Variable: r_errInpTgtThres
|
||||
* Referenced by: '<S20>/r_errInpTgtThres'
|
||||
*/
|
||||
9600,
|
||||
|
||||
/* Variable: r_fieldWeakHi
|
||||
* Referenced by: '<S42>/r_fieldWeakHi'
|
||||
*/
|
||||
16000,
|
||||
|
||||
/* Variable: r_fieldWeakLo
|
||||
* Referenced by: '<S42>/r_fieldWeakLo'
|
||||
*/
|
||||
12000,
|
||||
|
||||
/* Variable: cf_KbLimProt
|
||||
* Referenced by:
|
||||
* '<S82>/cf_KbLimProt'
|
||||
* '<S83>/cf_KbLimProt'
|
||||
*/
|
||||
768U,
|
||||
|
||||
/* Variable: cf_idKp
|
||||
* Referenced by: '<S63>/cf_idKp1'
|
||||
*/
|
||||
1638U,
|
||||
|
||||
/* Variable: cf_iqKp
|
||||
* Referenced by: '<S62>/cf_iqKp'
|
||||
*/
|
||||
2458U,
|
||||
|
||||
/* Variable: cf_nKp
|
||||
* Referenced by: '<S61>/cf_nKp'
|
||||
*/
|
||||
9666U,
|
||||
|
||||
/* Variable: cf_currFilt
|
||||
* Referenced by: '<S50>/cf_currFilt'
|
||||
*/
|
||||
7864U,
|
||||
|
||||
/* Variable: cf_idKi
|
||||
* Referenced by: '<S63>/cf_idKi1'
|
||||
*/
|
||||
1474U,
|
||||
|
||||
/* Variable: cf_iqKi
|
||||
* Referenced by: '<S62>/cf_iqKi'
|
||||
*/
|
||||
2458U,
|
||||
|
||||
/* Variable: cf_iqKiLimProt
|
||||
* Referenced by:
|
||||
* '<S81>/cf_iqKiLimProt'
|
||||
* '<S83>/cf_iqKiLimProt'
|
||||
*/
|
||||
1474U,
|
||||
|
||||
/* Variable: cf_nKi
|
||||
* Referenced by: '<S61>/cf_nKi'
|
||||
*/
|
||||
502U,
|
||||
|
||||
/* Variable: cf_nKiLimProt
|
||||
* Referenced by:
|
||||
* '<S82>/cf_nKiLimProt'
|
||||
* '<S83>/cf_nKiLimProt'
|
||||
*/
|
||||
492U,
|
||||
|
||||
/* Variable: n_polePairs
|
||||
* Referenced by: '<S15>/n_polePairs'
|
||||
*/
|
||||
15U,
|
||||
|
||||
/* Variable: z_ctrlTypSel
|
||||
* Referenced by: '<S1>/z_ctrlTypSel'
|
||||
*/
|
||||
2U,
|
||||
|
||||
/* Variable: z_selPhaCurMeasABC
|
||||
* Referenced by: '<S49>/z_selPhaCurMeasABC'
|
||||
*/
|
||||
0U,
|
||||
|
||||
/* Variable: b_angleMeasEna
|
||||
* Referenced by:
|
||||
* '<S3>/b_angleMeasEna'
|
||||
* '<S13>/b_angleMeasEna'
|
||||
*/
|
||||
0,
|
||||
|
||||
/* Variable: b_cruiseCtrlEna
|
||||
* Referenced by: '<S1>/b_cruiseCtrlEna'
|
||||
*/
|
||||
0,
|
||||
|
||||
/* Variable: b_diagEna
|
||||
* Referenced by: '<S4>/b_diagEna'
|
||||
*/
|
||||
1,
|
||||
|
||||
/* Variable: b_fieldWeakEna
|
||||
* Referenced by:
|
||||
* '<S6>/b_fieldWeakEna'
|
||||
* '<S97>/b_fieldWeakEna'
|
||||
*/
|
||||
0
|
||||
}; /* Modifiable parameters */
|
||||
|
||||
/*
|
||||
* File trailer for generated code.
|
||||
*
|
||||
* [EOF]
|
||||
*/
|
||||
@@ -0,0 +1,311 @@
|
||||
#ifndef BLDC_H
|
||||
#define BLDC_H
|
||||
|
||||
#include "board/body/bldc/bldc_defs.h"
|
||||
#include "board/body/boards/board_declarations.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "board/stm32h7/lladc.h"
|
||||
|
||||
// Matlab includes and defines - from auto-code generation
|
||||
#include "BLDC_controller.h" /* Model's header file */
|
||||
#include "BLDC_controller.c"
|
||||
#include "BLDC_controller_data.c"
|
||||
#include "rtwtypes.h"
|
||||
|
||||
static RT_MODEL rtM_Left_Obj;
|
||||
static RT_MODEL rtM_Right_Obj;
|
||||
|
||||
RT_MODEL *const rtM_Left = &rtM_Left_Obj;
|
||||
RT_MODEL *const rtM_Right = &rtM_Right_Obj;
|
||||
|
||||
static DW rtDW_Left; /* Observable states */
|
||||
static ExtU rtU_Left; /* External inputs */
|
||||
static ExtY rtY_Left; /* External outputs */
|
||||
extern P rtP_Left; // This is defined in BLDC_controller_data.c
|
||||
|
||||
static DW rtDW_Right; /* Observable states */
|
||||
static ExtU rtU_Right; /* External inputs */
|
||||
static ExtY rtY_Right; /* External outputs */
|
||||
static P rtP_Right; /* Parameters */
|
||||
|
||||
//static int16_t curDC_max = (I_DC_MAX * A2BIT_CONV);
|
||||
static int16_t curL_phaA = 0, curL_phaC = 0, curL_DC = 0;
|
||||
static int16_t curR_phaA = 0, curR_phaC = 0, curR_DC = 0;
|
||||
|
||||
volatile uint16_t batt_voltage_raw = 0;
|
||||
volatile uint16_t batt_percentage = 0;
|
||||
|
||||
volatile int rpm_left = 0;
|
||||
volatile int rpm_right = 0;
|
||||
|
||||
volatile bool enable_motors = 0; // initially motors are disabled for safety
|
||||
static bool enableFin = 0;
|
||||
|
||||
static const uint16_t pwm_res = ( (uint32_t)CORE_FREQ * 1000000U / 2U ) / PWM_FREQ;
|
||||
|
||||
static uint16_t offsetcount = 0;
|
||||
static uint32_t offsetrlA = 0;
|
||||
static uint32_t offsetrlC = 0;
|
||||
static uint32_t offsetrrA = 0;
|
||||
static uint32_t offsetrrC = 0;
|
||||
static uint32_t offsetdcl = 0;
|
||||
static uint32_t offsetdcr = 0;
|
||||
|
||||
#define ADC_CHANNEL_BLDC(a, c) {.adc = (a), .channel = (c), .sample_time = SAMPLETIME_16_CYCLES, .oversampling = OVERSAMPLING_4}
|
||||
|
||||
const adc_signal_t adc_curL_phaA = ADC_CHANNEL_BLDC(ADC2, 10);
|
||||
const adc_signal_t adc_curL_phaC = ADC_CHANNEL_BLDC(ADC2, 11);
|
||||
const adc_signal_t adc_curL_DC = ADC_CHANNEL_BLDC(ADC2, 18);
|
||||
const adc_signal_t adc_curR_phaA = ADC_CHANNEL_BLDC(ADC1, 7);
|
||||
const adc_signal_t adc_curR_phaC = ADC_CHANNEL_BLDC(ADC1, 15);
|
||||
const adc_signal_t adc_curR_DC = ADC_CHANNEL_BLDC(ADC1, 5);
|
||||
const adc_signal_t adc_batVoltage = ADC_CHANNEL_BLDC(ADC1, 4);
|
||||
|
||||
void motor_set_enable(bool enable) {
|
||||
enable_motors = enable;
|
||||
}
|
||||
|
||||
float motor_encoder_get_speed_rpm(uint8_t motor) {
|
||||
float speed_rpm = 0.0f;
|
||||
if (motor == BODY_MOTOR_LEFT) {
|
||||
speed_rpm = (float)rtY_Left.n_mot;
|
||||
} else if (motor == BODY_MOTOR_RIGHT) {
|
||||
speed_rpm = (float)rtY_Right.n_mot;
|
||||
}
|
||||
|
||||
if (ABS(speed_rpm) < RPM_DEADBAND) {
|
||||
speed_rpm = 0.0f;
|
||||
}
|
||||
|
||||
return speed_rpm;
|
||||
}
|
||||
|
||||
void bldc_init(void) {
|
||||
adc_init(ADC1);
|
||||
adc_init(ADC2);
|
||||
|
||||
// Initialize Hall Sensors for Left Motor (PB6, PB7, PB8)
|
||||
set_gpio_mode(GPIOB, 6, MODE_INPUT); set_gpio_pullup(GPIOB, 6, PULL_UP);
|
||||
set_gpio_mode(GPIOB, 7, MODE_INPUT); set_gpio_pullup(GPIOB, 7, PULL_UP);
|
||||
set_gpio_mode(GPIOB, 8, MODE_INPUT); set_gpio_pullup(GPIOB, 8, PULL_UP);
|
||||
|
||||
// Initialize Hall Sensors for Right Motor (PA0, PA1, PA2)
|
||||
set_gpio_mode(GPIOA, 0, MODE_INPUT); set_gpio_pullup(GPIOA, 0, PULL_UP);
|
||||
set_gpio_mode(GPIOA, 1, MODE_INPUT); set_gpio_pullup(GPIOA, 1, PULL_UP);
|
||||
set_gpio_mode(GPIOA, 2, MODE_INPUT); set_gpio_pullup(GPIOA, 2, PULL_UP);
|
||||
|
||||
// Setup the model pointers for Left motor
|
||||
rtM_Left->defaultParam = &rtP_Left;
|
||||
rtM_Left->inputs = &rtU_Left;
|
||||
rtM_Left->outputs = &rtY_Left;
|
||||
rtM_Left->dwork = &rtDW_Left;
|
||||
BLDC_controller_initialize(rtM_Left);
|
||||
|
||||
/* Set BLDC controller parameters */
|
||||
rtP_Left.b_angleMeasEna = 0; // Motor angle input: 0 = estimated angle, 1 = measured angle
|
||||
rtP_Left.z_selPhaCurMeasABC = 2; // Left motor measured current phases {Green, Blue} = {iA, iB}
|
||||
rtP_Left.z_ctrlTypSel = CTRL_TYP_SEL;
|
||||
rtP_Left.b_diagEna = DIAG_ENA;
|
||||
rtP_Left.i_max = (int16_t)(I_MOT_MAX * A2BIT_CONV) << 4;
|
||||
rtP_Left.n_max = N_MOT_MAX << 4;
|
||||
rtP_Left.b_fieldWeakEna = FIELD_WEAK_ENA;
|
||||
rtP_Left.id_fieldWeakMax = (int16_t)(FIELD_WEAK_MAX * A2BIT_CONV) << 4;
|
||||
rtP_Left.a_phaAdvMax = PHASE_ADV_MAX << 4;
|
||||
rtP_Left.r_fieldWeakHi = FIELD_WEAK_HI << 4;
|
||||
rtP_Left.r_fieldWeakLo = FIELD_WEAK_LO << 4;
|
||||
rtP_Left.z_maxCntRst = 4000;
|
||||
rtP_Left.cf_speedCoef = CF_SPEED_COEF;
|
||||
rtP_Left.t_errQual = 1280U; // 80ms at 16kHz loop rate
|
||||
rtP_Left.t_errDequal = T_ERR_DEQUAL_CYCLES;
|
||||
|
||||
// Setup the model pointers for Right motor
|
||||
rtP_Right = rtP_Left; // copy parameters
|
||||
// Right motor measured current phases A & C (based on adc_curR_phaA/C definitions)
|
||||
rtP_Right.z_selPhaCurMeasABC = 2;
|
||||
rtM_Right->defaultParam = &rtP_Right;
|
||||
rtM_Right->inputs = &rtU_Right;
|
||||
rtM_Right->outputs = &rtY_Right;
|
||||
rtM_Right->dwork = &rtDW_Right;
|
||||
BLDC_controller_initialize(rtM_Right);
|
||||
|
||||
// Initialize GPIOs for Motor Control
|
||||
// Left Motor (TIM1): PE8(CH1N), PE9(CH1), PE10(CH2N), PE11(CH2), PE12(CH3N), PE13(CH3)
|
||||
set_gpio_alternate(GPIOE, 8, GPIO_AF1_TIM1);
|
||||
set_gpio_alternate(GPIOE, 9, GPIO_AF1_TIM1);
|
||||
set_gpio_alternate(GPIOE, 10, GPIO_AF1_TIM1);
|
||||
set_gpio_alternate(GPIOE, 11, GPIO_AF1_TIM1);
|
||||
set_gpio_alternate(GPIOE, 12, GPIO_AF1_TIM1);
|
||||
set_gpio_alternate(GPIOE, 13, GPIO_AF1_TIM1);
|
||||
|
||||
// Right Motor (TIM8): PC6(CH1), PC7(CH2), PC8(CH3), PA5(CH1N), PB14(CH2N), PB15(CH3N)
|
||||
set_gpio_alternate(GPIOC, 6, GPIO_AF3_TIM8);
|
||||
set_gpio_alternate(GPIOC, 7, GPIO_AF3_TIM8);
|
||||
set_gpio_alternate(GPIOC, 8, GPIO_AF3_TIM8);
|
||||
set_gpio_alternate(GPIOA, 5, GPIO_AF3_TIM8);
|
||||
set_gpio_alternate(GPIOB, 14, GPIO_AF3_TIM8);
|
||||
set_gpio_alternate(GPIOB, 15, GPIO_AF3_TIM8);
|
||||
|
||||
// --- LEFT MOTOR (TIM1) ---
|
||||
// TIM8 is an advanced control timer. We configure it for 3-phase center-aligned PWM.
|
||||
LEFT_TIM->PSC = 0;
|
||||
LEFT_TIM->ARR = pwm_res; // Set auto-reload register for PWM_FREQ
|
||||
LEFT_TIM->CR1 = TIM_CR1_CMS_0; // Center-aligned mode 1
|
||||
LEFT_TIM->RCR = 1; // Update event once per 2 PWM periods (16kHz)
|
||||
|
||||
// Configure channel 1, 2, 3 as PWM mode 1, with preload enabled
|
||||
LEFT_TIM->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE | \
|
||||
TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE;
|
||||
LEFT_TIM->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE;
|
||||
|
||||
// Enable complementary outputs for channels 1, 2, 3
|
||||
LEFT_TIM->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE | \
|
||||
TIM_CCER_CC2E | TIM_CCER_CC2NE | \
|
||||
TIM_CCER_CC3E | TIM_CCER_CC3NE;
|
||||
|
||||
// --- RIGHT MOTOR (TIM8) ---
|
||||
RIGHT_TIM->PSC = 0;
|
||||
RIGHT_TIM->ARR = pwm_res;
|
||||
RIGHT_TIM->CR1 = TIM_CR1_CMS_0;
|
||||
RIGHT_TIM->RCR = 1;
|
||||
|
||||
RIGHT_TIM->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE | \
|
||||
TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE;
|
||||
RIGHT_TIM->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE;
|
||||
|
||||
RIGHT_TIM->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE | \
|
||||
TIM_CCER_CC2E | TIM_CCER_CC2NE | \
|
||||
TIM_CCER_CC3E | TIM_CCER_CC3NE;
|
||||
|
||||
// Set dead time (20 cycles -> ~166ns with 120MHz clock) and enable motor outputs
|
||||
LEFT_TIM->BDTR = 20U | TIM_BDTR_MOE;
|
||||
RIGHT_TIM->BDTR = 20U | TIM_BDTR_MOE;
|
||||
|
||||
// Generate an update event to load the registers
|
||||
LEFT_TIM->EGR = TIM_EGR_UG;
|
||||
RIGHT_TIM->EGR = TIM_EGR_UG;
|
||||
|
||||
// Enable TIM8 update interrupt for bldc_step
|
||||
LEFT_TIM->DIER |= TIM_DIER_UIE;
|
||||
|
||||
// Start the timers
|
||||
LEFT_TIM->CR1 |= TIM_CR1_CEN;
|
||||
RIGHT_TIM->CR1 |= TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
void bldc_step(void) {
|
||||
// Calibrate ADC offsets for the first few cycles
|
||||
if(offsetcount < 2000) { // calibrate ADC offsets
|
||||
offsetcount++;
|
||||
uint32_t rawL_A = adc_get_raw(&adc_curL_phaA);
|
||||
uint32_t rawL_C = adc_get_raw(&adc_curL_phaC);
|
||||
uint32_t rawR_A = adc_get_raw(&adc_curR_phaA);
|
||||
uint32_t rawR_C = adc_get_raw(&adc_curR_phaC);
|
||||
uint32_t rawL_DC = adc_get_raw(&adc_curL_DC);
|
||||
uint32_t rawR_DC = adc_get_raw(&adc_curR_DC);
|
||||
|
||||
if (offsetcount == 1) {
|
||||
offsetrlA = rawL_A; offsetrlC = rawL_C;
|
||||
offsetrrA = rawR_A; offsetrrC = rawR_C;
|
||||
offsetdcl = rawL_DC; offsetdcr = rawR_DC;
|
||||
} else {
|
||||
offsetrlA = (rawL_A + offsetrlA) / 2;
|
||||
offsetrlC = (rawL_C + offsetrlC) / 2;
|
||||
offsetrrA = (rawR_A + offsetrrA) / 2;
|
||||
offsetrrC = (rawR_C + offsetrrC) / 2;
|
||||
offsetdcl = (rawL_DC + offsetdcl) / 2;
|
||||
offsetdcr = (rawR_DC + offsetdcr) / 2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Get Left motor currents
|
||||
curL_phaA = (int16_t)(((int32_t)offsetrlA - (int32_t)adc_get_raw(&adc_curL_phaA)) >> 5);
|
||||
curL_phaC = (int16_t)(((int32_t)offsetrlC - (int32_t)adc_get_raw(&adc_curL_phaC)) >> 5);
|
||||
curL_DC = (int16_t)(((int32_t)offsetdcl - (int32_t)adc_get_raw(&adc_curL_DC)) >> 4);
|
||||
|
||||
// Get Right motor currents
|
||||
curR_phaA = (int16_t)(((int32_t)offsetrrA - (int32_t)adc_get_raw(&adc_curR_phaA)) >> 5);
|
||||
curR_phaC = (int16_t)(((int32_t)offsetrrC - (int32_t)adc_get_raw(&adc_curR_phaC)) >> 5);
|
||||
curR_DC = (int16_t)(((int32_t)offsetdcr - (int32_t)adc_get_raw(&adc_curR_DC)) >> 4);
|
||||
|
||||
// Safety: Don't enable if offsets are bogus (e.g. ADC failed)
|
||||
if (offsetrrA == 0 || offsetrrC == 0 || !enable_motors) {
|
||||
enableFin = 0;
|
||||
} else {
|
||||
enableFin = 1;
|
||||
}
|
||||
|
||||
// Read Hall Sensors
|
||||
rtU_Left.b_hallA = !((GPIOB->IDR >> 6) & 1);
|
||||
rtU_Left.b_hallB = !((GPIOB->IDR >> 7) & 1);
|
||||
rtU_Left.b_hallC = !((GPIOB->IDR >> 8) & 1);
|
||||
|
||||
rtU_Right.b_hallA = !((GPIOA->IDR >> 0) & 1);
|
||||
rtU_Right.b_hallB = !((GPIOA->IDR >> 1) & 1);
|
||||
rtU_Right.b_hallC = !((GPIOA->IDR >> 2) & 1);
|
||||
|
||||
if (!enableFin) {
|
||||
LEFT_TIM->BDTR &= ~TIM_BDTR_MOE;
|
||||
RIGHT_TIM->BDTR &= ~TIM_BDTR_MOE;
|
||||
} else {
|
||||
LEFT_TIM->BDTR |= TIM_BDTR_MOE;
|
||||
RIGHT_TIM->BDTR |= TIM_BDTR_MOE;
|
||||
}
|
||||
|
||||
// read battery voltage
|
||||
batt_voltage_raw = adc_get_raw(&adc_batVoltage);
|
||||
|
||||
int16_t batVoltageCalib = batt_voltage_raw * BAT_CALIB_REAL_VOLTAGE / BAT_CALIB_ADC;
|
||||
batt_percentage = 100 - (((420 * BAT_CELLS) - batVoltageCalib) / BAT_CELLS / VOLTS_PER_PERCENT / 100);
|
||||
|
||||
// ========================= LEFT MOTOR ===========================
|
||||
rtU_Left.b_motEna = enableFin;
|
||||
rtU_Left.z_ctrlModReq = CTRL_MOD_REQ; // Speed Mode
|
||||
int deadband_rpm_left = rpm_left;
|
||||
if (ABS(deadband_rpm_left) < RPM_DEADBAND) {
|
||||
deadband_rpm_left = 0;
|
||||
}
|
||||
rtU_Left.r_inpTgt = (CLAMP((int)deadband_rpm_left, -MAX_RPM, MAX_RPM) * RPM_TO_UNIT);
|
||||
|
||||
rtU_Left.i_phaAB = curL_phaA;
|
||||
rtU_Left.i_phaBC = curL_phaC;
|
||||
rtU_Left.i_DCLink = curL_DC;
|
||||
|
||||
BLDC_controller_step(rtM_Left);
|
||||
|
||||
int ul = rtY_Left.DC_phaA;
|
||||
int vl = rtY_Left.DC_phaB;
|
||||
int wl = rtY_Left.DC_phaC;
|
||||
|
||||
LEFT_TIM->CCR1 = (uint16_t)CLAMP((ul + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
|
||||
LEFT_TIM->CCR2 = (uint16_t)CLAMP((vl + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
|
||||
LEFT_TIM->CCR3 = (uint16_t)CLAMP((wl + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
|
||||
|
||||
// ========================= RIGHT MOTOR ===========================
|
||||
rtU_Right.b_motEna = enableFin;
|
||||
rtU_Right.z_ctrlModReq = CTRL_MOD_REQ; // Speed Mode
|
||||
int deadband_rpm_right = rpm_right;
|
||||
if (ABS(deadband_rpm_right) < RPM_DEADBAND) {
|
||||
deadband_rpm_right = 0;
|
||||
}
|
||||
rtU_Right.r_inpTgt = -(CLAMP((int)deadband_rpm_right, -MAX_RPM, MAX_RPM) * RPM_TO_UNIT);
|
||||
|
||||
rtU_Right.i_phaAB = curR_phaA;
|
||||
rtU_Right.i_phaBC = curR_phaC;
|
||||
rtU_Right.i_DCLink = curR_DC;
|
||||
|
||||
BLDC_controller_step(rtM_Right);
|
||||
|
||||
int ur = rtY_Right.DC_phaA;
|
||||
int vr = rtY_Right.DC_phaB;
|
||||
int wr = rtY_Right.DC_phaC;
|
||||
|
||||
RIGHT_TIM->CCR1 = (uint16_t)CLAMP((ur + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
|
||||
RIGHT_TIM->CCR2 = (uint16_t)CLAMP((vr + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
|
||||
RIGHT_TIM->CCR3 = (uint16_t)CLAMP((wr + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef BLDC_DEFS_H
|
||||
#define BLDC_DEFS_H
|
||||
|
||||
#include "stm32h7xx.h" // For GPIO_TypeDef
|
||||
|
||||
#define COM_CTRL 0 // [-] Commutation Control Type
|
||||
#define SIN_CTRL 1 // [-] Sinusoidal Control Type
|
||||
#define FOC_CTRL 2 // [-] Field Oriented Control (FOC) Type
|
||||
|
||||
#define LEFT_TIM TIM8
|
||||
#define RIGHT_TIM TIM1
|
||||
|
||||
#define PWM_FREQ 32000
|
||||
#define PWM_MARGIN 100
|
||||
#define CF_SPEED_COEF (PWM_FREQ / 3)
|
||||
#define MAX_RPM 1000
|
||||
#define RPM_TO_UNIT 16
|
||||
#define RPM_DEADBAND 1
|
||||
|
||||
#define BODY_MOTOR_LEFT 1U
|
||||
#define BODY_MOTOR_RIGHT 2U
|
||||
|
||||
// Stall detection recovery time. Time to wait after a stall before re-enabling controls.
|
||||
#define STALL_DEQUAL_TIME_MS 3000
|
||||
#define T_ERR_DEQUAL_CYCLES (uint16_t)(STALL_DEQUAL_TIME_MS * (PWM_FREQ / 2) / 1000)
|
||||
|
||||
// Motor
|
||||
#define I_DC_MAX 6
|
||||
#define I_MOT_MAX 6
|
||||
#define A2BIT_CONV 310
|
||||
#define N_MOT_MAX 1000
|
||||
|
||||
// Control selections
|
||||
#define CTRL_TYP_SEL FOC_CTRL // [-] Control type selection: COM_CTRL, SIN_CTRL, FOC_CTRL (default)
|
||||
#define CTRL_MOD_REQ SPD_MODE // [-] Control mode request: OPEN_MODE, VLT_MODE (default), SPD_MODE, TRQ_MODE. Note: SPD_MODE and TRQ_MODE are only available for CTRL_FOC!
|
||||
#define DIAG_ENA 1 // [-] Motor Diagnostics enable flag: 0 = Disabled, 1 = Enabled (default)
|
||||
|
||||
// Field Weakening / Phase Advance
|
||||
#define FIELD_WEAK_ENA 1 // [-] Field Weakening / Phase Advance enable flag: 0 = Disabled (default), 1 = Enabled
|
||||
#define FIELD_WEAK_MAX 5 // [A] Maximum Field Weakening D axis current (only for FOC).
|
||||
#define PHASE_ADV_MAX 25 // [deg] Maximum Phase Advance angle (only for SIN).
|
||||
#define FIELD_WEAK_HI 1000 // Input target High threshold
|
||||
#define FIELD_WEAK_LO 750 // Input target Low threshold
|
||||
|
||||
// Battery configuration
|
||||
#define BAT_CELLS 3 // 3 sets in series
|
||||
#define BAT_CELL_FULL_MV 4200U // mV per cell at 100%
|
||||
#define BAT_CELL_EMPTY_MV 3386U // mV per cell at 0% (from V1: 4200 - 100 * 8.14)
|
||||
#define VOLTS_PER_PERCENT 0.00814 // Volts per percent, for conversion of volts to percentage
|
||||
#define BAT_CALIB_REAL_VOLTAGE 1260U // multimeter voltage
|
||||
#define BAT_CALIB_ADC 1275U // adc reading voltage
|
||||
|
||||
void bldc_init(void);
|
||||
void bldc_step(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* File: rtwtypes.h
|
||||
*
|
||||
* Code generated for Simulink model 'BLDC_controller'.
|
||||
*
|
||||
* Model version : 1.1297
|
||||
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
|
||||
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
|
||||
*
|
||||
* Target selection: ert.tlc
|
||||
* Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||
* Emulation hardware selection:
|
||||
* Differs from embedded hardware (MATLAB Host)
|
||||
* Code generation objectives:
|
||||
* 1. Execution efficiency
|
||||
* 2. RAM efficiency
|
||||
* Validation result: Not run
|
||||
*/
|
||||
|
||||
#ifndef RTWTYPES_H
|
||||
#define RTWTYPES_H
|
||||
|
||||
/* Logical type definitions */
|
||||
#if (!defined(__cplusplus))
|
||||
# ifndef false
|
||||
# define false (0U)
|
||||
# endif
|
||||
|
||||
# ifndef true
|
||||
# define true (1U)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*=======================================================================*
|
||||
* Target hardware information
|
||||
* Device type: MATLAB Host
|
||||
* Number of bits: char: 8 short: 16 int: 32
|
||||
* long: 32 long long: 64
|
||||
* native word size: 64
|
||||
* Byte ordering: LittleEndian
|
||||
* Signed integer division rounds to: Zero
|
||||
* Shift right on a signed integer as arithmetic shift: on
|
||||
*=======================================================================*/
|
||||
|
||||
/*=======================================================================*
|
||||
* Fixed width word size data types: *
|
||||
* int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
|
||||
* uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
|
||||
* real32_T, real64_T - 32 and 64 bit floating point numbers *
|
||||
*=======================================================================*/
|
||||
typedef signed char int8_T;
|
||||
typedef unsigned char uint8_T;
|
||||
typedef short int16_T;
|
||||
typedef unsigned short uint16_T;
|
||||
typedef int int32_T;
|
||||
typedef unsigned int uint32_T;
|
||||
typedef long long int64_T;
|
||||
typedef unsigned long long uint64_T;
|
||||
typedef float real32_T;
|
||||
typedef double real64_T;
|
||||
|
||||
/*===========================================================================*
|
||||
* Generic type definitions: boolean_T, char_T, byte_T, int_T, uint_T, *
|
||||
* real_T, time_T, ulong_T, ulonglong_T. *
|
||||
*===========================================================================*/
|
||||
typedef double real_T;
|
||||
typedef double time_T;
|
||||
typedef unsigned char boolean_T;
|
||||
typedef int int_T;
|
||||
typedef unsigned int uint_T;
|
||||
typedef unsigned long ulong_T;
|
||||
typedef unsigned long long ulonglong_T;
|
||||
typedef char char_T;
|
||||
typedef unsigned char uchar_T;
|
||||
typedef char_T byte_T;
|
||||
|
||||
/*=======================================================================*
|
||||
* Min and Max: *
|
||||
* int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
|
||||
* uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
|
||||
*=======================================================================*/
|
||||
#define MAX_int8_T ((int8_T)(127))
|
||||
#define MIN_int8_T ((int8_T)(-128))
|
||||
#define MAX_uint8_T ((uint8_T)(255U))
|
||||
#define MAX_int16_T ((int16_T)(32767))
|
||||
#define MIN_int16_T ((int16_T)(-32768))
|
||||
#define MAX_uint16_T ((uint16_T)(65535U))
|
||||
#define MAX_int32_T ((int32_T)(2147483647))
|
||||
#define MIN_int32_T ((int32_T)(-2147483647-1))
|
||||
#define MAX_uint32_T ((uint32_T)(0xFFFFFFFFU))
|
||||
#define MAX_int64_T ((int64_T)(9223372036854775807LL))
|
||||
#define MIN_int64_T ((int64_T)(-9223372036854775807LL-1LL))
|
||||
#define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFULL))
|
||||
|
||||
/* Block D-Work pointer type */
|
||||
typedef void * pointer_T;
|
||||
|
||||
#endif /* RTWTYPES_H */
|
||||
|
||||
/*
|
||||
* File trailer for generated code.
|
||||
*
|
||||
* [EOF]
|
||||
*/
|
||||
@@ -1,21 +1,46 @@
|
||||
#include "board/body/motor_control.h"
|
||||
#include "board/body/boards/board_declarations.h"
|
||||
|
||||
void board_body_init(void) {
|
||||
motor_init();
|
||||
motor_encoder_init();
|
||||
motor_speed_controller_init();
|
||||
motor_encoder_reset(1);
|
||||
motor_encoder_reset(2);
|
||||
|
||||
// Initialize CAN pins
|
||||
set_gpio_pullup(GPIOD, 0, PULL_NONE);
|
||||
set_gpio_alternate(GPIOD, 0, GPIO_AF9_FDCAN1);
|
||||
set_gpio_pullup(GPIOD, 1, PULL_NONE);
|
||||
set_gpio_alternate(GPIOD, 1, GPIO_AF9_FDCAN1);
|
||||
set_gpio_pullup(CAN_RX_PORT, CAN_RX_PIN, PULL_NONE);
|
||||
set_gpio_alternate(CAN_RX_PORT, CAN_RX_PIN, GPIO_AF9_FDCAN1);
|
||||
set_gpio_pullup(CAN_TX_PORT, CAN_TX_PIN, PULL_NONE);
|
||||
set_gpio_alternate(CAN_TX_PORT, CAN_TX_PIN, GPIO_AF9_FDCAN1);
|
||||
|
||||
// Initialize button input (PC15)
|
||||
set_gpio_mode(IGNITION_SW_PORT, IGNITION_SW_PIN, MODE_INPUT);
|
||||
SYSCFG->EXTICR[3] &= ~(SYSCFG_EXTICR4_EXTI15);
|
||||
SYSCFG->EXTICR[3] |= SYSCFG_EXTICR4_EXTI15_PC;
|
||||
EXTI->PR1 = (1U << 15);
|
||||
EXTI->RTSR1 |= (1U << 15);
|
||||
EXTI->FTSR1 |= (1U << 15);
|
||||
EXTI->IMR1 |= (1U << 15);
|
||||
|
||||
// Initialize barrel jack detection input (PC13)
|
||||
set_gpio_pullup(CHARGING_DETECT_PORT, CHARGING_DETECT_PIN, PULL_UP);
|
||||
set_gpio_mode(CHARGING_DETECT_PORT, CHARGING_DETECT_PIN, MODE_INPUT);
|
||||
SYSCFG->EXTICR[3] &= ~(SYSCFG_EXTICR4_EXTI13);
|
||||
SYSCFG->EXTICR[3] |= SYSCFG_EXTICR4_EXTI13_PC;
|
||||
EXTI->PR1 = (1U << 13);
|
||||
EXTI->RTSR1 |= (1U << 13);
|
||||
EXTI->FTSR1 |= (1U << 13);
|
||||
EXTI->IMR1 |= (1U << 13);
|
||||
|
||||
// Initialize and turn on mici power
|
||||
set_gpio_mode(OBDC_POWER_ON_PORT, OBDC_POWER_ON_PIN, MODE_OUTPUT);
|
||||
set_gpio_output(OBDC_POWER_ON_PORT, OBDC_POWER_ON_PIN, 1);
|
||||
|
||||
// Initialize and turn off gpu power
|
||||
set_gpio_mode(GPU_POWER_ON_PORT, GPU_POWER_ON_PIN, MODE_OUTPUT);
|
||||
set_gpio_output(GPU_POWER_ON_PORT, GPU_POWER_ON_PIN, 0);
|
||||
|
||||
// Initialize and turn off ignition output
|
||||
set_gpio_mode(OBDC_IGNITION_ON_PORT, OBDC_IGNITION_ON_PIN, MODE_OUTPUT);
|
||||
set_gpio_output(OBDC_IGNITION_ON_PORT, OBDC_IGNITION_ON_PIN, 0);
|
||||
}
|
||||
|
||||
board board_body = {
|
||||
.led_GPIO = {GPIOC, GPIOC, GPIOC},
|
||||
.led_pin = {7, 7, 7},
|
||||
.led_GPIO = {GPIOA, GPIOA, GPIOA},
|
||||
.led_pin = {10, 10, 10},
|
||||
.init = board_body_init,
|
||||
};
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "board/body/bldc/bldc_defs.h"
|
||||
|
||||
// ******************** Prototypes ********************
|
||||
typedef void (*board_init)(void);
|
||||
@@ -19,3 +20,36 @@ struct board {
|
||||
|
||||
// ******************* Definitions ********************
|
||||
#define HW_TYPE_BODY 0xB1U
|
||||
|
||||
// Pin definitions
|
||||
// CAN
|
||||
#define CAN_TX_PORT GPIOD
|
||||
#define CAN_TX_PIN 1
|
||||
#define CAN_RX_PORT GPIOD
|
||||
#define CAN_RX_PIN 0
|
||||
#define CAN_TRANSCEIVER_EN_PORT GPIOD
|
||||
#define CAN_TRANSCEIVER_EN_PIN 12
|
||||
|
||||
// Ignition and charging detection
|
||||
#define IGNITION_SW_PORT GPIOC
|
||||
#define IGNITION_SW_PIN 15
|
||||
#define CHARGING_DETECT_PORT GPIOC
|
||||
#define CHARGING_DETECT_PIN 13
|
||||
|
||||
// Dotstar LED
|
||||
#define DOTSTAR_CLK_PORT GPIOB
|
||||
#define DOTSTAR_CLK_PIN 3
|
||||
#define DOTSTAR_DATA_PORT GPIOB
|
||||
#define DOTSTAR_DATA_PIN 5
|
||||
|
||||
// Mici Power On
|
||||
#define OBDC_POWER_ON_PORT GPIOB
|
||||
#define OBDC_POWER_ON_PIN 12
|
||||
|
||||
// GPU Power On
|
||||
#define GPU_POWER_ON_PORT GPIOD
|
||||
#define GPU_POWER_ON_PIN 8
|
||||
|
||||
// Ignition On
|
||||
#define OBDC_IGNITION_ON_PORT GPIOB
|
||||
#define OBDC_IGNITION_ON_PIN 11
|
||||
|
||||
+73
-31
@@ -5,65 +5,95 @@
|
||||
|
||||
#include "board/can.h"
|
||||
#include "board/health.h"
|
||||
#include "board/body/motor_control.h"
|
||||
#include "board/drivers/can_common_declarations.h"
|
||||
#include "board/body/boards/board_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
#include "opendbc/safety/declarations.h"
|
||||
#include "board/body/bldc/bldc.h"
|
||||
|
||||
#define BODY_CAN_ADDR_MOTOR_SPEED 0x201U
|
||||
#define BODY_CAN_MOTOR_SPEED_PERIOD_US 10000U
|
||||
#define BODY_BUS_NUMBER 0U
|
||||
#define BODY_CAN_ADDR_MOTOR_SPEED 0x201U
|
||||
#define BODY_CAN_ADDR_VAR_VALUES 0x202U
|
||||
#define BODY_CAN_ADDR_BODY_DATA 0x203U
|
||||
#define BODY_CAN_ADDR_V2_ID 0x222U
|
||||
#define BODY_CAN_MOTOR_SPEED_PERIOD_US 10000U
|
||||
#define BODY_CAN_CMD_TIMEOUT_US 100000U
|
||||
#define BODY_BUS_NUMBER 0U
|
||||
|
||||
static struct {
|
||||
bool pending;
|
||||
int32_t left_target_deci_rpm;
|
||||
int32_t right_target_deci_rpm;
|
||||
} body_can_command;
|
||||
static uint32_t last_can_cmd_timestamp_us = 0U;
|
||||
static uint16_t counter = 0U;
|
||||
|
||||
void body_can_send_motor_speeds(uint8_t bus, float left_speed_rpm, float right_speed_rpm) {
|
||||
CANPacket_t pkt;
|
||||
CANPacket_t pkt = {0};
|
||||
pkt.bus = bus;
|
||||
pkt.addr = BODY_CAN_ADDR_MOTOR_SPEED;
|
||||
pkt.returned = 0;
|
||||
pkt.rejected = 0;
|
||||
pkt.extended = 0;
|
||||
pkt.fd = 0;
|
||||
pkt.data_len_code = 8;
|
||||
int16_t left_speed_deci = left_speed_rpm * 10;
|
||||
int16_t right_speed_deci = right_speed_rpm * 10;
|
||||
int16_t left_speed_deci = left_speed_rpm;
|
||||
int16_t right_speed_deci = -(right_speed_rpm);
|
||||
pkt.data[0] = (uint8_t)((left_speed_deci >> 8) & 0xFFU);
|
||||
pkt.data[1] = (uint8_t)(left_speed_deci & 0xFFU);
|
||||
pkt.data[2] = (uint8_t)((right_speed_deci >> 8) & 0xFFU);
|
||||
pkt.data[3] = (uint8_t)(right_speed_deci & 0xFFU);
|
||||
pkt.data[4] = 0U;
|
||||
pkt.data[5] = 0U;
|
||||
pkt.data[6] = 0U;
|
||||
pkt.data[7] = 0U;
|
||||
pkt.data[6] = counter & 0xFFU;
|
||||
can_set_checksum(&pkt);
|
||||
can_send(&pkt, bus, true);
|
||||
counter++;
|
||||
}
|
||||
|
||||
void body_can_send_var_values(uint8_t bus, bool ignition, bool enable_motors, uint8_t fault, uint8_t left_z_errcode, uint8_t right_z_errcode) {
|
||||
CANPacket_t pkt = {0};
|
||||
pkt.bus = bus;
|
||||
pkt.addr = BODY_CAN_ADDR_VAR_VALUES;
|
||||
pkt.data_len_code = 3;
|
||||
pkt.data[0] = (ignition ? 1U : 0U) | ((enable_motors ? 1U : 0U) << 1U) | ((fault & 0x3FU) << 2U);
|
||||
pkt.data[1] = left_z_errcode;
|
||||
pkt.data[2] = right_z_errcode;
|
||||
can_set_checksum(&pkt);
|
||||
can_send(&pkt, bus, true);
|
||||
}
|
||||
|
||||
void body_can_send_body_data(uint8_t bus, uint8_t mcu_temp_raw, uint16_t batt_voltage_raw, uint8_t batt_percentage, bool charger_connected) {
|
||||
CANPacket_t pkt = {0};
|
||||
pkt.bus = bus;
|
||||
pkt.addr = BODY_CAN_ADDR_BODY_DATA;
|
||||
pkt.data_len_code = 4;
|
||||
pkt.data[0] = mcu_temp_raw;
|
||||
pkt.data[1] = (uint8_t)((batt_voltage_raw >> 8) & 0xFFU);
|
||||
pkt.data[2] = (uint8_t)(batt_voltage_raw & 0xFFU);
|
||||
pkt.data[3] = (charger_connected ? 1U : 0U) | ((batt_percentage & 0x7FU) << 1U);
|
||||
can_set_checksum(&pkt);
|
||||
can_send(&pkt, bus, true);
|
||||
}
|
||||
|
||||
void body_can_process_target(int16_t left_target_deci_rpm, int16_t right_target_deci_rpm) {
|
||||
body_can_command.left_target_deci_rpm = (int32_t)left_target_deci_rpm;
|
||||
body_can_command.right_target_deci_rpm = (int32_t)right_target_deci_rpm;
|
||||
body_can_command.pending = true;
|
||||
rpm_left = (int)(((float)left_target_deci_rpm) * 0.1f);
|
||||
rpm_right = (int)(((float)right_target_deci_rpm) * 0.1f);
|
||||
last_can_cmd_timestamp_us = microsecond_timer_get();
|
||||
}
|
||||
|
||||
void body_can_rx(CANPacket_t *msg) {
|
||||
if ((msg->addr == 0x250U) && (GET_LEN(msg) >= 4U)) {
|
||||
int16_t left_target_deci_rpm = (int16_t)((msg->data[0] << 8U) | msg->data[1]);
|
||||
int16_t right_target_deci_rpm = (int16_t)((msg->data[2] << 8U) | msg->data[3]);
|
||||
body_can_process_target(left_target_deci_rpm, right_target_deci_rpm);
|
||||
}
|
||||
}
|
||||
|
||||
void body_can_init(void) {
|
||||
body_can_command.pending = false;
|
||||
last_can_cmd_timestamp_us = 0U;
|
||||
can_silent = false;
|
||||
can_loopback = false;
|
||||
(void)set_safety_hooks(SAFETY_BODY, 0U);
|
||||
set_gpio_output(GPIOD, 2U, 0); // Enable CAN transceiver
|
||||
set_gpio_output(CAN_TRANSCEIVER_EN_PORT, CAN_TRANSCEIVER_EN_PIN, 0); // Enable CAN transceiver
|
||||
can_init_all();
|
||||
}
|
||||
|
||||
void body_can_periodic(uint32_t now) {
|
||||
if (body_can_command.pending) {
|
||||
body_can_command.pending = false;
|
||||
float left_target_rpm = ((float)body_can_command.left_target_deci_rpm) * 0.1f;
|
||||
float right_target_rpm = ((float)body_can_command.right_target_deci_rpm) * 0.1f;
|
||||
motor_speed_controller_set_target_rpm(BODY_MOTOR_LEFT, left_target_rpm);
|
||||
motor_speed_controller_set_target_rpm(BODY_MOTOR_RIGHT, right_target_rpm);
|
||||
void body_can_periodic(uint32_t now, bool ignition, bool plug_charging) {
|
||||
if ((last_can_cmd_timestamp_us != 0U) &&
|
||||
((now - last_can_cmd_timestamp_us) >= BODY_CAN_CMD_TIMEOUT_US)) {
|
||||
rpm_left = 0;
|
||||
rpm_right = 0;
|
||||
last_can_cmd_timestamp_us = 0U;
|
||||
}
|
||||
|
||||
static uint32_t last_motor_speed_tx_us = 0;
|
||||
@@ -71,6 +101,18 @@ void body_can_periodic(uint32_t now) {
|
||||
float left_speed_rpm = motor_encoder_get_speed_rpm(BODY_MOTOR_LEFT);
|
||||
float right_speed_rpm = motor_encoder_get_speed_rpm(BODY_MOTOR_RIGHT);
|
||||
body_can_send_motor_speeds(BODY_BUS_NUMBER, left_speed_rpm, right_speed_rpm);
|
||||
body_can_send_var_values(BODY_BUS_NUMBER, ignition, enable_motors, 0U, rtY_Left.z_errCode, rtY_Right.z_errCode);
|
||||
body_can_send_body_data(BODY_BUS_NUMBER, 0U, batt_voltage_raw, batt_percentage, plug_charging);
|
||||
|
||||
// Send message on 0x222 to identify as body v2
|
||||
CANPacket_t id_pkt = {0};
|
||||
id_pkt.bus = BODY_BUS_NUMBER;
|
||||
id_pkt.addr = BODY_CAN_ADDR_V2_ID;
|
||||
id_pkt.data_len_code = 1;
|
||||
id_pkt.data[0] = 1U;
|
||||
can_set_checksum(&id_pkt);
|
||||
can_send(&id_pkt, BODY_BUS_NUMBER, true);
|
||||
|
||||
last_motor_speed_tx_us = now;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board/config.h"
|
||||
#include "board/body/boards/board_declarations.h"
|
||||
|
||||
#define DOTSTAR_LED_COUNT 10U
|
||||
#define DOTSTAR_GLOBAL_BRIGHTNESS_MAX 31U
|
||||
|
||||
typedef struct {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} dotstar_rgb_t;
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
uint8_t global_brightness;
|
||||
dotstar_rgb_t pixels[DOTSTAR_LED_COUNT];
|
||||
} dotstar_state_t;
|
||||
|
||||
static dotstar_state_t dotstar_state = {
|
||||
.initialized = false,
|
||||
.global_brightness = DOTSTAR_GLOBAL_BRIGHTNESS_MAX,
|
||||
};
|
||||
|
||||
static inline void dotstar_set_clk(bool high) {
|
||||
if (high) {
|
||||
DOTSTAR_CLK_PORT->BSRR = (uint32_t)(1U << DOTSTAR_CLK_PIN);
|
||||
} else {
|
||||
DOTSTAR_CLK_PORT->BSRR = (uint32_t)(1U << (DOTSTAR_CLK_PIN + 16U));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dotstar_set_data(bool high) {
|
||||
if (high) {
|
||||
DOTSTAR_DATA_PORT->BSRR = (uint32_t)(1U << DOTSTAR_DATA_PIN);
|
||||
} else {
|
||||
DOTSTAR_DATA_PORT->BSRR = (uint32_t)(1U << (DOTSTAR_DATA_PIN + 16U));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dotstar_write_byte(uint8_t value) {
|
||||
for (int8_t bit = 7; bit >= 0; bit--) {
|
||||
dotstar_set_data(((value >> bit) & 0x1U) != 0U);
|
||||
delay(15);
|
||||
dotstar_set_clk(true);
|
||||
delay(15);
|
||||
dotstar_set_clk(false);
|
||||
delay(15);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint16_t dotstar_latch_len(uint16_t led_count) {
|
||||
uint16_t len = (uint16_t)((led_count + 15U) / 16U);
|
||||
if (len < led_count) {
|
||||
len = led_count;
|
||||
}
|
||||
return (len < 4U) ? 4U : len;
|
||||
}
|
||||
|
||||
static inline void dotstar_send_start_frame(void) {
|
||||
for (uint8_t i = 0U; i < 4U; i++) {
|
||||
dotstar_write_byte(0x00U);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dotstar_send_end_frame(uint16_t led_count) {
|
||||
uint16_t latch_len = dotstar_latch_len(led_count);
|
||||
for (uint16_t i = 0U; i < latch_len; i++) {
|
||||
dotstar_write_byte(0xFFU);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dotstar_show(void) {
|
||||
if (!dotstar_state.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
dotstar_send_start_frame();
|
||||
|
||||
uint8_t prefix = (uint8_t)(0xE0U | dotstar_state.global_brightness);
|
||||
for (uint16_t i = 0U; i < DOTSTAR_LED_COUNT; i++) {
|
||||
dotstar_rgb_t *pixel = &dotstar_state.pixels[i];
|
||||
dotstar_write_byte(prefix);
|
||||
dotstar_write_byte(pixel->b);
|
||||
dotstar_write_byte(pixel->g);
|
||||
dotstar_write_byte(pixel->r);
|
||||
}
|
||||
|
||||
dotstar_send_end_frame(DOTSTAR_LED_COUNT);
|
||||
}
|
||||
|
||||
static inline void dotstar_init(void) {
|
||||
set_gpio_pullup(DOTSTAR_CLK_PORT, DOTSTAR_CLK_PIN, PULL_NONE);
|
||||
set_gpio_output_type(DOTSTAR_CLK_PORT, DOTSTAR_CLK_PIN, OUTPUT_TYPE_PUSH_PULL);
|
||||
set_gpio_mode(DOTSTAR_CLK_PORT, DOTSTAR_CLK_PIN, MODE_OUTPUT);
|
||||
register_set(&(DOTSTAR_CLK_PORT->OSPEEDR), GPIO_OSPEEDR_OSPEED5, GPIO_OSPEEDR_OSPEED5_Msk);
|
||||
dotstar_set_clk(false);
|
||||
|
||||
set_gpio_pullup(DOTSTAR_DATA_PORT, DOTSTAR_DATA_PIN, PULL_NONE);
|
||||
set_gpio_output_type(DOTSTAR_DATA_PORT, DOTSTAR_DATA_PIN, OUTPUT_TYPE_PUSH_PULL);
|
||||
set_gpio_mode(DOTSTAR_DATA_PORT, DOTSTAR_DATA_PIN, MODE_OUTPUT);
|
||||
register_set(&(DOTSTAR_DATA_PORT->OSPEEDR), GPIO_OSPEEDR_OSPEED5, GPIO_OSPEEDR_OSPEED5_Msk);
|
||||
dotstar_set_data(false);
|
||||
|
||||
dotstar_state.initialized = true;
|
||||
dotstar_state.global_brightness = DOTSTAR_GLOBAL_BRIGHTNESS_MAX;
|
||||
|
||||
for (uint16_t i = 0U; i < DOTSTAR_LED_COUNT; i++) {
|
||||
dotstar_state.pixels[i].r = 0U;
|
||||
dotstar_state.pixels[i].g = 0U;
|
||||
dotstar_state.pixels[i].b = 0U;
|
||||
}
|
||||
|
||||
dotstar_show();
|
||||
}
|
||||
|
||||
static inline void dotstar_set_pixel(uint16_t index, uint8_t r, uint8_t g, uint8_t b) {
|
||||
if (!dotstar_state.initialized || (index >= DOTSTAR_LED_COUNT)) {
|
||||
return;
|
||||
}
|
||||
dotstar_state.pixels[index].r = r;
|
||||
dotstar_state.pixels[index].g = g;
|
||||
dotstar_state.pixels[index].b = b;
|
||||
}
|
||||
|
||||
static inline void dotstar_fill(uint8_t r, uint8_t g, uint8_t b) {
|
||||
if (!dotstar_state.initialized) {
|
||||
return;
|
||||
}
|
||||
for (uint16_t i = 0U; i < DOTSTAR_LED_COUNT; i++) {
|
||||
dotstar_state.pixels[i].r = r;
|
||||
dotstar_state.pixels[i].g = g;
|
||||
dotstar_state.pixels[i].b = b;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dotstar_set_global_brightness(uint8_t brightness) {
|
||||
dotstar_state.global_brightness = (brightness > DOTSTAR_GLOBAL_BRIGHTNESS_MAX) ? DOTSTAR_GLOBAL_BRIGHTNESS_MAX : brightness;
|
||||
}
|
||||
|
||||
static inline void dotstar_hue_to_rgb(uint16_t hue, uint8_t *r, uint8_t *g, uint8_t *b) {
|
||||
hue %= 765U;
|
||||
if (hue < 255U) {
|
||||
*r = (uint8_t)(255U - hue);
|
||||
*g = (uint8_t)hue;
|
||||
*b = 0U;
|
||||
} else if (hue < 510U) {
|
||||
hue -= 255U;
|
||||
*r = 0U;
|
||||
*g = (uint8_t)(255U - hue);
|
||||
*b = (uint8_t)hue;
|
||||
} else {
|
||||
hue -= 510U;
|
||||
*r = (uint8_t)hue;
|
||||
*g = 0U;
|
||||
*b = (uint8_t)(255U - hue);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dotstar_run_rainbow(uint32_t now_us) {
|
||||
uint32_t brightness_phase = (now_us / 40000U) % 62U;
|
||||
uint8_t brightness = (brightness_phase <= 31U) ? (uint8_t)(brightness_phase + 1U) : (uint8_t)(62U - brightness_phase);
|
||||
if (brightness == 0U) {
|
||||
brightness = 1U;
|
||||
}
|
||||
dotstar_set_global_brightness(brightness);
|
||||
|
||||
uint32_t base_hue = (now_us / 10000U) % 765U;
|
||||
for (uint16_t i = 0U; i < DOTSTAR_LED_COUNT; i++) {
|
||||
uint16_t hue = (uint16_t)((base_hue + (i * 70U)) % 765U);
|
||||
uint8_t r, g, b;
|
||||
dotstar_hue_to_rgb(hue, &r, &g, &b);
|
||||
dotstar_set_pixel(i, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dotstar_apply_breathe(dotstar_rgb_t color, uint32_t now_us, uint32_t cycle_us) {
|
||||
if (!dotstar_state.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cycle_us == 0U) {
|
||||
dotstar_set_global_brightness(DOTSTAR_GLOBAL_BRIGHTNESS_MAX);
|
||||
dotstar_fill(color.r, color.g, color.b);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t phase = now_us % cycle_us;
|
||||
uint32_t half_cycle = cycle_us / 2U;
|
||||
if (half_cycle == 0U) {
|
||||
half_cycle = 1U;
|
||||
}
|
||||
|
||||
uint32_t amplitude = (phase <= half_cycle) ? phase : (cycle_us - phase);
|
||||
uint32_t scale = (amplitude * 255U) / half_cycle;
|
||||
if (scale > 255U) {
|
||||
scale = 255U;
|
||||
}
|
||||
|
||||
uint8_t r = (uint8_t)((color.r * scale) / 255U);
|
||||
uint8_t g = (uint8_t)((color.g * scale) / 255U);
|
||||
uint8_t b = (uint8_t)((color.b * scale) / 255U);
|
||||
|
||||
dotstar_set_global_brightness(DOTSTAR_GLOBAL_BRIGHTNESS_MAX);
|
||||
dotstar_fill(r, g, b);
|
||||
}
|
||||
+70
-7
@@ -7,17 +7,23 @@
|
||||
#include "board/drivers/usb.h"
|
||||
#include "board/early_init.h"
|
||||
#include "board/obj/gitversion.h"
|
||||
#include "board/body/motor_control.h"
|
||||
#include "board/body/can.h"
|
||||
#include "opendbc/safety/safety.h"
|
||||
#include "board/drivers/can_common.h"
|
||||
#include "board/drivers/fdcan.h"
|
||||
#include "board/can_comms.h"
|
||||
#include "board/body/dotstar.h"
|
||||
#include "bldc/bldc.h"
|
||||
|
||||
extern int _app_start[0xc000];
|
||||
|
||||
#include "board/body/main_comms.h"
|
||||
|
||||
static volatile uint32_t tick_count = 0U;
|
||||
static volatile uint32_t ignition_press_timestamp_us = 0U;
|
||||
static volatile bool ignition = false;
|
||||
static volatile bool plug_charging = false;
|
||||
|
||||
void debug_ring_callback(uart_ring *ring) {
|
||||
char rcv;
|
||||
while (get_char(ring, &rcv)) {
|
||||
@@ -34,7 +40,12 @@ void __initialize_hardware_early(void) {
|
||||
early_initialization();
|
||||
}
|
||||
|
||||
volatile uint32_t tick_count = 0;
|
||||
void bldc_tim8_handler(void) {
|
||||
if ((LEFT_TIM->SR & TIM_SR_UIF) != 0) {
|
||||
LEFT_TIM->SR = ~TIM_SR_UIF;
|
||||
bldc_step();
|
||||
}
|
||||
}
|
||||
|
||||
void tick_handler(void) {
|
||||
if (TICK_TIMER->SR != 0) {
|
||||
@@ -49,6 +60,32 @@ void tick_handler(void) {
|
||||
TICK_TIMER->SR = 0;
|
||||
}
|
||||
|
||||
static void exti15_10_handler(void) {
|
||||
if ((EXTI->PR1 & (1U << CHARGING_DETECT_PIN)) != 0U) {
|
||||
EXTI->PR1 = (1U << CHARGING_DETECT_PIN);
|
||||
plug_charging = (get_gpio_input(CHARGING_DETECT_PORT, CHARGING_DETECT_PIN) != 0);
|
||||
}
|
||||
|
||||
if ((EXTI->PR1 & (1U << IGNITION_SW_PIN)) != 0U) {
|
||||
EXTI->PR1 = (1U << IGNITION_SW_PIN);
|
||||
|
||||
static uint32_t last_press_event_us = 0U;
|
||||
const uint32_t debounce_us = 200000U; // 200 ms
|
||||
|
||||
uint32_t now = microsecond_timer_get();
|
||||
bool pressed = (get_gpio_input(IGNITION_SW_PORT, IGNITION_SW_PIN) == 0);
|
||||
|
||||
if (pressed) {
|
||||
if (get_ts_elapsed(now, last_press_event_us) > debounce_us) {
|
||||
last_press_event_us = now;
|
||||
ignition_press_timestamp_us = now;
|
||||
ignition = !ignition;
|
||||
set_gpio_output(OBDC_IGNITION_ON_PORT, OBDC_IGNITION_ON_PIN, ignition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
disable_interrupts();
|
||||
init_interrupts(true);
|
||||
@@ -60,7 +97,15 @@ int main(void) {
|
||||
hw_type = HW_TYPE_BODY;
|
||||
|
||||
current_board->init();
|
||||
|
||||
|
||||
REGISTER_INTERRUPT(EXTI15_10_IRQn, exti15_10_handler, 10000U, FAULT_INTERRUPT_RATE_EXTI);
|
||||
NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
|
||||
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
||||
|
||||
REGISTER_INTERRUPT(TIM8_UP_TIM13_IRQn, bldc_tim8_handler, 100000U, FAULT_INTERRUPT_RATE_TICK);
|
||||
NVIC_ClearPendingIRQ(TIM8_UP_TIM13_IRQn);
|
||||
NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
|
||||
|
||||
REGISTER_INTERRUPT(TICK_TIMER_IRQ, tick_handler, 10U, FAULT_INTERRUPT_RATE_TICK);
|
||||
|
||||
led_init();
|
||||
@@ -68,14 +113,32 @@ int main(void) {
|
||||
tick_timer_init();
|
||||
usb_init();
|
||||
body_can_init();
|
||||
|
||||
dotstar_init();
|
||||
bldc_init();
|
||||
enable_interrupts();
|
||||
|
||||
plug_charging = (get_gpio_input(CHARGING_DETECT_PORT, CHARGING_DETECT_PIN) != 0);
|
||||
|
||||
while (true) {
|
||||
uint32_t now = microsecond_timer_get();
|
||||
motor_speed_controller_update(now);
|
||||
body_can_periodic(now);
|
||||
if (plug_charging) {
|
||||
motor_set_enable(false);
|
||||
dotstar_apply_breathe((dotstar_rgb_t){255U, 40U, 0U}, now, 2000000U);
|
||||
} else if (ignition) {
|
||||
dotstar_run_rainbow(now);
|
||||
} else {
|
||||
dotstar_apply_breathe((dotstar_rgb_t){0U, 255U, 10U}, now, 1500000U);
|
||||
}
|
||||
|
||||
if (ignition) {
|
||||
motor_set_enable(true);
|
||||
body_can_periodic(now, ignition, plug_charging);
|
||||
} else {
|
||||
motor_set_enable(false);
|
||||
}
|
||||
|
||||
dotstar_show();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -54,47 +54,27 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
NVIC_SystemReset();
|
||||
break;
|
||||
|
||||
// **** 0xe0: set motor speed
|
||||
case 0xe0:
|
||||
motor_set_speed((uint8_t)req->param1, (int8_t)req->param2);
|
||||
break;
|
||||
|
||||
// **** 0xe1: stop motor
|
||||
case 0xe1:
|
||||
motor_set_speed((uint8_t)req->param1, 0);
|
||||
break;
|
||||
|
||||
// **** 0xe2: get motor encoder state
|
||||
case 0xe2: {
|
||||
uint8_t motor = (uint8_t)req->param1;
|
||||
int32_t position = motor_encoder_get_position(motor);
|
||||
float rpm = motor_encoder_get_speed_rpm(motor);
|
||||
int32_t rpm_milli = (int32_t)(rpm * 1000.0f);
|
||||
(void)memcpy(resp, &position, sizeof(position));
|
||||
(void)memcpy(resp + sizeof(position), &rpm_milli, sizeof(rpm_milli));
|
||||
resp_len = (uint8_t)(sizeof(position) + sizeof(rpm_milli));
|
||||
// **** 0xdd: get healthpacket and CANPacket version hashes
|
||||
case 0xdd: {
|
||||
uint32_t versions[2] = {HEALTH_PACKET_VERSION, CAN_PACKET_VERSION_HASH};
|
||||
(void)memcpy(resp, (uint8_t *)versions, sizeof(versions));
|
||||
resp_len = sizeof(versions);
|
||||
break;
|
||||
}
|
||||
|
||||
// **** 0xe3: reset encoder position
|
||||
case 0xe3:
|
||||
motor_encoder_reset((uint8_t)req->param1);
|
||||
// **** 0xb3: set motor speeds
|
||||
case 0xb3:
|
||||
rpm_left = (int16_t)req->param1;
|
||||
rpm_right = (int16_t)req->param2;
|
||||
break;
|
||||
|
||||
// **** 0xe4: set motor target speed (rpm * 0.1)
|
||||
case 0xe4: {
|
||||
uint8_t motor = (uint8_t)req->param1;
|
||||
float target_rpm = ((int16_t)req->param2) * 0.1f;
|
||||
motor_speed_controller_set_target_rpm(motor, target_rpm);
|
||||
break;
|
||||
}
|
||||
|
||||
// **** 0xdd: get healthpacket and CANPacket versions
|
||||
case 0xdd:
|
||||
resp[0] = HEALTH_PACKET_VERSION;
|
||||
resp[1] = CAN_PACKET_VERSION;
|
||||
resp[2] = CAN_HEALTH_PACKET_VERSION;
|
||||
resp_len = 3U;
|
||||
// **** 0xb4: enable/disable motors
|
||||
case 0xb4:
|
||||
enable_motors = (req->param1 == 1U);
|
||||
if (enable_motors == 0) {
|
||||
rpm_left = 0;
|
||||
rpm_right = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define BODY_MOTOR_COUNT 2U
|
||||
|
||||
typedef enum {
|
||||
BODY_MOTOR_LEFT = 1U,
|
||||
BODY_MOTOR_RIGHT = 2U,
|
||||
} body_motor_id_e;
|
||||
|
||||
static inline bool body_motor_is_valid(uint8_t motor) {
|
||||
return (motor > 0U) && (motor <= BODY_MOTOR_COUNT);
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board/body/motor_common.h"
|
||||
#include "board/body/motor_encoder.h"
|
||||
|
||||
// Motor pin map:
|
||||
// M1 drive: PB8 -> TIM16_CH1, PB9 -> TIM17_CH1, PE2/PE3 enables
|
||||
// M2 drive: PA2 -> TIM15_CH1, PA3 -> TIM15_CH2, PE8/PE9 enables
|
||||
|
||||
#define PWM_TIMER_CLOCK_HZ 120000000U
|
||||
#define PWM_FREQUENCY_HZ 5000U
|
||||
#define PWM_PERCENT_MAX 100
|
||||
#define PWM_RELOAD_TICKS ((PWM_TIMER_CLOCK_HZ + (PWM_FREQUENCY_HZ / 2U)) / PWM_FREQUENCY_HZ)
|
||||
|
||||
#define KP 0.25f
|
||||
#define KI 0.5f
|
||||
#define KD 0.008f
|
||||
#define KFF 0.9f
|
||||
#define MAX_RPM 100.0f
|
||||
#define OUTPUT_MAX 100.0f
|
||||
#define DEADBAND_RPM 1.0f
|
||||
#define UPDATE_PERIOD_US 1000U
|
||||
|
||||
typedef struct {
|
||||
TIM_TypeDef *forward_timer;
|
||||
uint8_t forward_channel;
|
||||
TIM_TypeDef *reverse_timer;
|
||||
uint8_t reverse_channel;
|
||||
GPIO_TypeDef *pwm_port[2];
|
||||
uint8_t pwm_pin[2];
|
||||
uint8_t pwm_af[2];
|
||||
GPIO_TypeDef *enable_port[2];
|
||||
uint8_t enable_pin[2];
|
||||
} motor_pwm_config_t;
|
||||
|
||||
static const motor_pwm_config_t motor_pwm_config[BODY_MOTOR_COUNT] = {
|
||||
[BODY_MOTOR_LEFT - 1U] = {
|
||||
TIM16, 1U, TIM17, 1U,
|
||||
{GPIOB, GPIOB}, {8U, 9U}, {GPIO_AF1_TIM16, GPIO_AF1_TIM17},
|
||||
{GPIOE, GPIOE}, {2U, 3U},
|
||||
},
|
||||
[BODY_MOTOR_RIGHT - 1U] = {
|
||||
TIM15, 2U, TIM15, 1U,
|
||||
{GPIOA, GPIOA}, {2U, 3U}, {GPIO_AF4_TIM15, GPIO_AF4_TIM15},
|
||||
{GPIOE, GPIOE}, {8U, 9U},
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool active;
|
||||
float target_rpm;
|
||||
float integral;
|
||||
float previous_error;
|
||||
float last_output;
|
||||
uint32_t last_update_us;
|
||||
} motor_speed_state_t;
|
||||
|
||||
static inline float motor_absf(float value) {
|
||||
return (value < 0.0f) ? -value : value;
|
||||
}
|
||||
|
||||
static inline float motor_clampf(float value, float min_value, float max_value) {
|
||||
if (value < min_value) {
|
||||
return min_value;
|
||||
}
|
||||
if (value > max_value) {
|
||||
return max_value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static motor_speed_state_t motor_speed_states[BODY_MOTOR_COUNT];
|
||||
|
||||
static inline void motor_pwm_write(TIM_TypeDef *timer, uint8_t channel, uint8_t percentage) {
|
||||
uint32_t period = (timer->ARR != 0U) ? timer->ARR : PWM_RELOAD_TICKS;
|
||||
uint16_t comp = (uint16_t)((period * (uint32_t)percentage) / 100U);
|
||||
if (channel == 1U) {
|
||||
register_set(&(timer->CCR1), comp, 0xFFFFU);
|
||||
} else if (channel == 2U) {
|
||||
register_set(&(timer->CCR2), comp, 0xFFFFU);
|
||||
}
|
||||
}
|
||||
|
||||
static inline motor_speed_state_t *motor_speed_state_get(uint8_t motor) {
|
||||
return body_motor_is_valid(motor) ? &motor_speed_states[motor - 1U] : NULL;
|
||||
}
|
||||
|
||||
static inline void motor_speed_state_reset(motor_speed_state_t *state) {
|
||||
state->active = false;
|
||||
state->target_rpm = 0.0f;
|
||||
state->integral = 0.0f;
|
||||
state->previous_error = 0.0f;
|
||||
state->last_output = 0.0f;
|
||||
state->last_update_us = 0U;
|
||||
}
|
||||
|
||||
static void motor_speed_controller_init(void) {
|
||||
for (uint8_t i = 0U; i < BODY_MOTOR_COUNT; i++) {
|
||||
motor_speed_state_reset(&motor_speed_states[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void motor_speed_controller_disable(uint8_t motor) {
|
||||
motor_speed_state_t *state = motor_speed_state_get(motor);
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
motor_speed_state_reset(state);
|
||||
}
|
||||
|
||||
static inline void motor_write_enable(uint8_t motor_index, bool enable) {
|
||||
const motor_pwm_config_t *cfg = &motor_pwm_config[motor_index];
|
||||
uint8_t level = enable ? 1U : 0U;
|
||||
set_gpio_output(cfg->enable_port[0], cfg->enable_pin[0], level);
|
||||
set_gpio_output(cfg->enable_port[1], cfg->enable_pin[1], level);
|
||||
}
|
||||
|
||||
static void motor_init(void) {
|
||||
register_set_bits(&(RCC->AHB4ENR), RCC_AHB4ENR_GPIOAEN | RCC_AHB4ENR_GPIOBEN | RCC_AHB4ENR_GPIOEEN);
|
||||
register_set_bits(&(RCC->APB2ENR), RCC_APB2ENR_TIM16EN | RCC_APB2ENR_TIM17EN | RCC_APB2ENR_TIM15EN);
|
||||
|
||||
for (uint8_t i = 0U; i < BODY_MOTOR_COUNT; i++) {
|
||||
const motor_pwm_config_t *cfg = &motor_pwm_config[i];
|
||||
motor_write_enable(i, false);
|
||||
set_gpio_alternate(cfg->pwm_port[0], cfg->pwm_pin[0], cfg->pwm_af[0]);
|
||||
set_gpio_alternate(cfg->pwm_port[1], cfg->pwm_pin[1], cfg->pwm_af[1]);
|
||||
|
||||
pwm_init(cfg->forward_timer, cfg->forward_channel);
|
||||
pwm_init(cfg->reverse_timer, cfg->reverse_channel);
|
||||
|
||||
TIM_TypeDef *forward_timer = cfg->forward_timer;
|
||||
register_set(&(forward_timer->PSC), 0U, 0xFFFFU);
|
||||
register_set(&(forward_timer->ARR), PWM_RELOAD_TICKS, 0xFFFFU);
|
||||
forward_timer->EGR |= TIM_EGR_UG;
|
||||
register_set(&(forward_timer->BDTR), TIM_BDTR_MOE, 0xFFFFU);
|
||||
|
||||
if (cfg->reverse_timer != cfg->forward_timer) {
|
||||
TIM_TypeDef *reverse_timer = cfg->reverse_timer;
|
||||
register_set(&(reverse_timer->PSC), 0U, 0xFFFFU);
|
||||
register_set(&(reverse_timer->ARR), PWM_RELOAD_TICKS, 0xFFFFU);
|
||||
reverse_timer->EGR |= TIM_EGR_UG;
|
||||
register_set(&(reverse_timer->BDTR), TIM_BDTR_MOE, 0xFFFFU);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void motor_apply_pwm(uint8_t motor, int32_t speed_command) {
|
||||
if (!body_motor_is_valid(motor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t speed = (int8_t)motor_clampf((float)speed_command, -(float)PWM_PERCENT_MAX, (float)PWM_PERCENT_MAX);
|
||||
uint8_t pwm_value = (uint8_t)((speed < 0) ? -speed : speed);
|
||||
uint8_t motor_index = motor - 1U;
|
||||
motor_write_enable(motor_index, speed != 0);
|
||||
const motor_pwm_config_t *cfg = &motor_pwm_config[motor_index];
|
||||
|
||||
if (speed > 0) {
|
||||
motor_pwm_write(cfg->forward_timer, cfg->forward_channel, pwm_value);
|
||||
motor_pwm_write(cfg->reverse_timer, cfg->reverse_channel, 0U);
|
||||
} else if (speed < 0) {
|
||||
motor_pwm_write(cfg->forward_timer, cfg->forward_channel, 0U);
|
||||
motor_pwm_write(cfg->reverse_timer, cfg->reverse_channel, pwm_value);
|
||||
} else {
|
||||
motor_pwm_write(cfg->forward_timer, cfg->forward_channel, 0U);
|
||||
motor_pwm_write(cfg->reverse_timer, cfg->reverse_channel, 0U);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void motor_set_speed(uint8_t motor, int8_t speed) {
|
||||
motor_speed_controller_disable(motor);
|
||||
motor_apply_pwm(motor, (int32_t)speed);
|
||||
}
|
||||
|
||||
static inline void motor_speed_controller_set_target_rpm(uint8_t motor, float target_rpm) {
|
||||
motor_speed_state_t *state = motor_speed_state_get(motor);
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
target_rpm = motor_clampf(target_rpm, -MAX_RPM, MAX_RPM);
|
||||
if (motor_absf(target_rpm) <= DEADBAND_RPM) {
|
||||
motor_speed_controller_disable(motor);
|
||||
motor_apply_pwm(motor, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
state->active = true;
|
||||
state->target_rpm = target_rpm;
|
||||
state->integral = 0.0f;
|
||||
state->previous_error = target_rpm - motor_encoder_get_speed_rpm(motor);
|
||||
state->last_output = 0.0f;
|
||||
state->last_update_us = 0U;
|
||||
}
|
||||
|
||||
static inline void motor_speed_controller_update(uint32_t now_us) {
|
||||
for (uint8_t motor = BODY_MOTOR_LEFT; motor <= BODY_MOTOR_RIGHT; motor++) {
|
||||
motor_speed_state_t *state = motor_speed_state_get(motor);
|
||||
if (!state->active) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool first_update = (state->last_update_us == 0U);
|
||||
uint32_t dt_us = first_update ? UPDATE_PERIOD_US : (now_us - state->last_update_us);
|
||||
if (!first_update && (dt_us < UPDATE_PERIOD_US)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float measured_rpm = motor_encoder_get_speed_rpm(motor);
|
||||
float error = state->target_rpm - measured_rpm;
|
||||
|
||||
if ((motor_absf(state->target_rpm) <= DEADBAND_RPM) && (motor_absf(error) <= DEADBAND_RPM) && (motor_absf(measured_rpm) <= DEADBAND_RPM)) {
|
||||
motor_speed_controller_disable(motor);
|
||||
motor_apply_pwm(motor, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
float dt_s = (float)dt_us * 1.0e-6f;
|
||||
float control = KFF * state->target_rpm;
|
||||
|
||||
if (dt_s > 0.0f) {
|
||||
state->integral += error * dt_s;
|
||||
float derivative = first_update ? 0.0f : (error - state->previous_error) / dt_s;
|
||||
|
||||
control += (KP * error) + (KI * state->integral) + (KD * derivative);
|
||||
} else {
|
||||
state->integral = 0.0f;
|
||||
control += KP * error;
|
||||
}
|
||||
|
||||
if ((state->target_rpm > 0.0f) && (control < 0.0f)) {
|
||||
control = 0.0f;
|
||||
state->integral = 0.0f;
|
||||
} else if ((state->target_rpm < 0.0f) && (control > 0.0f)) {
|
||||
control = 0.0f;
|
||||
state->integral = 0.0f;
|
||||
}
|
||||
|
||||
control = motor_clampf(control, -OUTPUT_MAX, OUTPUT_MAX);
|
||||
|
||||
int32_t command = (control >= 0.0f) ? (int32_t)(control + 0.5f) : (int32_t)(control - 0.5f);
|
||||
motor_apply_pwm(motor, command);
|
||||
|
||||
state->previous_error = error;
|
||||
state->last_output = control;
|
||||
state->last_update_us = now_us;
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board/body/motor_common.h"
|
||||
|
||||
// Encoder pin map:
|
||||
// Left motor: PB6 -> TIM4_CH1, PB7 -> TIM4_CH2
|
||||
// Right motor: PA6 -> TIM3_CH1, PA7 -> TIM3_CH2
|
||||
|
||||
typedef struct {
|
||||
TIM_TypeDef *timer;
|
||||
GPIO_TypeDef *pin_a_port;
|
||||
uint8_t pin_a;
|
||||
uint8_t pin_a_af;
|
||||
GPIO_TypeDef *pin_b_port;
|
||||
uint8_t pin_b;
|
||||
uint8_t pin_b_af;
|
||||
int8_t direction;
|
||||
uint32_t counts_per_output_rev;
|
||||
uint32_t min_dt_us;
|
||||
float speed_alpha;
|
||||
uint32_t filter;
|
||||
} motor_encoder_config_t;
|
||||
|
||||
typedef struct {
|
||||
const motor_encoder_config_t *config;
|
||||
uint16_t last_timer_count;
|
||||
int32_t accumulated_count;
|
||||
int32_t last_speed_count;
|
||||
uint32_t last_speed_timestamp_us;
|
||||
float cached_speed_rps;
|
||||
} motor_encoder_state_t;
|
||||
|
||||
static const motor_encoder_config_t motor_encoder_config[BODY_MOTOR_COUNT] = {
|
||||
[BODY_MOTOR_LEFT - 1U] = {
|
||||
.timer = TIM4,
|
||||
.pin_a_port = GPIOB, .pin_a = 6U, .pin_a_af = GPIO_AF2_TIM4,
|
||||
.pin_b_port = GPIOB, .pin_b = 7U, .pin_b_af = GPIO_AF2_TIM4,
|
||||
.direction = -1,
|
||||
.counts_per_output_rev = 44U * 90U,
|
||||
.min_dt_us = 250U,
|
||||
.speed_alpha = 0.2f,
|
||||
.filter = 3U,
|
||||
},
|
||||
[BODY_MOTOR_RIGHT - 1U] = {
|
||||
.timer = TIM3,
|
||||
.pin_a_port = GPIOA, .pin_a = 6U, .pin_a_af = GPIO_AF2_TIM3,
|
||||
.pin_b_port = GPIOA, .pin_b = 7U, .pin_b_af = GPIO_AF2_TIM3,
|
||||
.direction = 1,
|
||||
.counts_per_output_rev = 44U * 90U,
|
||||
.min_dt_us = 250U,
|
||||
.speed_alpha = 0.2f,
|
||||
.filter = 3U,
|
||||
},
|
||||
};
|
||||
|
||||
static motor_encoder_state_t motor_encoders[BODY_MOTOR_COUNT] = {
|
||||
{ .config = &motor_encoder_config[0] },
|
||||
{ .config = &motor_encoder_config[1] },
|
||||
};
|
||||
|
||||
static void motor_encoder_configure_gpio(const motor_encoder_config_t *cfg) {
|
||||
set_gpio_pullup(cfg->pin_a_port, cfg->pin_a, PULL_UP);
|
||||
set_gpio_output_type(cfg->pin_a_port, cfg->pin_a, OUTPUT_TYPE_PUSH_PULL);
|
||||
set_gpio_alternate(cfg->pin_a_port, cfg->pin_a, cfg->pin_a_af);
|
||||
|
||||
set_gpio_pullup(cfg->pin_b_port, cfg->pin_b, PULL_UP);
|
||||
set_gpio_output_type(cfg->pin_b_port, cfg->pin_b, OUTPUT_TYPE_PUSH_PULL);
|
||||
set_gpio_alternate(cfg->pin_b_port, cfg->pin_b, cfg->pin_b_af);
|
||||
}
|
||||
|
||||
static void motor_encoder_configure_timer(motor_encoder_state_t *state) {
|
||||
const motor_encoder_config_t *cfg = state->config;
|
||||
TIM_TypeDef *timer = cfg->timer;
|
||||
timer->CR1 = 0U;
|
||||
timer->CR2 = 0U;
|
||||
timer->SMCR = 0U;
|
||||
timer->DIER = 0U;
|
||||
timer->SR = 0U;
|
||||
timer->CCMR1 = (TIM_CCMR1_CC1S_0) | (TIM_CCMR1_CC2S_0) | (cfg->filter << TIM_CCMR1_IC1F_Pos) | (cfg->filter << TIM_CCMR1_IC2F_Pos);
|
||||
timer->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
|
||||
timer->PSC = 0U;
|
||||
timer->ARR = 0xFFFFU;
|
||||
timer->CNT = 0U;
|
||||
state->last_timer_count = 0U;
|
||||
state->accumulated_count = 0;
|
||||
state->last_speed_count = 0;
|
||||
state->cached_speed_rps = 0.0f;
|
||||
timer->SMCR = (TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1);
|
||||
timer->CR1 = TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
static void motor_encoder_init(void) {
|
||||
register_set_bits(&(RCC->APB1LENR), RCC_APB1LENR_TIM4EN | RCC_APB1LENR_TIM3EN);
|
||||
register_set_bits(&(RCC->APB1LRSTR), RCC_APB1LRSTR_TIM4RST | RCC_APB1LRSTR_TIM3RST);
|
||||
register_clear_bits(&(RCC->APB1LRSTR), RCC_APB1LRSTR_TIM4RST | RCC_APB1LRSTR_TIM3RST);
|
||||
|
||||
for (uint8_t i = 0U; i < BODY_MOTOR_COUNT; i++) {
|
||||
motor_encoder_state_t *state = &motor_encoders[i];
|
||||
const motor_encoder_config_t *cfg = state->config;
|
||||
motor_encoder_configure_gpio(cfg);
|
||||
motor_encoder_configure_timer(state);
|
||||
state->last_speed_timestamp_us = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int32_t motor_encoder_refresh(motor_encoder_state_t *state) {
|
||||
const motor_encoder_config_t *cfg = state->config;
|
||||
TIM_TypeDef *timer = cfg->timer;
|
||||
uint16_t raw = (uint16_t)timer->CNT;
|
||||
int32_t delta = (int16_t)(raw - state->last_timer_count);
|
||||
delta *= cfg->direction;
|
||||
state->last_timer_count = raw;
|
||||
state->accumulated_count += delta;
|
||||
return state->accumulated_count;
|
||||
}
|
||||
|
||||
static inline int32_t motor_encoder_get_position(uint8_t motor) {
|
||||
if (!body_motor_is_valid(motor)) {
|
||||
return 0;
|
||||
}
|
||||
motor_encoder_state_t *state = &motor_encoders[motor - 1U];
|
||||
return motor_encoder_refresh(state);
|
||||
}
|
||||
|
||||
static void motor_encoder_reset(uint8_t motor) {
|
||||
if (!body_motor_is_valid(motor)) {
|
||||
return;
|
||||
}
|
||||
motor_encoder_state_t *state = &motor_encoders[motor - 1U];
|
||||
state->config->timer->CNT = 0U;
|
||||
state->last_timer_count = 0U;
|
||||
state->accumulated_count = 0;
|
||||
state->last_speed_count = 0;
|
||||
state->last_speed_timestamp_us = 0U;
|
||||
state->cached_speed_rps = 0.0f;
|
||||
}
|
||||
|
||||
static float motor_encoder_get_speed_rpm(uint8_t motor) {
|
||||
if (!body_motor_is_valid(motor)) {
|
||||
return 0.0f;
|
||||
}
|
||||
motor_encoder_state_t *state = &motor_encoders[motor - 1U];
|
||||
|
||||
const motor_encoder_config_t *cfg = state->config;
|
||||
motor_encoder_refresh(state);
|
||||
|
||||
uint32_t now = microsecond_timer_get();
|
||||
if (state->last_speed_timestamp_us == 0U) {
|
||||
state->last_speed_timestamp_us = now;
|
||||
state->last_speed_count = state->accumulated_count;
|
||||
state->cached_speed_rps = 0.0f;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
uint32_t dt = now - state->last_speed_timestamp_us;
|
||||
int32_t delta = state->accumulated_count - state->last_speed_count;
|
||||
if ((dt < cfg->min_dt_us) || (delta == 0)) {
|
||||
return state->cached_speed_rps * 60.0f;
|
||||
}
|
||||
|
||||
state->last_speed_count = state->accumulated_count;
|
||||
state->last_speed_timestamp_us = now;
|
||||
|
||||
float counts_per_second = ((float)delta * 1000000.0f) / (float)dt;
|
||||
float new_speed_rps = (cfg->counts_per_output_rev != 0U) ? (counts_per_second / (float)cfg->counts_per_output_rev) : 0.0f;
|
||||
state->cached_speed_rps += cfg->speed_alpha * (new_speed_rps - state->cached_speed_rps);
|
||||
return state->cached_speed_rps * 60.0f;
|
||||
}
|
||||
@@ -11,8 +11,8 @@
|
||||
#include "board/early_init.h"
|
||||
#include "board/provision.h"
|
||||
|
||||
#include "crypto/rsa.h"
|
||||
#include "crypto/sha.h"
|
||||
#include "board/crypto/rsa.h"
|
||||
#include "board/crypto/sha.h"
|
||||
|
||||
#include "board/obj/cert.h"
|
||||
#include "board/obj/gitversion.h"
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
// ******************** Prototypes ********************
|
||||
void print(const char *a){ UNUSED(a); }
|
||||
void puth(uint8_t i){ UNUSED(i); }
|
||||
void puth2(uint8_t i){ UNUSED(i); }
|
||||
void puth4(uint8_t i){ UNUSED(i); }
|
||||
void puth(unsigned int i){ UNUSED(i); }
|
||||
void puth2(unsigned int i){ UNUSED(i); }
|
||||
__attribute__((unused)) static void puth4(unsigned int i){ UNUSED(i); }
|
||||
void hexdump(const void *a, int l){ UNUSED(a); UNUSED(l); }
|
||||
typedef struct board board;
|
||||
typedef struct harness_configuration harness_configuration;
|
||||
void pwm_init(TIM_TypeDef *TIM, uint8_t channel);
|
||||
void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage);
|
||||
// No UART support in bootloader
|
||||
typedef struct uart_ring {} uart_ring;
|
||||
uart_ring uart_ring_som_debug;
|
||||
typedef struct uart_ring uart_ring;
|
||||
void uart_init(uart_ring *q, int baud) { UNUSED(q); UNUSED(baud); }
|
||||
|
||||
// ********************* Globals **********************
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
a certain number of CANPacket_t. The transaction is split
|
||||
into multiple transfers or chunks.
|
||||
|
||||
CAN packet byte layout (wire format used by comms_can_{read,write}):
|
||||
+--------+--------+--------+--------+--------+--------+--------+------------------------------+
|
||||
| byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | ... byte 13 / byte 69 |
|
||||
+--------+--------+--------+--------+--------+--------+--------+------------------------------+
|
||||
| DLC | addr | addr | addr | flags | cksum | data0 | ... data7 / data63 |
|
||||
| bus | | | | | | | (classic CAN / CAN FD) |
|
||||
| fd | | | | | | | |
|
||||
+--------+--------+--------+--------+--------+--------+--------+------------------------------+
|
||||
Byte/bit fields:
|
||||
byte 0: DLC[7:4], bus[3:1], fd[0]
|
||||
bytes 1..4: (addr << 3) | (extended << 2) | (returned << 1) | rejected
|
||||
byte 5: checksum = XOR(header[0..4] + payload)
|
||||
bytes 6..13 (classic CAN, up to 8 bytes) / bytes 6..69 (CAN FD, up to 64 bytes): payload
|
||||
|
||||
USB/SPI transfer chunking used by this file:
|
||||
+--------------------------------------------+ ... +--------------------------------------------+
|
||||
| transport chunk 0 | | transport chunk N |
|
||||
+--------------------------------------------+ +--------------------------------------------+
|
||||
| concatenated CANPacket_t bytes | | continuation and/or next CANPacket_t bytes |
|
||||
| (no per-64-byte counter/header in protocol)| | |
|
||||
+--------------------------------------------+ +--------------------------------------------+
|
||||
|
||||
* comms_can_read outputs this buffer in chunks of a specified length.
|
||||
chunks are always the given length, except the last one.
|
||||
* comms_can_write reads in this buffer in chunks.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
uint8_t request;
|
||||
uint16_t param1;
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
// platform includes
|
||||
#ifdef STM32H7
|
||||
#include "board/stm32h7/stm32h7_config.h"
|
||||
#elif defined(STM32F4)
|
||||
#include "board/stm32f4/stm32f4_config.h"
|
||||
#else
|
||||
// TODO: uncomment this, cppcheck complains
|
||||
// building for tests
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// ********************* Critical section helpers *********************
|
||||
void enable_interrupts(void);
|
||||
void disable_interrupts(void);
|
||||
|
||||
extern uint8_t global_critical_depth;
|
||||
|
||||
#define ENTER_CRITICAL() \
|
||||
__disable_irq(); \
|
||||
global_critical_depth += 1U;
|
||||
|
||||
#define EXIT_CRITICAL() \
|
||||
global_critical_depth -= 1U; \
|
||||
if ((global_critical_depth == 0U) && interrupts_enabled) { \
|
||||
__enable_irq(); \
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "bootkick_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
bool bootkick_reset_triggered = false;
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
extern bool bootkick_reset_triggered;
|
||||
|
||||
void bootkick_tick(bool ignition, bool recent_heartbeat);
|
||||
@@ -1,219 +0,0 @@
|
||||
#include "bxcan_declarations.h"
|
||||
|
||||
// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE
|
||||
// CAN2_TX, CAN2_RX0, CAN2_SCE
|
||||
// CAN3_TX, CAN3_RX0, CAN3_SCE
|
||||
|
||||
CAN_TypeDef *cans[PANDA_CAN_CNT] = {CAN1, CAN2, CAN3};
|
||||
uint8_t can_irq_number[CAN_IRQS_ARRAY_SIZE][CAN_IRQS_ARRAY_SIZE] = {
|
||||
{ CAN1_TX_IRQn, CAN1_RX0_IRQn, CAN1_SCE_IRQn },
|
||||
{ CAN2_TX_IRQn, CAN2_RX0_IRQn, CAN2_SCE_IRQn },
|
||||
{ CAN3_TX_IRQn, CAN3_RX0_IRQn, CAN3_SCE_IRQn },
|
||||
};
|
||||
|
||||
bool can_set_speed(uint8_t can_number) {
|
||||
bool ret = true;
|
||||
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
|
||||
|
||||
ret &= llcan_set_speed(
|
||||
CANx,
|
||||
bus_config[bus_number].can_speed,
|
||||
can_loopback,
|
||||
can_silent
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void can_clear_send(CAN_TypeDef *CANx, uint8_t can_number) {
|
||||
can_health[can_number].can_core_reset_cnt += 1U;
|
||||
llcan_clear_send(CANx);
|
||||
}
|
||||
|
||||
void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) {
|
||||
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
uint32_t esr_reg = CANx->ESR;
|
||||
|
||||
can_health[can_number].bus_off = ((esr_reg & CAN_ESR_BOFF) >> CAN_ESR_BOFF_Pos);
|
||||
can_health[can_number].bus_off_cnt += can_health[can_number].bus_off;
|
||||
can_health[can_number].error_warning = ((esr_reg & CAN_ESR_EWGF) >> CAN_ESR_EWGF_Pos);
|
||||
can_health[can_number].error_passive = ((esr_reg & CAN_ESR_EPVF) >> CAN_ESR_EPVF_Pos);
|
||||
|
||||
can_health[can_number].last_error = ((esr_reg & CAN_ESR_LEC) >> CAN_ESR_LEC_Pos);
|
||||
if ((can_health[can_number].last_error != 0U) && (can_health[can_number].last_error != 7U)) {
|
||||
can_health[can_number].last_stored_error = can_health[can_number].last_error;
|
||||
}
|
||||
|
||||
can_health[can_number].receive_error_cnt = ((esr_reg & CAN_ESR_REC) >> CAN_ESR_REC_Pos);
|
||||
can_health[can_number].transmit_error_cnt = ((esr_reg & CAN_ESR_TEC) >> CAN_ESR_TEC_Pos);
|
||||
|
||||
can_health[can_number].irq0_call_rate = interrupts[can_irq_number[can_number][0]].call_rate;
|
||||
can_health[can_number].irq1_call_rate = interrupts[can_irq_number[can_number][1]].call_rate;
|
||||
can_health[can_number].irq2_call_rate = interrupts[can_irq_number[can_number][2]].call_rate;
|
||||
|
||||
if (ir_reg != 0U) {
|
||||
can_health[can_number].total_error_cnt += 1U;
|
||||
|
||||
// RX message lost due to FIFO overrun
|
||||
if ((CANx->RF0R & (CAN_RF0R_FOVR0)) != 0U) {
|
||||
can_health[can_number].total_rx_lost_cnt += 1U;
|
||||
CANx->RF0R &= ~(CAN_RF0R_FOVR0);
|
||||
}
|
||||
can_clear_send(CANx, can_number);
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************** CAN *****************************
|
||||
// CANx_SCE IRQ Handler
|
||||
static void can_sce(uint8_t can_number) {
|
||||
update_can_health_pkt(can_number, 1U);
|
||||
}
|
||||
|
||||
// CANx_TX IRQ Handler
|
||||
void process_can(uint8_t can_number) {
|
||||
if (can_number != 0xffU) {
|
||||
|
||||
ENTER_CRITICAL();
|
||||
|
||||
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
|
||||
|
||||
// check for empty mailbox
|
||||
CANPacket_t to_send;
|
||||
if ((CANx->TSR & (CAN_TSR_TERR0 | CAN_TSR_ALST0)) != 0U) { // last TX failed due to error arbitration lost
|
||||
can_health[can_number].total_tx_lost_cnt += 1U;
|
||||
CANx->TSR |= (CAN_TSR_TERR0 | CAN_TSR_ALST0);
|
||||
}
|
||||
if ((CANx->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
|
||||
// add successfully transmitted message to my fifo
|
||||
if ((CANx->TSR & CAN_TSR_RQCP0) == CAN_TSR_RQCP0) {
|
||||
if ((CANx->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
|
||||
CANPacket_t to_push;
|
||||
to_push.fd = 0U;
|
||||
to_push.returned = 1U;
|
||||
to_push.rejected = 0U;
|
||||
to_push.extended = (CANx->sTxMailBox[0].TIR >> 2) & 0x1U;
|
||||
to_push.addr = (to_push.extended != 0U) ? (CANx->sTxMailBox[0].TIR >> 3) : (CANx->sTxMailBox[0].TIR >> 21);
|
||||
to_push.data_len_code = CANx->sTxMailBox[0].TDTR & 0xFU;
|
||||
to_push.bus = bus_number;
|
||||
WORD_TO_BYTE_ARRAY(&to_push.data[0], CANx->sTxMailBox[0].TDLR);
|
||||
WORD_TO_BYTE_ARRAY(&to_push.data[4], CANx->sTxMailBox[0].TDHR);
|
||||
can_set_checksum(&to_push);
|
||||
|
||||
rx_buffer_overflow += can_push(&can_rx_q, &to_push) ? 0U : 1U;
|
||||
}
|
||||
|
||||
// clear interrupt
|
||||
// careful, this can also be cleared by requesting a transmission
|
||||
CANx->TSR |= CAN_TSR_RQCP0;
|
||||
}
|
||||
|
||||
if (can_pop(can_queues[bus_number], &to_send)) {
|
||||
if (can_check_checksum(&to_send)) {
|
||||
can_health[can_number].total_tx_cnt += 1U;
|
||||
// only send if we have received a packet
|
||||
CANx->sTxMailBox[0].TIR = ((to_send.extended != 0U) ? (to_send.addr << 3) : (to_send.addr << 21)) | (to_send.extended << 2);
|
||||
CANx->sTxMailBox[0].TDTR = to_send.data_len_code;
|
||||
BYTE_ARRAY_TO_WORD(CANx->sTxMailBox[0].TDLR, &to_send.data[0]);
|
||||
BYTE_ARRAY_TO_WORD(CANx->sTxMailBox[0].TDHR, &to_send.data[4]);
|
||||
// Send request TXRQ
|
||||
CANx->sTxMailBox[0].TIR |= 0x1U;
|
||||
} else {
|
||||
can_health[can_number].total_tx_checksum_error_cnt += 1U;
|
||||
}
|
||||
|
||||
refresh_can_tx_slots_available();
|
||||
}
|
||||
}
|
||||
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
// CANx_RX0 IRQ Handler
|
||||
// blink blue when we are receiving CAN messages
|
||||
void can_rx(uint8_t can_number) {
|
||||
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
|
||||
|
||||
while ((CANx->RF0R & CAN_RF0R_FMP0) != 0U) {
|
||||
can_health[can_number].total_rx_cnt += 1U;
|
||||
|
||||
// add to my fifo
|
||||
CANPacket_t to_push;
|
||||
|
||||
to_push.fd = 0U;
|
||||
to_push.returned = 0U;
|
||||
to_push.rejected = 0U;
|
||||
to_push.extended = (CANx->sFIFOMailBox[0].RIR >> 2) & 0x1U;
|
||||
to_push.addr = (to_push.extended != 0U) ? (CANx->sFIFOMailBox[0].RIR >> 3) : (CANx->sFIFOMailBox[0].RIR >> 21);
|
||||
to_push.data_len_code = CANx->sFIFOMailBox[0].RDTR & 0xFU;
|
||||
to_push.bus = bus_number;
|
||||
WORD_TO_BYTE_ARRAY(&to_push.data[0], CANx->sFIFOMailBox[0].RDLR);
|
||||
WORD_TO_BYTE_ARRAY(&to_push.data[4], CANx->sFIFOMailBox[0].RDHR);
|
||||
can_set_checksum(&to_push);
|
||||
|
||||
// forwarding (panda only)
|
||||
int bus_fwd_num = safety_fwd_hook(bus_number, to_push.addr);
|
||||
if (bus_fwd_num != -1) {
|
||||
CANPacket_t to_send;
|
||||
|
||||
to_send.fd = 0U;
|
||||
to_send.returned = 0U;
|
||||
to_send.rejected = 0U;
|
||||
to_send.extended = to_push.extended; // TXRQ
|
||||
to_send.addr = to_push.addr;
|
||||
to_send.bus = to_push.bus;
|
||||
to_send.data_len_code = to_push.data_len_code;
|
||||
(void)memcpy(to_send.data, to_push.data, dlc_to_len[to_push.data_len_code]);
|
||||
can_set_checksum(&to_send);
|
||||
|
||||
can_send(&to_send, bus_fwd_num, true);
|
||||
can_health[can_number].total_fwd_cnt += 1U;
|
||||
}
|
||||
|
||||
safety_rx_invalid += safety_rx_hook(&to_push) ? 0U : 1U;
|
||||
ignition_can_hook(&to_push);
|
||||
|
||||
led_set(LED_BLUE, true);
|
||||
rx_buffer_overflow += can_push(&can_rx_q, &to_push) ? 0U : 1U;
|
||||
|
||||
// next
|
||||
CANx->RF0R |= CAN_RF0R_RFOM0;
|
||||
}
|
||||
}
|
||||
|
||||
static void CAN1_TX_IRQ_Handler(void) { process_can(0); }
|
||||
static void CAN1_RX0_IRQ_Handler(void) { can_rx(0); }
|
||||
static void CAN1_SCE_IRQ_Handler(void) { can_sce(0); }
|
||||
|
||||
static void CAN2_TX_IRQ_Handler(void) { process_can(1); }
|
||||
static void CAN2_RX0_IRQ_Handler(void) { can_rx(1); }
|
||||
static void CAN2_SCE_IRQ_Handler(void) { can_sce(1); }
|
||||
|
||||
static void CAN3_TX_IRQ_Handler(void) { process_can(2); }
|
||||
static void CAN3_RX0_IRQ_Handler(void) { can_rx(2); }
|
||||
static void CAN3_SCE_IRQ_Handler(void) { can_sce(2); }
|
||||
|
||||
bool can_init(uint8_t can_number) {
|
||||
bool ret = false;
|
||||
|
||||
REGISTER_INTERRUPT(CAN1_TX_IRQn, CAN1_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_RX0_IRQn, CAN1_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_SCE_IRQn, CAN1_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN2_TX_IRQn, CAN2_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
|
||||
REGISTER_INTERRUPT(CAN2_RX0_IRQn, CAN2_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
|
||||
REGISTER_INTERRUPT(CAN2_SCE_IRQn, CAN2_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
|
||||
REGISTER_INTERRUPT(CAN3_TX_IRQn, CAN3_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
|
||||
REGISTER_INTERRUPT(CAN3_RX0_IRQn, CAN3_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
|
||||
REGISTER_INTERRUPT(CAN3_SCE_IRQn, CAN3_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
|
||||
|
||||
if (can_number != 0xffU) {
|
||||
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
ret &= can_set_speed(can_number);
|
||||
ret &= llcan_init(CANx);
|
||||
// in case there are queued up messages
|
||||
process_can(can_number);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE
|
||||
// CAN2_TX, CAN2_RX0, CAN2_SCE
|
||||
// CAN3_TX, CAN3_RX0, CAN3_SCE
|
||||
|
||||
#define CAN_IRQS_ARRAY_SIZE 3
|
||||
extern CAN_TypeDef *cans[PANDA_CAN_CNT];
|
||||
extern uint8_t can_irq_number[CAN_IRQS_ARRAY_SIZE][CAN_IRQS_ARRAY_SIZE];
|
||||
|
||||
bool can_set_speed(uint8_t can_number);
|
||||
void can_clear_send(CAN_TypeDef *CANx, uint8_t can_number);
|
||||
void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg);
|
||||
|
||||
// ***************************** CAN *****************************
|
||||
// CANx_TX IRQ Handler
|
||||
void process_can(uint8_t can_number);
|
||||
// CANx_RX0 IRQ Handler
|
||||
// blink blue when we are receiving CAN messages
|
||||
void can_rx(uint8_t can_number);
|
||||
bool can_init(uint8_t can_number);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "can_common_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
uint32_t safety_tx_blocked = 0;
|
||||
uint32_t safety_rx_invalid = 0;
|
||||
@@ -20,16 +20,15 @@ bool can_loopback = false;
|
||||
extern can_ring can_##x; \
|
||||
can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = (size), .elems = (CANPacket_t *)&(elems_##x) };
|
||||
|
||||
#define CAN_RX_BUFFER_SIZE 4096U
|
||||
#define CAN_TX_BUFFER_SIZE 416U
|
||||
|
||||
#ifdef STM32H7
|
||||
#define CAN_RX_BUFFER_SIZE 4096U
|
||||
#define CAN_TX_BUFFER_SIZE 416U
|
||||
// ITCM RAM and DTCM RAM are the fastest for Cortex-M7 core access
|
||||
__attribute__((section(".axisram"))) can_buffer(rx_q, CAN_RX_BUFFER_SIZE)
|
||||
__attribute__((section(".itcmram"))) can_buffer(tx1_q, CAN_TX_BUFFER_SIZE)
|
||||
__attribute__((section(".itcmram"))) can_buffer(tx2_q, CAN_TX_BUFFER_SIZE)
|
||||
#else
|
||||
#define CAN_RX_BUFFER_SIZE 512U
|
||||
#define CAN_TX_BUFFER_SIZE 52U
|
||||
#else // kept for PC
|
||||
can_buffer(rx_q, CAN_RX_BUFFER_SIZE)
|
||||
can_buffer(tx1_q, CAN_TX_BUFFER_SIZE)
|
||||
can_buffer(tx2_q, CAN_TX_BUFFER_SIZE)
|
||||
@@ -138,9 +137,6 @@ bus_config_t bus_config[PANDA_CAN_CNT] = {
|
||||
void can_init_all(void) {
|
||||
for (uint8_t i=0U; i < PANDA_CAN_CNT; i++) {
|
||||
bus_config[i].canfd_enabled = false;
|
||||
#ifndef CANFD
|
||||
bus_config[i].can_data_speed = 0U;
|
||||
#endif
|
||||
can_clear(can_queues[i]);
|
||||
(void)can_init(i);
|
||||
}
|
||||
@@ -160,18 +156,8 @@ void can_set_forwarding(uint8_t from, uint8_t to) {
|
||||
#endif
|
||||
|
||||
void ignition_can_hook(CANPacket_t *msg) {
|
||||
static bool volkswagen_meb_gear_seen = false;
|
||||
static int volkswagen_meb_gear = 5; // 5 = Park (VOLKSWAGEN_MEB_GEAR_P)
|
||||
|
||||
if (msg->bus == 0U) {
|
||||
int len = GET_LEN(msg);
|
||||
const int TESLA_DI_GEAR_P = 1;
|
||||
const int TOYOTA_GEAR_P = 32;
|
||||
const int TOYOTA_HYBRID_GEAR_P = 0;
|
||||
static bool tesla_gear_seen = false;
|
||||
static int tesla_gear = TESLA_DI_GEAR_P;
|
||||
static int toyota_gear = TOYOTA_GEAR_P;
|
||||
static int toyota_hybrid_gear = TOYOTA_HYBRID_GEAR_P;
|
||||
|
||||
// GM exception
|
||||
if ((msg->addr == 0x1F1U) && (len == 8)) {
|
||||
@@ -203,71 +189,25 @@ void ignition_can_hook(CANPacket_t *msg) {
|
||||
if ((counter == ((prev_counter_tesla + 1) % 16)) && (prev_counter_tesla != -1)) {
|
||||
// VCFRONT_LVPowerState->VCFRONT_vehiclePowerState
|
||||
int power_state = (msg->data[0] >> 5U) & 0x3U;
|
||||
bool tesla_in_park = !tesla_gear_seen || (tesla_gear == TESLA_DI_GEAR_P);
|
||||
ignition_can = (power_state == 0x3) && !tesla_in_park; // VEHICLE_POWER_STATE_DRIVE=3
|
||||
ignition_can = power_state == 0x3; // VEHICLE_POWER_STATE_DRIVE=3
|
||||
ignition_can_cnt = 0U;
|
||||
}
|
||||
prev_counter_tesla = counter;
|
||||
}
|
||||
|
||||
if ((msg->addr == 0x118U) && (len == 8)) {
|
||||
tesla_gear = (msg->data[2] >> 5) & 0x7;
|
||||
tesla_gear_seen = true;
|
||||
}
|
||||
|
||||
// Mazda exception
|
||||
if ((msg->addr == 0x9EU) && (len == 8)) {
|
||||
ignition_can = (msg->data[0] >> 5) == 0x6U;
|
||||
ignition_can_cnt = 0U;
|
||||
}
|
||||
|
||||
// Toyota/Lexus exception
|
||||
if ((msg->addr == 0x3BCU) && (len == 8)) {
|
||||
int gear = msg->data[1] & 0x3FU;
|
||||
if ((gear == 0) || (gear == 1) || (gear == 8) || (gear == 16) || (gear == 32)) {
|
||||
toyota_gear = gear;
|
||||
ignition_can = toyota_gear != TOYOTA_GEAR_P;
|
||||
ignition_can_cnt = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
if ((msg->addr == 0x127U) && (len == 8)) {
|
||||
int gear = (msg->data[5] >> 4U) & 0xFU;
|
||||
if (gear <= 4) {
|
||||
toyota_hybrid_gear = gear;
|
||||
ignition_can = toyota_hybrid_gear != TOYOTA_HYBRID_GEAR_P;
|
||||
ignition_can_cnt = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Volkswagen MEB exception (Klemmen_Status_01 and gear messages)
|
||||
// On gateway harness cars these messages are on bus 1 (powertrain CAN), not bus 0.
|
||||
if ((msg->bus == 0U) || (msg->bus == 1U)) {
|
||||
int len = GET_LEN(msg);
|
||||
const int VOLKSWAGEN_MEB_GEAR_P = 5;
|
||||
|
||||
if ((msg->addr == 0xADU) && (len == 8)) {
|
||||
// Getriebe_11.GE_Fahrstufe (start bit 42, len 4)
|
||||
volkswagen_meb_gear = (msg->data[5] >> 2U) & 0xFU;
|
||||
volkswagen_meb_gear_seen = true;
|
||||
}
|
||||
|
||||
if ((msg->addr == 0x3DCU) && (len == 8)) {
|
||||
// Gateway_73.GE_Fahrstufe (start bit 40, len 4)
|
||||
volkswagen_meb_gear = msg->data[5] & 0xFU;
|
||||
volkswagen_meb_gear_seen = true;
|
||||
}
|
||||
|
||||
if ((msg->addr == 0x3C0U) && (len == 4)) {
|
||||
const bool meb_ignition = ((msg->data[2] >> 1U) & 1U) != 0U;
|
||||
const bool meb_in_park = !volkswagen_meb_gear_seen || (volkswagen_meb_gear == VOLKSWAGEN_MEB_GEAR_P);
|
||||
ignition_can = meb_ignition && !meb_in_park;
|
||||
ignition_can_cnt = 0U;
|
||||
}
|
||||
}
|
||||
// TODO: this is too loose, Teslas have 0x222
|
||||
// body v2 exception
|
||||
// if (((msg->bus == 0U) || (msg->bus == 2U)) && (msg->addr == 0x222U)) {
|
||||
// ignition_can = true;
|
||||
// ignition_can_cnt = 0U;
|
||||
// }
|
||||
}
|
||||
|
||||
bool can_tx_check_min_slots_free(uint32_t min) {
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "board/can.h"
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t w_ptr;
|
||||
volatile uint32_t r_ptr;
|
||||
uint32_t fifo_size;
|
||||
CANPacket_t *elems;
|
||||
} can_ring;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bus_lookup;
|
||||
uint8_t can_num_lookup;
|
||||
int8_t forwarding_bus;
|
||||
uint32_t can_speed;
|
||||
uint32_t can_data_speed;
|
||||
bool canfd_auto;
|
||||
bool canfd_enabled;
|
||||
bool brs_enabled;
|
||||
bool canfd_non_iso;
|
||||
} bus_config_t;
|
||||
|
||||
extern uint32_t safety_tx_blocked;
|
||||
extern uint32_t safety_rx_invalid;
|
||||
extern uint32_t tx_buffer_overflow;
|
||||
extern uint32_t rx_buffer_overflow;
|
||||
|
||||
extern can_health_t can_health[PANDA_CAN_CNT];
|
||||
|
||||
// Ignition detected from CAN meessages
|
||||
extern bool ignition_can;
|
||||
extern uint32_t ignition_can_cnt;
|
||||
|
||||
extern bool can_silent;
|
||||
extern bool can_loopback;
|
||||
|
||||
// ******************* functions prototypes *********************
|
||||
bool can_init(uint8_t can_number);
|
||||
void process_can(uint8_t can_number);
|
||||
|
||||
// ********************* instantiate queues *********************
|
||||
extern can_ring *can_queues[PANDA_CAN_CNT];
|
||||
|
||||
// helpers
|
||||
#define WORD_TO_BYTE_ARRAY(dst8, src32) 0[dst8] = ((src32) & 0xFFU); 1[dst8] = (((src32) >> 8U) & 0xFFU); 2[dst8] = (((src32) >> 16U) & 0xFFU); 3[dst8] = (((src32) >> 24U) & 0xFFU)
|
||||
#define BYTE_ARRAY_TO_WORD(dst32, src8) ((dst32) = 0[src8] | (1[src8] << 8U) | (2[src8] << 16U) | (3[src8] << 24U))
|
||||
|
||||
// ********************* interrupt safe queue *********************
|
||||
bool can_pop(can_ring *q, CANPacket_t *elem);
|
||||
bool can_push(can_ring *q, const CANPacket_t *elem);
|
||||
uint32_t can_slots_empty(const can_ring *q);
|
||||
extern bus_config_t bus_config[PANDA_CAN_CNT];
|
||||
|
||||
#define CANIF_FROM_CAN_NUM(num) (cans[num])
|
||||
#define BUS_NUM_FROM_CAN_NUM(num) (bus_config[num].bus_lookup)
|
||||
#define CAN_NUM_FROM_BUS_NUM(num) (bus_config[num].can_num_lookup)
|
||||
|
||||
void can_init_all(void);
|
||||
void can_set_orientation(bool flipped);
|
||||
#ifdef PANDA_JUNGLE
|
||||
void can_set_forwarding(uint8_t from, uint8_t to);
|
||||
#endif
|
||||
void ignition_can_hook(CANPacket_t *to_push);
|
||||
bool can_tx_check_min_slots_free(uint32_t min);
|
||||
uint8_t calculate_checksum(const uint8_t *dat, uint32_t len);
|
||||
void can_set_checksum(CANPacket_t *packet);
|
||||
bool can_check_checksum(CANPacket_t *packet);
|
||||
void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook);
|
||||
bool is_speed_valid(uint32_t speed, const uint32_t *all_speeds, uint8_t len);
|
||||
@@ -1,12 +1,16 @@
|
||||
#include "clock_source_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
#define CLOCK_SOURCE_PERIOD_MS 50U
|
||||
#define CLOCK_SOURCE_PULSE_LEN_MS 2U
|
||||
|
||||
void clock_source_set_timer_params(uint16_t param1, uint16_t param2) {
|
||||
// Pulse length of each channel
|
||||
register_set(&(TIM1->CCR1), (((param1 & 0xFF00U) >> 8U)*10U), 0xFFFFU);
|
||||
register_set(&(TIM1->CCR2), ((param1 & 0x00FFU)*10U), 0xFFFFU);
|
||||
register_set(&(TIM1->CCR3), (((param2 & 0xFF00U) >> 8U)*10U), 0xFFFFU);
|
||||
register_set(&(TIM8->CCR3), (((param2 & 0xFF00U) >> 8U)*10U), 0xFFFFU);
|
||||
// Timer period
|
||||
register_set(&(TIM1->ARR), (((param2 & 0x00FFU)*10U) - 1U), 0xFFFFU);
|
||||
register_set(&(TIM1->CCR4), ((TIM1->ARR + 1U) / 2U), 0xFFFFU);
|
||||
}
|
||||
|
||||
void clock_source_init(bool enable_channel1) {
|
||||
@@ -14,12 +18,12 @@ void clock_source_init(bool enable_channel1) {
|
||||
register_set(&(TIM1->PSC), ((APB2_TIMER_FREQ*100U)-1U), 0xFFFFU); // Tick on 0.1 ms
|
||||
register_set(&(TIM1->ARR), ((CLOCK_SOURCE_PERIOD_MS*10U) - 1U), 0xFFFFU); // Period
|
||||
register_set(&(TIM1->CCMR1), 0U, 0xFFFFU); // No output on compare
|
||||
register_set(&(TIM1->CCER), TIM_CCER_CC1E, 0xFFFFU); // Enable compare 1
|
||||
register_set(&(TIM1->CCER), TIM_CCER_CC1E | TIM_CCER_CC2NE, 0xFFFFU); // Enable compares
|
||||
register_set(&(TIM1->CCR1), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value
|
||||
register_set(&(TIM1->CCR2), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value
|
||||
register_set(&(TIM1->CCR3), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value
|
||||
register_set(&(TIM1->CCR2), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 2 value
|
||||
register_set(&(TIM1->CCR4), (CLOCK_SOURCE_PERIOD_MS*5U), 0xFFFFU); // For slave timer
|
||||
register_set_bits(&(TIM1->DIER), TIM_DIER_UIE | TIM_DIER_CC1IE); // Enable interrupts
|
||||
register_set(&(TIM1->CR1), TIM_CR1_CEN, 0x3FU); // Enable timer
|
||||
|
||||
|
||||
// No interrupts
|
||||
NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);
|
||||
@@ -30,15 +34,33 @@ void clock_source_init(bool enable_channel1) {
|
||||
set_gpio_alternate(GPIOA, 8, GPIO_AF1_TIM1);
|
||||
}
|
||||
set_gpio_alternate(GPIOB, 14, GPIO_AF1_TIM1);
|
||||
set_gpio_alternate(GPIOB, 15, GPIO_AF1_TIM1);
|
||||
|
||||
// Set PWM mode
|
||||
register_set(&(TIM1->CCMR1), (0b110UL << TIM_CCMR1_OC1M_Pos) | (0b110UL << TIM_CCMR1_OC2M_Pos), 0xFFFFU);
|
||||
register_set(&(TIM1->CCMR2), (0b110UL << TIM_CCMR2_OC3M_Pos), 0xFFFFU);
|
||||
register_set(&(TIM1->CCMR2), (0b110UL << TIM_CCMR2_OC3M_Pos) | (0b111UL << TIM_CCMR2_OC4M_Pos), 0xFFFFU);
|
||||
|
||||
// Enable output
|
||||
register_set(&(TIM1->BDTR), TIM_BDTR_MOE, 0xFFFFU);
|
||||
|
||||
// Enable complementary compares
|
||||
register_set_bits(&(TIM1->CCER), TIM_CCER_CC2NE | TIM_CCER_CC3NE);
|
||||
// Sync with slave
|
||||
register_set(&(TIM1->SMCR), TIM_SMCR_MSM , 0xFFFFU);
|
||||
register_set(&(TIM1->CR2), (0b0111U << TIM_CR2_MMS_Pos), 0xFFFFU);
|
||||
register_set(&(TIM8->SMCR), (0b0100U << TIM_SMCR_SMS_Pos) | (0b000U << TIM_SMCR_TS_Pos), 0xFFFFU);
|
||||
|
||||
// Setup slave timer (TIM8)
|
||||
register_set(&(TIM8->PSC), TIM1->PSC, 0xFFFFU);
|
||||
register_set(&(TIM8->ARR), TIM1->ARR, 0xFFFFU);
|
||||
register_set(&(TIM8->CCMR2), (0b110UL << TIM_CCMR2_OC3M_Pos), 0xFFFFU);
|
||||
register_set(&(TIM8->CCR3), (CLOCK_SOURCE_PULSE_LEN_MS * 10U), 0xFFFFU);
|
||||
register_set(&(TIM8->CCER), TIM_CCER_CC3NE, 0xFFFFU);
|
||||
|
||||
// MOE for TIM8 as well
|
||||
register_set(&(TIM8->BDTR), TIM_BDTR_MOE, 0xFFFFU);
|
||||
|
||||
// Set GPIO
|
||||
set_gpio_alternate(GPIOB, 15, GPIO_AF3_TIM8);
|
||||
|
||||
// Enable timers
|
||||
register_set(&(TIM1->CR1), TIM_CR1_CEN, 0x3FU);
|
||||
register_set(&(TIM8->CR1), TIM_CR1_CEN, 0x3FU);
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define CLOCK_SOURCE_PERIOD_MS 50U
|
||||
#define CLOCK_SOURCE_PULSE_LEN_MS 2U
|
||||
|
||||
void clock_source_set_timer_params(uint16_t param1, uint16_t param2);
|
||||
void clock_source_init(bool enable_channel1);
|
||||
@@ -0,0 +1,287 @@
|
||||
#pragma once
|
||||
|
||||
#include "board/can.h"
|
||||
#include "board/health.h"
|
||||
#include "board/crc.h"
|
||||
#ifdef STM32H7
|
||||
#include "board/stm32h7/lladc_declarations.h"
|
||||
#endif
|
||||
|
||||
// ******************** bootkick ********************
|
||||
|
||||
extern bool bootkick_reset_triggered;
|
||||
|
||||
void bootkick_tick(bool ignition, bool recent_heartbeat);
|
||||
|
||||
// ******************** can_common ********************
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t w_ptr;
|
||||
volatile uint32_t r_ptr;
|
||||
uint32_t fifo_size;
|
||||
CANPacket_t *elems;
|
||||
} can_ring;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bus_lookup;
|
||||
uint8_t can_num_lookup;
|
||||
int8_t forwarding_bus;
|
||||
uint32_t can_speed;
|
||||
uint32_t can_data_speed;
|
||||
bool canfd_auto;
|
||||
bool canfd_enabled;
|
||||
bool brs_enabled;
|
||||
bool canfd_non_iso;
|
||||
} bus_config_t;
|
||||
|
||||
extern uint32_t safety_tx_blocked;
|
||||
extern uint32_t safety_rx_invalid;
|
||||
extern uint32_t tx_buffer_overflow;
|
||||
extern uint32_t rx_buffer_overflow;
|
||||
|
||||
extern can_health_t can_health[PANDA_CAN_CNT];
|
||||
|
||||
// Ignition detected from CAN meessages
|
||||
extern bool ignition_can;
|
||||
extern uint32_t ignition_can_cnt;
|
||||
|
||||
extern bool can_silent;
|
||||
extern bool can_loopback;
|
||||
|
||||
// ******************* functions prototypes *********************
|
||||
bool can_init(uint8_t can_number);
|
||||
void process_can(uint8_t can_number);
|
||||
|
||||
// ********************* instantiate queues *********************
|
||||
extern can_ring *can_queues[PANDA_CAN_CNT];
|
||||
|
||||
// helpers
|
||||
#define WORD_TO_BYTE_ARRAY(dst8, src32) 0[dst8] = ((src32) & 0xFFU); 1[dst8] = (((src32) >> 8U) & 0xFFU); 2[dst8] = (((src32) >> 16U) & 0xFFU); 3[dst8] = (((src32) >> 24U) & 0xFFU)
|
||||
#define BYTE_ARRAY_TO_WORD(dst32, src8) ((dst32) = 0[src8] | (1[src8] << 8U) | (2[src8] << 16U) | (3[src8] << 24U))
|
||||
|
||||
// ********************* interrupt safe queue *********************
|
||||
bool can_pop(can_ring *q, CANPacket_t *elem);
|
||||
bool can_push(can_ring *q, const CANPacket_t *elem);
|
||||
uint32_t can_slots_empty(const can_ring *q);
|
||||
extern bus_config_t bus_config[PANDA_CAN_CNT];
|
||||
|
||||
#define CANIF_FROM_CAN_NUM(num) (cans[num])
|
||||
#define BUS_NUM_FROM_CAN_NUM(num) (bus_config[num].bus_lookup)
|
||||
#define CAN_NUM_FROM_BUS_NUM(num) (bus_config[num].can_num_lookup)
|
||||
|
||||
void can_init_all(void);
|
||||
void can_set_orientation(bool flipped);
|
||||
#ifdef PANDA_JUNGLE
|
||||
void can_set_forwarding(uint8_t from, uint8_t to);
|
||||
#endif
|
||||
void ignition_can_hook(CANPacket_t *to_push);
|
||||
bool can_tx_check_min_slots_free(uint32_t min);
|
||||
uint8_t calculate_checksum(const uint8_t *dat, uint32_t len);
|
||||
void can_set_checksum(CANPacket_t *packet);
|
||||
bool can_check_checksum(CANPacket_t *packet);
|
||||
void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook);
|
||||
bool is_speed_valid(uint32_t speed, const uint32_t *all_speeds, uint8_t len);
|
||||
|
||||
// ******************** clock_source ********************
|
||||
|
||||
void clock_source_set_timer_params(uint16_t param1, uint16_t param2);
|
||||
void clock_source_init(bool enable_channel1);
|
||||
|
||||
// ******************** fan ********************
|
||||
|
||||
struct fan_state_t {
|
||||
uint16_t tach_counter;
|
||||
uint16_t rpm;
|
||||
uint8_t power;
|
||||
float error_integral;
|
||||
uint8_t cooldown_counter;
|
||||
};
|
||||
extern struct fan_state_t fan_state;
|
||||
|
||||
void fan_set_power(uint8_t percentage);
|
||||
void llfan_init(void);
|
||||
void fan_init(void);
|
||||
// Call this at FAN_TICK_FREQ
|
||||
void fan_tick(void);
|
||||
|
||||
// ******************** fdcan ********************
|
||||
#ifdef STM32H7
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t header[2];
|
||||
volatile uint32_t data_word[CANPACKET_DATA_SIZE_MAX/4U];
|
||||
} canfd_fifo;
|
||||
|
||||
extern FDCAN_GlobalTypeDef *cans[PANDA_CAN_CNT];
|
||||
|
||||
#define CAN_ACK_ERROR 3U
|
||||
|
||||
void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number);
|
||||
void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg);
|
||||
|
||||
void process_can(uint8_t can_number);
|
||||
void can_rx(uint8_t can_number);
|
||||
bool can_init(uint8_t can_number);
|
||||
|
||||
// ******************** harness ********************
|
||||
|
||||
#define HARNESS_STATUS_NC 0U
|
||||
#define HARNESS_STATUS_NORMAL 1U
|
||||
#define HARNESS_STATUS_FLIPPED 2U
|
||||
|
||||
struct harness_t {
|
||||
uint8_t status;
|
||||
uint16_t sbu1_voltage_mV;
|
||||
uint16_t sbu2_voltage_mV;
|
||||
bool relay_driven;
|
||||
bool sbu_adc_lock;
|
||||
};
|
||||
extern struct harness_t harness;
|
||||
|
||||
struct harness_configuration {
|
||||
GPIO_TypeDef * const GPIO_SBU1;
|
||||
GPIO_TypeDef * const GPIO_SBU2;
|
||||
GPIO_TypeDef * const GPIO_relay_SBU1;
|
||||
GPIO_TypeDef * const GPIO_relay_SBU2;
|
||||
const uint8_t pin_SBU1;
|
||||
const uint8_t pin_SBU2;
|
||||
const uint8_t pin_relay_SBU1;
|
||||
const uint8_t pin_relay_SBU2;
|
||||
const adc_signal_t adc_signal_SBU1;
|
||||
const adc_signal_t adc_signal_SBU2;
|
||||
};
|
||||
|
||||
// The ignition relay is only used for testing purposes
|
||||
void set_intercept_relay(bool intercept, bool ignition_relay);
|
||||
bool harness_check_ignition(void);
|
||||
void harness_tick(void);
|
||||
void harness_init(void);
|
||||
|
||||
// ******************** interrupts ********************
|
||||
|
||||
typedef struct interrupt {
|
||||
IRQn_Type irq_type;
|
||||
void (*handler)(void);
|
||||
uint32_t call_counter;
|
||||
uint32_t call_rate;
|
||||
uint32_t max_call_rate; // Call rate is defined as the amount of calls each second
|
||||
uint32_t call_rate_fault;
|
||||
} interrupt;
|
||||
|
||||
void interrupt_timer_init(void);
|
||||
uint32_t microsecond_timer_get(void);
|
||||
void unused_interrupt_handler(void);
|
||||
|
||||
extern interrupt interrupts[NUM_INTERRUPTS];
|
||||
|
||||
#define REGISTER_INTERRUPT(irq_num, func_ptr, call_rate_max, rate_fault) \
|
||||
interrupts[irq_num].irq_type = (irq_num); \
|
||||
interrupts[irq_num].handler = (func_ptr); \
|
||||
interrupts[irq_num].call_counter = 0U; \
|
||||
interrupts[irq_num].call_rate = 0U; \
|
||||
interrupts[irq_num].max_call_rate = (call_rate_max); \
|
||||
interrupts[irq_num].call_rate_fault = (rate_fault);
|
||||
|
||||
extern float interrupt_load;
|
||||
|
||||
void handle_interrupt(IRQn_Type irq_type);
|
||||
// Every second
|
||||
void interrupt_timer_handler(void);
|
||||
void init_interrupts(bool check_rate_limit);
|
||||
|
||||
#endif // STM32H7
|
||||
|
||||
// ******************** registers ********************
|
||||
|
||||
// 10 bit hash with 23 as a prime
|
||||
#define REGISTER_MAP_SIZE 0x3FFU
|
||||
#define HASHING_PRIME 23U
|
||||
|
||||
// Do not put bits in the check mask that get changed by the hardware
|
||||
void register_set(volatile uint32_t *addr, uint32_t val, uint32_t mask);
|
||||
// Set individual bits. Also add them to the check_mask.
|
||||
// Do not use this to change bits that get reset by the hardware
|
||||
void register_set_bits(volatile uint32_t *addr, uint32_t val);
|
||||
// Clear individual bits. Also add them to the check_mask.
|
||||
// Do not use this to clear bits that get set by the hardware
|
||||
void register_clear_bits(volatile uint32_t *addr, uint32_t val);
|
||||
// To be called periodically
|
||||
void check_registers(void);
|
||||
void init_registers(void);
|
||||
|
||||
// ******************** simple_watchdog ********************
|
||||
|
||||
typedef struct simple_watchdog_state_t {
|
||||
uint32_t fault;
|
||||
uint32_t last_ts;
|
||||
uint32_t threshold;
|
||||
} simple_watchdog_state_t;
|
||||
|
||||
void simple_watchdog_kick(void);
|
||||
void simple_watchdog_init(uint32_t fault, uint32_t threshold);
|
||||
|
||||
// ******************** spi ********************
|
||||
|
||||
// got max rate from hitting a non-existent endpoint
|
||||
// in a tight loop, plus some buffer
|
||||
#define SPI_IRQ_RATE 16000U
|
||||
|
||||
#define SPI_BUF_SIZE 4096U
|
||||
extern uint8_t spi_buf_rx[SPI_BUF_SIZE];
|
||||
extern uint8_t spi_buf_tx[SPI_BUF_SIZE];
|
||||
|
||||
extern uint16_t spi_error_count;
|
||||
|
||||
void can_tx_comms_resume_spi(void);
|
||||
void spi_init(void);
|
||||
void spi_rx_done(void);
|
||||
void spi_tx_done(bool reset);
|
||||
|
||||
// ******************** uart ********************
|
||||
#ifdef STM32H7
|
||||
|
||||
// ***************************** Definitions *****************************
|
||||
#define FIFO_SIZE_INT 0x400U
|
||||
|
||||
typedef struct uart_ring {
|
||||
volatile uint16_t w_ptr_tx;
|
||||
volatile uint16_t r_ptr_tx;
|
||||
uint8_t *elems_tx;
|
||||
uint32_t tx_fifo_size;
|
||||
volatile uint16_t w_ptr_rx;
|
||||
volatile uint16_t r_ptr_rx;
|
||||
uint8_t *elems_rx;
|
||||
uint32_t rx_fifo_size;
|
||||
USART_TypeDef *uart;
|
||||
void (*callback)(struct uart_ring*);
|
||||
bool overwrite;
|
||||
} uart_ring;
|
||||
|
||||
// ***************************** Function prototypes *****************************
|
||||
void debug_ring_callback(uart_ring *ring);
|
||||
void uart_tx_ring(uart_ring *q);
|
||||
uart_ring *get_ring_by_number(int a);
|
||||
// ************************* Low-level buffer functions *************************
|
||||
bool get_char(uart_ring *q, char *elem);
|
||||
bool injectc(uart_ring *q, char elem);
|
||||
bool put_char(uart_ring *q, char elem);
|
||||
void clear_uart_buff(uart_ring *q);
|
||||
// ************************ High-level debug functions **********************
|
||||
void putch(const char a);
|
||||
void print(const char *a);
|
||||
void puthx(uint32_t i, uint8_t len);
|
||||
void puth(unsigned int i);
|
||||
#if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG)
|
||||
static void puth4(unsigned int i);
|
||||
#endif
|
||||
#if defined(DEBUG_SPI) || defined(DEBUG_USB) || defined(DEBUG_COMMS)
|
||||
static void hexdump(const void *a, int l);
|
||||
#endif
|
||||
|
||||
#endif // STM32H7
|
||||
|
||||
// ******************** usb ********************
|
||||
|
||||
void usb_init(void);
|
||||
void refresh_can_tx_slots_available(void);
|
||||
void can_tx_comms_resume_usb(void);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "fan_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
struct fan_state_t fan_state;
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
struct fan_state_t {
|
||||
uint16_t tach_counter;
|
||||
uint16_t rpm;
|
||||
uint8_t power;
|
||||
float error_integral;
|
||||
uint8_t cooldown_counter;
|
||||
};
|
||||
extern struct fan_state_t fan_state;
|
||||
|
||||
void fan_set_power(uint8_t percentage);
|
||||
void llfan_init(void);
|
||||
void fan_init(void);
|
||||
// Call this at FAN_TICK_FREQ
|
||||
void fan_tick(void);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "fdcan_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
FDCAN_GlobalTypeDef *cans[PANDA_CAN_CNT] = {FDCAN1, FDCAN2, FDCAN3};
|
||||
|
||||
@@ -215,6 +215,10 @@ void can_rx(uint8_t can_number) {
|
||||
can_health[can_number].total_fwd_cnt += 1U;
|
||||
}
|
||||
|
||||
#ifdef PANDA_BODY
|
||||
body_can_rx(&to_push);
|
||||
#endif
|
||||
|
||||
safety_rx_invalid += safety_rx_hook(&to_push) ? 0U : 1U;
|
||||
ignition_can_hook(&to_push);
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "board/can.h"
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t header[2];
|
||||
volatile uint32_t data_word[CANPACKET_DATA_SIZE_MAX/4U];
|
||||
} canfd_fifo;
|
||||
|
||||
extern FDCAN_GlobalTypeDef *cans[PANDA_CAN_CNT];
|
||||
|
||||
#define CAN_ACK_ERROR 3U
|
||||
|
||||
void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number);
|
||||
void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg);
|
||||
|
||||
void process_can(uint8_t can_number);
|
||||
void can_rx(uint8_t can_number);
|
||||
bool can_init(uint8_t can_number);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "harness_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
struct harness_t harness;
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define HARNESS_STATUS_NC 0U
|
||||
#define HARNESS_STATUS_NORMAL 1U
|
||||
#define HARNESS_STATUS_FLIPPED 2U
|
||||
|
||||
struct harness_t {
|
||||
uint8_t status;
|
||||
uint16_t sbu1_voltage_mV;
|
||||
uint16_t sbu2_voltage_mV;
|
||||
bool relay_driven;
|
||||
bool sbu_adc_lock;
|
||||
};
|
||||
extern struct harness_t harness;
|
||||
|
||||
struct harness_configuration {
|
||||
GPIO_TypeDef * const GPIO_SBU1;
|
||||
GPIO_TypeDef * const GPIO_SBU2;
|
||||
GPIO_TypeDef * const GPIO_relay_SBU1;
|
||||
GPIO_TypeDef * const GPIO_relay_SBU2;
|
||||
const uint8_t pin_SBU1;
|
||||
const uint8_t pin_SBU2;
|
||||
const uint8_t pin_relay_SBU1;
|
||||
const uint8_t pin_relay_SBU2;
|
||||
const adc_signal_t adc_signal_SBU1;
|
||||
const adc_signal_t adc_signal_SBU2;
|
||||
};
|
||||
|
||||
// The ignition relay is only used for testing purposes
|
||||
void set_intercept_relay(bool intercept, bool ignition_relay);
|
||||
bool harness_check_ignition(void);
|
||||
void harness_tick(void);
|
||||
void harness_init(void);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "interrupts_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
void unused_interrupt_handler(void) {
|
||||
// Something is wrong if this handler is called!
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct interrupt {
|
||||
IRQn_Type irq_type;
|
||||
void (*handler)(void);
|
||||
uint32_t call_counter;
|
||||
uint32_t call_rate;
|
||||
uint32_t max_call_rate; // Call rate is defined as the amount of calls each second
|
||||
uint32_t call_rate_fault;
|
||||
} interrupt;
|
||||
|
||||
void interrupt_timer_init(void);
|
||||
uint32_t microsecond_timer_get(void);
|
||||
void unused_interrupt_handler(void);
|
||||
|
||||
extern interrupt interrupts[NUM_INTERRUPTS];
|
||||
|
||||
#define REGISTER_INTERRUPT(irq_num, func_ptr, call_rate_max, rate_fault) \
|
||||
interrupts[irq_num].irq_type = (irq_num); \
|
||||
interrupts[irq_num].handler = (func_ptr); \
|
||||
interrupts[irq_num].call_counter = 0U; \
|
||||
interrupts[irq_num].call_rate = 0U; \
|
||||
interrupts[irq_num].max_call_rate = (call_rate_max); \
|
||||
interrupts[irq_num].call_rate_fault = (rate_fault);
|
||||
|
||||
extern float interrupt_load;
|
||||
|
||||
void handle_interrupt(IRQn_Type irq_type);
|
||||
// Every second
|
||||
void interrupt_timer_handler(void);
|
||||
void init_interrupts(bool check_rate_limit);
|
||||
@@ -1,4 +1,13 @@
|
||||
#include "registers_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
typedef struct reg {
|
||||
volatile uint32_t *address;
|
||||
uint32_t value;
|
||||
uint32_t check_mask;
|
||||
bool logged_fault;
|
||||
} reg;
|
||||
|
||||
#define CHECK_COLLISION(hash, addr) (((uint32_t) register_map[hash].address != 0U) && (register_map[hash].address != (addr)))
|
||||
|
||||
static reg register_map[REGISTER_MAP_SIZE];
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct reg {
|
||||
volatile uint32_t *address;
|
||||
uint32_t value;
|
||||
uint32_t check_mask;
|
||||
} reg;
|
||||
|
||||
// 10 bit hash with 23 as a prime
|
||||
#define REGISTER_MAP_SIZE 0x3FFU
|
||||
#define HASHING_PRIME 23U
|
||||
#define CHECK_COLLISION(hash, addr) (((uint32_t) register_map[hash].address != 0U) && (register_map[hash].address != (addr)))
|
||||
|
||||
// Do not put bits in the check mask that get changed by the hardware
|
||||
void register_set(volatile uint32_t *addr, uint32_t val, uint32_t mask);
|
||||
// Set individual bits. Also add them to the check_mask.
|
||||
// Do not use this to change bits that get reset by the hardware
|
||||
void register_set_bits(volatile uint32_t *addr, uint32_t val);
|
||||
// Clear individual bits. Also add them to the check_mask.
|
||||
// Do not use this to clear bits that get set by the hardware
|
||||
void register_clear_bits(volatile uint32_t *addr, uint32_t val);
|
||||
// To be called periodically
|
||||
void check_registers(void);
|
||||
void init_registers(void);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "simple_watchdog_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
static simple_watchdog_state_t wd_state;
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct simple_watchdog_state_t {
|
||||
uint32_t fault;
|
||||
uint32_t last_ts;
|
||||
uint32_t threshold;
|
||||
} simple_watchdog_state_t;
|
||||
|
||||
void simple_watchdog_kick(void);
|
||||
void simple_watchdog_init(uint32_t fault, uint32_t threshold);
|
||||
@@ -1,13 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "board/drivers/spi_declarations.h"
|
||||
#include "board/crc.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
// H7 DMA2 located in D2 domain, so we need to use SRAM1/SRAM2
|
||||
#ifdef STM32H7
|
||||
__attribute__((section(".sram12"))) uint8_t spi_buf_rx[SPI_BUF_SIZE];
|
||||
__attribute__((section(".sram12"))) uint8_t spi_buf_tx[SPI_BUF_SIZE];
|
||||
#else
|
||||
uint8_t spi_buf_rx[SPI_BUF_SIZE];
|
||||
uint8_t spi_buf_tx[SPI_BUF_SIZE];
|
||||
#endif
|
||||
|
||||
#define SPI_CHECKSUM_START 0xABU
|
||||
#define SPI_SYNC_BYTE 0x5AU
|
||||
#define SPI_HACK 0x79U
|
||||
#define SPI_DACK 0x85U
|
||||
#define SPI_NACK 0x1FU
|
||||
|
||||
// SPI states
|
||||
enum {
|
||||
SPI_STATE_HEADER,
|
||||
SPI_STATE_HEADER_ACK,
|
||||
SPI_STATE_HEADER_NACK,
|
||||
SPI_STATE_DATA_RX,
|
||||
SPI_STATE_DATA_RX_ACK,
|
||||
SPI_STATE_DATA_TX
|
||||
};
|
||||
|
||||
uint16_t spi_error_count = 0;
|
||||
|
||||
#define SPI_HEADER_SIZE 7U
|
||||
|
||||
// low level SPI prototypes
|
||||
void llspi_init(void);
|
||||
void llspi_mosi_dma(uint8_t *addr, int len);
|
||||
void llspi_miso_dma(uint8_t *addr, int len);
|
||||
|
||||
static uint8_t spi_state = SPI_STATE_HEADER;
|
||||
static uint16_t spi_data_len_mosi;
|
||||
static bool spi_can_tx_ready = false;
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "board/crc.h"
|
||||
|
||||
#define SPI_TIMEOUT_US 10000U
|
||||
|
||||
// got max rate from hitting a non-existent endpoint
|
||||
// in a tight loop, plus some buffer
|
||||
#define SPI_IRQ_RATE 16000U
|
||||
|
||||
#define SPI_BUF_SIZE 4096U
|
||||
// H7 DMA2 located in D2 domain, so we need to use SRAM1/SRAM2
|
||||
__attribute__((section(".sram12"))) extern uint8_t spi_buf_rx[SPI_BUF_SIZE];
|
||||
__attribute__((section(".sram12"))) extern uint8_t spi_buf_tx[SPI_BUF_SIZE];
|
||||
|
||||
#define SPI_CHECKSUM_START 0xABU
|
||||
#define SPI_SYNC_BYTE 0x5AU
|
||||
#define SPI_HACK 0x79U
|
||||
#define SPI_DACK 0x85U
|
||||
#define SPI_NACK 0x1FU
|
||||
|
||||
// SPI states
|
||||
enum {
|
||||
SPI_STATE_HEADER,
|
||||
SPI_STATE_HEADER_ACK,
|
||||
SPI_STATE_HEADER_NACK,
|
||||
SPI_STATE_DATA_RX,
|
||||
SPI_STATE_DATA_RX_ACK,
|
||||
SPI_STATE_DATA_TX
|
||||
};
|
||||
|
||||
extern uint16_t spi_error_count;
|
||||
|
||||
#define SPI_HEADER_SIZE 7U
|
||||
|
||||
// low level SPI prototypes
|
||||
void llspi_init(void);
|
||||
void llspi_mosi_dma(uint8_t *addr, int len);
|
||||
void llspi_miso_dma(uint8_t *addr, int len);
|
||||
|
||||
void can_tx_comms_resume_spi(void);
|
||||
void spi_init(void);
|
||||
void spi_rx_done(void);
|
||||
void spi_tx_done(bool reset);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "uart_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
// ***************************** Definitions *****************************
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// ***************************** Definitions *****************************
|
||||
#ifdef STM32H7
|
||||
#define FIFO_SIZE_INT 0x400U
|
||||
#else
|
||||
#define FIFO_SIZE_INT 0x200U
|
||||
#endif
|
||||
|
||||
typedef struct uart_ring {
|
||||
volatile uint16_t w_ptr_tx;
|
||||
volatile uint16_t r_ptr_tx;
|
||||
uint8_t *elems_tx;
|
||||
uint32_t tx_fifo_size;
|
||||
volatile uint16_t w_ptr_rx;
|
||||
volatile uint16_t r_ptr_rx;
|
||||
uint8_t *elems_rx;
|
||||
uint32_t rx_fifo_size;
|
||||
USART_TypeDef *uart;
|
||||
void (*callback)(struct uart_ring*);
|
||||
bool overwrite;
|
||||
} uart_ring;
|
||||
|
||||
// ***************************** Function prototypes *****************************
|
||||
void debug_ring_callback(uart_ring *ring);
|
||||
void uart_tx_ring(uart_ring *q);
|
||||
uart_ring *get_ring_by_number(int a);
|
||||
// ************************* Low-level buffer functions *************************
|
||||
bool get_char(uart_ring *q, char *elem);
|
||||
bool injectc(uart_ring *q, char elem);
|
||||
bool put_char(uart_ring *q, char elem);
|
||||
void clear_uart_buff(uart_ring *q);
|
||||
// ************************ High-level debug functions **********************
|
||||
void putch(const char a);
|
||||
void print(const char *a);
|
||||
void puthx(uint32_t i, uint8_t len);
|
||||
void puth(unsigned int i);
|
||||
#if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG)
|
||||
static void puth4(unsigned int i);
|
||||
#endif
|
||||
#if defined(DEBUG_SPI) || defined(DEBUG_USB) || defined(DEBUG_COMMS)
|
||||
static void hexdump(const void *a, int l);
|
||||
#endif
|
||||
@@ -1,4 +1,87 @@
|
||||
#include "usb_declarations.h"
|
||||
#include "board/drivers/drivers.h"
|
||||
|
||||
// IRQs: OTG_FS
|
||||
|
||||
typedef union {
|
||||
uint16_t w;
|
||||
struct BW {
|
||||
uint8_t msb;
|
||||
uint8_t lsb;
|
||||
}
|
||||
bw;
|
||||
} uint16_t_uint8_t;
|
||||
|
||||
typedef union _USB_Setup {
|
||||
uint32_t d8[2];
|
||||
struct _SetupPkt_Struc
|
||||
{
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t_uint8_t wValue;
|
||||
uint16_t_uint8_t wIndex;
|
||||
uint16_t_uint8_t wLength;
|
||||
} b;
|
||||
} USB_Setup_TypeDef;
|
||||
|
||||
// **** supporting defines ****
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
|
||||
#define USB_DESC_TYPE_DEVICE 0x01
|
||||
#define USB_DESC_TYPE_CONFIGURATION 0x02
|
||||
#define USB_DESC_TYPE_STRING 0x03
|
||||
#define USB_DESC_TYPE_INTERFACE 0x04
|
||||
#define USB_DESC_TYPE_ENDPOINT 0x05
|
||||
#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06
|
||||
#define USB_DESC_TYPE_BINARY_OBJECT_STORE 0x0f
|
||||
|
||||
// offsets for configuration strings
|
||||
#define STRING_OFFSET_LANGID 0x00
|
||||
#define STRING_OFFSET_IMANUFACTURER 0x01
|
||||
#define STRING_OFFSET_IPRODUCT 0x02
|
||||
#define STRING_OFFSET_ISERIAL 0x03
|
||||
#define STRING_OFFSET_ICONFIGURATION 0x04
|
||||
|
||||
// WinUSB requests
|
||||
#define WINUSB_REQ_GET_COMPATID_DESCRIPTOR 0x04
|
||||
#define WINUSB_REQ_GET_EXT_PROPS_OS 0x05
|
||||
#define WINUSB_REQ_GET_DESCRIPTOR 0x07
|
||||
|
||||
#define STS_DATA_UPDT 2
|
||||
#define STS_SETUP_UPDT 6
|
||||
|
||||
// for the repeating interfaces
|
||||
#define DSCR_INTERFACE_LEN 9
|
||||
#define DSCR_ENDPOINT_LEN 7
|
||||
#define DSCR_CONFIG_LEN 9
|
||||
#define DSCR_DEVICE_LEN 18
|
||||
|
||||
// endpoint types
|
||||
#define ENDPOINT_TYPE_BULK 2
|
||||
#define ENDPOINT_TYPE_INT 3
|
||||
|
||||
// These are arbitrary values used in bRequest
|
||||
#define MS_VENDOR_CODE 0x20
|
||||
#define WEBUSB_VENDOR_CODE 0x30
|
||||
|
||||
// BOS constants
|
||||
#define BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH 0x05
|
||||
#define BINARY_OBJECT_STORE_DESCRIPTOR 0x0F
|
||||
#define WINUSB_PLATFORM_DESCRIPTOR_LENGTH 0x9E
|
||||
|
||||
// Convert machine byte order to USB byte order
|
||||
#define TOUSBORDER(num)\
|
||||
((num) & 0xFFU), (((uint16_t)(num) >> 8) & 0xFFU)
|
||||
|
||||
// take in string length and return the first 2 bytes of a string descriptor
|
||||
#define STRING_DESCRIPTOR_HEADER(size)\
|
||||
(((((size) * 2) + 2) & 0xFF) | 0x0300)
|
||||
|
||||
#define ENDPOINT_RCV 0x80
|
||||
#define ENDPOINT_SND 0x00
|
||||
|
||||
static uint8_t response[USBPACKET_MAX_SIZE];
|
||||
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// IRQs: OTG_FS
|
||||
|
||||
typedef union {
|
||||
uint16_t w;
|
||||
struct BW {
|
||||
uint8_t msb;
|
||||
uint8_t lsb;
|
||||
}
|
||||
bw;
|
||||
} uint16_t_uint8_t;
|
||||
|
||||
typedef union _USB_Setup {
|
||||
uint32_t d8[2];
|
||||
struct _SetupPkt_Struc
|
||||
{
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t_uint8_t wValue;
|
||||
uint16_t_uint8_t wIndex;
|
||||
uint16_t_uint8_t wLength;
|
||||
} b;
|
||||
} USB_Setup_TypeDef;
|
||||
|
||||
void usb_init(void);
|
||||
void refresh_can_tx_slots_available(void);
|
||||
|
||||
// **** supporting defines ****
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||
#define USB_REQ_SET_FEATURE 0x03
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
#define USB_DESC_TYPE_DEVICE 0x01
|
||||
#define USB_DESC_TYPE_CONFIGURATION 0x02
|
||||
#define USB_DESC_TYPE_STRING 0x03
|
||||
#define USB_DESC_TYPE_INTERFACE 0x04
|
||||
#define USB_DESC_TYPE_ENDPOINT 0x05
|
||||
#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06
|
||||
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07
|
||||
#define USB_DESC_TYPE_BINARY_OBJECT_STORE 0x0f
|
||||
|
||||
// offsets for configuration strings
|
||||
#define STRING_OFFSET_LANGID 0x00
|
||||
#define STRING_OFFSET_IMANUFACTURER 0x01
|
||||
#define STRING_OFFSET_IPRODUCT 0x02
|
||||
#define STRING_OFFSET_ISERIAL 0x03
|
||||
#define STRING_OFFSET_ICONFIGURATION 0x04
|
||||
#define STRING_OFFSET_IINTERFACE 0x05
|
||||
|
||||
// WebUSB requests
|
||||
#define WEBUSB_REQ_GET_URL 0x02
|
||||
|
||||
// WebUSB types
|
||||
#define WEBUSB_DESC_TYPE_URL 0x03
|
||||
#define WEBUSB_URL_SCHEME_HTTPS 0x01
|
||||
#define WEBUSB_URL_SCHEME_HTTP 0x00
|
||||
|
||||
// WinUSB requests
|
||||
#define WINUSB_REQ_GET_COMPATID_DESCRIPTOR 0x04
|
||||
#define WINUSB_REQ_GET_EXT_PROPS_OS 0x05
|
||||
#define WINUSB_REQ_GET_DESCRIPTOR 0x07
|
||||
|
||||
#define STS_GOUT_NAK 1
|
||||
#define STS_DATA_UPDT 2
|
||||
#define STS_XFER_COMP 3
|
||||
#define STS_SETUP_COMP 4
|
||||
#define STS_SETUP_UPDT 6
|
||||
|
||||
// for the repeating interfaces
|
||||
#define DSCR_INTERFACE_LEN 9
|
||||
#define DSCR_ENDPOINT_LEN 7
|
||||
#define DSCR_CONFIG_LEN 9
|
||||
#define DSCR_DEVICE_LEN 18
|
||||
|
||||
// endpoint types
|
||||
#define ENDPOINT_TYPE_CONTROL 0
|
||||
#define ENDPOINT_TYPE_ISO 1
|
||||
#define ENDPOINT_TYPE_BULK 2
|
||||
#define ENDPOINT_TYPE_INT 3
|
||||
|
||||
// These are arbitrary values used in bRequest
|
||||
#define MS_VENDOR_CODE 0x20
|
||||
#define WEBUSB_VENDOR_CODE 0x30
|
||||
|
||||
// BOS constants
|
||||
#define BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH 0x05
|
||||
#define BINARY_OBJECT_STORE_DESCRIPTOR 0x0F
|
||||
#define WINUSB_PLATFORM_DESCRIPTOR_LENGTH 0x9E
|
||||
|
||||
// Convert machine byte order to USB byte order
|
||||
#define TOUSBORDER(num)\
|
||||
((num) & 0xFFU), (((uint16_t)(num) >> 8) & 0xFFU)
|
||||
|
||||
// take in string length and return the first 2 bytes of a string descriptor
|
||||
#define STRING_DESCRIPTOR_HEADER(size)\
|
||||
(((((size) * 2) + 2) & 0xFF) | 0x0300)
|
||||
|
||||
#define ENDPOINT_RCV 0x80
|
||||
#define ENDPOINT_SND 0x00
|
||||
|
||||
// ***************************** USB port *****************************
|
||||
void can_tx_comms_resume_usb(void);
|
||||
@@ -1,16 +1,10 @@
|
||||
// from the linker script
|
||||
#ifdef STM32H7
|
||||
#define APP_START_ADDRESS 0x8020000U
|
||||
#else
|
||||
#define APP_START_ADDRESS 0x8004000U
|
||||
#endif
|
||||
#define APP_START_ADDRESS 0x8020000U
|
||||
|
||||
// flasher state variables
|
||||
uint32_t *prog_ptr = NULL;
|
||||
bool unlocked = false;
|
||||
|
||||
void spi_init(void);
|
||||
|
||||
int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
int resp_len = 0;
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// When changing these structs, python/__init__.py needs to be kept up to date!
|
||||
#pragma once
|
||||
|
||||
#define CAN_PACKET_VERSION 4
|
||||
#define HEALTH_PACKET_VERSION 17
|
||||
struct __attribute__((packed)) health_t {
|
||||
uint32_t uptime_pkt;
|
||||
uint32_t voltage_pkt;
|
||||
@@ -28,9 +26,11 @@ struct __attribute__((packed)) health_t {
|
||||
uint16_t sbu1_voltage_mV;
|
||||
uint16_t sbu2_voltage_mV;
|
||||
uint8_t som_reset_triggered;
|
||||
uint16_t sound_output_level_pkt;
|
||||
uint8_t controls_allowed_lateral_pkt;
|
||||
uint8_t controls_allowed_longitudinal_pkt;
|
||||
};
|
||||
|
||||
#define CAN_HEALTH_PACKET_VERSION 5
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bus_off;
|
||||
uint32_t bus_off_cnt;
|
||||
|
||||
@@ -4,7 +4,7 @@ import struct
|
||||
from functools import wraps
|
||||
|
||||
from panda import Panda, PandaDFU
|
||||
from panda.python.constants import McuType
|
||||
from panda.python.constants import McuType, compute_version_hash
|
||||
|
||||
BASEDIR = os.path.dirname(os.path.realpath(__file__))
|
||||
FW_PATH = os.path.join(BASEDIR, "../obj/")
|
||||
@@ -39,7 +39,7 @@ class PandaJungle(Panda):
|
||||
H7_DEVICES = [HW_TYPE_V2, ]
|
||||
SUPPORTED_DEVICES = H7_DEVICES
|
||||
|
||||
HEALTH_PACKET_VERSION = 1
|
||||
HEALTH_PACKET_VERSION = compute_version_hash(os.path.join(BASEDIR, "jungle_health.h"))
|
||||
HEALTH_STRUCT = struct.Struct("<IffffffHHHHHHHHHHHH")
|
||||
|
||||
HARNESS_ORIENTATION_NONE = 0
|
||||
@@ -52,7 +52,7 @@ class PandaJungle(Panda):
|
||||
|
||||
def flash(self, fn=None, code=None, reconnect=True):
|
||||
if not fn:
|
||||
fn = os.path.join(FW_PATH, self._mcu_type.config.app_fn.replace("panda", "panda_jungle"))
|
||||
fn = os.path.join(FW_PATH, McuType.H7.config.app_fn.replace("panda", "panda_jungle"))
|
||||
super().flash(fn=fn, code=code, reconnect=reconnect)
|
||||
|
||||
def recover(self, timeout: int | None = 60, reset: bool = True) -> bool:
|
||||
@@ -73,15 +73,9 @@ class PandaJungle(Panda):
|
||||
self.flash()
|
||||
return True
|
||||
|
||||
def get_mcu_type(self) -> McuType:
|
||||
hw_type = self.get_type()
|
||||
if hw_type in PandaJungle.H7_DEVICES:
|
||||
return McuType.H7
|
||||
raise ValueError(f"unknown HW type: {hw_type}")
|
||||
|
||||
def up_to_date(self, fn=None) -> bool:
|
||||
if fn is None:
|
||||
fn = os.path.join(FW_PATH, self.get_mcu_type().config.app_fn.replace("panda", "panda_jungle"))
|
||||
fn = os.path.join(FW_PATH, McuType.H7.config.app_fn.replace("panda", "panda_jungle"))
|
||||
return super().up_to_date(fn=fn)
|
||||
|
||||
# ******************* health *******************
|
||||
@@ -114,13 +108,11 @@ class PandaJungle(Panda):
|
||||
|
||||
# ******************* control *******************
|
||||
|
||||
# Returns tuple with health packet version and CAN packet/USB packet version
|
||||
def get_packets_versions(self):
|
||||
dat = self._handle.controlRead(PandaJungle.REQUEST_IN, 0xdd, 0, 0, 3)
|
||||
if dat and len(dat) == 3:
|
||||
a = struct.unpack("BBB", dat)
|
||||
return (a[0], a[1], a[2])
|
||||
return (-1, -1, -1)
|
||||
dat = self._handle.controlRead(PandaJungle.REQUEST_IN, 0xdd, 0, 0, 8)
|
||||
if dat and len(dat) == 8:
|
||||
return struct.unpack("<II", dat)
|
||||
return (0, 0)
|
||||
|
||||
# ******************* jungle stuff *******************
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// When changing these structs, python/__init__.py needs to be kept up to date!
|
||||
|
||||
#define JUNGLE_HEALTH_PACKET_VERSION 1
|
||||
struct __attribute__((packed)) jungle_health_t {
|
||||
uint32_t uptime_pkt;
|
||||
float ch1_power;
|
||||
|
||||
@@ -75,11 +75,6 @@ void tick_handler(void) {
|
||||
// turn off the blue LED, turned on by CAN
|
||||
led_set(LED_BLUE, false);
|
||||
|
||||
// Blink and OBD CAN
|
||||
#ifdef FINAL_PROVISIONING
|
||||
current_board->set_can_mode(can_mode == CAN_MODE_NORMAL ? CAN_MODE_OBD_CAN2 : CAN_MODE_NORMAL);
|
||||
#endif
|
||||
|
||||
// on to the next one
|
||||
uptime_cnt += 1U;
|
||||
}
|
||||
@@ -91,33 +86,12 @@ void tick_handler(void) {
|
||||
current_board->set_panda_power(!panda_power);
|
||||
}
|
||||
|
||||
#ifdef FINAL_PROVISIONING
|
||||
// Ignition blinking
|
||||
uint8_t ignition_bitmask = 0U;
|
||||
for (uint8_t i = 0U; i < 6U; i++) {
|
||||
ignition_bitmask |= ((loop_counter % 12U) < ((uint32_t) i + 2U)) << i;
|
||||
}
|
||||
current_board->set_individual_ignition(ignition_bitmask);
|
||||
|
||||
// SBU voltage reporting
|
||||
for (uint8_t i = 0U; i < 6U; i++) {
|
||||
CANPacket_t pkt = { 0 };
|
||||
pkt.data_len_code = 8U;
|
||||
pkt.addr = 0x100U + i;
|
||||
*(uint16_t *) &pkt.data[0] = current_board->get_sbu_mV(i + 1U, SBU1);
|
||||
*(uint16_t *) &pkt.data[2] = current_board->get_sbu_mV(i + 1U, SBU2);
|
||||
pkt.data[4] = (ignition_bitmask >> i) & 1U;
|
||||
can_set_checksum(&pkt);
|
||||
can_send(&pkt, 0U, false);
|
||||
}
|
||||
#else
|
||||
// toggle ignition on button press
|
||||
static bool prev_button_status = false;
|
||||
if (!current_button_status && prev_button_status && button_press_cnt < 10){
|
||||
current_board->set_ignition(!ignition);
|
||||
}
|
||||
prev_button_status = current_button_status;
|
||||
#endif
|
||||
|
||||
button_press_cnt = current_button_status ? button_press_cnt + 1 : 0;
|
||||
|
||||
@@ -181,12 +155,6 @@ int main(void) {
|
||||
can_init_all();
|
||||
current_board->set_harness_orientation(HARNESS_ORIENTATION_1);
|
||||
|
||||
#ifdef FINAL_PROVISIONING
|
||||
print("---- FINAL PROVISIONING BUILD ---- \n");
|
||||
can_set_forwarding(0, 2);
|
||||
can_set_forwarding(1, 2);
|
||||
#endif
|
||||
|
||||
// LED should keep on blinking all the time
|
||||
uint32_t cnt = 0;
|
||||
for (cnt=0;;cnt++) {
|
||||
|
||||
@@ -180,13 +180,13 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
break;
|
||||
// **** 0xdd: get healthpacket and CANPacket versions
|
||||
case 0xdd:
|
||||
resp[0] = JUNGLE_HEALTH_PACKET_VERSION;
|
||||
resp[1] = CAN_PACKET_VERSION;
|
||||
resp[2] = CAN_HEALTH_PACKET_VERSION;
|
||||
resp_len = 3;
|
||||
// **** 0xdd: get healthpacket and CANPacket version hashes
|
||||
case 0xdd: {
|
||||
uint32_t versions[2] = {JUNGLE_HEALTH_PACKET_VERSION, CAN_PACKET_VERSION_HASH};
|
||||
(void)memcpy(resp, (uint8_t *)versions, sizeof(versions));
|
||||
resp_len = sizeof(versions);
|
||||
break;
|
||||
}
|
||||
// **** 0xde: set can bitrate
|
||||
case 0xde:
|
||||
if ((req->param1 < PANDA_CAN_CNT) && is_speed_valid(req->param2, speeds, sizeof(speeds)/sizeof(speeds[0]))) {
|
||||
|
||||
+20
-14
@@ -16,13 +16,9 @@
|
||||
|
||||
#include "board/drivers/can_common.h"
|
||||
|
||||
#ifdef STM32H7
|
||||
#include "board/drivers/fdcan.h"
|
||||
#else
|
||||
#include "board/drivers/bxcan.h"
|
||||
#endif
|
||||
#include "board/drivers/fdcan.h"
|
||||
|
||||
#include "board/power_saving.h"
|
||||
#include "board/sys/power_saving.h"
|
||||
|
||||
#include "board/obj/gitversion.h"
|
||||
|
||||
@@ -30,7 +26,7 @@
|
||||
#include "board/main_comms.h"
|
||||
|
||||
|
||||
// ********************* Serial debugging ********************
|
||||
// ********************* Serial debugging *********************
|
||||
|
||||
void debug_ring_callback(uart_ring *ring) {
|
||||
char rcv;
|
||||
@@ -49,7 +45,7 @@ void set_safety_mode(uint16_t mode, uint16_t param) {
|
||||
print("Error: safety set mode failed. Falling back to SILENT\n");
|
||||
mode_copy = SAFETY_SILENT;
|
||||
err = set_safety_hooks(mode_copy, 0U);
|
||||
// TERMINAL ERROR: we can't continue if SILENT safety mode isn't successfully set
|
||||
// TERMINAL ERROR: we can't continue if SILENT safety mode isn't succesfully set
|
||||
assert_fatal(err == 0, "Error: Failed setting SILENT mode. Hanging\n");
|
||||
}
|
||||
safety_tx_blocked = 0;
|
||||
@@ -152,7 +148,7 @@ static void tick_handler(void) {
|
||||
// re-init everything that uses harness status
|
||||
can_init_all();
|
||||
set_safety_mode(current_safety_mode, current_safety_param);
|
||||
set_power_save_state(power_save_status);
|
||||
set_power_save_state(power_save_enabled);
|
||||
}
|
||||
|
||||
// decimated to 1Hz
|
||||
@@ -166,12 +162,12 @@ static void tick_handler(void) {
|
||||
print("tx3:"); puth4(can_tx3_q.r_ptr); print("-"); puth4(can_tx3_q.w_ptr); print("\n");
|
||||
#endif
|
||||
|
||||
// set green LED to be controls allowed.
|
||||
// set green LED to be controls allowed
|
||||
led_set(LED_GREEN, controls_allowed);
|
||||
|
||||
// turn off the blue LED, turned on by CAN
|
||||
// unless we are in power saving mode
|
||||
led_set(LED_BLUE, (uptime_cnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
|
||||
led_set(LED_BLUE, (uptime_cnt & 1U) && power_save_enabled);
|
||||
|
||||
const bool recent_heartbeat = heartbeat_counter == 0U;
|
||||
|
||||
@@ -237,8 +233,8 @@ static void tick_handler(void) {
|
||||
set_safety_mode(SAFETY_SILENT, 0U);
|
||||
}
|
||||
|
||||
if (power_save_status != POWER_SAVE_STATUS_ENABLED) {
|
||||
set_power_save_state(POWER_SAVE_STATUS_ENABLED);
|
||||
if (!power_save_enabled) {
|
||||
set_power_save_state(true);
|
||||
}
|
||||
|
||||
// Also disable IR when the heartbeat goes missing
|
||||
@@ -347,7 +343,12 @@ int main(void) {
|
||||
|
||||
// LED should keep on blinking all the time
|
||||
while (true) {
|
||||
if (power_save_status == POWER_SAVE_STATUS_DISABLED) {
|
||||
#ifdef ALLOW_DEBUG
|
||||
if (stop_mode_requested) {
|
||||
enter_stop_mode();
|
||||
}
|
||||
#endif
|
||||
if (!power_save_enabled) {
|
||||
#ifdef DEBUG_FAULTS
|
||||
if (fault_status == FAULT_STATUS_NONE) {
|
||||
#endif
|
||||
@@ -375,6 +376,11 @@ int main(void) {
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if ((hw_type == HW_TYPE_CUATRO) && !current_board->read_som_gpio()) {
|
||||
assert_fatal(current_safety_mode == SAFETY_SILENT, "Error: Entering low power mode while not in SAFETY_SILENT. Hanging\n");
|
||||
enter_stop_mode(); // deep sleep, wakes on CAN or SBU activity
|
||||
assert_fatal(false, "Error: enter_stop_mode returned after system reset. Hanging\n");
|
||||
}
|
||||
__WFI();
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
}
|
||||
|
||||
+22
-11
@@ -24,13 +24,11 @@ static int get_health_pkt(void *dat) {
|
||||
health->safety_mode_pkt = (uint8_t)(current_safety_mode);
|
||||
health->safety_param_pkt = current_safety_param;
|
||||
health->alternative_experience_pkt = alternative_experience;
|
||||
health->power_save_enabled_pkt = power_save_status == POWER_SAVE_STATUS_ENABLED;
|
||||
health->power_save_enabled_pkt = power_save_enabled;
|
||||
health->heartbeat_lost_pkt = heartbeat_lost;
|
||||
health->safety_rx_checks_invalid_pkt = safety_rx_checks_invalid;
|
||||
|
||||
#ifndef STM32F4
|
||||
health->spi_error_count_pkt = spi_error_count;
|
||||
#endif
|
||||
health->spi_error_count_pkt = spi_error_count;
|
||||
|
||||
health->fault_status_pkt = fault_status;
|
||||
health->faults_pkt = faults;
|
||||
@@ -44,6 +42,11 @@ static int get_health_pkt(void *dat) {
|
||||
|
||||
health->som_reset_triggered = bootkick_reset_triggered;
|
||||
|
||||
health->sound_output_level_pkt = sound_output_level;
|
||||
|
||||
health->controls_allowed_lateral_pkt = controls_allowed || controls_allowed_lateral;
|
||||
health->controls_allowed_longitudinal_pkt = controls_allowed;
|
||||
|
||||
return sizeof(*health);
|
||||
}
|
||||
|
||||
@@ -97,6 +100,14 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
resp[1] = ((fan_state.rpm & 0xFF00U) >> 8U);
|
||||
resp_len = 2;
|
||||
break;
|
||||
// **** 0xb5: request deep sleep, wakes on CAN or SBU
|
||||
#ifdef ALLOW_DEBUG
|
||||
case 0xb5:
|
||||
set_safety_mode(SAFETY_SILENT, 0U);
|
||||
set_power_save_state(true);
|
||||
stop_mode_requested = true;
|
||||
break;
|
||||
#endif
|
||||
// **** 0xc0: reset communications state
|
||||
case 0xc0:
|
||||
comms_can_reset();
|
||||
@@ -218,13 +229,13 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
case 0xdc:
|
||||
set_safety_mode(req->param1, (uint16_t)req->param2);
|
||||
break;
|
||||
// **** 0xdd: get healthpacket and CANPacket versions
|
||||
case 0xdd:
|
||||
resp[0] = HEALTH_PACKET_VERSION;
|
||||
resp[1] = CAN_PACKET_VERSION;
|
||||
resp[2] = CAN_HEALTH_PACKET_VERSION;
|
||||
resp_len = 3;
|
||||
// **** 0xdd: get health and CAN packet versions
|
||||
case 0xdd: {
|
||||
uint32_t versions[2] = {HEALTH_PACKET_VERSION, CAN_PACKET_VERSION_HASH};
|
||||
(void)memcpy(resp, (uint8_t *)versions, sizeof(versions));
|
||||
resp_len = sizeof(versions);
|
||||
break;
|
||||
}
|
||||
// **** 0xde: set can bitrate
|
||||
case 0xde:
|
||||
if ((req->param1 < PANDA_CAN_CNT) && is_speed_valid(req->param2, speeds, sizeof(speeds)/sizeof(speeds[0]))) {
|
||||
@@ -267,7 +278,7 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
||||
break;
|
||||
// **** 0xe7: set power save state
|
||||
case 0xe7:
|
||||
set_power_save_state(req->param1);
|
||||
set_power_save_state(req->param1 != 0U);
|
||||
break;
|
||||
// **** 0xe8: set can-fd auto swithing mode
|
||||
case 0xe8:
|
||||
|
||||
@@ -20,3 +20,6 @@ extern bool heartbeat_disabled;
|
||||
|
||||
// siren state
|
||||
extern bool siren_enabled;
|
||||
|
||||
// sound
|
||||
extern uint16_t sound_output_level;
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#include "power_saving_declarations.h"
|
||||
|
||||
// WARNING: To stay in compliance with the SIL2 rules laid out in STM UM1840, we should never implement any of the available hardware low power modes.
|
||||
// See rule: CoU_3
|
||||
|
||||
int power_save_status = POWER_SAVE_STATUS_DISABLED;
|
||||
|
||||
void enable_can_transceivers(bool enabled) {
|
||||
// Leave main CAN always on for CAN-based ignition detection
|
||||
uint8_t main_bus = (harness.status == HARNESS_STATUS_FLIPPED) ? 3U : 1U;
|
||||
for(uint8_t i=1U; i<=4U; i++){
|
||||
current_board->enable_can_transceiver(i, (i == main_bus) || enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void set_power_save_state(int state) {
|
||||
bool is_valid_state = (state == POWER_SAVE_STATUS_ENABLED) || (state == POWER_SAVE_STATUS_DISABLED);
|
||||
if (is_valid_state && (state != power_save_status)) {
|
||||
bool enable = false;
|
||||
if (state == POWER_SAVE_STATUS_ENABLED) {
|
||||
print("enable power savings\n");
|
||||
|
||||
// Disable CAN interrupts
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
llcan_irq_disable(cans[0]);
|
||||
} else {
|
||||
llcan_irq_disable(cans[2]);
|
||||
}
|
||||
llcan_irq_disable(cans[1]);
|
||||
} else {
|
||||
print("disable power savings\n");
|
||||
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
llcan_irq_enable(cans[0]);
|
||||
} else {
|
||||
llcan_irq_enable(cans[2]);
|
||||
}
|
||||
llcan_irq_enable(cans[1]);
|
||||
|
||||
enable = true;
|
||||
}
|
||||
|
||||
enable_can_transceivers(enable);
|
||||
|
||||
// Switch off IR when in power saving
|
||||
if(!enable){
|
||||
current_board->set_ir_power(0U);
|
||||
}
|
||||
|
||||
power_save_status = state;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// WARNING: To stay in compliance with the SIL2 rules laid out in STM UM1840, we should never implement any of the available hardware low power modes.
|
||||
// See rule: CoU_3
|
||||
|
||||
#define POWER_SAVE_STATUS_DISABLED 0
|
||||
#define POWER_SAVE_STATUS_ENABLED 1
|
||||
|
||||
extern int power_save_status;
|
||||
|
||||
void set_power_save_state(int state);
|
||||
@@ -1,28 +0,0 @@
|
||||
// ///////////////////////////////////////////////////////////// //
|
||||
// Hardware abstraction layer for all different supported boards //
|
||||
// ///////////////////////////////////////////////////////////// //
|
||||
#include "board/boards/board_declarations.h"
|
||||
#include "board/boards/unused_funcs.h"
|
||||
|
||||
// ///// Board definition and detection ///// //
|
||||
#include "board/stm32f4/lladc.h"
|
||||
#include "board/drivers/harness.h"
|
||||
#include "board/drivers/fan.h"
|
||||
#include "board/stm32f4/llfan.h"
|
||||
#include "board/drivers/clock_source.h"
|
||||
#include "board/boards/dos.h"
|
||||
|
||||
void detect_board_type(void) {
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 1);
|
||||
if (!detect_with_pull(GPIOB, 1, PULL_UP) && !detect_with_pull(GPIOB, 7, PULL_UP)) {
|
||||
hw_type = HW_TYPE_DOS;
|
||||
current_board = &board_dos;
|
||||
} else if (!detect_with_pull(GPIOB, 15, PULL_UP)) {
|
||||
hw_type = HW_TYPE_DOS;
|
||||
current_board = &board_dos;
|
||||
}
|
||||
|
||||
// Return A13 to the alt mode to fix SWD
|
||||
set_gpio_alternate(GPIOA, 13, GPIO_AF0_SWJ);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
void clock_init(void) {
|
||||
// enable external oscillator
|
||||
register_set_bits(&(RCC->CR), RCC_CR_HSEON);
|
||||
while ((RCC->CR & RCC_CR_HSERDY) == 0U);
|
||||
|
||||
// divide things
|
||||
// AHB = 96MHz
|
||||
// APB1 = 48MHz
|
||||
// APB2 = 48MHz
|
||||
register_set(&(RCC->CFGR), RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV2, 0xFF7FFCF3U);
|
||||
|
||||
// 16MHz crystal
|
||||
// PLLM: 8
|
||||
// PLLN: 96
|
||||
// PLLP: 2
|
||||
// PLLQ: 4
|
||||
// P output: 96MHz
|
||||
// Q output: 48MHz
|
||||
register_set(&(RCC->PLLCFGR), RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE, 0x7F437FFFU);
|
||||
|
||||
// start PLL
|
||||
register_set_bits(&(RCC->CR), RCC_CR_PLLON);
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0U);
|
||||
|
||||
// Configure Flash prefetch, Instruction cache, Data cache and wait state
|
||||
// *** without this, it breaks ***
|
||||
register_set(&(FLASH->ACR), FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS, 0x1F0FU);
|
||||
|
||||
// switch to PLL
|
||||
register_set_bits(&(RCC->CFGR), RCC_CFGR_SW_PLL);
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
|
||||
|
||||
// *** running on PLL ***
|
||||
}
|
||||
@@ -1,284 +0,0 @@
|
||||
/**************************************************************************//**
|
||||
* @file cmsis_compiler.h
|
||||
* @brief CMSIS compiler generic header file
|
||||
* @version V5.1.0
|
||||
* @date 09. October 2018
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __CMSIS_COMPILER_H
|
||||
#define __CMSIS_COMPILER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Arm Compiler 4/5
|
||||
*/
|
||||
#if defined ( __CC_ARM )
|
||||
#include "cmsis_armcc.h"
|
||||
|
||||
|
||||
/*
|
||||
* Arm Compiler 6.6 LTM (armclang)
|
||||
*/
|
||||
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100)
|
||||
#include "cmsis_armclang_ltm.h"
|
||||
|
||||
/*
|
||||
* Arm Compiler above 6.10.1 (armclang)
|
||||
*/
|
||||
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
|
||||
#include "cmsis_armclang.h"
|
||||
|
||||
|
||||
/*
|
||||
* GNU Compiler
|
||||
*/
|
||||
#elif defined ( __GNUC__ )
|
||||
#include "cmsis_gcc.h"
|
||||
|
||||
|
||||
/*
|
||||
* IAR Compiler
|
||||
*/
|
||||
#elif defined ( __ICCARM__ )
|
||||
#include <cmsis_iccarm.h>
|
||||
|
||||
|
||||
/*
|
||||
* TI Arm Compiler
|
||||
*/
|
||||
#elif defined ( __TI_ARM__ )
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM __asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
#define __NO_RETURN __attribute__((noreturn))
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#define __USED __attribute__((used))
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT struct __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION union __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#define __RESTRICT __restrict
|
||||
#endif
|
||||
#ifndef __COMPILER_BARRIER
|
||||
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
|
||||
#define __COMPILER_BARRIER() (void)0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* TASKING Compiler
|
||||
*/
|
||||
#elif defined ( __TASKING__ )
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM __asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
#define __NO_RETURN __attribute__((noreturn))
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#define __USED __attribute__((used))
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __packed__
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT struct __packed__
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION union __packed__
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
struct __packed__ T_UINT32 { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __align(x)
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
|
||||
#define __RESTRICT
|
||||
#endif
|
||||
#ifndef __COMPILER_BARRIER
|
||||
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
|
||||
#define __COMPILER_BARRIER() (void)0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* COSMIC Compiler
|
||||
*/
|
||||
#elif defined ( __CSMC__ )
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM _asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
// NO RETURN is automatically detected hence no warning here
|
||||
#define __NO_RETURN
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#warning No compiler specific solution for __USED. __USED is ignored.
|
||||
#define __USED
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __weak
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED @packed
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT @packed struct
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION @packed union
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
@packed struct T_UINT32 { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
|
||||
#define __ALIGNED(x)
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
|
||||
#define __RESTRICT
|
||||
#endif
|
||||
#ifndef __COMPILER_BARRIER
|
||||
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
|
||||
#define __COMPILER_BARRIER() (void)0
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
#error Unknown compiler.
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __CMSIS_COMPILER_H */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,40 +0,0 @@
|
||||
/**************************************************************************//**
|
||||
* @file cmsis_version.h
|
||||
* @brief CMSIS Core(M) Version definitions
|
||||
* @version V5.0.3
|
||||
* @date 24. June 2019
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2009-2019 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined (__clang__)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CMSIS_VERSION_H
|
||||
#define __CMSIS_VERSION_H
|
||||
|
||||
/* CMSIS Version definitions */
|
||||
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
|
||||
#define __CM_CMSIS_VERSION_SUB ( 3U) /*!< [15:0] CMSIS Core(M) sub version */
|
||||
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
|
||||
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,273 +0,0 @@
|
||||
/******************************************************************************
|
||||
* @file mpu_armv7.h
|
||||
* @brief CMSIS MPU API for Armv7-M MPU
|
||||
* @version V5.1.0
|
||||
* @date 08. March 2019
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2017-2019 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined (__clang__)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef ARM_MPU_ARMV7_H
|
||||
#define ARM_MPU_ARMV7_H
|
||||
|
||||
#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes
|
||||
#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte
|
||||
#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes
|
||||
#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte
|
||||
#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes
|
||||
#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte
|
||||
#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes
|
||||
#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes
|
||||
|
||||
#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access
|
||||
#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only
|
||||
#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only
|
||||
#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access
|
||||
#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only
|
||||
#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access
|
||||
|
||||
/** MPU Region Base Address Register Value
|
||||
*
|
||||
* \param Region The region to be configured, number 0 to 15.
|
||||
* \param BaseAddress The base address for the region.
|
||||
*/
|
||||
#define ARM_MPU_RBAR(Region, BaseAddress) \
|
||||
(((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
|
||||
((Region) & MPU_RBAR_REGION_Msk) | \
|
||||
(MPU_RBAR_VALID_Msk))
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attributes
|
||||
*
|
||||
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
|
||||
* \param IsShareable Region is shareable between multiple bus masters.
|
||||
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
|
||||
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
|
||||
*/
|
||||
#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
|
||||
((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
|
||||
(((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
|
||||
(((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
|
||||
(((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
|
||||
|
||||
/**
|
||||
* MPU Region Attribute and Size Register Value
|
||||
*
|
||||
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
|
||||
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
|
||||
* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
|
||||
* \param SubRegionDisable Sub-region disable field.
|
||||
* \param Size Region size of the region to be configured, for example 4K, 8K.
|
||||
*/
|
||||
#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
|
||||
((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
|
||||
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
|
||||
(((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \
|
||||
(((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
|
||||
(((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
|
||||
(((MPU_RASR_ENABLE_Msk))))
|
||||
|
||||
/**
|
||||
* MPU Region Attribute and Size Register Value
|
||||
*
|
||||
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
|
||||
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
|
||||
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
|
||||
* \param IsShareable Region is shareable between multiple bus masters.
|
||||
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
|
||||
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
|
||||
* \param SubRegionDisable Sub-region disable field.
|
||||
* \param Size Region size of the region to be configured, for example 4K, 8K.
|
||||
*/
|
||||
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
|
||||
ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute for strongly ordered memory.
|
||||
* - TEX: 000b
|
||||
* - Shareable
|
||||
* - Non-cacheable
|
||||
* - Non-bufferable
|
||||
*/
|
||||
#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U)
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute for device memory.
|
||||
* - TEX: 000b (if shareable) or 010b (if non-shareable)
|
||||
* - Shareable or non-shareable
|
||||
* - Non-cacheable
|
||||
* - Bufferable (if shareable) or non-bufferable (if non-shareable)
|
||||
*
|
||||
* \param IsShareable Configures the device memory as shareable or non-shareable.
|
||||
*/
|
||||
#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U))
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute for normal memory.
|
||||
* - TEX: 1BBb (reflecting outer cacheability rules)
|
||||
* - Shareable or non-shareable
|
||||
* - Cacheable or non-cacheable (reflecting inner cacheability rules)
|
||||
* - Bufferable or non-bufferable (reflecting inner cacheability rules)
|
||||
*
|
||||
* \param OuterCp Configures the outer cache policy.
|
||||
* \param InnerCp Configures the inner cache policy.
|
||||
* \param IsShareable Configures the memory as shareable or non-shareable.
|
||||
*/
|
||||
#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U))
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute non-cacheable policy.
|
||||
*/
|
||||
#define ARM_MPU_CACHEP_NOCACHE 0U
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute write-back, write and read allocate policy.
|
||||
*/
|
||||
#define ARM_MPU_CACHEP_WB_WRA 1U
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute write-through, no write allocate policy.
|
||||
*/
|
||||
#define ARM_MPU_CACHEP_WT_NWA 2U
|
||||
|
||||
/**
|
||||
* MPU Memory Access Attribute write-back, no write allocate policy.
|
||||
*/
|
||||
#define ARM_MPU_CACHEP_WB_NWA 3U
|
||||
|
||||
|
||||
/**
|
||||
* Struct for a single MPU Region
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t RBAR; //!< The region base address register value (RBAR)
|
||||
uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
|
||||
} ARM_MPU_Region_t;
|
||||
|
||||
/** Enable the MPU.
|
||||
* \param MPU_Control Default access permissions for unconfigured regions.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
|
||||
{
|
||||
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
|
||||
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
|
||||
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
|
||||
#endif
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/** Disable the MPU.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_Disable(void)
|
||||
{
|
||||
__DMB();
|
||||
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
|
||||
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
|
||||
#endif
|
||||
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
|
||||
}
|
||||
|
||||
/** Clear and disable the given MPU region.
|
||||
* \param rnr Region number to be cleared.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
|
||||
{
|
||||
MPU->RNR = rnr;
|
||||
MPU->RASR = 0U;
|
||||
}
|
||||
|
||||
/** Configure an MPU region.
|
||||
* \param rbar Value for RBAR register.
|
||||
* \param rsar Value for RSAR register.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
|
||||
{
|
||||
MPU->RBAR = rbar;
|
||||
MPU->RASR = rasr;
|
||||
}
|
||||
|
||||
/** Configure the given MPU region.
|
||||
* \param rnr Region number to be configured.
|
||||
* \param rbar Value for RBAR register.
|
||||
* \param rsar Value for RSAR register.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
|
||||
{
|
||||
MPU->RNR = rnr;
|
||||
MPU->RBAR = rbar;
|
||||
MPU->RASR = rasr;
|
||||
}
|
||||
|
||||
/** Memcopy with strictly ordered memory access, e.g. for register targets.
|
||||
* \param dst Destination data is copied to.
|
||||
* \param src Source data is copied from.
|
||||
* \param len Amount of data words to be copied.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0U; i < len; ++i)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/** Load the given number of MPU regions from a table.
|
||||
* \param table Pointer to the MPU configuration table.
|
||||
* \param cnt Amount of regions to be configured.
|
||||
*/
|
||||
__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
|
||||
{
|
||||
const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
|
||||
while (cnt > MPU_TYPE_RALIASES) {
|
||||
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
|
||||
table += MPU_TYPE_RALIASES;
|
||||
cnt -= MPU_TYPE_RALIASES;
|
||||
}
|
||||
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,271 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f4xx.h
|
||||
* @author MCD Application Team
|
||||
* @version V2.6.0
|
||||
* @date 04-November-2016
|
||||
* @brief CMSIS STM32F4xx Device Peripheral Access Layer Header File.
|
||||
*
|
||||
* The file is the unique include file that the application programmer
|
||||
* is using in the C source code, usually in main.c. This file contains:
|
||||
* - Configuration section that allows to select:
|
||||
* - The STM32F4xx device used in the target application
|
||||
* - To use or not the peripheral’s drivers in application code(i.e.
|
||||
* code will be based on direct access to peripheral’s registers
|
||||
* rather than drivers API), this option is controlled by
|
||||
* "#define USE_HAL_DRIVER"
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32f4xx
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __STM32F4xx_H
|
||||
#define __STM32F4xx_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/** @addtogroup Library_configuration_section
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief STM32 Family
|
||||
*/
|
||||
#if !defined (STM32F4)
|
||||
#define STM32F4
|
||||
#endif /* STM32F4 */
|
||||
|
||||
/* Uncomment the line below according to the target STM32 device used in your
|
||||
application
|
||||
*/
|
||||
/* #if !defined (STM32F405xx) && !defined (STM32F415xx) && !defined (STM32F407xx) && !defined (STM32F417xx) && \
|
||||
!defined (STM32F427xx) && !defined (STM32F437xx) && !defined (STM32F429xx) && !defined (STM32F439xx) && \
|
||||
!defined (STM32F401xC) && !defined (STM32F401xE) && !defined (STM32F410Tx) && !defined (STM32F410Cx) && \
|
||||
!defined (STM32F410Rx) && !defined (STM32F411xE) && !defined (STM32F446xx) && !defined (STM32F469xx) && \
|
||||
!defined (STM32F479xx) && !defined (STM32F412Cx) && !defined (STM32F412Rx) && !defined (STM32F412Vx) && \
|
||||
!defined (STM32F412Zx) && !defined (STM32F413xx) && !defined (STM32F423xx) */
|
||||
/* #define STM32F405xx */ /*!< STM32F405RG, STM32F405VG and STM32F405ZG Devices */
|
||||
/* #define STM32F415xx */ /*!< STM32F415RG, STM32F415VG and STM32F415ZG Devices */
|
||||
/* #define STM32F407xx */ /*!< STM32F407VG, STM32F407VE, STM32F407ZG, STM32F407ZE, STM32F407IG and STM32F407IE Devices */
|
||||
/* #define STM32F417xx */ /*!< STM32F417VG, STM32F417VE, STM32F417ZG, STM32F417ZE, STM32F417IG and STM32F417IE Devices */
|
||||
/* #define STM32F427xx */ /*!< STM32F427VG, STM32F427VI, STM32F427ZG, STM32F427ZI, STM32F427IG and STM32F427II Devices */
|
||||
/* #define STM32F437xx */ /*!< STM32F437VG, STM32F437VI, STM32F437ZG, STM32F437ZI, STM32F437IG and STM32F437II Devices */
|
||||
/* #define STM32F429xx */ /*!< STM32F429VG, STM32F429VI, STM32F429ZG, STM32F429ZI, STM32F429BG, STM32F429BI, STM32F429NG,
|
||||
STM32F439NI, STM32F429IG and STM32F429II Devices */
|
||||
/* #define STM32F439xx */ /*!< STM32F439VG, STM32F439VI, STM32F439ZG, STM32F439ZI, STM32F439BG, STM32F439BI, STM32F439NG,
|
||||
STM32F439NI, STM32F439IG and STM32F439II Devices */
|
||||
/* #define STM32F401xC */ /*!< STM32F401CB, STM32F401CC, STM32F401RB, STM32F401RC, STM32F401VB and STM32F401VC Devices */
|
||||
/* #define STM32F401xE */ /*!< STM32F401CD, STM32F401RD, STM32F401VD, STM32F401CE, STM32F401RE and STM32F401VE Devices */
|
||||
/* #define STM32F410Tx */ /*!< STM32F410T8 and STM32F410TB Devices */
|
||||
/* #define STM32F410Cx */ /*!< STM32F410C8 and STM32F410CB Devices */
|
||||
/* #define STM32F410Rx */ /*!< STM32F410R8 and STM32F410RB Devices */
|
||||
/* #define STM32F411xE */ /*!< STM32F411CC, STM32F411RC, STM32F411VC, STM32F411CE, STM32F411RE and STM32F411VE Devices */
|
||||
/* #define STM32F446xx */ /*!< STM32F446MC, STM32F446ME, STM32F446RC, STM32F446RE, STM32F446VC, STM32F446VE, STM32F446ZC,
|
||||
and STM32F446ZE Devices */
|
||||
/* #define STM32F469xx */ /*!< STM32F469AI, STM32F469II, STM32F469BI, STM32F469NI, STM32F469AG, STM32F469IG, STM32F469BG,
|
||||
STM32F469NG, STM32F469AE, STM32F469IE, STM32F469BE and STM32F469NE Devices */
|
||||
/* #define STM32F479xx */ /*!< STM32F479AI, STM32F479II, STM32F479BI, STM32F479NI, STM32F479AG, STM32F479IG, STM32F479BG
|
||||
and STM32F479NG Devices */
|
||||
/* #define STM32F412Cx */ /*!< STM32F412CEU and STM32F412CGU Devices */
|
||||
/* #define STM32F412Zx */ /*!< STM32F412ZET, STM32F412ZGT, STM32F412ZEJ and STM32F412ZGJ Devices */
|
||||
/* #define STM32F412Vx */ /*!< STM32F412VET, STM32F412VGT, STM32F412VEH and STM32F412VGH Devices */
|
||||
/* #define STM32F412Rx */ /*!< STM32F412RET, STM32F412RGT, STM32F412REY and STM32F412RGY Devices */
|
||||
/* #define STM32F413xx */ /*!< STM32F413CH, STM32F413MH, STM32F413RH, STM32F413VH, STM32F413ZH, STM32F413CG, STM32F413MG,
|
||||
STM32F413RG, STM32F413VG and STM32F413ZG Devices */
|
||||
/* #define STM32F423xx */ /*!< STM32F423CH, STM32F423RH, STM32F423VH and STM32F423ZH Devices */
|
||||
//#endif
|
||||
|
||||
/* Tip: To avoid modifying this file each time you need to switch between these
|
||||
devices, you can define the device in your toolchain compiler preprocessor.
|
||||
*/
|
||||
#if !defined (USE_HAL_DRIVER)
|
||||
/**
|
||||
* @brief Comment the line below if you will not use the peripherals drivers.
|
||||
In this case, these drivers will not be included and the application code will
|
||||
be based on direct access to peripherals registers
|
||||
*/
|
||||
/*#define USE_HAL_DRIVER */
|
||||
#endif /* USE_HAL_DRIVER */
|
||||
|
||||
/**
|
||||
* @brief CMSIS version number V2.6.0
|
||||
*/
|
||||
#define __STM32F4xx_CMSIS_VERSION_MAIN (0x02U) /*!< [31:24] main version */
|
||||
#define __STM32F4xx_CMSIS_VERSION_SUB1 (0x06U) /*!< [23:16] sub1 version */
|
||||
#define __STM32F4xx_CMSIS_VERSION_SUB2 (0x00U) /*!< [15:8] sub2 version */
|
||||
#define __STM32F4xx_CMSIS_VERSION_RC (0x00U) /*!< [7:0] release candidate */
|
||||
#define __STM32F4xx_CMSIS_VERSION ((__STM32F4xx_CMSIS_VERSION_MAIN << 24)\
|
||||
|(__STM32F4xx_CMSIS_VERSION_SUB1 << 16)\
|
||||
|(__STM32F4xx_CMSIS_VERSION_SUB2 << 8 )\
|
||||
|(__STM32F4xx_CMSIS_VERSION))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Device_Included
|
||||
* @{
|
||||
*/
|
||||
|
||||
// #if defined(STM32F405xx)
|
||||
// #include "stm32f405xx.h"
|
||||
// #elif defined(STM32F415xx)
|
||||
// #include "stm32f415xx.h"
|
||||
// #elif defined(STM32F407xx)
|
||||
// #include "stm32f407xx.h"
|
||||
// #elif defined(STM32F417xx)
|
||||
// #include "stm32f417xx.h"
|
||||
// #elif defined(STM32F427xx)
|
||||
// #include "stm32f427xx.h"
|
||||
// #elif defined(STM32F437xx)
|
||||
// #include "stm32f437xx.h"
|
||||
// #elif defined(STM32F429xx)
|
||||
// #include "stm32f429xx.h"
|
||||
// #elif defined(STM32F439xx)
|
||||
// #include "stm32f439xx.h"
|
||||
// #elif defined(STM32F401xC)
|
||||
// #include "stm32f401xc.h"
|
||||
// #elif defined(STM32F401xE)
|
||||
// #include "stm32f401xe.h"
|
||||
// #elif defined(STM32F410Tx)
|
||||
// #include "stm32f410tx.h"
|
||||
// #elif defined(STM32F410Cx)
|
||||
// #include "stm32f410cx.h"
|
||||
// #elif defined(STM32F410Rx)
|
||||
// #include "stm32f410rx.h"
|
||||
// #elif defined(STM32F411xE)
|
||||
// #include "stm32f411xe.h"
|
||||
// #elif defined(STM32F446xx)
|
||||
// #include "stm32f446xx.h"
|
||||
// #elif defined(STM32F469xx)
|
||||
// #include "stm32f469xx.h"
|
||||
// #elif defined(STM32F479xx)
|
||||
// #include "stm32f479xx.h"
|
||||
// #elif defined(STM32F412Cx)
|
||||
// #include "stm32f412cx.h"
|
||||
// #elif defined(STM32F412Zx)
|
||||
// #include "stm32f412zx.h"
|
||||
// #elif defined(STM32F412Rx)
|
||||
// #include "stm32f412rx.h"
|
||||
// #elif defined(STM32F412Vx)
|
||||
// #include "stm32f412vx.h"
|
||||
#if defined(STM32F413xx)
|
||||
#include "stm32f413xx.h"
|
||||
#elif defined(STM32F423xx)
|
||||
#include "stm32f423xx.h"
|
||||
#else
|
||||
#error "Please select first the target STM32F4xx device used in your application (in stm32f4xx.h file)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Exported_types
|
||||
* @{
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
RESET = 0U,
|
||||
SET = !RESET
|
||||
} FlagStatus, ITStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DISABLE = 0U,
|
||||
ENABLE = !DISABLE
|
||||
} FunctionalState;
|
||||
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ERROR = 0U,
|
||||
SUCCESS = !ERROR
|
||||
} ErrorStatus;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Exported_macro
|
||||
* @{
|
||||
*/
|
||||
#define SET_BIT(REG, BIT) ((REG) |= (BIT))
|
||||
|
||||
#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
|
||||
|
||||
#define READ_BIT(REG, BIT) ((REG) & (BIT))
|
||||
|
||||
#define CLEAR_REG(REG) ((REG) = (0x0))
|
||||
|
||||
#define WRITE_REG(REG, VAL) ((REG) = (VAL))
|
||||
|
||||
#define READ_REG(REG) ((REG))
|
||||
|
||||
#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
|
||||
|
||||
#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL)))
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#if defined (USE_HAL_DRIVER)
|
||||
#include "stm32f4xx_hal.h"
|
||||
#endif /* USE_HAL_DRIVER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __STM32F4xx_H */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@@ -1,214 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f4xx_hal_def.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.6.0
|
||||
* @date 04-November-2016
|
||||
* @brief This file contains HAL common defines, enumeration, macros and
|
||||
* structures definitions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32F4xx_HAL_DEF
|
||||
#define __STM32F4xx_HAL_DEF
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f4xx.h"
|
||||
//#include "Legacy/stm32_hal_legacy.h"
|
||||
//#include <stdio.h>
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief HAL Status structures definition
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HAL_OK = 0x00U,
|
||||
HAL_ERROR = 0x01U,
|
||||
HAL_BUSY = 0x02U,
|
||||
HAL_TIMEOUT = 0x03U
|
||||
} HAL_StatusTypeDef;
|
||||
|
||||
/**
|
||||
* @brief HAL Lock structures definition
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HAL_UNLOCKED = 0x00U,
|
||||
HAL_LOCKED = 0x01U
|
||||
} HAL_LockTypeDef;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#define HAL_MAX_DELAY 0xFFFFFFFFU
|
||||
|
||||
#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET)
|
||||
#define HAL_IS_BIT_CLR(REG, BIT) (((REG) & (BIT)) == RESET)
|
||||
|
||||
#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__) \
|
||||
do{ \
|
||||
(__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \
|
||||
(__DMA_HANDLE__).Parent = (__HANDLE__); \
|
||||
} while(0)
|
||||
|
||||
#define UNUSED(x) ((void)(x))
|
||||
|
||||
/** @brief Reset the Handle's State field.
|
||||
* @param __HANDLE__: specifies the Peripheral Handle.
|
||||
* @note This macro can be used for the following purpose:
|
||||
* - When the Handle is declared as local variable; before passing it as parameter
|
||||
* to HAL_PPP_Init() for the first time, it is mandatory to use this macro
|
||||
* to set to 0 the Handle's "State" field.
|
||||
* Otherwise, "State" field may have any random value and the first time the function
|
||||
* HAL_PPP_Init() is called, the low level hardware initialization will be missed
|
||||
* (i.e. HAL_PPP_MspInit() will not be executed).
|
||||
* - When there is a need to reconfigure the low level hardware: instead of calling
|
||||
* HAL_PPP_DeInit() then HAL_PPP_Init(), user can make a call to this macro then HAL_PPP_Init().
|
||||
* In this later function, when the Handle's "State" field is set to 0, it will execute the function
|
||||
* HAL_PPP_MspInit() which will reconfigure the low level hardware.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = 0U)
|
||||
|
||||
#if (USE_RTOS == 1)
|
||||
/* Reserved for future use */
|
||||
#error "USE_RTOS should be 0 in the current HAL release"
|
||||
#else
|
||||
#define __HAL_LOCK(__HANDLE__) \
|
||||
do{ \
|
||||
if((__HANDLE__)->Lock == HAL_LOCKED) \
|
||||
{ \
|
||||
return HAL_BUSY; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(__HANDLE__)->Lock = HAL_LOCKED; \
|
||||
} \
|
||||
}while (0)
|
||||
|
||||
#define __HAL_UNLOCK(__HANDLE__) \
|
||||
do{ \
|
||||
(__HANDLE__)->Lock = HAL_UNLOCKED; \
|
||||
}while (0)
|
||||
#endif /* USE_RTOS */
|
||||
|
||||
#if defined ( __GNUC__ )
|
||||
#ifndef __weak
|
||||
#define __weak __attribute__((weak))
|
||||
#endif /* __weak */
|
||||
#ifndef __packed
|
||||
#define __packed __attribute__((__packed__))
|
||||
#endif /* __packed */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
|
||||
/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */
|
||||
#if defined (__GNUC__) /* GNU Compiler */
|
||||
#ifndef __ALIGN_END
|
||||
#define __ALIGN_END __attribute__ ((aligned (4)))
|
||||
#endif /* __ALIGN_END */
|
||||
#ifndef __ALIGN_BEGIN
|
||||
#define __ALIGN_BEGIN
|
||||
#endif /* __ALIGN_BEGIN */
|
||||
#else
|
||||
#ifndef __ALIGN_END
|
||||
#define __ALIGN_END
|
||||
#endif /* __ALIGN_END */
|
||||
#ifndef __ALIGN_BEGIN
|
||||
#if defined (__CC_ARM) /* ARM Compiler */
|
||||
#define __ALIGN_BEGIN __align(4)
|
||||
#elif defined (__ICCARM__) /* IAR Compiler */
|
||||
#define __ALIGN_BEGIN
|
||||
#endif /* __CC_ARM */
|
||||
#endif /* __ALIGN_BEGIN */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
|
||||
/**
|
||||
* @brief __RAM_FUNC definition
|
||||
*/
|
||||
#if defined ( __CC_ARM )
|
||||
/* ARM Compiler
|
||||
------------
|
||||
RAM functions are defined using the toolchain options.
|
||||
Functions that are executed in RAM should reside in a separate source module.
|
||||
Using the 'Options for File' dialog you can simply change the 'Code / Const'
|
||||
area of a module to a memory space in physical RAM.
|
||||
Available memory areas are declared in the 'Target' tab of the 'Options for Target'
|
||||
dialog.
|
||||
*/
|
||||
#define __RAM_FUNC HAL_StatusTypeDef
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
/* ICCARM Compiler
|
||||
---------------
|
||||
RAM functions are defined using a specific toolchain keyword "__ramfunc".
|
||||
*/
|
||||
#define __RAM_FUNC __ramfunc HAL_StatusTypeDef
|
||||
|
||||
#elif defined ( __GNUC__ )
|
||||
/* GNU Compiler
|
||||
------------
|
||||
RAM functions are defined using a specific toolchain attribute
|
||||
"__attribute__((section(".RamFunc")))".
|
||||
*/
|
||||
#define __RAM_FUNC HAL_StatusTypeDef __attribute__((section(".RamFunc")))
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief __NOINLINE definition
|
||||
*/
|
||||
#if defined ( __CC_ARM ) || defined ( __GNUC__ )
|
||||
/* ARM & GNUCompiler
|
||||
----------------
|
||||
*/
|
||||
#define __NOINLINE __attribute__ ( (noinline) )
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
/* ICCARM Compiler
|
||||
---------------
|
||||
*/
|
||||
#define __NOINLINE _Pragma("optimize = no_inline")
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ___STM32F4xx_HAL_DEF */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,124 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file system_stm32f4xx.h
|
||||
* @author MCD Application Team
|
||||
* @version V2.6.0
|
||||
* @date 04-November-2016
|
||||
* @brief CMSIS Cortex-M4 Device System Source File for STM32F4xx devices.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32f4xx_system
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Define to prevent recursive inclusion
|
||||
*/
|
||||
#ifndef __SYSTEM_STM32F4XX_H
|
||||
#define __SYSTEM_STM32F4XX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Includes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Exported_types
|
||||
* @{
|
||||
*/
|
||||
/* This variable is updated in three ways:
|
||||
1) by calling CMSIS function SystemCoreClockUpdate()
|
||||
2) by calling HAL API function HAL_RCC_GetSysClockFreq()
|
||||
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
|
||||
Note: If you use this function to configure the system clock; then there
|
||||
is no need to call the 2 first functions listed above, since SystemCoreClock
|
||||
variable is updated automatically.
|
||||
*/
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
|
||||
extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */
|
||||
extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Exported_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F4xx_System_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern void SystemInit(void);
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__SYSTEM_STM32F4XX_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@@ -1,98 +0,0 @@
|
||||
// ********************* Bare interrupt handlers *********************
|
||||
// Only implemented the STM32F413 interrupts for now
|
||||
|
||||
void WWDG_IRQHandler(void) {handle_interrupt(WWDG_IRQn);}
|
||||
void PVD_IRQHandler(void) {handle_interrupt(PVD_IRQn);}
|
||||
void TAMP_STAMP_IRQHandler(void) {handle_interrupt(TAMP_STAMP_IRQn);}
|
||||
void RTC_WKUP_IRQHandler(void) {handle_interrupt(RTC_WKUP_IRQn);}
|
||||
void FLASH_IRQHandler(void) {handle_interrupt(FLASH_IRQn);}
|
||||
void RCC_IRQHandler(void) {handle_interrupt(RCC_IRQn);}
|
||||
void EXTI0_IRQHandler(void) {handle_interrupt(EXTI0_IRQn);}
|
||||
void EXTI1_IRQHandler(void) {handle_interrupt(EXTI1_IRQn);}
|
||||
void EXTI2_IRQHandler(void) {handle_interrupt(EXTI2_IRQn);}
|
||||
void EXTI3_IRQHandler(void) {handle_interrupt(EXTI3_IRQn);}
|
||||
void EXTI4_IRQHandler(void) {handle_interrupt(EXTI4_IRQn);}
|
||||
void DMA1_Stream0_IRQHandler(void) {handle_interrupt(DMA1_Stream0_IRQn);}
|
||||
void DMA1_Stream1_IRQHandler(void) {handle_interrupt(DMA1_Stream1_IRQn);}
|
||||
void DMA1_Stream2_IRQHandler(void) {handle_interrupt(DMA1_Stream2_IRQn);}
|
||||
void DMA1_Stream3_IRQHandler(void) {handle_interrupt(DMA1_Stream3_IRQn);}
|
||||
void DMA1_Stream4_IRQHandler(void) {handle_interrupt(DMA1_Stream4_IRQn);}
|
||||
void DMA1_Stream5_IRQHandler(void) {handle_interrupt(DMA1_Stream5_IRQn);}
|
||||
void DMA1_Stream6_IRQHandler(void) {handle_interrupt(DMA1_Stream6_IRQn);}
|
||||
void ADC_IRQHandler(void) {handle_interrupt(ADC_IRQn);}
|
||||
void CAN1_TX_IRQHandler(void) {handle_interrupt(CAN1_TX_IRQn);}
|
||||
void CAN1_RX0_IRQHandler(void) {handle_interrupt(CAN1_RX0_IRQn);}
|
||||
void CAN1_RX1_IRQHandler(void) {handle_interrupt(CAN1_RX1_IRQn);}
|
||||
void CAN1_SCE_IRQHandler(void) {handle_interrupt(CAN1_SCE_IRQn);}
|
||||
void EXTI9_5_IRQHandler(void) {handle_interrupt(EXTI9_5_IRQn);}
|
||||
void TIM1_BRK_TIM9_IRQHandler(void) {handle_interrupt(TIM1_BRK_TIM9_IRQn);}
|
||||
void TIM1_UP_TIM10_IRQHandler(void) {handle_interrupt(TIM1_UP_TIM10_IRQn);}
|
||||
void TIM1_TRG_COM_TIM11_IRQHandler(void) {handle_interrupt(TIM1_TRG_COM_TIM11_IRQn);}
|
||||
void TIM1_CC_IRQHandler(void) {handle_interrupt(TIM1_CC_IRQn);}
|
||||
void TIM2_IRQHandler(void) {handle_interrupt(TIM2_IRQn);}
|
||||
void TIM3_IRQHandler(void) {handle_interrupt(TIM3_IRQn);}
|
||||
void TIM4_IRQHandler(void) {handle_interrupt(TIM4_IRQn);}
|
||||
void I2C1_EV_IRQHandler(void) {handle_interrupt(I2C1_EV_IRQn);}
|
||||
void I2C1_ER_IRQHandler(void) {handle_interrupt(I2C1_ER_IRQn);}
|
||||
void I2C2_EV_IRQHandler(void) {handle_interrupt(I2C2_EV_IRQn);}
|
||||
void I2C2_ER_IRQHandler(void) {handle_interrupt(I2C2_ER_IRQn);}
|
||||
void SPI1_IRQHandler(void) {handle_interrupt(SPI1_IRQn);}
|
||||
void SPI2_IRQHandler(void) {handle_interrupt(SPI2_IRQn);}
|
||||
void USART1_IRQHandler(void) {handle_interrupt(USART1_IRQn);}
|
||||
void USART2_IRQHandler(void) {handle_interrupt(USART2_IRQn);}
|
||||
void USART3_IRQHandler(void) {handle_interrupt(USART3_IRQn);}
|
||||
void EXTI15_10_IRQHandler(void) {handle_interrupt(EXTI15_10_IRQn);}
|
||||
void RTC_Alarm_IRQHandler(void) {handle_interrupt(RTC_Alarm_IRQn);}
|
||||
void OTG_FS_WKUP_IRQHandler(void) {handle_interrupt(OTG_FS_WKUP_IRQn);}
|
||||
void TIM8_BRK_TIM12_IRQHandler(void) {handle_interrupt(TIM8_BRK_TIM12_IRQn);}
|
||||
void TIM8_UP_TIM13_IRQHandler(void) {handle_interrupt(TIM8_UP_TIM13_IRQn);}
|
||||
void TIM8_TRG_COM_TIM14_IRQHandler(void) {handle_interrupt(TIM8_TRG_COM_TIM14_IRQn);}
|
||||
void TIM8_CC_IRQHandler(void) {handle_interrupt(TIM8_CC_IRQn);}
|
||||
void DMA1_Stream7_IRQHandler(void) {handle_interrupt(DMA1_Stream7_IRQn);}
|
||||
void FSMC_IRQHandler(void) {handle_interrupt(FSMC_IRQn);}
|
||||
void SDIO_IRQHandler(void) {handle_interrupt(SDIO_IRQn);}
|
||||
void TIM5_IRQHandler(void) {handle_interrupt(TIM5_IRQn);}
|
||||
void SPI3_IRQHandler(void) {handle_interrupt(SPI3_IRQn);}
|
||||
void UART4_IRQHandler(void) {handle_interrupt(UART4_IRQn);}
|
||||
void UART5_IRQHandler(void) {handle_interrupt(UART5_IRQn);}
|
||||
void TIM6_DAC_IRQHandler(void) {handle_interrupt(TIM6_DAC_IRQn);}
|
||||
void TIM7_IRQHandler(void) {handle_interrupt(TIM7_IRQn);}
|
||||
void DMA2_Stream0_IRQHandler(void) {handle_interrupt(DMA2_Stream0_IRQn);}
|
||||
void DMA2_Stream1_IRQHandler(void) {handle_interrupt(DMA2_Stream1_IRQn);}
|
||||
void DMA2_Stream2_IRQHandler(void) {handle_interrupt(DMA2_Stream2_IRQn);}
|
||||
void DMA2_Stream3_IRQHandler(void) {handle_interrupt(DMA2_Stream3_IRQn);}
|
||||
void DMA2_Stream4_IRQHandler(void) {handle_interrupt(DMA2_Stream4_IRQn);}
|
||||
void CAN2_TX_IRQHandler(void) {handle_interrupt(CAN2_TX_IRQn);}
|
||||
void CAN2_RX0_IRQHandler(void) {handle_interrupt(CAN2_RX0_IRQn);}
|
||||
void CAN2_RX1_IRQHandler(void) {handle_interrupt(CAN2_RX1_IRQn);}
|
||||
void CAN2_SCE_IRQHandler(void) {handle_interrupt(CAN2_SCE_IRQn);}
|
||||
void OTG_FS_IRQHandler(void) {handle_interrupt(OTG_FS_IRQn);}
|
||||
void DMA2_Stream5_IRQHandler(void) {handle_interrupt(DMA2_Stream5_IRQn);}
|
||||
void DMA2_Stream6_IRQHandler(void) {handle_interrupt(DMA2_Stream6_IRQn);}
|
||||
void DMA2_Stream7_IRQHandler(void) {handle_interrupt(DMA2_Stream7_IRQn);}
|
||||
void USART6_IRQHandler(void) {handle_interrupt(USART6_IRQn);}
|
||||
void I2C3_EV_IRQHandler(void) {handle_interrupt(I2C3_EV_IRQn);}
|
||||
void I2C3_ER_IRQHandler(void) {handle_interrupt(I2C3_ER_IRQn);}
|
||||
void DFSDM1_FLT0_IRQHandler(void) {handle_interrupt(DFSDM1_FLT0_IRQn);}
|
||||
void DFSDM1_FLT1_IRQHandler(void) {handle_interrupt(DFSDM1_FLT1_IRQn);}
|
||||
void CAN3_TX_IRQHandler(void) {handle_interrupt(CAN3_TX_IRQn);}
|
||||
void CAN3_RX0_IRQHandler(void) {handle_interrupt(CAN3_RX0_IRQn);}
|
||||
void CAN3_RX1_IRQHandler(void) {handle_interrupt(CAN3_RX1_IRQn);}
|
||||
void CAN3_SCE_IRQHandler(void) {handle_interrupt(CAN3_SCE_IRQn);}
|
||||
void RNG_IRQHandler(void) {handle_interrupt(RNG_IRQn);}
|
||||
void FPU_IRQHandler(void) {handle_interrupt(FPU_IRQn);}
|
||||
void UART7_IRQHandler(void) {handle_interrupt(UART7_IRQn);}
|
||||
void UART8_IRQHandler(void) {handle_interrupt(UART8_IRQn);}
|
||||
void SPI4_IRQHandler(void) {handle_interrupt(SPI4_IRQn);}
|
||||
void SPI5_IRQHandler(void) {handle_interrupt(SPI5_IRQn);}
|
||||
void SAI1_IRQHandler(void) {handle_interrupt(SAI1_IRQn);}
|
||||
void UART9_IRQHandler(void) {handle_interrupt(UART9_IRQn);}
|
||||
void UART10_IRQHandler(void) {handle_interrupt(UART10_IRQn);}
|
||||
void QUADSPI_IRQHandler(void) {handle_interrupt(QUADSPI_IRQn);}
|
||||
void FMPI2C1_EV_IRQHandler(void) {handle_interrupt(FMPI2C1_EV_IRQn);}
|
||||
void FMPI2C1_ER_IRQHandler(void) {handle_interrupt(FMPI2C1_ER_IRQn);}
|
||||
void LPTIM1_IRQHandler(void) {handle_interrupt(LPTIM1_IRQn);}
|
||||
void DFSDM2_FLT0_IRQHandler(void) {handle_interrupt(DFSDM2_FLT0_IRQn);}
|
||||
void DFSDM2_FLT1_IRQHandler(void) {handle_interrupt(DFSDM2_FLT1_IRQn);}
|
||||
void DFSDM2_FLT2_IRQHandler(void) {handle_interrupt(DFSDM2_FLT2_IRQn);}
|
||||
void DFSDM2_FLT3_IRQHandler(void) {handle_interrupt(DFSDM2_FLT3_IRQn);}
|
||||
@@ -1,34 +0,0 @@
|
||||
#include "lladc_declarations.h"
|
||||
|
||||
void register_set(volatile uint32_t *addr, uint32_t val, uint32_t mask);
|
||||
|
||||
void adc_init(ADC_TypeDef *adc) {
|
||||
register_set(&(ADC->CCR), ADC_CCR_TSVREFE | ADC_CCR_VBATE, 0xC30000U);
|
||||
register_set(&(adc->CR2), ADC_CR2_ADON, 0xFF7F0F03U);
|
||||
}
|
||||
|
||||
static uint16_t adc_get_raw(const adc_signal_t *signal) {
|
||||
// sample time
|
||||
if (signal->channel < 10U) {
|
||||
signal->adc->SMPR2 = ((uint32_t) signal->sample_time << (signal->channel * 3U));
|
||||
} else {
|
||||
signal->adc->SMPR1 = ((uint32_t) signal->sample_time << ((signal->channel - 10U) * 3U));
|
||||
}
|
||||
|
||||
// select channel
|
||||
signal->adc->JSQR = ((uint32_t) signal->channel << 15U);
|
||||
|
||||
// start conversion
|
||||
signal->adc->SR &= ~(ADC_SR_JEOC);
|
||||
signal->adc->CR2 |= ADC_CR2_JSWSTART;
|
||||
uint32_t timeout = 0U;
|
||||
while (!(signal->adc->SR & ADC_SR_JEOC)) {
|
||||
if (++timeout > 100000U) { break; }
|
||||
}
|
||||
|
||||
return signal->adc->JDR1;
|
||||
}
|
||||
|
||||
uint16_t adc_get_mV(const adc_signal_t *signal) {
|
||||
return (adc_get_raw(signal) * current_board->avdd_mV) / 4095U;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
SAMPLETIME_3_CYCLES = 0,
|
||||
SAMPLETIME_15_CYCLES = 1,
|
||||
SAMPLETIME_28_CYCLES = 2,
|
||||
SAMPLETIME_56_CYCLES = 3,
|
||||
SAMPLETIME_84_CYCLES = 4,
|
||||
SAMPLETIME_112_CYCLES = 5,
|
||||
SAMPLETIME_144_CYCLES = 6,
|
||||
SAMPLETIME_480_CYCLES = 7
|
||||
} adc_sample_time_t;
|
||||
|
||||
typedef struct {
|
||||
ADC_TypeDef *adc;
|
||||
uint8_t channel;
|
||||
adc_sample_time_t sample_time;
|
||||
} adc_signal_t;
|
||||
|
||||
#define ADC_CHANNEL_DEFAULT(a, c) {.adc = (a), .channel = (c), .sample_time = SAMPLETIME_480_CYCLES}
|
||||
@@ -1,140 +0,0 @@
|
||||
#include "llbxcan_declarations.h"
|
||||
|
||||
// kbps multiplied by 10
|
||||
const uint32_t speeds[SPEEDS_ARRAY_SIZE] = {100U, 200U, 500U, 1000U, 1250U, 2500U, 5000U, 10000U};
|
||||
const uint32_t data_speeds[DATA_SPEEDS_ARRAY_SIZE] = {0U}; // No separate data speed, dummy
|
||||
|
||||
bool llcan_set_speed(CAN_TypeDef *CANx, uint32_t speed, bool loopback, bool silent) {
|
||||
bool ret = true;
|
||||
|
||||
// initialization mode
|
||||
register_set(&(CANx->MCR), CAN_MCR_TTCM | CAN_MCR_INRQ, 0x180FFU);
|
||||
uint32_t timeout_counter = 0U;
|
||||
while((CANx->MSR & CAN_MSR_INAK) != CAN_MSR_INAK){
|
||||
// Delay for about 1ms
|
||||
delay(10000);
|
||||
timeout_counter++;
|
||||
|
||||
if(timeout_counter >= CAN_INIT_TIMEOUT_MS){
|
||||
print(CAN_NAME_FROM_CANIF(CANx)); print(" set_speed timed out (1)!\n");
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret){
|
||||
// set time quanta from defines
|
||||
register_set(&(CANx->BTR), ((CAN_BTR_TS1_0 * (CAN_SEQ1-1U)) |
|
||||
(CAN_BTR_TS2_0 * (CAN_SEQ2-1U)) |
|
||||
(CAN_BTR_SJW_0 * (CAN_SJW-1U)) |
|
||||
(can_speed_to_prescaler(speed) - 1U)), 0xC37F03FFU);
|
||||
|
||||
// silent loopback mode for debugging
|
||||
if (loopback) {
|
||||
register_set_bits(&(CANx->BTR), CAN_BTR_SILM | CAN_BTR_LBKM);
|
||||
}
|
||||
if (silent) {
|
||||
register_set_bits(&(CANx->BTR), CAN_BTR_SILM);
|
||||
}
|
||||
|
||||
// reset
|
||||
register_set(&(CANx->MCR), CAN_MCR_TTCM | CAN_MCR_ABOM, 0x180FFU);
|
||||
|
||||
timeout_counter = 0U;
|
||||
while(((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)) {
|
||||
// Delay for about 1ms
|
||||
delay(10000);
|
||||
timeout_counter++;
|
||||
|
||||
if(timeout_counter >= CAN_INIT_TIMEOUT_MS){
|
||||
print(CAN_NAME_FROM_CANIF(CANx)); print(" set_speed timed out (2)!\n");
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void llcan_irq_disable(const CAN_TypeDef *CANx) {
|
||||
if (CANx == CAN1) {
|
||||
NVIC_DisableIRQ(CAN1_TX_IRQn);
|
||||
NVIC_DisableIRQ(CAN1_RX0_IRQn);
|
||||
NVIC_DisableIRQ(CAN1_SCE_IRQn);
|
||||
} else if (CANx == CAN2) {
|
||||
NVIC_DisableIRQ(CAN2_TX_IRQn);
|
||||
NVIC_DisableIRQ(CAN2_RX0_IRQn);
|
||||
NVIC_DisableIRQ(CAN2_SCE_IRQn);
|
||||
} else if (CANx == CAN3) {
|
||||
NVIC_DisableIRQ(CAN3_TX_IRQn);
|
||||
NVIC_DisableIRQ(CAN3_RX0_IRQn);
|
||||
NVIC_DisableIRQ(CAN3_SCE_IRQn);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
void llcan_irq_enable(const CAN_TypeDef *CANx) {
|
||||
if (CANx == CAN1) {
|
||||
NVIC_EnableIRQ(CAN1_TX_IRQn);
|
||||
NVIC_EnableIRQ(CAN1_RX0_IRQn);
|
||||
NVIC_EnableIRQ(CAN1_SCE_IRQn);
|
||||
} else if (CANx == CAN2) {
|
||||
NVIC_EnableIRQ(CAN2_TX_IRQn);
|
||||
NVIC_EnableIRQ(CAN2_RX0_IRQn);
|
||||
NVIC_EnableIRQ(CAN2_SCE_IRQn);
|
||||
} else if (CANx == CAN3) {
|
||||
NVIC_EnableIRQ(CAN3_TX_IRQn);
|
||||
NVIC_EnableIRQ(CAN3_RX0_IRQn);
|
||||
NVIC_EnableIRQ(CAN3_SCE_IRQn);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
bool llcan_init(CAN_TypeDef *CANx) {
|
||||
bool ret = true;
|
||||
|
||||
// Enter init mode
|
||||
register_set_bits(&(CANx->FMR), CAN_FMR_FINIT);
|
||||
|
||||
// Wait for INAK bit to be set
|
||||
uint32_t timeout_counter = 0U;
|
||||
while(((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)) {
|
||||
// Delay for about 1ms
|
||||
delay(10000);
|
||||
timeout_counter++;
|
||||
|
||||
if(timeout_counter >= CAN_INIT_TIMEOUT_MS){
|
||||
print(CAN_NAME_FROM_CANIF(CANx)); print(" initialization timed out!\n");
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret){
|
||||
// no mask
|
||||
// For some weird reason some of these registers do not want to set properly on CAN2 and CAN3. Probably something to do with the single/dual mode and their different filters.
|
||||
CANx->sFilterRegister[0].FR1 = 0U;
|
||||
CANx->sFilterRegister[0].FR2 = 0U;
|
||||
CANx->sFilterRegister[14].FR1 = 0U;
|
||||
CANx->sFilterRegister[14].FR2 = 0U;
|
||||
CANx->FA1R |= 1U | (1UL << 14);
|
||||
|
||||
// Exit init mode, do not wait
|
||||
register_clear_bits(&(CANx->FMR), CAN_FMR_FINIT);
|
||||
|
||||
// enable certain CAN interrupts
|
||||
register_set_bits(&(CANx->IER), CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_ERRIE | CAN_IER_LECIE | CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE | CAN_IER_FOVIE0 | CAN_IER_FFIE0);
|
||||
|
||||
// clear overrun flag on init
|
||||
CANx->RF0R &= ~(CAN_RF0R_FOVR0);
|
||||
|
||||
llcan_irq_enable(CANx);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void llcan_clear_send(CAN_TypeDef *CANx) {
|
||||
CANx->TSR |= CAN_TSR_ABRQ0; // Abort message transmission on error interrupt
|
||||
CANx->MSR |= CAN_MSR_ERRI; // Clear error interrupt
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// SAE 2284-3 : minimum 16 tq, SJW 3, sample point at 81.3%
|
||||
#define CAN_QUANTA 16U
|
||||
#define CAN_SEQ1 12U
|
||||
#define CAN_SEQ2 3U
|
||||
#define CAN_SJW 3U
|
||||
|
||||
#define CAN_PCLK 48000U
|
||||
// 333 = 33.3 kbps
|
||||
// 5000 = 500 kbps
|
||||
#define can_speed_to_prescaler(x) (CAN_PCLK / CAN_QUANTA * 10U / (x))
|
||||
|
||||
#define CAN_NAME_FROM_CANIF(CAN_DEV) (((CAN_DEV)==CAN1) ? "CAN1" : (((CAN_DEV) == CAN2) ? "CAN2" : "CAN3"))
|
||||
|
||||
void print(const char *a);
|
||||
|
||||
// kbps multiplied by 10
|
||||
#define SPEEDS_ARRAY_SIZE 8
|
||||
extern const uint32_t speeds[SPEEDS_ARRAY_SIZE];
|
||||
#define DATA_SPEEDS_ARRAY_SIZE 1
|
||||
extern const uint32_t data_speeds[DATA_SPEEDS_ARRAY_SIZE]; // No separate data speed, dummy
|
||||
|
||||
bool llcan_set_speed(CAN_TypeDef *CANx, uint32_t speed, bool loopback, bool silent);
|
||||
void llcan_irq_disable(const CAN_TypeDef *CANx);
|
||||
void llcan_irq_enable(const CAN_TypeDef *CANx);
|
||||
bool llcan_init(CAN_TypeDef *CANx);
|
||||
void llcan_clear_send(CAN_TypeDef *CANx);
|
||||
@@ -1,23 +0,0 @@
|
||||
// TACH interrupt handler
|
||||
static void EXTI2_IRQ_Handler(void) {
|
||||
volatile unsigned int pr = EXTI->PR & (1U << 2);
|
||||
if ((pr & (1U << 2)) != 0U) {
|
||||
fan_state.tach_counter++;
|
||||
}
|
||||
EXTI->PR = (1U << 2);
|
||||
}
|
||||
|
||||
void llfan_init(void) {
|
||||
// 5000RPM * 4 tach edges / 60 seconds
|
||||
REGISTER_INTERRUPT(EXTI2_IRQn, EXTI2_IRQ_Handler, 700U, FAULT_INTERRUPT_RATE_TACH)
|
||||
|
||||
// Init PWM speed control
|
||||
pwm_init(TIM3, 3);
|
||||
|
||||
// Init TACH interrupt
|
||||
register_set(&(SYSCFG->EXTICR[0]), SYSCFG_EXTICR1_EXTI2_PD, 0xF00U);
|
||||
register_set_bits(&(EXTI->IMR), (1U << 2));
|
||||
register_set_bits(&(EXTI->RTSR), (1U << 2));
|
||||
register_set_bits(&(EXTI->FTSR), (1U << 2));
|
||||
NVIC_EnableIRQ(EXTI2_IRQn);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
bool flash_is_locked(void) {
|
||||
return (FLASH->CR & FLASH_CR_LOCK);
|
||||
}
|
||||
|
||||
void flash_unlock(void) {
|
||||
FLASH->KEYR = 0x45670123;
|
||||
FLASH->KEYR = 0xCDEF89AB;
|
||||
}
|
||||
|
||||
bool flash_erase_sector(uint8_t sector, bool unlocked) {
|
||||
// don't erase the bootloader(sector 0)
|
||||
if (sector != 0 && sector < 12 && unlocked) {
|
||||
FLASH->CR = (sector << 3) | FLASH_CR_SER;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void flash_write_word(void *prog_ptr, uint32_t data) {
|
||||
uint32_t *pp = prog_ptr;
|
||||
FLASH->CR = FLASH_CR_PSIZE_1 | FLASH_CR_PG;
|
||||
*pp = data;
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
}
|
||||
|
||||
void flush_write_buffer(void) { }
|
||||
@@ -1,12 +0,0 @@
|
||||
void llspi_miso_dma(uint8_t *addr, int len) {
|
||||
UNUSED(addr);
|
||||
UNUSED(len);
|
||||
}
|
||||
|
||||
void llspi_mosi_dma(uint8_t *addr, int len) {
|
||||
UNUSED(addr);
|
||||
UNUSED(len);
|
||||
}
|
||||
|
||||
void llspi_init(void) {
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user