diff --git a/.gitignore b/.gitignore index b700df0..6f68e13 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,6 @@ Pipfile # Ignore all local history of files .history .ionide + +# rick - keep panda_tici standalone +panda_tici/ diff --git a/SConstruct b/SConstruct index 648afda..7d34621 100644 --- a/SConstruct +++ b/SConstruct @@ -196,6 +196,7 @@ Export('messaging') # Build other submodules SConscript(['panda/SConscript']) +SConscript(['panda_tici/SConscript']) # Build rednose library SConscript(['rednose/SConscript']) diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 3348e85..3172be4 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -10,10 +10,13 @@ $Cxx.namespace("cereal"); # DO rename the structs # DON'T change the identifier (e.g. @0x81c2f05a394cf4af) -struct CustomReserved0 @0x81c2f05a394cf4af { +struct DpControlsState @0x81c2f05a394cf4af { + alkaActive @0 :Bool; } -struct CustomReserved1 @0xaedffd8f31e7b55d { +struct ModelExt @0xaedffd8f31e7b55d { + leftEdgeDetected @0 :Bool; + rightEdgeDetected @1 :Bool; } struct CustomReserved2 @0xf35cc4560bbf6ec2 { diff --git a/cereal/log.capnp b/cereal/log.capnp index 019fbbe..08c270f 100644 --- a/cereal/log.capnp +++ b/cereal/log.capnp @@ -2622,8 +2622,8 @@ struct Event { # DO change the name of the field and struct # DON'T change the ID (e.g. @107) # DON'T change which struct it points to - customReserved0 @107 :Custom.CustomReserved0; - customReserved1 @108 :Custom.CustomReserved1; + dpControlsState @107 :Custom.DpControlsState; + modelExt @108 :Custom.ModelExt; customReserved2 @109 :Custom.CustomReserved2; customReserved3 @110 :Custom.CustomReserved3; customReserved4 @111 :Custom.CustomReserved4; diff --git a/cereal/services.py b/cereal/services.py index edeca41..343ed81 100755 --- a/cereal/services.py +++ b/cereal/services.py @@ -95,6 +95,8 @@ _services: dict[str, tuple] = { "customReservedRawData0": (True, 0.), "customReservedRawData1": (True, 0.), "customReservedRawData2": (True, 0.), + "dpControlsState": (False, 100., 10), + "modelExt": (True, 20.), } SERVICE_LIST = {name: Service(*vals) for idx, (name, vals) in enumerate(_services.items())} diff --git a/common/params_keys.h b/common/params_keys.h index 65eadb2..5501e4f 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -130,4 +130,28 @@ inline static std::unordered_map keys = { {"Version", {PERSISTENT, STRING}}, {"dp_dev_last_log", {CLEAR_ON_ONROAD_TRANSITION, STRING}}, {"dp_dev_reset_conf", {CLEAR_ON_MANAGER_START, BOOL, "0"}}, + {"dp_dev_is_rhd", {PERSISTENT, BOOL, "0"}}, + {"dp_dev_monitoring_disabled", {PERSISTENT, BOOL, "0"}}, + {"dp_dev_beep", {PERSISTENT, BOOL, "0"}}, + {"dp_lat_alka", {PERSISTENT, BOOL, "0"}}, + {"dp_ui_display_mode", {PERSISTENT, INT, "0"}}, + {"dp_dev_model_selected", {PERSISTENT, STRING}}, + {"dp_dev_model_list", {PERSISTENT, STRING}}, + {"dp_lat_lca_speed", {PERSISTENT, INT, "20"}}, + {"dp_lat_lca_auto_sec", {PERSISTENT, FLOAT, "0.0"}}, + {"dp_dev_go_off_road", {CLEAR_ON_MANAGER_START, BOOL}}, + {"dp_ui_hide_hud_speed_kph", {PERSISTENT, INT, "0"}}, + {"dp_lon_ext_radar", {PERSISTENT, BOOL, "0"}}, + {"dp_lat_road_edge_detection", {PERSISTENT, BOOL, "0"}}, + {"dp_ui_rainbow", {PERSISTENT, BOOL, "0"}}, + {"dp_lon_acm", {PERSISTENT, BOOL, "0"}}, + {"dp_lon_aem", {PERSISTENT, BOOL, "0"}}, + {"dp_lon_dtsc", {PERSISTENT, BOOL, "0"}}, + {"dp_dev_audible_alert_mode", {PERSISTENT, INT, "0"}}, + {"dp_dev_auto_shutdown_in", {PERSISTENT, INT, "-5"}}, + {"dp_ui_lead", {PERSISTENT, INT, "0"}}, + {"dp_dev_dashy", {PERSISTENT, INT, "0"}}, + {"dp_dev_delay_loggerd", {PERSISTENT, INT, "0"}}, + {"dp_dev_disable_connect", {PERSISTENT, BOOL, "0"}}, + {"dp_dev_tethering", {PERSISTENT, BOOL, "0"}}, }; diff --git a/dragonpilot/dashy/.nojekyll b/dragonpilot/dashy/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/dragonpilot/dashy/LICENSE.md b/dragonpilot/dashy/LICENSE.md new file mode 100644 index 0000000..aa1b82f --- /dev/null +++ b/dragonpilot/dashy/LICENSE.md @@ -0,0 +1,15 @@ +Copyright (c) 2025, Rick Lan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, and/or sublicense, +for non-commercial purposes only, subject to the following conditions: + +- The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. +- Commercial use (e.g. use in a product, service, or activity intended to + generate revenue) is prohibited without explicit written permission from + the copyright holder. + +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. diff --git a/dragonpilot/dashy/README.md b/dragonpilot/dashy/README.md new file mode 100644 index 0000000..df5bb01 --- /dev/null +++ b/dragonpilot/dashy/README.md @@ -0,0 +1,46 @@ +# Dashy Release Branch + +This is the production-ready release branch of Dashy - Dragonpilot's All-in-one System Hub for You. + +## 🚀 Quick Installation + +```bash +git clone -b release https://github.com/efinilan/dashy +cd dashy +python3 backend/server.py +``` + +## 📁 What's Included + +- `backend/` - Python server with all dependencies included +- `web/` - Pre-built web interface (minified and optimized) + +## 🌐 Access + +After starting the server, open Chrome browser and navigate to: +``` +http://:5088 +``` + +## 🔧 Requirements + +- Network connection +- Port 5088 available + +## 📄 License + +Copyright (c) 2025, Rick Lan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, and/or sublicense, +for non-commercial purposes only, subject to the following conditions: + +- The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. +- Commercial use (e.g. use in a product, service, or activity intended to + generate revenue) is prohibited without explicit written permission from + the copyright holder. + +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. diff --git a/dragonpilot/dashy/backend/.gitignore b/dragonpilot/dashy/backend/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/dragonpilot/dashy/backend/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/dragonpilot/dashy/backend/server.py b/dragonpilot/dashy/backend/server.py new file mode 100755 index 0000000..407a631 --- /dev/null +++ b/dragonpilot/dashy/backend/server.py @@ -0,0 +1,194 @@ +""" +Copyright (c) 2025, Rick Lan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, and/or sublicense, +for non-commercial purposes only, subject to the following conditions: + +- The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. +- Commercial use (e.g. use in a product, service, or activity intended to + generate revenue) is prohibited without explicit written permission from + the copyright holder. + +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. +""" + +#!/usr/bin/env python3 + +import argparse +# import asyncio +# import json +import os +import logging +from datetime import datetime +from urllib.parse import quote +# import socket +# import sys + +from aiohttp import web + +from openpilot.common.params import Params +from openpilot.system.hardware import PC + + +# --- File Browser Settings --- +DEFAULT_DIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..') if PC else '/data/media/0/realdata') +WEB_DIST_PATH = os.path.join(os.path.dirname(__file__), "..", "web", "dist") + +def get_safe_path(requested_path): + """Ensures the requested path is within DEFAULT_DIR, preventing arbitrary file access""" + combined_path = os.path.join(DEFAULT_DIR, requested_path.lstrip('/')) + safe_path = os.path.realpath(combined_path) + if os.path.commonpath((safe_path, DEFAULT_DIR)) == DEFAULT_DIR: + return safe_path + return None + +async def list_files_api(request): + """API endpoint to list files and folders""" + try: + path_param = request.query.get('path', '/') + safe_path = get_safe_path(path_param) + if not safe_path or not os.path.isdir(safe_path): + return web.json_response({'error': 'Invalid or Not Found Path'}, status=404) + items = [] + for entry in os.listdir(safe_path): + full_path = os.path.join(safe_path, entry) + try: + stat = os.stat(full_path) + is_dir = os.path.isdir(full_path) + items.append({ + 'name': entry, + 'is_dir': is_dir, + 'mtime': datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M'), + 'size': stat.st_size if not is_dir else 0 + }) + except FileNotFoundError: + continue + directories = sorted([item for item in items if item['is_dir']], key=lambda x: x['mtime'], reverse=True) + files = sorted([item for item in items if not item['is_dir']], key=lambda x: x['mtime'], reverse=True) + items = directories + files + relative_path = os.path.relpath(safe_path, DEFAULT_DIR) + if relative_path == '.': + relative_path = '' + return web.json_response({'path': relative_path, 'files': items}) + except Exception as e: + return web.json_response({'error': str(e)}, status=500) + +async def serve_player_api(request): + """API endpoint to serve the HLS player page""" + file_path = request.query.get('file') + if not file_path: + return web.Response(text="File parameter is required.", status=400) + + player_html_path = os.path.join(WEB_DIST_PATH, 'pages', 'player.html') + try: + with open(player_html_path, 'r') as f: + html_template = f.read() + except FileNotFoundError: + return web.Response(text="Player HTML not found.", status=500) + + encoded_path = quote(file_path) + html = html_template.replace('{{FILE_PATH}}', encoded_path) + return web.Response(text=html, content_type='text/html') + +async def serve_manifest_api(request): + """API endpoint to dynamically generate m3u8 playlist""" + file_path = request.query.get('file').lstrip('/') + if not file_path: + return web.Response(text="File parameter is required.", status=400) + encoded_path = quote(file_path) + manifest = f"""#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:60\n#EXT-X-PLAYLIST-TYPE:VOD\n#EXTINF:60.0,\n/media/{encoded_path}\n#EXT-X-ENDLIST\n""" + return web.Response(text=manifest, content_type='application/vnd.apple.mpegurl') + +async def save_settings_api(request): + """API endpoint to receive and save settings""" + try: + data = await request.json() + logging.getLogger("web_ui").info(f"Received settings to save: {data}") + return web.json_response({'status': 'success', 'message': 'Settings saved successfully!'}) + except Exception as e: + logging.getLogger("web_ui").error(f"Error saving settings: {e}") + return web.json_response({'status': 'error', 'message': str(e)}, status=500) + +async def init_api(request): + """API endpoint to provide initial data to the client.""" + try: + params = Params() + return web.json_response({ + 'is_metric': params.get_bool("IsMetric"), + 'dp_dev_dashy': int(params.get("dp_dev_dashy") or 0) + }) + except Exception as e: + logging.getLogger("web_ui").error(f"Error fetching initial data: {e}") + return web.json_response({'error': f"Error fetching initial data: {e}"}, status=500) + +async def on_startup(app): + logging.getLogger("web_ui").info("Web UI application starting up...") + +async def on_cleanup(app): + logging.getLogger("web_ui").info("Web UI application shutting down...") + +# --- CORS Middleware --- +@web.middleware +async def cors_middleware(request, handler): + response = await handler(request) + response.headers['Access-Control-Allow-Origin'] = '*' + response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS' + response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization' + return response + +async def handle_cors_preflight(request): + if request.method == 'OPTIONS': + headers = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + 'Access-Control-Max-Age': '86400', + } + return web.Response(status=200, headers=headers) + return await request.app['handler'](request) + +def setup_aiohttp_app(host: str, port: int, debug: bool): + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') + logging.getLogger("web_ui").setLevel(logging.DEBUG if debug else logging.INFO) + + app = web.Application(middlewares=[cors_middleware]) + app['port'] = port + + # Register API endpoints + app.router.add_get("/api/init", init_api) + app.router.add_get("/api/files", list_files_api) + app.router.add_get("/api/play", serve_player_api) + app.router.add_get("/api/manifest.m3u8", serve_manifest_api) + # app.router.add_post("/api/settings", save_settings_api) + + # Static files + app.router.add_static('/media', path=DEFAULT_DIR, name='media', show_index=False, follow_symlinks=False) + app.router.add_static('/download', path=DEFAULT_DIR, name='download', show_index=False, follow_symlinks=False) + app.router.add_get("/", lambda r: web.FileResponse(os.path.join(WEB_DIST_PATH, "index.html"))) + app.router.add_static("/", path=WEB_DIST_PATH) + + app.on_startup.append(on_startup) + app.on_cleanup.append(on_cleanup) + + # Add CORS preflight handler + app.router.add_route('OPTIONS', '/{tail:.*}', handle_cors_preflight) + + return app + +def main(): + # rick - may need "sudo ufw allow 5088" to allow port access + parser = argparse.ArgumentParser(description="Dashy Server") + parser.add_argument("--host", type=str, default="0.0.0.0", help="Host to listen on") + parser.add_argument("--port", type=int, default=5088, help="Port to listen on") + parser.add_argument("--debug", action="store_true", help="Enable debug mode") + args = parser.parse_args() + + app = setup_aiohttp_app(args.host, args.port, args.debug) + web.run_app(app, host=args.host, port=args.port) + +if __name__ == "__main__": + main() diff --git a/dragonpilot/dashy/web/dist/README.md b/dragonpilot/dashy/web/dist/README.md new file mode 100644 index 0000000..24d84a3 --- /dev/null +++ b/dragonpilot/dashy/web/dist/README.md @@ -0,0 +1,58 @@ +# dashy - dragonpilot's All-in-one System Hub for You + +A modern web-based dashboard for monitoring and controlling your dragonpilot/openpilot remotely. + +## Usage + +These files should be served by the Dashy backend server running on your comma device. + +Access the interface by navigating to `http://:5088` in Chrome browser. + +## Files + +- `index.html` - Main application +- `js/app.js` - Minified JavaScript bundle +- `css/styles.css` - Minified styles +- `icons/` - Favicon +- `pages/player.html` - HLS video player + +## Features + +- **Live Driving View** - Real-time WebRTC video with augmented reality overlay +- **File Browser** - Access and stream driving recordings +- **Settings Control** - Configure vehicle and display preferences + +## 🎮 Usage + +### Navigation +- **Driving View** - Live camera feed with lane lines and path visualization +- **Files** - Browse `/data/media/0/realdata` recordings +- **Local Settings** - Adjust display preferences + +### Display Options +- Metric/Imperial units +- HUD mode for windshield projection + +## Requirements + +- dragonpilot/openpilot device (comma 3/3X) +- Chrome browser (recommended) +- Same network connection as vehicle + +## 📄 License + +Copyright (c) 2025, Rick Lan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, and/or sublicense, +for non-commercial purposes only, subject to the following conditions: + +- The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. +- Commercial use (e.g. use in a product, service, or activity intended to + generate revenue) is prohibited without explicit written permission from + the copyright holder. + +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. diff --git a/dragonpilot/dashy/web/dist/css/styles.css b/dragonpilot/dashy/web/dist/css/styles.css new file mode 100644 index 0000000..258ba46 --- /dev/null +++ b/dragonpilot/dashy/web/dist/css/styles.css @@ -0,0 +1 @@ +:root{--bg-dark:#1a202c;--bg-med:#2d3748;--bg-light:#4a5568;--border-color:#4a5568;--text-light:#e2e8f0;--text-med:#a0aec0;--accent-blue:#4299e1;--accent-green:#48bb78;--border-color-disengaged:#173349C8;--border-color-override:#919B95F1;--border-color-engaged:#178644F1;--alert-red:rgba(200, 0, 0, 0.95);--alert-orange:rgba(254, 140, 52, 0.95);--alert-black:rgba(0, 0, 0, 0.65)}body,html{margin:0;padding:0;width:100%;height:100%;overflow:hidden;background-color:var(--bg-dark);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}#app-container,.page{width:100%;height:100%;flex-direction:column}#app-container{display:flex}nav{background-color:var(--bg-med);flex-shrink:0;position:absolute;top:0;width:100%;z-index:1000;opacity:0;pointer-events:none;transition:opacity .3s cubic-bezier(.4,0,.2,1);will-change:opacity}nav.visible{opacity:1;pointer-events:auto}nav button{flex-grow:1;padding:12px 0;font-size:1rem;font-weight:500;background-color:transparent;border:0;border-bottom:3px solid transparent;color:var(--text-med);cursor:pointer;transition:color .2s,border-color .2s}#files-breadcrumbs a:hover,body,html,nav button:hover{color:var(--text-light)}nav button.active{color:#fff;border-bottom-color:var(--accent-blue)}.page{display:none;overflow:hidden;background-color:var(--bg-dark);position:relative;contain:layout style paint}.page.active,nav{display:flex}#driving-page-content{position:relative;width:100%;flex-grow:1;min-height:0;box-sizing:border-box}#uiCanvas,#videoPlayer{position:absolute;top:0;left:0;width:100%;height:100%;will-change:transform;transform:translateZ(0);backface-visibility:hidden}#videoPlayer{object-fit:cover;background-color:#000}#videoPlayer.hud-mode{transform:scaleY(-1)}#uiCanvas{z-index:1}.settings-page-wrapper{width:100%;height:100%;overflow-y:auto;padding:1.5rem;box-sizing:border-box;padding-bottom:80px;padding-top:60px}.settings-page h1{margin-top:0;color:#fff;border-bottom:1px solid var(--border-color);padding-bottom:.5rem}.settings-category{margin-top:2rem}.settings-category h2{color:var(--accent-blue);font-size:1.2rem;margin-bottom:1rem;border-bottom:1px solid var(--bg-light);padding-bottom:.5rem}.setting-item{background-color:var(--bg-med);padding:1rem;border-radius:8px;margin-bottom:1rem;display:flex;justify-content:space-between;align-items:center}#driving-page-content{background-color:#000}.setting-label p{margin:0;font-weight:500}.setting-label span{font-size:.85rem;color:var(--text-med)}.setting-control{display:flex;align-items:center;gap:10px}.toggle-switch{position:relative;display:inline-block;width:50px;height:28px}.toggle-switch input{opacity:0;width:0;height:0}.toggle-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:var(--bg-light);transition:background-color .4s cubic-bezier(.4,0,.2,1);border-radius:28px}.toggle-slider:before{position:absolute;content:"";height:20px;width:20px;left:4px;bottom:4px;background-color:#fff;transition:transform .4s cubic-bezier(.4,0,.2,1);border-radius:50%}input:checked+.toggle-slider{background-color:var(--accent-green)}input:checked+.toggle-slider:before{transform:translateX(22px)}.btn-group button,.stepper button{background:var(--bg-light);cursor:pointer}.stepper button{border:0;color:var(--text-light);width:30px;height:30px;border-radius:50%;font-size:1.2rem;line-height:30px;text-align:center}.stepper-value{font-weight:500;min-width:40px;text-align:center}.btn-group button{border:1px solid var(--border-color);color:var(--text-med);padding:8px 16px;transition:background-color .2s}.btn-group button:first-child{border-radius:8px 0 0 8px}.btn-group button:last-child{border-radius:0 8px 8px 0}.btn-group button.active{background:var(--accent-blue);color:#fff}.text-input{background:var(--bg-light);border:1px solid var(--border-color);color:var(--text-light);border-radius:8px;padding:8px 12px;font-size:1rem;width:150px}#save-bar{position:absolute;bottom:0;left:0;right:0;background:linear-gradient(to top,#1a202c,rgba(26,32,44,.8));padding:1rem;display:flex;justify-content:flex-end;align-items:center;gap:1rem}#save-status{color:var(--text-med);transition:opacity .5s}#save-settings-btn{background-color:var(--accent-blue);color:#fff;border:0;padding:10px 25px;border-radius:8px;font-size:1rem;font-weight:500;cursor:pointer;transition:background-color .2s}#save-settings-btn:hover{background-color:#2b6cb0}#save-settings-btn:disabled{background-color:var(--bg-light);cursor:not-allowed}#files-page{padding:1rem;box-sizing:border-box;overflow-y:auto;padding-top:60px}#files-breadcrumbs{margin-bottom:1rem;font-size:1.1em;word-wrap:break-word}#files-breadcrumbs a,#files-table td a{color:var(--text-med);text-decoration:none}#files-table{width:100%;border-collapse:collapse}#files-table td,#files-table th{padding:10px 8px;text-align:left;border-bottom:1px solid var(--bg-med);white-space:nowrap}#files-table th{font-weight:600}#files-table tr:hover{background-color:var(--bg-med)}#files-table td a{color:var(--text-light);font-weight:500}.file-icon{display:inline-block;width:2em;text-align:center}.file-size{text-align:right;color:var(--text-med)}.play-button{font-weight:700;color:#28a745;font-size:1.5em;cursor:pointer;text-decoration:none} \ No newline at end of file diff --git a/dragonpilot/dashy/web/dist/icons/icon-192x192.png b/dragonpilot/dashy/web/dist/icons/icon-192x192.png new file mode 100644 index 0000000..c1481e9 Binary files /dev/null and b/dragonpilot/dashy/web/dist/icons/icon-192x192.png differ diff --git a/dragonpilot/dashy/web/dist/index.html b/dragonpilot/dashy/web/dist/index.html new file mode 100644 index 0000000..41e3e85 --- /dev/null +++ b/dragonpilot/dashy/web/dist/index.html @@ -0,0 +1 @@ +Dashy by dragonpilot
NameLast ModifiedSize

Local Settings

\ No newline at end of file diff --git a/dragonpilot/dashy/web/dist/js/app.js b/dragonpilot/dashy/web/dist/js/app.js new file mode 100644 index 0000000..a04c574 --- /dev/null +++ b/dragonpilot/dashy/web/dist/js/app.js @@ -0,0 +1 @@ +const t=500,e=10,i=100,a=.5,s=60,n=1/30,r=[{r:13,g:248,b:122,a:102},{r:114,g:255,b:92,a:89},{r:114,g:255,b:92,a:0}],o=[{r:242,g:242,b:242,a:102},{r:242,g:242,b:242,a:89},{r:242,g:242,b:242,a:0}];function l(t,e){const i=[[0,0,0],[0,0,0],[0,0,0]];for(let a=0;a<3;a++)for(let s=0;s<3;s++)i[a][s]=t[a][0]*e[0][s]+t[a][1]*e[1][s]+t[a][2]*e[2][s];return i}function d(t,e){return[t[0][0]*e[0]+t[0][1]*e[1]+t[0][2]*e[2],t[1][0]*e[0]+t[1][1]*e[1]+t[1][2]*e[2],t[2][0]*e[0]+t[2][1]*e[1]+t[2][2]*e[2]]}function h(t,e,i,a){const s=t[0][0]*e+t[0][1]*i+t[0][2]*a,n=t[1][0]*e+t[1][1]*i+t[1][2]*a,r=t[2][0]*e+t[2][1]*i+t[2][2]*a;return Math.abs(r)<1e-6?{x:0,y:0,z:0,valid:!1}:{x:s/r,y:n/r,z:r,valid:!0}}function c(t,e,i){return Math.max(e,Math.min(i,t))}function _(t){const[e,i,a]=t,s=Math.cos(e),n=Math.sin(e),r=Math.cos(i),o=Math.sin(i),l=Math.cos(a),d=Math.sin(a);return[[l*r,l*o*n-d*s,l*o*s+d*n],[d*r,d*o*n+l*s,d*o*s-l*n],[-o,r*n,r*s]]}const g=[[0,-1,0],[0,0,-1],[1,0,0]],u={tici:{fcam:{intrinsics:[[2648,0,964],[0,2648,604],[0,0,1]],width:1928,height:1208}},mici:{fcam:{intrinsics:[[1141.5,0,672],[0,1141.5,380],[0,0,1]],width:1344,height:760}}};class p{constructor(){window.debug,this._longitudinal_control=!1,this._experimental_mode=!1,this._blend_factor=1,this._prev_allow_throttle=!0,this._lane_line_probs=new Float32Array(4),this._road_edge_stds=new Float32Array(2),this._lead_vehicles=[{},{}],this._path_offset_z=1.22,this._use_simple_lines=!0,this._path={raw_points:[],projected_points:[]},this._lane_lines=[{raw_points:[],projected_points:[]},{raw_points:[],projected_points:[]},{raw_points:[],projected_points:[]},{raw_points:[],projected_points:[]}],this._road_edges=[{raw_points:[],projected_points:[]},{raw_points:[],projected_points:[]}],this._acceleration_x=new Float32Array(0),this._maxPoints=200,this._leftPointsBuffer=new Array(this._maxPoints),this._rightPointsBuffer=new Array(this._maxPoints),this._transformCache=new Map,this._transformCacheValid=!1,this._batchTransformEnabled=!0,this._batchLeftX=new Float32Array(this._maxPoints),this._batchLeftY=new Float32Array(this._maxPoints),this._batchLeftZ=new Float32Array(this._maxPoints),this._batchRightX=new Float32Array(this._maxPoints),this._batchRightY=new Float32Array(this._maxPoints),this._batchRightZ=new Float32Array(this._maxPoints),this._gradientCache=new Map,this._gradientCacheMaxSize=20,this._pathCache=new Map,this._pathCacheMaxSize=10,this._lastPathPoints=null,this._lastPathHash=null,this._pathLengthCache=new Map,this._lastPathLengthCacheClear=0,this._framePathLengthCache=new Map,this._lastFrameTime=0,this._car_space_transform=[[1,0,0],[0,1,0],[0,0,1]],this._transform_dirty=!0,this._clip_region=null,this._rect=null,setInterval(()=>{this._transformCache.clear(),this._pathLengthCache.clear(),this._gradientCache.clear(),window.debug},3e4),this._exp_gradient={start:[0,1],end:[0,0],colors:[],stops:[]}}set_transform(t){window.debug,this._car_space_transform=t,this._transform_dirty=!0,this._transformCache.clear(),this._transformCacheValid=!1,this._gradientCache.clear(),this._transform_logged||(this._transform_logged=!0)}set_simple_lines_mode(t){window.debug,this._use_simple_lines=t}clear_caches(){window.debug,this._transformCache.clear(),this._transformCacheValid=!1,this._gradientCache.clear(),this._pathCache.clear(),this._lastPathHash=null}render(t,e,i){if(window.debug,this._rect=t,this.ctx=i,i.lineCap="round",i.lineJoin="round",this._debug_logged||(this._debug_logged=!0),!e.liveCalibration||!e.modelV2)return;this._clip_region={x:t.x,y:t.y,width:t.width,height:t.height},e.selfdriveState&&(this._experimental_mode=e.selfdriveState.experimentalMode||!1);const a=e.liveCalibration;a&&a.height&&a.height.length>0&&(this._path_offset_z=a.height[0]),e.updated&&e.updated.carParams?this._longitudinal_control=e.carParams.openpilotLongitudinalControl||!1:e.seen&&e.seen.carParams||(this._longitudinal_control=!0);const s=e.modelV2;if(!s)return;const n=e.valid&&e.valid.radarState?e.radarState:null,r=n?n.leadOne:null,o=this._longitudinal_control&&null!==n;!this._radar_logged&&n&&(this._radar_logged=!0);const l=e.updated&&e.updated.modelV2,d=e.updated&&e.updated.radarState;if(this._update_logged||!l&&!d||(this._update_logged=!0),l||d||this._transform_dirty){l&&this._update_raw_points(s);const t=this._path.raw_points.map(t=>t[0]);if(0===t.length)return;this._update_model(r,t),o&&this._update_leads(n,t),this._transform_dirty=!1}this._draw_lane_lines(),this._draw_path(e),o&&n&&this._draw_lead_indicator()}_update_raw_points(t){if(window.debug,t.position){this._path.raw_points.length=0;for(let e=0;e200){Array.from(this._transformCache.keys()).slice(0,100).forEach(t=>this._transformCache.delete(t)),window.debug}if(this._pathCache.size>this._pathCacheMaxSize){const t=Array.from(this._pathCache.entries()).slice(-5);this._pathCache.clear(),t.forEach(([t,e])=>this._pathCache.set(t,e))}t.laneLines&&t.laneLines.forEach((t,e)=>{this._lane_lines[e].raw_points.length=0;for(let i=0;i{this._road_edges[e].raw_points.length=0;for(let i=0;it[0]),s);this._batch_update_lines(n,t,a),this._update_experimental_gradient(this._rect.height)}_batch_update_lines(t,a,s){const n=[];for(let e=0;et[0]>=0);t.length>0&&(i.push({...a,points:t,startIdx:e,numPoints:t.length}),e+=2*t.length)}if(0===e)return;const a=new Float32Array(e),s=new Float32Array(e),n=new Float32Array(e);let r=0;for(const t of i)for(let e=0;e1){const t=[],e=[];let s=1/0;for(let n=0;ne.push(t));for(let t=a.length-1;t>=0;t--)e.push(a[t]);t.line.projected_points=e}}_update_leads(t,e){window.debug,this._lead_vehicles=[{},{}];const i=[t.leadOne,t.leadTwo],a=[],s={x:[],y:[],z:[]};for(let t=0;t=1e-6){const t=1/v;s[n]={x:m*t,y:b*t,valid:!0},r++}else s[n]={x:0,y:0,valid:!1}}return{points:s,validCount:r}}_map_line_to_polygon(t,e,i,a,s=!0){if(window.debug,0===t.length)return[];let n=t.slice(0,a+1);if(n=n.filter(t=>t[0]>=0),0===n.length)return[];const r=n.length,o=[],l=[];if(this._batchTransformEnabled&&r>10){for(let t=0;t1){const t=[],e=[];let i=1/0;for(let a=0;ad.push(t));for(let t=l.length-1;t>=0;t--)d.push(l[t]);return d}_get_path_length_idx(t,e){if(window.debug,0===t.length)return 0;const i=`${t.length}_${e.toFixed(2)}`,a=Date.now();if(a!==this._lastFrameTime&&(this._framePathLengthCache.clear(),this._lastFrameTime=a),this._framePathLengthCache.has(i))return this._framePathLengthCache.get(i);if(this._pathLengthCache.has(i)){const t=this._pathLengthCache.get(i);return this._framePathLengthCache.set(i,t),t}a-this._lastPathLengthCacheClear>6e4&&(this._pathLengthCache.clear(),this._lastPathLengthCacheClear=a);let s=0;for(let i=0;i{if(0===t.projected_points.length)return;const i=c(this._lane_line_probs[e],0,.7);this._draw_polygon(t.projected_points,`rgba(255, 255, 255, ${i})`)}),this._road_edges.forEach((t,e)=>{if(0===t.projected_points.length)return;const i=c(1-this._road_edge_stds[e],0,1);this._draw_polygon(t.projected_points,`rgba(255, 0, 0, ${i})`)}))}_batch_draw_all_lines(){const t=[];if(this._lane_lines.forEach((e,i)=>{if(e.raw_points.length<2)return;const a=this._lane_line_probs[i];if(a<.1)return;const s=c(a,0,.7);t.push({points:e.raw_points,color:`rgba(255, 255, 255, ${s})`,lineWidth:4})}),this._road_edges.forEach((e,i)=>{if(e.raw_points.length<2)return;const a=this._road_edge_stds[i];if(a>.9)return;const s=c(1-a,0,1);t.push({points:e.raw_points,color:`rgba(255, 0, 0, ${s})`,lineWidth:4})}),0===t.length)return;let e=0;const i=[];for(const a of t){const t=[];for(let e=0;e=0&&i[0]<=100&&t.push(e)}t.length>=2&&(i.push({...a,validIndices:t,startIdx:e,numPoints:t.length}),e+=t.length)}if(0===e)return;const a=new Float32Array(e),s=new Float32Array(e),n=new Float32Array(e);let r=0;for(const t of i)for(const e of t.validIndices){const i=t.points[e];a[r]=i[0],s[r]=i[1],n[r]=i[2],r++}const o=this._batch_transform(a,s,n,e),l=this.ctx;for(const t of i){l.strokeStyle=t.color,l.lineWidth=t.lineWidth,l.beginPath();let e=!1;for(let i=0;i0&&t.validIndices[i]-t.validIndices[i-1]===1?l.lineTo(s.x,s.y):(l.stroke(),l.beginPath(),l.moveTo(s.x,s.y)):(l.moveTo(s.x,s.y),e=!0):e&&(l.stroke(),l.beginPath(),e=!1)}e&&l.stroke()}}_draw_path(t){if(window.debug,0!==this._path.projected_points.length)if(this._experimental_mode)this._exp_gradient.colors.length>2?this._draw_polygon_gradient(this._path.projected_points,this._exp_gradient):this._draw_polygon(this._path.projected_points,"rgba(255, 255, 255, 0.12)");else{const e=t.longitudinalPlan&&t.longitudinalPlan.allowThrottle||!this._longitudinal_control;e!==this._prev_allow_throttle&&(this._prev_allow_throttle=e,this._blend_factor=Math.max(1-this._blend_factor,0)),this._blend_factor<1&&(this._blend_factor=Math.min(this._blend_factor+n,1));const i=e?o:r,a=e?r:o,s={start:[0,1],end:[0,0],colors:this._blend_colors(i,a,this._blend_factor),stops:[0,.5,1]};this._draw_polygon_gradient(this._path.projected_points,s)}}_draw_polygon(t,e){if(window.debug,t.length<3)return;const i=this.ctx;i.fillStyle=e;const a=this._getCachedPath2D(t);i.fill(a)}_getCachedPath2D(t){window.debug;const e=this._generatePointsHash(t);if(this._pathCache.has(e))return this._pathCache.get(e);const i=new Path2D;i.moveTo(t[0][0],t[0][1]);for(let e=1;ethis._pathCacheMaxSize){const t=this._pathCache.keys().next().value;this._pathCache.delete(t)}return i}_generatePointsHash(t){if(window.debug,t.length<3)return"empty";const e=t[0],i=t[Math.floor(t.length/2)],a=t[t.length-1],s=t=>Math.round(10*t)/10;return`${t.length}:${s(e[0])},${s(e[1])}:${s(i[0])},${s(i[1])}:${s(a[0])},${s(a[1])}`}_draw_simple_line(t,e,a=2){if(window.debug,t.length<2)return;const s=this.ctx;s.strokeStyle=e,s.lineWidth=a;const n=Math.min(i,t[t.length-1][0]||i),r=[],o=[],l=[],d=[];for(let e=0;e=0&&i[0]<=n&&(r.push(e),o.push(i[0]),l.push(i[1]),d.push(i[2]))}if(r.length<2)return;const h=this._batch_transform(new Float32Array(o),new Float32Array(l),new Float32Array(d),o.length);let c=!1;s.beginPath();for(let t=0;t0&&r[t]-r[t-1]===1?s.lineTo(e.x,e.y):(s.stroke(),s.beginPath(),s.moveTo(e.x,e.y)):(s.moveTo(e.x,e.y),c=!0):c&&(s.stroke(),s.beginPath(),c=!1)}c&&s.stroke()}_draw_polygon_gradient(t,e){if(window.debug,t.length<3)return;const i=this.ctx,a=this._rect,s=e.start[0]*a.width+a.x,n=e.start[1]*a.height+a.y,r=e.end[0]*a.width+a.x,o=e.end[1]*a.height+a.y,l=this._getCachedGradient(i,s,n,r,o,e),d=this._getCachedPath2D(t);i.fillStyle=l,i.fill(d)}_getCachedGradient(t,e,i,a,s,n){window.debug;const r=`${Math.round(e)},${Math.round(i)},${Math.round(a)},${Math.round(s)}:${n.colors.map(t=>`${t.r},${t.g},${t.b},${t.a}`).join("|")}:${n.stops.join(",")}`;if(this._gradientCache.has(r))return this._gradientCache.get(r);const o=t.createLinearGradient(e,i,a,s);for(let t=0;tthis._gradientCacheMaxSize){const t=this._gradientCache.keys().next().value;this._gradientCache.delete(t)}return o}_blend_colors(t,e,i){if(window.debug,i>=1)return e;if(i<=0)return t;const a=1-i;return t.map((t,s)=>{const n=e[s];return{r:Math.round(a*t.r+i*n.r),g:Math.round(a*t.g+i*n.g),b:Math.round(a*t.b+i*n.b),a:Math.round(a*t.a+i*n.a)}})}_update_experimental_gradient(t){window.debug,this._exp_gradient.colors=[],this._exp_gradient.stops=[]}_update_lead_vehicle(t,e,i,a){window.debug;const s=1.57*c(750/(t/3+30),15,30)*1;this._lead_size_logged||(this._lead_size_logged=!0);const n=c(i[0],0,a.width-s/2),r=Math.min(i[1],a.height-.6*s),o=s/5,l=s/10;let d=0;return t<40&&(d=255*(1-t/40),e<0&&(d+=e/10*-1*255),d=Math.min(d,255)),{glow:[[n+1.35*s+o,r+s+l],[n,r-l],[n-1.35*s-o,r+s+l]],chevron:[[n+1.25*s,r+s],[n,r],[n-1.25*s,r+s]],fill_alpha:d}}_draw_lead_indicator(){window.debug,this._lead_debug_logged||(this._lead_debug_logged=!0),this._lead_vehicles.forEach(t=>{t.glow&&t.chevron&&(this._draw_triangle_fan(t.glow,"rgba(218, 202, 37, 1)"),this._draw_triangle_fan(t.chevron,`rgba(201, 34, 49, ${t.fill_alpha/255})`))})}_draw_triangle_fan(t,e){if(window.debug,t.length<3)return;const i=this.ctx;i.fillStyle=e;const a=t[0],s=new Path2D;for(let e=1;e0&&this.set_speed0&&e-this.started_time>5e3?G:null;t.updated&&t.updated.selfdriveState&&(this.last_selfdrive_time=e);const i=t.deviceState;if(i&&["tici","tizi","mici"].includes(i.deviceType)&&this.last_selfdrive_time>0){const i=(e-this.last_selfdrive_time)/1e3;if(i>5){const e=t.selfdriveState;return e&&e.enabled&&i-515?A:I;this.ctx.font=`bold ${i}px Arial`,this.ctx.textBaseline="middle",this.ctx.fillText(e.text1,t.x+t.width/2,t.y+t.height/2),this.ctx.font="bold 48px Arial",this.ctx.textBaseline="top",this.ctx.fillText(e.text2,t.x+t.width/2,t.y+2*t.height/3)}}}window.AlertRenderer=j;const N=8,H="calibrated",W=[1.22],q={DISENGAGED:{r:23,g:51,b:73,a:200},OVERRIDE:{r:145,g:155,b:149,a:241},ENGAGED:{r:23,g:134,b:68,a:241}};function c(t,e,i){return Math.max(e,Math.min(i,t))}class U{constructor(){window.debug,this.device_camera=null,this.view_from_calib=[...g.map(t=>[...t])],this._last_calib_time=0,this._last_rect_dims={width:0,height:0},this._cached_matrix=null,this._content_rect={x:0,y:0,width:0,height:0},this.model_renderer=new p,this._hud_renderer=new C,this.alert_renderer=new j,this._click_callback=null}render(t,e,i){window.debug,this.sm=e,this.ctx=i,this._update_calibration();const a=t.width-16,s=t.height-16,n=this.device_camera||u.tici,r=a/s,o=n.fcam.width/n.fcam.height;let l=a,d=s,h=t.x+8,c=t.y+8;r>o?(l=s*o,h=t.x+8+(a-l)/2):(d=a/o,c=t.y+8+(s-d)/2),this._content_rect={x:h,y:c,width:l,height:d},this._draw_border(t),i.save(),i.beginPath(),i.rect(Math.floor(t.x),Math.floor(t.y),Math.floor(t.width),Math.floor(t.height)),i.clip(),this._calc_frame_matrix(),this.model_renderer.render(t,e,i),i.restore(),this._hud_renderer.render(t,e,i);this.alert_renderer.render(t,e,i);this._hud_renderer.handle_mouse_event(t)||this._click_callback}set_callbacks(t=null){window.debug,this._click_callback=t}invalidate_transform_cache(){window.debug,this._cached_matrix=null,this._last_rect_dims={width:0,height:0},this._last_calib_time=0,this.model_renderer&&this.model_renderer.clear_caches(),this.model_renderer&&(this.model_renderer._transform_dirty=!0)}_update_calibration(){window.debug;const t=this.sm;if(!this.device_camera&&t.seen&&t.seen.roadCameraState&&t.seen.deviceState){const e=t.deviceState?t.deviceState.deviceType:"tici";this.device_camera="mici"===e?u.mici:u.tici}if(!t.liveCalibration)return;const e=t.liveCalibration;if(!e.rpyCalib||3!==e.rpyCalib.length||e.calStatus!==H)return void(e.calStatus!==H&&(this.view_from_calib=[...g.map(t=>[...t])]));const i=_(e.rpyCalib);this.view_from_calib=l(g,i),this._cached_matrix=null}_calc_frame_matrix(){window.debug;const t=this.sm.updated&&this.sm.updated.liveCalibration,e=this.sm.recv_frame?this.sm.recv_frame.liveCalibration:Date.now(),i=this.ctx.canvas.width,a=this.ctx.canvas.height,s={width:i,height:a};if(!t&&this._last_calib_time===e&&this._last_rect_dims.width===s.width&&this._last_rect_dims.height===s.height&&null!==this._cached_matrix)return this._cached_matrix;const n=this.device_camera||u.tici,r=n.fcam.intrinsics,o=n.fcam.width,d=n.fcam.height,h=this.view_from_calib,c=(this._content_rect.x,this._content_rect.y,this._content_rect.width,this._content_rect.height,Math.max(i/o,a/d)),_=r[0][0]*c*1.1,g=l([[-_,0,i/2],[0,-_,a/2],[0,0,1]],h);return this.model_renderer.set_transform(g),this._last_calib_time=e,this._last_rect_dims=s,this._cached_matrix=g,this._cached_matrix}_draw_border(t){window.debug;const e=this.sm.selfdriveState&&this.sm.selfdriveState.engageable?"ENGAGED":"DISENGAGED",i=q[e]||q.DISENGAGED;this.ctx.strokeStyle=`rgba(${i.r}, ${i.g}, ${i.b}, ${i.a/255})`,this.ctx.lineWidth=8,this.ctx.strokeRect(t.x,t.y,t.width,t.height)}}window.AugmentedRoadView=U;const X=new URLSearchParams(window.location.search),Y="true"===X.get("debug"),J="true"===localStorage.getItem("debug");if(window.debug=Y||J||!1,Y!==J&&(Y?localStorage.setItem("debug","true"):X.has("debug")&&localStorage.removeItem("debug")),window._originalConsoleLog=console.log,console.log=function(...t){window.debug&&window._originalConsoleLog(...t)},window.debug){window._originalConsoleLog("%c🐛 Debug Mode Enabled","color: #00ff00; font-weight: bold; font-size: 16px"),window._originalConsoleLog("To disable: add ?debug=false to URL or run dashy.debug(false)");const t=document.createElement("div");t.id="debug-indicator",t.textContent="🐛 DEBUG",t.style.cssText="\n position: fixed;\n top: 10px;\n right: 10px;\n background: rgba(255, 0, 0, 0.8);\n color: white;\n padding: 5px 10px;\n border-radius: 5px;\n font-family: monospace;\n font-size: 12px;\n z-index: 10000;\n pointer-events: none;\n ",document.addEventListener("DOMContentLoaded",()=>{document.body.appendChild(t)})}window.dashy={debug:function(t=!0){return window.debug=t,t?(localStorage.setItem("debug","true"),window._originalConsoleLog("%c🐛 Debug Mode Enabled","color: #00ff00; font-weight: bold"),window._originalConsoleLog("Refresh page to see all debug logs")):(localStorage.removeItem("debug"),window._originalConsoleLog("%c🔇 Debug Mode Disabled","color: #ff0000; font-weight: bold")),t?"Debug enabled":"Debug disabled"},perf:function(){const t={fps:window._fps||0,frameTime:window._frameTime||0,drawCalls:window._drawCalls||0,canvasOps:window._canvasOps||0};return window._originalConsoleLog("%cPerformance Metrics","color: #00aaff; font-weight: bold"),window._originalConsoleLog(t),t},help:function(){window._originalConsoleLog("%cDashy Debug Commands:","color: #ffaa00; font-weight: bold; font-size: 14px"),window._originalConsoleLog("dashy.debug(true/false) - Enable/disable debug mode"),window._originalConsoleLog("dashy.perf() - Show performance metrics"),window._originalConsoleLog("dashy.help() - Show this help"),window._originalConsoleLog("\nURL Parameters:"),window._originalConsoleLog("?debug=true - Enable debug mode"),window._originalConsoleLog("?debug=false - Disable debug mode")}},function(){let t=0,e=null,i=0;function a(a,s,n){const r=document.getElementById("driving-page");if(!r||!r.classList.contains("active"))return;const o=window.innerWidth,l=window.innerHeight;if(a>o-100&&s>l-100){const r=Date.now();if(r-i<100)return void window._originalConsoleLog(`[Debug Toggle] Ignoring duplicate ${n} event`);if(i=r,t++,window._originalConsoleLog(`[Debug Toggle] ${n} count: ${t}/5 (at ${a},${s})`),e&&clearTimeout(e),e=setTimeout(()=>{t=0,window._originalConsoleLog("[Debug Toggle] Tap count reset to 0")},1e3),5===t){t=0;const e=!window.debug;window.dashy.debug(e);const i=document.createElement("div");i.textContent=e?"🐛 Debug Enabled":"🔇 Debug Disabled",i.style.cssText=`\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: ${e?"rgba(0, 255, 0, 0.9)":"rgba(255, 0, 0, 0.9)"};\n color: white;\n padding: 20px 40px;\n border-radius: 10px;\n font-size: 24px;\n font-weight: bold;\n z-index: 10001;\n pointer-events: none;\n `,document.body.appendChild(i),navigator.vibrate&&navigator.vibrate(e?[100,50,100]:[200]),setTimeout(()=>{i.remove(),location.reload()},1500)}}}document.addEventListener("touchstart",t=>{const e=t.touches[0];e.clientX>window.innerWidth-100&&e.clientY>window.innerHeight-100&&(a(e.clientX,e.clientY,"Touch"),t.preventDefault())},{passive:!1}),document.addEventListener("click",t=>{t.clientX>window.innerWidth-100&&t.clientY>window.innerHeight-100&&a(t.clientX,t.clientY,"Click")})}();const Z={sections:[{title:"Visual",settings:[{id:"HudModeEnabled",type:"toggle",label:"Heads-up Display (HUD) Mode",description:"Mirror the display for windshield projection.",defaultValue:!1,storage:"local"},{id:"ShowVideoInHud",type:"toggle",label:"Show Video",description:"Show or hide video stream in HUD mode.",defaultValue:!0,storage:"local",indent:!0,dependsOn:"HudModeEnabled"}]}]},K={events:{},on(t,e){return this.events[t]||(this.events[t]=[]),this.events[t].push(e),()=>this.off(t,e)},off(t,e){this.events[t]&&(this.events[t]=this.events[t].filter(t=>t!==e))},emit(t,e){this.events[t]&&this.events[t].forEach(t=>t(e))}},Q={_data:{settings:{},localSettings:{},ui:{currentPage:"files",navBarVisible:!1,hudModeEnabled:!1,showVideoInHud:!0},files:{currentPath:"/",items:[]}},get(t){return t.split(".").reduce((t,e)=>t?.[e],this._data)},set(t,e){const i=t.split("."),a=i.pop(),s=i.reduce((t,e)=>(t[e]||(t[e]={}),t[e]),this._data),n=s[a];n!==e&&(s[a]=e,K.emit("state:change",{path:t,value:e,oldValue:n}),K.emit(`state:${t}`,e))},subscribe:(t,e)=>K.on(`state:${t}`,e)},tt={fileRow:(t,e)=>{const i=t.is_dir?"📁":t.name.endsWith(".ts")?"🎞️":"📄",a=`${e}/${t.name}`.replace("//","/");return`\n \n ${i}${t.name.endsWith(".ts")?``:""}\n ${t.is_dir?`${t.name}`:`${t.name}`}\n ${t.mtime}\n ${t.is_dir?"-":Dt(t.size)}\n \n `},breadcrumb:t=>{const e=t.split("/").filter(Boolean);let i="";const a=['root'];return e.forEach((t,s)=>{i+="/"+t,s===e.length-1?a.push(t):a.push(`${t}`)}),a.join(" / ")},alert:(t,e,i="normal")=>`\n
\n

${t}

\n ${e?`

${e}

`:""}\n
\n `};function et(t,...e){const i=t(...e),a=document.createElement("div");return a.innerHTML=i,a.firstElementChild||a.childNodes}function it(t,e,i={}){const a=document.createElement(t);return e&&(a.className=e),Object.entries(i).forEach(([t,e])=>{"dataset"===t?Object.entries(e).forEach(([t,e])=>{a.dataset[t]=e}):a[t]=e}),a}function at(t){const e=it("label","toggle-switch"),i=it("input","",{type:"checkbox",dataset:{param:t.id}});t.storage&&(i.dataset.storage=t.storage),t.defaultValue&&(i.checked=!0);const a=it("span","toggle-slider");return e.appendChild(i),e.appendChild(a),e}function st(t){const e=it("div","setting-control stepper",{dataset:{param:t.id}});void 0!==t.min&&(e.dataset.min=t.min),void 0!==t.max&&(e.dataset.max=t.max);const i=it("button","",{dataset:{step:-t.step},textContent:"-"}),a=it("span","stepper-value",{textContent:t.defaultValue}),s=it("button","",{dataset:{step:t.step},textContent:"+"});return e.appendChild(i),e.appendChild(a),e.appendChild(s),e}function nt(t){const e=it("div","setting-control btn-group",{dataset:{param:t.id}});return t.storage&&(e.dataset.storage=t.storage),t.options.forEach(i=>{const a=it("button","",{dataset:{value:i.value},textContent:i.text});i.value===t.defaultValue&&a.classList.add("active"),e.appendChild(a)}),e}function rt(t){return it("input","text-input",{type:"text",placeholder:t.placeholder||"",dataset:{param:t.id}})}function ot(t){const e=it("div","setting-item",{id:"ShowVideoInHud"===t.id?"show-video-setting":""});t.indent&&(e.style.marginLeft="2rem"),t.dependsOn&&(e.style.display="none");const i=it("div","setting-label"),a=it("p","",{textContent:t.label}),s=it("span","",{textContent:t.description});i.appendChild(a),i.appendChild(s);const n=it("div","setting-control");let r;switch(t.type){case"toggle":r=at(t);break;case"stepper":return r=st(t),e.appendChild(i),e.appendChild(r),e;case"btn-group":return r=nt(t),e.appendChild(i),e.appendChild(r),e;case"text-input":r=rt(t),n.appendChild(r)}return"toggle"===t.type&&n.appendChild(r),e.appendChild(i),e.appendChild(n),e}function lt(t,e){t.sections.forEach(t=>{const i=it("div","settings-category"),a=it("h2","",{textContent:t.title});i.appendChild(a),t.settings.forEach(t=>{i.appendChild(ot(t))}),e.appendChild(i)})}const dt=document.getElementById("app-container"),ht=document.getElementById("driving-page"),ct=document.getElementById("files-page"),_t=document.getElementById("settings-page"),gt=document.getElementById("local-settings-page"),ut=document.getElementById("nav-driving"),pt=document.getElementById("nav-files"),ft=document.getElementById("nav-settings"),wt=document.getElementById("nav-local-settings"),mt=document.getElementById("files-breadcrumbs"),bt=document.querySelector("#files-table tbody"),vt=document.getElementById("driving-page-content"),xt=document.getElementById("videoPlayer"),yt=document.getElementById("uiCanvas"),Ct=yt.getContext("2d");function St(){window.debug,document.addEventListener("click",t=>{if(t.target.matches("nav button")){const e=t.target.id.replace("nav-","");return void It(e)}if(t.target.matches(".stepper button")){const e=t.target.parentElement,i=e.querySelector(".stepper-value"),a=parseFloat(t.target.dataset.step),s=parseFloat(e.dataset.min)||-1/0,n=parseFloat(e.dataset.max)||1/0;let r=parseFloat(i.textContent)+a;String(a).includes(".")&&(r=parseFloat(r.toFixed(2))),i.textContent=Math.max(s,Math.min(n,r));const o=t.target.closest("[data-param]");return void(o&&"local"===o.dataset.storage&&Le(()=>{const t=o.dataset.param,e=Et(!0)[t];void 0!==e&&Mt(t,e)},50))}if(t.target.matches(".btn-group button")){t.target.parentElement.querySelectorAll("button").forEach(t=>t.classList.remove("active")),t.target.classList.add("active");const e=t.target.closest("[data-param]");return void(e&&"local"===e.dataset.storage&&Le(()=>{const t=e.dataset.param,i=Et(!0)[t];void 0!==i&&Mt(t,i)},50))}if(t.target.matches("#files-table a, #files-breadcrumbs a")){if(t.target.href&&t.target.href.includes("/api/play"))return;const e=t.target.dataset.path;return void(void 0!==e&&(t.preventDefault(),Bt(e)))}}),document.addEventListener("change",t=>{const e=t.target.closest("[data-param]");e&&"local"===e.dataset.storage&&Le(()=>{const t=e.dataset.param,i=Et(!0)[t];void 0!==i&&Mt(t,i)},50)}),document.addEventListener("input",t=>{const e=t.target.closest('[data-param][data-storage="local"]');e&&t.target.matches(".text-input")&&Mt(e.dataset.param,t.target.value)})}function Et(t=!0){window.debug;const e={},i=t?'[data-param][data-storage="local"]':'[data-param]:not([data-storage="local"])';return document.querySelectorAll(i).forEach(t=>{const i=t.dataset.param;t.matches('input[type="checkbox"]')?e[i]=t.checked:t.matches(".stepper")?e[i]=parseFloat(t.querySelector(".stepper-value").textContent):t.matches(".btn-group")?e[i]=t.querySelector("button.active").dataset.value:t.matches(".text-input")&&(e[i]=t.value)}),e}function Mt(t,e){window.debug;try{let i=JSON.parse(localStorage.getItem("dashySettings"))||{};i[t]=e,localStorage.setItem("dashySettings",JSON.stringify(i)),Pt(t,e)}catch(t){}}let Tt;function Lt(){const t=Q.get("ui.hudModeEnabled"),e=Q.get("ui.showVideoInHud");xt.style.display=t&&!e?"none":""}function Pt(t,e){window.debug,Q.set(`ui.${t.charAt(0).toLowerCase()+t.slice(1)}`,e)}function $t(){Q.subscribe("ui.theme",t=>{}),Q.subscribe("ui.hudModeEnabled",t=>{if(t){xt.classList.add("hud-mode");const t=document.getElementById("show-video-setting");t&&(t.style.display="")}else{xt.classList.remove("hud-mode");const t=document.getElementById("show-video-setting");t&&(t.style.display="none"),xt.style.display=""}Lt()}),Q.subscribe("ui.showVideoInHud",t=>{Lt()}),Q.subscribe("ui.navBarVisible",t=>{K.emit("nav:visibility",t)}),Q.subscribe("ui.currentPage",t=>{K.emit("page:change",t)})}function At(){window.debug;try{const t=JSON.parse(localStorage.getItem("dashySettings"))||{};for(const[e,i]of Object.entries(t)){const t=document.querySelector(`[data-param="${e}"][data-storage="local"]`);if(t)if(t.matches('input[type="checkbox"]'))t.checked=i;else if(t.matches(".stepper"))t.querySelector(".stepper-value").textContent=i;else if(t.matches(".btn-group")){t.querySelectorAll("button").forEach(t=>t.classList.remove("active"));const e=t.querySelector(`[data-value="${i}"]`);e&&e.classList.add("active")}else t.matches(".text-input")&&(t.value=i);Pt(e,i)}Q.get("ui.hudModeEnabled")?document.getElementById("show-video-setting").style.display="":document.getElementById("show-video-setting").style.display="none"}catch(t){}}function It(t){window.debug,document.querySelectorAll(".page").forEach(t=>t.classList.remove("active")),document.querySelectorAll("nav button").forEach(t=>t.classList.remove("active")),document.getElementById(`${t}-page`).classList.add("active"),document.getElementById(`nav-${t}`).classList.add("active"),"files"!==t||bt.hasChildNodes()||Bt("/"),"driving"===t?(Me.classList.remove("visible"),$e(Te)):(Me.classList.add("visible"),$e(Te))}function Dt(t){if(0===t)return"0 B";const e=Math.floor(Math.log(t)/Math.log(1024));return parseFloat((t/Math.pow(1024,e)).toFixed(1))+" "+["B","KB","MB","GB","TB"][e]}function Rt(t){if(window.debug,Nt===t)return;Nt=t;const e=1===t||"1"===t,i=2===t||"2"===t;ut&&(ut.style.display=i?"":"none"),wt&&(wt.style.display=i?"":"none"),pt&&(pt.style.display=""),ft&&(ft.style.display=e||i?"none":"");let a="files";Q.get("ui.currentPage")!==a&&It(a)}function kt(t,e){let i;return function(...a){clearTimeout(i),i=setTimeout(()=>{clearTimeout(i),t(...a)},e)}}const zt=new Map;async function Bt(t="/"){window.debug;const e=zt.get(t);e&&e.abort();const i=new AbortController;zt.set(t,i);try{bt.innerHTML='Loading...';const e=await fetch(`/api/files?path=${encodeURIComponent(t)}`,{signal:i.signal});if(!e.ok)throw new Error(`Server error: ${e.statusText}`);const a=await e.json();Ft(a.path),Gt(a.path,a.files)}catch(t){if("AbortError"===t.name)return;bt.innerHTML=`Failed to load files: ${t.message}`}finally{zt.delete(t)}}function Ft(t){mt.innerHTML="Path: "+tt.breadcrumb(t),Q.set("files.currentPath",t)}function Gt(t,e){Q.set("files.items",e);let i="";if(t){const e=t.substring(0,t.lastIndexOf("/"))||"/";i+=`⤴️.. (Parent Directory)`}e.forEach(e=>{i+=tt.fileRow(e,t)}),bt.innerHTML=i}let Vt,Ot,jt=!1,Nt=null,Ht=null,Wt=null;const qt={modelV2:null,liveCalibration:null,longitudinalPlan:null,radarState:null,selfdriveState:null,deviceState:null,carState:null,controlsState:null,roadCameraState:null,driverStateV2:null,driverMonitoringState:null,recv_frame:{},recv_time:{},updated:{},valid:{},seen:{},frame:0};let Ut=0,Xt=0,Yt=0,Jt=0,Zt=0;const Kt={sm:qt,started_frame:0,is_metric:!1,status:"DISENGAGED",engaged:!1},Qt={textContent:""},te={style:{backgroundColor:""}},ee=20,ie=50;let ae=0,se=0,ne=0,re=!1;function oe(){window.debug;const{width:t,height:e}=vt.getBoundingClientRect();t>0&&(yt.width!==t||yt.height!==e)&&(yt.width=t,yt.height=e,Wt&&Wt.invalidate_transform_cache(),!Wt&&yt.width>0&&yt.height>0&&(Wt=new U,Wt.set_callbacks(()=>{qt.selfdriveState&&(qt.selfdriveState.experimentalMode=!qt.selfdriveState.experimentalMode)}),requestAnimationFrame(Fe)))}const le=new ResizeObserver(()=>oe());function de(){window.debug,!Wt&&yt.width>0&&yt.height>0&&(Wt=new U,Wt.set_callbacks(()=>{qt.selfdriveState&&(qt.selfdriveState.experimentalMode=!qt.selfdriveState.experimentalMode)}),requestAnimationFrame(Fe))}function he(t,e){window.debug,Qt.textContent=t;const i={green:"#48bb78",yellow:"#f6e05e",red:"#f56565"};te.style.backgroundColor=i[e]||i.red,we=!0,$e(Tt),Tt=Le(()=>{Qt.textContent="",we=!0},5e3)}le.observe(vt),window.addEventListener("orientationchange",()=>oe());let ce=0,_e=[];const ge=500;function ue(){window.debug;const t=Date.now();if(t-ce0&&t-Yt>2e3&&e.push({text:"Model data stale",severity:"warning"}),Jt>0&&t-Jt>2e3&&e.push({text:"Car state stale",severity:"warning"}),Zt>0&&t-Zt>3e3&&e.push({text:"Selfdrive state stale",severity:"critical"}),_e=e,e}let pe="",fe="",we=!0,me=null,be=null,ve=null;function xe(){window.debug;const t=Qt.textContent,e=te.style.backgroundColor;t===pe&&e===fe||(we=!0,pe=t,fe=e);const i=ue();if(i.length>0&&!t){const t=i.find(t=>"critical"===t.severity)||i[0];return void he(t.text,"critical"===t.severity?"red":"yellow")}if(t){if(ve&&ve.width===yt.width&&ve.height===yt.height||(we=!0,ve={width:yt.width,height:yt.height}),we){we=!1;const i=12,a=4,s=12;Ct.font=`${s}px Arial`;const n=Ct.measureText(t).width+2*i+6+4,r=s+2*a;me&&me.width===n&&me.height===r||(me=document.createElement("canvas"),me.width=n,me.height=r,be=me.getContext("2d")),be.clearRect(0,0,n,r);const o=5;be.fillStyle="rgba(0, 0, 0, 0.7)",be.beginPath(),be.roundRect(0,0,n,r,o),be.fill();const l=3,d=i+l,h=r/2;be.fillStyle=e,be.beginPath(),be.arc(d,h,l,0,2*Math.PI),be.fill(),be.fillStyle="white",be.font=`${s}px Arial`,be.textAlign="left",be.textBaseline="middle";const c=d+l+4;be.fillText(t,c,h)}if(me){const t=15,e=yt.width/2-me.width/2,i=yt.height-me.height-t;Ct.drawImage(me,e,i)}}}function ye(t){window.debug;const e=t.split("\r\n");let i=-1;const a=[];for(let t=0;t!n.includes(t)),l=r.slice(0,3).concat(n,o).join(" ");return e[i]=l,e.join("\r\n")}const Ce=new Set,Se=new Set;let Ee,Me,Te;function Le(t,e){const i=setTimeout(()=>{t(),Ce.delete(i)},e);return Ce.add(i),i}function Pe(t,e){const i=setInterval(t,e);return Se.add(i),i}function $e(t){clearTimeout(t),Ce.delete(t)}function Ae(t){clearInterval(t),Se.delete(t)}function Ie(){window.debug,Ce.forEach(t=>clearTimeout(t)),Ce.clear(),Se.forEach(t=>clearInterval(t)),Se.clear(),clearTimeout(Ee),clearInterval(Ht),Ht=null,Vt&&(Vt.close(),Vt=null),Ot&&(Ot.close(),Ot=null),Wt=null,window.animationFrameId&&cancelAnimationFrame(window.animationFrameId)}function De(){window.debug;const t=window.location.hostname;Ie(),ht.classList.contains("active")||2===Nt&&It("driving"),ke(t),de()}async function Re(){window.debug;const t=window.location.hostname;he(`Connecting to ${t}...`,"yellow");try{const e=await fetch(`http://${t}:5088/api/init`,{method:"GET",signal:AbortSignal.timeout(5e3)});if(!e.ok)throw new Error(`Connection failed: ${e.statusText}`);{const i=await e.json();jt=i.is_metric,Kt.is_metric=jt,void 0!==i.dp_dev_dashy?(Rt(i.dp_dev_dashy),2===i.dp_dev_dashy&&ke(t)):Rt(null)}}catch(e){he(`Could not connect to device at ${t}.`,"red")}}async function ke(t){window.debug,he("Initializing WebRTC...","yellow"),clearTimeout(Ee),lastDataReceivedTime=Date.now(),Vt&&(Vt.close(),Vt=null);try{Vt=new RTCPeerConnection({iceServers:[{urls:"stun:stun.l.google.com:19302"}]});Be(Vt.createDataChannel("data")),Vt.ontrack=t=>{"video"===t.track.kind&&(xt.srcObject=t.streams[0],oe(),he("Video connected","green"),xt.onplaying=()=>{clearTimeout(Ee)})},Vt.onconnectionstatechange=()=>{"failed"===Vt.connectionState||"disconnected"===Vt.connectionState||"closed"===Vt.connectionState?(he("WebRTC Error: Could not connect to server (server may be down or inaccessible)","red"),"driving"===Q.get("ui.currentPage")&&(Ee=Le(()=>De(),5e3))):"connected"===Vt.connectionState&&(he("WebRTC Connected","green"),clearTimeout(Ee))},Vt.addTransceiver("video",{direction:"recvonly"});const e=await Vt.createOffer();e.sdp=ye(e.sdp),await Vt.setLocalDescription(e);const i=await fetch(`http://${t}:5001/stream`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sdp:Vt.localDescription.sdp,cameras:["road"],bridge_services_in:[],bridge_services_out:["modelV2","liveCalibration","longitudinalPlan","radarState","selfdriveState","deviceState","carState","controlsState"]})});if(!i.ok){const t=await i.text();throw new Error(`HTTP Error! Status: ${i.status}, Message: ${t}`)}const a=await i.json();await Vt.setRemoteDescription(new RTCSessionDescription(a)),ze()}catch(t){let e=`WebRTC Error: ${t.message}`;t.message.includes("Failed to fetch")&&(e="WebRTC Error: Could not connect to server (server may be down or inaccessible)"),he(e,"red"),t.message.includes("Failed to fetch")&&"driving"===Q.get("ui.currentPage")&&(Ee=setTimeout(()=>De(),5e3))}}function ze(){window.debug,Ae(Ht),lastDataReceivedTime=Date.now(),lastVideoPlaybackTime=xt.currentTime,Ht=Pe(()=>{let t=!1,e="";Date.now()-lastDataReceivedTime>5e3&&(t=!0,e="Data stream stalled"),t||xt.paused||xt.currentTime!==lastVideoPlaybackTime||(t=!0,e="Video stream stalled"),t&&(he(`${e}. Reconnecting...`,"yellow"),De()),lastVideoPlaybackTime=xt.currentTime},2e3)}function Be(t){window.debug;const e=new TextDecoder("utf-8");let i="";function a(t){try{const e=JSON.parse(t.replace(/\bNaN\b/g,"null"));lastDataReceivedTime=Date.now();const i=Date.now();e.data&&void 0!==e.data.dp_dev_dashy&&Rt(e.data.dp_dev_dashy);const a=e.type;qt[a]=e.data,qt.recv_frame[a]=qt.frame,qt.recv_time[a]=i/1e3,qt.updated[a]=!0,qt.valid[a]=!0,qt.seen[a]=!0,"selfdriveState"===a?(Zt=i,0===Ut&&(Ut=i,Xt=qt.frame)):"modelV2"===a?Yt=i:"carState"===a&&(Jt=i),qt.frame++}catch(t){}}t.onmessage=t=>{const s="string"==typeof t.data?t.data:e.decode(t.data,{stream:!0});let n;for(i+=s;-1!==(n=i.indexOf("}{"));){a(i.substring(0,n+1)),i=i.substring(n+1)}i.length>0&&(a(i),i="")}}function Fe(t){window.animationFrameId=requestAnimationFrame(Fe);const e=t-ae;if(!(et.classList.remove("active")),document.querySelectorAll("nav button").forEach(t=>t.classList.remove("active")),document.getElementById(`${t}-page`).classList.add("active"),document.getElementById(`nav-${t}`).classList.add("active"),"files"!==t||bt.hasChildNodes()||Bt("/"),"driving"===e&&"driving"!==t&&Ie(),"driving"===t&&"driving"!==e&&De(),"driving"===t?(Me.classList.remove("visible"),Q.set("ui.navBarVisible",!1),vt.addEventListener("click",Ge)):(Me.classList.add("visible"),Q.set("ui.navBarVisible",!0),vt.removeEventListener("click",Ge),clearTimeout(Te))}function Ge(){Me||(Me=document.querySelector("nav")),Me.classList.toggle("visible"),Me.classList.contains("visible")?($e(Te),Te=Le(()=>{Me.classList.remove("visible")},3e3)):$e(Te)}async function Ve(){window.debug;document.getElementById("settings-content");const t=document.getElementById("local-settings-content");lt(Z,t),Me=document.querySelector("nav"),ut&&(ut.style.display="none"),wt&&(wt.style.display="none"),St();document.getElementById("driving-page-content").addEventListener("click",t=>{ht.classList.contains("active")&&Ge()}),xt.addEventListener("click",t=>{ht.classList.contains("active")&&Ge()}),yt.addEventListener("click",t=>{ht.classList.contains("active")&&Ge()}),$t(),At(),await Re(),It("files"),de(),xt.onstalled=()=>{"driving"===Q.get("ui.currentPage")&&De()},xt.onplaying=()=>{clearTimeout(Ee)}}window.addEventListener("beforeunload",Ie),window.addEventListener("unload",Ie),Ve(); diff --git a/dragonpilot/dashy/web/dist/lib/hls.js b/dragonpilot/dashy/web/dist/lib/hls.js new file mode 100644 index 0000000..2fd899f --- /dev/null +++ b/dragonpilot/dashy/web/dist/lib/hls.js @@ -0,0 +1,2 @@ +!function e(t){var r,i;r=this,i=function(){"use strict";function r(e,t){for(var r=0;r=this.minWeight_},t.getEstimate=function(){return this.canEstimate()?Math.min(this.fast_.getEstimate(),this.slow_.getEstimate()):this.defaultEstimate_},t.getEstimateTTFB=function(){return this.ttfb_.getTotalWeight()>=this.minWeight_?this.ttfb_.getEstimate():this.defaultTTFB_},t.destroy=function(){},i(e,[{key:"defaultEstimate",get:function(){return this.defaultEstimate_}}])}(),N=function(e,t){this.trace=void 0,this.debug=void 0,this.log=void 0,this.warn=void 0,this.info=void 0,this.error=void 0;var r="["+e+"]:";this.trace=U,this.debug=t.debug.bind(null,r),this.log=t.log.bind(null,r),this.warn=t.warn.bind(null,r),this.info=t.info.bind(null,r),this.error=t.error.bind(null,r)},U=function(){},B={trace:U,debug:U,log:U,warn:U,info:U,error:U};function G(){return a({},B)}function K(e,t,r){return t[e]?t[e].bind(t):function(e,t){var r=self.console[e];return r?r.bind(self.console,(t?"["+t+"] ":"")+"["+e+"] >"):U}(e,r)}var V=G();function H(e,t,r){var i=G();if("object"==typeof console&&!0===e||"object"==typeof e){var n=["debug","log","info","warn","error"];n.forEach((function(t){i[t]=K(t,e,r)}));try{i.log('Debug logs enabled for "'+t+'" in hls.js version 1.6.6')}catch(e){return G()}n.forEach((function(t){V[t]=K(t,e)}))}else a(V,i);return i}var Y=V;function W(e){if(void 0===e&&(e=!0),"undefined"!=typeof self)return(e||!self.MediaSource)&&self.ManagedMediaSource||self.MediaSource||self.WebKitMediaSource}function j(e,t){var r=Object.keys(e),i=Object.keys(t),n=r.length,a=i.length;return!n||!a||n===a&&!r.some((function(e){return-1===i.indexOf(e)}))}function q(e,t){if(void 0===t&&(t=!1),"undefined"!=typeof TextDecoder){var r=new TextDecoder("utf-8").decode(e);if(t){var i=r.indexOf("\0");return-1!==i?r.substring(0,i):r}return r.replace(/\0/g,"")}for(var n,a,s,o=e.length,l="",u=0;u>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:l+=String.fromCharCode(n);break;case 12:case 13:a=e[u++],l+=String.fromCharCode((31&n)<<6|63&a);break;case 14:a=e[u++],s=e[u++],l+=String.fromCharCode((15&n)<<12|(63&a)<<6|(63&s)<<0)}}return l}var X={hexDump:function(e){for(var t="",r=0;r1||1===r&&this.levelkeys[t[0]].encrypted)return!0}return!1}},{key:"programDateTime",get:function(){return null===this._programDateTime&&this.rawProgramDateTime&&(this.programDateTime=Date.parse(this.rawProgramDateTime)),this._programDateTime},set:function(e){A(e)?this._programDateTime=e:this._programDateTime=this.rawProgramDateTime=null}},{key:"ref",get:function(){return ee(this)?(this._ref||(this._ref={base:this.base,start:this.start,duration:this.duration,sn:this.sn,programDateTime:this.programDateTime}),this._ref):null}}])}(Z),re=function(e){function t(t,r,i,n,a){var s;(s=e.call(this,i)||this).fragOffset=0,s.duration=0,s.gap=!1,s.independent=!1,s.relurl=void 0,s.fragment=void 0,s.index=void 0,s.duration=t.decimalFloatingPoint("DURATION"),s.gap=t.bool("GAP"),s.independent=t.bool("INDEPENDENT"),s.relurl=t.enumeratedString("URI"),s.fragment=r,s.index=n;var o=t.enumeratedString("BYTERANGE");return o&&s.setByteRange(o,a),a&&(s.fragOffset=a.fragOffset+a.duration),s}return o(t,e),i(t,[{key:"start",get:function(){return this.fragment.start+this.fragOffset}},{key:"end",get:function(){return this.start+this.duration}},{key:"loaded",get:function(){var e=this.elementaryStreams;return!!(e.audio||e.video||e.audiovideo)}}])}(Z);function ie(e,t){var r=Object.getPrototypeOf(e);if(r){var i=Object.getOwnPropertyDescriptor(r,t);return i||ie(r,t)}}var ne=Math.pow(2,32)-1,ae=[].push,se={video:1,audio:2,id3:3,text:4};function oe(e){return String.fromCharCode.apply(null,e)}function le(e,t){var r=e[t]<<8|e[t+1];return r<0?65536+r:r}function ue(e,t){var r=he(e,t);return r<0?4294967296+r:r}function de(e,t){var r=ue(e,t);return r*=Math.pow(2,32),r+=ue(e,t+4)}function he(e,t){return e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3]}function fe(e,t){var r=[];if(!t.length)return r;for(var i=e.byteLength,n=0;n1?n+a:i;if(oe(e.subarray(n+4,n+8))===t[0])if(1===t.length)r.push(e.subarray(n+8,s));else{var o=fe(e.subarray(n+8,s),t.slice(1));o.length&&ae.apply(r,o)}n=s}return r}function ce(e){var t=[],r=e[0],i=8,n=ue(e,i);i+=4;var a=0,s=0;0===r?(a=ue(e,i),s=ue(e,i+4),i+=8):(a=de(e,i),s=de(e,i+8),i+=16),i+=2;var o=e.length+s,l=le(e,i);i+=2;for(var u=0;u>>31)return Y.warn("SIDX has hierarchical references (not supported)"),null;var c=ue(e,d);d+=4,t.push({referenceSize:f,subsegmentDuration:c,info:{duration:c/n,start:o,end:o+f-1}}),o+=f,i=d+=4}return{earliestPresentationTime:a,timescale:n,version:r,referencesCount:l,references:t}}function ge(e){for(var t=[],r=fe(e,["moov","trak"]),i=0;i3&&(a+="."+ye(u[1])+ye(u[2])+ye(u[3]),t=me("avc1"===l?"dva1":"dvav",i));break;case"mp4a":var d=fe(r,[n])[0],h=fe(d.subarray(28),["esds"])[0];if(h&&h.length>7){var f=4;if(3!==h[f++])break;f=pe(h,f),f+=2;var c=h[f++];if(128&c&&(f+=2),64&c&&(f+=h[f++]),4!==h[f++])break;f=pe(h,f);var g=h[f++];if(64!==g)break;if(a+="."+ye(g),f+=12,5!==h[f++])break;f=pe(h,f);var v=h[f++],m=(248&v)>>3;31===m&&(m+=1+((7&v)<<3)+((224&h[f])>>5)),a+="."+m}break;case"hvc1":case"hev1":var p=fe(i,["hvcC"])[0];if(p&&p.length>12){var y=p[1],E=["","A","B","C"][y>>6],T=31&y,S=ue(p,2),A=(32&y)>>5?"H":"L",L=p[12],R=p.subarray(6,12);a+="."+E+T,a+="."+function(e){for(var t=0,r=0;r<32;r++)t|=(e>>r&1)<<31-r;return t>>>0}(S).toString(16).toUpperCase(),a+="."+A+L;for(var I="",k=R.length;k--;){var b=R[k];(b||I)&&(I="."+b.toString(16).toUpperCase()+I)}a+=I}t=me("hev1"==l?"dvhe":"dvh1",i);break;case"dvh1":case"dvhe":case"dvav":case"dva1":case"dav1":a=me(a,i)||a;break;case"vp09":var D=fe(i,["vpcC"])[0];if(D&&D.length>6){var _=D[4],P=D[5],C=D[6]>>4&15;a+="."+Ee(_)+"."+Ee(P)+"."+Ee(C)}break;case"av01":var w=fe(i,["av1C"])[0];if(w&&w.length>2){var O=w[1]>>>5,x=31&w[1],M=w[2]>>>7?"H":"M",F=(64&w[2])>>6,N=(32&w[2])>>5,U=2===O&&F?N?12:10:F?10:8,B=(16&w[2])>>4,G=(8&w[2])>>3,K=(4&w[2])>>2,V=3&w[2];a+="."+O+"."+Ee(x)+M+"."+Ee(U)+"."+B+"."+G+K+V+"."+Ee(1)+"."+Ee(1)+"."+Ee(1)+".0",t=me("dav1",i)}}return{codec:a,encrypted:s,supplemental:t}}function me(e,t){var r=fe(t,["dvvC"]),i=r.length?r[0]:fe(t,["dvcC"])[0];if(i){var n=i[2]>>1&127,a=i[2]<<5&32|i[3]>>3&31;return e+"."+Ee(n)+"."+Ee(a)}}function pe(e,t){for(var r=t+5;128&e[t++]&&t>1&63;return 39===r||40===r}return 6==(31&t)}function Ie(e,t,r,i){var n=ke(e),a=0;a+=t;for(var s=0,o=0,l=0;a=n.length)break;s+=l=n[a++]}while(255===l);o=0;do{if(a>=n.length)break;o+=l=n[a++]}while(255===l);var u=n.length-a,d=a;if(ou){Y.error("Malformed SEI payload. "+o+" is too small, only "+u+" bytes left to parse.");break}if(4===s){if(181===n[d++]){var h=le(n,d);if(d+=2,49===h){var f=ue(n,d);if(d+=4,1195456820===f){var c=n[d++];if(3===c){var g=n[d++],v=64&g,m=v?2+3*(31&g):0,p=new Uint8Array(m);if(v){p[0]=g;for(var y=1;y16){for(var E=[],T=0;T<16;T++){var S=n[d++].toString(16);E.push(1==S.length?"0"+S:S),3!==T&&5!==T&&7!==T&&9!==T||E.push("-")}for(var A=o-16,L=new Uint8Array(A),R=0;R0&&new DataView(a.buffer).setUint32(0,r.byteLength,!1),function(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),i=1;i>24&255,o[1]=a>>16&255,o[2]=a>>8&255,o[3]=255&a,o.set(e,4),s=0,a=8;s>>24;if(0!==n&&1!==n)return{offset:r,size:t};var a=e.buffer,s=X.hexDump(new Uint8Array(a,r+12,16)),o=null,l=0;if(0===n)l=28;else if(1===n){var u=e.getUint32(28);if(!u||i<32+16*u)return{offset:r,size:t};o=[];for(var d=0;d4||-1!==["ac-3","ec-3","alac","fLaC","Opus"].indexOf(e))&&(Ke(e,"audio")||Ke(e,"video")))return e;if(t){var r=t.split(",");if(r.length>1){if(e)for(var i=r.length;i--;)if(r[i].substring(0,4)===e.substring(0,4))return r[i];return r[0]}}return t||e}function Ke(e,t){return Ce(e,t)&&Oe(e,t)}function Ve(e){if(e.startsWith("av01.")){for(var t=e.split("."),r=["0","111","01","01","01","0"],i=t.length;i>4&&i<10;i++)t[i]=r[i-4];return t.join(".")}return e}function He(e){var t=W(e)||{isTypeSupported:function(){return!1}};return{mpeg:t.isTypeSupported("audio/mpeg"),mp3:t.isTypeSupported('audio/mp4; codecs="mp3"'),ac3:t.isTypeSupported('audio/mp4; codecs="ac-3"')}}function Ye(e){return e.replace(/^.+codecs=["']?([^"']+).*$/,"$1")}var We={supported:!0,configurations:[],decodingInfoResults:[{supported:!0,powerEfficient:!0,smooth:!0}]};function je(e,t){return{supported:!1,configurations:t,decodingInfoResults:[{supported:!1,smooth:!1,powerEfficient:!1}],error:e}}function qe(e,t,r,i){void 0===i&&(i={});var n=e.videoCodec;if(!n&&!e.audioCodec||!r)return Promise.resolve(We);for(var a=[],s=function(e){var t,r=null==(t=e.videoCodec)?void 0:t.split(","),i=Qe(e),n=e.width||640,a=e.height||480,s=e.frameRate||30,o=e.videoRange.toLowerCase();return r?r.map((function(e){var t={contentType:xe(Ve(e),"video"),width:n,height:a,bitrate:i,framerate:s};return"sdr"!==o&&(t.transferFunction=o),t})):[]}(e),o=s.length,l=function(e,t,r){var i,n=null==(i=e.audioCodec)?void 0:i.split(","),a=Qe(e);return n&&e.audioGroups?e.audioGroups.reduce((function(e,i){var s,o=i?null==(s=t.groups[i])?void 0:s.tracks:null;return o?o.reduce((function(e,t){if(t.groupId===i){var s=parseFloat(t.channels||"");n.forEach((function(t){var i={contentType:xe(t,"audio"),bitrate:r?Xe(t,a):a};s&&(i.channels=""+s),e.push(i)}))}return e}),e):e}),[]):[]}(e,t,o>0),u=l.length,d=o||1*u||1;d--;){var h={type:"media-source"};if(o&&(h.video=s[d%o]),u){h.audio=l[d%u];var f=h.audio.bitrate;h.video&&f&&(h.video.bitrate-=f)}a.push(h)}if(n){var c=navigator.userAgent;if(n.split(",").some((function(e){return Le(e)}))&&_e())return Promise.resolve(je(new Error("Overriding Windows Firefox HEVC MediaCapabilities result based on user-agent string: ("+c+")"),a))}return Promise.all(a.map((function(e){var t,n,a,s,o=(n="",a=(t=e).audio,(s=t.video)&&(n+=Ye(s.contentType)+"_r"+s.height+"x"+s.width+"f"+Math.ceil(s.framerate)+(s.transferFunction||"sd")+"_"+Math.ceil(s.bitrate/1e5)),a&&(n+=(s?"_":"")+Ye(a.contentType)+"_c"+a.channels),n);return i[o]||(i[o]=r.decodingInfo(e))}))).then((function(e){return{supported:!e.some((function(e){return!e.supported})),configurations:a,decodingInfoResults:e}})).catch((function(e){return{supported:!1,configurations:a,decodingInfoResults:[],error:e}}))}function Xe(e,t){if(t<=1)return 1;var r=128e3;return"ec-3"===e?r=768e3:"ac-3"===e&&(r=64e4),Math.min(t/2,r)}function Qe(e){return 1e3*Math.ceil(Math.max(.9*e.bitrate,e.averageBitrate)/1e3)||1}var ze=["NONE","TYPE-0","TYPE-1",null],$e=["SDR","PQ","HLG"],Je="",Ze="YES",et="v2";function tt(e){var t=e.canSkipUntil,r=e.canSkipDateRanges,i=e.age;return t&&i-1;i--)if(r(e[i]))return i;for(var n=t+1;n-1&&v!==g,p=!!e||m;if(p||!l.paused&&l.playbackRate&&l.readyState){var y=s.mainForwardBufferInfo;if(p||null!==y){var E=r.bwEstimator.getEstimateTTFB(),T=Math.abs(l.playbackRate);if(!(f<=Math.max(E,h/(2*T)*1e3))){var S=y?y.len/T:0,L=d.loading.first?d.loading.first-d.loading.start:-1,R=d.loaded&&L>-1,I=r.getBwEstimate(),k=s.levels,D=k[g],_=Math.max(d.loaded,Math.round(h*(n.bitrate||D.averageBitrate)/8)),P=R?f-L:f;P<1&&R&&(P=Math.min(f,8*d.loaded/I));var C=R?1e3*d.loaded/P:0,w=E/1e3,O=C?(_-d.loaded)/C:8*_/I+w;if(!(O<=S)){var x,M=C?8*C:I,F=!0===(null==(t=(null==e?void 0:e.details)||r.hls.latestLevelDetails)?void 0:t.live),N=r.hls.config.abrBandWidthUpFactor,U=Number.POSITIVE_INFINITY;for(x=g-1;x>c;x--){var B=k[x].maxBitrate,G=!k[x].details||F;if((U=r.getTimeToLoadFrag(w,M,h*B,G))=O||U>10*h)){R?r.bwEstimator.sample(f-Math.min(E,L),d.loaded):r.bwEstimator.sampleTTFB(f);var K=k[x].maxBitrate;r.getBwEstimate()*N>K&&r.resetEstimator(K);var V=r.findBestLevel(K,c,x,0,S,1,1);V>-1&&(x=V),r.warn("Fragment "+n.sn+(a?" part "+a.index:"")+" of level "+g+" is loading too slowly;\n Fragment duration: "+n.duration.toFixed(3)+"\n Time to underbuffer: "+S.toFixed(3)+" s\n Estimated load time for current fragment: "+O.toFixed(3)+" s\n Estimated load time for down switch fragment: "+U.toFixed(3)+" s\n TTFB estimate: "+(0|L)+" ms\n Current BW estimate: "+(A(I)?0|I:"Unknown")+" bps\n New BW estimate: "+(0|r.getBwEstimate())+" bps\n Switching to level "+x+" @ "+(0|K)+" bps"),s.nextLoadLevel=s.nextAutoLevel=x,r.clearTimer();var H=function(){if(r.clearTimer(),r.fragCurrent===n&&r.hls.loadLevel===x&&x>0){var e=r.getStarvationDelay();if(r.warn("Aborting inflight request "+(x>0?"and switching down":"")+"\n Fragment duration: "+n.duration.toFixed(3)+" s\n Time to underbuffer: "+e.toFixed(3)+" s"),n.abortRequests(),r.fragCurrent=r.partCurrent=null,x>c){var t=r.findBestLevel(r.hls.levels[c].bitrate,c,x,0,e,1,1);-1===t&&(t=c),r.hls.nextLoadLevel=r.hls.nextAutoLevel=t,r.resetEstimator(r.hls.levels[t].bitrate)}}};m||O>2*U?H():r.timer=self.setInterval(H,1e3*U),s.trigger(b.FRAG_LOAD_EMERGENCY_ABORTED,{frag:n,part:a,stats:d})}}}}}}}},r.hls=t,r.bwEstimator=r.initEstimator(),r.registerListeners(),r}o(t,e);var r=t.prototype;return r.resetEstimator=function(e){e&&(this.log("setting initial bwe to "+e),this.hls.config.abrEwmaDefaultEstimate=e),this.firstSelection=-1,this.bwEstimator=this.initEstimator()},r.initEstimator=function(){var e=this.hls.config;return new F(e.abrEwmaSlowVoD,e.abrEwmaFastVoD,e.abrEwmaDefaultEstimate)},r.registerListeners=function(){var e=this.hls;e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.FRAG_LOADING,this.onFragLoading,this),e.on(b.FRAG_LOADED,this.onFragLoaded,this),e.on(b.FRAG_BUFFERED,this.onFragBuffered,this),e.on(b.LEVEL_SWITCHING,this.onLevelSwitching,this),e.on(b.LEVEL_LOADED,this.onLevelLoaded,this),e.on(b.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(b.MAX_AUTO_LEVEL_UPDATED,this.onMaxAutoLevelUpdated,this),e.on(b.ERROR,this.onError,this)},r.unregisterListeners=function(){var e=this.hls;e&&(e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.FRAG_LOADING,this.onFragLoading,this),e.off(b.FRAG_LOADED,this.onFragLoaded,this),e.off(b.FRAG_BUFFERED,this.onFragBuffered,this),e.off(b.LEVEL_SWITCHING,this.onLevelSwitching,this),e.off(b.LEVEL_LOADED,this.onLevelLoaded,this),e.off(b.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(b.MAX_AUTO_LEVEL_UPDATED,this.onMaxAutoLevelUpdated,this),e.off(b.ERROR,this.onError,this))},r.destroy=function(){this.unregisterListeners(),this.clearTimer(),this.hls=this._abandonRulesCheck=this.supportedCache=null,this.fragCurrent=this.partCurrent=null},r.onManifestLoading=function(e,t){this.lastLoadedFragLevel=-1,this.firstSelection=-1,this.lastLevelLoadSec=0,this.supportedCache={},this.fragCurrent=this.partCurrent=null,this.onLevelsUpdated(),this.clearTimer()},r.onLevelsUpdated=function(){this.lastLoadedFragLevel>-1&&this.fragCurrent&&(this.lastLoadedFragLevel=this.fragCurrent.level),this._nextAutoLevel=-1,this.onMaxAutoLevelUpdated(),this.codecTiers=null,this.audioTracksByGroup=null},r.onMaxAutoLevelUpdated=function(){this.firstSelection=-1,this.nextAutoLevelKey=""},r.onFragLoading=function(e,t){var r,i=t.frag;this.ignoreFragment(i)||(i.bitrateTest||(this.fragCurrent=i,this.partCurrent=null!=(r=t.part)?r:null),this.clearTimer(),this.timer=self.setInterval(this._abandonRulesCheck,100))},r.onLevelSwitching=function(e,t){this.clearTimer()},r.onError=function(e,t){if(!t.fatal)switch(t.details){case k.BUFFER_ADD_CODEC_ERROR:case k.BUFFER_APPEND_ERROR:this.lastLoadedFragLevel=-1,this.firstSelection=-1;break;case k.FRAG_LOAD_TIMEOUT:var r=t.frag,i=this.fragCurrent,n=this.partCurrent;if(r&&i&&r.sn===i.sn&&r.level===i.level){var a=performance.now(),s=n?n.stats:r.stats,o=a-s.loading.start,l=s.loading.first?s.loading.first-s.loading.start:-1;if(s.loaded&&l>-1){var u=this.bwEstimator.getEstimateTTFB();this.bwEstimator.sample(o-Math.min(u,l),s.loaded)}else this.bwEstimator.sampleTTFB(o)}}},r.getTimeToLoadFrag=function(e,t,r,i){return e+r/t+(i?e+this.lastLevelLoadSec:0)},r.onLevelLoaded=function(e,t){var r=this.hls.config,i=t.stats.loading,n=i.end-i.first;A(n)&&(this.lastLevelLoadSec=n/1e3),t.details.live?this.bwEstimator.update(r.abrEwmaSlowLive,r.abrEwmaFastLive):this.bwEstimator.update(r.abrEwmaSlowVoD,r.abrEwmaFastVoD),this.timer>-1&&this._abandonRulesCheck(t.levelInfo)},r.onFragLoaded=function(e,t){var r=t.frag,i=t.part,n=i?i.stats:r.stats;if(r.type===w&&this.bwEstimator.sampleTTFB(n.loading.first-n.loading.start),!this.ignoreFragment(r)){if(this.clearTimer(),r.level===this._nextAutoLevel&&(this._nextAutoLevel=-1),this.firstSelection=-1,this.hls.config.abrMaxWithRealBitrate){var a=i?i.duration:r.duration,s=this.hls.levels[r.level],o=(s.loaded?s.loaded.bytes:0)+n.loaded,l=(s.loaded?s.loaded.duration:0)+a;s.loaded={bytes:o,duration:l},s.realBitrate=Math.round(8*o/l)}if(r.bitrateTest){var u={stats:n,frag:r,part:i,id:r.type};this.onFragBuffered(b.FRAG_BUFFERED,u),r.bitrateTest=!1}else this.lastLoadedFragLevel=r.level}},r.onFragBuffered=function(e,t){var r=t.frag,i=t.part,n=null!=i&&i.stats.loaded?i.stats:r.stats;if(!n.aborted&&!this.ignoreFragment(r)){var a=n.parsing.end-n.loading.start-Math.min(n.loading.first-n.loading.start,this.bwEstimator.getEstimateTTFB());this.bwEstimator.sample(a,n.loaded),n.bwEstimate=this.getBwEstimate(),r.bitrateTest?this.bitrateTestDelay=a/1e3:this.bitrateTestDelay=0}},r.ignoreFragment=function(e){return e.type!==w||"initSegment"===e.sn},r.clearTimer=function(){this.timer>-1&&(self.clearInterval(this.timer),this.timer=-1)},r.getAutoLevelKey=function(){return this.getBwEstimate()+"_"+this.getStarvationDelay().toFixed(2)},r.getNextABRAutoLevel=function(){var e=this.fragCurrent,t=this.partCurrent,r=this.hls;if(r.levels.length<=1)return r.loadLevel;var i=r.maxAutoLevel,n=r.config,a=r.minAutoLevel,s=t?t.duration:e?e.duration:0,o=this.getBwEstimate(),l=this.getStarvationDelay(),u=n.abrBandWidthFactor,d=n.abrBandWidthUpFactor;if(l){var h=this.findBestLevel(o,a,i,l,0,u,d);if(h>=0)return this.rebufferNotice=-1,h}var f=s?Math.min(s,n.maxStarvationDelay):n.maxStarvationDelay;if(!l){var c=this.bitrateTestDelay;c&&(f=(s?Math.min(s,n.maxLoadingDelay):n.maxLoadingDelay)-c,this.info("bitrate test took "+Math.round(1e3*c)+"ms, set first fragment max fetchDuration to "+Math.round(1e3*f)+" ms"),u=d=1)}var g=this.findBestLevel(o,a,i,l,f,u,d);if(this.rebufferNotice!==g&&(this.rebufferNotice=g,this.info((l?"rebuffering expected":"buffer is empty")+", optimal quality level "+g)),g>-1)return g;var v=r.levels[a],m=r.loadLevelObj;return m&&(null==v?void 0:v.bitrate)0),f=Math.min(f,t.minHeight),c=Math.min(c,t.minFramerate),g=Math.min(g,t.minBitrate),T.filter((function(e){return t.videoRanges[e]>0})).length>0&&(h=!0)},L=a.length;L--;)S();f=A(f)?f:0,c=A(c)?c:0;var R=Math.max(1080,f),I=Math.max(30,c);g=A(g)?g:r,r=Math.max(g,r),h||(t=void 0);var k=a.length>1;return{codecSet:a.reduce((function(t,i){var n=e[i];if(i===t)return t;if(p=h?T.filter((function(e){return n.videoRanges[e]>0})):[],k){if(n.minBitrate>r)return ot(i,"min bitrate of "+n.minBitrate+" > current estimate of "+r),t;if(!n.hasDefaultAudio)return ot(i,"no renditions with default or auto-select sound found"),t;if(o&&i.indexOf(o.substring(0,4))%5!=0)return ot(i,'audio codec preference "'+o+'" not found'),t;if(s&&!u){if(!n.channels[s])return ot(i,"no renditions with "+s+" channel sound found (channels options: "+Object.keys(n.channels)+")"),t}else if((!o||u)&&d&&0===n.channels[2])return ot(i,"no renditions with stereo sound found"),t;if(n.minHeight>R)return ot(i,"min resolution of "+n.minHeight+" > maximum of "+R),t;if(n.minFramerate>I)return ot(i,"min framerate of "+n.minFramerate+" > maximum of "+I),t;if(!p.some((function(e){return n.videoRanges[e]>0})))return ot(i,"no variants with VIDEO-RANGE of "+st(p)+" found"),t;if(l&&i.indexOf(l.substring(0,4))%5!=0)return ot(i,'video codec preference "'+l+'" not found'),t;if(n.maxScore=Fe(t)||n.fragmentError>e[t].fragmentError)?t:(v=n.minIndex,m=n.maxScore,i)}),void 0),videoRanges:p,preferHDR:E,minFramerate:c,minBitrate:g,minIndex:v}}(P,R,e,k,b),w=C.codecSet,O=C.videoRanges,x=C.minFramerate,M=C.minBitrate,F=C.minIndex,N=C.preferHDR;_=F,E=w,R=N?O[O.length-1]:O[0],I=x,e=Math.max(e,M),this.log("picked start tier "+st(C))}else E=null==T?void 0:T.codecSet,R=null==T?void 0:T.videoRange;for(var U,B=c?c.duration:f?f.duration:0,G=this.bwEstimator.getEstimateTTFB()/1e3,K=[],V=function(){var t,o,f=v[H],g=H>h;if(!f)return 0;if(y.useMediaCapabilities&&!f.supportedResult&&!f.supportedPromise){var m=navigator.mediaCapabilities;"function"==typeof(null==m?void 0:m.decodingInfo)&&function(e,t,r,i,n,a){var s=e.videoCodec,o=e.audioCodec?e.audioGroups:null,l=null==a?void 0:a.audioCodec,u=null==a?void 0:a.channels,d=u?parseInt(u):l?1/0:2,h=null;if(null!=o&&o.length)try{h=1===o.length&&o[0]?t.groups[o[0]].channels:o.reduce((function(e,r){if(r){var i=t.groups[r];if(!i)throw new Error("Audio track group "+r+" not found");Object.keys(i.channels).forEach((function(t){e[t]=(e[t]||0)+i.channels[t]}))}return e}),{2:0})}catch(e){return!0}return void 0!==s&&(s.split(",").some((function(e){return Le(e)}))||e.width>1920&&e.height>1088||e.height>1920&&e.width>1088||e.frameRate>Math.max(i,30)||"SDR"!==e.videoRange&&e.videoRange!==r||e.bitrate>Math.max(n,8e6))||!!h&&A(d)&&Object.keys(h).some((function(e){return parseInt(e)>d}))}(f,D,R,I,e,k)?(f.supportedPromise=qe(f,D,m,l.supportedCache),f.supportedPromise.then((function(e){if(l.hls){f.supportedResult=e;var t=l.hls.levels,r=t.indexOf(f);e.error?l.warn('MediaCapabilities decodingInfo error: "'+e.error+'" for level '+r+" "+st(e)):e.supported?e.decodingInfoResults.some((function(e){return!1===e.smooth||!1===e.powerEfficient}))&&l.log("MediaCapabilities decodingInfo for level "+r+" not smooth or powerEfficient: "+st(e)):(l.warn("Unsupported MediaCapabilities decodingInfo result for level "+r+" "+st(e)),r>-1&&t.length>1&&(l.log("Removing unsupported level "+r),l.hls.removeLevel(r),-1===l.hls.loadLevel&&(l.hls.nextLoadLevel=0)))}}))):f.supportedResult=We}if((E&&f.codecSet!==E||R&&f.videoRange!==R||g&&I>f.frameRate||!g&&I>0&&I=2*B&&0===n?f.averageBitrate:f.maxBitrate,w=l.getTimeToLoadFrag(G,T,C*P,void 0===b);if(T>=C&&(H===d||0===f.loadError&&0===f.fragmentError)&&(w<=G||!A(w)||S&&!l.bitrateTestDelay||w"+H+" adjustedbw("+Math.round(T)+")-bitrate="+Math.round(T-C)+" ttfb:"+G.toFixed(1)+" avgDuration:"+P.toFixed(1)+" maxFetchDuration:"+u.toFixed(1)+" fetchDuration:"+w.toFixed(1)+" firstSelection:"+L+" codecSet:"+f.codecSet+" videoRange:"+f.videoRange+" hls.loadLevel:"+p)),L&&(l.firstSelection=H),{v:H}}},H=r;H>=t;H--)if(0!==(U=V())&&U)return U.v;return-1},r.deriveNextAutoLevel=function(e){var t=this.hls,r=t.maxAutoLevel,i=t.minAutoLevel;return Math.min(Math.max(e,i),r)},i(t,[{key:"firstAutoLevel",get:function(){var e=this.hls,t=e.maxAutoLevel,r=e.minAutoLevel,i=this.getBwEstimate(),n=this.hls.config.maxStarvationDelay,a=this.findBestLevel(i,r,t,0,n,1,1);if(a>-1)return a;var s=this.hls.firstLevel,o=Math.min(Math.max(s,r),t);return this.warn("Could not find best starting auto level. Defaulting to first in playlist "+s+" clamped to "+o),o}},{key:"forcedAutoLevel",get:function(){return this.nextAutoLevelKey?-1:this._nextAutoLevel}},{key:"nextAutoLevel",get:function(){var e=this.forcedAutoLevel,t=this.bwEstimator.canEstimate(),r=this.lastLoadedFragLevel>-1;if(!(-1===e||t&&r&&this.nextAutoLevelKey!==this.getAutoLevelKey()))return e;var i=t&&r?this.getNextABRAutoLevel():this.firstAutoLevel;if(-1!==e){var n=this.hls.levels;if(n.length>Math.max(e,i)&&n[e].loadError<=n[i].loadError)return e}return this._nextAutoLevel=i,this.nextAutoLevelKey=this.getAutoLevelKey(),i},set:function(e){var t=this.deriveNextAutoLevel(e);this._nextAutoLevel!==t&&(this.nextAutoLevelKey="",this._nextAutoLevel=t)}}])}(N),mt=function(e,t){for(var r=0,i=e.length-1,n=null,a=null;r<=i;){var s=t(a=e[n=(r+i)/2|0]);if(s>0)r=n+1;else{if(!(s<0))return a;i=n-1}}return null};function pt(e,t,r,i,n){void 0===r&&(r=0),void 0===i&&(i=0),void 0===n&&(n=.005);var a=null;if(e){a=t[1+e.sn-t[0].sn]||null;var s=e.endDTS-r;s>0&&s<15e-7&&(r+=15e-7),a&&e.level!==a.level&&a.end<=e.end&&(a=t[2+e.sn-t[0].sn]||null)}else 0===r&&0===t[0].start&&(a=t[0]);if(a&&((!e||e.level===a.level)&&0===yt(r,i,a)||function(e,t,r){if(t&&0===t.start&&t.level0){var i=t.tagList.reduce((function(e,t){return"INF"===t[0]&&(e+=parseFloat(t[1])),e}),r);return e.start<=i}return!1}(a,e,Math.min(n,i))))return a;var o=mt(t,yt.bind(null,r,i));return!o||o===e&&a?a:o}function yt(e,t,r){if(void 0===e&&(e=0),void 0===t&&(t=0),r.start<=e&&r.start+r.duration>e)return 0;var i=Math.min(t,r.duration+(r.deltaPTS?r.deltaPTS:0));return r.start+r.duration-i<=e?1:r.start-i>e&&r.start?-1:0}function Et(e,t,r){var i=1e3*Math.min(t,r.duration+(r.deltaPTS?r.deltaPTS:0));return(r.endProgramDateTime||0)-i>e}function Tt(e,t,r){if(e&&e.startCC<=t&&e.endCC>=t){var i,n=e.fragments,a=e.fragmentHint;return a&&(n=n.concat(a)),mt(n,(function(e){return e.cct?-1:(i=e,e.end<=r?1:e.start>r?-1:0)})),i||null}return null}function St(e){switch(e.details){case k.FRAG_LOAD_TIMEOUT:case k.KEY_LOAD_TIMEOUT:case k.LEVEL_LOAD_TIMEOUT:case k.MANIFEST_LOAD_TIMEOUT:return!0}return!1}function At(e,t){var r=St(t);return e.default[(r?"timeout":"error")+"Retry"]}function Lt(e,t){var r="linear"===e.backoff?1:Math.pow(2,t);return Math.min(r*e.retryDelayMs,e.maxRetryDelayMs)}function Rt(e){return d(d({},e),{errorRetry:null,timeoutRetry:null})}function It(e,t,r,i){if(!e)return!1;var n=null==i?void 0:i.code,a=t499)}(n)||!!r);return e.shouldRetry?e.shouldRetry(e,t,r,i,a):a}var kt=0,bt=2,Dt=3,_t=5,Pt=0,Ct=1,wt=2,Ot=function(e){function t(t){var r;return(r=e.call(this,"error-controller",t.logger)||this).hls=void 0,r.playlistError=0,r.penalizedRenditions={},r.hls=t,r.registerListeners(),r}o(t,e);var r=t.prototype;return r.registerListeners=function(){var e=this.hls;e.on(b.ERROR,this.onError,this),e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.LEVEL_UPDATED,this.onLevelUpdated,this)},r.unregisterListeners=function(){var e=this.hls;e&&(e.off(b.ERROR,this.onError,this),e.off(b.ERROR,this.onErrorOut,this),e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.LEVEL_UPDATED,this.onLevelUpdated,this))},r.destroy=function(){this.unregisterListeners(),this.hls=null,this.penalizedRenditions={}},r.startLoad=function(e){},r.stopLoad=function(){this.playlistError=0},r.getVariantLevelIndex=function(e){return(null==e?void 0:e.type)===w?e.level:this.hls.loadLevel},r.onManifestLoading=function(){this.playlistError=0,this.penalizedRenditions={}},r.onLevelUpdated=function(){this.playlistError=0},r.onError=function(e,t){var r;if(!t.fatal){var i=this.hls,n=t.context;switch(t.details){case k.FRAG_LOAD_ERROR:case k.FRAG_LOAD_TIMEOUT:case k.KEY_LOAD_ERROR:case k.KEY_LOAD_TIMEOUT:return void(t.errorAction=this.getFragRetryOrSwitchAction(t));case k.FRAG_PARSING_ERROR:if(null!=(r=t.frag)&&r.gap)return void(t.errorAction=xt());case k.FRAG_GAP:case k.FRAG_DECRYPT_ERROR:return t.errorAction=this.getFragRetryOrSwitchAction(t),void(t.errorAction.action=bt);case k.LEVEL_EMPTY_ERROR:case k.LEVEL_PARSING_ERROR:var a,s,o=t.parent===w?t.level:i.loadLevel;return void(t.details===k.LEVEL_EMPTY_ERROR&&null!=(a=t.context)&&null!=(s=a.levelDetails)&&s.live?t.errorAction=this.getPlaylistRetryOrSwitchAction(t,o):(t.levelRetry=!1,t.errorAction=this.getLevelSwitchAction(t,o)));case k.LEVEL_LOAD_ERROR:case k.LEVEL_LOAD_TIMEOUT:return void("number"==typeof(null==n?void 0:n.level)&&(t.errorAction=this.getPlaylistRetryOrSwitchAction(t,n.level)));case k.AUDIO_TRACK_LOAD_ERROR:case k.AUDIO_TRACK_LOAD_TIMEOUT:case k.SUBTITLE_LOAD_ERROR:case k.SUBTITLE_TRACK_LOAD_TIMEOUT:if(n){var l=i.loadLevelObj;if(l&&(n.type===P&&l.hasAudioGroup(n.groupId)||n.type===C&&l.hasSubtitleGroup(n.groupId)))return t.errorAction=this.getPlaylistRetryOrSwitchAction(t,i.loadLevel),t.errorAction.action=bt,void(t.errorAction.flags=Ct)}return;case k.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED:var u=i.loadLevelObj,d=null==u?void 0:u.attrs["HDCP-LEVEL"];return void(d?t.errorAction={action:bt,flags:wt,hdcpLevel:d}:this.keySystemError(t));case k.BUFFER_ADD_CODEC_ERROR:case k.REMUX_ALLOC_ERROR:case k.BUFFER_APPEND_ERROR:var h;return void(t.errorAction||(t.errorAction=this.getLevelSwitchAction(t,null!=(h=t.level)?h:i.loadLevel)));case k.INTERNAL_EXCEPTION:case k.BUFFER_APPENDING_ERROR:case k.BUFFER_FULL_ERROR:case k.LEVEL_SWITCH_ERROR:case k.BUFFER_STALLED_ERROR:case k.BUFFER_SEEK_OVER_HOLE:case k.BUFFER_NUDGE_ON_STALL:return void(t.errorAction=xt())}t.type===I.KEY_SYSTEM_ERROR&&this.keySystemError(t)}},r.keySystemError=function(e){var t=this.getVariantLevelIndex(e.frag);e.levelRetry=!1,e.errorAction=this.getLevelSwitchAction(e,t)},r.getPlaylistRetryOrSwitchAction=function(e,t){var r=At(this.hls.config.playlistLoadPolicy,e),i=this.playlistError++;if(It(r,i,St(e),e.response))return{action:_t,flags:Pt,retryConfig:r,retryCount:i};var n=this.getLevelSwitchAction(e,t);return r&&(n.retryConfig=r,n.retryCount=i),n},r.getFragRetryOrSwitchAction=function(e){var t=this.hls,r=this.getVariantLevelIndex(e.frag),i=t.levels[r],n=t.config,a=n.fragLoadPolicy,s=n.keyLoadPolicy,o=At(e.details.startsWith("key")?s:a,e),l=t.levels.reduce((function(e,t){return e+t.fragmentError}),0);if(i&&(e.details!==k.FRAG_GAP&&i.fragmentError++,It(o,l,St(e),e.response)))return{action:_t,flags:Pt,retryConfig:o,retryCount:l};var u=this.getLevelSwitchAction(e,r);return o&&(u.retryConfig=o,u.retryCount=l),u},r.getLevelSwitchAction=function(e,t){var r=this.hls;null==t&&(t=r.loadLevel);var i=this.hls.levels[t];if(i){var n,a,s=e.details;i.loadError++,s===k.BUFFER_APPEND_ERROR&&i.fragmentError++;var o=-1,l=r.levels,u=r.loadLevel,d=r.minAutoLevel,h=r.maxAutoLevel;r.autoLevelEnabled||r.config.preserveManualLevelOnError||(r.loadLevel=-1);for(var f,c=null==(n=e.frag)?void 0:n.type,g=(c===O&&s===k.FRAG_PARSING_ERROR||"audio"===e.sourceBufferName&&(s===k.BUFFER_ADD_CODEC_ERROR||s===k.BUFFER_APPEND_ERROR))&&l.some((function(e){var t=e.audioCodec;return i.audioCodec!==t})),v="video"===e.sourceBufferName&&(s===k.BUFFER_ADD_CODEC_ERROR||s===k.BUFFER_APPEND_ERROR)&&l.some((function(e){var t=e.codecSet,r=e.audioCodec;return i.codecSet!==t&&i.audioCodec===r})),m=null!=(a=e.context)?a:{},p=m.type,y=m.groupId,E=function(){var t=(T+u)%l.length;if(t!==u&&t>=d&&t<=h&&0===l[t].loadError){var r,n,a=l[t];if(s===k.FRAG_GAP&&c===w&&e.frag){var f=l[t].details;if(f){var m=pt(e.frag,f.fragments,e.frag.start);if(null!=m&&m.gap)return 0}}else{if(p===P&&a.hasAudioGroup(y)||p===C&&a.hasSubtitleGroup(y))return 0;if(c===O&&null!=(r=i.audioGroups)&&r.some((function(e){return a.hasAudioGroup(e)}))||c===x&&null!=(n=i.subtitleGroups)&&n.some((function(e){return a.hasSubtitleGroup(e)}))||g&&i.audioCodec===a.audioCodec||!g&&i.audioCodec!==a.audioCodec||v&&i.codecSet===a.codecSet)return 0}return o=t,1}},T=l.length;T--&&(0===(f=E())||1!==f););if(o>-1&&r.loadLevel!==o)return e.levelRetry=!0,this.playlistError=0,{action:bt,flags:Pt,nextAutoLevel:o}}return{action:bt,flags:Ct}},r.onErrorOut=function(e,t){var r;switch(null==(r=t.errorAction)?void 0:r.action){case kt:break;case bt:this.sendAlternateToPenaltyBox(t),t.errorAction.resolved||t.details===k.FRAG_GAP?/MediaSource readyState: ended/.test(t.error.message)&&(this.warn('MediaSource ended after "'+t.sourceBufferName+'" sourceBuffer append error. Attempting to recover from media error.'),this.hls.recoverMediaError()):t.fatal=!0}t.fatal&&this.hls.stopLoad()},r.sendAlternateToPenaltyBox=function(e){var t=this.hls,r=e.errorAction;if(r){var i=r.flags,n=r.hdcpLevel,a=r.nextAutoLevel;switch(i){case Pt:this.switchLevel(e,a);break;case wt:n&&(t.maxHdcpLevel=ze[ze.indexOf(n)-1],r.resolved=!0),this.warn('Restricting playback to HDCP-LEVEL of "'+t.maxHdcpLevel+'" or lower')}r.resolved||this.switchLevel(e,a)}},r.switchLevel=function(e,t){if(void 0!==t&&e.errorAction&&(this.warn("switching to level "+t+" after "+e.details),this.hls.nextAutoLevel=t,e.errorAction.resolved=!0,this.hls.nextLoadLevel=this.hls.nextAutoLevel,e.details===k.BUFFER_ADD_CODEC_ERROR&&e.mimeType&&"audiovideo"!==e.sourceBufferName))for(var r=Ye(e.mimeType),i=this.hls.levels,n=i.length;n--;)i[n][e.sourceBufferName+"Codec"]===r&&this.hls.removeLevel(n)},t}(N);function xt(e){var t={action:kt,flags:Pt};return e&&(t.resolved=!0),t}var Mt="NOT_LOADED",Ft="APPENDING",Nt="PARTIAL",Ut="OK",Bt=function(){function e(e){this.activePartLists=Object.create(null),this.endListFragments=Object.create(null),this.fragments=Object.create(null),this.timeRanges=Object.create(null),this.bufferPadding=.2,this.hls=void 0,this.hasGaps=!1,this.hls=e,this._registerListeners()}var t=e.prototype;return t._registerListeners=function(){var e=this.hls;e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.BUFFER_APPENDED,this.onBufferAppended,this),e.on(b.FRAG_BUFFERED,this.onFragBuffered,this),e.on(b.FRAG_LOADED,this.onFragLoaded,this)},t._unregisterListeners=function(){var e=this.hls;e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.BUFFER_APPENDED,this.onBufferAppended,this),e.off(b.FRAG_BUFFERED,this.onFragBuffered,this),e.off(b.FRAG_LOADED,this.onFragLoaded,this)},t.destroy=function(){this._unregisterListeners(),this.fragments=this.activePartLists=this.endListFragments=this.timeRanges=null},t.getAppendedFrag=function(e,t){var r=this.activePartLists[t];if(r)for(var i=r.length;i--;){var n=r[i];if(!n)break;var a=n.end;if(n.start<=e&&null!==a&&e<=a)return n}return this.getBufferedFrag(e,t)},t.getBufferedFrag=function(e,t){return this.getFragAtPos(e,t,!0)},t.getFragAtPos=function(e,t,r){for(var i=this.fragments,n=Object.keys(i),a=n.length;a--;){var s=i[n[a]];if((null==s?void 0:s.body.type)===t&&(!r||s.buffered)){var o=s.body;if(o.start<=e&&e<=o.end)return o}}return null},t.detectEvictedFragments=function(e,t,r,i,n){var a=this;this.timeRanges&&(this.timeRanges[e]=t);var s=(null==i?void 0:i.fragment.sn)||-1;Object.keys(this.fragments).forEach((function(i){var o=a.fragments[i];if(o&&!(s>=o.body.sn))if(o.buffered||o.loaded&&!n){var l=o.range[e];l&&(0!==l.time.length?l.time.some((function(e){var r=!a.isTimeBuffered(e.startPTS,e.endPTS,t);return r&&a.removeFragment(o.body),r})):a.removeFragment(o.body))}else o.body.type===r&&a.removeFragment(o.body)}))},t.detectPartialFragments=function(e){var t=this,r=this.timeRanges;if(r&&"initSegment"!==e.frag.sn){var i=e.frag,n=Kt(i),a=this.fragments[n];if(!(!a||a.buffered&&i.gap)){var s=!i.relurl;Object.keys(r).forEach((function(n){var o=i.elementaryStreams[n];if(o){var l=r[n],u=s||!0===o.partial;a.range[n]=t.getBufferedTimes(i,e.part,u,l)}})),a.loaded=null,Object.keys(a.range).length?(a.buffered=!0,(a.body.endList=i.endList||a.body.endList)&&(this.endListFragments[a.body.type]=a),Gt(a)||this.removeParts(i.sn-1,i.type)):this.removeFragment(a.body)}}},t.removeParts=function(e,t){var r=this.activePartLists[t];r&&(this.activePartLists[t]=Vt(r,(function(t){return t.fragment.sn>=e})))},t.fragBuffered=function(e,t){var r=Kt(e),i=this.fragments[r];!i&&t&&(i=this.fragments[r]={body:e,appendedPTS:null,loaded:null,buffered:!1,range:Object.create(null)},e.gap&&(this.hasGaps=!0)),i&&(i.loaded=null,i.buffered=!0)},t.getBufferedTimes=function(e,t,r,i){for(var n={time:[],partial:r},a=e.start,s=e.end,o=e.minEndPTS||s,l=e.maxStartPTS||a,u=0;u=d&&o<=h){n.time.push({startPTS:Math.max(a,i.start(u)),endPTS:Math.min(s,i.end(u))});break}if(ad){var f=Math.max(a,i.start(u)),c=Math.min(s,i.end(u));c>f&&(n.partial=!0,n.time.push({startPTS:f,endPTS:c}))}else if(s<=d)break}return n},t.getPartialFragment=function(e){var t,r,i,n=null,a=0,s=this.bufferPadding,o=this.fragments;return Object.keys(o).forEach((function(l){var u=o[l];u&&Gt(u)&&(r=u.body.start-s,i=u.body.end+s,e>=r&&e<=i&&(t=Math.min(e-r,i-e),a<=t&&(n=u.body,a=t)))})),n},t.isEndListAppended=function(e){var t=this.endListFragments[e];return void 0!==t&&(t.buffered||Gt(t))},t.getState=function(e){var t=Kt(e),r=this.fragments[t];return r?r.buffered?Gt(r)?Nt:Ut:Ft:Mt},t.isTimeBuffered=function(e,t,r){for(var i,n,a=0;a=i&&t<=n)return!0;if(t<=i)return!1}return!1},t.onManifestLoading=function(){this.removeAllFragments()},t.onFragLoaded=function(e,t){if("initSegment"!==t.frag.sn&&!t.frag.bitrateTest){var r=t.frag,i=t.part?null:t,n=Kt(r);this.fragments[n]={body:r,appendedPTS:null,loaded:i,buffered:!1,range:Object.create(null)}}},t.onBufferAppended=function(e,t){var r=t.frag,i=t.part,n=t.timeRanges,a=t.type;if("initSegment"!==r.sn){var s=r.type;if(i){var o=this.activePartLists[s];o||(this.activePartLists[s]=o=[]),o.push(i)}this.timeRanges=n;var l=n[a];this.detectEvictedFragments(a,l,s,i)}},t.onFragBuffered=function(e,t){this.detectPartialFragments(t)},t.hasFragment=function(e){var t=Kt(e);return!!this.fragments[t]},t.hasFragments=function(e){var t=this.fragments,r=Object.keys(t);if(!e)return r.length>0;for(var i=r.length;i--;){var n=t[r[i]];if((null==n?void 0:n.body.type)===e)return!0}return!1},t.hasParts=function(e){var t;return!(null==(t=this.activePartLists[e])||!t.length)},t.removeFragmentsInRange=function(e,t,r,i,n){var a=this;i&&!this.hasGaps||Object.keys(this.fragments).forEach((function(s){var o=a.fragments[s];if(o){var l=o.body;l.type!==r||i&&!l.gap||l.starte&&(o.buffered||n)&&a.removeFragment(l)}}))},t.removeFragment=function(e){var t=Kt(e);e.clearElementaryStreamInfo();var r=this.activePartLists[e.type];if(r){var i=e.sn;this.activePartLists[e.type]=Vt(r,(function(e){return e.fragment.sn!==i}))}delete this.fragments[t],e.endList&&delete this.endListFragments[e.type]},t.removeAllFragments=function(){var e,t;this.fragments=Object.create(null),this.endListFragments=Object.create(null),this.activePartLists=Object.create(null),this.hasGaps=!1;var r=null==(e=this.hls)||null==(t=e.latestLevelDetails)?void 0:t.partList;r&&r.forEach((function(e){return e.clearElementaryStreamInfo()}))},e}();function Gt(e){var t,r,i;return e.buffered&&(e.body.gap||(null==(t=e.range.video)?void 0:t.partial)||(null==(r=e.range.audio)?void 0:r.partial)||(null==(i=e.range.audiovideo)?void 0:i.partial))}function Kt(e){return e.type+"_"+e.level+"_"+e.sn}function Vt(e,t){return e.filter((function(e){var r=t(e);return r||e.clearElementaryStreamInfo(),r}))}var Ht=0,Yt=1,Wt=function(){function e(e,t,r){this.subtle=void 0,this.aesIV=void 0,this.aesMode=void 0,this.subtle=e,this.aesIV=t,this.aesMode=r}return e.prototype.decrypt=function(e,t){switch(this.aesMode){case Ht:return this.subtle.decrypt({name:"AES-CBC",iv:this.aesIV},t,e);case Yt:return this.subtle.decrypt({name:"AES-CTR",counter:this.aesIV,length:64},t,e);default:throw new Error("[AESCrypto] invalid aes mode "+this.aesMode)}},e}(),jt=function(){function e(){this.rcon=[0,1,2,4,8,16,32,64,128,27,54],this.subMix=[new Uint32Array(256),new Uint32Array(256),new Uint32Array(256),new Uint32Array(256)],this.invSubMix=[new Uint32Array(256),new Uint32Array(256),new Uint32Array(256),new Uint32Array(256)],this.sBox=new Uint32Array(256),this.invSBox=new Uint32Array(256),this.key=new Uint32Array(0),this.ksRows=0,this.keySize=0,this.keySchedule=void 0,this.invKeySchedule=void 0,this.initTable()}var t=e.prototype;return t.uint8ArrayToUint32Array_=function(e){for(var t=new DataView(e),r=new Uint32Array(4),i=0;i<4;i++)r[i]=t.getUint32(4*i);return r},t.initTable=function(){var e=this.sBox,t=this.invSBox,r=this.subMix,i=r[0],n=r[1],a=r[2],s=r[3],o=this.invSubMix,l=o[0],u=o[1],d=o[2],h=o[3],f=new Uint32Array(256),c=0,g=0,v=0;for(v=0;v<256;v++)f[v]=v<128?v<<1:v<<1^283;for(v=0;v<256;v++){var m=g^g<<1^g<<2^g<<3^g<<4;m=m>>>8^255&m^99,e[c]=m,t[m]=c;var p=f[c],y=f[p],E=f[y],T=257*f[m]^16843008*m;i[c]=T<<24|T>>>8,n[c]=T<<16|T>>>16,a[c]=T<<8|T>>>24,s[c]=T,T=16843009*E^65537*y^257*p^16843008*c,l[m]=T<<24|T>>>8,u[m]=T<<16|T>>>16,d[m]=T<<8|T>>>24,h[m]=T,c?(c=p^f[f[f[E^p]]],g^=f[f[g]]):c=g=1}},t.expandKey=function(e){for(var t=this.uint8ArrayToUint32Array_(e),r=!0,i=0;i1&&this.tickImmediate(),this._tickCallCount=0)},r.tickImmediate=function(){this.clearNextTick(),this._tickTimer=self.setTimeout(this._boundTick,0)},r.doTick=function(){},t}(N),tr=function(e,t,r,i,n,a){void 0===i&&(i=0),void 0===n&&(n=-1),void 0===a&&(a=!1),this.level=void 0,this.sn=void 0,this.part=void 0,this.id=void 0,this.size=void 0,this.partial=void 0,this.transmuxing={start:0,executeStart:0,executeEnd:0,end:0},this.buffering={audio:{start:0,executeStart:0,executeEnd:0,end:0},video:{start:0,executeStart:0,executeEnd:0,end:0},audiovideo:{start:0,executeStart:0,executeEnd:0,end:0}},this.level=e,this.sn=t,this.id=r,this.size=i,this.part=n,this.partial=a},rr={length:0,start:function(){return 0},end:function(){return 0}},ir=function(){function e(){}return e.isBuffered=function(t,r){if(t)for(var i=e.getBuffered(t),n=i.length;n--;)if(r>=i.start(n)&&r<=i.end(n))return!0;return!1},e.bufferedRanges=function(t){if(t){var r=e.getBuffered(t);return e.timeRangesToArray(r)}return[]},e.timeRangesToArray=function(e){for(var t=[],r=0;r1&&e.sort((function(e,t){return e.start-t.start||t.end-e.end}));var i=-1,n=[];if(r)for(var a=0;a=e[a].start&&t<=e[a].end&&(i=a);var s=n.length;if(s){var o=n[s-1].end;e[a].start-oo&&(n[s-1].end=e[a].end):n.push(e[a])}else n.push(e[a])}else n=e;for(var l,u=0,d=t,h=t,f=0;f=c&&t<=g&&(i=f),t+r>=c&&tNumber.MAX_SAFE_INTEGER?1/0:t},t.hexadecimalInteger=function(e){if(this[e]){var t=(this[e]||"0x").slice(2);t=(1&t.length?"0":"")+t;for(var r=new Uint8Array(t.length/2),i=0;iNumber.MAX_SAFE_INTEGER?1/0:t},t.decimalFloatingPoint=function(e){return parseFloat(this[e])},t.optionalFloat=function(e,t){var r=this[e];return r?parseFloat(r):t},t.enumeratedString=function(e){return this[e]},t.enumeratedStringList=function(e,t){var r=this[e];return(r?r.split(/[ ,]+/):[]).reduce((function(e,t){return e[t.toLowerCase()]=!0,e}),t)},t.bool=function(e){return"YES"===this[e]},t.decimalResolution=function(e){var t=ur.exec(this[e]);if(null!==t)return{width:parseInt(t[1],10),height:parseInt(t[2],10)}},e.parseAttrList=function(e,t){var r,i={};for(dr.lastIndex=0;null!==(r=dr.exec(e));){var n=r[1].trim(),a=r[2],s=0===a.indexOf('"')&&a.lastIndexOf('"')===a.length-1,o=!1;if(s)a=a.slice(1,-1);else switch(n){case"IV":case"SCTE35-CMD":case"SCTE35-IN":case"SCTE35-OUT":o=!0}if(t&&(s||o))a=sr(t,a);else if(!o&&!s)switch(n){case"CLOSED-CAPTIONS":if("NONE"===a)break;case"ALLOWED-CPC":case"CLASS":case"ASSOC-LANGUAGE":case"AUDIO":case"BYTERANGE":case"CHANNELS":case"CHARACTERISTICS":case"CODECS":case"DATA-ID":case"END-DATE":case"GROUP-ID":case"ID":case"IMPORT":case"INSTREAM-ID":case"KEYFORMAT":case"KEYFORMATVERSIONS":case"LANGUAGE":case"NAME":case"PATHWAY-ID":case"QUERYPARAM":case"RECENTLY-REMOVED-DATERANGES":case"SERVER-URI":case"STABLE-RENDITION-ID":case"STABLE-VARIANT-ID":case"START-DATE":case"SUBTITLES":case"SUPPLEMENTAL-CODECS":case"URI":case"VALUE":case"VIDEO":case"X-ASSET-LIST":case"X-ASSET-URI":Y.warn(e+": attribute "+n+" is missing quotes")}i[n]=a}return i},i(e,[{key:"clientAttrs",get:function(){return Object.keys(this).filter((function(e){return"X-"===e.substring(0,2)}))}}])}();function fr(e){return"SCTE35-OUT"===e||"SCTE35-IN"===e||"SCTE35-CMD"===e}var cr=function(){return i((function(e,t,r){var i;if(void 0===r&&(r=0),this.attr=void 0,this.tagAnchor=void 0,this.tagOrder=void 0,this._startDate=void 0,this._endDate=void 0,this._dateAtEnd=void 0,this._cue=void 0,this._badValueForSameId=void 0,this.tagAnchor=(null==t?void 0:t.tagAnchor)||null,this.tagOrder=null!=(i=null==t?void 0:t.tagOrder)?i:r,t){var n=t.attr;for(var s in n)if(Object.prototype.hasOwnProperty.call(e,s)&&e[s]!==n[s]){Y.warn('DATERANGE tag attribute: "'+s+'" does not match for tags with ID: "'+e.ID+'"'),this._badValueForSameId=s;break}e=a(new hr({}),n,e)}if(this.attr=e,t?(this._startDate=t._startDate,this._cue=t._cue,this._endDate=t._endDate,this._dateAtEnd=t._dateAtEnd):this._startDate=new Date(e["START-DATE"]),"END-DATE"in this.attr){var o=(null==t?void 0:t.endDate)||new Date(this.attr["END-DATE"]);A(o.getTime())&&(this._endDate=o)}}),[{key:"id",get:function(){return this.attr.ID}},{key:"class",get:function(){return this.attr.CLASS}},{key:"cue",get:function(){var e=this._cue;return void 0===e?this._cue=this.attr.enumeratedStringList(this.attr.CUE?"CUE":"X-CUE",{pre:!1,post:!1,once:!1}):e}},{key:"startTime",get:function(){var e=this.tagAnchor;return null===e||null===e.programDateTime?(Y.warn('Expected tagAnchor Fragment with PDT set for DateRange "'+this.id+'": '+e),NaN):e.start+(this.startDate.getTime()-e.programDateTime)/1e3}},{key:"startDate",get:function(){return this._startDate}},{key:"endDate",get:function(){var e=this._endDate||this._dateAtEnd;if(e)return e;var t=this.duration;return null!==t?this._dateAtEnd=new Date(this._startDate.getTime()+1e3*t):null}},{key:"duration",get:function(){if("DURATION"in this.attr){var e=this.attr.decimalFloatingPoint("DURATION");if(A(e))return e}else if(this._endDate)return(this._endDate.getTime()-this._startDate.getTime())/1e3;return null}},{key:"plannedDuration",get:function(){return"PLANNED-DURATION"in this.attr?this.attr.decimalFloatingPoint("PLANNED-DURATION"):null}},{key:"endOnNext",get:function(){return this.attr.bool("END-ON-NEXT")}},{key:"isInterstitial",get:function(){return"com.apple.hls.interstitial"===this.class}},{key:"isValid",get:function(){return!!this.id&&!this._badValueForSameId&&A(this.startDate.getTime())&&(null===this.duration||this.duration>=0)&&(!this.endOnNext||!!this.class)&&(!this.attr.CUE||!this.cue.pre&&!this.cue.post||this.cue.pre!==this.cue.post)&&(!this.isInterstitial||"X-ASSET-URI"in this.attr||"X-ASSET-LIST"in this.attr)}}])}(),gr=function(){function e(e){this.PTSKnown=!1,this.alignedSliding=!1,this.averagetargetduration=void 0,this.endCC=0,this.endSN=0,this.fragments=void 0,this.fragmentHint=void 0,this.partList=null,this.dateRanges=void 0,this.dateRangeTagCount=0,this.live=!0,this.requestScheduled=-1,this.ageHeader=0,this.advancedDateTime=void 0,this.updated=!0,this.advanced=!0,this.misses=0,this.startCC=0,this.startSN=0,this.startTimeOffset=null,this.targetduration=0,this.totalduration=0,this.type=null,this.url=void 0,this.m3u8="",this.version=null,this.canBlockReload=!1,this.canSkipUntil=0,this.canSkipDateRanges=!1,this.skippedSegments=0,this.recentlyRemovedDateranges=void 0,this.partHoldBack=0,this.holdBack=0,this.partTarget=0,this.preloadHint=void 0,this.renditionReports=void 0,this.tuneInGoal=0,this.deltaUpdateFailed=void 0,this.driftStartTime=0,this.driftEndTime=0,this.driftStart=0,this.driftEnd=0,this.encryptedFragments=void 0,this.playlistParsingError=null,this.variableList=null,this.hasVariableRefs=!1,this.appliedTimelineOffset=void 0,this.fragments=[],this.encryptedFragments=[],this.dateRanges={},this.url=e}return e.prototype.reloaded=function(e){if(!e)return this.advanced=!0,void(this.updated=!0);var t=this.lastPartSn-e.lastPartSn,r=this.lastPartIndex-e.lastPartIndex;this.updated=this.endSN!==e.endSN||!!r||!!t||!this.live,this.advanced=this.endSN>e.endSN||t>0||0===t&&r>0,this.updated||this.advanced?this.misses=Math.floor(.6*e.misses):this.misses=e.misses+1},i(e,[{key:"hasProgramDateTime",get:function(){return!!this.fragments.length&&A(this.fragments[this.fragments.length-1].programDateTime)}},{key:"levelTargetDuration",get:function(){return this.averagetargetduration||this.targetduration||10}},{key:"drift",get:function(){var e=this.driftEndTime-this.driftStartTime;return e>0?1e3*(this.driftEnd-this.driftStart)/e:1}},{key:"edge",get:function(){return this.partEnd||this.fragmentEnd}},{key:"partEnd",get:function(){var e;return null!=(e=this.partList)&&e.length?this.partList[this.partList.length-1].end:this.fragmentEnd}},{key:"fragmentEnd",get:function(){var e;return null!=(e=this.fragments)&&e.length?this.fragments[this.fragments.length-1].end:0}},{key:"fragmentStart",get:function(){var e;return null!=(e=this.fragments)&&e.length?this.fragments[0].start:0}},{key:"age",get:function(){return this.advancedDateTime?Math.max(Date.now()-this.advancedDateTime,0)/1e3:0}},{key:"lastPartIndex",get:function(){var e;return null!=(e=this.partList)&&e.length?this.partList[this.partList.length-1].index:-1}},{key:"maxPartIndex",get:function(){var e=this.partList;if(e){var t=this.lastPartIndex;if(-1!==t){for(var r=e.length;r--;)if(e[r].index>t)return e[r].index;return t}}return 0}},{key:"lastPartSn",get:function(){var e;return null!=(e=this.partList)&&e.length?this.partList[this.partList.length-1].fragment.sn:this.endSN}},{key:"expired",get:function(){if(this.live&&this.age&&this.misses<3){var e=this.partEnd-this.fragmentStart;return this.age>Math.max(e,this.totalduration)+this.levelTargetDuration}return!1}}])}();function vr(e){return"AES-128"===e||"AES-256"===e||"AES-256-CTR"===e}function mr(e){switch(e){case"AES-128":case"AES-256":return Ht;case"AES-256-CTR":return Yt;default:throw new Error("invalid full segment method "+e)}}function pr(e){return Uint8Array.from(atob(e),(function(e){return e.charCodeAt(0)}))}function yr(e){return Uint8Array.from(unescape(encodeURIComponent(e)),(function(e){return e.charCodeAt(0)}))}function Er(e){var t,r,i=e.split(":"),n=null;if("data"===i[0]&&2===i.length){var a=i[1].split(";"),s=a[a.length-1].split(",");if(2===s.length){var o="base64"===s[0],l=s[1];o?(a.splice(-1,1),n=pr(l)):(t=yr(l).subarray(0,16),(r=new Uint8Array(16)).set(t,16-t.length),n=r)}}return n}var Tr="undefined"!=typeof self?self:void 0,Sr={CLEARKEY:"org.w3.clearkey",FAIRPLAY:"com.apple.fps",PLAYREADY:"com.microsoft.playready",WIDEVINE:"com.widevine.alpha"},Ar="org.w3.clearkey",Lr="com.apple.streamingkeydelivery",Rr="com.microsoft.playready",Ir="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed";function kr(e){switch(e){case Lr:return Sr.FAIRPLAY;case Rr:return Sr.PLAYREADY;case Ir:return Sr.WIDEVINE;case Ar:return Sr.CLEARKEY}}var br="1077efecc0b24d02ace33c1e52e2fb4b",Dr="e2719d58a985b3c9781ab030af78d30e",_r="9a04f07998404286ab92e65be0885f95",Pr="edef8ba979d64acea3c827dcd51d21ed";function Cr(e){return e===Pr?Sr.WIDEVINE:e===_r?Sr.PLAYREADY:e===br||e===Dr?Sr.CLEARKEY:void 0}function wr(e){switch(e){case Sr.FAIRPLAY:return Lr;case Sr.PLAYREADY:return Rr;case Sr.WIDEVINE:return Ir;case Sr.CLEARKEY:return Ar}}function Or(e){var t=e.drmSystems,r=e.widevineLicenseUrl,i=t?[Sr.FAIRPLAY,Sr.WIDEVINE,Sr.PLAYREADY,Sr.CLEARKEY].filter((function(e){return!!t[e]})):[];return!i[Sr.WIDEVINE]&&r&&i.push(Sr.WIDEVINE),i}var xr,Mr=null!=Tr&&null!=(xr=Tr.navigator)&&xr.requestMediaKeySystemAccess?self.navigator.requestMediaKeySystemAccess.bind(self.navigator):null;function Fr(e){var t=new Uint16Array(e.buffer,e.byteOffset,e.byteLength/2),r=String.fromCharCode.apply(null,Array.from(t)),i=r.substring(r.indexOf("<"),r.length),n=(new DOMParser).parseFromString(i,"text/xml").getElementsByTagName("KID")[0];if(n){var a=n.childNodes[0]?n.childNodes[0].nodeValue:n.getAttribute("VALUE");if(a){var s=pr(a).subarray(0,16);return function(e){var t=function(e,t,r){var i=e[t];e[t]=e[r],e[r]=i};t(e,0,3),t(e,1,2),t(e,4,5),t(e,6,7)}(s),s}}return null}var Nr={},Ur=function(){function e(e,t,r,i,n){void 0===i&&(i=[1]),void 0===n&&(n=null),this.uri=void 0,this.method=void 0,this.keyFormat=void 0,this.keyFormatVersions=void 0,this.encrypted=void 0,this.isCommonEncryption=void 0,this.iv=null,this.key=null,this.keyId=null,this.pssh=null,this.method=e,this.uri=t,this.keyFormat=r,this.keyFormatVersions=i,this.iv=n,this.encrypted=!!e&&"NONE"!==e,this.isCommonEncryption=this.encrypted&&!vr(e)}e.clearKeyUriToKeyIdMap=function(){Nr={}};var t=e.prototype;return t.isSupported=function(){if(this.method){if(vr(this.method)||"NONE"===this.method)return!0;if("identity"===this.keyFormat)return"SAMPLE-AES"===this.method;switch(this.keyFormat){case Lr:case Ir:case Rr:case Ar:return-1!==["ISO-23001-7","SAMPLE-AES","SAMPLE-AES-CENC","SAMPLE-AES-CTR"].indexOf(this.method)}}return!1},t.getDecryptData=function(t){if(!this.encrypted||!this.uri)return null;if(vr(this.method)&&this.uri&&!this.iv){"number"!=typeof t&&(Y.warn('missing IV for initialization segment with method="'+this.method+'" - compliance issue'),t=0);var r=function(e){for(var t=new Uint8Array(16),r=12;r<16;r++)t[r]=e>>8*(15-r)&255;return t}(t);return new e(this.method,this.uri,"identity",this.keyFormatVersions,r)}var i=Er(this.uri);if(i)switch(this.keyFormat){case Ir:this.pssh=i,i.length>=22&&(this.keyId=i.subarray(i.length-22,i.length-6));break;case Rr:var n=new Uint8Array([154,4,240,121,152,64,66,134,171,146,230,91,224,136,95,149]);this.pssh=be(n,0,i),this.keyId=Fr(i);break;default:var a=i.subarray(0,16);if(16!==a.length){var s=new Uint8Array(16);s.set(a,16-a.length),a=s}this.keyId=a}if(!this.keyId||16!==this.keyId.byteLength){var o=Nr[this.uri];if(!o){var l=Object.keys(Nr).length%Number.MAX_SAFE_INTEGER;o=new Uint8Array(16),new DataView(o.buffer,12,4).setUint32(0,l),Nr[this.uri]=o}this.keyId=o}return this},e}(),Br=/#EXT-X-STREAM-INF:([^\r\n]*)(?:[\r\n](?:#[^\r\n]*)?)*([^\r\n]+)|#EXT-X-(SESSION-DATA|SESSION-KEY|DEFINE|CONTENT-STEERING|START):([^\r\n]*)[\r\n]+/g,Gr=/#EXT-X-MEDIA:(.*)/g,Kr=/^#EXT(?:INF|-X-TARGETDURATION):/m,Vr=new RegExp([/#EXTINF:\s*(\d*(?:\.\d+)?)(?:,(.*)\s+)?/.source,/(?!#) *(\S[^\r\n]*)/.source,/#.*/.source].join("|"),"g"),Hr=new RegExp([/#EXT-X-(PROGRAM-DATE-TIME|BYTERANGE|DATERANGE|DEFINE|KEY|MAP|PART|PART-INF|PLAYLIST-TYPE|PRELOAD-HINT|RENDITION-REPORT|SERVER-CONTROL|SKIP|START):(.+)/.source,/#EXT-X-(BITRATE|DISCONTINUITY-SEQUENCE|MEDIA-SEQUENCE|TARGETDURATION|VERSION): *(\d+)/.source,/#EXT-X-(DISCONTINUITY|ENDLIST|GAP|INDEPENDENT-SEGMENTS)/.source,/(#)([^:]*):(.*)/.source,/(#)(.*)(?:.*)\r?\n?/.source].join("|")),Yr=function(){function e(){}return e.findGroup=function(e,t){for(var r=0;r0&&a.length0&&ti(c,C,l),p=c.startSN=parseInt(w);break;case"SKIP":c.skippedSegments&&ei(c,C,l);var x=new hr(w,c),M=x.decimalInteger("SKIPPED-SEGMENTS");if(A(M)){c.skippedSegments+=M;for(var F=M;F--;)g.push(null);p+=M}var N=x.enumeratedString("RECENTLY-REMOVED-DATERANGES");N&&(c.recentlyRemovedDateranges=(c.recentlyRemovedDateranges||[]).concat(N.split("\t")));break;case"TARGETDURATION":0!==c.targetduration&&ei(c,C,l),c.targetduration=Math.max(parseInt(w),1);break;case"VERSION":null!==c.version&&ei(c,C,l),c.version=parseInt(w);break;case"INDEPENDENT-SEGMENTS":break;case"ENDLIST":c.live||ei(c,C,l),c.live=!1;break;case"#":(w||O)&&R.tagList.push(O?[w,O]:[w]);break;case"DISCONTINUITY":T++,R.tagList.push(["DIS"]);break;case"GAP":R.gap=!0,R.tagList.push([C]);break;case"BITRATE":R.tagList.push([C,w]),S=1e3*parseInt(w),A(S)?R.bitrate=S:S=0;break;case"DATERANGE":var U=new hr(w,c),B=new cr(U,c.dateRanges[U.ID],c.dateRangeTagCount);c.dateRangeTagCount++,B.isValid||c.skippedSegments?c.dateRanges[B.id]=B:Y.warn('Ignoring invalid DATERANGE tag: "'+w+'"'),R.tagList.push(["EXT-X-DATERANGE",w]);break;case"DEFINE":var G=new hr(w,c);"IMPORT"in G?lr(c,G,s):or(c,G,t);break;case"DISCONTINUITY-SEQUENCE":0!==c.startCC?ei(c,C,l):g.length>0&&ti(c,C,l),c.startCC=T=parseInt(w);break;case"KEY":var K=qr(w,t,c);if(K.isSupported()){if("NONE"===K.method){d=void 0;break}d||(d={}),d[K.keyFormat]&&(d=a({},d)),d[K.keyFormat]=K}else Y.warn('[Keys] Ignoring invalid EXT-X-KEY tag: "'+w+'"');break;case"START":c.startTimeOffset=Xr(w);break;case"MAP":var V=new hr(w,c);if(R.duration){var H=new te(i,f);Jr(H,V,r,d),m=H,R.initSegment=m,m.rawProgramDateTime&&!R.rawProgramDateTime&&(R.rawProgramDateTime=m.rawProgramDateTime)}else{var W=R.byteRangeEndOffset;if(W){var j=R.byteRangeStartOffset;b=W-j+"@"+j}else b=null;Jr(R,V,r,d),m=R,k=!0}m.cc=T;break;case"SERVER-CONTROL":h&&ei(c,C,l),h=new hr(w),c.canBlockReload=h.bool("CAN-BLOCK-RELOAD"),c.canSkipUntil=h.optionalFloat("CAN-SKIP-UNTIL",0),c.canSkipDateRanges=c.canSkipUntil>0&&h.bool("CAN-SKIP-DATERANGES"),c.partHoldBack=h.optionalFloat("PART-HOLD-BACK",0),c.holdBack=h.optionalFloat("HOLD-BACK",0);break;case"PART-INF":c.partTarget&&ei(c,C,l);var q=new hr(w);c.partTarget=q.decimalFloatingPoint("PART-TARGET");break;case"PART":var X=c.partList;X||(X=c.partList=[]);var Q=y>0?X[X.length-1]:void 0,z=y++,$=new hr(w,c),J=new re($,R,f,z,Q);X.push(J),R.duration+=J.duration;break;case"PRELOAD-HINT":var Z=new hr(w,c);c.preloadHint=Z;break;case"RENDITION-REPORT":var ee=new hr(w,c);c.renditionReports=c.renditionReports||[],c.renditionReports.push(ee);break;default:Y.warn("line parsed but not handled: "+l)}}}L&&!L.relurl?(g.pop(),E-=L.duration,c.partList&&(c.fragmentHint=L)):c.partList&&($r(R,L,v),R.cc=T,c.fragmentHint=R,d&&Zr(R,d,c)),c.targetduration||(c.playlistParsingError=new Error("#EXT-X-TARGETDURATION is required"));var ie=g.length,ne=g[0],ae=g[ie-1];if((E+=c.skippedSegments*c.targetduration)>0&&ie&&ae){c.averagetargetduration=E/ie;var se=ae.sn;c.endSN="initSegment"!==se?se:0,c.live||(ae.endList=!0),ne&&void 0===c.startCC&&(c.startCC=ne.cc),I>0&&(function(e,t){for(var r=e[t],i=t;i--;){var n=e[i];if(!n)return;n.programDateTime=r.programDateTime-1e3*n.duration,r=n}}(g,I),ne&&v.unshift(ne))}else c.endSN=0,c.startCC=0;return c.fragmentHint&&(E+=c.fragmentHint.duration),c.totalduration=E,v.length&&c.dateRangeTagCount&&ne&&Wr(v,c),c.endCC=T,c},e}();function Wr(e,t){var r=e.length;if(r)for(var i=e[r-1],n=t.live?1/0:t.totalduration,a=Object.keys(t.dateRanges),s=a.length;s--;){var o=t.dateRanges[a[s]],l=o.startDate.getTime();o.tagAnchor=i.ref;for(var u=r;u--;){var d=jr(t,l,e,u,n);if(-1!==d){o.tagAnchor=t.fragments[d].ref;break}}}}function jr(e,t,r,i,n){var a=r[i];if(a){var s,o=a.programDateTime;if((t>=o||0===i)&&t<=o+1e3*(((null==(s=r[i+1])?void 0:s.start)||n)-a.start)){var l=r[i].sn-e.startSN,u=e.fragments;if(u.length>r.length)for(var d=(r[i+1]||u[u.length-1]).sn-e.startSN;d>l;d--){var h=u[d].programDateTime;if(t>=h&&te.sn?(n=r-e.start,i=e):(n=e.start-r,i=t),i.duration!==n&&i.setDuration(n)}else t.sn>e.sn?e.cc===t.cc&&e.minEndPTS?t.setStart(e.start+(e.minEndPTS-e.start)):t.setStart(e.start+e.duration):t.setStart(Math.max(e.start-t.duration,0))}function ii(e,t,r,i,n,a){i-r<=0&&(Y.warn("Fragment should have a positive duration",t),i=r+t.duration,a=n+t.duration);var s=r,o=i,l=t.startPTS,u=t.endPTS;if(A(l)){var d=Math.abs(l-r);A(t.deltaPTS)?t.deltaPTS=Math.max(d,t.deltaPTS):t.deltaPTS=d,s=Math.max(r,l),r=Math.min(r,l),n=Math.min(n,t.startDTS),o=Math.min(i,u),i=Math.max(i,u),a=Math.max(a,t.endDTS)}var h=r-t.start;0!==t.start&&t.setStart(r),t.setDuration(i-t.start),t.startPTS=r,t.maxStartPTS=s,t.startDTS=n,t.endPTS=i,t.minEndPTS=o,t.endDTS=a;var f,c=t.sn;if(!e||ce.endSN)return 0;var g=c-e.startSN,v=e.fragments;for(v[g]=t,f=g;f>0;f--)ri(v[f],v[f-1]);for(f=g;f=0;s--){var o=n[s].initSegment;if(o){i=o;break}}e.fragmentHint&&delete e.fragmentHint.endPTS,function(e,t,r){for(var i=t.skippedSegments,n=Math.max(e.startSN,t.startSN)-t.startSN,a=(e.fragmentHint?1:0)+(i?t.endSN:Math.min(e.endSN,t.endSN))-t.startSN,s=t.startSN-e.startSN,o=t.fragmentHint?t.fragments.concat(t.fragmentHint):t.fragments,l=e.fragmentHint?e.fragments.concat(e.fragmentHint):e.fragments,u=n;u<=a;u++){var d=l[s+u],h=o[u];if(i&&!h&&d&&(h=t.fragments[u]=d),d&&h){if(r(d,h,u,o),d.url&&d.url!==h.url)return void(t.playlistParsingError=ai("media sequence mismatch "+h.sn+":",e,t,0,h));if(d.cc!==h.cc)return void(t.playlistParsingError=ai("discontinuity sequence mismatch ("+d.cc+"!="+h.cc+")",e,t,0,h))}}}(e,t,(function(e,n,a,s){if((!t.startCC||t.skippedSegments)&&n.cc!==e.cc){for(var o=e.cc-n.cc,l=a;l=0,s=0;if(a&&it){var n=1e3*i[i.length-1].duration;ne.startCC)}(t,e)){var r=Math.min(t.endCC,e.endCC),i=ci(t.fragments,r),n=ci(e.fragments,r);i&&n&&(Y.log("Aligning playlist at start of dicontinuity sequence "+r),vi(i.start-n.start,e))}}function pi(e,t){if(e.hasProgramDateTime&&t.hasProgramDateTime){var r=e.fragments,i=t.fragments;if(r.length&&i.length){var n,a,s=Math.min(t.endCC,e.endCC);t.startCCl.end){var c=o>f;(os.lastCurrentTime&&(s.lastCurrentTime=o),!s.loadingParts)){var g=Math.max(l.end,o),v=s.shouldLoadParts(s.getLevelDetails(),g);v&&(s.log("LL-Part loading ON after seeking to "+o.toFixed(2)+" with buffer @"+g.toFixed(2)),s.loadingParts=v)}s.hls.hasEnoughToStart||(s.log("Setting "+(u?"startPosition":"nextLoadPosition")+" to "+o+" for seek without enough to start"),s.nextLoadPosition=o,u&&(s.startPosition=o)),s.tickImmediate()},s.onMediaEnded=function(){s.log("setting startPosition to 0 because media ended"),s.startPosition=s.lastCurrentTime=0},s.playlistType=a,s.hls=t,s.fragmentLoader=new zt(t.config),s.keyLoader=i,s.fragmentTracker=r,s.config=t.config,s.decrypter=new Xt(t.config),s}o(t,e);var r=t.prototype;return r.registerListeners=function(){var e=this.hls;e.on(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(b.ERROR,this.onError,this)},r.unregisterListeners=function(){var e=this.hls;e.off(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(b.ERROR,this.onError,this)},r.doTick=function(){this.onTickEnd()},r.onTickEnd=function(){},r.startLoad=function(e){},r.stopLoad=function(){if(this.state!==Ei.STOPPED){this.fragmentLoader.abort(),this.keyLoader.abort(this.playlistType);var e=this.fragCurrent;null!=e&&e.loader&&(e.abortRequests(),this.fragmentTracker.removeFragment(e)),this.resetTransmuxer(),this.fragCurrent=null,this.fragPrevious=null,this.clearInterval(),this.clearNextTick(),this.state=Ei.STOPPED}},r.pauseBuffering=function(){this.buffering=!1},r.resumeBuffering=function(){this.buffering=!0},r._streamEnded=function(e,t){if(t.live||!this.media)return!1;var r=e.end||0,i=this.config.timelineOffset||0;if(r<=i)return!1;var n=e.buffered;this.config.maxBufferHole&&n&&n.length>1&&(e=ir.bufferedInfo(n,e.start,0));var a=e.nextStart;if(a&&a>i&&a0&&null!=a&&a.key&&a.iv&&vr(a.method)){var s=self.performance.now();return r.decrypter.decrypt(new Uint8Array(n),a.key.buffer,a.iv.buffer,mr(a.method)).catch((function(e){throw t.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.FRAG_DECRYPT_ERROR,fatal:!1,error:e,reason:e.message,frag:i}),e})).then((function(n){var a=self.performance.now();return t.trigger(b.FRAG_DECRYPTED,{frag:i,payload:n,stats:{tstart:s,tdecrypt:a}}),e.payload=n,r.completeInitSegmentLoad(e)}))}return r.completeInitSegmentLoad(e)})).catch((function(t){r.state!==Ei.STOPPED&&r.state!==Ei.ERROR&&(r.warn(t),r.resetFragmentLoading(e))}))},r.completeInitSegmentLoad=function(e){if(!this.levels)throw new Error("init load aborted, missing levels");var t=e.frag.stats;this.state!==Ei.STOPPED&&(this.state=Ei.IDLE),e.frag.data=new Uint8Array(e.payload),t.parsing.start=t.buffering.start=self.performance.now(),t.parsing.end=t.buffering.end=self.performance.now(),this.tick()},r.fragContextChanged=function(e){var t=this.fragCurrent;return!e||!t||e.sn!==t.sn||e.level!==t.level},r.fragBufferedComplete=function(e,t){var r=this.mediaBuffer?this.mediaBuffer:this.media;if(this.log("Buffered "+e.type+" sn: "+e.sn+(t?" part: "+t.index:"")+" of "+this.fragInfo(e,!1,t)+" > buffer:"+(r?yi(ir.getBuffered(r)):"(detached)")+")"),ee(e)){var i;if(e.type!==x){var n=e.elementaryStreams;if(!Object.keys(n).some((function(e){return!!n[e]})))return void(this.state=Ei.IDLE)}var a=null==(i=this.levels)?void 0:i[e.level];null!=a&&a.fragmentError&&(this.log("Resetting level fragment error count of "+a.fragmentError+" on frag buffered"),a.fragmentError=0)}this.state=Ei.IDLE},r._handleFragmentLoadComplete=function(e){var t=this.transmuxer;if(t){var r=e.frag,i=e.part,n=e.partsLoaded,a=!n||0===n.length||n.some((function(e){return!e})),s=new tr(r.level,r.sn,r.stats.chunkCount+1,0,i?i.index:-1,!a);t.flush(s)}},r._handleFragmentLoadProgress=function(e){},r._doFragLoad=function(e,t,r,i){var n,a=this;void 0===r&&(r=null),this.fragCurrent=e;var s=null==t?void 0:t.details;if(!this.levels||!s)throw new Error("frag load aborted, missing level"+(s?"":" detail")+"s");var o=null;!e.encrypted||null!=(n=e.decryptdata)&&n.key?e.encrypted||(o=this.keyLoader.loadClear(e,s.encryptedFragments))&&this.log("[eme] blocking frag load until media-keys acquired"):(this.log("Loading key for "+e.sn+" of ["+s.startSN+"-"+s.endSN+"], "+this.playlistLabel()+" "+e.level),this.state=Ei.KEY_LOADING,this.fragCurrent=e,o=this.keyLoader.load(e).then((function(e){if(!a.fragContextChanged(e.frag))return a.hls.trigger(b.KEY_LOADED,e),a.state===Ei.KEY_LOADING&&(a.state=Ei.IDLE),e})),this.hls.trigger(b.KEY_LOADING,{frag:e}),null===this.fragCurrent&&(o=Promise.reject(new Error("frag load aborted, context changed in KEY_LOADING"))));var l=this.fragPrevious;if(ee(e)&&(!l||e.sn!==l.sn)){var u=this.shouldLoadParts(t.details,e.end);u!==this.loadingParts&&(this.log("LL-Part loading "+(u?"ON":"OFF")+" loading sn "+(null==l?void 0:l.sn)+"->"+e.sn),this.loadingParts=u)}if(r=Math.max(e.start,r||0),this.loadingParts&&ee(e)){var d=s.partList;if(d&&i){r>e.end&&s.fragmentHint&&(e=s.fragmentHint);var h=this.getNextPart(d,e,r);if(h>-1){var f,c=d[h];return e=this.fragCurrent=c.fragment,this.log("Loading "+e.type+" sn: "+e.sn+" part: "+c.index+" ("+h+"/"+(d.length-1)+") of "+this.fragInfo(e,!1,c)+") cc: "+e.cc+" ["+s.startSN+"-"+s.endSN+"], target: "+parseFloat(r.toFixed(3))),this.nextLoadPosition=c.start+c.duration,this.state=Ei.FRAG_LOADING,f=o?o.then((function(r){return!r||a.fragContextChanged(r.frag)?null:a.doFragPartsLoad(e,c,t,i)})).catch((function(e){return a.handleFragLoadError(e)})):this.doFragPartsLoad(e,c,t,i).catch((function(e){return a.handleFragLoadError(e)})),this.hls.trigger(b.FRAG_LOADING,{frag:e,part:c,targetBufferTime:r}),null===this.fragCurrent?Promise.reject(new Error("frag load aborted, context changed in FRAG_LOADING parts")):f}if(!e.url||this.loadedEndOfParts(d,r))return Promise.resolve(null)}}if(ee(e)&&this.loadingParts)this.log("LL-Part loading OFF after next part miss @"+r.toFixed(2)),this.loadingParts=!1;else if(!e.url)return Promise.resolve(null);this.log("Loading "+e.type+" sn: "+e.sn+" of "+this.fragInfo(e,!1)+") cc: "+e.cc+" "+(s?"["+s.startSN+"-"+s.endSN+"]":"")+", target: "+parseFloat(r.toFixed(3))),A(e.sn)&&!this.bitrateTest&&(this.nextLoadPosition=e.start+e.duration),this.state=Ei.FRAG_LOADING;var g,v=this.config.progressive;return g=v&&o?o.then((function(t){return!t||a.fragContextChanged(null==t?void 0:t.frag)?null:a.fragmentLoader.load(e,i)})).catch((function(e){return a.handleFragLoadError(e)})):Promise.all([this.fragmentLoader.load(e,v?i:void 0),o]).then((function(e){var t=e[0];return!v&&t&&i&&i(t),t})).catch((function(e){return a.handleFragLoadError(e)})),this.hls.trigger(b.FRAG_LOADING,{frag:e,targetBufferTime:r}),null===this.fragCurrent?Promise.reject(new Error("frag load aborted, context changed in FRAG_LOADING")):g},r.doFragPartsLoad=function(e,t,r,i){var n=this;return new Promise((function(a,s){var o,l=[],u=null==(o=r.details)?void 0:o.partList,d=function(t){n.fragmentLoader.loadPart(e,t,i).then((function(i){l[t.index]=i;var s=i.part;n.hls.trigger(b.FRAG_LOADED,i);var o=di(r.details,e.sn,t.index+1)||hi(u,e.sn,t.index+1);if(!o)return a({frag:e,part:s,partsLoaded:l});d(o)})).catch(s)};d(t)}))},r.handleFragLoadError=function(e){if("data"in e){var t=e.data;e.data&&t.details===k.INTERNAL_ABORTED?this.handleFragLoadAborted(t.frag,t.part):this.hls.trigger(b.ERROR,t)}else this.hls.trigger(b.ERROR,{type:I.OTHER_ERROR,details:k.INTERNAL_EXCEPTION,err:e,error:e,fatal:!0});return null},r._handleTransmuxerFlush=function(e){var t=this.getCurrentContext(e);if(t&&this.state===Ei.PARSING){var r=t.frag,i=t.part,n=t.level,a=self.performance.now();r.stats.parsing.end=a,i&&(i.stats.parsing.end=a);var s=this.getLevelDetails(),o=s&&r.sn>s.endSN||this.shouldLoadParts(s,r.end);o!==this.loadingParts&&(this.log("LL-Part loading "+(o?"ON":"OFF")+" after parsing segment ending @"+r.end.toFixed(2)),this.loadingParts=o),this.updateLevelTiming(r,i,n,e.partial)}else this.fragCurrent||this.state===Ei.STOPPED||this.state===Ei.ERROR||(this.state=Ei.IDLE)},r.shouldLoadParts=function(e,t){if(this.config.lowLatencyMode){if(!e)return this.loadingParts;if(null!=e&&e.partList){var r,i,n=e.partList[0];if(t>=n.end+((null==(r=e.fragmentHint)?void 0:r.duration)||0)&&(this.hls.hasEnoughToStart?(null==(i=this.media)?void 0:i.currentTime)||this.lastCurrentTime:this.getLoadPosition())>n.start-n.fragment.duration)return!0}}return!1},r.getCurrentContext=function(e){var t=this.levels,r=this.fragCurrent,i=e.level,n=e.sn,a=e.part;if(null==t||!t[i])return this.warn("Levels object was unset while buffering fragment "+n+" of "+this.playlistLabel()+" "+i+". The current chunk will not be buffered."),null;var s=t[i],o=s.details,l=a>-1?di(o,n,a):null,u=l?l.fragment:ui(o,n,r);return u?(r&&r!==u&&(u.stats=r.stats),{frag:u,part:l,level:s}):null},r.bufferFragmentData=function(e,t,r,i,n){var a;if(e&&this.state===Ei.PARSING){var s=e.data1,o=e.data2,l=s;if(s&&o&&(l=Se(s,o)),null!=(a=l)&&a.length){var u=this.initPTS[t.cc],d=u?-u.baseTime/u.timescale:void 0,h={type:e.type,frag:t,part:r,chunkMeta:i,offset:d,parent:t.type,data:l};if(this.hls.trigger(b.BUFFER_APPENDING,h),e.dropped&&e.independent&&!r){if(n)return;this.flushBufferGap(t)}}}},r.flushBufferGap=function(e){var t=this.media;if(t)if(ir.isBuffered(t,t.currentTime)){var r=t.currentTime,i=ir.bufferInfo(t,r,0),n=e.duration,a=Math.min(2*this.config.maxFragLookUpTolerance,.25*n),s=Math.max(Math.min(e.start-a,i.end-a),r+a);e.start-s>a&&this.flushMainBuffer(s,e.start)}else this.flushMainBuffer(0,e.start)},r.getFwdBufferInfo=function(e,t){var r,i=this.getLoadPosition();if(!A(i))return null;var n=this.lastCurrentTime>i||null!=(r=this.media)&&r.paused?0:this.config.maxBufferHole;return this.getFwdBufferInfoAtPos(e,i,t,n)},r.getFwdBufferInfoAtPos=function(e,t,r,i){var n=ir.bufferInfo(e,t,i);if(0===n.len&&void 0!==n.nextStart){var a=this.fragmentTracker.getBufferedFrag(t,r);if(a&&(n.nextStart<=a.end||a.gap)){var s=Math.max(Math.min(n.nextStart,a.end)-t,i);return ir.bufferInfo(e,t,s)}}return n},r.getMaxBufferLength=function(e){var t,r=this.config;return t=e?Math.max(8*r.maxBufferSize/e,r.maxBufferLength):r.maxBufferLength,Math.min(t,r.maxMaxBufferLength)},r.reduceMaxBufferLength=function(e,t){var r=this.config,i=Math.max(Math.min(e-t,r.maxBufferLength),t),n=Math.max(e-3*t,r.maxMaxBufferLength/2,i);return n>=i&&(r.maxMaxBufferLength=n,this.warn("Reduce max buffer length to "+n+"s"),!0)},r.getAppendedFrag=function(e,t){var r;void 0===t&&(t=w);var i=null==(r=this.fragmentTracker)?void 0:r.getAppendedFrag(e,t);return i&&"fragment"in i?i.fragment:i},r.getNextFragment=function(e,t){var r=t.fragments,i=r.length;if(!i)return null;var n=this.config,a=r[0].start,s=n.lowLatencyMode&&!!t.partList,o=null;if(t.live){var l=n.initialLiveManifestSize;if(i=a?d:h)||o.start:e;this.log("Setting startPosition to "+f+" to match start frag at live edge. mainStart: "+d+" liveSyncPosition: "+h+" frag.start: "+(null==(u=o)?void 0:u.start)),this.startPosition=this.nextLoadPosition=f}}else e<=a&&(o=r[0]);if(!o){var c=this.loadingParts?t.partEnd:t.fragmentEnd;o=this.getFragmentAtPosition(e,c,t)}var g=this.filterReplacedPrimary(o,t);if(!g&&o){var v=o.sn-t.startSN;g=this.filterReplacedPrimary(r[v+1]||null,t)}return this.mapToInitFragWhenRequired(g)},r.isLoopLoading=function(e,t){var r=this.fragmentTracker.getState(e);return(r===Ut||r===Nt&&!!e.gap)&&this.nextLoadPosition>t},r.getNextFragmentLoopLoading=function(e,t,r,i,n){var a=null;if(e.gap&&(a=this.getNextFragment(this.nextLoadPosition,t))&&!a.gap&&r.nextStart){var s=this.getFwdBufferInfoAtPos(this.mediaBuffer?this.mediaBuffer:this.media,r.nextStart,i,0);if(null!==s&&r.len+s.len>=n){var o=a.sn;return this.loopSn!==o&&(this.log('buffer full after gaps in "'+i+'" playlist starting at sn: '+o),this.loopSn=o),null}}return this.loopSn=void 0,a},r.filterReplacedPrimary=function(e,t){if(!e)return e;if(Si(this.hls.config)&&e.type!==x){var r=this.hls.interstitialsManager,i=null==r?void 0:r.bufferingItem;if(i){var n=i.event;if(n){if(n.appendInPlace||Math.abs(e.start-i.start)>1||0===i.start)return null}else{if(e.end<=i.start&&!1===(null==t?void 0:t.live))return null;if(e.start>i.end&&i.nextEvent&&(i.nextEvent.appendInPlace||e.start-i.end>1))return null}}var a=null==r?void 0:r.playerQueue;if(a)for(var s=a.length;s--;){var o=a[s].interstitial;if(o.appendInPlace&&e.start>=o.startTime&&e.end<=o.resumeTime)return null}}return e},r.mapToInitFragWhenRequired=function(e){return null==e||!e.initSegment||null!=e&&e.initSegment.data||this.bitrateTest?e:e.initSegment},r.getNextPart=function(e,t,r){for(var i=-1,n=!1,a=!0,s=0,o=e.length;s-1&&rr.start&&r.loaded},r.getInitialLiveFragment=function(e){var t=e.fragments,r=this.fragPrevious,i=null;if(r){if(e.hasProgramDateTime&&(this.log("Live playlist, switching playlist, load frag with same PDT: "+r.programDateTime),i=function(e,t,r){if(null===t||!Array.isArray(e)||!e.length||!A(t))return null;if(t<(e[0].programDateTime||0))return null;if(t>=(e[e.length-1].endProgramDateTime||0))return null;for(var i=0;i=e.startSN&&n<=e.endSN){var a=t[n-e.startSN];r.cc===a.cc&&(i=a,this.log("Live playlist, switching playlist, load frag with next SN: "+i.sn))}i||(i=Tt(e,r.cc,r.end))&&this.log("Live playlist, switching playlist, load frag with same CC: "+i.sn)}}else{var s=this.hls.liveSyncPosition;null!==s&&(i=this.getFragmentAtPosition(s,this.bitrateTest?e.fragmentEnd:e.edge,e))}return i},r.getFragmentAtPosition=function(e,t,r){var i,n,a=this.config,s=this.fragPrevious,o=r.fragments,l=r.endSN,u=r.fragmentHint,d=a.maxFragLookUpTolerance,h=r.partList,f=!!(this.loadingParts&&null!=h&&h.length&&u);if(f&&u&&!this.bitrateTest&&h[h.length-1].fragment.sn===u.sn&&(o=o.concat(u),l=u.sn),i=et-d||null!=(n=this.media)&&n.paused||!this.startFragRequested?0:d):o[o.length-1]){var c=i.sn-r.startSN,g=this.fragmentTracker.getState(i);if((g===Ut||g===Nt&&i.gap)&&(s=i),s&&i.sn===s.sn&&(!f||h[0].fragment.sn>i.sn||!r.live&&!f)&&s&&i.level===s.level){var v=o[c+1];i=i.sn"+e.startSN+" fragments: "+i),o}return n},r.waitForCdnTuneIn=function(e){return e.live&&e.canBlockReload&&e.partTarget&&e.tuneInGoal>Math.max(e.partHoldBack,3*e.partTarget)},r.setStartPosition=function(e,t){var r=this.startPosition;r=0&&(r=this.nextLoadPosition),r},r.handleFragLoadAborted=function(e,t){this.transmuxer&&e.type===this.playlistType&&ee(e)&&e.stats.aborted&&(this.log("Fragment "+e.sn+(t?" part "+t.index:"")+" of "+this.playlistLabel()+" "+e.level+" was aborted"),this.resetFragmentLoading(e))},r.resetFragmentLoading=function(e){this.fragCurrent&&(this.fragContextChanged(e)||this.state===Ei.FRAG_LOADING_WAITING_RETRY)||(this.state=Ei.IDLE)},r.onFragmentOrKeyLoadError=function(e,t){if(t.chunkMeta&&!t.frag){var r=this.getCurrentContext(t.chunkMeta);r&&(t.frag=r.frag)}var i=t.frag;if(i&&i.type===e&&this.levels)if(this.fragContextChanged(i)){var n;this.warn("Frag load error must match current frag to retry "+i.url+" > "+(null==(n=this.fragCurrent)?void 0:n.url))}else{var a=t.details===k.FRAG_GAP;a&&this.fragmentTracker.fragBuffered(i,!0);var s=t.errorAction,o=s||{},l=o.action,u=o.flags,d=o.retryCount,h=void 0===d?0:d,f=o.retryConfig,c=!!s&&!!f,g=c&&l===_t,v=c&&!s.resolved&&u===Ct;if(!g&&v&&ee(i)&&!i.endList)this.resetFragmentErrors(e),this.treatAsGap(i),s.resolved=!0;else if((g||v)&&h.5;n&&this.reduceMaxBufferLength(i.len,(null==t?void 0:t.duration)||10);var a=!n;return a&&this.warn("Buffer full error while media.currentTime is not buffered, flush "+r+" buffer"),t&&(this.fragmentTracker.removeFragment(t),this.nextLoadPosition=t.start),this.resetLoadingState(),a}return!1},r.resetFragmentErrors=function(e){e===O&&(this.fragCurrent=null),this.hls.hasEnoughToStart||(this.startFragRequested=!1),this.state!==Ei.STOPPED&&(this.state=Ei.IDLE)},r.afterBufferFlushed=function(e,t,r){if(e){var i=ir.getBuffered(e);this.fragmentTracker.detectEvictedFragments(t,i,r),this.state===Ei.ENDED&&this.resetLoadingState()}},r.resetLoadingState=function(){this.log("Reset loading state"),this.fragCurrent=null,this.fragPrevious=null,this.state!==Ei.STOPPED&&(this.state=Ei.IDLE)},r.resetStartWhenNotLoaded=function(e){if(!this.hls.hasEnoughToStart){this.startFragRequested=!1;var t=e?e.details:null;null!=t&&t.live?(this.log("resetting startPosition for live start"),this.startPosition=-1,this.setStartPosition(t,t.fragmentStart),this.resetLoadingState()):this.nextLoadPosition=this.startPosition}},r.resetWhenMissingContext=function(e){this.warn("The loading context changed while buffering fragment "+e.sn+" of "+this.playlistLabel()+" "+e.level+". This chunk will not be buffered."),this.removeUnbufferedFrags(),this.resetStartWhenNotLoaded(this.levelLastLoaded),this.resetLoadingState()},r.removeUnbufferedFrags=function(e){void 0===e&&(e=0),this.fragmentTracker.removeFragmentsInRange(e,1/0,this.playlistType,!1,!0)},r.updateLevelTiming=function(e,t,r,i){var n=this,a=r.details;if(a){var s;if(!Object.keys(e.elementaryStreams).reduce((function(t,s){var o=e.elementaryStreams[s];if(o){var l=o.endPTS-o.startPTS;if(l<=0)return n.warn("Could not parse fragment "+e.sn+" "+s+" duration reliably ("+l+")"),t||!1;var u=i?0:ii(a,e,o.startPTS,o.endPTS,o.startDTS,o.endDTS);return n.hls.trigger(b.LEVEL_PTS_UPDATED,{details:a,level:r,drift:u,type:s,frag:e,start:o.startPTS,end:o.endPTS}),!0}return t}),!1)&&(0===r.fragmentError&&this.treatAsGap(e,r),null===(null==(s=this.transmuxer)?void 0:s.error))){var o=new Error("Found no media in fragment "+e.sn+" of "+this.playlistLabel()+" "+e.level+" resetting transmuxer to fallback to playlist timing");if(this.warn(o.message),this.hls.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.FRAG_PARSING_ERROR,fatal:!1,error:o,frag:e,reason:"Found no media in msn "+e.sn+" of "+this.playlistLabel()+' "'+r.url+'"'}),!this.hls)return;this.resetTransmuxer()}this.state=Ei.PARSED,this.log("Parsed "+e.type+" sn: "+e.sn+(t?" part: "+t.index:"")+" of "+this.fragInfo(e,!1,t)+")"),this.hls.trigger(b.FRAG_PARSED,{frag:e,part:t})}else this.warn("level.details undefined")},r.playlistLabel=function(){return this.playlistType===w?"level":"track"},r.fragInfo=function(e,t,r){var i,n;return void 0===t&&(t=!0),this.playlistLabel()+" "+e.level+" ("+(r?"part":"frag")+":["+(null!=(i=t&&!r?e.startPTS:(r||e).start)?i:NaN).toFixed(3)+"-"+(null!=(n=t&&!r?e.endPTS:(r||e).end)?n:NaN).toFixed(3)+"]"+(r&&"main"===e.type?"INDEPENDENT="+(r.independent?"YES":"NO"):"")},r.treatAsGap=function(e,t){t&&t.fragmentError++,e.gap=!0,this.fragmentTracker.removeFragment(e),this.fragmentTracker.fragBuffered(e,!0)},r.resetTransmuxer=function(){var e;null==(e=this.transmuxer)||e.reset()},r.recoverWorkerError=function(e){"demuxerWorker"===e.event&&(this.fragmentTracker.removeAllFragments(),this.transmuxer&&(this.transmuxer.destroy(),this.transmuxer=null),this.resetStartWhenNotLoaded(this.levelLastLoaded),this.resetLoadingState())},i(t,[{key:"startPositionValue",get:function(){var e=this.nextLoadPosition,t=this.startPosition;return-1===t&&e?e:t}},{key:"bufferingEnabled",get:function(){return this.buffering}},{key:"inFlightFrag",get:function(){return{frag:this.fragCurrent,state:this.state}}},{key:"timelineOffset",get:function(){var e,t=this.config.timelineOffset;return t?(null==(e=this.getLevelDetails())?void 0:e.appliedTimelineOffset)||t:0}},{key:"primaryPrefetch",get:function(){var e,t;return!(!Si(this.hls.config)||!(null==(e=this.hls.interstitialsManager)||null==(t=e.playingItem)?void 0:t.event))}},{key:"state",get:function(){return this._state},set:function(e){var t=this._state;t!==e&&(this._state=e,this.log(t+"->"+e))}}])}(er);function Si(e){return!!e.interstitialsController&&!1!==e.enableInterstitialPlayback}var Ai=function(){function e(){this.chunks=[],this.dataLength=0}var t=e.prototype;return t.push=function(e){this.chunks.push(e),this.dataLength+=e.length},t.flush=function(){var e,t=this.chunks,r=this.dataLength;return t.length?(e=1===t.length?t[0]:function(e,t){for(var r=new Uint8Array(t),i=0,n=0;n0)return e.subarray(r,r+i)}function bi(e,t){return 255===e[t]&&240==(246&e[t+1])}function Di(e,t){return 1&e[t+1]?7:9}function _i(e,t){return(3&e[t+3])<<11|e[t+4]<<3|(224&e[t+5])>>>5}function Pi(e,t){return t+1=e.length)return!1;var i=_i(e,t);if(i<=r)return!1;var n=t+i;return n===e.length||Pi(e,n)}return!1}function wi(e,t,r,i,n){if(!e.samplerate){var s=function(e,t,r,i){var n=t[r+2],a=n>>2&15;if(!(a>12)){var s=1+(n>>6&3),o=t[r+3]>>6&3|(1&n)<<2,l="mp4a.40."+s,u=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350][a],d=a;5!==s&&29!==s||(d-=3);var h=[s<<3|(14&d)>>1,(1&d)<<7|o<<3];return Y.log("manifest codec:"+i+", parsed codec:"+l+", channels:"+o+", rate:"+u+" (ADTS object type:"+s+" sampling index:"+a+")"),{config:h,samplerate:u,channelCount:o,codec:l,parsedCodec:l,manifestCodec:i}}var f=new Error("invalid ADTS sampling index:"+a);e.emit(b.ERROR,b.ERROR,{type:I.MEDIA_ERROR,details:k.FRAG_PARSING_ERROR,fatal:!0,error:f,reason:f.message})}(t,r,i,n);if(!s)return;a(e,s)}}function Oi(e){return 9216e4/e}function xi(e,t,r,i,n){var a,s=i+n*Oi(e.samplerate),o=function(e,t){var r=Di(e,t);if(t+r<=e.length){var i=_i(e,t)-r;if(i>0)return{headerLength:r,frameLength:i}}}(t,r);if(o){var l=o.frameLength,u=o.headerLength,d=u+l,h=Math.max(0,r+d-t.length);h?(a=new Uint8Array(d-u)).set(t.subarray(r+u,t.length),0):a=t.subarray(r+u,r+d);var f={unit:a,pts:s};return h||e.samples.push(f),{sample:f,length:d,missing:h}}var c=t.length-r;return(a=new Uint8Array(c)).set(t.subarray(r,t.length),0),{sample:{unit:a,pts:s},length:c,missing:-1}}function Mi(e,t){return Ri(e,t)&&Ii(e,t+6)+10<=e.length-t}function Fi(e,t,r){return void 0===t&&(t=0),void 0===r&&(r=1/0),function(e,t,r,i){var n=function(e){return e instanceof ArrayBuffer?e:e.buffer}(e),a=1;"BYTES_PER_ELEMENT"in i&&(a=i.BYTES_PER_ELEMENT);var s,o=(s=e)&&s.buffer instanceof ArrayBuffer&&void 0!==s.byteLength&&void 0!==s.byteOffset?e.byteOffset:0,l=(o+e.byteLength)/a,u=(o+t)/a,d=Math.floor(Math.max(0,Math.min(u,l))),h=Math.floor(Math.min(d+Math.max(r,0),l));return new i(n,d,h-d)}(e,t,r,Uint8Array)}function Ni(e){var t={key:e.type,description:"",data:"",mimeType:null,pictureType:null};if(!(e.size<2))if(3===e.data[0]){var r=e.data.subarray(1).indexOf(0);if(-1!==r){var i=q(Fi(e.data,1,r)),n=e.data[2+r],a=e.data.subarray(3+r).indexOf(0);if(-1!==a){var s,o=q(Fi(e.data,3+r,a));return s="--\x3e"===i?q(Fi(e.data,4+r+a)):function(e){return e instanceof ArrayBuffer?e:0==e.byteOffset&&e.byteLength==e.buffer.byteLength?e.buffer:new Uint8Array(e).buffer}(e.data.subarray(4+r+a)),t.mimeType=i,t.pictureType=n,t.description=o,t.data=s,t}}}else console.log("Ignore frame with unrecognized character encoding")}function Ui(e){return"PRIV"===e.type?function(e){if(!(e.size<2)){var t=q(e.data,!0),r=new Uint8Array(e.data.subarray(t.length+1));return{key:e.type,info:t,data:r.buffer}}}(e):"W"===e.type[0]?function(e){if("WXXX"===e.type){if(e.size<2)return;var t=1,r=q(e.data.subarray(t),!0);t+=r.length+1;var i=q(e.data.subarray(t));return{key:e.type,info:r,data:i}}var n=q(e.data);return{key:e.type,info:"",data:n}}(e):"APIC"===e.type?Ni(e):function(e){if(!(e.size<2)){if("TXXX"===e.type){var t=1,r=q(e.data.subarray(t),!0);t+=r.length+1;var i=q(e.data.subarray(t));return{key:e.type,info:r,data:i}}var n=q(e.data.subarray(1));return{key:e.type,info:"",data:n}}}(e)}function Bi(e){var t=String.fromCharCode(e[0],e[1],e[2],e[3]),r=Ii(e,4);return{type:t,size:r,data:e.subarray(10,10+r)}}var Gi=10,Ki=10;function Vi(e){for(var t=0,r=[];Ri(e,t);){var i=Ii(e,t+6);e[t+5]>>6&1&&(t+=Gi);for(var n=(t+=Gi)+i;t+Ki0&&s.samples.push({pts:this.lastPTS,dts:this.lastPTS,data:i,type:ji.audioId3,duration:Number.POSITIVE_INFINITY});nt.length)){var a=rn(t,r);if(a&&r+a.frameLength<=t.length){var s=i+n*(9e4*a.samplesPerFrame/a.sampleRate),o={unit:t.subarray(r,r+a.frameLength),pts:s,dts:s};return e.config=[],e.channelCount=a.channelCount,e.samplerate=a.sampleRate,e.samples.push(o),{sample:o,length:a.frameLength,missing:0}}}}function rn(e,t){var r=e[t+1]>>3&3,i=e[t+1]>>1&3,n=e[t+2]>>4&15,a=e[t+2]>>2&3;if(1!==r&&0!==n&&15!==n&&3!==a){var s=e[t+2]>>1&1,o=e[t+3]>>6,l=1e3*$i[14*(3===r?3-i:3===i?3:4)+n-1],u=Ji[3*(3===r?0:2===r?1:2)+a],d=3===o?1:2,h=Zi[r][i],f=en[i],c=8*h*f,g=Math.floor(h*l/u+s)*f;if(null===zi){var v=(navigator.userAgent||"").match(/Chrome\/(\d+)/i);zi=v?parseInt(v[1]):0}return!!zi&&zi<=87&&2===i&&l>=224e3&&0===o&&(e[t+3]=128|e[t+3]),{sampleRate:u,channelCount:d,frameLength:g,samplesPerFrame:c}}}function nn(e,t){return 255===e[t]&&224==(224&e[t+1])&&0!=(6&e[t+1])}function an(e,t){return t+10;){s[0]=e[t];var o=Math.min(i,8),l=8-o;a[0]=4278190080>>>24+l<>l,r=r?r<t.length)return-1;if(11!==t[r]||119!==t[r+1])return-1;var a=t[r+4]>>6;if(a>=3)return-1;var s=[48e3,44100,32e3][a],o=63&t[r+4],l=2*[64,69,96,64,70,96,80,87,120,80,88,120,96,104,144,96,105,144,112,121,168,112,122,168,128,139,192,128,140,192,160,174,240,160,175,240,192,208,288,192,209,288,224,243,336,224,244,336,256,278,384,256,279,384,320,348,480,320,349,480,384,417,576,384,418,576,448,487,672,448,488,672,512,557,768,512,558,768,640,696,960,640,697,960,768,835,1152,768,836,1152,896,975,1344,896,976,1344,1024,1114,1536,1024,1115,1536,1152,1253,1728,1152,1254,1728,1280,1393,1920,1280,1394,1920][3*o+a];if(r+l>t.length)return-1;var u=t[r+6]>>5,d=0;2===u?d+=2:(1&u&&1!==u&&(d+=2),4&u&&(d+=2));var h=(t[r+6]<<8|t[r+7])>>12-d&1,f=[2,1,2,3,3,4,4,5][u]+h,c=t[r+5]>>3,g=7&t[r+5],v=new Uint8Array([a<<6|c<<1|g>>2,(3&g)<<6|u<<3|h<<2|o>>4,o<<4&224]),m=i+n*(1536/s*9e4),p=t.subarray(r,r+l);return e.config=v,e.channelCount=f,e.samplerate=s,e.samples.push({unit:p,pts:m}),l}var hn=function(e){function t(){return e.apply(this,arguments)||this}o(t,e);var r=t.prototype;return r.resetInitSegment=function(t,r,i,n){e.prototype.resetInitSegment.call(this,t,r,i,n),this._audioTrack={container:"audio/mpeg",type:"audio",id:2,pid:-1,sequenceNumber:0,segmentCodec:"mp3",samples:[],manifestCodec:r,duration:n,inputTimeScale:9e4,dropped:0}},t.probe=function(e){if(!e)return!1;var t=ki(e,0),r=(null==t?void 0:t.length)||0;if(t&&11===e[r]&&119===e[r+1]&&void 0!==Wi(t)&&ln(e,r)<=16)return!1;for(var i=e.length;r8&&109===e[r+4]&&111===e[r+5]&&111===e[r+6]&&102===e[r+7])return!0;r=i>1?r+i:t}return!1}(e)},t.demux=function(e,t){this.timeOffset=t;var r=e,i=this.videoTrack,n=this.txtTrack;if(this.config.progressive){this.remainderData&&(r=Se(this.remainderData,e));var a=function(e){var t={valid:null,remainder:null},r=fe(e,["moof"]);if(r.length<2)return t.remainder=e,t;var i=r[r.length-1];return t.valid=e.slice(0,i.byteOffset-8),t.remainder=e.slice(i.byteOffset-8),t}(r);this.remainderData=a.remainder,i.samples=a.valid||new Uint8Array}else i.samples=r;var s=this.extractID3Track(i,t);return n.samples=Ae(t,i),{videoTrack:i,audioTrack:this.audioTrack,id3Track:s,textTrack:this.txtTrack}},t.flush=function(){var e=this.timeOffset,t=this.videoTrack,r=this.txtTrack;t.samples=this.remainderData||new Uint8Array,this.remainderData=null;var i=this.extractID3Track(t,this.timeOffset);return r.samples=Ae(e,t),{videoTrack:t,audioTrack:qi(),id3Track:i,textTrack:qi()}},t.extractID3Track=function(e,t){var r=this,i=this.id3Track;if(e.samples.length){var n=fe(e.samples,["emsg"]);n&&n.forEach((function(e){var n=function(e){var t=e[0],r="",i="",n=0,a=0,s=0,o=0,l=0,u=0;if(0===t){for(;"\0"!==oe(e.subarray(u,u+1));)r+=oe(e.subarray(u,u+1)),u+=1;for(r+=oe(e.subarray(u,u+1)),u+=1;"\0"!==oe(e.subarray(u,u+1));)i+=oe(e.subarray(u,u+1)),u+=1;i+=oe(e.subarray(u,u+1)),u+=1,n=ue(e,12),a=ue(e,16),o=ue(e,20),l=ue(e,24),u=28}else if(1===t){n=ue(e,u+=4);var d=ue(e,u+=4),h=ue(e,u+=4);for(u+=4,s=Math.pow(2,32)*d+h,L(s)||(s=Number.MAX_SAFE_INTEGER,Y.warn("Presentation time exceeds safe integer limit and wrapped to max safe integer in parsing emsg box")),o=ue(e,u),l=ue(e,u+=4),u+=4;"\0"!==oe(e.subarray(u,u+1));)r+=oe(e.subarray(u,u+1)),u+=1;for(r+=oe(e.subarray(u,u+1)),u+=1;"\0"!==oe(e.subarray(u,u+1));)i+=oe(e.subarray(u,u+1)),u+=1;i+=oe(e.subarray(u,u+1)),u+=1}return{schemeIdUri:r,value:i,timeScale:n,presentationTime:s,presentationTimeDelta:a,eventDuration:o,id:l,payload:e.subarray(u,e.byteLength)}}(e);if(fn.test(n.schemeIdUri)){var a=gn(n,t),s=4294967295===n.eventDuration?Number.POSITIVE_INFINITY:n.eventDuration/n.timeScale;s<=.001&&(s=Number.POSITIVE_INFINITY);var o=n.payload;i.samples.push({data:o,len:o.byteLength,dts:a,pts:a,type:ji.emsg,duration:s})}else if(r.config.enableEmsgKLVMetadata&&n.schemeIdUri.startsWith("urn:misb:KLV:bin:1910.1")){var l=gn(n,t);i.samples.push({data:n.payload,len:n.payload.byteLength,dts:l,pts:l,type:ji.misbklv,duration:Number.POSITIVE_INFINITY})}}))}return i},t.demuxSampleAes=function(e,t,r){return Promise.reject(new Error("The MP4 demuxer does not support SAMPLE-AES decryption"))},t.destroy=function(){this.config=null,this.remainderData=null,this.videoTrack=this.audioTrack=this.id3Track=this.txtTrack=void 0},e}();function gn(e,t){return A(e.presentationTime)?e.presentationTime/e.timeScale:t+e.presentationTimeDelta/e.timeScale}var vn=function(){function e(e,t,r){this.keyData=void 0,this.decrypter=void 0,this.keyData=r,this.decrypter=new Xt(t,{removePKCS7Padding:!1})}var t=e.prototype;return t.decryptBuffer=function(e){return this.decrypter.decrypt(e,this.keyData.key.buffer,this.keyData.iv.buffer,Ht)},t.decryptAacSample=function(e,t,r){var i=this,n=e[t].unit;if(!(n.length<=16)){var a=n.subarray(16,n.length-n.length%16),s=a.buffer.slice(a.byteOffset,a.byteOffset+a.length);this.decryptBuffer(s).then((function(a){var s=new Uint8Array(a);n.set(s,16),i.decrypter.isSync()||i.decryptAacSamples(e,t+1,r)}))}},t.decryptAacSamples=function(e,t,r){for(;;t++){if(t>=e.length)return void r();if(!(e[t].unit.length<32||(this.decryptAacSample(e,t,r),this.decrypter.isSync())))return}},t.getAvcEncryptedData=function(e){for(var t=16*Math.floor((e.length-48)/160)+16,r=new Int8Array(t),i=0,n=32;n=e.length)return void i();for(var n=e[t].units;!(r>=n.length);r++){var a=n[r];if(!(a.data.length<=48||1!==a.type&&5!==a.type||(this.decryptAvcSample(e,t,r,i,a),this.decrypter.isSync())))return}}},e}(),mn=function(){function e(){this.VideoSample=null}var t=e.prototype;return t.createVideoSample=function(e,t,r){return{key:e,frame:!1,pts:t,dts:r,units:[],length:0}},t.getLastNalUnit=function(e){var t,r,i=this.VideoSample;if(i&&0!==i.units.length||(i=e[e.length-1]),null!=(t=i)&&t.units){var n=i.units;r=n[n.length-1]}return r},t.pushAccessUnit=function(e,t){if(e.units.length&&e.frame){if(void 0===e.pts){var r=t.samples,i=r.length;if(!i)return void t.dropped++;var n=r[i-1];e.pts=n.pts,e.dts=n.dts}t.samples.push(e)}},t.parseNALu=function(e,t,r){var i,n,a=t.byteLength,s=e.naluState||0,o=s,l=[],u=0,d=-1,h=0;for(-1===s&&(d=0,h=this.getNALuType(t,0),s=0,u=1);u=0){var f={data:t.subarray(d,n),type:h};l.push(f)}else{var c=this.getLastNalUnit(e.samples);c&&(o&&u<=4-o&&c.state&&(c.data=c.data.subarray(0,c.data.byteLength-o)),n>0&&(c.data=Se(c.data,t.subarray(0,n)),c.state=0))}u=0&&s>=0){var g={data:t.subarray(d,a),type:h,state:s};l.push(g)}if(0===l.length){var v=this.getLastNalUnit(e.samples);v&&(v.data=Se(v.data,t))}return e.naluState=s,l},e}(),pn=function(){function e(e){this.data=void 0,this.bytesAvailable=void 0,this.word=void 0,this.bitsAvailable=void 0,this.data=e,this.bytesAvailable=e.byteLength,this.word=0,this.bitsAvailable=0}var t=e.prototype;return t.loadWord=function(){var e=this.data,t=this.bytesAvailable,r=e.byteLength-t,i=new Uint8Array(4),n=Math.min(4,t);if(0===n)throw new Error("no bytes available");i.set(e.subarray(r,r+n)),this.word=new DataView(i.buffer).getUint32(0),this.bitsAvailable=8*n,this.bytesAvailable-=n},t.skipBits=function(e){var t;e=Math.min(e,8*this.bytesAvailable+this.bitsAvailable),this.bitsAvailable>e?(this.word<<=e,this.bitsAvailable-=e):(e-=this.bitsAvailable,e-=(t=e>>3)<<3,this.bytesAvailable-=t,this.loadWord(),this.word<<=e,this.bitsAvailable-=e)},t.readBits=function(e){var t=Math.min(this.bitsAvailable,e),r=this.word>>>32-t;if(e>32&&Y.error("Cannot read more than 32 bits at a time"),this.bitsAvailable-=t,this.bitsAvailable>0)this.word<<=t;else{if(!(this.bytesAvailable>0))throw new Error("no bits available");this.loadWord()}return(t=e-t)>0&&this.bitsAvailable?r<>>e))return this.word<<=e,this.bitsAvailable-=e,e;return this.loadWord(),e+this.skipLZ()},t.skipUEG=function(){this.skipBits(1+this.skipLZ())},t.skipEG=function(){this.skipBits(1+this.skipLZ())},t.readUEG=function(){var e=this.skipLZ();return this.readBits(e+1)-1},t.readEG=function(){var e=this.readUEG();return 1&e?1+e>>>1:-1*(e>>>1)},t.readBoolean=function(){return 1===this.readBits(1)},t.readUByte=function(){return this.readBits(8)},t.readUShort=function(){return this.readBits(16)},t.readUInt=function(){return this.readBits(32)},e}(),yn=function(e){function t(){return e.apply(this,arguments)||this}o(t,e);var r=t.prototype;return r.parsePES=function(e,t,r,i){var n,a=this,s=this.parseNALu(e,r.data,i),o=this.VideoSample,l=!1;r.data=null,o&&s.length&&!e.audFound&&(this.pushAccessUnit(o,e),o=this.VideoSample=this.createVideoSample(!1,r.pts,r.dts)),s.forEach((function(i){var s,u;switch(i.type){case 1:var d=!1;n=!0;var h,f=i.data;if(l&&f.length>4){var c=a.readSliceType(f);2!==c&&4!==c&&7!==c&&9!==c||(d=!0)}d&&null!=(h=o)&&h.frame&&!o.key&&(a.pushAccessUnit(o,e),o=a.VideoSample=null),o||(o=a.VideoSample=a.createVideoSample(!0,r.pts,r.dts)),o.frame=!0,o.key=d;break;case 5:n=!0,null!=(s=o)&&s.frame&&!o.key&&(a.pushAccessUnit(o,e),o=a.VideoSample=null),o||(o=a.VideoSample=a.createVideoSample(!0,r.pts,r.dts)),o.key=!0,o.frame=!0;break;case 6:n=!0,Ie(i.data,1,r.pts,t.samples);break;case 7:var g,v;n=!0,l=!0;var m=i.data,p=a.readSPS(m);if(!e.sps||e.width!==p.width||e.height!==p.height||(null==(g=e.pixelRatio)?void 0:g[0])!==p.pixelRatio[0]||(null==(v=e.pixelRatio)?void 0:v[1])!==p.pixelRatio[1]){e.width=p.width,e.height=p.height,e.pixelRatio=p.pixelRatio,e.sps=[m];for(var y=m.subarray(1,4),E="avc1.",T=0;T<3;T++){var S=y[T].toString(16);S.length<2&&(S="0"+S),E+=S}e.codec=E}break;case 8:n=!0,e.pps=[i.data];break;case 9:n=!0,e.audFound=!0,null!=(u=o)&&u.frame&&(a.pushAccessUnit(o,e),o=null),o||(o=a.VideoSample=a.createVideoSample(!1,r.pts,r.dts));break;case 12:n=!0;break;default:n=!1}o&&n&&o.units.push(i)})),i&&o&&(this.pushAccessUnit(o,e),this.VideoSample=null)},r.getNALuType=function(e,t){return 31&e[t]},r.readSliceType=function(e){var t=new pn(e);return t.readUByte(),t.readUEG(),t.readUEG()},r.skipScalingList=function(e,t){for(var r=8,i=8,n=0;n>>1},r.ebsp2rbsp=function(e){for(var t=new Uint8Array(e.byteLength),r=0,i=0;i=2&&3===e[i]&&0===e[i-1]&&0===e[i-2]||(t[r]=e[i],r++);return new Uint8Array(t.buffer,0,r)},r.pushAccessUnit=function(t,r){e.prototype.pushAccessUnit.call(this,t,r),this.initVPS&&(this.initVPS=null)},r.readVPS=function(e){var t=new pn(e);return t.readUByte(),t.readUByte(),t.readBits(4),t.skipBits(2),t.readBits(6),{numTemporalLayers:t.readBits(3)+1,temporalIdNested:t.readBoolean()}},r.readSPS=function(e){var t=new pn(this.ebsp2rbsp(e));t.readUByte(),t.readUByte(),t.readBits(4);var r=t.readBits(3);t.readBoolean();for(var i=t.readBits(2),n=t.readBoolean(),a=t.readBits(5),s=t.readUByte(),o=t.readUByte(),l=t.readUByte(),u=t.readUByte(),d=t.readUByte(),h=t.readUByte(),f=t.readUByte(),c=t.readUByte(),g=t.readUByte(),v=t.readUByte(),m=t.readUByte(),p=[],y=[],E=0;E0)for(var T=r;T<8;T++)t.readBits(2);for(var S=0;S1&&t.readEG();for(var N=0;N0&&se<16?(ee=[1,12,10,16,40,24,20,32,80,18,15,64,160,4,3,2][se-1],te=[1,11,11,11,33,11,11,11,33,11,11,33,99,3,2,1][se-1]):255===se&&(ee=t.readBits(16),te=t.readBits(16))}if(t.readBoolean()&&t.readBoolean(),t.readBoolean()&&(t.readBits(3),t.readBoolean(),t.readBoolean()&&(t.readUByte(),t.readUByte(),t.readUByte())),t.readBoolean()&&(t.readUEG(),t.readUEG()),t.readBoolean(),t.readBoolean(),t.readBoolean(),(ae=t.readBoolean())&&(k+=t.readUEG(),b+=t.readUEG(),D+=t.readUEG(),_+=t.readUEG()),t.readBoolean()&&(ie=t.readBits(32),ne=t.readBits(32),t.readBoolean()&&t.readUEG(),t.readBoolean())){var oe=t.readBoolean(),le=t.readBoolean(),ue=!1;(oe||le)&&((ue=t.readBoolean())&&(t.readUByte(),t.readBits(5),t.readBoolean(),t.readBits(5)),t.readBits(4),t.readBits(4),ue&&t.readBits(4),t.readBits(5),t.readBits(5),t.readBits(5));for(var de=0;de<=r;de++){var he=!1;(re=t.readBoolean())||t.readBoolean()?t.readEG():he=t.readBoolean();var fe=he?1:t.readUEG()+1;if(oe)for(var ce=0;ce>Ae&1)<<31-Ae)>>>0;var Le=Se.toString(16);return 1===a&&"2"===Le&&(Le="6"),{codecString:"hvc1."+Ee+a+"."+Le+"."+(n?"H":"L")+m+".B0",params:{general_tier_flag:n,general_profile_idc:a,general_profile_space:i,general_profile_compatibility_flags:[s,o,l,u],general_constraint_indicator_flags:[d,h,f,c,g,v],general_level_idc:m,bit_depth:P+8,bit_depth_luma_minus8:P,bit_depth_chroma_minus8:C,min_spatial_segmentation_idc:Z,chroma_format_idc:A,frame_rate:{fixed:re,fps:ne/ie}},width:ve,height:me,pixelRatio:[ee,te]}},r.readPPS=function(e){var t=new pn(this.ebsp2rbsp(e));t.readUByte(),t.readUByte(),t.skipUEG(),t.skipUEG(),t.skipBits(2),t.skipBits(3),t.skipBits(2),t.skipUEG(),t.skipUEG(),t.skipEG(),t.skipBits(2),t.readBoolean()&&t.skipUEG(),t.skipEG(),t.skipEG(),t.skipBits(4);var r=t.readBoolean(),i=t.readBoolean(),n=1;return i&&r?n=0:i?n=3:r&&(n=2),{parallelismType:n}},r.matchSPS=function(e,t){return String.fromCharCode.apply(null,e).substr(3)===String.fromCharCode.apply(null,t).substr(3)},t}(mn),Tn=188,Sn=function(){function e(e,t,r,i){this.logger=void 0,this.observer=void 0,this.config=void 0,this.typeSupported=void 0,this.sampleAes=null,this.pmtParsed=!1,this.audioCodec=void 0,this.videoCodec=void 0,this._pmtId=-1,this._videoTrack=void 0,this._audioTrack=void 0,this._id3Track=void 0,this._txtTrack=void 0,this.aacOverFlow=null,this.remainderData=null,this.videoParser=void 0,this.observer=e,this.config=t,this.typeSupported=r,this.logger=i,this.videoParser=null}e.probe=function(t,r){var i=e.syncOffset(t);return i>0&&r.warn("MPEG2-TS detected but first sync word found @ offset "+i),-1!==i},e.syncOffset=function(e){for(var t=e.length,r=Math.min(940,t-Tn)+1,i=0;i1&&(0===a&&s>2||o+Tn>r))return a}i++}return-1},e.createTrack=function(e,t){return{container:"video"===e||"audio"===e?"video/mp2t":void 0,type:e,id:se[e],pid:-1,inputTimeScale:9e4,sequenceNumber:0,samples:[],dropped:0,duration:"audio"===e?t:void 0}};var t=e.prototype;return t.resetInitSegment=function(t,r,i,n){this.pmtParsed=!1,this._pmtId=-1,this._videoTrack=e.createTrack("video"),this._videoTrack.duration=n,this._audioTrack=e.createTrack("audio",n),this._id3Track=e.createTrack("id3"),this._txtTrack=e.createTrack("text"),this._audioTrack.segmentCodec="aac",this.aacOverFlow=null,this.remainderData=null,this.audioCodec=r,this.videoCodec=i},t.resetTimeStamp=function(){},t.resetContiguity=function(){var e=this._audioTrack,t=this._videoTrack,r=this._id3Track;e&&(e.pesData=null),t&&(t.pesData=null),r&&(r.pesData=null),this.aacOverFlow=null,this.remainderData=null},t.demux=function(t,r,i,n){var a;void 0===i&&(i=!1),void 0===n&&(n=!1),i||(this.sampleAes=null);var s=this._videoTrack,o=this._audioTrack,l=this._id3Track,u=this._txtTrack,d=s.pid,h=s.pesData,f=o.pid,c=l.pid,g=o.pesData,v=l.pesData,m=null,p=this.pmtParsed,y=this._pmtId,E=t.length;if(this.remainderData&&(E=(t=Se(this.remainderData,t)).length,this.remainderData=null),E>4>1){if((I=A+5+t[A+4])===A+Tn)continue}else I=A+4;switch(R){case d:if(L){if(h&&(a=bn(h,this.logger))){if(null===this.videoParser)switch(s.segmentCodec){case"avc":this.videoParser=new yn;break;case"hevc":this.videoParser=new En}null!==this.videoParser&&this.videoParser.parsePES(s,u,a,!1)}h={data:[],size:0}}h&&(h.data.push(t.subarray(I,A+Tn)),h.size+=A+Tn-I);break;case f:if(L){if(g&&(a=bn(g,this.logger)))switch(o.segmentCodec){case"aac":this.parseAACPES(o,a);break;case"mp3":this.parseMPEGPES(o,a);break;case"ac3":this.parseAC3PES(o,a)}g={data:[],size:0}}g&&(g.data.push(t.subarray(I,A+Tn)),g.size+=A+Tn-I);break;case c:L&&(v&&(a=bn(v,this.logger))&&this.parseID3PES(l,a),v={data:[],size:0}),v&&(v.data.push(t.subarray(I,A+Tn)),v.size+=A+Tn-I);break;case 0:L&&(I+=t[I]+1),y=this._pmtId=Ln(t,I);break;case y:L&&(I+=t[I]+1);var k=Rn(t,I,this.typeSupported,i,this.observer,this.logger);(d=k.videoPid)>0&&(s.pid=d,s.segmentCodec=k.segmentVideoCodec),(f=k.audioPid)>0&&(o.pid=f,o.segmentCodec=k.segmentAudioCodec),(c=k.id3Pid)>0&&(l.pid=c),null===m||p||(this.logger.warn("MPEG-TS PMT found at "+A+" after unknown PID '"+m+"'. Backtracking to sync byte @"+T+" to parse all TS packets."),m=null,A=T-188),p=this.pmtParsed=!0;break;case 17:case 8191:break;default:m=R}}else S++;S>0&&In(this.observer,new Error("Found "+S+" TS packet/s that do not start with 0x47"),void 0,this.logger),s.pesData=h,o.pesData=g,l.pesData=v;var b={audioTrack:o,videoTrack:s,id3Track:l,textTrack:u};return n&&this.extractRemainingSamples(b),b},t.flush=function(){var e,t=this.remainderData;return this.remainderData=null,e=t?this.demux(t,-1,!1,!0):{videoTrack:this._videoTrack,audioTrack:this._audioTrack,id3Track:this._id3Track,textTrack:this._txtTrack},this.extractRemainingSamples(e),this.sampleAes?this.decrypt(e,this.sampleAes):e},t.extractRemainingSamples=function(e){var t,r=e.audioTrack,i=e.videoTrack,n=e.id3Track,a=e.textTrack,s=i.pesData,o=r.pesData,l=n.pesData;if(s&&(t=bn(s,this.logger))){if(null===this.videoParser)switch(i.segmentCodec){case"avc":this.videoParser=new yn;break;case"hevc":this.videoParser=new En}null!==this.videoParser&&(this.videoParser.parsePES(i,a,t,!0),i.pesData=null)}else i.pesData=s;if(o&&(t=bn(o,this.logger))){switch(r.segmentCodec){case"aac":this.parseAACPES(r,t);break;case"mp3":this.parseMPEGPES(r,t);break;case"ac3":this.parseAC3PES(r,t)}r.pesData=null}else null!=o&&o.size&&this.logger.log("last AAC PES packet truncated,might overlap between fragments"),r.pesData=o;l&&(t=bn(l,this.logger))?(this.parseID3PES(n,t),n.pesData=null):n.pesData=l},t.demuxSampleAes=function(e,t,r){var i=this.demux(e,r,!0,!this.config.progressive),n=this.sampleAes=new vn(this.observer,this.config,t);return this.decrypt(i,n)},t.decrypt=function(e,t){return new Promise((function(r){var i=e.audioTrack,n=e.videoTrack;i.samples&&"aac"===i.segmentCodec?t.decryptAacSamples(i.samples,0,(function(){n.samples?t.decryptAvcSamples(n.samples,0,0,(function(){r(e)})):r(e)})):n.samples&&t.decryptAvcSamples(n.samples,0,0,(function(){r(e)}))}))},t.destroy=function(){this.observer&&this.observer.removeAllListeners(),this.config=this.logger=this.observer=null,this.aacOverFlow=this.videoParser=this.remainderData=this.sampleAes=null,this._videoTrack=this._audioTrack=this._id3Track=this._txtTrack=void 0},t.parseAACPES=function(e,t){var r,i,n,a=0,s=this.aacOverFlow,o=t.data;if(s){this.aacOverFlow=null;var l=s.missing,u=s.sample.unit.byteLength;if(-1===l)o=Se(s.sample.unit,o);else{var d=u-l;s.sample.unit.set(o.subarray(0,l),d),e.samples.push(s.sample),a=s.missing}}for(r=a,i=o.length;r0;)o+=n;else this.logger.warn("[tsdemuxer]: AC3 PES unknown PTS")},t.parseID3PES=function(e,t){if(void 0!==t.pts){var r=a({},t,{type:this._videoTrack?ji.emsg:ji.audioId3,duration:Number.POSITIVE_INFINITY});e.samples.push(r)}else this.logger.warn("[tsdemuxer]: ID3 PES unknown PTS")},e}();function An(e,t){return((31&e[t+1])<<8)+e[t+2]}function Ln(e,t){return(31&e[t+10])<<8|e[t+11]}function Rn(e,t,r,i,n,a){var s={audioPid:-1,videoPid:-1,id3Pid:-1,segmentVideoCodec:"avc",segmentAudioCodec:"aac"},o=t+3+((15&e[t+1])<<8|e[t+2])-4;for(t+=12+((15&e[t+10])<<8|e[t+11]);t0)for(var d=t+5,h=u;h>2;){106===e[d]&&(!0!==r.ac3?a.log("AC-3 audio found, not supported in this browser for now"):(s.audioPid=l,s.segmentAudioCodec="ac3"));var f=e[d+1]+2;d+=f,h-=f}break;case 194:case 135:return In(n,new Error("Unsupported EC-3 in M2TS found"),void 0,a),s;case 36:-1===s.videoPid&&(s.videoPid=l,s.segmentVideoCodec="hevc",a.log("HEVC in M2TS found"))}t+=u+5}return s}function In(e,t,r,i){i.warn("parsing error: "+t.message),e.emit(b.ERROR,b.ERROR,{type:I.MEDIA_ERROR,details:k.FRAG_PARSING_ERROR,fatal:!1,levelRetry:r,error:t,reason:t.message})}function kn(e,t){t.log(e+" with AES-128-CBC encryption found in unencrypted stream")}function bn(e,t){var r,i,n,a,s,o=0,l=e.data;if(!e||0===e.size)return null;for(;l[0].length<19&&l.length>1;)l[0]=Se(l[0],l[1]),l.splice(1,1);if(1===((r=l[0])[0]<<16)+(r[1]<<8)+r[2]){if((i=(r[4]<<8)+r[5])&&i>e.size-6)return null;var u=r[7];192&u&&(a=536870912*(14&r[9])+4194304*(255&r[10])+16384*(254&r[11])+128*(255&r[12])+(254&r[13])/2,64&u?a-(s=536870912*(14&r[14])+4194304*(255&r[15])+16384*(254&r[16])+128*(255&r[17])+(254&r[18])/2)>54e5&&(t.warn(Math.round((a-s)/9e4)+"s delta between PTS and DTS, align them"),a=s):s=a);var d=(n=r[8])+9;if(e.size<=d)return null;e.size-=d;for(var h=new Uint8Array(e.size),f=0,c=l.length;fg){d-=g;continue}r=r.subarray(d),g-=d,d=0}h.set(r,o),o+=g}return i&&(i-=n+3),{data:h,pts:a,dts:s,len:i}}return null}var Dn=function(){function e(){}return e.getSilentFrame=function(e,t){if("mp4a.40.2"===e){if(1===t)return new Uint8Array([0,200,0,128,35,128]);if(2===t)return new Uint8Array([33,0,73,144,2,25,0,35,128]);if(3===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,142]);if(4===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,128,44,128,8,2,56]);if(5===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,56]);if(6===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,0,178,0,32,8,224])}else{if(1===t)return new Uint8Array([1,64,34,128,163,78,230,128,186,8,0,0,0,28,6,241,193,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(2===t)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(3===t)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94])}},e}(),_n=Math.pow(2,32)-1,Pn=function(){function e(){}return e.init=function(){var t;for(t in e.types={avc1:[],avcC:[],hvc1:[],hvcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],".mp3":[],dac3:[],"ac-3":[],mvex:[],mvhd:[],pasp:[],sdtp:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[],smhd:[]},e.types)e.types.hasOwnProperty(t)&&(e.types[t]=[t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2),t.charCodeAt(3)]);var r=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),i=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]);e.HDLR_TYPES={video:r,audio:i};var n=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),a=new Uint8Array([0,0,0,0,0,0,0,0]);e.STTS=e.STSC=e.STCO=a,e.STSZ=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),e.VMHD=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0]),e.SMHD=new Uint8Array([0,0,0,0,0,0,0,0]),e.STSD=new Uint8Array([0,0,0,0,0,0,0,1]);var s=new Uint8Array([105,115,111,109]),o=new Uint8Array([97,118,99,49]),l=new Uint8Array([0,0,0,1]);e.FTYP=e.box(e.types.ftyp,s,l,s,o),e.DINF=e.box(e.types.dinf,e.box(e.types.dref,n))},e.box=function(e){for(var t=8,r=arguments.length,i=new Array(r>1?r-1:0),n=1;n>24&255,o[1]=t>>16&255,o[2]=t>>8&255,o[3]=255&t,o.set(e,4),a=0,t=8;a>24&255,t>>16&255,t>>8&255,255&t,i>>24,i>>16&255,i>>8&255,255&i,n>>24,n>>16&255,n>>8&255,255&n,85,196,0,0]))},e.mdia=function(t){return e.box(e.types.mdia,e.mdhd(t.timescale||0,t.duration||0),e.hdlr(t.type),e.minf(t))},e.mfhd=function(t){return e.box(e.types.mfhd,new Uint8Array([0,0,0,0,t>>24,t>>16&255,t>>8&255,255&t]))},e.minf=function(t){return"audio"===t.type?e.box(e.types.minf,e.box(e.types.smhd,e.SMHD),e.DINF,e.stbl(t)):e.box(e.types.minf,e.box(e.types.vmhd,e.VMHD),e.DINF,e.stbl(t))},e.moof=function(t,r,i){return e.box(e.types.moof,e.mfhd(t),e.traf(i,r))},e.moov=function(t){for(var r=t.length,i=[];r--;)i[r]=e.trak(t[r]);return e.box.apply(null,[e.types.moov,e.mvhd(t[0].timescale||0,t[0].duration||0)].concat(i).concat(e.mvex(t)))},e.mvex=function(t){for(var r=t.length,i=[];r--;)i[r]=e.trex(t[r]);return e.box.apply(null,[e.types.mvex].concat(i))},e.mvhd=function(t,r){r*=t;var i=Math.floor(r/(_n+1)),n=Math.floor(r%(_n+1)),a=new Uint8Array([1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,t>>24&255,t>>16&255,t>>8&255,255&t,i>>24,i>>16&255,i>>8&255,255&i,n>>24,n>>16&255,n>>8&255,255&n,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]);return e.box(e.types.mvhd,a)},e.sdtp=function(t){var r,i,n=t.samples||[],a=new Uint8Array(4+n.length);for(r=0;r>>8&255),a.push(255&n),a=a.concat(Array.prototype.slice.call(i));for(r=0;r>>8&255),s.push(255&n),s=s.concat(Array.prototype.slice.call(i));var o=e.box(e.types.avcC,new Uint8Array([1,a[3],a[4],a[5],255,224|t.sps.length].concat(a).concat([t.pps.length]).concat(s))),l=t.width,u=t.height,d=t.pixelRatio[0],h=t.pixelRatio[1];return e.box(e.types.avc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,l>>8&255,255&l,u>>8&255,255&u,0,72,0,0,0,72,0,0,0,0,0,0,0,1,18,100,97,105,108,121,109,111,116,105,111,110,47,104,108,115,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),o,e.box(e.types.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192])),e.box(e.types.pasp,new Uint8Array([d>>24,d>>16&255,d>>8&255,255&d,h>>24,h>>16&255,h>>8&255,255&h])))},e.esds=function(e){var t=e.config;return new Uint8Array([0,0,0,0,3,25,0,1,0,4,17,64,21,0,0,0,0,0,0,0,0,0,0,0,5,2].concat(t,[6,1,2]))},e.audioStsd=function(e){var t=e.samplerate||0;return new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,e.channelCount||0,0,16,0,0,0,0,t>>8&255,255&t,0,0])},e.mp4a=function(t){return e.box(e.types.mp4a,e.audioStsd(t),e.box(e.types.esds,e.esds(t)))},e.mp3=function(t){return e.box(e.types[".mp3"],e.audioStsd(t))},e.ac3=function(t){return e.box(e.types["ac-3"],e.audioStsd(t),e.box(e.types.dac3,t.config))},e.stsd=function(t){var r=t.segmentCodec;if("audio"===t.type){if("aac"===r)return e.box(e.types.stsd,e.STSD,e.mp4a(t));if("ac3"===r&&t.config)return e.box(e.types.stsd,e.STSD,e.ac3(t));if("mp3"===r&&"mp3"===t.codec)return e.box(e.types.stsd,e.STSD,e.mp3(t))}else{if(!t.pps||!t.sps)throw new Error("video track missing pps or sps");if("avc"===r)return e.box(e.types.stsd,e.STSD,e.avc1(t));if("hevc"===r&&t.vps)return e.box(e.types.stsd,e.STSD,e.hvc1(t))}throw new Error("unsupported "+t.type+" segment codec ("+r+"/"+t.codec+")")},e.tkhd=function(t){var r=t.id,i=(t.duration||0)*(t.timescale||0),n=t.width||0,a=t.height||0,s=Math.floor(i/(_n+1)),o=Math.floor(i%(_n+1));return e.box(e.types.tkhd,new Uint8Array([1,0,0,7,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,r>>24&255,r>>16&255,r>>8&255,255&r,0,0,0,0,s>>24,s>>16&255,s>>8&255,255&s,o>>24,o>>16&255,o>>8&255,255&o,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,n>>8&255,255&n,0,0,a>>8&255,255&a,0,0]))},e.traf=function(t,r){var i=e.sdtp(t),n=t.id,a=Math.floor(r/(_n+1)),s=Math.floor(r%(_n+1));return e.box(e.types.traf,e.box(e.types.tfhd,new Uint8Array([0,0,0,0,n>>24,n>>16&255,n>>8&255,255&n])),e.box(e.types.tfdt,new Uint8Array([1,0,0,0,a>>24,a>>16&255,a>>8&255,255&a,s>>24,s>>16&255,s>>8&255,255&s])),e.trun(t,i.length+16+20+8+16+8+8),i)},e.trak=function(t){return t.duration=t.duration||4294967295,e.box(e.types.trak,e.tkhd(t),e.mdia(t))},e.trex=function(t){var r=t.id;return e.box(e.types.trex,new Uint8Array([0,0,0,0,r>>24,r>>16&255,r>>8&255,255&r,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]))},e.trun=function(t,r){var i,n,a,s,o,l,u=t.samples||[],d=u.length,h=12+16*d,f=new Uint8Array(h);for(r+=8+h,f.set(["video"===t.type?1:0,0,15,1,d>>>24&255,d>>>16&255,d>>>8&255,255&d,r>>>24&255,r>>>16&255,r>>>8&255,255&r],0),i=0;i>>24&255,a>>>16&255,a>>>8&255,255&a,s>>>24&255,s>>>16&255,s>>>8&255,255&s,o.isLeading<<2|o.dependsOn,o.isDependedOn<<6|o.hasRedundancy<<4|o.paddingValue<<1|o.isNonSync,61440&o.degradPrio,15&o.degradPrio,l>>>24&255,l>>>16&255,l>>>8&255,255&l],12+16*i);return e.box(e.types.trun,f)},e.initSegment=function(t){e.types||e.init();var r=e.moov(t);return Se(e.FTYP,r)},e.hvc1=function(t){for(var r=t.params,i=[t.vps,t.sps,t.pps],n=new Uint8Array([1,r.general_profile_space<<6|(r.general_tier_flag?32:0)|r.general_profile_idc,r.general_profile_compatibility_flags[0],r.general_profile_compatibility_flags[1],r.general_profile_compatibility_flags[2],r.general_profile_compatibility_flags[3],r.general_constraint_indicator_flags[0],r.general_constraint_indicator_flags[1],r.general_constraint_indicator_flags[2],r.general_constraint_indicator_flags[3],r.general_constraint_indicator_flags[4],r.general_constraint_indicator_flags[5],r.general_level_idc,240|r.min_spatial_segmentation_idc>>8,255&r.min_spatial_segmentation_idc,252|r.parallelismType,252|r.chroma_format_idc,248|r.bit_depth_luma_minus8,248|r.bit_depth_chroma_minus8,0,parseInt(r.frame_rate.fps),3|r.temporal_id_nested<<2|r.num_temporal_layers<<3|(r.frame_rate.fixed?64:0),i.length]),a=n.length,s=0;s>8,255&i[d][h].length]),a),a+=2,l.set(i[d][h],a),a+=i[d][h].length}var f=e.box(e.types.hvcC,l),c=t.width,g=t.height,v=t.pixelRatio[0],m=t.pixelRatio[1];return e.box(e.types.hvc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,c>>8&255,255&c,g>>8&255,255&g,0,72,0,0,0,72,0,0,0,0,0,0,0,1,18,100,97,105,108,121,109,111,116,105,111,110,47,104,108,115,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),f,e.box(e.types.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192])),e.box(e.types.pasp,new Uint8Array([v>>24,v>>16&255,v>>8&255,255&v,m>>24,m>>16&255,m>>8&255,255&m])))},e}();Pn.types=void 0,Pn.HDLR_TYPES=void 0,Pn.STTS=void 0,Pn.STSC=void 0,Pn.STCO=void 0,Pn.STSZ=void 0,Pn.VMHD=void 0,Pn.SMHD=void 0,Pn.STSD=void 0,Pn.FTYP=void 0,Pn.DINF=void 0;var Cn=9e4;function wn(e,t,r,i){void 0===r&&(r=1),void 0===i&&(i=!1);var n=e*t*r;return i?Math.round(n):n}function On(e,t){return wn(e,1e3,1/Cn,t)}var xn=null,Mn=null;function Fn(e,t,r,i){return{duration:t,size:r,cts:i,flags:{isLeading:0,isDependedOn:0,hasRedundancy:0,degradPrio:0,dependsOn:e?2:1,isNonSync:e?0:1}}}var Nn=function(e){function t(t,r,i,n){var a;if((a=e.call(this,"mp4-remuxer",n)||this).observer=void 0,a.config=void 0,a.typeSupported=void 0,a.ISGenerated=!1,a._initPTS=null,a._initDTS=null,a.nextVideoTs=null,a.nextAudioTs=null,a.videoSampleDuration=null,a.isAudioContiguous=!1,a.isVideoContiguous=!1,a.videoTrackConfig=void 0,a.observer=t,a.config=r,a.typeSupported=i,a.ISGenerated=!1,null===xn){var s=(navigator.userAgent||"").match(/Chrome\/(\d+)/i);xn=s?parseInt(s[1]):0}if(null===Mn){var o=navigator.userAgent.match(/Safari\/(\d+)/i);Mn=o?parseInt(o[1]):0}return a}o(t,e);var r=t.prototype;return r.destroy=function(){this.config=this.videoTrackConfig=this._initPTS=this._initDTS=null},r.resetTimeStamp=function(e){this.log("initPTS & initDTS reset"),this._initPTS=this._initDTS=e},r.resetNextTimestamp=function(){this.log("reset next timestamp"),this.isVideoContiguous=!1,this.isAudioContiguous=!1},r.resetInitSegment=function(){this.log("ISGenerated flag reset"),this.ISGenerated=!1,this.videoTrackConfig=void 0},r.getVideoStartPts=function(e){var t=!1,r=e[0].pts,i=e.reduce((function(e,i){var n=i.pts,a=n-e;return a<-4294967296&&(t=!0,a=(n=Un(n,r))-e),a>0?e:n}),r);return t&&this.debug("PTS rollover detected"),i},r.remux=function(e,t,r,i,n,a,s,o){var l,u,d,h,f,c,g=n,v=n,m=e.pid>-1,p=t.pid>-1,y=t.samples.length,E=e.samples.length>0,T=s&&y>0||y>1;if((!m||E)&&(!p||T)||this.ISGenerated||s){if(this.ISGenerated){var S,A,L,R,I=this.videoTrackConfig;(I&&(t.width!==I.width||t.height!==I.height||(null==(S=t.pixelRatio)?void 0:S[0])!==(null==(A=I.pixelRatio)?void 0:A[0])||(null==(L=t.pixelRatio)?void 0:L[1])!==(null==(R=I.pixelRatio)?void 0:R[1]))||!I&&T||null===this.nextAudioTs&&E)&&this.resetInitSegment()}this.ISGenerated||(d=this.generateIS(e,t,n,a));var k,b=this.isVideoContiguous,D=-1;if(T&&(D=function(e){for(var t=0;t0){this.warn("Dropped "+D+" out of "+y+" video samples due to a missing keyframe");var _=this.getVideoStartPts(t.samples);t.samples=t.samples.slice(D),t.dropped+=D,k=v+=(t.samples[0].pts-_)/t.inputTimeScale}else-1===D&&(this.warn("No keyframe found out of "+y+" video samples"),c=!1);if(this.ISGenerated){if(E&&T){var P=this.getVideoStartPts(t.samples),C=(Un(e.samples[0].pts,P)-P)/t.inputTimeScale;g+=Math.max(0,C),v+=Math.max(0,-C)}if(E){if(e.samplerate||(this.warn("regenerate InitSegment as audio detected"),d=this.generateIS(e,t,n,a)),u=this.remuxAudio(e,g,this.isAudioContiguous,a,p||T||o===O?v:void 0),T){var w=u?u.endPTS-u.startPTS:0;t.inputTimeScale||(this.warn("regenerate InitSegment as video detected"),d=this.generateIS(e,t,n,a)),l=this.remuxVideo(t,v,b,w)}}else T&&(l=this.remuxVideo(t,v,b,0));l&&(l.firstKeyFrame=D,l.independent=-1!==D,l.firstKeyFramePTS=k)}}return this.ISGenerated&&this._initPTS&&this._initDTS&&(r.samples.length&&(f=Bn(r,n,this._initPTS,this._initDTS)),i.samples.length&&(h=Gn(i,n,this._initPTS))),{audio:u,video:l,initSegment:d,independent:c,text:h,id3:f}},r.generateIS=function(e,t,r,i){var n,a,s,o,l=e.samples,u=t.samples,d=this.typeSupported,h={},f=this._initPTS,c=!f||i,g="audio/mp4";if(c&&(n=a=1/0),e.config&&l.length){switch(e.timescale=e.samplerate,e.segmentCodec){case"mp3":d.mpeg?(g="audio/mpeg",e.codec=""):d.mp3&&(e.codec="mp3");break;case"ac3":e.codec="ac-3"}h.audio={id:"audio",container:g,codec:e.codec,initSegment:"mp3"===e.segmentCodec&&d.mpeg?new Uint8Array(0):Pn.initSegment([e]),metadata:{channelCount:e.channelCount}},c&&(o=e.id,s=e.inputTimeScale,f&&s===f.timescale?c=!1:n=a=l[0].pts-Math.round(s*r))}if(t.sps&&t.pps&&u.length){if(t.timescale=t.inputTimeScale,h.video={id:"main",container:"video/mp4",codec:t.codec,initSegment:Pn.initSegment([t]),metadata:{width:t.width,height:t.height}},c)if(o=t.id,s=t.inputTimeScale,f&&s===f.timescale)c=!1;else{var v=this.getVideoStartPts(u),m=Math.round(s*r);a=Math.min(a,Un(u[0].dts,v)-m),n=Math.min(n,v-m)}this.videoTrackConfig={width:t.width,height:t.height,pixelRatio:t.pixelRatio}}if(Object.keys(h).length)return this.ISGenerated=!0,c?(this._initPTS={baseTime:n,timescale:s},this._initDTS={baseTime:a,timescale:s}):n=s=void 0,{tracks:h,initPTS:n,timescale:s,trackId:o}},r.remuxVideo=function(e,t,r,i){var n,s,o=e.inputTimeScale,l=e.samples,u=[],d=l.length,h=this._initPTS,f=h.baseTime*o/h.timescale,c=this.nextVideoTs,g=8,v=this.videoSampleDuration,m=Number.POSITIVE_INFINITY,p=Number.NEGATIVE_INFINITY,y=!1;if(!r||null===c){var E=f+t*o,T=l[0].pts-Un(l[0].dts,l[0].pts);xn&&null!==c&&Math.abs(E-T-(c+f))<15e3?r=!0:c=E-T-f}for(var S=c+f,A=0;A0?A-1:A].dts&&(y=!0)}y&&l.sort((function(e,t){var r=e.dts-t.dts,i=e.pts-t.pts;return r||i})),n=l[0].dts;var R=(s=l[l.length-1].dts)-n,D=R?Math.round(R/(d-1)):v||e.inputTimeScale/30;if(r){var _=n-S,P=_>D,C=_<-1;if((P||C)&&(P?this.warn((e.segmentCodec||"").toUpperCase()+": "+On(_,!0)+" ms ("+_+"dts) hole between fragments detected at "+t.toFixed(3)):this.warn((e.segmentCodec||"").toUpperCase()+": "+On(-_,!0)+" ms ("+_+"dts) overlapping between fragments detected at "+t.toFixed(3)),!C||S>=l[0].pts||xn)){n=S;var w=l[0].pts-_;if(P)l[0].dts=n,l[0].pts=w;else for(var O=!0,x=0;xw&&O);x++){var M=l[x].pts;if(l[x].dts-=_,l[x].pts-=_,x0?te.dts-l[ee-1].dts:D;if(ue=ee>0?te.pts-l[ee-1].pts:D,de.stretchShortVideoTrack&&null!==this.nextAudioTs){var fe=Math.floor(de.maxBufferHole*o),ce=(i?m+i*o:this.nextAudioTs+f)-te.pts;ce>fe?((v=ce-he)<0?v=he:Q=!0,this.log("It is approximately "+ce/90+" ms to the next segment; using duration "+v/90+" ms for the last video frame.")):v=he}else v=he}var ge=Math.round(te.pts-te.dts);z=Math.min(z,v),J=Math.max(J,v),$=Math.min($,ue),Z=Math.max(Z,ue),u.push(Fn(te.key,v,ie,ge))}if(u.length)if(xn){if(xn<70){var ve=u[0].flags;ve.dependsOn=2,ve.isNonSync=0}}else if(Mn&&Z-$0&&(i&&Math.abs(y-(m+p))<9e3||Math.abs(Un(g[0].pts,y)-(m+p))<20*u),g.forEach((function(e){e.pts=Un(e.pts,y)})),!r||m<0){if(g=g.filter((function(e){return e.pts>=0})),!g.length)return;m=0===n?0:i&&!c?Math.max(0,y-p):g[0].pts-p}if("aac"===e.segmentCodec)for(var E=this.config.maxAudioFramesDrift,T=0,S=m+p;T=E*u&&D<1e4&&c){var _=Math.round(R/u);for(S=L-_*u;S<0&&_&&u;)_--,S+=u;0===T&&(this.nextAudioTs=m=S-p),this.warn("Injecting "+_+" audio frames @ "+((S-p)/s).toFixed(3)+"s due to "+Math.round(1e3*R/s)+" ms gap.");for(var P=0;P<_;P++){var C=Dn.getSilentFrame(e.parsedCodec||e.manifestCodec||e.codec,e.channelCount);C||(this.log("Unable to get silent frame for given audio codec; duplicating last frame instead."),C=A.unit.subarray()),g.splice(T,0,{unit:C,pts:S}),S+=u,T++}}A.pts=S,S+=u}for(var w,O=null,x=null,M=0,F=g.length;F--;)M+=g[F].unit.byteLength;for(var N=0,U=g.length;N0))return;M+=v;try{w=new Uint8Array(M)}catch(e){return void this.observer.emit(b.ERROR,b.ERROR,{type:I.MUX_ERROR,details:k.REMUX_ALLOC_ERROR,fatal:!1,error:e,bytes:M,reason:"fail allocating audio mdat "+M})}h||(new DataView(w.buffer).setUint32(0,M),w.set(Pn.types.mdat,4))}w.set(G,v);var V=G.byteLength;v+=V,f.push(Fn(!0,l,V,0)),x=K}var H=f.length;if(H){var Y=f[f.length-1];m=x-p,this.nextAudioTs=m+o*Y.duration;var W=h?new Uint8Array(0):Pn.moof(e.sequenceNumber++,O/o,a({},e,{samples:f}));e.samples=[];var j=(O-p)/s,q=m/s,X={data1:W,data2:w,startPTS:j,endPTS:q,startDTS:j,endDTS:q,type:"audio",hasAudio:!0,hasVideo:!1,nb:H};return this.isAudioContiguous=!0,X}},t}(N);function Un(e,t){var r;if(null===t)return e;for(r=t4294967296;)e+=r;return e}function Bn(e,t,r,i){var n=e.samples.length;if(n){for(var a=e.inputTimeScale,s=0;s0;n||(i=fe(t,["encv"])),i.forEach((function(e){fe(n?e.subarray(28):e.subarray(78),["sinf"]).forEach((function(e){var t=Te(e);if(t){var i=t.subarray(8,24);i.some((function(e){return 0!==e}))||(Y.log("[eme] Patching keyId in 'enc"+(n?"a":"v")+">sinf>>tenc' box: "+X.hexDump(i)+" -> "+X.hexDump(r)),t.set(r,8))}}))}))})),e}(e,i)),this.emitInitSegment=!0},r.generateInitSegment=function(e){var t=this.audioCodec,r=this.videoCodec;if(null==e||!e.byteLength)return this.initTracks=void 0,void(this.initData=void 0);var i=this.initData=ge(e);i.audio&&(t=Yn(i.audio,z,this)),i.video&&(r=Yn(i.video,$,this));var n={};i.audio&&i.video?n.audiovideo={container:"video/mp4",codec:t+","+r,supplemental:i.video.supplemental,initSegment:e,id:"main"}:i.audio?n.audio={container:"audio/mp4",codec:t,initSegment:e,id:"audio"}:i.video?n.video={container:"video/mp4",codec:r,supplemental:i.video.supplemental,initSegment:e,id:"main"}:this.warn("initSegment does not contain moov or trak boxes."),this.initTracks=n},r.remux=function(e,t,r,i,n,a){var s,o,l=this.initPTS,u=this.lastEndTime,d={audio:void 0,video:void 0,text:i,id3:r,initSegment:void 0};A(u)||(u=this.lastEndTime=n||0);var h=t.samples;if(null==h||!h.length)return d;var f={initPTS:void 0,timescale:void 0,trackId:void 0},c=this.initData;if(null!=(s=c)&&s.length||(this.generateInitSegment(h),c=this.initData),null==(o=c)||!o.length)return this.warn("Failed to generate initSegment."),d;this.emitInitSegment&&(f.tracks=this.initTracks,this.emitInitSegment=!1);var g,v=function(e,t,r){for(var i={},n=fe(e,["moof","traf"]),a=0;an}(l,L,n,R)&&f.timescale===l.timescale||(f.initPTS=L-n,f.timescale=1,l&&1===l.timescale&&this.warn("Adjusting initPTS @"+n+" from "+l.baseTime/l.timescale+" to "+f.initPTS),this.initPTS=l={baseTime:f.initPTS,timescale:1});var k=e?L-l.baseTime/l.timescale:u,b=k+R;R>0?this.lastEndTime=b:(this.warn("Duration parsed from mp4 should be greater than zero"),this.resetNextTimestamp());var D=!!c.audio,_=!!c.video,P="";D&&(P+="audio"),_&&(P+="video");var C={data1:h,startPTS:k,startDTS:k,endPTS:b,endDTS:b,type:P,hasAudio:D,hasVideo:_,nb:1,dropped:0};d.audio=D&&!_?C:void 0,d.video=_?C:void 0;var w=null==p?void 0:p.sampleCount;if(w){var O=p.keyFrameIndex,x=-1!==O;C.nb=w,C.dropped=0===O||this.isVideoContiguous?0:x?O:w,C.independent=x,C.firstKeyFrame=O,x&&p.keyFrameStart&&(C.firstKeyFramePTS=(p.keyFrameStart-l.baseTime)/l.timescale),this.isVideoContiguous||(d.independent=x),this.isVideoContiguous||(this.isVideoContiguous=x),C.dropped&&this.warn("fmp4 does not start with IDR: firstIDR "+O+"/"+w+" dropped: "+C.dropped+" start: "+(C.firstKeyFramePTS||"NA"))}return d.initSegment=f,d.id3=Bn(r,n,l,l),i.samples.length&&(d.text=Gn(i,n,l)),d},t}(N);function Hn(e,t,r){return void 0===r&&(r=!1),void 0!==(null==e?void 0:e.start)?(e.start+(r?e.duration:0))/e.timescale:t}function Yn(e,t,r){var i=null==e?void 0:e.codec;return i&&i.length>4?i:t===z?"ec-3"===i||"ac-3"===i||"alac"===i?i:"fLaC"===i||"Opus"===i?Be(i,!1):(r.warn('Unhandled audio codec "'+i+'" in mp4 MAP'),i||"mp4a"):(r.warn('Unhandled video codec "'+i+'" in mp4 MAP'),i||"avc1")}try{Kn=self.performance.now.bind(self.performance)}catch(e){Kn=Date.now}var Wn=[{demux:cn,remux:Vn},{demux:Sn,remux:Nn},{demux:on,remux:Nn},{demux:hn,remux:Nn}];Wn.splice(2,0,{demux:un,remux:Nn});var jn=function(){function e(e,t,r,i,n,a){this.asyncResult=!1,this.logger=void 0,this.observer=void 0,this.typeSupported=void 0,this.config=void 0,this.id=void 0,this.demuxer=void 0,this.remuxer=void 0,this.decrypter=void 0,this.probe=void 0,this.decryptionPromise=null,this.transmuxConfig=void 0,this.currentTransmuxState=void 0,this.observer=e,this.typeSupported=t,this.config=r,this.id=n,this.logger=a}var t=e.prototype;return t.configure=function(e){this.transmuxConfig=e,this.decrypter&&this.decrypter.reset()},t.push=function(e,t,r,i){var n=this,a=r.transmuxing;a.executeStart=Kn();var s=new Uint8Array(e),o=this.currentTransmuxState,l=this.transmuxConfig;i&&(this.currentTransmuxState=i);var u=i||o,d=u.contiguous,h=u.discontinuity,f=u.trackSwitch,c=u.accurateTimeOffset,g=u.timeOffset,v=u.initSegmentChange,m=l.audioCodec,p=l.videoCodec,y=l.defaultInitPts,E=l.duration,T=l.initSegmentData,S=function(e,t){var r=null;return e.byteLength>0&&null!=(null==t?void 0:t.key)&&null!==t.iv&&null!=t.method&&(r=t),r}(s,t);if(S&&vr(S.method)){var A=this.getDecrypter(),L=mr(S.method);if(!A.isSync())return this.asyncResult=!0,this.decryptionPromise=A.webCryptoDecrypt(s,S.key.buffer,S.iv.buffer,L).then((function(e){var t=n.push(e,null,r);return n.decryptionPromise=null,t})),this.decryptionPromise;var R=A.softwareDecrypt(s,S.key.buffer,S.iv.buffer,L);if(r.part>-1){var D=A.flush();R=D?D.buffer:D}if(!R)return a.executeEnd=Kn(),qn(r);s=new Uint8Array(R)}var _=this.needsProbing(h,f);if(_){var P=this.configureTransmuxer(s);if(P)return this.logger.warn("[transmuxer] "+P.message),this.observer.emit(b.ERROR,b.ERROR,{type:I.MEDIA_ERROR,details:k.FRAG_PARSING_ERROR,fatal:!1,error:P,reason:P.message}),a.executeEnd=Kn(),qn(r)}(h||f||v||_)&&this.resetInitSegment(T,m,p,E,t),(h||v||_)&&this.resetInitialTimestamp(y),d||this.resetContiguity();var C=this.transmux(s,S,g,c,r);this.asyncResult=Xn(C);var w=this.currentTransmuxState;return w.contiguous=!0,w.discontinuity=!1,w.trackSwitch=!1,a.executeEnd=Kn(),C},t.flush=function(e){var t=this,r=e.transmuxing;r.executeStart=Kn();var i=this.decrypter,n=this.currentTransmuxState,a=this.decryptionPromise;if(a)return this.asyncResult=!0,a.then((function(){return t.flush(e)}));var s=[],o=n.timeOffset;if(i){var l=i.flush();l&&s.push(this.push(l.buffer,null,e))}var u=this.demuxer,d=this.remuxer;if(!u||!d){r.executeEnd=Kn();var h=[qn(e)];return this.asyncResult?Promise.resolve(h):h}var f=u.flush(o);return Xn(f)?(this.asyncResult=!0,f.then((function(r){return t.flushRemux(s,r,e),s}))):(this.flushRemux(s,f,e),this.asyncResult?Promise.resolve(s):s)},t.flushRemux=function(e,t,r){var i=t.audioTrack,n=t.videoTrack,a=t.id3Track,s=t.textTrack,o=this.currentTransmuxState,l=o.accurateTimeOffset,u=o.timeOffset;this.logger.log("[transmuxer.ts]: Flushed "+this.id+" sn: "+r.sn+(r.part>-1?" part: "+r.part:"")+" of "+(this.id===w?"level":"track")+" "+r.level);var d=this.remuxer.remux(i,n,a,s,u,l,!0,this.id);e.push({remuxResult:d,chunkMeta:r}),r.transmuxing.executeEnd=Kn()},t.resetInitialTimestamp=function(e){var t=this.demuxer,r=this.remuxer;t&&r&&(t.resetTimeStamp(e),r.resetTimeStamp(e))},t.resetContiguity=function(){var e=this.demuxer,t=this.remuxer;e&&t&&(e.resetContiguity(),t.resetNextTimestamp())},t.resetInitSegment=function(e,t,r,i,n){var a=this.demuxer,s=this.remuxer;a&&s&&(a.resetInitSegment(e,t,r,i),s.resetInitSegment(e,t,r,n))},t.destroy=function(){this.demuxer&&(this.demuxer.destroy(),this.demuxer=void 0),this.remuxer&&(this.remuxer.destroy(),this.remuxer=void 0)},t.transmux=function(e,t,r,i,n){return t&&"SAMPLE-AES"===t.method?this.transmuxSampleAes(e,t,r,i,n):this.transmuxUnencrypted(e,r,i,n)},t.transmuxUnencrypted=function(e,t,r,i){var n=this.demuxer.demux(e,t,!1,!this.config.progressive),a=n.audioTrack,s=n.videoTrack,o=n.id3Track,l=n.textTrack;return{remuxResult:this.remuxer.remux(a,s,o,l,t,r,!1,this.id),chunkMeta:i}},t.transmuxSampleAes=function(e,t,r,i,n){var a=this;return this.demuxer.demuxSampleAes(e,t,r).then((function(e){return{remuxResult:a.remuxer.remux(e.audioTrack,e.videoTrack,e.id3Track,e.textTrack,r,i,!1,a.id),chunkMeta:n}}))},t.configureTransmuxer=function(e){for(var t,r=this.config,i=this.observer,n=this.typeSupported,a=0,s=Wn.length;a1&&l.id===(null==p?void 0:p.stats.chunkCount),L=!E&&(1===T||0===T&&(1===S||A&&S<=0)),R=self.performance.now();(E||T||0===n.stats.parsing.start)&&(n.stats.parsing.start=R),!a||!S&&L||(a.stats.parsing.start=R);var I=!(p&&(null==(d=n.initSegment)?void 0:d.url)===(null==(h=p.initSegment)?void 0:h.url)),k=new zn(y,L,o,E,v,I);if(!L||y||I){this.hls.logger.log("[transmuxer-interface]: Starting new transmux session for "+n.type+" sn: "+l.sn+(l.part>-1?" part: "+l.part:"")+" "+(this.id===w?"level":"track")+": "+l.level+" id: "+l.id+"\n discontinuity: "+y+"\n trackSwitch: "+E+"\n contiguous: "+L+"\n accurateTimeOffset: "+o+"\n timeOffset: "+v+"\n initSegmentChange: "+I);var b=new Qn(r,i,t,s,u);this.configureTransmuxer(b)}if(this.frag=n,this.part=a,this.workerContext)this.workerContext.worker.postMessage({instanceNo:c,cmd:"demux",data:e,decryptdata:m,chunkMeta:l,state:k},e instanceof ArrayBuffer?[e]:[]);else if(g){var D=g.push(e,m,l,k);Xn(D)?D.then((function(e){f.handleTransmuxComplete(e)})).catch((function(e){f.transmuxerError(e,l,"transmuxer-interface push error")})):this.handleTransmuxComplete(D)}},r.flush=function(e){var t=this;e.transmuxing.start=self.performance.now();var r=this.instanceNo,i=this.transmuxer;if(this.workerContext)this.workerContext.worker.postMessage({instanceNo:r,cmd:"flush",chunkMeta:e});else if(i){var n=i.flush(e);Xn(n)?n.then((function(r){t.handleFlushResult(r,e)})).catch((function(r){t.transmuxerError(r,e,"transmuxer-interface flush error")})):this.handleFlushResult(n,e)}},r.transmuxerError=function(e,t,r){this.hls&&(this.error=e,this.hls.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.FRAG_PARSING_ERROR,chunkMeta:t,frag:this.frag||void 0,part:this.part||void 0,fatal:!1,error:e,err:e,reason:r}))},r.handleFlushResult=function(e,t){var r=this;e.forEach((function(e){r.handleTransmuxComplete(e)})),this.onFlush(t)},r.configureTransmuxer=function(e){var t=this.instanceNo,r=this.transmuxer;this.workerContext?this.workerContext.worker.postMessage({instanceNo:t,cmd:"configure",config:e}):r&&r.configure(e)},r.handleTransmuxComplete=function(e){e.chunkMeta.transmuxing.end=self.performance.now(),this.onTransmuxComplete(e)},t}(),sa=function(e){function t(t,r,i){var n;return(n=e.call(this,t,r,i,"audio-stream-controller",O)||this).mainAnchor=null,n.mainFragLoading=null,n.audioOnly=!1,n.bufferedTrack=null,n.switchingTrack=null,n.trackId=-1,n.waitingData=null,n.mainDetails=null,n.flushing=!1,n.bufferFlushed=!1,n.cachedTrackLoadedData=null,n.registerListeners(),n}o(t,e);var r=t.prototype;return r.onHandlerDestroying=function(){this.unregisterListeners(),e.prototype.onHandlerDestroying.call(this),this.resetItem()},r.resetItem=function(){this.mainDetails=this.mainAnchor=this.mainFragLoading=this.bufferedTrack=this.switchingTrack=this.waitingData=this.cachedTrackLoadedData=null},r.registerListeners=function(){e.prototype.registerListeners.call(this);var t=this.hls;t.on(b.LEVEL_LOADED,this.onLevelLoaded,this),t.on(b.AUDIO_TRACKS_UPDATED,this.onAudioTracksUpdated,this),t.on(b.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),t.on(b.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),t.on(b.BUFFER_RESET,this.onBufferReset,this),t.on(b.BUFFER_CREATED,this.onBufferCreated,this),t.on(b.BUFFER_FLUSHING,this.onBufferFlushing,this),t.on(b.BUFFER_FLUSHED,this.onBufferFlushed,this),t.on(b.INIT_PTS_FOUND,this.onInitPtsFound,this),t.on(b.FRAG_LOADING,this.onFragLoading,this),t.on(b.FRAG_BUFFERED,this.onFragBuffered,this)},r.unregisterListeners=function(){var t=this.hls;t&&(e.prototype.unregisterListeners.call(this),t.off(b.LEVEL_LOADED,this.onLevelLoaded,this),t.off(b.AUDIO_TRACKS_UPDATED,this.onAudioTracksUpdated,this),t.off(b.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),t.off(b.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),t.off(b.BUFFER_RESET,this.onBufferReset,this),t.off(b.BUFFER_CREATED,this.onBufferCreated,this),t.off(b.BUFFER_FLUSHING,this.onBufferFlushing,this),t.off(b.BUFFER_FLUSHED,this.onBufferFlushed,this),t.off(b.INIT_PTS_FOUND,this.onInitPtsFound,this),t.off(b.FRAG_LOADING,this.onFragLoading,this),t.off(b.FRAG_BUFFERED,this.onFragBuffered,this))},r.onInitPtsFound=function(e,t){var r=t.frag,i=t.id,n=t.initPTS,a=t.timescale;if(i===w){var s=r.cc,o=this.fragCurrent;if(this.initPTS[s]={baseTime:n,timescale:a},this.log("InitPTS for cc: "+s+" found from main: "+n+"/"+a),this.mainAnchor=r,this.state===Ei.WAITING_INIT_PTS){var l=this.waitingData;(!l&&!this.loadingParts||l&&l.frag.cc!==s)&&this.syncWithAnchor(r,null==l?void 0:l.frag)}else!this.hls.hasEnoughToStart&&o&&o.cc!==s?(o.abortRequests(),this.syncWithAnchor(r,o)):this.state===Ei.IDLE&&this.tick()}},r.getLoadPosition=function(){return!this.startFragRequested&&this.nextLoadPosition>=0?this.nextLoadPosition:e.prototype.getLoadPosition.call(this)},r.syncWithAnchor=function(e,t){var r,i=(null==(r=this.mainFragLoading)?void 0:r.frag)||null;if(!t||(null==i?void 0:i.cc)!==t.cc){var n=(i||e).cc,a=Tt(this.getLevelDetails(),n,this.getLoadPosition());a&&(this.log("Waiting fragment cc ("+(null==t?void 0:t.cc)+") cancelled because video is at cc "+e.cc),this.startFragRequested=!1,this.nextLoadPosition=a.start,this.resetLoadingState(),this.state===Ei.IDLE&&this.doTickIdle())}},r.startLoad=function(e,t){if(!this.levels)return this.startPosition=e,void(this.state=Ei.STOPPED);var r=this.lastCurrentTime;this.stopLoad(),this.setInterval(100),r>0&&-1===e?(this.log("Override startPosition with lastCurrentTime @"+r.toFixed(3)),e=r,this.state=Ei.IDLE):this.state=Ei.WAITING_TRACK,this.nextLoadPosition=this.lastCurrentTime=e+this.timelineOffset,this.startPosition=t?-1:e,this.tick()},r.doTick=function(){switch(this.state){case Ei.IDLE:this.doTickIdle();break;case Ei.WAITING_TRACK:var t=this.levels,r=this.trackId,i=null==t?void 0:t[r],n=null==i?void 0:i.details;if(n&&!this.waitForLive(i)){if(this.waitForCdnTuneIn(n))break;this.state=Ei.WAITING_INIT_PTS}break;case Ei.FRAG_LOADING_WAITING_RETRY:var a,s=performance.now(),o=this.retryDate;if(!o||s>=o||null!=(a=this.media)&&a.seeking){var l=this.levels,u=this.trackId;this.log("RetryDate reached, switch back to IDLE state"),this.resetStartWhenNotLoaded((null==l?void 0:l[u])||null),this.state=Ei.IDLE}break;case Ei.WAITING_INIT_PTS:var d=this.waitingData;if(d){var h=d.frag,f=d.part,c=d.cache,g=d.complete,v=this.mainAnchor;if(void 0!==this.initPTS[h.cc]){this.waitingData=null,this.state=Ei.FRAG_LOADING;var m={frag:h,part:f,payload:c.flush().buffer,networkDetails:null};this._handleFragmentLoadProgress(m),g&&e.prototype._handleFragmentLoadComplete.call(this,m)}else v&&v.cc!==d.frag.cc&&this.syncWithAnchor(v,d.frag)}else this.state=Ei.IDLE}this.onTickEnd()},r.resetLoadingState=function(){var t=this.waitingData;t&&(this.fragmentTracker.removeFragment(t.frag),this.waitingData=null),e.prototype.resetLoadingState.call(this)},r.onTickEnd=function(){var e=this.media;null!=e&&e.readyState&&(this.lastCurrentTime=e.currentTime)},r.doTickIdle=function(){var e,t=this.hls,r=this.levels,i=this.media,n=this.trackId,a=t.config;if(this.buffering&&(i||this.primaryPrefetch||!this.startFragRequested&&a.startFragPrefetch)&&null!=r&&r[n]){var s=r[n],o=s.details;if(!o||this.waitForLive(s)||this.waitForCdnTuneIn(o))return this.state=Ei.WAITING_TRACK,void(this.startFragRequested=!1);var l=this.mediaBuffer?this.mediaBuffer:this.media;this.bufferFlushed&&l&&(this.bufferFlushed=!1,this.afterBufferFlushed(l,z,O));var u=this.getFwdBufferInfo(l,O);if(null!==u){if(!this.switchingTrack&&this._streamEnded(u,o))return t.trigger(b.BUFFER_EOS,{type:"audio"}),void(this.state=Ei.ENDED);var d=u.len,h=t.maxBufferLength,f=o.fragments,c=f[0].start,g=this.getLoadPosition(),v=this.flushing?g:u.end;if(this.switchingTrack&&i){var m=g;o.PTSKnown&&mc||u.nextStart)&&(this.log("Alt audio track ahead of main track, seek to start of alt audio track"),i.currentTime=c+.05)}if(!(d>=h&&!this.switchingTrack&&vy.end){var E=this.fragmentTracker.getFragAtPos(v,w);E&&E.end>y.end&&(y=E,this.mainFragLoading={frag:E,targetBufferTime:null})}if(p.start>y.end)return}this.loadFragment(p,s,v)}else this.bufferFlushed=!0}}}},r.onMediaDetaching=function(t,r){this.bufferFlushed=this.flushing=!1,e.prototype.onMediaDetaching.call(this,t,r)},r.onAudioTracksUpdated=function(e,t){var r=t.audioTracks;this.resetTransmuxer(),this.levels=r.map((function(e){return new it(e)}))},r.onAudioTrackSwitching=function(e,t){var r=!!t.url;this.trackId=t.id;var i=this.fragCurrent;i&&(i.abortRequests(),this.removeUnbufferedFrags(i.start)),this.resetLoadingState(),r?(this.switchingTrack=t,this.flushAudioIfNeeded(t),this.state!==Ei.STOPPED&&(this.setInterval(100),this.state=Ei.IDLE,this.tick())):(this.resetTransmuxer(),this.switchingTrack=null,this.bufferedTrack=t,this.clearInterval())},r.onManifestLoading=function(){e.prototype.onManifestLoading.call(this),this.bufferFlushed=this.flushing=this.audioOnly=!1,this.resetItem(),this.trackId=-1},r.onLevelLoaded=function(e,t){this.mainDetails=t.details;var r=this.cachedTrackLoadedData;r&&(this.cachedTrackLoadedData=null,this.onAudioTrackLoaded(b.AUDIO_TRACK_LOADED,r))},r.onAudioTrackLoaded=function(e,t){var r,i=this.levels,n=t.details,a=t.id,s=t.groupId,o=t.track;if(i){var l=this.mainDetails;if(!l||n.endCC>l.endCC||l.expired)return this.cachedTrackLoadedData=t,void(this.state!==Ei.STOPPED&&(this.state=Ei.WAITING_TRACK));this.cachedTrackLoadedData=null,this.log("Audio track "+a+' "'+o.name+'" of "'+s+'" loaded ['+n.startSN+","+n.endSN+"]"+(n.lastPartSn?"[part-"+n.lastPartSn+"-"+n.lastPartIndex+"]":"")+",duration:"+n.totalduration);var u=i[a],d=0;if(n.live||null!=(r=u.details)&&r.live){if(this.checkLiveUpdate(n),n.deltaUpdateFailed)return;var h;u.details&&(d=this.alignPlaylists(n,u.details,null==(h=this.levelLastLoaded)?void 0:h.details)),n.alignedSliding||(mi(n,l),n.alignedSliding||pi(n,l),d=n.fragmentStart)}u.details=n,this.levelLastLoaded=u,this.startFragRequested||this.setStartPosition(l,d),this.hls.trigger(b.AUDIO_TRACK_UPDATED,{details:n,id:a,groupId:t.groupId}),this.state!==Ei.WAITING_TRACK||this.waitForCdnTuneIn(n)||(this.state=Ei.IDLE),this.tick()}else this.warn("Audio tracks reset while loading track "+a+' "'+o.name+'" of "'+s+'"')},r._handleFragmentLoadProgress=function(e){var t,r=e.frag,i=e.part,n=e.payload,a=this.config,s=this.trackId,o=this.levels;if(o){var l=o[s];if(l){var u=l.details;if(!u)return this.warn("Audio track details undefined on fragment load progress"),void this.removeUnbufferedFrags(r.start);var d=a.defaultAudioCodec||l.audioCodec||"mp4a.40.2",h=this.transmuxer;h||(h=this.transmuxer=new aa(this.hls,O,this._handleTransmuxComplete.bind(this),this._handleTransmuxerFlush.bind(this)));var f=this.initPTS[r.cc],c=null==(t=r.initSegment)?void 0:t.data;if(void 0!==f){var g=i?i.index:-1,v=-1!==g,m=new tr(r.level,r.sn,r.stats.chunkCount,n.byteLength,g,v);h.push(n,c,d,"",r,i,u.totalduration,!1,m,f)}else this.log("Unknown video PTS for cc "+r.cc+", waiting for video PTS before demuxing audio frag "+r.sn+" of ["+u.startSN+" ,"+u.endSN+"],track "+s),(this.waitingData=this.waitingData||{frag:r,part:i,cache:new Ai,complete:!1}).cache.push(new Uint8Array(n)),this.state!==Ei.STOPPED&&(this.state=Ei.WAITING_INIT_PTS)}else this.warn("Audio track is undefined on fragment load progress")}else this.warn("Audio tracks were reset while fragment load was in progress. Fragment "+r.sn+" of level "+r.level+" will not be buffered")},r._handleFragmentLoadComplete=function(t){this.waitingData?this.waitingData.complete=!0:e.prototype._handleFragmentLoadComplete.call(this,t)},r.onBufferReset=function(){this.mediaBuffer=null},r.onBufferCreated=function(e,t){this.bufferFlushed=this.flushing=!1;var r=t.tracks.audio;r&&(this.mediaBuffer=r.buffer||null)},r.onFragLoading=function(e,t){!this.audioOnly&&t.frag.type===w&&ee(t.frag)&&(this.mainFragLoading=t,this.state===Ei.IDLE&&this.tick())},r.onFragBuffered=function(e,t){var r=t.frag,i=t.part;if(r.type===O)if(this.fragContextChanged(r))this.warn("Fragment "+r.sn+(i?" p: "+i.index:"")+" of level "+r.level+" finished buffering, but was aborted. state: "+this.state+", audioSwitch: "+(this.switchingTrack?this.switchingTrack.name:"false"));else{if(ee(r)){this.fragPrevious=r;var n=this.switchingTrack;n&&(this.bufferedTrack=n,this.switchingTrack=null,this.hls.trigger(b.AUDIO_TRACK_SWITCHED,d({},n)))}this.fragBufferedComplete(r,i),this.media&&this.tick()}else this.audioOnly||r.type!==w||r.elementaryStreams.video||r.elementaryStreams.audiovideo||(this.audioOnly=!0,this.mainFragLoading=null)},r.onError=function(t,r){var i;if(r.fatal)this.state=Ei.ERROR;else switch(r.details){case k.FRAG_GAP:case k.FRAG_PARSING_ERROR:case k.FRAG_DECRYPT_ERROR:case k.FRAG_LOAD_ERROR:case k.FRAG_LOAD_TIMEOUT:case k.KEY_LOAD_ERROR:case k.KEY_LOAD_TIMEOUT:this.onFragmentOrKeyLoadError(O,r);break;case k.AUDIO_TRACK_LOAD_ERROR:case k.AUDIO_TRACK_LOAD_TIMEOUT:case k.LEVEL_PARSING_ERROR:r.levelRetry||this.state!==Ei.WAITING_TRACK||(null==(i=r.context)?void 0:i.type)!==P||(this.state=Ei.IDLE);break;case k.BUFFER_ADD_CODEC_ERROR:case k.BUFFER_APPEND_ERROR:if("audio"!==r.parent)return;this.reduceLengthAndFlushBuffer(r)||this.resetLoadingState();break;case k.BUFFER_FULL_ERROR:if("audio"!==r.parent)return;this.reduceLengthAndFlushBuffer(r)&&(this.bufferedTrack=null,e.prototype.flushMainBuffer.call(this,0,Number.POSITIVE_INFINITY,"audio"));break;case k.INTERNAL_EXCEPTION:this.recoverWorkerError(r)}},r.onBufferFlushing=function(e,t){t.type!==$&&(this.flushing=!0)},r.onBufferFlushed=function(e,t){var r=t.type;if(r!==$){this.flushing=!1,this.bufferFlushed=!0,this.state===Ei.ENDED&&(this.state=Ei.IDLE);var i=this.mediaBuffer||this.media;i&&(this.afterBufferFlushed(i,r,O),this.tick())}},r._handleTransmuxComplete=function(e){var t,r="audio",i=this.hls,n=e.remuxResult,s=e.chunkMeta,o=this.getCurrentContext(s);if(o){var l=o.frag,u=o.part,d=o.level,h=d.details,f=n.audio,c=n.text,g=n.id3,v=n.initSegment;if(!this.fragContextChanged(l)&&h){if(this.state=Ei.PARSING,this.switchingTrack&&f&&this.completeAudioSwitch(this.switchingTrack),null!=v&&v.tracks){var m=l.initSegment||l;this._bufferInitSegment(d,v.tracks,m,s),i.trigger(b.FRAG_PARSING_INIT_SEGMENT,{frag:m,id:r,tracks:v.tracks})}if(f){var p=f.startPTS,y=f.endPTS,E=f.startDTS,T=f.endDTS;u&&(u.elementaryStreams[z]={startPTS:p,endPTS:y,startDTS:E,endDTS:T}),l.setElementaryStreamInfo(z,p,y,E,T),this.bufferFragmentData(f,l,u,s)}if(null!=g&&null!=(t=g.samples)&&t.length){var S=a({id:r,frag:l,details:h},g);i.trigger(b.FRAG_PARSING_METADATA,S)}if(c){var A=a({id:r,frag:l,details:h},c);i.trigger(b.FRAG_PARSING_USERDATA,A)}}else this.fragmentTracker.removeFragment(l)}else this.resetWhenMissingContext(s)},r._bufferInitSegment=function(e,t,r,i){if(this.state===Ei.PARSING&&(t.video&&delete t.video,t.audiovideo&&delete t.audiovideo,t.audio)){var n=t.audio;n.id=O;var a=e.audioCodec;this.log("Init audio buffer, container:"+n.container+", codecs[level/parsed]=["+a+"/"+n.codec+"]"),a&&1===a.split(",").length&&(n.levelCodec=a),this.hls.trigger(b.BUFFER_CODECS,t);var s=n.initSegment;if(null!=s&&s.byteLength){var o={type:"audio",frag:r,part:null,chunkMeta:i,parent:r.type,data:s};this.hls.trigger(b.BUFFER_APPENDING,o)}this.tickImmediate()}},r.loadFragment=function(t,r,i){var n,a=this.fragmentTracker.getState(t);if(this.switchingTrack||a===Mt||a===Nt)if(ee(t))if(null!=(n=r.details)&&n.live&&!this.initPTS[t.cc]){this.log("Waiting for video PTS in continuity counter "+t.cc+" of live stream before loading audio fragment "+t.sn+" of level "+this.trackId),this.state=Ei.WAITING_INIT_PTS;var s=this.mainDetails;s&&s.fragmentStart!==r.details.fragmentStart&&pi(r.details,s)}else e.prototype.loadFragment.call(this,t,r,i);else this._loadInitSegment(t,r);else this.clearTrackerIfNeeded(t)},r.flushAudioIfNeeded=function(t){if(this.media&&this.bufferedTrack){var r=this.bufferedTrack;ht({name:r.name,lang:r.lang,assocLang:r.assocLang,characteristics:r.characteristics,audioCodec:r.audioCodec,channels:r.channels},t,ft)||(gt(t.url,this.hls)?(this.log("Switching audio track : flushing all audio"),e.prototype.flushMainBuffer.call(this,0,Number.POSITIVE_INFINITY,"audio"),this.bufferedTrack=null):this.bufferedTrack=t)}},r.completeAudioSwitch=function(e){var t=this.hls;this.flushAudioIfNeeded(e),this.bufferedTrack=e,this.switchingTrack=null,t.trigger(b.AUDIO_TRACK_SWITCHED,d({},e))},t}(Ti),oa=function(e){function t(t,r){var i;return(i=e.call(this,r,t.logger)||this).hls=void 0,i.canLoad=!1,i.timer=-1,i.hls=t,i}o(t,e);var r=t.prototype;return r.destroy=function(){this.clearTimer(),this.hls=this.log=this.warn=null},r.clearTimer=function(){-1!==this.timer&&(self.clearTimeout(this.timer),this.timer=-1)},r.startLoad=function(){this.canLoad=!0,this.loadPlaylist()},r.stopLoad=function(){this.canLoad=!1,this.clearTimer()},r.switchParams=function(e,t,r){var i=null==t?void 0:t.renditionReports;if(i){for(var n=-1,a=0;a=0&&h>t.partTarget&&(d+=1)}var f=r&&tt(r);return new rt(u,d>=0?d:void 0,f)}}},r.loadPlaylist=function(e){this.clearTimer()},r.loadingPlaylist=function(e,t){this.clearTimer()},r.shouldLoadPlaylist=function(e){return this.canLoad&&!!e&&!!e.url&&(!e.details||e.details.live)},r.getUrlWithDirectives=function(e,t){if(t)try{return t.addDirectives(e)}catch(e){this.warn("Could not construct new URL with HLS Delivery Directives: "+e)}return e},r.playlistLoaded=function(e,t,r){var i=t.details,n=t.stats,a=self.performance.now(),s=n.loading.first?Math.max(0,a-n.loading.first):0;i.advancedDateTime=Date.now()-s;var o=this.hls.config.timelineOffset;if(o!==i.appliedTimelineOffset){var l=Math.max(o||0,0);i.appliedTimelineOffset=l,i.fragments.forEach((function(e){e.start=e.playlistOffset+l}))}if(i.live||null!=r&&r.live){var u="levelInfo"in t?t.levelInfo:t.track;if(i.reloaded(r),r&&i.fragments.length>0){ni(r,i);var d=i.playlistParsingError;if(d){this.warn(d);var h=this.hls;if(!h.config.ignorePlaylistParsingErrors){var f,c=t.networkDetails;return void h.trigger(b.ERROR,{type:I.NETWORK_ERROR,details:k.LEVEL_PARSING_ERROR,fatal:!1,url:i.url,error:d,reason:d.message,level:t.level||void 0,parent:null==(f=i.fragments[0])?void 0:f.type,networkDetails:c,stats:n})}i.playlistParsingError=null}}-1===i.requestScheduled&&(i.requestScheduled=n.loading.start);var g,v=this.hls.mainForwardBufferInfo,m=v?v.end-v.len:0,p=li(i,1e3*(i.edge-m));if(i.requestScheduled+p0){if(_>3*i.targetduration)this.log("Playlist last advanced "+D.toFixed(2)+"s ago. Omitting segment and part directives."),y=void 0,E=void 0;else if(null!=r&&r.tuneInGoal&&_-i.partTarget>r.tuneInGoal)this.warn("CDN Tune-in goal increased from: "+r.tuneInGoal+" to: "+P+" with playlist age: "+i.age),P=0;else{var C=Math.floor(P/i.targetduration);y+=C,void 0!==E&&(E+=Math.round(P%i.targetduration/i.partTarget)),this.log("CDN Tune-in age: "+i.ageHeader+"s last advanced "+D.toFixed(2)+"s goal: "+P+" skip sn "+C+" to part "+E)}i.tuneInGoal=P}if(g=this.getDeliveryDirectives(i,t.deliveryDirectives,y,E),T||!R)return i.requestScheduled=a,void this.loadingPlaylist(u,g)}else(i.canBlockReload||i.canSkipUntil)&&(g=this.getDeliveryDirectives(i,t.deliveryDirectives,y,E));g&&void 0!==y&&i.canBlockReload&&(i.requestScheduled=n.loading.first+Math.max(p-2*s,p/2)),this.scheduleLoading(u,g,i)}else this.clearTimer()},r.scheduleLoading=function(e,t,r){var i=this,n=r||e.details;if(n){var a=self.performance.now(),s=n.requestScheduled;if(a>=s)this.loadingPlaylist(e,t);else{var o=s-a;this.log("reload live playlist "+(e.name||e.bitrate+"bps")+" in "+Math.round(o)+" ms"),this.clearTimer(),this.timer=self.setTimeout((function(){return i.loadingPlaylist(e,t)}),o)}}else this.loadingPlaylist(e,t)},r.getDeliveryDirectives=function(e,t,r,i){var n=tt(e);return null!=t&&t.skip&&e.deltaUpdateFailed&&(r=t.msn,i=t.part,n=Je),new rt(r,i,n)},r.checkRetry=function(e){var t=this,r=e.details,i=St(e),n=e.errorAction,a=n||{},s=a.action,o=a.retryCount,l=void 0===o?0:o,u=a.retryConfig,d=!!n&&!!u&&(s===_t||!n.resolved&&s===bt);if(d){var h;if(l>=u.maxNumRetry)return!1;if(i&&null!=(h=e.context)&&h.deliveryDirectives)this.warn("Retrying playlist loading "+(l+1)+"/"+u.maxNumRetry+' after "'+r+'" without delivery-directives'),this.loadPlaylist();else{var f=Lt(u,l);this.clearTimer(),this.timer=self.setTimeout((function(){return t.loadPlaylist()}),f),this.warn("Retrying playlist loading "+(l+1)+"/"+u.maxNumRetry+' after "'+r+'" in '+f+"ms")}e.levelRetry=!0,n.resolved=!0}return d},t}(N);function la(e,t){if(e.length!==t.length)return!1;for(var r=0;r-1)n=a[o];else{var l=dt(s,this.tracks);n=this.tracks[l]}}var u=this.findTrackId(n);-1===u&&n&&(u=this.findTrackId(null));var d={audioTracks:a};this.log("Updating audio tracks, "+a.length+" track(s) found in group(s): "+(null==r?void 0:r.join(","))),this.hls.trigger(b.AUDIO_TRACKS_UPDATED,d);var h=this.trackId;if(-1!==u&&-1===h)this.setAudioTrack(u);else if(a.length&&-1===h){var f,c=new Error("No audio track selected for current audio group-ID(s): "+(null==(f=this.groupIds)?void 0:f.join(","))+" track count: "+a.length);this.warn(c.message),this.hls.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.AUDIO_TRACK_LOAD_ERROR,fatal:!0,error:c})}}}},r.onError=function(e,t){!t.fatal&&t.context&&(t.context.type!==P||t.context.id!==this.trackId||this.groupIds&&-1===this.groupIds.indexOf(t.context.groupId)||this.checkRetry(t))},r.setAudioOption=function(e){var t=this.hls;if(t.config.audioPreference=e,e){var r=this.allAudioTracks;if(this.selectDefaultTrack=!1,r.length){var i=this.currentTrack;if(i&&ht(e,i,ft))return i;var n=dt(e,this.tracksInGroup,ft);if(n>-1){var a=this.tracksInGroup[n];return this.setAudioTrack(n),a}if(i){var s=t.loadLevel;-1===s&&(s=t.firstAutoLevel);var o=function(e,t,r,i,n){var a=t[i],s=t.reduce((function(e,t,r){var i=t.uri;return(e[i]||(e[i]=[])).push(r),e}),{})[a.uri];s.length>1&&(i=Math.max.apply(Math,s));var o=a.videoRange,l=a.frameRate,u=a.codecSet.substring(0,4),d=ct(t,i,(function(t){if(t.videoRange!==o||t.frameRate!==l||t.codecSet.substring(0,4)!==u)return!1;var i=t.audioGroups,a=r.filter((function(e){return!i||-1!==i.indexOf(e.groupId)}));return dt(e,a,n)>-1}));return d>-1?d:ct(t,i,(function(t){var i=t.audioGroups,a=r.filter((function(e){return!i||-1!==i.indexOf(e.groupId)}));return dt(e,a,n)>-1}))}(e,t.levels,r,s,ft);if(-1===o)return null;t.nextLoadLevel=o}if(e.channels||e.audioCodec){var l=dt(e,r);if(l>-1)return r[l]}}}return null},r.setAudioTrack=function(e){var t=this.tracksInGroup;if(e<0||e>=t.length)this.warn("Invalid audio track id: "+e);else{this.selectDefaultTrack=!1;var r=this.currentTrack,i=t[e],n=i.details&&!i.details.live;if(!(e===this.trackId&&i===r&&n||(this.log("Switching to audio-track "+e+' "'+i.name+'" lang:'+i.lang+" group:"+i.groupId+" channels:"+i.channels),this.trackId=e,this.currentTrack=i,this.hls.trigger(b.AUDIO_TRACK_SWITCHING,d({},i)),n))){var a=this.switchParams(i.url,null==r?void 0:r.details,i.details);this.loadPlaylist(a)}}},r.findTrackId=function(e){for(var t=this.tracksInGroup,r=0;r":"\n"+this.list("video")+"\n"+this.list("audio")+"\n"+this.list("audiovideo")+"}"},t.list=function(e){var t,r;return null!=(t=this.queues)&&t[e]||null!=(r=this.tracks)&&r[e]?e+": ("+this.listSbInfo(e)+") "+this.listOps(e):""},t.listSbInfo=function(e){var t,r=null==(t=this.tracks)?void 0:t[e],i=null==r?void 0:r.buffer;return i?"SourceBuffer"+(i.updating?" updating":"")+(r.ended?" ended":"")+(r.ending?" ending":""):"none"},t.listOps=function(e){var t;return(null==(t=this.queues)?void 0:t[e].map((function(e){return e.label})).join(", "))||""},e}(),ca=/(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/,ga="HlsJsTrackRemovedError",va=function(e){function t(t){var r;return(r=e.call(this,t)||this).name=ga,r}return o(t,e),t}(c(Error)),ma=function(e){function t(t,r){var i,n;return(i=e.call(this,"buffer-controller",t.logger)||this).hls=void 0,i.fragmentTracker=void 0,i.details=null,i._objectUrl=null,i.operationQueue=null,i.bufferCodecEventsTotal=0,i.media=null,i.mediaSource=null,i.lastMpegAudioChunk=null,i.blockedAudioAppend=null,i.lastVideoAppendEnd=0,i.appendSource=void 0,i.transferData=void 0,i.overrides=void 0,i.appendErrors={audio:0,video:0,audiovideo:0},i.tracks={},i.sourceBuffers=[[null,null],[null,null]],i._onEndStreaming=function(e){var t;i.hls&&"open"===(null==(t=i.mediaSource)?void 0:t.readyState)&&i.hls.pauseBuffering()},i._onStartStreaming=function(e){i.hls&&i.hls.resumeBuffering()},i._onMediaSourceOpen=function(e){var t=i,r=t.media,n=t.mediaSource;e&&i.log("Media source opened"),r&&n&&(n.removeEventListener("sourceopen",i._onMediaSourceOpen),r.removeEventListener("emptied",i._onMediaEmptied),i.updateDuration(),i.hls.trigger(b.MEDIA_ATTACHED,{media:r,mediaSource:n}),null!==i.mediaSource&&i.checkPendingTracks())},i._onMediaSourceClose=function(){i.log("Media source closed")},i._onMediaSourceEnded=function(){i.log("Media source ended")},i._onMediaEmptied=function(){var e=i,t=e.mediaSrc,r=e._objectUrl;t!==r&&i.error("Media element src was set while attaching MediaSource ("+r+" > "+t+")")},i.hls=t,i.fragmentTracker=r,i.appendSource=(n=W(t.config.preferManagedMediaSource),"undefined"!=typeof self&&n===self.ManagedMediaSource),i.initTracks(),i.registerListeners(),i}o(t,e);var r=t.prototype;return r.hasSourceTypes=function(){return Object.keys(this.tracks).length>0},r.destroy=function(){this.unregisterListeners(),this.details=null,this.lastMpegAudioChunk=this.blockedAudioAppend=null,this.transferData=this.overrides=void 0,this.operationQueue&&(this.operationQueue.destroy(),this.operationQueue=null),this.hls=this.fragmentTracker=null,this._onMediaSourceOpen=this._onMediaSourceClose=null,this._onMediaSourceEnded=null,this._onStartStreaming=this._onEndStreaming=null},r.registerListeners=function(){var e=this.hls;e.on(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.MANIFEST_PARSED,this.onManifestParsed,this),e.on(b.BUFFER_RESET,this.onBufferReset,this),e.on(b.BUFFER_APPENDING,this.onBufferAppending,this),e.on(b.BUFFER_CODECS,this.onBufferCodecs,this),e.on(b.BUFFER_EOS,this.onBufferEos,this),e.on(b.BUFFER_FLUSHING,this.onBufferFlushing,this),e.on(b.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(b.FRAG_PARSED,this.onFragParsed,this),e.on(b.FRAG_CHANGED,this.onFragChanged,this),e.on(b.ERROR,this.onError,this)},r.unregisterListeners=function(){var e=this.hls;e.off(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.MANIFEST_PARSED,this.onManifestParsed,this),e.off(b.BUFFER_RESET,this.onBufferReset,this),e.off(b.BUFFER_APPENDING,this.onBufferAppending,this),e.off(b.BUFFER_CODECS,this.onBufferCodecs,this),e.off(b.BUFFER_EOS,this.onBufferEos,this),e.off(b.BUFFER_FLUSHING,this.onBufferFlushing,this),e.off(b.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(b.FRAG_PARSED,this.onFragParsed,this),e.off(b.FRAG_CHANGED,this.onFragChanged,this),e.off(b.ERROR,this.onError,this)},r.transferMedia=function(){var e=this,t=this.media,r=this.mediaSource;if(!t)return null;var i={};if(this.operationQueue){var n=this.isUpdating();n||this.operationQueue.removeBlockers();var s=this.isQueued();(n||s)&&this.warn("Transfering MediaSource with"+(s?" operations in queue":"")+(n?" updating SourceBuffer(s)":"")+" "+this.operationQueue),this.operationQueue.destroy()}var o=this.transferData;return!this.sourceBufferCount&&o&&o.mediaSource===r?a(i,o.tracks):this.sourceBuffers.forEach((function(t){var r=t[0];r&&(i[r]=a({},e.tracks[r]),e.removeBuffer(r)),t[0]=t[1]=null})),{media:t,mediaSource:r,tracks:i}},r.initTracks=function(){this.sourceBuffers=[[null,null],[null,null]],this.tracks={},this.resetQueue(),this.resetAppendErrors(),this.lastMpegAudioChunk=this.blockedAudioAppend=null,this.lastVideoAppendEnd=0},r.onManifestLoading=function(){this.bufferCodecEventsTotal=0,this.details=null},r.onManifestParsed=function(e,t){var r,i=2;(t.audio&&!t.video||!t.altAudio)&&(i=1),this.bufferCodecEventsTotal=i,this.log(i+" bufferCodec event(s) expected."),null!=(r=this.transferData)&&r.mediaSource&&this.sourceBufferCount&&i&&this.bufferCreated()},r.onMediaAttaching=function(e,t){var r=this.media=t.media,i=W(this.appendSource);if(this.transferData=this.overrides=void 0,r&&i){var n=!!t.mediaSource;(n||t.overrides)&&(this.transferData=t,this.overrides=t.overrides);var a=this.mediaSource=t.mediaSource||new i;if(this.assignMediaSource(a),n)this._objectUrl=r.src,this.attachTransferred();else{var s=this._objectUrl=self.URL.createObjectURL(a);if(this.appendSource)try{r.removeAttribute("src");var o=self.ManagedMediaSource;r.disableRemotePlayback=r.disableRemotePlayback||o&&a instanceof o,pa(r),function(e,t){var r=self.document.createElement("source");r.type="video/mp4",r.src=t,e.appendChild(r)}(r,s),r.load()}catch(e){r.src=s}else r.src=s}r.addEventListener("emptied",this._onMediaEmptied)}},r.assignMediaSource=function(e){var t,r;this.log(((null==(t=this.transferData)?void 0:t.mediaSource)===e?"transferred":"created")+" media source: "+(null==(r=e.constructor)?void 0:r.name)),e.addEventListener("sourceopen",this._onMediaSourceOpen),e.addEventListener("sourceended",this._onMediaSourceEnded),e.addEventListener("sourceclose",this._onMediaSourceClose),this.appendSource&&(e.addEventListener("startstreaming",this._onStartStreaming),e.addEventListener("endstreaming",this._onEndStreaming))},r.attachTransferred=function(){var e=this,t=this.media,r=this.transferData;if(r&&t){var i=this.tracks,n=r.tracks,a=n?Object.keys(n):null,s=a?a.length:0,o=function(){e.media&&e.mediaSourceOpenOrEnded&&e._onMediaSourceOpen()};if(n&&a&&s){if(!this.tracksReady)return this.hls.config.startFragPrefetch=!0,void this.log("attachTransferred: waiting for SourceBuffer track info");if(this.log("attachTransferred: (bufferCodecEventsTotal "+this.bufferCodecEventsTotal+")\nrequired tracks: "+st(i,(function(e,t){return"initSegment"===e?void 0:t}))+";\ntransfer tracks: "+st(n,(function(e,t){return"initSegment"===e?void 0:t}))+"}"),!j(n,i)){r.mediaSource=null,r.tracks=void 0;var l=t.currentTime,u=this.details,d=Math.max(l,(null==u?void 0:u.fragments[0].start)||0);return d-l>1?void this.log("attachTransferred: waiting for playback to reach new tracks start time "+l+" -> "+d):(this.warn('attachTransferred: resetting MediaSource for incompatible tracks ("'+Object.keys(n)+'"->"'+Object.keys(i)+'") start time: '+d+" currentTime: "+l),this.onMediaDetaching(b.MEDIA_DETACHING,{}),this.onMediaAttaching(b.MEDIA_ATTACHING,r),void(t.currentTime=d))}this.transferData=void 0,a.forEach((function(t){var r=t,i=n[r];if(i){var a=i.buffer;if(a){var s=e.fragmentTracker,o=i.id;if(s.hasFragments(o)||s.hasParts(o)){var l=ir.getBuffered(a);s.detectEvictedFragments(r,l,o,null,!0)}var u=ya(r),d=[r,a];e.sourceBuffers[u]=d,a.updating&&e.operationQueue&&e.operationQueue.prependBlocker(r),e.trackSourceBuffer(r,i)}}})),o(),this.bufferCreated()}else this.log("attachTransferred: MediaSource w/o SourceBuffers"),o()}},r.onMediaDetaching=function(e,t){var r=this,i=!!t.transferMedia;this.transferData=this.overrides=void 0;var n=this.media,a=this.mediaSource,s=this._objectUrl;if(a){if(this.log("media source "+(i?"transferring":"detaching")),i)this.sourceBuffers.forEach((function(e){var t=e[0];t&&r.removeBuffer(t)})),this.resetQueue();else{if(this.mediaSourceOpenOrEnded){var o="open"===a.readyState;try{for(var l=a.sourceBuffers,u=l.length;u--;)o&&l[u].abort(),a.removeSourceBuffer(l[u]);o&&a.endOfStream()}catch(e){this.warn("onMediaDetaching: "+e.message+" while calling endOfStream")}}this.sourceBufferCount&&this.onBufferReset()}a.removeEventListener("sourceopen",this._onMediaSourceOpen),a.removeEventListener("sourceended",this._onMediaSourceEnded),a.removeEventListener("sourceclose",this._onMediaSourceClose),this.appendSource&&(a.removeEventListener("startstreaming",this._onStartStreaming),a.removeEventListener("endstreaming",this._onEndStreaming)),this.mediaSource=null,this._objectUrl=null}n&&(n.removeEventListener("emptied",this._onMediaEmptied),i||(s&&self.URL.revokeObjectURL(s),this.mediaSrc===s?(n.removeAttribute("src"),this.appendSource&&pa(n),n.load()):this.warn("media|source.src was changed by a third party - skip cleanup")),this.media=null),this.hls.trigger(b.MEDIA_DETACHED,t)},r.onBufferReset=function(){var e=this;this.sourceBuffers.forEach((function(t){var r=t[0];r&&e.resetBuffer(r)})),this.initTracks()},r.resetBuffer=function(e){var t,r=null==(t=this.tracks[e])?void 0:t.buffer;if(this.removeBuffer(e),r)try{var i;null!=(i=this.mediaSource)&&i.sourceBuffers.length&&this.mediaSource.removeSourceBuffer(r)}catch(t){this.warn("onBufferReset "+e,t)}delete this.tracks[e]},r.removeBuffer=function(e){this.removeBufferListeners(e),this.sourceBuffers[ya(e)]=[null,null];var t=this.tracks[e];t&&(t.buffer=void 0)},r.resetQueue=function(){this.operationQueue&&this.operationQueue.destroy(),this.operationQueue=new fa(this.tracks)},r.onBufferCodecs=function(e,t){var r=this,i=this.tracks,n=Object.keys(t);this.log('BUFFER_CODECS: "'+n+'" (current SB count '+this.sourceBufferCount+")");var a="audiovideo"in t&&(i.audio||i.video)||i.audiovideo&&("audio"in t||"video"in t),s=!a&&this.sourceBufferCount&&this.media&&n.some((function(e){return!i[e]}));a||s?this.warn('Unsupported transition between "'+Object.keys(i)+'" and "'+n+'" SourceBuffers'):(n.forEach((function(e){var n,a,s,o=t[e],l=o.id,u=o.codec,d=o.levelCodec,h=o.container,f=o.metadata,c=o.supplemental,g=i[e],v=null==(n=r.transferData)||null==(a=n.tracks)?void 0:a[e],m=null!=v&&v.buffer?v:g,p=(null==m?void 0:m.pendingCodec)||(null==m?void 0:m.codec),y=null==m?void 0:m.levelCodec;g||(g=i[e]={buffer:void 0,listeners:[],codec:u,supplemental:c,container:h,levelCodec:d,metadata:f,id:l});var E=Ge(p,y),T=null==E?void 0:E.replace(ca,"$1"),S=Ge(u,d),A=null==(s=S)?void 0:s.replace(ca,"$1");S&&E&&T!==A&&("audio"===e.slice(0,5)&&(S=Be(S,r.appendSource)),r.log("switching codec "+p+" to "+S),S!==(g.pendingCodec||g.codec)&&(g.pendingCodec=S),g.container=h,r.appendChangeType(e,h,S))})),(this.tracksReady||this.sourceBufferCount)&&(t.tracks=this.sourceBufferTracks),this.sourceBufferCount||this.mediaSourceOpenOrEnded&&this.checkPendingTracks())},r.appendChangeType=function(e,t,r){var i=this,n=t+";codecs="+r,a={label:"change-type="+n,execute:function(){var a=i.tracks[e];if(a){var s=a.buffer;null!=s&&s.changeType&&(i.log("changing "+e+" sourceBuffer type to "+n),s.changeType(n),a.codec=r,a.container=t)}i.shiftAndExecuteNext(e)},onStart:function(){},onComplete:function(){},onError:function(t){i.warn("Failed to change "+e+" SourceBuffer type",t)}};this.append(a,e,this.isPending(this.tracks[e]))},r.blockAudio=function(e){var t,r=this,i=e.start,n=i+.05*e.duration;if(!0!==(null==(t=this.fragmentTracker.getAppendedFrag(i,w))?void 0:t.gap)){var a={label:"block-audio",execute:function(){var e,t=r.tracks.video;(r.lastVideoAppendEnd>n||null!=t&&t.buffer&&ir.isBuffered(t.buffer,n)||!0===(null==(e=r.fragmentTracker.getAppendedFrag(n,w))?void 0:e.gap))&&(r.blockedAudioAppend=null,r.shiftAndExecuteNext("audio"))},onStart:function(){},onComplete:function(){},onError:function(e){r.warn("Error executing block-audio operation",e)}};this.blockedAudioAppend={op:a,frag:e},this.append(a,"audio",!0)}},r.unblockAudio=function(){var e=this.blockedAudioAppend,t=this.operationQueue;e&&t&&(this.blockedAudioAppend=null,t.unblockAudio(e.op))},r.onBufferAppending=function(e,t){var r=this,i=this.tracks,n=t.data,a=t.type,s=t.parent,o=t.frag,l=t.part,u=t.chunkMeta,d=t.offset,h=u.buffering[a],f=o.sn,c=o.cc,g=self.performance.now();h.start=g;var v=o.stats.buffering,m=l?l.stats.buffering:null;0===v.start&&(v.start=g),m&&0===m.start&&(m.start=g);var p=i.audio,y=!1;"audio"===a&&"audio/mpeg"===(null==p?void 0:p.container)&&(y=!this.lastMpegAudioChunk||1===u.id||this.lastMpegAudioChunk.sn!==u.sn,this.lastMpegAudioChunk=u);var E=i.video,T=null==E?void 0:E.buffer;if(T&&"initSegment"!==f){var S=l||o,L=this.blockedAudioAppend;if("audio"!==a||"main"===s||this.blockedAudioAppend){if("video"===a){var R=S.end;if(L){var D=L.frag.start;(R>D||R=r.hls.config.appendErrorMaxRetry||n)&&(i.fatal=!0)}r.hls.trigger(b.ERROR,i)}};this.append(O,a,this.isPending(this.tracks[a]))},r.getFlushOp=function(e,t,r){var i=this;return this.log('queuing "'+e+'" remove '+t+"-"+r),{label:"remove",execute:function(){i.removeExecutor(e,t,r)},onStart:function(){},onComplete:function(){i.hls.trigger(b.BUFFER_FLUSHED,{type:e})},onError:function(n){i.warn("Failed to remove "+t+"-"+r+' from "'+e+'" SourceBuffer',n)}}},r.onBufferFlushing=function(e,t){var r=this,i=t.type,n=t.startOffset,a=t.endOffset;i?this.append(this.getFlushOp(i,n,a),i):this.sourceBuffers.forEach((function(e){var t=e[0];t&&r.append(r.getFlushOp(t,n,a),t)}))},r.onFragParsed=function(e,t){var r=this,i=t.frag,n=t.part,a=[],s=n?n.elementaryStreams:i.elementaryStreams;s[J]?a.push("audiovideo"):(s[z]&&a.push("audio"),s[$]&&a.push("video")),0===a.length&&this.warn("Fragments must have at least one ElementaryStreamType set. type: "+i.type+" level: "+i.level+" sn: "+i.sn),this.blockBuffers((function(){var e=self.performance.now();i.stats.buffering.end=e,n&&(n.stats.buffering.end=e);var t=n?n.stats:i.stats;r.hls.trigger(b.FRAG_BUFFERED,{frag:i,part:n,stats:t,id:i.type})}),a).catch((function(e){r.warn("Fragment buffered callback "+e),r.stepOperationQueue(r.sourceBufferTypes)}))},r.onFragChanged=function(e,t){this.trimBuffers()},r.onBufferEos=function(e,t){var r,i=this;this.sourceBuffers.forEach((function(e){var r=e[0];if(r){var n=i.tracks[r];t.type&&t.type!==r||(n.ending=!0,n.ended||(n.ended=!0,i.log(r+" buffer reached EOS")))}}));var n=!1!==(null==(r=this.overrides)?void 0:r.endOfStream);this.sourceBufferCount>0&&!this.sourceBuffers.some((function(e){var t,r=e[0];return r&&!(null!=(t=i.tracks[r])&&t.ended)}))&&(n?(this.log("Queueing EOS"),this.blockUntilOpen((function(){i.tracksEnded();var e=i.mediaSource;e&&"open"===e.readyState?(i.log("Calling mediaSource.endOfStream()"),e.endOfStream(),i.hls.trigger(b.BUFFERED_TO_END,void 0)):e&&i.log("Could not call mediaSource.endOfStream(). mediaSource.readyState: "+e.readyState)}))):(this.tracksEnded(),this.hls.trigger(b.BUFFERED_TO_END,void 0)))},r.tracksEnded=function(){var e=this;this.sourceBuffers.forEach((function(t){var r=t[0];if(null!==r){var i=e.tracks[r];i&&(i.ending=!1)}}))},r.onLevelUpdated=function(e,t){var r=t.details;r.fragments.length&&(this.details=r,this.updateDuration())},r.updateDuration=function(){var e=this;this.blockUntilOpen((function(){var t=e.getDurationAndRange();t&&e.updateMediaSource(t)}))},r.onError=function(e,t){if(t.details===k.BUFFER_APPEND_ERROR&&t.frag){var r,i=null==(r=t.errorAction)?void 0:r.nextAutoLevel;A(i)&&i!==t.frag.level&&this.resetAppendErrors()}},r.resetAppendErrors=function(){this.appendErrors={audio:0,video:0,audiovideo:0}},r.trimBuffers=function(){var e=this.hls,t=this.details,r=this.media;if(r&&null!==t&&this.sourceBufferCount){var i=e.config,n=r.currentTime,a=t.levelTargetDuration,s=t.live&&null!==i.liveBackBufferLength?i.liveBackBufferLength:i.backBufferLength;if(A(s)&&s>=0){var o=Math.max(s,a),l=Math.floor(n/a)*a-o;this.flushBackBuffer(n,a,l)}if(A(i.frontBufferFlushThreshold)&&i.frontBufferFlushThreshold>0){var u=Math.max(i.maxBufferLength,i.frontBufferFlushThreshold),d=Math.max(u,a),h=Math.floor(n/a)*a+d;this.flushFrontBuffer(n,a,h)}}},r.flushBackBuffer=function(e,t,r){var i=this;this.sourceBuffers.forEach((function(e){var t=e[0],n=e[1];if(n){var a=ir.getBuffered(n);if(a.length>0&&r>a.start(0)){var s;i.hls.trigger(b.BACK_BUFFER_REACHED,{bufferEnd:r});var o=i.tracks[t];if(null!=(s=i.details)&&s.live)i.hls.trigger(b.LIVE_BACK_BUFFER_REACHED,{bufferEnd:r});else if(null!=o&&o.ended)return void i.log("Cannot flush "+t+" back buffer while SourceBuffer is in ended state");i.hls.trigger(b.BUFFER_FLUSHING,{startOffset:0,endOffset:r,type:t})}}}))},r.flushFrontBuffer=function(e,t,r){var i=this;this.sourceBuffers.forEach((function(t){var n=t[0],a=t[1];if(a){var s=ir.getBuffered(a),o=s.length;if(o<2)return;var l=s.start(o-1),u=s.end(o-1);if(r>l||e>=l&&e<=u)return;i.hls.trigger(b.BUFFER_FLUSHING,{startOffset:l,endOffset:1/0,type:n})}}))},r.getDurationAndRange=function(){var e,t=this.details,r=this.mediaSource;if(!t||!this.media||"open"!==(null==r?void 0:r.readyState))return null;var i=t.edge;if(t.live&&this.hls.config.liveDurationInfinity){if(t.fragments.length&&t.live&&r.setLiveSeekableRange){var n=Math.max(0,t.fragmentStart);return{duration:1/0,start:n,end:Math.max(n,i)}}return{duration:1/0}}var a=null==(e=this.overrides)?void 0:e.duration;if(a)return A(a)?{duration:a}:null;var s=this.media.duration;return i>(A(r.duration)?r.duration:0)&&i>s||!A(s)?{duration:i}:null},r.updateMediaSource=function(e){var t=e.duration,r=e.start,i=e.end,n=this.mediaSource;this.media&&n&&"open"===n.readyState&&(n.duration!==t&&(A(t)&&this.log("Updating MediaSource duration to "+t.toFixed(3)),n.duration=t),void 0!==r&&void 0!==i&&(this.log("MediaSource duration is set to "+n.duration+". Setting seekable range to "+r+"-"+i+"."),n.setLiveSeekableRange(r,i)))},r.checkPendingTracks=function(){var e=this.bufferCodecEventsTotal,t=this.pendingTrackCount,r=this.tracks;if(this.log("checkPendingTracks (pending: "+t+" codec events expected: "+e+") "+st(r)),this.tracksReady){var i,n=null==(i=this.transferData)?void 0:i.tracks;n&&Object.keys(n).length?this.attachTransferred():this.createSourceBuffers()}},r.bufferCreated=function(){var e=this;if(this.sourceBufferCount){var t={};this.sourceBuffers.forEach((function(r){var i=r[0],n=r[1];if(i){var a=e.tracks[i];t[i]={buffer:n,container:a.container,codec:a.codec,supplemental:a.supplemental,levelCodec:a.levelCodec,id:a.id,metadata:a.metadata}}})),this.hls.trigger(b.BUFFER_CREATED,{tracks:t}),this.log("SourceBuffers created. Running queue: "+this.operationQueue),this.sourceBuffers.forEach((function(t){var r=t[0];e.executeNext(r)}))}else{var r=new Error("could not create source buffer for media codec(s)");this.hls.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.BUFFER_INCOMPATIBLE_CODECS_ERROR,fatal:!0,error:r,reason:r.message})}},r.createSourceBuffers=function(){var e=this.tracks,t=this.sourceBuffers,r=this.mediaSource;if(!r)throw new Error("createSourceBuffers called when mediaSource was null");for(var i in e){var n=i,a=e[n];if(this.isPending(a)){var s=this.getTrackCodec(a,n),o=a.container+";codecs="+s;a.codec=s,this.log("creating sourceBuffer("+o+")"+(this.currentOp(n)?" Queued":"")+" "+st(a));try{var l=r.addSourceBuffer(o),u=ya(n),d=[n,l];t[u]=d,a.buffer=l}catch(e){var h;return this.error("error while trying to add sourceBuffer: "+e.message),this.shiftAndExecuteNext(n),null==(h=this.operationQueue)||h.removeBlockers(),delete this.tracks[n],void this.hls.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.BUFFER_ADD_CODEC_ERROR,fatal:!1,error:e,sourceBufferName:n,mimeType:o,parent:a.id})}this.trackSourceBuffer(n,a)}}this.bufferCreated()},r.getTrackCodec=function(e,t){var r=e.supplemental,i=e.codec;r&&("video"===t||"audiovideo"===t)&&we(r,"video")&&(i=function(e,t){var r=[];if(e)for(var i=e.split(","),n=0;n=r&&(this.log("Updating "+i+" SourceBuffer timestampOffset to "+t+" (sn: "+n+" cc: "+a+")"),e.timestampOffset=t)},r.removeExecutor=function(e,t,r){var i=this.media,n=this.mediaSource,a=this.tracks[e],s=null==a?void 0:a.buffer;if(!i||!n||!s)return this.warn("Attempting to remove from the "+e+" SourceBuffer, but it does not exist"),void this.shiftAndExecuteNext(e);var o=A(i.duration)?i.duration:1/0,l=A(n.duration)?n.duration:1/0,u=Math.max(0,t),d=Math.min(r,o,l);d>u&&(!a.ending||a.ended)?(a.ended=!1,this.log("Removing ["+u+","+d+"] from the "+e+" SourceBuffer"),s.remove(u,d)):this.shiftAndExecuteNext(e)},r.appendExecutor=function(e,t){var r=this.tracks[t],i=null==r?void 0:r.buffer;if(!i)throw new va("Attempting to append to the "+t+" SourceBuffer, but it does not exist");r.ending=!1,r.ended=!1,i.appendBuffer(e)},r.blockUntilOpen=function(e){var t=this;if(this.isUpdating()||this.isQueued())this.blockBuffers(e).catch((function(e){t.warn("SourceBuffer blocked callback "+e),t.stepOperationQueue(t.sourceBufferTypes)}));else try{e()}catch(e){this.warn("Callback run without blocking "+this.operationQueue+" "+e)}},r.isUpdating=function(){return this.sourceBuffers.some((function(e){var t=e[0],r=e[1];return t&&r.updating}))},r.isQueued=function(){var e=this;return this.sourceBuffers.some((function(t){var r=t[0];return r&&!!e.currentOp(r)}))},r.isPending=function(e){return!!e&&!e.buffer},r.blockBuffers=function(e,t){var r=this;if(void 0===t&&(t=this.sourceBufferTypes),!t.length)return this.log("Blocking operation requested, but no SourceBuffers exist"),Promise.resolve().then(e);var i=this.operationQueue,n=t.map((function(e){return r.appendBlocker(e)}));return t.length>1&&!!this.blockedAudioAppend&&this.unblockAudio(),Promise.all(n).then((function(t){i===r.operationQueue&&(e(),r.stepOperationQueue(r.sourceBufferTypes))}))},r.stepOperationQueue=function(e){var t=this;e.forEach((function(e){var r,i=null==(r=t.tracks[e])?void 0:r.buffer;i&&!i.updating&&t.shiftAndExecuteNext(e)}))},r.append=function(e,t,r){this.operationQueue&&this.operationQueue.append(e,t,r)},r.appendBlocker=function(e){if(this.operationQueue)return this.operationQueue.appendBlocker(e)},r.currentOp=function(e){return this.operationQueue?this.operationQueue.current(e):null},r.executeNext=function(e){e&&this.operationQueue&&this.operationQueue.executeNext(e)},r.shiftAndExecuteNext=function(e){this.operationQueue&&this.operationQueue.shiftAndExecuteNext(e)},r.addBufferListener=function(e,t,r){var i=this.tracks[e];if(i){var n=i.buffer;if(n){var a=r.bind(this,e);i.listeners.push({event:t,listener:a}),n.addEventListener(t,a)}}},r.removeBufferListeners=function(e){var t=this.tracks[e];if(t){var r=t.buffer;r&&(t.listeners.forEach((function(e){r.removeEventListener(e.event,e.listener)})),t.listeners.length=0)}},i(t,[{key:"mediaSourceOpenOrEnded",get:function(){var e,t=null==(e=this.mediaSource)?void 0:e.readyState;return"open"===t||"ended"===t}},{key:"sourceBufferTracks",get:function(){var e=this;return Object.keys(this.tracks).reduce((function(t,r){var i=e.tracks[r];return t[r]={id:i.id,container:i.container,codec:i.codec,levelCodec:i.levelCodec},t}),{})}},{key:"bufferedToEnd",get:function(){var e=this;return this.sourceBufferCount>0&&!this.sourceBuffers.some((function(t){var r,i,n=t[0];return n&&(!(null!=(r=e.tracks[n])&&r.ended)||(null==(i=e.tracks[n])?void 0:i.ending))}))}},{key:"tracksReady",get:function(){var e=this.pendingTrackCount;return e>0&&(e>=this.bufferCodecEventsTotal||this.isPending(this.tracks.audiovideo))}},{key:"mediaSrc",get:function(){var e,t,r=(null==(e=this.media)||null==(t=e.querySelector)?void 0:t.call(e,"source"))||this.media;return null==r?void 0:r.src}},{key:"pendingTrackCount",get:function(){var e=this;return Object.keys(this.tracks).reduce((function(t,r){return t+(e.isPending(e.tracks[r])?1:0)}),0)}},{key:"sourceBufferCount",get:function(){return this.sourceBuffers.reduce((function(e,t){return e+(t[0]?1:0)}),0)}},{key:"sourceBufferTypes",get:function(){return this.sourceBuffers.map((function(e){return e[0]})).filter((function(e){return!!e}))}}])}(N);function pa(e){var t=e.querySelectorAll("source");[].slice.call(t).forEach((function(t){e.removeChild(t)}))}function ya(e){return"audio"===e?1:0}var Ea,Ta=function(){function e(e){this.hls=void 0,this.autoLevelCapping=void 0,this.firstLevel=void 0,this.media=void 0,this.restrictedLevels=void 0,this.timer=void 0,this.clientRect=void 0,this.streamController=void 0,this.hls=e,this.autoLevelCapping=Number.POSITIVE_INFINITY,this.firstLevel=-1,this.media=null,this.restrictedLevels=[],this.timer=void 0,this.clientRect=null,this.registerListeners()}var t=e.prototype;return t.setStreamController=function(e){this.streamController=e},t.destroy=function(){this.hls&&this.unregisterListener(),this.timer&&this.stopCapping(),this.media=null,this.clientRect=null,this.hls=this.streamController=null},t.registerListeners=function(){var e=this.hls;e.on(b.FPS_DROP_LEVEL_CAPPING,this.onFpsDropLevelCapping,this),e.on(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(b.MANIFEST_PARSED,this.onManifestParsed,this),e.on(b.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(b.BUFFER_CODECS,this.onBufferCodecs,this),e.on(b.MEDIA_DETACHING,this.onMediaDetaching,this)},t.unregisterListener=function(){var e=this.hls;e.off(b.FPS_DROP_LEVEL_CAPPING,this.onFpsDropLevelCapping,this),e.off(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(b.MANIFEST_PARSED,this.onManifestParsed,this),e.off(b.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(b.BUFFER_CODECS,this.onBufferCodecs,this),e.off(b.MEDIA_DETACHING,this.onMediaDetaching,this)},t.onFpsDropLevelCapping=function(e,t){var r=this.hls.levels[t.droppedLevel];this.isLevelAllowed(r)&&this.restrictedLevels.push({bitrate:r.bitrate,height:r.height,width:r.width})},t.onMediaAttaching=function(e,t){this.media=t.media instanceof HTMLVideoElement?t.media:null,this.clientRect=null,this.timer&&this.hls.levels.length&&this.detectPlayerSize()},t.onManifestParsed=function(e,t){var r=this.hls;this.restrictedLevels=[],this.firstLevel=t.firstLevel,r.config.capLevelToPlayerSize&&t.video&&this.startCapping()},t.onLevelsUpdated=function(e,t){this.timer&&A(this.autoLevelCapping)&&this.detectPlayerSize()},t.onBufferCodecs=function(e,t){this.hls.config.capLevelToPlayerSize&&t.video&&this.startCapping()},t.onMediaDetaching=function(){this.stopCapping(),this.media=null},t.detectPlayerSize=function(){if(this.media){if(this.mediaHeight<=0||this.mediaWidth<=0)return void(this.clientRect=null);var e=this.hls.levels;if(e.length){var t=this.hls,r=this.getMaxLevel(e.length-1);r!==this.autoLevelCapping&&t.logger.log("Setting autoLevelCapping to "+r+": "+e[r].height+"p@"+e[r].bitrate+" for media "+this.mediaWidth+"x"+this.mediaHeight),t.autoLevelCapping=r,t.autoLevelEnabled&&t.autoLevelCapping>this.autoLevelCapping&&this.streamController&&this.streamController.nextLevelSwitch(),this.autoLevelCapping=t.autoLevelCapping}}},t.getMaxLevel=function(t){var r=this,i=this.hls.levels;if(!i.length)return-1;var n=i.filter((function(e,i){return r.isLevelAllowed(e)&&i<=t}));return this.clientRect=null,e.getMaxLevelByMediaSize(n,this.mediaWidth,this.mediaHeight)},t.startCapping=function(){this.timer||(this.autoLevelCapping=Number.POSITIVE_INFINITY,self.clearInterval(this.timer),this.timer=self.setInterval(this.detectPlayerSize.bind(this),1e3),this.detectPlayerSize())},t.stopCapping=function(){this.restrictedLevels=[],this.firstLevel=-1,this.autoLevelCapping=Number.POSITIVE_INFINITY,this.timer&&(self.clearInterval(this.timer),this.timer=void 0)},t.getDimensions=function(){if(this.clientRect)return this.clientRect;var e=this.media,t={width:0,height:0};if(e){var r=e.getBoundingClientRect();t.width=r.width,t.height=r.height,t.width||t.height||(t.width=r.right-r.left||e.width||0,t.height=r.bottom-r.top||e.height||0)}return this.clientRect=t,t},t.isLevelAllowed=function(e){return!this.restrictedLevels.some((function(t){return e.bitrate===t.bitrate&&e.width===t.width&&e.height===t.height}))},e.getMaxLevelByMediaSize=function(e,t,r){if(null==e||!e.length)return-1;for(var i,n,a=e.length-1,s=Math.max(t,r),o=0;o=s||l.height>=s)&&(i=l,!(n=e[o+1])||i.width!==n.width||i.height!==n.height)){a=o;break}}return a},i(e,[{key:"mediaWidth",get:function(){return this.getDimensions().width*this.contentScaleFactor}},{key:"mediaHeight",get:function(){return this.getDimensions().height*this.contentScaleFactor}},{key:"contentScaleFactor",get:function(){var e=1;if(!this.hls.config.ignoreDevicePixelRatio)try{e=self.devicePixelRatio}catch(e){}return Math.min(e,this.hls.config.maxDevicePixelRatio)}}])}(),Sa={MANIFEST:"m",AUDIO:"a",VIDEO:"v",MUXED:"av",INIT:"i",CAPTION:"c",TIMED_TEXT:"tt",KEY:"k",OTHER:"o"},Aa={HLS:"h"},La={OBJECT:"CMCD-Object",REQUEST:"CMCD-Request",SESSION:"CMCD-Session",STATUS:"CMCD-Status"},Ra=((Ea={})[La.OBJECT]=["br","d","ot","tb"],Ea[La.REQUEST]=["bl","dl","mtp","nor","nrr","su"],Ea[La.SESSION]=["cid","pr","sf","sid","st","v"],Ea[La.STATUS]=["bs","rtp"],Ea),Ia=function e(t,r){Array.isArray(t)&&(t=t.map((function(t){return t instanceof e?t:new e(t)}))),this.value=t,this.params=r},ka="Dict";function ba(e,t,r,i){return new Error("failed to "+e+' "'+(n=t,(Array.isArray(n)?JSON.stringify(n):n instanceof Map?"Map{}":n instanceof Set?"Set{}":"object"==typeof n?JSON.stringify(n):String(n))+'" as ')+r,{cause:i});var n}function Da(e,t,r){return ba("serialize",e,t,r)}var _a=function(e){this.description=e},Pa="Bare Item",Ca="Boolean",wa="Byte Sequence";function Oa(e){if(!1===ArrayBuffer.isView(e))throw Da(e,wa);return":"+(t=e,btoa(String.fromCharCode.apply(String,t))+":");var t}var xa="Integer";function Ma(e){if(function(e){return e<-999999999999999||99999999999999912)throw Da(e,Na);var r=t.toString();return r.includes(".")?r:r+".0"}var Ba="String",Ga=/[\x00-\x1f\x7f]+/,Ka="Token";function Va(e){var t,r=(t=e).description||t.toString().slice(7,-1);if(!1===/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(r))throw Da(r,Ka);return r}function Ha(e){switch(typeof e){case"number":if(!A(e))throw Da(e,Pa);return Number.isInteger(e)?Ma(e):Ua(e);case"string":return function(e){if(Ga.test(e))throw Da(e,Ba);return'"'+e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')+'"'}(e);case"symbol":return Va(e);case"boolean":return function(e){if("boolean"!=typeof e)throw Da(e,Ca);return e?"?1":"?0"}(e);case"object":if(e instanceof Date)return function(e){return"@"+Ma(e.getTime()/1e3)}(e);if(e instanceof Uint8Array)return Oa(e);if(e instanceof _a)return Va(e);default:throw Da(e,Pa)}}var Ya="Key";function Wa(e){if(!1===/^[a-z*][a-z0-9\-_.*]*$/.test(e))throw Da(e,Ya);return e}function ja(e){return null==e?"":Object.entries(e).map((function(e){var t=e[0],r=e[1];return!0===r?";"+Wa(t):";"+Wa(t)+"="+Ha(r)})).join("")}function qa(e){return e instanceof Ia?""+Ha(e.value)+ja(e.params):Ha(e)}function Xa(e,t){if(void 0===t&&(t={whitespace:!0}),"object"!=typeof e)throw Da(e,ka);var r=e instanceof Map?e.entries():Object.entries(e),i=(null==t?void 0:t.whitespace)?" ":"";return Array.from(r).map((function(e){var t=e[0],r=e[1];r instanceof Ia==0&&(r=new Ia(r));var i,n=Wa(t);return!0===r.value?n+=ja(r.params):(n+="=",Array.isArray(r.value)?n+="("+(i=r).value.map(qa).join(" ")+")"+ja(i.params):n+=qa(r)),n})).join(","+i)}var Qa=function(e){return Math.round(e)},za=function(e){return 100*Qa(e/100)},$a={br:Qa,d:Qa,bl:za,dl:za,mtp:za,nor:function(e,t){return(null==t?void 0:t.baseUrl)&&(e=function(e,t){var r=new URL(e),i=new URL(t);if(r.origin!==i.origin)return e;for(var n=r.pathname.split("/").slice(1),a=i.pathname.split("/").slice(1,-1);n[0]===a[0];)n.shift(),a.shift();for(;a.length;)a.shift(),n.unshift("..");return n.join("/")}(e,t.baseUrl)),encodeURIComponent(e)},rtp:za,tb:Qa};function Ja(e,t){var r={};if(null==e||"object"!=typeof e)return r;var i=Object.keys(e).sort(),n=a({},$a,null==t?void 0:t.formatters),s=null==t?void 0:t.filter;return i.forEach((function(i){if(!(null==s?void 0:s(i))){var a=e[i],o=n[i];o&&(a=o(a,t)),"v"===i&&1===a||"pr"==i&&1===a||function(e){return"number"==typeof e?A(e):null!=e&&""!==e&&!1!==e}(a)&&(function(e){return"ot"===e||"sf"===e||"st"===e}(i)&&"string"==typeof a&&(a=new _a(a)),r[i]=a)}})),r}function Za(e,t){return void 0===t&&(t={}),e?function(e,t){return Xa(e,t)}(Ja(e,t),a({whitespace:!1},t)):""}function es(e,t,r){return a(e,function(e,t){void 0===t&&(t={});var r={};if(!e)return r;var i=Object.entries(e),n=Object.entries(Ra).concat(Object.entries((null==t?void 0:t.customHeaderMap)||{})),a=i.reduce((function(e,t){var r,i,a=t[0],s=t[1],o=(null===(r=n.find((function(e){return e[1].includes(a)})))||void 0===r?void 0:r[0])||La.REQUEST;return null!==(i=e[o])&&void 0!==i||(e[o]={}),e[o][a]=s,e}),{});return Object.entries(a).reduce((function(e,r){var i=r[0],n=r[1];return e[i]=Za(n,t),e}),r)}(t,r))}var ts="CMCD",rs=/CMCD=[^&#]+/;function is(e,t,r){var i=function(e,t){if(void 0===t&&(t={}),!e)return"";var r=Za(e,t);return ts+"="+encodeURIComponent(r)}(t,r);if(!i)return e;if(rs.test(e))return e.replace(rs,i);var n=e.includes("?")?"&":"?";return""+e+n+i}var ns=function(){function e(e){var t=this;this.hls=void 0,this.config=void 0,this.media=void 0,this.sid=void 0,this.cid=void 0,this.useHeaders=!1,this.includeKeys=void 0,this.initialized=!1,this.starved=!1,this.buffering=!0,this.audioBuffer=void 0,this.videoBuffer=void 0,this.onWaiting=function(){t.initialized&&(t.starved=!0),t.buffering=!0},this.onPlaying=function(){t.initialized||(t.initialized=!0),t.buffering=!1},this.applyPlaylistData=function(e){try{t.apply(e,{ot:Sa.MANIFEST,su:!t.initialized})}catch(e){t.hls.logger.warn("Could not generate manifest CMCD data.",e)}},this.applyFragmentData=function(e){try{var r=e.frag,i=e.part,n=t.hls.levels[r.level],a=t.getObjectType(r),s={d:1e3*(i||r).duration,ot:a};a!==Sa.VIDEO&&a!==Sa.AUDIO&&a!=Sa.MUXED||(s.br=n.bitrate/1e3,s.tb=t.getTopBandwidth(a)/1e3,s.bl=t.getBufferLength(a));var o=i?t.getNextPart(i):t.getNextFrag(r);null!=o&&o.url&&o.url!==r.url&&(s.nor=o.url),t.apply(e,s)}catch(e){t.hls.logger.warn("Could not generate segment CMCD data.",e)}},this.hls=e;var r=this.config=e.config,i=r.cmcd;null!=i&&(r.pLoader=this.createPlaylistLoader(),r.fLoader=this.createFragmentLoader(),this.sid=i.sessionId||e.sessionId,this.cid=i.contentId,this.useHeaders=!0===i.useHeaders,this.includeKeys=i.includeKeys,this.registerListeners())}var t=e.prototype;return t.registerListeners=function(){var e=this.hls;e.on(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(b.MEDIA_DETACHED,this.onMediaDetached,this),e.on(b.BUFFER_CREATED,this.onBufferCreated,this)},t.unregisterListeners=function(){var e=this.hls;e.off(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(b.MEDIA_DETACHED,this.onMediaDetached,this),e.off(b.BUFFER_CREATED,this.onBufferCreated,this)},t.destroy=function(){this.unregisterListeners(),this.onMediaDetached(),this.hls=this.config=this.audioBuffer=this.videoBuffer=null,this.onWaiting=this.onPlaying=this.media=null},t.onMediaAttached=function(e,t){this.media=t.media,this.media.addEventListener("waiting",this.onWaiting),this.media.addEventListener("playing",this.onPlaying)},t.onMediaDetached=function(){this.media&&(this.media.removeEventListener("waiting",this.onWaiting),this.media.removeEventListener("playing",this.onPlaying),this.media=null)},t.onBufferCreated=function(e,t){var r,i;this.audioBuffer=null==(r=t.tracks.audio)?void 0:r.buffer,this.videoBuffer=null==(i=t.tracks.video)?void 0:i.buffer},t.createData=function(){var e;return{v:1,sf:Aa.HLS,sid:this.sid,cid:this.cid,pr:null==(e=this.media)?void 0:e.playbackRate,mtp:this.hls.bandwidthEstimate/1e3}},t.apply=function(e,t){void 0===t&&(t={}),a(t,this.createData());var r=t.ot===Sa.INIT||t.ot===Sa.VIDEO||t.ot===Sa.MUXED;this.starved&&r&&(t.bs=!0,t.su=!0,this.starved=!1),null==t.su&&(t.su=this.buffering);var i=this.includeKeys;i&&(t=Object.keys(t).reduce((function(e,r){return i.includes(r)&&(e[r]=t[r]),e}),{}));var n={baseUrl:e.url};this.useHeaders?(e.headers||(e.headers={}),es(e.headers,t,n)):e.url=is(e.url,t,n)},t.getNextFrag=function(e){var t,r=null==(t=this.hls.levels[e.level])?void 0:t.details;if(r){var i=e.sn-r.startSN;return r.fragments[i+1]}},t.getNextPart=function(e){var t,r,i=e.index,n=e.fragment,a=null==(t=this.hls.levels[n.level])||null==(r=t.details)?void 0:r.partList;if(a)for(var s=n.sn,o=a.length-1;o>=0;o--){var l=a[o];if(l.index===i&&l.fragment.sn===s)return a[o+1]}},t.getObjectType=function(e){var t=e.type;return"subtitle"===t?Sa.TIMED_TEXT:"initSegment"===e.sn?Sa.INIT:"audio"===t?Sa.AUDIO:"main"===t?this.hls.audioTracks.length?Sa.VIDEO:Sa.MUXED:void 0},t.getTopBandwidth=function(e){var t,r=0,i=this.hls;if(e===Sa.AUDIO)t=i.audioTracks;else{var n=i.maxAutoLevel,a=n>-1?n+1:i.levels.length;t=i.levels.slice(0,a)}return t.forEach((function(e){e.bitrate>r&&(r=e.bitrate)})),r>0?r:NaN},t.getBufferLength=function(e){var t=this.media,r=e===Sa.AUDIO?this.audioBuffer:this.videoBuffer;return r&&t?1e3*ir.bufferInfo(r,t.currentTime,this.config.maxBufferHole).len:NaN},t.createPlaylistLoader=function(){var e=this.config.pLoader,t=this.applyPlaylistData,r=e||this.config.loader;return function(){function e(e){this.loader=void 0,this.loader=new r(e)}var n=e.prototype;return n.destroy=function(){this.loader.destroy()},n.abort=function(){this.loader.abort()},n.load=function(e,r,i){t(e),this.loader.load(e,r,i)},i(e,[{key:"stats",get:function(){return this.loader.stats}},{key:"context",get:function(){return this.loader.context}}])}()},t.createFragmentLoader=function(){var e=this.config.fLoader,t=this.applyFragmentData,r=e||this.config.loader;return function(){function e(e){this.loader=void 0,this.loader=new r(e)}var n=e.prototype;return n.destroy=function(){this.loader.destroy()},n.abort=function(){this.loader.abort()},n.load=function(e,r,i){t(e),this.loader.load(e,r,i)},i(e,[{key:"stats",get:function(){return this.loader.stats}},{key:"context",get:function(){return this.loader.context}}])}()},e}(),as=function(e){function t(t){var r;return(r=e.call(this,"content-steering",t.logger)||this).hls=void 0,r.loader=null,r.uri=null,r.pathwayId=".",r._pathwayPriority=null,r.timeToLoad=300,r.reloadTimer=-1,r.updated=0,r.started=!1,r.enabled=!0,r.levels=null,r.audioTracks=null,r.subtitleTracks=null,r.penalizedPathways={},r.hls=t,r.registerListeners(),r}o(t,e);var r=t.prototype;return r.registerListeners=function(){var e=this.hls;e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(b.MANIFEST_PARSED,this.onManifestParsed,this),e.on(b.ERROR,this.onError,this)},r.unregisterListeners=function(){var e=this.hls;e&&(e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(b.MANIFEST_PARSED,this.onManifestParsed,this),e.off(b.ERROR,this.onError,this))},r.pathways=function(){return(this.levels||[]).reduce((function(e,t){return-1===e.indexOf(t.pathwayId)&&e.push(t.pathwayId),e}),[])},r.startLoad=function(){if(this.started=!0,this.clearTimeout(),this.enabled&&this.uri){if(this.updated){var e=1e3*this.timeToLoad-(performance.now()-this.updated);if(e>0)return void this.scheduleRefresh(this.uri,e)}this.loadSteeringManifest(this.uri)}},r.stopLoad=function(){this.started=!1,this.loader&&(this.loader.destroy(),this.loader=null),this.clearTimeout()},r.clearTimeout=function(){-1!==this.reloadTimer&&(self.clearTimeout(this.reloadTimer),this.reloadTimer=-1)},r.destroy=function(){this.unregisterListeners(),this.stopLoad(),this.hls=null,this.levels=this.audioTracks=this.subtitleTracks=null},r.removeLevel=function(e){var t=this.levels;t&&(this.levels=t.filter((function(t){return t!==e})))},r.onManifestLoading=function(){this.stopLoad(),this.enabled=!0,this.timeToLoad=300,this.updated=0,this.uri=null,this.pathwayId=".",this.levels=this.audioTracks=this.subtitleTracks=null},r.onManifestLoaded=function(e,t){var r=t.contentSteering;null!==r&&(this.pathwayId=r.pathwayId,this.uri=r.uri,this.started&&this.startLoad())},r.onManifestParsed=function(e,t){this.audioTracks=t.audioTracks,this.subtitleTracks=t.subtitleTracks},r.onError=function(e,t){var r=t.errorAction;if((null==r?void 0:r.action)===bt&&r.flags===Ct){var i=this.levels,n=this._pathwayPriority,a=this.pathwayId;if(t.context){var s=t.context,o=s.groupId,l=s.pathwayId,u=s.type;o&&i?a=this.getPathwayForGroupId(o,u,a):l&&(a=l)}a in this.penalizedPathways||(this.penalizedPathways[a]=performance.now()),!n&&i&&(n=this.pathways()),n&&n.length>1&&(this.updatePathwayPriority(n),r.resolved=this.pathwayId!==a),t.details!==k.BUFFER_APPEND_ERROR||t.fatal?r.resolved||this.warn("Could not resolve "+t.details+' ("'+t.error.message+'") with content-steering for Pathway: '+a+" levels: "+(i?i.length:i)+" priorities: "+st(n)+" penalized: "+st(this.penalizedPathways)):r.resolved=!0}},r.filterParsedLevels=function(e){this.levels=e;var t=this.getLevelsForPathway(this.pathwayId);if(0===t.length){var r=e[0].pathwayId;this.log("No levels found in Pathway "+this.pathwayId+'. Setting initial Pathway to "'+r+'"'),t=this.getLevelsForPathway(r),this.pathwayId=r}return t.length!==e.length&&this.log("Found "+t.length+"/"+e.length+' levels in Pathway "'+this.pathwayId+'"'),t},r.getLevelsForPathway=function(e){return null===this.levels?[]:this.levels.filter((function(t){return e===t.pathwayId}))},r.updatePathwayPriority=function(e){var t;this._pathwayPriority=e;var r=this.penalizedPathways,i=performance.now();Object.keys(r).forEach((function(e){i-r[e]>3e5&&delete r[e]}));for(var n=0;n0){this.log('Setting Pathway to "'+a+'"'),this.pathwayId=a,fi(t),this.hls.trigger(b.LEVELS_UPDATED,{levels:t});var l=this.hls.levels[s];o&&l&&this.levels&&(l.attrs["STABLE-VARIANT-ID"]!==o.attrs["STABLE-VARIANT-ID"]&&l.bitrate!==o.bitrate&&this.log("Unstable Pathways change from bitrate "+o.bitrate+" to "+l.bitrate),this.hls.nextLoadLevel=s);break}}}},r.getPathwayForGroupId=function(e,t,r){for(var i=this.getLevelsForPathway(r).concat(this.levels||[]),n=0;n tenc");s=new Uint8Array(d.subarray(8,24)),o=Sr.FAIRPLAY}catch(e){return void i.warn(n+" Failed to parse sinf: "+e)}}else{if(l!==Sr.WIDEVINE&&l!==Sr.PLAYREADY)return void i.warn('Ignoring unexpected "'+e.type+'" event with init data type: "'+t+'" for selected key-system '+l);var h=function(e){var t=[];if(e instanceof ArrayBuffer)for(var r=e.byteLength,i=0;i+321&&i.warn(n+" Using first of "+f.length+" pssh found for selected key-system "+l);var c=f[0];if(!c)return void(0===h.length||h.some((function(e){return!e.systemId}))?i.warn(n+" contains incomplete or invalid pssh data"):i.log("ignoring "+n+" for "+h.map((function(e){return Cr(e.systemId)})).join(",")+" pssh data in favor of playlist keys"));if(o=Cr(c.systemId),0===c.version&&c.data)if(o===Sr.WIDEVINE){var g=c.data.length-22;s=new Uint8Array(c.data.subarray(g,g+16))}else o===Sr.PLAYREADY&&(s=Fr(c.data))}if(o&&s){for(var v,m=X.hexDump(s),p=i,y=p.keyIdToKeySessionPromise,E=p.mediaKeySessions,T=y[m],S=function(){var e=E[A],n=e.decryptdata;if(!n.keyId)return 0;var a=X.hexDump(n.keyId);return m===a||-1!==n.uri.replace(/-/g,"").indexOf(m)?(T=y[a],n.pssh||(delete y[a],n.pssh=new Uint8Array(r),n.keyId=s,(T=y[m]=T.then((function(){return i.generateRequestWithPreferredKeySession(e,t,r,"encrypted-event-key-match")}))).catch((function(e){return i.handleError(e)}))),1):void 0},A=0;A0)for(var a,s=0,o=n.length;s in key message");return yr(atob(c))},r.setupLicenseXHR=function(e,t,r,i){var n=this,a=this.config.licenseXhrSetup;return a?Promise.resolve().then((function(){if(!r.decryptdata)throw new Error("Key removed");return a.call(n.hls,e,t,r,i)})).catch((function(s){if(!r.decryptdata)throw s;return e.open("POST",t,!0),a.call(n.hls,e,t,r,i)})).then((function(r){return e.readyState||e.open("POST",t,!0),{xhr:e,licenseChallenge:r||i}})):(e.open("POST",t,!0),Promise.resolve({xhr:e,licenseChallenge:i}))},r.requestLicense=function(e,t){var r=this,i=this.config.keyLoadPolicy.default;return new Promise((function(n,a){var s=r.getLicenseServerUrlOrThrow(e.keySystem);r.log("Sending license request to URL: "+s);var o=new XMLHttpRequest;o.responseType="arraybuffer",o.onreadystatechange=function(){if(!r.hls||!e.mediaKeysSession)return a(new Error("invalid state"));if(4===o.readyState)if(200===o.status){r._requestLicenseFailureCount=0;var l=o.response;r.log("License received "+(l instanceof ArrayBuffer?l.byteLength:l));var u=r.config.licenseResponseCallback;if(u)try{l=u.call(r.hls,o,s,e)}catch(e){r.error(e)}n(l)}else{var d=i.errorRetry,h=d?d.maxNumRetry:0;if(r._requestLicenseFailureCount++,r._requestLicenseFailureCount>h||o.status>=400&&o.status<500)a(new hs({type:I.KEY_SYSTEM_ERROR,details:k.KEY_SYSTEM_LICENSE_REQUEST_FAILED,fatal:!0,networkDetails:o,response:{url:s,data:void 0,code:o.status,text:o.statusText}},"License Request XHR failed ("+s+"). Status: "+o.status+" ("+o.statusText+")"));else{var f=h-r._requestLicenseFailureCount+1;r.warn("Retrying license request, "+f+" attempts left"),r.requestLicense(e,t).then(n,a)}}},e.licenseXhr&&e.licenseXhr.readyState!==XMLHttpRequest.DONE&&e.licenseXhr.abort(),e.licenseXhr=o,r.setupLicenseXHR(o,s,e,t).then((function(t){var i=t.xhr,n=t.licenseChallenge;e.keySystem==Sr.PLAYREADY&&(n=r.unpackPlayReadyKeyMessage(i,n)),i.send(n)}))}))},r.onDestroying=function(){this.unregisterListeners(),this._clear()},r.onMediaAttached=function(e,t){if(this.config.emeEnabled){var r=t.media;this.media=r,ls(r,"encrypted",this.onMediaEncrypted),ls(r,"waitingforkey",this.onWaitingForKey)}},r.onMediaDetached=function(){var e=this.media;e&&(us(e,"encrypted",this.onMediaEncrypted),us(e,"waitingforkey",this.onWaitingForKey),this.media=null,this.mediaKeys=null)},r._clear=function(){var e,r=this;if(this._requestLicenseFailureCount=0,this.keyIdToKeySessionPromise={},this.mediaKeys||this.mediaKeySessions.length){var i=this.media,n=this.mediaKeySessions.slice();this.mediaKeySessions=[],this.mediaKeys=null,Ur.clearKeyUriToKeyIdMap();var a=n.length;t.CDMCleanupPromise=Promise.all(n.map((function(e){return r.removeSession(e)})).concat(null==i||null==(e=i.setMediaKeys(null))?void 0:e.catch((function(e){var t;r.log("Could not clear media keys: "+e),null==(t=r.hls)||t.trigger(b.ERROR,{type:I.OTHER_ERROR,details:k.KEY_SYSTEM_DESTROY_MEDIA_KEYS_ERROR,fatal:!1,error:new Error("Could not clear media keys: "+e)})})))).catch((function(e){var t;r.log("Could not close sessions and clear media keys: "+e),null==(t=r.hls)||t.trigger(b.ERROR,{type:I.OTHER_ERROR,details:k.KEY_SYSTEM_DESTROY_CLOSE_SESSION_ERROR,fatal:!1,error:new Error("Could not close sessions and clear media keys: "+e)})})).then((function(){a&&r.log("finished closing key sessions and clearing media keys")}))}},r.onManifestLoading=function(){this.keyFormatPromise=null},r.onManifestLoaded=function(e,t){var r=t.sessionKeys;if(r&&this.config.emeEnabled&&!this.keyFormatPromise){var i=r.reduce((function(e,t){return-1===e.indexOf(t.keyFormat)&&e.push(t.keyFormat),e}),[]);this.log("Selecting key-system from session-keys "+i.join(", ")),this.keyFormatPromise=this.getKeyFormatPromise(i)}},r.removeSession=function(e){var t=this,r=e.mediaKeysSession,i=e.licenseXhr;if(r){this.log("Remove licenses and keys and close session "+r.sessionId),e._onmessage&&(r.removeEventListener("message",e._onmessage),e._onmessage=void 0),e._onkeystatuseschange&&(r.removeEventListener("keystatuseschange",e._onkeystatuseschange),e._onkeystatuseschange=void 0),i&&i.readyState!==XMLHttpRequest.DONE&&i.abort(),e.mediaKeysSession=e.decryptdata=e.licenseXhr=void 0;var n=this.mediaKeySessions.indexOf(e);n>-1&&this.mediaKeySessions.splice(n,1);var a=function(e){var t;return"persistent-license"===e.sessionType||!(null==(t=e.sessionTypes)||!t.some((function(e){return"persistent-license"===e})))}(this.config.drmSystemOptions)?new Promise((function(e,t){self.setTimeout((function(){return t(new Error("MediaKeySession.remove() timeout"))}),8e3),r.remove().then(e)})):Promise.resolve();return a.catch((function(e){var r;t.log("Could not remove session: "+e),null==(r=t.hls)||r.trigger(b.ERROR,{type:I.OTHER_ERROR,details:k.KEY_SYSTEM_DESTROY_REMOVE_SESSION_ERROR,fatal:!1,error:new Error("Could not remove session: "+e)})})).then((function(){return r.close()})).catch((function(e){var r;t.log("Could not close session: "+e),null==(r=t.hls)||r.trigger(b.ERROR,{type:I.OTHER_ERROR,details:k.KEY_SYSTEM_DESTROY_CLOSE_SESSION_ERROR,fatal:!1,error:new Error("Could not close session: "+e)})}))}},t}(N);ds.CDMCleanupPromise=void 0;var hs=function(e){function t(t,r){var i;return(i=e.call(this,r)||this).data=void 0,t.error||(t.error=new Error(r)),i.data=t,t.err=t.error,i}return o(t,e),t}(c(Error)),fs=function(){function e(e){this.hls=void 0,this.isVideoPlaybackQualityAvailable=!1,this.timer=void 0,this.media=null,this.lastTime=void 0,this.lastDroppedFrames=0,this.lastDecodedFrames=0,this.streamController=void 0,this.hls=e,this.registerListeners()}var t=e.prototype;return t.setStreamController=function(e){this.streamController=e},t.registerListeners=function(){this.hls.on(b.MEDIA_ATTACHING,this.onMediaAttaching,this),this.hls.on(b.MEDIA_DETACHING,this.onMediaDetaching,this)},t.unregisterListeners=function(){this.hls.off(b.MEDIA_ATTACHING,this.onMediaAttaching,this),this.hls.off(b.MEDIA_DETACHING,this.onMediaDetaching,this)},t.destroy=function(){this.timer&&clearInterval(this.timer),this.unregisterListeners(),this.isVideoPlaybackQualityAvailable=!1,this.media=null},t.onMediaAttaching=function(e,t){var r=this.hls.config;if(r.capLevelOnFPSDrop){var i=t.media instanceof self.HTMLVideoElement?t.media:null;this.media=i,i&&"function"==typeof i.getVideoPlaybackQuality&&(this.isVideoPlaybackQualityAvailable=!0),self.clearInterval(this.timer),this.timer=self.setInterval(this.checkFPSInterval.bind(this),r.fpsDroppedMonitoringPeriod)}},t.onMediaDetaching=function(){this.media=null},t.checkFPS=function(e,t,r){var i=performance.now();if(t){if(this.lastTime){var n=i-this.lastTime,a=r-this.lastDroppedFrames,s=t-this.lastDecodedFrames,o=1e3*a/n,l=this.hls;if(l.trigger(b.FPS_DROP,{currentDropped:a,currentDecoded:s,totalDroppedFrames:r}),o>0&&a>l.config.fpsDroppedMonitoringThreshold*s){var u=l.currentLevel;l.logger.warn("drop FPS ratio greater than max allowed value for currentLevel: "+u),u>0&&(-1===l.autoLevelCapping||l.autoLevelCapping>=u)&&(u-=1,l.trigger(b.FPS_DROP_LEVEL_CAPPING,{level:u,droppedLevel:l.currentLevel}),l.autoLevelCapping=u,this.streamController.nextLevelSwitch())}}this.lastTime=i,this.lastDroppedFrames=r,this.lastDecodedFrames=t}},t.checkFPSInterval=function(){var e=this.media;if(e)if(this.isVideoPlaybackQualityAvailable){var t=e.getVideoPlaybackQuality();this.checkFPS(e,t.totalVideoFrames,t.droppedVideoFrames)}else this.checkFPS(e,e.webkitDecodedFrameCount,e.webkitDroppedFrameCount)},e}();function cs(e){for(var t=5381,r=e.length;r;)t=33*t^e.charCodeAt(--r);return(t>>>0).toString()}var gs=.025,vs=function(e){return e[e.Point=0]="Point",e[e.Range=1]="Range",e}({});function ms(e,t,r){return e.identifier+"-"+(r+1)+"-"+cs(t)}var ps=function(){function e(e,t){this.base=void 0,this._duration=null,this._timelineStart=null,this.appendInPlaceDisabled=void 0,this.appendInPlaceStarted=void 0,this.dateRange=void 0,this.hasPlayed=!1,this.cumulativeDuration=0,this.resumeOffset=NaN,this.playoutLimit=NaN,this.restrictions={skip:!1,jump:!1},this.snapOptions={out:!1,in:!1},this.assetList=[],this.assetListLoader=void 0,this.assetListResponse=null,this.resumeAnchor=void 0,this.error=void 0,this.resetOnResume=void 0,this.base=t,this.dateRange=e,this.setDateRange(e)}var t=e.prototype;return t.setDateRange=function(e){this.dateRange=e,this.resumeOffset=e.attr.optionalFloat("X-RESUME-OFFSET",this.resumeOffset),this.playoutLimit=e.attr.optionalFloat("X-PLAYOUT-LIMIT",this.playoutLimit),this.restrictions=e.attr.enumeratedStringList("X-RESTRICT",this.restrictions),this.snapOptions=e.attr.enumeratedStringList("X-SNAP",this.snapOptions)},t.reset=function(){var e;this.appendInPlaceStarted=!1,null==(e=this.assetListLoader)||e.destroy(),this.assetListLoader=void 0,this.supplementsPrimary||(this.assetListResponse=null,this.assetList=[],this._duration=null)},t.isAssetPastPlayoutLimit=function(e){var t;if(e>0&&e>=this.assetList.length)return!0;var r=this.playoutLimit;return!(e<=0||isNaN(r))&&(0===r||((null==(t=this.assetList[e])?void 0:t.startOffset)||0)>r)},t.findAssetIndex=function(e){return this.assetList.indexOf(e)},t.toString=function(){return'["'+(e=this).identifier+'" '+(e.cue.pre?"
":e.cue.post?"":"")+e.timelineStart.toFixed(2)+"-"+e.resumeTime.toFixed(2)+"]";var e},i(e,[{key:"identifier",get:function(){return this.dateRange.id}},{key:"startDate",get:function(){return this.dateRange.startDate}},{key:"startTime",get:function(){var e=this.dateRange.startTime;if(this.snapOptions.out){var t=this.dateRange.tagAnchor;if(t)return ys(e,t)}return e}},{key:"startOffset",get:function(){return this.cue.pre?0:this.startTime}},{key:"startIsAligned",get:function(){if(0===this.startTime||this.snapOptions.out)return!0;var e=this.dateRange.tagAnchor;if(e){var t=this.dateRange.startTime;return t-ys(t,e)<.1}return!1}},{key:"resumptionOffset",get:function(){var e=this.resumeOffset,t=A(e)?e:this.duration;return this.cumulativeDuration+t}},{key:"resumeTime",get:function(){var e=this.startOffset+this.resumptionOffset;if(this.snapOptions.in){var t=this.resumeAnchor;if(t)return ys(e,t)}return e}},{key:"appendInPlace",get:function(){return!!this.appendInPlaceStarted||!this.appendInPlaceDisabled&&!(this.cue.once||this.cue.pre||!this.startIsAligned||!(isNaN(this.playoutLimit)&&isNaN(this.resumeOffset)||this.resumeOffset&&this.duration&&Math.abs(this.resumeOffset-this.duration)0||null!==this.assetListResponse}}])}();function ys(e,t){return e-t.start=this._bufferedEosTime-.02},t.reachedPlayout=function(e){var t=this.interstitial.playoutLimit;return this.startOffset+e>=t},t.getAssetTime=function(e){var t=this.timelineOffset,r=this.duration;return Math.min(Math.max(0,e-t),r)},t.removeMediaListeners=function(){var e=this.mediaAttached;e&&(this._currentTime=e.currentTime,this.bufferSnapShot(),e.removeEventListener("timeupdate",this.checkPlayout))},t.bufferSnapShot=function(){var e;this.mediaAttached&&null!=(e=this.hls)&&e.bufferedToEnd&&(this._bufferedEosTime=this.bufferedEnd)},t.destroy=function(){this.removeMediaListeners(),this.hls.destroy(),this.hls=this.interstitial=null,this.tracks=this.mediaAttached=this.checkPlayout=null},t.attachMedia=function(e){this.hls.attachMedia(e)},t.detachMedia=function(){this.removeMediaListeners(),this.mediaAttached=null,this.hls.detachMedia()},t.resumeBuffering=function(){this.hls.resumeBuffering()},t.pauseBuffering=function(){this.hls.pauseBuffering()},t.transferMedia=function(){return this.bufferSnapShot(),this.hls.transferMedia()},t.resetDetails=function(){var e=this.hls;if(this.hasDetails){e.stopLoad();var t=function(e){return delete e.details};e.levels.forEach(t),e.allAudioTracks.forEach(t),e.allSubtitleTracks.forEach(t),this.hasDetails=!1}},t.on=function(e,t,r){this.hls.on(e,t)},t.once=function(e,t,r){this.hls.once(e,t)},t.off=function(e,t,r){this.hls.off(e,t)},t.toString=function(){var e;return"HlsAssetPlayer: "+Ss(this.assetItem)+" "+(null==(e=this.hls)?void 0:e.sessionId)+" "+(this.appendInPlace?"append-in-place":"")},i(e,[{key:"appendInPlace",get:function(){var e;return(null==(e=this.interstitial)?void 0:e.appendInPlace)||!1}},{key:"destroyed",get:function(){var e;return!(null!=(e=this.hls)&&e.userConfig)}},{key:"assetId",get:function(){return this.assetItem.identifier}},{key:"interstitialId",get:function(){return this.assetItem.parentIdentifier}},{key:"media",get:function(){var e;return(null==(e=this.hls)?void 0:e.media)||null}},{key:"bufferedEnd",get:function(){var e=this.media||this.mediaAttached;if(!e)return this._bufferedEosTime?this._bufferedEosTime:this.currentTime;var t=ir.bufferInfo(e,e.currentTime,.001);return this.getAssetTime(t.end)}},{key:"currentTime",get:function(){var e=this.media||this.mediaAttached;return e?this.getAssetTime(e.currentTime):this._currentTime||0}},{key:"duration",get:function(){var e=this.assetItem.duration;return e||0}},{key:"remaining",get:function(){var e=this.duration;return e?Math.max(0,e-this.currentTime):0}},{key:"startOffset",get:function(){return this.assetItem.startOffset}},{key:"timelineOffset",get:function(){var e;return(null==(e=this.hls)?void 0:e.config.timelineOffset)||0},set:function(e){var t=this.timelineOffset;if(e!==t){var r=e-t;if(Math.abs(r)>1/9e4){if(this.hasDetails)throw new Error("Cannot set timelineOffset after playlists are loaded");this.hls.config.timelineOffset=e}}}}])}(),Ls=function(e){function t(t,r){var i;return(i=e.call(this,"interstitials-sched",r)||this).onScheduleUpdate=void 0,i.eventMap={},i.events=null,i.items=null,i.durations={primary:0,playout:0,integrated:0},i.onScheduleUpdate=t,i}o(t,e);var r=t.prototype;return r.destroy=function(){this.reset(),this.onScheduleUpdate=null},r.reset=function(){this.eventMap={},this.setDurations(0,0,0),this.events&&this.events.forEach((function(e){return e.reset()})),this.events=this.items=null},r.resetErrorsInRange=function(e,t){return this.events?this.events.reduce((function(r,i){return e<=i.startOffset&&t>i.startOffset?(delete i.error,r+1):r}),0):0},r.getEvent=function(e){return e&&this.eventMap[e]||null},r.hasEvent=function(e){return e in this.eventMap},r.findItemIndex=function(e,t){if(e.event)return this.findEventIndex(e.event.identifier);var r=-1;e.nextEvent?r=this.findEventIndex(e.nextEvent.identifier)-1:e.previousEvent&&(r=this.findEventIndex(e.previousEvent.identifier)+1);var i=this.items;if(i)for(i[r]||(void 0===t&&(t=e.start),r=this.findItemIndexAtTime(t));r>=0&&null!=(n=i[r])&&n.event;){var n;r--}return r},r.findItemIndexAtTime=function(e,t){var r=this.items;if(r)for(var i=0;in.start&&e1)for(var n=0;ns&&t.005||Math.abs(e.playout.end-i[t].playout.end)>.005})))&&(this.items=n,this.onScheduleUpdate(t,i))}},r.parseDateRanges=function(e,t,r){for(var i=[],n=Object.keys(e),a=0;a.033){var A=s,L=o;o+=S;var R=a;a+=S;var I={previousEvent:e[i-1]||null,nextEvent:t,start:A,end:A+S,playout:{start:R,end:a},integrated:{start:L,end:o}};r.push(I)}else S>0&&d&&(d.cumulativeDuration+=S,r[r.length-1].end=f)}u&&(y=p),t.timelineStart=p;var k=o;o+=g;var b=a;a+=c,r.push({event:t,start:p,end:y,playout:{start:b,end:a},integrated:{start:k,end:o}})}var D=t.resumeTime;s=u||D>n?n:D})),sgs?(this.log('"'+e.identifier+'" resumption '+i+" not aligned with estimated timeline end "+n),!1):t?!Object.keys(t).some((function(n){var a=t[n].details,s=a.edge;if(i>=s)return r.log('"'+e.identifier+'" resumption '+i+" past "+n+" playlist end "+s),!1;var o=pt(null,a.fragments,i);if(!o)return r.log('"'+e.identifier+'" resumption '+i+" does not align with any fragments in "+n+" playlist ("+a.fragStart+"-"+a.fragmentEnd+")"),!0;var l="audio"===n?.175:0;return!(Math.abs(o.start-i)=n.end){var a,s=i.schedule.findItemIndexAtTime(i.timelinePos);if(!i.isInterstitial(n)&&null!=(a=i.media)&&a.paused&&(i.shouldPlay=!1),!r){var o=i.findItemIndex(n);if(s>o){var l=i.schedule.findJumpRestrictedIndex(o+1,s);if(l>o)return void i.setSchedulePosition(l)}}i.setSchedulePosition(s)}else{var u=i.playingAsset;if(u){var d=u.timelineStart,h=u.duration||0;(r&&e=d+h)&&i.setScheduleToAssetAtTime(e,u)}else if(i.playingLastItem&&i.isInterstitial(n)){var f=n.event.assetList[0];f&&(i.endedItem=i.playingItem,i.playingItem=null,i.setScheduleToAssetAtTime(e,f))}}else i.checkBuffer()}}},i.onTimeupdate=function(){var e=i.currentTime;if(void 0!==e&&!i.playbackDisabled&&e>i.timelinePos){i.timelinePos=e,e>i.bufferedPos&&i.checkBuffer();var t=i.playingItem;if(t&&!i.playingLastItem){if(e>=t.end){i.timelinePos=t.end;var r=i.findItemIndex(t);i.setSchedulePosition(r+1)}var n=i.playingAsset;n&&e>=n.timelineStart+(n.duration||0)&&i.setScheduleToAssetAtTime(e,n)}}},i.onScheduleUpdate=function(e,t){var r=i.schedule,n=i.playingItem,a=r.events||[],s=r.items||[],o=r.durations,l=e.map((function(e){return e.identifier})),u=!(!a.length&&!l.length);(u||t)&&i.log("INTERSTITIALS_UPDATED ("+a.length+"): "+a+"\nSchedule: "+s.map((function(e){return Rs(e)}))+" pos: "+i.timelinePos),l.length&&i.log("Removed events "+l),i.playerQueue.forEach((function(e){if(e.interstitial.appendInPlace){var t=e.assetItem.timelineStart,r=e.timelineOffset-t;if(r)try{e.timelineOffset=t}catch(n){Math.abs(r)>gs&&i.warn(n+' ("'+e.assetId+'" '+e.timelineOffset+"->"+t+")")}}}));var d=null;if(n){var h=i.updateItem(n,i.timelinePos);i.itemsMatch(n,h)&&(i.playingItem=h,i.waitingItem=i.endedItem=null,d=function(){return i.trimInPlace(h,n)})}else i.waitingItem=i.updateItem(i.waitingItem),i.endedItem=i.updateItem(i.endedItem);var f=i.bufferingItem;if(f){var c=i.updateItem(f,i.bufferedPos);i.itemsMatch(f,c)?(i.bufferingItem=c,d||(d=function(){return i.trimInPlace(c,f)})):f.event&&(i.bufferingItem=i.playingItem,i.clearInterstitial(f.event,null))}if(e.forEach((function(e){e.assetList.forEach((function(e){i.clearAssetPlayer(e.identifier,null)}))})),u||t){if(i.hls.trigger(b.INTERSTITIALS_UPDATED,{events:a.slice(0),schedule:s.slice(0),durations:o,removedIds:l}),i.isInterstitial(n)&&l.includes(n.event.identifier))return i.warn('Interstitial "'+n.event.identifier+'" removed while playing'),void i.primaryFallback(n.event);d&&d(),i.checkBuffer()}},i.hls=t,i.HlsPlayerClass=r,i.assetListLoader=new Is(t),i.schedule=new Ls(i.onScheduleUpdate,t.logger),i.registerListeners(),i}o(t,e);var r=t.prototype;return r.registerListeners=function(){var e=this.hls;e.on(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(b.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.on(b.AUDIO_TRACK_UPDATED,this.onAudioTrackUpdated,this),e.on(b.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.on(b.SUBTITLE_TRACK_UPDATED,this.onSubtitleTrackUpdated,this),e.on(b.EVENT_CUE_ENTER,this.onInterstitialCueEnter,this),e.on(b.ASSET_LIST_LOADED,this.onAssetListLoaded,this),e.on(b.BUFFER_APPENDED,this.onBufferAppended,this),e.on(b.BUFFER_FLUSHED,this.onBufferFlushed,this),e.on(b.BUFFERED_TO_END,this.onBufferedToEnd,this),e.on(b.MEDIA_ENDED,this.onMediaEnded,this),e.on(b.ERROR,this.onError,this),e.on(b.DESTROYING,this.onDestroying,this)},r.unregisterListeners=function(){var e=this.hls;e&&(e.off(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(b.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.off(b.AUDIO_TRACK_UPDATED,this.onAudioTrackUpdated,this),e.off(b.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.off(b.SUBTITLE_TRACK_UPDATED,this.onSubtitleTrackUpdated,this),e.off(b.EVENT_CUE_ENTER,this.onInterstitialCueEnter,this),e.off(b.ASSET_LIST_LOADED,this.onAssetListLoaded,this),e.off(b.BUFFER_CODECS,this.onBufferCodecs,this),e.off(b.BUFFER_APPENDED,this.onBufferAppended,this),e.off(b.BUFFER_FLUSHED,this.onBufferFlushed,this),e.off(b.BUFFERED_TO_END,this.onBufferedToEnd,this),e.off(b.MEDIA_ENDED,this.onMediaEnded,this),e.off(b.ERROR,this.onError,this),e.off(b.DESTROYING,this.onDestroying,this))},r.startLoad=function(){this.resumeBuffering()},r.stopLoad=function(){this.pauseBuffering()},r.resumeBuffering=function(){var e;null==(e=this.getBufferingPlayer())||e.resumeBuffering()},r.pauseBuffering=function(){var e;null==(e=this.getBufferingPlayer())||e.pauseBuffering()},r.destroy=function(){this.unregisterListeners(),this.stopLoad(),this.assetListLoader&&this.assetListLoader.destroy(),this.emptyPlayerQueue(),this.clearScheduleState(),this.schedule&&this.schedule.destroy(),this.media=this.detachedData=this.mediaSelection=this.requiredTracks=this.altSelection=this.manager=null,this.hls=this.HlsPlayerClass=this.schedule=this.log=null,this.assetListLoader=null,this.onPlay=this.onPause=this.onSeeking=this.onTimeupdate=null,this.onScheduleUpdate=null},r.onDestroying=function(){var e=this.primaryMedia||this.media;e&&this.removeMediaListeners(e)},r.removeMediaListeners=function(e){us(e,"play",this.onPlay),us(e,"pause",this.onPause),us(e,"seeking",this.onSeeking),us(e,"timeupdate",this.onTimeupdate)},r.onMediaAttaching=function(e,t){var r=this.media=t.media;ls(r,"seeking",this.onSeeking),ls(r,"timeupdate",this.onTimeupdate),ls(r,"play",this.onPlay),ls(r,"pause",this.onPause)},r.onMediaAttached=function(e,t){var r=this.effectivePlayingItem,i=this.detachedData;if(this.detachedData=null,null===r)this.checkStart();else if(!i){this.clearScheduleState();var n=this.findItemIndex(r);this.setSchedulePosition(n)}},r.clearScheduleState=function(){this.playingItem=this.bufferingItem=this.waitingItem=this.endedItem=this.playingAsset=this.endedAsset=this.bufferingAsset=null},r.onMediaDetaching=function(e,t){var r=!!t.transferMedia,i=this.media;if(this.media=null,!r&&(i&&this.removeMediaListeners(i),this.detachedData)){var n=this.getBufferingPlayer();n&&(this.playingAsset=this.endedAsset=this.bufferingAsset=this.bufferingItem=this.waitingItem=this.detachedData=null,n.detachMedia()),this.shouldPlay=!1}},r.isInterstitial=function(e){return!(null==e||!e.event)},r.retreiveMediaSource=function(e,t){var r=this.getAssetPlayer(e);r&&this.transferMediaFromPlayer(r,t)},r.transferMediaFromPlayer=function(e,t){var r=e.interstitial.appendInPlace,i=e.media;if(r&&i===this.primaryMedia){if(this.bufferingAsset=null,(!t||this.isInterstitial(t)&&!t.event.appendInPlace)&&t&&i)return void(this.detachedData={media:i});var n=e.transferMedia();this.log("transfer MediaSource from "+e+" "+st(n)),this.detachedData=n}else t&&i&&(this.shouldPlay||(this.shouldPlay=!i.paused))},r.transferMediaTo=function(e,t){var r,i,n=this;if(e.media!==t){var a,s=null,o=this.hls,l=e!==o,u=l&&e.interstitial.appendInPlace,d=null==(r=this.detachedData)?void 0:r.mediaSource;if(o.media)u&&(s=o.transferMedia(),this.detachedData=s),a="Primary";else if(d){var h=this.getBufferingPlayer();h?(s=h.transferMedia(),a=""+h):a="detached MediaSource"}else a="detached media";if(!s)if(d)s=this.detachedData,this.log("using detachedData: MediaSource "+st(s));else if(!this.detachedData||o.media===t){var f=this.playerQueue;f.length>1&&f.forEach((function(e){if(l&&e.interstitial.appendInPlace!==u){var t=e.interstitial;n.clearInterstitial(e.interstitial,null),t.appendInPlace=!1,t.appendInPlace&&n.warn("Could not change append strategy for queued assets "+t)}})),this.hls.detachMedia(),this.detachedData={media:t}}var c=s&&"mediaSource"in s&&"closed"!==(null==(i=s.mediaSource)?void 0:i.readyState),g=c&&s?s:t;if(this.log((c?"transfering MediaSource":"attaching media")+" to "+(l?e:"Primary")+" from "+a),g===s){var v=l&&e.assetId===this.schedule.assetIdAtEnd;g.overrides={duration:this.schedule.duration,endOfStream:!l||v,cueRemoval:!l}}e.attachMedia(g)}},r.onInterstitialCueEnter=function(){this.onTimeupdate()},r.checkStart=function(){var e=this.schedule,t=e.events;if(t&&!this.playbackDisabled&&this.media){-1===this.bufferedPos&&(this.bufferedPos=0);var r=this.timelinePos,i=this.effectivePlayingItem;if(-1===r){var n=this.hls.startPosition;if(this.timelinePos=n,t.length&&t[0].cue.pre){var a=e.findEventIndex(t[0].identifier);this.setSchedulePosition(a)}else if(n>=0||!this.primaryLive){var s=this.timelinePos=n>0?n:0,o=e.findItemIndexAtTime(s);this.setSchedulePosition(o)}}else if(i&&!this.playingItem){var l=e.findItemIndex(i);this.setSchedulePosition(l)}}},r.advanceAfterAssetEnded=function(e,t,r){var i=Ts(e,r);if(e.isAssetPastPlayoutLimit(i)){var n=this.schedule.items;if(n){var a=t+1;if(a>=n.length)return void this.setSchedulePosition(-1);var s=e.resumeTime;this.timelinePos=0?r[e]:null,n=this.playingItem,a=this.playingLastItem;if(this.isInterstitial(n)){var s,o=n.event,l=this.playingAsset,u=null==l?void 0:l.identifier,d=u?this.getAssetPlayer(u):null;if(d&&u&&(!this.eventItemsMatch(n,i)||void 0!==t&&u!==(null==(s=o.assetList)?void 0:s[t].identifier))){var h,f=o.findAssetIndex(l);if(this.log("INTERSTITIAL_ASSET_ENDED "+(f+1)+"/"+o.assetList.length+" "+Ss(l)),this.endedAsset=l,this.playingAsset=null,this.hls.trigger(b.INTERSTITIAL_ASSET_ENDED,{asset:l,assetListIndex:f,event:o,schedule:r.slice(0),scheduleIndex:e,player:d}),n!==this.playingItem)return void(this.itemsMatch(n,this.playingItem)&&!this.playingAsset&&this.advanceAfterAssetEnded(o,this.findItemIndex(this.playingItem),f));this.retreiveMediaSource(u,i),!d.media||null!=(h=this.detachedData)&&h.mediaSource||d.detachMedia()}if(!this.eventItemsMatch(n,i)&&(this.endedItem=n,this.playingItem=null,this.log("INTERSTITIAL_ENDED "+o+" "+Rs(n)),o.hasPlayed=!0,this.hls.trigger(b.INTERSTITIAL_ENDED,{event:o,schedule:r.slice(0),scheduleIndex:e}),o.cue.once)){this.updateSchedule();var c=this.schedule.items;if(i&&c){var g=this.findItemIndex(i);this.advanceSchedule(g,c,t,n,a)}return}}this.advanceSchedule(e,r,t,n,a)}},r.advanceSchedule=function(e,t,r,i,n){var a=this,s=e>=0?t[e]:null,o=this.primaryMedia,l=this.playerQueue;if(l.length&&l.forEach((function(t){var r=t.interstitial,i=a.schedule.findEventIndex(r.identifier);(ie+1)&&a.clearInterstitial(r,s)})),this.isInterstitial(s)){this.timelinePos=Math.min(Math.max(this.timelinePos,s.start),s.end);var u=s.event;if(void 0===r){var d=Ts(u,(r=this.schedule.findAssetIndex(u,this.timelinePos))-1);if(u.isAssetPastPlayoutLimit(d))return void this.advanceAfterAssetEnded(u,e,r);r=d}var h=this.waitingItem;this.assetsBuffered(s,o)||this.setBufferingItem(s);var f=this.preloadAssets(u,r);if(this.eventItemsMatch(s,h||i)||(this.waitingItem=s,this.log("INTERSTITIAL_STARTED "+Rs(s)+" "+(u.appendInPlace?"append in place":"")),this.hls.trigger(b.INTERSTITIAL_STARTED,{event:u,schedule:t.slice(0),scheduleIndex:e})),!u.assetListLoaded)return void this.log("Waiting for ASSET-LIST to complete loading "+u);if(u.assetListLoader&&(u.assetListLoader.destroy(),u.assetListLoader=void 0),!o)return void this.log("Waiting for attachMedia to start Interstitial "+u);this.waitingItem=this.endedItem=null,this.playingItem=s;var c=u.assetList[r];if(!c){var g=t[e+1],v=this.media;return g&&v&&!this.isInterstitial(g)&&v.currentTime=e.end)&&(n=this.getPrimaryResumption(e,t),this.timelinePos=n),this.attachPrimary(n,e)}if(r){var a=this.schedule.items;a&&(this.log("INTERSTITIALS_PRIMARY_RESUMED "+Rs(e)),this.hls.trigger(b.INTERSTITIALS_PRIMARY_RESUMED,{schedule:a.slice(0),scheduleIndex:t}),this.checkBuffer())}},r.getPrimaryResumption=function(e,t){var r=e.start;if(this.primaryLive){var i=this.primaryDetails;if(0===t)return this.hls.startPosition;if(i&&(ri.edge))return this.hls.liveSyncPosition||-1}return r},r.isAssetBuffered=function(e){var t=this.getAssetPlayer(e.identifier);return null!=t&&t.hls?t.hls.bufferedToEnd:ir.bufferInfo(this.primaryMedia,this.timelinePos,0).end+1>=e.timelineStart+(e.duration||0)},r.attachPrimary=function(e,t,r){t?this.setBufferingItem(t):this.bufferingItem=this.playingItem,this.bufferingAsset=null;var i=this.primaryMedia;if(i){var n=this.hls;n.media?this.checkBuffer():(this.transferMediaTo(n,i),r&&this.startLoadingPrimaryAt(e,r)),r||(this.timelinePos=e,this.startLoadingPrimaryAt(e,r))}},r.startLoadingPrimaryAt=function(e,t){var r,i=this.hls;!i.loadingEnabled||!i.media||Math.abs(((null==(r=i.mainForwardBufferInfo)?void 0:r.start)||i.media.currentTime)-e)>.5?i.startLoad(e,t):i.bufferingEnabled||i.resumeBuffering()},r.onManifestLoading=function(){this.stopLoad(),this.schedule.reset(),this.emptyPlayerQueue(),this.clearScheduleState(),this.shouldPlay=!1,this.bufferedPos=this.timelinePos=-1,this.mediaSelection=this.altSelection=this.manager=this.requiredTracks=null,this.hls.off(b.BUFFER_CODECS,this.onBufferCodecs,this),this.hls.on(b.BUFFER_CODECS,this.onBufferCodecs,this)},r.onLevelUpdated=function(e,t){if(-1!==t.level){var r=this.hls.levels[t.level],i=d(d({},this.mediaSelection||this.altSelection),{},{main:r});this.mediaSelection=i,this.schedule.parseInterstitialDateRanges(i,this.hls.config.interstitialAppendInPlace),!this.effectivePlayingItem&&this.schedule.items&&this.checkStart()}},r.onAudioTrackUpdated=function(e,t){var r=this.hls.audioTracks[t.id],i=this.mediaSelection;if(i){var n=d(d({},i),{},{audio:r});this.mediaSelection=n}else this.altSelection=d(d({},this.altSelection),{},{audio:r})},r.onSubtitleTrackUpdated=function(e,t){var r=this.hls.subtitleTracks[t.id],i=this.mediaSelection;if(i){var n=d(d({},i),{},{subtitles:r});this.mediaSelection=n}else this.altSelection=d(d({},this.altSelection),{},{subtitles:r})},r.onAudioTrackSwitching=function(e,t){var r=ut(t);this.playerQueue.forEach((function(e){return e.hls.setAudioOption(t)||e.hls.setAudioOption(r)}))},r.onSubtitleTrackSwitch=function(e,t){var r=ut(t);this.playerQueue.forEach((function(e){return e.hls.setSubtitleOption(t)||-1!==t.id&&e.hls.setSubtitleOption(r)}))},r.onBufferCodecs=function(e,t){var r=t.tracks;r&&(this.requiredTracks=r)},r.onBufferAppended=function(e,t){this.checkBuffer()},r.onBufferFlushed=function(e,t){var r=this.playingItem;if(r&&!this.itemsMatch(r,this.bufferingItem)&&!this.isInterstitial(r)){var i=this.timelinePos;this.bufferedPos=i,this.checkBuffer()}},r.onBufferedToEnd=function(e){var t=this.schedule.events;if(this.bufferedPos.25){e.event.assetList.forEach((function(t,i){e.event.isAssetPastPlayoutLimit(i)&&r.clearAssetPlayer(t.identifier,null)}));var i=e.end+.25,n=ir.bufferInfo(this.primaryMedia,i,0);(n.end>i||(n.nextStart||0)>i)&&(this.attachPrimary(i,null),this.flushFrontBuffer(i))}},r.itemsMatch=function(e,t){return!!t&&(e===t||e.event&&t.event&&this.eventItemsMatch(e,t)||!e.event&&!t.event&&this.findItemIndex(e)===this.findItemIndex(t))},r.eventItemsMatch=function(e,t){var r;return!!t&&(e===t||e.event.identifier===(null==(r=t.event)?void 0:r.identifier))},r.findItemIndex=function(e,t){return e?this.schedule.findItemIndex(e,t):-1},r.updateSchedule=function(){var e=this.mediaSelection;e&&this.schedule.updateSchedule(e,[])},r.checkBuffer=function(e){var t=this.schedule.items;if(t){var r=ir.bufferInfo(this.primaryMedia,this.timelinePos,0);e&&(this.bufferedPos=this.timelinePos),e||(e=r.len<1),this.updateBufferedPos(r.end,t,e)}},r.updateBufferedPos=function(e,t,r){var i=this.schedule,n=this.bufferingItem;if(!(this.bufferedPos>e))if(1===t.length&&this.itemsMatch(t[0],n))this.bufferedPos=e;else{var a=this.playingItem,s=this.findItemIndex(a),o=i.findItemIndexAtTime(e);if(this.bufferedPos=n.end||null!=(l=f.event)&&l.appendInPlace&&e+.01>=f.start)&&(o=h),h-s>1&&!1===(null==n||null==(u=n.event)?void 0:u.appendInPlace))return;if(this.bufferedPos=e,o>d&&o>s)this.bufferedToItem(f);else{var c=this.primaryDetails;this.primaryLive&&c&&e>c.edge-c.targetduration&&f.start0&&(s=Math.round(1e3*h)/1e3)}if(this.log("Load interstitial asset "+(t+1)+"/"+(r?1:i)+" "+e+(s?" live-start: "+d+" start-offset: "+s:"")),r)return this.createAsset(e,0,0,o,e.duration,r);var f=this.assetListLoader.loadAssetList(e,s);f&&(e.assetListLoader=f)}else if(!a&&i){for(var c=t;c1){var g=t.duration;g&&cl)&&(i.log('Interstitial asset "'+v+'" duration change '+l+" > "+o),t.duration=o,i.updateSchedule())}};y.on(b.LEVEL_UPDATED,(function(e,t){var r=t.details;return E(r)})),y.on(b.LEVEL_PTS_UPDATED,(function(e,t){var r=t.details;return E(r)}));var T=function(e,t){var r=i.getAssetPlayer(v);if(r&&t.tracks){r.off(b.BUFFER_CODECS,T),r.tracks=t.tracks;var n=i.primaryMedia;i.bufferingAsset===r.assetItem&&n&&!r.media&&i.bufferAssetPlayer(r,n)}};y.on(b.BUFFER_CODECS,T);var S=function(){var r,n=i.getAssetPlayer(v);if(i.log("buffered to end of asset "+n),n){var a=i.schedule.findEventIndex(e.identifier),s=null==(r=i.schedule.items)?void 0:r[a];if(i.isInterstitial(s)){var o=e.findAssetIndex(t),l=Ts(e,o);if(e.isAssetPastPlayoutLimit(l)){var u,d=null==(u=i.schedule.items)?void 0:u[a+1];d&&i.bufferedToItem(d)}else i.bufferedToItem(s,l)}}};y.on(b.BUFFERED_TO_END,S);var A=function(t){return function(){if(i.getAssetPlayer(v)){i.shouldPlay=!0;var r=i.schedule.findEventIndex(e.identifier);i.advanceAfterAssetEnded(e,r,t)}}};return y.once(b.MEDIA_ENDED,A(r)),y.once(b.PLAYOUT_LIMIT_REACHED,A(1/0)),y.on(b.ERROR,(function(t,n){var a=i.getAssetPlayer(v);if(n.details!==k.BUFFER_STALLED_ERROR)i.handleAssetItemError(n,e,i.schedule.findEventIndex(e.identifier),r,"Asset player error "+n.error+" "+e);else if(null!=a&&a.media){var s=a.currentTime,o=a.duration-s;s&&e.appendInPlace&&o/a.media.playbackRate<.5?(i.log("Advancing buffer past end of asset "+v+" "+e+" at "+a.media.currentTime),S()):(i.warn("Stalled at "+s+" of "+(s+o)+" in asset "+v+" "+e),i.onTimeupdate(),i.checkBuffer(!0))}})),y.on(b.DESTROYING,(function(){if(i.getAssetPlayer(v)){var t=new Error("Asset player destroyed unexpectedly "+v),n={fatal:!0,type:I.OTHER_ERROR,details:k.INTERSTITIAL_ASSET_ITEM_ERROR,error:t};i.handleAssetItemError(n,e,i.schedule.findEventIndex(e.identifier),r,t.message)}})),this.log("INTERSTITIAL_ASSET_PLAYER_CREATED "+Ss(t)),this.hls.trigger(b.INTERSTITIAL_ASSET_PLAYER_CREATED,{asset:t,assetListIndex:r,event:e,player:y}),y},r.clearInterstitial=function(e,t){var r=this;e.assetList.forEach((function(e){r.clearAssetPlayer(e.identifier,t)})),e.reset()},r.resetAssetPlayer=function(e){var t=this.getAssetPlayerQueueIndex(e);if(-1!==t){this.log('reset asset player "'+e+'" after error');var r=this.playerQueue[t];this.transferMediaFromPlayer(r,null),r.resetDetails()}},r.clearAssetPlayer=function(e,t){var r=this.getAssetPlayerQueueIndex(e);if(-1!==r){this.log('clear asset player "'+e+'" toSegment: '+(t?Rs(t):t));var i=this.playerQueue[r];this.transferMediaFromPlayer(i,t),this.playerQueue.splice(r,1),i.destroy()}},r.emptyPlayerQueue=function(){for(var e;e=this.playerQueue.pop();)e.destroy();this.playerQueue=[]},r.startAssetPlayer=function(e,t,r,i,n){var a=e.interstitial,s=e.assetItem,o=e.assetId,l=a.assetList.length,u=this.playingAsset;this.endedAsset=null,this.playingAsset=s,u&&u.identifier===o||(u&&(this.clearAssetPlayer(u.identifier,r[i]),delete u.error),this.log("INTERSTITIAL_ASSET_STARTED "+(t+1)+"/"+l+" "+Ss(s)),this.hls.trigger(b.INTERSTITIAL_ASSET_STARTED,{asset:s,assetListIndex:t,event:a,schedule:r.slice(0),scheduleIndex:i,player:e})),this.bufferAssetPlayer(e,n)},r.bufferAssetPlayer=function(e,t){var r,i,n=e.interstitial,a=e.assetItem,s=this.schedule.findEventIndex(n.identifier),o=null==(r=this.schedule.items)?void 0:r[s];if(o){this.setBufferingItem(o),this.bufferingAsset=a;var l=this.getBufferingPlayer();if(l!==e){var u=n.appendInPlace;if(!u||!1!==(null==l?void 0:l.interstitial.appendInPlace)){var d=(null==l?void 0:l.tracks)||(null==(i=this.detachedData)?void 0:i.tracks)||this.requiredTracks;if(u&&a!==this.playingAsset){if(!e.tracks)return;if(d&&!j(d,e.tracks)){var h=new Error("Asset "+Ss(a)+" SourceBuffer tracks ('"+Object.keys(e.tracks)+"') are not compatible with primary content tracks ('"+Object.keys(d)+"')"),f={fatal:!0,type:I.OTHER_ERROR,details:k.INTERSTITIAL_ASSET_ITEM_ERROR,error:h},c=n.findAssetIndex(a);return void this.handleAssetItemError(f,n,s,c,h.message)}}this.transferMediaTo(e,t)}}}},r.handleAssetItemError=function(e,t,r,i,n){if(e.details!==k.BUFFER_STALLED_ERROR){var s=t.assetList[i];this.warn("INTERSTITIAL_ASSET_ERROR "+(s?Ss(s):s)+" "+e.error);var o=null==s?void 0:s.identifier,l=this.getAssetPlayerQueueIndex(o),u=this.playerQueue[l]||null,d=this.schedule.items,h=a({},e,{fatal:!1,errorAction:xt(!0),asset:s,assetListIndex:i,event:t,schedule:d,scheduleIndex:r,player:u});if(this.hls.trigger(b.INTERSTITIAL_ASSET_ERROR,h),e.fatal){var f=this.playingAsset,c=new Error(n);if(s&&(this.clearAssetPlayer(o,null),s.error=c),t.assetList.some((function(e){return!e.error}))){for(var g=i;g")+" error: "+e.error);var i=this.timelinePos;-1===i&&(i=this.hls.startPosition);var n=this.updateItem(r,i);this.itemsMatch(r,n)&&this.clearInterstitial(e,null),e.appendInPlace&&(this.attachPrimary(t,null),this.flushFrontBuffer(t));var a=this.schedule.findItemIndexAtTime(i);this.setSchedulePosition(a)}else this.checkStart()},r.onAssetListLoaded=function(e,t){var r,i=this,n=t.event,a=n.identifier,s=t.assetListResponse.ASSETS;if(this.schedule.hasEvent(a)){var o=n.timelineStart,l=n.duration,u=0;s.forEach((function(e,t){var r=parseFloat(e.DURATION);i.createAsset(n,t,u,o+u,r,e.URI),u+=r})),n.duration=u,this.log("Loaded asset-list with duration: "+u+" (was: "+l+") "+n);var d=this.waitingItem,h=(null==d?void 0:d.event.identifier)===a;this.updateSchedule();var f=null==(r=this.bufferingItem)?void 0:r.event;if(h){var c,g=this.schedule.findEventIndex(a),v=null==(c=this.schedule.items)?void 0:c[g];if(v){if(!this.playingItem&&this.timelinePos>v.end&&this.schedule.findItemIndexAtTime(this.timelinePos)!==g)return n.error=new Error("Interstitial no longer within playback range "+this.timelinePos+" "+n),void this.primaryFallback(n);this.setBufferingItem(v)}this.setSchedulePosition(g)}else if((null==f?void 0:f.identifier)===a&&f.appendInPlace){var m=n.assetList[0],p=this.getAssetPlayer(m.identifier),y=this.primaryMedia;m&&p&&y&&this.bufferAssetPlayer(p,y)}}},r.onError=function(e,t){switch(t.details){case k.ASSET_LIST_PARSING_ERROR:case k.ASSET_LIST_LOAD_ERROR:case k.ASSET_LIST_LOAD_TIMEOUT:var r=t.interstitial;r&&this.primaryFallback(r);break;case k.BUFFER_STALLED_ERROR:this.onTimeupdate(),this.checkBuffer(!0)}},i(t,[{key:"interstitialsManager",get:function(){if(!this.manager){if(!this.hls)return null;var e=this,t=function(){return e.bufferingItem||e.waitingItem},r=function(t){return t?e.getAssetPlayer(t.identifier):t},i=function(t,i,a,s,o){if(t){var l=t[i].start,u=t.event;if(u){if("playout"===i||u.timelineOccupancy!==vs.Point){var d=r(a);(null==d?void 0:d.interstitial)===u&&(l+=d.assetItem.startOffset+d[o])}}else l+=("bufferedPos"===s?n():e[s])-t.start;return l}return 0},n=function(){var t=e.bufferedPos;return t===Number.MAX_VALUE?a("primary"):Math.max(t,0)},a=function(t){var r;return null!=(r=e.primaryDetails)&&r.live?e.primaryDetails.edge:e.schedule.durations[t]},s=function(t,n){var a,s,o=e.effectivePlayingItem;if(null==o||null==(a=o.event)||!a.restrictions.skip){e.log("seek to "+t+' "'+n+'"');var l=e.effectivePlayingItem,u=e.schedule.findItemIndexAtTime(t,n),d=null==(s=e.schedule.items)?void 0:s[u],h=e.getBufferingPlayer(),f=null==h?void 0:h.interstitial,c=null==f?void 0:f.appendInPlace,g=l&&e.itemsMatch(l,d);if(l&&(c||g)){var v=r(e.playingAsset),m=(null==v?void 0:v.media)||e.primaryMedia;if(m){var p="primary"===n?m.currentTime:i(l,n,e.playingAsset,"timelinePos","currentTime"),y=t-p,E=(c?p:m.currentTime)+y;if(E>=0&&(!v||c||E<=v.duration))return void(m.currentTime=E)}}if(d){var T=t;if("primary"!==n){var S=t-d[n].start;T=d.start+S}var A=!e.isInterstitial(d);if(e.isInterstitial(l)&&!l.event.appendInPlace||!A&&!d.event.appendInPlace){if(l){var L=e.findItemIndex(l);if(u>L){var R=e.schedule.findJumpRestrictedIndex(L+1,u);if(R>L)return void e.setSchedulePosition(R)}var I=0;if(A)e.timelinePos=T,e.checkBuffer();else{var k,b=null==d||null==(k=d.event)?void 0:k.assetList;if(b)for(var D=t-(d[n]||d).start,_=b.length;_--;){var P=b[_];if(P.duration&&D>=P.startOffset&&D0?t:0},set currentTime(e){s(e,"primary")},get duration(){return a("primary")},get seekableStart(){var t;return(null==(t=e.primaryDetails)?void 0:t.fragmentStart)||0}},integrated:{get bufferedEnd(){return i(t(),"integrated",e.bufferingAsset,"bufferedPos","bufferedEnd")},get currentTime(){return i(e.effectivePlayingItem,"integrated",e.effectivePlayingAsset,"timelinePos","currentTime")},set currentTime(e){s(e,"integrated")},get duration(){return a("integrated")},get seekableStart(){var t;return function(t,r){if(0!==t&&"primary"!==r&&e.schedule.length){var i,n=e.schedule.findItemIndexAtTime(t),a=null==(i=e.schedule.items)?void 0:i[n];if(a)return t+(a[r].start-a.start)}return t}((null==(t=e.primaryDetails)?void 0:t.fragmentStart)||0,"integrated")}},skip:function(){var t=e.effectivePlayingItem,r=null==t?void 0:t.event;if(r&&!r.restrictions.skip){var i=e.findItemIndex(t);if(r.appendInPlace){var n=t.playout.start+t.event.duration;s(n+.001,"playout")}else e.advanceAfterAssetEnded(r,i,1/0)}}}}return this.manager}},{key:"effectivePlayingItem",get:function(){return this.waitingItem||this.playingItem||this.endedItem}},{key:"effectivePlayingAsset",get:function(){return this.playingAsset||this.endedAsset}},{key:"playingLastItem",get:function(){var e,t=this.playingItem,r=null==(e=this.schedule)?void 0:e.items;return!!(this.playbackStarted&&t&&r)&&this.findItemIndex(t)===r.length-1}},{key:"playbackStarted",get:function(){return null!==this.effectivePlayingItem}},{key:"currentTime",get:function(){var e,t,r;if(null!==this.mediaSelection){var i=this.waitingItem||this.playingItem;if(!this.isInterstitial(i)||i.event.appendInPlace){var n=this.media;!n&&null!=(e=this.bufferingItem)&&null!=(t=e.event)&&t.appendInPlace&&(n=this.primaryMedia);var a=null==(r=n)?void 0:r.currentTime;if(void 0!==a&&A(a))return a}}}},{key:"primaryMedia",get:function(){var e;return this.media||(null==(e=this.detachedData)?void 0:e.media)||null}},{key:"playbackDisabled",get:function(){return!1===this.hls.config.enableInterstitialPlayback}},{key:"primaryDetails",get:function(){var e,t;return null==(e=this.mediaSelection)||null==(t=e.main)?void 0:t.details}},{key:"primaryLive",get:function(){var e;return!(null==(e=this.primaryDetails)||!e.live)}}])}(N),Ds=function(e){function t(t,r,i){var n;return(n=e.call(this,t,r,i,"subtitle-stream-controller",x)||this).currentTrackId=-1,n.tracksBuffered=[],n.mainDetails=null,n.registerListeners(),n}o(t,e);var r=t.prototype;return r.onHandlerDestroying=function(){this.unregisterListeners(),e.prototype.onHandlerDestroying.call(this),this.mainDetails=null},r.registerListeners=function(){e.prototype.registerListeners.call(this);var t=this.hls;t.on(b.LEVEL_LOADED,this.onLevelLoaded,this),t.on(b.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),t.on(b.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),t.on(b.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),t.on(b.SUBTITLE_FRAG_PROCESSED,this.onSubtitleFragProcessed,this),t.on(b.BUFFER_FLUSHING,this.onBufferFlushing,this)},r.unregisterListeners=function(){e.prototype.unregisterListeners.call(this);var t=this.hls;t.off(b.LEVEL_LOADED,this.onLevelLoaded,this),t.off(b.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),t.off(b.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),t.off(b.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),t.off(b.SUBTITLE_FRAG_PROCESSED,this.onSubtitleFragProcessed,this),t.off(b.BUFFER_FLUSHING,this.onBufferFlushing,this)},r.startLoad=function(e,t){this.stopLoad(),this.state=Ei.IDLE,this.setInterval(500),this.nextLoadPosition=this.lastCurrentTime=e+this.timelineOffset,this.startPosition=t?-1:e,this.tick()},r.onManifestLoading=function(){e.prototype.onManifestLoading.call(this),this.mainDetails=null},r.onMediaDetaching=function(t,r){this.tracksBuffered=[],e.prototype.onMediaDetaching.call(this,t,r)},r.onLevelLoaded=function(e,t){this.mainDetails=t.details},r.onSubtitleFragProcessed=function(e,t){var r=t.frag,i=t.success;if(this.fragContextChanged(r)||(ee(r)&&(this.fragPrevious=r),this.state=Ei.IDLE),i){var n=this.tracksBuffered[this.currentTrackId];if(n){for(var a,s=r.start,o=0;o=n[o].start&&s<=n[o].end){a=n[o];break}var l=r.start+r.duration;a?a.end=l:(a={start:s,end:l},n.push(a)),this.fragmentTracker.fragBuffered(r),this.fragBufferedComplete(r,null),this.media&&this.tick()}}},r.onBufferFlushing=function(e,t){var r=t.startOffset,i=t.endOffset;if(0===r&&i!==Number.POSITIVE_INFINITY){var n=i-1;if(n<=0)return;t.endOffsetSubtitles=Math.max(0,n),this.tracksBuffered.forEach((function(e){for(var t=0;t=n.length)&&o){this.log("Subtitle track "+s+" loaded ["+a.startSN+","+a.endSN+"]"+(a.lastPartSn?"[part-"+a.lastPartSn+"-"+a.lastPartIndex+"]":"")+",duration:"+a.totalduration),this.mediaBuffer=this.mediaBufferTimeRanges;var l=0;if(a.live||null!=(r=o.details)&&r.live){if(a.deltaUpdateFailed)return;var u=this.mainDetails;if(!u)return void(this.startFragRequested=!1);var d,h=u.fragments[0];o.details?0===(l=this.alignPlaylists(a,o.details,null==(d=this.levelLastLoaded)?void 0:d.details))&&h&&oi(a,l=h.start):a.hasProgramDateTime&&u.hasProgramDateTime?(pi(a,u),l=a.fragmentStart):h&&oi(a,l=h.start),u&&!this.startFragRequested&&this.setStartPosition(u,l)}o.details=a,this.levelLastLoaded=o,s===i&&(this.hls.trigger(b.SUBTITLE_TRACK_UPDATED,{details:a,id:s,groupId:t.groupId}),this.tick(),a.live&&!this.fragCurrent&&this.media&&this.state===Ei.IDLE&&(pt(null,a.fragments,this.media.currentTime,0)||(this.warn("Subtitle playlist not aligned with playback"),o.details=void 0)))}}else this.warn("Subtitle tracks were reset while loading level "+s)},r._handleFragmentLoadComplete=function(e){var t=this,r=e.frag,i=e.payload,n=r.decryptdata,a=this.hls;if(!this.fragContextChanged(r)&&i&&i.byteLength>0&&null!=n&&n.key&&n.iv&&vr(n.method)){var s=performance.now();this.decrypter.decrypt(new Uint8Array(i),n.key.buffer,n.iv.buffer,mr(n.method)).catch((function(e){throw a.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.FRAG_DECRYPT_ERROR,fatal:!1,error:e,reason:e.message,frag:r}),e})).then((function(e){var t=performance.now();a.trigger(b.FRAG_DECRYPTED,{frag:r,payload:e,stats:{tstart:s,tdecrypt:t}})})).catch((function(e){t.warn(e.name+": "+e.message),t.state=Ei.IDLE}))}},r.doTick=function(){if(this.media){if(this.state===Ei.IDLE){var e=this.currentTrackId,t=this.levels,r=null==t?void 0:t[e];if(!r||!t.length||!r.details)return;if(this.waitForLive(r))return;var i=this.config,n=this.getLoadPosition(),a=ir.bufferedInfo(this.tracksBuffered[this.currentTrackId]||[],n,i.maxBufferHole),s=a.end,o=a.len,l=r.details;if(o>this.hls.maxBufferLength+l.levelTargetDuration)return;var u=l.fragments,d=u.length,h=l.edge,f=null,c=this.fragPrevious;if(sh-g?0:g;!(f=pt(c,u,Math.max(u[0].start,s),v))&&c&&c.start>>=0)>i-1)throw new DOMException("Failed to execute '"+t+"' on 'TimeRanges': The index provided ("+r+") is greater than the maximum bound ("+i+")");return e[r][t]};this.buffered={get length(){return e.length},end:function(r){return t("end",r,e.length)},start:function(r){return t("start",r,e.length)}}};function Ps(e,t){var r;try{r=new Event("addtrack")}catch(e){(r=document.createEvent("Event")).initEvent("addtrack",!1,!1)}r.track=e,t.dispatchEvent(r)}function Cs(e,t){var r=e.mode;if("disabled"===r&&(e.mode="hidden"),e.cues&&!e.cues.getCueById(t.id))try{if(e.addCue(t),!e.cues.getCueById(t.id))throw new Error("addCue is failed for: "+t)}catch(r){Y.debug("[texttrack-utils]: "+r);try{var i=new self.TextTrackCue(t.startTime,t.endTime,t.text);i.id=t.id,e.addCue(i)}catch(e){Y.debug("[texttrack-utils]: Legacy TextTrackCue fallback failed: "+e)}}"disabled"===r&&(e.mode=r)}function ws(e,t){var r=e.mode;if("disabled"===r&&(e.mode="hidden"),e.cues)for(var i=e.cues.length;i--;)t&&e.cues[i].removeEventListener("enter",t),e.removeCue(e.cues[i]);"disabled"===r&&(e.mode=r)}function Os(e,t,r,i){var n=e.mode;if("disabled"===n&&(e.mode="hidden"),e.cues&&e.cues.length>0)for(var a=function(e,t,r){var i=[],n=function(e,t){if(t<=e[0].startTime)return 0;var r=e.length-1;if(t>e[r].endTime)return-1;for(var i,n=0,a=r;n<=a;)if(te[i].startTime&&n-1)for(var a=n,s=e.length;a=t&&o.endTime<=r)i.push(o);else if(o.startTime>r)return i}return i}(e.cues,t,r),s=0;s-1&&(this.subtitleTrack=this.queuedDefaultTrack,this.queuedDefaultTrack=-1),this.useTextTrackPolling=!(this.media.textTracks&&"onchange"in this.media.textTracks),this.useTextTrackPolling?this.pollTrackChange(500):this.media.textTracks.addEventListener("change",this.asyncPollTrackChange))},r.pollTrackChange=function(e){self.clearInterval(this.subtitlePollingInterval),this.subtitlePollingInterval=self.setInterval(this.onTextTracksChanged,e)},r.onMediaDetaching=function(e,t){var r=this.media;if(r){var i=!!t.transferMedia;self.clearInterval(this.subtitlePollingInterval),this.useTextTrackPolling||r.textTracks.removeEventListener("change",this.asyncPollTrackChange),this.trackId>-1&&(this.queuedDefaultTrack=this.trackId),this.subtitleTrack=-1,this.media=null,i||xs(r.textTracks).forEach((function(e){ws(e)}))}},r.onManifestLoading=function(){this.tracks=[],this.groupIds=null,this.tracksInGroup=[],this.trackId=-1,this.currentTrack=null,this.selectDefaultTrack=!0},r.onManifestParsed=function(e,t){this.tracks=t.subtitleTracks},r.onSubtitleTrackLoaded=function(e,t){var r=t.id,i=t.groupId,n=t.details,a=this.tracksInGroup[r];if(a&&a.groupId===i){var s=a.details;a.details=t.details,this.log("Subtitle track "+r+' "'+a.name+'" lang:'+a.lang+" group:"+i+" loaded ["+n.startSN+"-"+n.endSN+"]"),r===this.trackId&&this.playlistLoaded(r,t,s)}else this.warn("Subtitle track with id:"+r+" and group:"+i+" not found in active group "+(null==a?void 0:a.groupId))},r.onLevelLoading=function(e,t){this.switchLevel(t.level)},r.onLevelSwitching=function(e,t){this.switchLevel(t.level)},r.switchLevel=function(e){var t=this.hls.levels[e];if(t){var r=t.subtitleGroups||null,i=this.groupIds,n=this.currentTrack;if(!r||(null==i?void 0:i.length)!==(null==r?void 0:r.length)||null!=r&&r.some((function(e){return-1===(null==i?void 0:i.indexOf(e))}))){this.groupIds=r,this.trackId=-1,this.currentTrack=null;var a=this.tracks.filter((function(e){return!r||-1!==r.indexOf(e.groupId)}));if(a.length)this.selectDefaultTrack&&!a.some((function(e){return e.default}))&&(this.selectDefaultTrack=!1),a.forEach((function(e,t){e.id=t}));else if(!n&&!this.tracksInGroup.length)return;this.tracksInGroup=a;var s=this.hls.config.subtitlePreference;if(!n&&s){this.selectDefaultTrack=!1;var o=dt(s,a);if(o>-1)n=a[o];else{var l=dt(s,this.tracks);n=this.tracks[l]}}var u=this.findTrackId(n);-1===u&&n&&(u=this.findTrackId(null));var d={subtitleTracks:a};this.log("Updating subtitle tracks, "+a.length+' track(s) found in "'+(null==r?void 0:r.join(","))+'" group-id'),this.hls.trigger(b.SUBTITLE_TRACKS_UPDATED,d),-1!==u&&-1===this.trackId&&this.setSubtitleTrack(u)}}},r.findTrackId=function(e){for(var t=this.tracksInGroup,r=this.selectDefaultTrack,i=0;i-1){var n=this.tracksInGroup[i];return this.setSubtitleTrack(i),n}if(r)return null;var a=dt(e,t);if(a>-1)return t[a]}}return null},r.loadPlaylist=function(t){e.prototype.loadPlaylist.call(this),this.shouldLoadPlaylist(this.currentTrack)&&this.scheduleLoading(this.currentTrack,t)},r.loadingPlaylist=function(t,r){e.prototype.loadingPlaylist.call(this,t,r);var i=t.id,n=t.groupId,a=this.getUrlWithDirectives(t.url,r),s=t.details,o=null==s?void 0:s.age;this.log("Loading subtitle "+i+' "'+t.name+'" lang:'+t.lang+" group:"+n+(void 0!==(null==r?void 0:r.msn)?" at sn "+r.msn+" part "+r.part:"")+(o&&s.live?" age "+o.toFixed(1)+(s.type&&" "+s.type||""):"")+" "+a),this.hls.trigger(b.SUBTITLE_TRACK_LOADING,{url:a,id:i,groupId:n,deliveryDirectives:r||null,track:t})},r.toggleTrackModes=function(){var e=this.media;if(e){var t,r=xs(e.textTracks),i=this.currentTrack;if(i&&((t=r.filter((function(e){return da(i,e)}))[0])||this.warn('Unable to find subtitle TextTrack with name "'+i.name+'" and language "'+i.lang+'"')),[].slice.call(r).forEach((function(e){"disabled"!==e.mode&&e!==t&&(e.mode="disabled")})),t){var n=this.subtitleDisplay?"showing":"hidden";t.mode!==n&&(t.mode=n)}}},r.setSubtitleTrack=function(e){var t=this.tracksInGroup;if(this.media)if(e<-1||e>=t.length||!A(e))this.warn("Invalid subtitle track id: "+e);else{this.selectDefaultTrack=!1;var r=this.currentTrack,i=t[e]||null;if(this.trackId=e,this.currentTrack=i,this.toggleTrackModes(),i){var n=!!i.details&&!i.details.live;if(e!==this.trackId||i!==r||!n){this.log("Switching to subtitle-track "+e+(i?' "'+i.name+'" lang:'+i.lang+" group:"+i.groupId:""));var a=i.id,s=i.groupId,o=void 0===s?"":s,l=i.name,u=i.type,d=i.url;this.hls.trigger(b.SUBTITLE_TRACK_SWITCH,{id:a,groupId:o,name:l,type:u,url:d});var h=this.switchParams(i.url,null==r?void 0:r.details,i.details);this.loadPlaylist(h)}}else this.hls.trigger(b.SUBTITLE_TRACK_SWITCH,{id:e})}else this.queuedDefaultTrack=e},i(t,[{key:"subtitleDisplay",get:function(){return this._subtitleDisplay},set:function(e){this._subtitleDisplay=e,this.trackId>-1&&this.toggleTrackModes()}},{key:"allSubtitleTracks",get:function(){return this.tracks}},{key:"subtitleTracks",get:function(){return this.tracksInGroup}},{key:"subtitleTrack",get:function(){return this.trackId},set:function(e){this.selectDefaultTrack=!1,this.setSubtitleTrack(e)}}])}(oa),Fs={42:225,92:233,94:237,95:243,96:250,123:231,124:247,125:209,126:241,127:9608,128:174,129:176,130:189,131:191,132:8482,133:162,134:163,135:9834,136:224,137:32,138:232,139:226,140:234,141:238,142:244,143:251,144:193,145:201,146:211,147:218,148:220,149:252,150:8216,151:161,152:42,153:8217,154:9473,155:169,156:8480,157:8226,158:8220,159:8221,160:192,161:194,162:199,163:200,164:202,165:203,166:235,167:206,168:207,169:239,170:212,171:217,172:249,173:219,174:171,175:187,176:195,177:227,178:205,179:204,180:236,181:210,182:242,183:213,184:245,185:123,186:125,187:92,188:94,189:95,190:124,191:8764,192:196,193:228,194:214,195:246,196:223,197:165,198:164,199:9475,200:197,201:229,202:216,203:248,204:9487,205:9491,206:9495,207:9499},Ns=function(e){return String.fromCharCode(Fs[e]||e)},Us=15,Bs=100,Gs={17:1,18:3,21:5,22:7,23:9,16:11,19:12,20:14},Ks={17:2,18:4,21:6,22:8,23:10,19:13,20:15},Vs={25:1,26:3,29:5,30:7,31:9,24:11,27:12,28:14},Hs={25:2,26:4,29:6,30:8,31:10,27:13,28:15},Ys=["white","green","blue","cyan","red","yellow","magenta","black","transparent"],Ws=function(){function e(){this.time=null,this.verboseLevel=0}return e.prototype.log=function(e,t){if(this.verboseLevel>=e){var r="function"==typeof t?t():t;Y.log(this.time+" ["+e+"] "+r)}},e}(),js=function(e){for(var t=[],r=0;rBs&&(this.logger.log(3,"Too large cursor position "+this.pos),this.pos=Bs)},t.moveCursor=function(e){var t=this.pos+e;if(e>1)for(var r=this.pos+1;r=144&&this.backSpace();var r=Ns(e);this.pos>=Bs?this.logger.log(0,(function(){return"Cannot insert "+e.toString(16)+" ("+r+") at position "+t.pos+". Skipping it!"})):(this.chars[this.pos].setChar(r,this.currPenState),this.moveCursor(1))},t.clearFromPos=function(e){var t;for(t=e;t0&&(r=e?"["+t.join(" | ")+"]":t.join("\n")),r},t.getTextAndFormat=function(){return this.rows},e}(),$s=function(){function e(e,t,r){this.chNr=void 0,this.outputFilter=void 0,this.mode=void 0,this.verbose=void 0,this.displayedMemory=void 0,this.nonDisplayedMemory=void 0,this.lastOutputScreen=void 0,this.currRollUpRow=void 0,this.writeScreen=void 0,this.cueStartTime=void 0,this.logger=void 0,this.chNr=e,this.outputFilter=t,this.mode=null,this.verbose=0,this.displayedMemory=new zs(r),this.nonDisplayedMemory=new zs(r),this.lastOutputScreen=new zs(r),this.currRollUpRow=this.displayedMemory.rows[14],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null,this.logger=r}var t=e.prototype;return t.reset=function(){this.mode=null,this.displayedMemory.reset(),this.nonDisplayedMemory.reset(),this.lastOutputScreen.reset(),this.outputFilter.reset(),this.currRollUpRow=this.displayedMemory.rows[14],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null},t.getHandler=function(){return this.outputFilter},t.setHandler=function(e){this.outputFilter=e},t.setPAC=function(e){this.writeScreen.setPAC(e)},t.setBkgData=function(e){this.writeScreen.setBkgData(e)},t.setMode=function(e){e!==this.mode&&(this.mode=e,this.logger.log(2,(function(){return"MODE="+e})),"MODE_POP-ON"===this.mode?this.writeScreen=this.nonDisplayedMemory:(this.writeScreen=this.displayedMemory,this.writeScreen.reset()),"MODE_ROLL-UP"!==this.mode&&(this.displayedMemory.nrRollUpRows=null,this.nonDisplayedMemory.nrRollUpRows=null),this.mode=e)},t.insertChars=function(e){for(var t=this,r=0;r=46,t.italics)t.foreground="white";else{var r=Math.floor(e/2)-16;t.foreground=["white","green","blue","cyan","red","yellow","magenta"][r]}this.logger.log(2,"MIDROW: "+st(t)),this.writeScreen.setPen(t)},t.outputDataUpdate=function(e){void 0===e&&(e=!1);var t=this.logger.time;null!==t&&this.outputFilter&&(null!==this.cueStartTime||this.displayedMemory.isEmpty()?this.displayedMemory.equals(this.lastOutputScreen)||(this.outputFilter.newCue(this.cueStartTime,t,this.lastOutputScreen),e&&this.outputFilter.dispatchCue&&this.outputFilter.dispatchCue(),this.cueStartTime=this.displayedMemory.isEmpty()?null:t):this.cueStartTime=t,this.lastOutputScreen.copy(this.displayedMemory))},t.cueSplitAtTime=function(e){this.outputFilter&&(this.displayedMemory.isEmpty()||(this.outputFilter.newCue&&this.outputFilter.newCue(this.cueStartTime,e,this.displayedMemory),this.cueStartTime=e))},e}(),Js=function(){function e(e,t,r){this.channels=void 0,this.currentChannel=0,this.cmdHistory={a:null,b:null},this.logger=void 0;var i=this.logger=new Ws;this.channels=[null,new $s(e,t,i),new $s(e+1,r,i)]}var t=e.prototype;return t.getHandler=function(e){return this.channels[e].getHandler()},t.setHandler=function(e,t){this.channels[e].setHandler(t)},t.addData=function(e,t){var r=this;this.logger.time=e;for(var i=function(e){var i=127&t[e],n=127&t[e+1],a=!1,s=null;if(0===i&&0===n)return 0;r.logger.log(3,(function(){return"["+js([t[e],t[e+1]])+"] -> ("+js([i,n])+")"}));var o=r.cmdHistory;if(i>=16&&i<=31){if(function(e,t,r){return r.a===e&&r.b===t}(i,n,o))return Zs(null,null,o),r.logger.log(3,(function(){return"Repeated command ("+js([i,n])+") is dropped"})),0;Zs(i,n,r.cmdHistory),(a=r.parseCmd(i,n))||(a=r.parseMidrow(i,n)),a||(a=r.parsePAC(i,n)),a||(a=r.parseBackgroundAttributes(i,n))}else Zs(null,null,o);if(!a&&(s=r.parseChars(i,n))){var l=r.currentChannel;l&&l>0?r.channels[l].insertChars(s):r.logger.log(2,"No channel found yet. TEXT-MODE?")}a||s||r.logger.log(2,(function(){return"Couldn't parse cleaned data "+js([i,n])+" orig: "+js([t[e],t[e+1]])}))},n=0;n=32&&t<=47||(23===e||31===e)&&t>=33&&t<=35))return!1;var r=20===e||21===e||23===e?1:2,i=this.channels[r];return 20===e||21===e||28===e||29===e?32===t?i.ccRCL():33===t?i.ccBS():34===t?i.ccAOF():35===t?i.ccAON():36===t?i.ccDER():37===t?i.ccRU(2):38===t?i.ccRU(3):39===t?i.ccRU(4):40===t?i.ccFON():41===t?i.ccRDC():42===t?i.ccTR():43===t?i.ccRTD():44===t?i.ccEDM():45===t?i.ccCR():46===t?i.ccENM():47===t&&i.ccEOC():i.ccTO(t-32),this.currentChannel=r,!0},t.parseMidrow=function(e,t){var r=0;if((17===e||25===e)&&t>=32&&t<=47){if((r=17===e?1:2)!==this.currentChannel)return this.logger.log(0,"Mismatch channel in midrow parsing"),!1;var i=this.channels[r];return!!i&&(i.ccMIDROW(t),this.logger.log(3,(function(){return"MIDROW ("+js([e,t])+")"})),!0)}return!1},t.parsePAC=function(e,t){var r;if(!((e>=17&&e<=23||e>=25&&e<=31)&&t>=64&&t<=127||(16===e||24===e)&&t>=64&&t<=95))return!1;var i=e<=23?1:2;r=t>=64&&t<=95?1===i?Gs[e]:Vs[e]:1===i?Ks[e]:Hs[e];var n=this.channels[i];return!!n&&(n.setPAC(this.interpretPAC(r,t)),this.currentChannel=i,!0)},t.interpretPAC=function(e,t){var r,i={color:null,italics:!1,indent:null,underline:!1,row:e};return r=t>95?t-96:t-64,i.underline=1==(1&r),r<=13?i.color=["white","green","blue","cyan","red","yellow","magenta","white"][Math.floor(r/2)]:r<=15?(i.italics=!0,i.color="white"):i.indent=4*Math.floor((r-16)/2),i},t.parseChars=function(e,t){var r,i,n=null,a=null;return e>=25?(r=2,a=e-8):(r=1,a=e),a>=17&&a<=19?(i=17===a?t+80:18===a?t+112:t+144,this.logger.log(2,(function(){return"Special char '"+Ns(i)+"' in channel "+r})),n=[i]):e>=32&&e<=127&&(n=0===t?[e]:[e,t]),n&&this.logger.log(3,(function(){return"Char codes =  "+js(n).join(",")})),n},t.parseBackgroundAttributes=function(e,t){var r;if(!((16===e||24===e)&&t>=32&&t<=47||(23===e||31===e)&&t>=45&&t<=47))return!1;var i={};16===e||24===e?(r=Math.floor((t-32)/2),i.background=Ys[r],t%2==1&&(i.background=i.background+"_semi")):45===t?i.background="transparent":(i.foreground="black",47===t&&(i.underline=!0));var n=e<=23?1:2;return this.channels[n].setBkgData(i),!0},t.reset=function(){for(var e=0;e1?t-1:0),i=1;i100)throw new Error("Position must be between 0 and 100.");E=e,this.hasBeenReset=!0}})),Object.defineProperty(o,"positionAlign",n({},l,{get:function(){return T},set:function(e){var t=i(e);if(!t)throw new SyntaxError("An invalid or illegal string was specified.");T=t,this.hasBeenReset=!0}})),Object.defineProperty(o,"size",n({},l,{get:function(){return S},set:function(e){if(e<0||e>100)throw new Error("Size must be between 0 and 100.");S=e,this.hasBeenReset=!0}})),Object.defineProperty(o,"align",n({},l,{get:function(){return A},set:function(e){var t=i(e);if(!t)throw new SyntaxError("An invalid or illegal string was specified.");A=t,this.hasBeenReset=!0}})),o.displayState=void 0}return a.prototype.getCueAsHTML=function(){return self.WebVTT.convertCueToDOMTree(self,this.text)},a}(),to=function(){function e(){}return e.prototype.decode=function(e,t){if(!e)return"";if("string"!=typeof e)throw new Error("Error - expected string data.");return decodeURIComponent(encodeURIComponent(e))},e}();function ro(e){function t(e,t,r,i){return 3600*(0|e)+60*(0|t)+(0|r)+parseFloat(i||0)}var r=e.match(/^(?:(\d+):)?(\d{2}):(\d{2})(\.\d+)?/);return r?parseFloat(r[2])>59?t(r[2],r[3],0,r[4]):t(r[1],r[2],r[3],r[4]):null}var io=function(){function e(){this.values=Object.create(null)}var t=e.prototype;return t.set=function(e,t){this.get(e)||""===t||(this.values[e]=t)},t.get=function(e,t,r){return r?this.has(e)?this.values[e]:t[r]:this.has(e)?this.values[e]:t},t.has=function(e){return e in this.values},t.alt=function(e,t,r){for(var i=0;i=0&&r<=100)return this.set(e,r),!0}return!1},e}();function no(e,t,r,i){var n=i?e.split(i):[e];for(var a in n)if("string"==typeof n[a]){var s=n[a].split(r);2===s.length&&t(s[0],s[1])}}var ao=new eo(0,0,""),so="middle"===ao.align?"middle":"center";function oo(e,t,r){var i=e;function n(){var t=ro(e);if(null===t)throw new Error("Malformed timestamp: "+i);return e=e.replace(/^[^\sa-zA-Z-]+/,""),t}function a(){e=e.replace(/^\s+/,"")}if(a(),t.startTime=n(),a(),"--\x3e"!==e.slice(0,3))throw new Error("Malformed time stamp (time stamps must be separated by '--\x3e'): "+i);e=e.slice(3),a(),t.endTime=n(),a(),function(e,t){var i=new io;no(e,(function(e,t){var n;switch(e){case"region":for(var a=r.length-1;a>=0;a--)if(r[a].id===t){i.set(e,r[a].region);break}break;case"vertical":i.alt(e,t,["rl","lr"]);break;case"line":n=t.split(","),i.integer(e,n[0]),i.percent(e,n[0])&&i.set("snapToLines",!1),i.alt(e,n[0],["auto"]),2===n.length&&i.alt("lineAlign",n[1],["start",so,"end"]);break;case"position":n=t.split(","),i.percent(e,n[0]),2===n.length&&i.alt("positionAlign",n[1],["start",so,"end","line-left","line-right","auto"]);break;case"size":i.percent(e,t);break;case"align":i.alt(e,t,["start",so,"end","left","right"])}}),/:/,/\s/),t.region=i.get("region",null),t.vertical=i.get("vertical","");var n=i.get("line","auto");"auto"===n&&-1===ao.line&&(n=-1),t.line=n,t.lineAlign=i.get("lineAlign","start"),t.snapToLines=i.get("snapToLines",!0),t.size=i.get("size",100),t.align=i.get("align",so);var a=i.get("position","auto");"auto"===a&&50===ao.position&&(a="start"===t.align||"left"===t.align?0:"end"===t.align||"right"===t.align?100:50),t.position=a}(e,t)}function lo(e){return e.replace(//gi,"\n")}var uo=function(){function e(){this.state="INITIAL",this.buffer="",this.decoder=new to,this.regionList=[],this.cue=null,this.oncue=void 0,this.onparsingerror=void 0,this.onflush=void 0}var t=e.prototype;return t.parse=function(e){var t=this;function r(){var e=t.buffer,r=0;for(e=lo(e);r0&&f.push(e)},d.onparsingerror=function(e){u=e},d.onflush=function(){u?s(u):a(f)},h.forEach((function(e){if(p){if(fo(e,"X-TIMESTAMP-MAP=")){p=!1,e.slice(16).split(",").forEach((function(e){fo(e,"LOCAL:")?g=e.slice(6):fo(e,"MPEGTS:")&&(v=parseInt(e.slice(7)))}));try{m=function(e){var t=parseInt(e.slice(-3)),r=parseInt(e.slice(-6,-4)),i=parseInt(e.slice(-9,-7)),n=e.length>9?parseInt(e.substring(0,e.indexOf(":"))):0;if(!(A(t)&&A(r)&&A(i)&&A(n)))throw Error("Malformed X-TIMESTAMP-MAP: Local:"+e);return t+=1e3*r,(t+=6e4*i)+36e5*n}(g)/1e3}catch(e){u=e}return}""===e&&(p=!1)}d.parse(e+"\n")})),d.flush()}var vo="stpp.ttml.im1t",mo=/^(\d{2,}):(\d{2}):(\d{2}):(\d{2})\.?(\d+)?$/,po=/^(\d*(?:\.\d*)?)(h|m|s|ms|f|t)$/,yo={left:"start",center:"center",right:"end",start:"start",end:"end"};function Eo(e,t,r,i){var n=fe(new Uint8Array(e),["mdat"]);if(0!==n.length){var s,o,l,u,d=n.map((function(e){return q(e)})),h=(s=t.baseTime,o=1,void 0===(l=t.timescale)&&(l=1),void 0===u&&(u=!1),wn(s,o,1/l,u));try{d.forEach((function(e){return r(function(e,t){var r=(new DOMParser).parseFromString(e,"text/xml"),i=r.getElementsByTagName("tt")[0];if(!i)throw new Error("Invalid ttml");var n={frameRate:30,subFrameRate:1,frameRateMultiplier:0,tickRate:0},s=Object.keys(n).reduce((function(e,t){return e[t]=i.getAttribute("ttp:"+t)||n[t],e}),{}),o="preserve"!==i.getAttribute("xml:space"),l=So(To(i,"styling","style")),u=So(To(i,"layout","region")),d=To(i,"body","[begin]");return[].map.call(d,(function(e){var r=Ao(e,o);if(!r||!e.hasAttribute("begin"))return null;var i=Io(e.getAttribute("begin"),s),n=Io(e.getAttribute("dur"),s),d=Io(e.getAttribute("end"),s);if(null===i)throw Ro(e);if(null===d){if(null===n)throw Ro(e);d=i+n}var h=new eo(i-t,d-t,r);h.id=co(h.startTime,h.endTime,h.text);var f=function(e,t,r){var i="http://www.w3.org/ns/ttml#styling",n=null,a=["displayAlign","textAlign","color","backgroundColor","fontSize","fontFamily"],s=null!=e&&e.hasAttribute("style")?e.getAttribute("style"):null;return s&&r.hasOwnProperty(s)&&(n=r[s]),a.reduce((function(r,a){var s=Lo(t,i,a)||Lo(e,i,a)||Lo(n,i,a);return s&&(r[a]=s),r}),{})}(u[e.getAttribute("region")],l[e.getAttribute("style")],l),c=f.textAlign;if(c){var g=yo[c];g&&(h.lineAlign=g),h.align=c}return a(h,f),h})).filter((function(e){return null!==e}))}(e,h))}))}catch(e){i(e)}}else i(new Error("Could not parse IMSC1 mdat"))}function To(e,t,r){var i=e.getElementsByTagName(t)[0];return i?[].slice.call(i.querySelectorAll(r)):[]}function So(e){return e.reduce((function(e,t){var r=t.getAttribute("xml:id");return r&&(e[r]=t),e}),{})}function Ao(e,t){return[].slice.call(e.childNodes).reduce((function(e,r,i){var n;return"br"===r.nodeName&&i?e+"\n":null!=(n=r.childNodes)&&n.length?Ao(r,t):t?e+r.textContent.trim().replace(/\s+/g," "):e+r.textContent}),"")}function Lo(e,t,r){return e&&e.hasAttributeNS(t,r)?e.getAttributeNS(t,r):null}function Ro(e){return new Error("Could not parse ttml timestamp "+e)}function Io(e,t){if(!e)return null;var r=ro(e);return null===r&&(mo.test(e)?r=function(e,t){var r=mo.exec(e),i=(0|r[4])+(0|r[5])/t.subFrameRate;return 3600*(0|r[1])+60*(0|r[2])+(0|r[3])+i/t.frameRate}(e,t):po.test(e)&&(r=function(e,t){var r=po.exec(e),i=Number(r[1]);switch(r[2]){case"h":return 3600*i;case"m":return 60*i;case"ms":return 1e3*i;case"f":return i/t.frameRate;case"t":return i/t.tickRate}return i}(e,t))),r}var ko=function(){function e(e,t){this.timelineController=void 0,this.cueRanges=[],this.trackName=void 0,this.startTime=null,this.endTime=null,this.screen=null,this.timelineController=e,this.trackName=t}var t=e.prototype;return t.dispatchCue=function(){null!==this.startTime&&(this.timelineController.addCues(this.trackName,this.startTime,this.endTime,this.screen,this.cueRanges),this.startTime=null)},t.newCue=function(e,t,r){(null===this.startTime||this.startTime>e)&&(this.startTime=e),this.endTime=t,this.screen=r,this.timelineController.createCaptionsTrack(this.trackName)},t.reset=function(){this.cueRanges=[],this.startTime=null},e}(),bo=function(){function e(e){this.hls=void 0,this.media=null,this.config=void 0,this.enabled=!0,this.Cues=void 0,this.textTracks=[],this.tracks=[],this.initPTS=[],this.unparsedVttFrags=[],this.captionsTracks={},this.nonNativeCaptionsTracks={},this.cea608Parser1=void 0,this.cea608Parser2=void 0,this.lastCc=-1,this.lastSn=-1,this.lastPartIndex=-1,this.prevCC=-1,this.vttCCs={ccOffset:0,presentationOffset:0,0:{start:0,prevCC:-1,new:!0}},this.captionsProperties=void 0,this.hls=e,this.config=e.config,this.Cues=e.config.cueHandler,this.captionsProperties={textTrack1:{label:this.config.captionsTextTrack1Label,languageCode:this.config.captionsTextTrack1LanguageCode},textTrack2:{label:this.config.captionsTextTrack2Label,languageCode:this.config.captionsTextTrack2LanguageCode},textTrack3:{label:this.config.captionsTextTrack3Label,languageCode:this.config.captionsTextTrack3LanguageCode},textTrack4:{label:this.config.captionsTextTrack4Label,languageCode:this.config.captionsTextTrack4LanguageCode}},e.on(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(b.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.on(b.FRAG_LOADING,this.onFragLoading,this),e.on(b.FRAG_LOADED,this.onFragLoaded,this),e.on(b.FRAG_PARSING_USERDATA,this.onFragParsingUserdata,this),e.on(b.FRAG_DECRYPTED,this.onFragDecrypted,this),e.on(b.INIT_PTS_FOUND,this.onInitPtsFound,this),e.on(b.SUBTITLE_TRACKS_CLEARED,this.onSubtitleTracksCleared,this),e.on(b.BUFFER_FLUSHING,this.onBufferFlushing,this)}var t=e.prototype;return t.destroy=function(){var e=this.hls;e.off(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(b.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.off(b.FRAG_LOADING,this.onFragLoading,this),e.off(b.FRAG_LOADED,this.onFragLoaded,this),e.off(b.FRAG_PARSING_USERDATA,this.onFragParsingUserdata,this),e.off(b.FRAG_DECRYPTED,this.onFragDecrypted,this),e.off(b.INIT_PTS_FOUND,this.onInitPtsFound,this),e.off(b.SUBTITLE_TRACKS_CLEARED,this.onSubtitleTracksCleared,this),e.off(b.BUFFER_FLUSHING,this.onBufferFlushing,this),this.hls=this.config=this.media=null,this.cea608Parser1=this.cea608Parser2=void 0},t.initCea608Parsers=function(){var e=new ko(this,"textTrack1"),t=new ko(this,"textTrack2"),r=new ko(this,"textTrack3"),i=new ko(this,"textTrack4");this.cea608Parser1=new Js(1,e,t),this.cea608Parser2=new Js(3,r,i)},t.addCues=function(e,t,r,i,n){for(var a,s,o,l,u=!1,d=n.length;d--;){var h=n[d],f=(a=h[0],s=h[1],o=t,l=r,Math.min(s,l)-Math.max(a,o));if(f>=0&&(h[0]=Math.min(h[0],t),h[1]=Math.max(h[1],r),u=!0,f/(r-t)>.5))return}if(u||n.push([t,r]),this.config.renderTextTracksNatively){var c=this.captionsTracks[e];this.Cues.newCue(c,t,r,i)}else{var g=this.Cues.newCue(null,t,r,i);this.hls.trigger(b.CUES_PARSED,{type:"captions",cues:g,track:e})}},t.onInitPtsFound=function(e,t){var r=this,i=t.frag,n=t.id,a=t.initPTS,s=t.timescale,o=this.unparsedVttFrags;n===w&&(this.initPTS[i.cc]={baseTime:a,timescale:s}),o.length&&(this.unparsedVttFrags=[],o.forEach((function(e){r.initPTS[e.frag.cc]?r.onFragLoaded(b.FRAG_LOADED,e):r.hls.trigger(b.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:e.frag,error:new Error("Subtitle discontinuity domain does not match main")})})))},t.getExistingTrack=function(e,t){var r=this.media;if(r)for(var i=0;ii.cc||l.trigger(b.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:i,error:t})}))}else s.push(e)},t._fallbackToIMSC1=function(e,t){var r=this,i=this.tracks[e.level];i.textCodec||Eo(t,this.initPTS[e.cc],(function(){i.textCodec=vo,r._parseIMSC1(e,t)}),(function(){i.textCodec="wvtt"}))},t._appendCues=function(e,t){var r=this.hls;if(this.config.renderTextTracksNatively){var i=this.textTracks[t];if(!i||"disabled"===i.mode)return;e.forEach((function(e){return Cs(i,e)}))}else{var n=this.tracks[t];if(!n)return;var a=n.default?"default":"subtitles"+t;r.trigger(b.CUES_PARSED,{type:"subtitles",cues:e,track:a})}},t.onFragDecrypted=function(e,t){t.frag.type===x&&this.onFragLoaded(b.FRAG_LOADED,t)},t.onSubtitleTracksCleared=function(){this.tracks=[],this.captionsTracks={}},t.onFragParsingUserdata=function(e,t){if(this.enabled&&this.config.enableCEA708Captions){var r=t.frag,i=t.samples;if(r.type!==w||"NONE"!==this.closedCaptionsForLevel(r))for(var n=0;n=16?o--:o++;var g=lo(l.trim()),v=co(t,r,g);null!=e&&null!=(f=e.cues)&&f.getCueById(v)||((a=new d(t,r,g)).id=v,a.line=h+1,a.align="left",a.position=10+Math.min(80,10*Math.floor(8*o/32)),u.push(a))}return e&&u.length&&(u.sort((function(e,t){return"auto"===e.line||"auto"===t.line?0:e.line>8&&t.line>8?t.line-e.line:e.line-t.line})),u.forEach((function(t){return Cs(e,t)}))),u}},wo=/(\d+)-(\d+)\/(\d+)/,Oo=function(){function e(e){this.fetchSetup=void 0,this.requestTimeout=void 0,this.request=null,this.response=null,this.controller=void 0,this.context=null,this.config=null,this.callbacks=null,this.stats=void 0,this.loader=null,this.fetchSetup=e.fetchSetup||xo,this.controller=new self.AbortController,this.stats=new Q}var t=e.prototype;return t.destroy=function(){this.loader=this.callbacks=this.context=this.config=this.request=null,this.abortInternal(),this.response=null,this.fetchSetup=this.controller=this.stats=null},t.abortInternal=function(){this.controller&&!this.stats.loading.end&&(this.stats.aborted=!0,this.controller.abort())},t.abort=function(){var e;this.abortInternal(),null!=(e=this.callbacks)&&e.onAbort&&this.callbacks.onAbort(this.stats,this.context,this.response)},t.load=function(e,t,r){var i=this,n=this.stats;if(n.loading.start)throw new Error("Loader can only be used once.");n.loading.start=self.performance.now();var s=function(e,t){var r={method:"GET",mode:"cors",credentials:"same-origin",signal:t,headers:new self.Headers(a({},e.headers))};return e.rangeEnd&&r.headers.set("Range","bytes="+e.rangeStart+"-"+String(e.rangeEnd-1)),r}(e,this.controller.signal),o="arraybuffer"===e.responseType,l=o?"byteLength":"length",u=t.loadPolicy,d=u.maxTimeToFirstByteMs,h=u.maxLoadTimeMs;this.context=e,this.config=t,this.callbacks=r,this.request=this.fetchSetup(e,s),self.clearTimeout(this.requestTimeout),t.timeout=d&&A(d)?d:h,this.requestTimeout=self.setTimeout((function(){i.callbacks&&(i.abortInternal(),i.callbacks.onTimeout(n,e,i.response))}),t.timeout),(Xn(this.request)?this.request.then(self.fetch):self.fetch(this.request)).then((function(r){var a;i.response=i.loader=r;var s=Math.max(self.performance.now(),n.loading.start);if(self.clearTimeout(i.requestTimeout),t.timeout=h,i.requestTimeout=self.setTimeout((function(){i.callbacks&&(i.abortInternal(),i.callbacks.onTimeout(n,e,i.response))}),h-(s-n.loading.start)),!r.ok){var l=r.status,u=r.statusText;throw new Mo(u||"fetch, bad network response",l,r)}n.loading.first=s,n.total=function(e){var t=e.get("Content-Range");if(t){var r=function(e){var t=wo.exec(e);if(t)return parseInt(t[2])-parseInt(t[1])+1}(t);if(A(r))return r}var i=e.get("Content-Length");if(i)return parseInt(i)}(r.headers)||n.total;var d=null==(a=i.callbacks)?void 0:a.onProgress;return d&&A(t.highWaterMark)?i.loadProgressively(r,n,e,t.highWaterMark,d):o?r.arrayBuffer():"json"===e.responseType?r.json():r.text()})).then((function(r){var a,s,o=i.response;if(!o)throw new Error("loader destroyed");self.clearTimeout(i.requestTimeout),n.loading.end=Math.max(self.performance.now(),n.loading.first);var u=r[l];u&&(n.loaded=n.total=u);var d={url:o.url,data:r,code:o.status},h=null==(a=i.callbacks)?void 0:a.onProgress;h&&!A(t.highWaterMark)&&h(n,e,r,o),null==(s=i.callbacks)||s.onSuccess(d,n,e,o)})).catch((function(t){var r;if(self.clearTimeout(i.requestTimeout),!n.aborted){var a=t&&t.code||0,s=t?t.message:null;null==(r=i.callbacks)||r.onError({code:a,text:s},e,t?t.details:null,n)}}))},t.getCacheAge=function(){var e=null;if(this.response){var t=this.response.headers.get("age");e=t?parseFloat(t):null}return e},t.getResponseHeader=function(e){return this.response?this.response.headers.get(e):null},t.loadProgressively=function(e,t,r,i,n){void 0===i&&(i=0);var a=new Ai,s=e.body.getReader(),o=function(){return s.read().then((function(s){if(s.done)return a.dataLength&&n(t,r,a.flush().buffer,e),Promise.resolve(new ArrayBuffer(0));var l=s.value,u=l.length;return t.loaded+=u,u=i&&n(t,r,a.flush().buffer,e)):n(t,r,l.buffer,e),o()})).catch((function(){return Promise.reject()}))};return o()},e}();function xo(e,t){return new self.Request(e.url,t)}var Mo=function(e){function t(t,r,i){var n;return(n=e.call(this,t)||this).code=void 0,n.details=void 0,n.code=r,n.details=i,n}return o(t,e),t}(c(Error)),Fo=/^age:\s*[\d.]+\s*$/im,No=function(){function e(e){this.xhrSetup=void 0,this.requestTimeout=void 0,this.retryTimeout=void 0,this.retryDelay=void 0,this.config=null,this.callbacks=null,this.context=null,this.loader=null,this.stats=void 0,this.xhrSetup=e&&e.xhrSetup||null,this.stats=new Q,this.retryDelay=0}var t=e.prototype;return t.destroy=function(){this.callbacks=null,this.abortInternal(),this.loader=null,this.config=null,this.context=null,this.xhrSetup=null},t.abortInternal=function(){var e=this.loader;self.clearTimeout(this.requestTimeout),self.clearTimeout(this.retryTimeout),e&&(e.onreadystatechange=null,e.onprogress=null,4!==e.readyState&&(this.stats.aborted=!0,e.abort()))},t.abort=function(){var e;this.abortInternal(),null!=(e=this.callbacks)&&e.onAbort&&this.callbacks.onAbort(this.stats,this.context,this.loader)},t.load=function(e,t,r){if(this.stats.loading.start)throw new Error("Loader can only be used once.");this.stats.loading.start=self.performance.now(),this.context=e,this.config=t,this.callbacks=r,this.loadInternal()},t.loadInternal=function(){var e=this,t=this.config,r=this.context;if(t&&r){var i=this.loader=new self.XMLHttpRequest,n=this.stats;n.loading.first=0,n.loaded=0,n.aborted=!1;var a=this.xhrSetup;a?Promise.resolve().then((function(){if(e.loader===i&&!e.stats.aborted)return a(i,r.url)})).catch((function(t){if(e.loader===i&&!e.stats.aborted)return i.open("GET",r.url,!0),a(i,r.url)})).then((function(){e.loader!==i||e.stats.aborted||e.openAndSendXhr(i,r,t)})).catch((function(t){var a;null==(a=e.callbacks)||a.onError({code:i.status,text:t.message},r,i,n)})):this.openAndSendXhr(i,r,t)}},t.openAndSendXhr=function(e,t,r){e.readyState||e.open("GET",t.url,!0);var i=t.headers,n=r.loadPolicy,a=n.maxTimeToFirstByteMs,s=n.maxLoadTimeMs;if(i)for(var o in i)e.setRequestHeader(o,i[o]);t.rangeEnd&&e.setRequestHeader("Range","bytes="+t.rangeStart+"-"+(t.rangeEnd-1)),e.onreadystatechange=this.readystatechange.bind(this),e.onprogress=this.loadprogress.bind(this),e.responseType=t.responseType,self.clearTimeout(this.requestTimeout),r.timeout=a&&A(a)?a:s,this.requestTimeout=self.setTimeout(this.loadtimeout.bind(this),r.timeout),e.send()},t.readystatechange=function(){var e=this.context,t=this.loader,r=this.stats;if(e&&t){var i=t.readyState,n=this.config;if(!r.aborted&&i>=2&&(0===r.loading.first&&(r.loading.first=Math.max(self.performance.now(),r.loading.start),n.timeout!==n.loadPolicy.maxLoadTimeMs&&(self.clearTimeout(this.requestTimeout),n.timeout=n.loadPolicy.maxLoadTimeMs,this.requestTimeout=self.setTimeout(this.loadtimeout.bind(this),n.loadPolicy.maxLoadTimeMs-(r.loading.first-r.loading.start)))),4===i)){self.clearTimeout(this.requestTimeout),t.onreadystatechange=null,t.onprogress=null;var a=t.status,s="text"===t.responseType?t.responseText:null;if(a>=200&&a<300){var o=null!=s?s:t.response;if(null!=o){var l,u;r.loading.end=Math.max(self.performance.now(),r.loading.first);var d="arraybuffer"===t.responseType?o.byteLength:o.length;r.loaded=r.total=d,r.bwEstimate=8e3*r.total/(r.loading.end-r.loading.first);var h=null==(l=this.callbacks)?void 0:l.onProgress;h&&h(r,e,o,t);var f={url:t.responseURL,data:o,code:a};return void(null==(u=this.callbacks)||u.onSuccess(f,r,e,t))}}var c,g=n.loadPolicy.errorRetry;It(g,r.retry,!1,{url:e.url,data:void 0,code:a})?this.retry(g):(Y.error(a+" while loading "+e.url),null==(c=this.callbacks)||c.onError({code:a,text:t.statusText},e,t,r))}}},t.loadtimeout=function(){if(this.config){var e=this.config.loadPolicy.timeoutRetry;if(It(e,this.stats.retry,!0))this.retry(e);else{var t;Y.warn("timeout while loading "+(null==(t=this.context)?void 0:t.url));var r=this.callbacks;r&&(this.abortInternal(),r.onTimeout(this.stats,this.context,this.loader))}}},t.retry=function(e){var t=this.context,r=this.stats;this.retryDelay=Lt(e,r.retry),r.retry++,Y.warn((status?"HTTP Status "+status:"Timeout")+" while loading "+(null==t?void 0:t.url)+", retrying "+r.retry+"/"+e.maxNumRetry+" in "+this.retryDelay+"ms"),this.abortInternal(),this.loader=null,self.clearTimeout(this.retryTimeout),this.retryTimeout=self.setTimeout(this.loadInternal.bind(this),this.retryDelay)},t.loadprogress=function(e){var t=this.stats;t.loaded=e.loaded,e.lengthComputable&&(t.total=e.total)},t.getCacheAge=function(){var e=null;if(this.loader&&Fo.test(this.loader.getAllResponseHeaders())){var t=this.loader.getResponseHeader("age");e=t?parseFloat(t):null}return e},t.getResponseHeader=function(e){return this.loader&&new RegExp("^"+e+":\\s*[\\d.]+\\s*$","im").test(this.loader.getAllResponseHeaders())?this.loader.getResponseHeader(e):null},e}(),Uo=d(d({autoStartLoad:!0,startPosition:-1,defaultAudioCodec:void 0,debug:!1,capLevelOnFPSDrop:!1,capLevelToPlayerSize:!1,ignoreDevicePixelRatio:!1,maxDevicePixelRatio:Number.POSITIVE_INFINITY,preferManagedMediaSource:!0,initialLiveManifestSize:1,maxBufferLength:30,backBufferLength:1/0,frontBufferFlushThreshold:1/0,startOnSegmentBoundary:!1,maxBufferSize:6e7,maxFragLookUpTolerance:.25,maxBufferHole:.1,detectStallWithCurrentTimeMs:1250,highBufferWatchdogPeriod:2,nudgeOffset:.1,nudgeMaxRetry:3,nudgeOnVideoHole:!0,liveSyncMode:"edge",liveSyncDurationCount:3,liveSyncOnStallIncrease:1,liveMaxLatencyDurationCount:1/0,liveSyncDuration:void 0,liveMaxLatencyDuration:void 0,maxLiveSyncPlaybackRate:1,liveDurationInfinity:!1,liveBackBufferLength:null,maxMaxBufferLength:600,enableWorker:!0,workerPath:null,enableSoftwareAES:!0,startLevel:void 0,startFragPrefetch:!1,fpsDroppedMonitoringPeriod:5e3,fpsDroppedMonitoringThreshold:.2,appendErrorMaxRetry:3,ignorePlaylistParsingErrors:!1,loader:No,fLoader:void 0,pLoader:void 0,xhrSetup:void 0,licenseXhrSetup:void 0,licenseResponseCallback:void 0,abrController:vt,bufferController:ma,capLevelController:Ta,errorController:Ot,fpsController:fs,stretchShortVideoTrack:!1,maxAudioFramesDrift:1,forceKeyFrameOnDiscontinuity:!0,abrEwmaFastLive:3,abrEwmaSlowLive:9,abrEwmaFastVoD:3,abrEwmaSlowVoD:9,abrEwmaDefaultEstimate:5e5,abrEwmaDefaultEstimateMax:5e6,abrBandWidthFactor:.95,abrBandWidthUpFactor:.7,abrMaxWithRealBitrate:!1,maxStarvationDelay:4,maxLoadingDelay:4,minAutoBitrate:0,emeEnabled:!1,widevineLicenseUrl:void 0,drmSystems:{},drmSystemOptions:{},requestMediaKeySystemAccessFunc:Mr,requireKeySystemAccessOnStart:!1,testBandwidth:!0,progressive:!1,lowLatencyMode:!0,cmcd:void 0,enableDateRangeMetadataCues:!0,enableEmsgMetadataCues:!0,enableEmsgKLVMetadata:!1,enableID3MetadataCues:!0,enableInterstitialPlayback:!0,interstitialAppendInPlace:!0,interstitialLiveLookAhead:10,useMediaCapabilities:!0,preserveManualLevelOnError:!1,certLoadPolicy:{default:{maxTimeToFirstByteMs:8e3,maxLoadTimeMs:2e4,timeoutRetry:null,errorRetry:null}},keyLoadPolicy:{default:{maxTimeToFirstByteMs:8e3,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:2e4,backoff:"linear"},errorRetry:{maxNumRetry:8,retryDelayMs:1e3,maxRetryDelayMs:2e4,backoff:"linear"}}},manifestLoadPolicy:{default:{maxTimeToFirstByteMs:1/0,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},playlistLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:2,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},fragLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:12e4,timeoutRetry:{maxNumRetry:4,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:6,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},steeringManifestLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},interstitialAssetListLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:3e4,timeoutRetry:{maxNumRetry:0,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:0,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},manifestLoadingTimeOut:1e4,manifestLoadingMaxRetry:1,manifestLoadingRetryDelay:1e3,manifestLoadingMaxRetryTimeout:64e3,levelLoadingTimeOut:1e4,levelLoadingMaxRetry:4,levelLoadingRetryDelay:1e3,levelLoadingMaxRetryTimeout:64e3,fragLoadingTimeOut:2e4,fragLoadingMaxRetry:6,fragLoadingRetryDelay:1e3,fragLoadingMaxRetryTimeout:64e3},{cueHandler:Co,enableWebVTT:!0,enableIMSC1:!0,enableCEA708Captions:!0,captionsTextTrack1Label:"English",captionsTextTrack1LanguageCode:"en",captionsTextTrack2Label:"Spanish",captionsTextTrack2LanguageCode:"es",captionsTextTrack3Label:"Unknown CC",captionsTextTrack3LanguageCode:"",captionsTextTrack4Label:"Unknown CC",captionsTextTrack4LanguageCode:"",renderTextTracksNatively:!0}),{},{subtitleStreamController:Ds,subtitleTrackController:Ms,timelineController:bo,audioStreamController:sa,audioTrackController:ha,emeController:ds,cmcdController:ns,contentSteeringController:as,interstitialsController:bs});function Bo(e){return e&&"object"==typeof e?Array.isArray(e)?e.map(Bo):Object.keys(e).reduce((function(t,r){return t[r]=Bo(e[r]),t}),{}):e}function Go(e,t){var r=e.loader;r!==Oo&&r!==No?(t.log("[config]: Custom loader detected, cannot enable progressive streaming"),e.progressive=!1):function(){if(self.fetch&&self.AbortController&&self.ReadableStream&&self.Request)try{return new self.ReadableStream({}),!0}catch(e){}return!1}()&&(e.loader=Oo,e.progressive=!0,e.enableSoftwareAES=!0,t.log("[config]: Progressive streaming enabled, using FetchLoader"))}var Ko=function(e){function t(t,r){var i;return(i=e.call(this,"gap-controller",t.logger)||this).hls=null,i.fragmentTracker=null,i.media=null,i.mediaSource=void 0,i.nudgeRetry=0,i.stallReported=!1,i.stalled=null,i.moved=!1,i.seeking=!1,i.buffered={},i.lastCurrentTime=0,i.ended=0,i.waiting=0,i.onMediaPlaying=function(){i.ended=0,i.waiting=0},i.onMediaWaiting=function(){var e;null!=(e=i.media)&&e.seeking||(i.waiting=self.performance.now(),i.tick())},i.onMediaEnded=function(){var e;i.hls&&(i.ended=(null==(e=i.media)?void 0:e.currentTime)||1,i.hls.trigger(b.MEDIA_ENDED,{stalled:!1}))},i.hls=t,i.fragmentTracker=r,i.registerListeners(),i}o(t,e);var r=t.prototype;return r.registerListeners=function(){var e=this.hls;e&&(e.on(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(b.BUFFER_APPENDED,this.onBufferAppended,this))},r.unregisterListeners=function(){var e=this.hls;e&&(e.off(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(b.BUFFER_APPENDED,this.onBufferAppended,this))},r.destroy=function(){e.prototype.destroy.call(this),this.unregisterListeners(),this.media=this.hls=this.fragmentTracker=null,this.mediaSource=void 0},r.onMediaAttached=function(e,t){this.setInterval(100),this.mediaSource=t.mediaSource;var r=this.media=t.media;ls(r,"playing",this.onMediaPlaying),ls(r,"waiting",this.onMediaWaiting),ls(r,"ended",this.onMediaEnded)},r.onMediaDetaching=function(e,t){this.clearInterval();var r=this.media;r&&(us(r,"playing",this.onMediaPlaying),us(r,"waiting",this.onMediaWaiting),us(r,"ended",this.onMediaEnded),this.media=null),this.mediaSource=void 0},r.onBufferAppended=function(e,t){this.buffered=t.timeRanges},r.tick=function(){var e;if(null!=(e=this.media)&&e.readyState&&this.hasBuffered){var t=this.media.currentTime;this.poll(t,this.lastCurrentTime),this.lastCurrentTime=t}},r.poll=function(e,t){var r,i,n=null==(r=this.hls)?void 0:r.config;if(n){var a=this.media;if(a){var s=a.seeking,o=this.seeking&&!s,l=!this.seeking&&s,u=a.paused&&!s||a.ended||0===a.playbackRate;if(this.seeking=s,e!==t)return t&&(this.ended=0),this.moved=!0,s||(this.nudgeRetry=0,n.nudgeOnVideoHole&&!u&&e>t&&this.nudgeOnVideoHole(e,t)),void(0===this.waiting&&this.stallResolved(e));if(l||o)o&&this.stallResolved(e);else{if(u)return this.nudgeRetry=0,this.stallResolved(e),void(!this.ended&&a.ended&&this.hls&&(this.ended=e||1,this.hls.trigger(b.MEDIA_ENDED,{stalled:!1})));if(ir.getBuffered(a).length){var d=ir.bufferInfo(a,e,0),h=d.nextStart||0,f=this.fragmentTracker;if(s&&f&&this.hls){var c=Vo(this.hls.inFlightFragments,e),g=d.len>2,v=!h||c||h-e>2&&!f.getPartialFragment(e);if(g||v)return;this.moved=!1}var m=null==(i=this.hls)?void 0:i.latestLevelDetails;if(!this.moved&&null!==this.stalled&&f){if(!(d.len>0||h))return;var p=Math.max(h,d.start||0)-e,y=null!=m&&m.live?2*m.targetduration:2,E=f.getPartialFragment(e);if(p>0&&(p<=y||E))return void(a.paused||this._trySkipBufferHole(E))}var T=n.detectStallWithCurrentTimeMs,S=self.performance.now(),A=this.waiting,L=this.stalled;if(null===L){if(!(A>0&&S-A=T||A)&&this.hls){var I;if("ended"===(null==(I=this.mediaSource)?void 0:I.readyState)&&(null==m||!m.live)&&Math.abs(e-((null==m?void 0:m.edge)||0))<1){if(this.ended)return;return this.ended=e||1,void this.hls.trigger(b.MEDIA_ENDED,{stalled:!0})}if(this._reportStall(d),!this.media||!this.hls)return}var k=ir.bufferInfo(a,e,n.maxBufferHole);this._tryFixBufferStall(k,R,e)}else this.nudgeRetry=0}}}},r.stallResolved=function(e){var t=this.stalled;if(t&&this.hls&&(this.stalled=null,this.stallReported)){var r=self.performance.now()-t;this.log("playback not stuck anymore @"+e+", after "+Math.round(r)+"ms"),this.stallReported=!1,this.waiting=0,this.hls.trigger(b.STALL_RESOLVED,{})}},r.nudgeOnVideoHole=function(e,t){var r,i=this.buffered.video;if(this.hls&&this.media&&this.fragmentTracker&&null!=(r=this.buffered.audio)&&r.length&&i&&i.length>1&&e>i.end(0)){var n=ir.bufferedInfo(ir.timeRangesToArray(this.buffered.audio),e,0);if(n.len>1&&t>=n.start){var a=ir.timeRangesToArray(i),s=ir.bufferedInfo(a,t,0).bufferedIndex;if(s>-1&&ss)&&u-l<1&&e-l<2){var d=new Error("nudging playhead to flush pipeline after video hole. currentTime: "+e+" hole: "+l+" -> "+u+" buffered index: "+o);this.warn(d.message),this.media.currentTime+=1e-6;var h=this.fragmentTracker.getPartialFragment(e)||void 0,f=ir.bufferInfo(this.media,e,0);this.hls.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.BUFFER_SEEK_OVER_HOLE,fatal:!1,error:d,reason:d.message,frag:h,buffer:f.len,bufferInfo:f})}}}}},r._tryFixBufferStall=function(e,t,r){var i,n,a=this.fragmentTracker,s=this.media,o=null==(i=this.hls)?void 0:i.config;if(s&&a&&o){var l=null==(n=this.hls)?void 0:n.latestLevelDetails,u=a.getPartialFragment(r);if((u||null!=l&&l.live&&r1&&e.len>o.maxBufferHole||e.nextStart&&(e.nextStart-r1e3*o.highBufferWatchdogPeriod||this.waiting)&&(this.warn("Trying to nudge playhead over buffer-hole"),this._tryNudgeBuffer(e))}},r.adjacentTraversal=function(e,t){var r=this.fragmentTracker,i=e.nextStart;if(r&&i){var n=r.getFragAtPos(t,w),a=r.getFragAtPos(i,w);if(n&&a)return a.sn-n.sn<2}return!1},r._reportStall=function(e){var t=this.hls,r=this.media,i=this.stallReported,n=this.stalled;if(!i&&null!==n&&r&&t){this.stallReported=!0;var a=new Error("Playback stalling at @"+r.currentTime+" due to low buffer ("+st(e)+")");this.warn(a.message),t.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.BUFFER_STALLED_ERROR,fatal:!1,error:a,buffer:e.len,bufferInfo:e,stalled:{start:n}})}},r._trySkipBufferHole=function(e){var t,r=this.fragmentTracker,i=this.media,n=null==(t=this.hls)?void 0:t.config;if(!i||!r||!n)return 0;var a=i.currentTime,s=ir.bufferInfo(i,a,0),o=a0&&s.len<1&&i.readyState<3,d=o-a;if(d>0&&(l||u)){if(d>n.maxBufferHole){var h=!1;if(0===a){var f=r.getAppendedFrag(0,w);f&&o0}}])}(er);function Vo(e,t){var r=Ho(e.main);if(r&&r.start<=t)return r;var i=Ho(e.audio);return i&&i.start<=t?i:null}function Ho(e){if(!e)return null;switch(e.state){case Ei.IDLE:case Ei.STOPPED:case Ei.ENDED:case Ei.ERROR:return null}return e.frag}function Yo(){if("undefined"!=typeof self)return self.VTTCue||self.TextTrackCue}function Wo(e,t,r,i,n){var a=new e(t,r,"");try{a.value=i,n&&(a.type=n)}catch(s){a=new e(t,r,st(n?d({type:n},i):i))}return a}var jo=function(){var e=Yo();try{e&&new e(0,Number.POSITIVE_INFINITY,"")}catch(e){return Number.MAX_VALUE}return Number.POSITIVE_INFINITY}(),qo=function(){function e(e){var t=this;this.hls=void 0,this.id3Track=null,this.media=null,this.dateRangeCuesAppended={},this.removeCues=!0,this.onEventCueEnter=function(){t.hls&&t.hls.trigger(b.EVENT_CUE_ENTER,{})},this.hls=e,this._registerListeners()}var t=e.prototype;return t.destroy=function(){this._unregisterListeners(),this.id3Track=null,this.media=null,this.dateRangeCuesAppended={},this.hls=this.onEventCueEnter=null},t._registerListeners=function(){var e=this.hls;e.on(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.FRAG_PARSING_METADATA,this.onFragParsingMetadata,this),e.on(b.BUFFER_FLUSHING,this.onBufferFlushing,this),e.on(b.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(b.LEVEL_PTS_UPDATED,this.onLevelPtsUpdated,this)},t._unregisterListeners=function(){var e=this.hls;e.off(b.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.FRAG_PARSING_METADATA,this.onFragParsingMetadata,this),e.off(b.BUFFER_FLUSHING,this.onBufferFlushing,this),e.off(b.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(b.LEVEL_PTS_UPDATED,this.onLevelPtsUpdated,this)},t.onMediaAttaching=function(e,t){var r;this.media=t.media,!1===(null==(r=t.overrides)?void 0:r.cueRemoval)&&(this.removeCues=!1)},t.onMediaAttached=function(){var e=this.hls.latestLevelDetails;e&&this.updateDateRangeCues(e)},t.onMediaDetaching=function(e,t){this.media=null,t.transferMedia||(this.id3Track&&(this.removeCues&&ws(this.id3Track,this.onEventCueEnter),this.id3Track=null),this.dateRangeCuesAppended={})},t.onManifestLoading=function(){this.dateRangeCuesAppended={}},t.createTrack=function(e){var t=this.getID3Track(e.textTracks);return t.mode="hidden",t},t.getID3Track=function(e){if(this.media){for(var t=0;tjo&&(h=jo),h-d<=0&&(h=d+.25);for(var f=0;f.01&&this.updateDateRangeCues(t.details)},t.updateDateRangeCues=function(e,t){var r=this;if(this.media&&e.hasProgramDateTime&&this.hls.config.enableDateRangeMetadataCues){var i,n=this.id3Track,a=e.dateRanges,s=Object.keys(a),o=this.dateRangeCuesAppended;if(n&&t)if(null!=(i=n.cues)&&i.length)for(var l=Object.keys(o).filter((function(e){return!s.includes(e)})),u=function(){var e=l[d],t=o[e].cues;delete o[e],Object.keys(t).forEach((function(e){try{var i=t[e];i.removeEventListener("enter",r.onEventCueEnter),n.removeCue(i)}catch(e){}}))},d=l.length;d--;)u();else o=this.dateRangeCuesAppended={};var h=e.fragments[e.fragments.length-1];if(0!==s.length&&A(null==h?void 0:h.programDateTime)){this.id3Track||(this.id3Track=this.createTrack(this.media));for(var f=Yo(),c=function(){var e=s[g],t=a[e],i=t.startTime,n=o[e],l=(null==n?void 0:n.cues)||{},u=(null==n?void 0:n.durationKnown)||!1,d=jo,h=t.duration;if(t.endDate&&null!==h)d=i+h,u=!0;else if(t.endOnNext&&!u){var c=s.reduce((function(e,r){if(r!==t.id){var i=a[r];if(i.class===t.class&&i.startDate>t.startDate&&(!e||t.startDate.01&&(T.startTime=i,T.endTime=d);else if(f){var S=t.attr[E];fr(E)&&(v=S,S=Uint8Array.from(v.replace(/^0x/,"").replace(/([\da-fA-F]{2}) ?/g,"0x$1 ").replace(/ +$/,"").split(" ")).buffer);var A=Wo(f,i,d,{key:E,data:S},ji.dateRange);A&&(A.id=e,r.id3Track.addCue(A),l[E]=A,r.hls.config.interstitialsController&&("X-ASSET-LIST"!==E&&"X-ASSET-URL"!==E||A.addEventListener("enter",r.onEventCueEnter)))}}}o[e]={cues:l,dateRange:t,durationKnown:u}},g=0;g.05&&t.forwardBufferLength>1){var u=Math.min(2,Math.max(1,s)),d=Math.round(2/(1+Math.exp(-.75*l-t.edgeStalled))*20)/20,h=Math.min(u,Math.max(1,d));t.changeMediaPlaybackRate(e,h)}else 1!==e.playbackRate&&0!==e.playbackRate&&t.changeMediaPlaybackRate(e,1)}}}}},this.hls=e,this.config=e.config,this.registerListeners()}var t=e.prototype;return t.destroy=function(){this.unregisterListeners(),this.onMediaDetaching(),this.hls=null},t.registerListeners=function(){var e=this.hls;e&&(e.on(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(b.ERROR,this.onError,this))},t.unregisterListeners=function(){var e=this.hls;e&&(e.off(b.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(b.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(b.ERROR,this.onError,this))},t.onMediaAttached=function(e,t){this.media=t.media,this.media.addEventListener("timeupdate",this.onTimeupdate)},t.onMediaDetaching=function(){this.media&&(this.media.removeEventListener("timeupdate",this.onTimeupdate),this.media=null)},t.onManifestLoading=function(){this._latency=null,this.stallCount=0},t.onLevelUpdated=function(e,t){var r=t.details;r.advanced&&this.onTimeupdate(),!r.live&&this.media&&this.media.removeEventListener("timeupdate",this.onTimeupdate)},t.onError=function(e,t){var r;t.details===k.BUFFER_STALLED_ERROR&&(this.stallCount++,this.hls&&null!=(r=this.levelDetails)&&r.live&&this.hls.logger.warn("[latency-controller]: Stall detected, adjusting target latency"))},t.changeMediaPlaybackRate=function(e,t){var r,i;e.playbackRate!==t&&(null==(r=this.hls)||r.logger.debug("[latency-controller]: latency="+this.latency.toFixed(3)+", targetLatency="+(null==(i=this.targetLatency)?void 0:i.toFixed(3))+", forwardBufferLength="+this.forwardBufferLength.toFixed(3)+": adjusting playback rate from "+e.playbackRate+" to "+t),e.playbackRate=t)},t.estimateLiveEdge=function(){var e=this.levelDetails;return null===e?null:e.edge+e.age},t.computeLatency=function(){var e=this.estimateLiveEdge();return null===e?null:e-this.currentTime},i(e,[{key:"levelDetails",get:function(){var e;return(null==(e=this.hls)?void 0:e.latestLevelDetails)||null}},{key:"latency",get:function(){return this._latency||0}},{key:"maxLatency",get:function(){var e=this.config;if(void 0!==e.liveMaxLatencyDuration)return e.liveMaxLatencyDuration;var t=this.levelDetails;return t?e.liveMaxLatencyDurationCount*t.targetduration:0}},{key:"targetLatency",get:function(){var e=this.levelDetails;if(null===e||null===this.hls)return null;var t=e.holdBack,r=e.partHoldBack,i=e.targetduration,n=this.config,a=n.liveSyncDuration,s=n.liveSyncDurationCount,o=n.lowLatencyMode,l=this.hls.userConfig,u=o&&r||t;(this._targetLatencyUpdated||l.liveSyncDuration||l.liveSyncDurationCount||0===u)&&(u=void 0!==a?a:s*i);var d=i;return u+Math.min(this.stallCount*this.config.liveSyncOnStallIncrease,d)},set:function(e){this.stallCount=0,this.config.liveSyncDuration=e,this._targetLatencyUpdated=!0}},{key:"liveSyncPosition",get:function(){var e=this.estimateLiveEdge(),t=this.targetLatency;if(null===e||null===t)return null;var r=this.levelDetails;if(null===r)return null;var i=r.edge,n=e-t-this.edgeStalled,a=i-r.totalduration,s=i-(this.config.lowLatencyMode&&r.partTarget||r.targetduration);return Math.min(Math.max(a,n),s)}},{key:"drift",get:function(){var e=this.levelDetails;return null===e?1:e.drift}},{key:"edgeStalled",get:function(){var e=this.levelDetails;if(null===e)return 0;var t=3*(this.config.lowLatencyMode&&e.partTarget||e.targetduration);return Math.max(e.age-t,0)}},{key:"forwardBufferLength",get:function(){var e=this.media,t=this.levelDetails;if(!e||!t)return 0;var r=e.buffered.length;return(r?e.buffered.end(r-1):t.edge)-this.currentTime}}])}(),Qo=function(e){function t(t,r){var i;return(i=e.call(this,t,"level-controller")||this)._levels=[],i._firstLevel=-1,i._maxAutoLevel=-1,i._startLevel=void 0,i.currentLevel=null,i.currentLevelIndex=-1,i.manualLevelIndex=-1,i.steering=void 0,i.onParsedComplete=void 0,i.steering=r,i._registerListeners(),i}o(t,e);var r=t.prototype;return r._registerListeners=function(){var e=this.hls;e.on(b.MANIFEST_LOADING,this.onManifestLoading,this),e.on(b.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(b.LEVEL_LOADED,this.onLevelLoaded,this),e.on(b.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(b.FRAG_BUFFERED,this.onFragBuffered,this),e.on(b.ERROR,this.onError,this)},r._unregisterListeners=function(){var e=this.hls;e.off(b.MANIFEST_LOADING,this.onManifestLoading,this),e.off(b.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(b.LEVEL_LOADED,this.onLevelLoaded,this),e.off(b.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(b.FRAG_BUFFERED,this.onFragBuffered,this),e.off(b.ERROR,this.onError,this)},r.destroy=function(){this._unregisterListeners(),this.steering=null,this.resetLevels(),e.prototype.destroy.call(this)},r.stopLoad=function(){this._levels.forEach((function(e){e.loadError=0,e.fragmentError=0})),e.prototype.stopLoad.call(this)},r.resetLevels=function(){this._startLevel=void 0,this.manualLevelIndex=-1,this.currentLevelIndex=-1,this.currentLevel=null,this._levels=[],this._maxAutoLevel=-1},r.onManifestLoading=function(e,t){this.resetLevels()},r.onManifestLoaded=function(e,t){var r=this,i=this.hls.config.preferManagedMediaSource,n=[],a={},s={},o=!1,l=!1,u=!1;t.levels.forEach((function(e){var t=e.attrs,d=e.audioCodec,h=e.videoCodec;d&&(e.audioCodec=d=Be(d,i)||void 0),h&&(h=e.videoCodec=function(e){for(var t=e.split(","),r=0;r2&&"avc1"===i[0]&&(t[r]="avc1."+parseInt(i[1]).toString(16)+("000"+parseInt(i[2]).toString(16)).slice(-4))}return t.join(",")}(h));var f=e.width,c=e.height,g=e.unknownCodecs,v=g?g.length:0;if(g)for(var m=v;m--;){var p=g[m];r.isAudioSupported(p)?(e.audioCodec=d=d?d+","+p:p,v--,Pe.audio[d.substring(0,4)]=2):r.isVideoSupported(p)&&(e.videoCodec=h=h?h+","+p:p,v--,Pe.video[h.substring(0,4)]=2)}if(o||(o=!(!f||!c)),l||(l=!!h),u||(u=!!d),v||d&&!r.isAudioSupported(d)||h&&!r.isVideoSupported(h))r.log('Some or all CODECS not supported "'+t.CODECS+'"');else{var y=t.CODECS,E=t["FRAME-RATE"],T=t["HDCP-LEVEL"],S=t["PATHWAY-ID"],A=t.RESOLUTION,L=t["VIDEO-RANGE"],R=(S||".")+"-"+e.bitrate+"-"+A+"-"+E+"-"+y+"-"+L+"-"+T;if(a[R])if(a[R].uri===e.url||e.attrs["PATHWAY-ID"])a[R].addGroupId("audio",t.AUDIO),a[R].addGroupId("text",t.SUBTITLES);else{var I=s[R]+=1;e.attrs["PATHWAY-ID"]=new Array(I+1).join(".");var k=r.createLevel(e);a[R]=k,n.push(k)}else{var b=r.createLevel(e);a[R]=b,s[R]=1,n.push(b)}}})),this.filterAndSortMediaOptions(n,t,o,l,u)},r.createLevel=function(e){var t=new it(e),r=e.supplemental;if(null!=r&&r.videoCodec&&!this.isVideoSupported(r.videoCodec)){var i=new Error('SUPPLEMENTAL-CODECS not supported "'+r.videoCodec+'"');this.log(i.message),t.supportedResult=je(i,[])}return t},r.isAudioSupported=function(e){return we(e,"audio",this.hls.config.preferManagedMediaSource)},r.isVideoSupported=function(e){return we(e,"video",this.hls.config.preferManagedMediaSource)},r.filterAndSortMediaOptions=function(e,t,r,i,n){var a=this,s=[],o=[],l=e;if((r||i)&&n&&(l=l.filter((function(e){var t,r=e.videoCodec,i=e.videoRange,n=e.width,a=e.height;return(!!r||!(!n||!a))&&!!(t=i)&&$e.indexOf(t)>-1}))),0!==l.length){t.audioTracks&&zo(s=t.audioTracks.filter((function(e){return!e.audioCodec||a.isAudioSupported(e.audioCodec)}))),t.subtitles&&zo(o=t.subtitles);var u=l.slice(0);l.sort((function(e,t){if(e.attrs["HDCP-LEVEL"]!==t.attrs["HDCP-LEVEL"])return(e.attrs["HDCP-LEVEL"]||"")>(t.attrs["HDCP-LEVEL"]||"")?1:-1;if(r&&e.height!==t.height)return e.height-t.height;if(e.frameRate!==t.frameRate)return e.frameRate-t.frameRate;if(e.videoRange!==t.videoRange)return $e.indexOf(e.videoRange)-$e.indexOf(t.videoRange);if(e.videoCodec!==t.videoCodec){var i=Me(e.videoCodec),n=Me(t.videoCodec);if(i!==n)return n-i}if(e.uri===t.uri&&e.codecSet!==t.codecSet){var a=Fe(e.codecSet),s=Fe(t.codecSet);if(a!==s)return s-a}return e.averageBitrate!==t.averageBitrate?e.averageBitrate-t.averageBitrate:0}));var d=u[0];if(this.steering&&(l=this.steering.filterParsedLevels(l)).length!==u.length)for(var h=0;hv&&v===this.hls.abrEwmaDefaultEstimate&&(this.hls.bandwidthEstimate=m)}break}var p=n&&!i,y=this.hls.config,E=!(!y.audioStreamController||!y.audioTrackController),T={levels:l,audioTracks:s,subtitleTracks:o,sessionData:t.sessionData,sessionKeys:t.sessionKeys,firstLevel:this._firstLevel,stats:t.stats,audio:n,video:i,altAudio:E&&!p&&s.some((function(e){return!!e.url}))};this.hls.trigger(b.MANIFEST_PARSED,T)}else Promise.resolve().then((function(){if(a.hls){var e="no level with compatible codecs found in manifest",r=e;t.levels.length&&(r="one or more CODECS in variant not supported: "+st(t.levels.map((function(e){return e.attrs.CODECS})).filter((function(e,t,r){return r.indexOf(e)===t}))),a.warn(r),e+=" ("+r+")");var i=new Error(e);a.hls.trigger(b.ERROR,{type:I.MEDIA_ERROR,details:k.MANIFEST_INCOMPATIBLE_CODECS_ERROR,fatal:!0,url:t.url,error:i,reason:r})}}))},r.onError=function(e,t){!t.fatal&&t.context&&t.context.type===_&&t.context.level===this.level&&this.checkRetry(t)},r.onFragBuffered=function(e,t){var r=t.frag;if(void 0!==r&&r.type===w){var i=r.elementaryStreams;if(!Object.keys(i).some((function(e){return!!i[e]})))return;var n=this._levels[r.level];null!=n&&n.loadError&&(this.log("Resetting level error count of "+n.loadError+" on frag buffered"),n.loadError=0)}},r.onLevelLoaded=function(e,t){var r,i,n=t.level,a=t.details,s=t.levelInfo;if(!s)return this.warn("Invalid level index "+n),void(null!=(i=t.deliveryDirectives)&&i.skip&&(a.deltaUpdateFailed=!0));if(s===this.currentLevel||t.withoutMultiVariant){0===s.fragmentError&&(s.loadError=0);var o=s.details;o===t.details&&o.advanced&&(o=void 0),this.playlistLoaded(n,t,o)}else null!=(r=t.deliveryDirectives)&&r.skip&&(a.deltaUpdateFailed=!0)},r.loadPlaylist=function(t){e.prototype.loadPlaylist.call(this),this.shouldLoadPlaylist(this.currentLevel)&&this.scheduleLoading(this.currentLevel,t)},r.loadingPlaylist=function(t,r){e.prototype.loadingPlaylist.call(this,t,r);var i=this.getUrlWithDirectives(t.uri,r),n=this.currentLevelIndex,a=t.attrs["PATHWAY-ID"],s=t.details,o=null==s?void 0:s.age;this.log("Loading level index "+n+(void 0!==(null==r?void 0:r.msn)?" at sn "+r.msn+" part "+r.part:"")+(a?" Pathway "+a:"")+(o&&s.live?" age "+o.toFixed(1)+(s.type&&" "+s.type||""):"")+" "+i),this.hls.trigger(b.LEVEL_LOADING,{url:i,level:n,levelInfo:t,pathwayId:t.attrs["PATHWAY-ID"],id:0,deliveryDirectives:r||null})},r.removeLevel=function(e){var t,r=this;if(1!==this._levels.length){var i=this._levels.filter((function(t,i){return i!==e||(r.steering&&r.steering.removeLevel(t),t===r.currentLevel&&(r.currentLevel=null,r.currentLevelIndex=-1,t.details&&t.details.fragments.forEach((function(e){return e.level=-1}))),!1)}));fi(i),this._levels=i,this.currentLevelIndex>-1&&null!=(t=this.currentLevel)&&t.details&&(this.currentLevelIndex=this.currentLevel.details.fragments[0].level),this.manualLevelIndex>-1&&(this.manualLevelIndex=this.currentLevelIndex);var n=i.length-1;this._firstLevel=Math.min(this._firstLevel,n),this._startLevel&&(this._startLevel=Math.min(this._startLevel,n)),this.hls.trigger(b.LEVELS_UPDATED,{levels:i})}},r.onLevelsUpdated=function(e,t){var r=t.levels;this._levels=r},r.checkMaxAutoUpdated=function(){var e=this.hls,t=e.autoLevelCapping,r=e.maxAutoLevel,i=e.maxHdcpLevel;this._maxAutoLevel!==r&&(this._maxAutoLevel=r,this.hls.trigger(b.MAX_AUTO_LEVEL_UPDATED,{autoLevelCapping:t,levels:this.levels,maxAutoLevel:r,minAutoLevel:this.hls.minAutoLevel,maxHdcpLevel:i}))},i(t,[{key:"levels",get:function(){return 0===this._levels.length?null:this._levels}},{key:"loadLevelObj",get:function(){return this.currentLevel}},{key:"level",get:function(){return this.currentLevelIndex},set:function(e){var t=this._levels;if(0!==t.length){if(e<0||e>=t.length){var r=new Error("invalid level idx"),i=e<0;if(this.hls.trigger(b.ERROR,{type:I.OTHER_ERROR,details:k.LEVEL_SWITCH_ERROR,level:e,fatal:i,error:r,reason:r.message}),i)return;e=Math.min(e,t.length-1)}var n=this.currentLevelIndex,a=this.currentLevel,s=a?a.attrs["PATHWAY-ID"]:void 0,o=t[e],l=o.attrs["PATHWAY-ID"];if(this.currentLevelIndex=e,this.currentLevel=o,n!==e||!a||s!==l){this.log("Switching to level "+e+" ("+(o.height?o.height+"p ":"")+(o.videoRange?o.videoRange+" ":"")+(o.codecSet?o.codecSet+" ":"")+"@"+o.bitrate+")"+(l?" with Pathway "+l:"")+" from level "+n+(s?" with Pathway "+s:""));var u={level:e,attrs:o.attrs,details:o.details,bitrate:o.bitrate,averageBitrate:o.averageBitrate,maxBitrate:o.maxBitrate,realBitrate:o.realBitrate,width:o.width,height:o.height,codecSet:o.codecSet,audioCodec:o.audioCodec,videoCodec:o.videoCodec,audioGroups:o.audioGroups,subtitleGroups:o.subtitleGroups,loaded:o.loaded,loadError:o.loadError,fragmentError:o.fragmentError,name:o.name,id:o.id,uri:o.uri,url:o.url,urlId:0,audioGroupIds:o.audioGroupIds,textGroupIds:o.textGroupIds};this.hls.trigger(b.LEVEL_SWITCHING,u);var d=o.details;if(!d||d.live){var h=this.switchParams(o.uri,null==a?void 0:a.details,d);this.loadPlaylist(h)}}}}},{key:"manualLevel",get:function(){return this.manualLevelIndex},set:function(e){this.manualLevelIndex=e,void 0===this._startLevel&&(this._startLevel=e),-1!==e&&(this.level=e)}},{key:"firstLevel",get:function(){return this._firstLevel},set:function(e){this._firstLevel=e}},{key:"startLevel",get:function(){if(void 0===this._startLevel){var e=this.hls.config.startLevel;return void 0!==e?e:this.hls.firstAutoLevel}return this._startLevel},set:function(e){this._startLevel=e}},{key:"pathways",get:function(){return this.steering?this.steering.pathways():[]}},{key:"pathwayPriority",get:function(){return this.steering?this.steering.pathwayPriority:null},set:function(e){if(this.steering){var t=this.steering.pathways(),r=e.filter((function(e){return-1!==t.indexOf(e)}));if(e.length<1)return void this.warn("pathwayPriority "+e+" should contain at least one pathway from list: "+t);this.steering.pathwayPriority=r}}},{key:"nextLoadLevel",get:function(){return-1!==this.manualLevelIndex?this.manualLevelIndex:this.hls.nextAutoLevel},set:function(e){this.level=e,-1===this.manualLevelIndex&&(this.hls.nextAutoLevel=e)}}])}(oa);function zo(e){var t={};e.forEach((function(e){var r=e.groupId||"";e.id=t[r]=t[r]||0,t[r]++}))}function $o(){return self.SourceBuffer||self.WebKitSourceBuffer}function Jo(){if(!W())return!1;var e=$o();return!e||e.prototype&&"function"==typeof e.prototype.appendBuffer&&"function"==typeof e.prototype.remove}var Zo=function(e){function t(t,r,i){var n;return(n=e.call(this,t,r,i,"stream-controller",w)||this).audioCodecSwap=!1,n.level=-1,n._forceStartLoad=!1,n._hasEnoughToStart=!1,n.altAudio=0,n.audioOnly=!1,n.fragPlaying=null,n.fragLastKbps=0,n.couldBacktrack=!1,n.backtrackFragment=null,n.audioCodecSwitch=!1,n.videoBuffer=null,n.onMediaPlaying=function(){n.tick()},n.onMediaSeeked=function(){var e=n.media,t=e?e.currentTime:null;if(null!==t&&A(t)&&(n.log("Media seeked to "+t.toFixed(3)),n.getBufferedFrag(t))){var r=n.getFwdBufferInfoAtPos(e,t,w,0);null!==r&&0!==r.len?n.tick():n.warn("Main forward buffer length at "+t+' on "seeked" event '+(r?r.len:"empty")+")")}},n.registerListeners(),n}o(t,e);var r=t.prototype;return r.registerListeners=function(){e.prototype.registerListeners.call(this);var t=this.hls;t.on(b.MANIFEST_PARSED,this.onManifestParsed,this),t.on(b.LEVEL_LOADING,this.onLevelLoading,this),t.on(b.LEVEL_LOADED,this.onLevelLoaded,this),t.on(b.FRAG_LOAD_EMERGENCY_ABORTED,this.onFragLoadEmergencyAborted,this),t.on(b.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),t.on(b.AUDIO_TRACK_SWITCHED,this.onAudioTrackSwitched,this),t.on(b.BUFFER_CREATED,this.onBufferCreated,this),t.on(b.BUFFER_FLUSHED,this.onBufferFlushed,this),t.on(b.LEVELS_UPDATED,this.onLevelsUpdated,this),t.on(b.FRAG_BUFFERED,this.onFragBuffered,this)},r.unregisterListeners=function(){e.prototype.unregisterListeners.call(this);var t=this.hls;t.off(b.MANIFEST_PARSED,this.onManifestParsed,this),t.off(b.LEVEL_LOADED,this.onLevelLoaded,this),t.off(b.FRAG_LOAD_EMERGENCY_ABORTED,this.onFragLoadEmergencyAborted,this),t.off(b.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),t.off(b.AUDIO_TRACK_SWITCHED,this.onAudioTrackSwitched,this),t.off(b.BUFFER_CREATED,this.onBufferCreated,this),t.off(b.BUFFER_FLUSHED,this.onBufferFlushed,this),t.off(b.LEVELS_UPDATED,this.onLevelsUpdated,this),t.off(b.FRAG_BUFFERED,this.onFragBuffered,this)},r.onHandlerDestroying=function(){this.onMediaPlaying=this.onMediaSeeked=null,this.unregisterListeners(),e.prototype.onHandlerDestroying.call(this)},r.startLoad=function(e,t){if(this.levels){var r=this.lastCurrentTime,i=this.hls;if(this.stopLoad(),this.setInterval(100),this.level=-1,!this.startFragRequested){var n=i.startLevel;-1===n&&(i.config.testBandwidth&&this.levels.length>1?(n=0,this.bitrateTest=!0):n=i.firstAutoLevel),i.nextLoadLevel=n,this.level=i.loadLevel,this._hasEnoughToStart=!!t}r>0&&-1===e&&!t&&(this.log("Override startPosition with lastCurrentTime @"+r.toFixed(3)),e=r),this.state=Ei.IDLE,this.nextLoadPosition=this.lastCurrentTime=e+this.timelineOffset,this.startPosition=t?-1:e,this.tick()}else this._forceStartLoad=!0,this.state=Ei.STOPPED},r.stopLoad=function(){this._forceStartLoad=!1,e.prototype.stopLoad.call(this)},r.doTick=function(){switch(this.state){case Ei.WAITING_LEVEL:var e=this.levels,t=this.level,r=null==e?void 0:e[t],i=null==r?void 0:r.details;if(i&&(!i.live||this.levelLastLoaded===r&&!this.waitForLive(r))){if(this.waitForCdnTuneIn(i))break;this.state=Ei.IDLE;break}if(this.hls.nextLoadLevel!==this.level){this.state=Ei.IDLE;break}break;case Ei.FRAG_LOADING_WAITING_RETRY:var n,a=self.performance.now(),s=this.retryDate;if(!s||a>=s||null!=(n=this.media)&&n.seeking){var o=this.levels,l=this.level,u=null==o?void 0:o[l];this.resetStartWhenNotLoaded(u||null),this.state=Ei.IDLE}}this.state===Ei.IDLE&&this.doTickIdle(),this.onTickEnd()},r.onTickEnd=function(){var t;e.prototype.onTickEnd.call(this),null!=(t=this.media)&&t.readyState&&!1===this.media.seeking&&(this.lastCurrentTime=this.media.currentTime),this.checkFragmentChanged()},r.doTickIdle=function(){var e=this.hls,t=this.levelLastLoaded,r=this.levels,i=this.media;if(null!==t&&(i||this.primaryPrefetch||!this.startFragRequested&&e.config.startFragPrefetch)&&(!this.altAudio||!this.audioOnly)){var n=this.buffering?e.nextLoadLevel:e.loadLevel;if(null!=r&&r[n]){var a=r[n],s=this.getMainFwdBufferInfo();if(null!==s){var o=this.getLevelDetails();if(o&&this._streamEnded(s,o)){var l={};return 2===this.altAudio&&(l.type="video"),this.hls.trigger(b.BUFFER_EOS,l),void(this.state=Ei.ENDED)}if(this.buffering){e.loadLevel!==n&&-1===e.manualLevel&&this.log("Adapting to level "+n+" from level "+this.level),this.level=e.nextLoadLevel=n;var u=a.details;if(!u||this.state===Ei.WAITING_LEVEL||this.waitForLive(a))return this.level=n,this.state=Ei.WAITING_LEVEL,void(this.startFragRequested=!1);var d=s.len,h=this.getMaxBufferLength(a.maxBitrate);if(!(d>=h)){this.backtrackFragment&&this.backtrackFragment.start>s.end&&(this.backtrackFragment=null);var f=this.backtrackFragment?this.backtrackFragment.start:s.end,c=this.getNextFragment(f,u);if(this.couldBacktrack&&!this.fragPrevious&&c&&ee(c)&&this.fragmentTracker.getState(c)!==Ut){var g,v=(null!=(g=this.backtrackFragment)?g:c).sn-u.startSN,m=u.fragments[v-1];m&&c.cc===m.cc&&(c=m,this.fragmentTracker.removeFragment(m))}else this.backtrackFragment&&s.len&&(this.backtrackFragment=null);if(c&&this.isLoopLoading(c,f)){if(!c.gap){var p=this.audioOnly&&!this.altAudio?z:$,y=(p===$?this.videoBuffer:this.mediaBuffer)||this.media;y&&this.afterBufferFlushed(y,p,w)}c=this.getNextFragmentLoopLoading(c,u,s,w,h)}c&&(!c.initSegment||c.initSegment.data||this.bitrateTest||(c=c.initSegment),this.loadFragment(c,a,f))}}}}}},r.loadFragment=function(t,r,i){var n=this.fragmentTracker.getState(t);n===Mt||n===Nt?ee(t)?this.bitrateTest?(this.log("Fragment "+t.sn+" of level "+t.level+" is being downloaded to test bitrate and will not be buffered"),this._loadBitrateTestFrag(t,r)):e.prototype.loadFragment.call(this,t,r,i):this._loadInitSegment(t,r):this.clearTrackerIfNeeded(t)},r.getBufferedFrag=function(e){return this.fragmentTracker.getBufferedFrag(e,w)},r.followingBufferedFrag=function(e){return e?this.getBufferedFrag(e.end+.5):null},r.immediateLevelSwitch=function(){this.abortCurrentFrag(),this.flushMainBuffer(0,Number.POSITIVE_INFINITY)},r.nextLevelSwitch=function(){var e=this.levels,t=this.media;if(null!=t&&t.readyState){var r,i=this.getAppendedFrag(t.currentTime);i&&i.start>1&&this.flushMainBuffer(0,i.start-1);var n=this.getLevelDetails();if(null!=n&&n.live){var a=this.getMainFwdBufferInfo();if(!a||a.len<2*n.targetduration)return}if(!t.paused&&e){var s=e[this.hls.nextLoadLevel],o=this.fragLastKbps;r=o&&this.fragCurrent?this.fragCurrent.duration*s.maxBitrate/(1e3*o)+1:0}else r=0;var l=this.getBufferedFrag(t.currentTime+r);if(l){var u=this.followingBufferedFrag(l);if(u){this.abortCurrentFrag();var d=u.maxStartPTS?u.maxStartPTS:u.start,h=u.duration,f=Math.max(l.end,d+Math.min(Math.max(h-this.config.maxFragLookUpTolerance,h*(this.couldBacktrack?.5:.125)),h*(this.couldBacktrack?.75:.25)));this.flushMainBuffer(f,Number.POSITIVE_INFINITY)}}}},r.abortCurrentFrag=function(){var e=this.fragCurrent;switch(this.fragCurrent=null,this.backtrackFragment=null,e&&(e.abortRequests(),this.fragmentTracker.removeFragment(e)),this.state){case Ei.KEY_LOADING:case Ei.FRAG_LOADING:case Ei.FRAG_LOADING_WAITING_RETRY:case Ei.PARSING:case Ei.PARSED:this.state=Ei.IDLE}this.nextLoadPosition=this.getLoadPosition()},r.flushMainBuffer=function(t,r){e.prototype.flushMainBuffer.call(this,t,r,2===this.altAudio?"video":null)},r.onMediaAttached=function(t,r){e.prototype.onMediaAttached.call(this,t,r);var i=r.media;ls(i,"playing",this.onMediaPlaying),ls(i,"seeked",this.onMediaSeeked)},r.onMediaDetaching=function(t,r){var i=this.media;i&&(us(i,"playing",this.onMediaPlaying),us(i,"seeked",this.onMediaSeeked)),this.videoBuffer=null,this.fragPlaying=null,e.prototype.onMediaDetaching.call(this,t,r),r.transferMedia||(this._hasEnoughToStart=!1)},r.onManifestLoading=function(){e.prototype.onManifestLoading.call(this),this.log("Trigger BUFFER_RESET"),this.hls.trigger(b.BUFFER_RESET,void 0),this.couldBacktrack=!1,this.fragLastKbps=0,this.fragPlaying=this.backtrackFragment=null,this.altAudio=0,this.audioOnly=!1},r.onManifestParsed=function(e,t){var r,i,n=!1,a=!1;t.levels.forEach((function(e){var t=e.audioCodec;t&&(n=n||-1!==t.indexOf("mp4a.40.2"),a=a||-1!==t.indexOf("mp4a.40.5"))})),this.audioCodecSwitch=n&&a&&!("function"==typeof(null==(i=$o())||null==(r=i.prototype)?void 0:r.changeType)),this.audioCodecSwitch&&this.log("Both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC"),this.levels=t.levels,this.startFragRequested=!1},r.onLevelLoading=function(e,t){if(this.levels&&this.state===Ei.IDLE){var r=t.levelInfo;(!r.details||r.details.live&&(this.levelLastLoaded!==r||r.details.expired)||this.waitForCdnTuneIn(r.details))&&(this.state=Ei.WAITING_LEVEL)}},r.onLevelLoaded=function(e,t){var r,i=this.levels,n=this.startFragRequested,a=t.level,s=t.details,o=s.totalduration;if(i){this.log("Level "+a+" loaded ["+s.startSN+","+s.endSN+"]"+(s.lastPartSn?"[part-"+s.lastPartSn+"-"+s.lastPartIndex+"]":"")+", cc ["+s.startCC+", "+s.endCC+"] duration:"+o);var l=t.levelInfo,u=this.fragCurrent;!u||this.state!==Ei.FRAG_LOADING&&this.state!==Ei.FRAG_LOADING_WAITING_RETRY||u.level!==t.level&&u.loader&&this.abortCurrentFrag();var d=0;if(s.live||null!=(r=l.details)&&r.live){var h;if(this.checkLiveUpdate(s),s.deltaUpdateFailed)return;d=this.alignPlaylists(s,l.details,null==(h=this.levelLastLoaded)?void 0:h.details)}if(l.details=s,this.levelLastLoaded=l,n||this.setStartPosition(s,d),this.hls.trigger(b.LEVEL_UPDATED,{details:s,level:a}),this.state===Ei.WAITING_LEVEL){if(this.waitForCdnTuneIn(s))return;this.state=Ei.IDLE}n&&s.live&&this.synchronizeToLiveEdge(s),this.tick()}else this.warn("Levels were reset while loading level "+a)},r.synchronizeToLiveEdge=function(e){var t=this.config,r=this.media;if(r){var i=this.hls.liveSyncPosition,n=this.getLoadPosition(),a=e.fragmentStart,s=e.edge,o=n>=a-t.maxFragLookUpTolerance&&n<=s;if(null!==i&&r.duration>i&&(n-1&&this.fragCurrent&&(this.level=this.fragCurrent.level,-1===this.level&&this.resetWhenMissingContext(this.fragCurrent)),this.levels=t.levels},r.swapAudioCodec=function(){this.audioCodecSwap=!this.audioCodecSwap},r.seekToStartPos=function(){var e=this.media;if(e){var t=e.currentTime,r=this.startPosition;if(r>=0&&t0&&(oT.cc;if(!1!==n.independent){var R=d.startPTS,I=d.endPTS,k=d.startDTS,D=d.endDTS;if(l)l.elementaryStreams[d.type]={startPTS:R,endPTS:I,startDTS:k,endDTS:D};else if(d.firstKeyFrame&&d.independent&&1===a.id&&!L&&(this.couldBacktrack=!0),d.dropped&&d.independent){var _=this.getMainFwdBufferInfo(),P=(_?_.end:this.getLoadPosition())+this.config.maxBufferHole,C=d.firstKeyFramePTS?d.firstKeyFramePTS:R;if(!S&&P2&&(o.gap=!0);o.setElementaryStreamInfo(d.type,R,I,k,D),this.backtrackFragment&&(this.backtrackFragment=o),this.bufferFragmentData(d,o,l,a,S||L)}else{if(!S&&!L)return void this.backtrack(o);o.gap=!0}}if(v){var w=v.startPTS,O=v.endPTS,x=v.startDTS,M=v.endDTS;l&&(l.elementaryStreams[z]={startPTS:w,endPTS:O,startDTS:x,endDTS:M}),o.setElementaryStreamInfo(z,w,O,x,M),this.bufferFragmentData(v,o,l,a)}if(g&&null!=f&&null!=(t=f.samples)&&t.length){var F={id:r,frag:o,details:g,samples:f.samples};i.trigger(b.FRAG_PARSING_METADATA,F)}if(g&&h){var N={id:r,frag:o,details:g,samples:h.samples};i.trigger(b.FRAG_PARSING_USERDATA,N)}}}else this.resetWhenMissingContext(a)},r.logMuxedErr=function(e){this.warn((ee(e)?"Media":"Init")+" segment with muxed audiovideo where only video expected: "+e.url)},r._bufferInitSegment=function(e,t,r,i){var n=this;if(this.state===Ei.PARSING){this.audioOnly=!!t.audio&&!t.video,this.altAudio&&!this.audioOnly&&(delete t.audio,t.audiovideo&&this.logMuxedErr(r));var a=t.audio,s=t.video,o=t.audiovideo;if(a){var l=e.audioCodec,u=Ge(a.codec,l);"mp4a"===u&&(u="mp4a.40.5");var d=navigator.userAgent.toLowerCase();if(this.audioCodecSwitch){u&&(u=-1!==u.indexOf("mp4a.40.5")?"mp4a.40.2":"mp4a.40.5");var h=a.metadata;h&&"channelCount"in h&&1!==(h.channelCount||1)&&-1===d.indexOf("firefox")&&(u="mp4a.40.5")}u&&-1!==u.indexOf("mp4a.40.5")&&-1!==d.indexOf("android")&&"audio/mpeg"!==a.container&&(u="mp4a.40.2",this.log("Android: force audio codec to "+u)),l&&l!==u&&this.log('Swapping manifest audio codec "'+l+'" for "'+u+'"'),a.levelCodec=u,a.id=w,this.log("Init audio buffer, container:"+a.container+", codecs[selected/level/parsed]=["+(u||"")+"/"+(l||"")+"/"+a.codec+"]"),delete t.audiovideo}if(s){s.levelCodec=e.videoCodec,s.id=w;var f=s.codec;if(4===(null==f?void 0:f.length))switch(f){case"hvc1":case"hev1":s.codec="hvc1.1.6.L120.90";break;case"av01":s.codec="av01.0.04M.08";break;case"avc1":s.codec="avc1.42e01e"}this.log("Init video buffer, container:"+s.container+", codecs[level/parsed]=["+(e.videoCodec||"")+"/"+f+"]"+(s.codec!==f?" parsed-corrected="+s.codec:"")+(s.supplemental?" supplemental="+s.supplemental:"")),delete t.audiovideo}o&&(this.log("Init audiovideo buffer, container:"+o.container+", codecs[level/parsed]=["+e.codecs+"/"+o.codec+"]"),delete t.video,delete t.audio);var c=Object.keys(t);if(c.length){if(this.hls.trigger(b.BUFFER_CODECS,t),!this.hls)return;c.forEach((function(e){var a=t[e].initSegment;null!=a&&a.byteLength&&n.hls.trigger(b.BUFFER_APPENDING,{type:e,data:a,frag:r,part:null,chunkMeta:i,parent:r.type})}))}this.tickImmediate()}},r.getMainFwdBufferInfo=function(){var e=this.mediaBuffer&&2===this.altAudio?this.mediaBuffer:this.media;return this.getFwdBufferInfo(e,w)},r.backtrack=function(e){this.couldBacktrack=!0,this.backtrackFragment=e,this.resetTransmuxer(),this.flushBufferGap(e),this.fragmentTracker.removeFragment(e),this.fragPrevious=null,this.nextLoadPosition=e.start,this.state=Ei.IDLE},r.checkFragmentChanged=function(){var e=this.media,t=null;if(e&&e.readyState>1&&!1===e.seeking){var r=e.currentTime;if(ir.isBuffered(e,r)?t=this.getAppendedFrag(r):ir.isBuffered(e,r+.1)&&(t=this.getAppendedFrag(r+.1)),t){this.backtrackFragment=null;var i=this.fragPlaying,n=t.level;i&&t.sn===i.sn&&i.level===n||(this.fragPlaying=t,this.hls.trigger(b.FRAG_CHANGED,{frag:t}),i&&i.level===n||this.hls.trigger(b.LEVEL_SWITCHED,{level:n}))}}},i(t,[{key:"hasEnoughToStart",get:function(){return this._hasEnoughToStart}},{key:"maxBufferLength",get:function(){var e=this.levels,t=this.level,r=null==e?void 0:e[t];return r?this.getMaxBufferLength(r.maxBitrate):this.config.maxBufferLength}},{key:"nextLevel",get:function(){var e=this.nextBufferedFrag;return e?e.level:-1}},{key:"currentFrag",get:function(){var e;if(this.fragPlaying)return this.fragPlaying;var t=(null==(e=this.media)?void 0:e.currentTime)||this.lastCurrentTime;return A(t)?this.getAppendedFrag(t):null}},{key:"currentProgramDateTime",get:function(){var e,t=(null==(e=this.media)?void 0:e.currentTime)||this.lastCurrentTime;if(A(t)){var r=this.getLevelDetails(),i=this.currentFrag||(r?pt(null,r.fragments,t):null);if(i){var n=i.programDateTime;if(null!==n){var a=n+1e3*(t-i.start);return new Date(a)}}}return null}},{key:"currentLevel",get:function(){var e=this.currentFrag;return e?e.level:-1}},{key:"nextBufferedFrag",get:function(){var e=this.currentFrag;return e?this.followingBufferedFrag(e):null}},{key:"forceStartLoad",get:function(){return this._forceStartLoad}}])}(Ti),el=function(){function e(e){this.config=void 0,this.keyUriToKeyInfo={},this.emeController=null,this.config=e}var t=e.prototype;return t.abort=function(e){for(var t in this.keyUriToKeyInfo){var r=this.keyUriToKeyInfo[t].loader;if(r){var i;if(e&&e!==(null==(i=r.context)?void 0:i.frag.type))return;r.abort()}}},t.detach=function(){for(var e in this.keyUriToKeyInfo){var t=this.keyUriToKeyInfo[e];(t.mediaKeySessionContext||t.decryptdata.isCommonEncryption)&&delete this.keyUriToKeyInfo[e]}},t.destroy=function(){for(var e in this.detach(),this.keyUriToKeyInfo){var t=this.keyUriToKeyInfo[e].loader;t&&t.destroy()}this.keyUriToKeyInfo={}},t.createKeyLoadError=function(e,t,r,i,n){return void 0===t&&(t=k.KEY_LOAD_ERROR),new Zt({type:I.NETWORK_ERROR,details:t,fatal:!1,frag:e,response:n,error:r,networkDetails:i})},t.loadClear=function(e,t){var r=this;if(this.emeController&&this.config.emeEnabled&&!this.emeController.getSelectedKeySystemFormats().length)if(t.length){for(var i,n=e.sn,a=e.cc,s=function(){var e=t[o];if(a<=e.cc&&("initSegment"===n||"initSegment"===e.sn||n":"")+")"),this.started=!0,this.resumeBuffering();for(var r=0;r-1?this.abrController.forcedAutoLevel:e},set:function(e){this.logger.log("set startLevel:"+e),-1!==e&&(e=Math.max(e,this.minAutoLevel)),this.levelController.startLevel=e}},{key:"capLevelToPlayerSize",get:function(){return this.config.capLevelToPlayerSize},set:function(e){var t=!!e;t!==this.config.capLevelToPlayerSize&&(t?this.capLevelController.startCapping():(this.capLevelController.stopCapping(),this.autoLevelCapping=-1,this.streamController.nextLevelSwitch()),this.config.capLevelToPlayerSize=t)}},{key:"autoLevelCapping",get:function(){return this._autoLevelCapping},set:function(e){this._autoLevelCapping!==e&&(this.logger.log("set autoLevelCapping:"+e),this._autoLevelCapping=e,this.levelController.checkMaxAutoUpdated())}},{key:"bandwidthEstimate",get:function(){var e=this.abrController.bwEstimator;return e?e.getEstimate():NaN},set:function(e){this.abrController.resetEstimator(e)}},{key:"abrEwmaDefaultEstimate",get:function(){var e=this.abrController.bwEstimator;return e?e.defaultEstimate:NaN}},{key:"ttfbEstimate",get:function(){var e=this.abrController.bwEstimator;return e?e.getEstimateTTFB():NaN}},{key:"maxHdcpLevel",get:function(){return this._maxHdcpLevel},set:function(e){(function(e){return ze.indexOf(e)>-1})(e)&&this._maxHdcpLevel!==e&&(this._maxHdcpLevel=e,this.levelController.checkMaxAutoUpdated())}},{key:"autoLevelEnabled",get:function(){return-1===this.levelController.manualLevel}},{key:"manualLevel",get:function(){return this.levelController.manualLevel}},{key:"minAutoLevel",get:function(){var e=this.levels,t=this.config.minAutoBitrate;if(!e)return 0;for(var r=e.length,i=0;i=t)return i;return 0}},{key:"maxAutoLevel",get:function(){var e,t=this.levels,r=this.autoLevelCapping,i=this.maxHdcpLevel;if(e=-1===r&&null!=t&&t.length?t.length-1:r,i)for(var n=e;n--;){var a=t[n].attrs["HDCP-LEVEL"];if(a&&a<=i)return n}return e}},{key:"firstAutoLevel",get:function(){return this.abrController.firstAutoLevel}},{key:"nextAutoLevel",get:function(){return this.abrController.nextAutoLevel},set:function(e){this.abrController.nextAutoLevel=e}},{key:"playingDate",get:function(){return this.streamController.currentProgramDateTime}},{key:"mainForwardBufferInfo",get:function(){return this.streamController.getMainFwdBufferInfo()}},{key:"maxBufferLength",get:function(){return this.streamController.maxBufferLength}},{key:"allAudioTracks",get:function(){var e=this.audioTrackController;return e?e.allAudioTracks:[]}},{key:"audioTracks",get:function(){var e=this.audioTrackController;return e?e.audioTracks:[]}},{key:"audioTrack",get:function(){var e=this.audioTrackController;return e?e.audioTrack:-1},set:function(e){var t=this.audioTrackController;t&&(t.audioTrack=e)}},{key:"allSubtitleTracks",get:function(){var e=this.subtitleTrackController;return e?e.allSubtitleTracks:[]}},{key:"subtitleTracks",get:function(){var e=this.subtitleTrackController;return e?e.subtitleTracks:[]}},{key:"subtitleTrack",get:function(){var e=this.subtitleTrackController;return e?e.subtitleTrack:-1},set:function(e){var t=this.subtitleTrackController;t&&(t.subtitleTrack=e)}},{key:"media",get:function(){return this._media}},{key:"subtitleDisplay",get:function(){var e=this.subtitleTrackController;return!!e&&e.subtitleDisplay},set:function(e){var t=this.subtitleTrackController;t&&(t.subtitleDisplay=e)}},{key:"lowLatencyMode",get:function(){return this.config.lowLatencyMode},set:function(e){this.config.lowLatencyMode=e}},{key:"liveSyncPosition",get:function(){return this.latencyController.liveSyncPosition}},{key:"latency",get:function(){return this.latencyController.latency}},{key:"maxLatency",get:function(){return this.latencyController.maxLatency}},{key:"targetLatency",get:function(){return this.latencyController.targetLatency},set:function(e){this.latencyController.targetLatency=e}},{key:"drift",get:function(){return this.latencyController.drift}},{key:"forceStartLoad",get:function(){return this.streamController.forceStartLoad}},{key:"pathways",get:function(){return this.levelController.pathways}},{key:"pathwayPriority",get:function(){return this.levelController.pathwayPriority},set:function(e){this.levelController.pathwayPriority=e}},{key:"bufferedToEnd",get:function(){var e;return!(null==(e=this.bufferController)||!e.bufferedToEnd)}},{key:"interstitialsManager",get:function(){var e;return(null==(e=this.interstitialsController)?void 0:e.interstitialsManager)||null}}],[{key:"version",get:function(){return ra}},{key:"Events",get:function(){return b}},{key:"MetadataSchema",get:function(){return ji}},{key:"ErrorTypes",get:function(){return I}},{key:"ErrorDetails",get:function(){return k}},{key:"DefaultConfig",get:function(){return e.defaultConfig?e.defaultConfig:Uo},set:function(t){e.defaultConfig=t}}])}();return nl.defaultConfig=void 0,nl},"object"==typeof exports&&"undefined"!=typeof module?module.exports=i():"function"==typeof define&&define.amd?define(i):(r="undefined"!=typeof globalThis?globalThis:r||self).Hls=i()}(!1);
+//# sourceMappingURL=hls.min.js.map
diff --git a/dragonpilot/dashy/web/dist/pages/player.html b/dragonpilot/dashy/web/dist/pages/player.html
new file mode 100644
index 0000000..3fa81af
--- /dev/null
+++ b/dragonpilot/dashy/web/dist/pages/player.html
@@ -0,0 +1 @@
+HLS Player
\ No newline at end of file
diff --git a/dragonpilot/selfdrive/controls/lib/acm.py b/dragonpilot/selfdrive/controls/lib/acm.py
new file mode 100644
index 0000000..9318233
--- /dev/null
+++ b/dragonpilot/selfdrive/controls/lib/acm.py
@@ -0,0 +1,161 @@
+"""
+Copyright (c) 2025, Rick Lan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, and/or sublicense,
+for non-commercial purposes only, subject to the following conditions:
+
+- The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+- Commercial use (e.g. use in a product, service, or activity intended to
+  generate revenue) is prohibited without explicit written permission from
+  the copyright holder.
+
+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.
+"""
+
+import time
+import numpy as np
+from openpilot.common.swaglog import cloudlog
+
+# Configuration parameters
+SPEED_RATIO = 0.98  # Must be within 2% over cruise speed
+TTC_THRESHOLD = 3.0  # seconds - disable ACM when lead is within this time
+
+# Emergency thresholds - IMMEDIATELY disable ACM
+EMERGENCY_TTC = 2.0  # seconds - emergency situation
+EMERGENCY_RELATIVE_SPEED = 10.0  # m/s (~36 km/h closing speed - only for rapid closing)
+EMERGENCY_DECEL_THRESHOLD = -1.5  # m/s² - if MPC wants this much braking, emergency disable
+
+# Safety cooldown after lead detection
+LEAD_COOLDOWN_TIME = 0.5  # seconds - brief cooldown to handle sensor glitches
+
+# Speed-based distance scaling - more practical for real traffic
+SPEED_BP = [0., 10., 20., 30.]  # m/s (0, 36, 72, 108 km/h)
+MIN_DIST_V = [15., 20., 25., 30.]  # meters - closer to original 25m baseline
+
+
+class ACM:
+  def __init__(self):
+    self.enabled = False
+    self._is_speed_over_cruise = False
+    self._has_lead = False
+    self._active_prev = False
+    self._last_lead_time = 0.0  # Track when we last saw a lead
+
+    self.active = False
+    self.just_disabled = False
+
+  def _check_emergency_conditions(self, lead, v_ego, current_time):
+    """Check for emergency conditions that require immediate ACM disable."""
+    if not lead or not lead.status:
+      return False
+
+    self.lead_ttc = lead.dRel / max(v_ego, 0.1)
+    relative_speed = v_ego - lead.vLead  # Positive = closing
+
+    # Speed-adaptive minimum distance
+    min_dist_for_speed = np.interp(v_ego, SPEED_BP, MIN_DIST_V)
+
+    # Emergency disable conditions - only for truly dangerous situations
+    # Require BOTH close distance AND (fast closing OR very short TTC)
+    if lead.dRel < min_dist_for_speed and (
+        self.lead_ttc < EMERGENCY_TTC or
+        relative_speed > EMERGENCY_RELATIVE_SPEED):
+
+      self._last_lead_time = current_time
+      if self.active:  # Only log if we're actually disabling
+        cloudlog.warning(f"ACM emergency disable: dRel={lead.dRel:.1f}m, TTC={self.lead_ttc:.1f}s, relSpeed={relative_speed:.1f}m/s")
+      return True
+
+    return False
+
+  def _update_lead_status(self, lead, v_ego, current_time):
+    """Update lead vehicle detection status."""
+    if lead and lead.status:
+      self.lead_ttc = lead.dRel / max(v_ego, 0.1)
+
+      if self.lead_ttc < TTC_THRESHOLD:
+        self._has_lead = True
+        self._last_lead_time = current_time
+      else:
+        self._has_lead = False
+    else:
+      self._has_lead = False
+      self.lead_ttc = float('inf')
+
+  def _check_cooldown(self, current_time):
+    """Check if we're still in cooldown period after lead detection."""
+    time_since_lead = current_time - self._last_lead_time
+    return time_since_lead < LEAD_COOLDOWN_TIME
+
+  def _should_activate(self, user_ctrl_lon, v_ego, v_cruise, in_cooldown):
+    """Determine if ACM should be active based on all conditions."""
+    self._is_speed_over_cruise = v_ego > (v_cruise * SPEED_RATIO)
+
+    return (not user_ctrl_lon and
+            not self._has_lead and
+            not in_cooldown and
+            self._is_speed_over_cruise)
+
+  def update_states(self, cc, rs, user_ctrl_lon, v_ego, v_cruise):
+    """Update ACM state with multiple safety checks."""
+    # Basic validation
+    if not self.enabled or len(cc.orientationNED) != 3:
+      self.active = False
+      return
+
+    current_time = time.monotonic()
+    lead = rs.leadOne
+
+    # Check emergency conditions first (highest priority)
+    if self._check_emergency_conditions(lead, v_ego, current_time):
+      self.active = False
+      self._active_prev = self.active
+      return
+
+    # Update normal lead status
+    self._update_lead_status(lead, v_ego, current_time)
+
+    # Check cooldown period
+    in_cooldown = self._check_cooldown(current_time)
+
+    # Determine if ACM should be active
+    self.active = self._should_activate(user_ctrl_lon, v_ego, v_cruise, in_cooldown)
+
+    # Track state changes for logging
+    self.just_disabled = self._active_prev and not self.active
+    if self.active and not self._active_prev:
+      cloudlog.info(f"ACM activated: v_ego={v_ego*3.6:.1f} km/h, v_cruise={v_cruise*3.6:.1f} km/h")
+    elif self.just_disabled:
+      cloudlog.info("ACM deactivated")
+
+    self._active_prev = self.active
+
+  def update_a_desired_trajectory(self, a_desired_trajectory):
+    """
+    Modify acceleration trajectory to allow coasting.
+    SAFETY: Check for any strong braking request and abort.
+    """
+    if not self.active:
+      return a_desired_trajectory
+
+    # SAFETY CHECK: If MPC wants significant braking, DON'T suppress it
+    min_accel = np.min(a_desired_trajectory)
+    if min_accel < EMERGENCY_DECEL_THRESHOLD:
+      cloudlog.warning(f"ACM aborting: MPC requested {min_accel:.2f} m/s² braking")
+      self.active = False  # Immediately deactivate
+      return a_desired_trajectory  # Return unmodified trajectory
+
+    # Only suppress very mild braking (> -1.0 m/s²)
+    # This allows coasting but preserves any meaningful braking
+    modified_trajectory = np.copy(a_desired_trajectory)
+    for i in range(len(modified_trajectory)):
+      if -1.0 < modified_trajectory[i] < 0:
+        # Only suppress very gentle braking for cruise control
+        modified_trajectory[i] = 0.0
+      # Any braking stronger than -1.0 m/s² is preserved!
+
+    return modified_trajectory
diff --git a/dragonpilot/selfdrive/controls/lib/aem.py b/dragonpilot/selfdrive/controls/lib/aem.py
new file mode 100644
index 0000000..db13054
--- /dev/null
+++ b/dragonpilot/selfdrive/controls/lib/aem.py
@@ -0,0 +1,70 @@
+"""
+Copyright (c) 2025, Rick Lan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, and/or sublicense,
+for non-commercial purposes only, subject to the following conditions:
+
+- The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+- Commercial use (e.g. use in a product, service, or activity intended to
+  generate revenue) is prohibited without explicit written permission from
+  the copyright holder.
+
+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.
+"""
+
+import time
+import numpy as np
+from openpilot.selfdrive.modeld.constants import ModelConstants
+
+
+AEM_COOLDOWN_TIME = 0.5  # seconds
+
+SLOW_DOWN_BP = [0., 2.78, 5.56, 8.34, 11.12, 13.89, 15.28]
+SLOW_DOWN_DIST = [10, 30., 50., 70., 80., 90., 120.]
+
+# Allow throttle
+# ALLOW_THROTTLE_THRESHOLD = 0.4
+# MIN_ALLOW_THROTTLE_SPEED = 2.5
+
+
+class AEM:
+
+  def __init__(self):
+    self._active = False
+    self._cooldown_end_time = 0.0
+
+  def _perform_experimental_mode(self):
+    self._active = True
+    self._cooldown_end_time = time.monotonic() + AEM_COOLDOWN_TIME
+
+  def get_mode(self, mode):
+    # override mode
+    if time.monotonic() < self._cooldown_end_time:
+      mode = 'blended'
+    else:
+      self._active = False
+    return mode
+
+  def update_states(self, model_msg, radar_msg, v_ego):
+
+    # Stop sign/light detection
+    if not self._active:
+      if not radar_msg.leadOne.status and len(model_msg.orientation.x) == len(model_msg.position.x) == ModelConstants.IDX_N and \
+        model_msg.position.x[ModelConstants.IDX_N - 1] < np.interp(v_ego, SLOW_DOWN_BP, SLOW_DOWN_DIST):
+        self._perform_experimental_mode()
+
+    # throttle prob is low and there is no lead ahead (prep for brake?)
+    # if not self._active:
+    #   if len(model_msg.meta.disengagePredictions.gasPressProbs) > 1:
+    #     throttle_prob = model_msg.meta.disengagePredictions.gasPressProbs[1]
+    #   else:
+    #     throttle_prob = 1.0
+
+    #   allow_throttle = throttle_prob > ALLOW_THROTTLE_THRESHOLD or v_ego <= MIN_ALLOW_THROTTLE_SPEED
+    #   if not allow_throttle and not radar_msg.leadOne.status:
+    #     self._perform_experimental_mode()
+
diff --git a/dragonpilot/selfdrive/controls/lib/dtsc.py b/dragonpilot/selfdrive/controls/lib/dtsc.py
new file mode 100644
index 0000000..a7d15dd
--- /dev/null
+++ b/dragonpilot/selfdrive/controls/lib/dtsc.py
@@ -0,0 +1,145 @@
+"""
+Copyright (c) 2025, Rick Lan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, and/or sublicense,
+for non-commercial purposes only, subject to the following conditions:
+
+- The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+- Commercial use (e.g. use in a product, service, or activity intended to
+  generate revenue) is prohibited without explicit written permission from
+  the copyright holder.
+
+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.
+"""
+
+import numpy as np
+from openpilot.selfdrive.modeld.constants import ModelConstants
+from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import T_IDXS as T_IDXS_MPC
+from openpilot.common.swaglog import cloudlog
+
+# Physics constants
+COMFORT_LAT_G = 0.2  # g units - universal human comfort threshold
+BASE_LAT_ACC = COMFORT_LAT_G * 9.81  # ~2.0 m/s^2
+SAFETY_FACTOR = 0.9  # 10% safety margin on calculated speeds
+MIN_CURVE_DISTANCE = 5.0  # meters - minimum distance to react to curves
+MAX_DECEL = -2.0  # m/s^2 - maximum comfortable deceleration
+
+
+class DTSC:
+  """
+  Dynamic Turn Speed Controller - Predictive curve speed management via MPC constraints.
+
+  Core physics: v_max = sqrt(lateral_acceleration / curvature) * safety_factor
+
+  Operation:
+  1. Scans predicted path for curvature (up to ~10 seconds ahead)
+  2. Calculates safe speed for each point using physics + comfort limits
+  3. Identifies critical points where current speed would exceed safe speed
+  4. Calculates required deceleration to reach safe speed at critical point
+  5. Provides deceleration as MPC constraint for smooth trajectory planning
+  """
+
+  def __init__(self, aggressiveness=1.0):
+    """
+    Initialize DTSC with user-adjustable aggressiveness.
+
+    Args:
+      aggressiveness: Factor to adjust lateral acceleration limit
+                     0.7 = 30% more conservative (slower in curves)
+                     1.0 = default balanced behavior
+                     1.3 = 30% more aggressive (faster in curves)
+    """
+    self.aggressiveness = np.clip(aggressiveness, 0.5, 1.5)
+    self.active = False
+    self.debug_msg = ""
+    cloudlog.info(f"DTSC: Initialized with aggressiveness {self.aggressiveness:.2f}")
+
+  def set_aggressiveness(self, value):
+    """Update aggressiveness factor (0.5 to 1.5)."""
+    self.aggressiveness = np.clip(value, 0.5, 1.5)
+    cloudlog.info(f"DTSC: Aggressiveness updated to {self.aggressiveness:.2f}")
+
+  def get_mpc_constraints(self, model_msg, v_ego, base_a_min, base_a_max):
+    """
+    Calculate MPC acceleration constraints based on predicted path curvature.
+
+    Args:
+      model_msg: ModelDataV2 containing predicted path
+      v_ego: Current vehicle speed (m/s)
+      base_a_min: Default minimum acceleration constraint
+      base_a_max: Default maximum acceleration constraint
+
+    Returns:
+      (a_min_array, a_max_array): Modified constraints for each MPC timestep
+    """
+
+    # Initialize with base constraints
+    a_min = np.ones(len(T_IDXS_MPC)) * base_a_min
+    a_max = np.ones(len(T_IDXS_MPC)) * base_a_max
+
+    # Validate model data
+    if not self._is_model_data_valid(model_msg):
+      self.active = False
+      return a_min, a_max
+
+    # Extract predictions for MPC horizon
+    v_pred = np.interp(T_IDXS_MPC, ModelConstants.T_IDXS, model_msg.velocity.x)
+    turn_rates = np.interp(T_IDXS_MPC, ModelConstants.T_IDXS, model_msg.orientationRate.z)
+    positions = np.interp(T_IDXS_MPC, ModelConstants.T_IDXS, model_msg.position.x)
+
+    # Calculate curvature (turn_rate / velocity)
+    curvatures = np.abs(turn_rates / np.clip(v_pred, 1.0, 100.0))
+
+    # Calculate safe speeds
+    lat_acc_limit = BASE_LAT_ACC * self.aggressiveness
+    safe_speeds = np.sqrt(lat_acc_limit / (curvatures + 1e-6)) * SAFETY_FACTOR
+
+    # Find speed violations
+    speed_excess = v_pred - safe_speeds
+    if np.all(speed_excess <= 0):
+      self._deactivate()
+      return a_min, a_max
+
+    # Find critical point (maximum speed excess)
+    critical_idx = np.argmax(speed_excess)
+    critical_distance = positions[critical_idx]
+    critical_safe_speed = safe_speeds[critical_idx]
+
+    # Only act if we have sufficient distance
+    if critical_distance <= MIN_CURVE_DISTANCE:
+      self._deactivate()
+      return a_min, a_max
+
+    # Calculate required deceleration: a = (v_f^2 - v_i^2) / (2*d)
+    required_decel = (critical_safe_speed**2 - v_ego**2) / (2 * critical_distance)
+    required_decel = max(required_decel, MAX_DECEL)
+
+    # Apply constraint progressively until critical point
+    for i in range(len(T_IDXS_MPC)):
+      t = T_IDXS_MPC[i]
+      distance_at_t = v_ego * t + 0.5 * required_decel * t**2
+
+      if distance_at_t < critical_distance:
+        a_max[i] = min(a_max[i], required_decel)
+
+    # Update status
+    self.active = True
+    self.debug_msg = f"Curve in {critical_distance:.0f}m → {critical_safe_speed*3.6:.0f} km/h"
+    cloudlog.info(f"DTSC: {self.debug_msg} (aggr={self.aggressiveness:.1f})")
+
+    return a_min, a_max
+
+  def _is_model_data_valid(self, model_msg):
+    """Check if model message contains valid prediction data."""
+    return (len(model_msg.position.x) == ModelConstants.IDX_N and
+            len(model_msg.velocity.x) == ModelConstants.IDX_N and
+            len(model_msg.orientationRate.z) == ModelConstants.IDX_N)
+
+  def _deactivate(self):
+    """Clear active state and debug message."""
+    self.active = False
+    self.debug_msg = ""
diff --git a/dragonpilot/selfdrive/controls/lib/road_edge_detector.py b/dragonpilot/selfdrive/controls/lib/road_edge_detector.py
new file mode 100644
index 0000000..7dda578
--- /dev/null
+++ b/dragonpilot/selfdrive/controls/lib/road_edge_detector.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+"""
+Copyright (c) 2019, rav4kumar, Rick Lan, dragonpilot community, and a number of other of contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, and/or sublicense, 
+for non-commercial purposes only, subject to the following conditions:
+
+- The above copyright notice and this permission notice shall be included in 
+  all copies or substantial portions of the Software.
+- Commercial use (e.g. use in a product, service, or activity intended to 
+  generate revenue) is prohibited without explicit written permission from 
+  the copyright holder.
+
+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.
+"""
+
+import numpy as np
+
+NEARSIDE_PROB = 0.2
+EDGE_PROB = 0.35
+
+class RoadEdgeDetector:
+  def __init__(self, enabled = False):
+    self._is_enabled = enabled
+    self.left_edge_detected = False
+    self.right_edge_detected = False
+
+  def update(self, road_edge_stds, lane_line_probs):
+    if not self._is_enabled:
+      return
+
+    left_road_edge_prob = np.clip(1.0 - road_edge_stds[0], 0.0, 1.0)
+    left_lane_nearside_prob = lane_line_probs[0]
+
+    right_road_edge_prob = np.clip(1.0 - road_edge_stds[1], 0.0, 1.0)
+    right_lane_nearside_prob = lane_line_probs[3]
+
+    self.left_edge_detected = bool(
+      left_road_edge_prob > EDGE_PROB and
+      left_lane_nearside_prob < NEARSIDE_PROB and
+      right_lane_nearside_prob >= left_lane_nearside_prob
+    )
+
+    self.right_edge_detected = bool(
+      right_road_edge_prob > EDGE_PROB and
+      right_lane_nearside_prob < NEARSIDE_PROB and
+      left_lane_nearside_prob >= right_lane_nearside_prob
+    )
+
+  def set_enabled(self, enabled):
+    self._is_enabled = enabled
+
+  def is_enabled(self):
+    return self._is_enabled
diff --git a/dragonpilot/selfdrive/ui/beepd.py b/dragonpilot/selfdrive/ui/beepd.py
new file mode 100644
index 0000000..100f2ad
--- /dev/null
+++ b/dragonpilot/selfdrive/ui/beepd.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+"""
+Copyright (c) 2025, Rick Lan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, and/or sublicense, 
+for non-commercial purposes only, subject to the following conditions:
+
+- The above copyright notice and this permission notice shall be included in 
+  all copies or substantial portions of the Software.
+- Commercial use (e.g. use in a product, service, or activity intended to 
+  generate revenue) is prohibited without explicit written permission from 
+  the copyright holder.
+
+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.
+"""
+
+import subprocess
+import time
+from cereal import car, messaging
+from openpilot.common.realtime import Ratekeeper
+import threading
+
+AudibleAlert = car.CarControl.HUDControl.AudibleAlert
+
+class Beepd:
+  def __init__(self):
+    self.current_alert = AudibleAlert.none
+    self.enable_gpio()
+
+  def enable_gpio(self):
+    try:
+      subprocess.run("echo 42 | sudo tee /sys/class/gpio/export",
+                     shell=True,
+                     stderr=subprocess.DEVNULL,
+                     stdout=subprocess.DEVNULL,
+                     encoding='utf8')
+    except Exception:
+      pass
+    subprocess.run("echo \"out\" | sudo tee /sys/class/gpio/gpio42/direction",
+                   shell=True,
+                   stderr=subprocess.DEVNULL,
+                   stdout=subprocess.DEVNULL,
+                   encoding='utf8')
+
+  def _beep(self, on):
+    val = "1" if on else "0"
+    subprocess.run(f"echo \"{val}\" | sudo tee /sys/class/gpio/gpio42/value",
+                   shell=True,
+                   stderr=subprocess.DEVNULL,
+                   stdout=subprocess.DEVNULL,
+                   encoding='utf8')
+
+  def engage(self):
+    self._beep(True)
+    time.sleep(0.05)
+    self._beep(False)
+
+  def disengage(self):
+    for _ in range(2):
+      self._beep(True)
+      time.sleep(0.01)
+      self._beep(False)
+      time.sleep(0.01)
+
+  def warning(self):
+    for _ in range(3):
+      self._beep(True)
+      time.sleep(0.01)
+      self._beep(False)
+      time.sleep(0.01)
+
+  def warning_immediate(self):
+    for _ in range(5):
+      self._beep(True)
+      time.sleep(0.01)
+      self._beep(False)
+      time.sleep(0.01)
+
+  def dispatch_beep(self, func):
+    threading.Thread(target=func, daemon=True).start()
+
+  def update_alert(self, new_alert):
+    current_alert_played_once = self.current_alert == AudibleAlert.none
+    if self.current_alert != new_alert and (new_alert != AudibleAlert.none or current_alert_played_once):
+      self.current_alert = new_alert
+      # if new_alert == AudibleAlert.engage:
+      #   self.dispatch_beep(self.engage)
+      # if new_alert == AudibleAlert.disengage:
+      #   self.dispatch_beep(self.disengage)
+      if new_alert == AudibleAlert.warningImmediate:
+        self.dispatch_beep(self.warning_immediate)
+
+  def get_audible_alert(self, sm):
+    if sm.updated['selfdriveState']:
+      new_alert = sm['selfdriveState'].alertSound.raw
+      self.update_alert(new_alert)
+
+  def test_beepd_thread(self):
+    frame = 0
+    rk = Ratekeeper(20)
+    pm = messaging.PubMaster(['selfdriveState'])
+    while True:
+      cs = messaging.new_message('selfdriveState')
+      if frame == 20:
+        cs.selfdriveState.alertSound = AudibleAlert.engage
+      if frame == 40:
+        cs.selfdriveState.alertSound = AudibleAlert.disengage
+      if frame == 60:
+        cs.selfdriveState.alertSound = AudibleAlert.prompt
+      if frame == 80:
+        cs.selfdriveState.alertSound = AudibleAlert.disengage
+      if frame == 85:
+        cs.selfdriveState.alertSound = AudibleAlert.prompt
+
+      pm.send("selfdriveState", cs)
+      frame += 1
+      rk.keep_time()
+
+  def beepd_thread(self, test=False):
+    if test:
+      threading.Thread(target=self.test_beepd_thread, daemon=True).start()
+
+    sm = messaging.SubMaster(['selfdriveState'])
+    rk = Ratekeeper(20)
+
+    while True:
+      sm.update(0)
+      self.get_audible_alert(sm)
+      rk.keep_time()
+
+def main():
+  s = Beepd()
+  s.beepd_thread(test=False)
+
+if __name__ == "__main__":
+  main()
diff --git a/dragonpilot/selfdrive/ui/layouts/settings/dragonpilot.py b/dragonpilot/selfdrive/ui/layouts/settings/dragonpilot.py
index 5e4802f..3fb2a99 100644
--- a/dragonpilot/selfdrive/ui/layouts/settings/dragonpilot.py
+++ b/dragonpilot/selfdrive/ui/layouts/settings/dragonpilot.py
@@ -57,15 +57,187 @@ class DragonpilotLayout(Widget):
   def _lat_toggles(self):
     self._toggles["title_lat"] = simple_item(title=lambda: tr("### Lateral ###"))
 
+    self._toggles["dp_lat_alka"] = toggle_item(
+      title=lambda: tr("Always-on Lane Keeping Assist (ALKA)"),
+      description=lambda: tr("Allows openpilot to always steer to keep the car in its lane."),
+      initial_state=self._params.get_bool("dp_lat_alka"),
+      callback=lambda val: self._params.put_bool("dp_lat_alka", val),
+    )
+
+    self._toggles['dp_lat_lca_speed'] = spin_button_item(
+      title=lambda: tr('Lane Change Assist At:'),
+      description=lambda: tr("Off = Disable LCA.
1 mph = 1.2 km/h."), + initial_value=int(self._params.get("dp_lat_lca_speed") or 20), + callback=self._on_dp_lat_lca_speed_change, + min_val=0, + max_val=100, + step=5, + suffix=tr(" mph"), + special_value_text=tr("Off"), + ) + + self._toggles['dp_lat_lca_auto_sec'] = double_spin_button_item( + title=lambda: "+ " + tr('Auto Lane Change after:'), + description=lambda: tr("Off = Disable Auto Lane Change."), + initial_value=int(self._params.get("dp_lat_lca_auto_sec") or 0.0), + callback=lambda val: self._params.put("dp_lat_lca_auto_sec", float(val)), + min_val=0.0, + max_val=5.0, + step=0.5, + suffix=tr(" sec"), + special_value_text=tr("Off"), + # enabled=int(self._params.get("dp_lat_lca_speed") or 20) > 0 + ) + + self._toggles['dp_lat_road_edge_detection'] = toggle_item( + title=lambda: tr('Road Edge Detection (RED)'), + description=lambda: tr("Block lane change assist when the system detects the road edge.
NOTE: This will show 'Car Detected in Blindspot' warning."), + initial_state=self._params.get_bool("dp_lat_road_edge_detection"), + callback=lambda val: self._params.put_bool("dp_lat_road_edge_detection", val), + ) + def _lon_toggles(self): self._toggles["title_lon"] = simple_item(title=lambda: tr("### Longitudinal ###")) + self._toggles['dp_lon_ext_radar'] = toggle_item( + title=lambda: tr("Use External Radar"), + description=lambda: tr("See https://github.com/eFiniLan/openpilot-ext-radar-addon for more information."), + initial_state=self._params.get_bool("dp_lon_ext_radar"), + callback=lambda val: self._params.put_bool("dp_lon_ext_radar", val), + ) + + self._toggles["dp_lon_acm"] = toggle_item( + title=lambda: tr("Enable Adaptive Coasting Mode (ACM)"), + description=tr("Adaptive Coasting Mode (ACM) reduces braking to allow smoother coasting when appropriate."), + initial_state=self._params.get_bool("dp_lon_acm"), + callback=lambda val: self._params.put_bool("dp_lon_acm", val), + ) + + self._toggles["dp_lon_aem"] = toggle_item( + title=lambda: tr("Adaptive Experimental Mode (AEM)"), + description=lambda: tr("Adaptive mode switcher between ACC and Blended based on driving context."), + initial_state=self._params.get_bool("dp_lon_aem"), + callback=lambda val: self._params.put_bool("dp_lon_aem", val), + ) + + self._toggles["dp_lon_dtsc"] = toggle_item( + title=lambda: tr("Dynamic Turn Speed Control (DTSC)"), + description=lambda: tr("DTSC automatically adjusts the vehicle's predicted speed based on upcoming road curvature and grip conditions.
Originally from the openpilot TACO branch."), + initial_state=self._params.get_bool("dp_lon_dtsc"), + callback=lambda val: self._params.put_bool("dp_lon_dtsc", val), + ) + def _ui_toggles(self): self._toggles["title_ui"] = simple_item(title=lambda: tr("### UI ###")) + self._toggles["dp_ui_hide_hud_speed_kph"] = spin_button_item( + title=lambda: tr("Hide HUD When Moves above:"), + description=lambda: tr("To prevent screen burn-in, hide Speed, MAX Speed, and Steering/DM Icons when the car moves.
Off = Stock Behavior
1 km/h = 0.6 mph"), + initial_value=int(self._params.get("dp_ui_hide_hud_speed_kph") or 0), + callback=lambda val: self._params.put("dp_ui_hide_hud_speed_kph", val), + suffix=tr(" km/h"), + min_val=0, + max_val=120, + step=5, + special_value_text=tr("Off"), + ) + + self._toggles["dp_ui_rainbow"] = toggle_item( + title=lambda: tr("Rainbow Driving Path like Tesla"), + description=lambda: tr("Why not?"), + initial_state=self._params.get_bool("dp_ui_rainbow"), + callback=lambda val: self._params.put_bool("dp_ui_rainbow", val), + ) + + self._toggles["dp_ui_lead"] = text_spin_button_item( + title=lambda: tr("Display Lead Stats"), + description=lambda: tr("Display the statistics of lead car and/or radar tracking points.
Lead: Lead stats only
Radar: Radar tracking point stats only
All: Lead and Radar stats
NOTE: Radar option only works on certain vehicle models."), + initial_index=int(self._params.get("dp_ui_lead") or 0), + callback=lambda val: self._params.put("dp_ui_lead", val), + options=["Off", "Lead", "Radar", "All"] + ) + def _device_toggles(self): self._toggles["title_dev"] = simple_item(title=lambda: tr("### Device ###")) + if "LITE" in os.environ: + self._toggles["dp_dev_is_rhd"] = toggle_item( + title=lambda: tr("Enable Right-Hand Drive Mode"), + description=lambda: tr("Allow openpilot to obey right-hand traffic conventions on right driver seat."), + initial_state=self._params.get_bool("dp_dev_is_rhd"), + callback=lambda val: self._params.put_bool("dp_dev_is_rhd", val), + ) + + self._toggles["dp_dev_monitoring_disabled"] = toggle_item( + title=lambda: tr("Disable Driver Monitoring"), + description=lambda: tr("USE AT YOUR OWN RISK."), + initial_state=self._params.get_bool("dp_dev_monitoring_disabled"), + callback=lambda val: self._params.put_bool("dp_dev_monitoring_disabled", val), + ) + + self._toggles["dp_dev_beep"] = toggle_item( + title=lambda: tr("Enable Beep (Warning)"), + description=lambda: tr("Use Buzzer for audiable alerts."), + initial_state=self._params.get_bool("dp_dev_beep"), + callback=lambda val: self._params.put_bool("dp_dev_beep", val), + ) + + self._toggles["dp_ui_display_mode"] = text_spin_button_item( + title=lambda: tr("Display Mode"), + callback=lambda val: self._params.put("dp_ui_display_mode", val), + options=["Std.", "MAIN+", "OP+", "MAIN-", "OP-"], + initial_index=int(self._params.get("dp_ui_display_mode") or 0), + description=lambda: tr("Std.: Stock behavior.
MAIN+: ACC MAIN on = Display ON.
OP+: OP enabled = Display ON.
MAIN-: ACC MAIN on = Display OFF
OP-: OP enabled = Display OFF."), + ) + + if "LITE" not in os.environ: + self._toggles["dp_dev_audible_alert_mode"] = text_spin_button_item( + title=lambda: tr("Audible Alert"), + description=lambda: tr("Std.: Stock behaviour.
Warning: Only emits sound when there is a warning.
Off: Does not emit any sound at all."), + initial_index=int(self._params.get("dp_dev_audible_alert_mode") or 0), + callback=lambda val: self._params.put("dp_dev_audible_alert_mode", val), + options=["Std.", "Warning", "Off"], + ) + + self._toggles["dp_dev_auto_shutdown_in"] = spin_button_item( + title=lambda: tr("Auto Shutdown After"), + description=lambda: tr("0 mins = Immediately"), + initial_value=int(self._params.get("dp_dev_auto_shutdown_in") or -5), + callback=lambda val: self._params.put("dp_dev_auto_shutdown_in", val), + min_val=-5, + max_val=300, + step=5, + suffix=tr(" mins"), + special_value_text=tr("Off"), + ) + + self._toggles["dp_dev_dashy"] = text_spin_button_item( + title=lambda: tr("dashy"), + description=lambda: tr("dashy - dragonpilot's all-in-one system hub for you.

Visit http://:5088 to access.

Off - Turn off dashy completely.
File: File Manager only.
All: File Manager + Live Stream."), + initial_index=int(self._params.get("dp_dev_dashy") or 0), + callback=lambda val: self._params.put("dp_dev_dashy", val), + options=[tr("Off"), tr("File"), tr("All")], + ) + + self._toggles["dp_dev_delay_loggerd"] = spin_button_item( + title=lambda: tr("Delay Starting Loggerd for:"), + description=lambda: tr("Delays the startup of loggerd and its related processes when the device goes on-road.
This prevents the initial moments of a drive from being recorded, protecting location privacy at the start of a trip."), + initial_value=int(self._params.get("dp_dev_delay_loggerd") or 0), + callback=lambda val: self._params.put("dp_dev_delay_loggerd", val), + min_val=0, + max_val=300, + step=5, + suffix=tr(" secs"), + special_value_text=tr("Off"), + ) + + self._toggles["dp_dev_disable_connect"] = toggle_item( + title=lambda: tr("Disable Comma Connect"), + description=lambda: tr("Disable Comma connect service if you do not wish to upload / being tracked by the service."), + initial_state=self._params.get_bool("dp_dev_disable_connect"), + callback=lambda val: self._params.put_bool("dp_dev_disable_connect", val), + ) + def _reset_dp_conf(self): def reset_dp_conf(result: int): # Check engaged again in case it changed while the dialog was open @@ -85,3 +257,7 @@ class DragonpilotLayout(Widget): def _render(self, rect): self._scroller.render(rect) + + def _on_dp_lat_lca_speed_change(self, val): + self._params.put("dp_lat_lca_speed", int(val)) + self._toggles['dp_lat_lca_auto_sec'].action_item.set_enabled(val > 0) diff --git a/launch_chffrplus.sh b/launch_chffrplus.sh index d4689aa..8bf8d7b 100755 --- a/launch_chffrplus.sh +++ b/launch_chffrplus.sh @@ -27,6 +27,33 @@ function agnos_init { fi } +set_tici_hw() { + if grep -q "tici" /sys/firmware/devicetree/base/model 2>/dev/null; then + echo "Querying panda MCU type..." + MCU_OUTPUT=$(python -c "from panda_tici import Panda; p = Panda(cli=False); print(p.get_mcu_type()); p.close()" 2>/dev/null) + + if [[ "$MCU_OUTPUT" == *"McuType.F4"* ]]; then + echo "TICI (DOS) detected" + elif [[ "$MCU_OUTPUT" == *"McuType.H7"* ]]; then + echo "TICI (TRES) detected" + export TICI_TRES=1 + else + echo "TICI (UNKNOWN) detected" + fi + export TICI_HW=1 + fi +} + +set_lite_hw() { + output=$(i2cget -y 0 0x10 0x00 2>/dev/null) + + if [ -z "$output" ]; then + echo "Lite HW" + export LITE=1 + export DISABLE_DRIVER=1 + fi +} + function launch { # Remove orphaned git lock if it exists on boot [ -f "$DIR/.git/index.lock" ] && rm -f $DIR/.git/index.lock @@ -71,6 +98,8 @@ function launch { # hardware specific init if [ -f /AGNOS ]; then + set_tici_hw + set_lite_hw agnos_init fi diff --git a/opendbc_repo/opendbc/car/car_helpers.py b/opendbc_repo/opendbc/car/car_helpers.py index eaa6a2f..ebe4541 100644 --- a/opendbc_repo/opendbc/car/car_helpers.py +++ b/opendbc_repo/opendbc/car/car_helpers.py @@ -82,8 +82,8 @@ def can_fingerprint(can_recv: CanRecvCallable) -> tuple[str | None, dict[int, di # **** for use live only **** def fingerprint(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, num_pandas: int, - cached_params: CarParamsT | None) -> tuple[str | None, dict, str, list[CarParams.CarFw], CarParams.FingerprintSource, bool]: - fixed_fingerprint = os.environ.get('FINGERPRINT', "") + cached_params: CarParamsT | None, dp_fingerprint: str = "") -> tuple[str | None, dict, str, list[CarParams.CarFw], CarParams.FingerprintSource, bool]: + fixed_fingerprint = os.environ.get('FINGERPRINT', dp_fingerprint) skip_fw_query = os.environ.get('SKIP_FW_QUERY', False) disable_fw_cache = os.environ.get('DISABLE_FW_CACHE', False) ecu_rx_addrs = set() @@ -149,8 +149,8 @@ def fingerprint(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_mu def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, alpha_long_allowed: bool, - is_release: bool, num_pandas: int = 1, dp_params: int = 0, cached_params: CarParamsT | None = None): - candidate, fingerprints, vin, car_fw, source, exact_match = fingerprint(can_recv, can_send, set_obd_multiplexing, num_pandas, cached_params) + is_release: bool, num_pandas: int = 1, dp_params: int = 0, cached_params: CarParamsT | None = None, dp_fingerprint: str = ""): + candidate, fingerprints, vin, car_fw, source, exact_match = fingerprint(can_recv, can_send, set_obd_multiplexing, num_pandas, cached_params, dp_fingerprint=dp_fingerprint) if candidate is None: carlog.error({"event": "car doesn't match any fingerprints", "fingerprints": repr(fingerprints)}) diff --git a/opendbc_repo/opendbc/car/nissan/carcontroller.py b/opendbc_repo/opendbc/car/nissan/carcontroller.py index 16f990a..d488cd9 100644 --- a/opendbc_repo/opendbc/car/nissan/carcontroller.py +++ b/opendbc_repo/opendbc/car/nissan/carcontroller.py @@ -61,7 +61,7 @@ class CarController(CarControllerBase): # Below are the HUD messages. We copy the stock message and modify if self.CP.carFingerprint != CAR.NISSAN_ALTIMA: if self.frame % 2 == 0: - can_sends.append(nissancan.create_lkas_hud_msg(self.packer, CS.lkas_hud_msg, CC.enabled, hud_control.leftLaneVisible, hud_control.rightLaneVisible, + can_sends.append(nissancan.create_lkas_hud_msg(self.packer, CS.lkas_hud_msg, CC.latActive, hud_control.leftLaneVisible, hud_control.rightLaneVisible, hud_control.leftLaneDepart, hud_control.rightLaneDepart)) if self.frame % 50 == 0: diff --git a/opendbc_repo/opendbc/car/radar_interface.py b/opendbc_repo/opendbc/car/radar_interface.py new file mode 100644 index 0000000..656fa4e --- /dev/null +++ b/opendbc_repo/opendbc/car/radar_interface.py @@ -0,0 +1,162 @@ +""" +Copyright (c) 2025, Rick Lan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, and/or sublicense, +for non-commercial purposes only, subject to the following conditions: + +- The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. +- Commercial use (e.g. use in a product, service, or activity intended to + generate revenue) is prohibited without explicit written permission from + the copyright holder. + +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. +""" + +from opendbc.car.interfaces import RadarInterfaceBase +from opendbc.can.parser import CANParser +from opendbc.car.structs import RadarData +from typing import List, Tuple + +# car head to radar +DREL_OFFSET = -1.52 + + +# typically max lane width is 3.7m +LANE_WIDTH = 3.8 +LANE_WIDTH_HALF = LANE_WIDTH/2 + +LANE_CENTER_MIN_LAT = 0. +LANE_CENTER_MAX_LAT = LANE_WIDTH_HALF +LANE_CENTER_MIN_DIST = 5. + +LANE_SIDE_MIN_LAT = LANE_WIDTH_HALF +LANE_SIDE_MAX_LAT = LANE_WIDTH_HALF + LANE_WIDTH +LANE_SIDE_MIN_DIST = 10. + + +# lat distance, typically max lane width is 3.7m +MAX_LAT_DIST = 6. + +# objects to ignore thats really close to the vehicle (after DREL_OFFSET applied) +MIN_DIST = 5. + +# ignore oncoming objects +IGNORE_OBJ_STATE = 2 + +# ignore objects that we haven't seen for 5 secs +NOT_SEEN_INIT = 33 + +def _create_radar_parser(): + return CANParser('u_radar', [("Status", float('nan')), ("ObjectData", float('nan'))], 1) + +class RadarInterface(RadarInterfaceBase): + def __init__(self, CP): + super().__init__(CP) + + self.updated_messages = set() + + self.rcp = _create_radar_parser() + + self._pts_cache = dict() + self._pts_not_seen = {key: 0 for key in range(255)} + self._should_clear_cache = False + + # called by card.py, 100hz + def update(self, can_strings): + vls = self.rcp.update(can_strings) + self.updated_messages.update(vls) + + if 1546 in self.updated_messages: + self._should_clear_cache = True + + if 1547 in self.updated_messages: + all_objects = zip( + self.rcp.vl_all['ObjectData']['ID'], + self.rcp.vl_all['ObjectData']['DistLong'], + self.rcp.vl_all['ObjectData']['DistLat'], + self.rcp.vl_all['ObjectData']['VRelLong'], + self.rcp.vl_all['ObjectData']['VRelLat'], + self.rcp.vl_all['ObjectData']['DynProp'], + self.rcp.vl_all['ObjectData']['Class'], + self.rcp.vl_all['ObjectData']['RCS'], + ) + + # clean cache when we see a 0x60a then a 0x60b + if self._should_clear_cache: + self._pts_cache.clear() + self._should_clear_cache = False + + for track_id, dist_long, dist_lat, vrel_long, vrel_lat, dyn_prop, obj_class, rcs in all_objects: + + d_rel = dist_long + DREL_OFFSET + y_rel = -dist_lat + + should_ignore = False + + # ignore point (obj_class = 0) + if not should_ignore and int(obj_class) == 0: + should_ignore = True + + # ignore oncoming objects + # @todo remove this because it's always 0 ? + if not should_ignore and int(dyn_prop) == IGNORE_OBJ_STATE: + should_ignore = True + + # far away lane object, ignore + if not should_ignore and abs(y_rel) > LANE_SIDE_MAX_LAT: + should_ignore = True + + # close object, ignore, use vision + if not should_ignore and LANE_CENTER_MIN_LAT > abs(y_rel) > LANE_CENTER_MAX_LAT and d_rel < LANE_CENTER_MIN_DIST: + should_ignore = True + + # close object, ignore, use vision + if not should_ignore and LANE_SIDE_MIN_LAT > abs(y_rel) > LANE_SIDE_MAX_LAT and d_rel < LANE_SIDE_MIN_DIST: + should_ignore = True + + if not should_ignore and track_id not in self._pts_cache: + self._pts_cache[track_id] = RadarData.RadarPoint() + self._pts_cache[track_id].trackId = track_id + + if should_ignore: + self._pts_not_seen[track_id] = -1 + else: + self._pts_not_seen[track_id] = NOT_SEEN_INIT + + # init cache + if track_id not in self._pts_cache: + self._pts_cache[track_id] = RadarData.RadarPoint() + self._pts_cache[track_id].trackId = track_id + + # add/update to cache + self._pts_cache[track_id].dRel = d_rel + self._pts_cache[track_id].yRel = y_rel + self._pts_cache[track_id].vRel = float(vrel_long) + self._pts_cache[track_id].yvRel = float('nan') + self._pts_cache[track_id].aRel = float('nan') + self._pts_cache[track_id].measured = True + + self.updated_messages.clear() + + # publish to cereal + if self.frame % 3 == 0: + keys_to_remove = [key for key in self.pts if key not in self._pts_cache] + for key in keys_to_remove: + self._pts_not_seen[key] -= 1 + if self._pts_not_seen[key] <= 0: + del self.pts[key] + + self.pts.update(self._pts_cache) + + ret = RadarData() + if not self.rcp.can_valid: + ret.errors.canError = True + + ret.points = list(self.pts.values()) + return ret + + return None diff --git a/opendbc_repo/opendbc/car/structs.py b/opendbc_repo/opendbc/car/structs.py index 0959d5c..7389cec 100644 --- a/opendbc_repo/opendbc/car/structs.py +++ b/opendbc_repo/opendbc/car/structs.py @@ -20,4 +20,6 @@ CarControlT = capnp.lib.capnp._StructModule CarParamsT = capnp.lib.capnp._StructModule class DPFlags: + LateralALKA = 1 + ExtRadar = 2 pass diff --git a/opendbc_repo/opendbc/car/toyota/carcontroller.py b/opendbc_repo/opendbc/car/toyota/carcontroller.py index 8cfdaa0..ebeba7c 100644 --- a/opendbc_repo/opendbc/car/toyota/carcontroller.py +++ b/opendbc_repo/opendbc/car/toyota/carcontroller.py @@ -291,7 +291,7 @@ class CarController(CarControllerBase): if self.frame % 20 == 0 or send_ui: can_sends.append(toyotacan.create_ui_command(self.packer, steer_alert, pcm_cancel_cmd, hud_control.leftLaneVisible, hud_control.rightLaneVisible, hud_control.leftLaneDepart, - hud_control.rightLaneDepart, CC.enabled, CS.lkas_hud)) + hud_control.rightLaneDepart, lat_active, CS.lkas_hud)) if (self.frame % 100 == 0 or send_ui) and (self.CP.enableDsu or self.CP.flags & ToyotaFlags.DISABLE_RADAR.value): can_sends.append(toyotacan.create_fcw_command(self.packer, fcw_alert)) diff --git a/opendbc_repo/opendbc/car/toyota/values.py b/opendbc_repo/opendbc/car/toyota/values.py index fa6f96e..20115a9 100644 --- a/opendbc_repo/opendbc/car/toyota/values.py +++ b/opendbc_repo/opendbc/car/toyota/values.py @@ -77,6 +77,8 @@ class ToyotaFlags(IntFlag): RAISED_ACCEL_LIMIT = 1024 SECOC = 2048 + ALKA = 2 ** 12 + def dbc_dict(pt, radar): return {Bus.pt: pt, Bus.radar: radar} diff --git a/opendbc_repo/opendbc/dbc/u_radar.dbc b/opendbc_repo/opendbc/dbc/u_radar.dbc new file mode 100644 index 0000000..21f690b --- /dev/null +++ b/opendbc_repo/opendbc/dbc/u_radar.dbc @@ -0,0 +1,85 @@ + + +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: RADAR + +BO_ 513 RadarState: 8 XXX + SG_ NVMReadStatus : 6|1@0+ (1,0) [0|1] "" XXX + SG_ NVMWriteStatus : 7|1@0+ (1,0) [0|1] "" XXX + SG_ MaxDistanceCfg : 15|10@0+ (2,0) [0|2046] "m" XXX + SG_ RadarPowerCfg : 25|3@0+ (1,0) [0|7] "" XXX + SG_ SensorID : 34|3@0+ (1,0) [0|7] "" XXX + SG_ SortIndex : 38|3@0+ (1,0) [0|7] "" XXX + SG_ CtrlRelayCfg : 41|1@0+ (1,0) [0|1] "" XXX + SG_ OutputTypeCfg : 43|2@0+ (1,0) [0|3] "" XXX + SG_ QualityInfoCfg : 44|1@0+ (1,0) [0|1] "" XXX + SG_ ExtInfoCfg : 45|1@0+ (1,0) [0|1] "" XXX + SG_ CANBaudRate : 55|3@0+ (1,0) [0|7] "" XXX + SG_ InterfaceType : 57|2@0+ (1,0) [0|3] "" XXX + SG_ RCSThreshold : 58|3@1+ (1,0) [0|7] "" XXX + SG_ CalibrationEnabled : 63|2@0+ (1,0) [0|3] "" XXX + +VAL_ 513 NVMReadStatus 0 "Failed" 1 "Successful"; +VAL_ 513 NVMWriteStatus 0 "Failed" 1 "Successful"; +VAL_ 513 RadarPowerCfg 0 "Standard" 1 "-3dB Gain" 2 "-6dB Gain" 3 "-9dB Gain"; +VAL_ 513 SortIndex 0 "No Sorting" 1 "Sort By Range" 2 "Sort By RCS"; +VAL_ 513 CtrlRelayCfg 0 "Off" 1 "On"; +VAL_ 513 OutputTypeCfg 0 "None" 1 "Objects" 2 "Clusters"; +VAL_ 513 QualityInfoCfg 0 "Off" 1 "On"; +VAL_ 513 ExtInfoCfg 0 "Off" 1 "On"; +VAL_ 513 CANBaudRate 0 "500K" 1 "250K" 2 "1M"; +VAL_ 513 RCSThreshold 0 "Standard" 1 "High Sensitivity"; +VAL_ 513 CalibrationEnabled 1 "Enabled" 2 "Initial Recovery"; + +BO_ 1546 Status: 8 RADAR + SG_ NoOfObjects : 7|8@0+ (1,0) [0|255] "" XXX + SG_ MeasCount : 15|16@0+ (1,0) [0|65535] "" XXX + SG_ InterfaceVersion : 31|4@0+ (1,0) [0|15] "" XXX + +BO_ 1547 ObjectData: 8 RADAR + SG_ ID : 7|8@0+ (1,0) [0|255] "" XXX + SG_ DistLong : 15|13@0+ (0.2,-500) [-500|1138.2] "m" XXX + SG_ DistLat : 18|11@0+ (0.2,-204.6) [-204.6|204.8] "m" XXX + SG_ VRelLong : 39|10@0+ (0.25,-128) [-128|127.75] "m/s" XXX + SG_ VRelLat : 45|9@0+ (0.25,-64) [-64|63.75] "m/s" XXX + SG_ DynProp : 50|3@0+ (1,0) [0|7] "" XXX + SG_ Class : 52|2@0+ (1,0) [0|3] "" XXX + SG_ RCS : 63|8@0+ (0.5,-64) [-64|63.75] "dBm2" XXX + +CM_ BO_ 1547 "Object detection and tracking information"; +VAL_ 1547 DynProp 0 "moving" 1 "stationary" 2 "oncoming" 3 "crossing_left" 4 "crossing_right" 5 "unknown" 6 "stopped"; +VAL_ 1547 Class 0 "point" 1 "vehicle"; diff --git a/opendbc_repo/opendbc/safety/__init__.py b/opendbc_repo/opendbc/safety/__init__.py index 5d4c246..b89673c 100644 --- a/opendbc_repo/opendbc/safety/__init__.py +++ b/opendbc_repo/opendbc/safety/__init__.py @@ -8,3 +8,5 @@ class ALTERNATIVE_EXPERIENCE: DISABLE_STOCK_AEB = 2 RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX = 8 ALLOW_AEB = 16 + + ALKA = 2 ** 10 diff --git a/opendbc_repo/opendbc/safety/can.h b/opendbc_repo/opendbc/safety/can.h index 205ee3a..4eb443c 100644 --- a/opendbc_repo/opendbc/safety/can.h +++ b/opendbc_repo/opendbc/safety/can.h @@ -3,7 +3,12 @@ static const unsigned char dlc_to_len[] = {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U}; #define CANPACKET_HEAD_SIZE 6U // non-data portion of CANPacket_t -#define CANPACKET_DATA_SIZE_MAX 64U + +#ifdef CANFD + #define CANPACKET_DATA_SIZE_MAX 64U +#else + #define CANPACKET_DATA_SIZE_MAX 8U +#endif // bump this when changing the CAN packet #define CAN_PACKET_VERSION 4 diff --git a/opendbc_repo/opendbc/safety/declarations.h b/opendbc_repo/opendbc/safety/declarations.h index 31918c0..6704c09 100644 --- a/opendbc_repo/opendbc/safety/declarations.h +++ b/opendbc_repo/opendbc/safety/declarations.h @@ -230,7 +230,9 @@ void update_sample(struct sample_t *sample, int sample_new); bool get_longitudinal_allowed(void); int ROUND(float val); void gen_crc_lookup_table_8(uint8_t poly, uint8_t crc_lut[]); +#ifdef CANFD void gen_crc_lookup_table_16(uint16_t poly, uint16_t crc_lut[]); +#endif bool steer_torque_cmd_checks(int desired_torque, int steer_req, const TorqueSteeringLimits limits); bool steer_angle_cmd_checks(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits); bool steer_angle_cmd_checks_vm(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits, @@ -301,6 +303,8 @@ extern struct sample_t angle_meas; // last 6 steer angles/curvatures // This flag allows AEB to be commanded from openpilot. #define ALT_EXP_ALLOW_AEB 16 +#define ALT_EXP_ALKA 1024 + extern int alternative_experience; // time since safety mode has been changed diff --git a/opendbc_repo/opendbc/safety/lateral.h b/opendbc_repo/opendbc/safety/lateral.h index cfe15af..c5f2f61 100644 --- a/opendbc_repo/opendbc/safety/lateral.h +++ b/opendbc_repo/opendbc/safety/lateral.h @@ -60,8 +60,9 @@ static bool rt_torque_rate_limit_check(int val, int val_last, const int MAX_RT_D bool steer_torque_cmd_checks(int desired_torque, int steer_req, const TorqueSteeringLimits limits) { bool violation = false; uint32_t ts = microsecond_timer_get(); + bool alka = (alternative_experience & ALT_EXP_ALKA) != 0; - if (controls_allowed) { + if (controls_allowed || alka) { // Some safety models support variable torque limit based on vehicle speed int max_torque = limits.max_torque; if (limits.dynamic_max_torque) { @@ -96,7 +97,7 @@ bool steer_torque_cmd_checks(int desired_torque, int steer_req, const TorqueStee } // no torque if controls is not allowed - if (!controls_allowed && (desired_torque != 0)) { + if (!(controls_allowed || alka) && (desired_torque != 0)) { violation = true; } @@ -138,7 +139,7 @@ bool steer_torque_cmd_checks(int desired_torque, int steer_req, const TorqueStee } // reset to 0 if either controls is not allowed or there's a violation - if (violation || !controls_allowed) { + if (violation || !(controls_allowed || alka)) { valid_steer_req_count = 0; invalid_steer_req_count = 0; desired_torque_last = 0; @@ -176,7 +177,9 @@ static bool rt_angle_rate_limit_check(AngleSteeringLimits limits) { bool steer_angle_cmd_checks(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits) { bool violation = false; - if (controls_allowed && steer_control_enabled) { + bool alka = (alternative_experience & ALT_EXP_ALKA) != 0; + + if ((controls_allowed || alka) && steer_control_enabled) { // convert floating point angle rate limits to integers in the scale of the desired angle on CAN, // add 1 to not false trigger the violation. also fudge the speed by 1 m/s so rate limits are // always slightly above openpilot's in case we read an updated speed in between angle commands @@ -262,12 +265,12 @@ bool steer_angle_cmd_checks(int desired_angle, bool steer_control_enabled, const } // No angle control allowed when controls are not allowed - if (!controls_allowed) { + if (!(controls_allowed || alka)) { violation |= steer_control_enabled; } // reset to current angle if either controls is not allowed or there's a violation - if (violation || !controls_allowed) { + if (violation || !(controls_allowed || alka)) { if (limits.inactive_angle_is_zero) { desired_angle_last = 0; } else { @@ -304,7 +307,10 @@ bool steer_angle_cmd_checks_vm(int desired_angle, bool steer_control_enabled, co bool violation = false; - if (controls_allowed && steer_control_enabled) { + bool alka = (alternative_experience & ALT_EXP_ALKA) != 0; + + + if ((controls_allowed || alka) && steer_control_enabled) { // *** ISO lateral jerk limit *** // calculate maximum angle rate per second const float max_curvature_rate_sec = MAX_LATERAL_JERK / (fudged_speed * fudged_speed); @@ -340,12 +346,12 @@ bool steer_angle_cmd_checks_vm(int desired_angle, bool steer_control_enabled, co } // No angle control allowed when controls are not allowed - if (!controls_allowed) { + if (!(controls_allowed || alka)) { violation |= steer_control_enabled; } // reset to current angle if either controls is not allowed or there's a violation - if (violation || !controls_allowed) { + if (violation || !(controls_allowed || alka)) { desired_angle_last = SAFETY_CLAMP(angle_meas.values[0], -limits.max_angle, limits.max_angle); } diff --git a/opendbc_repo/opendbc/safety/modes/honda.h b/opendbc_repo/opendbc/safety/modes/honda.h index 9f49ef7..23451c2 100644 --- a/opendbc_repo/opendbc/safety/modes/honda.h +++ b/opendbc_repo/opendbc/safety/modes/honda.h @@ -238,7 +238,8 @@ static bool honda_tx_hook(const CANPacket_t *msg) { // STEER: safety check if ((msg->addr == 0xE4U) || (msg->addr == 0x194U)) { - if (!controls_allowed) { + bool alka = (alternative_experience & ALT_EXP_ALKA) != 0; + if (!(controls_allowed || alka)) { bool steer_applied = msg->data[0] | msg->data[1]; if (steer_applied) { tx = false; diff --git a/opendbc_repo/opendbc/safety/modes/hyundai_common.h b/opendbc_repo/opendbc/safety/modes/hyundai_common.h index bb2b951..945edaa 100644 --- a/opendbc_repo/opendbc/safety/modes/hyundai_common.h +++ b/opendbc_repo/opendbc/safety/modes/hyundai_common.h @@ -112,6 +112,7 @@ void hyundai_common_cruise_buttons_check(const int cruise_button, const bool mai } } +#ifdef CANFD uint32_t hyundai_common_canfd_compute_checksum(const CANPacket_t *msg) { int len = GET_LEN(msg); uint32_t address = msg->addr; @@ -136,3 +137,4 @@ uint32_t hyundai_common_canfd_compute_checksum(const CANPacket_t *msg) { return crc; } +#endif diff --git a/opendbc_repo/opendbc/safety/safety.h b/opendbc_repo/opendbc/safety/safety.h index d784bf5..ef1f605 100644 --- a/opendbc_repo/opendbc/safety/safety.h +++ b/opendbc_repo/opendbc/safety/safety.h @@ -25,7 +25,10 @@ #include "opendbc/safety/modes/elm327.h" #include "opendbc/safety/modes/body.h" #include "opendbc/safety/modes/psa.h" + +#ifdef CANFD #include "opendbc/safety/modes/hyundai_canfd.h" +#endif uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len) { uint32_t ret = 0U; @@ -292,6 +295,7 @@ void gen_crc_lookup_table_8(uint8_t poly, uint8_t crc_lut[]) { } } +#ifdef CANFD void gen_crc_lookup_table_16(uint16_t poly, uint16_t crc_lut[]) { for (uint16_t i = 0; i < 256U; i++) { uint16_t crc = i << 8U; @@ -305,6 +309,7 @@ void gen_crc_lookup_table_16(uint16_t poly, uint16_t crc_lut[]) { crc_lut[i] = crc; } } +#endif // 1Hz safety function called by main. Now just a check for lagging safety messages void safety_tick(const safety_config *cfg) { @@ -401,7 +406,9 @@ int set_safety_hooks(uint16_t mode, uint16_t param) { {SAFETY_FORD, &ford_hooks}, {SAFETY_RIVIAN, &rivian_hooks}, {SAFETY_TESLA, &tesla_hooks}, +#ifdef CANFD {SAFETY_HYUNDAI_CANFD, &hyundai_canfd_hooks}, +#endif #ifdef ALLOW_DEBUG {SAFETY_PSA, &psa_hooks}, {SAFETY_SUBARU_PREGLOBAL, &subaru_preglobal_hooks}, diff --git a/opendbc_repo/opendbc/safety/tests/libsafety/SConscript b/opendbc_repo/opendbc/safety/tests/libsafety/SConscript index 7cab268..d88318b 100644 --- a/opendbc_repo/opendbc/safety/tests/libsafety/SConscript +++ b/opendbc_repo/opendbc/safety/tests/libsafety/SConscript @@ -29,6 +29,7 @@ env = Environment( '-fprofile-arcs', '-ftest-coverage', '-DALLOW_DEBUG', + '-DCANFD', ], LINKFLAGS=[ '-fprofile-arcs', diff --git a/opendbc_repo/opendbc/safety/tests/misra/test_misra.sh b/opendbc_repo/opendbc/safety/tests/misra/test_misra.sh index a94d37d..b77aadd 100755 --- a/opendbc_repo/opendbc/safety/tests/misra/test_misra.sh +++ b/opendbc_repo/opendbc/safety/tests/misra/test_misra.sh @@ -55,8 +55,8 @@ cppcheck() { OPTS=" --enable=all --enable=unusedFunction --addon=misra" -printf "\n${GREEN}** Safety **${NC}\n" -cppcheck $OPTS $BASEDIR/opendbc/safety/tests/misra/main.c +printf "\n${GREEN}** Safety with CANFD **${NC}\n" +cppcheck $OPTS -DCANFD $BASEDIR/opendbc/safety/tests/misra/main.c printf "\n${GREEN}Success!${NC} took $SECONDS seconds\n" diff --git a/panda_tici/.gitignore b/panda_tici/.gitignore new file mode 100644 index 0000000..5557594 --- /dev/null +++ b/panda_tici/.gitignore @@ -0,0 +1,38 @@ +.venv +*.tmp +*.pyc +.*.swp +.*.swo +*.o +*.so +*.os +*.d +*.dump +a.out +*~ +.#* +dist/ +build/ +pandacan.egg-info/ +obj/ +examples/output.csv +.DS_Store +.vscode* +nosetests.xml +.mypy_cache/ +.sconsign.dblite +uv.lock +compile_commands.json + +# CTU info files generated by Cppcheck +*.*.ctu-info + +# safety coverage-related files +*.gcda +*.gcno +tests/safety/coverage-out +tests/safety/coverage.info + +*.profraw +*.profdata +mull.yml diff --git a/panda_tici/Dockerfile b/panda_tici/Dockerfile new file mode 100644 index 0000000..5bf8cac --- /dev/null +++ b/panda_tici/Dockerfile @@ -0,0 +1,21 @@ +FROM ubuntu:24.04 + +ENV PYTHONUNBUFFERED=1 +ENV PYTHONPATH=/tmp/pythonpath + +# deps install +COPY pyproject.toml __init__.py setup.sh /tmp/ +COPY python/__init__.py /tmp/python/ +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends sudo && /tmp/setup.sh + +COPY pyproject.toml __init__.py $PYTHONPATH/panda_tici/ +COPY python/__init__.py $PYTHONPATH/panda_tici/python/ +RUN pip3 install --break-system-packages --no-cache-dir $PYTHONPATH/panda_tici/[dev] + +RUN git config --global --add safe.directory $PYTHONPATH/panda_tici + +# for Jenkins +COPY README.md panda_tici.tar.* /tmp/ +RUN mkdir -p /tmp/pythonpath/panda_tici && \ + tar -xvf /tmp/panda_tici.tar.gz -C /tmp/pythonpath/panda_tici/ || true diff --git a/panda_tici/Jenkinsfile b/panda_tici/Jenkinsfile new file mode 100644 index 0000000..123f50c --- /dev/null +++ b/panda_tici/Jenkinsfile @@ -0,0 +1,152 @@ +def docker_run(String step_label, int timeout_mins, String cmd) { + timeout(time: timeout_mins, unit: 'MINUTES') { + sh script: "docker run --rm --privileged \ + --env PYTHONWARNINGS=error \ + --volume /dev/bus/usb:/dev/bus/usb \ + --volume /var/run/dbus:/var/run/dbus \ + --workdir /tmp/pythonpath/panda_tici \ + --net host \ + ${env.DOCKER_IMAGE_TAG} \ + bash -c 'scons -j8 && ${cmd}'", \ + label: step_label + } +} + + +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' + +set -e + + +source ~/.bash_profile +if [ -f /etc/profile ]; then + source /etc/profile +fi + +export CI=1 +export TEST_DIR=${env.TEST_DIR} +export SOURCE_DIR=${env.SOURCE_DIR} +export GIT_BRANCH=${env.GIT_BRANCH} +export GIT_COMMIT=${env.GIT_COMMIT} +export PYTHONPATH=${env.TEST_DIR}/../ +export PYTHONWARNINGS=error +ln -sf /data/openpilot/opendbc_repo/opendbc /data/opendbc + +cd ${env.TEST_DIR} || true +${cmd} +exit 0 + +END""" + + sh script: ssh_cmd, label: step_label + } +} + +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"),) + steps.each { item -> + phone(device_ip, item[0], item[1]) + } + } + } +} + + + +pipeline { + agent any + environment { + CI = "1" + PYTHONWARNINGS= "error" + DOCKER_IMAGE_TAG = "panda:build-${env.GIT_COMMIT}" + + TEST_DIR = "/data/panda_tici" + SOURCE_DIR = "/data/panda_tici_source/" + } + options { + timeout(time: 3, unit: 'HOURS') + disableConcurrentBuilds(abortPrevious: env.BRANCH_NAME != 'master') + } + + stages { + stage ('Acquire resource locks') { + options { + lock(resource: "pandas") + } + stages { + stage('Build Docker Image') { + steps { + timeout(time: 20, unit: 'MINUTES') { + script { + sh 'git archive -v -o panda.tar.gz --format=tar.gz HEAD' + dockerImage = docker.build("${env.DOCKER_IMAGE_TAG}") + } + } + } + } + stage('jungle tests') { + steps { + script { + retry (3) { + docker_run("reset hardware", 3, "python3 ./tests/hitl/reset_jungles.py") + } + } + } + } + + stage('parallel tests') { + parallel { + stage('test cuatro') { + agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } + steps { + phone_steps("panda-cuatro", [ + ["build", "scons -j4"], + ["flash", "cd scripts/ && ./reflash_internal_panda.py"], + ["flash jungle", "cd board/jungle && ./flash.py --all"], + ["test", "cd tests/hitl && HW_TYPES=10 pytest -n0 --durations=0 2*.py [5-9]*.py"], + ]) + } + } + + stage('test tres') { + agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } + steps { + phone_steps("panda-tres", [ + ["build", "scons -j4"], + ["flash", "cd scripts/ && ./reflash_internal_panda.py"], + ["flash jungle", "cd board/jungle && ./flash.py --all"], + ["test", "cd tests/hitl && HW_TYPES=9 pytest -n0 --durations=0 2*.py [5-9]*.py"], + ]) + } + } + + stage('test dos') { + agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } + steps { + phone_steps("panda-dos", [ + ["build", "scons -j4"], + ["flash", "cd scripts/ && ./reflash_internal_panda.py"], + ["flash jungle", "cd board/jungle && ./flash.py --all"], + ["test", "cd tests/hitl && HW_TYPES=6 pytest -n0 --durations=0 [2-9]*.py -k 'not test_send_recv'"], + ]) + } + } + + stage('bootkick tests') { + steps { + script { + docker_run("test", 10, "pytest -n0 ./tests/som/test_bootkick.py") + } + } + } + } + } + } + } + } +} diff --git a/panda_tici/LICENSE b/panda_tici/LICENSE new file mode 100644 index 0000000..8a6c697 --- /dev/null +++ b/panda_tici/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2016, Comma.ai, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/panda_tici/README.md b/panda_tici/README.md new file mode 100644 index 0000000..6561d51 --- /dev/null +++ b/panda_tici/README.md @@ -0,0 +1,91 @@ +# Welcome to panda + +panda speaks CAN and CAN FD, and it runs on [STM32F413](https://www.st.com/resource/en/reference_manual/rm0430-stm32f413423-advanced-armbased-32bit-mcus-stmicroelectronics.pdf) and [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 +├── drivers # Drivers (not needed for use with Python) +├── 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 safety firmware 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_tici/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_tici/blob/master/tests/misra/coverage_table). +* Compiler options are relatively strict: the flags `-Wall -Wextra -Wstrict-prototypes -Werror` are enforced. +* The [safety logic](https://github.com/commaai/panda_tici/tree/master/opendbc/safety) is tested and verified by [unit tests](https://github.com/commaai/panda_tici/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 USB and SPI + +The above tests are themselves tested by: +* a [mutation test](tests/misra/test_mutation.py) on the MISRA coverage + +In addition, we run the [ruff linter](https://github.com/astral-sh/ruff) and [mypy](https://mypy-lang.org/) on panda's Python library. + +## Usage + +```bash +git clone https://github.com/commaai/panda_tici.git +cd panda + +# setup your environment +./setup.sh + +# build fw + run the tests +./test.sh +``` + +See [the Panda class](https://github.com/commaai/panda_tici/blob/master/python/__init__.py) for how to interact with the panda. + +For example, to receive CAN messages: +``` python +>>> from panda_tici 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_tici/tree/master/drivers/linux) for Linux, such as +``` bash +sudo tee /etc/udev/rules.d/11-panda.rules < +#include + +// ******************** Prototypes ******************** +typedef enum { + BOOT_STANDBY, + BOOT_BOOTKICK, + BOOT_RESET, +} BootState; + +typedef void (*board_init)(void); +typedef void (*board_init_bootloader)(void); +typedef void (*board_enable_can_transceiver)(uint8_t transceiver, bool enabled); +typedef void (*board_set_can_mode)(uint8_t mode); +typedef bool (*board_check_ignition)(void); +typedef uint32_t (*board_read_voltage_mV)(void); +typedef uint32_t (*board_read_current_mA)(void); +typedef void (*board_set_ir_power)(uint8_t percentage); +typedef void (*board_set_fan_enabled)(bool enabled); +typedef void (*board_set_siren)(bool enabled); +typedef void (*board_set_bootkick)(BootState state); +typedef bool (*board_read_som_gpio)(void); +typedef void (*board_set_amp_enabled)(bool enabled); + +struct board { + harness_configuration *harness_config; + GPIO_TypeDef * const led_GPIO[3]; + const uint8_t led_pin[3]; + const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM + const bool has_spi; + const bool has_canfd; + const uint16_t fan_max_rpm; + const uint16_t avdd_mV; + const bool fan_stall_recovery; + const uint8_t fan_enable_cooldown_time; + const uint8_t fan_max_pwm; + board_init init; + board_init_bootloader init_bootloader; + board_enable_can_transceiver enable_can_transceiver; + board_set_can_mode set_can_mode; + board_check_ignition check_ignition; + board_read_voltage_mV read_voltage_mV; + board_read_current_mA read_current_mA; + board_set_ir_power set_ir_power; + board_set_fan_enabled set_fan_enabled; + board_set_siren set_siren; + board_set_bootkick set_bootkick; + board_read_som_gpio read_som_gpio; + board_set_amp_enabled set_amp_enabled; +}; + +// ******************* Definitions ******************** +// These should match the enums in cereal/log.capnp and __init__.py +#define HW_TYPE_UNKNOWN 0U +//#define HW_TYPE_WHITE_PANDA 1U +//#define HW_TYPE_GREY_PANDA 2U +//#define HW_TYPE_BLACK_PANDA 3U +//#define HW_TYPE_PEDAL 4U +//#define HW_TYPE_UNO 5U +#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 + +// USB power modes (from cereal.log.health) +#define USB_POWER_NONE 0U +#define USB_POWER_CLIENT 1U +#define USB_POWER_CDP 2U +#define USB_POWER_DCP 3U + +// CAN modes +#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; diff --git a/panda_tici/board/boards/cuatro.h b/panda_tici/board/boards/cuatro.h new file mode 100644 index 0000000..53b671e --- /dev/null +++ b/panda_tici/board/boards/cuatro.h @@ -0,0 +1,143 @@ +#pragma once + +#include "board_declarations.h" + +// ////////////////////////// // +// Cuatro (STM32H7) + Harness // +// ////////////////////////// // + +static void cuatro_enable_can_transceiver(uint8_t transceiver, bool enabled) { + switch (transceiver) { + case 1U: + set_gpio_output(GPIOB, 7, !enabled); + break; + case 2U: + set_gpio_output(GPIOB, 10, !enabled); + break; + case 3U: + set_gpio_output(GPIOD, 8, !enabled); + break; + case 4U: + set_gpio_output(GPIOB, 11, !enabled); + break; + default: + break; + } +} + +static uint32_t cuatro_read_voltage_mV(void) { + return adc_get_mV(8) * 11U; +} + +static uint32_t cuatro_read_current_mA(void) { + return adc_get_mV(3) * 2U; +} + +static void cuatro_set_fan_enabled(bool enabled) { + set_gpio_output(GPIOD, 3, !enabled); +} + +static void cuatro_set_bootkick(BootState state) { + set_gpio_output(GPIOA, 0, state != BOOT_BOOTKICK); + // TODO: confirm we need this + //set_gpio_output(GPIOC, 12, state != BOOT_RESET); +} + +static void cuatro_set_amp_enabled(bool enabled){ + set_gpio_output(GPIOA, 5, enabled); + set_gpio_output(GPIOB, 0, enabled); +} + +static void cuatro_init(void) { + common_init_gpio(); + + // 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 + + // Power readout + set_gpio_mode(GPIOC, 5, MODE_ANALOG); + set_gpio_mode(GPIOA, 6, MODE_ANALOG); + + // CAN transceiver enables + set_gpio_pullup(GPIOB, 7, PULL_NONE); + set_gpio_mode(GPIOB, 7, MODE_OUTPUT); + set_gpio_pullup(GPIOD, 8, PULL_NONE); + set_gpio_mode(GPIOD, 8, MODE_OUTPUT); + + // FDCAN3, different pins on this package than the rest of the reds + set_gpio_pullup(GPIOD, 12, PULL_NONE); + set_gpio_alternate(GPIOD, 12, GPIO_AF5_FDCAN3); + set_gpio_pullup(GPIOD, 13, PULL_NONE); + set_gpio_alternate(GPIOD, 13, GPIO_AF5_FDCAN3); + + // C2: SOM GPIO used as input (fan control at boot) + set_gpio_mode(GPIOC, 2, MODE_INPUT); + set_gpio_pullup(GPIOC, 2, PULL_DOWN); + + // SOM bootkick + reset lines + cuatro_set_bootkick(BOOT_BOOTKICK); + + // SOM debugging UART + gpio_uart7_init(); + uart_init(&uart_ring_som_debug, 115200); + + // fan setup + set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3); + register_set_bits(&(GPIOC->OTYPER), GPIO_OTYPER_OT8); // open drain + + // Clock source + clock_source_init(true); + + // Sound codec + cuatro_set_amp_enabled(false); + set_gpio_alternate(GPIOA, 2, GPIO_AF8_SAI4); // SAI4_SCK_B + set_gpio_alternate(GPIOC, 0, GPIO_AF8_SAI4); // SAI4_FS_B + set_gpio_alternate(GPIOD, 11, GPIO_AF10_SAI4); // SAI4_SD_A + set_gpio_alternate(GPIOE, 3, GPIO_AF8_SAI4); // SAI4_SD_B + set_gpio_alternate(GPIOE, 4, GPIO_AF3_DFSDM1); // DFSDM1_DATIN3 + set_gpio_alternate(GPIOE, 9, GPIO_AF3_DFSDM1); // DFSDM1_CKOUT + set_gpio_alternate(GPIOE, 6, GPIO_AF10_SAI4); // SAI4_MCLK_B + sound_init(); +} + +static harness_configuration cuatro_harness_config = { + .has_harness = true, + .GPIO_SBU1 = GPIOC, + .GPIO_SBU2 = GPIOA, + .GPIO_relay_SBU1 = GPIOA, + .GPIO_relay_SBU2 = GPIOA, + .pin_SBU1 = 4, + .pin_SBU2 = 1, + .pin_relay_SBU1 = 9, + .pin_relay_SBU2 = 3, + .adc_channel_SBU1 = 4, // ADC12_INP4 + .adc_channel_SBU2 = 17 // ADC1_INP17 +}; + +board board_cuatro = { + .harness_config = &cuatro_harness_config, + .has_spi = true, + .has_canfd = true, + .fan_max_rpm = 12500U, + .fan_max_pwm = 99U, // it can go up to 14k RPM, but 99% -> 100% is very non-linear + .avdd_mV = 1800U, + .fan_stall_recovery = false, + .fan_enable_cooldown_time = 3U, + .init = cuatro_init, + .init_bootloader = unused_init_bootloader, + .enable_can_transceiver = cuatro_enable_can_transceiver, + .led_GPIO = {GPIOC, GPIOC, GPIOC}, + .led_pin = {6, 7, 9}, + .led_pwm_channels = {1, 2, 4}, + .set_can_mode = tres_set_can_mode, + .check_ignition = red_check_ignition, + .read_voltage_mV = cuatro_read_voltage_mV, + .read_current_mA = cuatro_read_current_mA, + .set_fan_enabled = cuatro_set_fan_enabled, + .set_ir_power = unused_set_ir_power, + .set_siren = unused_set_siren, + .set_bootkick = cuatro_set_bootkick, + .read_som_gpio = tres_read_som_gpio, + .set_amp_enabled = cuatro_set_amp_enabled +}; diff --git a/panda_tici/board/boards/dos.h b/panda_tici/board/boards/dos.h new file mode 100644 index 0000000..5751f5d --- /dev/null +++ b/panda_tici/board/boards/dos.h @@ -0,0 +1,158 @@ +#pragma once + +#include "board_declarations.h" + +// /////////////////////// // +// Dos (STM32F4) + Harness // +// /////////////////////// // + +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)) { + // B12,B13: disable OBD mode + set_gpio_mode(GPIOB, 12, MODE_INPUT); + set_gpio_mode(GPIOB, 13, MODE_INPUT); + + // B5,B6: normal CAN2 mode + set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2); + dos_enable_can_transceiver(2U, true); + } else { + // B5,B6: disable normal CAN2 mode + set_gpio_mode(GPIOB, 5, MODE_INPUT); + set_gpio_mode(GPIOB, 6, MODE_INPUT); + + // B12,B13: OBD mode + 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 bool dos_check_ignition(void){ + // ignition is checked through harness + return harness_check_ignition(); +} + +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(12) * 11U; +} + +static bool dos_read_som_gpio (void){ + return (get_gpio_input(GPIOC, 2) != 0); +} + +static void dos_init(void) { + common_init_gpio(); + + // A8,A15: normal CAN3 mode + set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3); + set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3); + + // C8: FAN PWM aka TIM3_CH3 + set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3); + + // C2: SOM GPIO used as input (fan control at boot) + set_gpio_mode(GPIOC, 2, MODE_INPUT); + set_gpio_pullup(GPIOC, 2, PULL_DOWN); + + // Initialize IR PWM and set to 0% + set_gpio_alternate(GPIOB, 7, GPIO_AF2_TIM4); + pwm_init(TIM4, 2); + dos_set_ir_power(0U); + + // Bootkick + dos_set_bootkick(true); + + // Init clock source (camera strobe) using PWM + clock_source_init(false); +} + +static harness_configuration dos_harness_config = { + .has_harness = true, + .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_channel_SBU1 = 10, + .adc_channel_SBU2 = 13 +}; + +board board_dos = { + .harness_config = &dos_harness_config, +#ifdef ENABLE_SPI + .has_spi = true, +#else + .has_spi = false, +#endif + .has_canfd = false, + .fan_max_rpm = 6500U, + .fan_max_pwm = 100U, + .avdd_mV = 3300U, + .fan_stall_recovery = true, + .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, + .check_ignition = dos_check_ignition, + .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 +}; diff --git a/panda_tici/board/boards/red.h b/panda_tici/board/boards/red.h new file mode 100644 index 0000000..9871f95 --- /dev/null +++ b/panda_tici/board/boards/red.h @@ -0,0 +1,144 @@ +#pragma once + +#include "board_declarations.h" + +// ///////////////////////////// // +// Red Panda (STM32H7) + Harness // +// ///////////////////////////// // + +static void red_enable_can_transceiver(uint8_t transceiver, bool enabled) { + switch (transceiver) { + case 1U: + set_gpio_output(GPIOG, 11, !enabled); + break; + case 2U: + set_gpio_output(GPIOB, 3, !enabled); + break; + case 3U: + set_gpio_output(GPIOD, 7, !enabled); + break; + case 4U: + set_gpio_output(GPIOB, 4, !enabled); + break; + default: + break; + } +} + +static void red_set_can_mode(uint8_t mode) { + red_enable_can_transceiver(2U, false); + red_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)) { + // B12,B13: disable normal mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_mode(GPIOB, 12, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_mode(GPIOB, 13, MODE_ANALOG); + + // B5,B6: FDCAN2 mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_alternate(GPIOB, 5, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_FDCAN2); + red_enable_can_transceiver(2U, true); + } else { + // B5,B6: disable normal mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_mode(GPIOB, 5, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_mode(GPIOB, 6, MODE_ANALOG); + // B12,B13: FDCAN2 mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_alternate(GPIOB, 12, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_alternate(GPIOB, 13, GPIO_AF9_FDCAN2); + red_enable_can_transceiver(4U, true); + } + break; + default: + break; + } +} + +static bool red_check_ignition(void) { + // ignition is checked through harness + return harness_check_ignition(); +} + +static uint32_t red_read_voltage_mV(void){ + return adc_get_mV(2) * 11U; // TODO: is this correct? +} + +static void red_init(void) { + common_init_gpio(); + + // G11,B3,D7,B4: transceiver enable + set_gpio_pullup(GPIOG, 11, PULL_NONE); + set_gpio_mode(GPIOG, 11, MODE_OUTPUT); + + set_gpio_pullup(GPIOB, 3, PULL_NONE); + set_gpio_mode(GPIOB, 3, MODE_OUTPUT); + + set_gpio_pullup(GPIOD, 7, PULL_NONE); + set_gpio_mode(GPIOD, 7, MODE_OUTPUT); + + set_gpio_pullup(GPIOB, 4, PULL_NONE); + set_gpio_mode(GPIOB, 4, MODE_OUTPUT); + + //B1: 5VOUT_S + set_gpio_pullup(GPIOB, 1, PULL_NONE); + set_gpio_mode(GPIOB, 1, MODE_ANALOG); + + // B14: usb load switch, enabled by pull resistor on board, obsolete for red panda + set_gpio_output_type(GPIOB, 14, OUTPUT_TYPE_OPEN_DRAIN); + set_gpio_pullup(GPIOB, 14, PULL_UP); + set_gpio_mode(GPIOB, 14, MODE_OUTPUT); + set_gpio_output(GPIOB, 14, 1); +} + +static harness_configuration red_harness_config = { + .has_harness = true, + .GPIO_SBU1 = GPIOC, + .GPIO_SBU2 = GPIOA, + .GPIO_relay_SBU1 = GPIOC, + .GPIO_relay_SBU2 = GPIOC, + .pin_SBU1 = 4, + .pin_SBU2 = 1, + .pin_relay_SBU1 = 10, + .pin_relay_SBU2 = 11, + .adc_channel_SBU1 = 4, //ADC12_INP4 + .adc_channel_SBU2 = 17 //ADC1_INP17 +}; + +board board_red = { + .set_bootkick = unused_set_bootkick, + .harness_config = &red_harness_config, + .has_spi = false, + .has_canfd = true, + .fan_max_rpm = 0U, + .fan_max_pwm = 100U, + .avdd_mV = 3300U, + .fan_stall_recovery = false, + .fan_enable_cooldown_time = 0U, + .init = red_init, + .init_bootloader = unused_init_bootloader, + .enable_can_transceiver = red_enable_can_transceiver, + .led_GPIO = {GPIOE, GPIOE, GPIOE}, + .led_pin = {4, 3, 2}, + .set_can_mode = red_set_can_mode, + .check_ignition = red_check_ignition, + .read_voltage_mV = red_read_voltage_mV, + .read_current_mA = unused_read_current, + .set_fan_enabled = unused_set_fan_enabled, + .set_ir_power = unused_set_ir_power, + .set_siren = unused_set_siren, + .read_som_gpio = unused_read_som_gpio, + .set_amp_enabled = unused_set_amp_enabled +}; diff --git a/panda_tici/board/boards/tres.h b/panda_tici/board/boards/tres.h new file mode 100644 index 0000000..ab91951 --- /dev/null +++ b/panda_tici/board/boards/tres.h @@ -0,0 +1,180 @@ +#pragma once + +#include "board_declarations.h" + +// /////////////////////////// +// Tres (STM32H7) + Harness // +// /////////////////////////// + +static bool tres_ir_enabled; +static bool tres_fan_enabled; +static void tres_update_fan_ir_power(void) { + set_gpio_output(GPIOD, 3, tres_ir_enabled || tres_fan_enabled); +} + +static void tres_set_ir_power(uint8_t percentage){ + tres_ir_enabled = (percentage > 0U); + tres_update_fan_ir_power(); + pwm_set(TIM3, 4, percentage); +} + +static void tres_set_bootkick(BootState state) { + set_gpio_output(GPIOA, 0, state != BOOT_BOOTKICK); + set_gpio_output(GPIOC, 12, state != BOOT_RESET); +} + +static void tres_set_fan_enabled(bool enabled) { + // NOTE: fan controller reset doesn't work on a tres if IR is enabled + tres_fan_enabled = enabled; + tres_update_fan_ir_power(); +} + +static void tres_enable_can_transceiver(uint8_t transceiver, bool enabled) { + static bool can0_enabled = false; + static bool can2_enabled = false; + + switch (transceiver) { + case 1U: + can0_enabled = enabled; + break; + case 2U: + set_gpio_output(GPIOB, 10, !enabled); + break; + case 3U: + can2_enabled = enabled; + break; + case 4U: + set_gpio_output(GPIOB, 11, !enabled); + break; + default: + break; + } + + // CAN0 and 2 are tied, so enable both if either is enabled + set_gpio_output(GPIOG, 11, !(can0_enabled || can2_enabled)); + set_gpio_output(GPIOD, 7, !(can0_enabled || can2_enabled)); +} + +static void tres_set_can_mode(uint8_t mode) { + current_board->enable_can_transceiver(2U, false); + current_board->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)) { + // B12,B13: disable normal mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_mode(GPIOB, 12, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_mode(GPIOB, 13, MODE_ANALOG); + + // B5,B6: FDCAN2 mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_alternate(GPIOB, 5, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_FDCAN2); + current_board->enable_can_transceiver(2U, true); + } else { + // B5,B6: disable normal mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_mode(GPIOB, 5, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_mode(GPIOB, 6, MODE_ANALOG); + // B12,B13: FDCAN2 mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_alternate(GPIOB, 12, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_alternate(GPIOB, 13, GPIO_AF9_FDCAN2); + current_board->enable_can_transceiver(4U, true); + } + break; + default: + break; + } +} + +static bool tres_read_som_gpio (void) { + return (get_gpio_input(GPIOC, 2) != 0); +} + +static void tres_init(void) { + // Enable USB 3.3V LDO for USB block + register_set_bits(&(PWR->CR3), PWR_CR3_USBREGEN); + register_set_bits(&(PWR->CR3), PWR_CR3_USB33DEN); + while ((PWR->CR3 & PWR_CR3_USB33RDY) == 0U); + + common_init_gpio(); + + // C2: SOM GPIO used as input (fan control at boot) + set_gpio_mode(GPIOC, 2, MODE_INPUT); + set_gpio_pullup(GPIOC, 2, PULL_DOWN); + + // SOM bootkick + reset lines + // WARNING: make sure output state is set before configuring as output + tres_set_bootkick(BOOT_BOOTKICK); + set_gpio_mode(GPIOC, 12, MODE_OUTPUT); + + // SOM debugging UART + gpio_uart7_init(); + uart_init(&uart_ring_som_debug, 115200); + + // fan setup + set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3); + + // Initialize IR PWM and set to 0% + set_gpio_alternate(GPIOC, 9, GPIO_AF2_TIM3); + pwm_init(TIM3, 4); + tres_set_ir_power(0U); + + // Fake siren + set_gpio_alternate(GPIOC, 10, GPIO_AF4_I2C5); + set_gpio_alternate(GPIOC, 11, GPIO_AF4_I2C5); + register_set_bits(&(GPIOC->OTYPER), GPIO_OTYPER_OT10 | GPIO_OTYPER_OT11); // open drain + + // Clock source + clock_source_init(false); +} + +static harness_configuration tres_harness_config = { + .has_harness = true, + .GPIO_SBU1 = GPIOC, + .GPIO_SBU2 = GPIOA, + .GPIO_relay_SBU1 = GPIOA, + .GPIO_relay_SBU2 = GPIOA, + .pin_SBU1 = 4, + .pin_SBU2 = 1, + .pin_relay_SBU1 = 8, + .pin_relay_SBU2 = 3, + .adc_channel_SBU1 = 4, // ADC12_INP4 + .adc_channel_SBU2 = 17 // ADC1_INP17 +}; + +board board_tres = { + .harness_config = &tres_harness_config, + .has_spi = true, + .has_canfd = true, + .fan_max_rpm = 6600U, + .fan_max_pwm = 100U, + .avdd_mV = 1800U, + .fan_stall_recovery = false, + .fan_enable_cooldown_time = 3U, + .init = tres_init, + .init_bootloader = unused_init_bootloader, + .enable_can_transceiver = tres_enable_can_transceiver, + .led_GPIO = {GPIOE, GPIOE, GPIOE}, + .led_pin = {4, 3, 2}, + .set_can_mode = tres_set_can_mode, + .check_ignition = red_check_ignition, + .read_voltage_mV = red_read_voltage_mV, + .read_current_mA = unused_read_current, + .set_fan_enabled = tres_set_fan_enabled, + .set_ir_power = tres_set_ir_power, + .set_siren = fake_siren_set, + .set_bootkick = tres_set_bootkick, + .read_som_gpio = tres_read_som_gpio, + .set_amp_enabled = unused_set_amp_enabled +}; diff --git a/panda_tici/board/boards/unused_funcs.h b/panda_tici/board/boards/unused_funcs.h new file mode 100644 index 0000000..588cf63 --- /dev/null +++ b/panda_tici/board/boards/unused_funcs.h @@ -0,0 +1,32 @@ +#pragma once + +void unused_init_bootloader(void) { +} + +void unused_set_ir_power(uint8_t percentage) { + UNUSED(percentage); +} + +void unused_set_fan_enabled(bool enabled) { + UNUSED(enabled); +} + +void unused_set_siren(bool enabled) { + UNUSED(enabled); +} + +uint32_t unused_read_current(void) { + return 0U; +} + +void unused_set_bootkick(BootState state) { + UNUSED(state); +} + +bool unused_read_som_gpio(void) { + return false; +} + +void unused_set_amp_enabled(bool enabled) { + UNUSED(enabled); +} diff --git a/panda_tici/board/bootstub.c b/panda_tici/board/bootstub.c new file mode 100644 index 0000000..5e05fa6 --- /dev/null +++ b/panda_tici/board/bootstub.c @@ -0,0 +1,90 @@ +#define BOOTSTUB + +#define VERS_TAG 0x53524556 +#define MIN_VERSION 2 + +// ********************* Includes ********************* +#include "config.h" + +#include "drivers/led.h" +#include "drivers/pwm.h" +#include "drivers/usb.h" + +#include "early_init.h" +#include "provision.h" + +#include "crypto/rsa.h" +#include "crypto/sha.h" + +#include "obj/cert.h" +#include "obj/gitversion.h" +#include "flasher.h" + +// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck +void __initialize_hardware_early(void) { + early_initialization(); +} + +void fail(void) { + soft_flasher_start(); +} + +// know where to sig check +extern void *_app_start[]; + +// FIXME: sometimes your panda will fail flashing and will quickly blink a single Green LED +// BOUNTY: $200 coupon on shop.comma.ai or $100 check. + +int main(void) { + // Init interrupt table + init_interrupts(true); + + disable_interrupts(); + clock_init(); + detect_board_type(); + +#ifdef PANDA_JUNGLE + current_board->set_panda_power(true); +#endif + + if (enter_bootloader_mode == ENTER_SOFTLOADER_MAGIC) { + enter_bootloader_mode = 0; + soft_flasher_start(); + } + + // validate length + int len = (int)_app_start[0]; + if ((len < 8) || (len > (0x1000000 - 0x4000 - 4 - RSANUMBYTES))) goto fail; + + // compute SHA hash + uint8_t digest[SHA_DIGEST_SIZE]; + SHA_hash(&_app_start[1], len-4, digest); + + // verify version, last bytes in the signed area + uint32_t vers[2] = {0}; + memcpy(&vers, ((void*)&_app_start[0]) + len - sizeof(vers), sizeof(vers)); + if (vers[0] != VERS_TAG || vers[1] < MIN_VERSION) { + goto fail; + } + + // verify RSA signature + if (RSA_verify(&release_rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) { + goto good; + } + + // allow debug if built from source +#ifdef ALLOW_DEBUG + if (RSA_verify(&debug_rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) { + goto good; + } +#endif + +// here is a failure +fail: + fail(); + return 0; +good: + // jump to flash + ((void(*)(void)) _app_start[1])(); + return 0; +} diff --git a/panda_tici/board/bootstub_declarations.h b/panda_tici/board/bootstub_declarations.h new file mode 100644 index 0000000..5cdec50 --- /dev/null +++ b/panda_tici/board/bootstub_declarations.h @@ -0,0 +1,18 @@ +// ******************** 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 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; +void uart_init(uart_ring *q, int baud) { UNUSED(q); UNUSED(baud); } + +// ********************* Globals ********************** +uint8_t hw_type = 0; +board *current_board; diff --git a/panda_tici/board/can.h b/panda_tici/board/can.h new file mode 100644 index 0000000..d6e360a --- /dev/null +++ b/panda_tici/board/can.h @@ -0,0 +1,5 @@ +#pragma once + +#define PANDA_CAN_CNT 3U + +#include "opendbc/safety/can.h" diff --git a/panda_tici/board/can_comms.h b/panda_tici/board/can_comms.h new file mode 100644 index 0000000..99ee968 --- /dev/null +++ b/panda_tici/board/can_comms.h @@ -0,0 +1,122 @@ +/* + CAN transactions to and from the host come in the form of + a certain number of CANPacket_t. The transaction is split + into multiple transfers or chunks. + + * 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. + * both functions maintain an overflow buffer for a partial CANPacket_t that + spans multiple transfers/chunks. + * the overflow buffers are reset by a dedicated control transfer handler, + which is sent by the host on each start of a connection. +*/ + +typedef struct { + uint32_t ptr; + uint32_t tail_size; + uint8_t data[72]; +} asm_buffer; + +static asm_buffer can_read_buffer = {.ptr = 0U, .tail_size = 0U}; + +int comms_can_read(uint8_t *data, uint32_t max_len) { + uint32_t pos = 0U; + + // Send tail of previous message if it is in buffer + if (can_read_buffer.ptr > 0U) { + uint32_t overflow_len = MIN(max_len - pos, can_read_buffer.ptr); + (void)memcpy(&data[pos], can_read_buffer.data, overflow_len); + pos += overflow_len; + (void)memcpy(can_read_buffer.data, &can_read_buffer.data[overflow_len], can_read_buffer.ptr - overflow_len); + can_read_buffer.ptr -= overflow_len; + } + + if (can_read_buffer.ptr == 0U) { + // Fill rest of buffer with new data + CANPacket_t can_packet; + while ((pos < max_len) && can_pop(&can_rx_q, &can_packet)) { + uint32_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[can_packet.data_len_code]; + if ((pos + pckt_len) <= max_len) { + (void)memcpy(&data[pos], (uint8_t*)&can_packet, pckt_len); + pos += pckt_len; + } else { + (void)memcpy(&data[pos], (uint8_t*)&can_packet, max_len - pos); + can_read_buffer.ptr += pckt_len - (max_len - pos); + // cppcheck-suppress objectIndex + (void)memcpy(can_read_buffer.data, &((uint8_t*)&can_packet)[(max_len - pos)], can_read_buffer.ptr); + pos = max_len; + } + } + } + + return pos; +} + +static asm_buffer can_write_buffer = {.ptr = 0U, .tail_size = 0U}; + +// send on CAN +void comms_can_write(const uint8_t *data, uint32_t len) { + uint32_t pos = 0U; + + // Assembling can message with data from buffer + if (can_write_buffer.ptr != 0U) { + if (can_write_buffer.tail_size <= (len - pos)) { + // we have enough data to complete the buffer + CANPacket_t to_push = {0}; + (void)memcpy(&can_write_buffer.data[can_write_buffer.ptr], &data[pos], can_write_buffer.tail_size); + can_write_buffer.ptr += can_write_buffer.tail_size; + pos += can_write_buffer.tail_size; + + // send out + (void)memcpy((uint8_t*)&to_push, can_write_buffer.data, can_write_buffer.ptr); + can_send(&to_push, to_push.bus, false); + + // reset overflow buffer + can_write_buffer.ptr = 0U; + can_write_buffer.tail_size = 0U; + } else { + // maybe next time + uint32_t data_size = len - pos; + (void) memcpy(&can_write_buffer.data[can_write_buffer.ptr], &data[pos], data_size); + can_write_buffer.tail_size -= data_size; + can_write_buffer.ptr += data_size; + pos += data_size; + } + } + + // rest of the message + while (pos < len) { + uint32_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[(data[pos] >> 4U)]; + if ((pos + pckt_len) <= len) { + CANPacket_t to_push = {0}; + (void)memcpy((uint8_t*)&to_push, &data[pos], pckt_len); + can_send(&to_push, to_push.bus, false); + pos += pckt_len; + } else { + (void)memcpy(can_write_buffer.data, &data[pos], len - pos); + can_write_buffer.ptr = len - pos; + can_write_buffer.tail_size = pckt_len - can_write_buffer.ptr; + pos += can_write_buffer.ptr; + } + } + + refresh_can_tx_slots_available(); +} + +void comms_can_reset(void) { + can_write_buffer.ptr = 0U; + can_write_buffer.tail_size = 0U; + can_read_buffer.ptr = 0U; + can_read_buffer.tail_size = 0U; +} + +// TODO: make this more general! +void refresh_can_tx_slots_available(void) { + if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_USB_BULK_TRANSFER)) { + can_tx_comms_resume_usb(); + } + if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_SPI_BULK_TRANSFER)) { + can_tx_comms_resume_spi(); + } +} diff --git a/panda_tici/board/can_declarations.h b/panda_tici/board/can_declarations.h new file mode 100644 index 0000000..878d9c7 --- /dev/null +++ b/panda_tici/board/can_declarations.h @@ -0,0 +1,29 @@ +#pragma once + +// bump this when changing the CAN packet +#define CAN_PACKET_VERSION 4 + +#define CANPACKET_HEAD_SIZE 6U + +#if !defined(STM32F4) + #define CANFD + #define CANPACKET_DATA_SIZE_MAX 64U +#else + #define CANPACKET_DATA_SIZE_MAX 8U +#endif + +typedef struct { + unsigned char fd : 1; + unsigned char bus : 3; + unsigned char data_len_code : 4; // lookup length with dlc_to_len + unsigned char rejected : 1; + unsigned char returned : 1; + unsigned char extended : 1; + unsigned int addr : 29; + unsigned char checksum; + unsigned char data[CANPACKET_DATA_SIZE_MAX]; +} __attribute__((packed, aligned(4))) CANPacket_t; + +#define GET_BUS(msg) ((msg)->bus) +#define GET_LEN(msg) (dlc_to_len[(msg)->data_len_code]) +#define GET_ADDR(msg) ((msg)->addr) diff --git a/panda_tici/board/comms_definitions.h b/panda_tici/board/comms_definitions.h new file mode 100644 index 0000000..18a6d2f --- /dev/null +++ b/panda_tici/board/comms_definitions.h @@ -0,0 +1,12 @@ +typedef struct { + uint8_t request; + uint16_t param1; + uint16_t param2; + uint16_t length; +} __attribute__((packed)) ControlPacket_t; + +int comms_control_handler(ControlPacket_t *req, uint8_t *resp); +void comms_endpoint2_write(const uint8_t *data, uint32_t len); +void comms_can_write(const uint8_t *data, uint32_t len); +int comms_can_read(uint8_t *data, uint32_t max_len); +void comms_can_reset(void); diff --git a/panda_tici/board/config.h b/panda_tici/board/config.h new file mode 100644 index 0000000..6fb95ad --- /dev/null +++ b/panda_tici/board/config.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +//#define DEBUG +//#define DEBUG_UART +//#define DEBUG_USB +//#define DEBUG_SPI +//#define DEBUG_FAULTS +//#define DEBUG_COMMS +//#define DEBUG_FAN + +#define CAN_INIT_TIMEOUT_MS 500U +#define USBPACKET_MAX_SIZE 0x40U +#define MAX_CAN_MSGS_PER_USB_BULK_TRANSFER 51U +#define MAX_CAN_MSGS_PER_SPI_BULK_TRANSFER 170U + +// USB definitions +#define USB_VID 0x3801U + +#ifdef PANDA_JUNGLE + #ifdef BOOTSTUB + #define USB_PID 0xDDEFU + #else + #define USB_PID 0xDDCFU + #endif +#else + #ifdef BOOTSTUB + #define USB_PID 0xDDEEU + #else + #define USB_PID 0xDDCCU + #endif +#endif + +// platform includes +#ifdef STM32H7 + #include "stm32h7/stm32h7_config.h" +#elif defined(STM32F4) + #include "stm32f4/stm32f4_config.h" +#else + // TODO: uncomment this, cppcheck complains + // building for tests + //#include "fake_stm.h" +#endif diff --git a/panda_tici/board/crc.h b/panda_tici/board/crc.h new file mode 100644 index 0000000..a3caf78 --- /dev/null +++ b/panda_tici/board/crc.h @@ -0,0 +1,21 @@ +#pragma once + +#if defined(ENABLE_SPI) || defined(BOOTSTUB) +uint8_t crc_checksum(const uint8_t *dat, int len, const uint8_t poly) { + uint8_t crc = 0xFFU; + int i; + int j; + for (i = len - 1; i >= 0; i--) { + crc ^= dat[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x80U) != 0U) { + crc = (uint8_t)((crc << 1) ^ poly); + } + else { + crc <<= 1; + } + } + } + return crc; +} +#endif diff --git a/panda_tici/board/critical.h b/panda_tici/board/critical.h new file mode 100644 index 0000000..ae2d5c0 --- /dev/null +++ b/panda_tici/board/critical.h @@ -0,0 +1,16 @@ +#include "critical_declarations.h" + +// ********************* Critical section helpers ********************* +uint8_t global_critical_depth = 0U; + +static volatile bool interrupts_enabled = false; + +void enable_interrupts(void) { + interrupts_enabled = true; + __enable_irq(); +} + +void disable_interrupts(void) { + interrupts_enabled = false; + __disable_irq(); +} diff --git a/panda_tici/board/critical_declarations.h b/panda_tici/board/critical_declarations.h new file mode 100644 index 0000000..42211d4 --- /dev/null +++ b/panda_tici/board/critical_declarations.h @@ -0,0 +1,17 @@ +#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(); \ + } diff --git a/panda_tici/board/debug/README.md b/panda_tici/board/debug/README.md new file mode 100644 index 0000000..d475ce9 --- /dev/null +++ b/panda_tici/board/debug/README.md @@ -0,0 +1,26 @@ +# In-circuit debugging using openocd and gdb + +## Hardware +Connect an ST-Link V2 programmer to the SWD pins on the board. The pins that need to be connected are: +- GND +- VTref +- SWDIO +- SWCLK +- NRST + +Make sure you're using a genuine one for boards that do not have a 3.3V panda power rail. For example, the tres runs at 1.8V, which is not supported by the clones. + +## Openocd +Install openocd. For Ubuntu 24.04, the one in the package manager works fine: `sudo apt install openocd`. + +To run, use `./debug_f4.sh (TODO)` or `./debug_h7.sh` depending on the panda. + +## GDB +You need `gdb-multiarch`. + +Once openocd is running, you can connect from gdb as follows: +``` +$ gdb-multiarch +(gdb) target ext :3333 +``` +To reset and break, use `monitor reset halt`. diff --git a/panda_tici/board/debug/debug_h7.sh b/panda_tici/board/debug/debug_h7.sh new file mode 100755 index 0000000..126a9c3 --- /dev/null +++ b/panda_tici/board/debug/debug_h7.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e + +sudo openocd -f "interface/stlink.cfg" -c "transport select hla_swd" -f "target/stm32h7x.cfg" -c "init" diff --git a/panda_tici/board/debug/dfu_util_f4.sh b/panda_tici/board/debug/dfu_util_f4.sh new file mode 100755 index 0000000..8685c50 --- /dev/null +++ b/panda_tici/board/debug/dfu_util_f4.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -e + +DFU_UTIL="dfu-util" + +scons -u -j$(nproc) + +PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)" || true +sleep 1 +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D obj/panda.bin.signed +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.panda.bin diff --git a/panda_tici/board/debug/dfu_util_h7.sh b/panda_tici/board/debug/dfu_util_h7.sh new file mode 100755 index 0000000..c39a24e --- /dev/null +++ b/panda_tici/board/debug/dfu_util_h7.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -e + +DFU_UTIL="dfu-util" + +scons -u -j$(nproc) + +PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)" || true +sleep 1 +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08020000 -D obj/panda_h7.bin.signed +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.panda_h7.bin diff --git a/panda_tici/board/debug/gdb.sh b/panda_tici/board/debug/gdb.sh new file mode 100755 index 0000000..aa695d6 --- /dev/null +++ b/panda_tici/board/debug/gdb.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +gdb-multiarch --eval-command="target extended-remote localhost:3333" diff --git a/panda_tici/board/dfu_util_f4.sh b/panda_tici/board/dfu_util_f4.sh new file mode 100755 index 0000000..8685c50 --- /dev/null +++ b/panda_tici/board/dfu_util_f4.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -e + +DFU_UTIL="dfu-util" + +scons -u -j$(nproc) + +PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)" || true +sleep 1 +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D obj/panda.bin.signed +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.panda.bin diff --git a/panda_tici/board/dfu_util_h7.sh b/panda_tici/board/dfu_util_h7.sh new file mode 100755 index 0000000..c39a24e --- /dev/null +++ b/panda_tici/board/dfu_util_h7.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -e + +DFU_UTIL="dfu-util" + +scons -u -j$(nproc) + +PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)" || true +sleep 1 +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08020000 -D obj/panda_h7.bin.signed +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.panda_h7.bin diff --git a/panda_tici/board/drivers/bootkick.h b/panda_tici/board/drivers/bootkick.h new file mode 100644 index 0000000..eab7da3 --- /dev/null +++ b/panda_tici/board/drivers/bootkick.h @@ -0,0 +1,68 @@ +#include "bootkick_declarations.h" + +bool bootkick_reset_triggered = false; + +void bootkick_tick(bool ignition, bool recent_heartbeat) { + static uint16_t bootkick_last_serial_ptr = 0; + static uint8_t waiting_to_boot_countdown = 0; + static uint8_t boot_reset_countdown = 0; + static uint8_t bootkick_harness_status_prev = HARNESS_STATUS_NC; + static bool bootkick_ign_prev = false; + static BootState boot_state = BOOT_BOOTKICK; + BootState boot_state_prev = boot_state; + const bool harness_inserted = (harness.status != bootkick_harness_status_prev) && (harness.status != HARNESS_STATUS_NC); + + if ((ignition && !bootkick_ign_prev) || harness_inserted) { + // bootkick on rising edge of ignition or harness insertion + boot_state = BOOT_BOOTKICK; + } else if (recent_heartbeat) { + // disable bootkick once openpilot is up + boot_state = BOOT_STANDBY; + } else { + + } + + /* + Ensure SOM boots in case it goes into QDL mode. Reset behavior: + * shouldn't trigger on the first boot after power-on + * only try reset once per bootkick, i.e. don't keep trying until booted + * only try once per panda boot, since openpilot will reset panda on startup + * once BOOT_RESET is triggered, it stays until countdown is finished + */ + if (!bootkick_reset_triggered && (boot_state == BOOT_BOOTKICK) && (boot_state_prev == BOOT_STANDBY)) { + waiting_to_boot_countdown = 20U; + } + if (waiting_to_boot_countdown > 0U) { + bool serial_activity = uart_ring_som_debug.w_ptr_tx != bootkick_last_serial_ptr; + if (serial_activity || current_board->read_som_gpio() || (boot_state != BOOT_BOOTKICK)) { + waiting_to_boot_countdown = 0U; + } else { + // try a reset + if (waiting_to_boot_countdown == 1U) { + boot_reset_countdown = 5U; + } + } + } + + // handle reset state + if (boot_reset_countdown > 0U) { + boot_state = BOOT_RESET; + bootkick_reset_triggered = true; + } else { + if (boot_state == BOOT_RESET) { + boot_state = BOOT_BOOTKICK; + } + } + + // update state + bootkick_ign_prev = ignition; + bootkick_harness_status_prev = harness.status; + bootkick_last_serial_ptr = uart_ring_som_debug.w_ptr_tx; + if (waiting_to_boot_countdown > 0U) { + waiting_to_boot_countdown--; + } + if (boot_reset_countdown > 0U) { + boot_reset_countdown--; + } + current_board->set_bootkick(boot_state); +} diff --git a/panda_tici/board/drivers/bootkick_declarations.h b/panda_tici/board/drivers/bootkick_declarations.h new file mode 100644 index 0000000..3b55b72 --- /dev/null +++ b/panda_tici/board/drivers/bootkick_declarations.h @@ -0,0 +1,5 @@ +#pragma once + +extern bool bootkick_reset_triggered; + +void bootkick_tick(bool ignition, bool recent_heartbeat); diff --git a/panda_tici/board/drivers/bxcan.h b/panda_tici/board/drivers/bxcan.h new file mode 100644 index 0000000..75bd05d --- /dev/null +++ b/panda_tici/board/drivers/bxcan.h @@ -0,0 +1,222 @@ +#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[CAN_ARRAY_SIZE] = {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, + (unsigned int)(can_silent) & (1U << can_number) + ); + 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; + + // can is live + pending_can_live = 1; + + // 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; +} diff --git a/panda_tici/board/drivers/bxcan_declarations.h b/panda_tici/board/drivers/bxcan_declarations.h new file mode 100644 index 0000000..c0ed577 --- /dev/null +++ b/panda_tici/board/drivers/bxcan_declarations.h @@ -0,0 +1,22 @@ +#pragma once + +// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE +// CAN2_TX, CAN2_RX0, CAN2_SCE +// CAN3_TX, CAN3_RX0, CAN3_SCE + +#define CAN_ARRAY_SIZE 3 +#define CAN_IRQS_ARRAY_SIZE 3 +extern CAN_TypeDef *cans[CAN_ARRAY_SIZE]; +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); diff --git a/panda_tici/board/drivers/can_common.h b/panda_tici/board/drivers/can_common.h new file mode 100644 index 0000000..11622e0 --- /dev/null +++ b/panda_tici/board/drivers/can_common.h @@ -0,0 +1,262 @@ +#include "can_common_declarations.h" + +uint32_t safety_tx_blocked = 0; +uint32_t safety_rx_invalid = 0; +uint32_t tx_buffer_overflow = 0; +uint32_t rx_buffer_overflow = 0; + +can_health_t can_health[PANDA_CAN_CNT] = {{0}, {0}, {0}}; + +// Ignition detected from CAN meessages +bool ignition_can = false; +uint32_t ignition_can_cnt = 0U; + +int pending_can_live = 0; +bool can_silent = true; +bool can_loopback = false; + +// ********************* instantiate queues ********************* +#define can_buffer(x, size) \ + static CANPacket_t elems_##x[size]; \ + 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 +// 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 +can_buffer(rx_q, CAN_RX_BUFFER_SIZE) +can_buffer(tx1_q, CAN_TX_BUFFER_SIZE) +can_buffer(tx2_q, CAN_TX_BUFFER_SIZE) +#endif +can_buffer(tx3_q, CAN_TX_BUFFER_SIZE) + +// FIXME: +// cppcheck-suppress misra-c2012-9.3 +can_ring *can_queues[PANDA_CAN_CNT] = {&can_tx1_q, &can_tx2_q, &can_tx3_q}; + +// ********************* interrupt safe queue ********************* +bool can_pop(can_ring *q, CANPacket_t *elem) { + bool ret = 0; + + ENTER_CRITICAL(); + if (q->w_ptr != q->r_ptr) { + *elem = q->elems[q->r_ptr]; + if ((q->r_ptr + 1U) == q->fifo_size) { + q->r_ptr = 0; + } else { + q->r_ptr += 1U; + } + ret = 1; + } + EXIT_CRITICAL(); + + return ret; +} + +bool can_push(can_ring *q, const CANPacket_t *elem) { + bool ret = false; + uint32_t next_w_ptr; + + ENTER_CRITICAL(); + if ((q->w_ptr + 1U) == q->fifo_size) { + next_w_ptr = 0; + } else { + next_w_ptr = q->w_ptr + 1U; + } + if (next_w_ptr != q->r_ptr) { + q->elems[q->w_ptr] = *elem; + q->w_ptr = next_w_ptr; + ret = true; + } + EXIT_CRITICAL(); + if (!ret) { + #ifdef DEBUG + print("can_push to "); + if (q == &can_rx_q) { + print("can_rx_q"); + } else if (q == &can_tx1_q) { + print("can_tx1_q"); + } else if (q == &can_tx2_q) { + print("can_tx2_q"); + } else if (q == &can_tx3_q) { + print("can_tx3_q"); + } else { + print("unknown"); + } + print(" failed!\n"); + #endif + } + return ret; +} + +uint32_t can_slots_empty(const can_ring *q) { + uint32_t ret = 0; + + ENTER_CRITICAL(); + if (q->w_ptr >= q->r_ptr) { + ret = q->fifo_size - 1U - q->w_ptr + q->r_ptr; + } else { + ret = q->r_ptr - q->w_ptr - 1U; + } + EXIT_CRITICAL(); + + return ret; +} + +void can_clear(can_ring *q) { + ENTER_CRITICAL(); + q->w_ptr = 0; + q->r_ptr = 0; + EXIT_CRITICAL(); + // handle TX buffer full with zero ECUs awake on the bus + refresh_can_tx_slots_available(); +} + +// assign CAN numbering +// bus num: CAN Bus numbers in panda, sent to/from USB +// Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1) +// cans: Look up MCU can interface from bus number +// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc); +// bus_lookup: Translates from 'can number' to 'bus number'. +// can_num_lookup: Translates from 'bus number' to 'can number'. +// forwarding bus: If >= 0, forward all messages from this bus to the specified bus. + +// Helpers +// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3 +bus_config_t bus_config[PANDA_CAN_CNT] = { + { .bus_lookup = 0U, .can_num_lookup = 0U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, + { .bus_lookup = 1U, .can_num_lookup = 1U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, + { .bus_lookup = 2U, .can_num_lookup = 2U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, + // { .bus_lookup = 0xFFU, .can_num_lookup = 0xFFU, .forwarding_bus = -1, .can_speed = 333U, .can_data_speed = 333U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, +}; + +void can_init_all(void) { + for (uint8_t i=0U; i < PANDA_CAN_CNT; i++) { + if (!current_board->has_canfd) { + bus_config[i].can_data_speed = 0U; + bus_config[i].canfd_enabled = false; + } + can_clear(can_queues[i]); + (void)can_init(i); + } +} + +void can_set_orientation(bool flipped) { + bus_config[0].bus_lookup = flipped ? 2U : 0U; + bus_config[0].can_num_lookup = flipped ? 2U : 0U; + bus_config[2].bus_lookup = flipped ? 0U : 2U; + bus_config[2].can_num_lookup = flipped ? 0U : 2U; +} + +#ifdef PANDA_JUNGLE +void can_set_forwarding(uint8_t from, uint8_t to) { + bus_config[from].forwarding_bus = to; +} +#endif + +void ignition_can_hook(CANPacket_t *msg) { + if (msg->bus == 0U) { + int len = GET_LEN(msg); + + // GM exception + if ((msg->addr == 0x1F1U) && (len == 8)) { + // SystemPowerMode (2=Run, 3=Crank Request) + ignition_can = (msg->data[0] & 0x2U) != 0U; + ignition_can_cnt = 0U; + } + + // Rivian R1S/T GEN1 exception + if ((msg->addr == 0x152U) && (len == 8)) { + // 0x152 overlaps with Subaru pre-global which has this bit as the high beam + int counter = msg->data[1] & 0xFU; // max is only 14 + + static int prev_counter_rivian = -1; + if ((counter == ((prev_counter_rivian + 1) % 15)) && (prev_counter_rivian != -1)) { + // VDM_OutputSignals->VDM_EpasPowerMode + ignition_can = ((msg->data[7] >> 4U) & 0x3U) == 1U; // VDM_EpasPowerMode_Drive_On=1 + ignition_can_cnt = 0U; + } + prev_counter_rivian = counter; + } + + // Tesla Model 3/Y exception + if ((msg->addr == 0x221U) && (len == 8)) { + // 0x221 overlaps with Rivian which has random data on byte 0 + int counter = msg->data[6] >> 4; + + static int prev_counter_tesla = -1; + if ((counter == ((prev_counter_tesla + 1) % 16)) && (prev_counter_tesla != -1)) { + // VCFRONT_LVPowerState->VCFRONT_vehiclePowerState + int power_state = (msg->data[0] >> 5U) & 0x3U; + ignition_can = power_state == 0x3; // VEHICLE_POWER_STATE_DRIVE=3 + ignition_can_cnt = 0U; + } + prev_counter_tesla = counter; + } + + // Mazda exception + if ((msg->addr == 0x9EU) && (len == 8)) { + ignition_can = (msg->data[0] >> 5) == 0x6U; + ignition_can_cnt = 0U; + } + + } +} + +bool can_tx_check_min_slots_free(uint32_t min) { + return + (can_slots_empty(&can_tx1_q) >= min) && + (can_slots_empty(&can_tx2_q) >= min) && + (can_slots_empty(&can_tx3_q) >= min); +} + +uint8_t calculate_checksum(const uint8_t *dat, uint32_t len) { + uint8_t checksum = 0U; + for (uint32_t i = 0U; i < len; i++) { + checksum ^= dat[i]; + } + return checksum; +} + +void can_set_checksum(CANPacket_t *packet) { + packet->checksum = 0U; + packet->checksum = calculate_checksum((uint8_t *) packet, CANPACKET_HEAD_SIZE + GET_LEN(packet)); +} + +bool can_check_checksum(CANPacket_t *packet) { + return (calculate_checksum((uint8_t *) packet, CANPACKET_HEAD_SIZE + GET_LEN(packet)) == 0U); +} + +void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook) { + if (skip_tx_hook || safety_tx_hook(to_push) != 0) { + if (bus_number < PANDA_CAN_CNT) { + // add CAN packet to send queue + tx_buffer_overflow += can_push(can_queues[bus_number], to_push) ? 0U : 1U; + process_can(CAN_NUM_FROM_BUS_NUM(bus_number)); + } + } else { + safety_tx_blocked += 1U; + to_push->returned = 0U; + to_push->rejected = 1U; + + // data changed + can_set_checksum(to_push); + rx_buffer_overflow += can_push(&can_rx_q, to_push) ? 0U : 1U; + } +} + +bool is_speed_valid(uint32_t speed, const uint32_t *all_speeds, uint8_t len) { + bool ret = false; + for (uint8_t i = 0U; i < len; i++) { + if (all_speeds[i] == speed) { + ret = true; + } + } + return ret; +} diff --git a/panda_tici/board/drivers/can_common_declarations.h b/panda_tici/board/drivers/can_common_declarations.h new file mode 100644 index 0000000..a9410c6 --- /dev/null +++ b/panda_tici/board/drivers/can_common_declarations.h @@ -0,0 +1,81 @@ +#pragma once + +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 int pending_can_live; + +// ******************* 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); + +// assign CAN numbering +// bus num: CAN Bus numbers in panda, sent to/from USB +// Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1) +// cans: Look up MCU can interface from bus number +// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc); +// bus_lookup: Translates from 'can number' to 'bus number'. +// can_num_lookup: Translates from 'bus number' to 'can number'. +// forwarding bus: If >= 0, forward all messages from this bus to the specified bus. + +// Helpers +// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3 +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); diff --git a/panda_tici/board/drivers/clock_source.h b/panda_tici/board/drivers/clock_source.h new file mode 100644 index 0000000..87d89ad --- /dev/null +++ b/panda_tici/board/drivers/clock_source.h @@ -0,0 +1,44 @@ +#include "clock_source_declarations.h" + +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); + // Timer period + register_set(&(TIM1->ARR), (((param2 & 0x00FFU)*10U) - 1U), 0xFFFFU); +} + +void clock_source_init(bool enable_channel1) { + // Setup timer + 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->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_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); + NVIC_DisableIRQ(TIM1_CC_IRQn); + + // Set GPIO as timer channels + if (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); + + // Enable output + register_set(&(TIM1->BDTR), TIM_BDTR_MOE, 0xFFFFU); + + // Enable complementary compares + register_set_bits(&(TIM1->CCER), TIM_CCER_CC2NE | TIM_CCER_CC3NE); +} diff --git a/panda_tici/board/drivers/clock_source_declarations.h b/panda_tici/board/drivers/clock_source_declarations.h new file mode 100644 index 0000000..d95eb96 --- /dev/null +++ b/panda_tici/board/drivers/clock_source_declarations.h @@ -0,0 +1,7 @@ +#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); diff --git a/panda_tici/board/drivers/fake_siren.h b/panda_tici/board/drivers/fake_siren.h new file mode 100644 index 0000000..9468afd --- /dev/null +++ b/panda_tici/board/drivers/fake_siren.h @@ -0,0 +1,84 @@ +#include "stm32h7/lli2c.h" + +#define CODEC_I2C_ADDR 0x10 + +void fake_siren_init(void); + +void fake_siren_codec_enable(bool enabled) { + if (enabled) { + bool success = true; + success &= i2c_set_reg_bits(I2C5, CODEC_I2C_ADDR, 0x2B, (1U << 1)); // Left speaker mix from INA1 + success &= i2c_set_reg_bits(I2C5, CODEC_I2C_ADDR, 0x2C, (1U << 1)); // Right speaker mix from INA1 + success &= i2c_set_reg_mask(I2C5, CODEC_I2C_ADDR, 0x3D, 0x17, 0b11111); // Left speaker volume + success &= i2c_set_reg_mask(I2C5, CODEC_I2C_ADDR, 0x3E, 0x17, 0b11111); // Right speaker volume + success &= i2c_set_reg_mask(I2C5, CODEC_I2C_ADDR, 0x37, 0b101, 0b111); // INA gain + success &= i2c_set_reg_bits(I2C5, CODEC_I2C_ADDR, 0x4C, (1U << 7)); // Enable INA + success &= i2c_set_reg_bits(I2C5, CODEC_I2C_ADDR, 0x51, (1U << 7)); // Disable global shutdown + if (!success) { + print("Siren codec enable failed\n"); + fault_occurred(FAULT_SIREN_MALFUNCTION); + } + } else { + // Disable INA input. Make sure to retry a few times if the I2C bus is busy. + for (uint8_t i=0U; i<10U; i++) { + if (i2c_clear_reg_bits(I2C5, CODEC_I2C_ADDR, 0x4C, (1U << 7))) { + break; + } + } + } +} + + +void fake_siren_set(bool enabled) { + static bool initialized = false; + static bool fake_siren_enabled = false; + + if (!initialized) { + fake_siren_init(); + initialized = true; + } + + if (enabled != fake_siren_enabled) { + fake_siren_codec_enable(enabled); + } + + if (enabled) { + register_set_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + } else { + register_clear_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + } + fake_siren_enabled = enabled; +} + +void fake_siren_init(void) { + // 1Vpp sine wave with 1V offset + static const uint8_t fake_siren_lut[360] = { 134U, 135U, 137U, 138U, 139U, 140U, 141U, 143U, 144U, 145U, 146U, 148U, 149U, 150U, 151U, 152U, 154U, 155U, 156U, 157U, 158U, 159U, 160U, 162U, 163U, 164U, 165U, 166U, 167U, 168U, 169U, 170U, 171U, 172U, 174U, 175U, 176U, 177U, 177U, 178U, 179U, 180U, 181U, 182U, 183U, 184U, 185U, 186U, 186U, 187U, 188U, 189U, 190U, 190U, 191U, 192U, 193U, 193U, 194U, 195U, 195U, 196U, 196U, 197U, 197U, 198U, 199U, 199U, 199U, 200U, 200U, 201U, 201U, 202U, 202U, 202U, 203U, 203U, 203U, 203U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 205U, 205U, 205U, 205U, 205U, 205U, 205U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 203U, 203U, 203U, 203U, 202U, 202U, 202U, 201U, 201U, 200U, 200U, 199U, 199U, 199U, 198U, 197U, 197U, 196U, 196U, 195U, 195U, 194U, 193U, 193U, 192U, 191U, 190U, 190U, 189U, 188U, 187U, 186U, 186U, 185U, 184U, 183U, 182U, 181U, 180U, 179U, 178U, 177U, 177U, 176U, 175U, 174U, 172U, 171U, 170U, 169U, 168U, 167U, 166U, 165U, 164U, 163U, 162U, 160U, 159U, 158U, 157U, 156U, 155U, 154U, 152U, 151U, 150U, 149U, 148U, 146U, 145U, 144U, 143U, 141U, 140U, 139U, 138U, 137U, 135U, 134U, 133U, 132U, 130U, 129U, 128U, 127U, 125U, 124U, 123U, 122U, 121U, 119U, 118U, 117U, 116U, 115U, 113U, 112U, 111U, 110U, 109U, 108U, 106U, 105U, 104U, 103U, 102U, 101U, 100U, 99U, 98U, 97U, 96U, 95U, 94U, 93U, 92U, 91U, 90U, 89U, 88U, 87U, 86U, 85U, 84U, 83U, 82U, 82U, 81U, 80U, 79U, 78U, 78U, 77U, 76U, 76U, 75U, 74U, 74U, 73U, 72U, 72U, 71U, 71U, 70U, 70U, 69U, 69U, 68U, 68U, 67U, 67U, 67U, 66U, 66U, 66U, 65U, 65U, 65U, 65U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 63U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 65U, 65U, 65U, 65U, 66U, 66U, 66U, 67U, 67U, 67U, 68U, 68U, 69U, 69U, 70U, 70U, 71U, 71U, 72U, 72U, 73U, 74U, 74U, 75U, 76U, 76U, 77U, 78U, 78U, 79U, 80U, 81U, 82U, 82U, 83U, 84U, 85U, 86U, 87U, 88U, 89U, 90U, 91U, 92U, 93U, 94U, 95U, 96U, 97U, 98U, 99U, 100U, 101U, 102U, 103U, 104U, 105U, 106U, 108U, 109U, 110U, 111U, 112U, 113U, 115U, 116U, 117U, 118U, 119U, 121U, 122U, 123U, 124U, 125U, 127U, 128U, 129U, 130U, 132U, 133U }; + + // Init DAC + register_set(&DAC1->MCR, 0U, 0xFFFFFFFFU); + register_set(&DAC1->CR, DAC_CR_TEN1 | (6U << DAC_CR_TSEL1_Pos) | DAC_CR_DMAEN1, 0xFFFFFFFFU); + register_set_bits(&DAC1->CR, DAC_CR_EN1); + + // Setup DMAMUX (DAC_CH1_DMA as input) + register_set(&DMAMUX1_Channel1->CCR, 67U, DMAMUX_CxCR_DMAREQ_ID_Msk); + + // Setup DMA + register_set(&DMA1_Stream1->M0AR, (uint32_t) fake_siren_lut, 0xFFFFFFFFU); + register_set(&DMA1_Stream1->PAR, (uint32_t) &(DAC1->DHR8R1), 0xFFFFFFFFU); + DMA1_Stream1->NDTR = sizeof(fake_siren_lut); + register_set(&DMA1_Stream1->FCR, 0U, 0x00000083U); + DMA1_Stream1->CR = (0b11UL << DMA_SxCR_PL_Pos); + DMA1_Stream1->CR |= DMA_SxCR_MINC | DMA_SxCR_CIRC | (1U << DMA_SxCR_DIR_Pos); + + // Init trigger timer (around 2.5kHz) + register_set(&TIM7->PSC, 0U, 0xFFFFU); + register_set(&TIM7->ARR, 133U, 0xFFFFU); + register_set(&TIM7->CR2, (0b10U << TIM_CR2_MMS_Pos), TIM_CR2_MMS_Msk); + register_set(&TIM7->CR1, TIM_CR1_ARPE | TIM_CR1_URS, 0x088EU); + TIM7->SR = 0U; + TIM7->CR1 |= TIM_CR1_CEN; + + // Enable the I2C to the codec + i2c_init(I2C5); + fake_siren_codec_enable(false); +} diff --git a/panda_tici/board/drivers/fan.h b/panda_tici/board/drivers/fan.h new file mode 100644 index 0000000..ec0e1be --- /dev/null +++ b/panda_tici/board/drivers/fan.h @@ -0,0 +1,87 @@ +#include "fan_declarations.h" + +struct fan_state_t fan_state; + +static const uint8_t FAN_TICK_FREQ = 8U; +static const uint8_t FAN_STALL_THRESHOLD_MIN = 3U; + + +void fan_set_power(uint8_t percentage) { + fan_state.target_rpm = ((current_board->fan_max_rpm * CLAMP(percentage, 0U, 100U)) / 100U); +} + +void llfan_init(void); +void fan_init(void) { + fan_state.stall_threshold = FAN_STALL_THRESHOLD_MIN; + fan_state.cooldown_counter = current_board->fan_enable_cooldown_time * FAN_TICK_FREQ; + llfan_init(); +} + +// Call this at FAN_TICK_FREQ +void fan_tick(void) { + const float FAN_I = 6.5f; + const uint8_t FAN_STALL_THRESHOLD_MAX = 8U; + + if (current_board->fan_max_rpm > 0U) { + // Measure fan RPM + uint16_t fan_rpm_fast = fan_state.tach_counter * (60U * FAN_TICK_FREQ / 4U); // 4 interrupts per rotation + fan_state.tach_counter = 0U; + fan_state.rpm = (fan_rpm_fast + (3U * fan_state.rpm)) / 4U; + + // Stall detection + bool fan_stalled = false; + if (current_board->fan_stall_recovery) { + if (fan_state.target_rpm > 0U) { + if (fan_rpm_fast == 0U) { + fan_state.stall_counter = MIN(fan_state.stall_counter + 1U, 254U); + } else { + fan_state.stall_counter = 0U; + } + + if (fan_state.stall_counter > (fan_state.stall_threshold*FAN_TICK_FREQ)) { + fan_stalled = true; + fan_state.stall_counter = 0U; + fan_state.stall_threshold = CLAMP(fan_state.stall_threshold + 2U, FAN_STALL_THRESHOLD_MIN, FAN_STALL_THRESHOLD_MAX); + fan_state.total_stall_count += 1U; + + // datasheet gives this range as the minimum startup duty + fan_state.error_integral = CLAMP(fan_state.error_integral, 20.0f, 45.0f); + } + } else { + fan_state.stall_counter = 0U; + fan_state.stall_threshold = FAN_STALL_THRESHOLD_MIN; + } + } + + #ifdef DEBUG_FAN + puth(fan_state.target_rpm); + print(" "); puth(fan_rpm_fast); + print(" "); puth(fan_state.power); + print(" "); puth(fan_state.stall_counter); + print("\n"); + #endif + + // Cooldown counter + if (fan_state.target_rpm > 0U) { + fan_state.cooldown_counter = current_board->fan_enable_cooldown_time * FAN_TICK_FREQ; + } else { + if (fan_state.cooldown_counter > 0U) { + fan_state.cooldown_counter--; + } + } + + // Update controller + if (fan_state.target_rpm == 0U) { + fan_state.error_integral = 0.0f; + } else { + float error = (fan_state.target_rpm - fan_rpm_fast) / ((float) current_board->fan_max_rpm); + fan_state.error_integral += FAN_I * error; + } + fan_state.error_integral = CLAMP(fan_state.error_integral, 0U, current_board->fan_max_pwm); + fan_state.power = fan_state.error_integral; + + // Set PWM and enable line + pwm_set(TIM3, 3, fan_state.power); + current_board->set_fan_enabled(!fan_stalled && ((fan_state.target_rpm > 0U) || (fan_state.cooldown_counter > 0U))); + } +} diff --git a/panda_tici/board/drivers/fan_declarations.h b/panda_tici/board/drivers/fan_declarations.h new file mode 100644 index 0000000..4b7c1dc --- /dev/null +++ b/panda_tici/board/drivers/fan_declarations.h @@ -0,0 +1,20 @@ +#pragma once + +struct fan_state_t { + uint16_t tach_counter; + uint16_t rpm; + uint16_t target_rpm; + uint8_t power; + float error_integral; + uint8_t stall_counter; + uint8_t stall_threshold; + uint8_t total_stall_count; + 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); diff --git a/panda_tici/board/drivers/fdcan.h b/panda_tici/board/drivers/fdcan.h new file mode 100644 index 0000000..f3f8d99 --- /dev/null +++ b/panda_tici/board/drivers/fdcan.h @@ -0,0 +1,274 @@ +#include "fdcan_declarations.h" + +FDCAN_GlobalTypeDef *cans[CANS_ARRAY_SIZE] = {FDCAN1, FDCAN2, FDCAN3}; + +static bool can_set_speed(uint8_t can_number) { + bool ret = true; + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); + + ret &= llcan_set_speed( + FDCANx, + bus_config[bus_number].can_speed, + bus_config[bus_number].can_data_speed, + bus_config[bus_number].canfd_non_iso, + can_loopback, + (unsigned int)(can_silent) & (1U << can_number) + ); + return ret; +} + +void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number) { + static uint32_t last_reset = 0U; + uint32_t time = microsecond_timer_get(); + + // Resetting CAN core is a slow blocking operation, limit frequency + if (get_ts_elapsed(time, last_reset) > 100000U) { // 10 Hz + can_health[can_number].can_core_reset_cnt += 1U; + can_health[can_number].total_tx_lost_cnt += (FDCAN_TX_FIFO_EL_CNT - (FDCANx->TXFQS & FDCAN_TXFQS_TFFL)); // TX FIFO msgs will be lost after reset + llcan_clear_send(FDCANx); + last_reset = time; + } +} + +void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) { + uint8_t can_irq_number[3][2] = { + { FDCAN1_IT0_IRQn, FDCAN1_IT1_IRQn }, + { FDCAN2_IT0_IRQn, FDCAN2_IT1_IRQn }, + { FDCAN3_IT0_IRQn, FDCAN3_IT1_IRQn }, + }; + + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + uint32_t psr_reg = FDCANx->PSR; + uint32_t ecr_reg = FDCANx->ECR; + + can_health[can_number].bus_off = ((psr_reg & FDCAN_PSR_BO) >> FDCAN_PSR_BO_Pos); + can_health[can_number].bus_off_cnt += can_health[can_number].bus_off; + can_health[can_number].error_warning = ((psr_reg & FDCAN_PSR_EW) >> FDCAN_PSR_EW_Pos); + can_health[can_number].error_passive = ((psr_reg & FDCAN_PSR_EP) >> FDCAN_PSR_EP_Pos); + + can_health[can_number].last_error = ((psr_reg & FDCAN_PSR_LEC) >> FDCAN_PSR_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].last_data_error = ((psr_reg & FDCAN_PSR_DLEC) >> FDCAN_PSR_DLEC_Pos); + if ((can_health[can_number].last_data_error != 0U) && (can_health[can_number].last_data_error != 7U)) { + can_health[can_number].last_data_stored_error = can_health[can_number].last_data_error; + } + + can_health[can_number].receive_error_cnt = ((ecr_reg & FDCAN_ECR_REC) >> FDCAN_ECR_REC_Pos); + can_health[can_number].transmit_error_cnt = ((ecr_reg & FDCAN_ECR_TEC) >> FDCAN_ECR_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; + + + if (ir_reg != 0U) { + // Clear error interrupts + FDCANx->IR |= (FDCAN_IR_PED | FDCAN_IR_PEA | FDCAN_IR_EP | FDCAN_IR_BO | FDCAN_IR_RF0L); + can_health[can_number].total_error_cnt += 1U; + // Check for RX FIFO overflow + if ((ir_reg & (FDCAN_IR_RF0L)) != 0U) { + can_health[can_number].total_rx_lost_cnt += 1U; + } + // Cases: + // 1. while multiplexing between buses 1 and 3 we are getting ACK errors that overwhelm CAN core, by resetting it recovers faster + // 2. H7 gets stuck in bus off recovery state indefinitely + if ((((can_health[can_number].last_error == CAN_ACK_ERROR) || (can_health[can_number].last_data_error == CAN_ACK_ERROR)) && (can_health[can_number].transmit_error_cnt > 127U)) || + ((ir_reg & FDCAN_IR_BO) != 0U)) { + can_clear_send(FDCANx, can_number); + } + } +} + +// ***************************** CAN ***************************** +// FDFDCANx_IT1 IRQ Handler (TX) +void process_can(uint8_t can_number) { + if (can_number != 0xffU) { + ENTER_CRITICAL(); + + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); + + FDCANx->IR |= FDCAN_IR_TFE; // Clear Tx FIFO Empty flag + + if ((FDCANx->TXFQS & FDCAN_TXFQS_TFQF) == 0U) { + CANPacket_t to_send; + if (can_pop(can_queues[bus_number], &to_send)) { + if (can_check_checksum(&to_send)) { + can_health[can_number].total_tx_cnt += 1U; + + uint32_t TxFIFOSA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET) + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_SIZE); + // get the index of the next TX FIFO element (0 to FDCAN_TX_FIFO_EL_CNT - 1) + uint32_t tx_index = (FDCANx->TXFQS >> FDCAN_TXFQS_TFQPI_Pos) & 0x1FU; + // only send if we have received a packet + canfd_fifo *fifo; + fifo = (canfd_fifo *)(TxFIFOSA + (tx_index * FDCAN_TX_FIFO_EL_SIZE)); + + fifo->header[0] = (to_send.extended << 30) | ((to_send.extended != 0U) ? (to_send.addr) : (to_send.addr << 18)); + + // If canfd_auto is set, outgoing packets will be automatically sent as CAN-FD if an incoming CAN-FD packet was seen + bool fd = bus_config[can_number].canfd_auto ? bus_config[can_number].canfd_enabled : (bool)(to_send.fd > 0U); + uint32_t canfd_enabled_header = fd ? (1UL << 21) : 0UL; + + uint32_t brs_enabled_header = bus_config[can_number].brs_enabled ? (1UL << 20) : 0UL; + fifo->header[1] = (to_send.data_len_code << 16) | canfd_enabled_header | brs_enabled_header; + + uint8_t data_len_w = (dlc_to_len[to_send.data_len_code] / 4U); + data_len_w += ((dlc_to_len[to_send.data_len_code] % 4U) > 0U) ? 1U : 0U; + for (unsigned int i = 0; i < data_len_w; i++) { + BYTE_ARRAY_TO_WORD(fifo->data_word[i], &to_send.data[i*4U]); + } + + FDCANx->TXBAR = (1UL << tx_index); + + // Send back to USB + CANPacket_t to_push; + + to_push.fd = fd; + to_push.returned = 1U; + to_push.rejected = 0U; + to_push.extended = to_send.extended; + to_push.addr = to_send.addr; + to_push.bus = bus_number; + to_push.data_len_code = to_send.data_len_code; + (void)memcpy(to_push.data, to_send.data, dlc_to_len[to_push.data_len_code]); + can_set_checksum(&to_push); + + rx_buffer_overflow += can_push(&can_rx_q, &to_push) ? 0U : 1U; + } else { + can_health[can_number].total_tx_checksum_error_cnt += 1U; + } + + refresh_can_tx_slots_available(); + } + } + EXIT_CRITICAL(); + } +} + +// FDFDCANx_IT0 IRQ Handler (RX and errors) +// blink blue when we are receiving CAN messages +void can_rx(uint8_t can_number) { + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); + + uint32_t ir_reg = FDCANx->IR; + + // Clear all new messages from Rx FIFO 0 + FDCANx->IR |= FDCAN_IR_RF0N; + while((FDCANx->RXF0S & FDCAN_RXF0S_F0FL) != 0U) { + can_health[can_number].total_rx_cnt += 1U; + + // can is live + pending_can_live = 1; + + // get the index of the next RX FIFO element (0 to FDCAN_RX_FIFO_0_EL_CNT - 1) + uint32_t rx_fifo_idx = (uint8_t)((FDCANx->RXF0S >> FDCAN_RXF0S_F0GI_Pos) & 0x3FU); + + // Recommended to offset get index by at least +1 if RX FIFO is in overwrite mode and full (datasheet) + if((FDCANx->RXF0S & FDCAN_RXF0S_F0F) == FDCAN_RXF0S_F0F) { + rx_fifo_idx = ((rx_fifo_idx + 1U) >= FDCAN_RX_FIFO_0_EL_CNT) ? 0U : (rx_fifo_idx + 1U); + can_health[can_number].total_rx_lost_cnt += 1U; // At least one message was lost + } + + uint32_t RxFIFO0SA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET); + CANPacket_t to_push; + canfd_fifo *fifo; + + // getting address + fifo = (canfd_fifo *)(RxFIFO0SA + (rx_fifo_idx * FDCAN_RX_FIFO_0_EL_SIZE)); + + bool canfd_frame = ((fifo->header[1] >> 21) & 0x1U); + bool brs_frame = ((fifo->header[1] >> 20) & 0x1U); + + to_push.fd = canfd_frame; + to_push.returned = 0U; + to_push.rejected = 0U; + to_push.extended = (fifo->header[0] >> 30) & 0x1U; + to_push.addr = ((to_push.extended != 0U) ? (fifo->header[0] & 0x1FFFFFFFU) : ((fifo->header[0] >> 18) & 0x7FFU)); + to_push.bus = bus_number; + to_push.data_len_code = ((fifo->header[1] >> 16) & 0xFU); + + uint8_t data_len_w = (dlc_to_len[to_push.data_len_code] / 4U); + data_len_w += ((dlc_to_len[to_push.data_len_code] % 4U) > 0U) ? 1U : 0U; + for (unsigned int i = 0; i < data_len_w; i++) { + WORD_TO_BYTE_ARRAY(&to_push.data[i*4U], fifo->data_word[i]); + } + can_set_checksum(&to_push); + + // forwarding (panda only) + int bus_fwd_num = safety_fwd_hook(bus_number, to_push.addr); + if (bus_fwd_num < 0) { + bus_fwd_num = bus_config[can_number].forwarding_bus; + } + if (bus_fwd_num != -1) { + CANPacket_t to_send; + + to_send.fd = to_push.fd; + to_send.returned = 0U; + to_send.rejected = 0U; + to_send.extended = to_push.extended; + 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; + + // Enable CAN FD and BRS if CAN FD message was received + if (!(bus_config[can_number].canfd_enabled) && (canfd_frame)) { + bus_config[can_number].canfd_enabled = true; + } + if (!(bus_config[can_number].brs_enabled) && (brs_frame)) { + bus_config[can_number].brs_enabled = true; + } + + // update read index + FDCANx->RXF0A = rx_fifo_idx; + } + + // Error handling + if ((ir_reg & (FDCAN_IR_PED | FDCAN_IR_PEA | FDCAN_IR_EP | FDCAN_IR_BO | FDCAN_IR_RF0L)) != 0U) { + update_can_health_pkt(can_number, ir_reg); + } +} + +static void FDCAN1_IT0_IRQ_Handler(void) { can_rx(0); } +static void FDCAN1_IT1_IRQ_Handler(void) { process_can(0); } + +static void FDCAN2_IT0_IRQ_Handler(void) { can_rx(1); } +static void FDCAN2_IT1_IRQ_Handler(void) { process_can(1); } + +static void FDCAN3_IT0_IRQ_Handler(void) { can_rx(2); } +static void FDCAN3_IT1_IRQ_Handler(void) { process_can(2); } + +bool can_init(uint8_t can_number) { + bool ret = false; + + REGISTER_INTERRUPT(FDCAN1_IT0_IRQn, FDCAN1_IT0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1) + REGISTER_INTERRUPT(FDCAN1_IT1_IRQn, FDCAN1_IT1_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1) + REGISTER_INTERRUPT(FDCAN2_IT0_IRQn, FDCAN2_IT0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2) + REGISTER_INTERRUPT(FDCAN2_IT1_IRQn, FDCAN2_IT1_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2) + REGISTER_INTERRUPT(FDCAN3_IT0_IRQn, FDCAN3_IT0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3) + REGISTER_INTERRUPT(FDCAN3_IT1_IRQn, FDCAN3_IT1_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3) + + if (can_number != 0xffU) { + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + ret &= can_set_speed(can_number); + ret &= llcan_init(FDCANx); + // in case there are queued up messages + process_can(can_number); + } + return ret; +} diff --git a/panda_tici/board/drivers/fdcan_declarations.h b/panda_tici/board/drivers/fdcan_declarations.h new file mode 100644 index 0000000..9cdc424 --- /dev/null +++ b/panda_tici/board/drivers/fdcan_declarations.h @@ -0,0 +1,28 @@ +#pragma once + +// IRQs: FDCAN1_IT0, FDCAN1_IT1 +// FDCAN2_IT0, FDCAN2_IT1 +// FDCAN3_IT0, FDCAN3_IT1 + +#define CANFD + +typedef struct { + volatile uint32_t header[2]; + volatile uint32_t data_word[CANPACKET_DATA_SIZE_MAX/4U]; +} canfd_fifo; + +#define CANS_ARRAY_SIZE 3 +extern FDCAN_GlobalTypeDef *cans[CANS_ARRAY_SIZE]; + +#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); + +// ***************************** CAN ***************************** +// FDFDCANx_IT1 IRQ Handler (TX) +void process_can(uint8_t can_number); +// FDFDCANx_IT0 IRQ Handler (RX and errors) +// blink blue when we are receiving CAN messages +void can_rx(uint8_t can_number); +bool can_init(uint8_t can_number); diff --git a/panda_tici/board/drivers/gpio.h b/panda_tici/board/drivers/gpio.h new file mode 100644 index 0000000..aea6042 --- /dev/null +++ b/panda_tici/board/drivers/gpio.h @@ -0,0 +1,94 @@ +#define MODE_INPUT 0 +#define MODE_OUTPUT 1 +#define MODE_ALTERNATE 2 +#define MODE_ANALOG 3 + +#define PULL_NONE 0 +#define PULL_UP 1 +#define PULL_DOWN 2 + +#define OUTPUT_TYPE_PUSH_PULL 0U +#define OUTPUT_TYPE_OPEN_DRAIN 1U + +void set_gpio_mode(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode) { + ENTER_CRITICAL(); + uint32_t tmp = GPIO->MODER; + tmp &= ~(3U << (pin * 2U)); + tmp |= (mode << (pin * 2U)); + register_set(&(GPIO->MODER), tmp, 0xFFFFFFFFU); + EXIT_CRITICAL(); +} + +void set_gpio_output(GPIO_TypeDef *GPIO, unsigned int pin, bool enabled) { + ENTER_CRITICAL(); + if (enabled) { + register_set_bits(&(GPIO->ODR), (1UL << pin)); + } else { + register_clear_bits(&(GPIO->ODR), (1UL << pin)); + } + set_gpio_mode(GPIO, pin, MODE_OUTPUT); + EXIT_CRITICAL(); +} + +void set_gpio_output_type(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int output_type){ + ENTER_CRITICAL(); + if(output_type == OUTPUT_TYPE_OPEN_DRAIN) { + register_set_bits(&(GPIO->OTYPER), (1UL << pin)); + } else { + register_clear_bits(&(GPIO->OTYPER), (1U << pin)); + } + EXIT_CRITICAL(); +} + +void set_gpio_alternate(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode) { + ENTER_CRITICAL(); + uint32_t tmp = GPIO->AFR[pin >> 3U]; + tmp &= ~(0xFU << ((pin & 7U) * 4U)); + tmp |= mode << ((pin & 7U) * 4U); + register_set(&(GPIO->AFR[pin >> 3]), tmp, 0xFFFFFFFFU); + set_gpio_mode(GPIO, pin, MODE_ALTERNATE); + EXIT_CRITICAL(); +} + +void set_gpio_pullup(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode) { + ENTER_CRITICAL(); + uint32_t tmp = GPIO->PUPDR; + tmp &= ~(3U << (pin * 2U)); + tmp |= (mode << (pin * 2U)); + register_set(&(GPIO->PUPDR), tmp, 0xFFFFFFFFU); + EXIT_CRITICAL(); +} + +int get_gpio_input(const GPIO_TypeDef *GPIO, unsigned int pin) { + return (GPIO->IDR & (1UL << pin)) == (1UL << pin); +} + +#ifdef PANDA_JUNGLE +typedef struct { + GPIO_TypeDef * const bank; + uint8_t pin; +} gpio_t; + +void gpio_set_all_output(gpio_t *pins, uint8_t num_pins, bool enabled) { + for (uint8_t i = 0; i < num_pins; i++) { + set_gpio_output(pins[i].bank, pins[i].pin, enabled); + } +} + +void gpio_set_bitmask(gpio_t *pins, uint8_t num_pins, uint32_t bitmask) { + for (uint8_t i = 0; i < num_pins; i++) { + set_gpio_output(pins[i].bank, pins[i].pin, (bitmask >> i) & 1U); + } +} +#endif + +// Detection with internal pullup +#define PULL_EFFECTIVE_DELAY 4096 +bool detect_with_pull(GPIO_TypeDef *GPIO, int pin, int mode) { + set_gpio_mode(GPIO, pin, MODE_INPUT); + set_gpio_pullup(GPIO, pin, mode); + for (volatile int i=0; iharness_config->has_harness) { + bool drive_relay = intercept; + if (harness.status == HARNESS_STATUS_NC) { + // no harness, no relay to drive + drive_relay = false; + } + + if (drive_relay || ignition_relay) { + harness.relay_driven = true; + } + + // wait until we're not reading the analog voltages anymore + while (harness.sbu_adc_lock) {} + + if (harness.status == HARNESS_STATUS_NORMAL) { + set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !ignition_relay); + set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !drive_relay); + } else { + set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !drive_relay); + set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !ignition_relay); + } + + if (!(drive_relay || ignition_relay)) { + harness.relay_driven = false; + } + } +} + +bool harness_check_ignition(void) { + bool ret = false; + + // wait until we're not reading the analog voltages anymore + while (harness.sbu_adc_lock) {} + + switch(harness.status){ + case HARNESS_STATUS_NORMAL: + ret = !get_gpio_input(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1); + break; + case HARNESS_STATUS_FLIPPED: + ret = !get_gpio_input(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2); + break; + default: + break; + } + return ret; +} + +static uint8_t harness_detect_orientation(void) { + uint8_t ret = harness.status; + + #ifndef BOOTSTUB + // We can't detect orientation if the relay is being driven + if (!harness.relay_driven && current_board->harness_config->has_harness) { + harness.sbu_adc_lock = true; + set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_ANALOG); + set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_ANALOG); + + harness.sbu1_voltage_mV = adc_get_mV(current_board->harness_config->adc_channel_SBU1); + harness.sbu2_voltage_mV = adc_get_mV(current_board->harness_config->adc_channel_SBU2); + uint16_t detection_threshold = current_board->avdd_mV / 2U; + + // Detect connection and orientation + if((harness.sbu1_voltage_mV < detection_threshold) || (harness.sbu2_voltage_mV < detection_threshold)){ + if (harness.sbu1_voltage_mV < harness.sbu2_voltage_mV) { + // orientation flipped (PANDA_SBU1->HARNESS_SBU1(relay), PANDA_SBU2->HARNESS_SBU2(ign)) + ret = HARNESS_STATUS_FLIPPED; + } else { + // orientation normal (PANDA_SBU2->HARNESS_SBU1(relay), PANDA_SBU1->HARNESS_SBU2(ign)) + // (SBU1->SBU2 is the normal orientation connection per USB-C cable spec) + ret = HARNESS_STATUS_NORMAL; + } + } else { + ret = HARNESS_STATUS_NC; + } + + // Pins are not 5V tolerant in ADC mode + set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_INPUT); + set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_INPUT); + harness.sbu_adc_lock = false; + } + #endif + + return ret; +} + +void harness_tick(void) { + harness.status = harness_detect_orientation(); +} + +void harness_init(void) { + // init OBD_SBUx_RELAY + set_gpio_output_type(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, OUTPUT_TYPE_OPEN_DRAIN); + set_gpio_output_type(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, OUTPUT_TYPE_OPEN_DRAIN); + set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, 1); + set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, 1); + + // detect initial orientation + harness.status = harness_detect_orientation(); + + // keep buses connected by default + set_intercept_relay(false, false); +} diff --git a/panda_tici/board/drivers/harness_declarations.h b/panda_tici/board/drivers/harness_declarations.h new file mode 100644 index 0000000..953941f --- /dev/null +++ b/panda_tici/board/drivers/harness_declarations.h @@ -0,0 +1,34 @@ +#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 { + const bool has_harness; + 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 uint8_t adc_channel_SBU1; + const uint8_t adc_channel_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); diff --git a/panda_tici/board/drivers/interrupts.h b/panda_tici/board/drivers/interrupts.h new file mode 100644 index 0000000..1188a8e --- /dev/null +++ b/panda_tici/board/drivers/interrupts.h @@ -0,0 +1,81 @@ +#include "interrupts_declarations.h" + +void unused_interrupt_handler(void) { + // Something is wrong if this handler is called! + print("Unused interrupt handler called!\n"); + fault_occurred(FAULT_UNUSED_INTERRUPT_HANDLED); +} + +interrupt interrupts[NUM_INTERRUPTS]; + +static bool check_interrupt_rate = false; + +static uint32_t idle_time = 0U; +static uint32_t busy_time = 0U; +float interrupt_load = 0.0f; + +void handle_interrupt(IRQn_Type irq_type){ + static uint8_t interrupt_depth = 0U; + static uint32_t last_time = 0U; + ENTER_CRITICAL(); + if (interrupt_depth == 0U) { + uint32_t time = microsecond_timer_get(); + idle_time += get_ts_elapsed(time, last_time); + last_time = time; + } + interrupt_depth += 1U; + EXIT_CRITICAL(); + + interrupts[irq_type].call_counter++; + interrupts[irq_type].handler(); + + // Check that the interrupts don't fire too often + if (check_interrupt_rate && (interrupts[irq_type].call_counter > interrupts[irq_type].max_call_rate)) { + fault_occurred(interrupts[irq_type].call_rate_fault); + } + + ENTER_CRITICAL(); + interrupt_depth -= 1U; + if (interrupt_depth == 0U) { + uint32_t time = microsecond_timer_get(); + busy_time += get_ts_elapsed(time, last_time); + last_time = time; + } + EXIT_CRITICAL(); +} + +// Every second +void interrupt_timer_handler(void) { + if (INTERRUPT_TIMER->SR != 0U) { + for (uint16_t i = 0U; i < NUM_INTERRUPTS; i++) { + // Log IRQ call rate faults + if (check_interrupt_rate && (interrupts[i].call_counter > interrupts[i].max_call_rate)) { + print("Interrupt 0x"); puth(i); print(" fired too often (0x"); puth(interrupts[i].call_counter); print("/s)!\n"); + } + + // Reset interrupt counters + interrupts[i].call_rate = interrupts[i].call_counter; + interrupts[i].call_counter = 0U; + } + + // Calculate interrupt load + // The bootstub does not have the FPU enabled, so can't do float operations. +#if !defined(BOOTSTUB) + interrupt_load = ((busy_time + idle_time) > 0U) ? ((float) (((float) busy_time) / (busy_time + idle_time))) : 0.0f; +#endif + idle_time = 0U; + busy_time = 0U; + } + INTERRUPT_TIMER->SR = 0; +} + +void init_interrupts(bool check_rate_limit){ + check_interrupt_rate = check_rate_limit; + + for(uint16_t i=0U; iled_pwm_channels[color] != 0U) { + pwm_set(TIM3, current_board->led_pwm_channels[color], 100U - (enabled ? LED_PWM_POWER : 0U)); + } else { + set_gpio_output(current_board->led_GPIO[color], current_board->led_pin[color], !enabled); + } + } +} + +void led_init(void) { + for (uint8_t i = 0U; i<3U; i++){ + set_gpio_pullup(current_board->led_GPIO[i], current_board->led_pin[i], PULL_NONE); + set_gpio_output_type(current_board->led_GPIO[i], current_board->led_pin[i], OUTPUT_TYPE_OPEN_DRAIN); + + if (current_board->led_pwm_channels[i] != 0U) { + set_gpio_alternate(current_board->led_GPIO[i], current_board->led_pin[i], GPIO_AF2_TIM3); + pwm_init(TIM3, current_board->led_pwm_channels[i]); + } else { + set_gpio_mode(current_board->led_GPIO[i], current_board->led_pin[i], MODE_OUTPUT); + } + + led_set(i, false); + } +} diff --git a/panda_tici/board/drivers/pwm.h b/panda_tici/board/drivers/pwm.h new file mode 100644 index 0000000..67e5181 --- /dev/null +++ b/panda_tici/board/drivers/pwm.h @@ -0,0 +1,56 @@ +#define PWM_COUNTER_OVERFLOW 2000U // To get ~50kHz + +// TODO: Implement for 32-bit timers + +void pwm_init(TIM_TypeDef *TIM, uint8_t channel){ + // Enable timer and auto-reload + register_set(&(TIM->CR1), TIM_CR1_CEN | TIM_CR1_ARPE, 0x3FU); + + // Set channel as PWM mode 1 and enable output + switch(channel){ + case 1U: + register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE)); + register_set_bits(&(TIM->CCER), TIM_CCER_CC1E); + break; + case 2U: + register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE)); + register_set_bits(&(TIM->CCER), TIM_CCER_CC2E); + break; + case 3U: + register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE)); + register_set_bits(&(TIM->CCER), TIM_CCER_CC3E); + break; + case 4U: + register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE)); + register_set_bits(&(TIM->CCER), TIM_CCER_CC4E); + break; + default: + break; + } + + // Set max counter value + register_set(&(TIM->ARR), PWM_COUNTER_OVERFLOW, 0xFFFFU); + + // Update registers and clear counter + TIM->EGR |= TIM_EGR_UG; +} + +void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage){ + uint16_t comp_value = (((uint16_t) percentage * PWM_COUNTER_OVERFLOW) / 100U); + switch(channel){ + case 1U: + register_set(&(TIM->CCR1), comp_value, 0xFFFFU); + break; + case 2U: + register_set(&(TIM->CCR2), comp_value, 0xFFFFU); + break; + case 3U: + register_set(&(TIM->CCR3), comp_value, 0xFFFFU); + break; + case 4U: + register_set(&(TIM->CCR4), comp_value, 0xFFFFU); + break; + default: + break; + } +} diff --git a/panda_tici/board/drivers/registers.h b/panda_tici/board/drivers/registers.h new file mode 100644 index 0000000..ce4be14 --- /dev/null +++ b/panda_tici/board/drivers/registers.h @@ -0,0 +1,68 @@ +#include "registers_declarations.h" + +static reg register_map[REGISTER_MAP_SIZE]; + +// Hash spread in first and second iterations seems to be reasonable. +// See: tests/development/register_hashmap_spread.py +// Also, check the collision warnings in the debug output, and minimize those. +static uint16_t hash_addr(uint32_t input){ + return (((input >> 16U) ^ ((((input + 1U) & 0xFFFFU) * HASHING_PRIME) & 0xFFFFU)) & REGISTER_MAP_SIZE); +} + +// 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){ + ENTER_CRITICAL() + // Set bits in register that are also in the mask + (*addr) = ((*addr) & (~mask)) | (val & mask); + + // Add these values to the map + uint16_t hash = hash_addr((uint32_t) addr); + uint16_t tries = REGISTER_MAP_SIZE; + while(CHECK_COLLISION(hash, addr) && (tries > 0U)) { hash = hash_addr((uint32_t) hash); tries--;} + if (tries != 0U){ + register_map[hash].address = addr; + register_map[hash].value = (register_map[hash].value & (~mask)) | (val & mask); + register_map[hash].check_mask |= mask; + } else { + #ifdef DEBUG_FAULTS + print("Hash collision: address 0x"); puth((uint32_t) addr); print("!\n"); + #endif + } + EXIT_CRITICAL() +} + +// 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) { + register_set(addr, val, 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) { + register_set(addr, (~val), val); +} + +// To be called periodically +void check_registers(void){ + for(uint16_t i=0U; i wd_state.threshold) { + print("WD timeout 0x"); puth(et); print("\n"); + fault_occurred(wd_state.fault); + } + + wd_state.last_ts = ts; +} + +void simple_watchdog_init(uint32_t fault, uint32_t threshold) { + wd_state.fault = fault; + wd_state.threshold = threshold; + wd_state.last_ts = microsecond_timer_get(); +} diff --git a/panda_tici/board/drivers/simple_watchdog_declarations.h b/panda_tici/board/drivers/simple_watchdog_declarations.h new file mode 100644 index 0000000..2bda715 --- /dev/null +++ b/panda_tici/board/drivers/simple_watchdog_declarations.h @@ -0,0 +1,10 @@ +#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); diff --git a/panda_tici/board/drivers/spi.h b/panda_tici/board/drivers/spi.h new file mode 100644 index 0000000..2ca44ac --- /dev/null +++ b/panda_tici/board/drivers/spi.h @@ -0,0 +1,243 @@ +#pragma once + +#include "spi_declarations.h" +#include "crc.h" + +#ifdef STM32H7 +#define SPI_BUF_SIZE 2048U +// H7 DMA2 located in D2 domain, so we need to use SRAM1/SRAM2 +__attribute__((section(".sram12"))) uint8_t spi_buf_rx[SPI_BUF_SIZE]; +__attribute__((section(".sram12"))) uint8_t spi_buf_tx[SPI_BUF_SIZE]; +#else +#define SPI_BUF_SIZE 1024U +uint8_t spi_buf_rx[SPI_BUF_SIZE]; +uint8_t spi_buf_tx[SPI_BUF_SIZE]; +#endif + +uint16_t spi_error_count = 0; + +uint16_t spi_checksum_error_count = 0; + +#if defined(ENABLE_SPI) || defined(BOOTSTUB) +static uint8_t spi_state = SPI_STATE_HEADER; +static uint16_t spi_data_len_mosi; +static bool spi_can_tx_ready = false; +static const unsigned char version_text[] = "VERSION"; + +static uint16_t spi_version_packet(uint8_t *out) { + // this protocol version request is a stable portion of + // the panda's SPI protocol. its contents match that of the + // panda USB descriptors and are sufficent to list/enumerate + // a panda, determine panda type, and bootstub status. + + // the response is: + // VERSION + 2 byte data length + data + CRC8 + + // echo "VERSION" + (void)memcpy(out, version_text, 7); + + // write response + uint16_t data_len = 0; + uint16_t data_pos = 7U + 2U; + + // write serial + (void)memcpy(&out[data_pos], ((uint8_t *)UID_BASE), 12); + data_len += 12U; + + // HW type + out[data_pos + data_len] = hw_type; + data_len += 1U; + + // bootstub + out[data_pos + data_len] = USB_PID & 0xFFU; + data_len += 1U; + + // SPI protocol version + out[data_pos + data_len] = 0x2; + data_len += 1U; + + // data length + out[7] = data_len & 0xFFU; + out[8] = (data_len >> 8) & 0xFFU; + + // CRC8 + uint16_t resp_len = data_pos + data_len; + out[resp_len] = crc_checksum(out, resp_len, 0xD5U); + resp_len += 1U; + + return resp_len; +} + +void spi_init(void) { + // platform init + llspi_init(); + + // Start the first packet! + spi_state = SPI_STATE_HEADER; + llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); +} + +static bool validate_checksum(const uint8_t *data, uint16_t len) { + // TODO: can speed this up by casting the bulk to uint32_t and xor-ing the bytes afterwards + uint8_t checksum = SPI_CHECKSUM_START; + for(uint16_t i = 0U; i < len; i++){ + checksum ^= data[i]; + } + return checksum == 0U; +} + +void spi_rx_done(void) { + uint16_t response_len = 0U; + uint8_t next_rx_state = SPI_STATE_HEADER_NACK; + bool checksum_valid = false; + static uint8_t spi_endpoint; + static uint16_t spi_data_len_miso; + + // parse header + spi_endpoint = spi_buf_rx[1]; + spi_data_len_mosi = (spi_buf_rx[3] << 8) | spi_buf_rx[2]; + spi_data_len_miso = (spi_buf_rx[5] << 8) | spi_buf_rx[4]; + + if (memcmp(spi_buf_rx, version_text, 7) == 0) { + response_len = spi_version_packet(spi_buf_tx); + next_rx_state = SPI_STATE_HEADER_NACK;; + } else if (spi_state == SPI_STATE_HEADER) { + checksum_valid = validate_checksum(spi_buf_rx, SPI_HEADER_SIZE); + if ((spi_buf_rx[0] == SPI_SYNC_BYTE) && checksum_valid) { + // response: ACK and start receiving data portion + spi_buf_tx[0] = SPI_HACK; + next_rx_state = SPI_STATE_HEADER_ACK; + response_len = 1U; + } else { + // response: NACK and reset state machine + #ifdef DEBUG_SPI + print("- incorrect header sync or checksum "); hexdump(spi_buf_rx, SPI_HEADER_SIZE); + #endif + spi_buf_tx[0] = SPI_NACK; + next_rx_state = SPI_STATE_HEADER_NACK; + response_len = 1U; + } + } else if (spi_state == SPI_STATE_DATA_RX) { + // We got everything! Based on the endpoint specified, call the appropriate handler + bool response_ack = false; + checksum_valid = validate_checksum(&(spi_buf_rx[SPI_HEADER_SIZE]), spi_data_len_mosi + 1U); + if (checksum_valid) { + if (spi_endpoint == 0U) { + if (spi_data_len_mosi >= sizeof(ControlPacket_t)) { + ControlPacket_t ctrl = {0}; + (void)memcpy((uint8_t*)&ctrl, &spi_buf_rx[SPI_HEADER_SIZE], sizeof(ControlPacket_t)); + response_len = comms_control_handler(&ctrl, &spi_buf_tx[3]); + response_ack = true; + } else { + print("SPI: insufficient data for control handler\n"); + } + } else if ((spi_endpoint == 1U) || (spi_endpoint == 0x81U)) { + if (spi_data_len_mosi == 0U) { + response_len = comms_can_read(&(spi_buf_tx[3]), spi_data_len_miso); + response_ack = true; + } else { + print("SPI: did not expect data for can_read\n"); + } + } else if (spi_endpoint == 2U) { + comms_endpoint2_write(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi); + response_ack = true; + } else if (spi_endpoint == 3U) { + if (spi_data_len_mosi > 0U) { + if (spi_can_tx_ready) { + spi_can_tx_ready = false; + comms_can_write(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi); + response_ack = true; + } else { + response_ack = false; + print("SPI: CAN NACK\n"); + } + } else { + print("SPI: did expect data for can_write\n"); + } + } else if (spi_endpoint == 0xABU) { + // test endpoint, send max response length + response_len = spi_data_len_miso; + response_ack = true; + } else { + print("SPI: unexpected endpoint"); puth(spi_endpoint); print("\n"); + } + } else { + // Checksum was incorrect + response_ack = false; + #ifdef DEBUG_SPI + print("- incorrect data checksum "); + puth4(spi_data_len_mosi); + print("\n"); + hexdump(spi_buf_rx, SPI_HEADER_SIZE); + hexdump(&(spi_buf_rx[SPI_HEADER_SIZE]), MIN(spi_data_len_mosi, 64)); + print("\n"); + #endif + } + + if (!response_ack) { + spi_buf_tx[0] = SPI_NACK; + next_rx_state = SPI_STATE_HEADER_NACK; + response_len = 1U; + } else { + // Setup response header + spi_buf_tx[0] = SPI_DACK; + spi_buf_tx[1] = response_len & 0xFFU; + spi_buf_tx[2] = (response_len >> 8) & 0xFFU; + + // Add checksum + uint8_t checksum = SPI_CHECKSUM_START; + for(uint16_t i = 0U; i < (response_len + 3U); i++) { + checksum ^= spi_buf_tx[i]; + } + spi_buf_tx[response_len + 3U] = checksum; + response_len += 4U; + + next_rx_state = SPI_STATE_DATA_TX; + } + } else { + print("SPI: RX unexpected state: "); puth(spi_state); print("\n"); + } + + // send out response + if (response_len == 0U) { + print("SPI: no response\n"); + spi_buf_tx[0] = SPI_NACK; + spi_state = SPI_STATE_HEADER_NACK; + response_len = 1U; + } + llspi_miso_dma(spi_buf_tx, response_len); + + spi_state = next_rx_state; + if (!checksum_valid) { + spi_error_count += 1U; + } +} + +void spi_tx_done(bool reset) { + if ((spi_state == SPI_STATE_HEADER_NACK) || reset) { + // Reset state + spi_state = SPI_STATE_HEADER; + llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); + } else if (spi_state == SPI_STATE_HEADER_ACK) { + // ACK was sent, queue up the RX buf for the data + checksum + spi_state = SPI_STATE_DATA_RX; + llspi_mosi_dma(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi + 1U); + } else if (spi_state == SPI_STATE_DATA_TX) { + // Reset state + spi_state = SPI_STATE_HEADER; + llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); + } else { + spi_state = SPI_STATE_HEADER; + llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); + print("SPI: TX unexpected state: "); puth(spi_state); print("\n"); + } +} + +void can_tx_comms_resume_spi(void) { + spi_can_tx_ready = true; +} +#else +void can_tx_comms_resume_spi(void) { + return; +} +#endif diff --git a/panda_tici/board/drivers/spi_declarations.h b/panda_tici/board/drivers/spi_declarations.h new file mode 100644 index 0000000..75cff0a --- /dev/null +++ b/panda_tici/board/drivers/spi_declarations.h @@ -0,0 +1,52 @@ +#pragma once + +#include "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 + +#ifdef STM32H7 +#define SPI_BUF_SIZE 2048U +// 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]; +#else +#define SPI_BUF_SIZE 1024U +extern uint8_t spi_buf_rx[SPI_BUF_SIZE]; +extern 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 +}; + +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); +#if defined(ENABLE_SPI) || defined(BOOTSTUB) +void spi_init(void); +void spi_rx_done(void); +void spi_tx_done(bool reset); +#endif diff --git a/panda_tici/board/drivers/timers.h b/panda_tici/board/drivers/timers.h new file mode 100644 index 0000000..4c046a2 --- /dev/null +++ b/panda_tici/board/drivers/timers.h @@ -0,0 +1,31 @@ +static void timer_init(TIM_TypeDef *TIM, int psc) { + register_set(&(TIM->PSC), (psc-1), 0xFFFFU); + register_set(&(TIM->DIER), TIM_DIER_UIE, 0x5F5FU); + register_set(&(TIM->CR1), TIM_CR1_CEN, 0x3FU); + TIM->SR = 0; +} + +void microsecond_timer_init(void) { + MICROSECOND_TIMER->PSC = (APB1_TIMER_FREQ - 1U); + MICROSECOND_TIMER->CR1 = TIM_CR1_CEN; + MICROSECOND_TIMER->EGR = TIM_EGR_UG; +} + +uint32_t microsecond_timer_get(void) { + return MICROSECOND_TIMER->CNT; +} + +void interrupt_timer_init(void) { + enable_interrupt_timer(); + REGISTER_INTERRUPT(INTERRUPT_TIMER_IRQ, interrupt_timer_handler, 2U, FAULT_INTERRUPT_RATE_INTERRUPTS) + register_set(&(INTERRUPT_TIMER->PSC), ((uint16_t)(15.25*APB1_TIMER_FREQ)-1U), 0xFFFFU); + register_set(&(INTERRUPT_TIMER->DIER), TIM_DIER_UIE, 0x5F5FU); + register_set(&(INTERRUPT_TIMER->CR1), TIM_CR1_CEN, 0x3FU); + INTERRUPT_TIMER->SR = 0; + NVIC_EnableIRQ(INTERRUPT_TIMER_IRQ); +} + +void tick_timer_init(void) { + timer_init(TICK_TIMER, (uint16_t)((15.25*APB2_TIMER_FREQ)/8U)); + NVIC_EnableIRQ(TICK_TIMER_IRQ); +} diff --git a/panda_tici/board/drivers/uart.h b/panda_tici/board/drivers/uart.h new file mode 100644 index 0000000..ee15999 --- /dev/null +++ b/panda_tici/board/drivers/uart.h @@ -0,0 +1,165 @@ +#include "uart_declarations.h" + +// IRQs: USART2, USART3, UART5 + +// ***************************** Definitions ***************************** + +#define UART_BUFFER(x, size_rx, size_tx, uart_ptr, callback_ptr, overwrite_mode) \ + static uint8_t elems_rx_##x[size_rx]; \ + static uint8_t elems_tx_##x[size_tx]; \ + extern uart_ring uart_ring_##x; \ + uart_ring uart_ring_##x = { \ + .w_ptr_tx = 0, \ + .r_ptr_tx = 0, \ + .elems_tx = ((uint8_t *)&(elems_tx_##x)), \ + .tx_fifo_size = (size_tx), \ + .w_ptr_rx = 0, \ + .r_ptr_rx = 0, \ + .elems_rx = ((uint8_t *)&(elems_rx_##x)), \ + .rx_fifo_size = (size_rx), \ + .uart = (uart_ptr), \ + .callback = (callback_ptr), \ + .overwrite = (overwrite_mode) \ + }; + +// ******************************** UART buffers ******************************** + +// debug = USART2 +UART_BUFFER(debug, FIFO_SIZE_INT, FIFO_SIZE_INT, USART2, debug_ring_callback, true) + +// SOM debug = UART7 +#ifdef STM32H7 + UART_BUFFER(som_debug, FIFO_SIZE_INT, FIFO_SIZE_INT, UART7, NULL, true) +#else + // UART7 is not available on F4 + UART_BUFFER(som_debug, 1U, 1U, NULL, NULL, true) +#endif + +uart_ring *get_ring_by_number(int a) { + uart_ring *ring = NULL; + switch(a) { + case 0: + ring = &uart_ring_debug; + break; + case 4: + ring = &uart_ring_som_debug; + break; + default: + ring = NULL; + break; + } + return ring; +} + +// ************************* Low-level buffer functions ************************* +bool get_char(uart_ring *q, char *elem) { + bool ret = false; + + ENTER_CRITICAL(); + if (q->w_ptr_rx != q->r_ptr_rx) { + if (elem != NULL) *elem = q->elems_rx[q->r_ptr_rx]; + q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size; + ret = true; + } + EXIT_CRITICAL(); + + return ret; +} + +bool injectc(uart_ring *q, char elem) { + int ret = false; + uint16_t next_w_ptr; + + ENTER_CRITICAL(); + next_w_ptr = (q->w_ptr_rx + 1U) % q->rx_fifo_size; + + if ((next_w_ptr == q->r_ptr_rx) && q->overwrite) { + // overwrite mode: drop oldest byte + q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size; + } + + if (next_w_ptr != q->r_ptr_rx) { + q->elems_rx[q->w_ptr_rx] = elem; + q->w_ptr_rx = next_w_ptr; + ret = true; + } + EXIT_CRITICAL(); + + return ret; +} + +bool put_char(uart_ring *q, char elem) { + bool ret = false; + uint16_t next_w_ptr; + + ENTER_CRITICAL(); + next_w_ptr = (q->w_ptr_tx + 1U) % q->tx_fifo_size; + + if ((next_w_ptr == q->r_ptr_tx) && q->overwrite) { + // overwrite mode: drop oldest byte + q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size; + } + + if (next_w_ptr != q->r_ptr_tx) { + q->elems_tx[q->w_ptr_tx] = elem; + q->w_ptr_tx = next_w_ptr; + ret = true; + } + EXIT_CRITICAL(); + + uart_tx_ring(q); + + return ret; +} + +void clear_uart_buff(uart_ring *q) { + ENTER_CRITICAL(); + q->w_ptr_tx = 0; + q->r_ptr_tx = 0; + q->w_ptr_rx = 0; + q->r_ptr_rx = 0; + EXIT_CRITICAL(); +} + +// ************************ High-level debug functions ********************** +void putch(const char a) { + // misra-c2012-17.7: serial debug function, ok to ignore output + (void)injectc(&uart_ring_debug, a); +} + +void print(const char *a) { + for (const char *in = a; *in; in++) { + if (*in == '\n') putch('\r'); + putch(*in); + } +} + +void puthx(uint32_t i, uint8_t len) { + const char c[] = "0123456789abcdef"; + for (int pos = ((int)len * 4) - 4; pos > -4; pos -= 4) { + putch(c[(i >> (unsigned int)(pos)) & 0xFU]); + } +} + +void puth(unsigned int i) { + puthx(i, 8U); +} + +#if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG) +void puth4(unsigned int i) { + puthx(i, 4U); +} +#endif + +#if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG_USB) || defined(DEBUG_COMMS) +void hexdump(const void *a, int l) { + if (a != NULL) { + for (int i=0; i < l; i++) { + if ((i != 0) && ((i & 0xf) == 0)) print("\n"); + puthx(((const unsigned char*)a)[i], 2U); + print(" "); + } + } + print("\n"); +} +#endif diff --git a/panda_tici/board/drivers/uart_declarations.h b/panda_tici/board/drivers/uart_declarations.h new file mode 100644 index 0000000..f2775d3 --- /dev/null +++ b/panda_tici/board/drivers/uart_declarations.h @@ -0,0 +1,39 @@ +#pragma once + +// IRQs: USART2, USART3, UART5 + +// ***************************** 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(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG) +void puth4(unsigned int i); +#endif +void hexdump(const void *a, int l); diff --git a/panda_tici/board/drivers/usb.h b/panda_tici/board/drivers/usb.h new file mode 100644 index 0000000..1f715fe --- /dev/null +++ b/panda_tici/board/drivers/usb.h @@ -0,0 +1,798 @@ +#include "usb_declarations.h" + +static uint8_t response[USBPACKET_MAX_SIZE]; + +// current packet +static USB_Setup_TypeDef setup; +static uint8_t* ep0_txdata = NULL; +static uint16_t ep0_txlen = 0; +static bool outep3_processing = false; + +// Store the current interface alt setting. +static int current_int0_alt_setting = 0; + +// packet read and write + +static void *USB_ReadPacket(void *dest, uint16_t len) { + uint32_t *dest_copy = (uint32_t *)dest; + uint32_t count32b = ((uint32_t)len + 3U) / 4U; + + for (uint32_t i = 0; i < count32b; i++) { + *dest_copy = USBx_DFIFO(0U); + dest_copy++; + } + return ((void *)dest_copy); +} + +static void USB_WritePacket(const void *src, uint16_t len, uint32_t ep) { + #ifdef DEBUG_USB + print("writing "); + hexdump(src, len); + #endif + + uint32_t numpacket = ((uint32_t)len + (USBPACKET_MAX_SIZE - 1U)) / USBPACKET_MAX_SIZE; + uint32_t count32b = 0; + count32b = ((uint32_t)len + 3U) / 4U; + + // TODO: revisit this + USBx_INEP(ep)->DIEPTSIZ = ((numpacket << 19) & USB_OTG_DIEPTSIZ_PKTCNT) | + (len & USB_OTG_DIEPTSIZ_XFRSIZ); + USBx_INEP(ep)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); + + // load the FIFO + if (src != NULL) { + const uint32_t *src_copy = (const uint32_t *)src; + for (uint32_t i = 0; i < count32b; i++) { + USBx_DFIFO(ep) = *src_copy; + src_copy++; + } + } +} + +// IN EP 0 TX FIFO has a max size of 127 bytes (much smaller than the rest) +// so use TX FIFO empty interrupt to send larger amounts of data +static void USB_WritePacket_EP0(uint8_t *src, uint16_t len) { + #ifdef DEBUG_USB + print("writing "); + hexdump(src, len); + #endif + + uint16_t wplen = MIN(len, 0x40); + USB_WritePacket(src, wplen, 0); + + if (wplen < len) { + ep0_txdata = &src[wplen]; + ep0_txlen = len - wplen; + USBx_DEVICE->DIEPEMPMSK |= 1; + } else { + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + } +} + +static void usb_reset(void) { + // unmask endpoint interrupts, so many sets + USBx_DEVICE->DAINT = 0xFFFFFFFFU; + USBx_DEVICE->DAINTMSK = 0xFFFFFFFFU; + //USBx_DEVICE->DOEPMSK = (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM); + //USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM | USB_OTG_DIEPMSK_ITTXFEMSK); + //USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM); + + // all interrupts for debugging + USBx_DEVICE->DIEPMSK = 0xFFFFFFFFU; + USBx_DEVICE->DOEPMSK = 0xFFFFFFFFU; + + // clear interrupts + USBx_INEP(0U)->DIEPINT = 0xFF; + USBx_OUTEP(0U)->DOEPINT = 0xFF; + + // unset the address + USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD; + + // set up USB FIFOs + // RX start address is fixed to 0 + USBx->GRXFSIZ = 0x40; + + // 0x100 to offset past GRXFSIZ + USBx->DIEPTXF0_HNPTXFSIZ = (0x40UL << 16) | 0x40U; + + // EP1, massive + USBx->DIEPTXF[0] = (0x40UL << 16) | 0x80U; + + // flush TX fifo + USBx->GRSTCTL = USB_OTG_GRSTCTL_TXFFLSH | USB_OTG_GRSTCTL_TXFNUM_4; + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); + // flush RX FIFO + USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); + + // no global NAK + USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK; + + // ready to receive setup packets + USBx_OUTEP(0U)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19)) | (3U << 3); +} + +static char to_hex_char(uint8_t a) { + char ret; + if (a < 10U) { + ret = '0' + a; + } else { + ret = 'a' + (a - 10U); + } + return ret; +} + +static void usb_setup(void) { + static uint8_t device_desc[] = { + DSCR_DEVICE_LEN, USB_DESC_TYPE_DEVICE, //Length, Type + 0x10, 0x02, // bcdUSB max version of USB supported (2.1) + 0xFF, 0xFF, 0xFF, 0x40, // Class, Subclass, Protocol, Max Packet Size + TOUSBORDER(USB_VID), // idVendor + TOUSBORDER(USB_PID), // idProduct + 0x00, 0x00, // bcdDevice + 0x01, 0x02, // Manufacturer, Product + 0x03, 0x01 // Serial Number, Num Configurations + }; + + static uint8_t device_qualifier[] = { + 0x0a, USB_DESC_TYPE_DEVICE_QUALIFIER, //Length, Type + 0x10, 0x02, // bcdUSB max version of USB supported (2.1) + 0xFF, 0xFF, 0xFF, 0x40, // bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0 + 0x01, 0x00 // bNumConfigurations, bReserved + }; + + static uint8_t configuration_desc[] = { + DSCR_CONFIG_LEN, USB_DESC_TYPE_CONFIGURATION, // Length, Type, + TOUSBORDER(0x0045U), // Total Len (uint16) + 0x01, 0x01, STRING_OFFSET_ICONFIGURATION, // Num Interface, Config Value, Configuration + 0xc0, 0x32, // Attributes, Max Power + // interface 0 ALT 0 + DSCR_INTERFACE_LEN, USB_DESC_TYPE_INTERFACE, // Length, Type + 0x00, 0x00, 0x03, // Index, Alt Index idx, Endpoint count + 0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol + 0x00, // Interface + // endpoint 1, read CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_RCV | 1, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval (NA) + // endpoint 2, send serial + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + // endpoint 3, send CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + // interface 0 ALT 1 + DSCR_INTERFACE_LEN, USB_DESC_TYPE_INTERFACE, // Length, Type + 0x00, 0x01, 0x03, // Index, Alt Index idx, Endpoint count + 0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol + 0x00, // Interface + // endpoint 1, read CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_RCV | 1, ENDPOINT_TYPE_INT, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x05, // Polling Interval (5 frames) + // endpoint 2, send serial + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + // endpoint 3, send CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + }; + + // STRING_DESCRIPTOR_HEADER is for uint16 string descriptors + // it takes in a string length, which is bytes/2 because unicode + static uint16_t string_language_desc[] = { + STRING_DESCRIPTOR_HEADER(1), + 0x0409 // american english + }; + + // these strings are all uint16's so that we don't need to spam ,0 after every character + static uint16_t string_manufacturer_desc[] = { + STRING_DESCRIPTOR_HEADER(8), + 'c', 'o', 'm', 'm', 'a', '.', 'a', 'i' + }; + + static uint16_t string_product_desc[] = { + STRING_DESCRIPTOR_HEADER(5), + 'p', 'a', 'n', 'd', 'a' + }; + + // a string containing the default configuration index + static uint16_t string_configuration_desc[] = { + STRING_DESCRIPTOR_HEADER(2), + '0', '1' // "01" + }; + + // WCID (auto install WinUSB driver) + // https://github.com/pbatard/libwdi/wiki/WCID-Devices + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb-installation#automatic-installation-of--winusb-without-an-inf-file + // WinUSB 1.0 descriptors, this is mostly used by Windows XP + static uint8_t string_238_desc[] = { + 0x12, USB_DESC_TYPE_STRING, // bLength, bDescriptorType + 'M',0, 'S',0, 'F',0, 'T',0, '1',0, '0',0, '0',0, // qwSignature (MSFT100) + MS_VENDOR_CODE, 0x00 // bMS_VendorCode, bPad + }; + + static uint8_t winusb_ext_compatid_os_desc[] = { + 0x28, 0x00, 0x00, 0x00, // dwLength + 0x00, 0x01, // bcdVersion + 0x04, 0x00, // wIndex + 0x01, // bCount + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved + 0x00, // bFirstInterfaceNumber + 0x00, // Reserved + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subcompatible ID (none) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved + }; + + static uint8_t winusb_ext_prop_os_desc[] = { + 0x8e, 0x00, 0x00, 0x00, // dwLength + 0x00, 0x01, // bcdVersion + 0x05, 0x00, // wIndex + 0x01, 0x00, // wCount + // first property + 0x84, 0x00, 0x00, 0x00, // dwSize + 0x01, 0x00, 0x00, 0x00, // dwPropertyDataType + 0x28, 0x00, // wPropertyNameLength + 'D',0, 'e',0, 'v',0, 'i',0, 'c',0, 'e',0, 'I',0, 'n',0, 't',0, 'e',0, 'r',0, 'f',0, 'a',0, 'c',0, 'e',0, 'G',0, 'U',0, 'I',0, 'D',0, 0, 0, // bPropertyName (DeviceInterfaceGUID) + 0x4e, 0x00, 0x00, 0x00, // dwPropertyDataLength + '{',0, 'c',0, 'c',0, 'e',0, '5',0, '2',0, '9',0, '1',0, 'c',0, '-',0, 'a',0, '6',0, '9',0, 'f',0, '-',0, '4',0 ,'9',0 ,'9',0 ,'5',0 ,'-',0, 'a',0, '4',0, 'c',0, '2',0, '-',0, '2',0, 'a',0, 'e',0, '5',0, '7',0, 'a',0, '5',0, '1',0, 'a',0, 'd',0, 'e',0, '9',0, '}',0, 0, 0, // bPropertyData ({CCE5291C-A69F-4995-A4C2-2AE57A51ADE9}) + }; + + /* + Binary Object Store descriptor used to expose WebUSB (and more WinUSB) metadata + comments are from the wicg spec + References used: + https://wicg.github.io/webusb/#webusb-platform-capability-descriptor + https://github.com/sowbug/weblight/blob/192ad7a0e903542e2aa28c607d98254a12a6399d/firmware/webusb.c + https://os.mbed.com/users/larsgk/code/USBDevice_WebUSB/file/1d8a6665d607/WebUSBDevice/ + */ + static uint8_t binary_object_store_desc[] = { + // BOS header + BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH, // bLength, this is only the length of the header + BINARY_OBJECT_STORE_DESCRIPTOR, // bDescriptorType + 0x39, 0x00, // wTotalLength (LSB, MSB) + 0x02, // bNumDeviceCaps (WebUSB + WinUSB) + + // ------------------------------------------------- + // WebUSB descriptor + // header + 0x18, // bLength, Size of this descriptor. Must be set to 24. + 0x10, // bDescriptorType, DEVICE CAPABILITY descriptor + 0x05, // bDevCapabilityType, PLATFORM capability + 0x00, // bReserved, This field is reserved and shall be set to zero. + + // PlatformCapabilityUUID, Must be set to {3408b638-09a9-47a0-8bfd-a0768815b665}. + 0x38, 0xB6, 0x08, 0x34, + 0xA9, 0x09, 0xA0, 0x47, + 0x8B, 0xFD, 0xA0, 0x76, + 0x88, 0x15, 0xB6, 0x65, + // + + 0x00, 0x01, // bcdVersion, Protocol version supported. Must be set to 0x0100. + WEBUSB_VENDOR_CODE, // bVendorCode, bRequest value used for issuing WebUSB requests. + // there used to be a concept of "allowed origins", but it was removed from the spec + // it was intended to be a security feature, but then the entire security model relies on domain ownership + // https://github.com/WICG/webusb/issues/49 + // other implementations use various other indexed to leverate this no-longer-valid feature. we wont. + // the spec says we *must* reply to index 0x03 with the url, so we'll hint that that's the right index + 0x03, // iLandingPage, URL descriptor index of the device’s landing page. + + // ------------------------------------------------- + // WinUSB descriptor + // header + 0x1C, // Descriptor size (28 bytes) + 0x10, // Descriptor type (Device Capability) + 0x05, // Capability type (Platform) + 0x00, // Reserved + + // MS OS 2.0 Platform Capability ID (D8DD60DF-4589-4CC7-9CD2-659D9E648A9F) + // Indicates the device supports the Microsoft OS 2.0 descriptor + 0xDF, 0x60, 0xDD, 0xD8, + 0x89, 0x45, 0xC7, 0x4C, + 0x9C, 0xD2, 0x65, 0x9D, + 0x9E, 0x64, 0x8A, 0x9F, + + 0x00, 0x00, 0x03, 0x06, // Windows version, currently set to 8.1 (0x06030000) + + WINUSB_PLATFORM_DESCRIPTOR_LENGTH, 0x00, // MS OS 2.0 descriptor size (word) + MS_VENDOR_CODE, 0x00 // vendor code, no alternate enumeration + }; + + // WinUSB 2.0 descriptor. This is what modern systems use + // https://github.com/sowbug/weblight/blob/192ad7a0e903542e2aa28c607d98254a12a6399d/firmware/webusb.c + // http://janaxelson.com/files/ms_os_20_descriptors.c + // https://books.google.com/books?id=pkefBgAAQBAJ&pg=PA353&lpg=PA353 + static uint8_t winusb_20_desc[WINUSB_PLATFORM_DESCRIPTOR_LENGTH] = { + // Microsoft OS 2.0 descriptor set header (table 10) + 0x0A, 0x00, // Descriptor size (10 bytes) + 0x00, 0x00, // MS OS 2.0 descriptor set header + + 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) + WINUSB_PLATFORM_DESCRIPTOR_LENGTH, 0x00, // Total size of MS OS 2.0 descriptor set + + // Microsoft OS 2.0 compatible ID descriptor + 0x14, 0x00, // Descriptor size (20 bytes) + 0x03, 0x00, // MS OS 2.0 compatible ID descriptor + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub-compatible ID + + // Registry property descriptor + 0x80, 0x00, // Descriptor size (130 bytes) + 0x04, 0x00, // Registry Property descriptor + 0x01, 0x00, // Strings are null-terminated Unicode + 0x28, 0x00, // Size of Property Name (40 bytes) "DeviceInterfaceGUID" + + // bPropertyName (DeviceInterfaceGUID) + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, + 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, + 'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, + + 0x4E, 0x00, // Size of Property Data (78 bytes) + + // Vendor-defined property data: {CCE5291C-A69F-4995-A4C2-2AE57A51ADE9} + '{', 0x00, 'c', 0x00, 'c', 0x00, 'e', 0x00, '5', 0x00, '2', 0x00, '9', 0x00, '1', 0x00, // 16 + 'c', 0x00, '-', 0x00, 'a', 0x00, '6', 0x00, '9', 0x00, 'f', 0x00, '-', 0x00, '4', 0x00, // 32 + '9', 0x00, '9', 0x00, '5', 0x00, '-', 0x00, 'a', 0x00, '4', 0x00, 'c', 0x00, '2', 0x00, // 48 + '-', 0x00, '2', 0x00, 'a', 0x00, 'e', 0x00, '5', 0x00, '7', 0x00, 'a', 0x00, '5', 0x00, // 64 + '1', 0x00, 'a', 0x00, 'd', 0x00, 'e', 0x00, '9', 0x00, '}', 0x00, 0x00, 0x00 // 78 bytes + }; + + int resp_len; + ControlPacket_t control_req; + + // setup packet is ready + switch (setup.b.bRequest) { + case USB_REQ_SET_CONFIGURATION: + // enable other endpoints, has to be here? + USBx_INEP(1U)->DIEPCTL = (0x40U & USB_OTG_DIEPCTL_MPSIZ) | (2UL << 18) | (1UL << 22) | + USB_OTG_DIEPCTL_SD0PID_SEVNFRM | USB_OTG_DIEPCTL_USBAEP; + USBx_INEP(1U)->DIEPINT = 0xFF; + + USBx_OUTEP(2U)->DOEPTSIZ = (1UL << 19) | 0x40U; + USBx_OUTEP(2U)->DOEPCTL = (0x40U & USB_OTG_DOEPCTL_MPSIZ) | (2UL << 18) | + USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP; + USBx_OUTEP(2U)->DOEPINT = 0xFF; + + USBx_OUTEP(3U)->DOEPTSIZ = (32UL << 19) | 0x800U; + USBx_OUTEP(3U)->DOEPCTL = (0x40U & USB_OTG_DOEPCTL_MPSIZ) | (2UL << 18) | + USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP; + USBx_OUTEP(3U)->DOEPINT = 0xFF; + + // mark ready to receive + USBx_OUTEP(2U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + USBx_OUTEP(3U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_REQ_SET_ADDRESS: + // set now? + USBx_DEVICE->DCFG |= ((setup.b.wValue.w & 0x7fU) << 4); + + #ifdef DEBUG_USB + print(" set address\n"); + #endif + + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + + break; + case USB_REQ_GET_DESCRIPTOR: + switch (setup.b.wValue.bw.lsb) { + case USB_DESC_TYPE_DEVICE: + //print(" writing device descriptor\n"); + + // set bcdDevice to hardware type + device_desc[13] = hw_type; + // setup transfer + USB_WritePacket(device_desc, MIN(sizeof(device_desc), setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + + //print("D"); + break; + case USB_DESC_TYPE_CONFIGURATION: + USB_WritePacket(configuration_desc, MIN(sizeof(configuration_desc), setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_DESC_TYPE_DEVICE_QUALIFIER: + USB_WritePacket(device_qualifier, MIN(sizeof(device_qualifier), setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_DESC_TYPE_STRING: + switch (setup.b.wValue.bw.msb) { + case STRING_OFFSET_LANGID: + USB_WritePacket((uint8_t*)string_language_desc, MIN(sizeof(string_language_desc), setup.b.wLength.w), 0); + break; + case STRING_OFFSET_IMANUFACTURER: + USB_WritePacket((uint8_t*)string_manufacturer_desc, MIN(sizeof(string_manufacturer_desc), setup.b.wLength.w), 0); + break; + case STRING_OFFSET_IPRODUCT: + USB_WritePacket((uint8_t*)string_product_desc, MIN(sizeof(string_product_desc), setup.b.wLength.w), 0); + break; + case STRING_OFFSET_ISERIAL: + response[0] = 0x02 + (12 * 4); + response[1] = 0x03; + + // 96 bits = 12 bytes + for (int i = 0; i < 12; i++){ + uint8_t cc = ((uint8_t *)UID_BASE)[i]; + response[2 + (i * 4)] = to_hex_char((cc >> 4) & 0xFU); + response[2 + (i * 4) + 1] = '\0'; + response[2 + (i * 4) + 2] = to_hex_char((cc >> 0) & 0xFU); + response[2 + (i * 4) + 3] = '\0'; + } + + USB_WritePacket(response, MIN(response[0], setup.b.wLength.w), 0); + break; + case STRING_OFFSET_ICONFIGURATION: + USB_WritePacket((uint8_t*)string_configuration_desc, MIN(sizeof(string_configuration_desc), setup.b.wLength.w), 0); + break; + case 238: + USB_WritePacket((uint8_t*)string_238_desc, MIN(sizeof(string_238_desc), setup.b.wLength.w), 0); + break; + default: + // nothing + USB_WritePacket(0, 0, 0); + break; + } + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_DESC_TYPE_BINARY_OBJECT_STORE: + USB_WritePacket(binary_object_store_desc, MIN(sizeof(binary_object_store_desc), setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + default: + // nothing here? + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + } + break; + case USB_REQ_GET_STATUS: + // empty response? + response[0] = 0; + response[1] = 0; + USB_WritePacket((void*)&response, 2, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_REQ_SET_INTERFACE: + // Store the alt setting number for IN EP behavior. + current_int0_alt_setting = setup.b.wValue.w; + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case WEBUSB_VENDOR_CODE: + // probably asking for allowed origins, which was removed from the spec + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case MS_VENDOR_CODE: + switch (setup.b.wIndex.w) { + // winusb 2.0 descriptor from BOS + case WINUSB_REQ_GET_DESCRIPTOR: + USB_WritePacket_EP0((uint8_t*)winusb_20_desc, MIN(sizeof(winusb_20_desc), setup.b.wLength.w)); + break; + // Extended Compat ID OS Descriptor + case WINUSB_REQ_GET_COMPATID_DESCRIPTOR: + USB_WritePacket_EP0((uint8_t*)winusb_ext_compatid_os_desc, MIN(sizeof(winusb_ext_compatid_os_desc), setup.b.wLength.w)); + break; + // Extended Properties OS Descriptor + case WINUSB_REQ_GET_EXT_PROPS_OS: + USB_WritePacket_EP0((uint8_t*)winusb_ext_prop_os_desc, MIN(sizeof(winusb_ext_prop_os_desc), setup.b.wLength.w)); + break; + default: + USB_WritePacket_EP0(0, 0); + } + break; + default: + control_req.request = setup.b.bRequest; + control_req.param1 = setup.b.wValue.w; + control_req.param2 = setup.b.wIndex.w; + control_req.length = setup.b.wLength.w; + + resp_len = comms_control_handler(&control_req, response); + // response pending if -1 was returned + if (resp_len != -1) { + USB_WritePacket(response, MIN(resp_len, setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + } + } +} + + + +// ***************************** USB port ***************************** + +void usb_irqhandler(void) { + //USBx->GINTMSK = 0; + static uint8_t usbdata[0x100] __attribute__((aligned(4))); + unsigned int gintsts = USBx->GINTSTS; + unsigned int gotgint = USBx->GOTGINT; + unsigned int daint = USBx_DEVICE->DAINT; + + // gintsts SUSPEND? 04008428 + #ifdef DEBUG_USB + puth(gintsts); + print(" "); + /*puth(USBx->GCCFG); + print(" ");*/ + puth(gotgint); + print(" ep "); + puth(daint); + print(" USB interrupt!\n"); + #endif + + if ((gintsts & USB_OTG_GINTSTS_CIDSCHG) != 0U) { + print("connector ID status change\n"); + } + + if ((gintsts & USB_OTG_GINTSTS_USBRST) != 0U) { + #ifdef DEBUG_USB + print("USB reset\n"); + #endif + usb_reset(); + } + + if ((gintsts & USB_OTG_GINTSTS_ENUMDNE) != 0U) { + #ifdef DEBUG_USB + print("enumeration done\n"); + #endif + // Full speed, ENUMSPD + //puth(USBx_DEVICE->DSTS); + } + + if ((gintsts & USB_OTG_GINTSTS_OTGINT) != 0U) { + #ifdef DEBUG_USB + print("OTG int:"); + puth(USBx->GOTGINT); + print("\n"); + #endif + + // getting ADTOCHG + //USBx->GOTGINT = USBx->GOTGINT; + } + + // RX FIFO first + if ((gintsts & USB_OTG_GINTSTS_RXFLVL) != 0U) { + // 1. Read the Receive status pop register + volatile unsigned int rxst = USBx->GRXSTSP; + int status = (rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17; + + #ifdef DEBUG_USB + print(" RX FIFO:"); + puth(rxst); + print(" status: "); + puth(status); + print(" len: "); + puth((rxst & USB_OTG_GRXSTSP_BCNT) >> 4); + print("\n"); + #endif + + if (status == STS_DATA_UPDT) { + int endpoint = (rxst & USB_OTG_GRXSTSP_EPNUM); + int len = (rxst & USB_OTG_GRXSTSP_BCNT) >> 4; + (void)USB_ReadPacket(&usbdata, len); + #ifdef DEBUG_USB + print(" data "); + puth(len); + print("\n"); + hexdump(&usbdata, len); + #endif + + if (endpoint == 2) { + comms_endpoint2_write((uint8_t *) usbdata, len); + } + + if (endpoint == 3) { + outep3_processing = true; + comms_can_write(usbdata, len); + } + } else if (status == STS_SETUP_UPDT) { + (void)USB_ReadPacket(&setup, 8); + #ifdef DEBUG_USB + print(" setup "); + hexdump(&setup, 8); + print("\n"); + #endif + } else { + // status is neither STS_DATA_UPDT or STS_SETUP_UPDT, skip + } + } + + /*if (gintsts & USB_OTG_GINTSTS_HPRTINT) { + // host + print("HPRT:"); + puth(USBx_HOST_PORT->HPRT); + print("\n"); + if (USBx_HOST_PORT->HPRT & USB_OTG_HPRT_PCDET) { + USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PRST; + USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PCDET; + } + + }*/ + + if ((gintsts & USB_OTG_GINTSTS_BOUTNAKEFF) || (gintsts & USB_OTG_GINTSTS_GINAKEFF)) { + // no global NAK, why is this getting set? + #ifdef DEBUG_USB + print("GLOBAL NAK\n"); + #endif + USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK | USB_OTG_DCTL_CGINAK; + } + + if ((gintsts & USB_OTG_GINTSTS_SRQINT) != 0U) { + // we want to do "A-device host negotiation protocol" since we are the A-device + /*print("start request\n"); + puth(USBx->GOTGCTL); + print("\n");*/ + //USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + //USBx_HOST_PORT->HPRT = USB_OTG_HPRT_PPWR | USB_OTG_HPRT_PENA; + //USBx->GOTGCTL |= USB_OTG_GOTGCTL_SRQ; + } + + // out endpoint hit + if ((gintsts & USB_OTG_GINTSTS_OEPINT) != 0U) { + #ifdef DEBUG_USB + print(" 0:"); + puth(USBx_OUTEP(0U)->DOEPINT); + print(" 2:"); + puth(USBx_OUTEP(2U)->DOEPINT); + print(" 3:"); + puth(USBx_OUTEP(3U)->DOEPINT); + print(" "); + puth(USBx_OUTEP(3U)->DOEPCTL); + print(" 4:"); + puth(USBx_OUTEP(4)->DOEPINT); + print(" OUT ENDPOINT\n"); + #endif + + if ((USBx_OUTEP(2U)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0U) { + #ifdef DEBUG_USB + print(" OUT2 PACKET XFRC\n"); + #endif + USBx_OUTEP(2U)->DOEPTSIZ = (1UL << 19) | 0x40U; + USBx_OUTEP(2U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + } + + if ((USBx_OUTEP(3U)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0U) { + #ifdef DEBUG_USB + print(" OUT3 PACKET XFRC\n"); + #endif + // NAK cleared by process_can (if tx buffers have room) + outep3_processing = false; + refresh_can_tx_slots_available(); + } else if ((USBx_OUTEP(3U)->DOEPINT & 0x2000U) != 0U) { + #ifdef DEBUG_USB + print(" OUT3 PACKET WTF\n"); + #endif + // if NAK was set trigger this, unknown interrupt + // TODO: why was this here? fires when TX buffers when we can't clear NAK + // USBx_OUTEP(3U)->DOEPTSIZ = (1U << 19) | 0x40U; + // USBx_OUTEP(3U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + } else if ((USBx_OUTEP(3U)->DOEPINT) != 0U) { + #ifdef DEBUG_USB + print("OUTEP3 error "); + puth(USBx_OUTEP(3U)->DOEPINT); + print("\n"); + #endif + } else { + // USBx_OUTEP(3U)->DOEPINT is 0, ok to skip + } + + if ((USBx_OUTEP(0U)->DOEPINT & USB_OTG_DIEPINT_XFRC) != 0U) { + // ready for next packet + USBx_OUTEP(0U)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19)) | (1U << 3); + } + + // respond to setup packets + if ((USBx_OUTEP(0U)->DOEPINT & USB_OTG_DOEPINT_STUP) != 0U) { + usb_setup(); + } + + USBx_OUTEP(0U)->DOEPINT = USBx_OUTEP(0U)->DOEPINT; + USBx_OUTEP(2U)->DOEPINT = USBx_OUTEP(2U)->DOEPINT; + USBx_OUTEP(3U)->DOEPINT = USBx_OUTEP(3U)->DOEPINT; + } + + // interrupt endpoint hit (Page 1221) + if ((gintsts & USB_OTG_GINTSTS_IEPINT) != 0U) { + #ifdef DEBUG_USB + print(" "); + puth(USBx_INEP(0U)->DIEPINT); + print(" "); + puth(USBx_INEP(1U)->DIEPINT); + print(" IN ENDPOINT\n"); + #endif + + // Should likely check the EP of the IN request even if there is + // only one IN endpoint. + + // No need to set NAK in OTG_DIEPCTL0 when nothing to send, + // Appears USB core automatically sets NAK. WritePacket clears it. + + // Handle the two interface alternate settings. Setting 0 has EP1 + // as bulk. Setting 1 has EP1 as interrupt. The code to handle + // these two EP variations are very similar and can be + // restructured for smaller code footprint. Keeping split out for + // now for clarity. + + //TODO add default case. Should it NAK? + switch (current_int0_alt_setting) { + case 0: ////// Bulk config + // *** IN token received when TxFIFO is empty + if ((USBx_INEP(1U)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0U) { + #ifdef DEBUG_USB + print(" IN PACKET QUEUE\n"); + #endif + // TODO: always assuming max len, can we get the length? + USB_WritePacket((void *)response, comms_can_read(response, 0x40), 1); + } + break; + + case 1: ////// Interrupt config + // *** IN token received when TxFIFO is empty + if ((USBx_INEP(1U)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0U) { + #ifdef DEBUG_USB + print(" IN PACKET QUEUE\n"); + #endif + // TODO: always assuming max len, can we get the length? + int len = comms_can_read(response, 0x40); + if (len > 0) { + USB_WritePacket((void *)response, len, 1); + } + } + break; + default: + print("current_int0_alt_setting value invalid\n"); + break; + } + + if ((USBx_INEP(0U)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0U) { + #ifdef DEBUG_USB + print(" IN PACKET QUEUE\n"); + #endif + + if ((ep0_txlen != 0U) && ((USBx_INEP(0U)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40U)) { + uint16_t len = MIN(ep0_txlen, 0x40); + USB_WritePacket(ep0_txdata, len, 0); + ep0_txdata = &ep0_txdata[len]; + ep0_txlen -= len; + if (ep0_txlen == 0U) { + ep0_txdata = NULL; + USBx_DEVICE->DIEPEMPMSK &= ~1; + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + } + } + } + + // clear interrupts + USBx_INEP(0U)->DIEPINT = USBx_INEP(0U)->DIEPINT; // Why ep0? + USBx_INEP(1U)->DIEPINT = USBx_INEP(1U)->DIEPINT; + } + + // clear all interrupts we handled + USBx_DEVICE->DAINT = daint; + USBx->GOTGINT = gotgint; + USBx->GINTSTS = gintsts; + + //USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF); +} + +void can_tx_comms_resume_usb(void) { + ENTER_CRITICAL(); + if (!outep3_processing && (USBx_OUTEP(3U)->DOEPCTL & USB_OTG_DOEPCTL_NAKSTS) != 0U) { + USBx_OUTEP(3U)->DOEPTSIZ = (32UL << 19) | 0x800U; + USBx_OUTEP(3U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + } + EXIT_CRITICAL(); +} diff --git a/panda_tici/board/drivers/usb_declarations.h b/panda_tici/board/drivers/usb_declarations.h new file mode 100644 index 0000000..379b162 --- /dev/null +++ b/panda_tici/board/drivers/usb_declarations.h @@ -0,0 +1,111 @@ +#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); diff --git a/panda_tici/board/early_init.h b/panda_tici/board/early_init.h new file mode 100644 index 0000000..e48a806 --- /dev/null +++ b/panda_tici/board/early_init.h @@ -0,0 +1,66 @@ +// Early bringup +#define ENTER_BOOTLOADER_MAGIC 0xdeadbeefU +#define ENTER_SOFTLOADER_MAGIC 0xdeadc0deU +#define BOOT_NORMAL 0xdeadb111U + +extern void *g_pfnVectors; +extern uint32_t enter_bootloader_mode; + +typedef void (*bootloader_fcn)(void); +typedef bootloader_fcn *bootloader_fcn_ptr; + +static void jump_to_bootloader(void) { + // do enter bootloader + enter_bootloader_mode = 0; + + bootloader_fcn_ptr bootloader_ptr = (bootloader_fcn_ptr)BOOTLOADER_ADDRESS; + bootloader_fcn bootloader = *bootloader_ptr; + + // jump to bootloader + enable_interrupts(); + bootloader(); + + // reset on exit + enter_bootloader_mode = BOOT_NORMAL; + NVIC_SystemReset(); +} + +void early_initialization(void) { + // Reset global critical depth + disable_interrupts(); + global_critical_depth = 0; + + // Init register and interrupt tables + init_registers(); + + // after it's been in the bootloader, things are initted differently, so we reset + if ((enter_bootloader_mode != BOOT_NORMAL) && + (enter_bootloader_mode != ENTER_BOOTLOADER_MAGIC) && + (enter_bootloader_mode != ENTER_SOFTLOADER_MAGIC)) { + enter_bootloader_mode = BOOT_NORMAL; + NVIC_SystemReset(); + } + + // if wrong chip, reboot + volatile unsigned int id = DBGMCU->IDCODE; + if ((id & 0xFFFU) != MCU_IDCODE) { + enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; + } + + // setup interrupt table + SCB->VTOR = (uint32_t)&g_pfnVectors; + + // early GPIOs float everything + early_gpio_float(); + + detect_board_type(); + + if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) { + led_init(); + #ifdef PANDA + current_board->init_bootloader(); + #endif + led_set(LED_GREEN, 1); + jump_to_bootloader(); + } +} diff --git a/panda_tici/board/fake_stm.h b/panda_tici/board/fake_stm.h new file mode 100644 index 0000000..984fde1 --- /dev/null +++ b/panda_tici/board/fake_stm.h @@ -0,0 +1,35 @@ +// minimal code to fake a panda for tests +#include +#include +#include + +#include "utils.h" + +#define CANFD +#define ALLOW_DEBUG +#define PANDA + +#define ENTER_CRITICAL() 0 +#define EXIT_CRITICAL() 0 + +void print(const char *a) { + printf("%s", a); +} + +void puth(unsigned int i) { + printf("%u", i); +} + +typedef struct { + uint32_t CNT; +} TIM_TypeDef; + +TIM_TypeDef timer; +TIM_TypeDef *MICROSECOND_TIMER = &timer; +uint32_t microsecond_timer_get(void); + +uint32_t microsecond_timer_get(void) { + return MICROSECOND_TIMER->CNT; +} + +typedef uint32_t GPIO_TypeDef; diff --git a/panda_tici/board/faults.h b/panda_tici/board/faults.h new file mode 100644 index 0000000..0fc9d2c --- /dev/null +++ b/panda_tici/board/faults.h @@ -0,0 +1,25 @@ +#include "faults_declarations.h" + +uint8_t fault_status = FAULT_STATUS_NONE; +uint32_t faults = 0U; + +void fault_occurred(uint32_t fault) { + if ((faults & fault) == 0U) { + if ((PERMANENT_FAULTS & fault) != 0U) { + print("Permanent fault occurred: 0x"); puth(fault); print("\n"); + fault_status = FAULT_STATUS_PERMANENT; + } else { + print("Temporary fault occurred: 0x"); puth(fault); print("\n"); + fault_status = FAULT_STATUS_TEMPORARY; + } + } + faults |= fault; +} + +void fault_recovered(uint32_t fault) { + if ((PERMANENT_FAULTS & fault) == 0U) { + faults &= ~fault; + } else { + print("Cannot recover from a permanent fault!\n"); + } +} diff --git a/panda_tici/board/faults_declarations.h b/panda_tici/board/faults_declarations.h new file mode 100644 index 0000000..eab9fcc --- /dev/null +++ b/panda_tici/board/faults_declarations.h @@ -0,0 +1,44 @@ +#pragma once + +#define FAULT_STATUS_NONE 0U +#define FAULT_STATUS_TEMPORARY 1U +#define FAULT_STATUS_PERMANENT 2U + +// Fault types, matches cereal.log.PandaState.FaultType +#define FAULT_RELAY_MALFUNCTION (1UL << 0) +#define FAULT_UNUSED_INTERRUPT_HANDLED (1UL << 1) +#define FAULT_INTERRUPT_RATE_CAN_1 (1UL << 2) +#define FAULT_INTERRUPT_RATE_CAN_2 (1UL << 3) +#define FAULT_INTERRUPT_RATE_CAN_3 (1UL << 4) +#define FAULT_INTERRUPT_RATE_TACH (1UL << 5) +#define FAULT_INTERRUPT_RATE_GMLAN (1UL << 6) // deprecated +#define FAULT_INTERRUPT_RATE_INTERRUPTS (1UL << 7) +#define FAULT_INTERRUPT_RATE_SPI_DMA (1UL << 8) +#define FAULT_INTERRUPT_RATE_SPI_CS (1UL << 9) +#define FAULT_INTERRUPT_RATE_UART_1 (1UL << 10) +#define FAULT_INTERRUPT_RATE_UART_2 (1UL << 11) +#define FAULT_INTERRUPT_RATE_UART_3 (1UL << 12) +#define FAULT_INTERRUPT_RATE_UART_5 (1UL << 13) +#define FAULT_INTERRUPT_RATE_UART_DMA (1UL << 14) +#define FAULT_INTERRUPT_RATE_USB (1UL << 15) +#define FAULT_INTERRUPT_RATE_TIM1 (1UL << 16) +#define FAULT_INTERRUPT_RATE_TIM3 (1UL << 17) +#define FAULT_REGISTER_DIVERGENT (1UL << 18) +#define FAULT_INTERRUPT_RATE_KLINE_INIT (1UL << 19) +#define FAULT_INTERRUPT_RATE_CLOCK_SOURCE (1UL << 20) +#define FAULT_INTERRUPT_RATE_TICK (1UL << 21) +#define FAULT_INTERRUPT_RATE_EXTI (1UL << 22) +#define FAULT_INTERRUPT_RATE_SPI (1UL << 23) +#define FAULT_INTERRUPT_RATE_UART_7 (1UL << 24) +#define FAULT_SIREN_MALFUNCTION (1UL << 25) +#define FAULT_HEARTBEAT_LOOP_WATCHDOG (1UL << 26) +#define FAULT_INTERRUPT_RATE_SOUND_DMA (1UL << 27) + +// Permanent faults +#define PERMANENT_FAULTS 0U + +extern uint8_t fault_status; +extern uint32_t faults; + +void fault_occurred(uint32_t fault); +void fault_recovered(uint32_t fault); diff --git a/panda_tici/board/flash.py b/panda_tici/board/flash.py new file mode 100755 index 0000000..e55f6c9 --- /dev/null +++ b/panda_tici/board/flash.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import os +import subprocess +import argparse + +from panda_tici import Panda + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--all", action="store_true", help="Recover all Panda devices") + args = parser.parse_args() + + subprocess.check_call(f"scons -C {board_path}/.. -j$(nproc) {board_path}", shell=True) + + if args.all: + serials = Panda.list() + print(f"found {len(serials)} panda(s) - {serials}") + else: + serials = [None] + + for s in serials: + with Panda(serial=s) as p: + print("flashing", p.get_usb_serial()) + p.flash() + exit(1 if len(serials) == 0 else 0) diff --git a/panda_tici/board/flasher.h b/panda_tici/board/flasher.h new file mode 100644 index 0000000..9cf2154 --- /dev/null +++ b/panda_tici/board/flasher.h @@ -0,0 +1,159 @@ +// from the linker script +#ifdef STM32H7 + #define APP_START_ADDRESS 0x8020000U +#elif defined(STM32F4) + #define APP_START_ADDRESS 0x8004000U +#endif + +// 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; + + // flasher machine + memset(resp, 0, 4); + memcpy(resp+4, "\xde\xad\xd0\x0d", 4); + resp[0] = 0xff; + resp[2] = req->request; + resp[3] = ~req->request; + *((uint32_t **)&resp[8]) = prog_ptr; + resp_len = 0xc; + + int sec; + switch (req->request) { + // **** 0xb0: flasher echo + case 0xb0: + resp[1] = 0xff; + break; + // **** 0xb1: unlock flash + case 0xb1: + if (flash_is_locked()) { + flash_unlock(); + resp[1] = 0xff; + } + led_set(LED_GREEN, 1); + unlocked = true; + prog_ptr = (uint32_t *)APP_START_ADDRESS; + break; + // **** 0xb2: erase sector + case 0xb2: + sec = req->param1; + if (flash_erase_sector(sec, unlocked)) { + resp[1] = 0xff; + } + break; + // **** 0xc1: get hardware type + case 0xc1: + resp[0] = hw_type; + resp_len = 1; + break; + // **** 0xc3: fetch MCU UID + case 0xc3: + (void)memcpy(resp, ((uint8_t *)UID_BASE), 12); + resp_len = 12; + break; + // **** 0xd0: fetch serial number + case 0xd0: + // addresses are OTP + if (req->param1 == 1) { + memcpy(resp, (void *)DEVICE_SERIAL_NUMBER_ADDRESS, 0x10); + resp_len = 0x10; + } else { + get_provision_chunk(resp); + resp_len = PROVISION_CHUNK_LEN; + } + break; + // **** 0xd1: enter bootloader mode + case 0xd1: + // this allows reflashing of the bootstub + switch (req->param1) { + case 0: + print("-> entering bootloader\n"); + enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; + NVIC_SystemReset(); + break; + case 1: + print("-> entering softloader\n"); + enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC; + NVIC_SystemReset(); + break; + } + break; + // **** 0xd6: get version + case 0xd6: + COMPILE_TIME_ASSERT(sizeof(gitversion) <= USBPACKET_MAX_SIZE); + memcpy(resp, gitversion, sizeof(gitversion)); + resp_len = sizeof(gitversion); + break; + // **** 0xd8: reset ST + case 0xd8: + flush_write_buffer(); + NVIC_SystemReset(); + break; + } + return resp_len; +} + +void comms_can_write(const uint8_t *data, uint32_t len) { + UNUSED(data); + UNUSED(len); +} + +int comms_can_read(uint8_t *data, uint32_t max_len) { + UNUSED(data); + UNUSED(max_len); + return 0; +} + +void refresh_can_tx_slots_available(void) {} + +void comms_endpoint2_write(const uint8_t *data, uint32_t len) { + led_set(LED_RED, 0); + for (uint32_t i = 0; i < len/4; i++) { + flash_write_word(prog_ptr, *(uint32_t*)(data+(i*4))); + + //*(uint64_t*)(&spi_tx_buf[0x30+(i*4)]) = *prog_ptr; + prog_ptr++; + } + led_set(LED_RED, 1); +} + + +void soft_flasher_start(void) { + print("\n\n\n************************ FLASHER START ************************\n"); + + enter_bootloader_mode = 0; + + flasher_peripherals_init(); + + gpio_usart2_init(); + gpio_usb_init(); + led_init(); + + // enable USB + usb_init(); + +#ifdef ENABLE_SPI + if (current_board->has_spi) { + gpio_spi_init(); + spi_init(); + } +#endif + + // green LED on for flashing + led_set(LED_GREEN, 1); + + enable_interrupts(); + + for (;;) { + // blink the green LED fast + led_set(LED_GREEN, 0); + delay(500000); + led_set(LED_GREEN, 1); + delay(500000); + } +} diff --git a/panda_tici/board/gdb.sh b/panda_tici/board/gdb.sh new file mode 100755 index 0000000..aa695d6 --- /dev/null +++ b/panda_tici/board/gdb.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +gdb-multiarch --eval-command="target extended-remote localhost:3333" diff --git a/panda_tici/board/health.h b/panda_tici/board/health.h new file mode 100644 index 0000000..9040edf --- /dev/null +++ b/panda_tici/board/health.h @@ -0,0 +1,60 @@ +// When changing these structs, python/__init__.py needs to be kept up to date! + +#define HEALTH_PACKET_VERSION 17 +struct __attribute__((packed)) health_t { + uint32_t uptime_pkt; + uint32_t voltage_pkt; + uint32_t current_pkt; + uint32_t safety_tx_blocked_pkt; + uint32_t safety_rx_invalid_pkt; + uint32_t tx_buffer_overflow_pkt; + uint32_t rx_buffer_overflow_pkt; + uint32_t faults_pkt; + uint8_t ignition_line_pkt; + uint8_t ignition_can_pkt; + uint8_t controls_allowed_pkt; + uint8_t car_harness_status_pkt; + uint8_t safety_mode_pkt; + uint16_t safety_param_pkt; + uint8_t fault_status_pkt; + uint8_t power_save_enabled_pkt; + uint8_t heartbeat_lost_pkt; + uint16_t alternative_experience_pkt; + float interrupt_load_pkt; + uint8_t fan_power; + uint8_t safety_rx_checks_invalid_pkt; + uint16_t spi_error_count_pkt; + uint16_t sbu1_voltage_mV; + uint16_t sbu2_voltage_mV; + uint8_t som_reset_triggered; +}; + +#define CAN_HEALTH_PACKET_VERSION 5 +typedef struct __attribute__((packed)) { + uint8_t bus_off; + uint32_t bus_off_cnt; + uint8_t error_warning; + uint8_t error_passive; + uint8_t last_error; // real time LEC value + uint8_t last_stored_error; // last LEC positive error code stored + uint8_t last_data_error; // DLEC (for CANFD only) + uint8_t last_data_stored_error; // last DLEC positive error code stored (for CANFD only) + uint8_t receive_error_cnt; // Actual state of the receive error counter, values between 0 and 127. FDCAN_ECR.REC + uint8_t transmit_error_cnt; // Actual state of the transmit error counter, values between 0 and 255. FDCAN_ECR.TEC + uint32_t total_error_cnt; // How many times any error interrupt was invoked + uint32_t total_tx_lost_cnt; // Tx event FIFO element lost + uint32_t total_rx_lost_cnt; // Rx FIFO 0 message lost due to FIFO full condition + uint32_t total_tx_cnt; + uint32_t total_rx_cnt; + uint32_t total_fwd_cnt; // Messages forwarded from one bus to another + uint32_t total_tx_checksum_error_cnt; + uint16_t can_speed; + uint16_t can_data_speed; + uint8_t canfd_enabled; + uint8_t brs_enabled; + uint8_t canfd_non_iso; + uint32_t irq0_call_rate; + uint32_t irq1_call_rate; + uint32_t irq2_call_rate; + uint32_t can_core_reset_cnt; +} can_health_t; diff --git a/panda_tici/board/jungle/README.md b/panda_tici/board/jungle/README.md new file mode 100644 index 0000000..3fc645a --- /dev/null +++ b/panda_tici/board/jungle/README.md @@ -0,0 +1,26 @@ +Welcome to the jungle +====== + +Firmware for the Panda Jungle testing board. +Available for purchase at the [comma shop](https://comma.ai/shop/panda-jungle). + +## udev rules + +To make the jungle usable without root permissions, you might need to setup udev rules for it. +On ubuntu, this should do the trick: +``` bash +sudo tee /etc/udev/rules.d/12-panda_jungle.rules < bool: + dfu_serial = self.get_dfu_serial() + + if reset: + self.reset(enter_bootstub=True) + self.reset(enter_bootloader=True) + + if not self.wait_for_dfu(dfu_serial, timeout=timeout): + return False + + dfu = PandaJungleDFU(dfu_serial) + dfu.recover() + + # reflash after recover + self.connect(True, True) + self.flash() + return True + + def get_mcu_type(self) -> McuType: + hw_type = self.get_type() + if hw_type in PandaJungle.F4_DEVICES: + return McuType.F4 + elif hw_type in PandaJungle.H7_DEVICES: + return McuType.H7 + else: + # have to assume F4, see comment in Panda.connect + # initially Jungle V1 has HW type: bytearray(b'') + if hw_type == b'' or self._assume_f4_mcu: + return McuType.F4 + + 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")) + return super().up_to_date(fn=fn) + + # ******************* health ******************* + + @ensure_jungle_health_packet_version + def health(self): + dat = self._handle.controlRead(PandaJungle.REQUEST_IN, 0xd2, 0, 0, self.HEALTH_STRUCT.size) + a = self.HEALTH_STRUCT.unpack(dat) + return { + "uptime": a[0], + "ch1_power": a[1], + "ch2_power": a[2], + "ch3_power": a[3], + "ch4_power": a[4], + "ch5_power": a[5], + "ch6_power": a[6], + "ch1_sbu1_voltage": a[7] / 1000.0, + "ch1_sbu2_voltage": a[8] / 1000.0, + "ch2_sbu1_voltage": a[9] / 1000.0, + "ch2_sbu2_voltage": a[10] / 1000.0, + "ch3_sbu1_voltage": a[11] / 1000.0, + "ch3_sbu2_voltage": a[12] / 1000.0, + "ch4_sbu1_voltage": a[13] / 1000.0, + "ch4_sbu2_voltage": a[14] / 1000.0, + "ch5_sbu1_voltage": a[15] / 1000.0, + "ch5_sbu2_voltage": a[16] / 1000.0, + "ch6_sbu1_voltage": a[17] / 1000.0, + "ch6_sbu2_voltage": a[18] / 1000.0, + } + + # ******************* 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) + + # ******************* jungle stuff ******************* + + def set_panda_power(self, enabled): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa0, int(enabled), 0, b'') + + def set_panda_individual_power(self, port, enabled): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa3, int(port), int(enabled), b'') + + def set_harness_orientation(self, mode): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa1, int(mode), 0, b'') + + def set_ignition(self, enabled): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa2, int(enabled), 0, b'') + + def set_can_silent(self, silent): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xf5, int(silent), 0, b'') + + def set_generated_can(self, enabled): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa4, int(enabled), 0, b'') + + # ******************* serial ******************* + + def debug_read(self): + ret = [] + while 1: + lret = bytes(self._handle.controlRead(PandaJungle.REQUEST_IN, 0xe0, 0, 0, 0x40)) + if len(lret) == 0: + break + ret.append(lret) + return b''.join(ret) + + # ******************* header pins ******************* + + def set_header_pin(self, pin_num, enabled): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf7, int(pin_num), int(enabled), b'') diff --git a/panda_tici/board/jungle/boards/board_declarations.h b/panda_tici/board/jungle/boards/board_declarations.h new file mode 100644 index 0000000..8842704 --- /dev/null +++ b/panda_tici/board/jungle/boards/board_declarations.h @@ -0,0 +1,76 @@ +// ******************** Prototypes ******************** +typedef void (*board_init)(void); +typedef void (*board_board_tick)(void); +typedef bool (*board_get_button)(void); +typedef void (*board_set_panda_power)(bool enabled); +typedef void (*board_set_panda_individual_power)(uint8_t port_num, bool enabled); +typedef void (*board_set_ignition)(bool enabled); +typedef void (*board_set_individual_ignition)(uint8_t bitmask); +typedef void (*board_set_harness_orientation)(uint8_t orientation); +typedef void (*board_set_can_mode)(uint8_t mode); +typedef void (*board_enable_can_transceiver)(uint8_t transceiver, bool enabled); +typedef void (*board_enable_header_pin)(uint8_t pin_num, bool enabled); +typedef float (*board_get_channel_power)(uint8_t channel); +typedef uint16_t (*board_get_sbu_mV)(uint8_t channel, uint8_t sbu); + +struct board { + GPIO_TypeDef * const led_GPIO[3]; + const uint8_t led_pin[3]; + const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM + const bool has_canfd; + const bool has_sbu_sense; + const uint16_t avdd_mV; + board_init init; + board_board_tick board_tick; + board_get_button get_button; + board_set_panda_power set_panda_power; + board_set_panda_individual_power set_panda_individual_power; + board_set_ignition set_ignition; + board_set_individual_ignition set_individual_ignition; + board_set_harness_orientation set_harness_orientation; + board_set_can_mode set_can_mode; + board_enable_can_transceiver enable_can_transceiver; + board_enable_header_pin enable_header_pin; + board_get_channel_power get_channel_power; + board_get_sbu_mV get_sbu_mV; + + // TODO: shouldn't need these + bool has_spi; +}; + +// ******************* Definitions ******************** +#define HW_TYPE_UNKNOWN 0U +#define HW_TYPE_V1 1U +#define HW_TYPE_V2 2U + +// CAN modes +#define CAN_MODE_NORMAL 0U +#define CAN_MODE_OBD_CAN2 3U + +// Harness states +#define HARNESS_ORIENTATION_NONE 0U +#define HARNESS_ORIENTATION_1 1U +#define HARNESS_ORIENTATION_2 2U + +#define SBU1 0U +#define SBU2 1U + +// ********************* Globals ********************** +uint8_t harness_orientation = HARNESS_ORIENTATION_NONE; +uint8_t can_mode = CAN_MODE_NORMAL; +uint8_t ignition = 0U; + + +void unused_set_individual_ignition(uint8_t bitmask) { + UNUSED(bitmask); +} + +void unused_board_enable_header_pin(uint8_t pin_num, bool enabled) { + UNUSED(pin_num); + UNUSED(enabled); +} + +void unused_set_panda_individual_power(uint8_t port_num, bool enabled) { + UNUSED(port_num); + UNUSED(enabled); +} diff --git a/panda_tici/board/jungle/boards/board_v1.h b/panda_tici/board/jungle/boards/board_v1.h new file mode 100644 index 0000000..44e90b8 --- /dev/null +++ b/panda_tici/board/jungle/boards/board_v1.h @@ -0,0 +1,158 @@ +// ///////////////////////// // +// Jungle board v1 (STM32F4) // +// ///////////////////////// // + +void board_v1_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; + } +} + +void board_v1_set_can_mode(uint8_t mode) { + board_v1_enable_can_transceiver(2U, false); + board_v1_enable_can_transceiver(4U, false); + switch (mode) { + case CAN_MODE_NORMAL: + print("Setting normal CAN mode\n"); + // B12,B13: disable OBD mode + set_gpio_mode(GPIOB, 12, MODE_INPUT); + set_gpio_mode(GPIOB, 13, MODE_INPUT); + + // B5,B6: normal CAN2 mode + set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2); + can_mode = CAN_MODE_NORMAL; + board_v1_enable_can_transceiver(2U, true); + break; + case CAN_MODE_OBD_CAN2: + print("Setting OBD CAN mode\n"); + // B5,B6: disable normal CAN2 mode + set_gpio_mode(GPIOB, 5, MODE_INPUT); + set_gpio_mode(GPIOB, 6, MODE_INPUT); + + // B12,B13: OBD mode + set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2); + set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2); + can_mode = CAN_MODE_OBD_CAN2; + board_v1_enable_can_transceiver(4U, true); + break; + default: + print("Tried to set unsupported CAN mode: "); puth(mode); print("\n"); + break; + } +} + +void board_v1_set_harness_orientation(uint8_t orientation) { + switch (orientation) { + case HARNESS_ORIENTATION_NONE: + set_gpio_output(GPIOA, 2, false); + set_gpio_output(GPIOA, 3, false); + set_gpio_output(GPIOA, 4, false); + set_gpio_output(GPIOA, 5, false); + harness_orientation = orientation; + break; + case HARNESS_ORIENTATION_1: + set_gpio_output(GPIOA, 2, false); + set_gpio_output(GPIOA, 3, (ignition != 0U)); + set_gpio_output(GPIOA, 4, true); + set_gpio_output(GPIOA, 5, false); + harness_orientation = orientation; + break; + case HARNESS_ORIENTATION_2: + set_gpio_output(GPIOA, 2, (ignition != 0U)); + set_gpio_output(GPIOA, 3, false); + set_gpio_output(GPIOA, 4, false); + set_gpio_output(GPIOA, 5, true); + harness_orientation = orientation; + break; + default: + print("Tried to set an unsupported harness orientation: "); puth(orientation); print("\n"); + break; + } +} + +bool panda_power = false; +void board_v1_set_panda_power(bool enable) { + panda_power = enable; + set_gpio_output(GPIOB, 14, enable); +} + +bool board_v1_get_button(void) { + return get_gpio_input(GPIOC, 8); +} + +void board_v1_set_ignition(bool enabled) { + ignition = enabled ? 0xFFU : 0U; + board_v1_set_harness_orientation(harness_orientation); +} + +float board_v1_get_channel_power(uint8_t channel) { + UNUSED(channel); + return 0.0f; +} + +uint16_t board_v1_get_sbu_mV(uint8_t channel, uint8_t sbu) { + UNUSED(channel); UNUSED(sbu); + return 0U; +} + +void board_v1_init(void) { + common_init_gpio(); + + // A8,A15: normal CAN3 mode + set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3); + set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3); + + board_v1_set_can_mode(CAN_MODE_NORMAL); + + // Enable CAN transceivers + for(uint8_t i = 1; i <= 4; i++) { + board_v1_enable_can_transceiver(i, true); + } + + // Set normal CAN mode + board_v1_set_can_mode(CAN_MODE_NORMAL); + + // Set to no harness orientation + board_v1_set_harness_orientation(HARNESS_ORIENTATION_NONE); + + // Enable panda power by default + board_v1_set_panda_power(true); +} + +void board_v1_tick(void) {} + +board board_v1 = { + .has_canfd = false, + .has_sbu_sense = false, + .avdd_mV = 3300U, + .init = &board_v1_init, + .led_GPIO = {GPIOC, GPIOC, GPIOC}, + .led_pin = {9, 7, 6}, + .board_tick = &board_v1_tick, + .get_button = &board_v1_get_button, + .set_panda_power = &board_v1_set_panda_power, + .set_panda_individual_power = &unused_set_panda_individual_power, + .set_ignition = &board_v1_set_ignition, + .set_individual_ignition = &unused_set_individual_ignition, + .set_harness_orientation = &board_v1_set_harness_orientation, + .set_can_mode = &board_v1_set_can_mode, + .enable_can_transceiver = &board_v1_enable_can_transceiver, + .enable_header_pin = &unused_board_enable_header_pin, + .get_channel_power = &board_v1_get_channel_power, + .get_sbu_mV = &board_v1_get_sbu_mV, +}; diff --git a/panda_tici/board/jungle/boards/board_v2.h b/panda_tici/board/jungle/boards/board_v2.h new file mode 100644 index 0000000..ea0a099 --- /dev/null +++ b/panda_tici/board/jungle/boards/board_v2.h @@ -0,0 +1,308 @@ +// ///////////////////////// // +// Jungle board v2 (STM32H7) // +// ///////////////////////// // + +gpio_t power_pins[] = { + {.bank = GPIOA, .pin = 0}, + {.bank = GPIOA, .pin = 1}, + {.bank = GPIOF, .pin = 12}, + {.bank = GPIOA, .pin = 5}, + {.bank = GPIOC, .pin = 5}, + {.bank = GPIOB, .pin = 2}, +}; + +gpio_t sbu1_ignition_pins[] = { + {.bank = GPIOD, .pin = 0}, + {.bank = GPIOD, .pin = 5}, + {.bank = GPIOD, .pin = 12}, + {.bank = GPIOD, .pin = 14}, + {.bank = GPIOE, .pin = 5}, + {.bank = GPIOE, .pin = 9}, +}; + +gpio_t sbu1_relay_pins[] = { + {.bank = GPIOD, .pin = 1}, + {.bank = GPIOD, .pin = 6}, + {.bank = GPIOD, .pin = 11}, + {.bank = GPIOD, .pin = 15}, + {.bank = GPIOE, .pin = 6}, + {.bank = GPIOE, .pin = 10}, +}; + +gpio_t sbu2_ignition_pins[] = { + {.bank = GPIOD, .pin = 3}, + {.bank = GPIOD, .pin = 8}, + {.bank = GPIOD, .pin = 9}, + {.bank = GPIOE, .pin = 0}, + {.bank = GPIOE, .pin = 7}, + {.bank = GPIOE, .pin = 11}, +}; + +gpio_t sbu2_relay_pins[] = { + {.bank = GPIOD, .pin = 4}, + {.bank = GPIOD, .pin = 10}, + {.bank = GPIOD, .pin = 13}, + {.bank = GPIOE, .pin = 1}, + {.bank = GPIOE, .pin = 8}, + {.bank = GPIOE, .pin = 12}, +}; + +adc_channel_t sbu1_channels[] = { + {.adc = ADC3, .channel = 12}, + {.adc = ADC3, .channel = 2}, + {.adc = ADC3, .channel = 4}, + {.adc = ADC3, .channel = 6}, + {.adc = ADC3, .channel = 8}, + {.adc = ADC3, .channel = 10}, +}; + +adc_channel_t sbu2_channels[] = { + {.adc = ADC1, .channel = 13}, + {.adc = ADC3, .channel = 3}, + {.adc = ADC3, .channel = 5}, + {.adc = ADC3, .channel = 7}, + {.adc = ADC3, .channel = 9}, + {.adc = ADC3, .channel = 11}, +}; + +void board_v2_set_harness_orientation(uint8_t orientation) { + switch (orientation) { + case HARNESS_ORIENTATION_NONE: + gpio_set_all_output(sbu1_ignition_pins, sizeof(sbu1_ignition_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu1_relay_pins, sizeof(sbu1_relay_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu2_ignition_pins, sizeof(sbu2_ignition_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu2_relay_pins, sizeof(sbu2_relay_pins) / sizeof(gpio_t), false); + harness_orientation = orientation; + break; + case HARNESS_ORIENTATION_1: + gpio_set_all_output(sbu1_ignition_pins, sizeof(sbu1_ignition_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu1_relay_pins, sizeof(sbu1_relay_pins) / sizeof(gpio_t), true); + gpio_set_bitmask(sbu2_ignition_pins, sizeof(sbu2_ignition_pins) / sizeof(gpio_t), ignition); + gpio_set_all_output(sbu2_relay_pins, sizeof(sbu2_relay_pins) / sizeof(gpio_t), false); + harness_orientation = orientation; + break; + case HARNESS_ORIENTATION_2: + gpio_set_bitmask(sbu1_ignition_pins, sizeof(sbu1_ignition_pins) / sizeof(gpio_t), ignition); + gpio_set_all_output(sbu1_relay_pins, sizeof(sbu1_relay_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu2_ignition_pins, sizeof(sbu2_ignition_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu2_relay_pins, sizeof(sbu2_relay_pins) / sizeof(gpio_t), true); + harness_orientation = orientation; + break; + default: + print("Tried to set an unsupported harness orientation: "); puth(orientation); print("\n"); + break; + } +} + +void board_v2_enable_can_transceiver(uint8_t transceiver, bool enabled) { + switch (transceiver) { + case 1U: + set_gpio_output(GPIOG, 11, !enabled); + break; + case 2U: + set_gpio_output(GPIOB, 3, !enabled); + break; + case 3U: + set_gpio_output(GPIOD, 7, !enabled); + break; + case 4U: + set_gpio_output(GPIOB, 4, !enabled); + break; + default: + print("Invalid CAN transceiver ("); puth(transceiver); print("): enabling failed\n"); + break; + } +} + +void board_v2_enable_header_pin(uint8_t pin_num, bool enabled) { + if (pin_num < 8U) { + set_gpio_output(GPIOG, pin_num, enabled); + } else { + print("Invalid pin number ("); puth(pin_num); print("): enabling failed\n"); + } +} + +void board_v2_set_can_mode(uint8_t mode) { + board_v2_enable_can_transceiver(2U, false); + board_v2_enable_can_transceiver(4U, false); + switch (mode) { + case CAN_MODE_NORMAL: + // B12,B13: disable normal mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_mode(GPIOB, 12, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_mode(GPIOB, 13, MODE_ANALOG); + + // B5,B6: FDCAN2 mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_alternate(GPIOB, 5, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_FDCAN2); + can_mode = CAN_MODE_NORMAL; + board_v2_enable_can_transceiver(2U, true); + break; + case CAN_MODE_OBD_CAN2: + // B5,B6: disable normal mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_mode(GPIOB, 5, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_mode(GPIOB, 6, MODE_ANALOG); + // B12,B13: FDCAN2 mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_alternate(GPIOB, 12, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_alternate(GPIOB, 13, GPIO_AF9_FDCAN2); + can_mode = CAN_MODE_OBD_CAN2; + board_v2_enable_can_transceiver(4U, true); + break; + default: + break; + } +} + +bool panda_power = false; +uint8_t panda_power_bitmask = 0U; +void board_v2_set_panda_power(bool enable) { + panda_power = enable; + gpio_set_all_output(power_pins, sizeof(power_pins) / sizeof(gpio_t), enable); + if (enable) { + panda_power_bitmask = 0xFFU; + } else { + panda_power_bitmask = 0U; + } +} + +void board_v2_set_panda_individual_power(uint8_t port_num, bool enable) { + port_num -= 1U; + if (port_num < 6U) { + panda_power_bitmask &= ~(1U << port_num); + panda_power_bitmask |= (enable ? 1U : 0U) << port_num; + } else { + print("Invalid port number ("); puth(port_num); print("): enabling failed\n"); + } + gpio_set_bitmask(power_pins, sizeof(power_pins) / sizeof(gpio_t), (uint32_t)panda_power_bitmask); +} + +bool board_v2_get_button(void) { + return get_gpio_input(GPIOG, 15); +} + +void board_v2_set_ignition(bool enabled) { + ignition = enabled ? 0xFFU : 0U; + board_v2_set_harness_orientation(harness_orientation); +} + +void board_v2_set_individual_ignition(uint8_t bitmask) { + ignition = bitmask; + board_v2_set_harness_orientation(harness_orientation); +} + +float board_v2_get_channel_power(uint8_t channel) { + float ret = 0.0f; + if ((channel >= 1U) && (channel <= 6U)) { + uint16_t readout = adc_get_mV(ADC1, channel - 1U); // these are mapped nicely in hardware + + ret = (((float) readout / 33e6) - 0.8e-6) / 52e-6 * 12.0f; + } else { + print("Invalid channel ("); puth(channel); print(")\n"); + } + return ret; +} + +uint16_t board_v2_get_sbu_mV(uint8_t channel, uint8_t sbu) { + uint16_t ret = 0U; + if ((channel >= 1U) && (channel <= 6U)) { + switch(sbu){ + case SBU1: + ret = adc_get_mV(sbu1_channels[channel - 1U].adc, sbu1_channels[channel - 1U].channel); + break; + case SBU2: + ret = adc_get_mV(sbu2_channels[channel - 1U].adc, sbu2_channels[channel - 1U].channel); + break; + default: + print("Invalid SBU ("); puth(sbu); print(")\n"); + break; + } + } else { + print("Invalid channel ("); puth(channel); print(")\n"); + } + return ret; +} + +void board_v2_init(void) { + common_init_gpio(); + + // Normal CAN mode + board_v2_set_can_mode(CAN_MODE_NORMAL); + + // Enable CAN transceivers + for(uint8_t i = 1; i <= 4; i++) { + board_v2_enable_can_transceiver(i, true); + } + + // Set to no harness orientation + board_v2_set_harness_orientation(HARNESS_ORIENTATION_NONE); + + // Enable panda power by default + board_v2_set_panda_power(true); + + // Current monitor channels + adc_init(ADC1); + register_set_bits(&SYSCFG->PMCR, SYSCFG_PMCR_PA0SO | SYSCFG_PMCR_PA1SO); // open up analog switches for PA0_C and PA1_C + set_gpio_mode(GPIOF, 11, MODE_ANALOG); + set_gpio_mode(GPIOA, 6, MODE_ANALOG); + set_gpio_mode(GPIOC, 4, MODE_ANALOG); + set_gpio_mode(GPIOB, 1, MODE_ANALOG); + + // SBU channels + adc_init(ADC3); + set_gpio_mode(GPIOC, 2, MODE_ANALOG); + set_gpio_mode(GPIOC, 3, MODE_ANALOG); + set_gpio_mode(GPIOF, 9, MODE_ANALOG); + set_gpio_mode(GPIOF, 7, MODE_ANALOG); + set_gpio_mode(GPIOF, 5, MODE_ANALOG); + set_gpio_mode(GPIOF, 3, MODE_ANALOG); + set_gpio_mode(GPIOF, 10, MODE_ANALOG); + set_gpio_mode(GPIOF, 8, MODE_ANALOG); + set_gpio_mode(GPIOF, 6, MODE_ANALOG); + set_gpio_mode(GPIOF, 4, MODE_ANALOG); + set_gpio_mode(GPIOC, 0, MODE_ANALOG); + set_gpio_mode(GPIOC, 1, MODE_ANALOG); + + // Header pins + set_gpio_mode(GPIOG, 0, MODE_OUTPUT); + set_gpio_mode(GPIOG, 1, MODE_OUTPUT); + set_gpio_mode(GPIOG, 2, MODE_OUTPUT); + set_gpio_mode(GPIOG, 3, MODE_OUTPUT); + set_gpio_mode(GPIOG, 4, MODE_OUTPUT); + set_gpio_mode(GPIOG, 5, MODE_OUTPUT); + set_gpio_mode(GPIOG, 6, MODE_OUTPUT); + set_gpio_mode(GPIOG, 7, MODE_OUTPUT); +} + +void board_v2_tick(void) {} + +board board_v2 = { + .has_canfd = true, + .has_sbu_sense = true, + .avdd_mV = 3300U, + .init = &board_v2_init, + .led_GPIO = {GPIOE, GPIOE, GPIOE}, + .led_pin = {4, 3, 2}, + .board_tick = &board_v2_tick, + .get_button = &board_v2_get_button, + .set_panda_power = &board_v2_set_panda_power, + .set_panda_individual_power = &board_v2_set_panda_individual_power, + .set_ignition = &board_v2_set_ignition, + .set_individual_ignition = &board_v2_set_individual_ignition, + .set_harness_orientation = &board_v2_set_harness_orientation, + .set_can_mode = &board_v2_set_can_mode, + .enable_can_transceiver = &board_v2_enable_can_transceiver, + .enable_header_pin = &board_v2_enable_header_pin, + .get_channel_power = &board_v2_get_channel_power, + .get_sbu_mV = &board_v2_get_sbu_mV, +}; diff --git a/panda_tici/board/jungle/flash.py b/panda_tici/board/jungle/flash.py new file mode 100755 index 0000000..c58d55e --- /dev/null +++ b/panda_tici/board/jungle/flash.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import os +import subprocess +import argparse + +from panda_tici import PandaJungle + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--all", action="store_true", help="Recover all panda jungle devices") + args = parser.parse_args() + + subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) {board_path}", shell=True) + + if args.all: + serials = PandaJungle.list() + print(f"found {len(serials)} panda jungles(s) - {serials}") + else: + serials = [None] + + for s in serials: + with PandaJungle(serial=s) as p: + print("flashing", p.get_usb_serial()) + p.flash() + exit(1 if len(serials) == 0 else 0) diff --git a/panda_tici/board/jungle/jungle_health.h b/panda_tici/board/jungle/jungle_health.h new file mode 100644 index 0000000..931ed37 --- /dev/null +++ b/panda_tici/board/jungle/jungle_health.h @@ -0,0 +1,24 @@ +// 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; + float ch2_power; + float ch3_power; + float ch4_power; + float ch5_power; + float ch6_power; + uint16_t ch1_sbu1_mV; + uint16_t ch1_sbu2_mV; + uint16_t ch2_sbu1_mV; + uint16_t ch2_sbu2_mV; + uint16_t ch3_sbu1_mV; + uint16_t ch3_sbu2_mV; + uint16_t ch4_sbu1_mV; + uint16_t ch4_sbu2_mV; + uint16_t ch5_sbu1_mV; + uint16_t ch5_sbu2_mV; + uint16_t ch6_sbu1_mV; + uint16_t ch6_sbu2_mV; +}; diff --git a/panda_tici/board/jungle/main.c b/panda_tici/board/jungle/main.c new file mode 100644 index 0000000..3429c26 --- /dev/null +++ b/panda_tici/board/jungle/main.c @@ -0,0 +1,242 @@ +// ********************* Includes ********************* +#include "board/config.h" + +#include "opendbc/safety/safety.h" + +#include "board/drivers/led.h" +#include "board/drivers/pwm.h" +#include "board/drivers/usb.h" + +#include "board/early_init.h" +#include "board/provision.h" + +#include "board/health.h" +#include "jungle_health.h" + +#include "board/drivers/can_common.h" + +#ifdef STM32H7 + #include "board/drivers/fdcan.h" +#else + #include "board/drivers/bxcan.h" +#endif + +#include "board/obj/gitversion.h" + +#include "board/can_comms.h" +#include "main_comms.h" + + +// ********************* Serial debugging ********************* + +void debug_ring_callback(uart_ring *ring) { + char rcv; + while (get_char(ring, &rcv)) { + (void)injectc(ring, rcv); + } +} + +// ***************************** main code ***************************** + +// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck +void __initialize_hardware_early(void) { + early_initialization(); +} + +void __attribute__ ((noinline)) enable_fpu(void) { + // enable the FPU + SCB->CPACR |= ((3UL << (10U * 2U)) | (3UL << (11U * 2U))); +} + +// called at 8Hz +uint32_t loop_counter = 0U; +uint16_t button_press_cnt = 0U; +void tick_handler(void) { + if (TICK_TIMER->SR != 0) { + if (generated_can_traffic) { + for (int i = 0; i < 3; i++) { + if (can_health[i].transmit_error_cnt >= 128) { + (void)llcan_init(CANIF_FROM_CAN_NUM(i)); + } + } + } + + // decimated to 1Hz + if ((loop_counter % 8) == 0U) { + #ifdef DEBUG + print("** blink "); + print("rx:"); puth4(can_rx_q.r_ptr); print("-"); puth4(can_rx_q.w_ptr); print(" "); + print("tx1:"); puth4(can_tx1_q.r_ptr); print("-"); puth4(can_tx1_q.w_ptr); print(" "); + print("tx2:"); puth4(can_tx2_q.r_ptr); print("-"); puth4(can_tx2_q.w_ptr); print(" "); + print("tx3:"); puth4(can_tx3_q.r_ptr); print("-"); puth4(can_tx3_q.w_ptr); print("\n"); + #endif + + current_board->board_tick(); + + // check registers + check_registers(); + + // 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; + } + + led_set(LED_GREEN, green_led_enabled); + + // Check on button + bool current_button_status = current_board->get_button(); + + if (current_button_status && button_press_cnt == 10) { + 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 + if (current_board->has_sbu_sense) { + 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; + + loop_counter++; + } + TICK_TIMER->SR = 0; +} + + +int main(void) { + // Init interrupt table + init_interrupts(true); + + // shouldn't have interrupts here, but just in case + disable_interrupts(); + + // init early devices + clock_init(); + peripherals_init(); + detect_board_type(); + // red+green leds enabled until succesful USB init, as a debug indicator + led_set(LED_RED, true); + led_set(LED_GREEN, true); + + // print hello + print("\n\n\n************************ MAIN START ************************\n"); + + // check for non-supported board types + assert_fatal(hw_type != HW_TYPE_UNKNOWN, "Unsupported board type\n"); + + print("Config:\n"); + print(" Board type: 0x"); puth(hw_type); print("\n"); + + // init board + current_board->init(); + + // we have an FPU, let's use it! + enable_fpu(); + + microsecond_timer_init(); + + // 8Hz timer + REGISTER_INTERRUPT(TICK_TIMER_IRQ, tick_handler, 10U, FAULT_INTERRUPT_RATE_TICK) + tick_timer_init(); + +#ifdef DEBUG + print("DEBUG ENABLED\n"); +#endif + // enable USB (right before interrupts or enum can fail!) + usb_init(); + + led_set(LED_RED, false); + led_set(LED_GREEN, false); + + print("**** INTERRUPTS ON ****\n"); + enable_interrupts(); + + can_silent = false; + set_safety_hooks(SAFETY_ALLOUTPUT, 0U); + + 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++) { + if (generated_can_traffic) { + // fill up all the queues + can_ring *qs[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q}; + for (int j = 0; j < 3; j++) { + for (uint16_t n = 0U; n < can_slots_empty(qs[j]); n++) { + uint16_t i = cnt % 100U; + CANPacket_t to_send; + to_send.returned = 0U; + to_send.rejected = 0U; + to_send.extended = 0U; + to_send.addr = 0x200U + i; + to_send.bus = i % 3U; + to_send.data_len_code = i % 8U; + (void)memcpy(to_send.data, "\xff\xff\xff\xff\xff\xff\xff\xff", dlc_to_len[to_send.data_len_code]); + can_set_checksum(&to_send); + + can_send(&to_send, to_send.bus, true); + } + } + + delay(1000); + continue; + } + + // useful for debugging, fade breaks = panda is overloaded + for (uint32_t fade = 0U; fade < MAX_LED_FADE; fade += 1U) { + led_set(LED_RED, true); + delay(fade >> 4); + led_set(LED_RED, false); + delay((MAX_LED_FADE - fade) >> 4); + } + + for (uint32_t fade = MAX_LED_FADE; fade > 0U; fade -= 1U) { + led_set(LED_RED, true); + delay(fade >> 4); + led_set(LED_RED, false); + delay((MAX_LED_FADE - fade) >> 4); + } + } + + return 0; +} diff --git a/panda_tici/board/jungle/main_comms.h b/panda_tici/board/jungle/main_comms.h new file mode 100644 index 0000000..7c60a00 --- /dev/null +++ b/panda_tici/board/jungle/main_comms.h @@ -0,0 +1,267 @@ +extern int _app_start[0xc000]; // Only first 3 sectors of size 0x4000 are used + +bool generated_can_traffic = false; + +int get_jungle_health_pkt(void *dat) { + COMPILE_TIME_ASSERT(sizeof(struct jungle_health_t) <= USBPACKET_MAX_SIZE); + struct jungle_health_t * health = (struct jungle_health_t*)dat; + + health->uptime_pkt = uptime_cnt; + health->ch1_power = current_board->get_channel_power(1U); + health->ch2_power = current_board->get_channel_power(2U); + health->ch3_power = current_board->get_channel_power(3U); + health->ch4_power = current_board->get_channel_power(4U); + health->ch5_power = current_board->get_channel_power(5U); + health->ch6_power = current_board->get_channel_power(6U); + + health->ch1_sbu1_mV = current_board->get_sbu_mV(1U, SBU1); + health->ch1_sbu2_mV = current_board->get_sbu_mV(1U, SBU2); + health->ch2_sbu1_mV = current_board->get_sbu_mV(2U, SBU1); + health->ch2_sbu2_mV = current_board->get_sbu_mV(2U, SBU2); + health->ch3_sbu1_mV = current_board->get_sbu_mV(3U, SBU1); + health->ch3_sbu2_mV = current_board->get_sbu_mV(3U, SBU2); + health->ch4_sbu1_mV = current_board->get_sbu_mV(4U, SBU1); + health->ch4_sbu2_mV = current_board->get_sbu_mV(4U, SBU2); + health->ch5_sbu1_mV = current_board->get_sbu_mV(5U, SBU1); + health->ch5_sbu2_mV = current_board->get_sbu_mV(5U, SBU2); + health->ch6_sbu1_mV = current_board->get_sbu_mV(6U, SBU1); + health->ch6_sbu2_mV = current_board->get_sbu_mV(6U, SBU2); + + return sizeof(*health); +} + +// send on serial, first byte to select the ring +void comms_endpoint2_write(const uint8_t *data, uint32_t len) { + UNUSED(data); + UNUSED(len); +} + +int comms_control_handler(ControlPacket_t *req, uint8_t *resp) { + unsigned int resp_len = 0; + uint32_t time; + +#ifdef DEBUG_COMMS + print("raw control request: "); hexdump(req, sizeof(ControlPacket_t)); print("\n"); + print("- request "); puth(req->request); print("\n"); + print("- param1 "); puth(req->param1); print("\n"); + print("- param2 "); puth(req->param2); print("\n"); +#endif + + switch (req->request) { + // **** 0xa0: Set panda power. + case 0xa0: + current_board->set_panda_power((req->param1 == 1U)); + break; + // **** 0xa1: Set harness orientation. + case 0xa1: + current_board->set_harness_orientation(req->param1); + break; + // **** 0xa2: Set ignition. + case 0xa2: + current_board->set_ignition((req->param1 == 1U)); + break; + // **** 0xa3: Set panda power per channel by bitmask. + case 0xa3: + current_board->set_panda_individual_power(req->param1, (req->param2 > 0U)); + break; + // **** 0xa4: Enable generated CAN traffic. + case 0xa4: + generated_can_traffic = (req->param1 > 0U); + break; + // **** 0xa8: get microsecond timer + case 0xa8: + time = microsecond_timer_get(); + resp[0] = (time & 0x000000FFU); + resp[1] = ((time & 0x0000FF00U) >> 8U); + resp[2] = ((time & 0x00FF0000U) >> 16U); + resp[3] = ((time & 0xFF000000U) >> 24U); + resp_len = 4U; + break; + // **** 0xc0: reset communications + case 0xc0: + comms_can_reset(); + break; + // **** 0xc1: get hardware type + case 0xc1: + resp[0] = hw_type; + resp_len = 1; + break; + // **** 0xc2: CAN health stats + case 0xc2: + COMPILE_TIME_ASSERT(sizeof(can_health_t) <= USBPACKET_MAX_SIZE); + if (req->param1 < 3U) { + update_can_health_pkt(req->param1, 0U); + can_health[req->param1].can_speed = (bus_config[req->param1].can_speed / 10U); + can_health[req->param1].can_data_speed = (bus_config[req->param1].can_data_speed / 10U); + can_health[req->param1].canfd_enabled = bus_config[req->param1].canfd_enabled; + can_health[req->param1].brs_enabled = bus_config[req->param1].brs_enabled; + can_health[req->param1].canfd_non_iso = bus_config[req->param1].canfd_non_iso; + resp_len = sizeof(can_health[req->param1]); + (void)memcpy(resp, &can_health[req->param1], resp_len); + } + break; + // **** 0xc3: fetch MCU UID + case 0xc3: + (void)memcpy(resp, ((uint8_t *)UID_BASE), 12); + resp_len = 12; + break; + // **** 0xd0: fetch serial (aka the provisioned dongle ID) + case 0xd0: + // addresses are OTP + if (req->param1 == 1U) { + (void)memcpy(resp, (uint8_t *)DEVICE_SERIAL_NUMBER_ADDRESS, 0x10); + resp_len = 0x10; + } else { + get_provision_chunk(resp); + resp_len = PROVISION_CHUNK_LEN; + } + break; + // **** 0xd1: enter bootloader mode + case 0xd1: + // this allows reflashing of the bootstub + switch (req->param1) { + case 0: + // only allow bootloader entry on debug builds + #ifdef ALLOW_DEBUG + print("-> entering bootloader\n"); + enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; + NVIC_SystemReset(); + #endif + break; + case 1: + print("-> entering softloader\n"); + enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC; + NVIC_SystemReset(); + break; + default: + print("Bootloader mode invalid\n"); + break; + } + break; + // **** 0xd2: get health packet + case 0xd2: + resp_len = get_jungle_health_pkt(resp); + break; + // **** 0xd3: get first 64 bytes of signature + case 0xd3: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len], resp_len); + } + break; + // **** 0xd4: get second 64 bytes of signature + case 0xd4: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len + 64], resp_len); + } + break; + // **** 0xd6: get version + case 0xd6: + COMPILE_TIME_ASSERT(sizeof(gitversion) <= USBPACKET_MAX_SIZE); + (void)memcpy(resp, gitversion, sizeof(gitversion)); + resp_len = sizeof(gitversion) - 1U; + break; + // **** 0xd8: reset ST + case 0xd8: + NVIC_SystemReset(); + break; + // **** 0xdb: set OBD CAN multiplexing mode + case 0xdb: + if (req->param1 == 1U) { + // Enable OBD CAN + current_board->set_can_mode(CAN_MODE_OBD_CAN2); + } else { + // Disable OBD CAN + 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; + break; + // **** 0xde: set can bitrate + case 0xde: + if ((req->param1 < PANDA_CAN_CNT) && is_speed_valid(req->param2, speeds, sizeof(speeds)/sizeof(speeds[0]))) { + bus_config[req->param1].can_speed = req->param2; + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + // **** 0xe0: debug read + case 0xe0: + // read + while ((resp_len < MIN(req->length, USBPACKET_MAX_SIZE)) && get_char(get_ring_by_number(0), (char*)&resp[resp_len])) { + ++resp_len; + } + break; + // **** 0xe5: set CAN loopback (for testing) + case 0xe5: + can_loopback = (req->param1 > 0U); + can_init_all(); + break; + // **** 0xf1: Clear CAN ring buffer. + case 0xf1: + if (req->param1 == 0xFFFFU) { + print("Clearing CAN Rx queue\n"); + can_clear(&can_rx_q); + } else if (req->param1 < PANDA_CAN_CNT) { + print("Clearing CAN Tx queue\n"); + can_clear(can_queues[req->param1]); + } else { + print("Clearing CAN CAN ring buffer failed: wrong bus number\n"); + } + break; + // **** 0xf2: Clear debug ring buffer. + case 0xf2: + print("Clearing debug queue.\n"); + clear_uart_buff(get_ring_by_number(0)); + break; + // **** 0xf4: Set CAN transceiver enable pin + case 0xf4: + current_board->enable_can_transceiver(req->param1, req->param2 > 0U); + break; + // **** 0xf5: Set CAN silent mode + case 0xf5: + can_silent = (req->param1 > 0U); + can_init_all(); + break; + // **** 0xf7: enable/disable header pin by number + case 0xf7: + current_board->enable_header_pin(req->param1, req->param2 > 0U); + break; + // **** 0xf9: set CAN FD data bitrate + case 0xf9: + if ((req->param1 < PANDA_CAN_CNT) && + current_board->has_canfd && + is_speed_valid(req->param2, data_speeds, sizeof(data_speeds)/sizeof(data_speeds[0]))) { + bus_config[req->param1].can_data_speed = req->param2; + bus_config[req->param1].canfd_enabled = (req->param2 >= bus_config[req->param1].can_speed); + bus_config[req->param1].brs_enabled = (req->param2 > bus_config[req->param1].can_speed); + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + // **** 0xfc: set CAN FD non-ISO mode + case 0xfc: + if ((req->param1 < PANDA_CAN_CNT) && current_board->has_canfd) { + bus_config[req->param1].canfd_non_iso = (req->param2 != 0U); + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + default: + print("NO HANDLER "); + puth(req->request); + print("\n"); + break; + } + return resp_len; +} diff --git a/panda_tici/board/jungle/obj/.placeholder b/panda_tici/board/jungle/obj/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/panda_tici/board/jungle/recover.py b/panda_tici/board/jungle/recover.py new file mode 100755 index 0000000..3ff1ccb --- /dev/null +++ b/panda_tici/board/jungle/recover.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +import os +import time +import subprocess +import argparse + +from panda_tici import PandaJungle, PandaJungleDFU + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--all", action="store_true", help="Recover all panda jungle devices") + args = parser.parse_args() + + subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) {board_path}", shell=True) + + serials = PandaJungle.list() if args.all else [None] + for s in serials: + with PandaJungle(serial=s) as p: + print(f"putting {p.get_usb_serial()} in DFU mode") + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + + # wait for reset panda jungles to come back up + time.sleep(1) + + dfu_serials = PandaJungleDFU.list() + print(f"found {len(dfu_serials)} panda jungle(s) in DFU - {dfu_serials}") + for s in dfu_serials: + print("flashing", s) + PandaJungleDFU(s).recover() + exit(1 if len(dfu_serials) == 0 else 0) diff --git a/panda_tici/board/jungle/scripts/can_health.py b/panda_tici/board/jungle/scripts/can_health.py new file mode 100755 index 0000000..dba787f --- /dev/null +++ b/panda_tici/board/jungle/scripts/can_health.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import time +import re +from panda_tici import PandaJungle + +RED = '\033[91m' +GREEN = '\033[92m' + +def colorize_errors(value): + if isinstance(value, str): + if re.search(r'(?i)No error', value): + return f'{GREEN}{value}\033[0m' + elif re.search(r'(?i)(? 0.1: + dd = chr(27) + "[2J" + dd += "%5.2f\n" % (sec_since_boot() - start) + for (addr, bus), dat_log in sorted(all_msgs.items()): + dd += "%d: %s(%6d): %s\n" % (bus, "%04X(%4d)" % (addr, addr), len(dat_log), binascii.hexlify(dat_log[-1]).decode()) + print(dd) + lp = sec_since_boot() + +if __name__ == "__main__": + can_printer() diff --git a/panda_tici/board/jungle/scripts/debug_console.py b/panda_tici/board/jungle/scripts/debug_console.py new file mode 100755 index 0000000..39975ee --- /dev/null +++ b/panda_tici/board/jungle/scripts/debug_console.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import os +import sys +import time + +from panda_tici import PandaJungle + +setcolor = ["\033[1;32;40m", "\033[1;31;40m"] +unsetcolor = "\033[00m" + +if __name__ == "__main__": + while True: + try: + claim = os.getenv("CLAIM") is not None + + serials = PandaJungle.list() + if os.getenv("SERIAL"): + serials = [x for x in serials if x==os.getenv("SERIAL")] + + panda_jungles = [PandaJungle(x, claim=claim) for x in serials] + + if not len(panda_jungles): + sys.exit("no panda jungles found") + + while True: + for i, panda_jungle in enumerate(panda_jungles): + while True: + ret = panda_jungle.debug_read() + if len(ret) > 0: + sys.stdout.write(setcolor[i] + ret.decode('ascii') + unsetcolor) + sys.stdout.flush() + else: + break + time.sleep(0.01) + except Exception as e: + print(e) + print("panda jungle disconnected!") + time.sleep(0.5) diff --git a/panda_tici/board/jungle/scripts/echo_loopback_test.py b/panda_tici/board/jungle/scripts/echo_loopback_test.py new file mode 100755 index 0000000..d34b9a9 --- /dev/null +++ b/panda_tici/board/jungle/scripts/echo_loopback_test.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +import os +import time +import contextlib +import random +from termcolor import cprint + +from panda_tici import PandaJungle + +# This script is intended to be used in conjunction with the echo.py test script from panda_tici. +# It sends messages on bus 0, 1, 2 and checks for a reversed response to be sent back. + +################################################################# +############################# UTILS ############################# +################################################################# +def print_colored(text, color): + cprint(text + " "*40, color, end="\r") + +def get_test_string(): + return b"test"+os.urandom(4) + +################################################################# +############################# TEST ############################## +################################################################# + +def test_loopback(): + for bus in range(3): + # Clear can + jungle.can_clear(bus) + # Send a random message + address = random.randint(1, 2000) + data = get_test_string() + jungle.can_send(address, data, bus) + time.sleep(0.1) + + # Make sure it comes back reversed + incoming = jungle.can_recv() + found = False + for message in incoming: + incomingAddress, incomingData, incomingBus = message + if incomingAddress == address and incomingData == data[::-1] and incomingBus == bus: + found = True + break + if not found: + cprint("\nFAILED", "red") + raise AssertionError + +################################################################# +############################# MAIN ############################## +################################################################# +jungle = None +counter = 0 + +if __name__ == "__main__": + # Connect to jungle silently + print_colored("Connecting to jungle", "blue") + with open(os.devnull, "w") as devnull: + with contextlib.redirect_stdout(devnull): + jungle = PandaJungle() + jungle.set_panda_power(True) + jungle.set_ignition(False) + + # Run test + while True: + jungle.can_clear(0xFFFF) + test_loopback() + counter += 1 + print_colored(str(counter) + " loopback cycles complete", "blue") diff --git a/panda_tici/board/jungle/scripts/get_version.py b/panda_tici/board/jungle/scripts/get_version.py new file mode 100755 index 0000000..f525535 --- /dev/null +++ b/panda_tici/board/jungle/scripts/get_version.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 +from panda_tici import PandaJungle + +if __name__ == "__main__": + for p in PandaJungle.list(): + pp = PandaJungle(p) + print(f"{pp.get_serial()[0]}: {pp.get_version()}") + + diff --git a/panda_tici/board/jungle/scripts/health_test.py b/panda_tici/board/jungle/scripts/health_test.py new file mode 100755 index 0000000..d2bdc4e --- /dev/null +++ b/panda_tici/board/jungle/scripts/health_test.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +import time +from pprint import pprint + +from panda_tici import PandaJungle + +if __name__ == "__main__": + i = 0 + pi = 0 + + pj = PandaJungle() + while True: + st = time.monotonic() + while time.monotonic() - st < 1: + pj.health() + pj.can_health(0) + i += 1 + pprint(pj.health()) + print(f"Speed: {i - pi}Hz") + pi = i + diff --git a/panda_tici/board/jungle/scripts/loopback_test.py b/panda_tici/board/jungle/scripts/loopback_test.py new file mode 100755 index 0000000..e58ae8f --- /dev/null +++ b/panda_tici/board/jungle/scripts/loopback_test.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +import os +import time +import contextlib +import random +from termcolor import cprint + +from opendbc.car.structs import CarParams +from panda_tici import Panda, PandaJungle + +NUM_PANDAS_PER_TEST = 1 +FOR_RELEASE_BUILDS = os.getenv("RELEASE") is not None # Release builds do not have ALLOUTPUT mode + +BUS_SPEEDS = [125, 500, 1000] + +################################################################# +############################# UTILS ############################# +################################################################# +# To suppress the connection text +def silent_panda_connect(serial): + with open(os.devnull, "w") as devnull: + with contextlib.redirect_stdout(devnull): + panda = Panda(serial) + return panda + +def print_colored(text, color): + cprint(text + " "*40, color, end="\r") + +def connect_to_pandas(): + print_colored("Connecting to pandas", "blue") + # Connect to pandas + pandas = [] + for serial in panda_serials: + pandas.append(silent_panda_connect(serial)) + print_colored("Connected", "blue") + +def start_with_orientation(orientation): + print_colored("Restarting pandas with orientation " + str(orientation), "blue") + jungle.set_panda_power(False) + jungle.set_harness_orientation(orientation) + time.sleep(4) + jungle.set_panda_power(True) + time.sleep(2) + connect_to_pandas() + +def can_loopback(sender): + receivers = list(filter((lambda p: (p != sender)), [jungle] + pandas)) + + for bus in range(4): + obd = False + if bus == 3: + obd = True + bus = 1 + + # Clear buses + for receiver in receivers: + receiver.set_obd(obd) + receiver.can_clear(bus) # TX + receiver.can_clear(0xFFFF) # RX + + # Send a random string + addr = 0x18DB33F1 if FOR_RELEASE_BUILDS else random.randint(1, 2000) + string = b"test"+os.urandom(4) + sender.set_obd(obd) + time.sleep(0.2) + sender.can_send(addr, string, bus) + time.sleep(0.2) + + # Check if all receivers have indeed received them in their receiving buffers + for receiver in receivers: + content = receiver.can_recv() + + # Check amount of messages + if len(content) != 1: + raise Exception("Amount of received CAN messages (" + str(len(content)) + ") does not equal 1. Bus: " + str(bus) +" OBD: " + str(obd)) + + # Check content + if content[0][0] != addr or content[0][1] != string: + raise Exception("Received CAN message content or address does not match") + + # Check bus + if content[0][2] != bus: + raise Exception("Received CAN message bus does not match") + +################################################################# +############################# TEST ############################## +################################################################# + +def test_loopback(): + # disable safety modes + for panda in pandas: + panda.set_safety_mode(CarParams.SafetyModel.elm327 if FOR_RELEASE_BUILDS else CarParams.SafetyModel.allOutput) + + # perform loopback with jungle as a sender + can_loopback(jungle) + + # perform loopback with each possible panda as a sender + for panda in pandas: + can_loopback(panda) + + # enable safety modes + for panda in pandas: + panda.set_safety_mode(CarParams.SafetyModel.silent) + +################################################################# +############################# MAIN ############################## +################################################################# +jungle = None +pandas = [] # type: ignore +panda_serials = [] +counter = 0 + +if __name__ == "__main__": + # Connect to jungle silently + print_colored("Connecting to jungle", "blue") + with open(os.devnull, "w") as devnull: + with contextlib.redirect_stdout(devnull): + jungle = PandaJungle() + jungle.set_panda_power(True) + jungle.set_ignition(False) + + # Connect to new pandas before starting tests + print_colored("Waiting for " + str(NUM_PANDAS_PER_TEST) + " pandas to be connected", "yellow") + while True: + connected_serials = Panda.list() + if len(connected_serials) == NUM_PANDAS_PER_TEST: + panda_serials = connected_serials + break + + start_with_orientation(PandaJungle.HARNESS_ORIENTATION_1) + + # Set bus speeds + for device in pandas + [jungle]: + for bus in range(len(BUS_SPEEDS)): + device.set_can_speed_kbps(bus, BUS_SPEEDS[bus]) + + # Run test + while True: + test_loopback() + counter += 1 + print_colored(str(counter) + " loopback cycles complete", "blue") diff --git a/panda_tici/board/jungle/scripts/spam_can.py b/panda_tici/board/jungle/scripts/spam_can.py new file mode 100755 index 0000000..532c7b7 --- /dev/null +++ b/panda_tici/board/jungle/scripts/spam_can.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +import os +import random +from opendbc.car.structs import CarParams +from panda_tici import PandaJungle + +def get_test_string(): + return b"test" + os.urandom(10) + +if __name__ == "__main__": + p = PandaJungle() + + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + print("Spamming all buses...") + while True: + at = random.randint(1, 2000) + st = get_test_string()[0:8] + bus = random.randint(0, 2) + p.can_send(at, st, bus) + # print("Sent message on bus: ", bus) diff --git a/panda_tici/board/jungle/scripts/start.py b/panda_tici/board/jungle/scripts/start.py new file mode 100755 index 0000000..03ee9d9 --- /dev/null +++ b/panda_tici/board/jungle/scripts/start.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +import sys + +from panda_tici import PandaJungle + +if __name__ == "__main__": + jungle = PandaJungle() + + # If first argument specified, it sets the ignition (0 or 1) + if len(sys.argv) > 1: + if sys.argv[1] == '1': + jungle.set_ignition(True) + else: + jungle.set_ignition(False) + jungle.set_harness_orientation(1) + jungle.set_panda_power(True) + + diff --git a/panda_tici/board/jungle/stm32f4/board.h b/panda_tici/board/jungle/stm32f4/board.h new file mode 100644 index 0000000..0adf792 --- /dev/null +++ b/panda_tici/board/jungle/stm32f4/board.h @@ -0,0 +1,7 @@ +#include "boards/board_declarations.h" +#include "boards/board_v1.h" + +void detect_board_type(void) { + hw_type = HW_TYPE_V1; + current_board = &board_v1; +} diff --git a/panda_tici/board/jungle/stm32h7/board.h b/panda_tici/board/jungle/stm32h7/board.h new file mode 100644 index 0000000..4fe4fa4 --- /dev/null +++ b/panda_tici/board/jungle/stm32h7/board.h @@ -0,0 +1,9 @@ +#include "boards/board_declarations.h" + +#include "stm32h7/lladc.h" +#include "boards/board_v2.h" + +void detect_board_type(void) { + hw_type = HW_TYPE_V2; + current_board = &board_v2; +} diff --git a/panda_tici/board/jungle/stm32h7/lladc.h b/panda_tici/board/jungle/stm32h7/lladc.h new file mode 100644 index 0000000..06b742d --- /dev/null +++ b/panda_tici/board/jungle/stm32h7/lladc.h @@ -0,0 +1,54 @@ + +typedef struct { + ADC_TypeDef *adc; + uint8_t channel; +} adc_channel_t; + +void adc_init(ADC_TypeDef *adc) { + adc->CR &= ~(ADC_CR_DEEPPWD); // Reset deep-power-down mode + adc->CR |= ADC_CR_ADVREGEN; // Enable ADC regulator + while(!(adc->ISR & ADC_ISR_LDORDY) && (adc != ADC3)); + + if (adc != ADC3) { + adc->CR &= ~(ADC_CR_ADCALDIF); // Choose single-ended calibration + adc->CR |= ADC_CR_ADCALLIN; // Lineriality calibration + } + adc->CR |= ADC_CR_ADCAL; // Start calibrtation + while((adc->CR & ADC_CR_ADCAL) != 0); + + adc->ISR |= ADC_ISR_ADRDY; + adc->CR |= ADC_CR_ADEN; + while(!(adc->ISR & ADC_ISR_ADRDY)); +} + +uint16_t adc_get_raw(ADC_TypeDef *adc, uint8_t channel) { + adc->SQR1 &= ~(ADC_SQR1_L); + adc->SQR1 = ((uint32_t) channel << 6U); + + if (channel < 10U) { + adc->SMPR1 = (0x7U << (channel * 3U)); + } else { + adc->SMPR2 = (0x7U << ((channel - 10U) * 3U)); + } + adc->PCSEL_RES0 = (0x1U << channel); + + adc->CR |= ADC_CR_ADSTART; + while (!(adc->ISR & ADC_ISR_EOC)); + + uint16_t res = adc->DR; + + while (!(adc->ISR & ADC_ISR_EOS)); + adc->ISR |= ADC_ISR_EOS; + + return res; +} + +uint16_t adc_get_mV(ADC_TypeDef *adc, uint8_t channel) { + uint16_t ret = 0; + if ((adc == ADC1) || (adc == ADC2)) { + ret = (adc_get_raw(adc, channel) * current_board->avdd_mV) / 65535U; + } else if (adc == ADC3) { + ret = (adc_get_raw(adc, channel) * current_board->avdd_mV) / 4095U; + } else {} + return ret; +} diff --git a/panda_tici/board/libc.h b/panda_tici/board/libc.h new file mode 100644 index 0000000..c5f0219 --- /dev/null +++ b/panda_tici/board/libc.h @@ -0,0 +1,77 @@ +// **** libc **** + +void delay(uint32_t a) { + volatile uint32_t i; + for (i = 0; i < a; i++); +} + +void assert_fatal(bool condition, const char *msg) { + if (!condition) { + print("ASSERT FAILED\n"); + print(msg); + while (1) { + // hang + } + } +} + +// cppcheck-suppress misra-c2012-21.2 +void *memset(void *str, int c, unsigned int n) { + uint8_t *s = str; + for (unsigned int i = 0; i < n; i++) { + *s = c; + s++; + } + return str; +} + +#define UNALIGNED(X, Y) \ + (((uint32_t)(X) & (sizeof(uint32_t) - 1U)) | ((uint32_t)(Y) & (sizeof(uint32_t) - 1U))) + +// cppcheck-suppress misra-c2012-21.2 +void *memcpy(void *dest, const void *src, unsigned int len) { + unsigned int n = len; + uint8_t *d8 = dest; + const uint8_t *s8 = src; + + if ((n >= 4U) && !UNALIGNED(s8, d8)) { + uint32_t *d32 = (uint32_t *)d8; // cppcheck-suppress misra-c2012-11.3 ; already checked that it's properly aligned + const uint32_t *s32 = (const uint32_t *)s8; // cppcheck-suppress misra-c2012-11.3 ; already checked that it's properly aligned + + while(n >= 16U) { + *d32 = *s32; d32++; s32++; + *d32 = *s32; d32++; s32++; + *d32 = *s32; d32++; s32++; + *d32 = *s32; d32++; s32++; + n -= 16U; + } + + while(n >= 4U) { + *d32 = *s32; d32++; s32++; + n -= 4U; + } + + d8 = (uint8_t *)d32; + s8 = (const uint8_t *)s32; + } + while (n-- > 0U) { + *d8 = *s8; d8++; s8++; + } + return dest; +} + +// cppcheck-suppress misra-c2012-21.2 +int memcmp(const void * ptr1, const void * ptr2, unsigned int num) { + int ret = 0; + const uint8_t *p1 = ptr1; + const uint8_t *p2 = ptr2; + for (unsigned int i = 0; i < num; i++) { + if (*p1 != *p2) { + ret = -1; + break; + } + p1++; + p2++; + } + return ret; +} diff --git a/panda_tici/board/main.c b/panda_tici/board/main.c new file mode 100644 index 0000000..b88e986 --- /dev/null +++ b/panda_tici/board/main.c @@ -0,0 +1,418 @@ +// ********************* Includes ********************* +#include "config.h" + +#include "drivers/led.h" +#include "drivers/pwm.h" +#include "drivers/usb.h" +#include "drivers/simple_watchdog.h" +#include "drivers/bootkick.h" + +#include "early_init.h" +#include "provision.h" + +#include "opendbc/safety/safety.h" + +#include "health.h" + +#include "drivers/can_common.h" + +#ifdef STM32H7 + #include "drivers/fdcan.h" +#else + #include "drivers/bxcan.h" +#endif + +#include "power_saving.h" + +#include "obj/gitversion.h" + +#include "can_comms.h" +#include "main_comms.h" + + +// ********************* Serial debugging ********************* + +static bool check_started(void) { + bool started = current_board->check_ignition() || ignition_can; + return started; +} + +void debug_ring_callback(uart_ring *ring) { + char rcv; + while (get_char(ring, &rcv)) { + (void)put_char(ring, rcv); // misra-c2012-17.7: cast to void is ok: debug function + + // only allow bootloader entry on debug builds + #ifdef ALLOW_DEBUG + // jump to DFU flash + if (rcv == 'z') { + enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; + NVIC_SystemReset(); + } + #endif + + // normal reset + if (rcv == 'x') { + NVIC_SystemReset(); + } + } +} + +// ****************************** safety mode ****************************** + +// this is the only way to leave silent mode +void set_safety_mode(uint16_t mode, uint16_t param) { + uint16_t mode_copy = mode; + int err = set_safety_hooks(mode_copy, param); + if (err == -1) { + 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 succesfully set + assert_fatal(err == 0, "Error: Failed setting SILENT mode. Hanging\n"); + } + safety_tx_blocked = 0; + safety_rx_invalid = 0; + + switch (mode_copy) { + case SAFETY_SILENT: + set_intercept_relay(false, false); + if (current_board->harness_config->has_harness) { + current_board->set_can_mode(CAN_MODE_NORMAL); + } + can_silent = true; + break; + case SAFETY_NOOUTPUT: + set_intercept_relay(false, false); + if (current_board->harness_config->has_harness) { + current_board->set_can_mode(CAN_MODE_NORMAL); + } + can_silent = false; + break; + case SAFETY_ELM327: + set_intercept_relay(false, false); + heartbeat_counter = 0U; + heartbeat_lost = false; + if (current_board->harness_config->has_harness) { + // Clear any pending messages in the can core (i.e. sending while comma power is unplugged) + // TODO: rewrite using hardware queues rather than fifo to cancel specific messages + can_clear_send(CANIF_FROM_CAN_NUM(1), 1); + if (param == 0U) { + current_board->set_can_mode(CAN_MODE_OBD_CAN2); + } else { + current_board->set_can_mode(CAN_MODE_NORMAL); + } + } + can_silent = false; + break; + default: + set_intercept_relay(true, false); + heartbeat_counter = 0U; + heartbeat_lost = false; + if (current_board->harness_config->has_harness) { + current_board->set_can_mode(CAN_MODE_NORMAL); + } + can_silent = false; + break; + } + can_init_all(); +} + +bool is_car_safety_mode(uint16_t mode) { + return (mode != SAFETY_SILENT) && + (mode != SAFETY_NOOUTPUT) && + (mode != SAFETY_ALLOUTPUT) && + (mode != SAFETY_ELM327); +} + +// ***************************** main code ***************************** + +// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck +// cppcheck-suppress misra-c2012-8.4 +void __initialize_hardware_early(void) { + early_initialization(); +} + +static void __attribute__ ((noinline)) enable_fpu(void) { + // enable the FPU + SCB->CPACR |= ((3UL << (10U * 2U)) | (3UL << (11U * 2U))); +} + +// go into SILENT when heartbeat isn't received for this amount of seconds. +#define HEARTBEAT_IGNITION_CNT_ON 5U +#define HEARTBEAT_IGNITION_CNT_OFF 2U + +// called at 8Hz +static void tick_handler(void) { + static uint32_t siren_countdown = 0; // siren plays while countdown > 0 + static uint32_t controls_allowed_countdown = 0; + static uint8_t prev_harness_status = HARNESS_STATUS_NC; + static uint8_t loop_counter = 0U; + static bool relay_malfunction_prev = false; + + if (TICK_TIMER->SR != 0U) { + + // siren + current_board->set_siren((loop_counter & 1U) && (siren_enabled || (siren_countdown > 0U))); + + // tick drivers at 8Hz + fan_tick(); + harness_tick(); + simple_watchdog_kick(); + sound_tick(); + + if (relay_malfunction_prev != relay_malfunction) { + if (relay_malfunction) { + fault_occurred(FAULT_RELAY_MALFUNCTION); + } else { + fault_recovered(FAULT_RELAY_MALFUNCTION); + } + } + relay_malfunction_prev = relay_malfunction; + + // re-init everything that uses harness status + if (harness.status != prev_harness_status) { + prev_harness_status = harness.status; + can_set_orientation(harness.status == HARNESS_STATUS_FLIPPED); + + // 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); + } + + // decimated to 1Hz + if (loop_counter == 0U) { + // can_live = pending_can_live; + + //puth(usart1_dma); print(" "); puth(DMA2_Stream5->M0AR); print(" "); puth(DMA2_Stream5->NDTR); print("\n"); + + // reset this every 16th pass + if ((uptime_cnt & 0xFU) == 0U) { + pending_can_live = 0; + } + #ifdef DEBUG + print("** blink "); + print("rx:"); puth4(can_rx_q.r_ptr); print("-"); puth4(can_rx_q.w_ptr); print(" "); + print("tx1:"); puth4(can_tx1_q.r_ptr); print("-"); puth4(can_tx1_q.w_ptr); print(" "); + print("tx2:"); puth4(can_tx2_q.r_ptr); print("-"); puth4(can_tx2_q.w_ptr); print(" "); + 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 + led_set(LED_GREEN, controls_allowed | green_led_enabled); + + // 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)); + + const bool recent_heartbeat = heartbeat_counter == 0U; + + // tick drivers at 1Hz + bootkick_tick(check_started(), recent_heartbeat); + + // increase heartbeat counter and cap it at the uint32 limit + if (heartbeat_counter < UINT32_MAX) { + heartbeat_counter += 1U; + } + + // disabling heartbeat not allowed while in safety mode + if (is_car_safety_mode(current_safety_mode)) { + heartbeat_disabled = false; + } + + if (siren_countdown > 0U) { + siren_countdown -= 1U; + } + + if (controls_allowed || heartbeat_engaged) { + controls_allowed_countdown = 5U; + } else if (controls_allowed_countdown > 0U) { + controls_allowed_countdown -= 1U; + } else { + + } + + // exit controls allowed if unused by openpilot for a few seconds + if (controls_allowed && !heartbeat_engaged) { + heartbeat_engaged_mismatches += 1U; + if (heartbeat_engaged_mismatches >= 3U) { + controls_allowed = false; + } + } else { + heartbeat_engaged_mismatches = 0U; + } + + if (!heartbeat_disabled) { + // if the heartbeat has been gone for a while, go to SILENT safety mode and enter power save + if (heartbeat_counter >= (check_started() ? HEARTBEAT_IGNITION_CNT_ON : HEARTBEAT_IGNITION_CNT_OFF)) { + print("device hasn't sent a heartbeat for 0x"); + puth(heartbeat_counter); + print(" seconds. Safety is set to SILENT mode.\n"); + + if (controls_allowed_countdown > 0U) { + siren_countdown = 3U; + controls_allowed_countdown = 0U; + } + + // set flag to indicate the heartbeat was lost + if (is_car_safety_mode(current_safety_mode)) { + heartbeat_lost = true; + } + + // clear heartbeat engaged state + heartbeat_engaged = false; + + if (current_safety_mode != SAFETY_SILENT) { + set_safety_mode(SAFETY_SILENT, 0U); + } + + if (power_save_status != POWER_SAVE_STATUS_ENABLED) { + set_power_save_state(POWER_SAVE_STATUS_ENABLED); + } + + // Also disable IR when the heartbeat goes missing + current_board->set_ir_power(0U); + + // Run fan when device is up but not talking to us. + // The bootloader enables the SOM GPIO on boot. + fan_set_power(current_board->read_som_gpio() ? 30U : 0U); + } + } + + // check registers + check_registers(); + + // set ignition_can to false after 2s of no CAN seen + if (ignition_can_cnt > 2U) { + ignition_can = false; + } + + // on to the next one + uptime_cnt += 1U; + safety_mode_cnt += 1U; + ignition_can_cnt += 1U; + + // synchronous safety check + safety_tick(¤t_safety_config); + } + + loop_counter++; + loop_counter %= 8U; + } + TICK_TIMER->SR = 0; +} + +int main(void) { + // Init interrupt table + init_interrupts(true); + + // shouldn't have interrupts here, but just in case + disable_interrupts(); + + // init early devices + clock_init(); + peripherals_init(); + detect_board_type(); + led_init(); + // red+green leds enabled until succesful USB/SPI init, as a debug indicator + led_set(LED_RED, true); + led_set(LED_GREEN, true); + adc_init(); + + // print hello + print("\n\n\n************************ MAIN START ************************\n"); + + // check for non-supported board types + assert_fatal(hw_type != HW_TYPE_UNKNOWN, "Unsupported board type"); + + print("Config:\n"); + print(" Board type: 0x"); puth(hw_type); print("\n"); + + // init board + current_board->init(); + current_board->set_can_mode(CAN_MODE_NORMAL); + if (current_board->harness_config->has_harness) { + harness_init(); + } + + // panda has an FPU, let's use it! + enable_fpu(); + + microsecond_timer_init(); + + current_board->set_siren(false); + if (current_board->fan_max_rpm > 0U) { + fan_init(); + } + + // init to SILENT and can silent + set_safety_mode(SAFETY_SILENT, 0U); + + // enable CAN TXs + enable_can_transceivers(true); + + // init watchdog for heartbeat loop, fed at 8Hz + simple_watchdog_init(FAULT_HEARTBEAT_LOOP_WATCHDOG, (3U * 1000000U / 8U)); + + // 8Hz timer + REGISTER_INTERRUPT(TICK_TIMER_IRQ, tick_handler, 10U, FAULT_INTERRUPT_RATE_TICK) + tick_timer_init(); + +#ifdef DEBUG + print("DEBUG ENABLED\n"); +#endif + // enable USB (right before interrupts or enum can fail!) + usb_init(); + +#ifdef ENABLE_SPI + if (current_board->has_spi) { + gpio_spi_init(); + spi_init(); + } +#endif + + led_set(LED_RED, false); + led_set(LED_GREEN, false); + led_set(LED_BLUE, false); + + print("**** INTERRUPTS ON ****\n"); + enable_interrupts(); + + // LED should keep on blinking all the time + while (true) { + if (power_save_status == POWER_SAVE_STATUS_DISABLED) { + #ifdef DEBUG_FAULTS + if (fault_status == FAULT_STATUS_NONE) { + #endif + // useful for debugging, fade breaks = panda is overloaded + for (uint32_t fade = 0U; fade < MAX_LED_FADE; fade += 1U) { + led_set(LED_RED, true); + delay(fade >> 4); + led_set(LED_RED, false); + delay((MAX_LED_FADE - fade) >> 4); + } + + for (uint32_t fade = MAX_LED_FADE; fade > 0U; fade -= 1U) { + led_set(LED_RED, true); + delay(fade >> 4); + led_set(LED_RED, false); + delay((MAX_LED_FADE - fade) >> 4); + } + + #ifdef DEBUG_FAULTS + } else { + led_set(LED_RED, 1); + delay(512000U); + led_set(LED_RED, 0); + delay(512000U); + } + #endif + } else { + __WFI(); + SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + } + } + + return 0; +} diff --git a/panda_tici/board/main_comms.h b/panda_tici/board/main_comms.h new file mode 100644 index 0000000..5c3ca55 --- /dev/null +++ b/panda_tici/board/main_comms.h @@ -0,0 +1,395 @@ +extern int _app_start[0xc000]; // Only first 3 sectors of size 0x4000 are used + +// Prototypes +void set_safety_mode(uint16_t mode, uint16_t param); +bool is_car_safety_mode(uint16_t mode); + +static int get_health_pkt(void *dat) { + COMPILE_TIME_ASSERT(sizeof(struct health_t) <= USBPACKET_MAX_SIZE); + struct health_t * health = (struct health_t*)dat; + + health->uptime_pkt = uptime_cnt; + health->voltage_pkt = current_board->read_voltage_mV(); + health->current_pkt = current_board->read_current_mA(); + + // Use the GPIO pin to determine ignition or use a CAN based logic + health->ignition_line_pkt = (uint8_t)(current_board->check_ignition()); + health->ignition_can_pkt = ignition_can; + + health->controls_allowed_pkt = controls_allowed; + health->safety_tx_blocked_pkt = safety_tx_blocked; + health->safety_rx_invalid_pkt = safety_rx_invalid; + health->tx_buffer_overflow_pkt = tx_buffer_overflow; + health->rx_buffer_overflow_pkt = rx_buffer_overflow; + health->car_harness_status_pkt = harness.status; + 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->heartbeat_lost_pkt = heartbeat_lost; + health->safety_rx_checks_invalid_pkt = safety_rx_checks_invalid; + + health->spi_error_count_pkt = spi_error_count; + + health->fault_status_pkt = fault_status; + health->faults_pkt = faults; + + health->interrupt_load_pkt = interrupt_load; + + health->fan_power = fan_state.power; + + health->sbu1_voltage_mV = harness.sbu1_voltage_mV; + health->sbu2_voltage_mV = harness.sbu2_voltage_mV; + + health->som_reset_triggered = bootkick_reset_triggered; + + return sizeof(*health); +} + +// send on serial, first byte to select the ring +void comms_endpoint2_write(const uint8_t *data, uint32_t len) { + uart_ring *ur = get_ring_by_number(data[0]); + if ((len != 0U) && (ur != NULL)) { + if ((data[0] < 2U) || (data[0] >= 4U)) { + for (uint32_t i = 1; i < len; i++) { + while (!put_char(ur, data[i])) { + // wait + } + } + } + } +} + +int comms_control_handler(ControlPacket_t *req, uint8_t *resp) { + unsigned int resp_len = 0; + uart_ring *ur = NULL; + uint32_t time; + +#ifdef DEBUG_COMMS + print("raw control request: "); hexdump(req, sizeof(ControlPacket_t)); print("\n"); + print("- request "); puth(req->request); print("\n"); + print("- param1 "); puth(req->param1); print("\n"); + print("- param2 "); puth(req->param2); print("\n"); +#endif + + switch (req->request) { + // **** 0xa8: get microsecond timer + case 0xa8: + time = microsecond_timer_get(); + resp[0] = (time & 0x000000FFU); + resp[1] = ((time & 0x0000FF00U) >> 8U); + resp[2] = ((time & 0x00FF0000U) >> 16U); + resp[3] = ((time & 0xFF000000U) >> 24U); + resp_len = 4U; + break; + // **** 0xb0: set IR power + case 0xb0: + current_board->set_ir_power(req->param1); + break; + // **** 0xb1: set fan power + case 0xb1: + fan_set_power(req->param1); + break; + // **** 0xb2: get fan rpm + case 0xb2: + resp[0] = (fan_state.rpm & 0x00FFU); + resp[1] = ((fan_state.rpm & 0xFF00U) >> 8U); + resp_len = 2; + break; + // **** 0xc0: reset communications + case 0xc0: + comms_can_reset(); + break; + // **** 0xc1: get hardware type + case 0xc1: + resp[0] = hw_type; + resp_len = 1; + break; + // **** 0xc2: CAN health stats + case 0xc2: + COMPILE_TIME_ASSERT(sizeof(can_health_t) <= USBPACKET_MAX_SIZE); + if (req->param1 < 3U) { + update_can_health_pkt(req->param1, 0U); + can_health[req->param1].can_speed = (bus_config[req->param1].can_speed / 10U); + can_health[req->param1].can_data_speed = (bus_config[req->param1].can_data_speed / 10U); + can_health[req->param1].canfd_enabled = bus_config[req->param1].canfd_enabled; + can_health[req->param1].brs_enabled = bus_config[req->param1].brs_enabled; + can_health[req->param1].canfd_non_iso = bus_config[req->param1].canfd_non_iso; + resp_len = sizeof(can_health[req->param1]); + (void)memcpy(resp, (uint8_t*)(&can_health[req->param1]), resp_len); + } + break; + // **** 0xc3: fetch MCU UID + case 0xc3: + (void)memcpy(resp, ((uint8_t *)UID_BASE), 12); + resp_len = 12; + break; + // **** 0xc4: get interrupt call rate + case 0xc4: + if (req->param1 < NUM_INTERRUPTS) { + uint32_t load = interrupts[req->param1].call_rate; + resp[0] = (load & 0x000000FFU); + resp[1] = ((load & 0x0000FF00U) >> 8U); + resp[2] = ((load & 0x00FF0000U) >> 16U); + resp[3] = ((load & 0xFF000000U) >> 24U); + resp_len = 4U; + } + break; + // **** 0xc5: DEBUG: drive relay + case 0xc5: + set_intercept_relay((req->param1 & 0x1U), (req->param1 & 0x2U)); + break; + // **** 0xc6: DEBUG: read SOM GPIO + case 0xc6: + resp[0] = current_board->read_som_gpio(); + resp_len = 1; + break; + // **** 0xd0: fetch serial (aka the provisioned dongle ID) + case 0xd0: + // addresses are OTP + if (req->param1 == 1U) { + (void)memcpy(resp, (uint8_t *)DEVICE_SERIAL_NUMBER_ADDRESS, 0x10); + resp_len = 0x10; + } else { + get_provision_chunk(resp); + resp_len = PROVISION_CHUNK_LEN; + } + break; + // **** 0xd1: enter bootloader mode + case 0xd1: + // this allows reflashing of the bootstub + switch (req->param1) { + case 0: + // only allow bootloader entry on debug builds + #ifdef ALLOW_DEBUG + print("-> entering bootloader\n"); + enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; + NVIC_SystemReset(); + #endif + break; + case 1: + print("-> entering softloader\n"); + enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC; + NVIC_SystemReset(); + break; + default: + print("Bootloader mode invalid\n"); + break; + } + break; + // **** 0xd2: get health packet + case 0xd2: + resp_len = get_health_pkt(resp); + break; + // **** 0xd3: get first 64 bytes of signature + case 0xd3: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len], resp_len); + } + break; + // **** 0xd4: get second 64 bytes of signature + case 0xd4: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len + 64], resp_len); + } + break; + // **** 0xd6: get version + case 0xd6: + COMPILE_TIME_ASSERT(sizeof(gitversion) <= USBPACKET_MAX_SIZE); + (void)memcpy(resp, gitversion, sizeof(gitversion)); + resp_len = sizeof(gitversion) - 1U; + break; + // **** 0xd8: reset ST + case 0xd8: + NVIC_SystemReset(); + break; + // **** 0xdb: set OBD CAN multiplexing mode + case 0xdb: + if (current_board->harness_config->has_harness) { + if (req->param1 == 1U) { + // Enable OBD CAN + current_board->set_can_mode(CAN_MODE_OBD_CAN2); + } else { + // Disable OBD CAN + current_board->set_can_mode(CAN_MODE_NORMAL); + } + } + break; + + // **** 0xdc: set safety mode + 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; + break; + // **** 0xde: set can bitrate + case 0xde: + if ((req->param1 < PANDA_CAN_CNT) && is_speed_valid(req->param2, speeds, sizeof(speeds)/sizeof(speeds[0]))) { + bus_config[req->param1].can_speed = req->param2; + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + // **** 0xdf: set alternative experience + case 0xdf: + // you can only set this if you are in a non car safety mode + if (!is_car_safety_mode(current_safety_mode)) { + alternative_experience = req->param1; + } + break; + // **** 0xe0: uart read + case 0xe0: + ur = get_ring_by_number(req->param1); + if (!ur) { + break; + } + + // read + uint16_t req_length = MIN(req->length, USBPACKET_MAX_SIZE); + while ((resp_len < req_length) && + get_char(ur, (char*)&resp[resp_len])) { + ++resp_len; + } + break; + // **** 0xe1: uart set baud rate + case 0xe1: + ur = get_ring_by_number(req->param1); + if (!ur) { + break; + } + uart_set_baud(ur->uart, req->param2); + break; + // **** 0xe2: uart set parity + case 0xe2: + ur = get_ring_by_number(req->param1); + if (!ur) { + break; + } + switch (req->param2) { + case 0: + // disable parity, 8-bit + ur->uart->CR1 &= ~(USART_CR1_PCE | USART_CR1_M); + break; + case 1: + // even parity, 9-bit + ur->uart->CR1 &= ~USART_CR1_PS; + ur->uart->CR1 |= USART_CR1_PCE | USART_CR1_M; + break; + case 2: + // odd parity, 9-bit + ur->uart->CR1 |= USART_CR1_PS; + ur->uart->CR1 |= USART_CR1_PCE | USART_CR1_M; + break; + default: + break; + } + break; + // **** 0xe4: uart set baud rate extended + case 0xe4: + ur = get_ring_by_number(req->param1); + if (!ur) { + break; + } + uart_set_baud(ur->uart, (int)req->param2*300); + break; + // **** 0xe5: set CAN loopback (for testing) + case 0xe5: + can_loopback = req->param1 > 0U; + can_init_all(); + break; + // **** 0xe6: set custom clock source period and pulse length + case 0xe6: + clock_source_set_timer_params(req->param1, req->param2); + break; + // **** 0xe7: set power save state + case 0xe7: + set_power_save_state(req->param1); + break; + // **** 0xe8: set can-fd auto swithing mode + case 0xe8: + bus_config[req->param1].canfd_auto = req->param2 > 0U; + break; + // **** 0xf1: Clear CAN ring buffer. + case 0xf1: + if (req->param1 == 0xFFFFU) { + print("Clearing CAN Rx queue\n"); + can_clear(&can_rx_q); + } else if (req->param1 < PANDA_CAN_CNT) { + print("Clearing CAN Tx queue\n"); + can_clear(can_queues[req->param1]); + } else { + print("Clearing CAN CAN ring buffer failed: wrong bus number\n"); + } + break; + // **** 0xf2: Clear UART ring buffer. + case 0xf2: + { + uart_ring * rb = get_ring_by_number(req->param1); + if (rb != NULL) { + print("Clearing UART queue.\n"); + clear_uart_buff(rb); + } + break; + } + // **** 0xf3: Heartbeat. Resets heartbeat counter. + case 0xf3: + { + heartbeat_counter = 0U; + heartbeat_lost = false; + heartbeat_disabled = false; + heartbeat_engaged = (req->param1 == 1U); + break; + } + // **** 0xf6: set siren enabled + case 0xf6: + siren_enabled = (req->param1 != 0U); + break; + // **** 0xf7: set green led enabled + case 0xf7: + green_led_enabled = (req->param1 != 0U); + break; + // **** 0xf8: disable heartbeat checks + case 0xf8: + if (!is_car_safety_mode(current_safety_mode)) { + heartbeat_disabled = true; + } + break; + // **** 0xf9: set CAN FD data bitrate + case 0xf9: + if ((req->param1 < PANDA_CAN_CNT) && + current_board->has_canfd && + is_speed_valid(req->param2, data_speeds, sizeof(data_speeds)/sizeof(data_speeds[0]))) { + bus_config[req->param1].can_data_speed = req->param2; + bus_config[req->param1].canfd_enabled = (req->param2 >= bus_config[req->param1].can_speed); + bus_config[req->param1].brs_enabled = (req->param2 > bus_config[req->param1].can_speed); + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + // **** 0xfc: set CAN FD non-ISO mode + case 0xfc: + if ((req->param1 < PANDA_CAN_CNT) && current_board->has_canfd) { + bus_config[req->param1].canfd_non_iso = (req->param2 != 0U); + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + default: + print("NO HANDLER "); + puth(req->request); + print("\n"); + break; + } + return resp_len; +} diff --git a/panda_tici/board/main_declarations.h b/panda_tici/board/main_declarations.h new file mode 100644 index 0000000..3b4a807 --- /dev/null +++ b/panda_tici/board/main_declarations.h @@ -0,0 +1,25 @@ +#pragma once + +// ******************** Prototypes ******************** +void print(const char *a); +void puth(unsigned int i); +void puth4(unsigned int i); +void hexdump(const void *a, int 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); + +// ********************* Globals ********************** +extern uint8_t hw_type; +extern board *current_board; +extern uint32_t uptime_cnt; +extern bool green_led_enabled; + +// heartbeat state +extern uint32_t heartbeat_counter; +extern bool heartbeat_lost; +extern bool heartbeat_disabled; // set over USB + +// siren state +extern bool siren_enabled; diff --git a/panda_tici/board/main_definitions.h b/panda_tici/board/main_definitions.h new file mode 100644 index 0000000..137d987 --- /dev/null +++ b/panda_tici/board/main_definitions.h @@ -0,0 +1,15 @@ +#include "main_declarations.h" + +// ********************* Globals ********************** +uint8_t hw_type = 0; +board *current_board; +uint32_t uptime_cnt = 0; +bool green_led_enabled = false; + +// heartbeat state +uint32_t heartbeat_counter = 0; +bool heartbeat_lost = false; +bool heartbeat_disabled = false; // set over USB + +// siren state +bool siren_enabled = false; diff --git a/panda_tici/board/obj/.placeholder b/panda_tici/board/obj/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/panda_tici/board/power_saving.h b/panda_tici/board/power_saving.h new file mode 100644 index 0000000..dea4649 --- /dev/null +++ b/panda_tici/board/power_saving.h @@ -0,0 +1,52 @@ +#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 = (current_board->harness_config->has_harness && (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; + } +} diff --git a/panda_tici/board/power_saving_declarations.h b/panda_tici/board/power_saving_declarations.h new file mode 100644 index 0000000..7a474a5 --- /dev/null +++ b/panda_tici/board/power_saving_declarations.h @@ -0,0 +1,11 @@ +#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); diff --git a/panda_tici/board/provision.h b/panda_tici/board/provision.h new file mode 100644 index 0000000..d191e53 --- /dev/null +++ b/panda_tici/board/provision.h @@ -0,0 +1,13 @@ +// this is where we manage the dongle ID assigned during our +// manufacturing. aside from this, there's a UID for the MCU + +#define PROVISION_CHUNK_LEN 0x20 + +void get_provision_chunk(uint8_t *resp) { + const unsigned char unprovisioned_text[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; + + (void)memcpy(resp, (uint8_t *)PROVISION_CHUNK_ADDRESS, PROVISION_CHUNK_LEN); + if (memcmp(resp, unprovisioned_text, 0x20) == 0) { + (void)memcpy(resp, "unprovisioned\x00\x00\x00testing123\x00\x00\xa3\xa6\x99\xec", 0x20); + } +} diff --git a/panda_tici/board/recover.py b/panda_tici/board/recover.py new file mode 100755 index 0000000..b68e0ae --- /dev/null +++ b/panda_tici/board/recover.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import os +import time +import subprocess + +from panda_tici import Panda, PandaDFU + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + subprocess.check_call(f"scons -C {board_path}/.. -j$(nproc) {board_path}", shell=True) + + for s in Panda.list(): + with Panda(serial=s) as p: + print(f"putting {p.get_usb_serial()} in DFU mode") + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + + # wait for reset pandas to come back up + time.sleep(1) + + dfu_serials = PandaDFU.list() + print(f"found {len(dfu_serials)} panda(s) in DFU - {dfu_serials}") + for s in dfu_serials: + print("flashing", s) + PandaDFU(s).recover() + exit(1 if len(dfu_serials) == 0 else 0) diff --git a/panda_tici/board/stm32f4/board.h b/panda_tici/board/stm32f4/board.h new file mode 100644 index 0000000..e3941c2 --- /dev/null +++ b/panda_tici/board/stm32f4/board.h @@ -0,0 +1,42 @@ +// ///////////////////////////////////////////////////////////// // +// Hardware abstraction layer for all different supported boards // +// ///////////////////////////////////////////////////////////// // +#include "boards/board_declarations.h" +#include "boards/unused_funcs.h" + +// ///// Board definition and detection ///// // +#include "stm32f4/lladc.h" +#include "drivers/harness.h" +#include "drivers/fan.h" +#include "stm32f4/llfan.h" +#include "drivers/clock_source.h" +#include "boards/dos.h" + +// Unused functions on F4 +void sound_tick(void) {} + +void detect_board_type(void) { + // SPI lines floating: white (TODO: is this reliable? Not really, we have to enable ESP/GPS to be able to detect this on the UART) + 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; + // rick - for Lite, it detected as UNO before 0.9.9 + // Confirmed with mr. one, we are safe to do so for Lite + } else if(!detect_with_pull(GPIOB, 15, PULL_UP)) { + hw_type = HW_TYPE_DOS; + current_board = &board_dos; + } else if((detect_with_pull(GPIOA, 4, PULL_DOWN)) || (detect_with_pull(GPIOA, 5, PULL_DOWN)) || (detect_with_pull(GPIOA, 6, PULL_DOWN)) || (detect_with_pull(GPIOA, 7, PULL_DOWN))){ + // white is deprecated + } else if(detect_with_pull(GPIOA, 13, PULL_DOWN)) { // Rev AB deprecated, so no pullup means black. In REV C, A13 is pulled up to 5V with a 10K + // grey is deprecated + } else if(!detect_with_pull(GPIOB, 15, PULL_UP)) { + // uno is deprecated + } else { + // black is deprecated + } + + // Return A13 to the alt mode to fix SWD + set_gpio_alternate(GPIOA, 13, GPIO_AF0_SWJ); +} diff --git a/panda_tici/board/stm32f4/clock.h b/panda_tici/board/stm32f4/clock.h new file mode 100644 index 0000000..f0084fa --- /dev/null +++ b/panda_tici/board/stm32f4/clock.h @@ -0,0 +1,34 @@ +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 *** +} diff --git a/panda_tici/board/stm32f4/inc/cmsis_compiler.h b/panda_tici/board/stm32f4/inc/cmsis_compiler.h new file mode 100644 index 0000000..d0f39ee --- /dev/null +++ b/panda_tici/board/stm32f4/inc/cmsis_compiler.h @@ -0,0 +1,284 @@ +/**************************************************************************//** + * @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 + +/* + * 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 + + +/* + * TI Arm Compiler + */ +#elif defined ( __TI_ARM__ ) + #include + + #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 + + #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 */ + + diff --git a/panda_tici/board/stm32f4/inc/cmsis_gcc.h b/panda_tici/board/stm32f4/inc/cmsis_gcc.h new file mode 100644 index 0000000..2f68473 --- /dev/null +++ b/panda_tici/board/stm32f4/inc/cmsis_gcc.h @@ -0,0 +1,2169 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS compiler GCC header file + * @version V5.2.0 + * @date 08. May 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. + */ + +#ifndef __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +/* Fallback for __has_builtin */ +#ifndef __has_builtin + #define __has_builtin(x) (0) +#endif + +/* CMSIS compiler specific defines */ +#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 __attribute__((always_inline)) 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, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma GCC diagnostic pop + #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 + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START + +/** + \brief Initializes data and bss sections + \details This default implementations initialized all data and additional bss + sections relying on .copy.table and .zero.table specified properly + in the used linker script. + + */ +__STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) +{ + extern void _start(void) __NO_RETURN; + + typedef struct { + uint32_t const* src; + uint32_t* dest; + uint32_t wlen; + } __copy_table_t; + + typedef struct { + uint32_t* dest; + uint32_t wlen; + } __zero_table_t; + + extern const __copy_table_t __copy_table_start__; + extern const __copy_table_t __copy_table_end__; + extern const __zero_table_t __zero_table_start__; + extern const __zero_table_t __zero_table_end__; + + for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = pTable->src[i]; + } + } + + for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = 0u; + } + } + + _start(); +} + +#define __PROGRAM_START __cmsis_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP __StackTop +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT __StackLimit +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute((used, section(".vectors"))) +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_get_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + return __builtin_arm_get_fpscr(); +#else + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#endif +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_set_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + __builtin_arm_set_fpscr(fpscr); +#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); +#endif +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP() __ASM volatile ("nop") + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI() __ASM volatile ("wfi") + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE() __ASM volatile ("wfe") + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV() __ASM volatile ("sev") + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__STATIC_FORCEINLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__STATIC_FORCEINLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (int16_t)__builtin_bswap16(value); +#else + int16_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return result; +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__STATIC_FORCEINLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ + __extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#if 0 +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) +#endif + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#pragma GCC diagnostic pop + +#endif /* __CMSIS_GCC_H */ + diff --git a/panda_tici/board/stm32f4/inc/cmsis_version.h b/panda_tici/board/stm32f4/inc/cmsis_version.h new file mode 100644 index 0000000..bf57cf3 --- /dev/null +++ b/panda_tici/board/stm32f4/inc/cmsis_version.h @@ -0,0 +1,40 @@ +/**************************************************************************//** + * @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 + diff --git a/panda_tici/board/stm32f4/inc/core_cm4.h b/panda_tici/board/stm32f4/inc/core_cm4.h new file mode 100644 index 0000000..0d40081 --- /dev/null +++ b/panda_tici/board/stm32f4/inc/core_cm4.h @@ -0,0 +1,2125 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V5.1.0 + * @date 13. March 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 __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M4 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (4U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000U + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; + /* ARM Application Note 321 states that the M4 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + diff --git a/panda_tici/board/stm32f4/inc/mpu_armv7.h b/panda_tici/board/stm32f4/inc/mpu_armv7.h new file mode 100644 index 0000000..e72cc46 --- /dev/null +++ b/panda_tici/board/stm32f4/inc/mpu_armv7.h @@ -0,0 +1,273 @@ +/****************************************************************************** + * @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 + diff --git a/panda_tici/board/stm32f4/inc/stm32f413xx.h b/panda_tici/board/stm32f4/inc/stm32f413xx.h new file mode 100644 index 0000000..2e2a7bc --- /dev/null +++ b/panda_tici/board/stm32f4/inc/stm32f413xx.h @@ -0,0 +1,15463 @@ +/** + ****************************************************************************** + * @file stm32f413xx.h + * @author MCD Application Team + * @brief CMSIS STM32F413xx Device Peripheral Access Layer Header File. + * + * This file contains: + * - Data structures and the address mapping for all peripherals + * - peripherals registers declarations and bits definition + * - Macros to access peripheral's registers hardware + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS_Device + * @{ + */ + +/** @addtogroup stm32f413xx + * @{ + */ + +#ifndef __STM32F413xx_H +#define __STM32F413xx_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Configuration_section_for_CMSIS + * @{ + */ + +/** + * @brief Configuration of the Cortex-M4 Processor and Core Peripherals + */ +#define __CM4_REV 0x0001U /*!< Core revision r0p1 */ +#define __MPU_PRESENT 1U /*!< STM32F4XX provides an MPU */ +#define __NVIC_PRIO_BITS 4U /*!< STM32F4XX uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0U /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 1U /*!< FPU present */ + +/** + * @} + */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32F4XX Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum +{ + /****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ + /****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */ + DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */ + DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */ + DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */ + DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */ + DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */ + DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ + ADC_IRQn = 18, /*!< ADC1, ADC2 and ADC3 global Interrupts */ + CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */ + CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM9_IRQn = 24, /*!< TIM1 Break interrupt and TIM9 global interrupt */ + TIM1_UP_TIM10_IRQn = 25, /*!< TIM1 Update Interrupt and TIM10 global interrupt */ + TIM1_TRG_COM_TIM11_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS Wakeup through EXTI line interrupt */ + TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */ + TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */ + TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare global interrupt */ + DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */ + FSMC_IRQn = 48, + SDIO_IRQn = 49, /*!< SDIO global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */ + DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */ + DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */ + DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */ + DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ + DFSDM1_FLT0_IRQn = 61, /*!< DFSDM1 Filter 0 global Interrupt */ + DFSDM1_FLT1_IRQn = 62, /*!< DFSDM1 Filter 1 global Interrupt */ + CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */ + CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */ + CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */ + CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */ + OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */ + DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */ + DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */ + DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */ + USART6_IRQn = 71, /*!< USART6 global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + CAN3_TX_IRQn = 74, /*!< CAN3 TX Interrupt */ + CAN3_RX0_IRQn = 75, /*!< CAN3 RX0 Interrupt */ + CAN3_RX1_IRQn = 76, /*!< CAN3 RX1 Interrupt */ + CAN3_SCE_IRQn = 77, /*!< CAN3 SCE Interrupt */ + RNG_IRQn = 80, /*!< RNG global Interrupt */ + FPU_IRQn = 81, /*!< FPU global interrupt */ + UART7_IRQn = 82, /*!< UART7 global interrupt */ + UART8_IRQn = 83, /*!< UART8 global interrupt */ + SPI4_IRQn = 84, /*!< SPI4 global Interrupt */ + SPI5_IRQn = 85, /*!< SPI5 global Interrupt */ + SAI1_IRQn = 87, /*!< SAI1 global Interrupt */ + UART9_IRQn = 88, /*!< UART9 global Interrupt */ + UART10_IRQn = 89, /*!< UART10 global Interrupt */ + QUADSPI_IRQn = 92, /*!< QuadSPI global Interrupt */ + FMPI2C1_EV_IRQn = 95, /*!< FMPI2C1 Event Interrupt */ + FMPI2C1_ER_IRQn = 96, /*!< FMPI2C1 Error Interrupt */ + LPTIM1_IRQn = 97, /*!< LP TIM1 interrupt */ + DFSDM2_FLT0_IRQn = 98, /*!< DFSDM2 Filter 0 global Interrupt */ + DFSDM2_FLT1_IRQn = 99, /*!< DFSDM2 Filter 1 global Interrupt */ + DFSDM2_FLT2_IRQn = 100, /*!< DFSDM2 Filter 2 global Interrupt */ + DFSDM2_FLT3_IRQn = 101 /*!< DFSDM2 Filter 3 global Interrupt */ +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */ +#include "system_stm32f4xx.h" +#include + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t SR; /*!< ADC status register, Address offset: 0x00 */ + __IO uint32_t CR1; /*!< ADC control register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< ADC control register 2, Address offset: 0x08 */ + __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x0C */ + __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x10 */ + __IO uint32_t JOFR1; /*!< ADC injected channel data offset register 1, Address offset: 0x14 */ + __IO uint32_t JOFR2; /*!< ADC injected channel data offset register 2, Address offset: 0x18 */ + __IO uint32_t JOFR3; /*!< ADC injected channel data offset register 3, Address offset: 0x1C */ + __IO uint32_t JOFR4; /*!< ADC injected channel data offset register 4, Address offset: 0x20 */ + __IO uint32_t HTR; /*!< ADC watchdog higher threshold register, Address offset: 0x24 */ + __IO uint32_t LTR; /*!< ADC watchdog lower threshold register, Address offset: 0x28 */ + __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x2C */ + __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x30 */ + __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x34 */ + __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x38*/ + __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x3C */ + __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x40 */ + __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x44 */ + __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x48 */ + __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x4C */ +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< ADC Common status register, Address offset: ADC1 base address + 0x300 */ + __IO uint32_t CCR; /*!< ADC common control register, Address offset: ADC1 base address + 0x304 */ + __IO uint32_t CDR; /*!< ADC common regular data register for dual + AND triple modes, Address offset: ADC1 base address + 0x308 */ +} ADC_Common_TypeDef; + + +/** + * @brief Controller Area Network TxMailBox + */ + +typedef struct +{ + __IO uint32_t TIR; /*!< CAN TX mailbox identifier register */ + __IO uint32_t TDTR; /*!< CAN mailbox data length control and time stamp register */ + __IO uint32_t TDLR; /*!< CAN mailbox data low register */ + __IO uint32_t TDHR; /*!< CAN mailbox data high register */ +} CAN_TxMailBox_TypeDef; + +/** + * @brief Controller Area Network FIFOMailBox + */ + +typedef struct +{ + __IO uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */ + __IO uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */ + __IO uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */ + __IO uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */ +} CAN_FIFOMailBox_TypeDef; + +/** + * @brief Controller Area Network FilterRegister + */ + +typedef struct +{ + __IO uint32_t FR1; /*!< CAN Filter bank register 1 */ + __IO uint32_t FR2; /*!< CAN Filter bank register 1 */ +} CAN_FilterRegister_TypeDef; + +/** + * @brief Controller Area Network + */ + +typedef struct +{ + __IO uint32_t MCR; /*!< CAN master control register, Address offset: 0x00 */ + __IO uint32_t MSR; /*!< CAN master status register, Address offset: 0x04 */ + __IO uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */ + __IO uint32_t RF0R; /*!< CAN receive FIFO 0 register, Address offset: 0x0C */ + __IO uint32_t RF1R; /*!< CAN receive FIFO 1 register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */ + __IO uint32_t ESR; /*!< CAN error status register, Address offset: 0x18 */ + __IO uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */ + uint32_t RESERVED0[88]; /*!< Reserved, 0x020 - 0x17F */ + CAN_TxMailBox_TypeDef sTxMailBox[3]; /*!< CAN Tx MailBox, Address offset: 0x180 - 0x1AC */ + CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; /*!< CAN FIFO MailBox, Address offset: 0x1B0 - 0x1CC */ + uint32_t RESERVED1[12]; /*!< Reserved, 0x1D0 - 0x1FF */ + __IO uint32_t FMR; /*!< CAN filter master register, Address offset: 0x200 */ + __IO uint32_t FM1R; /*!< CAN filter mode register, Address offset: 0x204 */ + uint32_t RESERVED2; /*!< Reserved, 0x208 */ + __IO uint32_t FS1R; /*!< CAN filter scale register, Address offset: 0x20C */ + uint32_t RESERVED3; /*!< Reserved, 0x210 */ + __IO uint32_t FFA1R; /*!< CAN filter FIFO assignment register, Address offset: 0x214 */ + uint32_t RESERVED4; /*!< Reserved, 0x218 */ + __IO uint32_t FA1R; /*!< CAN filter activation register, Address offset: 0x21C */ + uint32_t RESERVED5[8]; /*!< Reserved, 0x220-0x23F */ + CAN_FilterRegister_TypeDef sFilterRegister[28]; /*!< CAN Filter Register, Address offset: 0x240-0x31C */ +} CAN_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + uint8_t RESERVED0; /*!< Reserved, 0x05 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ +} CRC_TypeDef; + +/** + * @brief DFSDM module registers + */ +typedef struct +{ + __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */ + __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */ + __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */ + __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */ + __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */ + __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */ + __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */ + __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */ + __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */ + __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */ + __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */ + __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */ + __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */ + __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */ + __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */ +} DFSDM_Filter_TypeDef; + +/** + * @brief DFSDM channel configuration registers + */ +typedef struct +{ + __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */ + __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */ + __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and + short circuit detector register, Address offset: 0x08 */ + __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */ + __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */ +} DFSDM_Channel_TypeDef; + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ +} DAC_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZ; /*!< Debug MCU APB1 freeze register, Address offset: 0x08 */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x0C */ +} DBGMCU_TypeDef; + + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA stream x configuration register */ + __IO uint32_t NDTR; /*!< DMA stream x number of data register */ + __IO uint32_t PAR; /*!< DMA stream x peripheral address register */ + __IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */ + __IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */ + __IO uint32_t FCR; /*!< DMA stream x FIFO control register */ +} DMA_Stream_TypeDef; + +typedef struct +{ + __IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */ + __IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */ + __IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */ + __IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */ +} DMA_TypeDef; + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR; /*!< EXTI Interrupt mask register, Address offset: 0x00 */ + __IO uint32_t EMR; /*!< EXTI Event mask register, Address offset: 0x04 */ + __IO uint32_t RTSR; /*!< EXTI Rising trigger selection register, Address offset: 0x08 */ + __IO uint32_t FTSR; /*!< EXTI Falling trigger selection register, Address offset: 0x0C */ + __IO uint32_t SWIER; /*!< EXTI Software interrupt event register, Address offset: 0x10 */ + __IO uint32_t PR; /*!< EXTI Pending register, Address offset: 0x14 */ +} EXTI_TypeDef; + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t KEYR; /*!< FLASH key register, Address offset: 0x04 */ + __IO uint32_t OPTKEYR; /*!< FLASH option key register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< FLASH status register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< FLASH control register, Address offset: 0x10 */ + __IO uint32_t OPTCR; /*!< FLASH option control register , Address offset: 0x14 */ + __IO uint32_t OPTCR1; /*!< FLASH option control register 1, Address offset: 0x18 */ +} FLASH_TypeDef; + + + +/** + * @brief Flexible Static Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FSMC_Bank1_TypeDef; + +/** + * @brief Flexible Static Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FSMC_Bank1E_TypeDef; +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ +} GPIO_TypeDef; + +/** + * @brief System configuration controller + */ + +typedef struct +{ + __IO uint32_t MEMRMP; /*!< SYSCFG memory remap register, Address offset: 0x00 */ + __IO uint32_t PMC; /*!< SYSCFG peripheral mode configuration register, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + uint32_t RESERVED; /*!< Reserved, 0x18 */ + __IO uint32_t CFGR2; /*!< SYSCFG Configuration register2, Address offset: 0x1C */ + __IO uint32_t CMPCR; /*!< SYSCFG Compensation cell control register, Address offset: 0x20 */ + uint32_t RESERVED1[2]; /*!< Reserved, 0x24-0x28 */ + __IO uint32_t CFGR; /*!< SYSCFG Configuration register, Address offset: 0x2C */ + __IO uint32_t MCHDLYCR; /*!< SYSCFG multi-channel delay register, Address offset: 0x30 */ +} SYSCFG_TypeDef; + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< I2C Own address register 1, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< I2C Own address register 2, Address offset: 0x0C */ + __IO uint32_t DR; /*!< I2C Data register, Address offset: 0x10 */ + __IO uint32_t SR1; /*!< I2C Status register 1, Address offset: 0x14 */ + __IO uint32_t SR2; /*!< I2C Status register 2, Address offset: 0x18 */ + __IO uint32_t CCR; /*!< I2C Clock control register, Address offset: 0x1C */ + __IO uint32_t TRISE; /*!< I2C TRISE register, Address offset: 0x20 */ + __IO uint32_t FLTR; /*!< I2C FLTR register, Address offset: 0x24 */ +} I2C_TypeDef; + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< FMPI2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< FMPI2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< FMPI2C Own address 1 register, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< FMPI2C Own address 2 register, Address offset: 0x0C */ + __IO uint32_t TIMINGR; /*!< FMPI2C Timing register, Address offset: 0x10 */ + __IO uint32_t TIMEOUTR; /*!< FMPI2C Timeout register, Address offset: 0x14 */ + __IO uint32_t ISR; /*!< FMPI2C Interrupt and status register, Address offset: 0x18 */ + __IO uint32_t ICR; /*!< FMPI2C Interrupt clear register, Address offset: 0x1C */ + __IO uint32_t PECR; /*!< FMPI2C PEC register, Address offset: 0x20 */ + __IO uint32_t RXDR; /*!< FMPI2C Receive data register, Address offset: 0x24 */ + __IO uint32_t TXDR; /*!< FMPI2C Transmit data register, Address offset: 0x28 */ +} FMPI2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ +} IWDG_TypeDef; + + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< PWR power control register, Address offset: 0x00 */ + __IO uint32_t CSR; /*!< PWR power control/status register, Address offset: 0x04 */ +} PWR_TypeDef; + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t PLLCFGR; /*!< RCC PLL configuration register, Address offset: 0x04 */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ + __IO uint32_t CIR; /*!< RCC clock interrupt register, Address offset: 0x0C */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x10 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x14 */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x18 */ + uint32_t RESERVED0; /*!< Reserved, 0x1C */ + __IO uint32_t APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x20 */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x24 */ + uint32_t RESERVED1[2]; /*!< Reserved, 0x28-0x2C */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0x30 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0x34 */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0x38 */ + uint32_t RESERVED2; /*!< Reserved, 0x3C */ + __IO uint32_t APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x40 */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x44 */ + uint32_t RESERVED3[2]; /*!< Reserved, 0x48-0x4C */ + __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */ + __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */ + __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */ + uint32_t RESERVED4; /*!< Reserved, 0x5C */ + __IO uint32_t APB1LPENR; /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */ + __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */ + uint32_t RESERVED5[2]; /*!< Reserved, 0x68-0x6C */ + __IO uint32_t BDCR; /*!< RCC Backup domain control register, Address offset: 0x70 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ + uint32_t RESERVED6[2]; /*!< Reserved, 0x78-0x7C */ + __IO uint32_t SSCGR; /*!< RCC spread spectrum clock generation register, Address offset: 0x80 */ + __IO uint32_t PLLI2SCFGR; /*!< RCC PLLI2S configuration register, Address offset: 0x84 */ + uint32_t RESERVED7; /*!< Reserved, 0x84 */ + __IO uint32_t DCKCFGR; /*!< RCC Dedicated Clocks configuration register, Address offset: 0x8C */ + __IO uint32_t CKGATENR; /*!< RCC Clocks Gated ENable Register, Address offset: 0x90 */ + __IO uint32_t DCKCFGR2; /*!< RCC Dedicated Clocks configuration register 2, Address offset: 0x94 */ +} RCC_TypeDef; + +/** + * @brief Real-Time Clock + */ + +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + __IO uint32_t CALIBR; /*!< RTC calibration register, Address offset: 0x18 */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAFCR; /*!< RTC tamper and alternate function configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR;/*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR;/*!< RTC alarm B sub second register, Address offset: 0x48 */ + uint32_t RESERVED7; /*!< Reserved, 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 1, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ +} RTC_TypeDef; + +/** + * @brief Serial Audio Interface + */ + +typedef struct +{ + __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ +} SAI_TypeDef; + +typedef struct +{ + __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ + __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ + __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ + __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ + __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ + __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ +} SAI_Block_TypeDef; + +/** + * @brief SD host Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDIO power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDI clock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDIO argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDIO command register, Address offset: 0x0C */ + __IO const uint32_t RESPCMD; /*!< SDIO command response register, Address offset: 0x10 */ + __IO const uint32_t RESP1; /*!< SDIO response 1 register, Address offset: 0x14 */ + __IO const uint32_t RESP2; /*!< SDIO response 2 register, Address offset: 0x18 */ + __IO const uint32_t RESP3; /*!< SDIO response 3 register, Address offset: 0x1C */ + __IO const uint32_t RESP4; /*!< SDIO response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDIO data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDIO data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDIO data control register, Address offset: 0x2C */ + __IO const uint32_t DCOUNT; /*!< SDIO data counter register, Address offset: 0x30 */ + __IO const uint32_t STA; /*!< SDIO status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDIO interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDIO mask register, Address offset: 0x3C */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x40-0x44 */ + __IO const uint32_t FIFOCNT; /*!< SDIO FIFO counter register, Address offset: 0x48 */ + uint32_t RESERVED1[13]; /*!< Reserved, 0x4C-0x7C */ + __IO uint32_t FIFO; /*!< SDIO data FIFO register, Address offset: 0x80 */ +} SDIO_TypeDef; + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< SPI control register 1 (not used in I2S mode), Address offset: 0x00 */ + __IO uint32_t CR2; /*!< SPI control register 2, Address offset: 0x04 */ + __IO uint32_t SR; /*!< SPI status register, Address offset: 0x08 */ + __IO uint32_t DR; /*!< SPI data register, Address offset: 0x0C */ + __IO uint32_t CRCPR; /*!< SPI CRC polynomial register (not used in I2S mode), Address offset: 0x10 */ + __IO uint32_t RXCRCR; /*!< SPI RX CRC register (not used in I2S mode), Address offset: 0x14 */ + __IO uint32_t TXCRCR; /*!< SPI TX CRC register (not used in I2S mode), Address offset: 0x18 */ + __IO uint32_t I2SCFGR; /*!< SPI_I2S configuration register, Address offset: 0x1C */ + __IO uint32_t I2SPR; /*!< SPI_I2S prescaler register, Address offset: 0x20 */ +} SPI_TypeDef; + +/** + * @brief QUAD Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< QUADSPI Control register, Address offset: 0x00 */ + __IO uint32_t DCR; /*!< QUADSPI Device Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< QUADSPI Status register, Address offset: 0x08 */ + __IO uint32_t FCR; /*!< QUADSPI Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DLR; /*!< QUADSPI Data Length register, Address offset: 0x10 */ + __IO uint32_t CCR; /*!< QUADSPI Communication Configuration register, Address offset: 0x14 */ + __IO uint32_t AR; /*!< QUADSPI Address register, Address offset: 0x18 */ + __IO uint32_t ABR; /*!< QUADSPI Alternate Bytes register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< QUADSPI Data register, Address offset: 0x20 */ + __IO uint32_t PSMKR; /*!< QUADSPI Polling Status Mask register, Address offset: 0x24 */ + __IO uint32_t PSMAR; /*!< QUADSPI Polling Status Match register, Address offset: 0x28 */ + __IO uint32_t PIR; /*!< QUADSPI Polling Interval register, Address offset: 0x2C */ + __IO uint32_t LPTR; /*!< QUADSPI Low Power Timeout register, Address offset: 0x30 */ +} QUADSPI_TypeDef; + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ + __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + __IO uint32_t OR; /*!< TIM option register, Address offset: 0x50 */ +} TIM_TypeDef; + +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint32_t SR; /*!< USART Status register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< USART Data register, Address offset: 0x04 */ + __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x08 */ + __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x0C */ + __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x10 */ + __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x14 */ + __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x18 */ +} USART_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ +} RNG_TypeDef; + +/** + * @brief USB_OTG_Core_Registers + */ +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h */ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h */ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h */ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch */ + __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h */ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h */ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h */ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch */ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h */ + __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h */ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h */ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< General Purpose IO Register 038h */ + __IO uint32_t CID; /*!< User ID Register 03Ch */ + uint32_t Reserved5[3]; /*!< Reserved 040h-048h */ + __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch */ + uint32_t Reserved6; /*!< Reserved 050h */ + __IO uint32_t GLPMCFG; /*!< LPM Register 054h */ + uint32_t Reserved; /*!< Reserved 058h */ + __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch */ + uint32_t Reserved43[40]; /*!< Reserved 058h-0FFh */ + __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg 100h */ + __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO */ +} USB_OTG_GlobalTypeDef; + +/** + * @brief USB_OTG_device_Registers + */ +typedef struct +{ + __IO uint32_t DCFG; /*!< dev Configuration Register 800h */ + __IO uint32_t DCTL; /*!< dev Control Register 804h */ + __IO uint32_t DSTS; /*!< dev Status Register (RO) 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask 810h */ + __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask 814h */ + __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg 818h */ + __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved9; /*!< Reserved 824h */ + __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register 828h */ + __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register 82Ch */ + __IO uint32_t DTHRCTL; /*!< dev threshold 830h */ + __IO uint32_t DIEPEMPMSK; /*!< dev empty msk 834h */ + __IO uint32_t DEACHINT; /*!< dedicated EP interrupt 838h */ + __IO uint32_t DEACHMSK; /*!< dedicated EP msk 83Ch */ + uint32_t Reserved40; /*!< dedicated EP mask 840h */ + __IO uint32_t DINEP1MSK; /*!< dedicated EP mask 844h */ + uint32_t Reserved44[15]; /*!< Reserved 844-87Ch */ + __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk 884h */ +} USB_OTG_DeviceTypeDef; + +/** + * @brief USB_OTG_IN_Endpoint-Specific_Register + */ +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h */ + __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h */ + __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h */ + __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h */ + uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch */ +} USB_OTG_INEndpointTypeDef; + +/** + * @brief USB_OTG_OUT_Endpoint-Specific_Registers + */ +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h */ + __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h */ + __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h */ + uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch */ +} USB_OTG_OUTEndpointTypeDef; + +/** + * @brief USB_OTG_Host_Mode_Register_Structures + */ +typedef struct +{ + __IO uint32_t HCFG; /*!< Host Configuration Register 400h */ + __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h */ + __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h */ + __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h */ + __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h */ +} USB_OTG_HostTypeDef; + +/** + * @brief USB_OTG_Host_Channel_Specific_Registers + */ +typedef struct +{ + __IO uint32_t HCCHAR; /*!< Host Channel Characteristics Register 500h */ + __IO uint32_t HCSPLT; /*!< Host Channel Split Control Register 504h */ + __IO uint32_t HCINT; /*!< Host Channel Interrupt Register 508h */ + __IO uint32_t HCINTMSK; /*!< Host Channel Interrupt Mask Register 50Ch */ + __IO uint32_t HCTSIZ; /*!< Host Channel Transfer Size Register 510h */ + __IO uint32_t HCDMA; /*!< Host Channel DMA Address Register 514h */ + uint32_t Reserved[2]; /*!< Reserved */ +} USB_OTG_HostChannelTypeDef; + +/** + * @brief LPTIMER + */ +typedef struct +{ + __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ + __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ + __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ + __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ + __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ + __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ + __IO uint32_t OR; /*!< LPTIM Option register, Address offset: 0x20 */ +} LPTIM_TypeDef; + +/** + * @} + */ + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define FLASH_BASE 0x08000000UL /*!< FLASH (up to 1.5 MB) base address in the alias region */ +#define SRAM1_BASE 0x20000000UL /*!< SRAM1(256 KB) base address in the alias region */ +#define SRAM2_BASE 0x20040000UL /*!< SRAM2(64 KB) base address in the alias region */ +#define PERIPH_BASE 0x40000000UL /*!< Peripheral base address in the alias region */ +#define FSMC_R_BASE 0xA0000000UL /*!< FSMC registers base address */ +#define QSPI_R_BASE 0xA0001000UL /*!< QuadSPI registers base address */ +#define SRAM1_BB_BASE 0x22000000UL /*!< SRAM1(256 KB) base address in the bit-band region */ +#define SRAM2_BB_BASE 0x22800000UL /*!< SRAM2(64 KB) base address in the bit-band region */ +#define PERIPH_BB_BASE 0x42000000UL /*!< Peripheral base address in the bit-band region */ +#define FLASH_END 0x0817FFFFUL /*!< FLASH end address */ +#define FLASH_OTP_BASE 0x1FFF7800UL /*!< Base address of : (up to 528 Bytes) embedded FLASH OTP Area */ +#define FLASH_OTP_END 0x1FFF7A0FUL /*!< End address of : (up to 528 Bytes) embedded FLASH OTP Area */ + +/* Legacy defines */ +#define SRAM_BASE SRAM1_BASE +#define SRAM_BB_BASE SRAM1_BB_BASE + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x10000000UL) + +/*!< APB1 peripherals */ +#define TIM2_BASE (APB1PERIPH_BASE + 0x0000UL) +#define TIM3_BASE (APB1PERIPH_BASE + 0x0400UL) +#define TIM4_BASE (APB1PERIPH_BASE + 0x0800UL) +#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00UL) +#define TIM6_BASE (APB1PERIPH_BASE + 0x1000UL) +#define TIM7_BASE (APB1PERIPH_BASE + 0x1400UL) +#define TIM12_BASE (APB1PERIPH_BASE + 0x1800UL) +#define TIM13_BASE (APB1PERIPH_BASE + 0x1C00UL) +#define TIM14_BASE (APB1PERIPH_BASE + 0x2000UL) +#define LPTIM1_BASE (APB1PERIPH_BASE + 0x2400UL) +#define RTC_BASE (APB1PERIPH_BASE + 0x2800UL) +#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00UL) +#define IWDG_BASE (APB1PERIPH_BASE + 0x3000UL) +#define I2S2ext_BASE (APB1PERIPH_BASE + 0x3400UL) +#define SPI2_BASE (APB1PERIPH_BASE + 0x3800UL) +#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00UL) +#define I2S3ext_BASE (APB1PERIPH_BASE + 0x4000UL) +#define USART2_BASE (APB1PERIPH_BASE + 0x4400UL) +#define USART3_BASE (APB1PERIPH_BASE + 0x4800UL) +#define UART4_BASE (APB1PERIPH_BASE + 0x4C00UL) +#define UART5_BASE (APB1PERIPH_BASE + 0x5000UL) +#define I2C1_BASE (APB1PERIPH_BASE + 0x5400UL) +#define I2C2_BASE (APB1PERIPH_BASE + 0x5800UL) +#define I2C3_BASE (APB1PERIPH_BASE + 0x5C00UL) +#define FMPI2C1_BASE (APB1PERIPH_BASE + 0x6000UL) +#define CAN1_BASE (APB1PERIPH_BASE + 0x6400UL) +#define CAN2_BASE (APB1PERIPH_BASE + 0x6800UL) +#define CAN3_BASE (APB1PERIPH_BASE + 0x6C00UL) +#define PWR_BASE (APB1PERIPH_BASE + 0x7000UL) +#define DAC_BASE (APB1PERIPH_BASE + 0x7400UL) +#define UART7_BASE (APB1PERIPH_BASE + 0x7800UL) +#define UART8_BASE (APB1PERIPH_BASE + 0x7C00UL) + +/*!< APB2 peripherals */ +#define TIM1_BASE (APB2PERIPH_BASE + 0x0000UL) +#define TIM8_BASE (APB2PERIPH_BASE + 0x0400UL) +#define USART1_BASE (APB2PERIPH_BASE + 0x1000UL) +#define USART6_BASE (APB2PERIPH_BASE + 0x1400UL) +#define UART9_BASE (APB2PERIPH_BASE + 0x1800UL) +#define UART10_BASE (APB2PERIPH_BASE + 0x1C00UL) +#define ADC1_BASE (APB2PERIPH_BASE + 0x2000UL) +#define ADC1_COMMON_BASE (APB2PERIPH_BASE + 0x2300UL) +/* Legacy define */ +#define ADC_BASE ADC1_COMMON_BASE +#define SDIO_BASE (APB2PERIPH_BASE + 0x2C00UL) +#define SPI1_BASE (APB2PERIPH_BASE + 0x3000UL) +#define SPI4_BASE (APB2PERIPH_BASE + 0x3400UL) +#define SYSCFG_BASE (APB2PERIPH_BASE + 0x3800UL) +#define EXTI_BASE (APB2PERIPH_BASE + 0x3C00UL) +#define TIM9_BASE (APB2PERIPH_BASE + 0x4000UL) +#define TIM10_BASE (APB2PERIPH_BASE + 0x4400UL) +#define TIM11_BASE (APB2PERIPH_BASE + 0x4800UL) +#define SPI5_BASE (APB2PERIPH_BASE + 0x5000UL) +#define DFSDM1_BASE (APB2PERIPH_BASE + 0x6000UL) +#define DFSDM2_BASE (APB2PERIPH_BASE + 0x6400UL) +#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x00UL) +#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x20UL) +#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x40UL) +#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x60UL) +#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x100UL) +#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x180UL) +#define DFSDM2_Channel0_BASE (DFSDM2_BASE + 0x00UL) +#define DFSDM2_Channel1_BASE (DFSDM2_BASE + 0x20UL) +#define DFSDM2_Channel2_BASE (DFSDM2_BASE + 0x40UL) +#define DFSDM2_Channel3_BASE (DFSDM2_BASE + 0x60UL) +#define DFSDM2_Channel4_BASE (DFSDM2_BASE + 0x80UL) +#define DFSDM2_Channel5_BASE (DFSDM2_BASE + 0xA0UL) +#define DFSDM2_Channel6_BASE (DFSDM2_BASE + 0xC0UL) +#define DFSDM2_Channel7_BASE (DFSDM2_BASE + 0xE0UL) +#define DFSDM2_Filter0_BASE (DFSDM2_BASE + 0x100UL) +#define DFSDM2_Filter1_BASE (DFSDM2_BASE + 0x180UL) +#define DFSDM2_Filter2_BASE (DFSDM2_BASE + 0x200UL) +#define DFSDM2_Filter3_BASE (DFSDM2_BASE + 0x280UL) +#define SAI1_BASE (APB2PERIPH_BASE + 0x5800UL) +#define SAI1_Block_A_BASE (SAI1_BASE + 0x004UL) +#define SAI1_Block_B_BASE (SAI1_BASE + 0x024UL) + +/*!< AHB1 peripherals */ +#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000UL) +#define GPIOB_BASE (AHB1PERIPH_BASE + 0x0400UL) +#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800UL) +#define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00UL) +#define GPIOE_BASE (AHB1PERIPH_BASE + 0x1000UL) +#define GPIOF_BASE (AHB1PERIPH_BASE + 0x1400UL) +#define GPIOG_BASE (AHB1PERIPH_BASE + 0x1800UL) +#define GPIOH_BASE (AHB1PERIPH_BASE + 0x1C00UL) +#define CRC_BASE (AHB1PERIPH_BASE + 0x3000UL) +#define RCC_BASE (AHB1PERIPH_BASE + 0x3800UL) +#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x3C00UL) +#define DMA1_BASE (AHB1PERIPH_BASE + 0x6000UL) +#define DMA1_Stream0_BASE (DMA1_BASE + 0x010UL) +#define DMA1_Stream1_BASE (DMA1_BASE + 0x028UL) +#define DMA1_Stream2_BASE (DMA1_BASE + 0x040UL) +#define DMA1_Stream3_BASE (DMA1_BASE + 0x058UL) +#define DMA1_Stream4_BASE (DMA1_BASE + 0x070UL) +#define DMA1_Stream5_BASE (DMA1_BASE + 0x088UL) +#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0UL) +#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8UL) +#define DMA2_BASE (AHB1PERIPH_BASE + 0x6400UL) +#define DMA2_Stream0_BASE (DMA2_BASE + 0x010UL) +#define DMA2_Stream1_BASE (DMA2_BASE + 0x028UL) +#define DMA2_Stream2_BASE (DMA2_BASE + 0x040UL) +#define DMA2_Stream3_BASE (DMA2_BASE + 0x058UL) +#define DMA2_Stream4_BASE (DMA2_BASE + 0x070UL) +#define DMA2_Stream5_BASE (DMA2_BASE + 0x088UL) +#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0UL) +#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8UL) + +/*!< AHB2 peripherals */ +#define RNG_BASE (AHB2PERIPH_BASE + 0x60800UL) + + +/*!< FSMC Bankx registers base address */ +#define FSMC_Bank1_R_BASE (FSMC_R_BASE + 0x0000UL) +#define FSMC_Bank1E_R_BASE (FSMC_R_BASE + 0x0104UL) + +/*!< Debug MCU registers base address */ +#define DBGMCU_BASE 0xE0042000UL +/*!< USB registers base address */ +#define USB_OTG_FS_PERIPH_BASE 0x50000000UL + +#define USB_OTG_GLOBAL_BASE 0x000UL +#define USB_OTG_DEVICE_BASE 0x800UL +#define USB_OTG_IN_ENDPOINT_BASE 0x900UL +#define USB_OTG_OUT_ENDPOINT_BASE 0xB00UL +#define USB_OTG_EP_REG_SIZE 0x20UL +#define USB_OTG_HOST_BASE 0x400UL +#define USB_OTG_HOST_PORT_BASE 0x440UL +#define USB_OTG_HOST_CHANNEL_BASE 0x500UL +#define USB_OTG_HOST_CHANNEL_SIZE 0x20UL +#define USB_OTG_PCGCCTL_BASE 0xE00UL +#define USB_OTG_FIFO_BASE 0x1000UL +#define USB_OTG_FIFO_SIZE 0x1000UL + +#define UID_BASE 0x1FFF7A10UL /*!< Unique device ID register base address */ +#define FLASHSIZE_BASE 0x1FFF7A22UL /*!< FLASH Size register base address */ +#define PACKAGE_BASE 0x1FFF7BF0UL /*!< Package size register base address */ +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define TIM12 ((TIM_TypeDef *) TIM12_BASE) +#define TIM13 ((TIM_TypeDef *) TIM13_BASE) +#define TIM14 ((TIM_TypeDef *) TIM14_BASE) +#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG ((WWDG_TypeDef *) WWDG_BASE) +#define IWDG ((IWDG_TypeDef *) IWDG_BASE) +#define I2S2ext ((SPI_TypeDef *) I2S2ext_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define I2S3ext ((SPI_TypeDef *) I2S3ext_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define FMPI2C1 ((FMPI2C_TypeDef *) FMPI2C1_BASE) +#define CAN1 ((CAN_TypeDef *) CAN1_BASE) +#define CAN2 ((CAN_TypeDef *) CAN2_BASE) +#define CAN3 ((CAN_TypeDef *) CAN3_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC1 ((DAC_TypeDef *) DAC_BASE) +#define DAC ((DAC_TypeDef *) DAC_BASE) /* Kept for legacy purpose */ +#define UART7 ((USART_TypeDef *) UART7_BASE) +#define UART8 ((USART_TypeDef *) UART8_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define USART6 ((USART_TypeDef *) USART6_BASE) +#define UART9 ((USART_TypeDef *) UART9_BASE) +#define UART10 ((USART_TypeDef *) UART10_BASE) +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC1_COMMON ((ADC_Common_TypeDef *) ADC1_COMMON_BASE) +/* Legacy define */ +#define ADC ADC1_COMMON +#define SDIO ((SDIO_TypeDef *) SDIO_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define SPI4 ((SPI_TypeDef *) SPI4_BASE) +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define TIM9 ((TIM_TypeDef *) TIM9_BASE) +#define TIM10 ((TIM_TypeDef *) TIM10_BASE) +#define TIM11 ((TIM_TypeDef *) TIM11_BASE) +#define SPI5 ((SPI_TypeDef *) SPI5_BASE) +#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE) +#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE) +#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE) +#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE) +#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE) +#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE) +#define DFSDM2_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM2_Channel0_BASE) +#define DFSDM2_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM2_Channel1_BASE) +#define DFSDM2_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM2_Channel2_BASE) +#define DFSDM2_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM2_Channel3_BASE) +#define DFSDM2_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM2_Channel4_BASE) +#define DFSDM2_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM2_Channel5_BASE) +#define DFSDM2_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM2_Channel6_BASE) +#define DFSDM2_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM2_Channel7_BASE) +#define DFSDM2_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM2_Filter0_BASE) +#define DFSDM2_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM2_Filter1_BASE) +#define DFSDM2_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM2_Filter2_BASE) +#define DFSDM2_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM2_Filter3_BASE) +#define SAI1 ((SAI_TypeDef *) SAI1_BASE) +#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) +#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA1_Stream0 ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE) +#define DMA1_Stream1 ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE) +#define DMA1_Stream2 ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE) +#define DMA1_Stream3 ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE) +#define DMA1_Stream4 ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE) +#define DMA1_Stream5 ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE) +#define DMA1_Stream6 ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE) +#define DMA1_Stream7 ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE) +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define DMA2_Stream0 ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE) +#define DMA2_Stream1 ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE) +#define DMA2_Stream2 ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE) +#define DMA2_Stream3 ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE) +#define DMA2_Stream4 ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE) +#define DMA2_Stream5 ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE) +#define DMA2_Stream6 ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE) +#define DMA2_Stream7 ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) +#define FSMC_Bank1 ((FSMC_Bank1_TypeDef *) FSMC_Bank1_R_BASE) +#define FSMC_Bank1E ((FSMC_Bank1E_TypeDef *) FSMC_Bank1E_R_BASE) +#define QUADSPI ((QUADSPI_TypeDef *) QSPI_R_BASE) +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) +#define USB_OTG_FS ((USB_OTG_GlobalTypeDef *) USB_OTG_FS_PERIPH_BASE) + +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + +/** @addtogroup Hardware_Constant_Definition + * @{ + */ +#define LSI_STARTUP_TIME 40U /*!< LSI Maximum startup time in us */ +/** + * @} + */ + +/** @addtogroup Peripheral_Registers_Bits_Definition +* @{ +*/ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ + +/******************** Bit definition for ADC_SR register ********************/ +#define ADC_SR_AWD_Pos (0U) +#define ADC_SR_AWD_Msk (0x1UL << ADC_SR_AWD_Pos) /*!< 0x00000001 */ +#define ADC_SR_AWD ADC_SR_AWD_Msk /*!
© COPYRIGHT(c) 2016 STMicroelectronics
+ * + * 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****/ diff --git a/panda_tici/board/stm32f4/inc/stm32f4xx_hal_def.h b/panda_tici/board/stm32f4/inc/stm32f4xx_hal_def.h new file mode 100644 index 0000000..b77f179 --- /dev/null +++ b/panda_tici/board/stm32f4/inc/stm32f4xx_hal_def.h @@ -0,0 +1,214 @@ +/** + ****************************************************************************** + * @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 + * + *

© COPYRIGHT(c) 2016 STMicroelectronics

+ * + * 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 + +/* 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****/ diff --git a/panda_tici/board/stm32f4/inc/stm32f4xx_hal_gpio_ex.h b/panda_tici/board/stm32f4/inc/stm32f4xx_hal_gpio_ex.h new file mode 100644 index 0000000..6c5f34d --- /dev/null +++ b/panda_tici/board/stm32f4/inc/stm32f4xx_hal_gpio_ex.h @@ -0,0 +1,1591 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_gpio_ex.h + * @author MCD Application Team + * @version V1.6.0 + * @date 04-November-2016 + * @brief Header file of GPIO HAL Extension module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2016 STMicroelectronics

+ * + * 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_GPIO_EX_H +#define __STM32F4xx_HAL_GPIO_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup GPIOEx GPIOEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Constants GPIO Exported Constants + * @{ + */ + +/** @defgroup GPIO_Alternate_function_selection GPIO Alternate Function Selection + * @{ + */ + +/*------------------------------------------ STM32F429xx/STM32F439xx ---------*/ +#if defined(STM32F429xx) || defined(STM32F439xx) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4 Alternate Function mapping */ +#define GPIO_AF5_SPI5 ((uint8_t)0x05U) /* SPI5 Alternate Function mapping */ +#define GPIO_AF5_SPI6 ((uint8_t)0x05U) /* SPI6 Alternate Function mapping */ +#define GPIO_AF5_I2S3ext ((uint8_t)0x05U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_I2S2ext ((uint8_t)0x06U) /* I2S2ext_SD Alternate Function mapping */ +#define GPIO_AF6_SAI1 ((uint8_t)0x06U) /* SAI1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_I2S3ext ((uint8_t)0x07U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ +#define GPIO_AF8_UART7 ((uint8_t)0x08U) /* UART7 Alternate Function mapping */ +#define GPIO_AF8_UART8 ((uint8_t)0x08U) /* UART8 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN2 Alternate Function mapping */ +#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ +#define GPIO_AF9_LTDC ((uint8_t)0x09U) /* LCD-TFT Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_OTG_HS ((uint8_t)0x0AU) /* OTG_HS Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_ETH ((uint8_t)0x0BU) /* ETHERNET Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0CU) /* FMC Alternate Function mapping */ +#define GPIO_AF12_OTG_HS_FS ((uint8_t)0x0CU) /* OTG HS configured in FS, Alternate Function mapping */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_DCMI ((uint8_t)0x0DU) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_LTDC ((uint8_t)0x0EU) /* LCD-TFT Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ +#endif /* STM32F429xx || STM32F439xx */ +/*----------------------------------------------------------------------------*/ + +/*---------------------------------- STM32F427xx/STM32F437xx------------------*/ +#if defined(STM32F427xx) || defined(STM32F437xx) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4 Alternate Function mapping */ +#define GPIO_AF5_SPI5 ((uint8_t)0x05U) /* SPI5 Alternate Function mapping */ +#define GPIO_AF5_SPI6 ((uint8_t)0x05U) /* SPI6 Alternate Function mapping */ +/** @brief GPIO_Legacy + */ +#define GPIO_AF5_I2S3ext GPIO_AF5_SPI3 /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_I2S2ext ((uint8_t)0x06U) /* I2S2ext_SD Alternate Function mapping */ +#define GPIO_AF6_SAI1 ((uint8_t)0x06U) /* SAI1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_I2S3ext ((uint8_t)0x07U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ +#define GPIO_AF8_UART7 ((uint8_t)0x08U) /* UART7 Alternate Function mapping */ +#define GPIO_AF8_UART8 ((uint8_t)0x08U) /* UART8 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN2 Alternate Function mapping */ +#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_OTG_HS ((uint8_t)0x0AU) /* OTG_HS Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_ETH ((uint8_t)0x0BU) /* ETHERNET Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0CU) /* FMC Alternate Function mapping */ +#define GPIO_AF12_OTG_HS_FS ((uint8_t)0x0CU) /* OTG HS configured in FS, Alternate Function mapping */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_DCMI ((uint8_t)0x0DU) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ +#endif /* STM32F427xx || STM32F437xx */ +/*----------------------------------------------------------------------------*/ + +/*---------------------------------- STM32F407xx/STM32F417xx------------------*/ +#if defined(STM32F407xx) || defined(STM32F417xx) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_I2S3ext ((uint8_t)0x05U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_I2S2ext ((uint8_t)0x06U) /* I2S2ext_SD Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_I2S3ext ((uint8_t)0x07U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN2 Alternate Function mapping */ +#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_OTG_HS ((uint8_t)0x0AU) /* OTG_HS Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_ETH ((uint8_t)0x0BU) /* ETHERNET Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FSMC ((uint8_t)0x0CU) /* FSMC Alternate Function mapping */ +#define GPIO_AF12_OTG_HS_FS ((uint8_t)0x0CU) /* OTG HS configured in FS, Alternate Function mapping */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_DCMI ((uint8_t)0x0DU) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ +#endif /* STM32F407xx || STM32F417xx */ +/*----------------------------------------------------------------------------*/ + +/*---------------------------------- STM32F405xx/STM32F415xx------------------*/ +#if defined(STM32F405xx) || defined(STM32F415xx) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_I2S3ext ((uint8_t)0x05U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_I2S2ext ((uint8_t)0x06U) /* I2S2ext_SD Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_I2S3ext ((uint8_t)0x07U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN2 Alternate Function mapping */ +#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_OTG_HS ((uint8_t)0x0AU) /* OTG_HS Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FSMC ((uint8_t)0x0CU) /* FSMC Alternate Function mapping */ +#define GPIO_AF12_OTG_HS_FS ((uint8_t)0x0CU) /* OTG HS configured in FS, Alternate Function mapping */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ +#endif /* STM32F405xx || STM32F415xx */ + +/*----------------------------------------------------------------------------*/ + +/*---------------------------------------- STM32F401xx------------------------*/ +#if defined(STM32F401xC) || defined(STM32F401xE) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4 Alternate Function mapping */ +#define GPIO_AF5_I2S3ext ((uint8_t)0x05U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_I2S2ext ((uint8_t)0x06U) /* I2S2ext_SD Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_I2S3ext ((uint8_t)0x07U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ +#define GPIO_AF9_I2C2 ((uint8_t)0x09U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF9_I2C3 ((uint8_t)0x09U) /* I2C3 Alternate Function mapping */ + + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ +#endif /* STM32F401xC || STM32F401xE */ +/*----------------------------------------------------------------------------*/ + +/*--------------- STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx-------------*/ +#if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_FMPI2C1 ((uint8_t)0x04U) /* FMPI2C1 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1/I2S1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4/I2S4 Alternate Function mapping */ +#define GPIO_AF5_I2S3ext ((uint8_t)0x05U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI2 ((uint8_t)0x06U) /* I2S2 Alternate Function mapping */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_SPI4 ((uint8_t)0x06U) /* SPI4/I2S4 Alternate Function mapping */ +#define GPIO_AF6_SPI5 ((uint8_t)0x06U) /* SPI5/I2S5 Alternate Function mapping */ +#define GPIO_AF6_I2S2ext ((uint8_t)0x06U) /* I2S2ext_SD Alternate Function mapping */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06U) /* DFSDM1 Alternate Function mapping */ +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_SPI3 ((uint8_t)0x07U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_I2S3ext ((uint8_t)0x07U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ +#define GPIO_AF8_USART3 ((uint8_t)0x08U) /* USART3 Alternate Function mapping */ +#define GPIO_AF8_DFSDM1 ((uint8_t)0x08U) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF8_CAN1 ((uint8_t)0x08U) /* CAN1 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ +#define GPIO_AF9_I2C2 ((uint8_t)0x09U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF9_I2C3 ((uint8_t)0x09U) /* I2C3 Alternate Function mapping */ +#define GPIO_AF9_FMPI2C1 ((uint8_t)0x09U) /* FMPI2C1 Alternate Function mapping */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_QSPI ((uint8_t)0x09U) /* QSPI Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_DFSDM1 ((uint8_t)0x0AU) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF10_QSPI ((uint8_t)0x0AU) /* QSPI Alternate Function mapping */ +#define GPIO_AF10_FMC ((uint8_t)0x0AU) /* FMC Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ +#define GPIO_AF12_FSMC ((uint8_t)0x0CU) /* FMC Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ +#endif /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx */ + +/*----------------------------------------------------------------------------*/ + +/*--------------- STM32F413xx/STM32F423xx-------------------------------------*/ +#if defined(STM32F413xx) || defined(STM32F423xx) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01U) /* LPTIM1 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ +#define GPIO_AF3_DFSDM2 ((uint8_t)0x03U) /* DFSDM2 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_FMPI2C1 ((uint8_t)0x04U) /* FMPI2C1 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1/I2S1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4/I2S4 Alternate Function mapping */ +#define GPIO_AF5_I2S3ext ((uint8_t)0x05U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI2 ((uint8_t)0x06U) /* I2S2 Alternate Function mapping */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_SPI4 ((uint8_t)0x06U) /* SPI4/I2S4 Alternate Function mapping */ +#define GPIO_AF6_SPI5 ((uint8_t)0x06U) /* SPI5/I2S5 Alternate Function mapping */ +#define GPIO_AF6_I2S2ext ((uint8_t)0x06U) /* I2S2ext_SD Alternate Function mapping */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06U) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF6_DFSDM2 ((uint8_t)0x06U) /* DFSDM2 Alternate Function mapping */ +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_SPI3 ((uint8_t)0x07U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF7_SAI1 ((uint8_t)0x07U) /* SAI1 Alternate Function mapping */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_I2S3ext ((uint8_t)0x07U) /* I2S3ext_SD Alternate Function mapping */ +#define GPIO_AF7_DFSDM2 ((uint8_t)0x07U) /* DFSDM2 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ +#define GPIO_AF8_USART3 ((uint8_t)0x08U) /* USART3 Alternate Function mapping */ +#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_UART7 ((uint8_t)0x08U) /* UART8 Alternate Function mapping */ +#define GPIO_AF8_UART8 ((uint8_t)0x08U) /* UART8 Alternate Function mapping */ +#define GPIO_AF8_DFSDM1 ((uint8_t)0x08U) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF8_CAN1 ((uint8_t)0x08U) /* CAN1 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ +#define GPIO_AF9_I2C2 ((uint8_t)0x09U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF9_I2C3 ((uint8_t)0x09U) /* I2C3 Alternate Function mapping */ +#define GPIO_AF9_FMPI2C1 ((uint8_t)0x09U) /* FMPI2C1 Alternate Function mapping */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_QSPI ((uint8_t)0x09U) /* QSPI Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_SAI1 ((uint8_t)0x0AU) /* SAI1 Alternate Function mapping */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_DFSDM1 ((uint8_t)0x0AU) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF10_DFSDM2 ((uint8_t)0x0AU) /* DFSDM2 Alternate Function mapping */ +#define GPIO_AF10_QSPI ((uint8_t)0x0AU) /* QSPI Alternate Function mapping */ +#define GPIO_AF10_FSMC ((uint8_t)0x0AU) /* FSMC Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_UART4 ((uint8_t)0x0BU) /* UART4 Alternate Function mapping */ +#define GPIO_AF11_UART5 ((uint8_t)0x0BU) /* UART5 Alternate Function mapping */ +#define GPIO_AF11_UART9 ((uint8_t)0x0BU) /* UART9 Alternate Function mapping */ +#define GPIO_AF11_UART10 ((uint8_t)0x0BU) /* UART10 Alternate Function mapping */ +#define GPIO_AF11_CAN3 ((uint8_t)0x0BU) /* CAN3 Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ +#define GPIO_AF12_FSMC ((uint8_t)0x0CU) /* FMC Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_RNG ((uint8_t)0x0EU) /* RNG Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ +#endif /* STM32F413xx || STM32F423xx */ + +/*---------------------------------------- STM32F411xx------------------------*/ +#if defined(STM32F411xE) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1/I2S1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4 Alternate Function mapping */ +#define GPIO_AF5_I2S3ext ((uint8_t)0x05U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI2 ((uint8_t)0x06U) /* I2S2 Alternate Function mapping */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_SPI4 ((uint8_t)0x06U) /* SPI4/I2S4 Alternate Function mapping */ +#define GPIO_AF6_SPI5 ((uint8_t)0x06U) /* SPI5/I2S5 Alternate Function mapping */ +#define GPIO_AF6_I2S2ext ((uint8_t)0x06U) /* I2S2ext_SD Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_SPI3 ((uint8_t)0x07U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_I2S3ext ((uint8_t)0x07U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ +#define GPIO_AF9_I2C2 ((uint8_t)0x09U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF9_I2C3 ((uint8_t)0x09U) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ +#endif /* STM32F411xE */ + +/*---------------------------------------- STM32F410xx------------------------*/ +#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01U) /* LPTIM1 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_FMPI2C1 ((uint8_t)0x04U) /* FMPI2C1 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1/I2S1 Alternate Function mapping */ +#if defined(STM32F410Cx) || defined(STM32F410Rx) +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#endif /* STM32F410Cx || STM32F410Rx */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI1 ((uint8_t)0x06U) /* SPI1 Alternate Function mapping */ +#if defined(STM32F410Cx) || defined(STM32F410Rx) +#define GPIO_AF6_SPI2 ((uint8_t)0x06U) /* I2S2 Alternate Function mapping */ +#endif /* STM32F410Cx || STM32F410Rx */ +#define GPIO_AF6_SPI5 ((uint8_t)0x06U) /* SPI5/I2S5 Alternate Function mapping */ +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_I2C2 ((uint8_t)0x09U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF9_FMPI2C1 ((uint8_t)0x09U) /* FMPI2C1 Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ +#endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */ + +/*---------------------------------------- STM32F446xx -----------------------*/ +#if defined(STM32F446xx) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ +#define GPIO_AF3_CEC ((uint8_t)0x03U) /* CEC Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_FMPI2C1 ((uint8_t)0x04U) /* FMPI2C1 Alternate Function mapping */ +#define GPIO_AF4_CEC ((uint8_t)0x04U) /* CEC Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1/I2S1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI2 ((uint8_t)0x06U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_SPI4 ((uint8_t)0x06U) /* SPI4 Alternate Function mapping */ +#define GPIO_AF6_SAI1 ((uint8_t)0x06U) /* SAI1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_UART5 ((uint8_t)0x07U) /* UART5 Alternate Function mapping */ +#define GPIO_AF7_SPI2 ((uint8_t)0x07U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF7_SPI3 ((uint8_t)0x07U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF7_SPDIFRX ((uint8_t)0x07U) /* SPDIFRX Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ +#define GPIO_AF8_SPDIFRX ((uint8_t)0x08U) /* SPDIFRX Alternate Function mapping */ +#define GPIO_AF8_SAI2 ((uint8_t)0x08U) /* SAI2 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN2 Alternate Function mapping */ +#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ +#define GPIO_AF9_QSPI ((uint8_t)0x09U) /* QSPI Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_OTG_HS ((uint8_t)0x0AU) /* OTG_HS Alternate Function mapping */ +#define GPIO_AF10_SAI2 ((uint8_t)0x0AU) /* SAI2 Alternate Function mapping */ +#define GPIO_AF10_QSPI ((uint8_t)0x0AU) /* QSPI Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_ETH ((uint8_t)0x0BU) /* ETHERNET Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0CU) /* FMC Alternate Function mapping */ +#define GPIO_AF12_OTG_HS_FS ((uint8_t)0x0CU) /* OTG HS configured in FS, Alternate Function mapping */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_DCMI ((uint8_t)0x0DU) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ + +#endif /* STM32F446xx */ +/*----------------------------------------------------------------------------*/ + +/*-------------------------------- STM32F469xx/STM32F479xx--------------------*/ +#if defined(STM32F469xx) || defined(STM32F479xx) +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00U) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00U) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_TAMPER ((uint8_t)0x00U) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00U) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00U) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01U) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01U) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02U) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02U) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02U) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03U) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM9 ((uint8_t)0x03U) /* TIM9 Alternate Function mapping */ +#define GPIO_AF3_TIM10 ((uint8_t)0x03U) /* TIM10 Alternate Function mapping */ +#define GPIO_AF3_TIM11 ((uint8_t)0x03U) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04U) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04U) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04U) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05U) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05U) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05U) /* SPI4 Alternate Function mapping */ +#define GPIO_AF5_SPI5 ((uint8_t)0x05U) /* SPI5 Alternate Function mapping */ +#define GPIO_AF5_SPI6 ((uint8_t)0x05U) /* SPI6 Alternate Function mapping */ +#define GPIO_AF5_I2S3ext ((uint8_t)0x05U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06U) /* SPI3/I2S3 Alternate Function mapping */ +#define GPIO_AF6_I2S2ext ((uint8_t)0x06U) /* I2S2ext_SD Alternate Function mapping */ +#define GPIO_AF6_SAI1 ((uint8_t)0x06U) /* SAI1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07U) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07U) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07U) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_I2S3ext ((uint8_t)0x07U) /* I2S3ext_SD Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08U) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08U) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_USART6 ((uint8_t)0x08U) /* USART6 Alternate Function mapping */ +#define GPIO_AF8_UART7 ((uint8_t)0x08U) /* UART7 Alternate Function mapping */ +#define GPIO_AF8_UART8 ((uint8_t)0x08U) /* UART8 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09U) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_CAN2 ((uint8_t)0x09U) /* CAN2 Alternate Function mapping */ +#define GPIO_AF9_TIM12 ((uint8_t)0x09U) /* TIM12 Alternate Function mapping */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09U) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09U) /* TIM14 Alternate Function mapping */ +#define GPIO_AF9_LTDC ((uint8_t)0x09U) /* LCD-TFT Alternate Function mapping */ +#define GPIO_AF9_QSPI ((uint8_t)0x09U) /* QSPI Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0AU) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_OTG_HS ((uint8_t)0x0AU) /* OTG_HS Alternate Function mapping */ +#define GPIO_AF10_QSPI ((uint8_t)0x0AU) /* QSPI Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_ETH ((uint8_t)0x0BU) /* ETHERNET Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0CU) /* FMC Alternate Function mapping */ +#define GPIO_AF12_OTG_HS_FS ((uint8_t)0x0CU) /* OTG HS configured in FS, Alternate Function mapping */ +#define GPIO_AF12_SDIO ((uint8_t)0x0CU) /* SDIO Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_DCMI ((uint8_t)0x0DU) /* DCMI Alternate Function mapping */ +#define GPIO_AF13_DSI ((uint8_t)0x0DU) /* DSI Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_LTDC ((uint8_t)0x0EU) /* LCD-TFT Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0FU) /* EVENTOUT Alternate Function mapping */ + +#endif /* STM32F469xx || STM32F479xx */ +/*----------------------------------------------------------------------------*/ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Macros GPIO Exported Macros + * @{ + */ +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Functions GPIO Exported Functions + * @{ + */ +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup GPIOEx_Private_Constants GPIO Private Constants + * @{ + */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup GPIOEx_Private_Macros GPIO Private Macros + * @{ + */ +/** @defgroup GPIOEx_Get_Port_Index GPIO Get Port Index + * @{ + */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) +#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U :\ + ((__GPIOx__) == (GPIOH))? 7U : 8U) +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx */ + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ + defined(STM32F469xx) || defined(STM32F479xx) +#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U :\ + ((__GPIOx__) == (GPIOH))? 7U :\ + ((__GPIOx__) == (GPIOI))? 8U :\ + ((__GPIOx__) == (GPIOJ))? 9U : 10U) +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ + +#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) +#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U : 7U) +#endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */ + +#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) +#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U : 7U) +#endif /* STM32F401xC || STM32F401xE || STM32F411xE */ + +#if defined(STM32F446xx) || defined(STM32F412Zx) ||defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) +#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U : 7U) +#endif /* STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ + +/** + * @} + */ + +/** @defgroup GPIOEx_IS_Alternat_function_selection GPIO Check Alternate Function + * @{ + */ +/*------------------------- STM32F429xx/STM32F439xx---------------------------*/ +#if defined(STM32F429xx) || defined(STM32F439xx) +#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ + ((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \ + ((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \ + ((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \ + ((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \ + ((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \ + ((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \ + ((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF5_SPI1) || \ + ((AF) == GPIO_AF5_SPI2) || ((AF) == GPIO_AF9_TIM13) || \ + ((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF9_TIM12) || \ + ((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \ + ((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF8_UART4) || \ + ((AF) == GPIO_AF8_UART5) || ((AF) == GPIO_AF8_USART6) || \ + ((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \ + ((AF) == GPIO_AF10_OTG_FS) || ((AF) == GPIO_AF10_OTG_HS) || \ + ((AF) == GPIO_AF11_ETH) || ((AF) == GPIO_AF12_OTG_HS_FS) || \ + ((AF) == GPIO_AF12_SDIO) || ((AF) == GPIO_AF13_DCMI) || \ + ((AF) == GPIO_AF15_EVENTOUT) || ((AF) == GPIO_AF5_SPI4) || \ + ((AF) == GPIO_AF5_SPI5) || ((AF) == GPIO_AF5_SPI6) || \ + ((AF) == GPIO_AF8_UART7) || ((AF) == GPIO_AF8_UART8) || \ + ((AF) == GPIO_AF12_FMC) || ((AF) == GPIO_AF6_SAI1) || \ + ((AF) == GPIO_AF14_LTDC)) + +#endif /* STM32F429xx || STM32F439xx */ +/*----------------------------------------------------------------------------*/ + +/*---------------------------------- STM32F427xx/STM32F437xx------------------*/ +#if defined(STM32F427xx) || defined(STM32F437xx) +#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ + ((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \ + ((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \ + ((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \ + ((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \ + ((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \ + ((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \ + ((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF5_SPI1) || \ + ((AF) == GPIO_AF5_SPI2) || ((AF) == GPIO_AF9_TIM13) || \ + ((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF9_TIM12) || \ + ((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \ + ((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF8_UART4) || \ + ((AF) == GPIO_AF8_UART5) || ((AF) == GPIO_AF8_USART6) || \ + ((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \ + ((AF) == GPIO_AF10_OTG_FS) || ((AF) == GPIO_AF10_OTG_HS) || \ + ((AF) == GPIO_AF11_ETH) || ((AF) == GPIO_AF12_OTG_HS_FS) || \ + ((AF) == GPIO_AF12_SDIO) || ((AF) == GPIO_AF13_DCMI) || \ + ((AF) == GPIO_AF15_EVENTOUT) || ((AF) == GPIO_AF5_SPI4) || \ + ((AF) == GPIO_AF5_SPI5) || ((AF) == GPIO_AF5_SPI6) || \ + ((AF) == GPIO_AF8_UART7) || ((AF) == GPIO_AF8_UART8) || \ + ((AF) == GPIO_AF12_FMC) || ((AF) == GPIO_AF6_SAI1)) + +#endif /* STM32F427xx || STM32F437xx */ +/*----------------------------------------------------------------------------*/ + +/*---------------------------------- STM32F407xx/STM32F417xx------------------*/ +#if defined(STM32F407xx) || defined(STM32F417xx) +#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ + ((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \ + ((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \ + ((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \ + ((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \ + ((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \ + ((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \ + ((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF5_SPI1) || \ + ((AF) == GPIO_AF5_SPI2) || ((AF) == GPIO_AF9_TIM13) || \ + ((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF9_TIM12) || \ + ((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \ + ((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF8_UART4) || \ + ((AF) == GPIO_AF8_UART5) || ((AF) == GPIO_AF8_USART6) || \ + ((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \ + ((AF) == GPIO_AF10_OTG_FS) || ((AF) == GPIO_AF10_OTG_HS) || \ + ((AF) == GPIO_AF11_ETH) || ((AF) == GPIO_AF12_OTG_HS_FS) || \ + ((AF) == GPIO_AF12_SDIO) || ((AF) == GPIO_AF13_DCMI) || \ + ((AF) == GPIO_AF12_FSMC) || ((AF) == GPIO_AF15_EVENTOUT)) + +#endif /* STM32F407xx || STM32F417xx */ +/*----------------------------------------------------------------------------*/ + +/*---------------------------------- STM32F405xx/STM32F415xx------------------*/ +#if defined(STM32F405xx) || defined(STM32F415xx) +#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ + ((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \ + ((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \ + ((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \ + ((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \ + ((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \ + ((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \ + ((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF5_SPI1) || \ + ((AF) == GPIO_AF5_SPI2) || ((AF) == GPIO_AF9_TIM13) || \ + ((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF9_TIM12) || \ + ((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \ + ((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF8_UART4) || \ + ((AF) == GPIO_AF8_UART5) || ((AF) == GPIO_AF8_USART6) || \ + ((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \ + ((AF) == GPIO_AF10_OTG_FS) || ((AF) == GPIO_AF10_OTG_HS) || \ + ((AF) == GPIO_AF12_OTG_HS_FS) || ((AF) == GPIO_AF12_SDIO) || \ + ((AF) == GPIO_AF12_FSMC) || ((AF) == GPIO_AF15_EVENTOUT)) + +#endif /* STM32F405xx || STM32F415xx */ + +/*----------------------------------------------------------------------------*/ + +/*---------------------------------------- STM32F401xx------------------------*/ +#if defined(STM32F401xC) || defined(STM32F401xE) +#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ + ((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \ + ((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \ + ((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \ + ((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \ + ((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF4_I2C1) || \ + ((AF) == GPIO_AF4_I2C2) || ((AF) == GPIO_AF4_I2C3) || \ + ((AF) == GPIO_AF5_SPI1) || ((AF) == GPIO_AF5_SPI2) || \ + ((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF5_SPI4) || \ + ((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \ + ((AF) == GPIO_AF8_USART6) || ((AF) == GPIO_AF10_OTG_FS) || \ + ((AF) == GPIO_AF9_I2C2) || ((AF) == GPIO_AF9_I2C3) || \ + ((AF) == GPIO_AF12_SDIO) || ((AF) == GPIO_AF15_EVENTOUT)) + +#endif /* STM32F401xC || STM32F401xE */ +/*----------------------------------------------------------------------------*/ +/*---------------------------------------- STM32F410xx------------------------*/ +#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) +#define IS_GPIO_AF(AF) (((AF) < 10U) || ((AF) == 15U)) +#endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */ + +/*---------------------------------------- STM32F411xx------------------------*/ +#if defined(STM32F411xE) +#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ + ((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \ + ((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \ + ((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \ + ((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \ + ((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF4_I2C1) || \ + ((AF) == GPIO_AF4_I2C2) || ((AF) == GPIO_AF4_I2C3) || \ + ((AF) == GPIO_AF5_SPI1) || ((AF) == GPIO_AF5_SPI2) || \ + ((AF) == GPIO_AF5_SPI3) || ((AF) == GPIO_AF6_SPI4) || \ + ((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF5_SPI4) || \ + ((AF) == GPIO_AF6_SPI5) || ((AF) == GPIO_AF7_SPI3) || \ + ((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \ + ((AF) == GPIO_AF8_USART6) || ((AF) == GPIO_AF10_OTG_FS) || \ + ((AF) == GPIO_AF9_I2C2) || ((AF) == GPIO_AF9_I2C3) || \ + ((AF) == GPIO_AF12_SDIO) || ((AF) == GPIO_AF15_EVENTOUT)) + +#endif /* STM32F411xE */ +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------- STM32F446xx ----------------*/ +#if defined(STM32F446xx) +#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ + ((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \ + ((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \ + ((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \ + ((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \ + ((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \ + ((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \ + ((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF5_SPI1) || \ + ((AF) == GPIO_AF5_SPI2) || ((AF) == GPIO_AF9_TIM13) || \ + ((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF9_TIM12) || \ + ((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \ + ((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF8_UART4) || \ + ((AF) == GPIO_AF8_UART5) || ((AF) == GPIO_AF8_USART6) || \ + ((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \ + ((AF) == GPIO_AF10_OTG_FS) || ((AF) == GPIO_AF10_OTG_HS) || \ + ((AF) == GPIO_AF11_ETH) || ((AF) == GPIO_AF12_OTG_HS_FS) || \ + ((AF) == GPIO_AF12_SDIO) || ((AF) == GPIO_AF13_DCMI) || \ + ((AF) == GPIO_AF15_EVENTOUT) || ((AF) == GPIO_AF5_SPI4) || \ + ((AF) == GPIO_AF12_FMC) || ((AF) == GPIO_AF6_SAI1) || \ + ((AF) == GPIO_AF3_CEC) || ((AF) == GPIO_AF4_CEC) || \ + ((AF) == GPIO_AF5_SPI3) || ((AF) == GPIO_AF6_SPI2) || \ + ((AF) == GPIO_AF6_SPI4) || ((AF) == GPIO_AF7_UART5) || \ + ((AF) == GPIO_AF7_SPI2) || ((AF) == GPIO_AF7_SPI3) || \ + ((AF) == GPIO_AF7_SPDIFRX) || ((AF) == GPIO_AF8_SPDIFRX) || \ + ((AF) == GPIO_AF8_SAI2) || ((AF) == GPIO_AF9_QSPI) || \ + ((AF) == GPIO_AF10_SAI2) || ((AF) == GPIO_AF10_QSPI)) + +#endif /* STM32F446xx */ +/*----------------------------------------------------------------------------*/ + +/*------------------------------------------- STM32F469xx/STM32F479xx --------*/ +#if defined(STM32F469xx) || defined(STM32F479xx) +#define IS_GPIO_AF(AF) (((AF) == GPIO_AF0_RTC_50Hz) || ((AF) == GPIO_AF9_TIM14) || \ + ((AF) == GPIO_AF0_MCO) || ((AF) == GPIO_AF0_TAMPER) || \ + ((AF) == GPIO_AF0_SWJ) || ((AF) == GPIO_AF0_TRACE) || \ + ((AF) == GPIO_AF1_TIM1) || ((AF) == GPIO_AF1_TIM2) || \ + ((AF) == GPIO_AF2_TIM3) || ((AF) == GPIO_AF2_TIM4) || \ + ((AF) == GPIO_AF2_TIM5) || ((AF) == GPIO_AF3_TIM8) || \ + ((AF) == GPIO_AF4_I2C1) || ((AF) == GPIO_AF4_I2C2) || \ + ((AF) == GPIO_AF4_I2C3) || ((AF) == GPIO_AF5_SPI1) || \ + ((AF) == GPIO_AF5_SPI2) || ((AF) == GPIO_AF9_TIM13) || \ + ((AF) == GPIO_AF6_SPI3) || ((AF) == GPIO_AF9_TIM12) || \ + ((AF) == GPIO_AF7_USART1) || ((AF) == GPIO_AF7_USART2) || \ + ((AF) == GPIO_AF7_USART3) || ((AF) == GPIO_AF8_UART4) || \ + ((AF) == GPIO_AF8_UART5) || ((AF) == GPIO_AF8_USART6) || \ + ((AF) == GPIO_AF9_CAN1) || ((AF) == GPIO_AF9_CAN2) || \ + ((AF) == GPIO_AF10_OTG_FS) || ((AF) == GPIO_AF10_OTG_HS) || \ + ((AF) == GPIO_AF11_ETH) || ((AF) == GPIO_AF12_OTG_HS_FS) || \ + ((AF) == GPIO_AF12_SDIO) || ((AF) == GPIO_AF13_DCMI) || \ + ((AF) == GPIO_AF15_EVENTOUT) || ((AF) == GPIO_AF5_SPI4) || \ + ((AF) == GPIO_AF5_SPI5) || ((AF) == GPIO_AF5_SPI6) || \ + ((AF) == GPIO_AF8_UART7) || ((AF) == GPIO_AF8_UART8) || \ + ((AF) == GPIO_AF12_FMC) || ((AF) == GPIO_AF6_SAI1) || \ + ((AF) == GPIO_AF14_LTDC) || ((AF) == GPIO_AF13_DSI) || \ + ((AF) == GPIO_AF9_QSPI) || ((AF) == GPIO_AF10_QSPI)) + +#endif /* STM32F469xx || STM32F479xx */ +/*----------------------------------------------------------------------------*/ + +/*------------------STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx-----------*/ +#if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) +#define IS_GPIO_AF(AF) (((AF) < 16U) && ((AF) != 11U) && ((AF) != 14U) && ((AF) != 13U)) +#endif /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx */ +/*----------------------------------------------------------------------------*/ + +/*------------------STM32F413xx/STM32F423xx-----------------------------------*/ +#if defined(STM32F413xx) || defined(STM32F423xx) +#define IS_GPIO_AF(AF) (((AF) < 16U) && ((AF) != 13U)) +#endif /* STM32F413xx || STM32F423xx */ +/*----------------------------------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup GPIOEx_Private_Functions GPIO Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_GPIO_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda_tici/board/stm32f4/inc/system_stm32f4xx.h b/panda_tici/board/stm32f4/inc/system_stm32f4xx.h new file mode 100644 index 0000000..7978dab --- /dev/null +++ b/panda_tici/board/stm32f4/inc/system_stm32f4xx.h @@ -0,0 +1,124 @@ +/** + ****************************************************************************** + * @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 + * + *

© COPYRIGHT(c) 2016 STMicroelectronics

+ * + * 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****/ diff --git a/panda_tici/board/stm32f4/interrupt_handlers.h b/panda_tici/board/stm32f4/interrupt_handlers.h new file mode 100644 index 0000000..41d7427 --- /dev/null +++ b/panda_tici/board/stm32f4/interrupt_handlers.h @@ -0,0 +1,98 @@ +// ********************* 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);} diff --git a/panda_tici/board/stm32f4/lladc.h b/panda_tici/board/stm32f4/lladc.h new file mode 100644 index 0000000..897abf2 --- /dev/null +++ b/panda_tici/board/stm32f4/lladc.h @@ -0,0 +1,24 @@ + +void register_set(volatile uint32_t *addr, uint32_t val, uint32_t mask); + +void adc_init(void) { + register_set(&(ADC->CCR), ADC_CCR_TSVREFE | ADC_CCR_VBATE, 0xC30000U); + register_set(&(ADC1->CR2), ADC_CR2_ADON, 0xFF7F0F03U); + register_set(&(ADC1->SMPR1), ADC_SMPR1_SMP12 | ADC_SMPR1_SMP13, 0x7FFFFFFU); +} + +static uint16_t adc_get_raw(uint8_t channel) { + // Select channel + register_set(&(ADC1->JSQR), ((uint32_t) channel << 15U), 0x3FFFFFU); + + // Start conversion + ADC1->SR &= ~(ADC_SR_JEOC); + ADC1->CR2 |= ADC_CR2_JSWSTART; + while (!(ADC1->SR & ADC_SR_JEOC)); + + return ADC1->JDR1; +} + +uint16_t adc_get_mV(uint8_t channel) { + return (adc_get_raw(channel) * current_board->avdd_mV) / 4095U; +} diff --git a/panda_tici/board/stm32f4/lladc_declarations.h b/panda_tici/board/stm32f4/lladc_declarations.h new file mode 100644 index 0000000..64a733a --- /dev/null +++ b/panda_tici/board/stm32f4/lladc_declarations.h @@ -0,0 +1,20 @@ +#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} diff --git a/panda_tici/board/stm32f4/llbxcan.h b/panda_tici/board/stm32f4/llbxcan.h new file mode 100644 index 0000000..82794be --- /dev/null +++ b/panda_tici/board/stm32f4/llbxcan.h @@ -0,0 +1,140 @@ +#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 +} diff --git a/panda_tici/board/stm32f4/llbxcan_declarations.h b/panda_tici/board/stm32f4/llbxcan_declarations.h new file mode 100644 index 0000000..aa10719 --- /dev/null +++ b/panda_tici/board/stm32f4/llbxcan_declarations.h @@ -0,0 +1,28 @@ +#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); diff --git a/panda_tici/board/stm32f4/llfan.h b/panda_tici/board/stm32f4/llfan.h new file mode 100644 index 0000000..9586166 --- /dev/null +++ b/panda_tici/board/stm32f4/llfan.h @@ -0,0 +1,23 @@ +// 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); +} diff --git a/panda_tici/board/stm32f4/llflash.h b/panda_tici/board/stm32f4/llflash.h new file mode 100644 index 0000000..61adcd4 --- /dev/null +++ b/panda_tici/board/stm32f4/llflash.h @@ -0,0 +1,28 @@ +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) { } diff --git a/panda_tici/board/stm32f4/llspi.h b/panda_tici/board/stm32f4/llspi.h new file mode 100644 index 0000000..e986adb --- /dev/null +++ b/panda_tici/board/stm32f4/llspi.h @@ -0,0 +1,91 @@ +#if defined(ENABLE_SPI) || defined(BOOTSTUB) +void llspi_miso_dma(uint8_t *addr, int len) { + // disable DMA + DMA2_Stream3->CR &= ~DMA_SxCR_EN; + register_clear_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN); + + // setup source and length + register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU); + DMA2_Stream3->NDTR = len; + + // enable DMA + register_set_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN); + DMA2_Stream3->CR |= DMA_SxCR_EN; +} + +void llspi_mosi_dma(uint8_t *addr, int len) { + // disable DMA + register_clear_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN); + DMA2_Stream2->CR &= ~DMA_SxCR_EN; + + // drain the bus + volatile uint8_t dat = SPI1->DR; + (void)dat; + + // setup destination and length + register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU); + DMA2_Stream2->NDTR = len; + + // enable DMA + DMA2_Stream2->CR |= DMA_SxCR_EN; + register_set_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN); +} +// SPI MOSI DMA FINISHED +static void DMA2_Stream2_IRQ_Handler(void) { + // Clear interrupt flag + ENTER_CRITICAL(); + DMA2->LIFCR = DMA_LIFCR_CTCIF2; + + spi_rx_done(); + + EXIT_CRITICAL(); +} + +// SPI MISO DMA FINISHED +static void DMA2_Stream3_IRQ_Handler(void) { + // Clear interrupt flag + DMA2->LIFCR = DMA_LIFCR_CTCIF3; + + // Wait until the transaction is actually finished and clear the DR + // Timeout to prevent hang when the master clock stops. + bool timed_out = false; + uint32_t start_time = microsecond_timer_get(); + while (!(SPI1->SR & SPI_SR_TXE)) { + if (get_ts_elapsed(microsecond_timer_get(), start_time) > SPI_TIMEOUT_US) { + timed_out = true; + break; + } + } + volatile uint8_t dat = SPI1->DR; + (void)dat; + SPI1->DR = 0U; + + if (timed_out) { + print("SPI: TX timeout\n"); + } + + spi_tx_done(timed_out); +} + +// ***************************** SPI init ***************************** +void llspi_init(void) { + REGISTER_INTERRUPT(DMA2_Stream2_IRQn, DMA2_Stream2_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA) + REGISTER_INTERRUPT(DMA2_Stream3_IRQn, DMA2_Stream3_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA) + + // Setup MOSI DMA + register_set(&(DMA2_Stream2->CR), (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_TCIE), 0x1E077EFEU); + register_set(&(DMA2_Stream2->PAR), (uint32_t)&(SPI1->DR), 0xFFFFFFFFU); + + // Setup MISO DMA + register_set(&(DMA2_Stream3->CR), (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE), 0x1E077EFEU); + register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI1->DR), 0xFFFFFFFFU); + + // Enable SPI and the error interrupts + // TODO: verify clock phase and polarity + register_set(&(SPI1->CR1), SPI_CR1_SPE, 0xFFFFU); + register_set(&(SPI1->CR2), 0U, 0xF7U); + + NVIC_EnableIRQ(DMA2_Stream2_IRQn); + NVIC_EnableIRQ(DMA2_Stream3_IRQn); +} +#endif diff --git a/panda_tici/board/stm32f4/lluart.h b/panda_tici/board/stm32f4/lluart.h new file mode 100644 index 0000000..660c1ce --- /dev/null +++ b/panda_tici/board/stm32f4/lluart.h @@ -0,0 +1,35 @@ +// ***************************** Interrupt handlers ***************************** + +void uart_tx_ring(uart_ring *q){ + ENTER_CRITICAL(); + // Send out next byte of TX buffer + if (q->w_ptr_tx != q->r_ptr_tx) { + // Only send if transmit register is empty (aka last byte has been sent) + if ((q->uart->SR & USART_SR_TXE) != 0U) { + q->uart->DR = q->elems_tx[q->r_ptr_tx]; // This clears TXE + q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size; + } + + // Enable TXE interrupt if there is still data to be sent + if(q->r_ptr_tx != q->w_ptr_tx){ + q->uart->CR1 |= USART_CR1_TXEIE; + } else { + q->uart->CR1 &= ~USART_CR1_TXEIE; + } + } + EXIT_CRITICAL(); +} + +// This read after reading SR clears all error interrupts. We don't want compiler warnings, nor optimizations +#define UART_READ_DR(uart) volatile uint8_t t = (uart)->DR; UNUSED(t); + +// ***************************** Hardware setup ***************************** + +#define DIV_(_PCLK_, _BAUD_) (((_PCLK_) * 25U) / (4U * (_BAUD_))) +#define DIVMANT_(_PCLK_, _BAUD_) (DIV_((_PCLK_), (_BAUD_)) / 100U) +#define DIVFRAQ_(_PCLK_, _BAUD_) ((((DIV_((_PCLK_), (_BAUD_)) - (DIVMANT_((_PCLK_), (_BAUD_)) * 100U)) * 16U) + 50U) / 100U) +#define USART_BRR_(_PCLK_, _BAUD_) ((DIVMANT_((_PCLK_), (_BAUD_)) << 4) | (DIVFRAQ_((_PCLK_), (_BAUD_)) & 0x0FU)) + +void uart_set_baud(USART_TypeDef *u, unsigned int baud) { + u->BRR = USART_BRR_(APB1_FREQ*1000000U, baud); +} diff --git a/panda_tici/board/stm32f4/llusb.h b/panda_tici/board/stm32f4/llusb.h new file mode 100644 index 0000000..3d3b35e --- /dev/null +++ b/panda_tici/board/stm32f4/llusb.h @@ -0,0 +1,80 @@ +#include "llusb_declarations.h" + +USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS; + +static void OTG_FS_IRQ_Handler(void) { + NVIC_DisableIRQ(OTG_FS_IRQn); + //__disable_irq(); + usb_irqhandler(); + //__enable_irq(); + NVIC_EnableIRQ(OTG_FS_IRQn); +} + +void usb_init(void) { + REGISTER_INTERRUPT(OTG_FS_IRQn, OTG_FS_IRQ_Handler, 1500000U, FAULT_INTERRUPT_RATE_USB) //TODO: Find out a better rate limit for USB. Now it's the 1.5MB/s rate + + // full speed PHY, do reset and remove power down + /*puth(USBx->GRSTCTL); + print(" resetting PHY\n");*/ + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U); + //print("AHB idle\n"); + + // reset PHY here + USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); + //print("reset done\n"); + + // internal PHY, force device mode + USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_FDMOD; + + // slowest timings + USBx->GUSBCFG |= ((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT); + + // power up the PHY + USBx->GCCFG = USB_OTG_GCCFG_PWRDWN; + + //USBx->GCCFG |= USB_OTG_GCCFG_VBDEN | USB_OTG_GCCFG_SDEN |USB_OTG_GCCFG_PDEN | USB_OTG_GCCFG_DCDEN; + + /* B-peripheral session valid override enable*/ + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; + + // be a device, slowest timings + //USBx->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL; + //USBx->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT); + //USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL; + + // **** for debugging, doesn't seem to work **** + //USBx->GUSBCFG |= USB_OTG_GUSBCFG_CTXPKT; + + // reset PHY clock + USBx_PCGCCTL = 0; + + // enable the fancy OTG things + // DCFG_FRAME_INTERVAL_80 is 0 + //USBx->GUSBCFG |= USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP; + USBx_DEVICE->DCFG |= USB_OTG_SPEED_FULL | USB_OTG_DCFG_NZLSOHSK; + + //USBx_DEVICE->DCFG = USB_OTG_DCFG_NZLSOHSK | USB_OTG_DCFG_DSPD; + //USBx_DEVICE->DCFG = USB_OTG_DCFG_DSPD; + + // clear pending interrupts + USBx->GINTSTS = 0xBFFFFFFFU; + + // setup USB interrupts + // all interrupts except TXFIFO EMPTY + //USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF); + //USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM); + USBx->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_OTGINT | + USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_GONAKEFFM | USB_OTG_GINTMSK_GINAKEFFM | + USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_USBSUSPM | + USB_OTG_GINTMSK_CIDSCHGM | USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_MMISM | USB_OTG_GINTMSK_EOPFM; + + USBx->GAHBCFG = USB_OTG_GAHBCFG_GINT; + + // DCTL startup value is 2 on new chip, 0 on old chip + USBx_DEVICE->DCTL = 0; + + // enable the IRQ + NVIC_EnableIRQ(OTG_FS_IRQn); +} diff --git a/panda_tici/board/stm32f4/llusb_declarations.h b/panda_tici/board/stm32f4/llusb_declarations.h new file mode 100644 index 0000000..5ca962b --- /dev/null +++ b/panda_tici/board/stm32f4/llusb_declarations.h @@ -0,0 +1,16 @@ +#pragma once + +extern USB_OTG_GlobalTypeDef *USBx; + +#define USBx_DEVICE ((USB_OTG_DeviceTypeDef *)((uint32_t)USBx + USB_OTG_DEVICE_BASE)) +#define USBx_INEP(i) ((USB_OTG_INEndpointTypeDef *)((uint32_t)USBx + USB_OTG_IN_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE))) +#define USBx_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)((uint32_t)USBx + USB_OTG_OUT_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE))) +#define USBx_DFIFO(i) *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_FIFO_BASE + ((i) * USB_OTG_FIFO_SIZE)) +#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_PCGCCTL_BASE) + +#define USBD_FS_TRDT_VALUE 5UL +#define USB_OTG_SPEED_FULL 3UL + + +void usb_irqhandler(void); +void usb_init(void); diff --git a/panda_tici/board/stm32f4/peripherals.h b/panda_tici/board/stm32f4/peripherals.h new file mode 100644 index 0000000..fc97409 --- /dev/null +++ b/panda_tici/board/stm32f4/peripherals.h @@ -0,0 +1,100 @@ +#ifdef BOOTSTUB +void gpio_usb_init(void) { +#else +static void gpio_usb_init(void) { +#endif + // A11,A12: USB + set_gpio_alternate(GPIOA, 11, GPIO_AF10_OTG_FS); + set_gpio_alternate(GPIOA, 12, GPIO_AF10_OTG_FS); + GPIOA->OSPEEDR = GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12; +} + +#ifdef ENABLE_SPI +void gpio_spi_init(void) { + // A4-A7: SPI + set_gpio_alternate(GPIOA, 4, GPIO_AF5_SPI1); + set_gpio_alternate(GPIOA, 5, GPIO_AF5_SPI1); + set_gpio_alternate(GPIOA, 6, GPIO_AF5_SPI1); + set_gpio_alternate(GPIOA, 7, GPIO_AF5_SPI1); + register_set_bits(&(GPIOA->OSPEEDR), GPIO_OSPEEDER_OSPEEDR4 | GPIO_OSPEEDER_OSPEEDR5 | GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7); +} +#endif + +#ifdef BOOTSTUB +void gpio_usart2_init(void) { + // A2,A3: USART 2 for debugging + set_gpio_alternate(GPIOA, 2, GPIO_AF7_USART2); + set_gpio_alternate(GPIOA, 3, GPIO_AF7_USART2); +} +#endif + +// Common GPIO initialization +void common_init_gpio(void) { + // TODO: Is this block actually doing something??? + // pull low to hold ESP in reset?? + // enable OTG out tied to ground + GPIOA->ODR = 0; + GPIOB->ODR = 0; + GPIOA->PUPDR = 0; + GPIOB->AFR[0] = 0; + GPIOB->AFR[1] = 0; + + // C2: Voltage sense line + set_gpio_mode(GPIOC, 2, MODE_ANALOG); + + gpio_usb_init(); + + // B8,B9: CAN 1 + set_gpio_alternate(GPIOB, 8, GPIO_AF8_CAN1); + set_gpio_alternate(GPIOB, 9, GPIO_AF8_CAN1); +} + +#ifdef BOOTSTUB +void flasher_peripherals_init(void) { + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; + RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; + RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN; + RCC->APB1ENR |= RCC_APB1ENR_USART2EN; +} +#endif + +// Peripheral initialization +void peripherals_init(void) { + // enable GPIO(A,B,C,D) + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; + RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; + + // Supplemental + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; + RCC->APB1ENR |= RCC_APB1ENR_PWREN; // for RTC config + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; + + // Connectivity + RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; + RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN; + RCC->APB1ENR |= RCC_APB1ENR_USART2EN; + RCC->APB1ENR |= RCC_APB1ENR_USART3EN; + RCC->APB1ENR |= RCC_APB1ENR_UART5EN; + RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; + RCC->APB1ENR |= RCC_APB1ENR_CAN2EN; + RCC->APB1ENR |= RCC_APB1ENR_CAN3EN; + + // Analog + RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; + RCC->APB1ENR |= RCC_APB1ENR_DACEN; + + // Timers + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // clock source timer + RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // main counter + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // pedal and fan PWM + RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // IR PWM + RCC->APB1ENR |= RCC_APB1ENR_TIM5EN; // k-line init + RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; // interrupt timer + RCC->APB2ENR |= RCC_APB2ENR_TIM9EN; // slow loop +} + +void enable_interrupt_timer(void) { + register_set_bits(&(RCC->APB1ENR), RCC_APB1ENR_TIM6EN); // Enable interrupt timer peripheral +} diff --git a/panda_tici/board/stm32f4/startup_stm32f413xx.s b/panda_tici/board/stm32f4/startup_stm32f413xx.s new file mode 100644 index 0000000..6e6fb5f --- /dev/null +++ b/panda_tici/board/stm32f4/startup_stm32f413xx.s @@ -0,0 +1,583 @@ +/** + ****************************************************************************** + * @file startup_stm32f413xx.s + * @author MCD Application Team + * @version V2.6.0 + * @date 04-November-2016 + * @brief STM32F413xx Devices vector table for GCC based toolchains. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * 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. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m4 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* set stack pointer */ + bl __initialize_hardware_early + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + /* bl SystemInit */ +/* Call static constructors */ + /* bl __libc_init_array */ +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word CAN1_TX_IRQHandler /* CAN1 TX */ + .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FSMC_IRQHandler /* FSMC */ + .word SDIO_IRQHandler /* SDIO */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6, DAC1 and DAC2 */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word DFSDM1_FLT0_IRQHandler /* DFSDM1 Filter0 */ + .word DFSDM1_FLT1_IRQHandler /* DFSDM1 Filter1 */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word CAN3_TX_IRQHandler /* CAN3 TX */ + .word CAN3_RX0_IRQHandler /* CAN3 RX0 */ + .word CAN3_RX1_IRQHandler /* CAN3 RX1 */ + .word CAN3_SCE_IRQHandler /* CAN3 SCE */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word RNG_IRQHandler /* RNG */ + .word FPU_IRQHandler /* FPU */ + .word UART7_IRQHandler /* UART7 */ + .word UART8_IRQHandler /* UART8 */ + .word SPI4_IRQHandler /* SPI4 */ + .word SPI5_IRQHandler /* SPI5 */ + .word 0 /* Reserved */ + .word SAI1_IRQHandler /* SAI1 */ + .word UART9_IRQHandler /* UART9 */ + .word UART10_IRQHandler /* UART10 */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word QUADSPI_IRQHandler /* QuadSPI */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word FMPI2C1_EV_IRQHandler /* FMPI2C1 Event */ + .word FMPI2C1_ER_IRQHandler /* FMPI2C1 Error */ + .word LPTIM1_IRQHandler /* LPTIM1 */ + .word DFSDM2_FLT0_IRQHandler /* DFSDM2 Filter0 */ + .word DFSDM2_FLT1_IRQHandler /* DFSDM2 Filter1 */ + .word DFSDM2_FLT2_IRQHandler /* DFSDM2 Filter2 */ + .word DFSDM2_FLT3_IRQHandler /* DFSDM2 Filter3 */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM9_IRQHandler + .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM10_IRQHandler + .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM11_IRQHandler + .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FSMC_IRQHandler + .thumb_set FSMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak DFSDM1_FLT0_IRQHandler + .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler + + .weak DFSDM1_FLT1_IRQHandler + .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak CAN3_TX_IRQHandler + .thumb_set CAN3_TX_IRQHandler,Default_Handler + + .weak CAN3_RX0_IRQHandler + .thumb_set CAN3_RX0_IRQHandler,Default_Handler + + .weak CAN3_RX1_IRQHandler + .thumb_set CAN3_RX1_IRQHandler,Default_Handler + + .weak CAN3_SCE_IRQHandler + .thumb_set CAN3_SCE_IRQHandler,Default_Handler + + .weak RNG_IRQHandler + .thumb_set RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak UART7_IRQHandler + .thumb_set UART7_IRQHandler,Default_Handler + + .weak UART8_IRQHandler + .thumb_set UART8_IRQHandler,Default_Handler + + .weak SPI4_IRQHandler + .thumb_set SPI4_IRQHandler,Default_Handler + + .weak SPI5_IRQHandler + .thumb_set SPI5_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak UART9_IRQHandler + .thumb_set UART9_IRQHandler,Default_Handler + + .weak UART10_IRQHandler + .thumb_set UART10_IRQHandler,Default_Handler + + .weak QUADSPI_IRQHandler + .thumb_set QUADSPI_IRQHandler,Default_Handler + + .weak FMPI2C1_EV_IRQHandler + .thumb_set FMPI2C1_EV_IRQHandler,Default_Handler + + .weak FMPI2C1_ER_IRQHandler + .thumb_set FMPI2C1_ER_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak DFSDM2_FLT0_IRQHandler + .thumb_set DFSDM2_FLT0_IRQHandler,Default_Handler + + .weak DFSDM2_FLT1_IRQHandler + .thumb_set DFSDM2_FLT1_IRQHandler,Default_Handler + + .weak DFSDM2_FLT2_IRQHandler + .thumb_set DFSDM2_FLT2_IRQHandler,Default_Handler + + .weak DFSDM2_FLT3_IRQHandler + .thumb_set DFSDM2_FLT3_IRQHandler,Default_Handler +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda_tici/board/stm32f4/stm32f4_config.h b/panda_tici/board/stm32f4/stm32f4_config.h new file mode 100644 index 0000000..b3fc2a8 --- /dev/null +++ b/panda_tici/board/stm32f4/stm32f4_config.h @@ -0,0 +1,78 @@ +#include "stm32f4/inc/stm32f4xx.h" +#include "stm32f4/inc/stm32f4xx_hal_gpio_ex.h" +#define MCU_IDCODE 0x463U + +#define CORE_FREQ 96U // in MHz +#define APB1_FREQ (CORE_FREQ/2U) +#define APB1_TIMER_FREQ (APB1_FREQ*2U) // APB1 is multiplied by 2 for the timer peripherals +#define APB2_FREQ (CORE_FREQ/2U) +#define APB2_TIMER_FREQ (APB2_FREQ*2U) // APB2 is multiplied by 2 for the timer peripherals + +#define BOOTLOADER_ADDRESS 0x1FFF0004U + +// Around (1Mbps / 8 bits/byte / 12 bytes per message) +#define CAN_INTERRUPT_RATE 12000U + +#define MAX_LED_FADE 8192U + +#define NUM_INTERRUPTS 102U // There are 102 external interrupt sources (see stm32f413.h) + +#define TICK_TIMER_IRQ TIM1_BRK_TIM9_IRQn +#define TICK_TIMER TIM9 + +#define MICROSECOND_TIMER TIM2 + +#define INTERRUPT_TIMER_IRQ TIM6_DAC_IRQn +#define INTERRUPT_TIMER TIM6 + +#define IND_WDG IWDG + +#define PROVISION_CHUNK_ADDRESS 0x1FFF79E0U +#define DEVICE_SERIAL_NUMBER_ADDRESS 0x1FFF79C0U + +#include "can.h" +#include "comms_definitions.h" + +#ifndef BOOTSTUB + #include "main_definitions.h" +#else + #include "bootstub_declarations.h" +#endif + +#include "libc.h" +#include "critical.h" +#include "faults.h" +#include "utils.h" + +#include "drivers/registers.h" +#include "drivers/interrupts.h" +#include "drivers/gpio.h" +#include "stm32f4/peripherals.h" +#include "stm32f4/interrupt_handlers.h" +#include "drivers/timers.h" +#include "stm32f4/board.h" +#include "stm32f4/clock.h" + +#include "drivers/spi.h" +#include "stm32f4/llspi.h" + +#if !defined(BOOTSTUB) + #include "drivers/uart.h" + #include "stm32f4/lluart.h" +#endif + +#ifdef BOOTSTUB + #include "stm32f4/llflash.h" +#else + #include "stm32f4/llbxcan.h" +#endif + +#include "stm32f4/llusb.h" + +void early_gpio_float(void) { + RCC->AHB1ENR = RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN; + + GPIOB->MODER = 0; GPIOC->MODER = 0; + GPIOA->ODR = 0; GPIOB->ODR = 0; GPIOC->ODR = 0; + GPIOA->PUPDR = 0; GPIOB->PUPDR = 0; GPIOC->PUPDR = 0; +} diff --git a/panda_tici/board/stm32f4/stm32f4_flash.ld b/panda_tici/board/stm32f4/stm32f4_flash.ld new file mode 100644 index 0000000..a601c1f --- /dev/null +++ b/panda_tici/board/stm32f4/stm32f4_flash.ld @@ -0,0 +1,166 @@ +/* +***************************************************************************** +** +** File : stm32f4_flash.ld +** +** Abstract : Linker script for STM32F407VG Device with +** 1024KByte FLASH, 192KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Environment : Atollic TrueSTUDIO(R) +** +** Distribution: The file is distributed "as is," without any warranty +** of any kind. +** +** (c)Copyright Atollic AB. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the Atollic TrueSTUDIO(R) toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +enter_bootloader_mode = 0x2001FFFC; +_estack = 0x2001FFFC; /* end of 128K RAM on AHB bus*/ +_app_start = 0x08004000; /* Reserve Sector 0(16K) for bootloader */ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K + RAM2 (xrw) : ORIGIN = 0x20040000, LENGTH = 64K + MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + _exit = .; + } >FLASH + + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array*)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = .; + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >RAM + + /* MEMORY_bank1 section, code must be located here explicitly */ + /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ + .memory_b1_text : + { + *(.mb1text) /* .mb1text sections (code) */ + *(.mb1text*) /* .mb1text* sections (code) */ + *(.mb1rodata) /* read-only data (constants) */ + *(.mb1rodata*) + } >MEMORY_B1 + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/panda_tici/board/stm32h7/board.h b/panda_tici/board/stm32h7/board.h new file mode 100644 index 0000000..0507ca3 --- /dev/null +++ b/panda_tici/board/stm32h7/board.h @@ -0,0 +1,49 @@ +// ///////////////////////////////////////////////////////////// // +// Hardware abstraction layer for all different supported boards // +// ///////////////////////////////////////////////////////////// // +#include "boards/board_declarations.h" +#include "boards/unused_funcs.h" + +// ///// Board definition and detection ///// // +#include "stm32h7/lladc.h" +#include "drivers/harness.h" +#include "drivers/fan.h" +#include "stm32h7/llfan.h" +#include "drivers/fake_siren.h" +#include "stm32h7/sound.h" +#include "drivers/clock_source.h" +#include "boards/red.h" +#include "boards/tres.h" +#include "boards/cuatro.h" + + +void detect_board_type(void) { + // On STM32H7 pandas, we use two different sets of pins. + const uint8_t id1 = detect_with_pull(GPIOF, 7, PULL_UP) | + (detect_with_pull(GPIOF, 8, PULL_UP) << 1U) | + (detect_with_pull(GPIOF, 9, PULL_UP) << 2U) | + (detect_with_pull(GPIOF, 10, PULL_UP) << 3U); + + const uint8_t id2 = detect_with_pull(GPIOD, 4, PULL_UP) | + (detect_with_pull(GPIOD, 5, PULL_UP) << 1U) | + (detect_with_pull(GPIOD, 6, PULL_UP) << 2U) | + (detect_with_pull(GPIOD, 7, PULL_UP) << 3U); + + if (id2 == 3U) { + hw_type = HW_TYPE_CUATRO; + current_board = &board_cuatro; + } else if (id1 == 0U) { + hw_type = HW_TYPE_RED_PANDA; + current_board = &board_red; + } else if (id1 == 1U) { + // deprecated + //hw_type = HW_TYPE_RED_PANDA_V2; + hw_type = HW_TYPE_UNKNOWN; + } else if (id1 == 2U) { + hw_type = HW_TYPE_TRES; + current_board = &board_tres; + } else { + hw_type = HW_TYPE_UNKNOWN; + print("Hardware type is UNKNOWN!\n"); + } +} diff --git a/panda_tici/board/stm32h7/clock.h b/panda_tici/board/stm32h7/clock.h new file mode 100644 index 0000000..40ad060 --- /dev/null +++ b/panda_tici/board/stm32h7/clock.h @@ -0,0 +1,120 @@ +/* +HSE: 25MHz +PLL1Q: 80MHz (for FDCAN) +HSI48 enabled (for USB) +CPU: 240MHz +CPU Systick: 240MHz +AXI: 120MHz +HCLK3: 60MHz +APB3 per: 60MHz +AHB1,2 per: 120MHz +APB1 per: 60MHz +APB1 tim: 120MHz +APB2 per: 60MHz +APB2 tim: 120MHz +AHB4 per: 120MHz +APB4 per: 60MHz +PCLK1: 60MHz (for USART2,3,4,5,7,8) +*/ + +typedef enum { + PACKAGE_UNKNOWN = 0, + PACKAGE_WITH_SMPS = 1, + PACKAGE_WITHOUT_SMPS = 2, +} PackageSMPSType; + +// TODO: find a better way to distinguish between H725 (using SMPS) and H723 (lacking SMPS) +// The package will do for now, since we have only used TFBGA100 for H723 +static PackageSMPSType get_package_smps_type(void) { + PackageSMPSType ret; + RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; // make sure SYSCFG clock is enabled. does seem to read fine without too though + + switch(SYSCFG->PKGR & 0xFU) { + case 0b0001U: // TFBGA100 Legacy + case 0b0011U: // TFBGA100 + ret = PACKAGE_WITHOUT_SMPS; + break; + case 0b0101U: // LQFP144 Legacy + case 0b0111U: // LQFP144 Industrial + case 0b1000U: // UFBGA169 + ret = PACKAGE_WITH_SMPS; + break; + default: + ret = PACKAGE_UNKNOWN; + } + return ret; +} + +void clock_init(void) { + /* + WARNING: PWR->CR3's lower byte can only be written once + * subsequent writes will silently fail + * only cleared with a full power-on-reset, not soft reset or reset pin + * some H7 have a bootrom with a DFU routine that writes (and locks) CR3 + * if the CR3 config doesn't match the HW, the core will deadlock and require immediately going into DFU from a cold boot + + In a normal bootup, the bootstub will be the first to write this. The app section calls clock_init again, but the CR3 write will silently fail. This is fine for most cases, but caution should be taken that the bootstub and app always write the same config. + */ + + // Set power mode to direct SMPS power supply (depends on the board layout) + PackageSMPSType package_smps = get_package_smps_type(); + if (package_smps == PACKAGE_WITHOUT_SMPS) { + register_set(&(PWR->CR3), PWR_CR3_LDOEN, 0xFU); // no SMPS, so powered by LDO + } else if (package_smps == PACKAGE_WITH_SMPS) { + register_set(&(PWR->CR3), PWR_CR3_SMPSEN, 0xFU); // powered only by SMPS + } else { + while(true); // unknown package, let's hang here + } + + // Set VOS level (VOS3 to 170Mhz, VOS2 to 300Mhz, VOS1 to 400Mhz, VOS0 to 550Mhz) + register_set(&(PWR->D3CR), PWR_D3CR_VOS_1 | PWR_D3CR_VOS_0, 0xC000U); //VOS1, needed for 80Mhz CAN FD + while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U); + while ((PWR->CSR1 & PWR_CSR1_ACTVOS) != (PWR->D3CR & PWR_D3CR_VOS)); // check that VOS level was actually set + + // Configure Flash ACR register LATENCY and WRHIGHFREQ (VOS0 range!) + register_set(&(FLASH->ACR), FLASH_ACR_LATENCY_2WS | 0x20U, 0x3FU); // VOS2, AXI 100MHz-150MHz + // enable external oscillator HSE + register_set_bits(&(RCC->CR), RCC_CR_HSEON); + while ((RCC->CR & RCC_CR_HSERDY) == 0U); + // enable internal HSI48 for USB FS kernel + register_set_bits(&(RCC->CR), RCC_CR_HSI48ON); + while ((RCC->CR & RCC_CR_HSI48RDY) == 0U); + // Specify the frequency source for PLL1, divider for DIVM1, DIVM2, DIVM3 : HSE, 5, 5, 5 + register_set(&(RCC->PLLCKSELR), RCC_PLLCKSELR_PLLSRC_HSE | RCC_PLLCKSELR_DIVM1_0 | RCC_PLLCKSELR_DIVM1_2 | RCC_PLLCKSELR_DIVM2_0 | RCC_PLLCKSELR_DIVM2_2 | RCC_PLLCKSELR_DIVM3_0 | RCC_PLLCKSELR_DIVM3_2, 0x3F3F3F3U); + + // *** PLL1 start *** + // Specify multiplier N and dividers P, Q, R for PLL1 : 48, 1, 3, 2 (clock 240Mhz, PLL1Q 80Mhz for CAN FD) + register_set(&(RCC->PLL1DIVR), 0x102002FU, 0x7F7FFFFFU); + // Specify the input and output frequency ranges, enable dividers for PLL1 + register_set(&(RCC->PLLCFGR), RCC_PLLCFGR_PLL1RGE_2 | RCC_PLLCFGR_DIVP1EN | RCC_PLLCFGR_DIVQ1EN | RCC_PLLCFGR_DIVR1EN, 0x7000CU); + // Enable PLL1 + register_set_bits(&(RCC->CR), RCC_CR_PLL1ON); + while((RCC->CR & RCC_CR_PLL1RDY) == 0U); + // *** PLL1 end *** + + //////////////OTHER CLOCKS//////////////////// + // RCC HCLK Clock Source / RCC APB3 Clock Source / RCC SYS Clock Source + register_set(&(RCC->D1CFGR), RCC_D1CFGR_HPRE_DIV2 | RCC_D1CFGR_D1PPRE_DIV2 | RCC_D1CFGR_D1CPRE_DIV1, 0xF7FU); + // RCC APB1 Clock Source / RCC APB2 Clock Source + register_set(&(RCC->D2CFGR), RCC_D2CFGR_D2PPRE1_DIV2 | RCC_D2CFGR_D2PPRE2_DIV2, 0x770U); + // RCC APB4 Clock Source + register_set(&(RCC->D3CFGR), RCC_D3CFGR_D3PPRE_DIV2, 0x70U); + + // Set SysClock source to PLL + register_set(&(RCC->CFGR), RCC_CFGR_SW_PLL1, 0x7U); + while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL1); + //////////////END OTHER CLOCKS//////////////////// + + // Configure clock source for USB (HSI48) + register_set(&(RCC->D2CCIP2R), RCC_D2CCIP2R_USBSEL_1 | RCC_D2CCIP2R_USBSEL_0, RCC_D2CCIP2R_USBSEL); + // Configure clock source for FDCAN (PLL1Q at 80Mhz) + register_set(&(RCC->D2CCIP1R), RCC_D2CCIP1R_FDCANSEL_0, RCC_D2CCIP1R_FDCANSEL); + // Configure clock source for DFSDM1 + register_set_bits(&(RCC->D2CCIP1R), RCC_D2CCIP1R_DFSDM1SEL); + // Configure clock source for ADC1,2,3 (per_ck(currently HSE)) + register_set(&(RCC->D3CCIPR), RCC_D3CCIPR_ADCSEL_1, RCC_D3CCIPR_ADCSEL); + //Enable the Clock Security System + register_set_bits(&(RCC->CR), RCC_CR_CSSHSEON); + //Enable Vdd33usb supply level detector + register_set_bits(&(PWR->CR3), PWR_CR3_USB33DEN); +} diff --git a/panda_tici/board/stm32h7/inc/cmsis_compiler.h b/panda_tici/board/stm32h7/inc/cmsis_compiler.h new file mode 100644 index 0000000..d0f39ee --- /dev/null +++ b/panda_tici/board/stm32h7/inc/cmsis_compiler.h @@ -0,0 +1,284 @@ +/**************************************************************************//** + * @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 + +/* + * 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 + + +/* + * TI Arm Compiler + */ +#elif defined ( __TI_ARM__ ) + #include + + #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 + + #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 */ + + diff --git a/panda_tici/board/stm32h7/inc/cmsis_gcc.h b/panda_tici/board/stm32h7/inc/cmsis_gcc.h new file mode 100644 index 0000000..2f68473 --- /dev/null +++ b/panda_tici/board/stm32h7/inc/cmsis_gcc.h @@ -0,0 +1,2169 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS compiler GCC header file + * @version V5.2.0 + * @date 08. May 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. + */ + +#ifndef __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +/* Fallback for __has_builtin */ +#ifndef __has_builtin + #define __has_builtin(x) (0) +#endif + +/* CMSIS compiler specific defines */ +#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 __attribute__((always_inline)) 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, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma GCC diagnostic pop + #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 + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START + +/** + \brief Initializes data and bss sections + \details This default implementations initialized all data and additional bss + sections relying on .copy.table and .zero.table specified properly + in the used linker script. + + */ +__STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) +{ + extern void _start(void) __NO_RETURN; + + typedef struct { + uint32_t const* src; + uint32_t* dest; + uint32_t wlen; + } __copy_table_t; + + typedef struct { + uint32_t* dest; + uint32_t wlen; + } __zero_table_t; + + extern const __copy_table_t __copy_table_start__; + extern const __copy_table_t __copy_table_end__; + extern const __zero_table_t __zero_table_start__; + extern const __zero_table_t __zero_table_end__; + + for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = pTable->src[i]; + } + } + + for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = 0u; + } + } + + _start(); +} + +#define __PROGRAM_START __cmsis_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP __StackTop +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT __StackLimit +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute((used, section(".vectors"))) +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_get_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + return __builtin_arm_get_fpscr(); +#else + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#endif +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_set_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + __builtin_arm_set_fpscr(fpscr); +#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); +#endif +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP() __ASM volatile ("nop") + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI() __ASM volatile ("wfi") + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE() __ASM volatile ("wfe") + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV() __ASM volatile ("sev") + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__STATIC_FORCEINLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__STATIC_FORCEINLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (int16_t)__builtin_bswap16(value); +#else + int16_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return result; +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__STATIC_FORCEINLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ + __extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#if 0 +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) +#endif + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#pragma GCC diagnostic pop + +#endif /* __CMSIS_GCC_H */ + diff --git a/panda_tici/board/stm32h7/inc/cmsis_version.h b/panda_tici/board/stm32h7/inc/cmsis_version.h new file mode 100644 index 0000000..bf57cf3 --- /dev/null +++ b/panda_tici/board/stm32h7/inc/cmsis_version.h @@ -0,0 +1,40 @@ +/**************************************************************************//** + * @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 + diff --git a/panda_tici/board/stm32h7/inc/core_cm7.h b/panda_tici/board/stm32h7/inc/core_cm7.h new file mode 100644 index 0000000..3da3c43 --- /dev/null +++ b/panda_tici/board/stm32h7/inc/core_cm7.h @@ -0,0 +1,2725 @@ +/**************************************************************************//** + * @file core_cm7.h + * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File + * @version V5.1.1 + * @date 28. March 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 __CORE_CM7_H_GENERIC +#define __CORE_CM7_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M7 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM7 definitions */ +#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ + __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (7U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM7_H_DEPENDANT +#define __CORE_CM7_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM7_REV + #define __CM7_REV 0x0000U + #warning "__CM7_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __ICACHE_PRESENT + #define __ICACHE_PRESENT 0U + #warning "__ICACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DCACHE_PRESENT + #define __DCACHE_PRESENT 0U + #warning "__DCACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DTCM_PRESENT + #define __DTCM_PRESENT 0U + #warning "__DTCM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M7 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED3[93U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ + +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISDYNADD_Pos 26U /*!< ACTLR: DISDYNADD Position */ +#define SCnSCB_ACTLR_DISDYNADD_Msk (1UL << SCnSCB_ACTLR_DISDYNADD_Pos) /*!< ACTLR: DISDYNADD Mask */ + +#define SCnSCB_ACTLR_DISISSCH1_Pos 21U /*!< ACTLR: DISISSCH1 Position */ +#define SCnSCB_ACTLR_DISISSCH1_Msk (0x1FUL << SCnSCB_ACTLR_DISISSCH1_Pos) /*!< ACTLR: DISISSCH1 Mask */ + +#define SCnSCB_ACTLR_DISDI_Pos 16U /*!< ACTLR: DISDI Position */ +#define SCnSCB_ACTLR_DISDI_Msk (0x1FUL << SCnSCB_ACTLR_DISDI_Pos) /*!< ACTLR: DISDI Mask */ + +#define SCnSCB_ACTLR_DISCRITAXIRUR_Pos 15U /*!< ACTLR: DISCRITAXIRUR Position */ +#define SCnSCB_ACTLR_DISCRITAXIRUR_Msk (1UL << SCnSCB_ACTLR_DISCRITAXIRUR_Pos) /*!< ACTLR: DISCRITAXIRUR Mask */ + +#define SCnSCB_ACTLR_DISBTACALLOC_Pos 14U /*!< ACTLR: DISBTACALLOC Position */ +#define SCnSCB_ACTLR_DISBTACALLOC_Msk (1UL << SCnSCB_ACTLR_DISBTACALLOC_Pos) /*!< ACTLR: DISBTACALLOC Mask */ + +#define SCnSCB_ACTLR_DISBTACREAD_Pos 13U /*!< ACTLR: DISBTACREAD Position */ +#define SCnSCB_ACTLR_DISBTACREAD_Msk (1UL << SCnSCB_ACTLR_DISBTACREAD_Pos) /*!< ACTLR: DISBTACREAD Mask */ + +#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ + +#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ +#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ + +#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ +#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED3[981U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = SCB->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## Cache functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/* Cache Size ID Register Macros */ +#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) +#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) + +#define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ +#define __SCB_ICACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_FORCEINLINE void SCB_EnableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */ + + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_FORCEINLINE void SCB_DisableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_FORCEINLINE void SCB_InvalidateICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; + __DSB(); + __ISB(); + #endif +} + + +/** + \brief I-Cache Invalidate by address + \details Invalidates I-Cache for the given address. + I-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. + I-Cache memory blocks which are part of given address + given size are invalidated. + \param[in] addr address + \param[in] isize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (void *addr, int32_t isize) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + if ( isize > 0 ) { + int32_t op_size = isize + (((uint32_t)addr) & (__SCB_ICACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_ICACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->ICIMVAU = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_ICACHE_LINE_SIZE; + op_size -= __SCB_ICACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_FORCEINLINE void SCB_EnableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */ + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + __DSB(); + + SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_FORCEINLINE void SCB_DisableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_FORCEINLINE void SCB_InvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_FORCEINLINE void SCB_CleanDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | + ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address. + D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are invalidated. + \param[in] addr address + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned. + \param[in] addr address + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned and invalidated. + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + +/*@} end of CMSIS_Core_CacheFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/panda_tici/board/stm32h7/inc/mpu_armv7.h b/panda_tici/board/stm32h7/inc/mpu_armv7.h new file mode 100644 index 0000000..e72cc46 --- /dev/null +++ b/panda_tici/board/stm32h7/inc/mpu_armv7.h @@ -0,0 +1,273 @@ +/****************************************************************************** + * @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 + diff --git a/panda_tici/board/stm32h7/inc/stm32h725xx.h b/panda_tici/board/stm32h7/inc/stm32h725xx.h new file mode 100644 index 0000000..0e0d4a9 --- /dev/null +++ b/panda_tici/board/stm32h7/inc/stm32h725xx.h @@ -0,0 +1,24740 @@ +/** + ****************************************************************************** + * @file stm32h735xx.h + * @author MCD Application Team + * @brief CMSIS STM32H735xx Device Peripheral Access Layer Header File. + * + * This file contains: + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral's registers hardware + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS_Device + * @{ + */ + +/** @addtogroup stm32h735xx + * @{ + */ + +#ifndef STM32H735xx_H +#define STM32H735xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32H7XX Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum +{ +/****** Cortex-M Processor Exceptions Numbers *****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 4 Cortex-M Memory Management Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt ( wwdg1_it, wwdg2_it) */ + PVD_AVD_IRQn = 1, /*!< PVD/AVD through EXTI Line detection Interrupt */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */ + DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */ + DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */ + DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */ + DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */ + DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */ + DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ + ADC_IRQn = 18, /*!< ADC1 and ADC2 global Interrupts */ + FDCAN1_IT0_IRQn = 19, /*!< FDCAN1 Interrupt line 0 */ + FDCAN2_IT0_IRQn = 20, /*!< FDCAN2 Interrupt line 0 */ + FDCAN1_IT1_IRQn = 21, /*!< FDCAN1 Interrupt line 1 */ + FDCAN2_IT1_IRQn = 22, /*!< FDCAN2 Interrupt line 1 */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */ + TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ + TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */ + TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */ + TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */ + FMC_IRQn = 48, /*!< FMC global Interrupt */ + SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */ + DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */ + DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */ + DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */ + DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ + ETH_IRQn = 61, /*!< Ethernet global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ + FDCAN_CAL_IRQn = 63, /*!< FDCAN Calibration unit Interrupt */ + DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */ + DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */ + DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */ + USART6_IRQn = 71, /*!< USART6 global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */ + OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */ + OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */ + OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */ + DCMI_PSSI_IRQn = 78, /*!< DCMI and PSSI global interrupt */ + CRYP_IRQn = 79, /*!< CRYP crypto global interrupt */ + HASH_RNG_IRQn = 80, /*!< HASH and RNG global interrupt */ + FPU_IRQn = 81, /*!< FPU global interrupt */ + UART7_IRQn = 82, /*!< UART7 global interrupt */ + UART8_IRQn = 83, /*!< UART8 global interrupt */ + SPI4_IRQn = 84, /*!< SPI4 global Interrupt */ + SPI5_IRQn = 85, /*!< SPI5 global Interrupt */ + SPI6_IRQn = 86, /*!< SPI6 global Interrupt */ + SAI1_IRQn = 87, /*!< SAI1 global Interrupt */ + LTDC_IRQn = 88, /*!< LTDC global Interrupt */ + LTDC_ER_IRQn = 89, /*!< LTDC Error global Interrupt */ + DMA2D_IRQn = 90, /*!< DMA2D global Interrupt */ + OCTOSPI1_IRQn = 92, /*!< OCTOSPI1 global interrupt */ + LPTIM1_IRQn = 93, /*!< LP TIM1 interrupt */ + CEC_IRQn = 94, /*!< HDMI-CEC global Interrupt */ + I2C4_EV_IRQn = 95, /*!< I2C4 Event Interrupt */ + I2C4_ER_IRQn = 96, /*!< I2C4 Error Interrupt */ + SPDIF_RX_IRQn = 97, /*!< SPDIF-RX global Interrupt */ + DMAMUX1_OVR_IRQn = 102, /*! + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC Interrupt and Status Register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< ADC Interrupt Enable Register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< ADC Configuration register, Address offset: 0x0C */ + __IO uint32_t CFGR2; /*!< ADC Configuration register 2, Address offset: 0x10 */ + __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x14 */ + __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x18 */ + __IO uint32_t PCSEL_RES0; /*!< Rserved for ADC3, ADC1/2 pre-channel selection, Address offset: 0x1C */ + __IO uint32_t LTR1_TR1; /*!< ADC watchdog Lower threshold register 1, Address offset: 0x20 */ + __IO uint32_t HTR1_TR2; /*!< ADC watchdog higher threshold register 1, Address offset: 0x24 */ + __IO uint32_t RES1_TR3; /*!< Rserved for ADC1/2, ADC3 threshold register, Address offset: 0x28 */ + uint32_t RESERVED2; /*!< Reserved, 0x02C */ + __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x30 */ + __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x34 */ + __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x38 */ + __IO uint32_t SQR4; /*!< ADC regular sequence register 4, Address offset: 0x3C */ + __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x40 */ + uint32_t RESERVED3; /*!< Reserved, 0x044 */ + uint32_t RESERVED4; /*!< Reserved, 0x048 */ + __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x4C */ + uint32_t RESERVED5[4]; /*!< Reserved, 0x050 - 0x05C */ + __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */ + __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */ + __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */ + __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */ + uint32_t RESERVED6[4]; /*!< Reserved, 0x070 - 0x07C */ + __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x80 */ + __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x84 */ + __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x88 */ + __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x8C */ + uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */ + __IO uint32_t AWD2CR; /*!< ADC Analog Watchdog 2 Configuration Register, Address offset: 0xA0 */ + __IO uint32_t AWD3CR; /*!< ADC Analog Watchdog 3 Configuration Register, Address offset: 0xA4 */ + uint32_t RESERVED8; /*!< Reserved, 0x0A8 */ + uint32_t RESERVED9; /*!< Reserved, 0x0AC */ + __IO uint32_t LTR2_DIFSEL; /*!< ADC watchdog Lower threshold register 2, Difsel for ADC3, Address offset: 0xB0 */ + __IO uint32_t HTR2_CALFACT; /*!< ADC watchdog Higher threshold register 2, Calfact for ADC3, Address offset: 0xB4 */ + __IO uint32_t LTR3_RES10; /*!< ADC watchdog Lower threshold register 3, specific ADC1/2, Address offset: 0xB8 */ + __IO uint32_t HTR3_RES11; /*!< ADC watchdog Higher threshold register 3, specific ADC1/2, Address offset: 0xBC */ + __IO uint32_t DIFSEL_RES12; /*!< ADC Differential Mode Selection Register specific ADC1/2, Address offset: 0xC0 */ + __IO uint32_t CALFACT_RES13; /*!< ADC Calibration Factors specific ADC1/2, Address offset: 0xC4 */ + __IO uint32_t CALFACT2_RES14; /*!< ADC Linearity Calibration Factors specific ADC1/2, Address offset: 0xC8 */ +} ADC_TypeDef; + + +typedef struct +{ +__IO uint32_t CSR; /*!< ADC Common status register, Address offset: ADC1/3 base address + 0x300 */ +uint32_t RESERVED; /*!< Reserved, ADC1/3 base address + 0x304 */ +__IO uint32_t CCR; /*!< ADC common control register, Address offset: ADC1/3 base address + 0x308 */ +__IO uint32_t CDR; /*!< ADC common regular data register for dual Address offset: ADC1/3 base address + 0x30C */ +__IO uint32_t CDR2; /*!< ADC common regular data register for 32-bit dual mode Address offset: ADC1/3 base address + 0x310 */ + +} ADC_Common_TypeDef; + + +/** + * @brief VREFBUF + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */ + __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */ +} VREFBUF_TypeDef; + + +/** + * @brief FD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t CREL; /*!< FDCAN Core Release register, Address offset: 0x000 */ + __IO uint32_t ENDN; /*!< FDCAN Endian register, Address offset: 0x004 */ + __IO uint32_t RESERVED1; /*!< Reserved, 0x008 */ + __IO uint32_t DBTP; /*!< FDCAN Data Bit Timing & Prescaler register, Address offset: 0x00C */ + __IO uint32_t TEST; /*!< FDCAN Test register, Address offset: 0x010 */ + __IO uint32_t RWD; /*!< FDCAN RAM Watchdog register, Address offset: 0x014 */ + __IO uint32_t CCCR; /*!< FDCAN CC Control register, Address offset: 0x018 */ + __IO uint32_t NBTP; /*!< FDCAN Nominal Bit Timing & Prescaler register, Address offset: 0x01C */ + __IO uint32_t TSCC; /*!< FDCAN Timestamp Counter Configuration register, Address offset: 0x020 */ + __IO uint32_t TSCV; /*!< FDCAN Timestamp Counter Value register, Address offset: 0x024 */ + __IO uint32_t TOCC; /*!< FDCAN Timeout Counter Configuration register, Address offset: 0x028 */ + __IO uint32_t TOCV; /*!< FDCAN Timeout Counter Value register, Address offset: 0x02C */ + __IO uint32_t RESERVED2[4]; /*!< Reserved, 0x030 - 0x03C */ + __IO uint32_t ECR; /*!< FDCAN Error Counter register, Address offset: 0x040 */ + __IO uint32_t PSR; /*!< FDCAN Protocol Status register, Address offset: 0x044 */ + __IO uint32_t TDCR; /*!< FDCAN Transmitter Delay Compensation register, Address offset: 0x048 */ + __IO uint32_t RESERVED3; /*!< Reserved, 0x04C */ + __IO uint32_t IR; /*!< FDCAN Interrupt register, Address offset: 0x050 */ + __IO uint32_t IE; /*!< FDCAN Interrupt Enable register, Address offset: 0x054 */ + __IO uint32_t ILS; /*!< FDCAN Interrupt Line Select register, Address offset: 0x058 */ + __IO uint32_t ILE; /*!< FDCAN Interrupt Line Enable register, Address offset: 0x05C */ + __IO uint32_t RESERVED4[8]; /*!< Reserved, 0x060 - 0x07C */ + __IO uint32_t GFC; /*!< FDCAN Global Filter Configuration register, Address offset: 0x080 */ + __IO uint32_t SIDFC; /*!< FDCAN Standard ID Filter Configuration register, Address offset: 0x084 */ + __IO uint32_t XIDFC; /*!< FDCAN Extended ID Filter Configuration register, Address offset: 0x088 */ + __IO uint32_t RESERVED5; /*!< Reserved, 0x08C */ + __IO uint32_t XIDAM; /*!< FDCAN Extended ID AND Mask register, Address offset: 0x090 */ + __IO uint32_t HPMS; /*!< FDCAN High Priority Message Status register, Address offset: 0x094 */ + __IO uint32_t NDAT1; /*!< FDCAN New Data 1 register, Address offset: 0x098 */ + __IO uint32_t NDAT2; /*!< FDCAN New Data 2 register, Address offset: 0x09C */ + __IO uint32_t RXF0C; /*!< FDCAN Rx FIFO 0 Configuration register, Address offset: 0x0A0 */ + __IO uint32_t RXF0S; /*!< FDCAN Rx FIFO 0 Status register, Address offset: 0x0A4 */ + __IO uint32_t RXF0A; /*!< FDCAN Rx FIFO 0 Acknowledge register, Address offset: 0x0A8 */ + __IO uint32_t RXBC; /*!< FDCAN Rx Buffer Configuration register, Address offset: 0x0AC */ + __IO uint32_t RXF1C; /*!< FDCAN Rx FIFO 1 Configuration register, Address offset: 0x0B0 */ + __IO uint32_t RXF1S; /*!< FDCAN Rx FIFO 1 Status register, Address offset: 0x0B4 */ + __IO uint32_t RXF1A; /*!< FDCAN Rx FIFO 1 Acknowledge register, Address offset: 0x0B8 */ + __IO uint32_t RXESC; /*!< FDCAN Rx Buffer/FIFO Element Size Configuration register, Address offset: 0x0BC */ + __IO uint32_t TXBC; /*!< FDCAN Tx Buffer Configuration register, Address offset: 0x0C0 */ + __IO uint32_t TXFQS; /*!< FDCAN Tx FIFO/Queue Status register, Address offset: 0x0C4 */ + __IO uint32_t TXESC; /*!< FDCAN Tx Buffer Element Size Configuration register, Address offset: 0x0C8 */ + __IO uint32_t TXBRP; /*!< FDCAN Tx Buffer Request Pending register, Address offset: 0x0CC */ + __IO uint32_t TXBAR; /*!< FDCAN Tx Buffer Add Request register, Address offset: 0x0D0 */ + __IO uint32_t TXBCR; /*!< FDCAN Tx Buffer Cancellation Request register, Address offset: 0x0D4 */ + __IO uint32_t TXBTO; /*!< FDCAN Tx Buffer Transmission Occurred register, Address offset: 0x0D8 */ + __IO uint32_t TXBCF; /*!< FDCAN Tx Buffer Cancellation Finished register, Address offset: 0x0DC */ + __IO uint32_t TXBTIE; /*!< FDCAN Tx Buffer Transmission Interrupt Enable register, Address offset: 0x0E0 */ + __IO uint32_t TXBCIE; /*!< FDCAN Tx Buffer Cancellation Finished Interrupt Enable register, Address offset: 0x0E4 */ + __IO uint32_t RESERVED6[2]; /*!< Reserved, 0x0E8 - 0x0EC */ + __IO uint32_t TXEFC; /*!< FDCAN Tx Event FIFO Configuration register, Address offset: 0x0F0 */ + __IO uint32_t TXEFS; /*!< FDCAN Tx Event FIFO Status register, Address offset: 0x0F4 */ + __IO uint32_t TXEFA; /*!< FDCAN Tx Event FIFO Acknowledge register, Address offset: 0x0F8 */ + __IO uint32_t RESERVED7; /*!< Reserved, 0x0FC */ +} FDCAN_GlobalTypeDef; + +/** + * @brief TTFD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t TTTMC; /*!< TT Trigger Memory Configuration register, Address offset: 0x100 */ + __IO uint32_t TTRMC; /*!< TT Reference Message Configuration register, Address offset: 0x104 */ + __IO uint32_t TTOCF; /*!< TT Operation Configuration register, Address offset: 0x108 */ + __IO uint32_t TTMLM; /*!< TT Matrix Limits register, Address offset: 0x10C */ + __IO uint32_t TURCF; /*!< TUR Configuration register, Address offset: 0x110 */ + __IO uint32_t TTOCN; /*!< TT Operation Control register, Address offset: 0x114 */ + __IO uint32_t TTGTP; /*!< TT Global Time Preset register, Address offset: 0x118 */ + __IO uint32_t TTTMK; /*!< TT Time Mark register, Address offset: 0x11C */ + __IO uint32_t TTIR; /*!< TT Interrupt register, Address offset: 0x120 */ + __IO uint32_t TTIE; /*!< TT Interrupt Enable register, Address offset: 0x124 */ + __IO uint32_t TTILS; /*!< TT Interrupt Line Select register, Address offset: 0x128 */ + __IO uint32_t TTOST; /*!< TT Operation Status register, Address offset: 0x12C */ + __IO uint32_t TURNA; /*!< TT TUR Numerator Actual register, Address offset: 0x130 */ + __IO uint32_t TTLGT; /*!< TT Local and Global Time register, Address offset: 0x134 */ + __IO uint32_t TTCTC; /*!< TT Cycle Time and Count register, Address offset: 0x138 */ + __IO uint32_t TTCPT; /*!< TT Capture Time register, Address offset: 0x13C */ + __IO uint32_t TTCSM; /*!< TT Cycle Sync Mark register, Address offset: 0x140 */ + __IO uint32_t RESERVED1[111]; /*!< Reserved, 0x144 - 0x2FC */ + __IO uint32_t TTTS; /*!< TT Trigger Select register, Address offset: 0x300 */ +} TTCAN_TypeDef; + +/** + * @brief FD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t CREL; /*!< Clock Calibration Unit Core Release register, Address offset: 0x00 */ + __IO uint32_t CCFG; /*!< Calibration Configuration register, Address offset: 0x04 */ + __IO uint32_t CSTAT; /*!< Calibration Status register, Address offset: 0x08 */ + __IO uint32_t CWD; /*!< Calibration Watchdog register, Address offset: 0x0C */ + __IO uint32_t IR; /*!< CCU Interrupt register, Address offset: 0x10 */ + __IO uint32_t IE; /*!< CCU Interrupt Enable register, Address offset: 0x14 */ +} FDCAN_ClockCalibrationUnit_TypeDef; + + +/** + * @brief Consumer Electronics Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CEC control register, Address offset:0x00 */ + __IO uint32_t CFGR; /*!< CEC configuration register, Address offset:0x04 */ + __IO uint32_t TXDR; /*!< CEC Tx data register , Address offset:0x08 */ + __IO uint32_t RXDR; /*!< CEC Rx Data Register, Address offset:0x0C */ + __IO uint32_t ISR; /*!< CEC Interrupt and Status Register, Address offset:0x10 */ + __IO uint32_t IER; /*!< CEC interrupt enable register, Address offset:0x14 */ +}CEC_TypeDef; + +/** + * @brief COordincate Rotation DIgital Computer + */ +typedef struct +{ + __IO uint32_t CSR; /*!< CORDIC control and status register, Address offset: 0x00 */ + __IO uint32_t WDATA; /*!< CORDIC argument register, Address offset: 0x04 */ + __IO uint32_t RDATA; /*!< CORDIC result register, Address offset: 0x08 */ +} CORDIC_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint32_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ +} CRC_TypeDef; + + +/** + * @brief Clock Recovery System + */ +typedef struct +{ +__IO uint32_t CR; /*!< CRS ccontrol register, Address offset: 0x00 */ +__IO uint32_t CFGR; /*!< CRS configuration register, Address offset: 0x04 */ +__IO uint32_t ISR; /*!< CRS interrupt and status register, Address offset: 0x08 */ +__IO uint32_t ICR; /*!< CRS interrupt flag clear register, Address offset: 0x0C */ +} CRS_TypeDef; + + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ + __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */ + __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */ + __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */ + __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */ + __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */ + __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */ +} DAC_TypeDef; + +/** + * @brief DFSDM module registers + */ +typedef struct +{ + __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */ + __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */ + __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */ + __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */ + __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */ + __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */ + __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */ + __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */ + __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */ + __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */ + __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */ + __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */ + __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */ + __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */ + __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */ +} DFSDM_Filter_TypeDef; + +/** + * @brief DFSDM channel configuration registers + */ +typedef struct +{ + __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */ + __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */ + __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and + short circuit detector register, Address offset: 0x08 */ + __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */ + __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */ +} DFSDM_Channel_TypeDef; + +/** + * @brief Debug MCU + */ +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + uint32_t RESERVED4[11]; /*!< Reserved, Address offset: 0x08 */ + __IO uint32_t APB3FZ1; /*!< Debug MCU APB3FZ1 freeze register, Address offset: 0x34 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x38 */ + __IO uint32_t APB1LFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x3C */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x40 */ + __IO uint32_t APB1HFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x44 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x48 */ + __IO uint32_t APB2FZ1; /*!< Debug MCU APB2FZ1 freeze register, Address offset: 0x4C */ + uint32_t RESERVED8; /*!< Reserved, Address offset: 0x50 */ + __IO uint32_t APB4FZ1; /*!< Debug MCU APB4FZ1 freeze register, Address offset: 0x54 */ + __IO uint32_t RESERVED9[990]; /*!< Reserved, Address offset: 0x58-0xFCC */ + __IO uint32_t PIDR4; /*!< Debug MCU peripheral identity register 4, Address offset: 0xFD0 */ + __IO uint32_t RESERVED10[3];/*!< Reserved, Address offset: 0xFD4-0xFDC */ + __IO uint32_t PIDR0; /*!< Debug MCU peripheral identity register 0, Address offset: 0xFE0 */ + __IO uint32_t PIDR1; /*!< Debug MCU peripheral identity register 1, Address offset: 0xFE4 */ + __IO uint32_t PIDR2; /*!< Debug MCU peripheral identity register 2, Address offset: 0xFE8 */ + __IO uint32_t PIDR3; /*!< Debug MCU peripheral identity register 3, Address offset: 0xFEC */ + __IO uint32_t CIDR0; /*!< Debug MCU component identity register 0, Address offset: 0xFF0 */ + __IO uint32_t CIDR1; /*!< Debug MCU component identity register 1, Address offset: 0xFF4 */ + __IO uint32_t CIDR2; /*!< Debug MCU component identity register 2, Address offset: 0xFF8 */ + __IO uint32_t CIDR3; /*!< Debug MCU component identity register 3, Address offset: 0xFFC */ +}DBGMCU_TypeDef; +/** + * @brief DCMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */ + __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */ + __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */ + __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */ + __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */ + __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */ + __IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */ + __IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */ + __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */ + __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */ + __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */ +} DCMI_TypeDef; + +/** + * @brief PSSI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< PSSI control register 1, Address offset: 0x000 */ + __IO uint32_t SR; /*!< PSSI status register, Address offset: 0x004 */ + __IO uint32_t RIS; /*!< PSSI raw interrupt status register, Address offset: 0x008 */ + __IO uint32_t IER; /*!< PSSI interrupt enable register, Address offset: 0x00C */ + __IO uint32_t MIS; /*!< PSSI masked interrupt status register, Address offset: 0x010 */ + __IO uint32_t ICR; /*!< PSSI interrupt clear register, Address offset: 0x014 */ + __IO uint32_t RESERVED1[4]; /*!< Reserved, 0x018 - 0x024 */ + __IO uint32_t DR; /*!< PSSI data register, Address offset: 0x028 */ + __IO uint32_t RESERVED2[241]; /*!< Reserved, 0x02C - 0x3EC */ + __IO uint32_t HWCFGR; /*!< PSSI IP HW configuration register, Address offset: 0x3F0 */ + __IO uint32_t VERR; /*!< PSSI IP version register, Address offset: 0x3F4 */ + __IO uint32_t IPIDR; /*!< PSSI IP ID register, Address offset: 0x3F8 */ + __IO uint32_t SIDR; /*!< PSSI SIZE ID register, Address offset: 0x3FC */ +} PSSI_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA stream x configuration register */ + __IO uint32_t NDTR; /*!< DMA stream x number of data register */ + __IO uint32_t PAR; /*!< DMA stream x peripheral address register */ + __IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */ + __IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */ + __IO uint32_t FCR; /*!< DMA stream x FIFO control register */ +} DMA_Stream_TypeDef; + +typedef struct +{ + __IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */ + __IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */ + __IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */ + __IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */ +} DMA_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CM0AR; /*!< DMA channel x memory 0 address register */ + __IO uint32_t CM1AR; /*!< DMA channel x memory 1 address register */ +} BDMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} BDMA_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA Multiplexer Channel x Control Register */ +}DMAMUX_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< DMA Channel Status Register */ + __IO uint32_t CFR; /*!< DMA Channel Clear Flag Register */ +}DMAMUX_ChannelStatus_TypeDef; + +typedef struct +{ + __IO uint32_t RGCR; /*!< DMA Request Generator x Control Register */ +}DMAMUX_RequestGen_TypeDef; + +typedef struct +{ + __IO uint32_t RGSR; /*!< DMA Request Generator Status Register */ + __IO uint32_t RGCFR; /*!< DMA Request Generator Clear Flag Register */ +}DMAMUX_RequestGenStatus_TypeDef; + +/** + * @brief MDMA Controller + */ +typedef struct +{ + __IO uint32_t GISR0; /*!< MDMA Global Interrupt/Status Register 0, Address offset: 0x00 */ +}MDMA_TypeDef; + +typedef struct +{ + __IO uint32_t CISR; /*!< MDMA channel x interrupt/status register, Address offset: 0x40 */ + __IO uint32_t CIFCR; /*!< MDMA channel x interrupt flag clear register, Address offset: 0x44 */ + __IO uint32_t CESR; /*!< MDMA Channel x error status register, Address offset: 0x48 */ + __IO uint32_t CCR; /*!< MDMA channel x control register, Address offset: 0x4C */ + __IO uint32_t CTCR; /*!< MDMA channel x Transfer Configuration register, Address offset: 0x50 */ + __IO uint32_t CBNDTR; /*!< MDMA Channel x block number of data register, Address offset: 0x54 */ + __IO uint32_t CSAR; /*!< MDMA channel x source address register, Address offset: 0x58 */ + __IO uint32_t CDAR; /*!< MDMA channel x destination address register, Address offset: 0x5C */ + __IO uint32_t CBRUR; /*!< MDMA channel x Block Repeat address Update register, Address offset: 0x60 */ + __IO uint32_t CLAR; /*!< MDMA channel x Link Address register, Address offset: 0x64 */ + __IO uint32_t CTBR; /*!< MDMA channel x Trigger and Bus selection Register, Address offset: 0x68 */ + uint32_t RESERVED0; /*!< Reserved, 0x6C */ + __IO uint32_t CMAR; /*!< MDMA channel x Mask address register, Address offset: 0x70 */ + __IO uint32_t CMDR; /*!< MDMA channel x Mask Data register, Address offset: 0x74 */ +}MDMA_Channel_TypeDef; + +/** + * @brief DMA2D Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA2D Control Register, Address offset: 0x00 */ + __IO uint32_t ISR; /*!< DMA2D Interrupt Status Register, Address offset: 0x04 */ + __IO uint32_t IFCR; /*!< DMA2D Interrupt Flag Clear Register, Address offset: 0x08 */ + __IO uint32_t FGMAR; /*!< DMA2D Foreground Memory Address Register, Address offset: 0x0C */ + __IO uint32_t FGOR; /*!< DMA2D Foreground Offset Register, Address offset: 0x10 */ + __IO uint32_t BGMAR; /*!< DMA2D Background Memory Address Register, Address offset: 0x14 */ + __IO uint32_t BGOR; /*!< DMA2D Background Offset Register, Address offset: 0x18 */ + __IO uint32_t FGPFCCR; /*!< DMA2D Foreground PFC Control Register, Address offset: 0x1C */ + __IO uint32_t FGCOLR; /*!< DMA2D Foreground Color Register, Address offset: 0x20 */ + __IO uint32_t BGPFCCR; /*!< DMA2D Background PFC Control Register, Address offset: 0x24 */ + __IO uint32_t BGCOLR; /*!< DMA2D Background Color Register, Address offset: 0x28 */ + __IO uint32_t FGCMAR; /*!< DMA2D Foreground CLUT Memory Address Register, Address offset: 0x2C */ + __IO uint32_t BGCMAR; /*!< DMA2D Background CLUT Memory Address Register, Address offset: 0x30 */ + __IO uint32_t OPFCCR; /*!< DMA2D Output PFC Control Register, Address offset: 0x34 */ + __IO uint32_t OCOLR; /*!< DMA2D Output Color Register, Address offset: 0x38 */ + __IO uint32_t OMAR; /*!< DMA2D Output Memory Address Register, Address offset: 0x3C */ + __IO uint32_t OOR; /*!< DMA2D Output Offset Register, Address offset: 0x40 */ + __IO uint32_t NLR; /*!< DMA2D Number of Line Register, Address offset: 0x44 */ + __IO uint32_t LWR; /*!< DMA2D Line Watermark Register, Address offset: 0x48 */ + __IO uint32_t AMTCR; /*!< DMA2D AHB Master Timer Configuration Register, Address offset: 0x4C */ + uint32_t RESERVED[236]; /*!< Reserved, 0x50-0x3FF */ + __IO uint32_t FGCLUT[256]; /*!< DMA2D Foreground CLUT, Address offset:400-7FF */ + __IO uint32_t BGCLUT[256]; /*!< DMA2D Background CLUT, Address offset:800-BFF */ +} DMA2D_TypeDef; + + +/** + * @brief Ethernet MAC + */ +typedef struct +{ + __IO uint32_t MACCR; + __IO uint32_t MACECR; + __IO uint32_t MACPFR; + __IO uint32_t MACWTR; + __IO uint32_t MACHT0R; + __IO uint32_t MACHT1R; + uint32_t RESERVED1[14]; + __IO uint32_t MACVTR; + uint32_t RESERVED2; + __IO uint32_t MACVHTR; + uint32_t RESERVED3; + __IO uint32_t MACVIR; + __IO uint32_t MACIVIR; + uint32_t RESERVED4[2]; + __IO uint32_t MACTFCR; + uint32_t RESERVED5[7]; + __IO uint32_t MACRFCR; + uint32_t RESERVED6[7]; + __IO uint32_t MACISR; + __IO uint32_t MACIER; + __IO uint32_t MACRXTXSR; + uint32_t RESERVED7; + __IO uint32_t MACPCSR; + __IO uint32_t MACRWKPFR; + uint32_t RESERVED8[2]; + __IO uint32_t MACLCSR; + __IO uint32_t MACLTCR; + __IO uint32_t MACLETR; + __IO uint32_t MAC1USTCR; + uint32_t RESERVED9[12]; + __IO uint32_t MACVR; + __IO uint32_t MACDR; + uint32_t RESERVED10; + __IO uint32_t MACHWF0R; + __IO uint32_t MACHWF1R; + __IO uint32_t MACHWF2R; + uint32_t RESERVED11[54]; + __IO uint32_t MACMDIOAR; + __IO uint32_t MACMDIODR; + uint32_t RESERVED12[2]; + __IO uint32_t MACARPAR; + uint32_t RESERVED13[59]; + __IO uint32_t MACA0HR; + __IO uint32_t MACA0LR; + __IO uint32_t MACA1HR; + __IO uint32_t MACA1LR; + __IO uint32_t MACA2HR; + __IO uint32_t MACA2LR; + __IO uint32_t MACA3HR; + __IO uint32_t MACA3LR; + uint32_t RESERVED14[248]; + __IO uint32_t MMCCR; + __IO uint32_t MMCRIR; + __IO uint32_t MMCTIR; + __IO uint32_t MMCRIMR; + __IO uint32_t MMCTIMR; + uint32_t RESERVED15[14]; + __IO uint32_t MMCTSCGPR; + __IO uint32_t MMCTMCGPR; + uint32_t RESERVED16[5]; + __IO uint32_t MMCTPCGR; + uint32_t RESERVED17[10]; + __IO uint32_t MMCRCRCEPR; + __IO uint32_t MMCRAEPR; + uint32_t RESERVED18[10]; + __IO uint32_t MMCRUPGR; + uint32_t RESERVED19[9]; + __IO uint32_t MMCTLPIMSTR; + __IO uint32_t MMCTLPITCR; + __IO uint32_t MMCRLPIMSTR; + __IO uint32_t MMCRLPITCR; + uint32_t RESERVED20[65]; + __IO uint32_t MACL3L4C0R; + __IO uint32_t MACL4A0R; + uint32_t RESERVED21[2]; + __IO uint32_t MACL3A0R0R; + __IO uint32_t MACL3A1R0R; + __IO uint32_t MACL3A2R0R; + __IO uint32_t MACL3A3R0R; + uint32_t RESERVED22[4]; + __IO uint32_t MACL3L4C1R; + __IO uint32_t MACL4A1R; + uint32_t RESERVED23[2]; + __IO uint32_t MACL3A0R1R; + __IO uint32_t MACL3A1R1R; + __IO uint32_t MACL3A2R1R; + __IO uint32_t MACL3A3R1R; + uint32_t RESERVED24[108]; + __IO uint32_t MACTSCR; + __IO uint32_t MACSSIR; + __IO uint32_t MACSTSR; + __IO uint32_t MACSTNR; + __IO uint32_t MACSTSUR; + __IO uint32_t MACSTNUR; + __IO uint32_t MACTSAR; + uint32_t RESERVED25; + __IO uint32_t MACTSSR; + uint32_t RESERVED26[3]; + __IO uint32_t MACTTSSNR; + __IO uint32_t MACTTSSSR; + uint32_t RESERVED27[2]; + __IO uint32_t MACACR; + uint32_t RESERVED28; + __IO uint32_t MACATSNR; + __IO uint32_t MACATSSR; + __IO uint32_t MACTSIACR; + __IO uint32_t MACTSEACR; + __IO uint32_t MACTSICNR; + __IO uint32_t MACTSECNR; + uint32_t RESERVED29[4]; + __IO uint32_t MACPPSCR; + uint32_t RESERVED30[3]; + __IO uint32_t MACPPSTTSR; + __IO uint32_t MACPPSTTNR; + __IO uint32_t MACPPSIR; + __IO uint32_t MACPPSWR; + uint32_t RESERVED31[12]; + __IO uint32_t MACPOCR; + __IO uint32_t MACSPI0R; + __IO uint32_t MACSPI1R; + __IO uint32_t MACSPI2R; + __IO uint32_t MACLMIR; + uint32_t RESERVED32[11]; + __IO uint32_t MTLOMR; + uint32_t RESERVED33[7]; + __IO uint32_t MTLISR; + uint32_t RESERVED34[55]; + __IO uint32_t MTLTQOMR; + __IO uint32_t MTLTQUR; + __IO uint32_t MTLTQDR; + uint32_t RESERVED35[8]; + __IO uint32_t MTLQICSR; + __IO uint32_t MTLRQOMR; + __IO uint32_t MTLRQMPOCR; + __IO uint32_t MTLRQDR; + uint32_t RESERVED36[177]; + __IO uint32_t DMAMR; + __IO uint32_t DMASBMR; + __IO uint32_t DMAISR; + __IO uint32_t DMADSR; + uint32_t RESERVED37[60]; + __IO uint32_t DMACCR; + __IO uint32_t DMACTCR; + __IO uint32_t DMACRCR; + uint32_t RESERVED38[2]; + __IO uint32_t DMACTDLAR; + uint32_t RESERVED39; + __IO uint32_t DMACRDLAR; + __IO uint32_t DMACTDTPR; + uint32_t RESERVED40; + __IO uint32_t DMACRDTPR; + __IO uint32_t DMACTDRLR; + __IO uint32_t DMACRDRLR; + __IO uint32_t DMACIER; + __IO uint32_t DMACRIWTR; +__IO uint32_t DMACSFCSR; + uint32_t RESERVED41; + __IO uint32_t DMACCATDR; + uint32_t RESERVED42; + __IO uint32_t DMACCARDR; + uint32_t RESERVED43; + __IO uint32_t DMACCATBR; + uint32_t RESERVED44; + __IO uint32_t DMACCARBR; + __IO uint32_t DMACSR; +uint32_t RESERVED45[2]; +__IO uint32_t DMACMFCR; +}ETH_TypeDef; +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ +__IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register, Address offset: 0x00 */ +__IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register, Address offset: 0x04 */ +__IO uint32_t SWIER1; /*!< EXTI Software interrupt event register, Address offset: 0x08 */ +__IO uint32_t D3PMR1; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR1) Address offset: 0x0C */ +__IO uint32_t D3PCR1L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR1L) Address offset: 0x10 */ +__IO uint32_t D3PCR1H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR1H) Address offset: 0x14 */ +uint32_t RESERVED1[2]; /*!< Reserved, 0x18 to 0x1C */ +__IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register, Address offset: 0x20 */ +__IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register, Address offset: 0x24 */ +__IO uint32_t SWIER2; /*!< EXTI Software interrupt event register, Address offset: 0x28 */ +__IO uint32_t D3PMR2; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR2) Address offset: 0x2C */ +__IO uint32_t D3PCR2L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR2L) Address offset: 0x30 */ +__IO uint32_t D3PCR2H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR2H) Address offset: 0x34 */ +uint32_t RESERVED2[2]; /*!< Reserved, 0x38 to 0x3C */ +__IO uint32_t RTSR3; /*!< EXTI Rising trigger selection register, Address offset: 0x40 */ +__IO uint32_t FTSR3; /*!< EXTI Falling trigger selection register, Address offset: 0x44 */ +__IO uint32_t SWIER3; /*!< EXTI Software interrupt event register, Address offset: 0x48 */ +__IO uint32_t D3PMR3; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR3) Address offset: 0x4C */ +__IO uint32_t D3PCR3L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR3L) Address offset: 0x50 */ +__IO uint32_t D3PCR3H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR3H) Address offset: 0x54 */ +uint32_t RESERVED3[10]; /*!< Reserved, 0x58 to 0x7C */ +__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x80 */ +__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x84 */ +__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x88 */ +uint32_t RESERVED4; /*!< Reserved, 0x8C */ +__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x90 */ +__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x94 */ +__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x98 */ +uint32_t RESERVED5; /*!< Reserved, 0x9C */ +__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0xA0 */ +__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0xA4 */ +__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0xA8 */ +}EXTI_TypeDef; + +/** + * @brief This structure registers corresponds to EXTI_Typdef CPU1/CPU2 registers subset (IMRx, EMRx and PRx), allowing to define EXTI_D1/EXTI_D2 + * with rapid/common access to these IMRx, EMRx, PRx registers for CPU1 and CPU2. + * Note that EXTI_D1 and EXTI_D2 bases addresses are calculated to point to CPUx first register: + * IMR1 in case of EXTI_D1 that is addressing CPU1 (Coretx-M7) + * C2IMR1 in case of EXTI_D2 that is addressing CPU2 (Coretx-M4) + * Note: EXTI_D2 and corresponding C2IMRx, C2EMRx and C2PRx registers are available for Dual Core devices only + */ + +typedef struct +{ +__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x00 */ +__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x04 */ +__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x08 */ +uint32_t RESERVED1; /*!< Reserved, 0x0C */ +__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x10 */ +__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x14 */ +__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x18 */ +uint32_t RESERVED2; /*!< Reserved, 0x1C */ +__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0x20 */ +__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0x24 */ +__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0x28 */ +}EXTI_Core_TypeDef; + + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t KEYR1; /*!< Flash Key Register for bank1, Address offset: 0x04 */ + __IO uint32_t OPTKEYR; /*!< Flash Option Key Register, Address offset: 0x08 */ + __IO uint32_t CR1; /*!< Flash Control Register for bank1, Address offset: 0x0C */ + __IO uint32_t SR1; /*!< Flash Status Register for bank1, Address offset: 0x10 */ + __IO uint32_t CCR1; /*!< Flash Control Register for bank1, Address offset: 0x14 */ + __IO uint32_t OPTCR; /*!< Flash Option Control Register, Address offset: 0x18 */ + __IO uint32_t OPTSR_CUR; /*!< Flash Option Status Current Register, Address offset: 0x1C */ + __IO uint32_t OPTSR_PRG; /*!< Flash Option Status to Program Register, Address offset: 0x20 */ + __IO uint32_t OPTCCR; /*!< Flash Option Clear Control Register, Address offset: 0x24 */ + __IO uint32_t PRAR_CUR1; /*!< Flash Current Protection Address Register for bank1, Address offset: 0x28 */ + __IO uint32_t PRAR_PRG1; /*!< Flash Protection Address to Program Register for bank1, Address offset: 0x2C */ + __IO uint32_t SCAR_CUR1; /*!< Flash Current Secure Address Register for bank1, Address offset: 0x30 */ + __IO uint32_t SCAR_PRG1; /*!< Flash Secure Address to Program Register for bank1, Address offset: 0x34 */ + __IO uint32_t WPSN_CUR1; /*!< Flash Current Write Protection Register on bank1, Address offset: 0x38 */ + __IO uint32_t WPSN_PRG1; /*!< Flash Write Protection to Program Register on bank1, Address offset: 0x3C */ + __IO uint32_t BOOT_CUR; /*!< Flash Current Boot Address for Pelican Core Register, Address offset: 0x40 */ + __IO uint32_t BOOT_PRG; /*!< Flash Boot Address to Program for Pelican Core Register, Address offset: 0x44 */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x48 to 0x4C */ + __IO uint32_t CRCCR1; /*!< Flash CRC Control register For Bank1 Register , Address offset: 0x50 */ + __IO uint32_t CRCSADD1; /*!< Flash CRC Start Address Register for Bank1 , Address offset: 0x54 */ + __IO uint32_t CRCEADD1; /*!< Flash CRC End Address Register for Bank1 , Address offset: 0x58 */ + __IO uint32_t CRCDATA; /*!< Flash CRC Data Register for Bank1 , Address offset: 0x5C */ + __IO uint32_t ECC_FA1; /*!< Flash ECC Fail Address For Bank1 Register , Address offset: 0x60 */ + uint32_t RESERVED[3]; /*!< Reserved, 0x64 to 0x6C */ + __IO uint32_t OPTSR2_CUR; /*!< Flash Option Status Current Register 2, Address offset: 0x70 */ + __IO uint32_t OPTSR2_PRG; /*!< Flash Option Status to Program Register 2, Address offset: 0x74 */ +} FLASH_TypeDef; + +/** + * @brief Filter and Mathematical ACcelerator + */ +typedef struct +{ + __IO uint32_t X1BUFCFG; /*!< FMAC X1 Buffer Configuration register, Address offset: 0x00 */ + __IO uint32_t X2BUFCFG; /*!< FMAC X2 Buffer Configuration register, Address offset: 0x04 */ + __IO uint32_t YBUFCFG; /*!< FMAC Y Buffer Configuration register, Address offset: 0x08 */ + __IO uint32_t PARAM; /*!< FMAC Parameter register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< FMAC Control register, Address offset: 0x10 */ + __IO uint32_t SR; /*!< FMAC Status register, Address offset: 0x14 */ + __IO uint32_t WDATA; /*!< FMAC Write Data register, Address offset: 0x18 */ + __IO uint32_t RDATA; /*!< FMAC Read Data register, Address offset: 0x1C */ +} FMAC_TypeDef; + +/** + * @brief Flexible Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FMC_Bank1_TypeDef; + +/** + * @brief Flexible Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FMC_Bank1E_TypeDef; + +/** + * @brief Flexible Memory Controller Bank2 + */ + +typedef struct +{ + __IO uint32_t PCR2; /*!< NAND Flash control register 2, Address offset: 0x60 */ + __IO uint32_t SR2; /*!< NAND Flash FIFO status and interrupt register 2, Address offset: 0x64 */ + __IO uint32_t PMEM2; /*!< NAND Flash Common memory space timing register 2, Address offset: 0x68 */ + __IO uint32_t PATT2; /*!< NAND Flash Attribute memory space timing register 2, Address offset: 0x6C */ + uint32_t RESERVED0; /*!< Reserved, 0x70 */ + __IO uint32_t ECCR2; /*!< NAND Flash ECC result registers 2, Address offset: 0x74 */ +} FMC_Bank2_TypeDef; + +/** + * @brief Flexible Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR; /*!< NAND Flash control register 3, Address offset: 0x80 */ + __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register 3, Address offset: 0x84 */ + __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register 3, Address offset: 0x88 */ + __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register 3, Address offset: 0x8C */ + uint32_t RESERVED; /*!< Reserved, 0x90 */ + __IO uint32_t ECCR; /*!< NAND Flash ECC result registers 3, Address offset: 0x94 */ +} FMC_Bank3_TypeDef; + +/** + * @brief Flexible Memory Controller Bank5 and 6 + */ + + +typedef struct +{ + __IO uint32_t SDCR[2]; /*!< SDRAM Control registers , Address offset: 0x140-0x144 */ + __IO uint32_t SDTR[2]; /*!< SDRAM Timing registers , Address offset: 0x148-0x14C */ + __IO uint32_t SDCMR; /*!< SDRAM Command Mode register, Address offset: 0x150 */ + __IO uint32_t SDRTR; /*!< SDRAM Refresh Timer register, Address offset: 0x154 */ + __IO uint32_t SDSR; /*!< SDRAM Status register, Address offset: 0x158 */ +} FMC_Bank5_6_TypeDef; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< GPIO port bit set/reset, Address offset: 0x18 */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ +} GPIO_TypeDef; + +/** + * @brief Operational Amplifier (OPAMP) + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */ + __IO uint32_t OTR; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */ + __IO uint32_t HSOTR; /*!< OPAMP offset trimming register for high speed mode, Address offset: 0x08 */ +} OPAMP_TypeDef; + +/** + * @brief System configuration controller + */ + +typedef struct +{ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x00 */ + __IO uint32_t PMCR; /*!< SYSCFG peripheral mode configuration register, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + __IO uint32_t CFGR; /*!< SYSCFG configuration registers, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t CCCSR; /*!< SYSCFG compensation cell control/status register, Address offset: 0x20 */ + __IO uint32_t CCVR; /*!< SYSCFG compensation cell value register, Address offset: 0x24 */ + __IO uint32_t CCCR; /*!< SYSCFG compensation cell code register, Address offset: 0x28 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x2C */ + __IO uint32_t ADC2ALT; /*!< ADC2 internal input alternate connection register, Address offset: 0x30 */ + uint32_t RESERVED4[60]; /*!< Reserved, 0x34-0x120 */ + __IO uint32_t PKGR; /*!< SYSCFG package register, Address offset: 0x124 */ + uint32_t RESERVED5[118]; /*!< Reserved, 0x128-0x2FC */ + __IO uint32_t UR0; /*!< SYSCFG user register 0, Address offset: 0x300 */ + __IO uint32_t UR1; /*!< SYSCFG user register 1, Address offset: 0x304 */ + __IO uint32_t UR2; /*!< SYSCFG user register 2, Address offset: 0x308 */ + __IO uint32_t UR3; /*!< SYSCFG user register 3, Address offset: 0x30C */ + __IO uint32_t UR4; /*!< SYSCFG user register 4, Address offset: 0x310 */ + __IO uint32_t UR5; /*!< SYSCFG user register 5, Address offset: 0x314 */ + __IO uint32_t UR6; /*!< SYSCFG user register 6, Address offset: 0x318 */ + __IO uint32_t UR7; /*!< SYSCFG user register 7, Address offset: 0x31C */ + uint32_t RESERVED6[3]; /*!< Reserved, Address offset: 0x320-0x328 */ + __IO uint32_t UR11; /*!< SYSCFG user register 11, Address offset: 0x32C */ + __IO uint32_t UR12; /*!< SYSCFG user register 12, Address offset: 0x330 */ + __IO uint32_t UR13; /*!< SYSCFG user register 13, Address offset: 0x334 */ + __IO uint32_t UR14; /*!< SYSCFG user register 14, Address offset: 0x338 */ + __IO uint32_t UR15; /*!< SYSCFG user register 15, Address offset: 0x33C */ + __IO uint32_t UR16; /*!< SYSCFG user register 16, Address offset: 0x340 */ + __IO uint32_t UR17; /*!< SYSCFG user register 17, Address offset: 0x344 */ + __IO uint32_t UR18; /*!< SYSCFG user register 18, Address offset: 0x348 */ + +} SYSCFG_TypeDef; + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */ + __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */ + __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */ + __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */ + __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */ + __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */ + __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */ + __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */ +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ + __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ +} IWDG_TypeDef; + + +/** + * @brief LCD-TFT Display Controller + */ + +typedef struct +{ + uint32_t RESERVED0[2]; /*!< Reserved, 0x00-0x04 */ + __IO uint32_t SSCR; /*!< LTDC Synchronization Size Configuration Register, Address offset: 0x08 */ + __IO uint32_t BPCR; /*!< LTDC Back Porch Configuration Register, Address offset: 0x0C */ + __IO uint32_t AWCR; /*!< LTDC Active Width Configuration Register, Address offset: 0x10 */ + __IO uint32_t TWCR; /*!< LTDC Total Width Configuration Register, Address offset: 0x14 */ + __IO uint32_t GCR; /*!< LTDC Global Control Register, Address offset: 0x18 */ + uint32_t RESERVED1[2]; /*!< Reserved, 0x1C-0x20 */ + __IO uint32_t SRCR; /*!< LTDC Shadow Reload Configuration Register, Address offset: 0x24 */ + uint32_t RESERVED2[1]; /*!< Reserved, 0x28 */ + __IO uint32_t BCCR; /*!< LTDC Background Color Configuration Register, Address offset: 0x2C */ + uint32_t RESERVED3[1]; /*!< Reserved, 0x30 */ + __IO uint32_t IER; /*!< LTDC Interrupt Enable Register, Address offset: 0x34 */ + __IO uint32_t ISR; /*!< LTDC Interrupt Status Register, Address offset: 0x38 */ + __IO uint32_t ICR; /*!< LTDC Interrupt Clear Register, Address offset: 0x3C */ + __IO uint32_t LIPCR; /*!< LTDC Line Interrupt Position Configuration Register, Address offset: 0x40 */ + __IO uint32_t CPSR; /*!< LTDC Current Position Status Register, Address offset: 0x44 */ + __IO uint32_t CDSR; /*!< LTDC Current Display Status Register, Address offset: 0x48 */ +} LTDC_TypeDef; + +/** + * @brief LCD-TFT Display layer x Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< LTDC Layerx Control Register Address offset: 0x84 */ + __IO uint32_t WHPCR; /*!< LTDC Layerx Window Horizontal Position Configuration Register Address offset: 0x88 */ + __IO uint32_t WVPCR; /*!< LTDC Layerx Window Vertical Position Configuration Register Address offset: 0x8C */ + __IO uint32_t CKCR; /*!< LTDC Layerx Color Keying Configuration Register Address offset: 0x90 */ + __IO uint32_t PFCR; /*!< LTDC Layerx Pixel Format Configuration Register Address offset: 0x94 */ + __IO uint32_t CACR; /*!< LTDC Layerx Constant Alpha Configuration Register Address offset: 0x98 */ + __IO uint32_t DCCR; /*!< LTDC Layerx Default Color Configuration Register Address offset: 0x9C */ + __IO uint32_t BFCR; /*!< LTDC Layerx Blending Factors Configuration Register Address offset: 0xA0 */ + uint32_t RESERVED0[2]; /*!< Reserved */ + __IO uint32_t CFBAR; /*!< LTDC Layerx Color Frame Buffer Address Register Address offset: 0xAC */ + __IO uint32_t CFBLR; /*!< LTDC Layerx Color Frame Buffer Length Register Address offset: 0xB0 */ + __IO uint32_t CFBLNR; /*!< LTDC Layerx ColorFrame Buffer Line Number Register Address offset: 0xB4 */ + uint32_t RESERVED1[3]; /*!< Reserved */ + __IO uint32_t CLUTWR; /*!< LTDC Layerx CLUT Write Register Address offset: 0x144 */ + +} LTDC_Layer_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */ + __IO uint32_t CSR1; /*!< PWR power control status register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x08 */ + __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x0C */ + __IO uint32_t CPUCR; /*!< PWR CPU control register, Address offset: 0x10 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t D3CR; /*!< PWR D3 domain control register, Address offset: 0x18 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t WKUPCR; /*!< PWR wakeup clear register, Address offset: 0x20 */ + __IO uint32_t WKUPFR; /*!< PWR wakeup flag register, Address offset: 0x24 */ + __IO uint32_t WKUPEPR; /*!< PWR wakeup enable and polarity register, Address offset: 0x28 */ +} PWR_TypeDef; + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t HSICFGR; /*!< HSI Clock Calibration Register, Address offset: 0x04 */ + __IO uint32_t CRRCR; /*!< Clock Recovery RC Register, Address offset: 0x08 */ + __IO uint32_t CSICFGR; /*!< CSI Clock Calibration Register, Address offset: 0x0C */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x10 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t D1CFGR; /*!< RCC Domain 1 configuration register, Address offset: 0x18 */ + __IO uint32_t D2CFGR; /*!< RCC Domain 2 configuration register, Address offset: 0x1C */ + __IO uint32_t D3CFGR; /*!< RCC Domain 3 configuration register, Address offset: 0x20 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t PLLCKSELR; /*!< RCC PLLs Clock Source Selection Register, Address offset: 0x28 */ + __IO uint32_t PLLCFGR; /*!< RCC PLLs Configuration Register, Address offset: 0x2C */ + __IO uint32_t PLL1DIVR; /*!< RCC PLL1 Dividers Configuration Register, Address offset: 0x30 */ + __IO uint32_t PLL1FRACR; /*!< RCC PLL1 Fractional Divider Configuration Register, Address offset: 0x34 */ + __IO uint32_t PLL2DIVR; /*!< RCC PLL2 Dividers Configuration Register, Address offset: 0x38 */ + __IO uint32_t PLL2FRACR; /*!< RCC PLL2 Fractional Divider Configuration Register, Address offset: 0x3C */ + __IO uint32_t PLL3DIVR; /*!< RCC PLL3 Dividers Configuration Register, Address offset: 0x40 */ + __IO uint32_t PLL3FRACR; /*!< RCC PLL3 Fractional Divider Configuration Register, Address offset: 0x44 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x48 */ + __IO uint32_t D1CCIPR; /*!< RCC Domain 1 Kernel Clock Configuration Register Address offset: 0x4C */ + __IO uint32_t D2CCIP1R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x50 */ + __IO uint32_t D2CCIP2R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x54 */ + __IO uint32_t D3CCIPR; /*!< RCC Domain 3 Kernel Clock Configuration Register Address offset: 0x58 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x5C */ + __IO uint32_t CIER; /*!< RCC Clock Source Interrupt Enable Register Address offset: 0x60 */ + __IO uint32_t CIFR; /*!< RCC Clock Source Interrupt Flag Register Address offset: 0x64 */ + __IO uint32_t CICR; /*!< RCC Clock Source Interrupt Clear Register Address offset: 0x68 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x6C */ + __IO uint32_t BDCR; /*!< RCC Vswitch Backup Domain Control Register, Address offset: 0x70 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x78 */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x7C */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x80 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x84 */ + __IO uint32_t AHB4RSTR; /*!< RCC AHB4 peripheral reset register, Address offset: 0x88 */ + __IO uint32_t APB3RSTR; /*!< RCC APB3 peripheral reset register, Address offset: 0x8C */ + __IO uint32_t APB1LRSTR; /*!< RCC APB1 peripheral reset Low Word register, Address offset: 0x90 */ + __IO uint32_t APB1HRSTR; /*!< RCC APB1 peripheral reset High Word register, Address offset: 0x94 */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x98 */ + __IO uint32_t APB4RSTR; /*!< RCC APB4 peripheral reset register, Address offset: 0x9C */ + __IO uint32_t GCR; /*!< RCC RCC Global Control Register, Address offset: 0xA0 */ + uint32_t RESERVED8; /*!< Reserved, Address offset: 0xA4 */ + __IO uint32_t D3AMR; /*!< RCC Domain 3 Autonomous Mode Register, Address offset: 0xA8 */ + uint32_t RESERVED11[9]; /*!< Reserved, 0xAC-0xCC Address offset: 0xAC */ + __IO uint32_t RSR; /*!< RCC Reset status register, Address offset: 0xD0 */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0xD4 */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0xD8 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0xDC */ + __IO uint32_t AHB4ENR; /*!< RCC AHB4 peripheral clock register, Address offset: 0xE0 */ + __IO uint32_t APB3ENR; /*!< RCC APB3 peripheral clock register, Address offset: 0xE4 */ + __IO uint32_t APB1LENR; /*!< RCC APB1 peripheral clock Low Word register, Address offset: 0xE8 */ + __IO uint32_t APB1HENR; /*!< RCC APB1 peripheral clock High Word register, Address offset: 0xEC */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock register, Address offset: 0xF0 */ + __IO uint32_t APB4ENR; /*!< RCC APB4 peripheral clock register, Address offset: 0xF4 */ + uint32_t RESERVED12; /*!< Reserved, Address offset: 0xF8 */ + __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral sleep clock register, Address offset: 0xFC */ + __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral sleep clock register, Address offset: 0x100 */ + __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral sleep clock register, Address offset: 0x104 */ + __IO uint32_t AHB4LPENR; /*!< RCC AHB4 peripheral sleep clock register, Address offset: 0x108 */ + __IO uint32_t APB3LPENR; /*!< RCC APB3 peripheral sleep clock register, Address offset: 0x10C */ + __IO uint32_t APB1LLPENR; /*!< RCC APB1 peripheral sleep clock Low Word register, Address offset: 0x110 */ + __IO uint32_t APB1HLPENR; /*!< RCC APB1 peripheral sleep clock High Word register, Address offset: 0x114 */ + __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral sleep clock register, Address offset: 0x118 */ + __IO uint32_t APB4LPENR; /*!< RCC APB4 peripheral sleep clock register, Address offset: 0x11C */ + uint32_t RESERVED13[4]; /*!< Reserved, 0x120-0x12C Address offset: 0x120 */ + +} RCC_TypeDef; + + +/** + * @brief Real-Time Clock + */ +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x18 */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */ + __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ + __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */ + __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */ + __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */ + __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */ + __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */ + __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */ + __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */ + __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */ + __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */ + __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */ + __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */ + __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */ +} RTC_TypeDef; + +/** + * @brief Serial Audio Interface + */ + +typedef struct +{ + __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ + uint32_t RESERVED0[16]; /*!< Reserved, 0x04 - 0x43 */ + __IO uint32_t PDMCR; /*!< SAI PDM control register, Address offset: 0x44 */ + __IO uint32_t PDMDLY; /*!< SAI PDM delay register, Address offset: 0x48 */ +} SAI_TypeDef; + +typedef struct +{ + __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ + __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ + __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ + __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ + __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ + __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ +} SAI_Block_TypeDef; + +/** + * @brief SPDIF-RX Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< Control register, Address offset: 0x00 */ + __IO uint32_t IMR; /*!< Interrupt mask register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< Status register, Address offset: 0x08 */ + __IO uint32_t IFCR; /*!< Interrupt Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DR; /*!< Data input register, Address offset: 0x10 */ + __IO uint32_t CSR; /*!< Channel Status register, Address offset: 0x14 */ + __IO uint32_t DIR; /*!< Debug Information register, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1A */ +} SPDIFRX_TypeDef; + + +/** + * @brief Secure digital input/output Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */ + __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */ + __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */ + __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */ + __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */ + __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */ + __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */ + __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */ + __IO uint32_t ACKTIME; /*!< SDMMC Acknowledgement timer register, Address offset: 0x40 */ + uint32_t RESERVED0[3]; /*!< Reserved, 0x44 - 0x4C - 0x4C */ + __IO uint32_t IDMACTRL; /*!< SDMMC DMA control register, Address offset: 0x50 */ + __IO uint32_t IDMABSIZE; /*!< SDMMC DMA buffer size register, Address offset: 0x54 */ + __IO uint32_t IDMABASE0; /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58 */ + __IO uint32_t IDMABASE1; /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C */ + uint32_t RESERVED1[8]; /*!< Reserved, 0x60-0x7C */ + __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */ + uint32_t RESERVED2[222]; /*!< Reserved, 0x84-0x3F8 */ + __IO uint32_t IPVR; /*!< SDMMC data FIFO register, Address offset: 0x3FC */ +} SDMMC_TypeDef; + + +/** + * @brief Delay Block DLYB + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DELAY BLOCK control register, Address offset: 0x00 */ + __IO uint32_t CFGR; /*!< DELAY BLOCK configuration register, Address offset: 0x04 */ +} DLYB_TypeDef; + +/** + * @brief HW Semaphore HSEM + */ + +typedef struct +{ + __IO uint32_t R[32]; /*!< 2-step write lock and read back registers, Address offset: 00h-7Ch */ + __IO uint32_t RLR[32]; /*!< 1-step read lock registers, Address offset: 80h-FCh */ + __IO uint32_t C1IER; /*!< HSEM Interrupt enable register , Address offset: 100h */ + __IO uint32_t C1ICR; /*!< HSEM Interrupt clear register , Address offset: 104h */ + __IO uint32_t C1ISR; /*!< HSEM Interrupt Status register , Address offset: 108h */ + __IO uint32_t C1MISR; /*!< HSEM Interrupt Masked Status register , Address offset: 10Ch */ + uint32_t Reserved[12]; /* Reserved Address offset: 110h-13Ch */ + __IO uint32_t CR; /*!< HSEM Semaphore clear register , Address offset: 140h */ + __IO uint32_t KEYR; /*!< HSEM Semaphore clear key register , Address offset: 144h */ + +} HSEM_TypeDef; + +typedef struct +{ + __IO uint32_t IER; /*!< HSEM interrupt enable register , Address offset: 0h */ + __IO uint32_t ICR; /*!< HSEM interrupt clear register , Address offset: 4h */ + __IO uint32_t ISR; /*!< HSEM interrupt status register , Address offset: 8h */ + __IO uint32_t MISR; /*!< HSEM masked interrupt status register , Address offset: Ch */ +} HSEM_Common_TypeDef; + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< SPI/I2S Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */ + __IO uint32_t CFG1; /*!< SPI Configuration register 1, Address offset: 0x08 */ + __IO uint32_t CFG2; /*!< SPI Configuration register 2, Address offset: 0x0C */ + __IO uint32_t IER; /*!< SPI/I2S Interrupt Enable register, Address offset: 0x10 */ + __IO uint32_t SR; /*!< SPI/I2S Status register, Address offset: 0x14 */ + __IO uint32_t IFCR; /*!< SPI/I2S Interrupt/Status flags clear register, Address offset: 0x18 */ + uint32_t RESERVED0; /*!< Reserved, 0x1C */ + __IO uint32_t TXDR; /*!< SPI/I2S Transmit data register, Address offset: 0x20 */ + uint32_t RESERVED1[3]; /*!< Reserved, 0x24-0x2C */ + __IO uint32_t RXDR; /*!< SPI/I2S Receive data register, Address offset: 0x30 */ + uint32_t RESERVED2[3]; /*!< Reserved, 0x34-0x3C */ + __IO uint32_t CRCPOLY; /*!< SPI CRC Polynomial register, Address offset: 0x40 */ + __IO uint32_t TXCRC; /*!< SPI Transmitter CRC register, Address offset: 0x44 */ + __IO uint32_t RXCRC; /*!< SPI Receiver CRC register, Address offset: 0x48 */ + __IO uint32_t UDRDR; /*!< SPI Underrun data register, Address offset: 0x4C */ + __IO uint32_t I2SCFGR; /*!< I2S Configuration register, Address offset: 0x50 */ + +} SPI_TypeDef; + +/** + * @brief DTS + */ +typedef struct +{ + __IO uint32_t CFGR1; /*!< DTS configuration register, Address offset: 0x00 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x04 */ + __IO uint32_t T0VALR1; /*!< DTS T0 Value register, Address offset: 0x08 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x0C */ + __IO uint32_t RAMPVALR; /*!< DTS Ramp value register, Address offset: 0x10 */ + __IO uint32_t ITR1; /*!< DTS Interrupt threshold register, Address offset: 0x14 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x18 */ + __IO uint32_t DR; /*!< DTS data register, Address offset: 0x1C */ + __IO uint32_t SR; /*!< DTS status register Address offset: 0x20 */ + __IO uint32_t ITENR; /*!< DTS Interrupt enable register, Address offset: 0x24 */ + __IO uint32_t ICIFR; /*!< DTS Clear Interrupt flag register, Address offset: 0x28 */ + __IO uint32_t OR; /*!< DTS option register 1, Address offset: 0x2C */ +} +DTS_TypeDef; + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ + __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + uint32_t RESERVED1; /*!< Reserved, 0x50 */ + __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */ + __IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */ + __IO uint32_t CCR6; /*!< TIM capture/compare register6, Address offset: 0x5C */ + __IO uint32_t AF1; /*!< TIM alternate function option register 1, Address offset: 0x60 */ + __IO uint32_t AF2; /*!< TIM alternate function option register 2, Address offset: 0x64 */ + __IO uint32_t TISEL; /*!< TIM Input Selection register, Address offset: 0x68 */ +} TIM_TypeDef; + +/** + * @brief LPTIMIMER + */ +typedef struct +{ + __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ + __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ + __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ + __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ + __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ + __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ + uint32_t RESERVED1; /*!< Reserved, 0x20 */ + __IO uint32_t CFGR2; /*!< LPTIM Configuration register, Address offset: 0x24 */ +} LPTIM_TypeDef; + +/** + * @brief Comparator + */ +typedef struct +{ + __IO uint32_t SR; /*!< Comparator status register, Address offset: 0x00 */ + __IO uint32_t ICFR; /*!< Comparator interrupt clear flag register, Address offset: 0x04 */ + __IO uint32_t OR; /*!< Comparator option register, Address offset: 0x08 */ +} COMPOPT_TypeDef; + +typedef struct +{ + __IO uint32_t CFGR; /*!< Comparator configuration register , Address offset: 0x00 */ +} COMP_TypeDef; + +typedef struct +{ + __IO uint32_t CFGR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */ +} COMP_Common_TypeDef; +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ + __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ + __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ + __IO uint32_t RQR; /*!< USART Request register, Address offset: 0x18 */ + __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */ + __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */ + __IO uint32_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */ + __IO uint32_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */ + __IO uint32_t PRESC; /*!< USART clock Prescaler register, Address offset: 0x2C */ +} USART_TypeDef; + +/** + * @brief Single Wire Protocol Master Interface SPWMI + */ +typedef struct +{ + __IO uint32_t CR; /*!< SWPMI Configuration/Control register, Address offset: 0x00 */ + __IO uint32_t BRR; /*!< SWPMI bitrate register, Address offset: 0x04 */ + uint32_t RESERVED1; /*!< Reserved, 0x08 */ + __IO uint32_t ISR; /*!< SWPMI Interrupt and Status register, Address offset: 0x0C */ + __IO uint32_t ICR; /*!< SWPMI Interrupt Flag Clear register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< SWPMI Interrupt Enable register, Address offset: 0x14 */ + __IO uint32_t RFL; /*!< SWPMI Receive Frame Length register, Address offset: 0x18 */ + __IO uint32_t TDR; /*!< SWPMI Transmit data register, Address offset: 0x1C */ + __IO uint32_t RDR; /*!< SWPMI Receive data register, Address offset: 0x20 */ + __IO uint32_t OR; /*!< SWPMI Option register, Address offset: 0x24 */ +} SWPMI_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + + +/** + * @brief RAM_ECC_Specific_Registers + */ +typedef struct +{ + __IO uint32_t CR; /*!< RAMECC monitor configuration register */ + __IO uint32_t SR; /*!< RAMECC monitor status register */ + __IO uint32_t FAR; /*!< RAMECC monitor failing address register */ + __IO uint32_t FDRL; /*!< RAMECC monitor failing data low register */ + __IO uint32_t FDRH; /*!< RAMECC monitor failing data high register */ + __IO uint32_t FECR; /*!< RAMECC monitor failing ECC error code register */ +} RAMECC_MonitorTypeDef; + +typedef struct +{ + __IO uint32_t IER; /*!< RAMECC interrupt enable register */ +} RAMECC_TypeDef; +/** + * @} + */ + + +/** + * @brief Crypto Processor + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CRYP control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< CRYP status register, Address offset: 0x04 */ + __IO uint32_t DIN; /*!< CRYP data input register, Address offset: 0x08 */ + __IO uint32_t DOUT; /*!< CRYP data output register, Address offset: 0x0C */ + __IO uint32_t DMACR; /*!< CRYP DMA control register, Address offset: 0x10 */ + __IO uint32_t IMSCR; /*!< CRYP interrupt mask set/clear register, Address offset: 0x14 */ + __IO uint32_t RISR; /*!< CRYP raw interrupt status register, Address offset: 0x18 */ + __IO uint32_t MISR; /*!< CRYP masked interrupt status register, Address offset: 0x1C */ + __IO uint32_t K0LR; /*!< CRYP key left register 0, Address offset: 0x20 */ + __IO uint32_t K0RR; /*!< CRYP key right register 0, Address offset: 0x24 */ + __IO uint32_t K1LR; /*!< CRYP key left register 1, Address offset: 0x28 */ + __IO uint32_t K1RR; /*!< CRYP key right register 1, Address offset: 0x2C */ + __IO uint32_t K2LR; /*!< CRYP key left register 2, Address offset: 0x30 */ + __IO uint32_t K2RR; /*!< CRYP key right register 2, Address offset: 0x34 */ + __IO uint32_t K3LR; /*!< CRYP key left register 3, Address offset: 0x38 */ + __IO uint32_t K3RR; /*!< CRYP key right register 3, Address offset: 0x3C */ + __IO uint32_t IV0LR; /*!< CRYP initialization vector left-word register 0, Address offset: 0x40 */ + __IO uint32_t IV0RR; /*!< CRYP initialization vector right-word register 0, Address offset: 0x44 */ + __IO uint32_t IV1LR; /*!< CRYP initialization vector left-word register 1, Address offset: 0x48 */ + __IO uint32_t IV1RR; /*!< CRYP initialization vector right-word register 1, Address offset: 0x4C */ + __IO uint32_t CSGCMCCM0R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 0, Address offset: 0x50 */ + __IO uint32_t CSGCMCCM1R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 1, Address offset: 0x54 */ + __IO uint32_t CSGCMCCM2R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 2, Address offset: 0x58 */ + __IO uint32_t CSGCMCCM3R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 3, Address offset: 0x5C */ + __IO uint32_t CSGCMCCM4R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 4, Address offset: 0x60 */ + __IO uint32_t CSGCMCCM5R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 5, Address offset: 0x64 */ + __IO uint32_t CSGCMCCM6R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 6, Address offset: 0x68 */ + __IO uint32_t CSGCMCCM7R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 7, Address offset: 0x6C */ + __IO uint32_t CSGCM0R; /*!< CRYP GCM/GMAC context swap register 0, Address offset: 0x70 */ + __IO uint32_t CSGCM1R; /*!< CRYP GCM/GMAC context swap register 1, Address offset: 0x74 */ + __IO uint32_t CSGCM2R; /*!< CRYP GCM/GMAC context swap register 2, Address offset: 0x78 */ + __IO uint32_t CSGCM3R; /*!< CRYP GCM/GMAC context swap register 3, Address offset: 0x7C */ + __IO uint32_t CSGCM4R; /*!< CRYP GCM/GMAC context swap register 4, Address offset: 0x80 */ + __IO uint32_t CSGCM5R; /*!< CRYP GCM/GMAC context swap register 5, Address offset: 0x84 */ + __IO uint32_t CSGCM6R; /*!< CRYP GCM/GMAC context swap register 6, Address offset: 0x88 */ + __IO uint32_t CSGCM7R; /*!< CRYP GCM/GMAC context swap register 7, Address offset: 0x8C */ +} CRYP_TypeDef; + +/** + * @brief HASH + */ + +typedef struct +{ + __IO uint32_t CR; /*!< HASH control register, Address offset: 0x00 */ + __IO uint32_t DIN; /*!< HASH data input register, Address offset: 0x04 */ + __IO uint32_t STR; /*!< HASH start register, Address offset: 0x08 */ + __IO uint32_t HR[5]; /*!< HASH digest registers, Address offset: 0x0C-0x1C */ + __IO uint32_t IMR; /*!< HASH interrupt enable register, Address offset: 0x20 */ + __IO uint32_t SR; /*!< HASH status register, Address offset: 0x24 */ + uint32_t RESERVED[52]; /*!< Reserved, 0x28-0xF4 */ + __IO uint32_t CSR[54]; /*!< HASH context swap registers, Address offset: 0x0F8-0x1CC */ +} HASH_TypeDef; + +/** + * @brief HASH_DIGEST + */ + +typedef struct +{ + __IO uint32_t HR[8]; /*!< HASH digest registers, Address offset: 0x310-0x32C */ +} HASH_DIGEST_TypeDef; + + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ + uint32_t RESERVED; + __IO uint32_t HTCR; /*!< RNG health test configuration register, Address offset: 0x10 */ +} RNG_TypeDef; + +/** + * @brief MDIOS + */ + +typedef struct +{ + __IO uint32_t CR; + __IO uint32_t WRFR; + __IO uint32_t CWRFR; + __IO uint32_t RDFR; + __IO uint32_t CRDFR; + __IO uint32_t SR; + __IO uint32_t CLRFR; + uint32_t RESERVED[57]; + __IO uint32_t DINR0; + __IO uint32_t DINR1; + __IO uint32_t DINR2; + __IO uint32_t DINR3; + __IO uint32_t DINR4; + __IO uint32_t DINR5; + __IO uint32_t DINR6; + __IO uint32_t DINR7; + __IO uint32_t DINR8; + __IO uint32_t DINR9; + __IO uint32_t DINR10; + __IO uint32_t DINR11; + __IO uint32_t DINR12; + __IO uint32_t DINR13; + __IO uint32_t DINR14; + __IO uint32_t DINR15; + __IO uint32_t DINR16; + __IO uint32_t DINR17; + __IO uint32_t DINR18; + __IO uint32_t DINR19; + __IO uint32_t DINR20; + __IO uint32_t DINR21; + __IO uint32_t DINR22; + __IO uint32_t DINR23; + __IO uint32_t DINR24; + __IO uint32_t DINR25; + __IO uint32_t DINR26; + __IO uint32_t DINR27; + __IO uint32_t DINR28; + __IO uint32_t DINR29; + __IO uint32_t DINR30; + __IO uint32_t DINR31; + __IO uint32_t DOUTR0; + __IO uint32_t DOUTR1; + __IO uint32_t DOUTR2; + __IO uint32_t DOUTR3; + __IO uint32_t DOUTR4; + __IO uint32_t DOUTR5; + __IO uint32_t DOUTR6; + __IO uint32_t DOUTR7; + __IO uint32_t DOUTR8; + __IO uint32_t DOUTR9; + __IO uint32_t DOUTR10; + __IO uint32_t DOUTR11; + __IO uint32_t DOUTR12; + __IO uint32_t DOUTR13; + __IO uint32_t DOUTR14; + __IO uint32_t DOUTR15; + __IO uint32_t DOUTR16; + __IO uint32_t DOUTR17; + __IO uint32_t DOUTR18; + __IO uint32_t DOUTR19; + __IO uint32_t DOUTR20; + __IO uint32_t DOUTR21; + __IO uint32_t DOUTR22; + __IO uint32_t DOUTR23; + __IO uint32_t DOUTR24; + __IO uint32_t DOUTR25; + __IO uint32_t DOUTR26; + __IO uint32_t DOUTR27; + __IO uint32_t DOUTR28; + __IO uint32_t DOUTR29; + __IO uint32_t DOUTR30; + __IO uint32_t DOUTR31; +} MDIOS_TypeDef; + + +/** + * @brief USB_OTG_Core_Registers + */ +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h */ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h */ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h */ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch */ + __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h */ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h */ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h */ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch */ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h */ + __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h */ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h */ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< General Purpose IO Register 038h */ + __IO uint32_t CID; /*!< User ID Register 03Ch */ + __IO uint32_t GSNPSID; /* USB_OTG core ID 040h*/ + __IO uint32_t GHWCFG1; /* User HW config1 044h*/ + __IO uint32_t GHWCFG2; /* User HW config2 048h*/ + __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch */ + uint32_t Reserved6; /*!< Reserved 050h */ + __IO uint32_t GLPMCFG; /*!< LPM Register 054h */ + __IO uint32_t GPWRDN; /*!< Power Down Register 058h */ + __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch */ + __IO uint32_t GADPCTL; /*!< ADP Timer, Control and Status Register 60Ch */ + uint32_t Reserved43[39]; /*!< Reserved 058h-0FFh */ + __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg 100h */ + __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO */ +} USB_OTG_GlobalTypeDef; + + +/** + * @brief USB_OTG_device_Registers + */ +typedef struct +{ + __IO uint32_t DCFG; /*!< dev Configuration Register 800h */ + __IO uint32_t DCTL; /*!< dev Control Register 804h */ + __IO uint32_t DSTS; /*!< dev Status Register (RO) 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask 810h */ + __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask 814h */ + __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg 818h */ + __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved9; /*!< Reserved 824h */ + __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register 828h */ + __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register 82Ch */ + __IO uint32_t DTHRCTL; /*!< dev threshold 830h */ + __IO uint32_t DIEPEMPMSK; /*!< dev empty msk 834h */ + __IO uint32_t DEACHINT; /*!< dedicated EP interrupt 838h */ + __IO uint32_t DEACHMSK; /*!< dedicated EP msk 83Ch */ + uint32_t Reserved40; /*!< dedicated EP mask 840h */ + __IO uint32_t DINEP1MSK; /*!< dedicated EP mask 844h */ + uint32_t Reserved44[15]; /*!< Reserved 844-87Ch */ + __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk 884h */ +} USB_OTG_DeviceTypeDef; + + +/** + * @brief USB_OTG_IN_Endpoint-Specific_Register + */ +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h */ + __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h */ + __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h */ + __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h */ + uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch */ +} USB_OTG_INEndpointTypeDef; + + +/** + * @brief USB_OTG_OUT_Endpoint-Specific_Registers + */ +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h */ + __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h */ + __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h */ + uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch */ +} USB_OTG_OUTEndpointTypeDef; + + +/** + * @brief USB_OTG_Host_Mode_Register_Structures + */ +typedef struct +{ + __IO uint32_t HCFG; /*!< Host Configuration Register 400h */ + __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h */ + __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h */ + __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h */ + __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h */ +} USB_OTG_HostTypeDef; + +/** + * @brief USB_OTG_Host_Channel_Specific_Registers + */ +typedef struct +{ + __IO uint32_t HCCHAR; /*!< Host Channel Characteristics Register 500h */ + __IO uint32_t HCSPLT; /*!< Host Channel Split Control Register 504h */ + __IO uint32_t HCINT; /*!< Host Channel Interrupt Register 508h */ + __IO uint32_t HCINTMSK; /*!< Host Channel Interrupt Mask Register 50Ch */ + __IO uint32_t HCTSIZ; /*!< Host Channel Transfer Size Register 510h */ + __IO uint32_t HCDMA; /*!< Host Channel DMA Address Register 514h */ + uint32_t Reserved[2]; /*!< Reserved */ +} USB_OTG_HostChannelTypeDef; +/** + * @} + */ + +/** + * @brief OCTO Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< OCTOSPI Control register, Address offset: 0x000 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x004 */ + __IO uint32_t DCR1; /*!< OCTOSPI Device Configuration register 1, Address offset: 0x008 */ + __IO uint32_t DCR2; /*!< OCTOSPI Device Configuration register 2, Address offset: 0x00C */ + __IO uint32_t DCR3; /*!< OCTOSPI Device Configuration register 3, Address offset: 0x010 */ + __IO uint32_t DCR4; /*!< OCTOSPI Device Configuration register 4, Address offset: 0x014 */ + uint32_t RESERVED1[2]; /*!< Reserved, Address offset: 0x018-0x01C */ + __IO uint32_t SR; /*!< OCTOSPI Status register, Address offset: 0x020 */ + __IO uint32_t FCR; /*!< OCTOSPI Flag Clear register, Address offset: 0x024 */ + uint32_t RESERVED2[6]; /*!< Reserved, Address offset: 0x028-0x03C */ + __IO uint32_t DLR; /*!< OCTOSPI Data Length register, Address offset: 0x040 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x044 */ + __IO uint32_t AR; /*!< OCTOSPI Address register, Address offset: 0x048 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x04C */ + __IO uint32_t DR; /*!< OCTOSPI Data register, Address offset: 0x050 */ + uint32_t RESERVED5[11]; /*!< Reserved, Address offset: 0x054-0x07C */ + __IO uint32_t PSMKR; /*!< OCTOSPI Polling Status Mask register, Address offset: 0x080 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x084 */ + __IO uint32_t PSMAR; /*!< OCTOSPI Polling Status Match register, Address offset: 0x088 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x08C */ + __IO uint32_t PIR; /*!< OCTOSPI Polling Interval register, Address offset: 0x090 */ + uint32_t RESERVED8[27]; /*!< Reserved, Address offset: 0x094-0x0FC */ + __IO uint32_t CCR; /*!< OCTOSPI Communication Configuration register, Address offset: 0x100 */ + uint32_t RESERVED9; /*!< Reserved, Address offset: 0x104 */ + __IO uint32_t TCR; /*!< OCTOSPI Timing Configuration register, Address offset: 0x108 */ + uint32_t RESERVED10; /*!< Reserved, Address offset: 0x10C */ + __IO uint32_t IR; /*!< OCTOSPI Instruction register, Address offset: 0x110 */ + uint32_t RESERVED11[3]; /*!< Reserved, Address offset: 0x114-0x11C */ + __IO uint32_t ABR; /*!< OCTOSPI Alternate Bytes register, Address offset: 0x120 */ + uint32_t RESERVED12[3]; /*!< Reserved, Address offset: 0x124-0x12C */ + __IO uint32_t LPTR; /*!< OCTOSPI Low Power Timeout register, Address offset: 0x130 */ + uint32_t RESERVED13[3]; /*!< Reserved, Address offset: 0x134-0x13C */ + __IO uint32_t WPCCR; /*!< OCTOSPI Wrap Communication Configuration register, Address offset: 0x140 */ + uint32_t RESERVED14; /*!< Reserved, Address offset: 0x144 */ + __IO uint32_t WPTCR; /*!< OCTOSPI Wrap Timing Configuration register, Address offset: 0x148 */ + uint32_t RESERVED15; /*!< Reserved, Address offset: 0x14C */ + __IO uint32_t WPIR; /*!< OCTOSPI Wrap Instruction register, Address offset: 0x150 */ + uint32_t RESERVED16[3]; /*!< Reserved, Address offset: 0x154-0x15C */ + __IO uint32_t WPABR; /*!< OCTOSPI Wrap Alternate Bytes register, Address offset: 0x160 */ + uint32_t RESERVED17[7]; /*!< Reserved, Address offset: 0x164-0x17C */ + __IO uint32_t WCCR; /*!< OCTOSPI Write Communication Configuration register, Address offset: 0x180 */ + uint32_t RESERVED18; /*!< Reserved, Address offset: 0x184 */ + __IO uint32_t WTCR; /*!< OCTOSPI Write Timing Configuration register, Address offset: 0x188 */ + uint32_t RESERVED19; /*!< Reserved, Address offset: 0x18C */ + __IO uint32_t WIR; /*!< OCTOSPI Write Instruction register, Address offset: 0x190 */ + uint32_t RESERVED20[3]; /*!< Reserved, Address offset: 0x194-0x19C */ + __IO uint32_t WABR; /*!< OCTOSPI Write Alternate Bytes register, Address offset: 0x1A0 */ + uint32_t RESERVED21[23]; /*!< Reserved, Address offset: 0x1A4-0x1FC */ + __IO uint32_t HLCR; /*!< OCTOSPI Hyperbus Latency Configuration register, Address offset: 0x200 */ + uint32_t RESERVED22[122]; /*!< Reserved, Address offset: 0x204-0x3EC */ + __IO uint32_t HWCFGR; /*!< OCTOSPI HW Configuration register, Address offset: 0x3F0 */ + __IO uint32_t VER; /*!< OCTOSPI Version register, Address offset: 0x3F4 */ + __IO uint32_t ID; /*!< OCTOSPI Identification register, Address offset: 0x3F8 */ + __IO uint32_t MID; /*!< OCTOPSI HW Magic ID register, Address offset: 0x3FC */ +} OCTOSPI_TypeDef; + +/** + * @} + */ +/** + * @brief OCTO Serial Peripheral Interface IO Manager + */ + +typedef struct +{ + __IO uint32_t CR; /*!< OCTOSPI IO Manager Control register, Address offset: 0x00 */ + __IO uint32_t PCR[3]; /*!< OCTOSPI IO Manager Port[1:3] Configuration register, Address offset: 0x04-0x20 */ +} OCTOSPIM_TypeDef; + +/** + * @} + */ + +/** + * @brief OTFD register + */ +typedef struct +{ + __IO uint32_t REG_CONFIGR; + __IO uint32_t REG_START_ADDR; + __IO uint32_t REG_END_ADDR; + __IO uint32_t REG_NONCER0; + __IO uint32_t REG_NONCER1; + __IO uint32_t REG_KEYR0; + __IO uint32_t REG_KEYR1; + __IO uint32_t REG_KEYR2; + __IO uint32_t REG_KEYR3; +} OTFDEC_Region_TypeDef; + +typedef struct +{ + __IO uint32_t CR; + uint32_t RESERVED1[191]; + __IO uint32_t ISR; + __IO uint32_t ICR; + __IO uint32_t IER; + uint32_t RESERVED2[56]; + __IO uint32_t HWCFGR2; + __IO uint32_t HWCFGR1; + __IO uint32_t VERR; + __IO uint32_t IPIDR; + __IO uint32_t SIDR; +} OTFDEC_TypeDef; +/** + * @} + */ + +/** + * @brief Global Programmer View + */ + +typedef struct +{ + uint32_t RESERVED0[2036]; /*!< Reserved, Address offset: 0x00-0x1FCC */ + __IO uint32_t AXI_PERIPH_ID_4; /*!< AXI interconnect - peripheral ID4 register, Address offset: 0x1FD0 */ + uint32_t AXI_PERIPH_ID_5; /*!< Reserved, Address offset: 0x1FD4 */ + uint32_t AXI_PERIPH_ID_6; /*!< Reserved, Address offset: 0x1FD8 */ + uint32_t AXI_PERIPH_ID_7; /*!< Reserved, Address offset: 0x1FDC */ + __IO uint32_t AXI_PERIPH_ID_0; /*!< AXI interconnect - peripheral ID0 register, Address offset: 0x1FE0 */ + __IO uint32_t AXI_PERIPH_ID_1; /*!< AXI interconnect - peripheral ID1 register, Address offset: 0x1FE4 */ + __IO uint32_t AXI_PERIPH_ID_2; /*!< AXI interconnect - peripheral ID2 register, Address offset: 0x1FE8 */ + __IO uint32_t AXI_PERIPH_ID_3; /*!< AXI interconnect - peripheral ID3 register, Address offset: 0x1FEC */ + __IO uint32_t AXI_COMP_ID_0; /*!< AXI interconnect - component ID0 register, Address offset: 0x1FF0 */ + __IO uint32_t AXI_COMP_ID_1; /*!< AXI interconnect - component ID1 register, Address offset: 0x1FF4 */ + __IO uint32_t AXI_COMP_ID_2; /*!< AXI interconnect - component ID2 register, Address offset: 0x1FF8 */ + __IO uint32_t AXI_COMP_ID_3; /*!< AXI interconnect - component ID3 register, Address offset: 0x1FFC */ + uint32_t RESERVED1[2]; /*!< Reserved, Address offset: 0x2000-0x2004 */ + __IO uint32_t AXI_TARG1_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 1 bus matrix issuing functionality register, Address offset: 0x2008 */ + uint32_t RESERVED2[6]; /*!< Reserved, Address offset: 0x200C-0x2020 */ + __IO uint32_t AXI_TARG1_FN_MOD2; /*!< AXI interconnect - TARG 1 bus matrix functionality 2 register, Address offset: 0x2024 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x2028 */ + __IO uint32_t AXI_TARG1_FN_MOD_LB; /*!< AXI interconnect - TARG 1 long burst functionality modification register, Address offset: 0x202C */ + uint32_t RESERVED4[54]; /*!< Reserved, Address offset: 0x2030-0x2104 */ + __IO uint32_t AXI_TARG1_FN_MOD; /*!< AXI interconnect - TARG 1 issuing functionality modification register, Address offset: 0x2108 */ + uint32_t RESERVED5[959]; /*!< Reserved, Address offset: 0x210C-0x3004 */ + __IO uint32_t AXI_TARG2_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 2 bus matrix issuing functionality register, Address offset: 0x3008 */ + uint32_t RESERVED6[6]; /*!< Reserved, Address offset: 0x300C-0x3020 */ + __IO uint32_t AXI_TARG2_FN_MOD2; /*!< AXI interconnect - TARG 2 bus matrix functionality 2 register, Address offset: 0x3024 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x3028 */ + __IO uint32_t AXI_TARG2_FN_MOD_LB; /*!< AXI interconnect - TARG 2 long burst functionality modification register, Address offset: 0x302C */ + uint32_t RESERVED8[54]; /*!< Reserved, Address offset: 0x3030-0x3104 */ + __IO uint32_t AXI_TARG2_FN_MOD; /*!< AXI interconnect - TARG 2 issuing functionality modification register, Address offset: 0x3108 */ + uint32_t RESERVED9[959]; /*!< Reserved, Address offset: 0x310C-0x4004 */ + __IO uint32_t AXI_TARG3_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 3 bus matrix issuing functionality register, Address offset: 0x4008 */ + uint32_t RESERVED10[1023]; /*!< Reserved, Address offset: 0x400C-0x5004 */ + __IO uint32_t AXI_TARG4_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 4 bus matrix issuing functionality register, Address offset: 0x5008 */ + uint32_t RESERVED11[1023]; /*!< Reserved, Address offset: 0x500C-0x6004 */ + __IO uint32_t AXI_TARG5_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 5 bus matrix issuing functionality register, Address offset: 0x6008 */ + uint32_t RESERVED12[1023]; /*!< Reserved, Address offset: 0x600C-0x7004 */ + __IO uint32_t AXI_TARG6_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 6 bus matrix issuing functionality register, Address offset: 0x7008 */ + uint32_t RESERVED13[1023]; /*!< Reserved, Address offset: 0x700C-0x8004 */ + __IO uint32_t AXI_TARG7_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 7 bus matrix issuing functionality register, Address offset: 0x8008 */ + uint32_t RESERVED14[6]; /*!< Reserved, Address offset: 0x800C-0x8020 */ + __IO uint32_t AXI_TARG7_FN_MOD2; /*!< AXI interconnect - TARG 7 bus matrix functionality 2 register, Address offset: 0x8024 */ + uint32_t RESERVED15; /*!< Reserved, Address offset: 0x8028 */ + __IO uint32_t AXI_TARG7_FN_MOD_LB; /*!< AXI interconnect - TARG 7 long burst functionality modification register, Address offset: 0x802C */ + uint32_t RESERVED16[54]; /*!< Reserved, Address offset: 0x8030-0x8104 */ + __IO uint32_t AXI_TARG7_FN_MOD; /*!< AXI interconnect - TARG 7 issuing functionality modification register, Address offset: 0x8108 */ + uint32_t RESERVED17[959]; /*!< Reserved, Address offset: 0x810C-0x9004 */ + __IO uint32_t AXI_TARG8_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 8 bus matrix issuing functionality register, Address offset: 0x9008 */ + uint32_t RESERVED117[6]; /*!< Reserved, Address offset: 0x900C-0x9020 */ + __IO uint32_t AXI_TARG8_FN_MOD2; /*!< AXI interconnect - TARG 8 bus matrix functionality 2 register, Address offset: 0x9024 */ + uint32_t RESERVED118[56]; /*!< Reserved, Address offset: 0x9028-0x9104 */ + __IO uint32_t AXI_TARG8_FN_MOD; /*!< AXI interconnect - TARG 8 issuing functionality modification register, Address offset: 0x9108 */ + uint32_t RESERVED119[58310]; /*!< Reserved, Address offset: 0x910C-0x42020 */ + __IO uint32_t AXI_INI1_FN_MOD2; /*!< AXI interconnect - INI 1 functionality modification 2 register, Address offset: 0x42024 */ + __IO uint32_t AXI_INI1_FN_MOD_AHB; /*!< AXI interconnect - INI 1 AHB functionality modification register, Address offset: 0x42028 */ + uint32_t RESERVED18[53]; /*!< Reserved, Address offset: 0x4202C-0x420FC */ + __IO uint32_t AXI_INI1_READ_QOS; /*!< AXI interconnect - INI 1 read QoS register, Address offset: 0x42100 */ + __IO uint32_t AXI_INI1_WRITE_QOS; /*!< AXI interconnect - INI 1 write QoS register, Address offset: 0x42104 */ + __IO uint32_t AXI_INI1_FN_MOD; /*!< AXI interconnect - INI 1 issuing functionality modification register, Address offset: 0x42108 */ + uint32_t RESERVED19[1021]; /*!< Reserved, Address offset: 0x4210C-0x430FC */ + __IO uint32_t AXI_INI2_READ_QOS; /*!< AXI interconnect - INI 2 read QoS register, Address offset: 0x43100 */ + __IO uint32_t AXI_INI2_WRITE_QOS; /*!< AXI interconnect - INI 2 write QoS register, Address offset: 0x43104 */ + __IO uint32_t AXI_INI2_FN_MOD; /*!< AXI interconnect - INI 2 issuing functionality modification register, Address offset: 0x43108 */ + uint32_t RESERVED20[966]; /*!< Reserved, Address offset: 0x4310C-0x44020 */ + __IO uint32_t AXI_INI3_FN_MOD2; /*!< AXI interconnect - INI 3 functionality modification 2 register, Address offset: 0x44024 */ + __IO uint32_t AXI_INI3_FN_MOD_AHB; /*!< AXI interconnect - INI 3 AHB functionality modification register, Address offset: 0x44028 */ + uint32_t RESERVED21[53]; /*!< Reserved, Address offset: 0x4402C-0x440FC */ + __IO uint32_t AXI_INI3_READ_QOS; /*!< AXI interconnect - INI 3 read QoS register, Address offset: 0x44100 */ + __IO uint32_t AXI_INI3_WRITE_QOS; /*!< AXI interconnect - INI 3 write QoS register, Address offset: 0x44104 */ + __IO uint32_t AXI_INI3_FN_MOD; /*!< AXI interconnect - INI 3 issuing functionality modification register, Address offset: 0x44108 */ + uint32_t RESERVED22[1021]; /*!< Reserved, Address offset: 0x4410C-0x450FC */ + __IO uint32_t AXI_INI4_READ_QOS; /*!< AXI interconnect - INI 4 read QoS register, Address offset: 0x45100 */ + __IO uint32_t AXI_INI4_WRITE_QOS; /*!< AXI interconnect - INI 4 write QoS register, Address offset: 0x45104 */ + __IO uint32_t AXI_INI4_FN_MOD; /*!< AXI interconnect - INI 4 issuing functionality modification register, Address offset: 0x45108 */ + uint32_t RESERVED23[1021]; /*!< Reserved, Address offset: 0x4510C-0x460FC */ + __IO uint32_t AXI_INI5_READ_QOS; /*!< AXI interconnect - INI 5 read QoS register, Address offset: 0x46100 */ + __IO uint32_t AXI_INI5_WRITE_QOS; /*!< AXI interconnect - INI 5 write QoS register, Address offset: 0x46104 */ + __IO uint32_t AXI_INI5_FN_MOD; /*!< AXI interconnect - INI 5 issuing functionality modification register, Address offset: 0x46108 */ + uint32_t RESERVED24[1021]; /*!< Reserved, Address offset: 0x4610C-0x470FC */ + __IO uint32_t AXI_INI6_READ_QOS; /*!< AXI interconnect - INI 6 read QoS register, Address offset: 0x47100 */ + __IO uint32_t AXI_INI6_WRITE_QOS; /*!< AXI interconnect - INI 6 write QoS register, Address offset: 0x47104 */ + __IO uint32_t AXI_INI6_FN_MOD; /*!< AXI interconnect - INI 6 issuing functionality modification register, Address offset: 0x47108 */ + +} GPV_TypeDef; + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define D1_ITCMRAM_BASE (0x00000000UL) /*!< Base address of : 64KB RAM reserved for CPU execution/instruction accessible over ITCM */ +#define D1_ITCMICP_BASE (0x00100000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over ITCM */ +#define D1_DTCMRAM_BASE (0x20000000UL) /*!< Base address of : 128KB system data RAM accessible over DTCM */ +#define D1_AXIFLASH_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) embedded FLASH memory accessible over AXI */ +#define D1_AXIICP_BASE (0x1FF00000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over AXI */ +#define D1_AXISRAM1_BASE (0x24000000UL) /*!< Base address of : (up to 128KB) system data RAM1 accessible over over AXI */ +#define D1_AXISRAM2_BASE (0x24020000UL) /*!< Base address of : (up to 192KB) system data RAM2 accessible over over AXI to be shared with ITCM (64K granularity) */ +#define D1_AXISRAM_BASE D1_AXISRAM1_BASE /*!< Base address of : (up to 320KB) system data RAM1/2 accessible over over AXI */ + +#define D2_AHBSRAM1_BASE (0x30000000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */ +#define D2_AHBSRAM2_BASE (0x30004000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */ +#define D2_AHBSRAM_BASE D2_AHBSRAM1_BASE /*!< Base address of : (up to 32KB) system data RAM1/2 accessible over over AXI->AHB Bridge */ + +#define D3_BKPSRAM_BASE (0x38800000UL) /*!< Base address of : Backup SRAM(4 KB) over AXI->AHB Bridge */ +#define D3_SRAM_BASE (0x38000000UL) /*!< Base address of : Backup SRAM(16 KB) over AXI->AHB Bridge */ + +#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */ +#define OCTOSPI1_BASE (0x90000000UL) /*!< Base address of : OCTOSPI1 memories accessible over AXI */ +#define OCTOSPI2_BASE (0x70000000UL) /*!< Base address of : OCTOSPI2 memories accessible over AXI */ + +#define FLASH_BANK1_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) Flash Bank1 accessible over AXI */ +#define FLASH_END (0x080FFFFFUL) /*!< FLASH end address */ + + +/* Legacy define */ +#define FLASH_BASE FLASH_BANK1_BASE + +/*!< Device electronic signature memory map */ +#define UID_BASE (0x1FF1E800UL) /*!< Unique device ID register base address */ +#define FLASHSIZE_BASE (0x1FF1E880UL) /*!< FLASH Size register base address */ + + +/*!< Peripheral memory map */ +#define D2_APB1PERIPH_BASE PERIPH_BASE +#define D2_APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define D2_AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define D2_AHB2PERIPH_BASE (PERIPH_BASE + 0x08020000UL) + +#define D1_APB1PERIPH_BASE (PERIPH_BASE + 0x10000000UL) +#define D1_AHB1PERIPH_BASE (PERIPH_BASE + 0x12000000UL) + +#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL) +#define D3_AHB1PERIPH_BASE (PERIPH_BASE + 0x18020000UL) + +/*!< Legacy Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000UL) + + +/*!< D1_AHB1PERIPH peripherals */ + +#define MDMA_BASE (D1_AHB1PERIPH_BASE + 0x0000UL) +#define DMA2D_BASE (D1_AHB1PERIPH_BASE + 0x1000UL) +#define FLASH_R_BASE (D1_AHB1PERIPH_BASE + 0x2000UL) +#define FMC_R_BASE (D1_AHB1PERIPH_BASE + 0x4000UL) +#define OCTOSPI1_R_BASE (D1_AHB1PERIPH_BASE + 0x5000UL) +#define DLYB_OCTOSPI1_BASE (D1_AHB1PERIPH_BASE + 0x6000UL) +#define SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x7000UL) +#define DLYB_SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x8000UL) +#define RAMECC1_BASE (D1_AHB1PERIPH_BASE + 0x9000UL) +#define OCTOSPI2_R_BASE (D1_AHB1PERIPH_BASE + 0xA000UL) +#define DLYB_OCTOSPI2_BASE (D1_AHB1PERIPH_BASE + 0xB000UL) +#define OCTOSPIM_BASE (D1_AHB1PERIPH_BASE + 0xB400UL) + +#define OTFDEC1_BASE (D1_AHB1PERIPH_BASE + 0xB800UL) +#define OTFDEC1_REGION1_BASE (OTFDEC1_BASE + 0x20UL) +#define OTFDEC1_REGION2_BASE (OTFDEC1_BASE + 0x50UL) +#define OTFDEC1_REGION3_BASE (OTFDEC1_BASE + 0x80UL) +#define OTFDEC1_REGION4_BASE (OTFDEC1_BASE + 0xB0UL) +#define OTFDEC2_BASE (D1_AHB1PERIPH_BASE + 0xBC00UL) +#define OTFDEC2_REGION1_BASE (OTFDEC2_BASE + 0x20UL) +#define OTFDEC2_REGION2_BASE (OTFDEC2_BASE + 0x50UL) +#define OTFDEC2_REGION3_BASE (OTFDEC2_BASE + 0x80UL) +#define OTFDEC2_REGION4_BASE (OTFDEC2_BASE + 0xB0UL) + +/*!< D2_AHB1PERIPH peripherals */ + +#define DMA1_BASE (D2_AHB1PERIPH_BASE + 0x0000UL) +#define DMA2_BASE (D2_AHB1PERIPH_BASE + 0x0400UL) +#define DMAMUX1_BASE (D2_AHB1PERIPH_BASE + 0x0800UL) +#define ADC1_BASE (D2_AHB1PERIPH_BASE + 0x2000UL) +#define ADC2_BASE (D2_AHB1PERIPH_BASE + 0x2100UL) +#define ADC12_COMMON_BASE (D2_AHB1PERIPH_BASE + 0x2300UL) +#define ETH_BASE (D2_AHB1PERIPH_BASE + 0x8000UL) +#define ETH_MAC_BASE (ETH_BASE) + +/*!< USB registers base address */ +#define USB1_OTG_HS_PERIPH_BASE (0x40040000UL) +#define USB_OTG_GLOBAL_BASE (0x000UL) +#define USB_OTG_DEVICE_BASE (0x800UL) +#define USB_OTG_IN_ENDPOINT_BASE (0x900UL) +#define USB_OTG_OUT_ENDPOINT_BASE (0xB00UL) +#define USB_OTG_EP_REG_SIZE (0x20UL) +#define USB_OTG_HOST_BASE (0x400UL) +#define USB_OTG_HOST_PORT_BASE (0x440UL) +#define USB_OTG_HOST_CHANNEL_BASE (0x500UL) +#define USB_OTG_HOST_CHANNEL_SIZE (0x20UL) +#define USB_OTG_PCGCCTL_BASE (0xE00UL) +#define USB_OTG_FIFO_BASE (0x1000UL) +#define USB_OTG_FIFO_SIZE (0x1000UL) + +/*!< D2_AHB2PERIPH peripherals */ + +#define DCMI_BASE (D2_AHB2PERIPH_BASE + 0x0000UL) +#define PSSI_BASE (D2_AHB2PERIPH_BASE + 0x0400UL) +#define CRYP_BASE (D2_AHB2PERIPH_BASE + 0x1000UL) +#define HASH_BASE (D2_AHB2PERIPH_BASE + 0x1400UL) +#define HASH_DIGEST_BASE (D2_AHB2PERIPH_BASE + 0x1710UL) +#define RNG_BASE (D2_AHB2PERIPH_BASE + 0x1800UL) +#define SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2400UL) +#define DLYB_SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2800UL) +#define RAMECC2_BASE (D2_AHB2PERIPH_BASE + 0x3000UL) +#define FMAC_BASE (D2_AHB2PERIPH_BASE + 0x4000UL) +#define CORDIC_BASE (D2_AHB2PERIPH_BASE + 0x4400UL) + +/*!< D3_AHB1PERIPH peripherals */ +#define GPIOA_BASE (D3_AHB1PERIPH_BASE + 0x0000UL) +#define GPIOB_BASE (D3_AHB1PERIPH_BASE + 0x0400UL) +#define GPIOC_BASE (D3_AHB1PERIPH_BASE + 0x0800UL) +#define GPIOD_BASE (D3_AHB1PERIPH_BASE + 0x0C00UL) +#define GPIOE_BASE (D3_AHB1PERIPH_BASE + 0x1000UL) +#define GPIOF_BASE (D3_AHB1PERIPH_BASE + 0x1400UL) +#define GPIOG_BASE (D3_AHB1PERIPH_BASE + 0x1800UL) +#define GPIOH_BASE (D3_AHB1PERIPH_BASE + 0x1C00UL) +#define GPIOJ_BASE (D3_AHB1PERIPH_BASE + 0x2400UL) +#define GPIOK_BASE (D3_AHB1PERIPH_BASE + 0x2800UL) +#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL) +#define PWR_BASE (D3_AHB1PERIPH_BASE + 0x4800UL) +#define CRC_BASE (D3_AHB1PERIPH_BASE + 0x4C00UL) +#define BDMA_BASE (D3_AHB1PERIPH_BASE + 0x5400UL) +#define DMAMUX2_BASE (D3_AHB1PERIPH_BASE + 0x5800UL) +#define ADC3_BASE (D3_AHB1PERIPH_BASE + 0x6000UL) +#define ADC3_COMMON_BASE (D3_AHB1PERIPH_BASE + 0x6300UL) +#define HSEM_BASE (D3_AHB1PERIPH_BASE + 0x6400UL) +#define RAMECC3_BASE (D3_AHB1PERIPH_BASE + 0x7000UL) + +/*!< D1_APB1PERIPH peripherals */ +#define LTDC_BASE (D1_APB1PERIPH_BASE + 0x1000UL) +#define LTDC_Layer1_BASE (LTDC_BASE + 0x84UL) +#define LTDC_Layer2_BASE (LTDC_BASE + 0x104UL) +#define WWDG1_BASE (D1_APB1PERIPH_BASE + 0x3000UL) + +/*!< D2_APB1PERIPH peripherals */ +#define TIM2_BASE (D2_APB1PERIPH_BASE + 0x0000UL) +#define TIM3_BASE (D2_APB1PERIPH_BASE + 0x0400UL) +#define TIM4_BASE (D2_APB1PERIPH_BASE + 0x0800UL) +#define TIM5_BASE (D2_APB1PERIPH_BASE + 0x0C00UL) +#define TIM6_BASE (D2_APB1PERIPH_BASE + 0x1000UL) +#define TIM7_BASE (D2_APB1PERIPH_BASE + 0x1400UL) +#define TIM12_BASE (D2_APB1PERIPH_BASE + 0x1800UL) +#define TIM13_BASE (D2_APB1PERIPH_BASE + 0x1C00UL) +#define TIM14_BASE (D2_APB1PERIPH_BASE + 0x2000UL) +#define LPTIM1_BASE (D2_APB1PERIPH_BASE + 0x2400UL) + + +#define SPI2_BASE (D2_APB1PERIPH_BASE + 0x3800UL) +#define SPI3_BASE (D2_APB1PERIPH_BASE + 0x3C00UL) +#define SPDIFRX_BASE (D2_APB1PERIPH_BASE + 0x4000UL) +#define USART2_BASE (D2_APB1PERIPH_BASE + 0x4400UL) +#define USART3_BASE (D2_APB1PERIPH_BASE + 0x4800UL) +#define UART4_BASE (D2_APB1PERIPH_BASE + 0x4C00UL) +#define UART5_BASE (D2_APB1PERIPH_BASE + 0x5000UL) +#define I2C1_BASE (D2_APB1PERIPH_BASE + 0x5400UL) +#define I2C2_BASE (D2_APB1PERIPH_BASE + 0x5800UL) +#define I2C3_BASE (D2_APB1PERIPH_BASE + 0x5C00UL) +#define I2C5_BASE (D2_APB1PERIPH_BASE + 0x6400UL) +#define CEC_BASE (D2_APB1PERIPH_BASE + 0x6C00UL) +#define DAC1_BASE (D2_APB1PERIPH_BASE + 0x7400UL) +#define UART7_BASE (D2_APB1PERIPH_BASE + 0x7800UL) +#define UART8_BASE (D2_APB1PERIPH_BASE + 0x7C00UL) +#define CRS_BASE (D2_APB1PERIPH_BASE + 0x8400UL) +#define SWPMI1_BASE (D2_APB1PERIPH_BASE + 0x8800UL) +#define OPAMP_BASE (D2_APB1PERIPH_BASE + 0x9000UL) +#define OPAMP1_BASE (D2_APB1PERIPH_BASE + 0x9000UL) +#define OPAMP2_BASE (D2_APB1PERIPH_BASE + 0x9010UL) +#define MDIOS_BASE (D2_APB1PERIPH_BASE + 0x9400UL) +#define FDCAN1_BASE (D2_APB1PERIPH_BASE + 0xA000UL) +#define FDCAN2_BASE (D2_APB1PERIPH_BASE + 0xA400UL) +#define FDCAN_CCU_BASE (D2_APB1PERIPH_BASE + 0xA800UL) +#define SRAMCAN_BASE (D2_APB1PERIPH_BASE + 0xAC00UL) +#define FDCAN3_BASE (D2_APB1PERIPH_BASE + 0xD400UL) +#define TIM23_BASE (D2_APB1PERIPH_BASE + 0xE000UL) +#define TIM24_BASE (D2_APB1PERIPH_BASE + 0xE400UL) + +/*!< D2_APB2PERIPH peripherals */ + +#define TIM1_BASE (D2_APB2PERIPH_BASE + 0x0000UL) +#define TIM8_BASE (D2_APB2PERIPH_BASE + 0x0400UL) +#define USART1_BASE (D2_APB2PERIPH_BASE + 0x1000UL) +#define USART6_BASE (D2_APB2PERIPH_BASE + 0x1400UL) +#define UART9_BASE (D2_APB2PERIPH_BASE + 0x1800UL) +#define USART10_BASE (D2_APB2PERIPH_BASE + 0x1C00UL) +#define SPI1_BASE (D2_APB2PERIPH_BASE + 0x3000UL) +#define SPI4_BASE (D2_APB2PERIPH_BASE + 0x3400UL) +#define TIM15_BASE (D2_APB2PERIPH_BASE + 0x4000UL) +#define TIM16_BASE (D2_APB2PERIPH_BASE + 0x4400UL) +#define TIM17_BASE (D2_APB2PERIPH_BASE + 0x4800UL) +#define SPI5_BASE (D2_APB2PERIPH_BASE + 0x5000UL) +#define SAI1_BASE (D2_APB2PERIPH_BASE + 0x5800UL) +#define SAI1_Block_A_BASE (SAI1_BASE + 0x004UL) +#define SAI1_Block_B_BASE (SAI1_BASE + 0x024UL) +#define DFSDM1_BASE (D2_APB2PERIPH_BASE + 0x7800UL) +#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x00UL) +#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x20UL) +#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x40UL) +#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x60UL) +#define DFSDM1_Channel4_BASE (DFSDM1_BASE + 0x80UL) +#define DFSDM1_Channel5_BASE (DFSDM1_BASE + 0xA0UL) +#define DFSDM1_Channel6_BASE (DFSDM1_BASE + 0xC0UL) +#define DFSDM1_Channel7_BASE (DFSDM1_BASE + 0xE0UL) +#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x100UL) +#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x180UL) +#define DFSDM1_Filter2_BASE (DFSDM1_BASE + 0x200UL) +#define DFSDM1_Filter3_BASE (DFSDM1_BASE + 0x280UL) + + +/*!< D3_APB1PERIPH peripherals */ +#define EXTI_BASE (D3_APB1PERIPH_BASE + 0x0000UL) +#define EXTI_D1_BASE (EXTI_BASE + 0x0080UL) +#define EXTI_D2_BASE (EXTI_BASE + 0x00C0UL) +#define SYSCFG_BASE (D3_APB1PERIPH_BASE + 0x0400UL) +#define LPUART1_BASE (D3_APB1PERIPH_BASE + 0x0C00UL) +#define SPI6_BASE (D3_APB1PERIPH_BASE + 0x1400UL) +#define I2C4_BASE (D3_APB1PERIPH_BASE + 0x1C00UL) +#define LPTIM2_BASE (D3_APB1PERIPH_BASE + 0x2400UL) +#define LPTIM3_BASE (D3_APB1PERIPH_BASE + 0x2800UL) +#define LPTIM4_BASE (D3_APB1PERIPH_BASE + 0x2C00UL) +#define LPTIM5_BASE (D3_APB1PERIPH_BASE + 0x3000UL) +#define COMP12_BASE (D3_APB1PERIPH_BASE + 0x3800UL) +#define COMP1_BASE (COMP12_BASE + 0x0CUL) +#define COMP2_BASE (COMP12_BASE + 0x10UL) +#define VREFBUF_BASE (D3_APB1PERIPH_BASE + 0x3C00UL) +#define RTC_BASE (D3_APB1PERIPH_BASE + 0x4000UL) +#define IWDG1_BASE (D3_APB1PERIPH_BASE + 0x4800UL) + + +#define SAI4_BASE (D3_APB1PERIPH_BASE + 0x5400UL) +#define SAI4_Block_A_BASE (SAI4_BASE + 0x004UL) +#define SAI4_Block_B_BASE (SAI4_BASE + 0x024UL) + +#define DTS_BASE (D3_APB1PERIPH_BASE + 0x6800UL) + + + +#define BDMA_Channel0_BASE (BDMA_BASE + 0x0008UL) +#define BDMA_Channel1_BASE (BDMA_BASE + 0x001CUL) +#define BDMA_Channel2_BASE (BDMA_BASE + 0x0030UL) +#define BDMA_Channel3_BASE (BDMA_BASE + 0x0044UL) +#define BDMA_Channel4_BASE (BDMA_BASE + 0x0058UL) +#define BDMA_Channel5_BASE (BDMA_BASE + 0x006CUL) +#define BDMA_Channel6_BASE (BDMA_BASE + 0x0080UL) +#define BDMA_Channel7_BASE (BDMA_BASE + 0x0094UL) + +#define DMAMUX2_Channel0_BASE (DMAMUX2_BASE) +#define DMAMUX2_Channel1_BASE (DMAMUX2_BASE + 0x0004UL) +#define DMAMUX2_Channel2_BASE (DMAMUX2_BASE + 0x0008UL) +#define DMAMUX2_Channel3_BASE (DMAMUX2_BASE + 0x000CUL) +#define DMAMUX2_Channel4_BASE (DMAMUX2_BASE + 0x0010UL) +#define DMAMUX2_Channel5_BASE (DMAMUX2_BASE + 0x0014UL) +#define DMAMUX2_Channel6_BASE (DMAMUX2_BASE + 0x0018UL) +#define DMAMUX2_Channel7_BASE (DMAMUX2_BASE + 0x001CUL) + +#define DMAMUX2_RequestGenerator0_BASE (DMAMUX2_BASE + 0x0100UL) +#define DMAMUX2_RequestGenerator1_BASE (DMAMUX2_BASE + 0x0104UL) +#define DMAMUX2_RequestGenerator2_BASE (DMAMUX2_BASE + 0x0108UL) +#define DMAMUX2_RequestGenerator3_BASE (DMAMUX2_BASE + 0x010CUL) +#define DMAMUX2_RequestGenerator4_BASE (DMAMUX2_BASE + 0x0110UL) +#define DMAMUX2_RequestGenerator5_BASE (DMAMUX2_BASE + 0x0114UL) +#define DMAMUX2_RequestGenerator6_BASE (DMAMUX2_BASE + 0x0118UL) +#define DMAMUX2_RequestGenerator7_BASE (DMAMUX2_BASE + 0x011CUL) + +#define DMAMUX2_ChannelStatus_BASE (DMAMUX2_BASE + 0x0080UL) +#define DMAMUX2_RequestGenStatus_BASE (DMAMUX2_BASE + 0x0140UL) + +#define DMA1_Stream0_BASE (DMA1_BASE + 0x010UL) +#define DMA1_Stream1_BASE (DMA1_BASE + 0x028UL) +#define DMA1_Stream2_BASE (DMA1_BASE + 0x040UL) +#define DMA1_Stream3_BASE (DMA1_BASE + 0x058UL) +#define DMA1_Stream4_BASE (DMA1_BASE + 0x070UL) +#define DMA1_Stream5_BASE (DMA1_BASE + 0x088UL) +#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0UL) +#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8UL) + +#define DMA2_Stream0_BASE (DMA2_BASE + 0x010UL) +#define DMA2_Stream1_BASE (DMA2_BASE + 0x028UL) +#define DMA2_Stream2_BASE (DMA2_BASE + 0x040UL) +#define DMA2_Stream3_BASE (DMA2_BASE + 0x058UL) +#define DMA2_Stream4_BASE (DMA2_BASE + 0x070UL) +#define DMA2_Stream5_BASE (DMA2_BASE + 0x088UL) +#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0UL) +#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8UL) + +#define DMAMUX1_Channel0_BASE (DMAMUX1_BASE) +#define DMAMUX1_Channel1_BASE (DMAMUX1_BASE + 0x0004UL) +#define DMAMUX1_Channel2_BASE (DMAMUX1_BASE + 0x0008UL) +#define DMAMUX1_Channel3_BASE (DMAMUX1_BASE + 0x000CUL) +#define DMAMUX1_Channel4_BASE (DMAMUX1_BASE + 0x0010UL) +#define DMAMUX1_Channel5_BASE (DMAMUX1_BASE + 0x0014UL) +#define DMAMUX1_Channel6_BASE (DMAMUX1_BASE + 0x0018UL) +#define DMAMUX1_Channel7_BASE (DMAMUX1_BASE + 0x001CUL) +#define DMAMUX1_Channel8_BASE (DMAMUX1_BASE + 0x0020UL) +#define DMAMUX1_Channel9_BASE (DMAMUX1_BASE + 0x0024UL) +#define DMAMUX1_Channel10_BASE (DMAMUX1_BASE + 0x0028UL) +#define DMAMUX1_Channel11_BASE (DMAMUX1_BASE + 0x002CUL) +#define DMAMUX1_Channel12_BASE (DMAMUX1_BASE + 0x0030UL) +#define DMAMUX1_Channel13_BASE (DMAMUX1_BASE + 0x0034UL) +#define DMAMUX1_Channel14_BASE (DMAMUX1_BASE + 0x0038UL) +#define DMAMUX1_Channel15_BASE (DMAMUX1_BASE + 0x003CUL) + +#define DMAMUX1_RequestGenerator0_BASE (DMAMUX1_BASE + 0x0100UL) +#define DMAMUX1_RequestGenerator1_BASE (DMAMUX1_BASE + 0x0104UL) +#define DMAMUX1_RequestGenerator2_BASE (DMAMUX1_BASE + 0x0108UL) +#define DMAMUX1_RequestGenerator3_BASE (DMAMUX1_BASE + 0x010CUL) +#define DMAMUX1_RequestGenerator4_BASE (DMAMUX1_BASE + 0x0110UL) +#define DMAMUX1_RequestGenerator5_BASE (DMAMUX1_BASE + 0x0114UL) +#define DMAMUX1_RequestGenerator6_BASE (DMAMUX1_BASE + 0x0118UL) +#define DMAMUX1_RequestGenerator7_BASE (DMAMUX1_BASE + 0x011CUL) + +#define DMAMUX1_ChannelStatus_BASE (DMAMUX1_BASE + 0x0080UL) +#define DMAMUX1_RequestGenStatus_BASE (DMAMUX1_BASE + 0x0140UL) + +/*!< FMC Banks registers base address */ +#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000UL) +#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104UL) +#define FMC_Bank2_R_BASE (FMC_R_BASE + 0x0060UL) +#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080UL) +#define FMC_Bank5_6_R_BASE (FMC_R_BASE + 0x0140UL) + +/* Debug MCU registers base address */ +#define DBGMCU_BASE (0x5C001000UL) + +#define MDMA_Channel0_BASE (MDMA_BASE + 0x00000040UL) +#define MDMA_Channel1_BASE (MDMA_BASE + 0x00000080UL) +#define MDMA_Channel2_BASE (MDMA_BASE + 0x000000C0UL) +#define MDMA_Channel3_BASE (MDMA_BASE + 0x00000100UL) +#define MDMA_Channel4_BASE (MDMA_BASE + 0x00000140UL) +#define MDMA_Channel5_BASE (MDMA_BASE + 0x00000180UL) +#define MDMA_Channel6_BASE (MDMA_BASE + 0x000001C0UL) +#define MDMA_Channel7_BASE (MDMA_BASE + 0x00000200UL) +#define MDMA_Channel8_BASE (MDMA_BASE + 0x00000240UL) +#define MDMA_Channel9_BASE (MDMA_BASE + 0x00000280UL) +#define MDMA_Channel10_BASE (MDMA_BASE + 0x000002C0UL) +#define MDMA_Channel11_BASE (MDMA_BASE + 0x00000300UL) +#define MDMA_Channel12_BASE (MDMA_BASE + 0x00000340UL) +#define MDMA_Channel13_BASE (MDMA_BASE + 0x00000380UL) +#define MDMA_Channel14_BASE (MDMA_BASE + 0x000003C0UL) +#define MDMA_Channel15_BASE (MDMA_BASE + 0x00000400UL) + +#define RAMECC1_Monitor1_BASE (RAMECC1_BASE + 0x20UL) +#define RAMECC1_Monitor2_BASE (RAMECC1_BASE + 0x40UL) +#define RAMECC1_Monitor3_BASE (RAMECC1_BASE + 0x60UL) +#define RAMECC1_Monitor4_BASE (RAMECC1_BASE + 0x80UL) +#define RAMECC1_Monitor5_BASE (RAMECC1_BASE + 0xA0UL) +#define RAMECC1_Monitor6_BASE (RAMECC1_BASE + 0xC0UL) + +#define RAMECC2_Monitor1_BASE (RAMECC2_BASE + 0x20UL) +#define RAMECC2_Monitor2_BASE (RAMECC2_BASE + 0x40UL) +#define RAMECC2_Monitor3_BASE (RAMECC2_BASE + 0x60UL) + +#define RAMECC3_Monitor1_BASE (RAMECC3_BASE + 0x20UL) +#define RAMECC3_Monitor2_BASE (RAMECC3_BASE + 0x40UL) + + + +#define GPV_BASE (PERIPH_BASE + 0x11000000UL) /*!< GPV_BASE (PERIPH_BASE + 0x11000000UL) */ + +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define TIM13 ((TIM_TypeDef *) TIM13_BASE) +#define TIM14 ((TIM_TypeDef *) TIM14_BASE) +#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG1 ((WWDG_TypeDef *) WWDG1_BASE) + + +#define IWDG1 ((IWDG_TypeDef *) IWDG1_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define SPI4 ((SPI_TypeDef *) SPI4_BASE) +#define SPI5 ((SPI_TypeDef *) SPI5_BASE) +#define SPI6 ((SPI_TypeDef *) SPI6_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define USART6 ((USART_TypeDef *) USART6_BASE) +#define USART10 ((USART_TypeDef *) USART10_BASE) +#define UART7 ((USART_TypeDef *) UART7_BASE) +#define UART8 ((USART_TypeDef *) UART8_BASE) +#define UART9 ((USART_TypeDef *) UART9_BASE) +#define CRS ((CRS_TypeDef *) CRS_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define I2C4 ((I2C_TypeDef *) I2C4_BASE) +#define I2C5 ((I2C_TypeDef *) I2C5_BASE) +#define FDCAN1 ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) +#define FDCAN2 ((FDCAN_GlobalTypeDef *) FDCAN2_BASE) +#define FDCAN_CCU ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE) +#define FDCAN3 ((FDCAN_GlobalTypeDef *) FDCAN3_BASE) +#define TIM23 ((TIM_TypeDef *) TIM23_BASE) +#define TIM24 ((TIM_TypeDef *) TIM24_BASE) +#define CEC ((CEC_TypeDef *) CEC_BASE) +#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC1 ((DAC_TypeDef *) DAC1_BASE) +#define LPUART1 ((USART_TypeDef *) LPUART1_BASE) +#define SWPMI1 ((SWPMI_TypeDef *) SWPMI1_BASE) +#define LPTIM2 ((LPTIM_TypeDef *) LPTIM2_BASE) +#define LPTIM3 ((LPTIM_TypeDef *) LPTIM3_BASE) +#define DTS ((DTS_TypeDef *) DTS_BASE) +#define LPTIM4 ((LPTIM_TypeDef *) LPTIM4_BASE) +#define LPTIM5 ((LPTIM_TypeDef *) LPTIM5_BASE) + +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define COMP12 ((COMPOPT_TypeDef *) COMP12_BASE) +#define COMP1 ((COMP_TypeDef *) COMP1_BASE) +#define COMP2 ((COMP_TypeDef *) COMP2_BASE) +#define COMP12_COMMON ((COMP_Common_TypeDef *) COMP2_BASE) +#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE) +#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE) +#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE) + + +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define EXTI_D1 ((EXTI_Core_TypeDef *) EXTI_D1_BASE) +#define EXTI_D2 ((EXTI_Core_TypeDef *) EXTI_D2_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define TIM12 ((TIM_TypeDef *) TIM12_BASE) +#define TIM15 ((TIM_TypeDef *) TIM15_BASE) +#define TIM16 ((TIM_TypeDef *) TIM16_BASE) +#define TIM17 ((TIM_TypeDef *) TIM17_BASE) +#define SAI1 ((SAI_TypeDef *) SAI1_BASE) +#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) +#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) +#define SAI4 ((SAI_TypeDef *) SAI4_BASE) +#define SAI4_Block_A ((SAI_Block_TypeDef *)SAI4_Block_A_BASE) +#define SAI4_Block_B ((SAI_Block_TypeDef *)SAI4_Block_B_BASE) + +#define SPDIFRX ((SPDIFRX_TypeDef *) SPDIFRX_BASE) +#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE) +#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE) +#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE) +#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE) +#define DFSDM1_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel4_BASE) +#define DFSDM1_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel5_BASE) +#define DFSDM1_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel6_BASE) +#define DFSDM1_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel7_BASE) +#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE) +#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE) +#define DFSDM1_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter2_BASE) +#define DFSDM1_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter3_BASE) +#define DMA2D ((DMA2D_TypeDef *) DMA2D_BASE) +#define DCMI ((DCMI_TypeDef *) DCMI_BASE) +#define PSSI ((PSSI_TypeDef *) PSSI_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) + +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE) +#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE) + +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define ADC3_COMMON ((ADC_Common_TypeDef *) ADC3_COMMON_BASE) +#define ADC12_COMMON ((ADC_Common_TypeDef *) ADC12_COMMON_BASE) + +#define CRYP ((CRYP_TypeDef *) CRYP_BASE) +#define HASH ((HASH_TypeDef *) HASH_BASE) +#define HASH_DIGEST ((HASH_DIGEST_TypeDef *) HASH_DIGEST_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) +#define SDMMC2 ((SDMMC_TypeDef *) SDMMC2_BASE) +#define DLYB_SDMMC2 ((DLYB_TypeDef *) DLYB_SDMMC2_BASE) +#define FMAC ((FMAC_TypeDef *) FMAC_BASE) +#define CORDIC ((CORDIC_TypeDef *) CORDIC_BASE) + +#define BDMA ((BDMA_TypeDef *) BDMA_BASE) +#define BDMA_Channel0 ((BDMA_Channel_TypeDef *) BDMA_Channel0_BASE) +#define BDMA_Channel1 ((BDMA_Channel_TypeDef *) BDMA_Channel1_BASE) +#define BDMA_Channel2 ((BDMA_Channel_TypeDef *) BDMA_Channel2_BASE) +#define BDMA_Channel3 ((BDMA_Channel_TypeDef *) BDMA_Channel3_BASE) +#define BDMA_Channel4 ((BDMA_Channel_TypeDef *) BDMA_Channel4_BASE) +#define BDMA_Channel5 ((BDMA_Channel_TypeDef *) BDMA_Channel5_BASE) +#define BDMA_Channel6 ((BDMA_Channel_TypeDef *) BDMA_Channel6_BASE) +#define BDMA_Channel7 ((BDMA_Channel_TypeDef *) BDMA_Channel7_BASE) + +#define RAMECC1 ((RAMECC_TypeDef *)RAMECC1_BASE) +#define RAMECC1_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor1_BASE) +#define RAMECC1_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor2_BASE) +#define RAMECC1_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor3_BASE) +#define RAMECC1_Monitor4 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor4_BASE) +#define RAMECC1_Monitor5 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor5_BASE) +#define RAMECC1_Monitor6 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor6_BASE) + +#define RAMECC2 ((RAMECC_TypeDef *)RAMECC2_BASE) +#define RAMECC2_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor1_BASE) +#define RAMECC2_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor2_BASE) +#define RAMECC2_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor3_BASE) + +#define RAMECC3 ((RAMECC_TypeDef *)RAMECC3_BASE) +#define RAMECC3_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor1_BASE) +#define RAMECC3_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor2_BASE) + +#define DMAMUX2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_BASE) +#define DMAMUX2_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel0_BASE) +#define DMAMUX2_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel1_BASE) +#define DMAMUX2_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel2_BASE) +#define DMAMUX2_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel3_BASE) +#define DMAMUX2_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel4_BASE) +#define DMAMUX2_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel5_BASE) +#define DMAMUX2_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel6_BASE) +#define DMAMUX2_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel7_BASE) + + +#define DMAMUX2_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator0_BASE) +#define DMAMUX2_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator1_BASE) +#define DMAMUX2_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator2_BASE) +#define DMAMUX2_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator3_BASE) +#define DMAMUX2_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator4_BASE) +#define DMAMUX2_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator5_BASE) +#define DMAMUX2_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator6_BASE) +#define DMAMUX2_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator7_BASE) + +#define DMAMUX2_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX2_ChannelStatus_BASE) +#define DMAMUX2_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX2_RequestGenStatus_BASE) + +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define DMA2_Stream0 ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE) +#define DMA2_Stream1 ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE) +#define DMA2_Stream2 ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE) +#define DMA2_Stream3 ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE) +#define DMA2_Stream4 ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE) +#define DMA2_Stream5 ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE) +#define DMA2_Stream6 ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE) +#define DMA2_Stream7 ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE) + +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA1_Stream0 ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE) +#define DMA1_Stream1 ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE) +#define DMA1_Stream2 ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE) +#define DMA1_Stream3 ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE) +#define DMA1_Stream4 ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE) +#define DMA1_Stream5 ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE) +#define DMA1_Stream6 ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE) +#define DMA1_Stream7 ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE) + + +#define DMAMUX1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_BASE) +#define DMAMUX1_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel0_BASE) +#define DMAMUX1_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel1_BASE) +#define DMAMUX1_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel2_BASE) +#define DMAMUX1_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel3_BASE) +#define DMAMUX1_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel4_BASE) +#define DMAMUX1_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel5_BASE) +#define DMAMUX1_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel6_BASE) +#define DMAMUX1_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel7_BASE) +#define DMAMUX1_Channel8 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel8_BASE) +#define DMAMUX1_Channel9 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel9_BASE) +#define DMAMUX1_Channel10 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel10_BASE) +#define DMAMUX1_Channel11 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel11_BASE) +#define DMAMUX1_Channel12 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel12_BASE) +#define DMAMUX1_Channel13 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel13_BASE) +#define DMAMUX1_Channel14 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel14_BASE) +#define DMAMUX1_Channel15 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel15_BASE) + +#define DMAMUX1_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator0_BASE) +#define DMAMUX1_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator1_BASE) +#define DMAMUX1_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator2_BASE) +#define DMAMUX1_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator3_BASE) +#define DMAMUX1_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator4_BASE) +#define DMAMUX1_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator5_BASE) +#define DMAMUX1_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator6_BASE) +#define DMAMUX1_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator7_BASE) + +#define DMAMUX1_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX1_ChannelStatus_BASE) +#define DMAMUX1_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX1_RequestGenStatus_BASE) + + +#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE) +#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE) +#define FMC_Bank2_R ((FMC_Bank2_TypeDef *) FMC_Bank2_R_BASE) +#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE) +#define FMC_Bank5_6_R ((FMC_Bank5_6_TypeDef *) FMC_Bank5_6_R_BASE) + +#define OCTOSPI1 ((OCTOSPI_TypeDef *) OCTOSPI1_R_BASE) +#define DLYB_OCTOSPI1 ((DLYB_TypeDef *) DLYB_OCTOSPI1_BASE) +#define OCTOSPI2 ((OCTOSPI_TypeDef *) OCTOSPI2_R_BASE) +#define DLYB_OCTOSPI2 ((DLYB_TypeDef *) DLYB_OCTOSPI2_BASE) +#define OCTOSPIM ((OCTOSPIM_TypeDef *) OCTOSPIM_BASE) + +#define OTFDEC1 ((OTFDEC_TypeDef *) OTFDEC1_BASE) +#define OTFDEC1_REGION1 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION1_BASE) +#define OTFDEC1_REGION2 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION2_BASE) +#define OTFDEC1_REGION3 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION3_BASE) +#define OTFDEC1_REGION4 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION4_BASE) + +#define OTFDEC2 ((OTFDEC_TypeDef *) OTFDEC2_BASE) +#define OTFDEC2_REGION1 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION1_BASE) +#define OTFDEC2_REGION2 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION2_BASE) +#define OTFDEC2_REGION3 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION3_BASE) +#define OTFDEC2_REGION4 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION4_BASE) + +#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE) +#define DLYB_SDMMC1 ((DLYB_TypeDef *) DLYB_SDMMC1_BASE) + +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) + +#define HSEM ((HSEM_TypeDef *) HSEM_BASE) +#define HSEM_COMMON ((HSEM_Common_TypeDef *) (HSEM_BASE + 0x100UL)) + +#define LTDC ((LTDC_TypeDef *)LTDC_BASE) +#define LTDC_Layer1 ((LTDC_Layer_TypeDef *)LTDC_Layer1_BASE) +#define LTDC_Layer2 ((LTDC_Layer_TypeDef *)LTDC_Layer2_BASE) + +#define MDIOS ((MDIOS_TypeDef *) MDIOS_BASE) + +#define ETH ((ETH_TypeDef *)ETH_BASE) +#define MDMA ((MDMA_TypeDef *)MDMA_BASE) +#define MDMA_Channel0 ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE) +#define MDMA_Channel1 ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE) +#define MDMA_Channel2 ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE) +#define MDMA_Channel3 ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE) +#define MDMA_Channel4 ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE) +#define MDMA_Channel5 ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE) +#define MDMA_Channel6 ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE) +#define MDMA_Channel7 ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE) +#define MDMA_Channel8 ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE) +#define MDMA_Channel9 ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE) +#define MDMA_Channel10 ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE) +#define MDMA_Channel11 ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE) +#define MDMA_Channel12 ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE) +#define MDMA_Channel13 ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE) +#define MDMA_Channel14 ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE) +#define MDMA_Channel15 ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE) + + +#define USB1_OTG_HS ((USB_OTG_GlobalTypeDef *) USB1_OTG_HS_PERIPH_BASE) + +/* Legacy defines */ +#define USB_OTG_HS USB1_OTG_HS +#define USB_OTG_HS_PERIPH_BASE USB1_OTG_HS_PERIPH_BASE + +#define GPV ((GPV_TypeDef *) GPV_BASE) + +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + + /** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ +/******************************* ADC VERSION ********************************/ +#define ADC_VER_V5_V90 +/******************** Bit definition for ADC_ISR register ********************/ +#define ADC_ISR_ADRDY_Pos (0U) +#define ADC_ISR_ADRDY_Msk (0x1UL << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */ +#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC Ready (ADRDY) flag */ +#define ADC_ISR_EOSMP_Pos (1U) +#define ADC_ISR_EOSMP_Msk (0x1UL << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */ +#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC End of Sampling flag */ +#define ADC_ISR_EOC_Pos (2U) +#define ADC_ISR_EOC_Msk (0x1UL << ADC_ISR_EOC_Pos) /*!< 0x00000004 */ +#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC End of Regular Conversion flag */ +#define ADC_ISR_EOS_Pos (3U) +#define ADC_ISR_EOS_Msk (0x1UL << ADC_ISR_EOS_Pos) /*!< 0x00000008 */ +#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC End of Regular sequence of Conversions flag */ +#define ADC_ISR_OVR_Pos (4U) +#define ADC_ISR_OVR_Msk (0x1UL << ADC_ISR_OVR_Pos) /*!< 0x00000010 */ +#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC overrun flag */ +#define ADC_ISR_JEOC_Pos (5U) +#define ADC_ISR_JEOC_Msk (0x1UL << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */ +#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC End of Injected Conversion flag */ +#define ADC_ISR_JEOS_Pos (6U) +#define ADC_ISR_JEOS_Msk (0x1UL << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */ +#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC End of Injected sequence of Conversions flag */ +#define ADC_ISR_AWD1_Pos (7U) +#define ADC_ISR_AWD1_Msk (0x1UL << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */ +#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC Analog watchdog 1 flag */ +#define ADC_ISR_AWD2_Pos (8U) +#define ADC_ISR_AWD2_Msk (0x1UL << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */ +#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC Analog watchdog 2 flag */ +#define ADC_ISR_AWD3_Pos (9U) +#define ADC_ISR_AWD3_Msk (0x1UL << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */ +#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC Analog watchdog 3 flag */ +#define ADC_ISR_JQOVF_Pos (10U) +#define ADC_ISR_JQOVF_Msk (0x1UL << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */ +#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC Injected Context Queue Overflow flag */ +#define ADC_ISR_LDORDY_Pos (12U) +#define ADC_ISR_LDORDY_Msk (0x1UL << ADC_ISR_LDORDY_Pos) /*!< 0x00001000 */ +#define ADC_ISR_LDORDY ADC_ISR_LDORDY_Msk /*!< ADC LDO Ready (LDORDY) flag */ + +/******************** Bit definition for ADC_IER register ********************/ +#define ADC_IER_ADRDYIE_Pos (0U) +#define ADC_IER_ADRDYIE_Msk (0x1UL << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */ +#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC Ready (ADRDY) interrupt source */ +#define ADC_IER_EOSMPIE_Pos (1U) +#define ADC_IER_EOSMPIE_Msk (0x1UL << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */ +#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC End of Sampling interrupt source */ +#define ADC_IER_EOCIE_Pos (2U) +#define ADC_IER_EOCIE_Msk (0x1UL << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */ +#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC End of Regular Conversion interrupt source */ +#define ADC_IER_EOSIE_Pos (3U) +#define ADC_IER_EOSIE_Msk (0x1UL << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */ +#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC End of Regular sequence of Conversions interrupt source */ +#define ADC_IER_OVRIE_Pos (4U) +#define ADC_IER_OVRIE_Msk (0x1UL << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */ +#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC overrun interrupt source */ +#define ADC_IER_JEOCIE_Pos (5U) +#define ADC_IER_JEOCIE_Msk (0x1UL << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */ +#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC End of Injected Conversion interrupt source */ +#define ADC_IER_JEOSIE_Pos (6U) +#define ADC_IER_JEOSIE_Msk (0x1UL << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */ +#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC End of Injected sequence of Conversions interrupt source */ +#define ADC_IER_AWD1IE_Pos (7U) +#define ADC_IER_AWD1IE_Msk (0x1UL << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */ +#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC Analog watchdog 1 interrupt source */ +#define ADC_IER_AWD2IE_Pos (8U) +#define ADC_IER_AWD2IE_Msk (0x1UL << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */ +#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC Analog watchdog 2 interrupt source */ +#define ADC_IER_AWD3IE_Pos (9U) +#define ADC_IER_AWD3IE_Msk (0x1UL << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */ +#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC Analog watchdog 3 interrupt source */ +#define ADC_IER_JQOVFIE_Pos (10U) +#define ADC_IER_JQOVFIE_Msk (0x1UL << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */ +#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC Injected Context Queue Overflow interrupt source */ + +/******************** Bit definition for ADC_CR register ********************/ +#define ADC_CR_ADEN_Pos (0U) +#define ADC_CR_ADEN_Msk (0x1UL << ADC_CR_ADEN_Pos) /*!< 0x00000001 */ +#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC Enable control */ +#define ADC_CR_ADDIS_Pos (1U) +#define ADC_CR_ADDIS_Msk (0x1UL << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */ +#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC Disable command */ +#define ADC_CR_ADSTART_Pos (2U) +#define ADC_CR_ADSTART_Msk (0x1UL << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */ +#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC Start of Regular conversion */ +#define ADC_CR_JADSTART_Pos (3U) +#define ADC_CR_JADSTART_Msk (0x1UL << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */ +#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC Start of injected conversion */ +#define ADC_CR_ADSTP_Pos (4U) +#define ADC_CR_ADSTP_Msk (0x1UL << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */ +#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC Stop of Regular conversion */ +#define ADC_CR_JADSTP_Pos (5U) +#define ADC_CR_JADSTP_Msk (0x1UL << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */ +#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC Stop of injected conversion */ +#define ADC_CR_BOOST_Pos (8U) +#define ADC_CR_BOOST_Msk (0x3UL << ADC_CR_BOOST_Pos) /*!< 0x00000300 */ +#define ADC_CR_BOOST ADC_CR_BOOST_Msk /*!< ADC Boost Mode configuration */ +#define ADC_CR_BOOST_0 (0x1UL << ADC_CR_BOOST_Pos) /*!< 0x00000100 */ +#define ADC_CR_BOOST_1 (0x2UL << ADC_CR_BOOST_Pos) /*!< 0x00000200 */ +#define ADC_CR_ADCALLIN_Pos (16U) +#define ADC_CR_ADCALLIN_Msk (0x1UL << ADC_CR_ADCALLIN_Pos) /*!< 0x00010000 */ +#define ADC_CR_ADCALLIN ADC_CR_ADCALLIN_Msk /*!< ADC Linearity calibration */ +#define ADC_CR_LINCALRDYW1_Pos (22U) +#define ADC_CR_LINCALRDYW1_Msk (0x1UL << ADC_CR_LINCALRDYW1_Pos) /*!< 0x00400000 */ +#define ADC_CR_LINCALRDYW1 ADC_CR_LINCALRDYW1_Msk /*!< ADC Linearity calibration ready Word 1 */ +#define ADC_CR_LINCALRDYW2_Pos (23U) +#define ADC_CR_LINCALRDYW2_Msk (0x1UL << ADC_CR_LINCALRDYW2_Pos) /*!< 0x00800000 */ +#define ADC_CR_LINCALRDYW2 ADC_CR_LINCALRDYW2_Msk /*!< ADC Linearity calibration ready Word 2 */ +#define ADC_CR_LINCALRDYW3_Pos (24U) +#define ADC_CR_LINCALRDYW3_Msk (0x1UL << ADC_CR_LINCALRDYW3_Pos) /*!< 0x01000000 */ +#define ADC_CR_LINCALRDYW3 ADC_CR_LINCALRDYW3_Msk /*!< ADC Linearity calibration ready Word 3 */ +#define ADC_CR_LINCALRDYW4_Pos (25U) +#define ADC_CR_LINCALRDYW4_Msk (0x1UL << ADC_CR_LINCALRDYW4_Pos) /*!< 0x02000000 */ +#define ADC_CR_LINCALRDYW4 ADC_CR_LINCALRDYW4_Msk /*!< ADC Linearity calibration ready Word 4 */ +#define ADC_CR_LINCALRDYW5_Pos (26U) +#define ADC_CR_LINCALRDYW5_Msk (0x1UL << ADC_CR_LINCALRDYW5_Pos) /*!< 0x04000000 */ +#define ADC_CR_LINCALRDYW5 ADC_CR_LINCALRDYW5_Msk /*!< ADC Linearity calibration ready Word 5 */ +#define ADC_CR_LINCALRDYW6_Pos (27U) +#define ADC_CR_LINCALRDYW6_Msk (0x1UL << ADC_CR_LINCALRDYW6_Pos) /*!< 0x08000000 */ +#define ADC_CR_LINCALRDYW6 ADC_CR_LINCALRDYW6_Msk /*!< ADC Linearity calibration ready Word 6 */ +#define ADC_CR_ADVREGEN_Pos (28U) +#define ADC_CR_ADVREGEN_Msk (0x1UL << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */ +#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC Voltage regulator Enable */ +#define ADC_CR_DEEPPWD_Pos (29U) +#define ADC_CR_DEEPPWD_Msk (0x1UL << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */ +#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC Deep power down Enable */ +#define ADC_CR_ADCALDIF_Pos (30U) +#define ADC_CR_ADCALDIF_Msk (0x1UL << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */ +#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC Differential Mode for calibration */ +#define ADC_CR_ADCAL_Pos (31U) +#define ADC_CR_ADCAL_Msk (0x1UL << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */ +#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC Calibration */ + +/******************** Bit definition for ADC_CFGR register ********************/ +#define ADC_CFGR_DMNGT_Pos (0U) +#define ADC_CFGR_DMNGT_Msk (0x3UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000003 */ +#define ADC_CFGR_DMNGT ADC_CFGR_DMNGT_Msk /*!< ADC Data Management configuration */ +#define ADC_CFGR_DMNGT_0 (0x1UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000001 */ +#define ADC_CFGR_DMNGT_1 (0x2UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000002 */ + +#define ADC_CFGR_RES_Pos (2U) +#define ADC_CFGR_RES_Msk (0x7UL << ADC_CFGR_RES_Pos) /*!< 0x0000001C */ +#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC Data resolution */ +#define ADC_CFGR_RES_0 (0x1UL << ADC_CFGR_RES_Pos) /*!< 0x00000004 */ +#define ADC_CFGR_RES_1 (0x2UL << ADC_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC_CFGR_RES_2 (0x4UL << ADC_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR_EXTSEL_Pos (5U) +#define ADC_CFGR_EXTSEL_Msk (0x1FUL << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003E0 */ +#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC External trigger selection for regular group */ +#define ADC_CFGR_EXTSEL_0 (0x01UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000020 */ +#define ADC_CFGR_EXTSEL_1 (0x02UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */ +#define ADC_CFGR_EXTSEL_2 (0x04UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */ +#define ADC_CFGR_EXTSEL_3 (0x08UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */ +#define ADC_CFGR_EXTSEL_4 (0x10UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */ + +#define ADC_CFGR_EXTEN_Pos (10U) +#define ADC_CFGR_EXTEN_Msk (0x3UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */ +#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC External trigger enable and polarity selection for regular channels */ +#define ADC_CFGR_EXTEN_0 (0x1UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */ +#define ADC_CFGR_EXTEN_1 (0x2UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */ + +#define ADC_CFGR_OVRMOD_Pos (12U) +#define ADC_CFGR_OVRMOD_Msk (0x1UL << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */ +#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC overrun mode */ +#define ADC_CFGR_CONT_Pos (13U) +#define ADC_CFGR_CONT_Msk (0x1UL << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */ +#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC Single/continuous conversion mode for regular conversion */ +#define ADC_CFGR_AUTDLY_Pos (14U) +#define ADC_CFGR_AUTDLY_Msk (0x1UL << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */ +#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC Delayed conversion mode */ + +#define ADC_CFGR_DISCEN_Pos (16U) +#define ADC_CFGR_DISCEN_Msk (0x1UL << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */ +#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC Discontinuous mode for regular channels */ + +#define ADC_CFGR_DISCNUM_Pos (17U) +#define ADC_CFGR_DISCNUM_Msk (0x7UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */ +#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC Discontinuous mode channel count */ +#define ADC_CFGR_DISCNUM_0 (0x1UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */ +#define ADC_CFGR_DISCNUM_1 (0x2UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */ +#define ADC_CFGR_DISCNUM_2 (0x4UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */ + +#define ADC_CFGR_JDISCEN_Pos (20U) +#define ADC_CFGR_JDISCEN_Msk (0x1UL << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */ +#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC Discontinuous mode on injected channels */ +#define ADC_CFGR_JQM_Pos (21U) +#define ADC_CFGR_JQM_Msk (0x1UL << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */ +#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC JSQR Queue mode */ +#define ADC_CFGR_AWD1SGL_Pos (22U) +#define ADC_CFGR_AWD1SGL_Msk (0x1UL << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */ +#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< Enable the watchdog 1 on a single channel or on all channels */ +#define ADC_CFGR_AWD1EN_Pos (23U) +#define ADC_CFGR_AWD1EN_Msk (0x1UL << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */ +#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC Analog watchdog 1 enable on regular Channels */ +#define ADC_CFGR_JAWD1EN_Pos (24U) +#define ADC_CFGR_JAWD1EN_Msk (0x1UL << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */ +#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC Analog watchdog 1 enable on injected Channels */ +#define ADC_CFGR_JAUTO_Pos (25U) +#define ADC_CFGR_JAUTO_Msk (0x1UL << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */ +#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC Automatic injected group conversion */ + +#define ADC_CFGR_AWD1CH_Pos (26U) +#define ADC_CFGR_AWD1CH_Msk (0x1FUL << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */ +#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC Analog watchdog 1 Channel selection */ +#define ADC_CFGR_AWD1CH_0 (0x01UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */ +#define ADC_CFGR_AWD1CH_1 (0x02UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */ +#define ADC_CFGR_AWD1CH_2 (0x04UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */ +#define ADC_CFGR_AWD1CH_3 (0x08UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */ +#define ADC_CFGR_AWD1CH_4 (0x10UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */ + +#define ADC_CFGR_JQDIS_Pos (31U) +#define ADC_CFGR_JQDIS_Msk (0x1UL << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */ +#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC Injected queue disable */ + +#define ADC3_CFGR_DMAEN_Pos (0U) +#define ADC3_CFGR_DMAEN_Msk (0x1UL << ADC3_CFGR_DMAEN_Pos) /*!< 0x00000001 */ +#define ADC3_CFGR_DMAEN ADC3_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */ +#define ADC3_CFGR_DMACFG_Pos (1U) +#define ADC3_CFGR_DMACFG_Msk (0x1UL << ADC3_CFGR_DMACFG_Pos) /*!< 0x00000002 */ +#define ADC3_CFGR_DMACFG ADC3_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */ + +#define ADC3_CFGR_RES_Pos (3U) +#define ADC3_CFGR_RES_Msk (0x3UL << ADC3_CFGR_RES_Pos) /*!< 0x00000018 */ +#define ADC3_CFGR_RES ADC3_CFGR_RES_Msk /*!< ADC data resolution */ +#define ADC3_CFGR_RES_0 (0x1UL << ADC3_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC3_CFGR_RES_1 (0x2UL << ADC3_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC3_CFGR_ALIGN_Pos (15U) +#define ADC3_CFGR_ALIGN_Msk (0x1UL << ADC3_CFGR_ALIGN_Pos) /*!< 0x00008000 */ +#define ADC3_CFGR_ALIGN ADC3_CFGR_ALIGN_Msk /*!< ADC data alignment */ +/******************** Bit definition for ADC_CFGR2 register ********************/ +#define ADC_CFGR2_ROVSE_Pos (0U) +#define ADC_CFGR2_ROVSE_Msk (0x1UL << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */ +#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC Regular group oversampler enable */ +#define ADC_CFGR2_JOVSE_Pos (1U) +#define ADC_CFGR2_JOVSE_Msk (0x1UL << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */ +#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC Injected group oversampler enable */ + +#define ADC_CFGR2_OVSS_Pos (5U) +#define ADC_CFGR2_OVSS_Msk (0xFUL << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */ +#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC Regular Oversampling shift */ +#define ADC_CFGR2_OVSS_0 (0x1UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */ +#define ADC_CFGR2_OVSS_1 (0x2UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */ +#define ADC_CFGR2_OVSS_2 (0x4UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */ +#define ADC_CFGR2_OVSS_3 (0x8UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */ + +#define ADC_CFGR2_TROVS_Pos (9U) +#define ADC_CFGR2_TROVS_Msk (0x1UL << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */ +#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC Triggered regular Oversampling */ +#define ADC_CFGR2_ROVSM_Pos (10U) +#define ADC_CFGR2_ROVSM_Msk (0x1UL << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */ +#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC Regular oversampling mode */ + +#define ADC_CFGR2_RSHIFT1_Pos (11U) +#define ADC_CFGR2_RSHIFT1_Msk (0x1UL << ADC_CFGR2_RSHIFT1_Pos) /*!< 0x00000800 */ +#define ADC_CFGR2_RSHIFT1 ADC_CFGR2_RSHIFT1_Msk /*!< ADC Right-shift data after Offset 1 correction */ +#define ADC_CFGR2_RSHIFT2_Pos (12U) +#define ADC_CFGR2_RSHIFT2_Msk (0x1UL << ADC_CFGR2_RSHIFT2_Pos) /*!< 0x00001000 */ +#define ADC_CFGR2_RSHIFT2 ADC_CFGR2_RSHIFT2_Msk /*!< ADC Right-shift data after Offset 2 correction */ +#define ADC_CFGR2_RSHIFT3_Pos (13U) +#define ADC_CFGR2_RSHIFT3_Msk (0x1UL << ADC_CFGR2_RSHIFT3_Pos) /*!< 0x00002000 */ +#define ADC_CFGR2_RSHIFT3 ADC_CFGR2_RSHIFT3_Msk /*!< ADC Right-shift data after Offset 3 correction */ +#define ADC_CFGR2_RSHIFT4_Pos (14U) +#define ADC_CFGR2_RSHIFT4_Msk (0x1UL << ADC_CFGR2_RSHIFT4_Pos) /*!< 0x00004000 */ +#define ADC_CFGR2_RSHIFT4 ADC_CFGR2_RSHIFT4_Msk /*!< ADC Right-shift data after Offset 4 correction */ + +#define ADC_CFGR2_OVSR_Pos (16U) +#define ADC_CFGR2_OVSR_Msk (0x3FFUL << ADC_CFGR2_OVSR_Pos) /*!< 0x03FF0000 */ +#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling Ratio */ +#define ADC_CFGR2_OVSR_0 (0x001UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00010000 */ +#define ADC_CFGR2_OVSR_1 (0x002UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00020000 */ +#define ADC_CFGR2_OVSR_2 (0x004UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00040000 */ +#define ADC_CFGR2_OVSR_3 (0x008UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00080000 */ +#define ADC_CFGR2_OVSR_4 (0x010UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00100000 */ +#define ADC_CFGR2_OVSR_5 (0x020UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00200000 */ +#define ADC_CFGR2_OVSR_6 (0x040UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00400000 */ +#define ADC_CFGR2_OVSR_7 (0x080UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00800000 */ +#define ADC_CFGR2_OVSR_8 (0x100UL << ADC_CFGR2_OVSR_Pos) /*!< 0x01000000 */ +#define ADC_CFGR2_OVSR_9 (0x200UL << ADC_CFGR2_OVSR_Pos) /*!< 0x02000000 */ + +#define ADC_CFGR2_LSHIFT_Pos (28U) +#define ADC_CFGR2_LSHIFT_Msk (0xFUL << ADC_CFGR2_LSHIFT_Pos) /*!< 0xF0000000 */ +#define ADC_CFGR2_LSHIFT ADC_CFGR2_LSHIFT_Msk /*!< ADC Left shift factor */ +#define ADC_CFGR2_LSHIFT_0 (0x1UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x10000000 */ +#define ADC_CFGR2_LSHIFT_1 (0x2UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x20000000 */ +#define ADC_CFGR2_LSHIFT_2 (0x4UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x40000000 */ +#define ADC_CFGR2_LSHIFT_3 (0x8UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x80000000 */ + +#define ADC3_CFGR2_OVSR_Pos (2U) +#define ADC3_CFGR2_OVSR_Msk (0x7UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x0000001C */ +#define ADC3_CFGR2_OVSR ADC3_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */ +#define ADC3_CFGR2_OVSR_0 (0x1UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000004 */ +#define ADC3_CFGR2_OVSR_1 (0x2UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000008 */ +#define ADC3_CFGR2_OVSR_2 (0x4UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000010 */ + +#define ADC3_CFGR2_SWTRIG_Pos (25U) +#define ADC3_CFGR2_SWTRIG_Msk (0x1UL << ADC3_CFGR2_SWTRIG_Pos) /*!< 0x02000000 */ +#define ADC3_CFGR2_SWTRIG ADC3_CFGR2_SWTRIG_Msk /*!< ADC Software Trigger Bit for Sample time control trigger mode */ +#define ADC3_CFGR2_BULB_Pos (26U) +#define ADC3_CFGR2_BULB_Msk (0x1UL << ADC3_CFGR2_BULB_Pos) /*!< 0x04000000 */ +#define ADC3_CFGR2_BULB ADC3_CFGR2_BULB_Msk /*!< ADC Bulb sampling mode */ +#define ADC3_CFGR2_SMPTRIG_Pos (27U) +#define ADC3_CFGR2_SMPTRIG_Msk (0x1UL << ADC3_CFGR2_SMPTRIG_Pos) /*!< 0x08000000 */ +#define ADC3_CFGR2_SMPTRIG ADC3_CFGR2_SMPTRIG_Msk /*!< ADC Sample Time Control Trigger mode */ +/******************** Bit definition for ADC_SMPR1 register ********************/ +#define ADC_SMPR1_SMP0_Pos (0U) +#define ADC_SMPR1_SMP0_Msk (0x7UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */ +#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC Channel 0 Sampling time selection */ +#define ADC_SMPR1_SMP0_0 (0x1UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */ +#define ADC_SMPR1_SMP0_1 (0x2UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */ +#define ADC_SMPR1_SMP0_2 (0x4UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR1_SMP1_Pos (3U) +#define ADC_SMPR1_SMP1_Msk (0x7UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */ +#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC Channel 1 Sampling time selection */ +#define ADC_SMPR1_SMP1_0 (0x1UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */ +#define ADC_SMPR1_SMP1_1 (0x2UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */ +#define ADC_SMPR1_SMP1_2 (0x4UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR1_SMP2_Pos (6U) +#define ADC_SMPR1_SMP2_Msk (0x7UL << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC Channel 2 Sampling time selection */ +#define ADC_SMPR1_SMP2_0 (0x1UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */ +#define ADC_SMPR1_SMP2_1 (0x2UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */ +#define ADC_SMPR1_SMP2_2 (0x4UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR1_SMP3_Pos (9U) +#define ADC_SMPR1_SMP3_Msk (0x7UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC Channel 3 Sampling time selection */ +#define ADC_SMPR1_SMP3_0 (0x1UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */ +#define ADC_SMPR1_SMP3_1 (0x2UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */ +#define ADC_SMPR1_SMP3_2 (0x4UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR1_SMP4_Pos (12U) +#define ADC_SMPR1_SMP4_Msk (0x7UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */ +#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC Channel 4 Sampling time selection */ +#define ADC_SMPR1_SMP4_0 (0x1UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */ +#define ADC_SMPR1_SMP4_1 (0x2UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */ +#define ADC_SMPR1_SMP4_2 (0x4UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR1_SMP5_Pos (15U) +#define ADC_SMPR1_SMP5_Msk (0x7UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */ +#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC Channel 5 Sampling time selection */ +#define ADC_SMPR1_SMP5_0 (0x1UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */ +#define ADC_SMPR1_SMP5_1 (0x2UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */ +#define ADC_SMPR1_SMP5_2 (0x4UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR1_SMP6_Pos (18U) +#define ADC_SMPR1_SMP6_Msk (0x7UL << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC Channel 6 Sampling time selection */ +#define ADC_SMPR1_SMP6_0 (0x1UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */ +#define ADC_SMPR1_SMP6_1 (0x2UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */ +#define ADC_SMPR1_SMP6_2 (0x4UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR1_SMP7_Pos (21U) +#define ADC_SMPR1_SMP7_Msk (0x7UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC Channel 7 Sampling time selection */ +#define ADC_SMPR1_SMP7_0 (0x1UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */ +#define ADC_SMPR1_SMP7_1 (0x2UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */ +#define ADC_SMPR1_SMP7_2 (0x4UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR1_SMP8_Pos (24U) +#define ADC_SMPR1_SMP8_Msk (0x7UL << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */ +#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC Channel 8 Sampling time selection */ +#define ADC_SMPR1_SMP8_0 (0x1UL << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */ +#define ADC_SMPR1_SMP8_1 (0x2UL << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */ +#define ADC_SMPR1_SMP8_2 (0x4UL << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR1_SMP9_Pos (27U) +#define ADC_SMPR1_SMP9_Msk (0x7UL << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */ +#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC Channel 9 Sampling time selection */ +#define ADC_SMPR1_SMP9_0 (0x1UL << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */ +#define ADC_SMPR1_SMP9_1 (0x2UL << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */ +#define ADC_SMPR1_SMP9_2 (0x4UL << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_SMPR2 register ********************/ +#define ADC_SMPR2_SMP10_Pos (0U) +#define ADC_SMPR2_SMP10_Msk (0x7UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */ +#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC Channel 10 Sampling time selection */ +#define ADC_SMPR2_SMP10_0 (0x1UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */ +#define ADC_SMPR2_SMP10_1 (0x2UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */ +#define ADC_SMPR2_SMP10_2 (0x4UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR2_SMP11_Pos (3U) +#define ADC_SMPR2_SMP11_Msk (0x7UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */ +#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC Channel 11 Sampling time selection */ +#define ADC_SMPR2_SMP11_0 (0x1UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */ +#define ADC_SMPR2_SMP11_1 (0x2UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */ +#define ADC_SMPR2_SMP11_2 (0x4UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR2_SMP12_Pos (6U) +#define ADC_SMPR2_SMP12_Msk (0x7UL << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC Channel 12 Sampling time selection */ +#define ADC_SMPR2_SMP12_0 (0x1UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */ +#define ADC_SMPR2_SMP12_1 (0x2UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */ +#define ADC_SMPR2_SMP12_2 (0x4UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR2_SMP13_Pos (9U) +#define ADC_SMPR2_SMP13_Msk (0x7UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC Channel 13 Sampling time selection */ +#define ADC_SMPR2_SMP13_0 (0x1UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */ +#define ADC_SMPR2_SMP13_1 (0x2UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */ +#define ADC_SMPR2_SMP13_2 (0x4UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR2_SMP14_Pos (12U) +#define ADC_SMPR2_SMP14_Msk (0x7UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */ +#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC Channel 14 Sampling time selection */ +#define ADC_SMPR2_SMP14_0 (0x1UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */ +#define ADC_SMPR2_SMP14_1 (0x2UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */ +#define ADC_SMPR2_SMP14_2 (0x4UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR2_SMP15_Pos (15U) +#define ADC_SMPR2_SMP15_Msk (0x7UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */ +#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC Channel 15 Sampling time selection */ +#define ADC_SMPR2_SMP15_0 (0x1UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */ +#define ADC_SMPR2_SMP15_1 (0x2UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */ +#define ADC_SMPR2_SMP15_2 (0x4UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR2_SMP16_Pos (18U) +#define ADC_SMPR2_SMP16_Msk (0x7UL << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC Channel 16 Sampling time selection */ +#define ADC_SMPR2_SMP16_0 (0x1UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */ +#define ADC_SMPR2_SMP16_1 (0x2UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */ +#define ADC_SMPR2_SMP16_2 (0x4UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR2_SMP17_Pos (21U) +#define ADC_SMPR2_SMP17_Msk (0x7UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC Channel 17 Sampling time selection */ +#define ADC_SMPR2_SMP17_0 (0x1UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */ +#define ADC_SMPR2_SMP17_1 (0x2UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */ +#define ADC_SMPR2_SMP17_2 (0x4UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR2_SMP18_Pos (24U) +#define ADC_SMPR2_SMP18_Msk (0x7UL << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */ +#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC Channel 18 Sampling time selection */ +#define ADC_SMPR2_SMP18_0 (0x1UL << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */ +#define ADC_SMPR2_SMP18_1 (0x2UL << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */ +#define ADC_SMPR2_SMP18_2 (0x4UL << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR2_SMP19_Pos (27U) +#define ADC_SMPR2_SMP19_Msk (0x7UL << ADC_SMPR2_SMP19_Pos) /*!< 0x38000000 */ +#define ADC_SMPR2_SMP19 ADC_SMPR2_SMP19_Msk /*!< ADC Channel 19 Sampling time selection */ +#define ADC_SMPR2_SMP19_0 (0x1UL << ADC_SMPR2_SMP19_Pos) /*!< 0x08000000 */ +#define ADC_SMPR2_SMP19_1 (0x2UL << ADC_SMPR2_SMP19_Pos) /*!< 0x10000000 */ +#define ADC_SMPR2_SMP19_2 (0x4UL << ADC_SMPR2_SMP19_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_PCSEL register ********************/ +#define ADC_PCSEL_PCSEL_Pos (0U) +#define ADC_PCSEL_PCSEL_Msk (0xFFFFFUL << ADC_PCSEL_PCSEL_Pos) /*!< 0x000FFFFF */ +#define ADC_PCSEL_PCSEL ADC_PCSEL_PCSEL_Msk /*!< ADC pre channel selection */ +#define ADC_PCSEL_PCSEL_0 (0x00001UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000001 */ +#define ADC_PCSEL_PCSEL_1 (0x00002UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000002 */ +#define ADC_PCSEL_PCSEL_2 (0x00004UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000004 */ +#define ADC_PCSEL_PCSEL_3 (0x00008UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000008 */ +#define ADC_PCSEL_PCSEL_4 (0x00010UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000010 */ +#define ADC_PCSEL_PCSEL_5 (0x00020UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000020 */ +#define ADC_PCSEL_PCSEL_6 (0x00040UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000040 */ +#define ADC_PCSEL_PCSEL_7 (0x00080UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000080 */ +#define ADC_PCSEL_PCSEL_8 (0x00100UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000100 */ +#define ADC_PCSEL_PCSEL_9 (0x00200UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000200 */ +#define ADC_PCSEL_PCSEL_10 (0x00400UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000400 */ +#define ADC_PCSEL_PCSEL_11 (0x00800UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000800 */ +#define ADC_PCSEL_PCSEL_12 (0x01000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00001000 */ +#define ADC_PCSEL_PCSEL_13 (0x02000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00002000 */ +#define ADC_PCSEL_PCSEL_14 (0x04000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00004000 */ +#define ADC_PCSEL_PCSEL_15 (0x08000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00008000 */ +#define ADC_PCSEL_PCSEL_16 (0x10000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00010000 */ +#define ADC_PCSEL_PCSEL_17 (0x20000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00020000 */ +#define ADC_PCSEL_PCSEL_18 (0x40000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00040000 */ +#define ADC_PCSEL_PCSEL_19 (0x80000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00080000 */ + +/***************** Bit definition for ADC_LTR1, 2, 3 registers *****************/ +#define ADC_LTR_LT_Pos (0U) +#define ADC_LTR_LT_Msk (0x3FFFFFFUL << ADC_LTR_LT_Pos) /*!< 0x03FFFFFF */ +#define ADC_LTR_LT ADC_LTR_LT_Msk /*!< ADC Analog watchdog 1, 2 and 3 lower threshold */ + +/***************** Bit definition for ADC_HTR1, 2, 3 registers ****************/ +#define ADC_HTR_HT_Pos (0U) +#define ADC_HTR_HT_Msk (0x3FFFFFFUL << ADC_HTR_HT_Pos) /*!< 0x03FFFFFF */ +#define ADC_HTR_HT ADC_HTR_HT_Msk /*!< ADC Analog watchdog 1,2 and 3 higher threshold */ + +/******************** Bit definition for ADC3_TR1 register *******************/ +#define ADC3_TR1_LT1_Pos (0U) +#define ADC3_TR1_LT1_Msk (0xFFFUL << ADC3_TR1_LT1_Pos) /*!< 0x00000FFF */ +#define ADC3_TR1_LT1 ADC3_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */ + +#define ADC3_TR1_AWDFILT_Pos (12U) +#define ADC3_TR1_AWDFILT_Msk (0x7UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00007000 */ +#define ADC3_TR1_AWDFILT ADC3_TR1_AWDFILT_Msk /*!< ADC analog watchdog filtering parameter */ +#define ADC3_TR1_AWDFILT_0 (0x1UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00001000 */ +#define ADC3_TR1_AWDFILT_1 (0x2UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00002000 */ +#define ADC3_TR1_AWDFILT_2 (0x4UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00004000 */ + +#define ADC3_TR1_HT1_Pos (16U) +#define ADC3_TR1_HT1_Msk (0xFFFUL << ADC3_TR1_HT1_Pos) /*!< 0x0FFF0000 */ +#define ADC3_TR1_HT1 ADC3_TR1_HT1_Msk /*!< ADC analog watchdog 1 threshold high */ + +/******************** Bit definition for ADC3_TR2 register *******************/ +#define ADC3_TR2_LT2_Pos (0U) +#define ADC3_TR2_LT2_Msk (0xFFUL << ADC3_TR2_LT2_Pos) /*!< 0x000000FF */ +#define ADC3_TR2_LT2 ADC3_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */ + +#define ADC3_TR2_HT2_Pos (16U) +#define ADC3_TR2_HT2_Msk (0xFFUL << ADC3_TR2_HT2_Pos) /*!< 0x00FF0000 */ +#define ADC3_TR2_HT2 ADC3_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */ + +/******************** Bit definition for ADC3_TR3 register *******************/ +#define ADC3_TR3_LT3_Pos (0U) +#define ADC3_TR3_LT3_Msk (0xFFUL << ADC3_TR3_LT3_Pos) /*!< 0x000000FF */ +#define ADC3_TR3_LT3 ADC3_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */ + +#define ADC3_TR3_HT3_Pos (16U) +#define ADC3_TR3_HT3_Msk (0xFFUL << ADC3_TR3_HT3_Pos) /*!< 0x00FF0000 */ +#define ADC3_TR3_HT3 ADC3_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */ + +/******************** Bit definition for ADC_SQR1 register ********************/ +#define ADC_SQR1_L_Pos (0U) +#define ADC_SQR1_L_Msk (0xFUL << ADC_SQR1_L_Pos) /*!< 0x0000000F */ +#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC regular channel sequence length */ +#define ADC_SQR1_L_0 (0x1UL << ADC_SQR1_L_Pos) /*!< 0x00000001 */ +#define ADC_SQR1_L_1 (0x2UL << ADC_SQR1_L_Pos) /*!< 0x00000002 */ +#define ADC_SQR1_L_2 (0x4UL << ADC_SQR1_L_Pos) /*!< 0x00000004 */ +#define ADC_SQR1_L_3 (0x8UL << ADC_SQR1_L_Pos) /*!< 0x00000008 */ + +#define ADC_SQR1_SQ1_Pos (6U) +#define ADC_SQR1_SQ1_Msk (0x1FUL << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */ +#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC 1st conversion in regular sequence */ +#define ADC_SQR1_SQ1_0 (0x01UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */ +#define ADC_SQR1_SQ1_1 (0x02UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */ +#define ADC_SQR1_SQ1_2 (0x04UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */ +#define ADC_SQR1_SQ1_3 (0x08UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */ +#define ADC_SQR1_SQ1_4 (0x10UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */ + +#define ADC_SQR1_SQ2_Pos (12U) +#define ADC_SQR1_SQ2_Msk (0x1FUL << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */ +#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC 2nd conversion in regular sequence */ +#define ADC_SQR1_SQ2_0 (0x01UL << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */ +#define ADC_SQR1_SQ2_1 (0x02UL << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */ +#define ADC_SQR1_SQ2_2 (0x04UL << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */ +#define ADC_SQR1_SQ2_3 (0x08UL << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */ +#define ADC_SQR1_SQ2_4 (0x10UL << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */ + +#define ADC_SQR1_SQ3_Pos (18U) +#define ADC_SQR1_SQ3_Msk (0x1FUL << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */ +#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC 3rd conversion in regular sequence */ +#define ADC_SQR1_SQ3_0 (0x01UL << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */ +#define ADC_SQR1_SQ3_1 (0x02UL << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */ +#define ADC_SQR1_SQ3_2 (0x04UL << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */ +#define ADC_SQR1_SQ3_3 (0x08UL << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */ +#define ADC_SQR1_SQ3_4 (0x10UL << ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */ + +#define ADC_SQR1_SQ4_Pos (24U) +#define ADC_SQR1_SQ4_Msk (0x1FUL << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */ +#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC 4th conversion in regular sequence */ +#define ADC_SQR1_SQ4_0 (0x01UL << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */ +#define ADC_SQR1_SQ4_1 (0x02UL << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */ +#define ADC_SQR1_SQ4_2 (0x04UL << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */ +#define ADC_SQR1_SQ4_3 (0x08UL << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */ +#define ADC_SQR1_SQ4_4 (0x10UL << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR2 register ********************/ +#define ADC_SQR2_SQ5_Pos (0U) +#define ADC_SQR2_SQ5_Msk (0x1FUL << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */ +#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC 5th conversion in regular sequence */ +#define ADC_SQR2_SQ5_0 (0x01UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */ +#define ADC_SQR2_SQ5_1 (0x02UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */ +#define ADC_SQR2_SQ5_2 (0x04UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */ +#define ADC_SQR2_SQ5_3 (0x08UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */ +#define ADC_SQR2_SQ5_4 (0x10UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */ + +#define ADC_SQR2_SQ6_Pos (6U) +#define ADC_SQR2_SQ6_Msk (0x1FUL << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */ +#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC 6th conversion in regular sequence */ +#define ADC_SQR2_SQ6_0 (0x01UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */ +#define ADC_SQR2_SQ6_1 (0x02UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */ +#define ADC_SQR2_SQ6_2 (0x04UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */ +#define ADC_SQR2_SQ6_3 (0x08UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */ +#define ADC_SQR2_SQ6_4 (0x10UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */ + +#define ADC_SQR2_SQ7_Pos (12U) +#define ADC_SQR2_SQ7_Msk (0x1FUL << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */ +#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC 7th conversion in regular sequence */ +#define ADC_SQR2_SQ7_0 (0x01UL << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */ +#define ADC_SQR2_SQ7_1 (0x02UL << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */ +#define ADC_SQR2_SQ7_2 (0x04UL << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */ +#define ADC_SQR2_SQ7_3 (0x08UL << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */ +#define ADC_SQR2_SQ7_4 (0x10UL << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */ + +#define ADC_SQR2_SQ8_Pos (18U) +#define ADC_SQR2_SQ8_Msk (0x1FUL << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */ +#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC 8th conversion in regular sequence */ +#define ADC_SQR2_SQ8_0 (0x01UL << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */ +#define ADC_SQR2_SQ8_1 (0x02UL << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */ +#define ADC_SQR2_SQ8_2 (0x04UL << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */ +#define ADC_SQR2_SQ8_3 (0x08UL << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */ +#define ADC_SQR2_SQ8_4 (0x10UL << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */ + +#define ADC_SQR2_SQ9_Pos (24U) +#define ADC_SQR2_SQ9_Msk (0x1FUL << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */ +#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC 9th conversion in regular sequence */ +#define ADC_SQR2_SQ9_0 (0x01UL << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */ +#define ADC_SQR2_SQ9_1 (0x02UL << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */ +#define ADC_SQR2_SQ9_2 (0x04UL << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */ +#define ADC_SQR2_SQ9_3 (0x08UL << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */ +#define ADC_SQR2_SQ9_4 (0x10UL << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR3 register ********************/ +#define ADC_SQR3_SQ10_Pos (0U) +#define ADC_SQR3_SQ10_Msk (0x1FUL << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */ +#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC 10th conversion in regular sequence */ +#define ADC_SQR3_SQ10_0 (0x01UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */ +#define ADC_SQR3_SQ10_1 (0x02UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */ +#define ADC_SQR3_SQ10_2 (0x04UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */ +#define ADC_SQR3_SQ10_3 (0x08UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */ +#define ADC_SQR3_SQ10_4 (0x10UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */ + +#define ADC_SQR3_SQ11_Pos (6U) +#define ADC_SQR3_SQ11_Msk (0x1FUL << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */ +#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC 11th conversion in regular sequence */ +#define ADC_SQR3_SQ11_0 (0x01UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */ +#define ADC_SQR3_SQ11_1 (0x02UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */ +#define ADC_SQR3_SQ11_2 (0x04UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */ +#define ADC_SQR3_SQ11_3 (0x08UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */ +#define ADC_SQR3_SQ11_4 (0x10UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */ + +#define ADC_SQR3_SQ12_Pos (12U) +#define ADC_SQR3_SQ12_Msk (0x1FUL << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */ +#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC 12th conversion in regular sequence */ +#define ADC_SQR3_SQ12_0 (0x01UL << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */ +#define ADC_SQR3_SQ12_1 (0x02UL << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */ +#define ADC_SQR3_SQ12_2 (0x04UL << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */ +#define ADC_SQR3_SQ12_3 (0x08UL << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */ +#define ADC_SQR3_SQ12_4 (0x10UL << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */ + +#define ADC_SQR3_SQ13_Pos (18U) +#define ADC_SQR3_SQ13_Msk (0x1FUL << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */ +#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC 13th conversion in regular sequence */ +#define ADC_SQR3_SQ13_0 (0x01UL << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */ +#define ADC_SQR3_SQ13_1 (0x02UL << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */ +#define ADC_SQR3_SQ13_2 (0x04UL << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */ +#define ADC_SQR3_SQ13_3 (0x08UL << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */ +#define ADC_SQR3_SQ13_4 (0x10UL << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */ + +#define ADC_SQR3_SQ14_Pos (24U) +#define ADC_SQR3_SQ14_Msk (0x1FUL << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */ +#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC 14th conversion in regular sequence */ +#define ADC_SQR3_SQ14_0 (0x01UL << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */ +#define ADC_SQR3_SQ14_1 (0x02UL << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */ +#define ADC_SQR3_SQ14_2 (0x04UL << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */ +#define ADC_SQR3_SQ14_3 (0x08UL << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */ +#define ADC_SQR3_SQ14_4 (0x10UL << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR4 register ********************/ +#define ADC_SQR4_SQ15_Pos (0U) +#define ADC_SQR4_SQ15_Msk (0x1FUL << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */ +#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC 15th conversion in regular sequence */ +#define ADC_SQR4_SQ15_0 (0x01UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */ +#define ADC_SQR4_SQ15_1 (0x02UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */ +#define ADC_SQR4_SQ15_2 (0x04UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */ +#define ADC_SQR4_SQ15_3 (0x08UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */ +#define ADC_SQR4_SQ15_4 (0x10UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */ + +#define ADC_SQR4_SQ16_Pos (6U) +#define ADC_SQR4_SQ16_Msk (0x1FUL << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */ +#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC 16th conversion in regular sequence */ +#define ADC_SQR4_SQ16_0 (0x01UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */ +#define ADC_SQR4_SQ16_1 (0x02UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */ +#define ADC_SQR4_SQ16_2 (0x04UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */ +#define ADC_SQR4_SQ16_3 (0x08UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */ +#define ADC_SQR4_SQ16_4 (0x10UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */ +/******************** Bit definition for ADC_DR register ********************/ +#define ADC_DR_RDATA_Pos (0U) +#define ADC_DR_RDATA_Msk (0xFFFFFFFFUL << ADC_DR_RDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC regular Data converted */ + +/******************** Bit definition for ADC_JSQR register ********************/ +#define ADC_JSQR_JL_Pos (0U) +#define ADC_JSQR_JL_Msk (0x3UL << ADC_JSQR_JL_Pos) /*!< 0x00000003 */ +#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC injected channel sequence length */ +#define ADC_JSQR_JL_0 (0x1UL << ADC_JSQR_JL_Pos) /*!< 0x00000001 */ +#define ADC_JSQR_JL_1 (0x2UL << ADC_JSQR_JL_Pos) /*!< 0x00000002 */ + +#define ADC_JSQR_JEXTSEL_Pos (2U) +#define ADC_JSQR_JEXTSEL_Msk (0x1FUL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000007C */ +#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC external trigger selection for injected group */ +#define ADC_JSQR_JEXTSEL_0 (0x01UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */ +#define ADC_JSQR_JEXTSEL_1 (0x02UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */ +#define ADC_JSQR_JEXTSEL_2 (0x04UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */ +#define ADC_JSQR_JEXTSEL_3 (0x08UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */ +#define ADC_JSQR_JEXTSEL_4 (0x10UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000040 */ + +#define ADC_JSQR_JEXTEN_Pos (7U) +#define ADC_JSQR_JEXTEN_Msk (0x3UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000180 */ +#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC external trigger enable and polarity selection for injected channels */ +#define ADC_JSQR_JEXTEN_0 (0x1UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */ +#define ADC_JSQR_JEXTEN_1 (0x2UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000100 */ + +#define ADC_JSQR_JSQ1_Pos (9U) +#define ADC_JSQR_JSQ1_Msk (0x1FUL << ADC_JSQR_JSQ1_Pos) /*!< 0x00003E00 */ +#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC 1st conversion in injected sequence */ +#define ADC_JSQR_JSQ1_0 (0x01UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */ +#define ADC_JSQR_JSQ1_1 (0x02UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */ +#define ADC_JSQR_JSQ1_2 (0x04UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */ +#define ADC_JSQR_JSQ1_3 (0x08UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */ +#define ADC_JSQR_JSQ1_4 (0x10UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00002000 */ + +#define ADC_JSQR_JSQ2_Pos (15U) +#define ADC_JSQR_JSQ2_Msk (0x1FUL << ADC_JSQR_JSQ2_Pos) /*!< 0x000F8000 */ +#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC 2nd conversion in injected sequence */ +#define ADC_JSQR_JSQ2_0 (0x01UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */ +#define ADC_JSQR_JSQ2_1 (0x02UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */ +#define ADC_JSQR_JSQ2_2 (0x04UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */ +#define ADC_JSQR_JSQ2_3 (0x08UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */ +#define ADC_JSQR_JSQ2_4 (0x10UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00080000 */ + +#define ADC_JSQR_JSQ3_Pos (21U) +#define ADC_JSQR_JSQ3_Msk (0x1FUL << ADC_JSQR_JSQ3_Pos) /*!< 0x03E00000 */ +#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC 3rd conversion in injected sequence */ +#define ADC_JSQR_JSQ3_0 (0x01UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */ +#define ADC_JSQR_JSQ3_1 (0x02UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */ +#define ADC_JSQR_JSQ3_2 (0x04UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */ +#define ADC_JSQR_JSQ3_3 (0x08UL << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */ +#define ADC_JSQR_JSQ3_4 (0x10UL << ADC_JSQR_JSQ3_Pos) /*!< 0x02000000 */ + +#define ADC_JSQR_JSQ4_Pos (27U) +#define ADC_JSQR_JSQ4_Msk (0x1FUL << ADC_JSQR_JSQ4_Pos) /*!< 0xF8000000 */ +#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC 4th conversion in injected sequence */ +#define ADC_JSQR_JSQ4_0 (0x01UL << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */ +#define ADC_JSQR_JSQ4_1 (0x02UL << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */ +#define ADC_JSQR_JSQ4_2 (0x04UL << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */ +#define ADC_JSQR_JSQ4_3 (0x08UL << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */ +#define ADC_JSQR_JSQ4_4 (0x10UL << ADC_JSQR_JSQ4_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_OFR1 register ********************/ +#define ADC_OFR1_OFFSET1_Pos (0U) +#define ADC_OFR1_OFFSET1_Msk (0x3FFFFFFUL << ADC_OFR1_OFFSET1_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */ +#define ADC_OFR1_OFFSET1_0 (0x0000001UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000001 */ +#define ADC_OFR1_OFFSET1_1 (0x0000002UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000002 */ +#define ADC_OFR1_OFFSET1_2 (0x0000004UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000004 */ +#define ADC_OFR1_OFFSET1_3 (0x0000008UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000008 */ +#define ADC_OFR1_OFFSET1_4 (0x0000010UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000010 */ +#define ADC_OFR1_OFFSET1_5 (0x0000020UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000020 */ +#define ADC_OFR1_OFFSET1_6 (0x0000040UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000040 */ +#define ADC_OFR1_OFFSET1_7 (0x0000080UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000080 */ +#define ADC_OFR1_OFFSET1_8 (0x0000100UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000100 */ +#define ADC_OFR1_OFFSET1_9 (0x0000200UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000200 */ +#define ADC_OFR1_OFFSET1_10 (0x0000400UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000400 */ +#define ADC_OFR1_OFFSET1_11 (0x0000800UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000800 */ +#define ADC_OFR1_OFFSET1_12 (0x0001000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00001000 */ +#define ADC_OFR1_OFFSET1_13 (0x0002000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00002000 */ +#define ADC_OFR1_OFFSET1_14 (0x0004000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00004000 */ +#define ADC_OFR1_OFFSET1_15 (0x0008000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00008000 */ +#define ADC_OFR1_OFFSET1_16 (0x0010000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00010000 */ +#define ADC_OFR1_OFFSET1_17 (0x0020000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00020000 */ +#define ADC_OFR1_OFFSET1_18 (0x0040000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00040000 */ +#define ADC_OFR1_OFFSET1_19 (0x0080000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00080000 */ +#define ADC_OFR1_OFFSET1_20 (0x0100000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00100000 */ +#define ADC_OFR1_OFFSET1_21 (0x0200000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00200000 */ +#define ADC_OFR1_OFFSET1_22 (0x0400000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00400000 */ +#define ADC_OFR1_OFFSET1_23 (0x0800000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00800000 */ +#define ADC_OFR1_OFFSET1_24 (0x1000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x01000000 */ +#define ADC_OFR1_OFFSET1_25 (0x2000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x02000000 */ + +#define ADC_OFR1_OFFSET1_CH_Pos (26U) +#define ADC_OFR1_OFFSET1_CH_Msk (0x1FUL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC Channel selection for the data offset 1 */ +#define ADC_OFR1_OFFSET1_CH_0 (0x01UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR1_OFFSET1_CH_1 (0x02UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR1_OFFSET1_CH_2 (0x04UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR1_OFFSET1_CH_3 (0x08UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR1_OFFSET1_CH_4 (0x10UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR1_SSATE_Pos (31U) +#define ADC_OFR1_SSATE_Msk (0x1UL << ADC_OFR1_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR1_SSATE ADC_OFR1_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR1_OFFSET1_Pos (0U) +#define ADC3_OFR1_OFFSET1_Msk (0xFFFUL << ADC3_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR1_OFFSET1 ADC3_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR1_OFFSETPOS_Pos (24U) +#define ADC3_OFR1_OFFSETPOS_Msk (0x1UL << ADC3_OFR1_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR1_OFFSETPOS ADC3_OFR1_OFFSETPOS_Msk /*!< ADC offset number 1 positive */ +#define ADC3_OFR1_SATEN_Pos (25U) +#define ADC3_OFR1_SATEN_Msk (0x1UL << ADC3_OFR1_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR1_SATEN ADC3_OFR1_SATEN_Msk /*!< ADC offset number 1 saturation enable */ + +#define ADC3_OFR1_OFFSET1_EN_Pos (31U) +#define ADC3_OFR1_OFFSET1_EN_Msk (0x1UL << ADC3_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR1_OFFSET1_EN ADC3_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */ + +/******************** Bit definition for ADC_OFR2 register ********************/ +#define ADC_OFR2_OFFSET2_Pos (0U) +#define ADC_OFR2_OFFSET2_Msk (0x3FFFFFFUL << ADC_OFR2_OFFSET2_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET2_CH[4:0] */ +#define ADC_OFR2_OFFSET2_0 (0x0000001UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000001 */ +#define ADC_OFR2_OFFSET2_1 (0x0000002UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000002 */ +#define ADC_OFR2_OFFSET2_2 (0x0000004UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000004 */ +#define ADC_OFR2_OFFSET2_3 (0x0000008UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000008 */ +#define ADC_OFR2_OFFSET2_4 (0x0000010UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000010 */ +#define ADC_OFR2_OFFSET2_5 (0x0000020UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000020 */ +#define ADC_OFR2_OFFSET2_6 (0x0000040UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000040 */ +#define ADC_OFR2_OFFSET2_7 (0x0000080UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000080 */ +#define ADC_OFR2_OFFSET2_8 (0x0000100UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000100 */ +#define ADC_OFR2_OFFSET2_9 (0x0000200UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000200 */ +#define ADC_OFR2_OFFSET2_10 (0x0000400UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000400 */ +#define ADC_OFR2_OFFSET2_11 (0x0000800UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000800 */ +#define ADC_OFR2_OFFSET2_12 (0x0001000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00001000 */ +#define ADC_OFR2_OFFSET2_13 (0x0002000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00002000 */ +#define ADC_OFR2_OFFSET2_14 (0x0004000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00004000 */ +#define ADC_OFR2_OFFSET2_15 (0x0008000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00008000 */ +#define ADC_OFR2_OFFSET2_16 (0x0010000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00010000 */ +#define ADC_OFR2_OFFSET2_17 (0x0020000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00020000 */ +#define ADC_OFR2_OFFSET2_18 (0x0040000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00040000 */ +#define ADC_OFR2_OFFSET2_19 (0x0080000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00080000 */ +#define ADC_OFR2_OFFSET2_20 (0x0100000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00100000 */ +#define ADC_OFR2_OFFSET2_21 (0x0200000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00200000 */ +#define ADC_OFR2_OFFSET2_22 (0x0400000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00400000 */ +#define ADC_OFR2_OFFSET2_23 (0x0800000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00800000 */ +#define ADC_OFR2_OFFSET2_24 (0x1000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x01000000 */ +#define ADC_OFR2_OFFSET2_25 (0x2000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x02000000 */ + +#define ADC_OFR2_OFFSET2_CH_Pos (26U) +#define ADC_OFR2_OFFSET2_CH_Msk (0x1FUL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC Channel selection for the data offset 2 */ +#define ADC_OFR2_OFFSET2_CH_0 (0x01UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR2_OFFSET2_CH_1 (0x02UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR2_OFFSET2_CH_2 (0x04UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR2_OFFSET2_CH_3 (0x08UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR2_OFFSET2_CH_4 (0x10UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR2_SSATE_Pos (31U) +#define ADC_OFR2_SSATE_Msk (0x1UL << ADC_OFR2_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR2_SSATE ADC_OFR2_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR2_OFFSET2_Pos (0U) +#define ADC3_OFR2_OFFSET2_Msk (0xFFFUL << ADC3_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR2_OFFSET2 ADC3_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR2_OFFSETPOS_Pos (24U) +#define ADC3_OFR2_OFFSETPOS_Msk (0x1UL << ADC3_OFR2_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR2_OFFSETPOS ADC3_OFR2_OFFSETPOS_Msk /*!< ADC offset number 2 positive */ +#define ADC3_OFR2_SATEN_Pos (25U) +#define ADC3_OFR2_SATEN_Msk (0x1UL << ADC3_OFR2_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR2_SATEN ADC3_OFR2_SATEN_Msk /*!< ADC offset number 2 saturation enable */ + +#define ADC3_OFR2_OFFSET2_EN_Pos (31U) +#define ADC3_OFR2_OFFSET2_EN_Msk (0x1UL << ADC3_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR2_OFFSET2_EN ADC3_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */ + +/******************** Bit definition for ADC_OFR3 register ********************/ +#define ADC_OFR3_OFFSET3_Pos (0U) +#define ADC_OFR3_OFFSET3_Msk (0x3FFFFFFUL << ADC_OFR3_OFFSET3_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET3_CH[4:0] */ +#define ADC_OFR3_OFFSET3_0 (0x0000001UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000001 */ +#define ADC_OFR3_OFFSET3_1 (0x0000002UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000002 */ +#define ADC_OFR3_OFFSET3_2 (0x0000004UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000004 */ +#define ADC_OFR3_OFFSET3_3 (0x0000008UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000008 */ +#define ADC_OFR3_OFFSET3_4 (0x0000010UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000010 */ +#define ADC_OFR3_OFFSET3_5 (0x0000020UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000020 */ +#define ADC_OFR3_OFFSET3_6 (0x0000040UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000040 */ +#define ADC_OFR3_OFFSET3_7 (0x0000080UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000080 */ +#define ADC_OFR3_OFFSET3_8 (0x0000100UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000100 */ +#define ADC_OFR3_OFFSET3_9 (0x0000200UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000200 */ +#define ADC_OFR3_OFFSET3_10 (0x0000400UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000400 */ +#define ADC_OFR3_OFFSET3_11 (0x0000800UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000800 */ +#define ADC_OFR3_OFFSET3_12 (0x0001000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00001000 */ +#define ADC_OFR3_OFFSET3_13 (0x0002000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00002000 */ +#define ADC_OFR3_OFFSET3_14 (0x0004000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00004000 */ +#define ADC_OFR3_OFFSET3_15 (0x0008000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00008000 */ +#define ADC_OFR3_OFFSET3_16 (0x0010000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00010000 */ +#define ADC_OFR3_OFFSET3_17 (0x0020000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00020000 */ +#define ADC_OFR3_OFFSET3_18 (0x0040000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00040000 */ +#define ADC_OFR3_OFFSET3_19 (0x0080000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00080000 */ +#define ADC_OFR3_OFFSET3_20 (0x0100000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00100000 */ +#define ADC_OFR3_OFFSET3_21 (0x0200000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00200000 */ +#define ADC_OFR3_OFFSET3_22 (0x0400000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00400000 */ +#define ADC_OFR3_OFFSET3_23 (0x0800000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00800000 */ +#define ADC_OFR3_OFFSET3_24 (0x1000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x01000000 */ +#define ADC_OFR3_OFFSET3_25 (0x2000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x02000000 */ + +#define ADC_OFR3_OFFSET3_CH_Pos (26U) +#define ADC_OFR3_OFFSET3_CH_Msk (0x1FUL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC Channel selection for the data offset 3 */ +#define ADC_OFR3_OFFSET3_CH_0 (0x01UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR3_OFFSET3_CH_1 (0x02UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR3_OFFSET3_CH_2 (0x04UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR3_OFFSET3_CH_3 (0x08UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR3_OFFSET3_CH_4 (0x10UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR3_SSATE_Pos (31U) +#define ADC_OFR3_SSATE_Msk (0x1UL << ADC_OFR3_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR3_SSATE ADC_OFR3_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR3_OFFSET3_Pos (0U) +#define ADC3_OFR3_OFFSET3_Msk (0xFFFUL << ADC3_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR3_OFFSET3 ADC3_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR3_OFFSETPOS_Pos (24U) +#define ADC3_OFR3_OFFSETPOS_Msk (0x1UL << ADC3_OFR3_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR3_OFFSETPOS ADC3_OFR3_OFFSETPOS_Msk /*!< ADC offset number 3 positive */ +#define ADC3_OFR3_SATEN_Pos (25U) +#define ADC3_OFR3_SATEN_Msk (0x1UL << ADC3_OFR3_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR3_SATEN ADC3_OFR3_SATEN_Msk /*!< ADC offset number 3 saturation enable */ + +#define ADC3_OFR3_OFFSET3_EN_Pos (31U) +#define ADC3_OFR3_OFFSET3_EN_Msk (0x1UL << ADC3_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR3_OFFSET3_EN ADC3_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */ + +/******************** Bit definition for ADC_OFR4 register ********************/ +#define ADC_OFR4_OFFSET4_Pos (0U) +#define ADC_OFR4_OFFSET4_Msk (0x3FFFFFFUL << ADC_OFR4_OFFSET4_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET4_CH[4:0] */ +#define ADC_OFR4_OFFSET4_0 (0x0000001UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000001 */ +#define ADC_OFR4_OFFSET4_1 (0x0000002UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000002 */ +#define ADC_OFR4_OFFSET4_2 (0x0000004UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000004 */ +#define ADC_OFR4_OFFSET4_3 (0x0000008UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000008 */ +#define ADC_OFR4_OFFSET4_4 (0x0000010UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000010 */ +#define ADC_OFR4_OFFSET4_5 (0x0000020UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000020 */ +#define ADC_OFR4_OFFSET4_6 (0x0000040UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000040 */ +#define ADC_OFR4_OFFSET4_7 (0x0000080UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000080 */ +#define ADC_OFR4_OFFSET4_8 (0x0000100UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000100 */ +#define ADC_OFR4_OFFSET4_9 (0x0000200UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000200 */ +#define ADC_OFR4_OFFSET4_10 (0x0000400UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000400 */ +#define ADC_OFR4_OFFSET4_11 (0x0000800UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000800 */ +#define ADC_OFR4_OFFSET4_12 (0x0001000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00001000 */ +#define ADC_OFR4_OFFSET4_13 (0x0002000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00002000 */ +#define ADC_OFR4_OFFSET4_14 (0x0004000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00004000 */ +#define ADC_OFR4_OFFSET4_15 (0x0008000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00008000 */ +#define ADC_OFR4_OFFSET4_16 (0x0010000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00010000 */ +#define ADC_OFR4_OFFSET4_17 (0x0020000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00020000 */ +#define ADC_OFR4_OFFSET4_18 (0x0040000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00040000 */ +#define ADC_OFR4_OFFSET4_19 (0x0080000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00080000 */ +#define ADC_OFR4_OFFSET4_20 (0x0100000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00100000 */ +#define ADC_OFR4_OFFSET4_21 (0x0200000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00200000 */ +#define ADC_OFR4_OFFSET4_22 (0x0400000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00400000 */ +#define ADC_OFR4_OFFSET4_23 (0x0800000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00800000 */ +#define ADC_OFR4_OFFSET4_24 (0x1000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x01000000 */ +#define ADC_OFR4_OFFSET4_25 (0x2000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x02000000 */ + +#define ADC_OFR4_OFFSET4_CH_Pos (26U) +#define ADC_OFR4_OFFSET4_CH_Msk (0x1FUL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC Channel selection for the data offset 4 */ +#define ADC_OFR4_OFFSET4_CH_0 (0x01UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR4_OFFSET4_CH_1 (0x02UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR4_OFFSET4_CH_2 (0x04UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR4_OFFSET4_CH_3 (0x08UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR4_OFFSET4_CH_4 (0x10UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR4_SSATE_Pos (31U) +#define ADC_OFR4_SSATE_Msk (0x1UL << ADC_OFR4_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR4_SSATE ADC_OFR4_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR4_OFFSET4_Pos (0U) +#define ADC3_OFR4_OFFSET4_Msk (0xFFFUL << ADC3_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR4_OFFSET4 ADC3_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR4_OFFSETPOS_Pos (24U) +#define ADC3_OFR4_OFFSETPOS_Msk (0x1UL << ADC3_OFR4_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR4_OFFSETPOS ADC3_OFR4_OFFSETPOS_Msk /*!< ADC offset number 4 positive */ +#define ADC3_OFR4_SATEN_Pos (25U) +#define ADC3_OFR4_SATEN_Msk (0x1UL << ADC3_OFR4_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR4_SATEN ADC3_OFR4_SATEN_Msk /*!< ADC offset number 4 saturation enable */ + +#define ADC3_OFR4_OFFSET4_EN_Pos (31U) +#define ADC3_OFR4_OFFSET4_EN_Msk (0x1UL << ADC3_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR4_OFFSET4_EN ADC3_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */ + +/******************** Bit definition for ADC_JDR1 register ********************/ +#define ADC_JDR1_JDATA_Pos (0U) +#define ADC_JDR1_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR1_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR1_JDATA_0 (0x00000001UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR1_JDATA_1 (0x00000002UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR1_JDATA_2 (0x00000004UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR1_JDATA_3 (0x00000008UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR1_JDATA_4 (0x00000010UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR1_JDATA_5 (0x00000020UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR1_JDATA_6 (0x00000040UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR1_JDATA_7 (0x00000080UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR1_JDATA_8 (0x00000100UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR1_JDATA_9 (0x00000200UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR1_JDATA_10 (0x00000400UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR1_JDATA_11 (0x00000800UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR1_JDATA_12 (0x00001000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR1_JDATA_13 (0x00002000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR1_JDATA_14 (0x00004000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR1_JDATA_15 (0x00008000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR1_JDATA_16 (0x00010000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR1_JDATA_17 (0x00020000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR1_JDATA_18 (0x00040000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR1_JDATA_19 (0x00080000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR1_JDATA_20 (0x00100000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR1_JDATA_21 (0x00200000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR1_JDATA_22 (0x00400000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR1_JDATA_23 (0x00800000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR1_JDATA_24 (0x01000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR1_JDATA_25 (0x02000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR1_JDATA_26 (0x04000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR1_JDATA_27 (0x08000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR1_JDATA_28 (0x10000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR1_JDATA_29 (0x20000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR1_JDATA_30 (0x40000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR1_JDATA_31 (0x80000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR2 register ********************/ +#define ADC_JDR2_JDATA_Pos (0U) +#define ADC_JDR2_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR2_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR2_JDATA_0 (0x00000001UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR2_JDATA_1 (0x00000002UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR2_JDATA_2 (0x00000004UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR2_JDATA_3 (0x00000008UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR2_JDATA_4 (0x00000010UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR2_JDATA_5 (0x00000020UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR2_JDATA_6 (0x00000040UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR2_JDATA_7 (0x00000080UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR2_JDATA_8 (0x00000100UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR2_JDATA_9 (0x00000200UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR2_JDATA_10 (0x00000400UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR2_JDATA_11 (0x00000800UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR2_JDATA_12 (0x00001000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR2_JDATA_13 (0x00002000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR2_JDATA_14 (0x00004000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR2_JDATA_15 (0x00008000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR2_JDATA_16 (0x00010000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR2_JDATA_17 (0x00020000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR2_JDATA_18 (0x00040000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR2_JDATA_19 (0x00080000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR2_JDATA_20 (0x00100000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR2_JDATA_21 (0x00200000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR2_JDATA_22 (0x00400000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR2_JDATA_23 (0x00800000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR2_JDATA_24 (0x01000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR2_JDATA_25 (0x02000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR2_JDATA_26 (0x04000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR2_JDATA_27 (0x08000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR2_JDATA_28 (0x10000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR2_JDATA_29 (0x20000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR2_JDATA_30 (0x40000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR2_JDATA_31 (0x80000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR3 register ********************/ +#define ADC_JDR3_JDATA_Pos (0U) +#define ADC_JDR3_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR3_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR3_JDATA_0 (0x00000001UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR3_JDATA_1 (0x00000002UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR3_JDATA_2 (0x00000004UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR3_JDATA_3 (0x00000008UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR3_JDATA_4 (0x00000010UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR3_JDATA_5 (0x00000020UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR3_JDATA_6 (0x00000040UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR3_JDATA_7 (0x00000080UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR3_JDATA_8 (0x00000100UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR3_JDATA_9 (0x00000200UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR3_JDATA_10 (0x00000400UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR3_JDATA_11 (0x00000800UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR3_JDATA_12 (0x00001000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR3_JDATA_13 (0x00002000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR3_JDATA_14 (0x00004000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR3_JDATA_15 (0x00008000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR3_JDATA_16 (0x00010000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR3_JDATA_17 (0x00020000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR3_JDATA_18 (0x00040000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR3_JDATA_19 (0x00080000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR3_JDATA_20 (0x00100000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR3_JDATA_21 (0x00200000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR3_JDATA_22 (0x00400000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR3_JDATA_23 (0x00800000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR3_JDATA_24 (0x01000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR3_JDATA_25 (0x02000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR3_JDATA_26 (0x04000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR3_JDATA_27 (0x08000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR3_JDATA_28 (0x10000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR3_JDATA_29 (0x20000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR3_JDATA_30 (0x40000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR3_JDATA_31 (0x80000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR4 register ********************/ +#define ADC_JDR4_JDATA_Pos (0U) +#define ADC_JDR4_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR4_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR4_JDATA_0 (0x00000001UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR4_JDATA_1 (0x00000002UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR4_JDATA_2 (0x00000004UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR4_JDATA_3 (0x00000008UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR4_JDATA_4 (0x00000010UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR4_JDATA_5 (0x00000020UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR4_JDATA_6 (0x00000040UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR4_JDATA_7 (0x00000080UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR4_JDATA_8 (0x00000100UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR4_JDATA_9 (0x00000200UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR4_JDATA_10 (0x00000400UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR4_JDATA_11 (0x00000800UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR4_JDATA_12 (0x00001000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR4_JDATA_13 (0x00002000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR4_JDATA_14 (0x00004000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR4_JDATA_15 (0x00008000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR4_JDATA_16 (0x00010000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR4_JDATA_17 (0x00020000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR4_JDATA_18 (0x00040000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR4_JDATA_19 (0x00080000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR4_JDATA_20 (0x00100000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR4_JDATA_21 (0x00200000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR4_JDATA_22 (0x00400000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR4_JDATA_23 (0x00800000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR4_JDATA_24 (0x01000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR4_JDATA_25 (0x02000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR4_JDATA_26 (0x04000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR4_JDATA_27 (0x08000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR4_JDATA_28 (0x10000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR4_JDATA_29 (0x20000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR4_JDATA_30 (0x40000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR4_JDATA_31 (0x80000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_AWD2CR register ********************/ +#define ADC_AWD2CR_AWD2CH_Pos (0U) +#define ADC_AWD2CR_AWD2CH_Msk (0xFFFFFUL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x000FFFFF */ +#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC Analog watchdog 2 channel selection */ +#define ADC_AWD2CR_AWD2CH_0 (0x00001UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD2CR_AWD2CH_1 (0x00002UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD2CR_AWD2CH_2 (0x00004UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD2CR_AWD2CH_3 (0x00008UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD2CR_AWD2CH_4 (0x00010UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD2CR_AWD2CH_5 (0x00020UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD2CR_AWD2CH_6 (0x00040UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD2CR_AWD2CH_7 (0x00080UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD2CR_AWD2CH_8 (0x00100UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD2CR_AWD2CH_9 (0x00200UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD2CR_AWD2CH_10 (0x00400UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD2CR_AWD2CH_11 (0x00800UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD2CR_AWD2CH_12 (0x01000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD2CR_AWD2CH_13 (0x02000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD2CR_AWD2CH_14 (0x04000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD2CR_AWD2CH_15 (0x08000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD2CR_AWD2CH_16 (0x10000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD2CR_AWD2CH_17 (0x20000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD2CR_AWD2CH_18 (0x40000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */ +#define ADC_AWD2CR_AWD2CH_19 (0x80000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_AWD3CR register ********************/ +#define ADC_AWD3CR_AWD3CH_Pos (0U) +#define ADC_AWD3CR_AWD3CH_Msk (0xFFFFFUL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x000FFFFF */ +#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC Analog watchdog 2 channel selection */ +#define ADC_AWD3CR_AWD3CH_0 (0x00001UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD3CR_AWD3CH_1 (0x00002UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD3CR_AWD3CH_2 (0x00004UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD3CR_AWD3CH_3 (0x00008UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD3CR_AWD3CH_4 (0x00010UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD3CR_AWD3CH_5 (0x00020UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD3CR_AWD3CH_6 (0x00040UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD3CR_AWD3CH_7 (0x00080UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD3CR_AWD3CH_8 (0x00100UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD3CR_AWD3CH_9 (0x00200UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD3CR_AWD3CH_10 (0x00400UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD3CR_AWD3CH_11 (0x00800UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD3CR_AWD3CH_12 (0x01000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD3CR_AWD3CH_13 (0x02000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD3CR_AWD3CH_14 (0x04000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD3CR_AWD3CH_15 (0x08000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD3CR_AWD3CH_16 (0x10000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD3CR_AWD3CH_17 (0x20000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD3CR_AWD3CH_18 (0x40000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */ +#define ADC_AWD3CR_AWD3CH_19 (0x80000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_DIFSEL register ********************/ +#define ADC_DIFSEL_DIFSEL_Pos (0U) +#define ADC_DIFSEL_DIFSEL_Msk (0xFFFFFUL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x000FFFFF */ +#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC differential modes for channels 1 to 18 */ +#define ADC_DIFSEL_DIFSEL_0 (0x00001UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */ +#define ADC_DIFSEL_DIFSEL_1 (0x00002UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */ +#define ADC_DIFSEL_DIFSEL_2 (0x00004UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */ +#define ADC_DIFSEL_DIFSEL_3 (0x00008UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */ +#define ADC_DIFSEL_DIFSEL_4 (0x00010UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */ +#define ADC_DIFSEL_DIFSEL_5 (0x00020UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */ +#define ADC_DIFSEL_DIFSEL_6 (0x00040UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */ +#define ADC_DIFSEL_DIFSEL_7 (0x00080UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */ +#define ADC_DIFSEL_DIFSEL_8 (0x00100UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */ +#define ADC_DIFSEL_DIFSEL_9 (0x00200UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */ +#define ADC_DIFSEL_DIFSEL_10 (0x00400UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */ +#define ADC_DIFSEL_DIFSEL_11 (0x00800UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */ +#define ADC_DIFSEL_DIFSEL_12 (0x01000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */ +#define ADC_DIFSEL_DIFSEL_13 (0x02000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */ +#define ADC_DIFSEL_DIFSEL_14 (0x04000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */ +#define ADC_DIFSEL_DIFSEL_15 (0x08000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */ +#define ADC_DIFSEL_DIFSEL_16 (0x10000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */ +#define ADC_DIFSEL_DIFSEL_17 (0x20000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */ +#define ADC_DIFSEL_DIFSEL_18 (0x40000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */ +#define ADC_DIFSEL_DIFSEL_19 (0x80000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_CALFACT register ********************/ +#define ADC_CALFACT_CALFACT_S_Pos (0U) +#define ADC_CALFACT_CALFACT_S_Msk (0x7FFUL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x000007FF */ +#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factors in single-ended mode */ +#define ADC_CALFACT_CALFACT_S_0 (0x001UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT_CALFACT_S_1 (0x002UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT_CALFACT_S_2 (0x004UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT_CALFACT_S_3 (0x008UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT_CALFACT_S_4 (0x010UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT_CALFACT_S_5 (0x020UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT_CALFACT_S_6 (0x040UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000040 */ +#define ADC_CALFACT_CALFACT_S_7 (0x080UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000080 */ +#define ADC_CALFACT_CALFACT_S_8 (0x100UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000100 */ +#define ADC_CALFACT_CALFACT_S_9 (0x200UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000200 */ +#define ADC_CALFACT_CALFACT_S_10 (0x400UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000400 */ +#define ADC_CALFACT_CALFACT_D_Pos (16U) +#define ADC_CALFACT_CALFACT_D_Msk (0x7FFUL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x07FF0000 */ +#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factors in differential mode */ +#define ADC_CALFACT_CALFACT_D_0 (0x001UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT_CALFACT_D_1 (0x002UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT_CALFACT_D_2 (0x004UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT_CALFACT_D_3 (0x008UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT_CALFACT_D_4 (0x010UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT_CALFACT_D_5 (0x020UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT_CALFACT_D_6 (0x040UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00400000 */ +#define ADC_CALFACT_CALFACT_D_7 (0x080UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00800000 */ +#define ADC_CALFACT_CALFACT_D_8 (0x100UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x01000000 */ +#define ADC_CALFACT_CALFACT_D_9 (0x200UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x02000000 */ +#define ADC_CALFACT_CALFACT_D_10 (0x400UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x04000000 */ + +/******************** Bit definition for ADC_CALFACT2 register ********************/ +#define ADC_CALFACT2_LINCALFACT_Pos (0U) +#define ADC_CALFACT2_LINCALFACT_Msk (0x3FFFFFFFUL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x3FFFFFFF */ +#define ADC_CALFACT2_LINCALFACT ADC_CALFACT2_LINCALFACT_Msk /*!< ADC Linearity calibration factors */ +#define ADC_CALFACT2_LINCALFACT_0 (0x00000001UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT2_LINCALFACT_1 (0x00000002UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT2_LINCALFACT_2 (0x00000004UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT2_LINCALFACT_3 (0x00000008UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT2_LINCALFACT_4 (0x00000010UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT2_LINCALFACT_5 (0x00000020UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT2_LINCALFACT_6 (0x00000040UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000040 */ +#define ADC_CALFACT2_LINCALFACT_7 (0x00000080UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000080 */ +#define ADC_CALFACT2_LINCALFACT_8 (0x00000100UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000100 */ +#define ADC_CALFACT2_LINCALFACT_9 (0x00000200UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000200 */ +#define ADC_CALFACT2_LINCALFACT_10 (0x00000400UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000400 */ +#define ADC_CALFACT2_LINCALFACT_11 (0x00000800UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000800 */ +#define ADC_CALFACT2_LINCALFACT_12 (0x00001000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00001000 */ +#define ADC_CALFACT2_LINCALFACT_13 (0x00002000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00002000 */ +#define ADC_CALFACT2_LINCALFACT_14 (0x00004000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00004000 */ +#define ADC_CALFACT2_LINCALFACT_15 (0x00008000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00008000 */ +#define ADC_CALFACT2_LINCALFACT_16 (0x00010000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT2_LINCALFACT_17 (0x00020000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT2_LINCALFACT_18 (0x00040000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT2_LINCALFACT_19 (0x00080000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT2_LINCALFACT_20 (0x00100000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT2_LINCALFACT_21 (0x00200000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT2_LINCALFACT_22 (0x00400000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00400000 */ +#define ADC_CALFACT2_LINCALFACT_23 (0x00800000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00800000 */ +#define ADC_CALFACT2_LINCALFACT_24 (0x01000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x01000000 */ +#define ADC_CALFACT2_LINCALFACT_25 (0x02000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x02000000 */ +#define ADC_CALFACT2_LINCALFACT_26 (0x04000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x04000000 */ +#define ADC_CALFACT2_LINCALFACT_27 (0x08000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x08000000 */ +#define ADC_CALFACT2_LINCALFACT_28 (0x10000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x10000000 */ +#define ADC_CALFACT2_LINCALFACT_29 (0x20000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x20000000 */ + +/************************* ADC Common registers *****************************/ +/******************** Bit definition for ADC_CSR register ********************/ +#define ADC_CSR_ADRDY_MST_Pos (0U) +#define ADC_CSR_ADRDY_MST_Msk (0x1UL << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */ +#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< Master ADC ready */ +#define ADC_CSR_EOSMP_MST_Pos (1U) +#define ADC_CSR_EOSMP_MST_Msk (0x1UL << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */ +#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< End of sampling phase flag of the master ADC */ +#define ADC_CSR_EOC_MST_Pos (2U) +#define ADC_CSR_EOC_MST_Msk (0x1UL << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */ +#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< End of regular conversion of the master ADC */ +#define ADC_CSR_EOS_MST_Pos (3U) +#define ADC_CSR_EOS_MST_Msk (0x1UL << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */ +#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< End of regular sequence flag of the master ADC */ +#define ADC_CSR_OVR_MST_Pos (4U) +#define ADC_CSR_OVR_MST_Msk (0x1UL << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */ +#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< Overrun flag of the master ADC */ +#define ADC_CSR_JEOC_MST_Pos (5U) +#define ADC_CSR_JEOC_MST_Msk (0x1UL << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */ +#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< End of injected conversion of the master ADC */ +#define ADC_CSR_JEOS_MST_Pos (6U) +#define ADC_CSR_JEOS_MST_Msk (0x1UL << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */ +#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< End of injected sequence flag of the master ADC */ +#define ADC_CSR_AWD1_MST_Pos (7U) +#define ADC_CSR_AWD1_MST_Msk (0x1UL << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */ +#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< Analog watchdog 1 flag of the master ADC */ +#define ADC_CSR_AWD2_MST_Pos (8U) +#define ADC_CSR_AWD2_MST_Msk (0x1UL << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */ +#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< Analog watchdog 2 flag of the master ADC */ +#define ADC_CSR_AWD3_MST_Pos (9U) +#define ADC_CSR_AWD3_MST_Msk (0x1UL << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */ +#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< Analog watchdog 3 flag of the master ADC */ +#define ADC_CSR_JQOVF_MST_Pos (10U) +#define ADC_CSR_JQOVF_MST_Msk (0x1UL << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */ +#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< Injected context queue overflow flag of the master ADC */ +#define ADC_CSR_ADRDY_SLV_Pos (16U) +#define ADC_CSR_ADRDY_SLV_Msk (0x1UL << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< Slave ADC ready */ +#define ADC_CSR_EOSMP_SLV_Pos (17U) +#define ADC_CSR_EOSMP_SLV_Msk (0x1UL << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< End of sampling phase flag of the slave ADC */ +#define ADC_CSR_EOC_SLV_Pos (18U) +#define ADC_CSR_EOC_SLV_Msk (0x1UL << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< End of regular conversion of the slave ADC */ +#define ADC_CSR_EOS_SLV_Pos (19U) +#define ADC_CSR_EOS_SLV_Msk (0x1UL << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< End of regular sequence flag of the slave ADC */ +#define ADC_CSR_OVR_SLV_Pos (20U) +#define ADC_CSR_OVR_SLV_Msk (0x1UL << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< Overrun flag of the slave ADC */ +#define ADC_CSR_JEOC_SLV_Pos (21U) +#define ADC_CSR_JEOC_SLV_Msk (0x1UL << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< End of injected conversion of the slave ADC */ +#define ADC_CSR_JEOS_SLV_Pos (22U) +#define ADC_CSR_JEOS_SLV_Msk (0x1UL << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< End of injected sequence flag of the slave ADC */ +#define ADC_CSR_AWD1_SLV_Pos (23U) +#define ADC_CSR_AWD1_SLV_Msk (0x1UL << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< Analog watchdog 1 flag of the slave ADC */ +#define ADC_CSR_AWD2_SLV_Pos (24U) +#define ADC_CSR_AWD2_SLV_Msk (0x1UL << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< Analog watchdog 2 flag of the slave ADC */ +#define ADC_CSR_AWD3_SLV_Pos (25U) +#define ADC_CSR_AWD3_SLV_Msk (0x1UL << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< Analog watchdog 3 flag of the slave ADC */ +#define ADC_CSR_JQOVF_SLV_Pos (26U) +#define ADC_CSR_JQOVF_SLV_Msk (0x1UL << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< Injected context queue overflow flag of the slave ADC */ + +/******************** Bit definition for ADC_CCR register ********************/ +#define ADC_CCR_DUAL_Pos (0U) +#define ADC_CCR_DUAL_Msk (0x1FUL << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */ +#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< Dual ADC mode selection */ +#define ADC_CCR_DUAL_0 (0x01UL << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */ +#define ADC_CCR_DUAL_1 (0x02UL << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */ +#define ADC_CCR_DUAL_2 (0x04UL << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */ +#define ADC_CCR_DUAL_3 (0x08UL << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */ +#define ADC_CCR_DUAL_4 (0x10UL << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */ + +#define ADC_CCR_DELAY_Pos (8U) +#define ADC_CCR_DELAY_Msk (0xFUL << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */ +#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< Delay between 2 sampling phases */ +#define ADC_CCR_DELAY_0 (0x1UL << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */ +#define ADC_CCR_DELAY_1 (0x2UL << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */ +#define ADC_CCR_DELAY_2 (0x4UL << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */ +#define ADC_CCR_DELAY_3 (0x8UL << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */ + + +#define ADC_CCR_DAMDF_Pos (14U) +#define ADC_CCR_DAMDF_Msk (0x3UL << ADC_CCR_DAMDF_Pos) /*!< 0x0000C000 */ +#define ADC_CCR_DAMDF ADC_CCR_DAMDF_Msk /*!< Dual ADC mode Data format */ +#define ADC_CCR_DAMDF_0 (0x1UL << ADC_CCR_DAMDF_Pos) /*!< 0x00004000 */ +#define ADC_CCR_DAMDF_1 (0x2UL << ADC_CCR_DAMDF_Pos) /*!< 0x00008000 */ + +#define ADC_CCR_CKMODE_Pos (16U) +#define ADC_CCR_CKMODE_Msk (0x3UL << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */ +#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC clock mode */ +#define ADC_CCR_CKMODE_0 (0x1UL << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */ +#define ADC_CCR_CKMODE_1 (0x2UL << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */ + +#define ADC_CCR_PRESC_Pos (18U) +#define ADC_CCR_PRESC_Msk (0xFUL << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */ +#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC prescaler */ +#define ADC_CCR_PRESC_0 (0x1UL << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */ +#define ADC_CCR_PRESC_1 (0x2UL << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */ +#define ADC_CCR_PRESC_2 (0x4UL << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */ +#define ADC_CCR_PRESC_3 (0x8UL << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */ + +#define ADC_CCR_VREFEN_Pos (22U) +#define ADC_CCR_VREFEN_Msk (0x1UL << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */ +#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< VREFINT enable */ +#define ADC_CCR_TSEN_Pos (23U) +#define ADC_CCR_TSEN_Msk (0x1UL << ADC_CCR_TSEN_Pos) /*!< 0x00800000 */ +#define ADC_CCR_TSEN ADC_CCR_TSEN_Msk /*!< Temperature sensor enable */ +#define ADC_CCR_VBATEN_Pos (24U) +#define ADC_CCR_VBATEN_Msk (0x1UL << ADC_CCR_VBATEN_Pos) /*!< 0x01000000 */ +#define ADC_CCR_VBATEN ADC_CCR_VBATEN_Msk /*!< VBAT enable */ + +/******************** Bit definition for ADC_CDR register *******************/ +#define ADC_CDR_RDATA_MST_Pos (0U) +#define ADC_CDR_RDATA_MST_Msk (0xFFFFUL << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */ +#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */ + +#define ADC_CDR_RDATA_SLV_Pos (16U) +#define ADC_CDR_RDATA_SLV_Msk (0xFFFFUL << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */ +#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */ + +/******************** Bit definition for ADC_CDR2 register ******************/ +#define ADC_CDR2_RDATA_ALT_Pos (0U) +#define ADC_CDR2_RDATA_ALT_Msk (0xFFFFFFFFUL << ADC_CDR2_RDATA_ALT_Pos) /*!< 0xFFFFFFFF */ +#define ADC_CDR2_RDATA_ALT ADC_CDR2_RDATA_ALT_Msk /*!< Regular data of the master/slave alternated ADCs */ + + +/******************************************************************************/ +/* */ +/* VREFBUF */ +/* */ +/******************************************************************************/ +/******************* Bit definition for VREFBUF_CSR register ****************/ +#define VREFBUF_CSR_ENVR_Pos (0U) +#define VREFBUF_CSR_ENVR_Msk (0x1UL << VREFBUF_CSR_ENVR_Pos) /*!< 0x00000001 */ +#define VREFBUF_CSR_ENVR VREFBUF_CSR_ENVR_Msk /*!*/ +#define DAC_CR_CEN1_Pos (14U) +#define DAC_CR_CEN1_Msk (0x1UL << DAC_CR_CEN1_Pos) /*!< 0x00004000 */ +#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/ + +#define DAC_CR_EN2_Pos (16U) +#define DAC_CR_EN2_Msk (0x1UL << DAC_CR_EN2_Pos) /*!< 0x00010000 */ +#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/ +#define DAC_CR_CEN2_Pos (30U) +#define DAC_CR_CEN2_Msk (0x1UL << DAC_CR_CEN2_Pos) /*!< 0x40000000 */ +#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/ + +/***************** Bit definition for DAC_SWTRIGR register ******************/ +#define DAC_SWTRIGR_SWTRIG1_Pos (0U) +#define DAC_SWTRIGR_SWTRIG1_Msk (0x1UL << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */ +#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*!
© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.
+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS_Device + * @{ + */ + +/** @addtogroup stm32h735xx + * @{ + */ + +#ifndef STM32H735xx_H +#define STM32H735xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32H7XX Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum +{ +/****** Cortex-M Processor Exceptions Numbers *****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 4 Cortex-M Memory Management Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt ( wwdg1_it, wwdg2_it) */ + PVD_AVD_IRQn = 1, /*!< PVD/AVD through EXTI Line detection Interrupt */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */ + DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */ + DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */ + DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */ + DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */ + DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */ + DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ + ADC_IRQn = 18, /*!< ADC1 and ADC2 global Interrupts */ + FDCAN1_IT0_IRQn = 19, /*!< FDCAN1 Interrupt line 0 */ + FDCAN2_IT0_IRQn = 20, /*!< FDCAN2 Interrupt line 0 */ + FDCAN1_IT1_IRQn = 21, /*!< FDCAN1 Interrupt line 1 */ + FDCAN2_IT1_IRQn = 22, /*!< FDCAN2 Interrupt line 1 */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */ + TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ + TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */ + TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */ + TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */ + FMC_IRQn = 48, /*!< FMC global Interrupt */ + SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */ + DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */ + DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */ + DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */ + DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ + ETH_IRQn = 61, /*!< Ethernet global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ + FDCAN_CAL_IRQn = 63, /*!< FDCAN Calibration unit Interrupt */ + DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */ + DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */ + DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */ + USART6_IRQn = 71, /*!< USART6 global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */ + OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */ + OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */ + OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */ + DCMI_PSSI_IRQn = 78, /*!< DCMI and PSSI global interrupt */ + CRYP_IRQn = 79, /*!< CRYP crypto global interrupt */ + HASH_RNG_IRQn = 80, /*!< HASH and RNG global interrupt */ + FPU_IRQn = 81, /*!< FPU global interrupt */ + UART7_IRQn = 82, /*!< UART7 global interrupt */ + UART8_IRQn = 83, /*!< UART8 global interrupt */ + SPI4_IRQn = 84, /*!< SPI4 global Interrupt */ + SPI5_IRQn = 85, /*!< SPI5 global Interrupt */ + SPI6_IRQn = 86, /*!< SPI6 global Interrupt */ + SAI1_IRQn = 87, /*!< SAI1 global Interrupt */ + LTDC_IRQn = 88, /*!< LTDC global Interrupt */ + LTDC_ER_IRQn = 89, /*!< LTDC Error global Interrupt */ + DMA2D_IRQn = 90, /*!< DMA2D global Interrupt */ + OCTOSPI1_IRQn = 92, /*!< OCTOSPI1 global interrupt */ + LPTIM1_IRQn = 93, /*!< LP TIM1 interrupt */ + CEC_IRQn = 94, /*!< HDMI-CEC global Interrupt */ + I2C4_EV_IRQn = 95, /*!< I2C4 Event Interrupt */ + I2C4_ER_IRQn = 96, /*!< I2C4 Error Interrupt */ + SPDIF_RX_IRQn = 97, /*!< SPDIF-RX global Interrupt */ + DMAMUX1_OVR_IRQn = 102, /*! + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC Interrupt and Status Register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< ADC Interrupt Enable Register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< ADC Configuration register, Address offset: 0x0C */ + __IO uint32_t CFGR2; /*!< ADC Configuration register 2, Address offset: 0x10 */ + __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x14 */ + __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x18 */ + __IO uint32_t PCSEL_RES0; /*!< Rserved for ADC3, ADC1/2 pre-channel selection, Address offset: 0x1C */ + __IO uint32_t LTR1_TR1; /*!< ADC watchdog Lower threshold register 1, Address offset: 0x20 */ + __IO uint32_t HTR1_TR2; /*!< ADC watchdog higher threshold register 1, Address offset: 0x24 */ + __IO uint32_t RES1_TR3; /*!< Rserved for ADC1/2, ADC3 threshold register, Address offset: 0x28 */ + uint32_t RESERVED2; /*!< Reserved, 0x02C */ + __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x30 */ + __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x34 */ + __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x38 */ + __IO uint32_t SQR4; /*!< ADC regular sequence register 4, Address offset: 0x3C */ + __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x40 */ + uint32_t RESERVED3; /*!< Reserved, 0x044 */ + uint32_t RESERVED4; /*!< Reserved, 0x048 */ + __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x4C */ + uint32_t RESERVED5[4]; /*!< Reserved, 0x050 - 0x05C */ + __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */ + __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */ + __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */ + __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */ + uint32_t RESERVED6[4]; /*!< Reserved, 0x070 - 0x07C */ + __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x80 */ + __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x84 */ + __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x88 */ + __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x8C */ + uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */ + __IO uint32_t AWD2CR; /*!< ADC Analog Watchdog 2 Configuration Register, Address offset: 0xA0 */ + __IO uint32_t AWD3CR; /*!< ADC Analog Watchdog 3 Configuration Register, Address offset: 0xA4 */ + uint32_t RESERVED8; /*!< Reserved, 0x0A8 */ + uint32_t RESERVED9; /*!< Reserved, 0x0AC */ + __IO uint32_t LTR2_DIFSEL; /*!< ADC watchdog Lower threshold register 2, Difsel for ADC3, Address offset: 0xB0 */ + __IO uint32_t HTR2_CALFACT; /*!< ADC watchdog Higher threshold register 2, Calfact for ADC3, Address offset: 0xB4 */ + __IO uint32_t LTR3_RES10; /*!< ADC watchdog Lower threshold register 3, specific ADC1/2, Address offset: 0xB8 */ + __IO uint32_t HTR3_RES11; /*!< ADC watchdog Higher threshold register 3, specific ADC1/2, Address offset: 0xBC */ + __IO uint32_t DIFSEL_RES12; /*!< ADC Differential Mode Selection Register specific ADC1/2, Address offset: 0xC0 */ + __IO uint32_t CALFACT_RES13; /*!< ADC Calibration Factors specific ADC1/2, Address offset: 0xC4 */ + __IO uint32_t CALFACT2_RES14; /*!< ADC Linearity Calibration Factors specific ADC1/2, Address offset: 0xC8 */ +} ADC_TypeDef; + + +typedef struct +{ +__IO uint32_t CSR; /*!< ADC Common status register, Address offset: ADC1/3 base address + 0x300 */ +uint32_t RESERVED; /*!< Reserved, ADC1/3 base address + 0x304 */ +__IO uint32_t CCR; /*!< ADC common control register, Address offset: ADC1/3 base address + 0x308 */ +__IO uint32_t CDR; /*!< ADC common regular data register for dual Address offset: ADC1/3 base address + 0x30C */ +__IO uint32_t CDR2; /*!< ADC common regular data register for 32-bit dual mode Address offset: ADC1/3 base address + 0x310 */ + +} ADC_Common_TypeDef; + + +/** + * @brief VREFBUF + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */ + __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */ +} VREFBUF_TypeDef; + + +/** + * @brief FD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t CREL; /*!< FDCAN Core Release register, Address offset: 0x000 */ + __IO uint32_t ENDN; /*!< FDCAN Endian register, Address offset: 0x004 */ + __IO uint32_t RESERVED1; /*!< Reserved, 0x008 */ + __IO uint32_t DBTP; /*!< FDCAN Data Bit Timing & Prescaler register, Address offset: 0x00C */ + __IO uint32_t TEST; /*!< FDCAN Test register, Address offset: 0x010 */ + __IO uint32_t RWD; /*!< FDCAN RAM Watchdog register, Address offset: 0x014 */ + __IO uint32_t CCCR; /*!< FDCAN CC Control register, Address offset: 0x018 */ + __IO uint32_t NBTP; /*!< FDCAN Nominal Bit Timing & Prescaler register, Address offset: 0x01C */ + __IO uint32_t TSCC; /*!< FDCAN Timestamp Counter Configuration register, Address offset: 0x020 */ + __IO uint32_t TSCV; /*!< FDCAN Timestamp Counter Value register, Address offset: 0x024 */ + __IO uint32_t TOCC; /*!< FDCAN Timeout Counter Configuration register, Address offset: 0x028 */ + __IO uint32_t TOCV; /*!< FDCAN Timeout Counter Value register, Address offset: 0x02C */ + __IO uint32_t RESERVED2[4]; /*!< Reserved, 0x030 - 0x03C */ + __IO uint32_t ECR; /*!< FDCAN Error Counter register, Address offset: 0x040 */ + __IO uint32_t PSR; /*!< FDCAN Protocol Status register, Address offset: 0x044 */ + __IO uint32_t TDCR; /*!< FDCAN Transmitter Delay Compensation register, Address offset: 0x048 */ + __IO uint32_t RESERVED3; /*!< Reserved, 0x04C */ + __IO uint32_t IR; /*!< FDCAN Interrupt register, Address offset: 0x050 */ + __IO uint32_t IE; /*!< FDCAN Interrupt Enable register, Address offset: 0x054 */ + __IO uint32_t ILS; /*!< FDCAN Interrupt Line Select register, Address offset: 0x058 */ + __IO uint32_t ILE; /*!< FDCAN Interrupt Line Enable register, Address offset: 0x05C */ + __IO uint32_t RESERVED4[8]; /*!< Reserved, 0x060 - 0x07C */ + __IO uint32_t GFC; /*!< FDCAN Global Filter Configuration register, Address offset: 0x080 */ + __IO uint32_t SIDFC; /*!< FDCAN Standard ID Filter Configuration register, Address offset: 0x084 */ + __IO uint32_t XIDFC; /*!< FDCAN Extended ID Filter Configuration register, Address offset: 0x088 */ + __IO uint32_t RESERVED5; /*!< Reserved, 0x08C */ + __IO uint32_t XIDAM; /*!< FDCAN Extended ID AND Mask register, Address offset: 0x090 */ + __IO uint32_t HPMS; /*!< FDCAN High Priority Message Status register, Address offset: 0x094 */ + __IO uint32_t NDAT1; /*!< FDCAN New Data 1 register, Address offset: 0x098 */ + __IO uint32_t NDAT2; /*!< FDCAN New Data 2 register, Address offset: 0x09C */ + __IO uint32_t RXF0C; /*!< FDCAN Rx FIFO 0 Configuration register, Address offset: 0x0A0 */ + __IO uint32_t RXF0S; /*!< FDCAN Rx FIFO 0 Status register, Address offset: 0x0A4 */ + __IO uint32_t RXF0A; /*!< FDCAN Rx FIFO 0 Acknowledge register, Address offset: 0x0A8 */ + __IO uint32_t RXBC; /*!< FDCAN Rx Buffer Configuration register, Address offset: 0x0AC */ + __IO uint32_t RXF1C; /*!< FDCAN Rx FIFO 1 Configuration register, Address offset: 0x0B0 */ + __IO uint32_t RXF1S; /*!< FDCAN Rx FIFO 1 Status register, Address offset: 0x0B4 */ + __IO uint32_t RXF1A; /*!< FDCAN Rx FIFO 1 Acknowledge register, Address offset: 0x0B8 */ + __IO uint32_t RXESC; /*!< FDCAN Rx Buffer/FIFO Element Size Configuration register, Address offset: 0x0BC */ + __IO uint32_t TXBC; /*!< FDCAN Tx Buffer Configuration register, Address offset: 0x0C0 */ + __IO uint32_t TXFQS; /*!< FDCAN Tx FIFO/Queue Status register, Address offset: 0x0C4 */ + __IO uint32_t TXESC; /*!< FDCAN Tx Buffer Element Size Configuration register, Address offset: 0x0C8 */ + __IO uint32_t TXBRP; /*!< FDCAN Tx Buffer Request Pending register, Address offset: 0x0CC */ + __IO uint32_t TXBAR; /*!< FDCAN Tx Buffer Add Request register, Address offset: 0x0D0 */ + __IO uint32_t TXBCR; /*!< FDCAN Tx Buffer Cancellation Request register, Address offset: 0x0D4 */ + __IO uint32_t TXBTO; /*!< FDCAN Tx Buffer Transmission Occurred register, Address offset: 0x0D8 */ + __IO uint32_t TXBCF; /*!< FDCAN Tx Buffer Cancellation Finished register, Address offset: 0x0DC */ + __IO uint32_t TXBTIE; /*!< FDCAN Tx Buffer Transmission Interrupt Enable register, Address offset: 0x0E0 */ + __IO uint32_t TXBCIE; /*!< FDCAN Tx Buffer Cancellation Finished Interrupt Enable register, Address offset: 0x0E4 */ + __IO uint32_t RESERVED6[2]; /*!< Reserved, 0x0E8 - 0x0EC */ + __IO uint32_t TXEFC; /*!< FDCAN Tx Event FIFO Configuration register, Address offset: 0x0F0 */ + __IO uint32_t TXEFS; /*!< FDCAN Tx Event FIFO Status register, Address offset: 0x0F4 */ + __IO uint32_t TXEFA; /*!< FDCAN Tx Event FIFO Acknowledge register, Address offset: 0x0F8 */ + __IO uint32_t RESERVED7; /*!< Reserved, 0x0FC */ +} FDCAN_GlobalTypeDef; + +/** + * @brief TTFD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t TTTMC; /*!< TT Trigger Memory Configuration register, Address offset: 0x100 */ + __IO uint32_t TTRMC; /*!< TT Reference Message Configuration register, Address offset: 0x104 */ + __IO uint32_t TTOCF; /*!< TT Operation Configuration register, Address offset: 0x108 */ + __IO uint32_t TTMLM; /*!< TT Matrix Limits register, Address offset: 0x10C */ + __IO uint32_t TURCF; /*!< TUR Configuration register, Address offset: 0x110 */ + __IO uint32_t TTOCN; /*!< TT Operation Control register, Address offset: 0x114 */ + __IO uint32_t TTGTP; /*!< TT Global Time Preset register, Address offset: 0x118 */ + __IO uint32_t TTTMK; /*!< TT Time Mark register, Address offset: 0x11C */ + __IO uint32_t TTIR; /*!< TT Interrupt register, Address offset: 0x120 */ + __IO uint32_t TTIE; /*!< TT Interrupt Enable register, Address offset: 0x124 */ + __IO uint32_t TTILS; /*!< TT Interrupt Line Select register, Address offset: 0x128 */ + __IO uint32_t TTOST; /*!< TT Operation Status register, Address offset: 0x12C */ + __IO uint32_t TURNA; /*!< TT TUR Numerator Actual register, Address offset: 0x130 */ + __IO uint32_t TTLGT; /*!< TT Local and Global Time register, Address offset: 0x134 */ + __IO uint32_t TTCTC; /*!< TT Cycle Time and Count register, Address offset: 0x138 */ + __IO uint32_t TTCPT; /*!< TT Capture Time register, Address offset: 0x13C */ + __IO uint32_t TTCSM; /*!< TT Cycle Sync Mark register, Address offset: 0x140 */ + __IO uint32_t RESERVED1[111]; /*!< Reserved, 0x144 - 0x2FC */ + __IO uint32_t TTTS; /*!< TT Trigger Select register, Address offset: 0x300 */ +} TTCAN_TypeDef; + +/** + * @brief FD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t CREL; /*!< Clock Calibration Unit Core Release register, Address offset: 0x00 */ + __IO uint32_t CCFG; /*!< Calibration Configuration register, Address offset: 0x04 */ + __IO uint32_t CSTAT; /*!< Calibration Status register, Address offset: 0x08 */ + __IO uint32_t CWD; /*!< Calibration Watchdog register, Address offset: 0x0C */ + __IO uint32_t IR; /*!< CCU Interrupt register, Address offset: 0x10 */ + __IO uint32_t IE; /*!< CCU Interrupt Enable register, Address offset: 0x14 */ +} FDCAN_ClockCalibrationUnit_TypeDef; + + +/** + * @brief Consumer Electronics Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CEC control register, Address offset:0x00 */ + __IO uint32_t CFGR; /*!< CEC configuration register, Address offset:0x04 */ + __IO uint32_t TXDR; /*!< CEC Tx data register , Address offset:0x08 */ + __IO uint32_t RXDR; /*!< CEC Rx Data Register, Address offset:0x0C */ + __IO uint32_t ISR; /*!< CEC Interrupt and Status Register, Address offset:0x10 */ + __IO uint32_t IER; /*!< CEC interrupt enable register, Address offset:0x14 */ +}CEC_TypeDef; + +/** + * @brief COordincate Rotation DIgital Computer + */ +typedef struct +{ + __IO uint32_t CSR; /*!< CORDIC control and status register, Address offset: 0x00 */ + __IO uint32_t WDATA; /*!< CORDIC argument register, Address offset: 0x04 */ + __IO uint32_t RDATA; /*!< CORDIC result register, Address offset: 0x08 */ +} CORDIC_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint32_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ +} CRC_TypeDef; + + +/** + * @brief Clock Recovery System + */ +typedef struct +{ +__IO uint32_t CR; /*!< CRS ccontrol register, Address offset: 0x00 */ +__IO uint32_t CFGR; /*!< CRS configuration register, Address offset: 0x04 */ +__IO uint32_t ISR; /*!< CRS interrupt and status register, Address offset: 0x08 */ +__IO uint32_t ICR; /*!< CRS interrupt flag clear register, Address offset: 0x0C */ +} CRS_TypeDef; + + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ + __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */ + __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */ + __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */ + __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */ + __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */ + __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */ +} DAC_TypeDef; + +/** + * @brief DFSDM module registers + */ +typedef struct +{ + __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */ + __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */ + __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */ + __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */ + __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */ + __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */ + __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */ + __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */ + __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */ + __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */ + __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */ + __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */ + __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */ + __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */ + __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */ +} DFSDM_Filter_TypeDef; + +/** + * @brief DFSDM channel configuration registers + */ +typedef struct +{ + __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */ + __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */ + __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and + short circuit detector register, Address offset: 0x08 */ + __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */ + __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */ +} DFSDM_Channel_TypeDef; + +/** + * @brief Debug MCU + */ +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + uint32_t RESERVED4[11]; /*!< Reserved, Address offset: 0x08 */ + __IO uint32_t APB3FZ1; /*!< Debug MCU APB3FZ1 freeze register, Address offset: 0x34 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x38 */ + __IO uint32_t APB1LFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x3C */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x40 */ + __IO uint32_t APB1HFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x44 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x48 */ + __IO uint32_t APB2FZ1; /*!< Debug MCU APB2FZ1 freeze register, Address offset: 0x4C */ + uint32_t RESERVED8; /*!< Reserved, Address offset: 0x50 */ + __IO uint32_t APB4FZ1; /*!< Debug MCU APB4FZ1 freeze register, Address offset: 0x54 */ + __IO uint32_t RESERVED9[990]; /*!< Reserved, Address offset: 0x58-0xFCC */ + __IO uint32_t PIDR4; /*!< Debug MCU peripheral identity register 4, Address offset: 0xFD0 */ + __IO uint32_t RESERVED10[3];/*!< Reserved, Address offset: 0xFD4-0xFDC */ + __IO uint32_t PIDR0; /*!< Debug MCU peripheral identity register 0, Address offset: 0xFE0 */ + __IO uint32_t PIDR1; /*!< Debug MCU peripheral identity register 1, Address offset: 0xFE4 */ + __IO uint32_t PIDR2; /*!< Debug MCU peripheral identity register 2, Address offset: 0xFE8 */ + __IO uint32_t PIDR3; /*!< Debug MCU peripheral identity register 3, Address offset: 0xFEC */ + __IO uint32_t CIDR0; /*!< Debug MCU component identity register 0, Address offset: 0xFF0 */ + __IO uint32_t CIDR1; /*!< Debug MCU component identity register 1, Address offset: 0xFF4 */ + __IO uint32_t CIDR2; /*!< Debug MCU component identity register 2, Address offset: 0xFF8 */ + __IO uint32_t CIDR3; /*!< Debug MCU component identity register 3, Address offset: 0xFFC */ +}DBGMCU_TypeDef; +/** + * @brief DCMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */ + __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */ + __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */ + __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */ + __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */ + __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */ + __IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */ + __IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */ + __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */ + __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */ + __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */ +} DCMI_TypeDef; + +/** + * @brief PSSI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< PSSI control register 1, Address offset: 0x000 */ + __IO uint32_t SR; /*!< PSSI status register, Address offset: 0x004 */ + __IO uint32_t RIS; /*!< PSSI raw interrupt status register, Address offset: 0x008 */ + __IO uint32_t IER; /*!< PSSI interrupt enable register, Address offset: 0x00C */ + __IO uint32_t MIS; /*!< PSSI masked interrupt status register, Address offset: 0x010 */ + __IO uint32_t ICR; /*!< PSSI interrupt clear register, Address offset: 0x014 */ + __IO uint32_t RESERVED1[4]; /*!< Reserved, 0x018 - 0x024 */ + __IO uint32_t DR; /*!< PSSI data register, Address offset: 0x028 */ + __IO uint32_t RESERVED2[241]; /*!< Reserved, 0x02C - 0x3EC */ + __IO uint32_t HWCFGR; /*!< PSSI IP HW configuration register, Address offset: 0x3F0 */ + __IO uint32_t VERR; /*!< PSSI IP version register, Address offset: 0x3F4 */ + __IO uint32_t IPIDR; /*!< PSSI IP ID register, Address offset: 0x3F8 */ + __IO uint32_t SIDR; /*!< PSSI SIZE ID register, Address offset: 0x3FC */ +} PSSI_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA stream x configuration register */ + __IO uint32_t NDTR; /*!< DMA stream x number of data register */ + __IO uint32_t PAR; /*!< DMA stream x peripheral address register */ + __IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */ + __IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */ + __IO uint32_t FCR; /*!< DMA stream x FIFO control register */ +} DMA_Stream_TypeDef; + +typedef struct +{ + __IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */ + __IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */ + __IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */ + __IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */ +} DMA_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CM0AR; /*!< DMA channel x memory 0 address register */ + __IO uint32_t CM1AR; /*!< DMA channel x memory 1 address register */ +} BDMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} BDMA_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA Multiplexer Channel x Control Register */ +}DMAMUX_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< DMA Channel Status Register */ + __IO uint32_t CFR; /*!< DMA Channel Clear Flag Register */ +}DMAMUX_ChannelStatus_TypeDef; + +typedef struct +{ + __IO uint32_t RGCR; /*!< DMA Request Generator x Control Register */ +}DMAMUX_RequestGen_TypeDef; + +typedef struct +{ + __IO uint32_t RGSR; /*!< DMA Request Generator Status Register */ + __IO uint32_t RGCFR; /*!< DMA Request Generator Clear Flag Register */ +}DMAMUX_RequestGenStatus_TypeDef; + +/** + * @brief MDMA Controller + */ +typedef struct +{ + __IO uint32_t GISR0; /*!< MDMA Global Interrupt/Status Register 0, Address offset: 0x00 */ +}MDMA_TypeDef; + +typedef struct +{ + __IO uint32_t CISR; /*!< MDMA channel x interrupt/status register, Address offset: 0x40 */ + __IO uint32_t CIFCR; /*!< MDMA channel x interrupt flag clear register, Address offset: 0x44 */ + __IO uint32_t CESR; /*!< MDMA Channel x error status register, Address offset: 0x48 */ + __IO uint32_t CCR; /*!< MDMA channel x control register, Address offset: 0x4C */ + __IO uint32_t CTCR; /*!< MDMA channel x Transfer Configuration register, Address offset: 0x50 */ + __IO uint32_t CBNDTR; /*!< MDMA Channel x block number of data register, Address offset: 0x54 */ + __IO uint32_t CSAR; /*!< MDMA channel x source address register, Address offset: 0x58 */ + __IO uint32_t CDAR; /*!< MDMA channel x destination address register, Address offset: 0x5C */ + __IO uint32_t CBRUR; /*!< MDMA channel x Block Repeat address Update register, Address offset: 0x60 */ + __IO uint32_t CLAR; /*!< MDMA channel x Link Address register, Address offset: 0x64 */ + __IO uint32_t CTBR; /*!< MDMA channel x Trigger and Bus selection Register, Address offset: 0x68 */ + uint32_t RESERVED0; /*!< Reserved, 0x6C */ + __IO uint32_t CMAR; /*!< MDMA channel x Mask address register, Address offset: 0x70 */ + __IO uint32_t CMDR; /*!< MDMA channel x Mask Data register, Address offset: 0x74 */ +}MDMA_Channel_TypeDef; + +/** + * @brief DMA2D Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA2D Control Register, Address offset: 0x00 */ + __IO uint32_t ISR; /*!< DMA2D Interrupt Status Register, Address offset: 0x04 */ + __IO uint32_t IFCR; /*!< DMA2D Interrupt Flag Clear Register, Address offset: 0x08 */ + __IO uint32_t FGMAR; /*!< DMA2D Foreground Memory Address Register, Address offset: 0x0C */ + __IO uint32_t FGOR; /*!< DMA2D Foreground Offset Register, Address offset: 0x10 */ + __IO uint32_t BGMAR; /*!< DMA2D Background Memory Address Register, Address offset: 0x14 */ + __IO uint32_t BGOR; /*!< DMA2D Background Offset Register, Address offset: 0x18 */ + __IO uint32_t FGPFCCR; /*!< DMA2D Foreground PFC Control Register, Address offset: 0x1C */ + __IO uint32_t FGCOLR; /*!< DMA2D Foreground Color Register, Address offset: 0x20 */ + __IO uint32_t BGPFCCR; /*!< DMA2D Background PFC Control Register, Address offset: 0x24 */ + __IO uint32_t BGCOLR; /*!< DMA2D Background Color Register, Address offset: 0x28 */ + __IO uint32_t FGCMAR; /*!< DMA2D Foreground CLUT Memory Address Register, Address offset: 0x2C */ + __IO uint32_t BGCMAR; /*!< DMA2D Background CLUT Memory Address Register, Address offset: 0x30 */ + __IO uint32_t OPFCCR; /*!< DMA2D Output PFC Control Register, Address offset: 0x34 */ + __IO uint32_t OCOLR; /*!< DMA2D Output Color Register, Address offset: 0x38 */ + __IO uint32_t OMAR; /*!< DMA2D Output Memory Address Register, Address offset: 0x3C */ + __IO uint32_t OOR; /*!< DMA2D Output Offset Register, Address offset: 0x40 */ + __IO uint32_t NLR; /*!< DMA2D Number of Line Register, Address offset: 0x44 */ + __IO uint32_t LWR; /*!< DMA2D Line Watermark Register, Address offset: 0x48 */ + __IO uint32_t AMTCR; /*!< DMA2D AHB Master Timer Configuration Register, Address offset: 0x4C */ + uint32_t RESERVED[236]; /*!< Reserved, 0x50-0x3FF */ + __IO uint32_t FGCLUT[256]; /*!< DMA2D Foreground CLUT, Address offset:400-7FF */ + __IO uint32_t BGCLUT[256]; /*!< DMA2D Background CLUT, Address offset:800-BFF */ +} DMA2D_TypeDef; + + +/** + * @brief Ethernet MAC + */ +typedef struct +{ + __IO uint32_t MACCR; + __IO uint32_t MACECR; + __IO uint32_t MACPFR; + __IO uint32_t MACWTR; + __IO uint32_t MACHT0R; + __IO uint32_t MACHT1R; + uint32_t RESERVED1[14]; + __IO uint32_t MACVTR; + uint32_t RESERVED2; + __IO uint32_t MACVHTR; + uint32_t RESERVED3; + __IO uint32_t MACVIR; + __IO uint32_t MACIVIR; + uint32_t RESERVED4[2]; + __IO uint32_t MACTFCR; + uint32_t RESERVED5[7]; + __IO uint32_t MACRFCR; + uint32_t RESERVED6[7]; + __IO uint32_t MACISR; + __IO uint32_t MACIER; + __IO uint32_t MACRXTXSR; + uint32_t RESERVED7; + __IO uint32_t MACPCSR; + __IO uint32_t MACRWKPFR; + uint32_t RESERVED8[2]; + __IO uint32_t MACLCSR; + __IO uint32_t MACLTCR; + __IO uint32_t MACLETR; + __IO uint32_t MAC1USTCR; + uint32_t RESERVED9[12]; + __IO uint32_t MACVR; + __IO uint32_t MACDR; + uint32_t RESERVED10; + __IO uint32_t MACHWF0R; + __IO uint32_t MACHWF1R; + __IO uint32_t MACHWF2R; + uint32_t RESERVED11[54]; + __IO uint32_t MACMDIOAR; + __IO uint32_t MACMDIODR; + uint32_t RESERVED12[2]; + __IO uint32_t MACARPAR; + uint32_t RESERVED13[59]; + __IO uint32_t MACA0HR; + __IO uint32_t MACA0LR; + __IO uint32_t MACA1HR; + __IO uint32_t MACA1LR; + __IO uint32_t MACA2HR; + __IO uint32_t MACA2LR; + __IO uint32_t MACA3HR; + __IO uint32_t MACA3LR; + uint32_t RESERVED14[248]; + __IO uint32_t MMCCR; + __IO uint32_t MMCRIR; + __IO uint32_t MMCTIR; + __IO uint32_t MMCRIMR; + __IO uint32_t MMCTIMR; + uint32_t RESERVED15[14]; + __IO uint32_t MMCTSCGPR; + __IO uint32_t MMCTMCGPR; + uint32_t RESERVED16[5]; + __IO uint32_t MMCTPCGR; + uint32_t RESERVED17[10]; + __IO uint32_t MMCRCRCEPR; + __IO uint32_t MMCRAEPR; + uint32_t RESERVED18[10]; + __IO uint32_t MMCRUPGR; + uint32_t RESERVED19[9]; + __IO uint32_t MMCTLPIMSTR; + __IO uint32_t MMCTLPITCR; + __IO uint32_t MMCRLPIMSTR; + __IO uint32_t MMCRLPITCR; + uint32_t RESERVED20[65]; + __IO uint32_t MACL3L4C0R; + __IO uint32_t MACL4A0R; + uint32_t RESERVED21[2]; + __IO uint32_t MACL3A0R0R; + __IO uint32_t MACL3A1R0R; + __IO uint32_t MACL3A2R0R; + __IO uint32_t MACL3A3R0R; + uint32_t RESERVED22[4]; + __IO uint32_t MACL3L4C1R; + __IO uint32_t MACL4A1R; + uint32_t RESERVED23[2]; + __IO uint32_t MACL3A0R1R; + __IO uint32_t MACL3A1R1R; + __IO uint32_t MACL3A2R1R; + __IO uint32_t MACL3A3R1R; + uint32_t RESERVED24[108]; + __IO uint32_t MACTSCR; + __IO uint32_t MACSSIR; + __IO uint32_t MACSTSR; + __IO uint32_t MACSTNR; + __IO uint32_t MACSTSUR; + __IO uint32_t MACSTNUR; + __IO uint32_t MACTSAR; + uint32_t RESERVED25; + __IO uint32_t MACTSSR; + uint32_t RESERVED26[3]; + __IO uint32_t MACTTSSNR; + __IO uint32_t MACTTSSSR; + uint32_t RESERVED27[2]; + __IO uint32_t MACACR; + uint32_t RESERVED28; + __IO uint32_t MACATSNR; + __IO uint32_t MACATSSR; + __IO uint32_t MACTSIACR; + __IO uint32_t MACTSEACR; + __IO uint32_t MACTSICNR; + __IO uint32_t MACTSECNR; + uint32_t RESERVED29[4]; + __IO uint32_t MACPPSCR; + uint32_t RESERVED30[3]; + __IO uint32_t MACPPSTTSR; + __IO uint32_t MACPPSTTNR; + __IO uint32_t MACPPSIR; + __IO uint32_t MACPPSWR; + uint32_t RESERVED31[12]; + __IO uint32_t MACPOCR; + __IO uint32_t MACSPI0R; + __IO uint32_t MACSPI1R; + __IO uint32_t MACSPI2R; + __IO uint32_t MACLMIR; + uint32_t RESERVED32[11]; + __IO uint32_t MTLOMR; + uint32_t RESERVED33[7]; + __IO uint32_t MTLISR; + uint32_t RESERVED34[55]; + __IO uint32_t MTLTQOMR; + __IO uint32_t MTLTQUR; + __IO uint32_t MTLTQDR; + uint32_t RESERVED35[8]; + __IO uint32_t MTLQICSR; + __IO uint32_t MTLRQOMR; + __IO uint32_t MTLRQMPOCR; + __IO uint32_t MTLRQDR; + uint32_t RESERVED36[177]; + __IO uint32_t DMAMR; + __IO uint32_t DMASBMR; + __IO uint32_t DMAISR; + __IO uint32_t DMADSR; + uint32_t RESERVED37[60]; + __IO uint32_t DMACCR; + __IO uint32_t DMACTCR; + __IO uint32_t DMACRCR; + uint32_t RESERVED38[2]; + __IO uint32_t DMACTDLAR; + uint32_t RESERVED39; + __IO uint32_t DMACRDLAR; + __IO uint32_t DMACTDTPR; + uint32_t RESERVED40; + __IO uint32_t DMACRDTPR; + __IO uint32_t DMACTDRLR; + __IO uint32_t DMACRDRLR; + __IO uint32_t DMACIER; + __IO uint32_t DMACRIWTR; +__IO uint32_t DMACSFCSR; + uint32_t RESERVED41; + __IO uint32_t DMACCATDR; + uint32_t RESERVED42; + __IO uint32_t DMACCARDR; + uint32_t RESERVED43; + __IO uint32_t DMACCATBR; + uint32_t RESERVED44; + __IO uint32_t DMACCARBR; + __IO uint32_t DMACSR; +uint32_t RESERVED45[2]; +__IO uint32_t DMACMFCR; +}ETH_TypeDef; +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ +__IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register, Address offset: 0x00 */ +__IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register, Address offset: 0x04 */ +__IO uint32_t SWIER1; /*!< EXTI Software interrupt event register, Address offset: 0x08 */ +__IO uint32_t D3PMR1; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR1) Address offset: 0x0C */ +__IO uint32_t D3PCR1L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR1L) Address offset: 0x10 */ +__IO uint32_t D3PCR1H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR1H) Address offset: 0x14 */ +uint32_t RESERVED1[2]; /*!< Reserved, 0x18 to 0x1C */ +__IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register, Address offset: 0x20 */ +__IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register, Address offset: 0x24 */ +__IO uint32_t SWIER2; /*!< EXTI Software interrupt event register, Address offset: 0x28 */ +__IO uint32_t D3PMR2; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR2) Address offset: 0x2C */ +__IO uint32_t D3PCR2L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR2L) Address offset: 0x30 */ +__IO uint32_t D3PCR2H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR2H) Address offset: 0x34 */ +uint32_t RESERVED2[2]; /*!< Reserved, 0x38 to 0x3C */ +__IO uint32_t RTSR3; /*!< EXTI Rising trigger selection register, Address offset: 0x40 */ +__IO uint32_t FTSR3; /*!< EXTI Falling trigger selection register, Address offset: 0x44 */ +__IO uint32_t SWIER3; /*!< EXTI Software interrupt event register, Address offset: 0x48 */ +__IO uint32_t D3PMR3; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR3) Address offset: 0x4C */ +__IO uint32_t D3PCR3L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR3L) Address offset: 0x50 */ +__IO uint32_t D3PCR3H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR3H) Address offset: 0x54 */ +uint32_t RESERVED3[10]; /*!< Reserved, 0x58 to 0x7C */ +__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x80 */ +__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x84 */ +__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x88 */ +uint32_t RESERVED4; /*!< Reserved, 0x8C */ +__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x90 */ +__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x94 */ +__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x98 */ +uint32_t RESERVED5; /*!< Reserved, 0x9C */ +__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0xA0 */ +__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0xA4 */ +__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0xA8 */ +}EXTI_TypeDef; + +/** + * @brief This structure registers corresponds to EXTI_Typdef CPU1/CPU2 registers subset (IMRx, EMRx and PRx), allowing to define EXTI_D1/EXTI_D2 + * with rapid/common access to these IMRx, EMRx, PRx registers for CPU1 and CPU2. + * Note that EXTI_D1 and EXTI_D2 bases addresses are calculated to point to CPUx first register: + * IMR1 in case of EXTI_D1 that is addressing CPU1 (Coretx-M7) + * C2IMR1 in case of EXTI_D2 that is addressing CPU2 (Coretx-M4) + * Note: EXTI_D2 and corresponding C2IMRx, C2EMRx and C2PRx registers are available for Dual Core devices only + */ + +typedef struct +{ +__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x00 */ +__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x04 */ +__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x08 */ +uint32_t RESERVED1; /*!< Reserved, 0x0C */ +__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x10 */ +__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x14 */ +__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x18 */ +uint32_t RESERVED2; /*!< Reserved, 0x1C */ +__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0x20 */ +__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0x24 */ +__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0x28 */ +}EXTI_Core_TypeDef; + + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t KEYR1; /*!< Flash Key Register for bank1, Address offset: 0x04 */ + __IO uint32_t OPTKEYR; /*!< Flash Option Key Register, Address offset: 0x08 */ + __IO uint32_t CR1; /*!< Flash Control Register for bank1, Address offset: 0x0C */ + __IO uint32_t SR1; /*!< Flash Status Register for bank1, Address offset: 0x10 */ + __IO uint32_t CCR1; /*!< Flash Control Register for bank1, Address offset: 0x14 */ + __IO uint32_t OPTCR; /*!< Flash Option Control Register, Address offset: 0x18 */ + __IO uint32_t OPTSR_CUR; /*!< Flash Option Status Current Register, Address offset: 0x1C */ + __IO uint32_t OPTSR_PRG; /*!< Flash Option Status to Program Register, Address offset: 0x20 */ + __IO uint32_t OPTCCR; /*!< Flash Option Clear Control Register, Address offset: 0x24 */ + __IO uint32_t PRAR_CUR1; /*!< Flash Current Protection Address Register for bank1, Address offset: 0x28 */ + __IO uint32_t PRAR_PRG1; /*!< Flash Protection Address to Program Register for bank1, Address offset: 0x2C */ + __IO uint32_t SCAR_CUR1; /*!< Flash Current Secure Address Register for bank1, Address offset: 0x30 */ + __IO uint32_t SCAR_PRG1; /*!< Flash Secure Address to Program Register for bank1, Address offset: 0x34 */ + __IO uint32_t WPSN_CUR1; /*!< Flash Current Write Protection Register on bank1, Address offset: 0x38 */ + __IO uint32_t WPSN_PRG1; /*!< Flash Write Protection to Program Register on bank1, Address offset: 0x3C */ + __IO uint32_t BOOT_CUR; /*!< Flash Current Boot Address for Pelican Core Register, Address offset: 0x40 */ + __IO uint32_t BOOT_PRG; /*!< Flash Boot Address to Program for Pelican Core Register, Address offset: 0x44 */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x48 to 0x4C */ + __IO uint32_t CRCCR1; /*!< Flash CRC Control register For Bank1 Register , Address offset: 0x50 */ + __IO uint32_t CRCSADD1; /*!< Flash CRC Start Address Register for Bank1 , Address offset: 0x54 */ + __IO uint32_t CRCEADD1; /*!< Flash CRC End Address Register for Bank1 , Address offset: 0x58 */ + __IO uint32_t CRCDATA; /*!< Flash CRC Data Register for Bank1 , Address offset: 0x5C */ + __IO uint32_t ECC_FA1; /*!< Flash ECC Fail Address For Bank1 Register , Address offset: 0x60 */ + uint32_t RESERVED[3]; /*!< Reserved, 0x64 to 0x6C */ + __IO uint32_t OPTSR2_CUR; /*!< Flash Option Status Current Register 2, Address offset: 0x70 */ + __IO uint32_t OPTSR2_PRG; /*!< Flash Option Status to Program Register 2, Address offset: 0x74 */ +} FLASH_TypeDef; + +/** + * @brief Filter and Mathematical ACcelerator + */ +typedef struct +{ + __IO uint32_t X1BUFCFG; /*!< FMAC X1 Buffer Configuration register, Address offset: 0x00 */ + __IO uint32_t X2BUFCFG; /*!< FMAC X2 Buffer Configuration register, Address offset: 0x04 */ + __IO uint32_t YBUFCFG; /*!< FMAC Y Buffer Configuration register, Address offset: 0x08 */ + __IO uint32_t PARAM; /*!< FMAC Parameter register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< FMAC Control register, Address offset: 0x10 */ + __IO uint32_t SR; /*!< FMAC Status register, Address offset: 0x14 */ + __IO uint32_t WDATA; /*!< FMAC Write Data register, Address offset: 0x18 */ + __IO uint32_t RDATA; /*!< FMAC Read Data register, Address offset: 0x1C */ +} FMAC_TypeDef; + +/** + * @brief Flexible Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FMC_Bank1_TypeDef; + +/** + * @brief Flexible Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FMC_Bank1E_TypeDef; + +/** + * @brief Flexible Memory Controller Bank2 + */ + +typedef struct +{ + __IO uint32_t PCR2; /*!< NAND Flash control register 2, Address offset: 0x60 */ + __IO uint32_t SR2; /*!< NAND Flash FIFO status and interrupt register 2, Address offset: 0x64 */ + __IO uint32_t PMEM2; /*!< NAND Flash Common memory space timing register 2, Address offset: 0x68 */ + __IO uint32_t PATT2; /*!< NAND Flash Attribute memory space timing register 2, Address offset: 0x6C */ + uint32_t RESERVED0; /*!< Reserved, 0x70 */ + __IO uint32_t ECCR2; /*!< NAND Flash ECC result registers 2, Address offset: 0x74 */ +} FMC_Bank2_TypeDef; + +/** + * @brief Flexible Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR; /*!< NAND Flash control register 3, Address offset: 0x80 */ + __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register 3, Address offset: 0x84 */ + __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register 3, Address offset: 0x88 */ + __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register 3, Address offset: 0x8C */ + uint32_t RESERVED; /*!< Reserved, 0x90 */ + __IO uint32_t ECCR; /*!< NAND Flash ECC result registers 3, Address offset: 0x94 */ +} FMC_Bank3_TypeDef; + +/** + * @brief Flexible Memory Controller Bank5 and 6 + */ + + +typedef struct +{ + __IO uint32_t SDCR[2]; /*!< SDRAM Control registers , Address offset: 0x140-0x144 */ + __IO uint32_t SDTR[2]; /*!< SDRAM Timing registers , Address offset: 0x148-0x14C */ + __IO uint32_t SDCMR; /*!< SDRAM Command Mode register, Address offset: 0x150 */ + __IO uint32_t SDRTR; /*!< SDRAM Refresh Timer register, Address offset: 0x154 */ + __IO uint32_t SDSR; /*!< SDRAM Status register, Address offset: 0x158 */ +} FMC_Bank5_6_TypeDef; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< GPIO port bit set/reset, Address offset: 0x18 */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ +} GPIO_TypeDef; + +/** + * @brief Operational Amplifier (OPAMP) + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */ + __IO uint32_t OTR; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */ + __IO uint32_t HSOTR; /*!< OPAMP offset trimming register for high speed mode, Address offset: 0x08 */ +} OPAMP_TypeDef; + +/** + * @brief System configuration controller + */ + +typedef struct +{ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x00 */ + __IO uint32_t PMCR; /*!< SYSCFG peripheral mode configuration register, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + __IO uint32_t CFGR; /*!< SYSCFG configuration registers, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t CCCSR; /*!< SYSCFG compensation cell control/status register, Address offset: 0x20 */ + __IO uint32_t CCVR; /*!< SYSCFG compensation cell value register, Address offset: 0x24 */ + __IO uint32_t CCCR; /*!< SYSCFG compensation cell code register, Address offset: 0x28 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x2C */ + __IO uint32_t ADC2ALT; /*!< ADC2 internal input alternate connection register, Address offset: 0x30 */ + uint32_t RESERVED4[60]; /*!< Reserved, 0x34-0x120 */ + __IO uint32_t PKGR; /*!< SYSCFG package register, Address offset: 0x124 */ + uint32_t RESERVED5[118]; /*!< Reserved, 0x128-0x2FC */ + __IO uint32_t UR0; /*!< SYSCFG user register 0, Address offset: 0x300 */ + __IO uint32_t UR1; /*!< SYSCFG user register 1, Address offset: 0x304 */ + __IO uint32_t UR2; /*!< SYSCFG user register 2, Address offset: 0x308 */ + __IO uint32_t UR3; /*!< SYSCFG user register 3, Address offset: 0x30C */ + __IO uint32_t UR4; /*!< SYSCFG user register 4, Address offset: 0x310 */ + __IO uint32_t UR5; /*!< SYSCFG user register 5, Address offset: 0x314 */ + __IO uint32_t UR6; /*!< SYSCFG user register 6, Address offset: 0x318 */ + __IO uint32_t UR7; /*!< SYSCFG user register 7, Address offset: 0x31C */ + uint32_t RESERVED6[3]; /*!< Reserved, Address offset: 0x320-0x328 */ + __IO uint32_t UR11; /*!< SYSCFG user register 11, Address offset: 0x32C */ + __IO uint32_t UR12; /*!< SYSCFG user register 12, Address offset: 0x330 */ + __IO uint32_t UR13; /*!< SYSCFG user register 13, Address offset: 0x334 */ + __IO uint32_t UR14; /*!< SYSCFG user register 14, Address offset: 0x338 */ + __IO uint32_t UR15; /*!< SYSCFG user register 15, Address offset: 0x33C */ + __IO uint32_t UR16; /*!< SYSCFG user register 16, Address offset: 0x340 */ + __IO uint32_t UR17; /*!< SYSCFG user register 17, Address offset: 0x344 */ + __IO uint32_t UR18; /*!< SYSCFG user register 18, Address offset: 0x348 */ + +} SYSCFG_TypeDef; + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */ + __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */ + __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */ + __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */ + __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */ + __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */ + __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */ + __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */ +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ + __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ +} IWDG_TypeDef; + + +/** + * @brief LCD-TFT Display Controller + */ + +typedef struct +{ + uint32_t RESERVED0[2]; /*!< Reserved, 0x00-0x04 */ + __IO uint32_t SSCR; /*!< LTDC Synchronization Size Configuration Register, Address offset: 0x08 */ + __IO uint32_t BPCR; /*!< LTDC Back Porch Configuration Register, Address offset: 0x0C */ + __IO uint32_t AWCR; /*!< LTDC Active Width Configuration Register, Address offset: 0x10 */ + __IO uint32_t TWCR; /*!< LTDC Total Width Configuration Register, Address offset: 0x14 */ + __IO uint32_t GCR; /*!< LTDC Global Control Register, Address offset: 0x18 */ + uint32_t RESERVED1[2]; /*!< Reserved, 0x1C-0x20 */ + __IO uint32_t SRCR; /*!< LTDC Shadow Reload Configuration Register, Address offset: 0x24 */ + uint32_t RESERVED2[1]; /*!< Reserved, 0x28 */ + __IO uint32_t BCCR; /*!< LTDC Background Color Configuration Register, Address offset: 0x2C */ + uint32_t RESERVED3[1]; /*!< Reserved, 0x30 */ + __IO uint32_t IER; /*!< LTDC Interrupt Enable Register, Address offset: 0x34 */ + __IO uint32_t ISR; /*!< LTDC Interrupt Status Register, Address offset: 0x38 */ + __IO uint32_t ICR; /*!< LTDC Interrupt Clear Register, Address offset: 0x3C */ + __IO uint32_t LIPCR; /*!< LTDC Line Interrupt Position Configuration Register, Address offset: 0x40 */ + __IO uint32_t CPSR; /*!< LTDC Current Position Status Register, Address offset: 0x44 */ + __IO uint32_t CDSR; /*!< LTDC Current Display Status Register, Address offset: 0x48 */ +} LTDC_TypeDef; + +/** + * @brief LCD-TFT Display layer x Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< LTDC Layerx Control Register Address offset: 0x84 */ + __IO uint32_t WHPCR; /*!< LTDC Layerx Window Horizontal Position Configuration Register Address offset: 0x88 */ + __IO uint32_t WVPCR; /*!< LTDC Layerx Window Vertical Position Configuration Register Address offset: 0x8C */ + __IO uint32_t CKCR; /*!< LTDC Layerx Color Keying Configuration Register Address offset: 0x90 */ + __IO uint32_t PFCR; /*!< LTDC Layerx Pixel Format Configuration Register Address offset: 0x94 */ + __IO uint32_t CACR; /*!< LTDC Layerx Constant Alpha Configuration Register Address offset: 0x98 */ + __IO uint32_t DCCR; /*!< LTDC Layerx Default Color Configuration Register Address offset: 0x9C */ + __IO uint32_t BFCR; /*!< LTDC Layerx Blending Factors Configuration Register Address offset: 0xA0 */ + uint32_t RESERVED0[2]; /*!< Reserved */ + __IO uint32_t CFBAR; /*!< LTDC Layerx Color Frame Buffer Address Register Address offset: 0xAC */ + __IO uint32_t CFBLR; /*!< LTDC Layerx Color Frame Buffer Length Register Address offset: 0xB0 */ + __IO uint32_t CFBLNR; /*!< LTDC Layerx ColorFrame Buffer Line Number Register Address offset: 0xB4 */ + uint32_t RESERVED1[3]; /*!< Reserved */ + __IO uint32_t CLUTWR; /*!< LTDC Layerx CLUT Write Register Address offset: 0x144 */ + +} LTDC_Layer_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */ + __IO uint32_t CSR1; /*!< PWR power control status register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x08 */ + __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x0C */ + __IO uint32_t CPUCR; /*!< PWR CPU control register, Address offset: 0x10 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t D3CR; /*!< PWR D3 domain control register, Address offset: 0x18 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t WKUPCR; /*!< PWR wakeup clear register, Address offset: 0x20 */ + __IO uint32_t WKUPFR; /*!< PWR wakeup flag register, Address offset: 0x24 */ + __IO uint32_t WKUPEPR; /*!< PWR wakeup enable and polarity register, Address offset: 0x28 */ +} PWR_TypeDef; + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t HSICFGR; /*!< HSI Clock Calibration Register, Address offset: 0x04 */ + __IO uint32_t CRRCR; /*!< Clock Recovery RC Register, Address offset: 0x08 */ + __IO uint32_t CSICFGR; /*!< CSI Clock Calibration Register, Address offset: 0x0C */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x10 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t D1CFGR; /*!< RCC Domain 1 configuration register, Address offset: 0x18 */ + __IO uint32_t D2CFGR; /*!< RCC Domain 2 configuration register, Address offset: 0x1C */ + __IO uint32_t D3CFGR; /*!< RCC Domain 3 configuration register, Address offset: 0x20 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t PLLCKSELR; /*!< RCC PLLs Clock Source Selection Register, Address offset: 0x28 */ + __IO uint32_t PLLCFGR; /*!< RCC PLLs Configuration Register, Address offset: 0x2C */ + __IO uint32_t PLL1DIVR; /*!< RCC PLL1 Dividers Configuration Register, Address offset: 0x30 */ + __IO uint32_t PLL1FRACR; /*!< RCC PLL1 Fractional Divider Configuration Register, Address offset: 0x34 */ + __IO uint32_t PLL2DIVR; /*!< RCC PLL2 Dividers Configuration Register, Address offset: 0x38 */ + __IO uint32_t PLL2FRACR; /*!< RCC PLL2 Fractional Divider Configuration Register, Address offset: 0x3C */ + __IO uint32_t PLL3DIVR; /*!< RCC PLL3 Dividers Configuration Register, Address offset: 0x40 */ + __IO uint32_t PLL3FRACR; /*!< RCC PLL3 Fractional Divider Configuration Register, Address offset: 0x44 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x48 */ + __IO uint32_t D1CCIPR; /*!< RCC Domain 1 Kernel Clock Configuration Register Address offset: 0x4C */ + __IO uint32_t D2CCIP1R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x50 */ + __IO uint32_t D2CCIP2R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x54 */ + __IO uint32_t D3CCIPR; /*!< RCC Domain 3 Kernel Clock Configuration Register Address offset: 0x58 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x5C */ + __IO uint32_t CIER; /*!< RCC Clock Source Interrupt Enable Register Address offset: 0x60 */ + __IO uint32_t CIFR; /*!< RCC Clock Source Interrupt Flag Register Address offset: 0x64 */ + __IO uint32_t CICR; /*!< RCC Clock Source Interrupt Clear Register Address offset: 0x68 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x6C */ + __IO uint32_t BDCR; /*!< RCC Vswitch Backup Domain Control Register, Address offset: 0x70 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x78 */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x7C */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x80 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x84 */ + __IO uint32_t AHB4RSTR; /*!< RCC AHB4 peripheral reset register, Address offset: 0x88 */ + __IO uint32_t APB3RSTR; /*!< RCC APB3 peripheral reset register, Address offset: 0x8C */ + __IO uint32_t APB1LRSTR; /*!< RCC APB1 peripheral reset Low Word register, Address offset: 0x90 */ + __IO uint32_t APB1HRSTR; /*!< RCC APB1 peripheral reset High Word register, Address offset: 0x94 */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x98 */ + __IO uint32_t APB4RSTR; /*!< RCC APB4 peripheral reset register, Address offset: 0x9C */ + __IO uint32_t GCR; /*!< RCC RCC Global Control Register, Address offset: 0xA0 */ + uint32_t RESERVED8; /*!< Reserved, Address offset: 0xA4 */ + __IO uint32_t D3AMR; /*!< RCC Domain 3 Autonomous Mode Register, Address offset: 0xA8 */ + uint32_t RESERVED11[9]; /*!< Reserved, 0xAC-0xCC Address offset: 0xAC */ + __IO uint32_t RSR; /*!< RCC Reset status register, Address offset: 0xD0 */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0xD4 */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0xD8 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0xDC */ + __IO uint32_t AHB4ENR; /*!< RCC AHB4 peripheral clock register, Address offset: 0xE0 */ + __IO uint32_t APB3ENR; /*!< RCC APB3 peripheral clock register, Address offset: 0xE4 */ + __IO uint32_t APB1LENR; /*!< RCC APB1 peripheral clock Low Word register, Address offset: 0xE8 */ + __IO uint32_t APB1HENR; /*!< RCC APB1 peripheral clock High Word register, Address offset: 0xEC */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock register, Address offset: 0xF0 */ + __IO uint32_t APB4ENR; /*!< RCC APB4 peripheral clock register, Address offset: 0xF4 */ + uint32_t RESERVED12; /*!< Reserved, Address offset: 0xF8 */ + __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral sleep clock register, Address offset: 0xFC */ + __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral sleep clock register, Address offset: 0x100 */ + __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral sleep clock register, Address offset: 0x104 */ + __IO uint32_t AHB4LPENR; /*!< RCC AHB4 peripheral sleep clock register, Address offset: 0x108 */ + __IO uint32_t APB3LPENR; /*!< RCC APB3 peripheral sleep clock register, Address offset: 0x10C */ + __IO uint32_t APB1LLPENR; /*!< RCC APB1 peripheral sleep clock Low Word register, Address offset: 0x110 */ + __IO uint32_t APB1HLPENR; /*!< RCC APB1 peripheral sleep clock High Word register, Address offset: 0x114 */ + __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral sleep clock register, Address offset: 0x118 */ + __IO uint32_t APB4LPENR; /*!< RCC APB4 peripheral sleep clock register, Address offset: 0x11C */ + uint32_t RESERVED13[4]; /*!< Reserved, 0x120-0x12C Address offset: 0x120 */ + +} RCC_TypeDef; + + +/** + * @brief Real-Time Clock + */ +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x18 */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */ + __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ + __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */ + __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */ + __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */ + __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */ + __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */ + __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */ + __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */ + __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */ + __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */ + __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */ + __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */ + __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */ +} RTC_TypeDef; + +/** + * @brief Serial Audio Interface + */ + +typedef struct +{ + __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ + uint32_t RESERVED0[16]; /*!< Reserved, 0x04 - 0x43 */ + __IO uint32_t PDMCR; /*!< SAI PDM control register, Address offset: 0x44 */ + __IO uint32_t PDMDLY; /*!< SAI PDM delay register, Address offset: 0x48 */ +} SAI_TypeDef; + +typedef struct +{ + __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ + __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ + __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ + __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ + __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ + __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ +} SAI_Block_TypeDef; + +/** + * @brief SPDIF-RX Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< Control register, Address offset: 0x00 */ + __IO uint32_t IMR; /*!< Interrupt mask register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< Status register, Address offset: 0x08 */ + __IO uint32_t IFCR; /*!< Interrupt Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DR; /*!< Data input register, Address offset: 0x10 */ + __IO uint32_t CSR; /*!< Channel Status register, Address offset: 0x14 */ + __IO uint32_t DIR; /*!< Debug Information register, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1A */ +} SPDIFRX_TypeDef; + + +/** + * @brief Secure digital input/output Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */ + __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */ + __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */ + __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */ + __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */ + __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */ + __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */ + __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */ + __IO uint32_t ACKTIME; /*!< SDMMC Acknowledgement timer register, Address offset: 0x40 */ + uint32_t RESERVED0[3]; /*!< Reserved, 0x44 - 0x4C - 0x4C */ + __IO uint32_t IDMACTRL; /*!< SDMMC DMA control register, Address offset: 0x50 */ + __IO uint32_t IDMABSIZE; /*!< SDMMC DMA buffer size register, Address offset: 0x54 */ + __IO uint32_t IDMABASE0; /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58 */ + __IO uint32_t IDMABASE1; /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C */ + uint32_t RESERVED1[8]; /*!< Reserved, 0x60-0x7C */ + __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */ + uint32_t RESERVED2[222]; /*!< Reserved, 0x84-0x3F8 */ + __IO uint32_t IPVR; /*!< SDMMC data FIFO register, Address offset: 0x3FC */ +} SDMMC_TypeDef; + + +/** + * @brief Delay Block DLYB + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DELAY BLOCK control register, Address offset: 0x00 */ + __IO uint32_t CFGR; /*!< DELAY BLOCK configuration register, Address offset: 0x04 */ +} DLYB_TypeDef; + +/** + * @brief HW Semaphore HSEM + */ + +typedef struct +{ + __IO uint32_t R[32]; /*!< 2-step write lock and read back registers, Address offset: 00h-7Ch */ + __IO uint32_t RLR[32]; /*!< 1-step read lock registers, Address offset: 80h-FCh */ + __IO uint32_t C1IER; /*!< HSEM Interrupt enable register , Address offset: 100h */ + __IO uint32_t C1ICR; /*!< HSEM Interrupt clear register , Address offset: 104h */ + __IO uint32_t C1ISR; /*!< HSEM Interrupt Status register , Address offset: 108h */ + __IO uint32_t C1MISR; /*!< HSEM Interrupt Masked Status register , Address offset: 10Ch */ + uint32_t Reserved[12]; /* Reserved Address offset: 110h-13Ch */ + __IO uint32_t CR; /*!< HSEM Semaphore clear register , Address offset: 140h */ + __IO uint32_t KEYR; /*!< HSEM Semaphore clear key register , Address offset: 144h */ + +} HSEM_TypeDef; + +typedef struct +{ + __IO uint32_t IER; /*!< HSEM interrupt enable register , Address offset: 0h */ + __IO uint32_t ICR; /*!< HSEM interrupt clear register , Address offset: 4h */ + __IO uint32_t ISR; /*!< HSEM interrupt status register , Address offset: 8h */ + __IO uint32_t MISR; /*!< HSEM masked interrupt status register , Address offset: Ch */ +} HSEM_Common_TypeDef; + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< SPI/I2S Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */ + __IO uint32_t CFG1; /*!< SPI Configuration register 1, Address offset: 0x08 */ + __IO uint32_t CFG2; /*!< SPI Configuration register 2, Address offset: 0x0C */ + __IO uint32_t IER; /*!< SPI/I2S Interrupt Enable register, Address offset: 0x10 */ + __IO uint32_t SR; /*!< SPI/I2S Status register, Address offset: 0x14 */ + __IO uint32_t IFCR; /*!< SPI/I2S Interrupt/Status flags clear register, Address offset: 0x18 */ + uint32_t RESERVED0; /*!< Reserved, 0x1C */ + __IO uint32_t TXDR; /*!< SPI/I2S Transmit data register, Address offset: 0x20 */ + uint32_t RESERVED1[3]; /*!< Reserved, 0x24-0x2C */ + __IO uint32_t RXDR; /*!< SPI/I2S Receive data register, Address offset: 0x30 */ + uint32_t RESERVED2[3]; /*!< Reserved, 0x34-0x3C */ + __IO uint32_t CRCPOLY; /*!< SPI CRC Polynomial register, Address offset: 0x40 */ + __IO uint32_t TXCRC; /*!< SPI Transmitter CRC register, Address offset: 0x44 */ + __IO uint32_t RXCRC; /*!< SPI Receiver CRC register, Address offset: 0x48 */ + __IO uint32_t UDRDR; /*!< SPI Underrun data register, Address offset: 0x4C */ + __IO uint32_t I2SCFGR; /*!< I2S Configuration register, Address offset: 0x50 */ + +} SPI_TypeDef; + +/** + * @brief DTS + */ +typedef struct +{ + __IO uint32_t CFGR1; /*!< DTS configuration register, Address offset: 0x00 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x04 */ + __IO uint32_t T0VALR1; /*!< DTS T0 Value register, Address offset: 0x08 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x0C */ + __IO uint32_t RAMPVALR; /*!< DTS Ramp value register, Address offset: 0x10 */ + __IO uint32_t ITR1; /*!< DTS Interrupt threshold register, Address offset: 0x14 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x18 */ + __IO uint32_t DR; /*!< DTS data register, Address offset: 0x1C */ + __IO uint32_t SR; /*!< DTS status register Address offset: 0x20 */ + __IO uint32_t ITENR; /*!< DTS Interrupt enable register, Address offset: 0x24 */ + __IO uint32_t ICIFR; /*!< DTS Clear Interrupt flag register, Address offset: 0x28 */ + __IO uint32_t OR; /*!< DTS option register 1, Address offset: 0x2C */ +} +DTS_TypeDef; + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ + __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + uint32_t RESERVED1; /*!< Reserved, 0x50 */ + __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */ + __IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */ + __IO uint32_t CCR6; /*!< TIM capture/compare register6, Address offset: 0x5C */ + __IO uint32_t AF1; /*!< TIM alternate function option register 1, Address offset: 0x60 */ + __IO uint32_t AF2; /*!< TIM alternate function option register 2, Address offset: 0x64 */ + __IO uint32_t TISEL; /*!< TIM Input Selection register, Address offset: 0x68 */ +} TIM_TypeDef; + +/** + * @brief LPTIMIMER + */ +typedef struct +{ + __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ + __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ + __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ + __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ + __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ + __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ + uint32_t RESERVED1; /*!< Reserved, 0x20 */ + __IO uint32_t CFGR2; /*!< LPTIM Configuration register, Address offset: 0x24 */ +} LPTIM_TypeDef; + +/** + * @brief Comparator + */ +typedef struct +{ + __IO uint32_t SR; /*!< Comparator status register, Address offset: 0x00 */ + __IO uint32_t ICFR; /*!< Comparator interrupt clear flag register, Address offset: 0x04 */ + __IO uint32_t OR; /*!< Comparator option register, Address offset: 0x08 */ +} COMPOPT_TypeDef; + +typedef struct +{ + __IO uint32_t CFGR; /*!< Comparator configuration register , Address offset: 0x00 */ +} COMP_TypeDef; + +typedef struct +{ + __IO uint32_t CFGR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */ +} COMP_Common_TypeDef; +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ + __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ + __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ + __IO uint32_t RQR; /*!< USART Request register, Address offset: 0x18 */ + __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */ + __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */ + __IO uint32_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */ + __IO uint32_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */ + __IO uint32_t PRESC; /*!< USART clock Prescaler register, Address offset: 0x2C */ +} USART_TypeDef; + +/** + * @brief Single Wire Protocol Master Interface SPWMI + */ +typedef struct +{ + __IO uint32_t CR; /*!< SWPMI Configuration/Control register, Address offset: 0x00 */ + __IO uint32_t BRR; /*!< SWPMI bitrate register, Address offset: 0x04 */ + uint32_t RESERVED1; /*!< Reserved, 0x08 */ + __IO uint32_t ISR; /*!< SWPMI Interrupt and Status register, Address offset: 0x0C */ + __IO uint32_t ICR; /*!< SWPMI Interrupt Flag Clear register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< SWPMI Interrupt Enable register, Address offset: 0x14 */ + __IO uint32_t RFL; /*!< SWPMI Receive Frame Length register, Address offset: 0x18 */ + __IO uint32_t TDR; /*!< SWPMI Transmit data register, Address offset: 0x1C */ + __IO uint32_t RDR; /*!< SWPMI Receive data register, Address offset: 0x20 */ + __IO uint32_t OR; /*!< SWPMI Option register, Address offset: 0x24 */ +} SWPMI_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + + +/** + * @brief RAM_ECC_Specific_Registers + */ +typedef struct +{ + __IO uint32_t CR; /*!< RAMECC monitor configuration register */ + __IO uint32_t SR; /*!< RAMECC monitor status register */ + __IO uint32_t FAR; /*!< RAMECC monitor failing address register */ + __IO uint32_t FDRL; /*!< RAMECC monitor failing data low register */ + __IO uint32_t FDRH; /*!< RAMECC monitor failing data high register */ + __IO uint32_t FECR; /*!< RAMECC monitor failing ECC error code register */ +} RAMECC_MonitorTypeDef; + +typedef struct +{ + __IO uint32_t IER; /*!< RAMECC interrupt enable register */ +} RAMECC_TypeDef; +/** + * @} + */ + + +/** + * @brief Crypto Processor + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CRYP control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< CRYP status register, Address offset: 0x04 */ + __IO uint32_t DIN; /*!< CRYP data input register, Address offset: 0x08 */ + __IO uint32_t DOUT; /*!< CRYP data output register, Address offset: 0x0C */ + __IO uint32_t DMACR; /*!< CRYP DMA control register, Address offset: 0x10 */ + __IO uint32_t IMSCR; /*!< CRYP interrupt mask set/clear register, Address offset: 0x14 */ + __IO uint32_t RISR; /*!< CRYP raw interrupt status register, Address offset: 0x18 */ + __IO uint32_t MISR; /*!< CRYP masked interrupt status register, Address offset: 0x1C */ + __IO uint32_t K0LR; /*!< CRYP key left register 0, Address offset: 0x20 */ + __IO uint32_t K0RR; /*!< CRYP key right register 0, Address offset: 0x24 */ + __IO uint32_t K1LR; /*!< CRYP key left register 1, Address offset: 0x28 */ + __IO uint32_t K1RR; /*!< CRYP key right register 1, Address offset: 0x2C */ + __IO uint32_t K2LR; /*!< CRYP key left register 2, Address offset: 0x30 */ + __IO uint32_t K2RR; /*!< CRYP key right register 2, Address offset: 0x34 */ + __IO uint32_t K3LR; /*!< CRYP key left register 3, Address offset: 0x38 */ + __IO uint32_t K3RR; /*!< CRYP key right register 3, Address offset: 0x3C */ + __IO uint32_t IV0LR; /*!< CRYP initialization vector left-word register 0, Address offset: 0x40 */ + __IO uint32_t IV0RR; /*!< CRYP initialization vector right-word register 0, Address offset: 0x44 */ + __IO uint32_t IV1LR; /*!< CRYP initialization vector left-word register 1, Address offset: 0x48 */ + __IO uint32_t IV1RR; /*!< CRYP initialization vector right-word register 1, Address offset: 0x4C */ + __IO uint32_t CSGCMCCM0R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 0, Address offset: 0x50 */ + __IO uint32_t CSGCMCCM1R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 1, Address offset: 0x54 */ + __IO uint32_t CSGCMCCM2R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 2, Address offset: 0x58 */ + __IO uint32_t CSGCMCCM3R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 3, Address offset: 0x5C */ + __IO uint32_t CSGCMCCM4R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 4, Address offset: 0x60 */ + __IO uint32_t CSGCMCCM5R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 5, Address offset: 0x64 */ + __IO uint32_t CSGCMCCM6R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 6, Address offset: 0x68 */ + __IO uint32_t CSGCMCCM7R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 7, Address offset: 0x6C */ + __IO uint32_t CSGCM0R; /*!< CRYP GCM/GMAC context swap register 0, Address offset: 0x70 */ + __IO uint32_t CSGCM1R; /*!< CRYP GCM/GMAC context swap register 1, Address offset: 0x74 */ + __IO uint32_t CSGCM2R; /*!< CRYP GCM/GMAC context swap register 2, Address offset: 0x78 */ + __IO uint32_t CSGCM3R; /*!< CRYP GCM/GMAC context swap register 3, Address offset: 0x7C */ + __IO uint32_t CSGCM4R; /*!< CRYP GCM/GMAC context swap register 4, Address offset: 0x80 */ + __IO uint32_t CSGCM5R; /*!< CRYP GCM/GMAC context swap register 5, Address offset: 0x84 */ + __IO uint32_t CSGCM6R; /*!< CRYP GCM/GMAC context swap register 6, Address offset: 0x88 */ + __IO uint32_t CSGCM7R; /*!< CRYP GCM/GMAC context swap register 7, Address offset: 0x8C */ +} CRYP_TypeDef; + +/** + * @brief HASH + */ + +typedef struct +{ + __IO uint32_t CR; /*!< HASH control register, Address offset: 0x00 */ + __IO uint32_t DIN; /*!< HASH data input register, Address offset: 0x04 */ + __IO uint32_t STR; /*!< HASH start register, Address offset: 0x08 */ + __IO uint32_t HR[5]; /*!< HASH digest registers, Address offset: 0x0C-0x1C */ + __IO uint32_t IMR; /*!< HASH interrupt enable register, Address offset: 0x20 */ + __IO uint32_t SR; /*!< HASH status register, Address offset: 0x24 */ + uint32_t RESERVED[52]; /*!< Reserved, 0x28-0xF4 */ + __IO uint32_t CSR[54]; /*!< HASH context swap registers, Address offset: 0x0F8-0x1CC */ +} HASH_TypeDef; + +/** + * @brief HASH_DIGEST + */ + +typedef struct +{ + __IO uint32_t HR[8]; /*!< HASH digest registers, Address offset: 0x310-0x32C */ +} HASH_DIGEST_TypeDef; + + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ + uint32_t RESERVED; + __IO uint32_t HTCR; /*!< RNG health test configuration register, Address offset: 0x10 */ +} RNG_TypeDef; + +/** + * @brief MDIOS + */ + +typedef struct +{ + __IO uint32_t CR; + __IO uint32_t WRFR; + __IO uint32_t CWRFR; + __IO uint32_t RDFR; + __IO uint32_t CRDFR; + __IO uint32_t SR; + __IO uint32_t CLRFR; + uint32_t RESERVED[57]; + __IO uint32_t DINR0; + __IO uint32_t DINR1; + __IO uint32_t DINR2; + __IO uint32_t DINR3; + __IO uint32_t DINR4; + __IO uint32_t DINR5; + __IO uint32_t DINR6; + __IO uint32_t DINR7; + __IO uint32_t DINR8; + __IO uint32_t DINR9; + __IO uint32_t DINR10; + __IO uint32_t DINR11; + __IO uint32_t DINR12; + __IO uint32_t DINR13; + __IO uint32_t DINR14; + __IO uint32_t DINR15; + __IO uint32_t DINR16; + __IO uint32_t DINR17; + __IO uint32_t DINR18; + __IO uint32_t DINR19; + __IO uint32_t DINR20; + __IO uint32_t DINR21; + __IO uint32_t DINR22; + __IO uint32_t DINR23; + __IO uint32_t DINR24; + __IO uint32_t DINR25; + __IO uint32_t DINR26; + __IO uint32_t DINR27; + __IO uint32_t DINR28; + __IO uint32_t DINR29; + __IO uint32_t DINR30; + __IO uint32_t DINR31; + __IO uint32_t DOUTR0; + __IO uint32_t DOUTR1; + __IO uint32_t DOUTR2; + __IO uint32_t DOUTR3; + __IO uint32_t DOUTR4; + __IO uint32_t DOUTR5; + __IO uint32_t DOUTR6; + __IO uint32_t DOUTR7; + __IO uint32_t DOUTR8; + __IO uint32_t DOUTR9; + __IO uint32_t DOUTR10; + __IO uint32_t DOUTR11; + __IO uint32_t DOUTR12; + __IO uint32_t DOUTR13; + __IO uint32_t DOUTR14; + __IO uint32_t DOUTR15; + __IO uint32_t DOUTR16; + __IO uint32_t DOUTR17; + __IO uint32_t DOUTR18; + __IO uint32_t DOUTR19; + __IO uint32_t DOUTR20; + __IO uint32_t DOUTR21; + __IO uint32_t DOUTR22; + __IO uint32_t DOUTR23; + __IO uint32_t DOUTR24; + __IO uint32_t DOUTR25; + __IO uint32_t DOUTR26; + __IO uint32_t DOUTR27; + __IO uint32_t DOUTR28; + __IO uint32_t DOUTR29; + __IO uint32_t DOUTR30; + __IO uint32_t DOUTR31; +} MDIOS_TypeDef; + + +/** + * @brief USB_OTG_Core_Registers + */ +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h */ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h */ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h */ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch */ + __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h */ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h */ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h */ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch */ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h */ + __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h */ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h */ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< General Purpose IO Register 038h */ + __IO uint32_t CID; /*!< User ID Register 03Ch */ + __IO uint32_t GSNPSID; /* USB_OTG core ID 040h*/ + __IO uint32_t GHWCFG1; /* User HW config1 044h*/ + __IO uint32_t GHWCFG2; /* User HW config2 048h*/ + __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch */ + uint32_t Reserved6; /*!< Reserved 050h */ + __IO uint32_t GLPMCFG; /*!< LPM Register 054h */ + __IO uint32_t GPWRDN; /*!< Power Down Register 058h */ + __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch */ + __IO uint32_t GADPCTL; /*!< ADP Timer, Control and Status Register 60Ch */ + uint32_t Reserved43[39]; /*!< Reserved 058h-0FFh */ + __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg 100h */ + __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO */ +} USB_OTG_GlobalTypeDef; + + +/** + * @brief USB_OTG_device_Registers + */ +typedef struct +{ + __IO uint32_t DCFG; /*!< dev Configuration Register 800h */ + __IO uint32_t DCTL; /*!< dev Control Register 804h */ + __IO uint32_t DSTS; /*!< dev Status Register (RO) 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask 810h */ + __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask 814h */ + __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg 818h */ + __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved9; /*!< Reserved 824h */ + __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register 828h */ + __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register 82Ch */ + __IO uint32_t DTHRCTL; /*!< dev threshold 830h */ + __IO uint32_t DIEPEMPMSK; /*!< dev empty msk 834h */ + __IO uint32_t DEACHINT; /*!< dedicated EP interrupt 838h */ + __IO uint32_t DEACHMSK; /*!< dedicated EP msk 83Ch */ + uint32_t Reserved40; /*!< dedicated EP mask 840h */ + __IO uint32_t DINEP1MSK; /*!< dedicated EP mask 844h */ + uint32_t Reserved44[15]; /*!< Reserved 844-87Ch */ + __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk 884h */ +} USB_OTG_DeviceTypeDef; + + +/** + * @brief USB_OTG_IN_Endpoint-Specific_Register + */ +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h */ + __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h */ + __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h */ + __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h */ + uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch */ +} USB_OTG_INEndpointTypeDef; + + +/** + * @brief USB_OTG_OUT_Endpoint-Specific_Registers + */ +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h */ + __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h */ + __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h */ + uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch */ +} USB_OTG_OUTEndpointTypeDef; + + +/** + * @brief USB_OTG_Host_Mode_Register_Structures + */ +typedef struct +{ + __IO uint32_t HCFG; /*!< Host Configuration Register 400h */ + __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h */ + __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h */ + __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h */ + __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h */ +} USB_OTG_HostTypeDef; + +/** + * @brief USB_OTG_Host_Channel_Specific_Registers + */ +typedef struct +{ + __IO uint32_t HCCHAR; /*!< Host Channel Characteristics Register 500h */ + __IO uint32_t HCSPLT; /*!< Host Channel Split Control Register 504h */ + __IO uint32_t HCINT; /*!< Host Channel Interrupt Register 508h */ + __IO uint32_t HCINTMSK; /*!< Host Channel Interrupt Mask Register 50Ch */ + __IO uint32_t HCTSIZ; /*!< Host Channel Transfer Size Register 510h */ + __IO uint32_t HCDMA; /*!< Host Channel DMA Address Register 514h */ + uint32_t Reserved[2]; /*!< Reserved */ +} USB_OTG_HostChannelTypeDef; +/** + * @} + */ + +/** + * @brief OCTO Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< OCTOSPI Control register, Address offset: 0x000 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x004 */ + __IO uint32_t DCR1; /*!< OCTOSPI Device Configuration register 1, Address offset: 0x008 */ + __IO uint32_t DCR2; /*!< OCTOSPI Device Configuration register 2, Address offset: 0x00C */ + __IO uint32_t DCR3; /*!< OCTOSPI Device Configuration register 3, Address offset: 0x010 */ + __IO uint32_t DCR4; /*!< OCTOSPI Device Configuration register 4, Address offset: 0x014 */ + uint32_t RESERVED1[2]; /*!< Reserved, Address offset: 0x018-0x01C */ + __IO uint32_t SR; /*!< OCTOSPI Status register, Address offset: 0x020 */ + __IO uint32_t FCR; /*!< OCTOSPI Flag Clear register, Address offset: 0x024 */ + uint32_t RESERVED2[6]; /*!< Reserved, Address offset: 0x028-0x03C */ + __IO uint32_t DLR; /*!< OCTOSPI Data Length register, Address offset: 0x040 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x044 */ + __IO uint32_t AR; /*!< OCTOSPI Address register, Address offset: 0x048 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x04C */ + __IO uint32_t DR; /*!< OCTOSPI Data register, Address offset: 0x050 */ + uint32_t RESERVED5[11]; /*!< Reserved, Address offset: 0x054-0x07C */ + __IO uint32_t PSMKR; /*!< OCTOSPI Polling Status Mask register, Address offset: 0x080 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x084 */ + __IO uint32_t PSMAR; /*!< OCTOSPI Polling Status Match register, Address offset: 0x088 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x08C */ + __IO uint32_t PIR; /*!< OCTOSPI Polling Interval register, Address offset: 0x090 */ + uint32_t RESERVED8[27]; /*!< Reserved, Address offset: 0x094-0x0FC */ + __IO uint32_t CCR; /*!< OCTOSPI Communication Configuration register, Address offset: 0x100 */ + uint32_t RESERVED9; /*!< Reserved, Address offset: 0x104 */ + __IO uint32_t TCR; /*!< OCTOSPI Timing Configuration register, Address offset: 0x108 */ + uint32_t RESERVED10; /*!< Reserved, Address offset: 0x10C */ + __IO uint32_t IR; /*!< OCTOSPI Instruction register, Address offset: 0x110 */ + uint32_t RESERVED11[3]; /*!< Reserved, Address offset: 0x114-0x11C */ + __IO uint32_t ABR; /*!< OCTOSPI Alternate Bytes register, Address offset: 0x120 */ + uint32_t RESERVED12[3]; /*!< Reserved, Address offset: 0x124-0x12C */ + __IO uint32_t LPTR; /*!< OCTOSPI Low Power Timeout register, Address offset: 0x130 */ + uint32_t RESERVED13[3]; /*!< Reserved, Address offset: 0x134-0x13C */ + __IO uint32_t WPCCR; /*!< OCTOSPI Wrap Communication Configuration register, Address offset: 0x140 */ + uint32_t RESERVED14; /*!< Reserved, Address offset: 0x144 */ + __IO uint32_t WPTCR; /*!< OCTOSPI Wrap Timing Configuration register, Address offset: 0x148 */ + uint32_t RESERVED15; /*!< Reserved, Address offset: 0x14C */ + __IO uint32_t WPIR; /*!< OCTOSPI Wrap Instruction register, Address offset: 0x150 */ + uint32_t RESERVED16[3]; /*!< Reserved, Address offset: 0x154-0x15C */ + __IO uint32_t WPABR; /*!< OCTOSPI Wrap Alternate Bytes register, Address offset: 0x160 */ + uint32_t RESERVED17[7]; /*!< Reserved, Address offset: 0x164-0x17C */ + __IO uint32_t WCCR; /*!< OCTOSPI Write Communication Configuration register, Address offset: 0x180 */ + uint32_t RESERVED18; /*!< Reserved, Address offset: 0x184 */ + __IO uint32_t WTCR; /*!< OCTOSPI Write Timing Configuration register, Address offset: 0x188 */ + uint32_t RESERVED19; /*!< Reserved, Address offset: 0x18C */ + __IO uint32_t WIR; /*!< OCTOSPI Write Instruction register, Address offset: 0x190 */ + uint32_t RESERVED20[3]; /*!< Reserved, Address offset: 0x194-0x19C */ + __IO uint32_t WABR; /*!< OCTOSPI Write Alternate Bytes register, Address offset: 0x1A0 */ + uint32_t RESERVED21[23]; /*!< Reserved, Address offset: 0x1A4-0x1FC */ + __IO uint32_t HLCR; /*!< OCTOSPI Hyperbus Latency Configuration register, Address offset: 0x200 */ + uint32_t RESERVED22[122]; /*!< Reserved, Address offset: 0x204-0x3EC */ + __IO uint32_t HWCFGR; /*!< OCTOSPI HW Configuration register, Address offset: 0x3F0 */ + __IO uint32_t VER; /*!< OCTOSPI Version register, Address offset: 0x3F4 */ + __IO uint32_t ID; /*!< OCTOSPI Identification register, Address offset: 0x3F8 */ + __IO uint32_t MID; /*!< OCTOPSI HW Magic ID register, Address offset: 0x3FC */ +} OCTOSPI_TypeDef; + +/** + * @} + */ +/** + * @brief OCTO Serial Peripheral Interface IO Manager + */ + +typedef struct +{ + __IO uint32_t CR; /*!< OCTOSPI IO Manager Control register, Address offset: 0x00 */ + __IO uint32_t PCR[3]; /*!< OCTOSPI IO Manager Port[1:3] Configuration register, Address offset: 0x04-0x20 */ +} OCTOSPIM_TypeDef; + +/** + * @} + */ + +/** + * @brief OTFD register + */ +typedef struct +{ + __IO uint32_t REG_CONFIGR; + __IO uint32_t REG_START_ADDR; + __IO uint32_t REG_END_ADDR; + __IO uint32_t REG_NONCER0; + __IO uint32_t REG_NONCER1; + __IO uint32_t REG_KEYR0; + __IO uint32_t REG_KEYR1; + __IO uint32_t REG_KEYR2; + __IO uint32_t REG_KEYR3; +} OTFDEC_Region_TypeDef; + +typedef struct +{ + __IO uint32_t CR; + uint32_t RESERVED1[191]; + __IO uint32_t ISR; + __IO uint32_t ICR; + __IO uint32_t IER; + uint32_t RESERVED2[56]; + __IO uint32_t HWCFGR2; + __IO uint32_t HWCFGR1; + __IO uint32_t VERR; + __IO uint32_t IPIDR; + __IO uint32_t SIDR; +} OTFDEC_TypeDef; +/** + * @} + */ + +/** + * @brief Global Programmer View + */ + +typedef struct +{ + uint32_t RESERVED0[2036]; /*!< Reserved, Address offset: 0x00-0x1FCC */ + __IO uint32_t AXI_PERIPH_ID_4; /*!< AXI interconnect - peripheral ID4 register, Address offset: 0x1FD0 */ + uint32_t AXI_PERIPH_ID_5; /*!< Reserved, Address offset: 0x1FD4 */ + uint32_t AXI_PERIPH_ID_6; /*!< Reserved, Address offset: 0x1FD8 */ + uint32_t AXI_PERIPH_ID_7; /*!< Reserved, Address offset: 0x1FDC */ + __IO uint32_t AXI_PERIPH_ID_0; /*!< AXI interconnect - peripheral ID0 register, Address offset: 0x1FE0 */ + __IO uint32_t AXI_PERIPH_ID_1; /*!< AXI interconnect - peripheral ID1 register, Address offset: 0x1FE4 */ + __IO uint32_t AXI_PERIPH_ID_2; /*!< AXI interconnect - peripheral ID2 register, Address offset: 0x1FE8 */ + __IO uint32_t AXI_PERIPH_ID_3; /*!< AXI interconnect - peripheral ID3 register, Address offset: 0x1FEC */ + __IO uint32_t AXI_COMP_ID_0; /*!< AXI interconnect - component ID0 register, Address offset: 0x1FF0 */ + __IO uint32_t AXI_COMP_ID_1; /*!< AXI interconnect - component ID1 register, Address offset: 0x1FF4 */ + __IO uint32_t AXI_COMP_ID_2; /*!< AXI interconnect - component ID2 register, Address offset: 0x1FF8 */ + __IO uint32_t AXI_COMP_ID_3; /*!< AXI interconnect - component ID3 register, Address offset: 0x1FFC */ + uint32_t RESERVED1[2]; /*!< Reserved, Address offset: 0x2000-0x2004 */ + __IO uint32_t AXI_TARG1_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 1 bus matrix issuing functionality register, Address offset: 0x2008 */ + uint32_t RESERVED2[6]; /*!< Reserved, Address offset: 0x200C-0x2020 */ + __IO uint32_t AXI_TARG1_FN_MOD2; /*!< AXI interconnect - TARG 1 bus matrix functionality 2 register, Address offset: 0x2024 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x2028 */ + __IO uint32_t AXI_TARG1_FN_MOD_LB; /*!< AXI interconnect - TARG 1 long burst functionality modification register, Address offset: 0x202C */ + uint32_t RESERVED4[54]; /*!< Reserved, Address offset: 0x2030-0x2104 */ + __IO uint32_t AXI_TARG1_FN_MOD; /*!< AXI interconnect - TARG 1 issuing functionality modification register, Address offset: 0x2108 */ + uint32_t RESERVED5[959]; /*!< Reserved, Address offset: 0x210C-0x3004 */ + __IO uint32_t AXI_TARG2_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 2 bus matrix issuing functionality register, Address offset: 0x3008 */ + uint32_t RESERVED6[6]; /*!< Reserved, Address offset: 0x300C-0x3020 */ + __IO uint32_t AXI_TARG2_FN_MOD2; /*!< AXI interconnect - TARG 2 bus matrix functionality 2 register, Address offset: 0x3024 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x3028 */ + __IO uint32_t AXI_TARG2_FN_MOD_LB; /*!< AXI interconnect - TARG 2 long burst functionality modification register, Address offset: 0x302C */ + uint32_t RESERVED8[54]; /*!< Reserved, Address offset: 0x3030-0x3104 */ + __IO uint32_t AXI_TARG2_FN_MOD; /*!< AXI interconnect - TARG 2 issuing functionality modification register, Address offset: 0x3108 */ + uint32_t RESERVED9[959]; /*!< Reserved, Address offset: 0x310C-0x4004 */ + __IO uint32_t AXI_TARG3_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 3 bus matrix issuing functionality register, Address offset: 0x4008 */ + uint32_t RESERVED10[1023]; /*!< Reserved, Address offset: 0x400C-0x5004 */ + __IO uint32_t AXI_TARG4_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 4 bus matrix issuing functionality register, Address offset: 0x5008 */ + uint32_t RESERVED11[1023]; /*!< Reserved, Address offset: 0x500C-0x6004 */ + __IO uint32_t AXI_TARG5_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 5 bus matrix issuing functionality register, Address offset: 0x6008 */ + uint32_t RESERVED12[1023]; /*!< Reserved, Address offset: 0x600C-0x7004 */ + __IO uint32_t AXI_TARG6_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 6 bus matrix issuing functionality register, Address offset: 0x7008 */ + uint32_t RESERVED13[1023]; /*!< Reserved, Address offset: 0x700C-0x8004 */ + __IO uint32_t AXI_TARG7_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 7 bus matrix issuing functionality register, Address offset: 0x8008 */ + uint32_t RESERVED14[6]; /*!< Reserved, Address offset: 0x800C-0x8020 */ + __IO uint32_t AXI_TARG7_FN_MOD2; /*!< AXI interconnect - TARG 7 bus matrix functionality 2 register, Address offset: 0x8024 */ + uint32_t RESERVED15; /*!< Reserved, Address offset: 0x8028 */ + __IO uint32_t AXI_TARG7_FN_MOD_LB; /*!< AXI interconnect - TARG 7 long burst functionality modification register, Address offset: 0x802C */ + uint32_t RESERVED16[54]; /*!< Reserved, Address offset: 0x8030-0x8104 */ + __IO uint32_t AXI_TARG7_FN_MOD; /*!< AXI interconnect - TARG 7 issuing functionality modification register, Address offset: 0x8108 */ + uint32_t RESERVED17[959]; /*!< Reserved, Address offset: 0x810C-0x9004 */ + __IO uint32_t AXI_TARG8_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 8 bus matrix issuing functionality register, Address offset: 0x9008 */ + uint32_t RESERVED117[6]; /*!< Reserved, Address offset: 0x900C-0x9020 */ + __IO uint32_t AXI_TARG8_FN_MOD2; /*!< AXI interconnect - TARG 8 bus matrix functionality 2 register, Address offset: 0x9024 */ + uint32_t RESERVED118[56]; /*!< Reserved, Address offset: 0x9028-0x9104 */ + __IO uint32_t AXI_TARG8_FN_MOD; /*!< AXI interconnect - TARG 8 issuing functionality modification register, Address offset: 0x9108 */ + uint32_t RESERVED119[58310]; /*!< Reserved, Address offset: 0x910C-0x42020 */ + __IO uint32_t AXI_INI1_FN_MOD2; /*!< AXI interconnect - INI 1 functionality modification 2 register, Address offset: 0x42024 */ + __IO uint32_t AXI_INI1_FN_MOD_AHB; /*!< AXI interconnect - INI 1 AHB functionality modification register, Address offset: 0x42028 */ + uint32_t RESERVED18[53]; /*!< Reserved, Address offset: 0x4202C-0x420FC */ + __IO uint32_t AXI_INI1_READ_QOS; /*!< AXI interconnect - INI 1 read QoS register, Address offset: 0x42100 */ + __IO uint32_t AXI_INI1_WRITE_QOS; /*!< AXI interconnect - INI 1 write QoS register, Address offset: 0x42104 */ + __IO uint32_t AXI_INI1_FN_MOD; /*!< AXI interconnect - INI 1 issuing functionality modification register, Address offset: 0x42108 */ + uint32_t RESERVED19[1021]; /*!< Reserved, Address offset: 0x4210C-0x430FC */ + __IO uint32_t AXI_INI2_READ_QOS; /*!< AXI interconnect - INI 2 read QoS register, Address offset: 0x43100 */ + __IO uint32_t AXI_INI2_WRITE_QOS; /*!< AXI interconnect - INI 2 write QoS register, Address offset: 0x43104 */ + __IO uint32_t AXI_INI2_FN_MOD; /*!< AXI interconnect - INI 2 issuing functionality modification register, Address offset: 0x43108 */ + uint32_t RESERVED20[966]; /*!< Reserved, Address offset: 0x4310C-0x44020 */ + __IO uint32_t AXI_INI3_FN_MOD2; /*!< AXI interconnect - INI 3 functionality modification 2 register, Address offset: 0x44024 */ + __IO uint32_t AXI_INI3_FN_MOD_AHB; /*!< AXI interconnect - INI 3 AHB functionality modification register, Address offset: 0x44028 */ + uint32_t RESERVED21[53]; /*!< Reserved, Address offset: 0x4402C-0x440FC */ + __IO uint32_t AXI_INI3_READ_QOS; /*!< AXI interconnect - INI 3 read QoS register, Address offset: 0x44100 */ + __IO uint32_t AXI_INI3_WRITE_QOS; /*!< AXI interconnect - INI 3 write QoS register, Address offset: 0x44104 */ + __IO uint32_t AXI_INI3_FN_MOD; /*!< AXI interconnect - INI 3 issuing functionality modification register, Address offset: 0x44108 */ + uint32_t RESERVED22[1021]; /*!< Reserved, Address offset: 0x4410C-0x450FC */ + __IO uint32_t AXI_INI4_READ_QOS; /*!< AXI interconnect - INI 4 read QoS register, Address offset: 0x45100 */ + __IO uint32_t AXI_INI4_WRITE_QOS; /*!< AXI interconnect - INI 4 write QoS register, Address offset: 0x45104 */ + __IO uint32_t AXI_INI4_FN_MOD; /*!< AXI interconnect - INI 4 issuing functionality modification register, Address offset: 0x45108 */ + uint32_t RESERVED23[1021]; /*!< Reserved, Address offset: 0x4510C-0x460FC */ + __IO uint32_t AXI_INI5_READ_QOS; /*!< AXI interconnect - INI 5 read QoS register, Address offset: 0x46100 */ + __IO uint32_t AXI_INI5_WRITE_QOS; /*!< AXI interconnect - INI 5 write QoS register, Address offset: 0x46104 */ + __IO uint32_t AXI_INI5_FN_MOD; /*!< AXI interconnect - INI 5 issuing functionality modification register, Address offset: 0x46108 */ + uint32_t RESERVED24[1021]; /*!< Reserved, Address offset: 0x4610C-0x470FC */ + __IO uint32_t AXI_INI6_READ_QOS; /*!< AXI interconnect - INI 6 read QoS register, Address offset: 0x47100 */ + __IO uint32_t AXI_INI6_WRITE_QOS; /*!< AXI interconnect - INI 6 write QoS register, Address offset: 0x47104 */ + __IO uint32_t AXI_INI6_FN_MOD; /*!< AXI interconnect - INI 6 issuing functionality modification register, Address offset: 0x47108 */ + +} GPV_TypeDef; + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define D1_ITCMRAM_BASE (0x00000000UL) /*!< Base address of : 64KB RAM reserved for CPU execution/instruction accessible over ITCM */ +#define D1_ITCMICP_BASE (0x00100000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over ITCM */ +#define D1_DTCMRAM_BASE (0x20000000UL) /*!< Base address of : 128KB system data RAM accessible over DTCM */ +#define D1_AXIFLASH_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) embedded FLASH memory accessible over AXI */ +#define D1_AXIICP_BASE (0x1FF00000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over AXI */ +#define D1_AXISRAM1_BASE (0x24000000UL) /*!< Base address of : (up to 128KB) system data RAM1 accessible over over AXI */ +#define D1_AXISRAM2_BASE (0x24020000UL) /*!< Base address of : (up to 192KB) system data RAM2 accessible over over AXI to be shared with ITCM (64K granularity) */ +#define D1_AXISRAM_BASE D1_AXISRAM1_BASE /*!< Base address of : (up to 320KB) system data RAM1/2 accessible over over AXI */ + +#define D2_AHBSRAM1_BASE (0x30000000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */ +#define D2_AHBSRAM2_BASE (0x30004000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */ +#define D2_AHBSRAM_BASE D2_AHBSRAM1_BASE /*!< Base address of : (up to 32KB) system data RAM1/2 accessible over over AXI->AHB Bridge */ + +#define D3_BKPSRAM_BASE (0x38800000UL) /*!< Base address of : Backup SRAM(4 KB) over AXI->AHB Bridge */ +#define D3_SRAM_BASE (0x38000000UL) /*!< Base address of : Backup SRAM(16 KB) over AXI->AHB Bridge */ + +#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */ +#define OCTOSPI1_BASE (0x90000000UL) /*!< Base address of : OCTOSPI1 memories accessible over AXI */ +#define OCTOSPI2_BASE (0x70000000UL) /*!< Base address of : OCTOSPI2 memories accessible over AXI */ + +#define FLASH_BANK1_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) Flash Bank1 accessible over AXI */ +#define FLASH_END (0x080FFFFFUL) /*!< FLASH end address */ + + +/* Legacy define */ +#define FLASH_BASE FLASH_BANK1_BASE + +/*!< Device electronic signature memory map */ +#define UID_BASE (0x1FF1E800UL) /*!< Unique device ID register base address */ +#define FLASHSIZE_BASE (0x1FF1E880UL) /*!< FLASH Size register base address */ + + +/*!< Peripheral memory map */ +#define D2_APB1PERIPH_BASE PERIPH_BASE +#define D2_APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define D2_AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define D2_AHB2PERIPH_BASE (PERIPH_BASE + 0x08020000UL) + +#define D1_APB1PERIPH_BASE (PERIPH_BASE + 0x10000000UL) +#define D1_AHB1PERIPH_BASE (PERIPH_BASE + 0x12000000UL) + +#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL) +#define D3_AHB1PERIPH_BASE (PERIPH_BASE + 0x18020000UL) + +/*!< Legacy Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000UL) + + +/*!< D1_AHB1PERIPH peripherals */ + +#define MDMA_BASE (D1_AHB1PERIPH_BASE + 0x0000UL) +#define DMA2D_BASE (D1_AHB1PERIPH_BASE + 0x1000UL) +#define FLASH_R_BASE (D1_AHB1PERIPH_BASE + 0x2000UL) +#define FMC_R_BASE (D1_AHB1PERIPH_BASE + 0x4000UL) +#define OCTOSPI1_R_BASE (D1_AHB1PERIPH_BASE + 0x5000UL) +#define DLYB_OCTOSPI1_BASE (D1_AHB1PERIPH_BASE + 0x6000UL) +#define SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x7000UL) +#define DLYB_SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x8000UL) +#define RAMECC1_BASE (D1_AHB1PERIPH_BASE + 0x9000UL) +#define OCTOSPI2_R_BASE (D1_AHB1PERIPH_BASE + 0xA000UL) +#define DLYB_OCTOSPI2_BASE (D1_AHB1PERIPH_BASE + 0xB000UL) +#define OCTOSPIM_BASE (D1_AHB1PERIPH_BASE + 0xB400UL) + +#define OTFDEC1_BASE (D1_AHB1PERIPH_BASE + 0xB800UL) +#define OTFDEC1_REGION1_BASE (OTFDEC1_BASE + 0x20UL) +#define OTFDEC1_REGION2_BASE (OTFDEC1_BASE + 0x50UL) +#define OTFDEC1_REGION3_BASE (OTFDEC1_BASE + 0x80UL) +#define OTFDEC1_REGION4_BASE (OTFDEC1_BASE + 0xB0UL) +#define OTFDEC2_BASE (D1_AHB1PERIPH_BASE + 0xBC00UL) +#define OTFDEC2_REGION1_BASE (OTFDEC2_BASE + 0x20UL) +#define OTFDEC2_REGION2_BASE (OTFDEC2_BASE + 0x50UL) +#define OTFDEC2_REGION3_BASE (OTFDEC2_BASE + 0x80UL) +#define OTFDEC2_REGION4_BASE (OTFDEC2_BASE + 0xB0UL) + +/*!< D2_AHB1PERIPH peripherals */ + +#define DMA1_BASE (D2_AHB1PERIPH_BASE + 0x0000UL) +#define DMA2_BASE (D2_AHB1PERIPH_BASE + 0x0400UL) +#define DMAMUX1_BASE (D2_AHB1PERIPH_BASE + 0x0800UL) +#define ADC1_BASE (D2_AHB1PERIPH_BASE + 0x2000UL) +#define ADC2_BASE (D2_AHB1PERIPH_BASE + 0x2100UL) +#define ADC12_COMMON_BASE (D2_AHB1PERIPH_BASE + 0x2300UL) +#define ETH_BASE (D2_AHB1PERIPH_BASE + 0x8000UL) +#define ETH_MAC_BASE (ETH_BASE) + +/*!< USB registers base address */ +#define USB1_OTG_HS_PERIPH_BASE (0x40040000UL) +#define USB_OTG_GLOBAL_BASE (0x000UL) +#define USB_OTG_DEVICE_BASE (0x800UL) +#define USB_OTG_IN_ENDPOINT_BASE (0x900UL) +#define USB_OTG_OUT_ENDPOINT_BASE (0xB00UL) +#define USB_OTG_EP_REG_SIZE (0x20UL) +#define USB_OTG_HOST_BASE (0x400UL) +#define USB_OTG_HOST_PORT_BASE (0x440UL) +#define USB_OTG_HOST_CHANNEL_BASE (0x500UL) +#define USB_OTG_HOST_CHANNEL_SIZE (0x20UL) +#define USB_OTG_PCGCCTL_BASE (0xE00UL) +#define USB_OTG_FIFO_BASE (0x1000UL) +#define USB_OTG_FIFO_SIZE (0x1000UL) + +/*!< D2_AHB2PERIPH peripherals */ + +#define DCMI_BASE (D2_AHB2PERIPH_BASE + 0x0000UL) +#define PSSI_BASE (D2_AHB2PERIPH_BASE + 0x0400UL) +#define CRYP_BASE (D2_AHB2PERIPH_BASE + 0x1000UL) +#define HASH_BASE (D2_AHB2PERIPH_BASE + 0x1400UL) +#define HASH_DIGEST_BASE (D2_AHB2PERIPH_BASE + 0x1710UL) +#define RNG_BASE (D2_AHB2PERIPH_BASE + 0x1800UL) +#define SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2400UL) +#define DLYB_SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2800UL) +#define RAMECC2_BASE (D2_AHB2PERIPH_BASE + 0x3000UL) +#define FMAC_BASE (D2_AHB2PERIPH_BASE + 0x4000UL) +#define CORDIC_BASE (D2_AHB2PERIPH_BASE + 0x4400UL) + +/*!< D3_AHB1PERIPH peripherals */ +#define GPIOA_BASE (D3_AHB1PERIPH_BASE + 0x0000UL) +#define GPIOB_BASE (D3_AHB1PERIPH_BASE + 0x0400UL) +#define GPIOC_BASE (D3_AHB1PERIPH_BASE + 0x0800UL) +#define GPIOD_BASE (D3_AHB1PERIPH_BASE + 0x0C00UL) +#define GPIOE_BASE (D3_AHB1PERIPH_BASE + 0x1000UL) +#define GPIOF_BASE (D3_AHB1PERIPH_BASE + 0x1400UL) +#define GPIOG_BASE (D3_AHB1PERIPH_BASE + 0x1800UL) +#define GPIOH_BASE (D3_AHB1PERIPH_BASE + 0x1C00UL) +#define GPIOJ_BASE (D3_AHB1PERIPH_BASE + 0x2400UL) +#define GPIOK_BASE (D3_AHB1PERIPH_BASE + 0x2800UL) +#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL) +#define PWR_BASE (D3_AHB1PERIPH_BASE + 0x4800UL) +#define CRC_BASE (D3_AHB1PERIPH_BASE + 0x4C00UL) +#define BDMA_BASE (D3_AHB1PERIPH_BASE + 0x5400UL) +#define DMAMUX2_BASE (D3_AHB1PERIPH_BASE + 0x5800UL) +#define ADC3_BASE (D3_AHB1PERIPH_BASE + 0x6000UL) +#define ADC3_COMMON_BASE (D3_AHB1PERIPH_BASE + 0x6300UL) +#define HSEM_BASE (D3_AHB1PERIPH_BASE + 0x6400UL) +#define RAMECC3_BASE (D3_AHB1PERIPH_BASE + 0x7000UL) + +/*!< D1_APB1PERIPH peripherals */ +#define LTDC_BASE (D1_APB1PERIPH_BASE + 0x1000UL) +#define LTDC_Layer1_BASE (LTDC_BASE + 0x84UL) +#define LTDC_Layer2_BASE (LTDC_BASE + 0x104UL) +#define WWDG1_BASE (D1_APB1PERIPH_BASE + 0x3000UL) + +/*!< D2_APB1PERIPH peripherals */ +#define TIM2_BASE (D2_APB1PERIPH_BASE + 0x0000UL) +#define TIM3_BASE (D2_APB1PERIPH_BASE + 0x0400UL) +#define TIM4_BASE (D2_APB1PERIPH_BASE + 0x0800UL) +#define TIM5_BASE (D2_APB1PERIPH_BASE + 0x0C00UL) +#define TIM6_BASE (D2_APB1PERIPH_BASE + 0x1000UL) +#define TIM7_BASE (D2_APB1PERIPH_BASE + 0x1400UL) +#define TIM12_BASE (D2_APB1PERIPH_BASE + 0x1800UL) +#define TIM13_BASE (D2_APB1PERIPH_BASE + 0x1C00UL) +#define TIM14_BASE (D2_APB1PERIPH_BASE + 0x2000UL) +#define LPTIM1_BASE (D2_APB1PERIPH_BASE + 0x2400UL) + + +#define SPI2_BASE (D2_APB1PERIPH_BASE + 0x3800UL) +#define SPI3_BASE (D2_APB1PERIPH_BASE + 0x3C00UL) +#define SPDIFRX_BASE (D2_APB1PERIPH_BASE + 0x4000UL) +#define USART2_BASE (D2_APB1PERIPH_BASE + 0x4400UL) +#define USART3_BASE (D2_APB1PERIPH_BASE + 0x4800UL) +#define UART4_BASE (D2_APB1PERIPH_BASE + 0x4C00UL) +#define UART5_BASE (D2_APB1PERIPH_BASE + 0x5000UL) +#define I2C1_BASE (D2_APB1PERIPH_BASE + 0x5400UL) +#define I2C2_BASE (D2_APB1PERIPH_BASE + 0x5800UL) +#define I2C3_BASE (D2_APB1PERIPH_BASE + 0x5C00UL) +#define I2C5_BASE (D2_APB1PERIPH_BASE + 0x6400UL) +#define CEC_BASE (D2_APB1PERIPH_BASE + 0x6C00UL) +#define DAC1_BASE (D2_APB1PERIPH_BASE + 0x7400UL) +#define UART7_BASE (D2_APB1PERIPH_BASE + 0x7800UL) +#define UART8_BASE (D2_APB1PERIPH_BASE + 0x7C00UL) +#define CRS_BASE (D2_APB1PERIPH_BASE + 0x8400UL) +#define SWPMI1_BASE (D2_APB1PERIPH_BASE + 0x8800UL) +#define OPAMP_BASE (D2_APB1PERIPH_BASE + 0x9000UL) +#define OPAMP1_BASE (D2_APB1PERIPH_BASE + 0x9000UL) +#define OPAMP2_BASE (D2_APB1PERIPH_BASE + 0x9010UL) +#define MDIOS_BASE (D2_APB1PERIPH_BASE + 0x9400UL) +#define FDCAN1_BASE (D2_APB1PERIPH_BASE + 0xA000UL) +#define FDCAN2_BASE (D2_APB1PERIPH_BASE + 0xA400UL) +#define FDCAN_CCU_BASE (D2_APB1PERIPH_BASE + 0xA800UL) +#define SRAMCAN_BASE (D2_APB1PERIPH_BASE + 0xAC00UL) +#define FDCAN3_BASE (D2_APB1PERIPH_BASE + 0xD400UL) +#define TIM23_BASE (D2_APB1PERIPH_BASE + 0xE000UL) +#define TIM24_BASE (D2_APB1PERIPH_BASE + 0xE400UL) + +/*!< D2_APB2PERIPH peripherals */ + +#define TIM1_BASE (D2_APB2PERIPH_BASE + 0x0000UL) +#define TIM8_BASE (D2_APB2PERIPH_BASE + 0x0400UL) +#define USART1_BASE (D2_APB2PERIPH_BASE + 0x1000UL) +#define USART6_BASE (D2_APB2PERIPH_BASE + 0x1400UL) +#define UART9_BASE (D2_APB2PERIPH_BASE + 0x1800UL) +#define USART10_BASE (D2_APB2PERIPH_BASE + 0x1C00UL) +#define SPI1_BASE (D2_APB2PERIPH_BASE + 0x3000UL) +#define SPI4_BASE (D2_APB2PERIPH_BASE + 0x3400UL) +#define TIM15_BASE (D2_APB2PERIPH_BASE + 0x4000UL) +#define TIM16_BASE (D2_APB2PERIPH_BASE + 0x4400UL) +#define TIM17_BASE (D2_APB2PERIPH_BASE + 0x4800UL) +#define SPI5_BASE (D2_APB2PERIPH_BASE + 0x5000UL) +#define SAI1_BASE (D2_APB2PERIPH_BASE + 0x5800UL) +#define SAI1_Block_A_BASE (SAI1_BASE + 0x004UL) +#define SAI1_Block_B_BASE (SAI1_BASE + 0x024UL) +#define DFSDM1_BASE (D2_APB2PERIPH_BASE + 0x7800UL) +#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x00UL) +#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x20UL) +#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x40UL) +#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x60UL) +#define DFSDM1_Channel4_BASE (DFSDM1_BASE + 0x80UL) +#define DFSDM1_Channel5_BASE (DFSDM1_BASE + 0xA0UL) +#define DFSDM1_Channel6_BASE (DFSDM1_BASE + 0xC0UL) +#define DFSDM1_Channel7_BASE (DFSDM1_BASE + 0xE0UL) +#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x100UL) +#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x180UL) +#define DFSDM1_Filter2_BASE (DFSDM1_BASE + 0x200UL) +#define DFSDM1_Filter3_BASE (DFSDM1_BASE + 0x280UL) + + +/*!< D3_APB1PERIPH peripherals */ +#define EXTI_BASE (D3_APB1PERIPH_BASE + 0x0000UL) +#define EXTI_D1_BASE (EXTI_BASE + 0x0080UL) +#define EXTI_D2_BASE (EXTI_BASE + 0x00C0UL) +#define SYSCFG_BASE (D3_APB1PERIPH_BASE + 0x0400UL) +#define LPUART1_BASE (D3_APB1PERIPH_BASE + 0x0C00UL) +#define SPI6_BASE (D3_APB1PERIPH_BASE + 0x1400UL) +#define I2C4_BASE (D3_APB1PERIPH_BASE + 0x1C00UL) +#define LPTIM2_BASE (D3_APB1PERIPH_BASE + 0x2400UL) +#define LPTIM3_BASE (D3_APB1PERIPH_BASE + 0x2800UL) +#define LPTIM4_BASE (D3_APB1PERIPH_BASE + 0x2C00UL) +#define LPTIM5_BASE (D3_APB1PERIPH_BASE + 0x3000UL) +#define COMP12_BASE (D3_APB1PERIPH_BASE + 0x3800UL) +#define COMP1_BASE (COMP12_BASE + 0x0CUL) +#define COMP2_BASE (COMP12_BASE + 0x10UL) +#define VREFBUF_BASE (D3_APB1PERIPH_BASE + 0x3C00UL) +#define RTC_BASE (D3_APB1PERIPH_BASE + 0x4000UL) +#define IWDG1_BASE (D3_APB1PERIPH_BASE + 0x4800UL) + + +#define SAI4_BASE (D3_APB1PERIPH_BASE + 0x5400UL) +#define SAI4_Block_A_BASE (SAI4_BASE + 0x004UL) +#define SAI4_Block_B_BASE (SAI4_BASE + 0x024UL) + +#define DTS_BASE (D3_APB1PERIPH_BASE + 0x6800UL) + + + +#define BDMA_Channel0_BASE (BDMA_BASE + 0x0008UL) +#define BDMA_Channel1_BASE (BDMA_BASE + 0x001CUL) +#define BDMA_Channel2_BASE (BDMA_BASE + 0x0030UL) +#define BDMA_Channel3_BASE (BDMA_BASE + 0x0044UL) +#define BDMA_Channel4_BASE (BDMA_BASE + 0x0058UL) +#define BDMA_Channel5_BASE (BDMA_BASE + 0x006CUL) +#define BDMA_Channel6_BASE (BDMA_BASE + 0x0080UL) +#define BDMA_Channel7_BASE (BDMA_BASE + 0x0094UL) + +#define DMAMUX2_Channel0_BASE (DMAMUX2_BASE) +#define DMAMUX2_Channel1_BASE (DMAMUX2_BASE + 0x0004UL) +#define DMAMUX2_Channel2_BASE (DMAMUX2_BASE + 0x0008UL) +#define DMAMUX2_Channel3_BASE (DMAMUX2_BASE + 0x000CUL) +#define DMAMUX2_Channel4_BASE (DMAMUX2_BASE + 0x0010UL) +#define DMAMUX2_Channel5_BASE (DMAMUX2_BASE + 0x0014UL) +#define DMAMUX2_Channel6_BASE (DMAMUX2_BASE + 0x0018UL) +#define DMAMUX2_Channel7_BASE (DMAMUX2_BASE + 0x001CUL) + +#define DMAMUX2_RequestGenerator0_BASE (DMAMUX2_BASE + 0x0100UL) +#define DMAMUX2_RequestGenerator1_BASE (DMAMUX2_BASE + 0x0104UL) +#define DMAMUX2_RequestGenerator2_BASE (DMAMUX2_BASE + 0x0108UL) +#define DMAMUX2_RequestGenerator3_BASE (DMAMUX2_BASE + 0x010CUL) +#define DMAMUX2_RequestGenerator4_BASE (DMAMUX2_BASE + 0x0110UL) +#define DMAMUX2_RequestGenerator5_BASE (DMAMUX2_BASE + 0x0114UL) +#define DMAMUX2_RequestGenerator6_BASE (DMAMUX2_BASE + 0x0118UL) +#define DMAMUX2_RequestGenerator7_BASE (DMAMUX2_BASE + 0x011CUL) + +#define DMAMUX2_ChannelStatus_BASE (DMAMUX2_BASE + 0x0080UL) +#define DMAMUX2_RequestGenStatus_BASE (DMAMUX2_BASE + 0x0140UL) + +#define DMA1_Stream0_BASE (DMA1_BASE + 0x010UL) +#define DMA1_Stream1_BASE (DMA1_BASE + 0x028UL) +#define DMA1_Stream2_BASE (DMA1_BASE + 0x040UL) +#define DMA1_Stream3_BASE (DMA1_BASE + 0x058UL) +#define DMA1_Stream4_BASE (DMA1_BASE + 0x070UL) +#define DMA1_Stream5_BASE (DMA1_BASE + 0x088UL) +#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0UL) +#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8UL) + +#define DMA2_Stream0_BASE (DMA2_BASE + 0x010UL) +#define DMA2_Stream1_BASE (DMA2_BASE + 0x028UL) +#define DMA2_Stream2_BASE (DMA2_BASE + 0x040UL) +#define DMA2_Stream3_BASE (DMA2_BASE + 0x058UL) +#define DMA2_Stream4_BASE (DMA2_BASE + 0x070UL) +#define DMA2_Stream5_BASE (DMA2_BASE + 0x088UL) +#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0UL) +#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8UL) + +#define DMAMUX1_Channel0_BASE (DMAMUX1_BASE) +#define DMAMUX1_Channel1_BASE (DMAMUX1_BASE + 0x0004UL) +#define DMAMUX1_Channel2_BASE (DMAMUX1_BASE + 0x0008UL) +#define DMAMUX1_Channel3_BASE (DMAMUX1_BASE + 0x000CUL) +#define DMAMUX1_Channel4_BASE (DMAMUX1_BASE + 0x0010UL) +#define DMAMUX1_Channel5_BASE (DMAMUX1_BASE + 0x0014UL) +#define DMAMUX1_Channel6_BASE (DMAMUX1_BASE + 0x0018UL) +#define DMAMUX1_Channel7_BASE (DMAMUX1_BASE + 0x001CUL) +#define DMAMUX1_Channel8_BASE (DMAMUX1_BASE + 0x0020UL) +#define DMAMUX1_Channel9_BASE (DMAMUX1_BASE + 0x0024UL) +#define DMAMUX1_Channel10_BASE (DMAMUX1_BASE + 0x0028UL) +#define DMAMUX1_Channel11_BASE (DMAMUX1_BASE + 0x002CUL) +#define DMAMUX1_Channel12_BASE (DMAMUX1_BASE + 0x0030UL) +#define DMAMUX1_Channel13_BASE (DMAMUX1_BASE + 0x0034UL) +#define DMAMUX1_Channel14_BASE (DMAMUX1_BASE + 0x0038UL) +#define DMAMUX1_Channel15_BASE (DMAMUX1_BASE + 0x003CUL) + +#define DMAMUX1_RequestGenerator0_BASE (DMAMUX1_BASE + 0x0100UL) +#define DMAMUX1_RequestGenerator1_BASE (DMAMUX1_BASE + 0x0104UL) +#define DMAMUX1_RequestGenerator2_BASE (DMAMUX1_BASE + 0x0108UL) +#define DMAMUX1_RequestGenerator3_BASE (DMAMUX1_BASE + 0x010CUL) +#define DMAMUX1_RequestGenerator4_BASE (DMAMUX1_BASE + 0x0110UL) +#define DMAMUX1_RequestGenerator5_BASE (DMAMUX1_BASE + 0x0114UL) +#define DMAMUX1_RequestGenerator6_BASE (DMAMUX1_BASE + 0x0118UL) +#define DMAMUX1_RequestGenerator7_BASE (DMAMUX1_BASE + 0x011CUL) + +#define DMAMUX1_ChannelStatus_BASE (DMAMUX1_BASE + 0x0080UL) +#define DMAMUX1_RequestGenStatus_BASE (DMAMUX1_BASE + 0x0140UL) + +/*!< FMC Banks registers base address */ +#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000UL) +#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104UL) +#define FMC_Bank2_R_BASE (FMC_R_BASE + 0x0060UL) +#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080UL) +#define FMC_Bank5_6_R_BASE (FMC_R_BASE + 0x0140UL) + +/* Debug MCU registers base address */ +#define DBGMCU_BASE (0x5C001000UL) + +#define MDMA_Channel0_BASE (MDMA_BASE + 0x00000040UL) +#define MDMA_Channel1_BASE (MDMA_BASE + 0x00000080UL) +#define MDMA_Channel2_BASE (MDMA_BASE + 0x000000C0UL) +#define MDMA_Channel3_BASE (MDMA_BASE + 0x00000100UL) +#define MDMA_Channel4_BASE (MDMA_BASE + 0x00000140UL) +#define MDMA_Channel5_BASE (MDMA_BASE + 0x00000180UL) +#define MDMA_Channel6_BASE (MDMA_BASE + 0x000001C0UL) +#define MDMA_Channel7_BASE (MDMA_BASE + 0x00000200UL) +#define MDMA_Channel8_BASE (MDMA_BASE + 0x00000240UL) +#define MDMA_Channel9_BASE (MDMA_BASE + 0x00000280UL) +#define MDMA_Channel10_BASE (MDMA_BASE + 0x000002C0UL) +#define MDMA_Channel11_BASE (MDMA_BASE + 0x00000300UL) +#define MDMA_Channel12_BASE (MDMA_BASE + 0x00000340UL) +#define MDMA_Channel13_BASE (MDMA_BASE + 0x00000380UL) +#define MDMA_Channel14_BASE (MDMA_BASE + 0x000003C0UL) +#define MDMA_Channel15_BASE (MDMA_BASE + 0x00000400UL) + +#define RAMECC1_Monitor1_BASE (RAMECC1_BASE + 0x20UL) +#define RAMECC1_Monitor2_BASE (RAMECC1_BASE + 0x40UL) +#define RAMECC1_Monitor3_BASE (RAMECC1_BASE + 0x60UL) +#define RAMECC1_Monitor4_BASE (RAMECC1_BASE + 0x80UL) +#define RAMECC1_Monitor5_BASE (RAMECC1_BASE + 0xA0UL) +#define RAMECC1_Monitor6_BASE (RAMECC1_BASE + 0xC0UL) + +#define RAMECC2_Monitor1_BASE (RAMECC2_BASE + 0x20UL) +#define RAMECC2_Monitor2_BASE (RAMECC2_BASE + 0x40UL) +#define RAMECC2_Monitor3_BASE (RAMECC2_BASE + 0x60UL) + +#define RAMECC3_Monitor1_BASE (RAMECC3_BASE + 0x20UL) +#define RAMECC3_Monitor2_BASE (RAMECC3_BASE + 0x40UL) + + + +#define GPV_BASE (PERIPH_BASE + 0x11000000UL) /*!< GPV_BASE (PERIPH_BASE + 0x11000000UL) */ + +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define TIM13 ((TIM_TypeDef *) TIM13_BASE) +#define TIM14 ((TIM_TypeDef *) TIM14_BASE) +#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG1 ((WWDG_TypeDef *) WWDG1_BASE) + + +#define IWDG1 ((IWDG_TypeDef *) IWDG1_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define SPI4 ((SPI_TypeDef *) SPI4_BASE) +#define SPI5 ((SPI_TypeDef *) SPI5_BASE) +#define SPI6 ((SPI_TypeDef *) SPI6_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define USART6 ((USART_TypeDef *) USART6_BASE) +#define USART10 ((USART_TypeDef *) USART10_BASE) +#define UART7 ((USART_TypeDef *) UART7_BASE) +#define UART8 ((USART_TypeDef *) UART8_BASE) +#define UART9 ((USART_TypeDef *) UART9_BASE) +#define CRS ((CRS_TypeDef *) CRS_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define I2C4 ((I2C_TypeDef *) I2C4_BASE) +#define I2C5 ((I2C_TypeDef *) I2C5_BASE) +#define FDCAN1 ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) +#define FDCAN2 ((FDCAN_GlobalTypeDef *) FDCAN2_BASE) +#define FDCAN_CCU ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE) +#define FDCAN3 ((FDCAN_GlobalTypeDef *) FDCAN3_BASE) +#define TIM23 ((TIM_TypeDef *) TIM23_BASE) +#define TIM24 ((TIM_TypeDef *) TIM24_BASE) +#define CEC ((CEC_TypeDef *) CEC_BASE) +#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC1 ((DAC_TypeDef *) DAC1_BASE) +#define LPUART1 ((USART_TypeDef *) LPUART1_BASE) +#define SWPMI1 ((SWPMI_TypeDef *) SWPMI1_BASE) +#define LPTIM2 ((LPTIM_TypeDef *) LPTIM2_BASE) +#define LPTIM3 ((LPTIM_TypeDef *) LPTIM3_BASE) +#define DTS ((DTS_TypeDef *) DTS_BASE) +#define LPTIM4 ((LPTIM_TypeDef *) LPTIM4_BASE) +#define LPTIM5 ((LPTIM_TypeDef *) LPTIM5_BASE) + +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define COMP12 ((COMPOPT_TypeDef *) COMP12_BASE) +#define COMP1 ((COMP_TypeDef *) COMP1_BASE) +#define COMP2 ((COMP_TypeDef *) COMP2_BASE) +#define COMP12_COMMON ((COMP_Common_TypeDef *) COMP2_BASE) +#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE) +#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE) +#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE) + + +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define EXTI_D1 ((EXTI_Core_TypeDef *) EXTI_D1_BASE) +#define EXTI_D2 ((EXTI_Core_TypeDef *) EXTI_D2_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define TIM12 ((TIM_TypeDef *) TIM12_BASE) +#define TIM15 ((TIM_TypeDef *) TIM15_BASE) +#define TIM16 ((TIM_TypeDef *) TIM16_BASE) +#define TIM17 ((TIM_TypeDef *) TIM17_BASE) +#define SAI1 ((SAI_TypeDef *) SAI1_BASE) +#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) +#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) +#define SAI4 ((SAI_TypeDef *) SAI4_BASE) +#define SAI4_Block_A ((SAI_Block_TypeDef *)SAI4_Block_A_BASE) +#define SAI4_Block_B ((SAI_Block_TypeDef *)SAI4_Block_B_BASE) + +#define SPDIFRX ((SPDIFRX_TypeDef *) SPDIFRX_BASE) +#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE) +#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE) +#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE) +#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE) +#define DFSDM1_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel4_BASE) +#define DFSDM1_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel5_BASE) +#define DFSDM1_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel6_BASE) +#define DFSDM1_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel7_BASE) +#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE) +#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE) +#define DFSDM1_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter2_BASE) +#define DFSDM1_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter3_BASE) +#define DMA2D ((DMA2D_TypeDef *) DMA2D_BASE) +#define DCMI ((DCMI_TypeDef *) DCMI_BASE) +#define PSSI ((PSSI_TypeDef *) PSSI_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) + +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE) +#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE) + +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define ADC3_COMMON ((ADC_Common_TypeDef *) ADC3_COMMON_BASE) +#define ADC12_COMMON ((ADC_Common_TypeDef *) ADC12_COMMON_BASE) + +#define CRYP ((CRYP_TypeDef *) CRYP_BASE) +#define HASH ((HASH_TypeDef *) HASH_BASE) +#define HASH_DIGEST ((HASH_DIGEST_TypeDef *) HASH_DIGEST_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) +#define SDMMC2 ((SDMMC_TypeDef *) SDMMC2_BASE) +#define DLYB_SDMMC2 ((DLYB_TypeDef *) DLYB_SDMMC2_BASE) +#define FMAC ((FMAC_TypeDef *) FMAC_BASE) +#define CORDIC ((CORDIC_TypeDef *) CORDIC_BASE) + +#define BDMA ((BDMA_TypeDef *) BDMA_BASE) +#define BDMA_Channel0 ((BDMA_Channel_TypeDef *) BDMA_Channel0_BASE) +#define BDMA_Channel1 ((BDMA_Channel_TypeDef *) BDMA_Channel1_BASE) +#define BDMA_Channel2 ((BDMA_Channel_TypeDef *) BDMA_Channel2_BASE) +#define BDMA_Channel3 ((BDMA_Channel_TypeDef *) BDMA_Channel3_BASE) +#define BDMA_Channel4 ((BDMA_Channel_TypeDef *) BDMA_Channel4_BASE) +#define BDMA_Channel5 ((BDMA_Channel_TypeDef *) BDMA_Channel5_BASE) +#define BDMA_Channel6 ((BDMA_Channel_TypeDef *) BDMA_Channel6_BASE) +#define BDMA_Channel7 ((BDMA_Channel_TypeDef *) BDMA_Channel7_BASE) + +#define RAMECC1 ((RAMECC_TypeDef *)RAMECC1_BASE) +#define RAMECC1_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor1_BASE) +#define RAMECC1_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor2_BASE) +#define RAMECC1_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor3_BASE) +#define RAMECC1_Monitor4 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor4_BASE) +#define RAMECC1_Monitor5 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor5_BASE) +#define RAMECC1_Monitor6 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor6_BASE) + +#define RAMECC2 ((RAMECC_TypeDef *)RAMECC2_BASE) +#define RAMECC2_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor1_BASE) +#define RAMECC2_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor2_BASE) +#define RAMECC2_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor3_BASE) + +#define RAMECC3 ((RAMECC_TypeDef *)RAMECC3_BASE) +#define RAMECC3_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor1_BASE) +#define RAMECC3_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor2_BASE) + +#define DMAMUX2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_BASE) +#define DMAMUX2_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel0_BASE) +#define DMAMUX2_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel1_BASE) +#define DMAMUX2_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel2_BASE) +#define DMAMUX2_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel3_BASE) +#define DMAMUX2_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel4_BASE) +#define DMAMUX2_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel5_BASE) +#define DMAMUX2_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel6_BASE) +#define DMAMUX2_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel7_BASE) + + +#define DMAMUX2_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator0_BASE) +#define DMAMUX2_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator1_BASE) +#define DMAMUX2_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator2_BASE) +#define DMAMUX2_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator3_BASE) +#define DMAMUX2_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator4_BASE) +#define DMAMUX2_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator5_BASE) +#define DMAMUX2_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator6_BASE) +#define DMAMUX2_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator7_BASE) + +#define DMAMUX2_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX2_ChannelStatus_BASE) +#define DMAMUX2_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX2_RequestGenStatus_BASE) + +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define DMA2_Stream0 ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE) +#define DMA2_Stream1 ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE) +#define DMA2_Stream2 ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE) +#define DMA2_Stream3 ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE) +#define DMA2_Stream4 ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE) +#define DMA2_Stream5 ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE) +#define DMA2_Stream6 ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE) +#define DMA2_Stream7 ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE) + +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA1_Stream0 ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE) +#define DMA1_Stream1 ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE) +#define DMA1_Stream2 ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE) +#define DMA1_Stream3 ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE) +#define DMA1_Stream4 ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE) +#define DMA1_Stream5 ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE) +#define DMA1_Stream6 ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE) +#define DMA1_Stream7 ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE) + + +#define DMAMUX1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_BASE) +#define DMAMUX1_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel0_BASE) +#define DMAMUX1_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel1_BASE) +#define DMAMUX1_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel2_BASE) +#define DMAMUX1_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel3_BASE) +#define DMAMUX1_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel4_BASE) +#define DMAMUX1_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel5_BASE) +#define DMAMUX1_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel6_BASE) +#define DMAMUX1_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel7_BASE) +#define DMAMUX1_Channel8 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel8_BASE) +#define DMAMUX1_Channel9 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel9_BASE) +#define DMAMUX1_Channel10 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel10_BASE) +#define DMAMUX1_Channel11 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel11_BASE) +#define DMAMUX1_Channel12 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel12_BASE) +#define DMAMUX1_Channel13 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel13_BASE) +#define DMAMUX1_Channel14 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel14_BASE) +#define DMAMUX1_Channel15 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel15_BASE) + +#define DMAMUX1_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator0_BASE) +#define DMAMUX1_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator1_BASE) +#define DMAMUX1_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator2_BASE) +#define DMAMUX1_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator3_BASE) +#define DMAMUX1_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator4_BASE) +#define DMAMUX1_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator5_BASE) +#define DMAMUX1_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator6_BASE) +#define DMAMUX1_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator7_BASE) + +#define DMAMUX1_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX1_ChannelStatus_BASE) +#define DMAMUX1_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX1_RequestGenStatus_BASE) + + +#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE) +#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE) +#define FMC_Bank2_R ((FMC_Bank2_TypeDef *) FMC_Bank2_R_BASE) +#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE) +#define FMC_Bank5_6_R ((FMC_Bank5_6_TypeDef *) FMC_Bank5_6_R_BASE) + +#define OCTOSPI1 ((OCTOSPI_TypeDef *) OCTOSPI1_R_BASE) +#define DLYB_OCTOSPI1 ((DLYB_TypeDef *) DLYB_OCTOSPI1_BASE) +#define OCTOSPI2 ((OCTOSPI_TypeDef *) OCTOSPI2_R_BASE) +#define DLYB_OCTOSPI2 ((DLYB_TypeDef *) DLYB_OCTOSPI2_BASE) +#define OCTOSPIM ((OCTOSPIM_TypeDef *) OCTOSPIM_BASE) + +#define OTFDEC1 ((OTFDEC_TypeDef *) OTFDEC1_BASE) +#define OTFDEC1_REGION1 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION1_BASE) +#define OTFDEC1_REGION2 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION2_BASE) +#define OTFDEC1_REGION3 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION3_BASE) +#define OTFDEC1_REGION4 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION4_BASE) + +#define OTFDEC2 ((OTFDEC_TypeDef *) OTFDEC2_BASE) +#define OTFDEC2_REGION1 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION1_BASE) +#define OTFDEC2_REGION2 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION2_BASE) +#define OTFDEC2_REGION3 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION3_BASE) +#define OTFDEC2_REGION4 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION4_BASE) + +#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE) +#define DLYB_SDMMC1 ((DLYB_TypeDef *) DLYB_SDMMC1_BASE) + +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) + +#define HSEM ((HSEM_TypeDef *) HSEM_BASE) +#define HSEM_COMMON ((HSEM_Common_TypeDef *) (HSEM_BASE + 0x100UL)) + +#define LTDC ((LTDC_TypeDef *)LTDC_BASE) +#define LTDC_Layer1 ((LTDC_Layer_TypeDef *)LTDC_Layer1_BASE) +#define LTDC_Layer2 ((LTDC_Layer_TypeDef *)LTDC_Layer2_BASE) + +#define MDIOS ((MDIOS_TypeDef *) MDIOS_BASE) + +#define ETH ((ETH_TypeDef *)ETH_BASE) +#define MDMA ((MDMA_TypeDef *)MDMA_BASE) +#define MDMA_Channel0 ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE) +#define MDMA_Channel1 ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE) +#define MDMA_Channel2 ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE) +#define MDMA_Channel3 ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE) +#define MDMA_Channel4 ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE) +#define MDMA_Channel5 ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE) +#define MDMA_Channel6 ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE) +#define MDMA_Channel7 ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE) +#define MDMA_Channel8 ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE) +#define MDMA_Channel9 ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE) +#define MDMA_Channel10 ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE) +#define MDMA_Channel11 ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE) +#define MDMA_Channel12 ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE) +#define MDMA_Channel13 ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE) +#define MDMA_Channel14 ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE) +#define MDMA_Channel15 ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE) + + +#define USB1_OTG_HS ((USB_OTG_GlobalTypeDef *) USB1_OTG_HS_PERIPH_BASE) + +/* Legacy defines */ +#define USB_OTG_HS USB1_OTG_HS +#define USB_OTG_HS_PERIPH_BASE USB1_OTG_HS_PERIPH_BASE + +#define GPV ((GPV_TypeDef *) GPV_BASE) + +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + + /** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ +/******************************* ADC VERSION ********************************/ +#define ADC_VER_V5_V90 +/******************** Bit definition for ADC_ISR register ********************/ +#define ADC_ISR_ADRDY_Pos (0U) +#define ADC_ISR_ADRDY_Msk (0x1UL << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */ +#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC Ready (ADRDY) flag */ +#define ADC_ISR_EOSMP_Pos (1U) +#define ADC_ISR_EOSMP_Msk (0x1UL << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */ +#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC End of Sampling flag */ +#define ADC_ISR_EOC_Pos (2U) +#define ADC_ISR_EOC_Msk (0x1UL << ADC_ISR_EOC_Pos) /*!< 0x00000004 */ +#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC End of Regular Conversion flag */ +#define ADC_ISR_EOS_Pos (3U) +#define ADC_ISR_EOS_Msk (0x1UL << ADC_ISR_EOS_Pos) /*!< 0x00000008 */ +#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC End of Regular sequence of Conversions flag */ +#define ADC_ISR_OVR_Pos (4U) +#define ADC_ISR_OVR_Msk (0x1UL << ADC_ISR_OVR_Pos) /*!< 0x00000010 */ +#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC overrun flag */ +#define ADC_ISR_JEOC_Pos (5U) +#define ADC_ISR_JEOC_Msk (0x1UL << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */ +#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC End of Injected Conversion flag */ +#define ADC_ISR_JEOS_Pos (6U) +#define ADC_ISR_JEOS_Msk (0x1UL << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */ +#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC End of Injected sequence of Conversions flag */ +#define ADC_ISR_AWD1_Pos (7U) +#define ADC_ISR_AWD1_Msk (0x1UL << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */ +#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC Analog watchdog 1 flag */ +#define ADC_ISR_AWD2_Pos (8U) +#define ADC_ISR_AWD2_Msk (0x1UL << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */ +#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC Analog watchdog 2 flag */ +#define ADC_ISR_AWD3_Pos (9U) +#define ADC_ISR_AWD3_Msk (0x1UL << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */ +#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC Analog watchdog 3 flag */ +#define ADC_ISR_JQOVF_Pos (10U) +#define ADC_ISR_JQOVF_Msk (0x1UL << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */ +#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC Injected Context Queue Overflow flag */ +#define ADC_ISR_LDORDY_Pos (12U) +#define ADC_ISR_LDORDY_Msk (0x1UL << ADC_ISR_LDORDY_Pos) /*!< 0x00001000 */ +#define ADC_ISR_LDORDY ADC_ISR_LDORDY_Msk /*!< ADC LDO Ready (LDORDY) flag */ + +/******************** Bit definition for ADC_IER register ********************/ +#define ADC_IER_ADRDYIE_Pos (0U) +#define ADC_IER_ADRDYIE_Msk (0x1UL << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */ +#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC Ready (ADRDY) interrupt source */ +#define ADC_IER_EOSMPIE_Pos (1U) +#define ADC_IER_EOSMPIE_Msk (0x1UL << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */ +#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC End of Sampling interrupt source */ +#define ADC_IER_EOCIE_Pos (2U) +#define ADC_IER_EOCIE_Msk (0x1UL << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */ +#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC End of Regular Conversion interrupt source */ +#define ADC_IER_EOSIE_Pos (3U) +#define ADC_IER_EOSIE_Msk (0x1UL << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */ +#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC End of Regular sequence of Conversions interrupt source */ +#define ADC_IER_OVRIE_Pos (4U) +#define ADC_IER_OVRIE_Msk (0x1UL << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */ +#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC overrun interrupt source */ +#define ADC_IER_JEOCIE_Pos (5U) +#define ADC_IER_JEOCIE_Msk (0x1UL << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */ +#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC End of Injected Conversion interrupt source */ +#define ADC_IER_JEOSIE_Pos (6U) +#define ADC_IER_JEOSIE_Msk (0x1UL << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */ +#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC End of Injected sequence of Conversions interrupt source */ +#define ADC_IER_AWD1IE_Pos (7U) +#define ADC_IER_AWD1IE_Msk (0x1UL << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */ +#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC Analog watchdog 1 interrupt source */ +#define ADC_IER_AWD2IE_Pos (8U) +#define ADC_IER_AWD2IE_Msk (0x1UL << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */ +#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC Analog watchdog 2 interrupt source */ +#define ADC_IER_AWD3IE_Pos (9U) +#define ADC_IER_AWD3IE_Msk (0x1UL << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */ +#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC Analog watchdog 3 interrupt source */ +#define ADC_IER_JQOVFIE_Pos (10U) +#define ADC_IER_JQOVFIE_Msk (0x1UL << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */ +#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC Injected Context Queue Overflow interrupt source */ + +/******************** Bit definition for ADC_CR register ********************/ +#define ADC_CR_ADEN_Pos (0U) +#define ADC_CR_ADEN_Msk (0x1UL << ADC_CR_ADEN_Pos) /*!< 0x00000001 */ +#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC Enable control */ +#define ADC_CR_ADDIS_Pos (1U) +#define ADC_CR_ADDIS_Msk (0x1UL << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */ +#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC Disable command */ +#define ADC_CR_ADSTART_Pos (2U) +#define ADC_CR_ADSTART_Msk (0x1UL << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */ +#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC Start of Regular conversion */ +#define ADC_CR_JADSTART_Pos (3U) +#define ADC_CR_JADSTART_Msk (0x1UL << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */ +#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC Start of injected conversion */ +#define ADC_CR_ADSTP_Pos (4U) +#define ADC_CR_ADSTP_Msk (0x1UL << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */ +#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC Stop of Regular conversion */ +#define ADC_CR_JADSTP_Pos (5U) +#define ADC_CR_JADSTP_Msk (0x1UL << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */ +#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC Stop of injected conversion */ +#define ADC_CR_BOOST_Pos (8U) +#define ADC_CR_BOOST_Msk (0x3UL << ADC_CR_BOOST_Pos) /*!< 0x00000300 */ +#define ADC_CR_BOOST ADC_CR_BOOST_Msk /*!< ADC Boost Mode configuration */ +#define ADC_CR_BOOST_0 (0x1UL << ADC_CR_BOOST_Pos) /*!< 0x00000100 */ +#define ADC_CR_BOOST_1 (0x2UL << ADC_CR_BOOST_Pos) /*!< 0x00000200 */ +#define ADC_CR_ADCALLIN_Pos (16U) +#define ADC_CR_ADCALLIN_Msk (0x1UL << ADC_CR_ADCALLIN_Pos) /*!< 0x00010000 */ +#define ADC_CR_ADCALLIN ADC_CR_ADCALLIN_Msk /*!< ADC Linearity calibration */ +#define ADC_CR_LINCALRDYW1_Pos (22U) +#define ADC_CR_LINCALRDYW1_Msk (0x1UL << ADC_CR_LINCALRDYW1_Pos) /*!< 0x00400000 */ +#define ADC_CR_LINCALRDYW1 ADC_CR_LINCALRDYW1_Msk /*!< ADC Linearity calibration ready Word 1 */ +#define ADC_CR_LINCALRDYW2_Pos (23U) +#define ADC_CR_LINCALRDYW2_Msk (0x1UL << ADC_CR_LINCALRDYW2_Pos) /*!< 0x00800000 */ +#define ADC_CR_LINCALRDYW2 ADC_CR_LINCALRDYW2_Msk /*!< ADC Linearity calibration ready Word 2 */ +#define ADC_CR_LINCALRDYW3_Pos (24U) +#define ADC_CR_LINCALRDYW3_Msk (0x1UL << ADC_CR_LINCALRDYW3_Pos) /*!< 0x01000000 */ +#define ADC_CR_LINCALRDYW3 ADC_CR_LINCALRDYW3_Msk /*!< ADC Linearity calibration ready Word 3 */ +#define ADC_CR_LINCALRDYW4_Pos (25U) +#define ADC_CR_LINCALRDYW4_Msk (0x1UL << ADC_CR_LINCALRDYW4_Pos) /*!< 0x02000000 */ +#define ADC_CR_LINCALRDYW4 ADC_CR_LINCALRDYW4_Msk /*!< ADC Linearity calibration ready Word 4 */ +#define ADC_CR_LINCALRDYW5_Pos (26U) +#define ADC_CR_LINCALRDYW5_Msk (0x1UL << ADC_CR_LINCALRDYW5_Pos) /*!< 0x04000000 */ +#define ADC_CR_LINCALRDYW5 ADC_CR_LINCALRDYW5_Msk /*!< ADC Linearity calibration ready Word 5 */ +#define ADC_CR_LINCALRDYW6_Pos (27U) +#define ADC_CR_LINCALRDYW6_Msk (0x1UL << ADC_CR_LINCALRDYW6_Pos) /*!< 0x08000000 */ +#define ADC_CR_LINCALRDYW6 ADC_CR_LINCALRDYW6_Msk /*!< ADC Linearity calibration ready Word 6 */ +#define ADC_CR_ADVREGEN_Pos (28U) +#define ADC_CR_ADVREGEN_Msk (0x1UL << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */ +#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC Voltage regulator Enable */ +#define ADC_CR_DEEPPWD_Pos (29U) +#define ADC_CR_DEEPPWD_Msk (0x1UL << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */ +#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC Deep power down Enable */ +#define ADC_CR_ADCALDIF_Pos (30U) +#define ADC_CR_ADCALDIF_Msk (0x1UL << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */ +#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC Differential Mode for calibration */ +#define ADC_CR_ADCAL_Pos (31U) +#define ADC_CR_ADCAL_Msk (0x1UL << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */ +#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC Calibration */ + +/******************** Bit definition for ADC_CFGR register ********************/ +#define ADC_CFGR_DMNGT_Pos (0U) +#define ADC_CFGR_DMNGT_Msk (0x3UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000003 */ +#define ADC_CFGR_DMNGT ADC_CFGR_DMNGT_Msk /*!< ADC Data Management configuration */ +#define ADC_CFGR_DMNGT_0 (0x1UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000001 */ +#define ADC_CFGR_DMNGT_1 (0x2UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000002 */ + +#define ADC_CFGR_RES_Pos (2U) +#define ADC_CFGR_RES_Msk (0x7UL << ADC_CFGR_RES_Pos) /*!< 0x0000001C */ +#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC Data resolution */ +#define ADC_CFGR_RES_0 (0x1UL << ADC_CFGR_RES_Pos) /*!< 0x00000004 */ +#define ADC_CFGR_RES_1 (0x2UL << ADC_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC_CFGR_RES_2 (0x4UL << ADC_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR_EXTSEL_Pos (5U) +#define ADC_CFGR_EXTSEL_Msk (0x1FUL << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003E0 */ +#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC External trigger selection for regular group */ +#define ADC_CFGR_EXTSEL_0 (0x01UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000020 */ +#define ADC_CFGR_EXTSEL_1 (0x02UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */ +#define ADC_CFGR_EXTSEL_2 (0x04UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */ +#define ADC_CFGR_EXTSEL_3 (0x08UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */ +#define ADC_CFGR_EXTSEL_4 (0x10UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */ + +#define ADC_CFGR_EXTEN_Pos (10U) +#define ADC_CFGR_EXTEN_Msk (0x3UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */ +#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC External trigger enable and polarity selection for regular channels */ +#define ADC_CFGR_EXTEN_0 (0x1UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */ +#define ADC_CFGR_EXTEN_1 (0x2UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */ + +#define ADC_CFGR_OVRMOD_Pos (12U) +#define ADC_CFGR_OVRMOD_Msk (0x1UL << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */ +#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC overrun mode */ +#define ADC_CFGR_CONT_Pos (13U) +#define ADC_CFGR_CONT_Msk (0x1UL << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */ +#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC Single/continuous conversion mode for regular conversion */ +#define ADC_CFGR_AUTDLY_Pos (14U) +#define ADC_CFGR_AUTDLY_Msk (0x1UL << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */ +#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC Delayed conversion mode */ + +#define ADC_CFGR_DISCEN_Pos (16U) +#define ADC_CFGR_DISCEN_Msk (0x1UL << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */ +#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC Discontinuous mode for regular channels */ + +#define ADC_CFGR_DISCNUM_Pos (17U) +#define ADC_CFGR_DISCNUM_Msk (0x7UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */ +#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC Discontinuous mode channel count */ +#define ADC_CFGR_DISCNUM_0 (0x1UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */ +#define ADC_CFGR_DISCNUM_1 (0x2UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */ +#define ADC_CFGR_DISCNUM_2 (0x4UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */ + +#define ADC_CFGR_JDISCEN_Pos (20U) +#define ADC_CFGR_JDISCEN_Msk (0x1UL << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */ +#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC Discontinuous mode on injected channels */ +#define ADC_CFGR_JQM_Pos (21U) +#define ADC_CFGR_JQM_Msk (0x1UL << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */ +#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC JSQR Queue mode */ +#define ADC_CFGR_AWD1SGL_Pos (22U) +#define ADC_CFGR_AWD1SGL_Msk (0x1UL << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */ +#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< Enable the watchdog 1 on a single channel or on all channels */ +#define ADC_CFGR_AWD1EN_Pos (23U) +#define ADC_CFGR_AWD1EN_Msk (0x1UL << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */ +#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC Analog watchdog 1 enable on regular Channels */ +#define ADC_CFGR_JAWD1EN_Pos (24U) +#define ADC_CFGR_JAWD1EN_Msk (0x1UL << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */ +#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC Analog watchdog 1 enable on injected Channels */ +#define ADC_CFGR_JAUTO_Pos (25U) +#define ADC_CFGR_JAUTO_Msk (0x1UL << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */ +#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC Automatic injected group conversion */ + +#define ADC_CFGR_AWD1CH_Pos (26U) +#define ADC_CFGR_AWD1CH_Msk (0x1FUL << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */ +#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC Analog watchdog 1 Channel selection */ +#define ADC_CFGR_AWD1CH_0 (0x01UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */ +#define ADC_CFGR_AWD1CH_1 (0x02UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */ +#define ADC_CFGR_AWD1CH_2 (0x04UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */ +#define ADC_CFGR_AWD1CH_3 (0x08UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */ +#define ADC_CFGR_AWD1CH_4 (0x10UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */ + +#define ADC_CFGR_JQDIS_Pos (31U) +#define ADC_CFGR_JQDIS_Msk (0x1UL << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */ +#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC Injected queue disable */ + +#define ADC3_CFGR_DMAEN_Pos (0U) +#define ADC3_CFGR_DMAEN_Msk (0x1UL << ADC3_CFGR_DMAEN_Pos) /*!< 0x00000001 */ +#define ADC3_CFGR_DMAEN ADC3_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */ +#define ADC3_CFGR_DMACFG_Pos (1U) +#define ADC3_CFGR_DMACFG_Msk (0x1UL << ADC3_CFGR_DMACFG_Pos) /*!< 0x00000002 */ +#define ADC3_CFGR_DMACFG ADC3_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */ + +#define ADC3_CFGR_RES_Pos (3U) +#define ADC3_CFGR_RES_Msk (0x3UL << ADC3_CFGR_RES_Pos) /*!< 0x00000018 */ +#define ADC3_CFGR_RES ADC3_CFGR_RES_Msk /*!< ADC data resolution */ +#define ADC3_CFGR_RES_0 (0x1UL << ADC3_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC3_CFGR_RES_1 (0x2UL << ADC3_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC3_CFGR_ALIGN_Pos (15U) +#define ADC3_CFGR_ALIGN_Msk (0x1UL << ADC3_CFGR_ALIGN_Pos) /*!< 0x00008000 */ +#define ADC3_CFGR_ALIGN ADC3_CFGR_ALIGN_Msk /*!< ADC data alignment */ +/******************** Bit definition for ADC_CFGR2 register ********************/ +#define ADC_CFGR2_ROVSE_Pos (0U) +#define ADC_CFGR2_ROVSE_Msk (0x1UL << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */ +#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC Regular group oversampler enable */ +#define ADC_CFGR2_JOVSE_Pos (1U) +#define ADC_CFGR2_JOVSE_Msk (0x1UL << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */ +#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC Injected group oversampler enable */ + +#define ADC_CFGR2_OVSS_Pos (5U) +#define ADC_CFGR2_OVSS_Msk (0xFUL << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */ +#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC Regular Oversampling shift */ +#define ADC_CFGR2_OVSS_0 (0x1UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */ +#define ADC_CFGR2_OVSS_1 (0x2UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */ +#define ADC_CFGR2_OVSS_2 (0x4UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */ +#define ADC_CFGR2_OVSS_3 (0x8UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */ + +#define ADC_CFGR2_TROVS_Pos (9U) +#define ADC_CFGR2_TROVS_Msk (0x1UL << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */ +#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC Triggered regular Oversampling */ +#define ADC_CFGR2_ROVSM_Pos (10U) +#define ADC_CFGR2_ROVSM_Msk (0x1UL << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */ +#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC Regular oversampling mode */ + +#define ADC_CFGR2_RSHIFT1_Pos (11U) +#define ADC_CFGR2_RSHIFT1_Msk (0x1UL << ADC_CFGR2_RSHIFT1_Pos) /*!< 0x00000800 */ +#define ADC_CFGR2_RSHIFT1 ADC_CFGR2_RSHIFT1_Msk /*!< ADC Right-shift data after Offset 1 correction */ +#define ADC_CFGR2_RSHIFT2_Pos (12U) +#define ADC_CFGR2_RSHIFT2_Msk (0x1UL << ADC_CFGR2_RSHIFT2_Pos) /*!< 0x00001000 */ +#define ADC_CFGR2_RSHIFT2 ADC_CFGR2_RSHIFT2_Msk /*!< ADC Right-shift data after Offset 2 correction */ +#define ADC_CFGR2_RSHIFT3_Pos (13U) +#define ADC_CFGR2_RSHIFT3_Msk (0x1UL << ADC_CFGR2_RSHIFT3_Pos) /*!< 0x00002000 */ +#define ADC_CFGR2_RSHIFT3 ADC_CFGR2_RSHIFT3_Msk /*!< ADC Right-shift data after Offset 3 correction */ +#define ADC_CFGR2_RSHIFT4_Pos (14U) +#define ADC_CFGR2_RSHIFT4_Msk (0x1UL << ADC_CFGR2_RSHIFT4_Pos) /*!< 0x00004000 */ +#define ADC_CFGR2_RSHIFT4 ADC_CFGR2_RSHIFT4_Msk /*!< ADC Right-shift data after Offset 4 correction */ + +#define ADC_CFGR2_OVSR_Pos (16U) +#define ADC_CFGR2_OVSR_Msk (0x3FFUL << ADC_CFGR2_OVSR_Pos) /*!< 0x03FF0000 */ +#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling Ratio */ +#define ADC_CFGR2_OVSR_0 (0x001UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00010000 */ +#define ADC_CFGR2_OVSR_1 (0x002UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00020000 */ +#define ADC_CFGR2_OVSR_2 (0x004UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00040000 */ +#define ADC_CFGR2_OVSR_3 (0x008UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00080000 */ +#define ADC_CFGR2_OVSR_4 (0x010UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00100000 */ +#define ADC_CFGR2_OVSR_5 (0x020UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00200000 */ +#define ADC_CFGR2_OVSR_6 (0x040UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00400000 */ +#define ADC_CFGR2_OVSR_7 (0x080UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00800000 */ +#define ADC_CFGR2_OVSR_8 (0x100UL << ADC_CFGR2_OVSR_Pos) /*!< 0x01000000 */ +#define ADC_CFGR2_OVSR_9 (0x200UL << ADC_CFGR2_OVSR_Pos) /*!< 0x02000000 */ + +#define ADC_CFGR2_LSHIFT_Pos (28U) +#define ADC_CFGR2_LSHIFT_Msk (0xFUL << ADC_CFGR2_LSHIFT_Pos) /*!< 0xF0000000 */ +#define ADC_CFGR2_LSHIFT ADC_CFGR2_LSHIFT_Msk /*!< ADC Left shift factor */ +#define ADC_CFGR2_LSHIFT_0 (0x1UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x10000000 */ +#define ADC_CFGR2_LSHIFT_1 (0x2UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x20000000 */ +#define ADC_CFGR2_LSHIFT_2 (0x4UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x40000000 */ +#define ADC_CFGR2_LSHIFT_3 (0x8UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x80000000 */ + +#define ADC3_CFGR2_OVSR_Pos (2U) +#define ADC3_CFGR2_OVSR_Msk (0x7UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x0000001C */ +#define ADC3_CFGR2_OVSR ADC3_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */ +#define ADC3_CFGR2_OVSR_0 (0x1UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000004 */ +#define ADC3_CFGR2_OVSR_1 (0x2UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000008 */ +#define ADC3_CFGR2_OVSR_2 (0x4UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000010 */ + +#define ADC3_CFGR2_SWTRIG_Pos (25U) +#define ADC3_CFGR2_SWTRIG_Msk (0x1UL << ADC3_CFGR2_SWTRIG_Pos) /*!< 0x02000000 */ +#define ADC3_CFGR2_SWTRIG ADC3_CFGR2_SWTRIG_Msk /*!< ADC Software Trigger Bit for Sample time control trigger mode */ +#define ADC3_CFGR2_BULB_Pos (26U) +#define ADC3_CFGR2_BULB_Msk (0x1UL << ADC3_CFGR2_BULB_Pos) /*!< 0x04000000 */ +#define ADC3_CFGR2_BULB ADC3_CFGR2_BULB_Msk /*!< ADC Bulb sampling mode */ +#define ADC3_CFGR2_SMPTRIG_Pos (27U) +#define ADC3_CFGR2_SMPTRIG_Msk (0x1UL << ADC3_CFGR2_SMPTRIG_Pos) /*!< 0x08000000 */ +#define ADC3_CFGR2_SMPTRIG ADC3_CFGR2_SMPTRIG_Msk /*!< ADC Sample Time Control Trigger mode */ +/******************** Bit definition for ADC_SMPR1 register ********************/ +#define ADC_SMPR1_SMP0_Pos (0U) +#define ADC_SMPR1_SMP0_Msk (0x7UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */ +#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC Channel 0 Sampling time selection */ +#define ADC_SMPR1_SMP0_0 (0x1UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */ +#define ADC_SMPR1_SMP0_1 (0x2UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */ +#define ADC_SMPR1_SMP0_2 (0x4UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR1_SMP1_Pos (3U) +#define ADC_SMPR1_SMP1_Msk (0x7UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */ +#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC Channel 1 Sampling time selection */ +#define ADC_SMPR1_SMP1_0 (0x1UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */ +#define ADC_SMPR1_SMP1_1 (0x2UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */ +#define ADC_SMPR1_SMP1_2 (0x4UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR1_SMP2_Pos (6U) +#define ADC_SMPR1_SMP2_Msk (0x7UL << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC Channel 2 Sampling time selection */ +#define ADC_SMPR1_SMP2_0 (0x1UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */ +#define ADC_SMPR1_SMP2_1 (0x2UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */ +#define ADC_SMPR1_SMP2_2 (0x4UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR1_SMP3_Pos (9U) +#define ADC_SMPR1_SMP3_Msk (0x7UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC Channel 3 Sampling time selection */ +#define ADC_SMPR1_SMP3_0 (0x1UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */ +#define ADC_SMPR1_SMP3_1 (0x2UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */ +#define ADC_SMPR1_SMP3_2 (0x4UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR1_SMP4_Pos (12U) +#define ADC_SMPR1_SMP4_Msk (0x7UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */ +#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC Channel 4 Sampling time selection */ +#define ADC_SMPR1_SMP4_0 (0x1UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */ +#define ADC_SMPR1_SMP4_1 (0x2UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */ +#define ADC_SMPR1_SMP4_2 (0x4UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR1_SMP5_Pos (15U) +#define ADC_SMPR1_SMP5_Msk (0x7UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */ +#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC Channel 5 Sampling time selection */ +#define ADC_SMPR1_SMP5_0 (0x1UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */ +#define ADC_SMPR1_SMP5_1 (0x2UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */ +#define ADC_SMPR1_SMP5_2 (0x4UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR1_SMP6_Pos (18U) +#define ADC_SMPR1_SMP6_Msk (0x7UL << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC Channel 6 Sampling time selection */ +#define ADC_SMPR1_SMP6_0 (0x1UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */ +#define ADC_SMPR1_SMP6_1 (0x2UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */ +#define ADC_SMPR1_SMP6_2 (0x4UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR1_SMP7_Pos (21U) +#define ADC_SMPR1_SMP7_Msk (0x7UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC Channel 7 Sampling time selection */ +#define ADC_SMPR1_SMP7_0 (0x1UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */ +#define ADC_SMPR1_SMP7_1 (0x2UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */ +#define ADC_SMPR1_SMP7_2 (0x4UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR1_SMP8_Pos (24U) +#define ADC_SMPR1_SMP8_Msk (0x7UL << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */ +#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC Channel 8 Sampling time selection */ +#define ADC_SMPR1_SMP8_0 (0x1UL << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */ +#define ADC_SMPR1_SMP8_1 (0x2UL << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */ +#define ADC_SMPR1_SMP8_2 (0x4UL << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR1_SMP9_Pos (27U) +#define ADC_SMPR1_SMP9_Msk (0x7UL << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */ +#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC Channel 9 Sampling time selection */ +#define ADC_SMPR1_SMP9_0 (0x1UL << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */ +#define ADC_SMPR1_SMP9_1 (0x2UL << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */ +#define ADC_SMPR1_SMP9_2 (0x4UL << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_SMPR2 register ********************/ +#define ADC_SMPR2_SMP10_Pos (0U) +#define ADC_SMPR2_SMP10_Msk (0x7UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */ +#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC Channel 10 Sampling time selection */ +#define ADC_SMPR2_SMP10_0 (0x1UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */ +#define ADC_SMPR2_SMP10_1 (0x2UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */ +#define ADC_SMPR2_SMP10_2 (0x4UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR2_SMP11_Pos (3U) +#define ADC_SMPR2_SMP11_Msk (0x7UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */ +#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC Channel 11 Sampling time selection */ +#define ADC_SMPR2_SMP11_0 (0x1UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */ +#define ADC_SMPR2_SMP11_1 (0x2UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */ +#define ADC_SMPR2_SMP11_2 (0x4UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR2_SMP12_Pos (6U) +#define ADC_SMPR2_SMP12_Msk (0x7UL << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC Channel 12 Sampling time selection */ +#define ADC_SMPR2_SMP12_0 (0x1UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */ +#define ADC_SMPR2_SMP12_1 (0x2UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */ +#define ADC_SMPR2_SMP12_2 (0x4UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR2_SMP13_Pos (9U) +#define ADC_SMPR2_SMP13_Msk (0x7UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC Channel 13 Sampling time selection */ +#define ADC_SMPR2_SMP13_0 (0x1UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */ +#define ADC_SMPR2_SMP13_1 (0x2UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */ +#define ADC_SMPR2_SMP13_2 (0x4UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR2_SMP14_Pos (12U) +#define ADC_SMPR2_SMP14_Msk (0x7UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */ +#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC Channel 14 Sampling time selection */ +#define ADC_SMPR2_SMP14_0 (0x1UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */ +#define ADC_SMPR2_SMP14_1 (0x2UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */ +#define ADC_SMPR2_SMP14_2 (0x4UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR2_SMP15_Pos (15U) +#define ADC_SMPR2_SMP15_Msk (0x7UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */ +#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC Channel 15 Sampling time selection */ +#define ADC_SMPR2_SMP15_0 (0x1UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */ +#define ADC_SMPR2_SMP15_1 (0x2UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */ +#define ADC_SMPR2_SMP15_2 (0x4UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR2_SMP16_Pos (18U) +#define ADC_SMPR2_SMP16_Msk (0x7UL << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC Channel 16 Sampling time selection */ +#define ADC_SMPR2_SMP16_0 (0x1UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */ +#define ADC_SMPR2_SMP16_1 (0x2UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */ +#define ADC_SMPR2_SMP16_2 (0x4UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR2_SMP17_Pos (21U) +#define ADC_SMPR2_SMP17_Msk (0x7UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC Channel 17 Sampling time selection */ +#define ADC_SMPR2_SMP17_0 (0x1UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */ +#define ADC_SMPR2_SMP17_1 (0x2UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */ +#define ADC_SMPR2_SMP17_2 (0x4UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR2_SMP18_Pos (24U) +#define ADC_SMPR2_SMP18_Msk (0x7UL << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */ +#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC Channel 18 Sampling time selection */ +#define ADC_SMPR2_SMP18_0 (0x1UL << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */ +#define ADC_SMPR2_SMP18_1 (0x2UL << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */ +#define ADC_SMPR2_SMP18_2 (0x4UL << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR2_SMP19_Pos (27U) +#define ADC_SMPR2_SMP19_Msk (0x7UL << ADC_SMPR2_SMP19_Pos) /*!< 0x38000000 */ +#define ADC_SMPR2_SMP19 ADC_SMPR2_SMP19_Msk /*!< ADC Channel 19 Sampling time selection */ +#define ADC_SMPR2_SMP19_0 (0x1UL << ADC_SMPR2_SMP19_Pos) /*!< 0x08000000 */ +#define ADC_SMPR2_SMP19_1 (0x2UL << ADC_SMPR2_SMP19_Pos) /*!< 0x10000000 */ +#define ADC_SMPR2_SMP19_2 (0x4UL << ADC_SMPR2_SMP19_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_PCSEL register ********************/ +#define ADC_PCSEL_PCSEL_Pos (0U) +#define ADC_PCSEL_PCSEL_Msk (0xFFFFFUL << ADC_PCSEL_PCSEL_Pos) /*!< 0x000FFFFF */ +#define ADC_PCSEL_PCSEL ADC_PCSEL_PCSEL_Msk /*!< ADC pre channel selection */ +#define ADC_PCSEL_PCSEL_0 (0x00001UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000001 */ +#define ADC_PCSEL_PCSEL_1 (0x00002UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000002 */ +#define ADC_PCSEL_PCSEL_2 (0x00004UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000004 */ +#define ADC_PCSEL_PCSEL_3 (0x00008UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000008 */ +#define ADC_PCSEL_PCSEL_4 (0x00010UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000010 */ +#define ADC_PCSEL_PCSEL_5 (0x00020UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000020 */ +#define ADC_PCSEL_PCSEL_6 (0x00040UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000040 */ +#define ADC_PCSEL_PCSEL_7 (0x00080UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000080 */ +#define ADC_PCSEL_PCSEL_8 (0x00100UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000100 */ +#define ADC_PCSEL_PCSEL_9 (0x00200UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000200 */ +#define ADC_PCSEL_PCSEL_10 (0x00400UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000400 */ +#define ADC_PCSEL_PCSEL_11 (0x00800UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000800 */ +#define ADC_PCSEL_PCSEL_12 (0x01000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00001000 */ +#define ADC_PCSEL_PCSEL_13 (0x02000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00002000 */ +#define ADC_PCSEL_PCSEL_14 (0x04000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00004000 */ +#define ADC_PCSEL_PCSEL_15 (0x08000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00008000 */ +#define ADC_PCSEL_PCSEL_16 (0x10000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00010000 */ +#define ADC_PCSEL_PCSEL_17 (0x20000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00020000 */ +#define ADC_PCSEL_PCSEL_18 (0x40000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00040000 */ +#define ADC_PCSEL_PCSEL_19 (0x80000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00080000 */ + +/***************** Bit definition for ADC_LTR1, 2, 3 registers *****************/ +#define ADC_LTR_LT_Pos (0U) +#define ADC_LTR_LT_Msk (0x3FFFFFFUL << ADC_LTR_LT_Pos) /*!< 0x03FFFFFF */ +#define ADC_LTR_LT ADC_LTR_LT_Msk /*!< ADC Analog watchdog 1, 2 and 3 lower threshold */ + +/***************** Bit definition for ADC_HTR1, 2, 3 registers ****************/ +#define ADC_HTR_HT_Pos (0U) +#define ADC_HTR_HT_Msk (0x3FFFFFFUL << ADC_HTR_HT_Pos) /*!< 0x03FFFFFF */ +#define ADC_HTR_HT ADC_HTR_HT_Msk /*!< ADC Analog watchdog 1,2 and 3 higher threshold */ + +/******************** Bit definition for ADC3_TR1 register *******************/ +#define ADC3_TR1_LT1_Pos (0U) +#define ADC3_TR1_LT1_Msk (0xFFFUL << ADC3_TR1_LT1_Pos) /*!< 0x00000FFF */ +#define ADC3_TR1_LT1 ADC3_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */ + +#define ADC3_TR1_AWDFILT_Pos (12U) +#define ADC3_TR1_AWDFILT_Msk (0x7UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00007000 */ +#define ADC3_TR1_AWDFILT ADC3_TR1_AWDFILT_Msk /*!< ADC analog watchdog filtering parameter */ +#define ADC3_TR1_AWDFILT_0 (0x1UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00001000 */ +#define ADC3_TR1_AWDFILT_1 (0x2UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00002000 */ +#define ADC3_TR1_AWDFILT_2 (0x4UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00004000 */ + +#define ADC3_TR1_HT1_Pos (16U) +#define ADC3_TR1_HT1_Msk (0xFFFUL << ADC3_TR1_HT1_Pos) /*!< 0x0FFF0000 */ +#define ADC3_TR1_HT1 ADC3_TR1_HT1_Msk /*!< ADC analog watchdog 1 threshold high */ + +/******************** Bit definition for ADC3_TR2 register *******************/ +#define ADC3_TR2_LT2_Pos (0U) +#define ADC3_TR2_LT2_Msk (0xFFUL << ADC3_TR2_LT2_Pos) /*!< 0x000000FF */ +#define ADC3_TR2_LT2 ADC3_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */ + +#define ADC3_TR2_HT2_Pos (16U) +#define ADC3_TR2_HT2_Msk (0xFFUL << ADC3_TR2_HT2_Pos) /*!< 0x00FF0000 */ +#define ADC3_TR2_HT2 ADC3_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */ + +/******************** Bit definition for ADC3_TR3 register *******************/ +#define ADC3_TR3_LT3_Pos (0U) +#define ADC3_TR3_LT3_Msk (0xFFUL << ADC3_TR3_LT3_Pos) /*!< 0x000000FF */ +#define ADC3_TR3_LT3 ADC3_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */ + +#define ADC3_TR3_HT3_Pos (16U) +#define ADC3_TR3_HT3_Msk (0xFFUL << ADC3_TR3_HT3_Pos) /*!< 0x00FF0000 */ +#define ADC3_TR3_HT3 ADC3_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */ + +/******************** Bit definition for ADC_SQR1 register ********************/ +#define ADC_SQR1_L_Pos (0U) +#define ADC_SQR1_L_Msk (0xFUL << ADC_SQR1_L_Pos) /*!< 0x0000000F */ +#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC regular channel sequence length */ +#define ADC_SQR1_L_0 (0x1UL << ADC_SQR1_L_Pos) /*!< 0x00000001 */ +#define ADC_SQR1_L_1 (0x2UL << ADC_SQR1_L_Pos) /*!< 0x00000002 */ +#define ADC_SQR1_L_2 (0x4UL << ADC_SQR1_L_Pos) /*!< 0x00000004 */ +#define ADC_SQR1_L_3 (0x8UL << ADC_SQR1_L_Pos) /*!< 0x00000008 */ + +#define ADC_SQR1_SQ1_Pos (6U) +#define ADC_SQR1_SQ1_Msk (0x1FUL << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */ +#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC 1st conversion in regular sequence */ +#define ADC_SQR1_SQ1_0 (0x01UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */ +#define ADC_SQR1_SQ1_1 (0x02UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */ +#define ADC_SQR1_SQ1_2 (0x04UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */ +#define ADC_SQR1_SQ1_3 (0x08UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */ +#define ADC_SQR1_SQ1_4 (0x10UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */ + +#define ADC_SQR1_SQ2_Pos (12U) +#define ADC_SQR1_SQ2_Msk (0x1FUL << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */ +#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC 2nd conversion in regular sequence */ +#define ADC_SQR1_SQ2_0 (0x01UL << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */ +#define ADC_SQR1_SQ2_1 (0x02UL << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */ +#define ADC_SQR1_SQ2_2 (0x04UL << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */ +#define ADC_SQR1_SQ2_3 (0x08UL << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */ +#define ADC_SQR1_SQ2_4 (0x10UL << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */ + +#define ADC_SQR1_SQ3_Pos (18U) +#define ADC_SQR1_SQ3_Msk (0x1FUL << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */ +#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC 3rd conversion in regular sequence */ +#define ADC_SQR1_SQ3_0 (0x01UL << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */ +#define ADC_SQR1_SQ3_1 (0x02UL << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */ +#define ADC_SQR1_SQ3_2 (0x04UL << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */ +#define ADC_SQR1_SQ3_3 (0x08UL << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */ +#define ADC_SQR1_SQ3_4 (0x10UL << ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */ + +#define ADC_SQR1_SQ4_Pos (24U) +#define ADC_SQR1_SQ4_Msk (0x1FUL << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */ +#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC 4th conversion in regular sequence */ +#define ADC_SQR1_SQ4_0 (0x01UL << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */ +#define ADC_SQR1_SQ4_1 (0x02UL << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */ +#define ADC_SQR1_SQ4_2 (0x04UL << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */ +#define ADC_SQR1_SQ4_3 (0x08UL << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */ +#define ADC_SQR1_SQ4_4 (0x10UL << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR2 register ********************/ +#define ADC_SQR2_SQ5_Pos (0U) +#define ADC_SQR2_SQ5_Msk (0x1FUL << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */ +#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC 5th conversion in regular sequence */ +#define ADC_SQR2_SQ5_0 (0x01UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */ +#define ADC_SQR2_SQ5_1 (0x02UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */ +#define ADC_SQR2_SQ5_2 (0x04UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */ +#define ADC_SQR2_SQ5_3 (0x08UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */ +#define ADC_SQR2_SQ5_4 (0x10UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */ + +#define ADC_SQR2_SQ6_Pos (6U) +#define ADC_SQR2_SQ6_Msk (0x1FUL << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */ +#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC 6th conversion in regular sequence */ +#define ADC_SQR2_SQ6_0 (0x01UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */ +#define ADC_SQR2_SQ6_1 (0x02UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */ +#define ADC_SQR2_SQ6_2 (0x04UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */ +#define ADC_SQR2_SQ6_3 (0x08UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */ +#define ADC_SQR2_SQ6_4 (0x10UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */ + +#define ADC_SQR2_SQ7_Pos (12U) +#define ADC_SQR2_SQ7_Msk (0x1FUL << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */ +#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC 7th conversion in regular sequence */ +#define ADC_SQR2_SQ7_0 (0x01UL << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */ +#define ADC_SQR2_SQ7_1 (0x02UL << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */ +#define ADC_SQR2_SQ7_2 (0x04UL << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */ +#define ADC_SQR2_SQ7_3 (0x08UL << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */ +#define ADC_SQR2_SQ7_4 (0x10UL << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */ + +#define ADC_SQR2_SQ8_Pos (18U) +#define ADC_SQR2_SQ8_Msk (0x1FUL << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */ +#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC 8th conversion in regular sequence */ +#define ADC_SQR2_SQ8_0 (0x01UL << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */ +#define ADC_SQR2_SQ8_1 (0x02UL << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */ +#define ADC_SQR2_SQ8_2 (0x04UL << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */ +#define ADC_SQR2_SQ8_3 (0x08UL << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */ +#define ADC_SQR2_SQ8_4 (0x10UL << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */ + +#define ADC_SQR2_SQ9_Pos (24U) +#define ADC_SQR2_SQ9_Msk (0x1FUL << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */ +#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC 9th conversion in regular sequence */ +#define ADC_SQR2_SQ9_0 (0x01UL << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */ +#define ADC_SQR2_SQ9_1 (0x02UL << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */ +#define ADC_SQR2_SQ9_2 (0x04UL << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */ +#define ADC_SQR2_SQ9_3 (0x08UL << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */ +#define ADC_SQR2_SQ9_4 (0x10UL << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR3 register ********************/ +#define ADC_SQR3_SQ10_Pos (0U) +#define ADC_SQR3_SQ10_Msk (0x1FUL << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */ +#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC 10th conversion in regular sequence */ +#define ADC_SQR3_SQ10_0 (0x01UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */ +#define ADC_SQR3_SQ10_1 (0x02UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */ +#define ADC_SQR3_SQ10_2 (0x04UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */ +#define ADC_SQR3_SQ10_3 (0x08UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */ +#define ADC_SQR3_SQ10_4 (0x10UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */ + +#define ADC_SQR3_SQ11_Pos (6U) +#define ADC_SQR3_SQ11_Msk (0x1FUL << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */ +#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC 11th conversion in regular sequence */ +#define ADC_SQR3_SQ11_0 (0x01UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */ +#define ADC_SQR3_SQ11_1 (0x02UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */ +#define ADC_SQR3_SQ11_2 (0x04UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */ +#define ADC_SQR3_SQ11_3 (0x08UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */ +#define ADC_SQR3_SQ11_4 (0x10UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */ + +#define ADC_SQR3_SQ12_Pos (12U) +#define ADC_SQR3_SQ12_Msk (0x1FUL << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */ +#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC 12th conversion in regular sequence */ +#define ADC_SQR3_SQ12_0 (0x01UL << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */ +#define ADC_SQR3_SQ12_1 (0x02UL << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */ +#define ADC_SQR3_SQ12_2 (0x04UL << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */ +#define ADC_SQR3_SQ12_3 (0x08UL << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */ +#define ADC_SQR3_SQ12_4 (0x10UL << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */ + +#define ADC_SQR3_SQ13_Pos (18U) +#define ADC_SQR3_SQ13_Msk (0x1FUL << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */ +#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC 13th conversion in regular sequence */ +#define ADC_SQR3_SQ13_0 (0x01UL << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */ +#define ADC_SQR3_SQ13_1 (0x02UL << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */ +#define ADC_SQR3_SQ13_2 (0x04UL << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */ +#define ADC_SQR3_SQ13_3 (0x08UL << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */ +#define ADC_SQR3_SQ13_4 (0x10UL << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */ + +#define ADC_SQR3_SQ14_Pos (24U) +#define ADC_SQR3_SQ14_Msk (0x1FUL << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */ +#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC 14th conversion in regular sequence */ +#define ADC_SQR3_SQ14_0 (0x01UL << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */ +#define ADC_SQR3_SQ14_1 (0x02UL << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */ +#define ADC_SQR3_SQ14_2 (0x04UL << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */ +#define ADC_SQR3_SQ14_3 (0x08UL << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */ +#define ADC_SQR3_SQ14_4 (0x10UL << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR4 register ********************/ +#define ADC_SQR4_SQ15_Pos (0U) +#define ADC_SQR4_SQ15_Msk (0x1FUL << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */ +#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC 15th conversion in regular sequence */ +#define ADC_SQR4_SQ15_0 (0x01UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */ +#define ADC_SQR4_SQ15_1 (0x02UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */ +#define ADC_SQR4_SQ15_2 (0x04UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */ +#define ADC_SQR4_SQ15_3 (0x08UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */ +#define ADC_SQR4_SQ15_4 (0x10UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */ + +#define ADC_SQR4_SQ16_Pos (6U) +#define ADC_SQR4_SQ16_Msk (0x1FUL << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */ +#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC 16th conversion in regular sequence */ +#define ADC_SQR4_SQ16_0 (0x01UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */ +#define ADC_SQR4_SQ16_1 (0x02UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */ +#define ADC_SQR4_SQ16_2 (0x04UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */ +#define ADC_SQR4_SQ16_3 (0x08UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */ +#define ADC_SQR4_SQ16_4 (0x10UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */ +/******************** Bit definition for ADC_DR register ********************/ +#define ADC_DR_RDATA_Pos (0U) +#define ADC_DR_RDATA_Msk (0xFFFFFFFFUL << ADC_DR_RDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC regular Data converted */ + +/******************** Bit definition for ADC_JSQR register ********************/ +#define ADC_JSQR_JL_Pos (0U) +#define ADC_JSQR_JL_Msk (0x3UL << ADC_JSQR_JL_Pos) /*!< 0x00000003 */ +#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC injected channel sequence length */ +#define ADC_JSQR_JL_0 (0x1UL << ADC_JSQR_JL_Pos) /*!< 0x00000001 */ +#define ADC_JSQR_JL_1 (0x2UL << ADC_JSQR_JL_Pos) /*!< 0x00000002 */ + +#define ADC_JSQR_JEXTSEL_Pos (2U) +#define ADC_JSQR_JEXTSEL_Msk (0x1FUL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000007C */ +#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC external trigger selection for injected group */ +#define ADC_JSQR_JEXTSEL_0 (0x01UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */ +#define ADC_JSQR_JEXTSEL_1 (0x02UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */ +#define ADC_JSQR_JEXTSEL_2 (0x04UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */ +#define ADC_JSQR_JEXTSEL_3 (0x08UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */ +#define ADC_JSQR_JEXTSEL_4 (0x10UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000040 */ + +#define ADC_JSQR_JEXTEN_Pos (7U) +#define ADC_JSQR_JEXTEN_Msk (0x3UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000180 */ +#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC external trigger enable and polarity selection for injected channels */ +#define ADC_JSQR_JEXTEN_0 (0x1UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */ +#define ADC_JSQR_JEXTEN_1 (0x2UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000100 */ + +#define ADC_JSQR_JSQ1_Pos (9U) +#define ADC_JSQR_JSQ1_Msk (0x1FUL << ADC_JSQR_JSQ1_Pos) /*!< 0x00003E00 */ +#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC 1st conversion in injected sequence */ +#define ADC_JSQR_JSQ1_0 (0x01UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */ +#define ADC_JSQR_JSQ1_1 (0x02UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */ +#define ADC_JSQR_JSQ1_2 (0x04UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */ +#define ADC_JSQR_JSQ1_3 (0x08UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */ +#define ADC_JSQR_JSQ1_4 (0x10UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00002000 */ + +#define ADC_JSQR_JSQ2_Pos (15U) +#define ADC_JSQR_JSQ2_Msk (0x1FUL << ADC_JSQR_JSQ2_Pos) /*!< 0x000F8000 */ +#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC 2nd conversion in injected sequence */ +#define ADC_JSQR_JSQ2_0 (0x01UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */ +#define ADC_JSQR_JSQ2_1 (0x02UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */ +#define ADC_JSQR_JSQ2_2 (0x04UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */ +#define ADC_JSQR_JSQ2_3 (0x08UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */ +#define ADC_JSQR_JSQ2_4 (0x10UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00080000 */ + +#define ADC_JSQR_JSQ3_Pos (21U) +#define ADC_JSQR_JSQ3_Msk (0x1FUL << ADC_JSQR_JSQ3_Pos) /*!< 0x03E00000 */ +#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC 3rd conversion in injected sequence */ +#define ADC_JSQR_JSQ3_0 (0x01UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */ +#define ADC_JSQR_JSQ3_1 (0x02UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */ +#define ADC_JSQR_JSQ3_2 (0x04UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */ +#define ADC_JSQR_JSQ3_3 (0x08UL << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */ +#define ADC_JSQR_JSQ3_4 (0x10UL << ADC_JSQR_JSQ3_Pos) /*!< 0x02000000 */ + +#define ADC_JSQR_JSQ4_Pos (27U) +#define ADC_JSQR_JSQ4_Msk (0x1FUL << ADC_JSQR_JSQ4_Pos) /*!< 0xF8000000 */ +#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC 4th conversion in injected sequence */ +#define ADC_JSQR_JSQ4_0 (0x01UL << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */ +#define ADC_JSQR_JSQ4_1 (0x02UL << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */ +#define ADC_JSQR_JSQ4_2 (0x04UL << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */ +#define ADC_JSQR_JSQ4_3 (0x08UL << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */ +#define ADC_JSQR_JSQ4_4 (0x10UL << ADC_JSQR_JSQ4_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_OFR1 register ********************/ +#define ADC_OFR1_OFFSET1_Pos (0U) +#define ADC_OFR1_OFFSET1_Msk (0x3FFFFFFUL << ADC_OFR1_OFFSET1_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */ +#define ADC_OFR1_OFFSET1_0 (0x0000001UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000001 */ +#define ADC_OFR1_OFFSET1_1 (0x0000002UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000002 */ +#define ADC_OFR1_OFFSET1_2 (0x0000004UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000004 */ +#define ADC_OFR1_OFFSET1_3 (0x0000008UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000008 */ +#define ADC_OFR1_OFFSET1_4 (0x0000010UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000010 */ +#define ADC_OFR1_OFFSET1_5 (0x0000020UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000020 */ +#define ADC_OFR1_OFFSET1_6 (0x0000040UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000040 */ +#define ADC_OFR1_OFFSET1_7 (0x0000080UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000080 */ +#define ADC_OFR1_OFFSET1_8 (0x0000100UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000100 */ +#define ADC_OFR1_OFFSET1_9 (0x0000200UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000200 */ +#define ADC_OFR1_OFFSET1_10 (0x0000400UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000400 */ +#define ADC_OFR1_OFFSET1_11 (0x0000800UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000800 */ +#define ADC_OFR1_OFFSET1_12 (0x0001000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00001000 */ +#define ADC_OFR1_OFFSET1_13 (0x0002000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00002000 */ +#define ADC_OFR1_OFFSET1_14 (0x0004000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00004000 */ +#define ADC_OFR1_OFFSET1_15 (0x0008000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00008000 */ +#define ADC_OFR1_OFFSET1_16 (0x0010000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00010000 */ +#define ADC_OFR1_OFFSET1_17 (0x0020000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00020000 */ +#define ADC_OFR1_OFFSET1_18 (0x0040000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00040000 */ +#define ADC_OFR1_OFFSET1_19 (0x0080000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00080000 */ +#define ADC_OFR1_OFFSET1_20 (0x0100000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00100000 */ +#define ADC_OFR1_OFFSET1_21 (0x0200000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00200000 */ +#define ADC_OFR1_OFFSET1_22 (0x0400000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00400000 */ +#define ADC_OFR1_OFFSET1_23 (0x0800000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00800000 */ +#define ADC_OFR1_OFFSET1_24 (0x1000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x01000000 */ +#define ADC_OFR1_OFFSET1_25 (0x2000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x02000000 */ + +#define ADC_OFR1_OFFSET1_CH_Pos (26U) +#define ADC_OFR1_OFFSET1_CH_Msk (0x1FUL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC Channel selection for the data offset 1 */ +#define ADC_OFR1_OFFSET1_CH_0 (0x01UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR1_OFFSET1_CH_1 (0x02UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR1_OFFSET1_CH_2 (0x04UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR1_OFFSET1_CH_3 (0x08UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR1_OFFSET1_CH_4 (0x10UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR1_SSATE_Pos (31U) +#define ADC_OFR1_SSATE_Msk (0x1UL << ADC_OFR1_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR1_SSATE ADC_OFR1_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR1_OFFSET1_Pos (0U) +#define ADC3_OFR1_OFFSET1_Msk (0xFFFUL << ADC3_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR1_OFFSET1 ADC3_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR1_OFFSETPOS_Pos (24U) +#define ADC3_OFR1_OFFSETPOS_Msk (0x1UL << ADC3_OFR1_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR1_OFFSETPOS ADC3_OFR1_OFFSETPOS_Msk /*!< ADC offset number 1 positive */ +#define ADC3_OFR1_SATEN_Pos (25U) +#define ADC3_OFR1_SATEN_Msk (0x1UL << ADC3_OFR1_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR1_SATEN ADC3_OFR1_SATEN_Msk /*!< ADC offset number 1 saturation enable */ + +#define ADC3_OFR1_OFFSET1_EN_Pos (31U) +#define ADC3_OFR1_OFFSET1_EN_Msk (0x1UL << ADC3_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR1_OFFSET1_EN ADC3_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */ + +/******************** Bit definition for ADC_OFR2 register ********************/ +#define ADC_OFR2_OFFSET2_Pos (0U) +#define ADC_OFR2_OFFSET2_Msk (0x3FFFFFFUL << ADC_OFR2_OFFSET2_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET2_CH[4:0] */ +#define ADC_OFR2_OFFSET2_0 (0x0000001UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000001 */ +#define ADC_OFR2_OFFSET2_1 (0x0000002UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000002 */ +#define ADC_OFR2_OFFSET2_2 (0x0000004UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000004 */ +#define ADC_OFR2_OFFSET2_3 (0x0000008UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000008 */ +#define ADC_OFR2_OFFSET2_4 (0x0000010UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000010 */ +#define ADC_OFR2_OFFSET2_5 (0x0000020UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000020 */ +#define ADC_OFR2_OFFSET2_6 (0x0000040UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000040 */ +#define ADC_OFR2_OFFSET2_7 (0x0000080UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000080 */ +#define ADC_OFR2_OFFSET2_8 (0x0000100UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000100 */ +#define ADC_OFR2_OFFSET2_9 (0x0000200UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000200 */ +#define ADC_OFR2_OFFSET2_10 (0x0000400UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000400 */ +#define ADC_OFR2_OFFSET2_11 (0x0000800UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000800 */ +#define ADC_OFR2_OFFSET2_12 (0x0001000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00001000 */ +#define ADC_OFR2_OFFSET2_13 (0x0002000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00002000 */ +#define ADC_OFR2_OFFSET2_14 (0x0004000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00004000 */ +#define ADC_OFR2_OFFSET2_15 (0x0008000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00008000 */ +#define ADC_OFR2_OFFSET2_16 (0x0010000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00010000 */ +#define ADC_OFR2_OFFSET2_17 (0x0020000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00020000 */ +#define ADC_OFR2_OFFSET2_18 (0x0040000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00040000 */ +#define ADC_OFR2_OFFSET2_19 (0x0080000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00080000 */ +#define ADC_OFR2_OFFSET2_20 (0x0100000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00100000 */ +#define ADC_OFR2_OFFSET2_21 (0x0200000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00200000 */ +#define ADC_OFR2_OFFSET2_22 (0x0400000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00400000 */ +#define ADC_OFR2_OFFSET2_23 (0x0800000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00800000 */ +#define ADC_OFR2_OFFSET2_24 (0x1000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x01000000 */ +#define ADC_OFR2_OFFSET2_25 (0x2000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x02000000 */ + +#define ADC_OFR2_OFFSET2_CH_Pos (26U) +#define ADC_OFR2_OFFSET2_CH_Msk (0x1FUL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC Channel selection for the data offset 2 */ +#define ADC_OFR2_OFFSET2_CH_0 (0x01UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR2_OFFSET2_CH_1 (0x02UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR2_OFFSET2_CH_2 (0x04UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR2_OFFSET2_CH_3 (0x08UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR2_OFFSET2_CH_4 (0x10UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR2_SSATE_Pos (31U) +#define ADC_OFR2_SSATE_Msk (0x1UL << ADC_OFR2_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR2_SSATE ADC_OFR2_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR2_OFFSET2_Pos (0U) +#define ADC3_OFR2_OFFSET2_Msk (0xFFFUL << ADC3_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR2_OFFSET2 ADC3_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR2_OFFSETPOS_Pos (24U) +#define ADC3_OFR2_OFFSETPOS_Msk (0x1UL << ADC3_OFR2_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR2_OFFSETPOS ADC3_OFR2_OFFSETPOS_Msk /*!< ADC offset number 2 positive */ +#define ADC3_OFR2_SATEN_Pos (25U) +#define ADC3_OFR2_SATEN_Msk (0x1UL << ADC3_OFR2_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR2_SATEN ADC3_OFR2_SATEN_Msk /*!< ADC offset number 2 saturation enable */ + +#define ADC3_OFR2_OFFSET2_EN_Pos (31U) +#define ADC3_OFR2_OFFSET2_EN_Msk (0x1UL << ADC3_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR2_OFFSET2_EN ADC3_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */ + +/******************** Bit definition for ADC_OFR3 register ********************/ +#define ADC_OFR3_OFFSET3_Pos (0U) +#define ADC_OFR3_OFFSET3_Msk (0x3FFFFFFUL << ADC_OFR3_OFFSET3_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET3_CH[4:0] */ +#define ADC_OFR3_OFFSET3_0 (0x0000001UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000001 */ +#define ADC_OFR3_OFFSET3_1 (0x0000002UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000002 */ +#define ADC_OFR3_OFFSET3_2 (0x0000004UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000004 */ +#define ADC_OFR3_OFFSET3_3 (0x0000008UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000008 */ +#define ADC_OFR3_OFFSET3_4 (0x0000010UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000010 */ +#define ADC_OFR3_OFFSET3_5 (0x0000020UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000020 */ +#define ADC_OFR3_OFFSET3_6 (0x0000040UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000040 */ +#define ADC_OFR3_OFFSET3_7 (0x0000080UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000080 */ +#define ADC_OFR3_OFFSET3_8 (0x0000100UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000100 */ +#define ADC_OFR3_OFFSET3_9 (0x0000200UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000200 */ +#define ADC_OFR3_OFFSET3_10 (0x0000400UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000400 */ +#define ADC_OFR3_OFFSET3_11 (0x0000800UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000800 */ +#define ADC_OFR3_OFFSET3_12 (0x0001000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00001000 */ +#define ADC_OFR3_OFFSET3_13 (0x0002000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00002000 */ +#define ADC_OFR3_OFFSET3_14 (0x0004000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00004000 */ +#define ADC_OFR3_OFFSET3_15 (0x0008000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00008000 */ +#define ADC_OFR3_OFFSET3_16 (0x0010000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00010000 */ +#define ADC_OFR3_OFFSET3_17 (0x0020000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00020000 */ +#define ADC_OFR3_OFFSET3_18 (0x0040000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00040000 */ +#define ADC_OFR3_OFFSET3_19 (0x0080000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00080000 */ +#define ADC_OFR3_OFFSET3_20 (0x0100000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00100000 */ +#define ADC_OFR3_OFFSET3_21 (0x0200000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00200000 */ +#define ADC_OFR3_OFFSET3_22 (0x0400000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00400000 */ +#define ADC_OFR3_OFFSET3_23 (0x0800000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00800000 */ +#define ADC_OFR3_OFFSET3_24 (0x1000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x01000000 */ +#define ADC_OFR3_OFFSET3_25 (0x2000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x02000000 */ + +#define ADC_OFR3_OFFSET3_CH_Pos (26U) +#define ADC_OFR3_OFFSET3_CH_Msk (0x1FUL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC Channel selection for the data offset 3 */ +#define ADC_OFR3_OFFSET3_CH_0 (0x01UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR3_OFFSET3_CH_1 (0x02UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR3_OFFSET3_CH_2 (0x04UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR3_OFFSET3_CH_3 (0x08UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR3_OFFSET3_CH_4 (0x10UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR3_SSATE_Pos (31U) +#define ADC_OFR3_SSATE_Msk (0x1UL << ADC_OFR3_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR3_SSATE ADC_OFR3_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR3_OFFSET3_Pos (0U) +#define ADC3_OFR3_OFFSET3_Msk (0xFFFUL << ADC3_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR3_OFFSET3 ADC3_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR3_OFFSETPOS_Pos (24U) +#define ADC3_OFR3_OFFSETPOS_Msk (0x1UL << ADC3_OFR3_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR3_OFFSETPOS ADC3_OFR3_OFFSETPOS_Msk /*!< ADC offset number 3 positive */ +#define ADC3_OFR3_SATEN_Pos (25U) +#define ADC3_OFR3_SATEN_Msk (0x1UL << ADC3_OFR3_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR3_SATEN ADC3_OFR3_SATEN_Msk /*!< ADC offset number 3 saturation enable */ + +#define ADC3_OFR3_OFFSET3_EN_Pos (31U) +#define ADC3_OFR3_OFFSET3_EN_Msk (0x1UL << ADC3_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR3_OFFSET3_EN ADC3_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */ + +/******************** Bit definition for ADC_OFR4 register ********************/ +#define ADC_OFR4_OFFSET4_Pos (0U) +#define ADC_OFR4_OFFSET4_Msk (0x3FFFFFFUL << ADC_OFR4_OFFSET4_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET4_CH[4:0] */ +#define ADC_OFR4_OFFSET4_0 (0x0000001UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000001 */ +#define ADC_OFR4_OFFSET4_1 (0x0000002UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000002 */ +#define ADC_OFR4_OFFSET4_2 (0x0000004UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000004 */ +#define ADC_OFR4_OFFSET4_3 (0x0000008UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000008 */ +#define ADC_OFR4_OFFSET4_4 (0x0000010UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000010 */ +#define ADC_OFR4_OFFSET4_5 (0x0000020UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000020 */ +#define ADC_OFR4_OFFSET4_6 (0x0000040UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000040 */ +#define ADC_OFR4_OFFSET4_7 (0x0000080UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000080 */ +#define ADC_OFR4_OFFSET4_8 (0x0000100UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000100 */ +#define ADC_OFR4_OFFSET4_9 (0x0000200UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000200 */ +#define ADC_OFR4_OFFSET4_10 (0x0000400UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000400 */ +#define ADC_OFR4_OFFSET4_11 (0x0000800UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000800 */ +#define ADC_OFR4_OFFSET4_12 (0x0001000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00001000 */ +#define ADC_OFR4_OFFSET4_13 (0x0002000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00002000 */ +#define ADC_OFR4_OFFSET4_14 (0x0004000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00004000 */ +#define ADC_OFR4_OFFSET4_15 (0x0008000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00008000 */ +#define ADC_OFR4_OFFSET4_16 (0x0010000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00010000 */ +#define ADC_OFR4_OFFSET4_17 (0x0020000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00020000 */ +#define ADC_OFR4_OFFSET4_18 (0x0040000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00040000 */ +#define ADC_OFR4_OFFSET4_19 (0x0080000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00080000 */ +#define ADC_OFR4_OFFSET4_20 (0x0100000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00100000 */ +#define ADC_OFR4_OFFSET4_21 (0x0200000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00200000 */ +#define ADC_OFR4_OFFSET4_22 (0x0400000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00400000 */ +#define ADC_OFR4_OFFSET4_23 (0x0800000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00800000 */ +#define ADC_OFR4_OFFSET4_24 (0x1000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x01000000 */ +#define ADC_OFR4_OFFSET4_25 (0x2000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x02000000 */ + +#define ADC_OFR4_OFFSET4_CH_Pos (26U) +#define ADC_OFR4_OFFSET4_CH_Msk (0x1FUL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC Channel selection for the data offset 4 */ +#define ADC_OFR4_OFFSET4_CH_0 (0x01UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR4_OFFSET4_CH_1 (0x02UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR4_OFFSET4_CH_2 (0x04UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR4_OFFSET4_CH_3 (0x08UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR4_OFFSET4_CH_4 (0x10UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR4_SSATE_Pos (31U) +#define ADC_OFR4_SSATE_Msk (0x1UL << ADC_OFR4_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR4_SSATE ADC_OFR4_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR4_OFFSET4_Pos (0U) +#define ADC3_OFR4_OFFSET4_Msk (0xFFFUL << ADC3_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR4_OFFSET4 ADC3_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR4_OFFSETPOS_Pos (24U) +#define ADC3_OFR4_OFFSETPOS_Msk (0x1UL << ADC3_OFR4_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR4_OFFSETPOS ADC3_OFR4_OFFSETPOS_Msk /*!< ADC offset number 4 positive */ +#define ADC3_OFR4_SATEN_Pos (25U) +#define ADC3_OFR4_SATEN_Msk (0x1UL << ADC3_OFR4_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR4_SATEN ADC3_OFR4_SATEN_Msk /*!< ADC offset number 4 saturation enable */ + +#define ADC3_OFR4_OFFSET4_EN_Pos (31U) +#define ADC3_OFR4_OFFSET4_EN_Msk (0x1UL << ADC3_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR4_OFFSET4_EN ADC3_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */ + +/******************** Bit definition for ADC_JDR1 register ********************/ +#define ADC_JDR1_JDATA_Pos (0U) +#define ADC_JDR1_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR1_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR1_JDATA_0 (0x00000001UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR1_JDATA_1 (0x00000002UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR1_JDATA_2 (0x00000004UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR1_JDATA_3 (0x00000008UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR1_JDATA_4 (0x00000010UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR1_JDATA_5 (0x00000020UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR1_JDATA_6 (0x00000040UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR1_JDATA_7 (0x00000080UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR1_JDATA_8 (0x00000100UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR1_JDATA_9 (0x00000200UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR1_JDATA_10 (0x00000400UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR1_JDATA_11 (0x00000800UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR1_JDATA_12 (0x00001000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR1_JDATA_13 (0x00002000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR1_JDATA_14 (0x00004000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR1_JDATA_15 (0x00008000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR1_JDATA_16 (0x00010000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR1_JDATA_17 (0x00020000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR1_JDATA_18 (0x00040000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR1_JDATA_19 (0x00080000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR1_JDATA_20 (0x00100000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR1_JDATA_21 (0x00200000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR1_JDATA_22 (0x00400000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR1_JDATA_23 (0x00800000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR1_JDATA_24 (0x01000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR1_JDATA_25 (0x02000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR1_JDATA_26 (0x04000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR1_JDATA_27 (0x08000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR1_JDATA_28 (0x10000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR1_JDATA_29 (0x20000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR1_JDATA_30 (0x40000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR1_JDATA_31 (0x80000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR2 register ********************/ +#define ADC_JDR2_JDATA_Pos (0U) +#define ADC_JDR2_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR2_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR2_JDATA_0 (0x00000001UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR2_JDATA_1 (0x00000002UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR2_JDATA_2 (0x00000004UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR2_JDATA_3 (0x00000008UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR2_JDATA_4 (0x00000010UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR2_JDATA_5 (0x00000020UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR2_JDATA_6 (0x00000040UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR2_JDATA_7 (0x00000080UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR2_JDATA_8 (0x00000100UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR2_JDATA_9 (0x00000200UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR2_JDATA_10 (0x00000400UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR2_JDATA_11 (0x00000800UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR2_JDATA_12 (0x00001000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR2_JDATA_13 (0x00002000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR2_JDATA_14 (0x00004000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR2_JDATA_15 (0x00008000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR2_JDATA_16 (0x00010000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR2_JDATA_17 (0x00020000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR2_JDATA_18 (0x00040000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR2_JDATA_19 (0x00080000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR2_JDATA_20 (0x00100000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR2_JDATA_21 (0x00200000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR2_JDATA_22 (0x00400000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR2_JDATA_23 (0x00800000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR2_JDATA_24 (0x01000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR2_JDATA_25 (0x02000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR2_JDATA_26 (0x04000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR2_JDATA_27 (0x08000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR2_JDATA_28 (0x10000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR2_JDATA_29 (0x20000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR2_JDATA_30 (0x40000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR2_JDATA_31 (0x80000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR3 register ********************/ +#define ADC_JDR3_JDATA_Pos (0U) +#define ADC_JDR3_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR3_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR3_JDATA_0 (0x00000001UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR3_JDATA_1 (0x00000002UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR3_JDATA_2 (0x00000004UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR3_JDATA_3 (0x00000008UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR3_JDATA_4 (0x00000010UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR3_JDATA_5 (0x00000020UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR3_JDATA_6 (0x00000040UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR3_JDATA_7 (0x00000080UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR3_JDATA_8 (0x00000100UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR3_JDATA_9 (0x00000200UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR3_JDATA_10 (0x00000400UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR3_JDATA_11 (0x00000800UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR3_JDATA_12 (0x00001000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR3_JDATA_13 (0x00002000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR3_JDATA_14 (0x00004000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR3_JDATA_15 (0x00008000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR3_JDATA_16 (0x00010000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR3_JDATA_17 (0x00020000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR3_JDATA_18 (0x00040000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR3_JDATA_19 (0x00080000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR3_JDATA_20 (0x00100000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR3_JDATA_21 (0x00200000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR3_JDATA_22 (0x00400000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR3_JDATA_23 (0x00800000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR3_JDATA_24 (0x01000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR3_JDATA_25 (0x02000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR3_JDATA_26 (0x04000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR3_JDATA_27 (0x08000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR3_JDATA_28 (0x10000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR3_JDATA_29 (0x20000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR3_JDATA_30 (0x40000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR3_JDATA_31 (0x80000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR4 register ********************/ +#define ADC_JDR4_JDATA_Pos (0U) +#define ADC_JDR4_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR4_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR4_JDATA_0 (0x00000001UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR4_JDATA_1 (0x00000002UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR4_JDATA_2 (0x00000004UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR4_JDATA_3 (0x00000008UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR4_JDATA_4 (0x00000010UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR4_JDATA_5 (0x00000020UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR4_JDATA_6 (0x00000040UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR4_JDATA_7 (0x00000080UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR4_JDATA_8 (0x00000100UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR4_JDATA_9 (0x00000200UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR4_JDATA_10 (0x00000400UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR4_JDATA_11 (0x00000800UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR4_JDATA_12 (0x00001000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR4_JDATA_13 (0x00002000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR4_JDATA_14 (0x00004000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR4_JDATA_15 (0x00008000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR4_JDATA_16 (0x00010000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR4_JDATA_17 (0x00020000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR4_JDATA_18 (0x00040000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR4_JDATA_19 (0x00080000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR4_JDATA_20 (0x00100000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR4_JDATA_21 (0x00200000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR4_JDATA_22 (0x00400000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR4_JDATA_23 (0x00800000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR4_JDATA_24 (0x01000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR4_JDATA_25 (0x02000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR4_JDATA_26 (0x04000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR4_JDATA_27 (0x08000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR4_JDATA_28 (0x10000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR4_JDATA_29 (0x20000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR4_JDATA_30 (0x40000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR4_JDATA_31 (0x80000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_AWD2CR register ********************/ +#define ADC_AWD2CR_AWD2CH_Pos (0U) +#define ADC_AWD2CR_AWD2CH_Msk (0xFFFFFUL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x000FFFFF */ +#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC Analog watchdog 2 channel selection */ +#define ADC_AWD2CR_AWD2CH_0 (0x00001UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD2CR_AWD2CH_1 (0x00002UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD2CR_AWD2CH_2 (0x00004UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD2CR_AWD2CH_3 (0x00008UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD2CR_AWD2CH_4 (0x00010UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD2CR_AWD2CH_5 (0x00020UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD2CR_AWD2CH_6 (0x00040UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD2CR_AWD2CH_7 (0x00080UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD2CR_AWD2CH_8 (0x00100UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD2CR_AWD2CH_9 (0x00200UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD2CR_AWD2CH_10 (0x00400UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD2CR_AWD2CH_11 (0x00800UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD2CR_AWD2CH_12 (0x01000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD2CR_AWD2CH_13 (0x02000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD2CR_AWD2CH_14 (0x04000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD2CR_AWD2CH_15 (0x08000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD2CR_AWD2CH_16 (0x10000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD2CR_AWD2CH_17 (0x20000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD2CR_AWD2CH_18 (0x40000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */ +#define ADC_AWD2CR_AWD2CH_19 (0x80000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_AWD3CR register ********************/ +#define ADC_AWD3CR_AWD3CH_Pos (0U) +#define ADC_AWD3CR_AWD3CH_Msk (0xFFFFFUL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x000FFFFF */ +#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC Analog watchdog 2 channel selection */ +#define ADC_AWD3CR_AWD3CH_0 (0x00001UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD3CR_AWD3CH_1 (0x00002UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD3CR_AWD3CH_2 (0x00004UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD3CR_AWD3CH_3 (0x00008UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD3CR_AWD3CH_4 (0x00010UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD3CR_AWD3CH_5 (0x00020UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD3CR_AWD3CH_6 (0x00040UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD3CR_AWD3CH_7 (0x00080UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD3CR_AWD3CH_8 (0x00100UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD3CR_AWD3CH_9 (0x00200UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD3CR_AWD3CH_10 (0x00400UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD3CR_AWD3CH_11 (0x00800UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD3CR_AWD3CH_12 (0x01000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD3CR_AWD3CH_13 (0x02000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD3CR_AWD3CH_14 (0x04000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD3CR_AWD3CH_15 (0x08000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD3CR_AWD3CH_16 (0x10000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD3CR_AWD3CH_17 (0x20000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD3CR_AWD3CH_18 (0x40000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */ +#define ADC_AWD3CR_AWD3CH_19 (0x80000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_DIFSEL register ********************/ +#define ADC_DIFSEL_DIFSEL_Pos (0U) +#define ADC_DIFSEL_DIFSEL_Msk (0xFFFFFUL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x000FFFFF */ +#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC differential modes for channels 1 to 18 */ +#define ADC_DIFSEL_DIFSEL_0 (0x00001UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */ +#define ADC_DIFSEL_DIFSEL_1 (0x00002UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */ +#define ADC_DIFSEL_DIFSEL_2 (0x00004UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */ +#define ADC_DIFSEL_DIFSEL_3 (0x00008UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */ +#define ADC_DIFSEL_DIFSEL_4 (0x00010UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */ +#define ADC_DIFSEL_DIFSEL_5 (0x00020UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */ +#define ADC_DIFSEL_DIFSEL_6 (0x00040UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */ +#define ADC_DIFSEL_DIFSEL_7 (0x00080UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */ +#define ADC_DIFSEL_DIFSEL_8 (0x00100UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */ +#define ADC_DIFSEL_DIFSEL_9 (0x00200UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */ +#define ADC_DIFSEL_DIFSEL_10 (0x00400UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */ +#define ADC_DIFSEL_DIFSEL_11 (0x00800UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */ +#define ADC_DIFSEL_DIFSEL_12 (0x01000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */ +#define ADC_DIFSEL_DIFSEL_13 (0x02000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */ +#define ADC_DIFSEL_DIFSEL_14 (0x04000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */ +#define ADC_DIFSEL_DIFSEL_15 (0x08000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */ +#define ADC_DIFSEL_DIFSEL_16 (0x10000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */ +#define ADC_DIFSEL_DIFSEL_17 (0x20000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */ +#define ADC_DIFSEL_DIFSEL_18 (0x40000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */ +#define ADC_DIFSEL_DIFSEL_19 (0x80000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_CALFACT register ********************/ +#define ADC_CALFACT_CALFACT_S_Pos (0U) +#define ADC_CALFACT_CALFACT_S_Msk (0x7FFUL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x000007FF */ +#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factors in single-ended mode */ +#define ADC_CALFACT_CALFACT_S_0 (0x001UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT_CALFACT_S_1 (0x002UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT_CALFACT_S_2 (0x004UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT_CALFACT_S_3 (0x008UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT_CALFACT_S_4 (0x010UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT_CALFACT_S_5 (0x020UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT_CALFACT_S_6 (0x040UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000040 */ +#define ADC_CALFACT_CALFACT_S_7 (0x080UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000080 */ +#define ADC_CALFACT_CALFACT_S_8 (0x100UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000100 */ +#define ADC_CALFACT_CALFACT_S_9 (0x200UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000200 */ +#define ADC_CALFACT_CALFACT_S_10 (0x400UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000400 */ +#define ADC_CALFACT_CALFACT_D_Pos (16U) +#define ADC_CALFACT_CALFACT_D_Msk (0x7FFUL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x07FF0000 */ +#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factors in differential mode */ +#define ADC_CALFACT_CALFACT_D_0 (0x001UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT_CALFACT_D_1 (0x002UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT_CALFACT_D_2 (0x004UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT_CALFACT_D_3 (0x008UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT_CALFACT_D_4 (0x010UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT_CALFACT_D_5 (0x020UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT_CALFACT_D_6 (0x040UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00400000 */ +#define ADC_CALFACT_CALFACT_D_7 (0x080UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00800000 */ +#define ADC_CALFACT_CALFACT_D_8 (0x100UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x01000000 */ +#define ADC_CALFACT_CALFACT_D_9 (0x200UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x02000000 */ +#define ADC_CALFACT_CALFACT_D_10 (0x400UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x04000000 */ + +/******************** Bit definition for ADC_CALFACT2 register ********************/ +#define ADC_CALFACT2_LINCALFACT_Pos (0U) +#define ADC_CALFACT2_LINCALFACT_Msk (0x3FFFFFFFUL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x3FFFFFFF */ +#define ADC_CALFACT2_LINCALFACT ADC_CALFACT2_LINCALFACT_Msk /*!< ADC Linearity calibration factors */ +#define ADC_CALFACT2_LINCALFACT_0 (0x00000001UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT2_LINCALFACT_1 (0x00000002UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT2_LINCALFACT_2 (0x00000004UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT2_LINCALFACT_3 (0x00000008UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT2_LINCALFACT_4 (0x00000010UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT2_LINCALFACT_5 (0x00000020UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT2_LINCALFACT_6 (0x00000040UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000040 */ +#define ADC_CALFACT2_LINCALFACT_7 (0x00000080UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000080 */ +#define ADC_CALFACT2_LINCALFACT_8 (0x00000100UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000100 */ +#define ADC_CALFACT2_LINCALFACT_9 (0x00000200UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000200 */ +#define ADC_CALFACT2_LINCALFACT_10 (0x00000400UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000400 */ +#define ADC_CALFACT2_LINCALFACT_11 (0x00000800UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000800 */ +#define ADC_CALFACT2_LINCALFACT_12 (0x00001000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00001000 */ +#define ADC_CALFACT2_LINCALFACT_13 (0x00002000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00002000 */ +#define ADC_CALFACT2_LINCALFACT_14 (0x00004000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00004000 */ +#define ADC_CALFACT2_LINCALFACT_15 (0x00008000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00008000 */ +#define ADC_CALFACT2_LINCALFACT_16 (0x00010000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT2_LINCALFACT_17 (0x00020000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT2_LINCALFACT_18 (0x00040000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT2_LINCALFACT_19 (0x00080000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT2_LINCALFACT_20 (0x00100000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT2_LINCALFACT_21 (0x00200000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT2_LINCALFACT_22 (0x00400000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00400000 */ +#define ADC_CALFACT2_LINCALFACT_23 (0x00800000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00800000 */ +#define ADC_CALFACT2_LINCALFACT_24 (0x01000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x01000000 */ +#define ADC_CALFACT2_LINCALFACT_25 (0x02000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x02000000 */ +#define ADC_CALFACT2_LINCALFACT_26 (0x04000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x04000000 */ +#define ADC_CALFACT2_LINCALFACT_27 (0x08000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x08000000 */ +#define ADC_CALFACT2_LINCALFACT_28 (0x10000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x10000000 */ +#define ADC_CALFACT2_LINCALFACT_29 (0x20000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x20000000 */ + +/************************* ADC Common registers *****************************/ +/******************** Bit definition for ADC_CSR register ********************/ +#define ADC_CSR_ADRDY_MST_Pos (0U) +#define ADC_CSR_ADRDY_MST_Msk (0x1UL << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */ +#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< Master ADC ready */ +#define ADC_CSR_EOSMP_MST_Pos (1U) +#define ADC_CSR_EOSMP_MST_Msk (0x1UL << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */ +#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< End of sampling phase flag of the master ADC */ +#define ADC_CSR_EOC_MST_Pos (2U) +#define ADC_CSR_EOC_MST_Msk (0x1UL << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */ +#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< End of regular conversion of the master ADC */ +#define ADC_CSR_EOS_MST_Pos (3U) +#define ADC_CSR_EOS_MST_Msk (0x1UL << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */ +#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< End of regular sequence flag of the master ADC */ +#define ADC_CSR_OVR_MST_Pos (4U) +#define ADC_CSR_OVR_MST_Msk (0x1UL << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */ +#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< Overrun flag of the master ADC */ +#define ADC_CSR_JEOC_MST_Pos (5U) +#define ADC_CSR_JEOC_MST_Msk (0x1UL << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */ +#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< End of injected conversion of the master ADC */ +#define ADC_CSR_JEOS_MST_Pos (6U) +#define ADC_CSR_JEOS_MST_Msk (0x1UL << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */ +#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< End of injected sequence flag of the master ADC */ +#define ADC_CSR_AWD1_MST_Pos (7U) +#define ADC_CSR_AWD1_MST_Msk (0x1UL << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */ +#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< Analog watchdog 1 flag of the master ADC */ +#define ADC_CSR_AWD2_MST_Pos (8U) +#define ADC_CSR_AWD2_MST_Msk (0x1UL << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */ +#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< Analog watchdog 2 flag of the master ADC */ +#define ADC_CSR_AWD3_MST_Pos (9U) +#define ADC_CSR_AWD3_MST_Msk (0x1UL << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */ +#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< Analog watchdog 3 flag of the master ADC */ +#define ADC_CSR_JQOVF_MST_Pos (10U) +#define ADC_CSR_JQOVF_MST_Msk (0x1UL << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */ +#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< Injected context queue overflow flag of the master ADC */ +#define ADC_CSR_ADRDY_SLV_Pos (16U) +#define ADC_CSR_ADRDY_SLV_Msk (0x1UL << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< Slave ADC ready */ +#define ADC_CSR_EOSMP_SLV_Pos (17U) +#define ADC_CSR_EOSMP_SLV_Msk (0x1UL << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< End of sampling phase flag of the slave ADC */ +#define ADC_CSR_EOC_SLV_Pos (18U) +#define ADC_CSR_EOC_SLV_Msk (0x1UL << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< End of regular conversion of the slave ADC */ +#define ADC_CSR_EOS_SLV_Pos (19U) +#define ADC_CSR_EOS_SLV_Msk (0x1UL << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< End of regular sequence flag of the slave ADC */ +#define ADC_CSR_OVR_SLV_Pos (20U) +#define ADC_CSR_OVR_SLV_Msk (0x1UL << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< Overrun flag of the slave ADC */ +#define ADC_CSR_JEOC_SLV_Pos (21U) +#define ADC_CSR_JEOC_SLV_Msk (0x1UL << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< End of injected conversion of the slave ADC */ +#define ADC_CSR_JEOS_SLV_Pos (22U) +#define ADC_CSR_JEOS_SLV_Msk (0x1UL << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< End of injected sequence flag of the slave ADC */ +#define ADC_CSR_AWD1_SLV_Pos (23U) +#define ADC_CSR_AWD1_SLV_Msk (0x1UL << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< Analog watchdog 1 flag of the slave ADC */ +#define ADC_CSR_AWD2_SLV_Pos (24U) +#define ADC_CSR_AWD2_SLV_Msk (0x1UL << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< Analog watchdog 2 flag of the slave ADC */ +#define ADC_CSR_AWD3_SLV_Pos (25U) +#define ADC_CSR_AWD3_SLV_Msk (0x1UL << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< Analog watchdog 3 flag of the slave ADC */ +#define ADC_CSR_JQOVF_SLV_Pos (26U) +#define ADC_CSR_JQOVF_SLV_Msk (0x1UL << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< Injected context queue overflow flag of the slave ADC */ + +/******************** Bit definition for ADC_CCR register ********************/ +#define ADC_CCR_DUAL_Pos (0U) +#define ADC_CCR_DUAL_Msk (0x1FUL << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */ +#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< Dual ADC mode selection */ +#define ADC_CCR_DUAL_0 (0x01UL << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */ +#define ADC_CCR_DUAL_1 (0x02UL << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */ +#define ADC_CCR_DUAL_2 (0x04UL << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */ +#define ADC_CCR_DUAL_3 (0x08UL << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */ +#define ADC_CCR_DUAL_4 (0x10UL << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */ + +#define ADC_CCR_DELAY_Pos (8U) +#define ADC_CCR_DELAY_Msk (0xFUL << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */ +#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< Delay between 2 sampling phases */ +#define ADC_CCR_DELAY_0 (0x1UL << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */ +#define ADC_CCR_DELAY_1 (0x2UL << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */ +#define ADC_CCR_DELAY_2 (0x4UL << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */ +#define ADC_CCR_DELAY_3 (0x8UL << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */ + + +#define ADC_CCR_DAMDF_Pos (14U) +#define ADC_CCR_DAMDF_Msk (0x3UL << ADC_CCR_DAMDF_Pos) /*!< 0x0000C000 */ +#define ADC_CCR_DAMDF ADC_CCR_DAMDF_Msk /*!< Dual ADC mode Data format */ +#define ADC_CCR_DAMDF_0 (0x1UL << ADC_CCR_DAMDF_Pos) /*!< 0x00004000 */ +#define ADC_CCR_DAMDF_1 (0x2UL << ADC_CCR_DAMDF_Pos) /*!< 0x00008000 */ + +#define ADC_CCR_CKMODE_Pos (16U) +#define ADC_CCR_CKMODE_Msk (0x3UL << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */ +#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC clock mode */ +#define ADC_CCR_CKMODE_0 (0x1UL << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */ +#define ADC_CCR_CKMODE_1 (0x2UL << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */ + +#define ADC_CCR_PRESC_Pos (18U) +#define ADC_CCR_PRESC_Msk (0xFUL << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */ +#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC prescaler */ +#define ADC_CCR_PRESC_0 (0x1UL << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */ +#define ADC_CCR_PRESC_1 (0x2UL << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */ +#define ADC_CCR_PRESC_2 (0x4UL << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */ +#define ADC_CCR_PRESC_3 (0x8UL << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */ + +#define ADC_CCR_VREFEN_Pos (22U) +#define ADC_CCR_VREFEN_Msk (0x1UL << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */ +#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< VREFINT enable */ +#define ADC_CCR_TSEN_Pos (23U) +#define ADC_CCR_TSEN_Msk (0x1UL << ADC_CCR_TSEN_Pos) /*!< 0x00800000 */ +#define ADC_CCR_TSEN ADC_CCR_TSEN_Msk /*!< Temperature sensor enable */ +#define ADC_CCR_VBATEN_Pos (24U) +#define ADC_CCR_VBATEN_Msk (0x1UL << ADC_CCR_VBATEN_Pos) /*!< 0x01000000 */ +#define ADC_CCR_VBATEN ADC_CCR_VBATEN_Msk /*!< VBAT enable */ + +/******************** Bit definition for ADC_CDR register *******************/ +#define ADC_CDR_RDATA_MST_Pos (0U) +#define ADC_CDR_RDATA_MST_Msk (0xFFFFUL << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */ +#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */ + +#define ADC_CDR_RDATA_SLV_Pos (16U) +#define ADC_CDR_RDATA_SLV_Msk (0xFFFFUL << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */ +#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */ + +/******************** Bit definition for ADC_CDR2 register ******************/ +#define ADC_CDR2_RDATA_ALT_Pos (0U) +#define ADC_CDR2_RDATA_ALT_Msk (0xFFFFFFFFUL << ADC_CDR2_RDATA_ALT_Pos) /*!< 0xFFFFFFFF */ +#define ADC_CDR2_RDATA_ALT ADC_CDR2_RDATA_ALT_Msk /*!< Regular data of the master/slave alternated ADCs */ + + +/******************************************************************************/ +/* */ +/* VREFBUF */ +/* */ +/******************************************************************************/ +/******************* Bit definition for VREFBUF_CSR register ****************/ +#define VREFBUF_CSR_ENVR_Pos (0U) +#define VREFBUF_CSR_ENVR_Msk (0x1UL << VREFBUF_CSR_ENVR_Pos) /*!< 0x00000001 */ +#define VREFBUF_CSR_ENVR VREFBUF_CSR_ENVR_Msk /*!*/ +#define DAC_CR_CEN1_Pos (14U) +#define DAC_CR_CEN1_Msk (0x1UL << DAC_CR_CEN1_Pos) /*!< 0x00004000 */ +#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/ + +#define DAC_CR_EN2_Pos (16U) +#define DAC_CR_EN2_Msk (0x1UL << DAC_CR_EN2_Pos) /*!< 0x00010000 */ +#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/ +#define DAC_CR_CEN2_Pos (30U) +#define DAC_CR_CEN2_Msk (0x1UL << DAC_CR_CEN2_Pos) /*!< 0x40000000 */ +#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/ + +/***************** Bit definition for DAC_SWTRIGR register ******************/ +#define DAC_SWTRIGR_SWTRIG1_Pos (0U) +#define DAC_SWTRIGR_SWTRIG1_Msk (0x1UL << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */ +#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*!
© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.
+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32h7xx + * @{ + */ + +#ifndef STM32H7xx_H +#define STM32H7xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Library_configuration_section + * @{ + */ + +/** + * @brief STM32 Family + */ +#if !defined (STM32H7) +#define STM32H7 +#endif /* STM32H7 */ + + +/* Uncomment the line below according to the target STM32H7 device used in your + application + */ + +/* #if !defined (STM32H743xx) && !defined (STM32H753xx) && !defined (STM32H750xx) && !defined (STM32H742xx) && \ + !defined (STM32H745xx) && !defined (STM32H755xx) && !defined (STM32H747xx) && !defined (STM32H757xx) && \ + !defined (STM32H7A3xx) && !defined (STM32H7A3xxQ) && !defined (STM32H7B3xx) && !defined (STM32H7B3xxQ) && !defined (STM32H7B0xx) && !defined (STM32H7B0xxQ) && \ + !defined (STM32H735xx) && !defined (STM32H733xx) && !defined (STM32H730xx) && !defined (STM32H730xxQ) && !defined (STM32H725xx) && !defined (STM32H723xx) */ + /* #define STM32H742xx */ /*!< STM32H742VI, STM32H742ZI, STM32H742AI, STM32H742II, STM32H742BI, STM32H742XI Devices */ + /* #define STM32H743xx */ /*!< STM32H743VI, STM32H743ZI, STM32H743AI, STM32H743II, STM32H743BI, STM32H743XI Devices */ + /* #define STM32H753xx */ /*!< STM32H753VI, STM32H753ZI, STM32H753AI, STM32H753II, STM32H753BI, STM32H753XI Devices */ + /* #define STM32H750xx */ /*!< STM32H750V, STM32H750I, STM32H750X Devices */ + /* #define STM32H747xx */ /*!< STM32H747ZI, STM32H747AI, STM32H747II, STM32H747BI, STM32H747XI Devices */ + /* #define STM32H757xx */ /*!< STM32H757ZI, STM32H757AI, STM32H757II, STM32H757BI, STM32H757XI Devices */ + /* #define STM32H745xx */ /*!< STM32H745ZI, STM32H745II, STM32H745BI, STM32H745XI Devices */ + /* #define STM32H755xx */ /*!< STM32H755ZI, STM32H755II, STM32H755BI, STM32H755XI Devices */ + /* #define STM32H7B0xx */ /*!< STM32H7B0ABIxQ, STM32H7B0IBTx, STM32H7B0RBTx, STM32H7B0VBTx, STM32H7B0ZBTx, STM32H7B0IBKxQ */ + /* #define STM32H7A3xx */ /*!< STM32H7A3IIK6, STM32H7A3IIT6, STM32H7A3NIH6, STM32H7A3RIT6, STM32H7A3VIH6, STM32H7A3VIT6, STM32H7A3ZIT6 */ + /* #define STM32H7A3xxQ */ /*!< STM32H7A3QIY6Q, STM32H7A3IIK6Q, STM32H7A3IIT6Q, STM32H7A3LIH6Q, STM32H7A3VIH6Q, STM32H7A3VIT6Q, STM32H7A3AII6Q, STM32H7A3ZIT6Q */ + /* #define STM32H7B3xx */ /*!< STM32H7B3IIK6, STM32H7B3IIT6, STM32H7B3NIH6, STM32H7B3RIT6, STM32H7B3VIH6, STM32H7B3VIT6, STM32H7B3ZIT6 */ + /* #define STM32H7B3xxQ */ /*!< STM32H7B3QIY6Q, STM32H7B3IIK6Q, STM32H7B3IIT6Q, STM32H7B3LIH6Q, STM32H7B3VIH6Q, STM32H7B3VIT6Q, STM32H7B3AII6Q, STM32H7B3ZIT6Q */ + /* #define STM32H735xx */ /*!< STM32H735AGI6, STM32H735IGK6, STM32H735RGV6, STM32H735VGT6, STM32H735VGY6, STM32H735ZGT6 Devices */ + /* #define STM32H733xx */ /*!< STM32H733VGH6, STM32H733VGT6, STM32H733ZGI6, STM32H733ZGT6, Devices */ + /* #define STM32H730xx */ /*!< STM32H730VBH6, STM32H730VBT6, STM32H730ZBT6, STM32H730ZBI6 Devices */ + /* #define STM32H730xxQ */ /*!< STM32H730IBT6Q, STM32H730ABI6Q, STM32H730IBK6Q Devices */ + /* #define STM32H725xx */ /*!< STM32H725AGI6, STM32H725IGK6, STM32H725IGT6, STM32H725RGV6, STM32H725VGT6, STM32H725VGY6, STM32H725ZGT6, STM32H725REV6, SM32H725VET6, STM32H725ZET6, STM32H725AEI6, STM32H725IET6, STM32H725IEK6 Devices */ + /* #define STM32H723xx */ /*!< STM32H723VGH6, STM32H723VGT6, STM32H723ZGI6, STM32H723ZGT6, STM32H723VET6, STM32H723VEH6, STM32H723ZET6, STM32H723ZEI6 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(DUAL_CORE) && !defined(CORE_CM4) && !defined(CORE_CM7) + #error "Dual core device, please select CORE_CM4 or CORE_CM7" +#endif + +#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 Device version number V1.10.0 + */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION_SUB1 (0x0A) /*!< [23:16] sub1 version */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION ((__STM32H7xx_CMSIS_DEVICE_VERSION_MAIN << 24)\ + |(__STM32H7xx_CMSIS_DEVICE_VERSION_SUB1 << 16)\ + |(__STM32H7xx_CMSIS_DEVICE_VERSION_SUB2 << 8 )\ + |(__STM32H7xx_CMSIS_DEVICE_VERSION_RC)) + +/** + * @} + */ + +/** @addtogroup Device_Included + * @{ + */ + +#if defined(STM32H743xx) + #include "stm32h743xx.h" +// #elif defined(STM32H753xx) +// #include "stm32h753xx.h" +// #elif defined(STM32H750xx) +// #include "stm32h750xx.h" +// #elif defined(STM32H742xx) +// #include "stm32h742xx.h" +// #elif defined(STM32H745xx) +// #include "stm32h745xx.h" +// #elif defined(STM32H755xx) +// #include "stm32h755xx.h" +// #elif defined(STM32H747xx) +// #include "stm32h747xx.h" +// #elif defined(STM32H757xx) +// #include "stm32h757xx.h" +// #elif defined(STM32H7B0xx) +// #include "stm32h7b0xx.h" +// #elif defined(STM32H7B0xxQ) +// #include "stm32h7b0xxq.h" +// #elif defined(STM32H7A3xx) +// #include "stm32h7a3xx.h" +// #elif defined(STM32H7B3xx) +// #include "stm32h7b3xx.h" +// #elif defined(STM32H7A3xxQ) +// #include "stm32h7a3xxq.h" +// #elif defined(STM32H7B3xxQ) +// #include "stm32h7b3xxq.h" +#elif defined(STM32H735xx) + #include "stm32h735xx.h" +// #elif defined(STM32H733xx) +// #include "stm32h733xx.h" +// #elif defined(STM32H730xx) +// #include "stm32h730xx.h" +// #elif defined(STM32H730xxQ) +// #include "stm32h730xxq.h" +#elif defined(STM32H725xx) + #include "stm32h725xx.h" +// #elif defined(STM32H723xx) +// #include "stm32h723xx.h" +#else + #error "Please select first the target STM32H7xx device used in your application (in stm32h7xx.h file)" +#endif + +/** + * @} + */ + +/** @addtogroup Exported_types + * @{ + */ +typedef enum +{ + RESET = 0, + SET = !RESET +} FlagStatus, ITStatus; + +typedef enum +{ + DISABLE = 0, + ENABLE = !DISABLE +} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum +{ + SUCCESS = 0, + ERROR = !SUCCESS +} ErrorStatus; + +/** + * @} + */ + + +/** @addtogroup Exported_macros + * @{ + */ +#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 "stm32h7xx_hal.h" +#endif /* USE_HAL_DRIVER */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* STM32H7xx_H */ +/** + * @} + */ + +/** + * @} + */ + + + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda_tici/board/stm32h7/inc/stm32h7xx_hal_def.h b/panda_tici/board/stm32h7/inc/stm32h7xx_hal_def.h new file mode 100644 index 0000000..3854b1c --- /dev/null +++ b/panda_tici/board/stm32h7/inc/stm32h7xx_hal_def.h @@ -0,0 +1,221 @@ +/** + ****************************************************************************** + * @file stm32h7xx_hal_def.h + * @author MCD Application Team + * @brief This file contains HAL common defines, enumeration, macros and + * structures definitions. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32H7xx_HAL_DEF +#define STM32H7xx_HAL_DEF + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx.h" +//#include "Legacy/stm32_hal_legacy.h" +//#include +//#include + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief HAL Status structures definition + */ +typedef enum +{ + HAL_OK = 0x00, + HAL_ERROR = 0x01, + HAL_BUSY = 0x02, + HAL_TIMEOUT = 0x03 +} HAL_StatusTypeDef; + +/** + * @brief HAL Lock structures definition + */ +typedef enum +{ + HAL_UNLOCKED = 0x00, + HAL_LOCKED = 0x01 +} HAL_LockTypeDef; + +/* Exported macro ------------------------------------------------------------*/ + +#define HAL_MAX_DELAY 0xFFFFFFFFU + +#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) == (BIT)) +#define HAL_IS_BIT_CLR(REG, BIT) (((REG) & (BIT)) == 0U) + +#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 = 0) + +#if (USE_RTOS == 1) + #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 (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */ + #ifndef __weak + #define __weak __attribute__((weak)) + #endif + #ifndef __packed + #define __packed __attribute__((packed)) + #endif +#elif defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ + #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 (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */ + #ifndef __ALIGN_BEGIN + #define __ALIGN_BEGIN + #endif + #ifndef __ALIGN_END + #define __ALIGN_END __attribute__ ((aligned (4))) + #endif +#elif defined ( __GNUC__ ) && !defined (__CC_ARM) /* 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 V5 */ + #define __ALIGN_BEGIN __align(4) + #elif defined (__ICCARM__) /* IAR Compiler */ + #define __ALIGN_BEGIN + #endif /* __CC_ARM */ + #endif /* __ALIGN_BEGIN */ +#endif /* __GNUC__ */ + +/* Macro to get variable aligned on 32-bytes,needed for cache maintenance purpose */ +#if defined (__GNUC__) /* GNU Compiler */ + #define ALIGN_32BYTES(buf) buf __attribute__ ((aligned (32))) +#elif defined (__ICCARM__) /* IAR Compiler */ + #define ALIGN_32BYTES(buf) _Pragma("data_alignment=32") buf +#elif defined (__CC_ARM) /* ARM Compiler */ + #define ALIGN_32BYTES(buf) __align(32) buf +#endif + +/** + * @brief __RAM_FUNC definition + */ +#if defined ( __CC_ARM ) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) +/* ARM Compiler V4/V5 and V6 + -------------------------- + 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 + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- + RAM functions are defined using a specific toolchain keyword "__ramfunc". +*/ +#define __RAM_FUNC __ramfunc + +#elif defined ( __GNUC__ ) +/* GNU Compiler + ------------ + RAM functions are defined using a specific toolchain attribute + "__attribute__((section(".RamFunc")))". +*/ +#define __RAM_FUNC __attribute__((section(".RamFunc"))) + +#endif + +/** + * @brief __NOINLINE definition + */ +#if defined ( __CC_ARM ) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) || defined ( __GNUC__ ) +/* ARM V4/V5 and V6 & GNU Compiler + ------------------------------- +*/ +#define __NOINLINE __attribute__ ( (noinline) ) + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- +*/ +#define __NOINLINE _Pragma("optimize = no_inline") + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H7xx_HAL_DEF */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda_tici/board/stm32h7/inc/stm32h7xx_hal_gpio_ex.h b/panda_tici/board/stm32h7/inc/stm32h7xx_hal_gpio_ex.h new file mode 100644 index 0000000..14f576a --- /dev/null +++ b/panda_tici/board/stm32h7/inc/stm32h7xx_hal_gpio_ex.h @@ -0,0 +1,489 @@ +/** + ****************************************************************************** + * @file stm32h7xx_hal_gpio_ex.h + * @author MCD Application Team + * @brief Header file of GPIO HAL Extension module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32H7xx_HAL_GPIO_EX_H +#define STM32H7xx_HAL_GPIO_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx_hal_def.h" + +/** @addtogroup STM32H7xx_HAL_Driver + * @{ + */ + +/** @addtogroup GPIOEx GPIOEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Constants GPIO Exported Constants + * @{ + */ + +/** @defgroup GPIO_Alternate_function_selection GPIO Alternate Function Selection + * @{ + */ + +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_LCDBIAS ((uint8_t)0x00) /* LCDBIAS Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ +#if defined (PWR_CPUCR_PDDS_D2) /* PWR D1 and D2 domains exists */ +#define GPIO_AF0_C1DSLEEP ((uint8_t)0x00) /* Cortex-M7 Deep Sleep Alternate Function mapping : available on STM32H7 Rev.B and above */ +#define GPIO_AF0_C1SLEEP ((uint8_t)0x00) /* Cortex-M7 Sleep Alternate Function mapping : available on STM32H7 Rev.B and above */ +#define GPIO_AF0_D1PWREN ((uint8_t)0x00) /* Domain 1 PWR enable Alternate Function mapping : available on STM32H7 Rev.B and above */ +#define GPIO_AF0_D2PWREN ((uint8_t)0x00) /* Domain 2 PWR enable Alternate Function mapping : available on STM32H7 Rev.B and above */ +#if defined(DUAL_CORE) +#define GPIO_AF0_C2DSLEEP ((uint8_t)0x00) /* Cortex-M4 Deep Sleep Alternate Function mapping : available on STM32H7 Rev.B and above */ +#define GPIO_AF0_C2SLEEP ((uint8_t)0x00) /* Cortex-M4 Sleep Alternate Function mapping : available on STM32H7 Rev.B and above */ +#endif /* DUAL_CORE */ +#endif /* PWR_CPUCR_PDDS_D2 */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_TIM16 ((uint8_t)0x01) /* TIM16 Alternate Function mapping */ +#define GPIO_AF1_TIM17 ((uint8_t)0x01) /* TIM17 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#if defined(HRTIM1) +#define GPIO_AF1_HRTIM1 ((uint8_t)0x01) /* HRTIM1 Alternate Function mapping */ +#endif /* HRTIM1 */ +#if defined(SAI4) +#define GPIO_AF1_SAI4 ((uint8_t)0x01) /* SAI4 Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ +#endif /* SAI4 */ +#define GPIO_AF1_FMC ((uint8_t)0x01) /* FMC Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ + + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02) /* TIM5 Alternate Function mapping */ +#define GPIO_AF2_TIM12 ((uint8_t)0x02) /* TIM12 Alternate Function mapping */ +#define GPIO_AF2_SAI1 ((uint8_t)0x02) /* SAI1 Alternate Function mapping */ +#if defined(HRTIM1) +#define GPIO_AF2_HRTIM1 ((uint8_t)0x02) /* HRTIM1 Alternate Function mapping */ +#endif /* HRTIM1 */ +#define GPIO_AF2_TIM15 ((uint8_t)0x02) /* TIM15 Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ +#if defined(FDCAN3) +#define GPIO_AF2_FDCAN3 ((uint8_t)0x02) /* FDCAN3 Alternate Function mapping */ +#endif /*FDCAN3*/ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_LPTIM2 ((uint8_t)0x03) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF3_DFSDM1 ((uint8_t)0x03) /* DFSDM Alternate Function mapping */ +#define GPIO_AF3_LPTIM3 ((uint8_t)0x03) /* LPTIM3 Alternate Function mapping */ +#define GPIO_AF3_LPTIM4 ((uint8_t)0x03) /* LPTIM4 Alternate Function mapping */ +#define GPIO_AF3_LPTIM5 ((uint8_t)0x03) /* LPTIM5 Alternate Function mapping */ +#define GPIO_AF3_LPUART ((uint8_t)0x03) /* LPUART Alternate Function mapping */ +#if defined(OCTOSPIM) +#define GPIO_AF3_OCTOSPIM_P1 ((uint8_t)0x03) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF3_OCTOSPIM_P2 ((uint8_t)0x03) /* OCTOSPI Manager Port 2 Alternate Function mapping */ +#endif /* OCTOSPIM */ +#if defined(HRTIM1) +#define GPIO_AF3_HRTIM1 ((uint8_t)0x03) /* HRTIM1 Alternate Function mapping */ +#endif /* HRTIM1 */ +#define GPIO_AF3_LTDC ((uint8_t)0x03) /* LTDC Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_I2C4 ((uint8_t)0x04) /* I2C4 Alternate Function mapping */ +#if defined(I2C5) +#define GPIO_AF4_I2C5 ((uint8_t)0x04) /* I2C5 Alternate Function mapping */ +#endif /* I2C5*/ +#define GPIO_AF4_TIM15 ((uint8_t)0x04) /* TIM15 Alternate Function mapping */ +#define GPIO_AF4_CEC ((uint8_t)0x04) /* CEC Alternate Function mapping */ +#define GPIO_AF4_LPTIM2 ((uint8_t)0x04) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF4_USART1 ((uint8_t)0x04) /* USART1 Alternate Function mapping */ +#if defined(USART10) +#define GPIO_AF4_USART10 ((uint8_t)0x04) /* USART10 Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ +#endif /*USART10*/ +#define GPIO_AF4_DFSDM1 ((uint8_t)0x04) /* DFSDM Alternate Function mapping */ +#if defined(DFSDM2_BASE) +#define GPIO_AF4_DFSDM2 ((uint8_t)0x04) /* DFSDM2 Alternate Function mapping */ +#endif /* DFSDM2_BASE */ +#define GPIO_AF4_DCMI ((uint8_t)0x04) /* DCMI Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ +#if defined(PSSI) +#define GPIO_AF4_PSSI ((uint8_t)0x04) /* PSSI Alternate Function mapping */ +#endif /* PSSI */ +#if defined(OCTOSPIM) +#define GPIO_AF4_OCTOSPIM_P1 ((uint8_t)0x04) /* OCTOSPI Manager Port 1 Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05) /* SPI3 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05) /* SPI4 Alternate Function mapping */ +#define GPIO_AF5_SPI5 ((uint8_t)0x05) /* SPI5 Alternate Function mapping */ +#define GPIO_AF5_SPI6 ((uint8_t)0x05) /* SPI6 Alternate Function mapping */ +#define GPIO_AF5_CEC ((uint8_t)0x05) /* CEC Alternate Function mapping */ +#if defined(FDCAN3) +#define GPIO_AF5_FDCAN3 ((uint8_t)0x05) /* FDCAN3 Alternate Function mapping */ +#endif /*FDCAN3*/ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI2 ((uint8_t)0x06) /* SPI2 Alternate Function mapping */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_SAI1 ((uint8_t)0x06) /* SAI1 Alternate Function mapping */ +#define GPIO_AF6_I2C4 ((uint8_t)0x06) /* I2C4 Alternate Function mapping */ +#if defined(I2C5) +#define GPIO_AF6_I2C5 ((uint8_t)0x06) /* I2C5 Alternate Function mapping */ +#endif /* I2C5*/ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM Alternate Function mapping */ +#define GPIO_AF6_UART4 ((uint8_t)0x06) /* UART4 Alternate Function mapping */ +#if defined(DFSDM2_BASE) +#define GPIO_AF6_DFSDM2 ((uint8_t)0x06) /* DFSDM2 Alternate Function mapping */ +#endif /* DFSDM2_BASE */ +#if defined(SAI3) +#define GPIO_AF6_SAI3 ((uint8_t)0x06) /* SAI3 Alternate Function mapping */ +#endif /* SAI3 */ +#if defined(OCTOSPIM) +#define GPIO_AF6_OCTOSPIM_P1 ((uint8_t)0x06) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_SPI2 ((uint8_t)0x07) /* SPI2 Alternate Function mapping */ +#define GPIO_AF7_SPI3 ((uint8_t)0x07) /* SPI3 Alternate Function mapping */ +#define GPIO_AF7_SPI6 ((uint8_t)0x07) /* SPI6 Alternate Function mapping */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_USART6 ((uint8_t)0x07) /* USART6 Alternate Function mapping */ +#define GPIO_AF7_UART7 ((uint8_t)0x07) /* UART7 Alternate Function mapping */ +#define GPIO_AF7_SDMMC1 ((uint8_t)0x07) /* SDMMC1 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_SPI6 ((uint8_t)0x08) /* SPI6 Alternate Function mapping */ +#if defined(SAI2) +#define GPIO_AF8_SAI2 ((uint8_t)0x08) /* SAI2 Alternate Function mapping */ +#endif /*SAI2*/ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_UART8 ((uint8_t)0x08) /* UART8 Alternate Function mapping */ +#define GPIO_AF8_SPDIF ((uint8_t)0x08) /* SPDIF Alternate Function mapping */ +#define GPIO_AF8_LPUART ((uint8_t)0x08) /* LPUART Alternate Function mapping */ +#define GPIO_AF8_SDMMC1 ((uint8_t)0x08) /* SDMMC1 Alternate Function mapping */ +#if defined(SAI4) +#define GPIO_AF8_SAI4 ((uint8_t)0x08) /* SAI4 Alternate Function mapping */ +#endif /* SAI4 */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_FDCAN1 ((uint8_t)0x09) /* FDCAN1 Alternate Function mapping */ +#define GPIO_AF9_FDCAN2 ((uint8_t)0x09) /* FDCAN2 Alternate Function mapping */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09) /* TIM14 Alternate Function mapping */ +#define GPIO_AF9_SDMMC2 ((uint8_t)0x09) /* SDMMC2 Alternate Function mapping */ +#define GPIO_AF9_LTDC ((uint8_t)0x09) /* LTDC Alternate Function mapping */ +#define GPIO_AF9_SPDIF ((uint8_t)0x09) /* SPDIF Alternate Function mapping */ +#define GPIO_AF9_FMC ((uint8_t)0x09) /* FMC Alternate Function mapping */ +#if defined(QUADSPI) +#define GPIO_AF9_QUADSPI ((uint8_t)0x09) /* QUADSPI Alternate Function mapping */ +#endif /* QUADSPI */ +#if defined(SAI4) +#define GPIO_AF9_SAI4 ((uint8_t)0x09) /* SAI4 Alternate Function mapping */ +#endif /* SAI4 */ +#if defined(OCTOSPIM) +#define GPIO_AF9_OCTOSPIM_P1 ((uint8_t)0x09) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF9_OCTOSPIM_P2 ((uint8_t)0x09) /* OCTOSPI Manager Port 2 Alternate Function mapping */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 10 selection + */ +#if defined(SAI2) +#define GPIO_AF10_SAI2 ((uint8_t)0x0A) /* SAI2 Alternate Function mapping */ +#endif /*SAI2*/ +#define GPIO_AF10_SDMMC2 ((uint8_t)0x0A) /* SDMMC2 Alternate Function mapping */ +#if defined(USB2_OTG_FS) +#define GPIO_AF10_OTG2_FS ((uint8_t)0x0A) /* OTG2_FS Alternate Function mapping */ +#endif /*USB2_OTG_FS*/ +#define GPIO_AF10_COMP1 ((uint8_t)0x0A) /* COMP1 Alternate Function mapping */ +#define GPIO_AF10_COMP2 ((uint8_t)0x0A) /* COMP2 Alternate Function mapping */ +#if defined(LTDC) +#define GPIO_AF10_LTDC ((uint8_t)0x0A) /* LTDC Alternate Function mapping */ +#endif /*LTDC*/ +#define GPIO_AF10_CRS_SYNC ((uint8_t)0x0A) /* CRS Sync Alternate Function mapping : available on STM32H7 Rev.B and above */ +#if defined(QUADSPI) +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ +#endif /* QUADSPI */ +#if defined(SAI4) +#define GPIO_AF10_SAI4 ((uint8_t)0x0A) /* SAI4 Alternate Function mapping */ +#endif /* SAI4 */ +#if !defined(USB2_OTG_FS) +#define GPIO_AF10_OTG1_FS ((uint8_t)0x0A) /* OTG1_FS Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ +#endif /* !USB2_OTG_FS */ +#define GPIO_AF10_OTG1_HS ((uint8_t)0x0A) /* OTG1_HS Alternate Function mapping */ +#if defined(OCTOSPIM) +#define GPIO_AF10_OCTOSPIM_P1 ((uint8_t)0x0A) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#endif /* OCTOSPIM */ +#define GPIO_AF10_TIM8 ((uint8_t)0x0A) /* TIM8 Alternate Function mapping */ +#define GPIO_AF10_FMC ((uint8_t)0x0A) /* FMC Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_SWP ((uint8_t)0x0B) /* SWP Alternate Function mapping */ +#define GPIO_AF11_MDIOS ((uint8_t)0x0B) /* MDIOS Alternate Function mapping */ +#define GPIO_AF11_UART7 ((uint8_t)0x0B) /* UART7 Alternate Function mapping */ +#define GPIO_AF11_SDMMC2 ((uint8_t)0x0B) /* SDMMC2 Alternate Function mapping */ +#define GPIO_AF11_DFSDM1 ((uint8_t)0x0B) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF11_COMP1 ((uint8_t)0x0B) /* COMP1 Alternate Function mapping */ +#define GPIO_AF11_COMP2 ((uint8_t)0x0B) /* COMP2 Alternate Function mapping */ +#define GPIO_AF11_TIM1 ((uint8_t)0x0B) /* TIM1 Alternate Function mapping */ +#define GPIO_AF11_TIM8 ((uint8_t)0x0B) /* TIM8 Alternate Function mapping */ +#define GPIO_AF11_I2C4 ((uint8_t)0x0B) /* I2C4 Alternate Function mapping */ +#if defined(DFSDM2_BASE) +#define GPIO_AF11_DFSDM2 ((uint8_t)0x0B) /* DFSDM2 Alternate Function mapping */ +#endif /* DFSDM2_BASE */ +#if defined(USART10) +#define GPIO_AF11_USART10 ((uint8_t)0x0B) /* USART10 Alternate Function mapping */ +#endif /* USART10 */ +#if defined(UART9) +#define GPIO_AF11_UART9 ((uint8_t)0x0B) /* UART9 Alternate Function mapping */ +#endif /* UART9 */ +#if defined(ETH) +#define GPIO_AF11_ETH ((uint8_t)0x0B) /* ETH Alternate Function mapping */ +#endif /* ETH */ +#if defined(LTDC) +#define GPIO_AF11_LTDC ((uint8_t)0x0B) /* LTDC Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ +#endif /*LTDC*/ +#if defined(OCTOSPIM) +#define GPIO_AF11_OCTOSPIM_P1 ((uint8_t)0x0B) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ +#define GPIO_AF12_MDIOS ((uint8_t)0x0C) /* MDIOS Alternate Function mapping */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_TIM1 ((uint8_t)0x0C) /* TIM1 Alternate Function mapping */ +#define GPIO_AF12_TIM8 ((uint8_t)0x0C) /* TIM8 Alternate Function mapping */ +#if defined(LTDC) +#define GPIO_AF12_LTDC ((uint8_t)0x0C) /* LTDC Alternate Function mapping */ +#endif /*LTDC*/ +#if defined(USB2_OTG_FS) +#define GPIO_AF12_OTG1_FS ((uint8_t)0x0C) /* OTG1_FS Alternate Function mapping */ +#endif /* USB2_OTG_FS */ +#if defined(OCTOSPIM) +#define GPIO_AF12_OCTOSPIM_P1 ((uint8_t)0x0C) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_DCMI ((uint8_t)0x0D) /* DCMI Alternate Function mapping */ +#define GPIO_AF13_COMP1 ((uint8_t)0x0D) /* COMP1 Alternate Function mapping */ +#define GPIO_AF13_COMP2 ((uint8_t)0x0D) /* COMP2 Alternate Function mapping */ +#if defined(LTDC) +#define GPIO_AF13_LTDC ((uint8_t)0x0D) /* LTDC Alternate Function mapping */ +#endif /*LTDC*/ +#if defined(DSI) +#define GPIO_AF13_DSI ((uint8_t)0x0D) /* DSI Alternate Function mapping */ +#endif /* DSI */ +#if defined(PSSI) +#define GPIO_AF13_PSSI ((uint8_t)0x0D) /* PSSI Alternate Function mapping */ +#endif /* PSSI */ +#define GPIO_AF13_TIM1 ((uint8_t)0x0D) /* TIM1 Alternate Function mapping */ +#if defined(TIM23) +#define GPIO_AF13_TIM23 ((uint8_t)0x0D) /* TIM23 Alternate Function mapping */ +#endif /*TIM23*/ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_LTDC ((uint8_t)0x0E) /* LTDC Alternate Function mapping */ +#define GPIO_AF14_UART5 ((uint8_t)0x0E) /* UART5 Alternate Function mapping */ +#if defined(TIM24) +#define GPIO_AF14_TIM24 ((uint8_t)0x0E) /* TIM24 Alternate Function mapping */ +#endif /*TIM24*/ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + + + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Macros GPIO Exported Macros + * @{ + */ +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Functions GPIO Exported Functions + * @{ + */ +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup GPIOEx_Private_Constants GPIO Private Constants + * @{ + */ + +/** + * @brief GPIO pin available on the platform + */ +/* Defines the available pins per GPIOs */ +#define GPIOA_PIN_AVAILABLE GPIO_PIN_All +#define GPIOB_PIN_AVAILABLE GPIO_PIN_All +#define GPIOC_PIN_AVAILABLE GPIO_PIN_All +#define GPIOD_PIN_AVAILABLE GPIO_PIN_All +#define GPIOE_PIN_AVAILABLE GPIO_PIN_All +#define GPIOF_PIN_AVAILABLE GPIO_PIN_All +#define GPIOG_PIN_AVAILABLE GPIO_PIN_All +#if defined(GPIOI) +#define GPIOI_PIN_AVAILABLE GPIO_PIN_All +#endif /*GPIOI*/ +#if defined(GPIOI) +#define GPIOJ_PIN_AVAILABLE GPIO_PIN_All +#else +#define GPIOJ_PIN_AVAILABLE (GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 ) +#endif /* GPIOI */ +#define GPIOH_PIN_AVAILABLE GPIO_PIN_All +#if defined(GPIOI) +#define GPIOK_PIN_AVAILABLE (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | \ + GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7) +#else +#define GPIOK_PIN_AVAILABLE (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 ) +#endif /* GPIOI */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup GPIOEx_Private_Macros GPIO Private Macros + * @{ + */ +/** @defgroup GPIOEx_Get_Port_Index GPIO Get Port Index + * @{ + */ +#if defined(GPIOI) +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0UL :\ + ((__GPIOx__) == (GPIOB))? 1UL :\ + ((__GPIOx__) == (GPIOC))? 2UL :\ + ((__GPIOx__) == (GPIOD))? 3UL :\ + ((__GPIOx__) == (GPIOE))? 4UL :\ + ((__GPIOx__) == (GPIOF))? 5UL :\ + ((__GPIOx__) == (GPIOG))? 6UL :\ + ((__GPIOx__) == (GPIOH))? 7UL :\ + ((__GPIOx__) == (GPIOI))? 8UL :\ + ((__GPIOx__) == (GPIOJ))? 9UL : 10UL) +#else +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0UL :\ + ((__GPIOx__) == (GPIOB))? 1UL :\ + ((__GPIOx__) == (GPIOC))? 2UL :\ + ((__GPIOx__) == (GPIOD))? 3UL :\ + ((__GPIOx__) == (GPIOE))? 4UL :\ + ((__GPIOx__) == (GPIOF))? 5UL :\ + ((__GPIOx__) == (GPIOG))? 6UL :\ + ((__GPIOx__) == (GPIOH))? 7UL :\ + ((__GPIOx__) == (GPIOJ))? 9UL : 10UL) +#endif /* GPIOI */ + +/** + * @} + */ + +/** @defgroup GPIOEx_IS_Alternat_function_selection GPIO Check Alternate Function + * @{ + */ +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup GPIOEx_Private_Functions GPIO Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H7xx_HAL_GPIO_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda_tici/board/stm32h7/inc/system_stm32h7xx.h b/panda_tici/board/stm32h7/inc/system_stm32h7xx.h new file mode 100644 index 0000000..dd75af6 --- /dev/null +++ b/panda_tici/board/stm32h7/inc/system_stm32h7xx.h @@ -0,0 +1,105 @@ +/** + ****************************************************************************** + * @file system_stm32h7xx.h + * @author MCD Application Team + * @brief CMSIS Cortex-Mx Device System Source File for STM32H7xx devices. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32h7xx_system + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#ifndef SYSTEM_STM32H7XX_H +#define SYSTEM_STM32H7XX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @addtogroup STM32H7xx_System_Includes + * @{ + */ + +/** + * @} + */ + + +/** @addtogroup STM32H7xx_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 Domain1 Clock Frequency */ +extern uint32_t SystemD2Clock; /*!< System Domain2 Clock Frequency */ +extern const uint8_t D1CorePrescTable[16] ; /*!< D1CorePrescTable prescalers table values */ + +/** + * @} + */ + +/** @addtogroup STM32H7xx_System_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32H7xx_System_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32H7xx_System_Exported_Functions + * @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_STM32H7XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda_tici/board/stm32h7/interrupt_handlers.h b/panda_tici/board/stm32h7/interrupt_handlers.h new file mode 100644 index 0000000..8148021 --- /dev/null +++ b/panda_tici/board/stm32h7/interrupt_handlers.h @@ -0,0 +1,143 @@ +// ********************* Bare interrupt handlers ********************* +// Interrupts for STM32H7x5 + +void WWDG_IRQHandler(void) {handle_interrupt(WWDG_IRQn);} +void PVD_AVD_IRQHandler(void) {handle_interrupt(PVD_AVD_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 FDCAN1_IT0_IRQHandler(void) {handle_interrupt(FDCAN1_IT0_IRQn);} +void FDCAN2_IT0_IRQHandler(void) {handle_interrupt(FDCAN2_IT0_IRQn);} +void FDCAN1_IT1_IRQHandler(void) {handle_interrupt(FDCAN1_IT1_IRQn);} +void FDCAN2_IT1_IRQHandler(void) {handle_interrupt(FDCAN2_IT1_IRQn);} +void EXTI9_5_IRQHandler(void) {handle_interrupt(EXTI9_5_IRQn);} +void TIM1_BRK_IRQHandler(void) {handle_interrupt(TIM1_BRK_IRQn);} +void TIM1_UP_TIM10_IRQHandler(void) {handle_interrupt(TIM1_UP_TIM10_IRQn);} +void TIM1_TRG_COM_IRQHandler(void) {handle_interrupt(TIM1_TRG_COM_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 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 FMC_IRQHandler(void) {handle_interrupt(FMC_IRQn);} +void SDMMC1_IRQHandler(void) {handle_interrupt(SDMMC1_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 ETH_IRQHandler(void) {handle_interrupt(ETH_IRQn);} +void ETH_WKUP_IRQHandler(void) {handle_interrupt(ETH_WKUP_IRQn);} +void FDCAN_CAL_IRQHandler(void) {handle_interrupt(FDCAN_CAL_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 OTG_HS_EP1_OUT_IRQHandler(void) {handle_interrupt(OTG_HS_EP1_OUT_IRQn);} +void OTG_HS_EP1_IN_IRQHandler(void) {handle_interrupt(OTG_HS_EP1_IN_IRQn);} +void OTG_HS_WKUP_IRQHandler(void) {handle_interrupt(OTG_HS_WKUP_IRQn);} +void OTG_HS_IRQHandler(void) {handle_interrupt(OTG_HS_IRQn);} +void DCMI_PSSI_IRQHandler(void) {handle_interrupt(DCMI_PSSI_IRQn);} +void CRYP_IRQHandler(void) {handle_interrupt(CRYP_IRQn);} +void HASH_RNG_IRQHandler(void) {handle_interrupt(HASH_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 SPI6_IRQHandler(void) {handle_interrupt(SPI6_IRQn);} +void SAI1_IRQHandler(void) {handle_interrupt(SAI1_IRQn);} +void LTDC_IRQHandler(void) {handle_interrupt(LTDC_IRQn);} +void LTDC_ER_IRQHandler(void) {handle_interrupt(LTDC_ER_IRQn);} +void DMA2D_IRQHandler(void) {handle_interrupt(DMA2D_IRQn);} +void OCTOSPI1_IRQHandler(void) {handle_interrupt(OCTOSPI1_IRQn);} +void LPTIM1_IRQHandler(void) {handle_interrupt(LPTIM1_IRQn);} +void CEC_IRQHandler(void) {handle_interrupt(CEC_IRQn);} +void I2C4_EV_IRQHandler(void) {handle_interrupt(I2C4_EV_IRQn);} +void I2C4_ER_IRQHandler(void) {handle_interrupt(I2C4_ER_IRQn);} +void SPDIF_RX_IRQHandler(void) {handle_interrupt(SPDIF_RX_IRQn);} +void DMAMUX1_OVR_IRQHandler(void) {handle_interrupt(DMAMUX1_OVR_IRQn);} +void DFSDM1_FLT0_IRQHandler(void) {handle_interrupt(DFSDM1_FLT0_IRQn);} +void DFSDM1_FLT1_IRQHandler(void) {handle_interrupt(DFSDM1_FLT1_IRQn);} +void DFSDM1_FLT2_IRQHandler(void) {handle_interrupt(DFSDM1_FLT2_IRQn);} +void DFSDM1_FLT3_IRQHandler(void) {handle_interrupt(DFSDM1_FLT3_IRQn);} +void SWPMI1_IRQHandler(void) {handle_interrupt(SWPMI1_IRQn);} +void TIM15_IRQHandler(void) {handle_interrupt(TIM15_IRQn);} +void TIM16_IRQHandler(void) {handle_interrupt(TIM16_IRQn);} +void TIM17_IRQHandler(void) {handle_interrupt(TIM17_IRQn);} +void MDIOS_WKUP_IRQHandler(void) {handle_interrupt(MDIOS_WKUP_IRQn);} +void MDIOS_IRQHandler(void) {handle_interrupt(MDIOS_IRQn);} +void MDMA_IRQHandler(void) {handle_interrupt(MDMA_IRQn);} +void SDMMC2_IRQHandler(void) {handle_interrupt(SDMMC2_IRQn);} +void HSEM1_IRQHandler(void) {handle_interrupt(HSEM1_IRQn);} +void ADC3_IRQHandler(void) {handle_interrupt(ADC3_IRQn);} +void DMAMUX2_OVR_IRQHandler(void) {handle_interrupt(DMAMUX2_OVR_IRQn);} +void BDMA_Channel0_IRQHandler(void) {handle_interrupt(BDMA_Channel0_IRQn);} +void BDMA_Channel1_IRQHandler(void) {handle_interrupt(BDMA_Channel1_IRQn);} +void BDMA_Channel2_IRQHandler(void) {handle_interrupt(BDMA_Channel2_IRQn);} +void BDMA_Channel3_IRQHandler(void) {handle_interrupt(BDMA_Channel3_IRQn);} +void BDMA_Channel4_IRQHandler(void) {handle_interrupt(BDMA_Channel4_IRQn);} +void BDMA_Channel5_IRQHandler(void) {handle_interrupt(BDMA_Channel5_IRQn);} +void BDMA_Channel6_IRQHandler(void) {handle_interrupt(BDMA_Channel6_IRQn);} +void BDMA_Channel7_IRQHandler(void) {handle_interrupt(BDMA_Channel7_IRQn);} +void COMP_IRQHandler(void) {handle_interrupt(COMP_IRQn);} +void LPTIM2_IRQHandler(void) {handle_interrupt(LPTIM2_IRQn);} +void LPTIM3_IRQHandler(void) {handle_interrupt(LPTIM3_IRQn);} +void LPTIM4_IRQHandler(void) {handle_interrupt(LPTIM4_IRQn);} +void LPTIM5_IRQHandler(void) {handle_interrupt(LPTIM5_IRQn);} +void LPUART1_IRQHandler(void) {handle_interrupt(LPUART1_IRQn);} +void CRS_IRQHandler(void) {handle_interrupt(CRS_IRQn);} +void ECC_IRQHandler(void) {handle_interrupt(ECC_IRQn);} +void SAI4_IRQHandler(void) {handle_interrupt(SAI4_IRQn);} +void DTS_IRQHandler(void) {handle_interrupt(DTS_IRQn);} +void WAKEUP_PIN_IRQHandler(void) {handle_interrupt(WAKEUP_PIN_IRQn);} +void OCTOSPI2_IRQHandler(void) {handle_interrupt(OCTOSPI2_IRQn);} +void OTFDEC1_IRQHandler(void) {handle_interrupt(OTFDEC1_IRQn);} +void OTFDEC2_IRQHandler(void) {handle_interrupt(OTFDEC2_IRQn);} +void FMAC_IRQHandler(void) {handle_interrupt(FMAC_IRQn);} +void CORDIC_IRQHandler(void) {handle_interrupt(CORDIC_IRQn);} +void UART9_IRQHandler(void) {handle_interrupt(UART9_IRQn);} +void USART10_IRQHandler(void) {handle_interrupt(USART10_IRQn);} +void I2C5_EV_IRQHandler(void) {handle_interrupt(I2C5_EV_IRQn);} +void I2C5_ER_IRQHandler(void) {handle_interrupt(I2C5_ER_IRQn);} +void FDCAN3_IT0_IRQHandler(void) {handle_interrupt(FDCAN3_IT0_IRQn);} +void FDCAN3_IT1_IRQHandler(void) {handle_interrupt(FDCAN3_IT1_IRQn);} +void TIM23_IRQHandler(void) {handle_interrupt(TIM23_IRQn);} +void TIM24_IRQHandler(void) {handle_interrupt(TIM24_IRQn);} diff --git a/panda_tici/board/stm32h7/lladc.h b/panda_tici/board/stm32h7/lladc.h new file mode 100644 index 0000000..9ff2b54 --- /dev/null +++ b/panda_tici/board/stm32h7/lladc.h @@ -0,0 +1,39 @@ + +void adc_init(void) { + ADC1->CR &= ~(ADC_CR_DEEPPWD); //Reset deep-power-down mode + ADC1->CR |= ADC_CR_ADVREGEN; // Enable ADC regulator + while(!(ADC1->ISR & ADC_ISR_LDORDY)); + + ADC1->CR &= ~(ADC_CR_ADCALDIF); // Choose single-ended calibration + ADC1->CR |= ADC_CR_ADCALLIN; // Lineriality calibration + ADC1->CR |= ADC_CR_ADCAL; // Start calibrtation + while((ADC1->CR & ADC_CR_ADCAL) != 0U); + + ADC1->ISR |= ADC_ISR_ADRDY; + ADC1->CR |= ADC_CR_ADEN; + while(!(ADC1->ISR & ADC_ISR_ADRDY)); +} + +static uint16_t adc_get_raw(uint8_t channel) { + uint16_t res = 0U; + ADC1->SQR1 &= ~(ADC_SQR1_L); + ADC1->SQR1 = (uint32_t)channel << 6U; + + ADC1->SMPR1 = 0x4UL << (channel * 3UL); + ADC1->PCSEL_RES0 = (0x1UL << channel); + ADC1->CFGR2 = (63UL << ADC_CFGR2_OVSR_Pos) | (0x6U << ADC_CFGR2_OVSS_Pos) | ADC_CFGR2_ROVSE; + + ADC1->CR |= ADC_CR_ADSTART; + while (!(ADC1->ISR & ADC_ISR_EOC)); + + res = ADC1->DR; + + while (!(ADC1->ISR & ADC_ISR_EOS)); + ADC1->ISR |= ADC_ISR_EOS; + + return res; +} + +uint16_t adc_get_mV(uint8_t channel) { + return (adc_get_raw(channel) * current_board->avdd_mV) / 65535U; +} diff --git a/panda_tici/board/stm32h7/lladc_declarations.h b/panda_tici/board/stm32h7/lladc_declarations.h new file mode 100644 index 0000000..979919c --- /dev/null +++ b/panda_tici/board/stm32h7/lladc_declarations.h @@ -0,0 +1,37 @@ +#pragma once + +typedef enum { + SAMPLETIME_1_CYCLE = 0, + SAMPLETIME_2_CYCLES = 1, + SAMPLETIME_8_CYCLES = 2, + SAMPLETIME_16_CYCLES = 3, + SAMPLETIME_32_CYCLES = 4, + SAMPLETIME_64_CYCLES = 5, + SAMPLETIME_387_CYCLES = 6, + SAMPLETIME_810_CYCLES = 7 +} adc_sample_time_t; + +typedef enum { + OVERSAMPLING_1 = 0, + OVERSAMPLING_2 = 1, + OVERSAMPLING_4 = 2, + OVERSAMPLING_8 = 3, + OVERSAMPLING_16 = 4, + OVERSAMPLING_32 = 5, + OVERSAMPLING_64 = 6, + OVERSAMPLING_128 = 7, + OVERSAMPLING_256 = 8, + OVERSAMPLING_512 = 9, + OVERSAMPLING_1024 = 10 +} adc_oversampling_t; + +typedef struct { + ADC_TypeDef *adc; + uint8_t channel; + adc_sample_time_t sample_time; + adc_oversampling_t oversampling; +} adc_signal_t; + +#define ADC_CHANNEL_DEFAULT(a, c) {.adc = (a), .channel = (c), .sample_time = SAMPLETIME_32_CYCLES, .oversampling = OVERSAMPLING_64} + +#define VREFINT_CAL_ADDR ((uint16_t *)0x1FF1E860UL) diff --git a/panda_tici/board/stm32h7/llfan.h b/panda_tici/board/stm32h7/llfan.h new file mode 100644 index 0000000..06309d0 --- /dev/null +++ b/panda_tici/board/stm32h7/llfan.h @@ -0,0 +1,23 @@ +// TACH interrupt handler +static void EXTI2_IRQ_Handler(void) { + volatile unsigned int pr = EXTI->PR1 & (1U << 2); + if ((pr & (1U << 2)) != 0U) { + fan_state.tach_counter++; + } + EXTI->PR1 = (1U << 2); +} + +void llfan_init(void) { + // 12000RPM * 4 tach edges / 60 seconds + REGISTER_INTERRUPT(EXTI2_IRQn, EXTI2_IRQ_Handler, 1000U, 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->IMR1), (1U << 2)); + register_set_bits(&(EXTI->RTSR1), (1U << 2)); + register_set_bits(&(EXTI->FTSR1), (1U << 2)); + NVIC_EnableIRQ(EXTI2_IRQn); +} diff --git a/panda_tici/board/stm32h7/llfdcan.h b/panda_tici/board/stm32h7/llfdcan.h new file mode 100644 index 0000000..64a40bd --- /dev/null +++ b/panda_tici/board/stm32h7/llfdcan.h @@ -0,0 +1,227 @@ +#include "llfdcan_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] = {100U, 200U, 500U, 1000U, 1250U, 2500U, 5000U, 10000U, 20000U, 50000U}; + +static bool fdcan_request_init(FDCAN_GlobalTypeDef *FDCANx) { + bool ret = true; + // Exit from sleep mode + FDCANx->CCCR &= ~(FDCAN_CCCR_CSR); + while ((FDCANx->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA); + + // Request init + uint32_t timeout_counter = 0U; + FDCANx->CCCR |= FDCAN_CCCR_INIT; + while ((FDCANx->CCCR & FDCAN_CCCR_INIT) == 0U) { + // Delay for about 1ms + delay(10000); + timeout_counter++; + + if (timeout_counter >= CAN_INIT_TIMEOUT_MS){ + ret = false; + break; + } + } + return ret; +} + +static bool fdcan_exit_init(FDCAN_GlobalTypeDef *FDCANx) { + bool ret = true; + + FDCANx->CCCR &= ~(FDCAN_CCCR_INIT); + uint32_t timeout_counter = 0U; + while ((FDCANx->CCCR & FDCAN_CCCR_INIT) != 0U) { + // Delay for about 1ms + delay(10000); + timeout_counter++; + + if (timeout_counter >= CAN_INIT_TIMEOUT_MS) { + ret = false; + break; + } + } + return ret; +} + +bool llcan_set_speed(FDCAN_GlobalTypeDef *FDCANx, uint32_t speed, uint32_t data_speed, bool non_iso, bool loopback, bool silent) { + UNUSED(speed); + bool ret = fdcan_request_init(FDCANx); + + if (ret) { + // Enable config change + FDCANx->CCCR |= FDCAN_CCCR_CCE; + + //Reset operation mode to Normal + FDCANx->CCCR &= ~(FDCAN_CCCR_TEST); + FDCANx->TEST &= ~(FDCAN_TEST_LBCK); + FDCANx->CCCR &= ~(FDCAN_CCCR_MON); + FDCANx->CCCR &= ~(FDCAN_CCCR_ASM); + FDCANx->CCCR &= ~(FDCAN_CCCR_NISO); + + // TODO: add as a separate safety mode + // Enable ASM restricted operation(for debug or automatic bitrate switching) + //FDCANx->CCCR |= FDCAN_CCCR_ASM; + + uint8_t prescaler = BITRATE_PRESCALER; + if (speed < 2500U) { + // The only way to support speeds lower than 250Kbit/s (down to 10Kbit/s) + prescaler = BITRATE_PRESCALER * 16U; + } + + // Set the nominal bit timing values + uint32_t tq = CAN_QUANTA(speed, prescaler); + uint32_t sp = CAN_SP_NOMINAL; + uint32_t seg1 = CAN_SEG1(tq, sp); + uint32_t seg2 = CAN_SEG2(tq, sp); + uint8_t sjw = MIN(127U, seg2); + + FDCANx->NBTP = (((sjw & 0x7FUL)-1U)<DBTP = (((sjw & 0xFUL)-1U)<CCCR |= FDCAN_CCCR_NISO; + } + + // Silent loopback is known as internal loopback in the docs + if (loopback) { + FDCANx->CCCR |= FDCAN_CCCR_TEST; + FDCANx->TEST |= FDCAN_TEST_LBCK; + FDCANx->CCCR |= FDCAN_CCCR_MON; + } + // Silent is known as bus monitoring in the docs + if (silent) { + FDCANx->CCCR |= FDCAN_CCCR_MON; + } + ret = fdcan_exit_init(FDCANx); + if (!ret) { + print(CAN_NAME_FROM_CANIF(FDCANx)); print(" set_speed timed out! (2)\n"); + } + } else { + print(CAN_NAME_FROM_CANIF(FDCANx)); print(" set_speed timed out! (1)\n"); + } + return ret; +} + +void llcan_irq_disable(const FDCAN_GlobalTypeDef *FDCANx) { + if (FDCANx == FDCAN1) { + NVIC_DisableIRQ(FDCAN1_IT0_IRQn); + NVIC_DisableIRQ(FDCAN1_IT1_IRQn); + } else if (FDCANx == FDCAN2) { + NVIC_DisableIRQ(FDCAN2_IT0_IRQn); + NVIC_DisableIRQ(FDCAN2_IT1_IRQn); + } else if (FDCANx == FDCAN3) { + NVIC_DisableIRQ(FDCAN3_IT0_IRQn); + NVIC_DisableIRQ(FDCAN3_IT1_IRQn); + } else { + } +} + +void llcan_irq_enable(const FDCAN_GlobalTypeDef *FDCANx) { + if (FDCANx == FDCAN1) { + NVIC_EnableIRQ(FDCAN1_IT0_IRQn); + NVIC_EnableIRQ(FDCAN1_IT1_IRQn); + } else if (FDCANx == FDCAN2) { + NVIC_EnableIRQ(FDCAN2_IT0_IRQn); + NVIC_EnableIRQ(FDCAN2_IT1_IRQn); + } else if (FDCANx == FDCAN3) { + NVIC_EnableIRQ(FDCAN3_IT0_IRQn); + NVIC_EnableIRQ(FDCAN3_IT1_IRQn); + } else { + } +} + +bool llcan_init(FDCAN_GlobalTypeDef *FDCANx) { + uint32_t can_number = CAN_NUM_FROM_CANIF(FDCANx); + bool ret = fdcan_request_init(FDCANx); + + if (ret) { + // Enable config change + FDCANx->CCCR |= FDCAN_CCCR_CCE; + // Enable automatic retransmission + FDCANx->CCCR &= ~(FDCAN_CCCR_DAR); + // Enable transmission pause feature + FDCANx->CCCR |= FDCAN_CCCR_TXP; + // Disable protocol exception handling + FDCANx->CCCR |= FDCAN_CCCR_PXHD; + // FD with BRS + FDCANx->CCCR |= (FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE); + + // Set TX mode to FIFO + FDCANx->TXBC &= ~(FDCAN_TXBC_TFQM); + // Configure TX element data size + FDCANx->TXESC |= 0x7U << FDCAN_TXESC_TBDS_Pos; // 64 bytes + //Configure RX FIFO0 element data size + FDCANx->RXESC |= 0x7U << FDCAN_RXESC_F0DS_Pos; + // Disable filtering, accept all valid frames received + FDCANx->XIDFC &= ~(FDCAN_XIDFC_LSE); // No extended filters + FDCANx->SIDFC &= ~(FDCAN_SIDFC_LSS); // No standard filters + FDCANx->GFC &= ~(FDCAN_GFC_RRFE); // Accept extended remote frames + FDCANx->GFC &= ~(FDCAN_GFC_RRFS); // Accept standard remote frames + FDCANx->GFC &= ~(FDCAN_GFC_ANFE); // Accept extended frames to FIFO 0 + FDCANx->GFC &= ~(FDCAN_GFC_ANFS); // Accept standard frames to FIFO 0 + + uint32_t RxFIFO0SA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET); + uint32_t TxFIFOSA = RxFIFO0SA + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_SIZE); + + // RX FIFO 0 + FDCANx->RXF0C |= (FDCAN_RX_FIFO_0_OFFSET + (can_number * FDCAN_OFFSET_W)) << FDCAN_RXF0C_F0SA_Pos; + FDCANx->RXF0C |= FDCAN_RX_FIFO_0_EL_CNT << FDCAN_RXF0C_F0S_Pos; + // RX FIFO 0 switch to non-blocking (overwrite) mode + FDCANx->RXF0C |= FDCAN_RXF0C_F0OM; + + // TX FIFO (mode set earlier) + FDCANx->TXBC |= (FDCAN_TX_FIFO_OFFSET + (can_number * FDCAN_OFFSET_W)) << FDCAN_TXBC_TBSA_Pos; + FDCANx->TXBC |= FDCAN_TX_FIFO_EL_CNT << FDCAN_TXBC_TFQS_Pos; + + // Flush allocated RAM + uint32_t EndAddress = TxFIFOSA + (FDCAN_TX_FIFO_EL_CNT * FDCAN_TX_FIFO_EL_SIZE); + for (uint32_t RAMcounter = RxFIFO0SA; RAMcounter < EndAddress; RAMcounter += 4U) { + *(uint32_t *)(RAMcounter) = 0x00000000; + } + + // Enable both interrupts for each module + FDCANx->ILE = (FDCAN_ILE_EINT0 | FDCAN_ILE_EINT1); + + FDCANx->IE &= 0x0U; // Reset all interrupts + // Messages for INT0 + FDCANx->IE |= FDCAN_IE_RF0NE; // Rx FIFO 0 new message + FDCANx->IE |= FDCAN_IE_PEDE | FDCAN_IE_PEAE | FDCAN_IE_BOE | FDCAN_IE_EPE | FDCAN_IE_RF0LE; + + // Messages for INT1 (Only TFE works??) + FDCANx->ILS |= FDCAN_ILS_TFEL; + FDCANx->IE |= FDCAN_IE_TFEE; // Tx FIFO empty + + ret = fdcan_exit_init(FDCANx); + if(!ret) { + print(CAN_NAME_FROM_CANIF(FDCANx)); print(" llcan_init timed out (2)!\n"); + } + + llcan_irq_enable(FDCANx); + + } else { + print(CAN_NAME_FROM_CANIF(FDCANx)); print(" llcan_init timed out (1)!\n"); + } + return ret; +} + +void llcan_clear_send(FDCAN_GlobalTypeDef *FDCANx) { + // from datasheet: "Transmit cancellation is not intended for Tx FIFO operation." + // so we need to clear pending transmission manually by resetting FDCAN core + FDCANx->IR |= 0x3FCFFFFFU; // clear all interrupts + bool ret = llcan_init(FDCANx); + UNUSED(ret); +} diff --git a/panda_tici/board/stm32h7/llfdcan_declarations.h b/panda_tici/board/stm32h7/llfdcan_declarations.h new file mode 100644 index 0000000..7938490 --- /dev/null +++ b/panda_tici/board/stm32h7/llfdcan_declarations.h @@ -0,0 +1,53 @@ +#pragma once + +// SAE J2284-4 document specifies a bus-line network running at 2 Mbit/s +// SAE J2284-5 document specifies a point-to-point communication running at 5 Mbit/s + +#define CAN_PCLK 80000U // KHz, sourced from PLL1Q +#define BITRATE_PRESCALER 2U // Valid from 250Kbps to 5Mbps with 80Mhz clock +#define CAN_SP_NOMINAL 80U // 80% for both SAE J2284-4 and SAE J2284-5 +#define CAN_SP_DATA_2M 80U // 80% for SAE J2284-4 +#define CAN_SP_DATA_5M 75U // 75% for SAE J2284-5 +#define CAN_QUANTA(speed, prescaler) (CAN_PCLK / ((speed) / 10U * (prescaler))) +#define CAN_SEG1(tq, sp) (((tq) * (sp) / 100U)- 1U) +#define CAN_SEG2(tq, sp) ((tq) * (100U - (sp)) / 100U) + +// FDCAN core settings +#define FDCAN_START_ADDRESS 0x4000AC00UL +#define FDCAN_OFFSET 3384UL // bytes for each FDCAN module, equally +#define FDCAN_OFFSET_W 846UL // words for each FDCAN module, equally + +// FDCAN_RX_FIFO_0_EL_CNT + FDCAN_TX_FIFO_EL_CNT can't exceed 47 elements (47 * 72 bytes = 3,384 bytes) per FDCAN module + +// RX FIFO 0 +#define FDCAN_RX_FIFO_0_EL_CNT 46UL +#define FDCAN_RX_FIFO_0_HEAD_SIZE 8UL // bytes +#define FDCAN_RX_FIFO_0_DATA_SIZE 64UL // bytes +#define FDCAN_RX_FIFO_0_EL_SIZE (FDCAN_RX_FIFO_0_HEAD_SIZE + FDCAN_RX_FIFO_0_DATA_SIZE) +#define FDCAN_RX_FIFO_0_EL_W_SIZE (FDCAN_RX_FIFO_0_EL_SIZE / 4UL) +#define FDCAN_RX_FIFO_0_OFFSET 0UL + +// TX FIFO +#define FDCAN_TX_FIFO_EL_CNT 1UL +#define FDCAN_TX_FIFO_HEAD_SIZE 8UL // bytes +#define FDCAN_TX_FIFO_DATA_SIZE 64UL // bytes +#define FDCAN_TX_FIFO_EL_SIZE (FDCAN_TX_FIFO_HEAD_SIZE + FDCAN_TX_FIFO_DATA_SIZE) +#define FDCAN_TX_FIFO_OFFSET (FDCAN_RX_FIFO_0_OFFSET + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_W_SIZE)) + +#define CAN_NAME_FROM_CANIF(CAN_DEV) (((CAN_DEV)==FDCAN1) ? "FDCAN1" : (((CAN_DEV) == FDCAN2) ? "FDCAN2" : "FDCAN3")) +#define CAN_NUM_FROM_CANIF(CAN_DEV) (((CAN_DEV)==FDCAN1) ? 0UL : (((CAN_DEV) == FDCAN2) ? 1UL : 2UL)) + + +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 10 +extern const uint32_t data_speeds[DATA_SPEEDS_ARRAY_SIZE]; + +bool llcan_set_speed(FDCAN_GlobalTypeDef *FDCANx, uint32_t speed, uint32_t data_speed, bool non_iso, bool loopback, bool silent); +void llcan_irq_disable(const FDCAN_GlobalTypeDef *FDCANx); +void llcan_irq_enable(const FDCAN_GlobalTypeDef *FDCANx); +bool llcan_init(FDCAN_GlobalTypeDef *FDCANx); +void llcan_clear_send(FDCAN_GlobalTypeDef *FDCANx); diff --git a/panda_tici/board/stm32h7/llflash.h b/panda_tici/board/stm32h7/llflash.h new file mode 100644 index 0000000..b95011a --- /dev/null +++ b/panda_tici/board/stm32h7/llflash.h @@ -0,0 +1,33 @@ +bool flash_is_locked(void) { + return (FLASH->CR1 & FLASH_CR_LOCK); +} + +void flash_unlock(void) { + FLASH->KEYR1 = 0x45670123; + FLASH->KEYR1 = 0xCDEF89AB; +} + +bool flash_erase_sector(uint8_t sector, bool unlocked) { + // don't erase the bootloader(sector 0) + if (sector != 0 && sector < 8 && unlocked) { + FLASH->CR1 = (sector << 8) | FLASH_CR_SER; + FLASH->CR1 |= FLASH_CR_START; + while (FLASH->SR1 & FLASH_SR_QW); + return true; + } + return false; +} + +void flash_write_word(void *prog_ptr, uint32_t data) { + uint32_t *pp = prog_ptr; + FLASH->CR1 |= FLASH_CR_PG; + *pp = data; + while (FLASH->SR1 & FLASH_SR_QW); +} + +void flush_write_buffer(void) { + if (FLASH->SR1 & FLASH_SR_WBNE) { + FLASH->CR1 |= FLASH_CR_FW; + while (FLASH->SR1 & FLASH_CR_FW); + } +} diff --git a/panda_tici/board/stm32h7/lli2c.h b/panda_tici/board/stm32h7/lli2c.h new file mode 100644 index 0000000..5d79beb --- /dev/null +++ b/panda_tici/board/stm32h7/lli2c.h @@ -0,0 +1,167 @@ +// TODO: this driver relies heavily on polling, +// if we want it to be more async, we should use interrupts + +#define I2C_RETRY_COUNT 10U +#define I2C_TIMEOUT_US 100000U + +bool i2c_status_wait(const volatile uint32_t *reg, uint32_t mask, uint32_t val) { + uint32_t start_time = microsecond_timer_get(); + while(((*reg & mask) != val) && (get_ts_elapsed(microsecond_timer_get(), start_time) < I2C_TIMEOUT_US)); + return ((*reg & mask) == val); +} + +void i2c_reset(I2C_TypeDef *I2C) { + // peripheral reset + register_clear_bits(&I2C->CR1, I2C_CR1_PE); + while ((I2C->CR1 & I2C_CR1_PE) != 0U); + register_set_bits(&I2C->CR1, I2C_CR1_PE); +} + +bool i2c_write_reg(I2C_TypeDef *I2C, uint8_t addr, uint8_t reg, uint8_t value) { + bool ret = false; + + // Setup transfer and send START + addr + for (uint32_t i = 0U; i < I2C_RETRY_COUNT; i++) { + register_clear_bits(&I2C->CR2, I2C_CR2_ADD10); + I2C->CR2 = ((uint32_t)addr << 1U) & I2C_CR2_SADD_Msk; + register_clear_bits(&I2C->CR2, I2C_CR2_RD_WRN); + register_set_bits(&I2C->CR2, I2C_CR2_AUTOEND); + I2C->CR2 |= 2UL << I2C_CR2_NBYTES_Pos; + + I2C->CR2 |= I2C_CR2_START; + if(!i2c_status_wait(&I2C->CR2, I2C_CR2_START, 0U)) { + continue; + } + + // check if we lost arbitration + if ((I2C->ISR & I2C_ISR_ARLO) != 0U) { + register_set_bits(&I2C->ICR, I2C_ICR_ARLOCF); + } else { + ret = true; + break; + } + } + + if (!ret) { + goto end; + } + + // Send data + ret = i2c_status_wait(&I2C->ISR, I2C_ISR_TXIS, I2C_ISR_TXIS); + if(!ret) { + goto end; + } + I2C->TXDR = reg; + + ret = i2c_status_wait(&I2C->ISR, I2C_ISR_TXIS, I2C_ISR_TXIS); + if(!ret) { + goto end; + } + I2C->TXDR = value; + +end: + return ret; +} + +bool i2c_read_reg(I2C_TypeDef *I2C, uint8_t addr, uint8_t reg, uint8_t *value) { + bool ret = false; + + // Setup transfer and send START + addr + for (uint32_t i = 0U; i < I2C_RETRY_COUNT; i++) { + register_clear_bits(&I2C->CR2, I2C_CR2_ADD10); + I2C->CR2 = ((uint32_t)addr << 1U) & I2C_CR2_SADD_Msk; + register_clear_bits(&I2C->CR2, I2C_CR2_RD_WRN); + register_clear_bits(&I2C->CR2, I2C_CR2_AUTOEND); + I2C->CR2 |= 1UL << I2C_CR2_NBYTES_Pos; + + I2C->CR2 |= I2C_CR2_START; + if(!i2c_status_wait(&I2C->CR2, I2C_CR2_START, 0U)) { + continue; + } + + // check if we lost arbitration + if ((I2C->ISR & I2C_ISR_ARLO) != 0U) { + register_set_bits(&I2C->ICR, I2C_ICR_ARLOCF); + } else { + ret = true; + break; + } + } + + if (!ret) { + goto end; + } + + // Send data + ret = i2c_status_wait(&I2C->ISR, I2C_ISR_TXIS, I2C_ISR_TXIS); + if(!ret) { + goto end; + } + I2C->TXDR = reg; + + // Restart + I2C->CR2 = (((addr << 1) | 0x1U) & I2C_CR2_SADD_Msk) | (1UL << I2C_CR2_NBYTES_Pos) | I2C_CR2_RD_WRN | I2C_CR2_START; + ret = i2c_status_wait(&I2C->CR2, I2C_CR2_START, 0U); + if(!ret) { + goto end; + } + + // check if we lost arbitration + if ((I2C->ISR & I2C_ISR_ARLO) != 0U) { + register_set_bits(&I2C->ICR, I2C_ICR_ARLOCF); + ret = false; + goto end; + } + + // Read data + ret = i2c_status_wait(&I2C->ISR, I2C_ISR_RXNE, I2C_ISR_RXNE); + if(!ret) { + goto end; + } + *value = I2C->RXDR; + + // Stop + I2C->CR2 |= I2C_CR2_STOP; + +end: + + if (!ret) { + i2c_reset(I2C); + } + + return ret; +} + +bool i2c_set_reg_bits(I2C_TypeDef *I2C, uint8_t address, uint8_t regis, uint8_t bits) { + uint8_t value; + bool ret = i2c_read_reg(I2C, address, regis, &value); + if(ret) { + ret = i2c_write_reg(I2C, address, regis, value | bits); + } + return ret; +} + +bool i2c_clear_reg_bits(I2C_TypeDef *I2C, uint8_t address, uint8_t regis, uint8_t bits) { + uint8_t value; + bool ret = i2c_read_reg(I2C, address, regis, &value); + if (ret) { + ret = i2c_write_reg(I2C, address, regis, value & (uint8_t) (~bits)); + } + return ret; +} + +bool i2c_set_reg_mask(I2C_TypeDef *I2C, uint8_t address, uint8_t regis, uint8_t value, uint8_t mask) { + uint8_t old_value; + bool ret = i2c_read_reg(I2C, address, regis, &old_value); + if(ret) { + ret = i2c_write_reg(I2C, address, regis, (old_value & (uint8_t) (~mask)) | (value & mask)); + } + return ret; +} + +void i2c_init(I2C_TypeDef *I2C) { + // 100kHz clock speed + I2C->TIMINGR = 0x107075B0; + + i2c_reset(I2C); +} diff --git a/panda_tici/board/stm32h7/llspi.h b/panda_tici/board/stm32h7/llspi.h new file mode 100644 index 0000000..a5dca37 --- /dev/null +++ b/panda_tici/board/stm32h7/llspi.h @@ -0,0 +1,109 @@ +#if defined(ENABLE_SPI) || defined(BOOTSTUB) +// master -> panda DMA start +void llspi_mosi_dma(uint8_t *addr, int len) { + // disable DMA + SPI + register_clear_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); + DMA2_Stream2->CR &= ~DMA_SxCR_EN; + register_clear_bits(&(SPI4->CR1), SPI_CR1_SPE); + + // drain the bus + while ((SPI4->SR & SPI_SR_RXP) != 0U) { + volatile uint8_t dat = SPI4->RXDR; + (void)dat; + } + + // clear all pending + SPI4->IFCR |= (0x1FFU << 3U); + register_set(&(SPI4->IER), 0, 0x3FFU); + + // setup destination and length + register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU); + DMA2_Stream2->NDTR = len; + + // enable DMA + SPI + DMA2_Stream2->CR |= DMA_SxCR_EN; + register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); + register_set_bits(&(SPI4->CR1), SPI_CR1_SPE); +} + +// panda -> master DMA start +void llspi_miso_dma(uint8_t *addr, int len) { + // disable DMA + SPI + DMA2_Stream3->CR &= ~DMA_SxCR_EN; + register_clear_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); + register_clear_bits(&(SPI4->CR1), SPI_CR1_SPE); + + // setup source and length + register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU); + DMA2_Stream3->NDTR = len; + + // clear under-run while we were reading + SPI4->IFCR |= (0x1FFU << 3U); + + // setup interrupt on TXC + register_set(&(SPI4->IER), (1U << SPI_IER_EOTIE_Pos), 0x3FFU); + + // enable DMA + SPI + register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); + DMA2_Stream3->CR |= DMA_SxCR_EN; + register_set_bits(&(SPI4->CR1), SPI_CR1_SPE); +} + +static bool spi_tx_dma_done = false; +// master -> panda DMA finished +static void DMA2_Stream2_IRQ_Handler(void) { + // Clear interrupt flag + DMA2->LIFCR = DMA_LIFCR_CTCIF2; + + spi_rx_done(); +} + +// panda -> master DMA finished +static void DMA2_Stream3_IRQ_Handler(void) { + ENTER_CRITICAL(); + + DMA2->LIFCR = DMA_LIFCR_CTCIF3; + spi_tx_dma_done = true; + + EXIT_CRITICAL(); +} + +// panda TX finished +static void SPI4_IRQ_Handler(void) { + // clear flag + SPI4->IFCR |= (0x1FFU << 3U); + + if (spi_tx_dma_done && ((SPI4->SR & SPI_SR_TXC) != 0U)) { + spi_tx_dma_done = false; + spi_tx_done(false); + } +} + + +void llspi_init(void) { + REGISTER_INTERRUPT(SPI4_IRQn, SPI4_IRQ_Handler, (SPI_IRQ_RATE * 2U), FAULT_INTERRUPT_RATE_SPI) + REGISTER_INTERRUPT(DMA2_Stream2_IRQn, DMA2_Stream2_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA) + REGISTER_INTERRUPT(DMA2_Stream3_IRQn, DMA2_Stream3_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA) + + // Setup MOSI DMA + register_set(&(DMAMUX1_Channel10->CCR), 83U, 0xFFFFFFFFU); + register_set(&(DMA2_Stream2->CR), (DMA_SxCR_MINC | DMA_SxCR_TCIE), 0x1E077EFEU); + register_set(&(DMA2_Stream2->PAR), (uint32_t)&(SPI4->RXDR), 0xFFFFFFFFU); + + // Setup MISO DMA, memory -> peripheral + register_set(&(DMAMUX1_Channel11->CCR), 84U, 0xFFFFFFFFU); + register_set(&(DMA2_Stream3->CR), (DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE), 0x1E077EFEU); + register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI4->TXDR), 0xFFFFFFFFU); + + // Enable SPI + register_set(&(SPI4->IER), 0, 0x3FFU); + register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); + register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging + register_set(&(SPI4->CR1), SPI_CR1_SPE, 0xFFFFU); + register_set(&(SPI4->CR2), 0, 0xFFFFU); + + NVIC_EnableIRQ(DMA2_Stream2_IRQn); + NVIC_EnableIRQ(DMA2_Stream3_IRQn); + NVIC_EnableIRQ(SPI4_IRQn); +} +#endif diff --git a/panda_tici/board/stm32h7/lluart.h b/panda_tici/board/stm32h7/lluart.h new file mode 100644 index 0000000..742549b --- /dev/null +++ b/panda_tici/board/stm32h7/lluart.h @@ -0,0 +1,106 @@ +static void uart_rx_ring(uart_ring *q){ + // Do not read out directly if DMA enabled + ENTER_CRITICAL(); + + // Read out RX buffer + uint8_t c = q->uart->RDR; // This read after reading SR clears a bunch of interrupts + + uint16_t next_w_ptr = (q->w_ptr_rx + 1U) % q->rx_fifo_size; + + if ((next_w_ptr == q->r_ptr_rx) && q->overwrite) { + // overwrite mode: drop oldest byte + q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size; + } + + // Do not overwrite buffer data + if (next_w_ptr != q->r_ptr_rx) { + q->elems_rx[q->w_ptr_rx] = c; + q->w_ptr_rx = next_w_ptr; + if (q->callback != NULL) { + q->callback(q); + } + } + + EXIT_CRITICAL(); +} + +void uart_tx_ring(uart_ring *q){ + ENTER_CRITICAL(); + // Send out next byte of TX buffer + if (q->w_ptr_tx != q->r_ptr_tx) { + // Only send if transmit register is empty (aka last byte has been sent) + if ((q->uart->ISR & USART_ISR_TXE_TXFNF) != 0U) { + q->uart->TDR = q->elems_tx[q->r_ptr_tx]; // This clears TXE + q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size; + } + + // Enable TXE interrupt if there is still data to be sent + if(q->r_ptr_tx != q->w_ptr_tx){ + q->uart->CR1 |= USART_CR1_TXEIE; + } else { + q->uart->CR1 &= ~USART_CR1_TXEIE; + } + } + EXIT_CRITICAL(); +} + +void uart_set_baud(USART_TypeDef *u, unsigned int baud) { + // UART7 is connected to APB1 at 60MHz + u->BRR = 60000000U / baud; +} + +// This read after reading ISR clears all error interrupts. We don't want compiler warnings, nor optimizations +#define UART_READ_RDR(uart) volatile uint8_t t = (uart)->RDR; UNUSED(t); + +static void uart_interrupt_handler(uart_ring *q) { + ENTER_CRITICAL(); + + // Read UART status. This is also the first step necessary in clearing most interrupts + uint32_t status = q->uart->ISR; + + // If RXFNE is set, perform a read. This clears RXFNE, ORE, IDLE, NF and FE + if((status & USART_ISR_RXNE_RXFNE) != 0U){ + uart_rx_ring(q); + } + + // Detect errors and clear them + uint32_t err = (status & USART_ISR_ORE) | (status & USART_ISR_NE) | (status & USART_ISR_FE) | (status & USART_ISR_PE); + if(err != 0U){ + #ifdef DEBUG_UART + print("Encountered UART error: "); puth(err); print("\n"); + #endif + UART_READ_RDR(q->uart) + } + + if ((err & USART_ISR_ORE) != 0U) { + q->uart->ICR |= USART_ICR_ORECF; + } else if ((err & USART_ISR_NE) != 0U) { + q->uart->ICR |= USART_ICR_NECF; + } else if ((err & USART_ISR_FE) != 0U) { + q->uart->ICR |= USART_ICR_FECF; + } else if ((err & USART_ISR_PE) != 0U) { + q->uart->ICR |= USART_ICR_PECF; + } else {} + + // Send if necessary + uart_tx_ring(q); + + EXIT_CRITICAL(); +} + +static void UART7_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_som_debug); } + +void uart_init(uart_ring *q, int baud) { + if (q->uart == UART7) { + REGISTER_INTERRUPT(UART7_IRQn, UART7_IRQ_Handler, 150000U, FAULT_INTERRUPT_RATE_UART_7) + + uart_set_baud(q->uart, baud); + q->uart->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; + + // Enable interrupt on RX not empty + q->uart->CR1 |= USART_CR1_RXNEIE; + + // Enable UART interrupts + NVIC_EnableIRQ(UART7_IRQn); + } +} diff --git a/panda_tici/board/stm32h7/llusb.h b/panda_tici/board/stm32h7/llusb.h new file mode 100644 index 0000000..f1bcf16 --- /dev/null +++ b/panda_tici/board/stm32h7/llusb.h @@ -0,0 +1,79 @@ +#include "llusb_declarations.h" + +USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS; + +static void OTG_HS_IRQ_Handler(void) { + NVIC_DisableIRQ(OTG_HS_IRQn); + usb_irqhandler(); + NVIC_EnableIRQ(OTG_HS_IRQn); +} + +void usb_init(void) { + REGISTER_INTERRUPT(OTG_HS_IRQn, OTG_HS_IRQ_Handler, 1500000U, FAULT_INTERRUPT_RATE_USB) // TODO: Find out a better rate limit for USB. Now it's the 1.5MB/s rate + + // Disable global interrupt + USBx->GAHBCFG &= ~(USB_OTG_GAHBCFG_GINT); + // Select FS Embedded PHY + USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; + // Force device mode + USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD); + USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + delay(250000); // Wait for about 25ms (explicitly stated in H7 ref manual) + // Wait for AHB master IDLE state. + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U); + // Core Soft Reset + USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); + // Activate the USB Transceiver + USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN; + + for (uint8_t i = 0U; i < 15U; i++) { + USBx->DIEPTXF[i] = 0U; + } + + // VBUS Sensing setup + USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS; + // Deactivate VBUS Sensing B + USBx->GCCFG &= ~(USB_OTG_GCCFG_VBDEN); + // B-peripheral session valid override enable + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; + // Restart the Phy Clock + USBx_PCGCCTL = 0U; + // Device mode configuration + USBx_DEVICE->DCFG |= DCFG_FRAME_INTERVAL_80; + USBx_DEVICE->DCFG |= USB_OTG_SPEED_FULL | USB_OTG_DCFG_NZLSOHSK; + + // Flush FIFOs + USBx->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (0x10U << 6)); + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); + + USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); + + // Clear all pending Device Interrupts + USBx_DEVICE->DIEPMSK = 0U; + USBx_DEVICE->DOEPMSK = 0U; + USBx_DEVICE->DAINTMSK = 0U; + USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM); + + // Disable all interrupts. + USBx->GINTMSK = 0U; + // Clear any pending interrupts + USBx->GINTSTS = 0xBFFFFFFFU; + // Enable interrupts matching to the Device mode ONLY + USBx->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_OTGINT | + USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_GONAKEFFM | USB_OTG_GINTMSK_GINAKEFFM | + USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT | + USB_OTG_GINTMSK_CIDSCHGM | USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_MMISM; + + // Set USB Turnaround time + USBx->GUSBCFG |= ((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT); + // Enables the controller's Global Int in the AHB Config reg + USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + // Soft disconnect disable: + USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_SDIS); + + // enable the IRQ + NVIC_EnableIRQ(OTG_HS_IRQn); +} diff --git a/panda_tici/board/stm32h7/llusb_declarations.h b/panda_tici/board/stm32h7/llusb_declarations.h new file mode 100644 index 0000000..a11d3f5 --- /dev/null +++ b/panda_tici/board/stm32h7/llusb_declarations.h @@ -0,0 +1,16 @@ +#pragma once + +extern USB_OTG_GlobalTypeDef *USBx; + +#define USBx_DEVICE ((USB_OTG_DeviceTypeDef *)((uint32_t)USBx + USB_OTG_DEVICE_BASE)) +#define USBx_INEP(i) ((USB_OTG_INEndpointTypeDef *)((uint32_t)USBx + USB_OTG_IN_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE))) +#define USBx_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)((uint32_t)USBx + USB_OTG_OUT_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE))) +#define USBx_DFIFO(i) *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_FIFO_BASE + ((i) * USB_OTG_FIFO_SIZE)) +#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_PCGCCTL_BASE) + +#define USBD_FS_TRDT_VALUE 6UL +#define USB_OTG_SPEED_FULL 3U +#define DCFG_FRAME_INTERVAL_80 0U + +void usb_irqhandler(void); +void usb_init(void); diff --git a/panda_tici/board/stm32h7/peripherals.h b/panda_tici/board/stm32h7/peripherals.h new file mode 100644 index 0000000..3e9256d --- /dev/null +++ b/panda_tici/board/stm32h7/peripherals.h @@ -0,0 +1,137 @@ +#ifdef BOOTSTUB +void gpio_usb_init(void) { +#else +static void gpio_usb_init(void) { +#endif + // A11,A12: USB + set_gpio_alternate(GPIOA, 11, GPIO_AF10_OTG1_FS); + set_gpio_alternate(GPIOA, 12, GPIO_AF10_OTG1_FS); + GPIOA->OSPEEDR = GPIO_OSPEEDR_OSPEED11 | GPIO_OSPEEDR_OSPEED12; +} + +#ifdef ENABLE_SPI +void gpio_spi_init(void) { + set_gpio_alternate(GPIOE, 11, GPIO_AF5_SPI4); + set_gpio_alternate(GPIOE, 12, GPIO_AF5_SPI4); + set_gpio_alternate(GPIOE, 13, GPIO_AF5_SPI4); + set_gpio_alternate(GPIOE, 14, GPIO_AF5_SPI4); + register_set_bits(&(GPIOE->OSPEEDR), GPIO_OSPEEDR_OSPEED11 | GPIO_OSPEEDR_OSPEED12 | GPIO_OSPEEDR_OSPEED13 | GPIO_OSPEEDR_OSPEED14); +} +#endif + +#ifdef BOOTSTUB +void gpio_usart2_init(void) { + // A2,A3: USART 2 for debugging + set_gpio_alternate(GPIOA, 2, GPIO_AF7_USART2); + set_gpio_alternate(GPIOA, 3, GPIO_AF7_USART2); +} +#endif + +void gpio_uart7_init(void) { + // E7,E8: UART 7 for debugging + set_gpio_alternate(GPIOE, 7, GPIO_AF7_UART7); + set_gpio_alternate(GPIOE, 8, GPIO_AF7_UART7); +} + +// Common GPIO initialization +void common_init_gpio(void) { + //F11: VOLT_S + set_gpio_pullup(GPIOF, 11, PULL_NONE); + set_gpio_mode(GPIOF, 11, MODE_ANALOG); + + gpio_usb_init(); + + // B8,B9: FDCAN1 + set_gpio_pullup(GPIOB, 8, PULL_NONE); + set_gpio_alternate(GPIOB, 8, GPIO_AF9_FDCAN1); + + set_gpio_pullup(GPIOB, 9, PULL_NONE); + set_gpio_alternate(GPIOB, 9, GPIO_AF9_FDCAN1); + + // B5,B6 (mplex to B12,B13): FDCAN2 + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_pullup(GPIOB, 13, PULL_NONE); + + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_alternate(GPIOB, 5, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_FDCAN2); + + // G9,G10: FDCAN3 + set_gpio_pullup(GPIOG, 9, PULL_NONE); + set_gpio_alternate(GPIOG, 9, GPIO_AF2_FDCAN3); + + set_gpio_pullup(GPIOG, 10, PULL_NONE); + set_gpio_alternate(GPIOG, 10, GPIO_AF2_FDCAN3); +} + +#ifdef BOOTSTUB +void flasher_peripherals_init(void) { + RCC->AHB1ENR |= RCC_AHB1ENR_USB1OTGHSEN; + + // SPI + DMA + RCC->APB2ENR |= RCC_APB2ENR_SPI4EN; + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; + + // LED PWM + RCC->APB1LENR |= RCC_APB1LENR_TIM3EN; +} +#endif + +// Peripheral initialization +void peripherals_init(void) { + // enable GPIO(A,B,C,D,E,F,G,H) + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOAEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOBEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOCEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIODEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOEEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOFEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOGEN; + + // Enable CPU access to SRAMs for DMA + RCC->AHB2ENR |= RCC_AHB2ENR_SRAM1EN | RCC_AHB2ENR_SRAM2EN; + + // Supplemental + RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; // DAC DMA + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // SPI DMA + RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; + RCC->AHB4ENR |= RCC_AHB4ENR_BDMAEN; // Audio DMA + + // Connectivity + RCC->APB2ENR |= RCC_APB2ENR_SPI4EN; // SPI + RCC->APB1LENR |= RCC_APB1LENR_I2C5EN; // codec I2C + RCC->AHB1ENR |= RCC_AHB1ENR_USB1OTGHSEN; // USB + RCC->AHB1LPENR |= RCC_AHB1LPENR_USB1OTGHSLPEN; // USB LP needed for CSleep state(__WFI()) + RCC->AHB1LPENR &= ~(RCC_AHB1LPENR_USB1OTGHSULPILPEN); // disable USB ULPI + RCC->APB1LENR |= RCC_APB1LENR_UART7EN; // SOM uart + RCC->APB1HENR |= RCC_APB1HENR_FDCANEN; // FDCAN core enable + + // Analog + RCC->AHB1ENR |= RCC_AHB1ENR_ADC12EN; // Enable ADC12 clocks + RCC->APB1LENR |= RCC_APB1LENR_DAC12EN; // DAC + + // Audio + RCC->APB2ENR |= RCC_APB2ENR_DFSDM1EN; // D/S demodulator for mic + RCC->APB4ENR |= RCC_APB4ENR_SAI4EN; // SAI4 + + // Timers + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // clock source timer + RCC->APB1LENR |= RCC_APB1LENR_TIM2EN; // main counter + RCC->APB1LENR |= RCC_APB1LENR_TIM3EN; // fan + led pwm + RCC->APB1LENR |= RCC_APB1LENR_TIM6EN; // interrupt timer + RCC->APB1LENR |= RCC_APB1LENR_TIM7EN; // DMA trigger timer + RCC->APB2ENR |= RCC_APB2ENR_TIM8EN; // tick timer + RCC->APB1LENR |= RCC_APB1LENR_TIM12EN; // slow loop + RCC->APB1LENR |= RCC_APB1LENR_TIM5EN; // sound trigger timer + +#ifdef PANDA_JUNGLE + RCC->AHB3ENR |= RCC_AHB3ENR_SDMMC1EN; // SDMMC + RCC->AHB4ENR |= RCC_AHB4ENR_ADC3EN; // Enable ADC3 clocks +#endif +} + +void enable_interrupt_timer(void) { + register_set_bits(&(RCC->APB1LENR), RCC_APB1LENR_TIM6EN); // Enable interrupt timer peripheral +} diff --git a/panda_tici/board/stm32h7/sound.h b/panda_tici/board/stm32h7/sound.h new file mode 100644 index 0000000..467c356 --- /dev/null +++ b/panda_tici/board/stm32h7/sound.h @@ -0,0 +1,183 @@ +#define SOUND_RX_BUF_SIZE 1000U +#define SOUND_TX_BUF_SIZE (SOUND_RX_BUF_SIZE/2U) +#define MIC_RX_BUF_SIZE 512U +#define MIC_TX_BUF_SIZE (MIC_RX_BUF_SIZE * 2U) +__attribute__((section(".sram4"))) static uint16_t sound_rx_buf[2][SOUND_RX_BUF_SIZE]; +__attribute__((section(".sram4"))) static uint16_t sound_tx_buf[2][SOUND_TX_BUF_SIZE]; +__attribute__((section(".sram4"))) static uint32_t mic_rx_buf[2][MIC_RX_BUF_SIZE]; + +#define SOUND_IDLE_TIMEOUT 4U +static uint8_t sound_idle_count; +static uint8_t mic_idle_count; + +void sound_tick(void) { + if (sound_idle_count > 0U) { + sound_idle_count--; + if (sound_idle_count == 0U) { + current_board->set_amp_enabled(false); + register_clear_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + } + } + + if (mic_idle_count > 0U) { + mic_idle_count--; + if (mic_idle_count == 0U) { + register_clear_bits(&DFSDM1_Channel0->CHCFGR1, DFSDM_CHCFGR1_DFSDMEN); + } + } +} + +// Recording processing +static void DMA1_Stream0_IRQ_Handler(void) { + __attribute__((section(".sram4"))) static uint16_t tx_buf[MIC_TX_BUF_SIZE]; + + DMA1->LIFCR |= 0x7D; // clear flags + + // process samples + uint8_t buf_idx = (((DMA1_Stream0->CR & DMA_SxCR_CT) >> DMA_SxCR_CT_Pos) == 1U) ? 0U : 1U; + for (uint16_t i=0U; i < MIC_RX_BUF_SIZE; i++) { + tx_buf[2U*i] = ((mic_rx_buf[buf_idx][i] >> 16U) & 0xFFFFU); + tx_buf[(2U*i)+1U] = tx_buf[2U*i]; + } + + BDMA->IFCR |= BDMA_IFCR_CGIF1; + BDMA_Channel1->CCR &= ~BDMA_CCR_EN; + register_set(&BDMA_Channel1->CM0AR, (uint32_t) tx_buf, 0xFFFFFFFFU); + BDMA_Channel1->CNDTR = MIC_TX_BUF_SIZE; + BDMA_Channel1->CCR |= BDMA_CCR_EN; +} + +// Playback processing +static void BDMA_Channel0_IRQ_Handler(void) { + static uint8_t playback_buf = 0U; + + BDMA->IFCR |= BDMA_IFCR_CGIF0; // clear flag + + uint8_t rx_buf_idx = (((BDMA_Channel0->CCR & BDMA_CCR_CT) >> BDMA_CCR_CT_Pos) == 1U) ? 0U : 1U; + playback_buf = 1U - playback_buf; + + // wait until we're done playing the current buf + for (uint32_t timeout_counter = 100000U; timeout_counter > 0U; timeout_counter--){ + uint8_t playing_buf = (DMA1_Stream1->CR & DMA_SxCR_CT) >> DMA_SxCR_CT_Pos; + if ((playing_buf != playback_buf) || (!(DMA1_Stream1->CR & DMA_SxCR_EN))) { + break; + } + } + + // process samples (shift to 12b and bias to be unsigned) + bool sound_playing = false; + for (uint16_t i=0U; i < SOUND_RX_BUF_SIZE; i += 2U) { + // since we are playing mono and receiving stereo, we take every other sample + sound_tx_buf[playback_buf][i/2U] = ((sound_rx_buf[rx_buf_idx][i] + (1UL << 14)) >> 3); + if (sound_rx_buf[rx_buf_idx][i] > 0U) { + sound_playing = true; + } + } + + // manage amp state + if (sound_playing) { + if (sound_idle_count == 0U) { + current_board->set_amp_enabled(true); + + // empty the other buf and start playing that + for (uint16_t i=0U; i < SOUND_TX_BUF_SIZE; i++) { + sound_tx_buf[1U - playback_buf][i] = (1UL << 11); + } + register_clear_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + DMA1_Stream1->CR = (DMA1_Stream1->CR & ~DMA_SxCR_CT_Msk) | ((1UL - playback_buf) << DMA_SxCR_CT_Pos); + register_set_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + } + sound_idle_count = SOUND_IDLE_TIMEOUT; + } + + // manage mic state + if (mic_idle_count == 0U) { + register_set_bits(&DFSDM1_Channel0->CHCFGR1, DFSDM_CHCFGR1_DFSDMEN); + DFSDM1_Filter0->FLTCR1 |= DFSDM_FLTCR1_RSWSTART; + } + mic_idle_count = SOUND_IDLE_TIMEOUT; + + sound_tick(); +} + +void sound_init(void) { + REGISTER_INTERRUPT(BDMA_Channel0_IRQn, BDMA_Channel0_IRQ_Handler, 128U, FAULT_INTERRUPT_RATE_SOUND_DMA) + REGISTER_INTERRUPT(DMA1_Stream0_IRQn, DMA1_Stream0_IRQ_Handler, 128U, FAULT_INTERRUPT_RATE_SOUND_DMA) + + // Init DAC + DAC1->DHR12R1 = (1UL << 11); + register_set(&DAC1->MCR, 0U, 0xFFFFFFFFU); + register_set(&DAC1->CR, DAC_CR_TEN1 | (4U << DAC_CR_TSEL1_Pos) | DAC_CR_DMAEN1, 0xFFFFFFFFU); + register_set_bits(&DAC1->CR, DAC_CR_EN1); + + // Setup DMAMUX (DAC_CH1_DMA as input) + register_set(&DMAMUX1_Channel1->CCR, 67U, DMAMUX_CxCR_DMAREQ_ID_Msk); + + // Setup DMA + register_set(&DMA1_Stream1->PAR, (uint32_t) &(DAC1->DHR12R1), 0xFFFFFFFFU); + register_set(&DMA1_Stream1->M0AR, (uint32_t) sound_tx_buf[0], 0xFFFFFFFFU); + register_set(&DMA1_Stream1->M1AR, (uint32_t) sound_tx_buf[1], 0xFFFFFFFFU); + register_set(&DMA1_Stream1->FCR, 0U, 0x00000083U); + DMA1_Stream1->NDTR = SOUND_TX_BUF_SIZE; + DMA1_Stream1->CR = DMA_SxCR_DBM | (0b11UL << DMA_SxCR_PL_Pos) | (0b01UL << DMA_SxCR_MSIZE_Pos) | (0b01UL << DMA_SxCR_PSIZE_Pos) | DMA_SxCR_MINC | (1U << DMA_SxCR_DIR_Pos); + + // Init trigger timer (little slower than 48kHz, pulled in sync by SAI4_FS_B) + register_set(&TIM5->PSC, 2600U, 0xFFFFU); + register_set(&TIM5->ARR, 100U, 0xFFFFFFFFU); // not important + register_set(&TIM5->AF1, (0b0010UL << TIM5_AF1_ETRSEL_Pos), TIM5_AF1_ETRSEL_Msk); + register_set(&TIM5->CR2, (0b010U << TIM_CR2_MMS_Pos), TIM_CR2_MMS_Msk); + register_set(&TIM5->SMCR, TIM_SMCR_ECE | (0b00111UL << TIM_SMCR_TS_Pos)| (0b0100UL << TIM_SMCR_SMS_Pos), 0x31FFF7U); + TIM5->CNT = 0U; TIM5->SR = 0U; + TIM5->CR1 |= TIM_CR1_CEN; + + // sync both SAIs + register_set(&SAI4->GCR, (0b10UL << SAI_GCR_SYNCOUT_Pos), SAI_GCR_SYNCIN_Msk | SAI_GCR_SYNCOUT_Msk); + + // stereo audio in + register_set(&SAI4_Block_B->CR1, SAI_xCR1_DMAEN | (0b00UL << SAI_xCR1_SYNCEN_Pos) | (0b100U << SAI_xCR1_DS_Pos) | (0b11U << SAI_xCR1_MODE_Pos), 0x0FFB3FEFU); + register_set(&SAI4_Block_B->CR2, (0b001U << SAI_xCR2_FTH_Pos), 0xFFFBU); + register_set(&SAI4_Block_B->FRCR, (31U << SAI_xFRCR_FRL_Pos), 0x7FFFFU); + register_set(&SAI4_Block_B->SLOTR, (0b11UL << SAI_xSLOTR_SLOTEN_Pos) | (1UL << SAI_xSLOTR_NBSLOT_Pos) | (0b01UL << SAI_xSLOTR_SLOTSZ_Pos), 0xFFFF0FDFU); // NBSLOT definition is vague + + // init sound DMA (SAI4_B -> memory, double buffers) + register_set(&BDMA_Channel0->CPAR, (uint32_t) &(SAI4_Block_B->DR), 0xFFFFFFFFU); + register_set(&BDMA_Channel0->CM0AR, (uint32_t) sound_rx_buf[0], 0xFFFFFFFFU); + register_set(&BDMA_Channel0->CM1AR, (uint32_t) sound_rx_buf[1], 0xFFFFFFFFU); + BDMA_Channel0->CNDTR = SOUND_RX_BUF_SIZE; + register_set(&BDMA_Channel0->CCR, BDMA_CCR_DBM | (0b01UL << BDMA_CCR_MSIZE_Pos) | (0b01UL << BDMA_CCR_PSIZE_Pos) | BDMA_CCR_MINC | BDMA_CCR_CIRC | BDMA_CCR_TCIE, 0xFFFFU); + register_set(&DMAMUX2_Channel0->CCR, 16U, DMAMUX_CxCR_DMAREQ_ID_Msk); // SAI4_B_DMA + register_set_bits(&BDMA_Channel0->CCR, BDMA_CCR_EN); + + // mic output + register_set(&SAI4_Block_A->CR1, SAI_xCR1_DMAEN | (0b01UL << SAI_xCR1_SYNCEN_Pos) | (0b100UL << SAI_xCR1_DS_Pos) | (0b10UL << SAI_xCR1_MODE_Pos), 0x0FFB3FEFU); + register_set(&SAI4_Block_A->CR2, 0U, 0xFFFBU); + register_set(&SAI4_Block_A->FRCR, (31U << SAI_xFRCR_FRL_Pos), 0x7FFFFU); + register_set(&SAI4_Block_A->SLOTR, (0b11UL << SAI_xSLOTR_SLOTEN_Pos) | (1UL << SAI_xSLOTR_NBSLOT_Pos) | (0b01U << SAI_xSLOTR_SLOTSZ_Pos), 0xFFFF0FDFU); // NBSLOT definition is vague + + // init DFSDM for PDM mic + register_set(&DFSDM1_Channel0->CHCFGR1, (76UL << DFSDM_CHCFGR1_CKOUTDIV_Pos) | DFSDM_CHCFGR1_CHEN, 0xC0FFF1EFU); // CH0 controls the clock + register_set(&DFSDM1_Channel3->CHCFGR1, (0b01UL << DFSDM_CHCFGR1_SPICKSEL_Pos) | (0b00U << DFSDM_CHCFGR1_SITP_Pos) | DFSDM_CHCFGR1_CHEN, 0x0000F1EFU); // SITP determines sample edge + register_set(&DFSDM1_Filter0->FLTFCR, (0U << DFSDM_FLTFCR_IOSR_Pos) | (64UL << DFSDM_FLTFCR_FOSR_Pos) | (4UL << DFSDM_FLTFCR_FORD_Pos), 0xE3FF00FFU); + register_set(&DFSDM1_Filter0->FLTCR1, DFSDM_FLTCR1_FAST | (3UL << DFSDM_FLTCR1_RCH_Pos) | DFSDM_FLTCR1_RDMAEN | DFSDM_FLTCR1_RCONT | DFSDM_FLTCR1_DFEN, 0x672E7F3BU); + + // DMA (DFSDM1 -> memory) + register_set(&DMA1_Stream0->PAR, (uint32_t) &DFSDM1_Filter0->FLTRDATAR, 0xFFFFFFFFU); + register_set(&DMA1_Stream0->M0AR, (uint32_t)mic_rx_buf[0], 0xFFFFFFFFU); + register_set(&DMA1_Stream0->M1AR, (uint32_t)mic_rx_buf[1], 0xFFFFFFFFU); + DMA1_Stream0->NDTR = MIC_RX_BUF_SIZE; + register_set(&DMA1_Stream0->CR, DMA_SxCR_DBM | (0b10UL << DMA_SxCR_MSIZE_Pos) | (0b10UL << DMA_SxCR_PSIZE_Pos) | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_TCIE, 0x01F7FFFFU); + register_set(&DMAMUX1_Channel0->CCR, 101U, DMAMUX_CxCR_DMAREQ_ID_Msk); // DFSDM1_DMA0 + register_set_bits(&DMA1_Stream0->CR, DMA_SxCR_EN); + DMA1->LIFCR |= 0x7D; // clear flags + + // DMA (memory -> SAI4) + register_set(&BDMA_Channel1->CPAR, (uint32_t) &(SAI4_Block_A->DR), 0xFFFFFFFFU); + register_set(&BDMA_Channel1->CCR, (0b01UL << BDMA_CCR_MSIZE_Pos) | (0b01UL << BDMA_CCR_PSIZE_Pos) | BDMA_CCR_MINC | (0b1U << BDMA_CCR_DIR_Pos), 0xFFFEU); + register_set(&DMAMUX2_Channel1->CCR, 15U, DMAMUX_CxCR_DMAREQ_ID_Msk); // SAI4_A_DMA + + // enable all initted blocks + register_set_bits(&SAI4_Block_A->CR1, SAI_xCR1_SAIEN); + register_set_bits(&SAI4_Block_B->CR1, SAI_xCR1_SAIEN); + NVIC_EnableIRQ(BDMA_Channel0_IRQn); + NVIC_EnableIRQ(DMA1_Stream0_IRQn); +} diff --git a/panda_tici/board/stm32h7/startup_stm32h7x5xx.s b/panda_tici/board/stm32h7/startup_stm32h7x5xx.s new file mode 100644 index 0000000..15015a1 --- /dev/null +++ b/panda_tici/board/stm32h7/startup_stm32h7x5xx.s @@ -0,0 +1,767 @@ +/** + ****************************************************************************** + * @file startup_stm32h735xx.s + * @author MCD Application Team + * @brief STM32H735xx Devices vector table for GCC based toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m7 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* set stack pointer */ + bl __initialize_hardware_early + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + /* bl SystemInit */ +/* Call static constructors */ + /* bl __libc_init_array */ +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_AVD_IRQHandler /* PVD/AVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word FDCAN1_IT0_IRQHandler /* FDCAN1 interrupt line 0 */ + .word FDCAN2_IT0_IRQHandler /* FDCAN2 interrupt line 0 */ + .word FDCAN1_IT1_IRQHandler /* FDCAN1 interrupt line 1 */ + .word FDCAN2_IT1_IRQHandler /* FDCAN2 interrupt line 1 */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_IRQHandler /* TIM1 Break interrupt */ + .word TIM1_UP_IRQHandler /* TIM1 Update interrupt */ + .word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation interrupt */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word 0 /* Reserved */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FMC_IRQHandler /* FMC */ + .word SDMMC1_IRQHandler /* SDMMC1 */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word ETH_IRQHandler /* Ethernet */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .word FDCAN_CAL_IRQHandler /* FDCAN calibration unit interrupt*/ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .word OTG_HS_IRQHandler /* USB OTG HS */ + .word DCMI_PSSI_IRQHandler /* DCMI, PSSI */ + .word CRYP_IRQHandler /* CRYP */ + .word HASH_RNG_IRQHandler /* Hash and Rng */ + .word FPU_IRQHandler /* FPU */ + .word UART7_IRQHandler /* UART7 */ + .word UART8_IRQHandler /* UART8 */ + .word SPI4_IRQHandler /* SPI4 */ + .word SPI5_IRQHandler /* SPI5 */ + .word SPI6_IRQHandler /* SPI6 */ + .word SAI1_IRQHandler /* SAI1 */ + .word LTDC_IRQHandler /* LTDC */ + .word LTDC_ER_IRQHandler /* LTDC error */ + .word DMA2D_IRQHandler /* DMA2D */ + .word 0 /* Reserved */ + .word OCTOSPI1_IRQHandler /* OCTOSPI1 */ + .word LPTIM1_IRQHandler /* LPTIM1 */ + .word CEC_IRQHandler /* HDMI_CEC */ + .word I2C4_EV_IRQHandler /* I2C4 Event */ + .word I2C4_ER_IRQHandler /* I2C4 Error */ + .word SPDIF_RX_IRQHandler /* SPDIF_RX */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word DMAMUX1_OVR_IRQHandler /* DMAMUX1 Overrun interrupt */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word DFSDM1_FLT0_IRQHandler /* DFSDM Filter0 Interrupt */ + .word DFSDM1_FLT1_IRQHandler /* DFSDM Filter1 Interrupt */ + .word DFSDM1_FLT2_IRQHandler /* DFSDM Filter2 Interrupt */ + .word DFSDM1_FLT3_IRQHandler /* DFSDM Filter3 Interrupt */ + .word 0 /* Reserved */ + .word SWPMI1_IRQHandler /* Serial Wire Interface 1 global interrupt */ + .word TIM15_IRQHandler /* TIM15 global Interrupt */ + .word TIM16_IRQHandler /* TIM16 global Interrupt */ + .word TIM17_IRQHandler /* TIM17 global Interrupt */ + .word MDIOS_WKUP_IRQHandler /* MDIOS Wakeup Interrupt */ + .word MDIOS_IRQHandler /* MDIOS global Interrupt */ + .word 0 /* Reserved */ + .word MDMA_IRQHandler /* MDMA global Interrupt */ + .word 0 /* Reserved */ + .word SDMMC2_IRQHandler /* SDMMC2 global Interrupt */ + .word HSEM1_IRQHandler /* HSEM1 global Interrupt */ + .word 0 /* Reserved */ + .word ADC3_IRQHandler /* ADC3 global Interrupt */ + .word DMAMUX2_OVR_IRQHandler /* DMAMUX Overrun interrupt */ + .word BDMA_Channel0_IRQHandler /* BDMA Channel 0 global Interrupt */ + .word BDMA_Channel1_IRQHandler /* BDMA Channel 1 global Interrupt */ + .word BDMA_Channel2_IRQHandler /* BDMA Channel 2 global Interrupt */ + .word BDMA_Channel3_IRQHandler /* BDMA Channel 3 global Interrupt */ + .word BDMA_Channel4_IRQHandler /* BDMA Channel 4 global Interrupt */ + .word BDMA_Channel5_IRQHandler /* BDMA Channel 5 global Interrupt */ + .word BDMA_Channel6_IRQHandler /* BDMA Channel 6 global Interrupt */ + .word BDMA_Channel7_IRQHandler /* BDMA Channel 7 global Interrupt */ + .word COMP1_IRQHandler /* COMP1 global Interrupt */ + .word LPTIM2_IRQHandler /* LP TIM2 global interrupt */ + .word LPTIM3_IRQHandler /* LP TIM3 global interrupt */ + .word LPTIM4_IRQHandler /* LP TIM4 global interrupt */ + .word LPTIM5_IRQHandler /* LP TIM5 global interrupt */ + .word LPUART1_IRQHandler /* LP UART1 interrupt */ + .word 0 /* Reserved */ + .word CRS_IRQHandler /* Clock Recovery Global Interrupt */ + .word ECC_IRQHandler /* ECC diagnostic Global Interrupt */ + .word SAI4_IRQHandler /* SAI4 global interrupt */ + .word DTS_IRQHandler /* Digital Temperature Sensor interrupt */ + .word 0 /* Reserved */ + .word WAKEUP_PIN_IRQHandler /* Interrupt for all 6 wake-up pins */ + .word OCTOSPI2_IRQHandler /* OCTOSPI2 Interrupt */ + .word OTFDEC1_IRQHandler /* OTFDEC1 Interrupt */ + .word OTFDEC2_IRQHandler /* OTFDEC2 Interrupt */ + .word FMAC_IRQHandler /* FMAC Interrupt */ + .word CORDIC_IRQHandler /* CORDIC Interrupt */ + .word UART9_IRQHandler /* UART9 Interrupt */ + .word USART10_IRQHandler /* UART10 Interrupt */ + .word I2C5_EV_IRQHandler /* I2C5 Event Interrupt */ + .word I2C5_ER_IRQHandler /* I2C5 Error Interrupt */ + .word FDCAN3_IT0_IRQHandler /* FDCAN3 interrupt line 0 */ + .word FDCAN3_IT1_IRQHandler /* FDCAN3 interrupt line 1 */ + .word TIM23_IRQHandler /* TIM23 global interrupt */ + .word TIM24_IRQHandler /* TIM24 global interrupt */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_AVD_IRQHandler + .thumb_set PVD_AVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak FDCAN1_IT0_IRQHandler + .thumb_set FDCAN1_IT0_IRQHandler,Default_Handler + + .weak FDCAN2_IT0_IRQHandler + .thumb_set FDCAN2_IT0_IRQHandler,Default_Handler + + .weak FDCAN1_IT1_IRQHandler + .thumb_set FDCAN1_IT1_IRQHandler,Default_Handler + + .weak FDCAN2_IT1_IRQHandler + .thumb_set FDCAN2_IT1_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler + + .weak TIM1_UP_IRQHandler + .thumb_set TIM1_UP_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_IRQHandler + .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FMC_IRQHandler + .thumb_set FMC_IRQHandler,Default_Handler + + .weak SDMMC1_IRQHandler + .thumb_set SDMMC1_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak ETH_IRQHandler + .thumb_set ETH_IRQHandler,Default_Handler + + .weak ETH_WKUP_IRQHandler + .thumb_set ETH_WKUP_IRQHandler,Default_Handler + + .weak FDCAN_CAL_IRQHandler + .thumb_set FDCAN_CAL_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_OUT_IRQHandler + .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_IN_IRQHandler + .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler + + .weak OTG_HS_WKUP_IRQHandler + .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler + + .weak OTG_HS_IRQHandler + .thumb_set OTG_HS_IRQHandler,Default_Handler + + .weak DCMI_PSSI_IRQHandler + .thumb_set DCMI_PSSI_IRQHandler,Default_Handler + + .weak CRYP_IRQHandler + .thumb_set CRYP_IRQHandler,Default_Handler + + .weak HASH_RNG_IRQHandler + .thumb_set HASH_RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak UART7_IRQHandler + .thumb_set UART7_IRQHandler,Default_Handler + + .weak UART8_IRQHandler + .thumb_set UART8_IRQHandler,Default_Handler + + .weak SPI4_IRQHandler + .thumb_set SPI4_IRQHandler,Default_Handler + + .weak SPI5_IRQHandler + .thumb_set SPI5_IRQHandler,Default_Handler + + .weak SPI6_IRQHandler + .thumb_set SPI6_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak LTDC_IRQHandler + .thumb_set LTDC_IRQHandler,Default_Handler + + .weak LTDC_ER_IRQHandler + .thumb_set LTDC_ER_IRQHandler,Default_Handler + + .weak DMA2D_IRQHandler + .thumb_set DMA2D_IRQHandler,Default_Handler + + .weak OCTOSPI1_IRQHandler + .thumb_set OCTOSPI1_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak CEC_IRQHandler + .thumb_set CEC_IRQHandler,Default_Handler + + .weak I2C4_EV_IRQHandler + .thumb_set I2C4_EV_IRQHandler,Default_Handler + + .weak I2C4_ER_IRQHandler + .thumb_set I2C4_ER_IRQHandler,Default_Handler + + .weak SPDIF_RX_IRQHandler + .thumb_set SPDIF_RX_IRQHandler,Default_Handler + + .weak DMAMUX1_OVR_IRQHandler + .thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler + + .weak DFSDM1_FLT0_IRQHandler + .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler + + .weak DFSDM1_FLT1_IRQHandler + .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler + + .weak DFSDM1_FLT2_IRQHandler + .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler + + .weak DFSDM1_FLT3_IRQHandler + .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler + + .weak SWPMI1_IRQHandler + .thumb_set SWPMI1_IRQHandler,Default_Handler + + .weak TIM15_IRQHandler + .thumb_set TIM15_IRQHandler,Default_Handler + + .weak TIM16_IRQHandler + .thumb_set TIM16_IRQHandler,Default_Handler + + .weak TIM17_IRQHandler + .thumb_set TIM17_IRQHandler,Default_Handler + + .weak MDIOS_WKUP_IRQHandler + .thumb_set MDIOS_WKUP_IRQHandler,Default_Handler + + .weak MDIOS_IRQHandler + .thumb_set MDIOS_IRQHandler,Default_Handler + + .weak MDMA_IRQHandler + .thumb_set MDMA_IRQHandler,Default_Handler + + .weak SDMMC2_IRQHandler + .thumb_set SDMMC2_IRQHandler,Default_Handler + + .weak HSEM1_IRQHandler + .thumb_set HSEM1_IRQHandler,Default_Handler + + .weak ADC3_IRQHandler + .thumb_set ADC3_IRQHandler,Default_Handler + + .weak DMAMUX2_OVR_IRQHandler + .thumb_set DMAMUX2_OVR_IRQHandler,Default_Handler + + .weak BDMA_Channel0_IRQHandler + .thumb_set BDMA_Channel0_IRQHandler,Default_Handler + + .weak BDMA_Channel1_IRQHandler + .thumb_set BDMA_Channel1_IRQHandler,Default_Handler + + .weak BDMA_Channel2_IRQHandler + .thumb_set BDMA_Channel2_IRQHandler,Default_Handler + + .weak BDMA_Channel3_IRQHandler + .thumb_set BDMA_Channel3_IRQHandler,Default_Handler + + .weak BDMA_Channel4_IRQHandler + .thumb_set BDMA_Channel4_IRQHandler,Default_Handler + + .weak BDMA_Channel5_IRQHandler + .thumb_set BDMA_Channel5_IRQHandler,Default_Handler + + .weak BDMA_Channel6_IRQHandler + .thumb_set BDMA_Channel6_IRQHandler,Default_Handler + + .weak BDMA_Channel7_IRQHandler + .thumb_set BDMA_Channel7_IRQHandler,Default_Handler + + .weak COMP1_IRQHandler + .thumb_set COMP1_IRQHandler,Default_Handler + + .weak LPTIM2_IRQHandler + .thumb_set LPTIM2_IRQHandler,Default_Handler + + .weak LPTIM3_IRQHandler + .thumb_set LPTIM3_IRQHandler,Default_Handler + + .weak LPTIM4_IRQHandler + .thumb_set LPTIM4_IRQHandler,Default_Handler + + .weak LPTIM5_IRQHandler + .thumb_set LPTIM5_IRQHandler,Default_Handler + + .weak LPUART1_IRQHandler + .thumb_set LPUART1_IRQHandler,Default_Handler + + .weak CRS_IRQHandler + .thumb_set CRS_IRQHandler,Default_Handler + + .weak ECC_IRQHandler + .thumb_set ECC_IRQHandler,Default_Handler + + .weak SAI4_IRQHandler + .thumb_set SAI4_IRQHandler,Default_Handler + + .weak DTS_IRQHandler + .thumb_set DTS_IRQHandler,Default_Handler + + .weak WAKEUP_PIN_IRQHandler + .thumb_set WAKEUP_PIN_IRQHandler,Default_Handler + + .weak OCTOSPI2_IRQHandler + .thumb_set OCTOSPI2_IRQHandler,Default_Handler + + .weak OTFDEC1_IRQHandler + .thumb_set OTFDEC1_IRQHandler,Default_Handler + + .weak OTFDEC2_IRQHandler + .thumb_set OTFDEC2_IRQHandler,Default_Handler + + .weak FMAC_IRQHandler + .thumb_set FMAC_IRQHandler,Default_Handler + + .weak CORDIC_IRQHandler + .thumb_set CORDIC_IRQHandler,Default_Handler + + .weak UART9_IRQHandler + .thumb_set UART9_IRQHandler,Default_Handler + + .weak USART10_IRQHandler + .thumb_set USART10_IRQHandler,Default_Handler + + .weak I2C5_EV_IRQHandler + .thumb_set I2C5_EV_IRQHandler,Default_Handler + + .weak I2C5_ER_IRQHandler + .thumb_set I2C5_ER_IRQHandler,Default_Handler + + .weak FDCAN3_IT0_IRQHandler + .thumb_set FDCAN3_IT0_IRQHandler,Default_Handler + + .weak FDCAN3_IT1_IRQHandler + .thumb_set FDCAN3_IT1_IRQHandler,Default_Handler + + .weak TIM23_IRQHandler + .thumb_set TIM23_IRQHandler,Default_Handler + + .weak TIM24_IRQHandler + .thumb_set TIM24_IRQHandler,Default_Handler + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/panda_tici/board/stm32h7/stm32h7_config.h b/panda_tici/board/stm32h7/stm32h7_config.h new file mode 100644 index 0000000..4355fe8 --- /dev/null +++ b/panda_tici/board/stm32h7/stm32h7_config.h @@ -0,0 +1,91 @@ +#include "stm32h7/inc/stm32h7xx.h" +#include "stm32h7/inc/stm32h7xx_hal_gpio_ex.h" +#define MCU_IDCODE 0x483U + +#define CORE_FREQ 240U // in Mhz +//APB1 - 120Mhz, APB2 - 120Mhz +#define APB1_FREQ (CORE_FREQ/4U) +#define APB1_TIMER_FREQ (APB1_FREQ*2U) // APB1 is multiplied by 2 for the timer peripherals +#define APB2_FREQ (CORE_FREQ/4U) +#define APB2_TIMER_FREQ (APB2_FREQ*2U) // APB2 is multiplied by 2 for the timer peripherals + +#define BOOTLOADER_ADDRESS 0x1FF09804U + +/* +An IRQ is received on message RX/TX (or RX errors), with +separate IRQs for RX and TX. + +0-byte CAN FD frame as the worst case: +- 17 slow bits = SOF + 11 ID + R1 + IDE + EDL + R0 + BRS +- 23 fast bits = ESI + 4 DLC + 0 DATA + 17 CRC + CRC delimeter +- 12 slow bits = ACK + DEL + 7 EOF + 3 IFS +- all currently supported cars are 0.5 Mbps / 2 Mbps + +1 / ((29 bits / 0.5Mbps) + (23 bits / 2Mbps)) = 14388Hz +*/ +#define CAN_INTERRUPT_RATE 16000U + +#define MAX_LED_FADE 10240U + +// There are 163 external interrupt sources (see stm32f735xx.h) +#define NUM_INTERRUPTS 163U + +#define TICK_TIMER_IRQ TIM8_BRK_TIM12_IRQn +#define TICK_TIMER TIM12 + +#define MICROSECOND_TIMER TIM2 + +#define INTERRUPT_TIMER_IRQ TIM6_DAC_IRQn +#define INTERRUPT_TIMER TIM6 + +#define IND_WDG IWDG1 + +#define PROVISION_CHUNK_ADDRESS 0x080FFFE0U +#define DEVICE_SERIAL_NUMBER_ADDRESS 0x080FFFC0U + +#include "can.h" +#include "comms_definitions.h" + +#ifndef BOOTSTUB + #include "main_definitions.h" +#else + #include "bootstub_declarations.h" +#endif + +#include "libc.h" +#include "critical.h" +#include "faults.h" +#include "utils.h" + +#include "drivers/registers.h" +#include "drivers/interrupts.h" +#include "drivers/gpio.h" +#include "stm32h7/peripherals.h" +#include "stm32h7/interrupt_handlers.h" +#include "drivers/timers.h" + +#if !defined(BOOTSTUB) + #include "drivers/uart.h" + #include "stm32h7/lluart.h" +#endif + +#include "stm32h7/board.h" +#include "stm32h7/clock.h" + +#ifdef BOOTSTUB + #include "stm32h7/llflash.h" +#else + #include "stm32h7/llfdcan.h" +#endif + +#include "stm32h7/llusb.h" + +#include "drivers/spi.h" +#include "stm32h7/llspi.h" + +void early_gpio_float(void) { + RCC->AHB4ENR = RCC_AHB4ENR_GPIOAEN | RCC_AHB4ENR_GPIOBEN | RCC_AHB4ENR_GPIOCEN | RCC_AHB4ENR_GPIODEN | RCC_AHB4ENR_GPIOEEN | RCC_AHB4ENR_GPIOFEN | RCC_AHB4ENR_GPIOGEN | RCC_AHB4ENR_GPIOHEN; + GPIOA->MODER = 0xAB000000U; GPIOB->MODER = 0; GPIOC->MODER = 0; GPIOD->MODER = 0; GPIOE->MODER = 0; GPIOF->MODER = 0; GPIOG->MODER = 0; GPIOH->MODER = 0; + GPIOA->ODR = 0; GPIOB->ODR = 0; GPIOC->ODR = 0; GPIOD->ODR = 0; GPIOE->ODR = 0; GPIOF->ODR = 0; GPIOG->ODR = 0; GPIOH->ODR = 0; + GPIOA->PUPDR = 0; GPIOB->PUPDR = 0; GPIOC->PUPDR = 0; GPIOD->PUPDR = 0; GPIOE->PUPDR = 0; GPIOF->PUPDR = 0; GPIOG->PUPDR = 0; GPIOH->PUPDR = 0; +} diff --git a/panda_tici/board/stm32h7/stm32h7x5_flash.ld b/panda_tici/board/stm32h7/stm32h7x5_flash.ld new file mode 100644 index 0000000..3b6eee5 --- /dev/null +++ b/panda_tici/board/stm32h7/stm32h7x5_flash.ld @@ -0,0 +1,221 @@ +/* +****************************************************************************** +** + +** File : LinkerScript.ld +** +** Author : Auto-generated by System Workbench for STM32 +** +** Abstract : Linker script for STM32H735ZGTx series +** 1024Kbytes FLASH and 560Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +***************************************************************************** +** @attention +** +**

© COPYRIGHT(c) 2019 STMicroelectronics

+** +** 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. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +enter_bootloader_mode = 0x38001FFC; +_estack = 0x20020000; /* end of RAM */ +_app_start = 0x08020000; /* Reserve Sector 0(128K) for bootloader */ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +/* RAM */ +BACKUP_SRAM (xrw) : ORIGIN = 0x38800000, LENGTH = 4K /* Backup SRAM(4kb) */ +SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 16K /* SRAM4(16kb) best for BDMA and SDMMC1*/ +SRAM12 (xrw) : ORIGIN = 0x30000000, LENGTH = 32K /* SRAM1(16kb) + SRAM2(16kb), not for BDMA or SDMMC1 */ +AXISRAM (xrw) : ORIGIN = 0x24000000, LENGTH = 320K /* AXI SRAM */ +DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* DTCM */ + +/* Code */ +SYSTEM (rx) : ORIGIN = 0x1FF00000, LENGTH = 128K /* System memory */ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K +ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >DTCMRAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >DTCMRAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >DTCMRAM + + .itcmram (NOLOAD) : + { + . = ALIGN(4); + *(.itcmram*) + } >ITCMRAM + + .axisram (NOLOAD) : + { + . = ALIGN(4); + *(.axisram*) + } >AXISRAM + + .sram12 (NOLOAD) : + { + . = ALIGN(4); + *(.sram12*) + } >SRAM12 + + .sram4 (NOLOAD) : + { + . = ALIGN(4); + *(.sram4*) + } >SRAM4 + + .backup_sram (NOLOAD) : + { + . = ALIGN(4); + *(.backup_sram*) + } >BACKUP_SRAM + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/panda_tici/board/utils.h b/panda_tici/board/utils.h new file mode 100644 index 0000000..f355ce8 --- /dev/null +++ b/panda_tici/board/utils.h @@ -0,0 +1,47 @@ +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define MIN(a, b) ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + (_a < _b) ? _a : _b; \ +}) + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define MAX(a, b) ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + (_a > _b) ? _a : _b; \ +}) + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define CLAMP(x, low, high) ({ \ + __typeof__(x) __x = (x); \ + __typeof__(low) __low = (low);\ + __typeof__(high) __high = (high);\ + (__x > __high) ? __high : ((__x < __low) ? __low : __x); \ +}) + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define ABS(a) ({ \ + __typeof__ (a) _a = (a); \ + (_a > 0) ? _a : (-_a); \ +}) + +#ifndef NULL +// this just provides a standard implementation of NULL +// in lieu of including libc in the panda build +// cppcheck-suppress [misra-c2012-21.1] +#define NULL ((void*)0) +#endif + +// STM32 HAL defines this +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) +#endif + +#define COMPILE_TIME_ASSERT(pred) ((void)sizeof(char[1 - (2 * (!(pred) ? 1 : 0))])) + +// compute the time elapsed (in microseconds) from 2 counter samples +// case where ts < ts_last is ok: overflow is properly re-casted into uint32_t +uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) { + return ts - ts_last; +} diff --git a/panda_tici/certs/debug b/panda_tici/certs/debug new file mode 100644 index 0000000..39864b6 --- /dev/null +++ b/panda_tici/certs/debug @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQC948lnRo4x44Rd7Y8bQAML4aKDC4XRx958fHV8K6+FbCaP1Z42 +U2kX0yygak0LjoDutpgObmGHZA+Iz3HeUD6VGjr/teN24vPk+A95cRsjt8rgmGQ9 +6HNjaNgjR+gl1F9XxFimMzir82Xpl1ekTueJNXa7ia5HVH1nFdiksOKHGQIDAQAB +AoGAQuPw2I6EHJLW1/eNB75e1FqhUqRGeYV8nEGDaUBCTi+wzc4kM2LijF/5QnDv +vvht9qkfm0XK2VSoHDtnEzcVM/l1ksb68n4R/1nUooAWY6cQI7dCSk/A6yS1EJFg +BXsgGbT/65khw9pzBW2zVtMVcVNWFayqfCO1I9WcDdA1x1kCQQDfrhoZTZNoDEUE +JKM4fiUdWr1h3Aw8KLJFFexSWeGDwo+qqnujYcKWkHa9qaH1RG5x8Kir9s9Oi4Js +mzKwov8fAkEA2VPJPWxJ4vVQpXle6wC1nyoL7s739yxMWFcabvkzDDhlIVBNdVJd +gZKsFWV7QnVNdDMjn9D27FwKu3i2D+kKxwJBANp1SMojqO765MEKI1t+YDNONx6H +cm+i85Fjuv4nCIjOEdCGVuCYDxtMFpxgO2y3HAMuHx5sm8XDnWsDHLvFRdMCQD7V +XqWHnYUk8AAnqy2+ssQl3/VXmZG5GQmhhV74Za3u0C5ljT+SZL6FrYMyKAT67T3f +WzllrT6BDglNyTWoZxkCQQCt0XSoGM3603GGYNt6AUlGSgtXSo/2Px7odGUtQoKA +FH9q6FVMYpQJ38spZxIGufZJmLP8LLg6YIWJj1F+akxr +-----END RSA PRIVATE KEY----- diff --git a/panda_tici/certs/debug.pub b/panda_tici/certs/debug.pub new file mode 100644 index 0000000..00e219d --- /dev/null +++ b/panda_tici/certs/debug.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC948lnRo4x44Rd7Y8bQAML4aKDC4XRx958fHV8K6+FbCaP1Z42U2kX0yygak0LjoDutpgObmGHZA+Iz3HeUD6VGjr/teN24vPk+A95cRsjt8rgmGQ96HNjaNgjR+gl1F9XxFimMzir82Xpl1ekTueJNXa7ia5HVH1nFdiksOKHGQ== batman@y840 diff --git a/panda_tici/certs/release.pub b/panda_tici/certs/release.pub new file mode 100644 index 0000000..19066e2 --- /dev/null +++ b/panda_tici/certs/release.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDGN9GU2nOc0kKq6vdZI5qUMzHt234ngqofrgCFFxL0D2Whex0zACp9gar0HZp+bvtpoSgU/Ev8wexNKr+A9QTradljiuxi5ctrOra9k+wxqNj63Wrcu4+wU5UnJEVf/buV4jCOFffMT8z3PO4imt8LzHuEIC/m/ASKVYyvuvBRQQ== batman@y840 diff --git a/panda_tici/crypto/hash-internal.h b/panda_tici/crypto/hash-internal.h new file mode 100644 index 0000000..05ec3ec --- /dev/null +++ b/panda_tici/crypto/hash-internal.h @@ -0,0 +1,63 @@ +/* + * Copyright 2007 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google Inc. 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 Google Inc. ``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 Google Inc. 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. + */ + +#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ +#define SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ + +#include "stdint.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct HASH_CTX; // forward decl + +typedef struct HASH_VTAB { + void (* const init)(struct HASH_CTX*); + void (* const update)(struct HASH_CTX*, const void*, int); + const uint8_t* (* const final)(struct HASH_CTX*); + const uint8_t* (* const hash)(const void*, int, uint8_t*); + int size; +} HASH_VTAB; + +typedef struct HASH_CTX { + const HASH_VTAB * f; + uint64_t count; + uint8_t buf[64]; + uint32_t state[8]; // upto SHA2 +} HASH_CTX; + +#define HASH_init(ctx) (ctx)->f->init(ctx) +#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len) +#define HASH_final(ctx) (ctx)->f->final(ctx) +#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest) +#define HASH_size(ctx) (ctx)->f->size + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ diff --git a/panda_tici/crypto/rsa.c b/panda_tici/crypto/rsa.c new file mode 100644 index 0000000..24171e8 --- /dev/null +++ b/panda_tici/crypto/rsa.c @@ -0,0 +1,294 @@ +/* rsa.c +** +** Copyright 2012, The Android Open Source Project +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of Google Inc. 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 Google Inc. ``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 Google Inc. 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. +*/ + +#include "rsa.h" +#include "sha.h" + +// a[] -= mod +static void subM(const RSAPublicKey* key, + uint32_t* a) { + int64_t A = 0; + int i; + for (i = 0; i < key->len; ++i) { + A += (uint64_t)a[i] - key->n[i]; + a[i] = (uint32_t)A; + A >>= 32; + } +} + +// return a[] >= mod +static int geM(const RSAPublicKey* key, + const uint32_t* a) { + int i; + for (i = key->len; i;) { + --i; + if (a[i] < key->n[i]) return 0; + if (a[i] > key->n[i]) return 1; + } + return 1; // equal +} + +// montgomery c[] += a * b[] / R % mod +static void montMulAdd(const RSAPublicKey* key, + uint32_t* c, + const uint32_t a, + const uint32_t* b) { + uint64_t A = (uint64_t)a * b[0] + c[0]; + uint32_t d0 = (uint32_t)A * key->n0inv; + uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A; + int i; + + for (i = 1; i < key->len; ++i) { + A = (A >> 32) + (uint64_t)a * b[i] + c[i]; + B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A; + c[i - 1] = (uint32_t)B; + } + + A = (A >> 32) + (B >> 32); + + c[i - 1] = (uint32_t)A; + + if (A >> 32) { + subM(key, c); + } +} + +// montgomery c[] = a[] * b[] / R % mod +static void montMul(const RSAPublicKey* key, + uint32_t* c, + const uint32_t* a, + const uint32_t* b) { + int i; + for (i = 0; i < key->len; ++i) { + c[i] = 0; + } + for (i = 0; i < key->len; ++i) { + montMulAdd(key, c, a[i], b); + } +} + +// In-place public exponentiation. +// Input and output big-endian byte array in inout. +static void modpow(const RSAPublicKey* key, + uint8_t* inout) { + uint32_t a[RSANUMWORDS]; + uint32_t aR[RSANUMWORDS]; + uint32_t aaR[RSANUMWORDS]; + uint32_t* aaa = 0; + int i; + + // Convert from big endian byte array to little endian word array. + for (i = 0; i < key->len; ++i) { + uint32_t tmp = + (inout[((key->len - 1 - i) * 4) + 0] << 24) | + (inout[((key->len - 1 - i) * 4) + 1] << 16) | + (inout[((key->len - 1 - i) * 4) + 2] << 8) | + (inout[((key->len - 1 - i) * 4) + 3] << 0); + a[i] = tmp; + } + + if (key->exponent == 65537) { + aaa = aaR; // Re-use location. + montMul(key, aR, a, key->rr); // aR = a * RR / R mod M + for (i = 0; i < 16; i += 2) { + montMul(key, aaR, aR, aR); // aaR = aR * aR / R mod M + montMul(key, aR, aaR, aaR); // aR = aaR * aaR / R mod M + } + montMul(key, aaa, aR, a); // aaa = aR * a / R mod M + } else if (key->exponent == 3) { + aaa = aR; // Re-use location. + montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */ + montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */ + montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */ + } + + // Make sure aaa < mod; aaa is at most 1x mod too large. + if (geM(key, aaa)) { + subM(key, aaa); + } + + // Convert to bigendian byte array + for (i = key->len - 1; i >= 0; --i) { + uint32_t tmp = aaa[i]; + *inout++ = tmp >> 24; + *inout++ = tmp >> 16; + *inout++ = tmp >> 8; + *inout++ = tmp >> 0; + } +} + +// Expected PKCS1.5 signature padding bytes, for a keytool RSA signature. +// Has the 0-length optional parameter encoded in the ASN1 (as opposed to the +// other flavor which omits the optional parameter entirely). This code does not +// accept signatures without the optional parameter. + +/* +static const uint8_t sha_padding[RSANUMBYTES] = { + 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30, + 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, + 0x05, 0x00, 0x04, 0x14, + + // 20 bytes of hash go here. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; +*/ + +static const uint8_t sha_padding_1024[RSANUMBYTES] = { + 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, + + // 20 bytes of hash go here. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + +// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above. +// At the location of the bytes of the hash all 00 are hashed. +/*static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = { + 0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e, + 0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68, + 0x7c, 0xfb, 0xf1, 0x67 +};*/ + +// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash. +// Both e=3 and e=65537 are supported. hash_len may be +// SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or +// SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash. No other +// values are supported. +// +// Returns 1 on successful verification, 0 on failure. +int RSA_verify(const RSAPublicKey *key, + const uint8_t *signature, + const int len, + const uint8_t *hash, + const int hash_len) { + uint8_t buf[RSANUMBYTES]; + int i; + //const uint8_t* padding_hash; + + if (key->len != RSANUMWORDS) { + return 0; // Wrong key passed in. + } + + if (len != sizeof(buf)) { + return 0; // Wrong input length. + } + + if (hash_len != SHA_DIGEST_SIZE) { + return 0; // Unsupported hash. + } + + if (key->exponent != 3 && key->exponent != 65537) { + return 0; // Unsupported exponent. + } + + for (i = 0; i < len; ++i) { // Copy input to local workspace. + buf[i] = signature[i]; + } + + modpow(key, buf); // In-place exponentiation. + +#ifdef TEST_RSA + printf("sig\n"); + for (i=0;i + +#ifdef __cplusplus +extern "C" { +#endif + +#define RSANUMBYTES 128 /* 1024 bit key length */ +#define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t)) + +typedef struct RSAPublicKey { + int len; /* Length of n[] in number of uint32_t */ + uint32_t n0inv; /* -1 / n[0] mod 2^32 */ + uint32_t n[RSANUMWORDS]; /* modulus as little endian array */ + uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */ + int exponent; /* 3 or 65537 */ +} RSAPublicKey; + +int RSA_verify(const RSAPublicKey *key, + const uint8_t* signature, + const int len, + const uint8_t* hash, + const int hash_len); + +#ifdef __cplusplus +} +#endif + +#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_ diff --git a/panda_tici/crypto/sha.c b/panda_tici/crypto/sha.c new file mode 100644 index 0000000..a13162c --- /dev/null +++ b/panda_tici/crypto/sha.c @@ -0,0 +1,179 @@ +/* sha.c +** +** Copyright 2013, The Android Open Source Project +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of Google Inc. 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 Google Inc. ``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 Google Inc. 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. +*/ + +// Optimized for minimal code size. + +void *memcpy(void *str1, const void *str2, unsigned int n); + +#include "sha.h" + +#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +static void SHA1_Transform(SHA_CTX* ctx) { + uint32_t W[80]; + uint32_t A, B, C, D, E; + uint8_t* p = ctx->buf; + int t; + + for(t = 0; t < 16; ++t) { + uint32_t tmp = *p++ << 24; + tmp |= *p++ << 16; + tmp |= *p++ << 8; + tmp |= *p++; + W[t] = tmp; + } + + for(; t < 80; t++) { + W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + + for(t = 0; t < 80; t++) { + uint32_t tmp = rol(5,A) + E + W[t]; + + if (t < 20) + tmp += (D^(B&(C^D))) + 0x5A827999; + else if ( t < 40) + tmp += (B^C^D) + 0x6ED9EBA1; + else if ( t < 60) + tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC; + else + tmp += (B^C^D) + 0xCA62C1D6; + + E = D; + D = C; + C = rol(30,B); + B = A; + A = tmp; + } + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +static const HASH_VTAB SHA_VTAB = { + SHA_init, + SHA_update, + SHA_final, + SHA_hash, + SHA_DIGEST_SIZE +}; + +void SHA_init(SHA_CTX* ctx) { + ctx->f = &SHA_VTAB; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + ctx->count = 0; +} + + +void SHA_update(SHA_CTX* ctx, const void* data, int len) { + int i = (int) (ctx->count & 63); + const uint8_t* p = (const uint8_t*)data; + + ctx->count += len; + + while (len--) { + ctx->buf[i++] = *p++; + if (i == 64) { + SHA1_Transform(ctx); + i = 0; + } + } +} + + +const uint8_t* SHA_final(SHA_CTX* ctx) { + uint8_t *p = ctx->buf; + uint64_t cnt = ctx->count * 8; + int i; + + SHA_update(ctx, (uint8_t*)"\x80", 1); + while ((ctx->count & 63) != 56) { + SHA_update(ctx, (uint8_t*)"\0", 1); + } + + /* Hack - right shift operator with non const argument requires + * libgcc.a which is missing in EON + * thus expanding for loop from + + for (i = 0; i < 8; ++i) { + uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8)); + SHA_update(ctx, &tmp, 1); + } + + to + */ + + uint8_t tmp = 0; + tmp = (uint8_t) (cnt >> ((7 - 0) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 1) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 2) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 3) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 4) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 5) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 6) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 7) * 8)); + SHA_update(ctx, &tmp, 1); + + for (i = 0; i < 5; i++) { + uint32_t tmp = ctx->state[i]; + *p++ = tmp >> 24; + *p++ = tmp >> 16; + *p++ = tmp >> 8; + *p++ = tmp >> 0; + } + + return ctx->buf; +} + +/* Convenience function */ +const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) { + SHA_CTX ctx; + SHA_init(&ctx); + SHA_update(&ctx, data, len); + memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE); + return digest; +} diff --git a/panda_tici/crypto/sha.h b/panda_tici/crypto/sha.h new file mode 100644 index 0000000..4b51a53 --- /dev/null +++ b/panda_tici/crypto/sha.h @@ -0,0 +1,51 @@ +/* + * Copyright 2005 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google Inc. 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 Google Inc. ``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 Google Inc. 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. + */ +#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ +#define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ + +#include "hash-internal.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef HASH_CTX SHA_CTX; + +void SHA_init(SHA_CTX* ctx); +void SHA_update(SHA_CTX* ctx, const void* data, int len); +const uint8_t* SHA_final(SHA_CTX* ctx); + +// Convenience method. Returns digest address. +// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes. +const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest); + +#define SHA_DIGEST_SIZE 20 + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ diff --git a/panda_tici/crypto/sign.py b/panda_tici/crypto/sign.py new file mode 100755 index 0000000..daea386 --- /dev/null +++ b/panda_tici/crypto/sign.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import os +import sys +import struct +import hashlib +from Crypto.PublicKey import RSA +import binascii + +# increment this to make new hardware not run old versions +VERSION = 2 + +if __name__ == "__main__": + with open(sys.argv[3]) as k: + rsa = RSA.importKey(k.read()) + + with open(sys.argv[1], "rb") as f: + dat = f.read() + + print("signing", len(dat), "bytes") + + with open(sys.argv[2], "wb") as f: + if os.getenv("SETLEN") is not None: + # add the version at the end + dat += b"VERS" + struct.pack("I", VERSION) + # add the length at the beginning + x = struct.pack("I", len(dat)) + dat[4:] + # mock signature of dat[4:] + dd = hashlib.sha1(dat[4:]).digest() + else: + x = dat + dd = hashlib.sha1(dat).digest() + + print("hash:", str(binascii.hexlify(dd), "utf-8")) + dd = b"\x00\x01" + b"\xff" * 0x69 + b"\x00" + dd + rsa_out = pow(int.from_bytes(dd, byteorder='big', signed=False), rsa.d, rsa.n) + sig = (hex(rsa_out)[2:].rjust(0x100, '0')) + x += binascii.unhexlify(sig) + f.write(x) diff --git a/panda_tici/docs/CANPacket_structure.png b/panda_tici/docs/CANPacket_structure.png new file mode 100644 index 0000000..7dd1343 Binary files /dev/null and b/panda_tici/docs/CANPacket_structure.png differ diff --git a/panda_tici/docs/USB_packet_structure.png b/panda_tici/docs/USB_packet_structure.png new file mode 100644 index 0000000..30e848c Binary files /dev/null and b/panda_tici/docs/USB_packet_structure.png differ diff --git a/panda_tici/drivers/spi/.gitignore b/panda_tici/drivers/spi/.gitignore new file mode 100644 index 0000000..49dc09d --- /dev/null +++ b/panda_tici/drivers/spi/.gitignore @@ -0,0 +1,7 @@ +spidev.c +*.ko +*.cmd +*.mod +*.symvers +*.order +*.mod.c diff --git a/panda_tici/drivers/spi/Makefile b/panda_tici/drivers/spi/Makefile new file mode 100644 index 0000000..9a2a0ab --- /dev/null +++ b/panda_tici/drivers/spi/Makefile @@ -0,0 +1,14 @@ +obj-m += spidev_panda.o + +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +# GCC9 bug, apply kernel patch instead? +# https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0b999ae3614d09d97a1575936bcee884f912b10e +ccflags-y := -Wno-missing-attributes + +default: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean diff --git a/panda_tici/drivers/spi/load.sh b/panda_tici/drivers/spi/load.sh new file mode 100755 index 0000000..3446591 --- /dev/null +++ b/panda_tici/drivers/spi/load.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +make -j8 + +sudo su -c "echo spi0.0 > /sys/bus/spi/drivers/spidev/unbind" || true + +sudo dmesg -C + +#sudo rmmod -f spidev_panda +sudo rmmod spidev_panda || true +sudo insmod spidev_panda.ko + +sudo su -c "echo 'file $DIR/spidev_panda.c +p' > /sys/kernel/debug/dynamic_debug/control" +sudo su -c "echo 'file $DIR/spi_panda.h +p' > /sys/kernel/debug/dynamic_debug/control" + +sudo lsmod + +echo "loaded" +ls -la /dev/spi* +sudo chmod 666 /dev/spi* +ipython -c "from panda_tici import Panda; print(Panda.list())" +KERN=1 ipython -c "from panda_tici import Panda; print(Panda.list())" +dmesg diff --git a/panda_tici/drivers/spi/patch b/panda_tici/drivers/spi/patch new file mode 100644 index 0000000..a146303 --- /dev/null +++ b/panda_tici/drivers/spi/patch @@ -0,0 +1,33 @@ +53c53,54 +< #define SPIDEV_MAJOR 153 /* assigned */ +--- +> int SPIDEV_MAJOR = 0; +> //#define SPIDEV_MAJOR 153 /* assigned */ +354a356,358 +> +> #include "spi_panda.h" +> +413,414c417,419 +< retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, +< (__u8 __user *)arg); +--- +> retval = panda_transfer(spidev, spi, arg); +> //retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, +> // (__u8 __user *)arg); +697,698d701 +< { .compatible = "rohm,dh2228fv" }, +< { .compatible = "lineartechnology,ltc2488" }, +831c834 +< .name = "spidev", +--- +> .name = "spidev_panda", +856c859 +< status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops); +--- +> status = register_chrdev(0, "spi", &spidev_fops); +860c863,865 +< spidev_class = class_create(THIS_MODULE, "spidev"); +--- +> SPIDEV_MAJOR = status; +> +> spidev_class = class_create(THIS_MODULE, "spidev_panda"); diff --git a/panda_tici/drivers/spi/pull-src.sh b/panda_tici/drivers/spi/pull-src.sh new file mode 100755 index 0000000..64dac9b --- /dev/null +++ b/panda_tici/drivers/spi/pull-src.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +rm -f spidev.c +wget https://raw.githubusercontent.com/commaai/agnos-kernel-sdm845/master/drivers/spi/spidev.c + +# diff spidev.c spidev_panda.c > patch +# git diff --no-index spidev.c spidev_panda.c +patch -o spidev_panda.c spidev.c -i patch diff --git a/panda_tici/drivers/spi/spi_panda.h b/panda_tici/drivers/spi/spi_panda.h new file mode 100644 index 0000000..c7da681 --- /dev/null +++ b/panda_tici/drivers/spi/spi_panda.h @@ -0,0 +1,160 @@ +#include +#include +#include + +#define SPI_SYNC 0x5AU +#define SPI_HACK 0x79U +#define SPI_DACK 0x85U +#define SPI_NACK 0x1FU +#define SPI_CHECKSUM_START 0xABU + +struct __attribute__((packed)) spi_header { + u8 sync; + u8 endpoint; + uint16_t tx_len; + uint16_t max_rx_len; +}; + +struct spi_panda_transfer { + __u64 rx_buf; + __u64 tx_buf; + __u32 tx_length; + __u32 rx_length_max; + __u32 timeout; + __u8 endpoint; + __u8 expect_disconnect; +}; + +static u8 panda_calc_checksum(u8 *buf, u16 length) { + int i; + u8 checksum = SPI_CHECKSUM_START; + for (i = 0U; i < length; i++) { + checksum ^= buf[i]; + } + return checksum; +} + +static long panda_wait_for_ack(struct spidev_data *spidev, u8 ack_val, u8 length) { + int i; + int ret; + for (i = 0; i < 1000; i++) { + ret = spidev_sync_read(spidev, length); + if (ret < 0) { + return ret; + } + + if (spidev->rx_buffer[0] == ack_val) { + return 0; + } else if (spidev->rx_buffer[0] == SPI_NACK) { + return -2; + } + if (i > 20) usleep_range(10, 20); + } + return -1; +} + +static long panda_transfer_raw(struct spidev_data *spidev, struct spi_device *spi, unsigned long arg) { + u16 rx_len; + long retval = -1; + struct spi_header header; + struct spi_panda_transfer pt; + + struct spi_transfer t = { + .len = 0, + .tx_buf = spidev->tx_buffer, + .rx_buf = spidev->rx_buffer, + .speed_hz = spidev->spi->max_speed_hz, + }; + + struct spi_message m; + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + // read struct from user + if (!access_ok(VERIFY_WRITE, arg, sizeof(pt))) { + return -1; + } + if (copy_from_user(&pt, (void __user *)arg, sizeof(pt))) { + return -1; + } + dev_dbg(&spi->dev, "ep: %d, tx len: %d\n", pt.endpoint, pt.tx_length); + + // send header + header.sync = 0x5a; + header.endpoint = pt.endpoint; + header.tx_len = pt.tx_length; + header.max_rx_len = pt.rx_length_max; + memcpy(spidev->tx_buffer, &header, sizeof(header)); + spidev->tx_buffer[sizeof(header)] = panda_calc_checksum(spidev->tx_buffer, sizeof(header)); + + t.len = sizeof(header) + 1; + retval = spidev_sync(spidev, &m); + if (retval < 0) { + dev_dbg(&spi->dev, "spi xfer failed %ld\n", retval); + return retval; + } + + // wait for ACK + retval = panda_wait_for_ack(spidev, SPI_HACK, 1); + if (retval < 0) { + dev_dbg(&spi->dev, "no header ack %ld\n", retval); + return retval; + } + + // send data + dev_dbg(&spi->dev, "sending data\n"); + retval = copy_from_user(spidev->tx_buffer, (const u8 __user *)(uintptr_t)pt.tx_buf, pt.tx_length); + spidev->tx_buffer[pt.tx_length] = panda_calc_checksum(spidev->tx_buffer, pt.tx_length); + t.len = pt.tx_length + 1; + retval = spidev_sync(spidev, &m); + + if (pt.expect_disconnect) { + return 0; + } + + // wait for ACK + retval = panda_wait_for_ack(spidev, SPI_DACK, 3); + if (retval < 0) { + dev_dbg(&spi->dev, "no data ack\n"); + return retval; + } + + // get response + t.rx_buf = spidev->rx_buffer + 3; + rx_len = (spidev->rx_buffer[2] << 8) | (spidev->rx_buffer[1]); + dev_dbg(&spi->dev, "rx len %u\n", rx_len); + if (rx_len > pt.rx_length_max) { + dev_dbg(&spi->dev, "RX len greater than max\n"); + return -1; + } + + // do the read + t.len = rx_len + 1; + retval = spidev_sync(spidev, &m); + if (retval < 0) { + dev_dbg(&spi->dev, "spi xfer failed %ld\n", retval); + return retval; + } + if (panda_calc_checksum(spidev->rx_buffer, 3 + rx_len + 1) != 0) { + dev_dbg(&spi->dev, "bad checksum\n"); + return -1; + } + + retval = copy_to_user((u8 __user *)(uintptr_t)pt.rx_buf, spidev->rx_buffer + 3, rx_len); + + return rx_len; +} + +static long panda_transfer(struct spidev_data *spidev, struct spi_device *spi, unsigned long arg) { + int i; + int ret; + dev_dbg(&spi->dev, "=== XFER start ===\n"); + for (i = 0; i < 20; i++) { + ret = panda_transfer_raw(spidev, spi, arg); + if (ret >= 0) { + break; + } + } + dev_dbg(&spi->dev, "took %d tries\n", i+1); + return ret; +} diff --git a/panda_tici/drivers/spi/spidev_panda.c b/panda_tici/drivers/spi/spidev_panda.c new file mode 100644 index 0000000..f21fe33 --- /dev/null +++ b/panda_tici/drivers/spi/spidev_panda.c @@ -0,0 +1,891 @@ +/* + * Simple synchronous userspace interface to SPI devices + * + * Copyright (C) 2006 SWAPP + * Andrea Paterniani + * Copyright (C) 2007 David Brownell (simplification, cleanup) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +/* + * This supports access to SPI devices using normal userspace I/O calls. + * Note that while traditional UNIX/POSIX I/O semantics are half duplex, + * and often mask message boundaries, full SPI support requires full duplex + * transfers. There are several kinds of internal message boundaries to + * handle chipselect management and other protocol options. + * + * SPI has a character major number assigned. We allocate minor numbers + * dynamically using a bitmask. You must use hotplug tools, such as udev + * (or mdev with busybox) to create and destroy the /dev/spidevB.C device + * nodes, since there is no fixed association of minor numbers with any + * particular SPI bus or device. + */ +int SPIDEV_MAJOR = 0; +//#define SPIDEV_MAJOR 153 /* assigned */ +#define N_SPI_MINORS 32 /* ... up to 256 */ + +static DECLARE_BITMAP(minors, N_SPI_MINORS); + + +/* Bit masks for spi_device.mode management. Note that incorrect + * settings for some settings can cause *lots* of trouble for other + * devices on a shared bus: + * + * - CS_HIGH ... this device will be active when it shouldn't be + * - 3WIRE ... when active, it won't behave as it should + * - NO_CS ... there will be no explicit message boundaries; this + * is completely incompatible with the shared bus model + * - READY ... transfers may proceed when they shouldn't. + * + * REVISIT should changing those flags be privileged? + */ +#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ + | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ + | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \ + | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD) + +struct spidev_data { + dev_t devt; + spinlock_t spi_lock; + struct spi_device *spi; + struct list_head device_entry; + + /* TX/RX buffers are NULL unless this device is open (users > 0) */ + struct mutex buf_lock; + unsigned users; + u8 *tx_buffer; + u8 *rx_buffer; + u32 speed_hz; +}; + +static LIST_HEAD(device_list); +static DEFINE_MUTEX(device_list_lock); + +static unsigned bufsiz = 4096; +module_param(bufsiz, uint, S_IRUGO); +MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message"); + +/*-------------------------------------------------------------------------*/ + +static ssize_t +spidev_sync(struct spidev_data *spidev, struct spi_message *message) +{ + DECLARE_COMPLETION_ONSTACK(done); + int status; + struct spi_device *spi; + + spin_lock_irq(&spidev->spi_lock); + spi = spidev->spi; + spin_unlock_irq(&spidev->spi_lock); + + if (spi == NULL) + status = -ESHUTDOWN; + else + status = spi_sync(spi, message); + + if (status == 0) + status = message->actual_length; + + return status; +} + +static inline ssize_t +spidev_sync_write(struct spidev_data *spidev, size_t len) +{ + struct spi_transfer t = { + .tx_buf = spidev->tx_buffer, + .len = len, + .speed_hz = spidev->speed_hz, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spidev_sync(spidev, &m); +} + +static inline ssize_t +spidev_sync_read(struct spidev_data *spidev, size_t len) +{ + struct spi_transfer t = { + .rx_buf = spidev->rx_buffer, + .len = len, + .speed_hz = spidev->speed_hz, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spidev_sync(spidev, &m); +} + +/*-------------------------------------------------------------------------*/ + +/* Read-only message with current device setup */ +static ssize_t +spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + struct spidev_data *spidev; + ssize_t status = 0; + + /* chipselect only toggles at start or end of operation */ + if (count > bufsiz) + return -EMSGSIZE; + + spidev = filp->private_data; + + mutex_lock(&spidev->buf_lock); + status = spidev_sync_read(spidev, count); + if (status > 0) { + unsigned long missing; + + missing = copy_to_user(buf, spidev->rx_buffer, status); + if (missing == status) + status = -EFAULT; + else + status = status - missing; + } + mutex_unlock(&spidev->buf_lock); + + return status; +} + +/* Write-only message with current device setup */ +static ssize_t +spidev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + struct spidev_data *spidev; + ssize_t status = 0; + unsigned long missing; + + /* chipselect only toggles at start or end of operation */ + if (count > bufsiz) + return -EMSGSIZE; + + spidev = filp->private_data; + + mutex_lock(&spidev->buf_lock); + missing = copy_from_user(spidev->tx_buffer, buf, count); + if (missing == 0) + status = spidev_sync_write(spidev, count); + else + status = -EFAULT; + mutex_unlock(&spidev->buf_lock); + + return status; +} + +static int spidev_message(struct spidev_data *spidev, + struct spi_ioc_transfer *u_xfers, unsigned n_xfers) +{ + struct spi_message msg; + struct spi_transfer *k_xfers; + struct spi_transfer *k_tmp; + struct spi_ioc_transfer *u_tmp; + unsigned n, total, tx_total, rx_total; + u8 *tx_buf, *rx_buf; + int status = -EFAULT; + + spi_message_init(&msg); + k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL); + if (k_xfers == NULL) + return -ENOMEM; + + /* Construct spi_message, copying any tx data to bounce buffer. + * We walk the array of user-provided transfers, using each one + * to initialize a kernel version of the same transfer. + */ + tx_buf = spidev->tx_buffer; + rx_buf = spidev->rx_buffer; + total = 0; + tx_total = 0; + rx_total = 0; + for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; + n; + n--, k_tmp++, u_tmp++) { + k_tmp->len = u_tmp->len; + + total += k_tmp->len; + /* Since the function returns the total length of transfers + * on success, restrict the total to positive int values to + * avoid the return value looking like an error. Also check + * each transfer length to avoid arithmetic overflow. + */ + if (total > INT_MAX || k_tmp->len > INT_MAX) { + status = -EMSGSIZE; + goto done; + } + + if (u_tmp->rx_buf) { + /* this transfer needs space in RX bounce buffer */ + rx_total += k_tmp->len; + if (rx_total > bufsiz) { + status = -EMSGSIZE; + goto done; + } + k_tmp->rx_buf = rx_buf; + if (!access_ok(VERIFY_WRITE, (u8 __user *) + (uintptr_t) u_tmp->rx_buf, + u_tmp->len)) + goto done; + rx_buf += k_tmp->len; + } + if (u_tmp->tx_buf) { + /* this transfer needs space in TX bounce buffer */ + tx_total += k_tmp->len; + if (tx_total > bufsiz) { + status = -EMSGSIZE; + goto done; + } + k_tmp->tx_buf = tx_buf; + if (copy_from_user(tx_buf, (const u8 __user *) + (uintptr_t) u_tmp->tx_buf, + u_tmp->len)) + goto done; + tx_buf += k_tmp->len; + } + + k_tmp->cs_change = !!u_tmp->cs_change; + k_tmp->tx_nbits = u_tmp->tx_nbits; + k_tmp->rx_nbits = u_tmp->rx_nbits; + k_tmp->bits_per_word = u_tmp->bits_per_word; + k_tmp->delay_usecs = u_tmp->delay_usecs; + k_tmp->speed_hz = u_tmp->speed_hz; + if (!k_tmp->speed_hz) + k_tmp->speed_hz = spidev->speed_hz; +#ifdef VERBOSE + dev_dbg(&spidev->spi->dev, + " xfer len %u %s%s%s%dbits %u usec %uHz\n", + u_tmp->len, + u_tmp->rx_buf ? "rx " : "", + u_tmp->tx_buf ? "tx " : "", + u_tmp->cs_change ? "cs " : "", + u_tmp->bits_per_word ? : spidev->spi->bits_per_word, + u_tmp->delay_usecs, + u_tmp->speed_hz ? : spidev->spi->max_speed_hz); +#endif + spi_message_add_tail(k_tmp, &msg); + } + + status = spidev_sync(spidev, &msg); + if (status < 0) + goto done; + + /* copy any rx data out of bounce buffer */ + rx_buf = spidev->rx_buffer; + for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { + if (u_tmp->rx_buf) { + if (__copy_to_user((u8 __user *) + (uintptr_t) u_tmp->rx_buf, rx_buf, + u_tmp->len)) { + status = -EFAULT; + goto done; + } + rx_buf += u_tmp->len; + } + } + status = total; + +done: + kfree(k_xfers); + return status; +} + +static struct spi_ioc_transfer * +spidev_get_ioc_message(unsigned int cmd, struct spi_ioc_transfer __user *u_ioc, + unsigned *n_ioc) +{ + struct spi_ioc_transfer *ioc; + u32 tmp; + + /* Check type, command number and direction */ + if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC + || _IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0)) + || _IOC_DIR(cmd) != _IOC_WRITE) + return ERR_PTR(-ENOTTY); + + tmp = _IOC_SIZE(cmd); + if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) + return ERR_PTR(-EINVAL); + *n_ioc = tmp / sizeof(struct spi_ioc_transfer); + if (*n_ioc == 0) + return NULL; + + /* copy into scratch area */ + ioc = kmalloc(tmp, GFP_KERNEL); + if (!ioc) + return ERR_PTR(-ENOMEM); + if (__copy_from_user(ioc, u_ioc, tmp)) { + kfree(ioc); + return ERR_PTR(-EFAULT); + } + return ioc; +} + + +#include "spi_panda.h" + +static long +spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int err = 0; + int retval = 0; + struct spidev_data *spidev; + struct spi_device *spi; + u32 tmp; + unsigned n_ioc; + struct spi_ioc_transfer *ioc; + + /* Check type and command number */ + if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC) + return -ENOTTY; + + /* Check access direction once here; don't repeat below. + * IOC_DIR is from the user perspective, while access_ok is + * from the kernel perspective; so they look reversed. + */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, + (void __user *)arg, _IOC_SIZE(cmd)); + if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, + (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + /* guard against device removal before, or while, + * we issue this ioctl. + */ + spidev = filp->private_data; + spin_lock_irq(&spidev->spi_lock); + spi = spi_dev_get(spidev->spi); + spin_unlock_irq(&spidev->spi_lock); + + if (spi == NULL) + return -ESHUTDOWN; + + /* use the buffer lock here for triple duty: + * - prevent I/O (from us) so calling spi_setup() is safe; + * - prevent concurrent SPI_IOC_WR_* from morphing + * data fields while SPI_IOC_RD_* reads them; + * - SPI_IOC_MESSAGE needs the buffer locked "normally". + */ + mutex_lock(&spidev->buf_lock); + + switch (cmd) { + /* read requests */ + case SPI_IOC_RD_MODE: + retval = __put_user(spi->mode & SPI_MODE_MASK, + (__u8 __user *)arg); + break; + case SPI_IOC_RD_MODE32: + retval = __put_user(spi->mode & SPI_MODE_MASK, + (__u32 __user *)arg); + break; + case SPI_IOC_RD_LSB_FIRST: + retval = panda_transfer(spidev, spi, arg); + //retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, + // (__u8 __user *)arg); + break; + case SPI_IOC_RD_BITS_PER_WORD: + retval = __put_user(spi->bits_per_word, (__u8 __user *)arg); + break; + case SPI_IOC_RD_MAX_SPEED_HZ: + retval = __put_user(spidev->speed_hz, (__u32 __user *)arg); + break; + + /* write requests */ + case SPI_IOC_WR_MODE: + case SPI_IOC_WR_MODE32: + if (cmd == SPI_IOC_WR_MODE) + retval = __get_user(tmp, (u8 __user *)arg); + else + retval = __get_user(tmp, (u32 __user *)arg); + if (retval == 0) { + u32 save = spi->mode; + + if (tmp & ~SPI_MODE_MASK) { + retval = -EINVAL; + break; + } + + tmp |= spi->mode & ~SPI_MODE_MASK; + spi->mode = (u16)tmp; + retval = spi_setup(spi); + if (retval < 0) + spi->mode = save; + else + dev_dbg(&spi->dev, "spi mode %x\n", tmp); + } + break; + case SPI_IOC_WR_LSB_FIRST: + retval = __get_user(tmp, (__u8 __user *)arg); + if (retval == 0) { + u32 save = spi->mode; + + if (tmp) + spi->mode |= SPI_LSB_FIRST; + else + spi->mode &= ~SPI_LSB_FIRST; + retval = spi_setup(spi); + if (retval < 0) + spi->mode = save; + else + dev_dbg(&spi->dev, "%csb first\n", + tmp ? 'l' : 'm'); + } + break; + case SPI_IOC_WR_BITS_PER_WORD: + retval = __get_user(tmp, (__u8 __user *)arg); + if (retval == 0) { + u8 save = spi->bits_per_word; + + spi->bits_per_word = tmp; + retval = spi_setup(spi); + if (retval < 0) + spi->bits_per_word = save; + else + dev_dbg(&spi->dev, "%d bits per word\n", tmp); + } + break; + case SPI_IOC_WR_MAX_SPEED_HZ: + retval = __get_user(tmp, (__u32 __user *)arg); + if (retval == 0) { + u32 save = spi->max_speed_hz; + + spi->max_speed_hz = tmp; + retval = spi_setup(spi); + if (retval >= 0) + spidev->speed_hz = tmp; + else + dev_dbg(&spi->dev, "%d Hz (max)\n", tmp); + spi->max_speed_hz = save; + } + break; + + default: + /* segmented and/or full-duplex I/O request */ + /* Check message and copy into scratch area */ + ioc = spidev_get_ioc_message(cmd, + (struct spi_ioc_transfer __user *)arg, &n_ioc); + if (IS_ERR(ioc)) { + retval = PTR_ERR(ioc); + break; + } + if (!ioc) + break; /* n_ioc is also 0 */ + + /* translate to spi_message, execute */ + retval = spidev_message(spidev, ioc, n_ioc); + kfree(ioc); + break; + } + + mutex_unlock(&spidev->buf_lock); + spi_dev_put(spi); + return retval; +} + +#ifdef CONFIG_COMPAT +static long +spidev_compat_ioc_message(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct spi_ioc_transfer __user *u_ioc; + int retval = 0; + struct spidev_data *spidev; + struct spi_device *spi; + unsigned n_ioc, n; + struct spi_ioc_transfer *ioc; + + u_ioc = (struct spi_ioc_transfer __user *) compat_ptr(arg); + if (!access_ok(VERIFY_READ, u_ioc, _IOC_SIZE(cmd))) + return -EFAULT; + + /* guard against device removal before, or while, + * we issue this ioctl. + */ + spidev = filp->private_data; + spin_lock_irq(&spidev->spi_lock); + spi = spi_dev_get(spidev->spi); + spin_unlock_irq(&spidev->spi_lock); + + if (spi == NULL) + return -ESHUTDOWN; + + /* SPI_IOC_MESSAGE needs the buffer locked "normally" */ + mutex_lock(&spidev->buf_lock); + + /* Check message and copy into scratch area */ + ioc = spidev_get_ioc_message(cmd, u_ioc, &n_ioc); + if (IS_ERR(ioc)) { + retval = PTR_ERR(ioc); + goto done; + } + if (!ioc) + goto done; /* n_ioc is also 0 */ + + /* Convert buffer pointers */ + for (n = 0; n < n_ioc; n++) { + ioc[n].rx_buf = (uintptr_t) compat_ptr(ioc[n].rx_buf); + ioc[n].tx_buf = (uintptr_t) compat_ptr(ioc[n].tx_buf); + } + + /* translate to spi_message, execute */ + retval = spidev_message(spidev, ioc, n_ioc); + kfree(ioc); + +done: + mutex_unlock(&spidev->buf_lock); + spi_dev_put(spi); + return retval; +} + +static long +spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + if (_IOC_TYPE(cmd) == SPI_IOC_MAGIC + && _IOC_NR(cmd) == _IOC_NR(SPI_IOC_MESSAGE(0)) + && _IOC_DIR(cmd) == _IOC_WRITE) + return spidev_compat_ioc_message(filp, cmd, arg); + + return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#else +#define spidev_compat_ioctl NULL +#endif /* CONFIG_COMPAT */ + +static int spidev_open(struct inode *inode, struct file *filp) +{ + struct spidev_data *spidev; + int status = -ENXIO; + + mutex_lock(&device_list_lock); + + list_for_each_entry(spidev, &device_list, device_entry) { + if (spidev->devt == inode->i_rdev) { + status = 0; + break; + } + } + + if (status) { + pr_debug("spidev: nothing for minor %d\n", iminor(inode)); + goto err_find_dev; + } + + if (!spidev->tx_buffer) { + spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); + if (!spidev->tx_buffer) { + dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); + status = -ENOMEM; + goto err_find_dev; + } + } + + if (!spidev->rx_buffer) { + spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); + if (!spidev->rx_buffer) { + dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); + status = -ENOMEM; + goto err_alloc_rx_buf; + } + } + + spidev->users++; + filp->private_data = spidev; + nonseekable_open(inode, filp); + + mutex_unlock(&device_list_lock); + return 0; + +err_alloc_rx_buf: + kfree(spidev->tx_buffer); + spidev->tx_buffer = NULL; +err_find_dev: + mutex_unlock(&device_list_lock); + return status; +} + +static int spidev_release(struct inode *inode, struct file *filp) +{ + struct spidev_data *spidev; + + mutex_lock(&device_list_lock); + spidev = filp->private_data; + filp->private_data = NULL; + + /* last close? */ + spidev->users--; + if (!spidev->users) { + int dofree; + + kfree(spidev->tx_buffer); + spidev->tx_buffer = NULL; + + kfree(spidev->rx_buffer); + spidev->rx_buffer = NULL; + + spin_lock_irq(&spidev->spi_lock); + if (spidev->spi) + spidev->speed_hz = spidev->spi->max_speed_hz; + + /* ... after we unbound from the underlying device? */ + dofree = (spidev->spi == NULL); + spin_unlock_irq(&spidev->spi_lock); + + if (dofree) + kfree(spidev); + } + mutex_unlock(&device_list_lock); + + return 0; +} + +static const struct file_operations spidev_fops = { + .owner = THIS_MODULE, + /* REVISIT switch to aio primitives, so that userspace + * gets more complete API coverage. It'll simplify things + * too, except for the locking. + */ + .write = spidev_write, + .read = spidev_read, + .unlocked_ioctl = spidev_ioctl, + .compat_ioctl = spidev_compat_ioctl, + .open = spidev_open, + .release = spidev_release, + .llseek = no_llseek, +}; + +/*-------------------------------------------------------------------------*/ + +/* The main reason to have this class is to make mdev/udev create the + * /dev/spidevB.C character device nodes exposing our userspace API. + * It also simplifies memory management. + */ + +static struct class *spidev_class; + +#ifdef CONFIG_OF +static const struct of_device_id spidev_dt_ids[] = { + { .compatible = "commaai,panda" }, + {}, +}; +MODULE_DEVICE_TABLE(of, spidev_dt_ids); +#endif + +#ifdef CONFIG_ACPI + +/* Dummy SPI devices not to be used in production systems */ +#define SPIDEV_ACPI_DUMMY 1 + +static const struct acpi_device_id spidev_acpi_ids[] = { + /* + * The ACPI SPT000* devices are only meant for development and + * testing. Systems used in production should have a proper ACPI + * description of the connected peripheral and they should also use + * a proper driver instead of poking directly to the SPI bus. + */ + { "SPT0001", SPIDEV_ACPI_DUMMY }, + { "SPT0002", SPIDEV_ACPI_DUMMY }, + { "SPT0003", SPIDEV_ACPI_DUMMY }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, spidev_acpi_ids); + +static void spidev_probe_acpi(struct spi_device *spi) +{ + const struct acpi_device_id *id; + + if (!has_acpi_companion(&spi->dev)) + return; + + id = acpi_match_device(spidev_acpi_ids, &spi->dev); + if (WARN_ON(!id)) + return; + + if (id->driver_data == SPIDEV_ACPI_DUMMY) + dev_warn(&spi->dev, "do not use this driver in production systems!\n"); +} +#else +static inline void spidev_probe_acpi(struct spi_device *spi) {} +#endif + +/*-------------------------------------------------------------------------*/ + +static int spidev_probe(struct spi_device *spi) +{ + struct spidev_data *spidev; + int status; + unsigned long minor; + + /* + * spidev should never be referenced in DT without a specific + * compatible string, it is a Linux implementation thing + * rather than a description of the hardware. + */ + if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) { + dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n"); + WARN_ON(spi->dev.of_node && + !of_match_device(spidev_dt_ids, &spi->dev)); + } + + spidev_probe_acpi(spi); + + /* Allocate driver data */ + spidev = kzalloc(sizeof(*spidev), GFP_KERNEL); + if (!spidev) + return -ENOMEM; + + /* Initialize the driver data */ + spidev->spi = spi; + spin_lock_init(&spidev->spi_lock); + mutex_init(&spidev->buf_lock); + + INIT_LIST_HEAD(&spidev->device_entry); + + /* If we can allocate a minor number, hook up this device. + * Reusing minors is fine so long as udev or mdev is working. + */ + mutex_lock(&device_list_lock); + minor = find_first_zero_bit(minors, N_SPI_MINORS); + if (minor < N_SPI_MINORS) { + struct device *dev; + + spidev->devt = MKDEV(SPIDEV_MAJOR, minor); + dev = device_create(spidev_class, &spi->dev, spidev->devt, + spidev, "spidev%d.%d", + spi->master->bus_num, spi->chip_select); + status = PTR_ERR_OR_ZERO(dev); + } else { + dev_dbg(&spi->dev, "no minor number available!\n"); + status = -ENODEV; + } + if (status == 0) { + set_bit(minor, minors); + list_add(&spidev->device_entry, &device_list); + } + mutex_unlock(&device_list_lock); + + spidev->speed_hz = spi->max_speed_hz; + + if (status == 0) + spi_set_drvdata(spi, spidev); + else + kfree(spidev); + + return status; +} + +static int spidev_remove(struct spi_device *spi) +{ + struct spidev_data *spidev = spi_get_drvdata(spi); + + /* make sure ops on existing fds can abort cleanly */ + spin_lock_irq(&spidev->spi_lock); + spidev->spi = NULL; + spin_unlock_irq(&spidev->spi_lock); + + /* prevent new opens */ + mutex_lock(&device_list_lock); + list_del(&spidev->device_entry); + device_destroy(spidev_class, spidev->devt); + clear_bit(MINOR(spidev->devt), minors); + if (spidev->users == 0) + kfree(spidev); + mutex_unlock(&device_list_lock); + + return 0; +} + +static struct spi_driver spidev_spi_driver = { + .driver = { + .name = "spidev_panda", + .of_match_table = of_match_ptr(spidev_dt_ids), + .acpi_match_table = ACPI_PTR(spidev_acpi_ids), + }, + .probe = spidev_probe, + .remove = spidev_remove, + + /* NOTE: suspend/resume methods are not necessary here. + * We don't do anything except pass the requests to/from + * the underlying controller. The refrigerator handles + * most issues; the controller driver handles the rest. + */ +}; + +/*-------------------------------------------------------------------------*/ + +static int __init spidev_init(void) +{ + int status; + + /* Claim our 256 reserved device numbers. Then register a class + * that will key udev/mdev to add/remove /dev nodes. Last, register + * the driver which manages those device numbers. + */ + BUILD_BUG_ON(N_SPI_MINORS > 256); + status = register_chrdev(0, "spi", &spidev_fops); + if (status < 0) + return status; + + SPIDEV_MAJOR = status; + + spidev_class = class_create(THIS_MODULE, "spidev_panda"); + if (IS_ERR(spidev_class)) { + unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); + return PTR_ERR(spidev_class); + } + + status = spi_register_driver(&spidev_spi_driver); + if (status < 0) { + class_destroy(spidev_class); + unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); + } + return status; +} +module_init(spidev_init); + +static void __exit spidev_exit(void) +{ + spi_unregister_driver(&spidev_spi_driver); + class_destroy(spidev_class); + unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); +} +module_exit(spidev_exit); + +MODULE_AUTHOR("Andrea Paterniani, "); +MODULE_DESCRIPTION("User mode SPI device interface"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:spidev"); diff --git a/panda_tici/examples/__init__.py b/panda_tici/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panda_tici/examples/can_bit_transition.md b/panda_tici/examples/can_bit_transition.md new file mode 100644 index 0000000..fa0a6c6 --- /dev/null +++ b/panda_tici/examples/can_bit_transition.md @@ -0,0 +1,25 @@ +# How to use can_bit_transition.py to reverse engineer a single bit field + +Let's say our goal is to find a brake pedal signal (caused by your foot pressing the brake pedal vs adaptive cruise control braking). + +The following process will allow you to quickly find bits that are always 0 during a period of time (when you know you were not pressing the brake with your foot) and always 1 in a different period of time (when you know you were pressing the brake with your foot). + +Open up a drive in cabana where you can find a place you used the brake pedal and another place where you did not use the brake pedal (and you can identify when you were on the brake pedal and when you were not). You may want to go out for a drive and put something in front of the camera after you put your foot on the brake and take it away before you take your foot off the brake so you can easily identify exactly when you had your foot on the brake based on the video in cabana. This is critical because this script needs the brake signal to always be high the entire time for one of the time frames. A 10 second time frame worked well for me. + +I found a drive where I knew I was not pressing the brake between timestamp 50.0 thru 65.0 and I was pressing the brake between timestamp 69.0 thru 79.0. Determine what the timestamps are in cabana by plotting any message and putting your mouse over the plot at the location you want to discover the timestamp. The tool tip on mouse hover has the format: timestamp: value + +Now download the log from cabana (Save Log button) and run the script passing in the timestamps +(replace csv file name with cabana log you downloaded and time ranges with your own) +``` +./can_bit_transition.py ./honda_crv_ex_2017_can-1520354796875.csv 50.0-65.0 69.0-79.0 +``` + +The script will output bits that were always low in the first time range and always high in the second time range (and vice versa) +``` +id 17c 0 -> 1 at byte 4 bitmask 1 +id 17c 0 -> 1 at byte 6 bitmask 32 +id 221 1 -> 0 at byte 0 bitmask 4 +id 1be 0 -> 1 at byte 0 bitmask 16 +``` + +Now I go back to cabana and graph the above bits by searching for the message by id, double clicking on the appropriate bit, and then selecting "show plot". I already knew that message id 0x17c is both user brake and adaptive cruise control braking combined, so I plotted one of those signals along side 0x221 and 0x1be. By replaying a drive I could see that 0x221 was not a brake signal (when high at random times that did not correspond to braking). Next I looked at 0x1be and I found it was the brake pedal signal I was looking for (went high whenever I pressed the brake pedal and did not go high when adaptive cruise control was braking). \ No newline at end of file diff --git a/panda_tici/examples/can_bit_transition.py b/panda_tici/examples/can_bit_transition.py new file mode 100755 index 0000000..1e7bad5 --- /dev/null +++ b/panda_tici/examples/can_bit_transition.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +import csv +import sys + +CSV_KEYS = { + "logger": { + "time": "Time", + "message_id": "MessageID", + "data": "Message", + "bus": "Bus" + }, + "cabana": { + "time": "time", + "message_id": "addr", + "data": "data", + "bus": "bus" + } +} + + +class Message(): + """Details about a specific message ID.""" + + def __init__(self, message_id): + self.message_id = message_id + self.ones = [0] * 64 # bit set if 1 is always seen + self.zeros = [0] * 64 # bit set if 0 is always seen + + def printBitDiff(self, other): + """Prints bits that transition from always zero to always 1 and vice versa.""" + for i in range(len(self.ones)): + zero_to_one = other.zeros[i] & self.ones[i] + if zero_to_one: + print('id %s 0 -> 1 at byte %d bitmask %d' % (self.message_id, i, zero_to_one)) + one_to_zero = other.ones[i] & self.zeros[i] + if one_to_zero: + print('id %s 1 -> 0 at byte %d bitmask %d' % (self.message_id, i, one_to_zero)) + + +class Info(): + """A collection of Messages.""" + + def __init__(self): + self.messages = {} # keyed by MessageID + + def load(self, filename, start, end): + """Given a CSV file, adds information about message IDs and their values.""" + with open(filename, newline='') as inp: + reader = csv.DictReader(inp) + dtype = None + for row in reader: + if not len(row): + continue + if dtype is None: + dtype = "logger" if "Bus" in row else "cabana" + + time = float(row[CSV_KEYS[dtype]["time"]]) + bus = int(row[CSV_KEYS[dtype]["bus"]]) + if time < start or bus > 127: + continue + elif time > end: + break + + message_id = row[CSV_KEYS[dtype]["message_id"]] + if message_id.startswith('0x'): + message_id = message_id[2:] # remove leading '0x' + else: + message_id = hex(int(message_id))[2:] # old message IDs are in decimal + message_id = f'{bus}:{message_id}' + + data = row[CSV_KEYS[dtype]["data"]] + if data.startswith('0x'): + data = data[2:] # remove leading '0x' + else: + data = data + new_message = False + if message_id not in self.messages: + self.messages[message_id] = Message(message_id) + new_message = True + message = self.messages[message_id] + bts = bytearray.fromhex(data) + for i in range(len(bts)): + ones = int(bts[i]) + message.ones[i] = ones if new_message else message.ones[i] & ones + # Inverts the data and masks it to a byte to get the zeros as ones. + zeros = (~int(bts[i])) & 0xff + message.zeros[i] = zeros if new_message else message.zeros[i] & zeros + +def PrintUnique(log_file, low_range, high_range): + # find messages with bits that are always low + start, end = list(map(float, low_range.split('-'))) + low = Info() + low.load(log_file, start, end) + # find messages with bits that are always high + start, end = list(map(float, high_range.split('-'))) + high = Info() + high.load(log_file, start, end) + # print messages that go from low to high + found = False + for message_id in sorted(high.messages, key=lambda x: int(x.split(':')[1], 16)): + if message_id in low.messages: + high.messages[message_id].printBitDiff(low.messages[message_id]) + found = True + if not found: + print('No messages that transition from always low to always high found!') + +if __name__ == "__main__": + if len(sys.argv) < 4: + print('Usage:\n%s log.csv - -' % sys.argv[0]) + sys.exit(0) + PrintUnique(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/panda_tici/examples/can_logger.py b/panda_tici/examples/can_logger.py new file mode 100755 index 0000000..ad77072 --- /dev/null +++ b/panda_tici/examples/can_logger.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +import csv +import time +from panda_tici import Panda + +def can_logger(): + p = Panda() + + try: + outputfile = open('output.csv', 'w') + csvwriter = csv.writer(outputfile) + # Write Header + csvwriter.writerow(['Bus', 'MessageID', 'Message', 'MessageLength', 'Time']) + print("Writing csv file output.csv. Press Ctrl-C to exit...\n") + + bus0_msg_cnt = 0 + bus1_msg_cnt = 0 + bus2_msg_cnt = 0 + + start_time = time.time() + while True: + can_recv = p.can_recv() + + for address, dat, src in can_recv: + csvwriter.writerow( + [str(src), str(hex(address)), f"0x{dat.hex()}", len(dat), str(time.time() - start_time)]) + + if src == 0: + bus0_msg_cnt += 1 + elif src == 1: + bus1_msg_cnt += 1 + elif src == 2: + bus2_msg_cnt += 1 + + print(f"Message Counts... Bus 0: {bus0_msg_cnt} Bus 1: {bus1_msg_cnt} Bus 2: {bus2_msg_cnt}", end='\r') + + except KeyboardInterrupt: + print(f"\nNow exiting. Final message Counts... Bus 0: {bus0_msg_cnt} Bus 1: {bus1_msg_cnt} Bus 2: {bus2_msg_cnt}") + outputfile.close() + +if __name__ == "__main__": + can_logger() diff --git a/panda_tici/examples/can_unique.md b/panda_tici/examples/can_unique.md new file mode 100644 index 0000000..4d8ac46 --- /dev/null +++ b/panda_tici/examples/can_unique.md @@ -0,0 +1,103 @@ +# How to use can_unique.py to reverse engineer a single bit field + +Let's say our goal is to find the CAN message indicating that the driver's door is either open or closed. +The following process is great for simple single-bit messages. +However for frequently changing values, such as RPM or speed, Cabana's graphical plots are probably better to use. + + +First record a few minutes of background CAN messages with all the doors closed and save it in background.csv: +``` +./can_logger.py +mv output.csv background.csv +``` +Then run can_logger.py for a few seconds while performing the action you're interested, such as opening and then closing the +front-left door and save it as door-fl-1.csv +Repeat the process and save it as door-f1-2.csv to have an easy way to confirm any suspicions. + +Now we'll use can_unique.py to look for unique bits: +``` +$ ./can_unique.py door-fl-1.csv background* +id 820 new one at byte 2 bitmask 2 +id 520 new one at byte 3 bitmask 7 +id 520 new zero at byte 3 bitmask 8 +id 520 new one at byte 5 bitmask 6 +id 520 new zero at byte 5 bitmask 9 +id 559 new zero at byte 6 bitmask 4 +id 804 new one at byte 5 bitmask 2 +id 804 new zero at byte 5 bitmask 1 + +$ ./can_unique.py door-fl-2.csv background* +id 672 new one at byte 3 bitmask 3 +id 820 new one at byte 2 bitmask 2 +id 520 new one at byte 3 bitmask 7 +id 520 new zero at byte 3 bitmask 8 +id 520 new one at byte 5 bitmask 6 +id 520 new zero at byte 5 bitmask 9 +id 559 new zero at byte 6 bitmask 4 +``` + +One of these bits hopefully indicates that the driver's door is open. +Let's go through each message ID to figure out which one is correct. +We expect any correct bits to have changed in both runs. +We can rule out 804 because it only occurred in the first run. +We can rule out 672 because it only occurred in the second run. +That leaves us with these message IDs: 820, 520, 559. Let's take a closer look at each one. + +``` +$ fgrep ,559, door-fl-1.csv |head +0,559,00ff0000000024f0 +0,559,00ff000000004464 +0,559,00ff0000000054a9 +0,559,00ff0000000064e3 +0,559,00ff00000000742e +0,559,00ff000000008451 +0,559,00ff00000000949c +0,559,00ff00000000a4d6 +0,559,00ff00000000b41b +0,559,00ff00000000c442 +``` +Message ID 559 looks like an incrementing value, so it's not what we're looking for. + +``` +$ fgrep ,520, door-fl-2.csv +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +``` +Message ID 520 oscillates between two values. However I only opened and closed the door once, so this is probably not it. + +``` +$ fgrep ,820, door-fl-1.csv +0,820,44000100a500c802 +0,820,44000100a500c803 +0,820,44000300a500c803 +0,820,44000300a500c802 +0,820,44000300a500c802 +0,820,44000300a500c802 +0,820,44000100a500c802 +0,820,44000100a500c802 +0,820,44000100a500c802 +``` +Message ID 820 looks promising! It starts off at 44000100a500c802 when the door is closed. +When the door is open it goes to 44000300a500c802. +Then when the door is closed again, it goes back to 44000100a500c802. +Let's confirm by looking at the data from our other run: +``` +$ fgrep ,820, door-fl-2.csv +0,820,44000100a500c802 +0,820,44000300a500c802 +0,820,44000100a500c802 +``` +Perfect! We now know that message id 820 at byte 2 bitmask 2 is set if the driver's door is open. +If we repeat the process with the front passenger's door, +then we'll find that message id 820 at byte 2 bitmask 4 is set if the front-right door is open. +This confirms our finding because it's common for similar signals to be near each other. diff --git a/panda_tici/examples/can_unique.py b/panda_tici/examples/can_unique.py new file mode 100755 index 0000000..05977af --- /dev/null +++ b/panda_tici/examples/can_unique.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +# Given an interesting CSV file of CAN messages and a list of background CAN +# messages, print which bits in the interesting file have never appeared +# in the background files. + +# Expects the CSV file to be in one of the following formats: + +# can_logger.py +# Bus,MessageID,Message,MessageLength +# 0,0x292,0x040000001068,6 + +# The old can_logger.py format is also supported: +# Bus,MessageID,Message +# 0,344,c000c00000000000 + +# Cabana "Save Log" format +# time,addr,bus,data +# 240.47911496100002,53,0,0acc0ade0074bf9e + + +import csv +import sys + +class Message(): + """Details about a specific message ID.""" + + def __init__(self, message_id): + self.message_id = message_id + self.data = {} # keyed by hex string encoded message data + self.ones = [0] * 64 # bit set if 1 is seen + self.zeros = [0] * 64 # bit set if 0 has been seen + + def printBitDiff(self, other): + """Prints bits that are set or cleared compared to other background.""" + for i in range(len(self.ones)): + new_ones = ((~other.ones[i]) & 0xff) & self.ones[i] + if new_ones: + print('id %s new one at byte %d bitmask %d' % ( + self.message_id, i, new_ones)) + new_zeros = ((~other.zeros[i]) & 0xff) & self.zeros[i] + if new_zeros: + print('id %s new zero at byte %d bitmask %d' % ( + self.message_id, i, new_zeros)) + + +class Info(): + """A collection of Messages.""" + + def __init__(self): + self.messages = {} # keyed by MessageID + + def load(self, filename): + """Given a CSV file, adds information about message IDs and their values.""" + with open(filename) as inp: + reader = csv.reader(inp) + header = next(reader, None) + if header[0] == 'time': + self.cabana(reader) + else: + self.logger(reader) + + def cabana(self, reader): + for row in reader: + bus = row[2] + message_id = hex(int(row[1]))[2:] + message_id = f'{bus}:{message_id}' + data = row[3] + self.store(message_id, data) + + def logger(self, reader): + for row in reader: + bus = row[0] + if row[1].startswith('0x'): + message_id = row[1][2:] # remove leading '0x' + else: + message_id = hex(int(row[1]))[2:] # old message IDs are in decimal + message_id = f'{bus}:{message_id}' + if row[1].startswith('0x'): + data = row[2][2:] # remove leading '0x' + else: + data = row[2] + self.store(message_id, data) + + def store(self, message_id, data): + if message_id not in self.messages: + self.messages[message_id] = Message(message_id) + message = self.messages[message_id] + if data not in self.messages[message_id].data: + message.data[data] = True + bts = bytearray.fromhex(data) + for i in range(len(bts)): + message.ones[i] = message.ones[i] | int(bts[i]) + # Inverts the data and masks it to a byte to get the zeros as ones. + message.zeros[i] = message.zeros[i] | ((~int(bts[i])) & 0xff) + + +def PrintUnique(interesting_file, background_files): + background = Info() + for background_file in background_files: + background.load(background_file) + interesting = Info() + interesting.load(interesting_file) + for message_id in sorted(interesting.messages): + if message_id not in background.messages: + print('New message_id: %s' % message_id) + else: + interesting.messages[message_id].printBitDiff( + background.messages[message_id]) + + +if __name__ == "__main__": + if len(sys.argv) < 3: + print('Usage:\n%s interesting.csv background*.csv' % sys.argv[0]) + sys.exit(0) + PrintUnique(sys.argv[1], sys.argv[2:]) diff --git a/panda_tici/examples/query_fw_versions.py b/panda_tici/examples/query_fw_versions.py new file mode 100755 index 0000000..d8130a2 --- /dev/null +++ b/panda_tici/examples/query_fw_versions.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +import argparse +from tqdm import tqdm +from opendbc.car.carlog import carlog +from opendbc.car.uds import UdsClient, MessageTimeoutError, NegativeResponseError, InvalidSubAddressError, \ + SESSION_TYPE, DATA_IDENTIFIER_TYPE +from opendbc.car.structs import CarParams +from panda_tici import Panda + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--rxoffset", default="") + parser.add_argument("--nonstandard", action="store_true") + parser.add_argument("--no-obd", action="store_true", help="Bus 1 will not be multiplexed to the OBD-II port") + parser.add_argument("--no-29bit", action="store_true", help="29 bit addresses will not be queried") + parser.add_argument("--debug", action="store_true") + parser.add_argument("--addr") + parser.add_argument("--sub_addr", "--subaddr", help="A hex sub-address or `scan` to scan the full sub-address range") + parser.add_argument("--bus") + parser.add_argument('-s', '--serial', help="Serial number of panda to use") + args = parser.parse_args() + + if args.debug: + carlog.setLevel('DEBUG') + + if args.addr: + addrs = [int(args.addr, base=16)] + else: + addrs = [0x700 + i for i in range(256)] + if not args.no_29bit: + addrs += [0x18da0000 + (i << 8) + 0xf1 for i in range(256)] + results = {} + + sub_addrs: list[int | None] = [None] + if args.sub_addr: + if args.sub_addr == "scan": + sub_addrs = list(range(0xff + 1)) + else: + sub_addrs = [int(args.sub_addr, base=16)] + if sub_addrs[0] > 0xff: # type: ignore + print(f"Invalid sub-address: 0x{sub_addrs[0]:X}, needs to be in range 0x0 to 0xff") + parser.print_help() + exit() + + uds_data_ids = {} + for std_id in DATA_IDENTIFIER_TYPE: + uds_data_ids[std_id.value] = std_id.name + if args.nonstandard: + for uds_id in range(0xf100, 0xf180): + uds_data_ids[uds_id] = "IDENTIFICATION_OPTION_VEHICLE_MANUFACTURER_SPECIFIC_DATA_IDENTIFIER" + for uds_id in range(0xf1a0, 0xf1f0): + uds_data_ids[uds_id] = "IDENTIFICATION_OPTION_VEHICLE_MANUFACTURER_SPECIFIC" + for uds_id in range(0xf1f0, 0xf200): + uds_data_ids[uds_id] = "IDENTIFICATION_OPTION_SYSTEM_SUPPLIER_SPECIFIC" + + panda_serials = Panda.list() + if args.serial is None and len(panda_serials) > 1: + print("\nMultiple pandas found, choose one:") + for serial in panda_serials: + with Panda(serial) as panda: + print(f" {serial}: internal={panda.is_internal()}") + print() + parser.print_help() + exit() + + panda = Panda(serial=args.serial) + panda.set_safety_mode(CarParams.SafetyModel.elm327, 1 if args.no_obd else 0) + print("querying addresses ...") + with tqdm(addrs) as t: + for addr in t: + # skip functional broadcast addrs + if addr == 0x7df or addr == 0x18db33f1: + continue + + if args.bus: + bus = int(args.bus) + else: + bus = 1 if panda.has_obd() else 0 + rx_addr = addr + int(args.rxoffset, base=16) if args.rxoffset else None + + # Try all sub-addresses for addr. By default, this is None + for sub_addr in sub_addrs: + sub_addr_str = hex(sub_addr) if sub_addr is not None else None + t.set_description(f"{hex(addr)}, {sub_addr_str}") + uds_client = UdsClient(panda, addr, rx_addr, bus, sub_addr=sub_addr, timeout=0.2) + # Check for anything alive at this address, and switch to the highest + # available diagnostic session without security access + try: + uds_client.tester_present() + uds_client.diagnostic_session_control(SESSION_TYPE.DEFAULT) + uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC) + except NegativeResponseError: + pass + except MessageTimeoutError: + continue + except InvalidSubAddressError as e: + print(f'*** Skipping address {hex(addr)}: {e}') + break + + # Run queries against all standard UDS data identifiers, plus selected + # non-standardized identifier ranges if requested + resp = {} + for uds_data_id in sorted(uds_data_ids): + try: + data = uds_client.read_data_by_identifier(DATA_IDENTIFIER_TYPE(uds_data_id)) + if data: + resp[uds_data_id] = data + except (NegativeResponseError, MessageTimeoutError, InvalidSubAddressError): + pass + + if resp.keys(): + results[(addr, sub_addr)] = resp + + if len(results.items()): + for (addr, sub_addr), resp in results.items(): + sub_addr_str = f", sub-address 0x{sub_addr:X}" if sub_addr is not None else "" + print(f"\n\n*** Results for address 0x{addr:X}{sub_addr_str} ***\n\n") + for rid, dat in resp.items(): + print(f"0x{rid:02X} {uds_data_ids[rid]}: {dat}") + else: + print("no fw versions found!") diff --git a/panda_tici/examples/query_vin_and_stats.py b/panda_tici/examples/query_vin_and_stats.py new file mode 100755 index 0000000..2316896 --- /dev/null +++ b/panda_tici/examples/query_vin_and_stats.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +import time +import struct +from opendbc.car.structs import CarParams +from panda_tici import Panda +from hexdump import hexdump +from opendbc.car.isotp import isotp_send, isotp_recv + +# 0x7e0 = Toyota +# 0x18DB33F1 for Honda? + + +def get_current_data_for_pid(pid): + # 01 xx = Show current data + isotp_send(panda, b"\x01" + bytes([pid]), 0x7e0) + return isotp_recv(panda, 0x7e8) + +def get_supported_pids(): + ret = [] + pid = 0 + while 1: + supported = struct.unpack(">I", get_current_data_for_pid(pid)[2:])[0] + for i in range(1 + pid, 0x21 + pid): + if supported & 0x80000000: + ret.append(i) + supported <<= 1 + pid += 0x20 + if pid not in ret: + break + return ret + +if __name__ == "__main__": + panda = Panda() + panda.set_safety_mode(CarParams.SafetyModel.elm327) + panda.can_clear(0) + + # 09 02 = Get VIN + isotp_send(panda, b"\x09\x02", 0x7df) + ret = isotp_recv(panda, 0x7e8) + hexdump(ret) + print("VIN: %s" % "".join(map(chr, ret[:2]))) + + # 03 = get DTCS + isotp_send(panda, b"\x03", 0x7e0) + dtcs = isotp_recv(panda, 0x7e8) + print("DTCs:", "".join(map(chr, dtcs[:2]))) + + supported_pids = get_supported_pids() + print("Supported PIDs:", supported_pids) + + while 1: + speed = struct.unpack(">B", get_current_data_for_pid(13)[2:])[0] # kph + rpm = struct.unpack(">H", get_current_data_for_pid(12)[2:])[0] / 4.0 # revs + throttle = struct.unpack(">B", get_current_data_for_pid(17)[2:])[0] / 255.0 * 100 # percent + temp = struct.unpack(">B", get_current_data_for_pid(5)[2:])[0] - 40 # degrees C + load = struct.unpack(">B", get_current_data_for_pid(4)[2:])[0] / 255.0 * 100 # percent + print("%d KPH, %d RPM, %.1f%% Throttle, %d deg C, %.1f%% load" % (speed, rpm, throttle, temp, load)) + time.sleep(0.2) diff --git a/panda_tici/examples/tesla_tester.py b/panda_tici/examples/tesla_tester.py new file mode 100755 index 0000000..d075fc2 --- /dev/null +++ b/panda_tici/examples/tesla_tester.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +import binascii +from opendbc.car.structs import CarParams +from panda_tici import Panda + +def tesla_tester(): + p = Panda() + + body_bus_speed = 125 # Tesla Body busses (B, BF) are 125kbps, rest are 500kbps + body_bus_num = 1 # My TDC to OBD adapter has PT on bus0 BDY on bus1 and CH on bus2 + p.set_can_speed_kbps(body_bus_num, body_bus_speed) + + # Now set the panda from its default of SAFETY_SILENT (read only) to SAFETY_ALLOUTPUT + # Careful, as this will let us send any CAN messages we want (which could be very bad!) + print("Setting Panda to output mode...") + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + # BDY 0x248 is the MCU_commands message, which includes folding mirrors, opening the trunk, frunk, setting the cars lock state and more. + # For our test, we will edit the 3rd byte, which is MCU_lockRequest. 0x01 will lock, 0x02 will unlock: + print("Unlocking Tesla...") + p.can_send(0x248, b"\x00\x00\x02\x00\x00\x00\x00\x00", body_bus_num) + + #Or, we can set the first byte, MCU_frontHoodCommand + MCU_liftgateSwitch, to 0x01 to pop the frunk, or 0x04 to open/close the trunk (0x05 should open both) + print("Opening Frunk...") + p.can_send(0x248, b"\x01\x00\x00\x00\x00\x00\x00\x00", body_bus_num) + + #Back to safety... + print("Disabling output on Panda...") + p.set_safety_mode(CarParams.SafetyModel.silent) + + print("Reading VIN from 0x568. This is painfully slow and can take up to 3 minutes (1 minute per message; 3 messages needed for full VIN)...") + + vin = {} + while True: + #Read the VIN + can_recv = p.can_recv() + for address, dat, src in can_recv: + if src == body_bus_num: + if address == 1384: # 0x568 is VIN + vin_index = int(binascii.hexlify(dat)[:2]) # first byte is the index, 00, 01, 02 + vin_string = binascii.hexlify(dat)[2:] # rest of the string is the actual VIN data + vin[vin_index] = vin_string.decode("hex") + print("Got VIN index " + str(vin_index) + " data " + vin[vin_index]) + #if we have all 3 parts of the VIN, print it and break out of our while loop + if 0 in vin and 1 in vin and 2 in vin: + print("VIN: " + vin[0] + vin[1] + vin[2][:3]) + break + +if __name__ == "__main__": + tesla_tester() diff --git a/panda_tici/pyproject.toml b/panda_tici/pyproject.toml new file mode 100644 index 0000000..3b58209 --- /dev/null +++ b/panda_tici/pyproject.toml @@ -0,0 +1,76 @@ +[project] +name = "pandacan" +version = "0.0.10" +description = "Code powering the comma.ai panda" +readme = "README.md" +requires-python = ">=3.11,<3.13" +license = {text = "MIT"} +authors = [{name = "comma.ai"}] +classifiers = [ + "Natural Language :: English", + "Programming Language :: Python :: 3", + "Topic :: System :: Hardware", +] +dependencies = [ + "libusb1", + "opendbc @ git+https://github.com/commaai/opendbc.git@45bf6c8f548473dece52f780f60bd8e20c32bd65#egg=opendbc", +] + +[project.optional-dependencies] +dev = [ + "scons", + "pycryptodome >= 3.9.8", + "cffi", + "flaky", + "pytest", + "pytest-mock", + "pytest-xdist", + "pytest-timeout", + "pytest-randomly", + "ruff", + "mypy", + "setuptools", + "spidev; platform_system == 'Linux'", +] + +[build-system] +requires = ["setuptools>=61", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +packages = ["panda_tici"] + +[tool.setuptools.package-dir] +panda = "." + +[tool.mypy] +# third-party packages +ignore_missing_imports = true + +# helpful warnings +warn_redundant_casts = true +warn_unreachable = true +warn_unused_ignores = true + +# restrict dynamic typing +warn_return_any = true + +# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml +[tool.ruff] +line-length = 160 +target-version="py311" + +[tool.ruff.lint] +select = ["E", "F", "W", "PIE", "C4", "ISC", "RUF100", "A"] +ignore = ["W292", "E741", "E402", "C408", "ISC003"] +flake8-implicit-str-concat.allow-multiline=false + +[tool.ruff.lint.flake8-tidy-imports.banned-api] +"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!" + +[tool.pytest.ini_options] +addopts = "-n0 -Werror --strict-config --strict-markers --durations=10 --ignore-glob='*.sh' --ignore=tests/misra --ignore=tests/som --ignore=tests/hitl" +python_files = "test_*.py" +testpaths = [ + "tests/" +] \ No newline at end of file diff --git a/panda_tici/python/__init__.py b/panda_tici/python/__init__.py new file mode 100644 index 0000000..10dc368 --- /dev/null +++ b/panda_tici/python/__init__.py @@ -0,0 +1,860 @@ +# python library to interface with panda +import os +import sys +import time +import usb1 +import struct +import hashlib +import binascii +from functools import wraps, partial +from itertools import accumulate + +from opendbc.car.structs import CarParams + +from .base import BaseHandle +from .constants import FW_PATH, McuType +from .dfu import PandaDFU +from .spi import PandaSpiHandle, PandaSpiException, PandaProtocolMismatch +from .usb import PandaUsbHandle +from .utils import logger + +__version__ = '0.0.10' + +CANPACKET_HEAD_SIZE = 0x6 +DLC_TO_LEN = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64] +LEN_TO_DLC = {length: dlc for (dlc, length) in enumerate(DLC_TO_LEN)} +PANDA_CAN_CNT = 3 + + +def calculate_checksum(data): + res = 0 + for b in data: + res ^= b + return res + +def pack_can_buffer(arr, fd=False): + snds = [b''] + for address, dat, bus in arr: + assert len(dat) in LEN_TO_DLC + #logger.debug(" W 0x%x: 0x%s", address, dat.hex()) + + extended = 1 if address >= 0x800 else 0 + data_len_code = LEN_TO_DLC[len(dat)] + header = bytearray(CANPACKET_HEAD_SIZE) + word_4b = address << 3 | extended << 2 + header[0] = (data_len_code << 4) | (bus << 1) | int(fd) + header[1] = word_4b & 0xFF + header[2] = (word_4b >> 8) & 0xFF + header[3] = (word_4b >> 16) & 0xFF + header[4] = (word_4b >> 24) & 0xFF + header[5] = calculate_checksum(header[:5] + dat) + + snds[-1] += header + dat + if len(snds[-1]) > 256: # Limit chunks to 256 bytes + snds.append(b'') + + return snds + +def unpack_can_buffer(dat): + ret = [] + + while len(dat) >= CANPACKET_HEAD_SIZE: + data_len = DLC_TO_LEN[(dat[0]>>4)] + + header = dat[:CANPACKET_HEAD_SIZE] + + bus = (header[0] >> 1) & 0x7 + address = (header[4] << 24 | header[3] << 16 | header[2] << 8 | header[1]) >> 3 + + if (header[1] >> 1) & 0x1: + # returned + bus += 128 + if header[1] & 0x1: + # rejected + bus += 192 + + # we need more from the next transfer + if data_len > len(dat) - CANPACKET_HEAD_SIZE: + break + + assert calculate_checksum(dat[:(CANPACKET_HEAD_SIZE+data_len)]) == 0, "CAN packet checksum incorrect" + + data = dat[CANPACKET_HEAD_SIZE:(CANPACKET_HEAD_SIZE+data_len)] + dat = dat[(CANPACKET_HEAD_SIZE+data_len):] + + ret.append((address, data, bus)) + + return (ret, dat) + + +def ensure_version(desc, lib_field, panda_field, fn): + @wraps(fn) + def wrapper(self, *args, **kwargs): + lib_version = getattr(self, lib_field) + panda_version = getattr(self, panda_field) + if lib_version != panda_version: + raise RuntimeError(f"{desc} packet version mismatch: panda's firmware v{panda_version}, library v{lib_version}. Reflash panda.") + return fn(self, *args, **kwargs) + return wrapper +ensure_can_packet_version = partial(ensure_version, "CAN", "CAN_PACKET_VERSION", "can_version") +ensure_can_health_packet_version = partial(ensure_version, "CAN health", "CAN_HEALTH_PACKET_VERSION", "can_health_version") +ensure_health_packet_version = partial(ensure_version, "health", "HEALTH_PACKET_VERSION", "health_version") + + + +class Panda: + + SERIAL_DEBUG = 0 + SERIAL_ESP = 1 + SERIAL_LIN1 = 2 + SERIAL_LIN2 = 3 + SERIAL_SOM_DEBUG = 4 + + USB_VIDS = (0xbbaa, 0x3801) # 0x3801 is comma's registered VID + USB_PIDS = (0xddee, 0xddcc) + REQUEST_IN = usb1.ENDPOINT_IN | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE + REQUEST_OUT = usb1.ENDPOINT_OUT | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE + + HW_TYPE_UNKNOWN = b'\x00' + HW_TYPE_WHITE_PANDA = b'\x01' + HW_TYPE_GREY_PANDA = b'\x02' + HW_TYPE_BLACK_PANDA = b'\x03' + HW_TYPE_PEDAL = b'\x04' + HW_TYPE_UNO = b'\x05' + HW_TYPE_DOS = b'\x06' + HW_TYPE_RED_PANDA = b'\x07' + HW_TYPE_RED_PANDA_V2 = b'\x08' + HW_TYPE_TRES = b'\x09' + HW_TYPE_CUATRO = b'\x0a' + + CAN_PACKET_VERSION = 4 + HEALTH_PACKET_VERSION = 17 + CAN_HEALTH_PACKET_VERSION = 5 + HEALTH_STRUCT = struct.Struct(" 0: + print("INFO: some attached pandas are in DFU mode.") + + pandas = self.list() + if len(pandas) == 0: + print("INFO: panda not available") + return None + if len(pandas) == 1: + print(f"INFO: connecting to panda {pandas[0]}") + return pandas[0] + while True: + print("Multiple pandas available:") + pandas.sort() + for idx, serial in enumerate(pandas): + print(f"{[idx]}: {serial}") + try: + choice = int(input("Choose serial [0]:") or "0") + return pandas[choice] + except (ValueError, IndexError): + print("Enter a valid index.") + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def close(self): + if self._handle_open: + self._handle.close() + self._handle_open = False + if self._context is not None: + self._context.close() + + def connect(self, claim=True, wait=False): + self.close() + + self._handle = None + while self._handle is None: + # try USB first, then SPI + self._context, self._handle, serial, self.bootstub = self.usb_connect(self._connect_serial, claim=claim, no_error=wait) + if self._handle is None: + self._context, self._handle, serial, self.bootstub = self.spi_connect(self._connect_serial) + if not wait: + break + + if self._handle is None: + raise Exception("failed to connect to panda") + + # Some fallback logic to determine panda and MCU type for old bootstubs, + # since we now support multiple MCUs and need to know which fw to flash. + # Three cases to consider: + # A) oldest bootstubs don't have any way to distinguish + # MCU or panda type + # B) slightly newer (~2 weeks after first C3's built) bootstubs + # have the panda type set in the USB bcdDevice + # C) latest bootstubs also implement the endpoint for panda type + self._bcd_hw_type = None + ret = self._handle.controlRead(Panda.REQUEST_IN, 0xc1, 0, 0, 0x40) + # rick - UNO to DOS for lite + if ret == bytearray(b'\x05'): + ret = bytearray(b'\x06') + missing_hw_type_endpoint = self.bootstub and ret.startswith(b'\xff\x00\xc1\x3e\xde\xad\xd0\x0d') + if missing_hw_type_endpoint and bcd is not None: + self._bcd_hw_type = bcd + + # For case A, we assume F4 MCU type, since all H7 pandas should be case B at worst + self._assume_f4_mcu = (self._bcd_hw_type is None) and missing_hw_type_endpoint + + self._serial = serial + self._connect_serial = serial + self._handle_open = True + self._mcu_type = self.get_mcu_type() + self.health_version, self.can_version, self.can_health_version = self.get_packets_versions() + logger.debug("connected") + + # disable openpilot's heartbeat checks + if self._disable_checks: + self.set_heartbeat_disabled() + self.set_power_save(0) + + # reset comms + self.can_reset_communications() + + # disable automatic CAN-FD switching + for bus in range(PANDA_CAN_CNT): + self.set_canfd_auto(bus, False) + + # set CAN speed + for bus in range(PANDA_CAN_CNT): + self.set_can_speed_kbps(bus, self._can_speed_kbps) + + @property + def spi(self) -> bool: + return isinstance(self._handle, PandaSpiHandle) + + @classmethod + def spi_connect(cls, serial, ignore_version=False): + try: + handle = PandaSpiHandle() + dat = handle.get_protocol_version() + except PandaSpiException: + return None, None, None, False + + spi_serial = binascii.hexlify(dat[:12]).decode() + pid = dat[13] + if pid not in (0xcc, 0xee): + raise PandaProtocolMismatch(f"invalid bootstub status ({pid=}). reflash panda") + bootstub = pid == 0xee + spi_version = dat[14] + + # did we get the right panda? + if serial is not None and spi_serial != serial: + return None, None, None, False + + # ensure our protocol version matches the panda + if (not ignore_version) and spi_version != handle.PROTOCOL_VERSION: + raise PandaProtocolMismatch(f"panda protocol mismatch: expected {handle.PROTOCOL_VERSION}, got {spi_version}. reflash panda") + + # got a device and all good + return None, handle, spi_serial, bootstub + + @classmethod + def usb_connect(cls, serial, claim=True, no_error=False): + handle, usb_serial, bootstub = None, None, None + context = usb1.USBContext() + context.open() + try: + for device in context.getDeviceList(skip_on_error=True): + if device.getVendorID() in cls.USB_VIDS and device.getProductID() in cls.USB_PIDS: + try: + this_serial = device.getSerialNumber() + except Exception: + # Allow to ignore errors on reconnect. USB hubs need some time to initialize after panda reset + if not no_error: + logger.exception("failed to get serial number of panda") + continue + + if serial is None or this_serial == serial: + logger.debug("opening device %s %s", this_serial, hex(device.getProductID())) + + usb_serial = this_serial + bootstub = (device.getProductID() & 0xF0) == 0xe0 + handle = device.open() + if sys.platform not in ("win32", "cygwin", "msys", "darwin"): + handle.setAutoDetachKernelDriver(True) + if claim: + handle.claimInterface(0) + # handle.setInterfaceAltSetting(0, 0) # Issue in USB stack + + break + except Exception: + logger.exception("USB connect error") + + usb_handle = None + if handle is not None: + usb_handle = PandaUsbHandle(handle) + else: + context.close() + + return context, usb_handle, usb_serial, bootstub + + def is_connected_spi(self): + return isinstance(self._handle, PandaSpiHandle) + + def is_connected_usb(self): + return isinstance(self._handle, PandaUsbHandle) + + @classmethod + def list(cls, usb_only: bool = False): + ret = cls.usb_list() + if not usb_only: + ret += cls.spi_list() + return list(set(ret)) + + @classmethod + def usb_list(cls): + ret = [] + try: + with usb1.USBContext() as context: + for device in context.getDeviceList(skip_on_error=True): + if device.getVendorID() in cls.USB_VIDS and device.getProductID() in cls.USB_PIDS: + try: + serial = device.getSerialNumber() + if len(serial) == 24: + ret.append(serial) + else: + logger.warning(f"found device with panda descriptors but invalid serial: {serial}", RuntimeWarning) + except Exception: + logger.exception("error connecting to panda") + except Exception: + logger.exception("exception while listing pandas") + return ret + + @classmethod + def spi_list(cls): + _, _, serial, _ = cls.spi_connect(None, ignore_version=True) + if serial is not None: + return [serial, ] + return [] + + def reset(self, enter_bootstub=False, enter_bootloader=False, reconnect=True): + # no response is expected since it resets right away + timeout = 5000 if isinstance(self._handle, PandaSpiHandle) else 15000 + try: + if enter_bootloader: + self._handle.controlWrite(Panda.REQUEST_IN, 0xd1, 0, 0, b'', timeout=timeout, expect_disconnect=True) + else: + if enter_bootstub: + self._handle.controlWrite(Panda.REQUEST_IN, 0xd1, 1, 0, b'', timeout=timeout, expect_disconnect=True) + else: + self._handle.controlWrite(Panda.REQUEST_IN, 0xd8, 0, 0, b'', timeout=timeout, expect_disconnect=True) + except Exception: + pass + + self.close() + if not enter_bootloader and reconnect: + self.reconnect() + + @property + def connected(self) -> bool: + return self._handle_open + + def reconnect(self): + if self._handle_open: + self.close() + + success = False + # wait up to 15 seconds + for _ in range(15*10): + try: + self.connect(claim=False, wait=True) + success = True + break + except Exception: + pass + time.sleep(0.1) + if not success: + raise Exception("reconnect failed") + + @staticmethod + def flasher_present(handle: BaseHandle) -> bool: + fr = handle.controlRead(Panda.REQUEST_IN, 0xb0, 0, 0, 0xc) + return fr[4:8] == b"\xde\xad\xd0\x0d" + + @staticmethod + def flash_static(handle, code, mcu_type): + assert mcu_type is not None, "must set valid mcu_type to flash" + + # confirm flasher is present + assert Panda.flasher_present(handle) + + # determine sectors to erase + apps_sectors_cumsum = accumulate(mcu_type.config.sector_sizes[1:]) + last_sector = next((i + 1 for i, v in enumerate(apps_sectors_cumsum) if v > len(code)), -1) + assert last_sector >= 1, "Binary too small? No sector to erase." + assert last_sector < 7, "Binary too large! Risk of overwriting provisioning chunk." + + # unlock flash + logger.info("flash: unlocking") + handle.controlWrite(Panda.REQUEST_IN, 0xb1, 0, 0, b'') + + # erase sectors + logger.info(f"flash: erasing sectors 1 - {last_sector}") + for i in range(1, last_sector + 1): + handle.controlWrite(Panda.REQUEST_IN, 0xb2, i, 0, b'') + + # flash over EP2 + STEP = 0x200 + logger.info("flash: flashing") + for i in range(0, len(code), STEP): + handle.bulkWrite(2, code[i:i + STEP]) + + # reset + logger.info("flash: resetting") + try: + handle.controlWrite(Panda.REQUEST_IN, 0xd8, 0, 0, b'', expect_disconnect=True) + except Exception: + pass + + def flash(self, fn=None, code=None, reconnect=True): + if self.up_to_date(fn=fn): + logger.info("flash: already up to date") + return + + if not fn: + fn = os.path.join(FW_PATH, self._mcu_type.config.app_fn) + assert os.path.isfile(fn) + logger.debug("flash: main version is %s", self.get_version()) + if not self.bootstub: + self.reset(enter_bootstub=True) + assert(self.bootstub) + + if code is None: + with open(fn, "rb") as f: + code = f.read() + + # get version + logger.debug("flash: bootstub version is %s", self.get_version()) + + # do flash + Panda.flash_static(self._handle, code, mcu_type=self._mcu_type) + + # reconnect + if reconnect: + self.reconnect() + + def recover(self, timeout: int | None = 60, reset: bool = True) -> bool: + dfu_serial = self.get_dfu_serial() + + if reset: + self.reset(enter_bootstub=True) + self.reset(enter_bootloader=True) + + if not self.wait_for_dfu(dfu_serial, timeout=timeout): + return False + + dfu = PandaDFU(dfu_serial) + dfu.recover() + + # reflash after recover + self.connect(True, True) + self.flash() + return True + + @staticmethod + def wait_for_dfu(dfu_serial: str | None, timeout: int | None = None) -> bool: + t_start = time.monotonic() + dfu_list = PandaDFU.list() + while (dfu_serial is None and len(dfu_list) == 0) or (dfu_serial is not None and dfu_serial not in dfu_list): + logger.debug("waiting for DFU...") + time.sleep(0.1) + if timeout is not None and (time.monotonic() - t_start) > timeout: + return False + dfu_list = PandaDFU.list() + return True + + @staticmethod + def wait_for_panda(serial: str | None, timeout: int) -> bool: + t_start = time.monotonic() + serials = Panda.list() + while (serial is None and len(serials) == 0) or (serial is not None and serial not in serials): + logger.debug("waiting for panda...") + time.sleep(0.1) + if timeout is not None and (time.monotonic() - t_start) > timeout: + return False + serials = Panda.list() + return True + + def up_to_date(self, fn=None) -> bool: + current = self.get_signature() + if fn is None: + fn = os.path.join(FW_PATH, self.get_mcu_type().config.app_fn) + expected = Panda.get_signature_from_firmware(fn) + return (current == expected) + + def call_control_api(self, msg): + self._handle.controlWrite(Panda.REQUEST_OUT, msg, 0, 0, b'') + + # ******************* health ******************* + + @ensure_health_packet_version + def health(self): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, self.HEALTH_STRUCT.size) + a = self.HEALTH_STRUCT.unpack(dat) + return { + "uptime": a[0], + "voltage": a[1], + "current": a[2], + "safety_tx_blocked": a[3], + "safety_rx_invalid": a[4], + "tx_buffer_overflow": a[5], + "rx_buffer_overflow": a[6], + "faults": a[7], + "ignition_line": a[8], + "ignition_can": a[9], + "controls_allowed": a[10], + "car_harness_status": a[11], + "safety_mode": a[12], + "safety_param": a[13], + "fault_status": a[14], + "power_save_enabled": a[15], + "heartbeat_lost": a[16], + "alternative_experience": a[17], + "interrupt_load": a[18], + "fan_power": a[19], + "safety_rx_checks_invalid": a[20], + "spi_error_count": a[21], + "sbu1_voltage_mV": a[22], + "sbu2_voltage_mV": a[23], + "som_reset_triggered": a[24], + } + + @ensure_can_health_packet_version + def can_health(self, can_number): + LEC_ERROR_CODE = { + 0: "No error", + 1: "Stuff error", + 2: "Form error", + 3: "AckError", + 4: "Bit1Error", + 5: "Bit0Error", + 6: "CRCError", + 7: "NoChange", + } + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc2, int(can_number), 0, self.CAN_HEALTH_STRUCT.size) + a = self.CAN_HEALTH_STRUCT.unpack(dat) + return { + "bus_off": a[0], + "bus_off_cnt": a[1], + "error_warning": a[2], + "error_passive": a[3], + "last_error": LEC_ERROR_CODE[a[4]], + "last_stored_error": LEC_ERROR_CODE[a[5]], + "last_data_error": LEC_ERROR_CODE[a[6]], + "last_data_stored_error": LEC_ERROR_CODE[a[7]], + "receive_error_cnt": a[8], + "transmit_error_cnt": a[9], + "total_error_cnt": a[10], + "total_tx_lost_cnt": a[11], + "total_rx_lost_cnt": a[12], + "total_tx_cnt": a[13], + "total_rx_cnt": a[14], + "total_fwd_cnt": a[15], + "total_tx_checksum_error_cnt": a[16], + "can_speed": a[17], + "can_data_speed": a[18], + "canfd_enabled": a[19], + "brs_enabled": a[20], + "canfd_non_iso": a[21], + "irq0_call_rate": a[22], + "irq1_call_rate": a[23], + "irq2_call_rate": a[24], + "can_core_reset_count": a[25], + } + + # ******************* control ******************* + + def get_version(self): + return self._handle.controlRead(Panda.REQUEST_IN, 0xd6, 0, 0, 0x40).decode('utf8') + + @staticmethod + def get_signature_from_firmware(fn) -> bytes: + with open(fn, 'rb') as f: + f.seek(-128, 2) # Seek from end of file + return f.read(128) + + def get_signature(self) -> bytes: + part_1 = self._handle.controlRead(Panda.REQUEST_IN, 0xd3, 0, 0, 0x40) + part_2 = self._handle.controlRead(Panda.REQUEST_IN, 0xd4, 0, 0, 0x40) + return bytes(part_1 + part_2) + + def get_type(self): + ret = self._handle.controlRead(Panda.REQUEST_IN, 0xc1, 0, 0, 0x40) + # rick - UNO to DOS for lite + if ret == bytearray(b'\x05'): + ret = bytearray(b'\x06') + + # old bootstubs don't implement this endpoint, see comment in Panda.device + if self._bcd_hw_type is not None and (ret is None or len(ret) != 1): + ret = self._bcd_hw_type + + return ret + + # Returns tuple with health packet version and CAN packet/USB packet version + def get_packets_versions(self): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xdd, 0, 0, 3) + if dat and len(dat) == 3: + a = struct.unpack("BBB", dat) + return (a[0], a[1], a[2]) + else: + return (0, 0, 0) + + def get_mcu_type(self) -> McuType: + hw_type = self.get_type() + if hw_type in Panda.F4_DEVICES: + return McuType.F4 + elif hw_type in Panda.H7_DEVICES: + return McuType.H7 + else: + # have to assume F4, see comment in Panda.connect + if self._assume_f4_mcu: + return McuType.F4 + + raise ValueError(f"unknown HW type: {hw_type}") + + def has_obd(self): + return self.get_type() in Panda.HAS_OBD + + def is_internal(self): + return self.get_type() in Panda.INTERNAL_DEVICES + + def get_serial(self): + """ + Returns the comma-issued dongle ID from our provisioning + """ + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd0, 0, 0, 0x20) + hashsig, calc_hash = dat[0x1c:], hashlib.sha1(dat[0:0x1c]).digest()[0:4] + assert(hashsig == calc_hash) + return [dat[0:0x10].decode("utf8"), dat[0x10:0x10 + 10].decode("utf8")] + + def get_usb_serial(self): + """ + Returns the serial number reported from the USB descriptor; + matches the MCU UID + """ + return self._serial + + def get_dfu_serial(self): + return PandaDFU.st_serial_to_dfu_serial(self._serial, self._mcu_type) + + def get_uid(self): + """ + Returns the UID from the MCU + """ + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc3, 0, 0, 12) + return binascii.hexlify(dat).decode() + + def get_secret(self): + return self._handle.controlRead(Panda.REQUEST_IN, 0xd0, 1, 0, 0x10) + + def get_interrupt_call_rate(self, irqnum): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc4, int(irqnum), 0, 4) + return struct.unpack("I", dat)[0] + + # ******************* configuration ******************* + + def set_alternative_experience(self, alternative_experience): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xdf, int(alternative_experience), 0, b'') + + def set_power_save(self, power_save_enabled=0): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe7, int(power_save_enabled), 0, b'') + + def set_safety_mode(self, mode=CarParams.SafetyModel.silent, param=0): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xdc, mode, param, b'') + + def set_obd(self, obd): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xdb, int(obd), 0, b'') + + def set_can_loopback(self, enable): + # set can loopback mode for all buses + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe5, int(enable), 0, b'') + + def set_can_enable(self, bus_num, enable): + # sets the can transceiver enable pin + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf4, int(bus_num), int(enable), b'') + + def set_can_speed_kbps(self, bus, speed): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xde, bus, int(speed * 10), b'') + + def set_can_data_speed_kbps(self, bus, speed): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf9, bus, int(speed * 10), b'') + + def set_canfd_non_iso(self, bus, non_iso): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xfc, bus, int(non_iso), b'') + + def set_canfd_auto(self, bus, auto): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe8, bus, int(auto), b'') + + def set_uart_baud(self, uart, rate): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe4, uart, int(rate / 300), b'') + + def set_uart_parity(self, uart, parity): + # parity, 0=off, 1=even, 2=odd + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe2, uart, parity, b'') + + def set_uart_callback(self, uart, install): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe3, uart, int(install), b'') + + # ******************* can ******************* + + # The panda will NAK CAN writes when there is CAN congestion. + # libusb will try to send it again, with a max timeout. + # Timeout is in ms. If set to 0, the timeout is infinite. + CAN_SEND_TIMEOUT_MS = 10 + + def can_reset_communications(self): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xc0, 0, 0, b'') + + @ensure_can_packet_version + def can_send_many(self, arr, *, fd=False, timeout=CAN_SEND_TIMEOUT_MS): + snds = pack_can_buffer(arr, fd=fd) + for tx in snds: + while len(tx) > 0: + bs = self._handle.bulkWrite(3, tx, timeout=timeout) + tx = tx[bs:] + + def can_send(self, addr, dat, bus, *, fd=False, timeout=CAN_SEND_TIMEOUT_MS): + self.can_send_many([[addr, dat, bus]], fd=fd, timeout=timeout) + + @ensure_can_packet_version + def can_recv(self): + dat = bytearray() + while True: + try: + dat = self._handle.bulkRead(1, 16384) # Max receive batch size + 2 extra reserve frames + break + except (usb1.USBErrorIO, usb1.USBErrorOverflow): + logger.error("CAN: BAD RECV, RETRYING") + time.sleep(0.1) + msgs, self.can_rx_overflow_buffer = unpack_can_buffer(self.can_rx_overflow_buffer + dat) + return msgs + + def can_clear(self, bus): + """Clears all messages from the specified internal CAN ringbuffer as + though it were drained. + + Args: + bus (int): can bus number to clear a tx queue, or 0xFFFF to clear the + global can rx queue. + + """ + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf1, bus, 0, b'') + + # ******************* serial ******************* + + def serial_read(self, port_number, maxlen=1024): + ret = b'' + while 1: + r = bytes(self._handle.controlRead(Panda.REQUEST_IN, 0xe0, port_number, 0, 0x40)) + if len(r) == 0 or len(ret) >= maxlen: + break + ret += r + return ret + + def serial_write(self, port_number, ln): + ret = 0 + if isinstance(ln, str): + ln = bytes(ln, 'utf-8') + for i in range(0, len(ln), 0x20): + ret += self._handle.bulkWrite(2, struct.pack("B", port_number) + ln[i:i + 0x20]) + return ret + + def serial_clear(self, port_number): + """Clears all messages (tx and rx) from the specified internal uart + ringbuffer as though it were drained. + + Args: + port_number (int): port number of the uart to clear. + + """ + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf2, port_number, 0, b'') + + def send_heartbeat(self, engaged=True): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf3, engaged, 0, b'') + + # disable heartbeat checks for use outside of openpilot + # sending a heartbeat will reenable the checks + def set_heartbeat_disabled(self): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf8, 0, 0, b'') + + # ****************** Timer ***************** + def get_microsecond_timer(self): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xa8, 0, 0, 4) + return struct.unpack("I", dat)[0] + + # ******************* IR ******************* + def set_ir_power(self, percentage): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xb0, int(percentage), 0, b'') + + # ******************* Fan ****************** + def set_fan_power(self, percentage): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xb1, int(percentage), 0, b'') + + def get_fan_rpm(self): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xb2, 0, 0, 2) + a = struct.unpack("H", dat) + return a[0] + + # ****************** Siren ***************** + def set_siren(self, enabled): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf6, int(enabled), 0, b'') + + # ****************** Debug ***************** + def set_green_led(self, enabled): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf7, int(enabled), 0, b'') + + # arr: timer period + # ccrN: channel N pulse length + def set_clock_source_timer_params(self, arr, ccr1, ccr2, ccr3): + param1 = ((ccr1 & 0xFF) << 8) | (ccr2 & 0xFF) + param2 = ((ccr3 & 0xFF) << 8) | (arr & 0xFF) + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe6, param1, param2, b'') + + def force_relay_drive(self, intercept_relay_drive, ignition_relay_drive): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xc5, (int(intercept_relay_drive) | int(ignition_relay_drive) << 1), 0, b'') + + def read_som_gpio(self) -> bool: + r = self._handle.controlRead(Panda.REQUEST_IN, 0xc6, 0, 0, 1) + return r[0] == 1 diff --git a/panda_tici/python/base.py b/panda_tici/python/base.py new file mode 100644 index 0000000..ffe9353 --- /dev/null +++ b/panda_tici/python/base.py @@ -0,0 +1,61 @@ +from abc import ABC, abstractmethod + +from .constants import McuType + +TIMEOUT = int(15 * 1e3) # default timeout, in milliseconds + +class BaseHandle(ABC): + """ + A handle to talk to a panda. + Borrows heavily from the libusb1 handle API. + """ + + @abstractmethod + def close(self) -> None: + ... + + @abstractmethod + def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = TIMEOUT, expect_disconnect: bool = False): + ... + + @abstractmethod + def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = TIMEOUT) -> bytes: + ... + + @abstractmethod + def bulkWrite(self, endpoint: int, data: bytes, timeout: int = TIMEOUT) -> int: + ... + + @abstractmethod + def bulkRead(self, endpoint: int, length: int, timeout: int = TIMEOUT) -> bytes: + ... + + +class BaseSTBootloaderHandle(ABC): + """ + A handle to talk to a panda while it's in the STM32 bootloader. + """ + + @abstractmethod + def get_mcu_type(self) -> McuType: + ... + + @abstractmethod + def close(self) -> None: + ... + + @abstractmethod + def clear_status(self) -> None: + ... + + @abstractmethod + def program(self, address: int, dat: bytes) -> None: + ... + + @abstractmethod + def erase_sector(self, sector: int) -> None: + ... + + @abstractmethod + def jump(self, address: int) -> None: + ... diff --git a/panda_tici/python/constants.py b/panda_tici/python/constants.py new file mode 100644 index 0000000..8b09593 --- /dev/null +++ b/panda_tici/python/constants.py @@ -0,0 +1,65 @@ +import os +import enum +from typing import NamedTuple + +BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../") +FW_PATH = os.path.join(BASEDIR, "board/obj/") + +USBPACKET_MAX_SIZE = 0x40 + +class McuConfig(NamedTuple): + mcu: str + mcu_idcode: int + sector_sizes: list[int] + sector_count: int # total sector count, used for MCU identification in DFU mode + uid_address: int + block_size: int + serial_number_address: int + app_address: int + app_fn: str + bootstub_address: int + bootstub_fn: str + + def sector_address(self, i): + # assume bootstub is in sector 0 + return self.bootstub_address + sum(self.sector_sizes[:i]) + +F4Config = McuConfig( + "STM32F4", + 0x463, + [0x4000 for _ in range(4)] + [0x10000] + [0x20000 for _ in range(11)], + 16, + 0x1FFF7A10, + 0x800, + 0x1FFF79C0, + 0x8004000, + "panda.bin.signed", + 0x8000000, + "bootstub.panda.bin", +) + +H7Config = McuConfig( + "STM32H7", + 0x483, + [0x20000 for _ in range(7)], + 8, + 0x1FF1E800, + 0x400, + # there is an 8th sector, but we use that for the provisioning chunk, so don't program over that! + 0x080FFFC0, + 0x8020000, + "panda_h7.bin.signed", + 0x8000000, + "bootstub.panda_h7.bin", +) + +@enum.unique +class McuType(enum.Enum): + F4 = F4Config + H7 = H7Config + + @property + def config(self): + return self.value + +MCU_TYPE_BY_IDCODE = {m.config.mcu_idcode: m for m in McuType} diff --git a/panda_tici/python/dfu.py b/panda_tici/python/dfu.py new file mode 100644 index 0000000..df6c1f7 --- /dev/null +++ b/panda_tici/python/dfu.py @@ -0,0 +1,139 @@ +import os +import usb1 +import struct +import binascii + +from .base import BaseSTBootloaderHandle +from .spi import STBootloaderSPIHandle, PandaSpiException +from .usb import STBootloaderUSBHandle +from .constants import FW_PATH, McuType + + +class PandaDFU: + def __init__(self, dfu_serial: str | None): + # try USB, then SPI + handle: BaseSTBootloaderHandle | None + self._context, handle = PandaDFU.usb_connect(dfu_serial) + if handle is None: + self._context, handle = PandaDFU.spi_connect(dfu_serial) + + if handle is None: + raise Exception(f"failed to open DFU device {dfu_serial}") + + self._handle: BaseSTBootloaderHandle = handle + self._mcu_type: McuType = self._handle.get_mcu_type() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def close(self): + if self._handle is not None: + self._handle.close() + self._handle = None + if self._context is not None: + self._context.close() + + @staticmethod + def usb_connect(dfu_serial: str | None): + handle = None + context = usb1.USBContext() + context.open() + for device in context.getDeviceList(skip_on_error=True): + if device.getVendorID() == 0x0483 and device.getProductID() == 0xdf11: + try: + this_dfu_serial = device.open().getASCIIStringDescriptor(3) + except Exception: + continue + + if this_dfu_serial == dfu_serial or dfu_serial is None: + handle = STBootloaderUSBHandle(device, device.open()) + break + + return context, handle + + @staticmethod + def spi_connect(dfu_serial: str | None): + handle = None + this_dfu_serial = None + + try: + handle = STBootloaderSPIHandle() + this_dfu_serial = PandaDFU.st_serial_to_dfu_serial(handle.get_uid(), handle.get_mcu_type()) + except PandaSpiException: + handle = None + + if dfu_serial is not None and dfu_serial != this_dfu_serial: + handle = None + + return None, handle + + @staticmethod + def usb_list() -> list[str]: + dfu_serials = [] + try: + with usb1.USBContext() as context: + for device in context.getDeviceList(skip_on_error=True): + if device.getVendorID() == 0x0483 and device.getProductID() == 0xdf11: + try: + dfu_serials.append(device.open().getASCIIStringDescriptor(3)) + except Exception: + pass + except Exception: + pass + return dfu_serials + + @staticmethod + def spi_list() -> list[str]: + try: + _, h = PandaDFU.spi_connect(None) + if h is not None: + dfu_serial = PandaDFU.st_serial_to_dfu_serial(h.get_uid(), h.get_mcu_type()) + return [dfu_serial, ] + except PandaSpiException: + pass + return [] + + @staticmethod + def st_serial_to_dfu_serial(st: str, mcu_type: McuType = McuType.F4): + if st is None or st == "none": + return None + try: + uid_base = struct.unpack("H" * 6, bytes.fromhex(st)) + if mcu_type == McuType.H7: + return binascii.hexlify(struct.pack("!HHH", uid_base[1] + uid_base[5], uid_base[0] + uid_base[4], uid_base[3])).upper().decode("utf-8") + else: + return binascii.hexlify(struct.pack("!HHH", uid_base[1] + uid_base[5], uid_base[0] + uid_base[4] + 0xA, uid_base[3])).upper().decode("utf-8") + except struct.error: + return None + + def get_mcu_type(self) -> McuType: + return self._mcu_type + + def reset(self): + self._handle.jump(self._mcu_type.config.bootstub_address) + + def program_bootstub(self, code_bootstub): + self._handle.clear_status() + + # erase bootstub + app sectors + for i in (0, 1): + self._handle.erase_sector(i) + + # write bootstub + self._handle.program(self._mcu_type.config.bootstub_address, code_bootstub) + + def recover(self): + fn = os.path.join(FW_PATH, self._mcu_type.config.bootstub_fn) + with open(fn, "rb") as f: + code = f.read() + self.program_bootstub(code) + self.reset() + + @staticmethod + def list() -> list[str]: + ret = PandaDFU.usb_list() + ret += PandaDFU.spi_list() + return list(set(ret)) diff --git a/panda_tici/python/serial.py b/panda_tici/python/serial.py new file mode 100644 index 0000000..c2e965b --- /dev/null +++ b/panda_tici/python/serial.py @@ -0,0 +1,35 @@ +# mimic a python serial port +class PandaSerial: + def __init__(self, panda, port, baud): + self.panda = panda + self.port = port + self.panda.set_uart_parity(self.port, 0) + self._baudrate = baud + self.panda.set_uart_baud(self.port, baud) + self.buf = b"" + + def read(self, l=1): + tt = self.panda.serial_read(self.port) + if len(tt) > 0: + self.buf += tt + ret = self.buf[0:l] + self.buf = self.buf[l:] + return ret + + def write(self, dat): + return self.panda.serial_write(self.port, dat) + + def close(self): + pass + + def flush(self): + pass + + @property + def baudrate(self): + return self._baudrate + + @baudrate.setter + def baudrate(self, value): + self.panda.set_uart_baud(self.port, value) + self._baudrate = value diff --git a/panda_tici/python/socketpanda.py b/panda_tici/python/socketpanda.py new file mode 100644 index 0000000..b80f1b1 --- /dev/null +++ b/panda_tici/python/socketpanda.py @@ -0,0 +1,96 @@ +import socket +import struct + +# /** +# * struct canfd_frame - CAN flexible data rate frame structure +# * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition +# * @len: frame payload length in byte (0 .. CANFD_MAX_DLEN) +# * @flags: additional flags for CAN FD +# * @__res0: reserved / padding +# * @__res1: reserved / padding +# * @data: CAN FD frame payload (up to CANFD_MAX_DLEN byte) +# */ +# struct canfd_frame { +# canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ +# __u8 len; /* frame payload length in byte */ +# __u8 flags; /* additional flags for CAN FD */ +# __u8 __res0; /* reserved / padding */ +# __u8 __res1; /* reserved / padding */ +# __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8))); +# }; +CAN_HEADER_FMT = "=IBB2x" +CAN_HEADER_LEN = struct.calcsize(CAN_HEADER_FMT) +CAN_MAX_DLEN = 8 +CANFD_MAX_DLEN = 64 + +CANFD_BRS = 0x01 # bit rate switch (second bitrate for payload data) +CANFD_FDF = 0x04 # mark CAN FD for dual use of struct canfd_frame + +# socket.SO_RXQ_OVFL is missing +# https://github.com/torvalds/linux/blob/47ac09b91befbb6a235ab620c32af719f8208399/include/uapi/asm-generic/socket.h#L61 +SO_RXQ_OVFL = 40 + +import typing +@typing.no_type_check # mypy struggles with macOS here... +def create_socketcan(interface:str, recv_buffer_size:int, fd:bool) -> socket.socket: + # settings mostly from https://github.com/linux-can/can-utils/blob/master/candump.c + socketcan = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW) + if fd: + socketcan.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FD_FRAMES, 1) + socketcan.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, recv_buffer_size) + # TODO: why is it always 2x the requested size? + assert socketcan.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF) == recv_buffer_size * 2 + # TODO: how to dectect and alert on buffer overflow? + socketcan.setsockopt(socket.SOL_SOCKET, SO_RXQ_OVFL, 1) + socketcan.bind((interface,)) + return socketcan + +# Panda class substitute for socketcan device (to support using the uds/iso-tp/xcp/ccp library) +class SocketPanda(): + def __init__(self, interface:str="can0", bus:int=0, fd:bool=False, recv_buffer_size:int=212992) -> None: + self.interface = interface + self.bus = bus + self.fd = fd + self.flags = CANFD_BRS | CANFD_FDF if fd else 0 + self.data_len = CANFD_MAX_DLEN if fd else CAN_MAX_DLEN + self.recv_buffer_size = recv_buffer_size + self.socket = create_socketcan(interface, recv_buffer_size, fd) + + def __del__(self): + self.socket.close() + + def get_serial(self) -> tuple[int, int]: + return (0, 0) # TODO: implemented in panda socketcan driver + + def get_version(self) -> int: + return 0 # TODO: implemented in panda socketcan driver + + def can_clear(self, bus:int) -> None: + # TODO: implemented in panda socketcan driver + self.socket.close() + self.socket = create_socketcan(self.interface, self.recv_buffer_size, self.fd) + + def set_safety_mode(self, mode:int, param=0) -> None: + pass # TODO: implemented in panda socketcan driver + + def has_obd(self) -> bool: + return False # TODO: implemented in panda socketcan driver + + def can_send(self, addr, dat, bus=0, timeout=0) -> None: + msg_len = len(dat) + msg_dat = dat.ljust(self.data_len, b'\x00') + can_frame = struct.pack(CAN_HEADER_FMT, addr, msg_len, self.flags) + msg_dat + self.socket.sendto(can_frame, (self.interface,)) + + def can_recv(self) -> list[tuple[int, bytes, int]]: + msgs = list() + while True: + try: + dat, _ = self.socket.recvfrom(self.recv_buffer_size, socket.MSG_DONTWAIT) + assert len(dat) == CAN_HEADER_LEN + self.data_len, f"ERROR: received {len(dat)} bytes" + can_id, msg_len, _ = struct.unpack(CAN_HEADER_FMT, dat[:CAN_HEADER_LEN]) + msg_dat = dat[CAN_HEADER_LEN:CAN_HEADER_LEN+msg_len] + msgs.append((can_id, msg_dat, self.bus)) + except BlockingIOError: + break # buffered data exhausted + return msgs diff --git a/panda_tici/python/spi.py b/panda_tici/python/spi.py new file mode 100644 index 0000000..cee8755 --- /dev/null +++ b/panda_tici/python/spi.py @@ -0,0 +1,445 @@ +import binascii +import ctypes +import os +import fcntl +import math +import time +import struct +import threading +from contextlib import contextmanager +from functools import reduce +from collections.abc import Callable + +from .base import BaseHandle, BaseSTBootloaderHandle, TIMEOUT +from .constants import McuType, MCU_TYPE_BY_IDCODE, USBPACKET_MAX_SIZE +from .utils import logger + +try: + import spidev +except ImportError: + spidev = None + +# Constants +SYNC = 0x5A +HACK = 0x79 +DACK = 0x85 +NACK = 0x1F +CHECKSUM_START = 0xAB + +MIN_ACK_TIMEOUT_MS = 100 +MAX_XFER_RETRY_COUNT = 5 + +XFER_SIZE = 0x40*31 + +DEV_PATH = "/dev/spidev0.0" + + +def crc8(data): + crc = 0xFF # standard init value + poly = 0xD5 # standard crc8: x8+x7+x6+x4+x2+1 + size = len(data) + for i in range(size - 1, -1, -1): + crc ^= data[i] + for _ in range(8): + if ((crc & 0x80) != 0): + crc = ((crc << 1) ^ poly) & 0xFF + else: + crc <<= 1 + return crc + + +class PandaSpiException(Exception): + pass + +class PandaProtocolMismatch(PandaSpiException): + pass + +class PandaSpiUnavailable(PandaSpiException): + pass + +class PandaSpiNackResponse(PandaSpiException): + pass + +class PandaSpiMissingAck(PandaSpiException): + pass + +class PandaSpiBadChecksum(PandaSpiException): + pass + +class PandaSpiTransferFailed(PandaSpiException): + pass + + +class PandaSpiTransfer(ctypes.Structure): + _fields_ = [ + ('rx_buf', ctypes.c_uint64), + ('tx_buf', ctypes.c_uint64), + ('tx_length', ctypes.c_uint32), + ('rx_length_max', ctypes.c_uint32), + ('timeout', ctypes.c_uint32), + ('endpoint', ctypes.c_uint8), + ('expect_disconnect', ctypes.c_uint8), + ] + + +SPI_LOCK = threading.Lock() +SPI_DEVICES = {} +class SpiDevice: + """ + Provides locked, thread-safe access to a panda's SPI interface. + """ + + # 50MHz is the max of the 845. older rev comma three + # may not support the full 50MHz + MAX_SPEED = 50000000 + + def __init__(self, speed=MAX_SPEED): + assert speed <= self.MAX_SPEED + + if not os.path.exists(DEV_PATH): + raise PandaSpiUnavailable(f"SPI device not found: {DEV_PATH}") + if spidev is None: + raise PandaSpiUnavailable("spidev is not installed") + + with SPI_LOCK: + if speed not in SPI_DEVICES: + SPI_DEVICES[speed] = spidev.SpiDev() + SPI_DEVICES[speed].open(0, 0) + SPI_DEVICES[speed].max_speed_hz = speed + self._spidev = SPI_DEVICES[speed] + + @contextmanager + def acquire(self): + try: + SPI_LOCK.acquire() + fcntl.flock(self._spidev, fcntl.LOCK_EX) + yield self._spidev + finally: + fcntl.flock(self._spidev, fcntl.LOCK_UN) + SPI_LOCK.release() + + def close(self): + pass + + +class PandaSpiHandle(BaseHandle): + """ + A class that mimics a libusb1 handle for panda SPI communications. + """ + + PROTOCOL_VERSION = 2 + + def __init__(self) -> None: + self.dev = SpiDevice() + + self._transfer_raw: Callable[[SpiDevice, int, bytes, int, int, bool], bytes] = self._transfer_spidev + + if "KERN" in os.environ: + self._transfer_raw = self._transfer_kernel_driver + + self.tx_buf = bytearray(1024) + self.rx_buf = bytearray(1024) + tx_buf_raw = ctypes.c_char.from_buffer(self.tx_buf) + rx_buf_raw = ctypes.c_char.from_buffer(self.rx_buf) + + self.ioctl_data = PandaSpiTransfer() + self.ioctl_data.tx_buf = ctypes.addressof(tx_buf_raw) + self.ioctl_data.rx_buf = ctypes.addressof(rx_buf_raw) + self.fileno = self.dev._spidev.fileno() + + # helpers + def _calc_checksum(self, data: bytes) -> int: + cksum = CHECKSUM_START + for b in data: + cksum ^= b + return cksum + + def _wait_for_ack(self, spi, ack_val: int, timeout: int, tx: int, length: int = 1) -> bytes: + timeout_s = max(MIN_ACK_TIMEOUT_MS, timeout) * 1e-3 + + start = time.monotonic() + while (timeout == 0) or ((time.monotonic() - start) < timeout_s): + dat = spi.xfer2([tx, ] * length) + if dat[0] == NACK: + raise PandaSpiNackResponse + elif dat[0] == ack_val: + return bytes(dat) + + raise PandaSpiMissingAck + + def _transfer_spidev(self, spi, endpoint: int, data, timeout: int, max_rx_len: int = 1000, expect_disconnect: bool = False) -> bytes: + max_rx_len = max(USBPACKET_MAX_SIZE, max_rx_len) + + logger.debug("- send header") + packet = struct.pack(" max_rx_len: + raise PandaSpiException(f"response length greater than max ({max_rx_len} {response_len})") + + # read rest + remaining = (response_len + 1) - preread_len + if remaining > 0: + dat += bytes(spi.readbytes(remaining)) + + + dat = dat[:3 + response_len + 1] + if self._calc_checksum(dat) != 0: + raise PandaSpiBadChecksum + + return dat[3:-1] + + def _transfer_kernel_driver(self, spi, endpoint: int, data, timeout: int, max_rx_len: int = 1000, expect_disconnect: bool = False) -> bytes: + import spidev2 + self.tx_buf[:len(data)] = data + self.ioctl_data.endpoint = endpoint + self.ioctl_data.tx_length = len(data) + self.ioctl_data.rx_length_max = max_rx_len + self.ioctl_data.expect_disconnect = int(expect_disconnect) + + # TODO: use our own ioctl request + try: + ret = fcntl.ioctl(self.fileno, spidev2.SPI_IOC_RD_LSB_FIRST, self.ioctl_data) + except OSError as e: + raise PandaSpiException from e + if ret < 0: + raise PandaSpiException(f"ioctl returned {ret}") + return bytes(self.rx_buf[:ret]) + + def _transfer(self, endpoint: int, data, timeout: int, max_rx_len: int = 1000, expect_disconnect: bool = False) -> bytes: + logger.debug("starting transfer: endpoint=%d, max_rx_len=%d", endpoint, max_rx_len) + logger.debug("==============================================") + + n = 0 + start_time = time.monotonic() + exc = PandaSpiException() + while (timeout == 0) or (time.monotonic() - start_time) < timeout*1e-3: + n += 1 + logger.debug("\ntry #%d", n) + with self.dev.acquire() as spi: + try: + return self._transfer_raw(spi, endpoint, data, timeout, max_rx_len, expect_disconnect) + except PandaSpiException as e: + exc = e + logger.debug("SPI transfer failed, retrying", exc_info=True) + + raise exc + + def get_protocol_version(self) -> bytes: + vers_str = b"VERSION" + def _get_version(spi) -> bytes: + spi.writebytes(vers_str) + + logger.debug("- waiting for echo") + start = time.monotonic() + while True: + version_bytes = spi.readbytes(len(vers_str) + 2) + if bytes(version_bytes).startswith(vers_str): + break + if (time.monotonic() - start) > 0.001: + raise PandaSpiMissingAck + + rlen = struct.unpack(" 1000: + raise PandaSpiException("response length greater than max") + + # get response + dat = spi.readbytes(rlen + 1) + resp = dat[:-1] + calculated_crc = crc8(bytes(version_bytes + resp)) + if calculated_crc != dat[-1]: + raise PandaSpiBadChecksum + return bytes(resp) + + exc = PandaSpiException() + with self.dev.acquire() as spi: + for _ in range(10): + try: + return _get_version(spi) + except PandaSpiException as e: + exc = e + logger.debug("SPI get protocol version failed, retrying", exc_info=True) + raise exc + + # libusb1 functions + def close(self): + self.dev.close() + + def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = TIMEOUT, expect_disconnect: bool = False): + return self._transfer(0, struct.pack(" int: + for x in range(math.ceil(len(data) / XFER_SIZE)): + self._transfer(endpoint, data[XFER_SIZE*x:XFER_SIZE*(x+1)], timeout) + return len(data) + + def bulkRead(self, endpoint: int, length: int, timeout: int = TIMEOUT) -> bytes: + ret = b"" + for _ in range(math.ceil(length / XFER_SIZE)): + d = self._transfer(endpoint, [], timeout, max_rx_len=XFER_SIZE) + ret += d + if len(d) < XFER_SIZE: + break + return ret + + +class STBootloaderSPIHandle(BaseSTBootloaderHandle): + """ + Implementation of the STM32 SPI bootloader protocol described in: + https://www.st.com/resource/en/application_note/an4286-spi-protocol-used-in-the-stm32-bootloader-stmicroelectronics.pdf + """ + + SYNC = 0x5A + ACK = 0x79 + NACK = 0x1F + + def __init__(self): + self.dev = SpiDevice(speed=1000000) + + # say hello + try: + with self.dev.acquire() as spi: + spi.xfer([self.SYNC, ]) + try: + self._get_ack(spi, 0.1) + except (PandaSpiNackResponse, PandaSpiMissingAck): + # NACK ok here, will only ACK the first time + pass + + self._mcu_type = MCU_TYPE_BY_IDCODE[self.get_chip_id()] + except PandaSpiException: + raise PandaSpiException("failed to connect to panda") from None + + def _get_ack(self, spi, timeout=1.0): + data = 0x00 + start_time = time.monotonic() + while data not in (self.ACK, self.NACK) and (time.monotonic() - start_time < timeout): + data = spi.xfer([0x00, ])[0] + time.sleep(0) + spi.xfer([self.ACK, ]) + + if data == self.NACK: + raise PandaSpiNackResponse + elif data != self.ACK: + raise PandaSpiMissingAck + + def _cmd_no_retry(self, cmd: int, data: list[bytes] | None = None, read_bytes: int = 0, predata=None) -> bytes: + ret = b"" + with self.dev.acquire() as spi: + # sync + command + spi.xfer([self.SYNC, ]) + spi.xfer([cmd, cmd ^ 0xFF]) + self._get_ack(spi, timeout=0.01) + + # "predata" - for commands that send the first data without a checksum + if predata is not None: + spi.xfer(predata) + self._get_ack(spi) + + # send data + if data is not None: + for d in data: + if predata is not None: + spi.xfer(d + self._checksum(predata + d)) + else: + spi.xfer(d + self._checksum(d)) + self._get_ack(spi, timeout=20) + + # receive + if read_bytes > 0: + ret = spi.xfer([0x00, ]*(read_bytes + 1))[1:] + if data is None or len(data) == 0: + self._get_ack(spi) + + return bytes(ret) + + def _cmd(self, cmd: int, data: list[bytes] | None = None, read_bytes: int = 0, predata=None) -> bytes: + exc = PandaSpiException() + for n in range(MAX_XFER_RETRY_COUNT): + try: + return self._cmd_no_retry(cmd, data, read_bytes, predata) + except PandaSpiException as e: + exc = e + logger.debug("SPI transfer failed, %d retries left", MAX_XFER_RETRY_COUNT - n - 1, exc_info=True) + raise exc + + def _checksum(self, data: bytes) -> bytes: + if len(data) == 1: + ret = data[0] ^ 0xFF + else: + ret = reduce(lambda a, b: a ^ b, data) + return bytes([ret, ]) + + # *** Bootloader commands *** + + def read(self, address: int, length: int): + data = [struct.pack('>I', address), struct.pack('B', length - 1)] + return self._cmd(0x11, data=data, read_bytes=length) + + def get_bootloader_id(self): + return self.read(0x1FF1E7FE, 1) + + def get_chip_id(self) -> int: + r = self._cmd(0x02, read_bytes=3) + if r[0] != 1: # response length - 1 + raise PandaSpiException("incorrect response length") + return ((r[1] << 8) + r[2]) + + def go_cmd(self, address: int) -> None: + self._cmd(0x21, data=[struct.pack('>I', address), ]) + + # *** helpers *** + + def get_uid(self): + dat = self.read(McuType.H7.config.uid_address, 12) + return binascii.hexlify(dat).decode() + + def erase_sector(self, sector: int): + p = struct.pack('>H', 0) # number of sectors to erase + d = struct.pack('>H', sector) + self._cmd(0x44, data=[d, ], predata=p) + + # *** PandaDFU API *** + + def get_mcu_type(self): + return self._mcu_type + + def clear_status(self): + pass + + def close(self): + self.dev.close() + + def program(self, address, dat): + bs = 256 # max block size for writing to flash over SPI + dat += b"\xFF" * ((bs - len(dat)) % bs) + for i in range(len(dat) // bs): + block = dat[i * bs:(i + 1) * bs] + self._cmd(0x31, data=[ + struct.pack('>I', address + i*bs), + bytes([len(block) - 1]) + block, + ]) + + def jump(self, address): + self.go_cmd(self._mcu_type.config.bootstub_address) diff --git a/panda_tici/python/usb.py b/panda_tici/python/usb.py new file mode 100644 index 0000000..0a01289 --- /dev/null +++ b/panda_tici/python/usb.py @@ -0,0 +1,98 @@ +import struct + +from .base import BaseHandle, BaseSTBootloaderHandle, TIMEOUT +from .constants import McuType + +class PandaUsbHandle(BaseHandle): + def __init__(self, libusb_handle): + self._libusb_handle = libusb_handle + + def close(self): + self._libusb_handle.close() + + def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = TIMEOUT, expect_disconnect: bool = False): + return self._libusb_handle.controlWrite(request_type, request, value, index, data, timeout) + + def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = TIMEOUT): + return self._libusb_handle.controlRead(request_type, request, value, index, length, timeout) + + def bulkWrite(self, endpoint: int, data: bytes, timeout: int = TIMEOUT) -> int: + return self._libusb_handle.bulkWrite(endpoint, data, timeout) # type: ignore + + def bulkRead(self, endpoint: int, length: int, timeout: int = TIMEOUT) -> bytes: + return self._libusb_handle.bulkRead(endpoint, length, timeout) # type: ignore + + + +class STBootloaderUSBHandle(BaseSTBootloaderHandle): + DFU_DNLOAD = 1 + DFU_UPLOAD = 2 + DFU_GETSTATUS = 3 + DFU_CLRSTATUS = 4 + DFU_ABORT = 6 + + def __init__(self, libusb_device, libusb_handle): + self._libusb_handle = libusb_handle + + # example from F4: lsusb -v | grep Flash + # iInterface 4 @Internal Flash /0x08000000/04*016Kg,01*064Kg,011*128Kg + for i in range(20): + desc = libusb_handle.getStringDescriptor(i, 0) + if desc is not None and desc.startswith("@Internal Flash"): + sector_count = sum([int(s.split('*')[0]) for s in desc.split('/')[-1].split(',')]) + break + mcu_by_sector_count = {m.config.sector_count: m for m in McuType} + assert sector_count in mcu_by_sector_count, f"Unkown MCU: {sector_count=}" + self._mcu_type = mcu_by_sector_count[sector_count] + + def _status(self) -> None: + while 1: + dat = self._libusb_handle.controlRead(0x21, self.DFU_GETSTATUS, 0, 0, 6) + if dat[1] == 0: + break + + def _erase_page_address(self, address: int) -> None: + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 0, 0, b"\x41" + struct.pack("I", address)) + self._status() + + def get_mcu_type(self): + return self._mcu_type + + def erase_sector(self, sector: int): + self._erase_page_address(self._mcu_type.config.sector_address(sector)) + + def clear_status(self): + # Clear status + stat = self._libusb_handle.controlRead(0x21, self.DFU_GETSTATUS, 0, 0, 6) + if stat[4] == 0xa: + self._libusb_handle.controlRead(0x21, self.DFU_CLRSTATUS, 0, 0, 0) + elif stat[4] == 0x9: + self._libusb_handle.controlWrite(0x21, self.DFU_ABORT, 0, 0, b"") + self._status() + stat = str(self._libusb_handle.controlRead(0x21, self.DFU_GETSTATUS, 0, 0, 6)) + + def close(self): + self._libusb_handle.close() + + def program(self, address, dat): + # Set Address Pointer + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 0, 0, b"\x21" + struct.pack("I", address)) + self._status() + + # Program + bs = min(len(dat), self._mcu_type.config.block_size) + dat += b"\xFF" * ((bs - len(dat)) % bs) + for i in range(len(dat) // bs): + ldat = dat[i * bs:(i + 1) * bs] + print("programming %d with length %d" % (i, len(ldat))) + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 2 + i, 0, ldat) + self._status() + + def jump(self, address): + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 0, 0, b"\x21" + struct.pack("I", address)) + self._status() + try: + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 2, 0, b"") + _ = str(self._libusb_handle.controlRead(0x21, self.DFU_GETSTATUS, 0, 0, 6)) + except Exception: + pass diff --git a/panda_tici/python/utils.py b/panda_tici/python/utils.py new file mode 100644 index 0000000..55181e0 --- /dev/null +++ b/panda_tici/python/utils.py @@ -0,0 +1,11 @@ +import os +import logging + +# set up logging +LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper() +logger = logging.getLogger('panda') +logger.setLevel(LOGLEVEL) + +handler = logging.StreamHandler() +handler.setFormatter(logging.Formatter('%(message)s')) +logger.addHandler(handler) diff --git a/panda_tici/scripts/benchmark.py b/panda_tici/scripts/benchmark.py new file mode 100755 index 0000000..7cfb735 --- /dev/null +++ b/panda_tici/scripts/benchmark.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +import time +from contextlib import contextmanager + +from panda_tici import Panda, PandaDFU +from panda_tici.tests.hitl.helpers import get_random_can_messages + + +@contextmanager +def print_time(desc): + start = time.perf_counter() + yield + end = time.perf_counter() + print(f"{end - start:.2f}s - {desc}") + + +if __name__ == "__main__": + with print_time("Panda()"): + p = Panda() + + with print_time("PandaDFU.list()"): + PandaDFU.list() + + fxn = [ + 'reset', + 'reconnect', + 'up_to_date', + 'health', + #'flash', + ] + for f in fxn: + with print_time(f"Panda.{f}()"): + getattr(p, f)() + + p.set_can_loopback(True) + + for n in range(6): + msgs = get_random_can_messages(int(10**n)) + with print_time(f"Panda.can_send_many() - {len(msgs)} msgs"): + p.can_send_many(msgs) + + with print_time("Panda.can_recv()"): + m = p.can_recv() diff --git a/panda_tici/scripts/bulk_write_test.py b/panda_tici/scripts/bulk_write_test.py new file mode 100755 index 0000000..3743371 --- /dev/null +++ b/panda_tici/scripts/bulk_write_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import os +import time +import threading +from typing import Any + +from opendbc.car.structs import CarParams +from panda_tici import Panda + +JUNGLE = "JUNGLE" in os.environ +if JUNGLE: + from panda_tici import PandaJungle + +# The TX buffers on pandas is 0x100 in length. +NUM_MESSAGES_PER_BUS = 10000 + +def flood_tx(panda): + print('Sending!') + msg = b"\xaa" * 4 + packet = [[0xaa, msg, 0], [0xaa, msg, 1], [0xaa, msg, 2]] * NUM_MESSAGES_PER_BUS + panda.can_send_many(packet, timeout=10000) + print(f"Done sending {3*NUM_MESSAGES_PER_BUS} messages!") + +if __name__ == "__main__": + serials = Panda.list() + if JUNGLE: + sender = Panda() + receiver = PandaJungle() + else: + if len(serials) != 2: + raise Exception("Connect two pandas to perform this test!") + sender = Panda(serials[0]) + receiver = Panda(serials[1]) # type: ignore + receiver.set_safety_mode(CarParams.SafetyModel.allOutput) + + sender.set_safety_mode(CarParams.SafetyModel.allOutput) + + # Start transmisson + threading.Thread(target=flood_tx, args=(sender,)).start() + + # Receive as much as we can in a few second time period + rx: list[Any] = [] + old_len = 0 + start_time = time.time() + while time.time() - start_time < 3 or len(rx) > old_len: + old_len = len(rx) + print(old_len) + rx.extend(receiver.can_recv()) + print(f"Received {len(rx)} messages") diff --git a/panda_tici/scripts/can_health.py b/panda_tici/scripts/can_health.py new file mode 100755 index 0000000..d672cd4 --- /dev/null +++ b/panda_tici/scripts/can_health.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import time +import re +from panda_tici import Panda + +RED = '\033[91m' +GREEN = '\033[92m' + +def colorize_errors(value): + if isinstance(value, str): + if re.search(r'(?i)No error', value): + return f'{GREEN}{value}\033[0m' + elif re.search(r'(?i)(? 0.1: + dd = chr(27) + "[2J" + dd += "%5.2f\n" % (sec_since_boot() - start) + for (addr, bus), dat_log in sorted(all_msgs.items()): + dd += "%d: %s(%6d): %s\n" % (bus, "%04X(%4d)" % (addr, addr), len(dat_log), binascii.hexlify(dat_log[-1]).decode()) + print(dd) + lp = sec_since_boot() + +if __name__ == "__main__": + can_printer() diff --git a/panda_tici/scripts/check_fw_size.py b/panda_tici/scripts/check_fw_size.py new file mode 100755 index 0000000..53681c5 --- /dev/null +++ b/panda_tici/scripts/check_fw_size.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +import subprocess +from collections import defaultdict + + +def check_space(file, mcu): + MCUS = { + "H7": { + ".flash": 1024*1024, # FLASH + ".dtcmram": 128*1024, # DTCMRAM + ".itcmram": 64*1024, # ITCMRAM + ".axisram": 320*1024, # AXI SRAM + ".sram12": 32*1024, # SRAM1(16kb) + SRAM2(16kb) + ".sram4": 16*1024, # SRAM4 + ".backup_sram": 4*1024, # SRAM4 + }, + "F4": { + ".flash": 1024*1024, # FLASH + ".dtcmram": 256*1024, # RAM + ".ram_d1": 64*1024, # RAM2 + }, + } + IGNORE_LIST = [ + ".ARM.attributes", + ".comment", + ".debug_line", + ".debug_info", + ".debug_abbrev", + ".debug_aranges", + ".debug_str", + ".debug_ranges", + ".debug_loc", + ".debug_frame", + ".debug_line_str", + ".debug_rnglists", + ".debug_loclists", + ] + FLASH = [ + ".isr_vector", + ".text", + ".rodata", + ".data" + ] + RAM = [ + ".data", + ".bss", + "._user_heap_stack" # _user_heap_stack considered free? + ] + + result = {} + calcs = defaultdict(int) + + output = str(subprocess.check_output(f"arm-none-eabi-size -x --format=sysv {file}", shell=True), 'utf-8') + + for row in output.split('\n'): + pop = False + line = row.split() + if len(line) == 3 and line[0].startswith('.'): + if line[0] in IGNORE_LIST: + continue + result[line[0]] = [line[1], line[2]] + if line[0] in FLASH: + calcs[".flash"] += int(line[1], 16) + pop = True + if line[0] in RAM: + calcs[".dtcmram"] += int(line[1], 16) + pop = True + if pop: + result.pop(line[0]) + + if len(result): + for line in result: + calcs[line] += int(result[line][0], 16) + + print(f"=======SUMMARY FOR {mcu} FILE {file}=======") + for line in calcs: + if line in MCUS[mcu]: + used_percent = (100 - (MCUS[mcu][line] - calcs[line]) / MCUS[mcu][line] * 100) + print(f"SECTION: {line} size: {MCUS[mcu][line]} USED: {calcs[line]}({used_percent:.2f}%) FREE: {MCUS[mcu][line] - calcs[line]}") + else: + print(line, calcs[line]) + print() + + +if __name__ == "__main__": + # red panda + check_space("../board/obj/bootstub.panda_h7.elf", "H7") + check_space("../board/obj/panda_h7.elf", "H7") + # black panda + check_space("../board/obj/bootstub.panda.elf", "F4") + check_space("../board/obj/panda.elf", "F4") + # jungle v1 + check_space("../board/jungle/obj/bootstub.panda_jungle.elf", "F4") + check_space("../board/jungle/obj/panda_jungle.elf", "F4") + # jungle v2 + check_space("../board/jungle/obj/bootstub.panda_jungle_h7.elf", "H7") + check_space("../board/jungle/obj/panda_jungle_h7.elf", "H7") diff --git a/panda_tici/scripts/debug_console.py b/panda_tici/scripts/debug_console.py new file mode 100755 index 0000000..4adefdf --- /dev/null +++ b/panda_tici/scripts/debug_console.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +import os +import sys +import time +import select +import codecs + +from panda_tici import Panda + +setcolor = ["\033[1;32;40m", "\033[1;31;40m"] +unsetcolor = "\033[00m" + +port_number = int(os.getenv("PORT", "0")) +claim = os.getenv("CLAIM") is not None +no_color = os.getenv("NO_COLOR") is not None +no_reconnect = os.getenv("NO_RECONNECT") is not None + +if __name__ == "__main__": + while True: + try: + serials = Panda.list() + if os.getenv("SERIAL"): + serials = [x for x in serials if x == os.getenv("SERIAL")] + + pandas = [Panda(x, claim=claim) for x in serials] + decoders = [codecs.getincrementaldecoder('utf-8')() for _ in pandas] + + if not len(pandas): + print("no pandas found") + if no_reconnect: + sys.exit(0) + time.sleep(1) + continue + + if os.getenv("BAUD") is not None: + for panda in pandas: + panda.set_uart_baud(port_number, int(os.getenv("BAUD"))) # type: ignore + + while True: + for i, panda in enumerate(pandas): + while True: + ret = panda.serial_read(port_number) + if len(ret) > 0: + decoded = decoders[i].decode(ret) + if no_color: + sys.stdout.write(decoded) + else: + sys.stdout.write(setcolor[i] + decoded + unsetcolor) + sys.stdout.flush() + else: + break + if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []): + ln = sys.stdin.readline() + if claim: + panda.serial_write(port_number, ln) + time.sleep(0.01) + except KeyboardInterrupt: + break + except Exception: + print("panda disconnected!") + time.sleep(0.5) diff --git a/panda_tici/scripts/development/register_hashmap_spread.py b/panda_tici/scripts/development/register_hashmap_spread.py new file mode 100755 index 0000000..854ddd1 --- /dev/null +++ b/panda_tici/scripts/development/register_hashmap_spread.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import matplotlib.pyplot as plt + +HASHING_PRIME = 23 +REGISTER_MAP_SIZE = 0x3FF +BYTES_PER_REG = 4 + +# From ST32F413 datasheet +REGISTER_ADDRESS_REGIONS = [ + (0x40000000, 0x40007FFF), + (0x40010000, 0x400107FF), + (0x40011000, 0x400123FF), + (0x40012C00, 0x40014BFF), + (0x40015000, 0x400153FF), + (0x40015800, 0x40015BFF), + (0x40016000, 0x400167FF), + (0x40020000, 0x40021FFF), + (0x40023000, 0x400233FF), + (0x40023800, 0x40023FFF), + (0x40026000, 0x400267FF), + (0x50000000, 0x5003FFFF), + (0x50060000, 0x500603FF), + (0x50060800, 0x50060BFF), + (0x50060800, 0x50060BFF), + (0xE0000000, 0xE00FFFFF) +] + +def _hash(reg_addr): + return (((reg_addr >> 16) ^ ((((reg_addr + 1) & 0xFFFF) * HASHING_PRIME) & 0xFFFF)) & REGISTER_MAP_SIZE) + +# Calculate hash for each address +hashes = [] +double_hashes = [] +for (start_addr, stop_addr) in REGISTER_ADDRESS_REGIONS: + for addr in range(start_addr, stop_addr + 1, BYTES_PER_REG): + h = _hash(addr) + hashes.append(h) + double_hashes.append(_hash(h)) + +# Make histograms +plt.subplot(2, 1, 1) +plt.hist(hashes, bins=REGISTER_MAP_SIZE) +plt.title("Number of collisions per _hash") +plt.xlabel("Address") + +plt.subplot(2, 1, 2) +plt.hist(double_hashes, bins=REGISTER_MAP_SIZE) +plt.title("Number of collisions per double _hash") +plt.xlabel("Address") +plt.show() diff --git a/panda_tici/scripts/echo.py b/panda_tici/scripts/echo.py new file mode 100755 index 0000000..996120c --- /dev/null +++ b/panda_tici/scripts/echo.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +from opendbc.car.structs import CarParams +from panda_tici import Panda + +# This script is intended to be used in conjunction with the echo_loopback_test.py test script from panda jungle. +# It sends a reversed response back for every message received containing b"test". +if __name__ == "__main__": + p = Panda() + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_power_save(False) + + while True: + incoming = p.can_recv() + for message in incoming: + address, data, bus = message + if b'test' in data: + p.can_send(address, data[::-1], bus) diff --git a/panda_tici/scripts/fan/fan_test.py b/panda_tici/scripts/fan/fan_test.py new file mode 100755 index 0000000..83dce6e --- /dev/null +++ b/panda_tici/scripts/fan/fan_test.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +import time + +from panda_tici import Panda + +if __name__ == "__main__": + p = Panda() + power = 0 + while True: + p.set_fan_power(power) + time.sleep(5) + print("Power: ", power, "RPM:", str(p.get_fan_rpm()), "Expected:", int(6500 * power / 100)) + power += 10 + power %= 110 diff --git a/panda_tici/scripts/fan/fan_tuning.py b/panda_tici/scripts/fan/fan_tuning.py new file mode 100755 index 0000000..2bbe928 --- /dev/null +++ b/panda_tici/scripts/fan/fan_tuning.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +import json +import time +import threading + +from panda_tici import Panda + +def drain_serial(p): + ret = [] + while True: + d = p.serial_read(0) + if len(d) == 0: + break + ret.append(d) + return ret + + +fan_cmd = 0. + +def logger(event): + # requires a build with DEBUG_FAN + with Panda(claim=False) as p, open('/tmp/fan_log', 'w') as f: + power = None + target_rpm = None + stall_count = None + rpm_fast = None + t = time.monotonic() + + drain_serial(p) + while not event.is_set(): + p.set_fan_power(fan_cmd) + + for l in drain_serial(p)[::-1]: + ns = l.decode('utf8').strip().split(' ') + if len(ns) == 4: + target_rpm, rpm_fast, power, stall_count = (int(n, 16) for n in ns) + break + + dat = { + 't': time.monotonic() - t, + 'cmd_power': fan_cmd, + 'pwm_power': power, + 'target_rpm': target_rpm, + 'rpm_fast': rpm_fast, + 'rpm': p.get_fan_rpm(), + 'stall_counter': stall_count, + 'total_stall_count': p.health()['fan_stall_count'], + } + f.write(json.dumps(dat) + '\n') + time.sleep(1/16.) + p.set_fan_power(0) + +def get_overshoot_rpm(p, power): + global fan_cmd + + # make sure the fan is stopped completely + fan_cmd = 0. + while p.get_fan_rpm() > 100: + time.sleep(0.1) + time.sleep(3) + + # set it to 30% power to mimic going onroad + fan_cmd = power + max_rpm = 0 + max_power = 0 + for _ in range(70): + max_rpm = max(max_rpm, p.get_fan_rpm()) + max_power = max(max_power, p.health()['fan_power']) + time.sleep(0.1) + + # tolerate 10% overshoot + expected_rpm = Panda.MAX_FAN_RPMs[bytes(p.get_type())] * power / 100 + overshoot = (max_rpm / expected_rpm) - 1 + + return overshoot, max_rpm, max_power + + +if __name__ == "__main__": + event = threading.Event() + threading.Thread(target=logger, args=(event, )).start() + + try: + p = Panda() + for power in range(10, 101, 10): + overshoot, max_rpm, max_power = get_overshoot_rpm(p, power) + print(f"Fan power {power}%: overshoot {overshoot:.2%}, Max RPM {max_rpm}, Max power {max_power}%") + finally: + event.set() diff --git a/panda_tici/scripts/get_version.py b/panda_tici/scripts/get_version.py new file mode 100755 index 0000000..766874b --- /dev/null +++ b/panda_tici/scripts/get_version.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +from panda_tici import Panda + +if __name__ == "__main__": + for p in Panda.list(): + pp = Panda(p) + print(f"{pp.get_serial()[0]}: {pp.get_version()}") diff --git a/panda_tici/scripts/health_test.py b/panda_tici/scripts/health_test.py new file mode 100755 index 0000000..5666ce3 --- /dev/null +++ b/panda_tici/scripts/health_test.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +import time +from panda_tici import Panda + +if __name__ == "__main__": + i = 0 + pi = 0 + + panda = Panda() + while True: + st = time.monotonic() + while time.monotonic() - st < 1: + panda.health() + i += 1 + print(i, panda.health(), "\n") + print(f"Speed: {i - pi}Hz") + pi = i + diff --git a/panda_tici/scripts/ir_test.py b/panda_tici/scripts/ir_test.py new file mode 100755 index 0000000..104352f --- /dev/null +++ b/panda_tici/scripts/ir_test.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +import time + +from panda_tici import Panda + +power = 0 +if __name__ == "__main__": + p = Panda() + while True: + p.set_ir_power(power) + print("Power: ", str(power)) + time.sleep(1) + power += 10 + power %= 100 diff --git a/panda_tici/scripts/loopback_test.py b/panda_tici/scripts/loopback_test.py new file mode 100755 index 0000000..a0c0919 --- /dev/null +++ b/panda_tici/scripts/loopback_test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 + +import os +import time +import random +import argparse +from itertools import permutations + +from opendbc.car.structs import CarParams +from panda_tici import Panda + +def get_test_string(): + return b"test" + os.urandom(10) + +def run_test(sleep_duration): + pandas = Panda.list() + print(pandas) + + if len(pandas) < 2: + raise Exception("Minimum two pandas are needed for test") + + run_test_w_pandas(pandas, sleep_duration) + +def run_test_w_pandas(pandas, sleep_duration): + h = [Panda(x) for x in pandas] + print("H", h) + + for hh in h: + hh.set_safety_mode(CarParams.SafetyModel.allOutput) + + # test both directions + for ho in permutations(list(range(len(h))), r=2): + print("***************** TESTING", ho) + + panda0, panda1 = h[ho[0]], h[ho[1]] + + # **** test health packet **** + print("health", ho[0], h[ho[0]].health()) + + # **** test can line loopback **** + for bus, obd in [(0, False), (1, False), (2, False), (1, True), (2, True)]: + print("\ntest can", bus) + # flush + cans_echo = panda0.can_recv() + cans_loop = panda1.can_recv() + + panda0.set_obd(None) + panda1.set_obd(None) + + if obd is True: + panda0.set_obd(bus) + panda1.set_obd(bus) + bus = 3 + + # send the characters + at = random.randint(1, 2000) + st = get_test_string()[0:8] + panda0.can_send(at, st, bus) + time.sleep(0.1) + + # check for receive + cans_echo = panda0.can_recv() + cans_loop = panda1.can_recv() + + print("Bus", bus, "echo", cans_echo, "loop", cans_loop) + + assert len(cans_echo) == 1 + assert len(cans_loop) == 1 + + assert cans_echo[0][0] == at + assert cans_loop[0][0] == at + + assert cans_echo[0][1] == st + assert cans_loop[0][1] == st + + assert cans_echo[0][2] == 0x80 | bus + if cans_loop[0][2] != bus: + print("EXPECTED %d GOT %d" % (bus, cans_loop[0][2])) + assert cans_loop[0][2] == bus + + print("CAN pass", bus, ho) + time.sleep(sleep_duration) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("-n", type=int, help="Number of test iterations to run") + parser.add_argument("-sleep", type=int, help="Sleep time between tests", default=0) + args = parser.parse_args() + + if args.n is None: + while True: + run_test(sleep_duration=args.sleep) + else: + for _ in range(args.n): + run_test(sleep_duration=args.sleep) diff --git a/panda_tici/scripts/make_release.sh b/panda_tici/scripts/make_release.sh new file mode 100755 index 0000000..cfecac3 --- /dev/null +++ b/panda_tici/scripts/make_release.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +export CERT=/home/batman/xx/pandaextra/certs/release + +if [ ! -f "$CERT" ]; then + echo "No release cert found, cannot build release." + echo "You probably aren't looking to do this anyway." + exit +fi + +export RELEASE=1 +export BUILDER=DEV + +cd $DIR/../board +scons -u -c +rm obj/* +scons -u +cd obj +RELEASE_NAME=$(awk '{print $1}' version) +zip -j ../../release/panda-$RELEASE_NAME.zip version panda.bin.signed bootstub.panda.bin panda_h7.bin.signed bootstub.panda_h7.bin diff --git a/panda_tici/scripts/message_drop_test.py b/panda_tici/scripts/message_drop_test.py new file mode 100755 index 0000000..22a39f6 --- /dev/null +++ b/panda_tici/scripts/message_drop_test.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +import os +import usb1 +import time +import struct +import itertools +import threading +from typing import Any + +from opendbc.car.structs import CarParams +from panda_tici import Panda + +JUNGLE = "JUNGLE" in os.environ +if JUNGLE: + from panda_tici import PandaJungle + +# Generate unique messages +NUM_MESSAGES_PER_BUS = 10000 +messages = [bytes(struct.pack("Q", i)) for i in range(NUM_MESSAGES_PER_BUS)] +tx_messages = list(itertools.chain.from_iterable([[0xaa, msg, 0], [0xaa, msg, 1], [0xaa, msg, 2]] for msg in messages)) + +def flood_tx(panda): + print('Sending!') + transferred = 0 + while True: + try: + print(f"Sending block {transferred}-{len(tx_messages)}: ", end="") + panda.can_send_many(tx_messages[transferred:], timeout=10) + print("OK") + break + except usb1.USBErrorTimeout as e: + transferred += (e.transferred // 16) + print("timeout, transferred: ", transferred) + + print(f"Done sending {3*NUM_MESSAGES_PER_BUS} messages!") + +if __name__ == "__main__": + serials = Panda.list() + receiver: Panda | PandaJungle + if JUNGLE: + sender = Panda() + receiver = PandaJungle() + else: + if len(serials) != 2: + raise Exception("Connect two pandas to perform this test!") + sender = Panda(serials[0]) + receiver = Panda(serials[1]) + receiver.set_safety_mode(CarParams.SafetyModel.allOutput) + + sender.set_safety_mode(CarParams.SafetyModel.allOutput) + + # Start transmisson + threading.Thread(target=flood_tx, args=(sender,)).start() + + # Receive as much as we can, and stop when there hasn't been anything for a second + rx: list[Any] = [] + old_len = 0 + last_change = time.monotonic() + while time.monotonic() - last_change < 1: + if old_len < len(rx): + last_change = time.monotonic() + old_len = len(rx) + + rx.extend(receiver.can_recv()) + print(f"Received {len(rx)} messages") + + # Check if we received everything + for bus in range(3): + received_msgs = {bytes(m[1]) for m in filter(lambda m, b=bus: m[2] == b, rx)} # type: ignore + dropped_msgs = set(messages).difference(received_msgs) + print(f"Bus {bus} dropped msgs: {len(list(dropped_msgs))} / {len(messages)}") diff --git a/panda_tici/scripts/read_flash_spi.py b/panda_tici/scripts/read_flash_spi.py new file mode 100755 index 0000000..559a1f6 --- /dev/null +++ b/panda_tici/scripts/read_flash_spi.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +from panda_tici import Panda, PandaDFU + +if __name__ == "__main__": + try: + from openpilot.system.hardware import HARDWARE + HARDWARE.recover_internal_panda() + Panda.wait_for_dfu(None, 5) + except Exception: + pass + + p = PandaDFU(None) + cfg = p.get_mcu_type().config + + def readmem(addr, length, fn): + print(f"reading {hex(addr)} {hex(length)} bytes to {fn}") + max_size = 255 + with open(fn, "wb") as f: + to_read = length + while to_read > 0: + l = min(to_read, max_size) + dat = p._handle.read(addr, l) + assert len(dat) == l + f.write(dat) + + to_read -= len(dat) + addr += len(dat) + + addr = cfg.bootstub_address + for i, sector_size in enumerate(cfg.sector_sizes): + readmem(addr, sector_size, f"sector_{i}.bin") + addr += sector_size diff --git a/panda_tici/scripts/read_st_flash.sh b/panda_tici/scripts/read_st_flash.sh new file mode 100755 index 0000000..65b0709 --- /dev/null +++ b/panda_tici/scripts/read_st_flash.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +rm -f /tmp/dump_bootstub +rm -f /tmp/dump_main +dfu-util -a 0 -s 0x08000000 -U /tmp/dump_bootstub +dfu-util -a 0 -s 0x08004000 -U /tmp/dump_main + diff --git a/panda_tici/scripts/reflash_internal_panda.py b/panda_tici/scripts/reflash_internal_panda.py new file mode 100755 index 0000000..0a5045a --- /dev/null +++ b/panda_tici/scripts/reflash_internal_panda.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +import time +from panda_tici import Panda, PandaDFU + +class GPIO: + STM_RST_N = 124 + STM_BOOT0 = 134 + + +def gpio_init(pin, output): + with open(f"/sys/class/gpio/gpio{pin}/direction", 'wb') as f: + f.write(b"out" if output else b"in") + +def gpio_set(pin, high): + with open(f"/sys/class/gpio/gpio{pin}/value", 'wb') as f: + f.write(b"1" if high else b"0") + + +if __name__ == "__main__": + for pin in (GPIO.STM_RST_N, GPIO.STM_BOOT0): + gpio_init(pin, True) + + # flash bootstub + print("resetting into DFU") + gpio_set(GPIO.STM_RST_N, 1) + gpio_set(GPIO.STM_BOOT0, 1) + time.sleep(0.2) + gpio_set(GPIO.STM_RST_N, 0) + gpio_set(GPIO.STM_BOOT0, 0) + + # bootstub flash takes 2s and is limited by the 255 byte flashing chunk size + print("flashing bootstub") + assert Panda.wait_for_dfu(None, 5) + PandaDFU(None).recover() + + print("flashing app") + assert Panda.wait_for_panda(None, 5) + p = Panda() + assert p.bootstub + p.flash() diff --git a/panda_tici/scripts/relay_test.py b/panda_tici/scripts/relay_test.py new file mode 100755 index 0000000..b0561b1 --- /dev/null +++ b/panda_tici/scripts/relay_test.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python +import time +from opendbc.car.structs import CarParams +from panda_tici import Panda + +p = Panda() + +while True: + p.set_safety_mode(CarParams.SafetyModel.toyota) + p.send_heartbeat() + print("ON") + time.sleep(1) + p.set_safety_mode(CarParams.SafetyModel.noOutput) + p.send_heartbeat() + print("OFF") + time.sleep(1) + diff --git a/panda_tici/scripts/restore_flash_spi.py b/panda_tici/scripts/restore_flash_spi.py new file mode 100755 index 0000000..1c60388 --- /dev/null +++ b/panda_tici/scripts/restore_flash_spi.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +from panda_tici import Panda, PandaDFU, STBootloaderSPIHandle + +if __name__ == "__main__": + try: + from openpilot.system.hardware import HARDWARE + HARDWARE.recover_internal_panda() + Panda.wait_for_dfu(None, 5) + except Exception: + pass + + p = PandaDFU(None) + assert isinstance(p._handle, STBootloaderSPIHandle) + cfg = p.get_mcu_type().config + + print("restoring from backup...") + addr = cfg.bootstub_address + for i, sector_size in enumerate(cfg.sector_sizes): + print(f"- sector #{i}") + p._handle.erase_sector(i) + with open(f"sector_{i}.bin", "rb") as f: + dat = f.read() + assert len(dat) == sector_size + p._handle.program(addr, dat) + addr += len(dat) + + p.reset() diff --git a/panda_tici/scripts/som_debug.sh b/panda_tici/scripts/som_debug.sh new file mode 100755 index 0000000..6f0a865 --- /dev/null +++ b/panda_tici/scripts/som_debug.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +PYTHONUNBUFFERED=1 NO_COLOR=1 CLAIM=1 PORT=4 ./debug_console.py diff --git a/panda_tici/scripts/spam_can.py b/panda_tici/scripts/spam_can.py new file mode 100755 index 0000000..3103ccc --- /dev/null +++ b/panda_tici/scripts/spam_can.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +import os +import random + +from opendbc.car.structs import CarParams +from panda_tici import Panda + +def get_test_string(): + return b"test" + os.urandom(10) + +if __name__ == "__main__": + p = Panda() + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + print("Spamming all buses...") + while True: + at = random.randint(1, 2000) + st = get_test_string()[0:8] + bus = random.randint(0, 2) + p.can_send(at, st, bus) + # print("Sent message on bus: ", bus) diff --git a/panda_tici/scripts/standalone_test.py b/panda_tici/scripts/standalone_test.py new file mode 100755 index 0000000..e5a5ba7 --- /dev/null +++ b/panda_tici/scripts/standalone_test.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +import struct +import time + +from opendbc.car.structs import CarParams +from panda_tici import Panda + +if __name__ == "__main__": + p = Panda() + print(p.get_serial()) + print(p.health()) + + t1 = time.time() + for _ in range(100): + p.get_serial() + t2 = time.time() + print("100 requests took %.2f ms" % ((t2 - t1) * 1000)) + + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + a = 0 + while True: + # flood + msg = b"\xaa" * 4 + struct.pack("I", a) + p.can_send(0xaa, msg, 0) + p.can_send(0xaa, msg, 1) + p.can_send(0xaa, msg, 4) + time.sleep(0.01) + + dat = p.can_recv() + if len(dat) > 0: + print(dat) + a += 1 diff --git a/panda_tici/scripts/test_canfd.py b/panda_tici/scripts/test_canfd.py new file mode 100755 index 0000000..ce3ddd7 --- /dev/null +++ b/panda_tici/scripts/test_canfd.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +import os +import time +import random +from collections import defaultdict +from opendbc.car.structs import CarParams +from panda_tici import Panda, calculate_checksum, DLC_TO_LEN +from panda_tici import PandaJungle +from panda_tici.tests.hitl.helpers import time_many_sends + +H7_HW_TYPES = [Panda.HW_TYPE_RED_PANDA, Panda.HW_TYPE_RED_PANDA_V2] +JUNGLE_SERIAL = os.getenv("JUNGLE") +H7_PANDAS_EXCLUDE = [] # type: ignore +if os.getenv("H7_PANDAS_EXCLUDE"): + H7_PANDAS_EXCLUDE = os.getenv("H7_PANDAS_EXCLUDE").strip().split(" ") # type: ignore + +def panda_reset(): + panda_serials = [] + + panda_jungle = PandaJungle(JUNGLE_SERIAL) + panda_jungle.set_can_silent(True) + panda_jungle.set_panda_power(False) + time.sleep(1) + panda_jungle.set_panda_power(True) + time.sleep(4) + + for serial in Panda.list(): + if serial not in H7_PANDAS_EXCLUDE: + with Panda(serial=serial) as p: + if p.get_type() in H7_HW_TYPES: + p.reset() + panda_serials.append(serial) + + print("test pandas", panda_serials) + assert len(panda_serials) == 2, "Two H7 pandas required" + + return panda_serials + +def panda_init(serial, enable_canfd=False, enable_non_iso=False): + p = Panda(serial=serial) + p.set_power_save(False) + for bus in range(3): + p.set_can_speed_kbps(0, 500) + if enable_canfd: + p.set_can_data_speed_kbps(bus, 2000) + if enable_non_iso: + p.set_canfd_non_iso(bus, True) + p.set_safety_mode(CarParams.SafetyModel.allOutput) + return p + +def test_canfd_throughput(p, p_recv=None): + two_pandas = p_recv is not None + p.set_safety_mode(CarParams.SafetyModel.allOutput) + if two_pandas: + p_recv.set_safety_mode(CarParams.SafetyModel.allOutput) + # enable output mode + else: + p.set_can_loopback(True) + + tests = [ + [500, 1000, 2000], # speeds + [93, 87, 78], # saturation thresholds + ] + + for i in range(len(tests[0])): + # set bus 0 data speed to speed + p.set_can_data_speed_kbps(0, tests[0][i]) + if p_recv is not None: + p_recv.set_can_data_speed_kbps(0, tests[0][i]) + time.sleep(0.05) + + comp_kbps = time_many_sends(p, 0, p_recv=p_recv, msg_count=400, two_pandas=two_pandas, msg_len=64) + + # bit count from https://en.wikipedia.org/wiki/CAN_bus + saturation_pct = (comp_kbps / tests[0][i]) * 100.0 + assert saturation_pct > tests[1][i] + assert saturation_pct < 100 + +def canfd_test(p_send, p_recv): + for n in range(100): + sent_msgs = defaultdict(set) + to_send = [] + for _ in range(200): + bus = random.randrange(3) + for dlc in range(len(DLC_TO_LEN)): + address = random.randrange(1, 1<<29) + data = bytearray(random.getrandbits(8) for _ in range(DLC_TO_LEN[dlc])) + if len(data) >= 2: + data[0] = calculate_checksum(data[1:] + bytes(str(address), encoding="utf-8")) + to_send.append([address, data, bus]) + sent_msgs[bus].add((address, bytes(data))) + + p_send.can_send_many(to_send, timeout=0) + + start_time = time.monotonic() + while (time.monotonic() - start_time < 1) and any(len(x) > 0 for x in sent_msgs.values()): + incoming = p_recv.can_recv() + for msg in incoming: + address, data, bus = msg + if len(data) >= 2: + assert calculate_checksum(data[1:] + bytes(str(address), encoding="utf-8")) == data[0] + k = (address, bytes(data)) + assert k in sent_msgs[bus], f"message {k} was never sent on bus {bus}" + sent_msgs[bus].discard(k) + + for bus in range(3): + assert not len(sent_msgs[bus]), f"loop {n}: bus {bus} missing {len(sent_msgs[bus])} messages" + +def setup_test(enable_non_iso=False): + panda_serials = panda_reset() + + p_send = panda_init(panda_serials[0], enable_canfd=False, enable_non_iso=enable_non_iso) + p_recv = panda_init(panda_serials[1], enable_canfd=True, enable_non_iso=enable_non_iso) + + # Check that sending panda CAN FD and BRS are turned off + for bus in range(3): + health = p_send.can_health(bus) + assert not health["canfd_enabled"] + assert not health["brs_enabled"] + assert health["canfd_non_iso"] == enable_non_iso + + # Receiving panda sends dummy CAN FD message that should enable CAN FD on sender side + for bus in range(3): + p_recv.can_send(0x200, b"dummymessage", bus) + p_recv.can_recv() + p_send.can_recv() + + # Check if all tested buses on sending panda have swithed to CAN FD with BRS + for bus in range(3): + health = p_send.can_health(bus) + assert health["canfd_enabled"] + assert health["brs_enabled"] + assert health["canfd_non_iso"] == enable_non_iso + + return p_send, p_recv + +def main(): + print("[TEST CAN-FD]") + p_send, p_recv = setup_test() + canfd_test(p_send, p_recv) + + print("[TEST CAN-FD non-ISO]") + p_send, p_recv = setup_test(enable_non_iso=True) + canfd_test(p_send, p_recv) + + print("[TEST CAN-FD THROUGHPUT]") + panda_serials = panda_reset() + p_send = panda_init(panda_serials[0], enable_canfd=True) + p_recv = panda_init(panda_serials[1], enable_canfd=True) + test_canfd_throughput(p_send, p_recv) + +if __name__ == "__main__": + main() diff --git a/panda_tici/setup.sh b/panda_tici/setup.sh new file mode 100755 index 0000000..016b182 --- /dev/null +++ b/panda_tici/setup.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +PLATFORM=$(uname -s) + +echo "installing dependencies" +if [[ $PLATFORM == "Darwin" ]]; then + export HOMEBREW_NO_AUTO_UPDATE=1 + brew install --cask gcc-arm-embedded + brew install python3 gcc@13 +elif [[ $PLATFORM == "Linux" ]]; then + sudo apt-get install -y --no-install-recommends \ + curl \ + make g++ git libnewlib-arm-none-eabi \ + libusb-1.0-0 \ + gcc-arm-none-eabi python3-pip python3-venv python3-dev +else + echo "WARNING: unsupported platform. skipping apt/brew install." +fi + +if ! command -v uv &>/dev/null; then + echo "'uv' is not installed. Installing 'uv'..." + curl -LsSf https://astral.sh/uv/install.sh | sh + + # doesn't require sourcing on all platforms + set +e + source $HOME/.local/bin/env + set -e +fi + +export UV_PROJECT_ENVIRONMENT="$DIR/.venv" +uv sync --all-extras +source "$DIR/.venv/bin/activate" diff --git a/panda_tici/test.sh b/panda_tici/test.sh new file mode 100755 index 0000000..7287977 --- /dev/null +++ b/panda_tici/test.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +# *** env setup *** +source ./setup.sh + +# *** build *** +scons -j8 + +# *** lint *** +ruff check . +mypy python/ + + +# *** test *** + +# TODO: make xdist and randomly work +pytest -n0 --randomly-dont-reorganize tests/ diff --git a/panda_tici/tests/hitl/1_program.py b/panda_tici/tests/hitl/1_program.py new file mode 100644 index 0000000..ec293a7 --- /dev/null +++ b/panda_tici/tests/hitl/1_program.py @@ -0,0 +1,103 @@ +import os +import time +import pytest + +from panda_tici import Panda, PandaDFU, McuType, BASEDIR + + +def check_signature(p): + assert not p.bootstub, "Flashed firmware not booting. Stuck in bootstub." + assert p.up_to_date() + + +def test_dfu(p): + app_mcu_type = p.get_mcu_type() + dfu_serial = p.get_dfu_serial() + + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + assert Panda.wait_for_dfu(dfu_serial, timeout=19), "failed to enter DFU" + + dfu = PandaDFU(dfu_serial) + assert dfu.get_mcu_type() == app_mcu_type + + assert dfu_serial in PandaDFU.list() + + dfu._handle.clear_status() + dfu.reset() + p.reconnect() + +# TODO: make more comprehensive bootstub tests and run on a few production ones + current +# TODO: also test release-signed app +@pytest.mark.timeout(30) +def test_known_bootstub(p): + """ + Test that compiled app can work with known production bootstub + """ + known_bootstubs = { + # covers the two cases listed in Panda.connect + McuType.F4: [ + # case A - no bcdDevice or panda type, has to assume F4 + "bootstub_f4_first_dos_production.panda.bin", + + # case B - just bcdDevice + "bootstub_f4_only_bcd.panda.bin", + ], + McuType.H7: ["bootstub.panda_h7.bin"], + } + + for kb in known_bootstubs[p.get_mcu_type()]: + app_ids = (p.get_mcu_type(), p.get_usb_serial()) + assert None not in app_ids + + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + + dfu_serial = p.get_dfu_serial() + assert Panda.wait_for_dfu(dfu_serial, timeout=30) + + dfu = PandaDFU(dfu_serial) + with open(os.path.join(BASEDIR, "tests/hitl/known_bootstub", kb), "rb") as f: + code = f.read() + + dfu.program_bootstub(code) + dfu.reset() + + p.connect(claim=False, wait=True) + + # check for MCU or serial mismatch + with Panda(p._serial, claim=False) as np: + bootstub_ids = (np.get_mcu_type(), np.get_usb_serial()) + assert app_ids == bootstub_ids + + # ensure we can flash app and it jumps to app + p.flash() + check_signature(p) + assert not p.bootstub + +@pytest.mark.timeout(25) +def test_recover(p): + assert p.recover(timeout=30) + check_signature(p) + +@pytest.mark.timeout(25) +def test_flash(p): + # test flash from bootstub + serial = p._serial + assert serial is not None + p.reset(enter_bootstub=True) + p.close() + time.sleep(2) + + with Panda(serial) as np: + assert np.bootstub + assert np._serial == serial + np.flash() + + p.reconnect() + p.reset() + check_signature(p) + + # test flash from app + p.flash() + check_signature(p) diff --git a/panda_tici/tests/hitl/2_health.py b/panda_tici/tests/hitl/2_health.py new file mode 100644 index 0000000..fe3a4db --- /dev/null +++ b/panda_tici/tests/hitl/2_health.py @@ -0,0 +1,67 @@ +import time +import pytest + +from opendbc.car.hyundai.values import HyundaiSafetyFlags +from opendbc.car.structs import CarParams +from panda_tici import Panda + + +@pytest.mark.skip_panda_types((Panda.HW_TYPE_DOS, )) +def test_voltage(p): + for _ in range(10): + voltage = p.health()['voltage'] + assert ((voltage > 11000) and (voltage < 13000)) + time.sleep(0.1) + +def test_hw_type(p): + """ + hw type should be same in bootstub as application + """ + + hw_type = p.get_type() + mcu_type = p.get_mcu_type() + assert mcu_type is not None + + app_uid = p.get_uid() + usb_serial = p.get_usb_serial() + assert app_uid == usb_serial + + p.reset(enter_bootstub=True, reconnect=True) + p.close() + time.sleep(3) + with Panda(p.get_usb_serial()) as pp: + assert pp.bootstub + assert pp.get_type() == hw_type, "Bootstub and app hw type mismatch" + assert pp.get_mcu_type() == mcu_type, "Bootstub and app MCU type mismatch" + assert pp.get_uid() == app_uid + +def test_heartbeat(p, panda_jungle): + panda_jungle.set_ignition(True) + # TODO: add more cases here once the tests aren't super slow + p.set_safety_mode(mode=CarParams.SafetyModel.hyundai, param=HyundaiSafetyFlags.LONG) + p.send_heartbeat() + assert p.health()['safety_mode'] == CarParams.SafetyModel.hyundai + assert p.health()['safety_param'] == HyundaiSafetyFlags.LONG + + # shouldn't do anything once we're in a car safety mode + p.set_heartbeat_disabled() + + time.sleep(6.) + + h = p.health() + assert h['heartbeat_lost'] + assert h['safety_mode'] == CarParams.SafetyModel.silent + assert h['safety_param'] == 0 + assert h['controls_allowed'] == 0 + +def test_microsecond_timer(p): + start_time = p.get_microsecond_timer() + time.sleep(1) + end_time = p.get_microsecond_timer() + + # account for uint32 overflow + if end_time < start_time: + end_time += 2**32 + + time_diff = (end_time - start_time) / 1e6 + assert 0.98 < time_diff < 1.02, f"Timer not running at the correct speed! (got {time_diff:.2f}s instead of 1.0s)" diff --git a/panda_tici/tests/hitl/3_usb.py b/panda_tici/tests/hitl/3_usb.py new file mode 100644 index 0000000..ba7081a --- /dev/null +++ b/panda_tici/tests/hitl/3_usb.py @@ -0,0 +1,92 @@ +import time +import pytest +from flaky import flaky + +from opendbc.car.structs import CarParams +from panda import Panda +from panda.tests.hitl.helpers import time_many_sends + +pytestmark = [ + pytest.mark.test_panda_types((Panda.HW_TYPE_DOS, Panda.HW_TYPE_RED_PANDA)) +] + +def test_can_loopback(p): + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_can_loopback(True) + + for bus in (0, 1, 2): + # set bus 0 speed to 5000 + p.set_can_speed_kbps(bus, 500) + + # send a message on bus 0 + p.can_send(0x1aa, b"message", bus) + + # confirm receive both on loopback and send receipt + time.sleep(0.05) + r = p.can_recv() + sr = [x for x in r if x[2] == 0x80 | bus] + lb = [x for x in r if x[2] == bus] + assert len(sr) == 1 + assert len(lb) == 1 + + # confirm data is correct + assert 0x1aa == sr[0][0] == lb[0][0] + assert b"message" == sr[0][1] == lb[0][1] + +def test_reliability(p): + MSG_COUNT = 100 + + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_can_loopback(True) + p.set_can_speed_kbps(0, 1000) + + addrs = list(range(100, 100 + MSG_COUNT)) + ts = [(j, b"\xaa" * 8, 0) for j in addrs] + + for _ in range(100): + st = time.monotonic() + + p.can_send_many(ts) + + r = [] + while len(r) < 200 and (time.monotonic() - st) < 0.5: + r.extend(p.can_recv()) + + sent_echo = [x for x in r if x[2] == 0x80] + loopback_resp = [x for x in r if x[2] == 0] + + assert sorted([x[0] for x in loopback_resp]) == addrs + assert sorted([x[0] for x in sent_echo]) == addrs + assert len(r) == 200 + + # take sub 20ms + et = (time.monotonic() - st) * 1000.0 + assert et < 20 + +@flaky(max_runs=6, min_passes=1) +def test_throughput(p): + # enable output mode + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + # enable CAN loopback mode + p.set_can_loopback(True) + + for speed in [10, 20, 50, 100, 125, 250, 500, 1000]: + # set bus 0 speed to speed + p.set_can_speed_kbps(0, speed) + time.sleep(0.05) + + comp_kbps = time_many_sends(p, 0) + + # bit count from https://en.wikipedia.org/wiki/CAN_bus + saturation_pct = (comp_kbps / speed) * 100.0 + assert saturation_pct > 80 + assert saturation_pct < 100 + + print("loopback 100 messages at speed %d, comp speed is %.2f, percent %.2f" % (speed, comp_kbps, saturation_pct)) + +# this will fail if you have hardware serial connected +def test_serial_debug(p): + _ = p.serial_read(Panda.SERIAL_DEBUG) # junk + p.call_control_api(0x01) + assert p.serial_read(Panda.SERIAL_DEBUG).startswith(b"NO HANDLER") diff --git a/panda_tici/tests/hitl/3_usb_to_can.py b/panda_tici/tests/hitl/3_usb_to_can.py new file mode 100644 index 0000000..46856a2 --- /dev/null +++ b/panda_tici/tests/hitl/3_usb_to_can.py @@ -0,0 +1,87 @@ +import time +from flaky import flaky + +from opendbc.car.structs import CarParams +from panda_tici import Panda +from panda_tici.tests.hitl.helpers import time_many_sends + +def test_can_loopback(p): + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_can_loopback(True) + + for bus in (0, 1, 2): + # set bus 0 speed to 5000 + p.set_can_speed_kbps(bus, 500) + + # send a message on bus 0 + p.can_send(0x1aa, b"message", bus) + + # confirm receive both on loopback and send receipt + time.sleep(0.05) + r = p.can_recv() + sr = [x for x in r if x[2] == 0x80 | bus] + lb = [x for x in r if x[2] == bus] + assert len(sr) == 1 + assert len(lb) == 1 + + # confirm data is correct + assert 0x1aa == sr[0][0] == lb[0][0] + assert b"message" == sr[0][1] == lb[0][1] + +def test_reliability(p): + MSG_COUNT = 100 + + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_can_loopback(True) + p.set_can_speed_kbps(0, 1000) + + addrs = list(range(100, 100 + MSG_COUNT)) + ts = [(j, b"\xaa" * 8, 0) for j in addrs] + + for _ in range(100): + st = time.monotonic() + + p.can_send_many(ts) + + r = [] + while len(r) < 200 and (time.monotonic() - st) < 0.5: + r.extend(p.can_recv()) + + sent_echo = [x for x in r if x[2] == 0x80] + loopback_resp = [x for x in r if x[2] == 0] + + assert sorted([x[0] for x in loopback_resp]) == addrs + assert sorted([x[0] for x in sent_echo]) == addrs + assert len(r) == 200 + + # take sub 20ms + et = (time.monotonic() - st) * 1000.0 + assert et < 20 + +@flaky(max_runs=6, min_passes=1) +def test_throughput(p): + # enable output mode + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + # enable CAN loopback mode + p.set_can_loopback(True) + + for speed in [10, 20, 50, 100, 125, 250, 500, 1000]: + # set bus 0 speed to speed + p.set_can_speed_kbps(0, speed) + time.sleep(0.05) + + comp_kbps = time_many_sends(p, 0) + + # bit count from https://en.wikipedia.org/wiki/CAN_bus + saturation_pct = (comp_kbps / speed) * 100.0 + assert saturation_pct > 80 + assert saturation_pct < 100 + + print("loopback 100 messages at speed %d, comp speed is %.2f, percent %.2f" % (speed, comp_kbps, saturation_pct)) + +# this will fail if you have hardware serial connected +def test_serial_debug(p): + _ = p.serial_read(Panda.SERIAL_DEBUG) # junk + p.call_control_api(0x01) + assert p.serial_read(Panda.SERIAL_DEBUG).startswith(b"NO HANDLER") diff --git a/panda_tici/tests/hitl/4_can_loopback.py b/panda_tici/tests/hitl/4_can_loopback.py new file mode 100644 index 0000000..ac8f135 --- /dev/null +++ b/panda_tici/tests/hitl/4_can_loopback.py @@ -0,0 +1,202 @@ +import os +import time +import pytest +import random +import threading +from flaky import flaky +from collections import defaultdict + +from opendbc.car.structs import CarParams +from panda_tici.tests.hitl.conftest import PandaGroup +from panda_tici.tests.hitl.helpers import time_many_sends, get_random_can_messages, clear_can_buffers + +@flaky(max_runs=3, min_passes=1) +@pytest.mark.timeout(35) +def test_send_recv(p, panda_jungle): + def test(p_send, p_recv): + for bus in (0, 1, 2): + for speed in (10, 20, 50, 100, 125, 250, 500, 1000): + clear_can_buffers(p_send, speed) + clear_can_buffers(p_recv, speed) + + comp_kbps = time_many_sends(p_send, bus, p_recv, two_pandas=True) + + saturation_pct = (comp_kbps / speed) * 100.0 + assert 80 < saturation_pct < 100 + + print(f"two pandas bus {bus}, 100 messages at speed {speed:4d}, comp speed is {comp_kbps:7.2f}, {saturation_pct:6.2f}%") + + # Run tests in both directions + p.set_safety_mode(CarParams.SafetyModel.allOutput) + test(p, panda_jungle) + test(panda_jungle, p) + + +@flaky(max_runs=6, min_passes=1) +@pytest.mark.timeout(30) +def test_latency(p, panda_jungle): + def test(p_send, p_recv): + for bus in (0, 1, 2): + for speed in (10, 20, 50, 100, 125, 250, 500, 1000): + clear_can_buffers(p_send, speed) + clear_can_buffers(p_recv, speed) + + latencies = [] + comp_kbps_list = [] + saturation_pcts = [] + + num_messages = 100 + + for _ in range(num_messages): + st = time.monotonic() + p_send.can_send(0x1ab, b"message", bus) + r = [] + while len(r) < 1 and (time.monotonic() - st) < 5: + r = p_recv.can_recv() + et = time.monotonic() + r_echo = [] + while len(r_echo) < 1 and (time.monotonic() - st) < 10: + r_echo = p_send.can_recv() + + if len(r) == 0 or len(r_echo) == 0: + print(f"r: {r}, r_echo: {r_echo}") + + assert len(r) == 1 + assert len(r_echo) == 1 + + et = (et - st) * 1000.0 + comp_kbps = (1 + 11 + 1 + 1 + 1 + 4 + 8 * 8 + 15 + 1 + 1 + 1 + 7) / et + latency = et - ((1 + 11 + 1 + 1 + 1 + 4 + 8 * 8 + 15 + 1 + 1 + 1 + 7) / speed) + + assert latency < 5.0 + + saturation_pct = (comp_kbps / speed) * 100.0 + latencies.append(latency) + comp_kbps_list.append(comp_kbps) + saturation_pcts.append(saturation_pct) + + average_latency = sum(latencies) / num_messages + assert average_latency < 1.0 + average_comp_kbps = sum(comp_kbps_list) / num_messages + average_saturation_pct = sum(saturation_pcts) / num_messages + + print("two pandas bus {}, {} message average at speed {:4d}, latency is {:5.3f}ms, comp speed is {:7.2f}, percent {:6.2f}" + .format(bus, num_messages, speed, average_latency, average_comp_kbps, average_saturation_pct)) + + # Run tests in both directions + p.set_safety_mode(CarParams.SafetyModel.allOutput) + test(p, panda_jungle) + test(panda_jungle, p) + + +@pytest.mark.panda_expect_can_error +@pytest.mark.test_panda_types(PandaGroup.GEN2) +def test_gen2_loopback(p, panda_jungle): + def test(p_send, p_recv, address=None): + for bus in range(4): + obd = False + if bus == 3: + obd = True + bus = 1 + + # Clear buses + clear_can_buffers(p_send) + clear_can_buffers(p_recv) + + # Send a random string + addr = address if address else random.randint(1, 2000) + string = b"test" + os.urandom(4) + p_send.set_obd(obd) + p_recv.set_obd(obd) + time.sleep(0.2) + p_send.can_send(addr, string, bus) + time.sleep(0.2) + + content = p_recv.can_recv() + + # Check amount of messages + assert len(content) == 1 + + # Check content + assert content[0][0] == addr and content[0][1] == string + + # Check bus + assert content[0][2] == bus + + print("Bus:", bus, "address:", addr, "OBD:", obd, "OK") + + # Run tests in both directions + p.set_safety_mode(CarParams.SafetyModel.allOutput) + test(p, panda_jungle) + test(panda_jungle, p) + + # Test extended frame address with ELM327 mode + p.set_safety_mode(CarParams.SafetyModel.elm327) + test(p, panda_jungle, 0x18DB33F1) + test(panda_jungle, p, 0x18DB33F1) + + # TODO: why it's not being reset by fixtures reinit? + p.set_obd(False) + panda_jungle.set_obd(False) + +def test_bulk_write(p, panda_jungle): + # The TX buffers on pandas is 0x100 in length. + NUM_MESSAGES_PER_BUS = 10000 + + def flood_tx(panda): + print('Sending!') + msg = b"\xaa" * 8 + packet = [] + # start with many messages on a single bus (higher contention for single TX ring buffer) + packet += [[0xaa, msg, 0]] * NUM_MESSAGES_PER_BUS + # end with many messages on multiple buses + packet += [[0xaa, msg, 0], [0xaa, msg, 1], [0xaa, msg, 2]] * NUM_MESSAGES_PER_BUS + + # Disable timeout + panda.set_safety_mode(CarParams.SafetyModel.allOutput) + panda.can_send_many(packet, timeout=0) + print(f"Done sending {4 * NUM_MESSAGES_PER_BUS} messages!", time.monotonic()) + print(panda.health()) + + # Start transmisson + threading.Thread(target=flood_tx, args=(p,)).start() + + # Receive as much as we can in a few second time period + rx = [] + old_len = 0 + start_time = time.monotonic() + while time.monotonic() - start_time < 5 or len(rx) > old_len: + old_len = len(rx) + rx.extend(panda_jungle.can_recv()) + print(f"Received {len(rx)} messages", time.monotonic()) + + # All messages should have been received + if len(rx) != 4 * NUM_MESSAGES_PER_BUS: + raise Exception("Did not receive all messages!") + +def test_message_integrity(p): + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_can_loopback(True) + for i in range(250): + sent_msgs = defaultdict(set) + for _ in range(random.randrange(10)): + to_send = get_random_can_messages(random.randrange(100)) + for m in to_send: + sent_msgs[m[2]].add((m[0], m[1])) + p.can_send_many(to_send, timeout=0) + + start_time = time.monotonic() + while time.monotonic() - start_time < 2 and any(len(sent_msgs[bus]) for bus in range(3)): + recvd = p.can_recv() + for msg in recvd: + if msg[2] >= 128: + k = (msg[0], bytes(msg[1])) + bus = msg[2]-128 + assert k in sent_msgs[bus], f"message {k} was never sent on bus {bus}" + sent_msgs[msg[2]-128].discard(k) + + # if a set isn't empty, messages got dropped + for bus in range(3): + assert not len(sent_msgs[bus]), f"loop {i}: bus {bus} missing {len(sent_msgs[bus])} messages" + + print("Got all messages intact") diff --git a/panda_tici/tests/hitl/5_spi.py b/panda_tici/tests/hitl/5_spi.py new file mode 100644 index 0000000..f9826af --- /dev/null +++ b/panda_tici/tests/hitl/5_spi.py @@ -0,0 +1,103 @@ +import binascii +import pytest +import random +from unittest.mock import patch + +from panda_tici import Panda, PandaDFU +from panda_tici.python.spi import SpiDevice, PandaProtocolMismatch, PandaSpiNackResponse + +pytestmark = [ + pytest.mark.test_panda_types((Panda.HW_TYPE_TRES, )) +] + +@pytest.mark.skip("doesn't work, bootloader seems to ignore commands once it sees junk") +def test_dfu_with_spam(p): + dfu_serial = p.get_dfu_serial() + + # enter DFU + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + assert Panda.wait_for_dfu(dfu_serial, timeout=19), "failed to enter DFU" + + # send junk + d = SpiDevice() + for _ in range(9): + with d.acquire() as spi: + dat = [random.randint(-1, 255) for _ in range(random.randint(1, 100))] + spi.xfer(dat) + + # should still show up + assert dfu_serial in PandaDFU.list() + +class TestSpi: + def _ping(self, mocker, panda): + # should work with no retries + spy = mocker.spy(panda._handle, '_wait_for_ack') + panda.health() + assert spy.call_count == 2 + mocker.stop(spy) + + def test_protocol_version_check(self, p): + for bootstub in (False, True): + p.reset(enter_bootstub=bootstub) + with patch('panda.python.spi.PandaSpiHandle.PROTOCOL_VERSION', return_value="abc"): + # list should still work with wrong version + assert p._serial in Panda.list() + + # connect but raise protocol error + with pytest.raises(PandaProtocolMismatch): + Panda(p._serial) + + def test_protocol_version_data(self, p): + for bootstub in (False, True): + p.reset(enter_bootstub=bootstub) + v = p._handle.get_protocol_version() + + uid = binascii.hexlify(v[:12]).decode() + assert uid == p.get_uid() + + hwtype = v[12] + assert hwtype == ord(p.get_type()) + + bstub = v[13] + assert bstub == (0xEE if bootstub else 0xCC) + + def test_all_comm_types(self, mocker, p): + spy = mocker.spy(p._handle, '_wait_for_ack') + + # controlRead + controlWrite + p.health() + p.can_clear(0) + assert spy.call_count == 2*2 + + # bulkRead + bulkWrite + p.can_recv() + p.can_send(0x123, b"somedata", 0) + assert spy.call_count == 2*4 + + def test_bad_header(self, mocker, p): + with patch('panda.python.spi.SYNC', return_value=0): + with pytest.raises(PandaSpiNackResponse): + p._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, p.HEALTH_STRUCT.size, timeout=50) + self._ping(mocker, p) + + def test_bad_checksum(self, mocker, p): + cnt = p.health()['spi_checksum_error_count'] + with patch('panda.python.spi.PandaSpiHandle._calc_checksum', return_value=0): + with pytest.raises(PandaSpiNackResponse): + p._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, p.HEALTH_STRUCT.size, timeout=50) + self._ping(mocker, p) + assert (p.health()['spi_checksum_error_count'] - cnt) > 0 + + def test_non_existent_endpoint(self, mocker, p): + for _ in range(10): + ep = random.randint(4, 20) + with pytest.raises(PandaSpiNackResponse): + p._handle.bulkRead(ep, random.randint(1, 1000), timeout=50) + + self._ping(mocker, p) + + with pytest.raises(PandaSpiNackResponse): + p._handle.bulkWrite(ep, b"abc", timeout=50) + + self._ping(mocker, p) diff --git a/panda_tici/tests/hitl/6_safety.py b/panda_tici/tests/hitl/6_safety.py new file mode 100644 index 0000000..ed0988e --- /dev/null +++ b/panda_tici/tests/hitl/6_safety.py @@ -0,0 +1,30 @@ +import time + +from opendbc.car.structs import CarParams +from panda_tici import Panda + + +def test_safety_nooutput(p): + p.set_safety_mode(CarParams.SafetyModel.silent) + p.set_can_loopback(True) + + # send a message on bus 0 + p.can_send(0x1aa, b"message", 0) + + # confirm receive nothing + time.sleep(0.05) + r = p.can_recv() + # bus 192 is messages blocked by TX safety hook on bus 0 + assert len([x for x in r if x[2] != 192]) == 0 + assert len([x for x in r if x[2] == 192]) == 1 + + +def test_canfd_safety_modes(p): + # works on all pandas + p.set_safety_mode(CarParams.SafetyModel.toyota) + assert p.health()['safety_mode'] == CarParams.SafetyModel.toyota + + # shouldn't be able to set a CAN-FD safety mode on non CAN-FD panda + p.set_safety_mode(CarParams.SafetyModel.hyundaiCanfd) + expected_mode = CarParams.SafetyModel.hyundaiCanfd if p.get_type() in Panda.H7_DEVICES else CarParams.SafetyModel.silent + assert p.health()['safety_mode'] == expected_mode diff --git a/panda_tici/tests/hitl/7_internal.py b/panda_tici/tests/hitl/7_internal.py new file mode 100644 index 0000000..fa0bb9a --- /dev/null +++ b/panda_tici/tests/hitl/7_internal.py @@ -0,0 +1,67 @@ +import time +import pytest + +from panda_tici import Panda + +pytestmark = [ + pytest.mark.test_panda_types(Panda.INTERNAL_DEVICES) +] + +@pytest.mark.timeout(2*60) +def test_fan_controller(p): + start_health = p.health() + + for power in (30, 50, 80, 100): + p.set_fan_power(0) + while p.get_fan_rpm() > 0: + time.sleep(0.1) + + # wait until fan spins up (and recovers if needed), + # then wait a bit more for the RPM to converge + p.set_fan_power(power) + for _ in range(20): + time.sleep(1) + if p.get_fan_rpm() > 1000: + break + time.sleep(5) + + expected_rpm = Panda.MAX_FAN_RPMs[bytes(p.get_type())] * power / 100 + assert 0.9 * expected_rpm <= p.get_fan_rpm() <= 1.1 * expected_rpm + + # Ensure the stall detection is tested on dos + if p.get_type() == Panda.HW_TYPE_DOS: + stalls = p.health()['fan_stall_count'] - start_health['fan_stall_count'] + assert stalls >= 2 + print("stall count", stalls) + else: + assert p.health()['fan_stall_count'] == 0 + +def test_fan_cooldown(p): + # if the fan cooldown doesn't work, we get high frequency noise on the tach line + # while the rotor spins down. this makes sure it never goes beyond the expected max RPM + p.set_fan_power(100) + time.sleep(3) + p.set_fan_power(0) + for _ in range(5): + assert p.get_fan_rpm() <= Panda.MAX_FAN_RPMs[bytes(p.get_type())] + time.sleep(0.5) + +def test_fan_overshoot(p): + if p.get_type() == Panda.HW_TYPE_DOS: + pytest.skip("panda's fan controller overshoots on the comma three fans that need stall recovery") + + # make sure it's stopped completely + p.set_fan_power(0) + while p.get_fan_rpm() > 0: + time.sleep(0.1) + + # set it to 30% power to mimic going onroad + p.set_fan_power(30) + max_rpm = 0 + for _ in range(50): + max_rpm = max(max_rpm, p.get_fan_rpm()) + time.sleep(0.1) + + # tolerate 10% overshoot + expected_rpm = Panda.MAX_FAN_RPMs[bytes(p.get_type())] * 30 / 100 + assert max_rpm <= 1.1 * expected_rpm, f"Fan overshoot: {(max_rpm / expected_rpm * 100) - 100:.1f}%" diff --git a/panda_tici/tests/hitl/8_misc.py b/panda_tici/tests/hitl/8_misc.py new file mode 100644 index 0000000..1fa7627 --- /dev/null +++ b/panda_tici/tests/hitl/8_misc.py @@ -0,0 +1,13 @@ +import time + +from panda_tici import Panda + +def test_boot_time(p): + # boot time should be instant + st = time.monotonic() + p.reset(reconnect=False) + assert Panda.wait_for_panda(p.get_usb_serial(), timeout=3.0) + + # USB enumeration is slow, so SPI is faster + assert time.monotonic() - st < (1.0 if p.spi else 5.0) + diff --git a/panda_tici/tests/hitl/9_harness.py b/panda_tici/tests/hitl/9_harness.py new file mode 100644 index 0000000..542aba8 --- /dev/null +++ b/panda_tici/tests/hitl/9_harness.py @@ -0,0 +1,78 @@ +import time +import pytest +import itertools + +from opendbc.car.structs import CarParams +from panda_tici import Panda +from panda_tici.tests.hitl.conftest import PandaGroup + +# TODO: test relay + +@pytest.mark.panda_expect_can_error +@pytest.mark.test_panda_types(PandaGroup.GEN2) +def test_harness_status(p, panda_jungle): + # map from jungle orientations to panda orientations + orientation_map = { + Panda.HARNESS_STATUS_NC: Panda.HARNESS_STATUS_NC, + } + + # this shouldn't be parameterized since we don't want the panda to be reset + # between the tests. + for ignition, orientation in itertools.product([True, False], [Panda.HARNESS_STATUS_NC, Panda.HARNESS_STATUS_NORMAL, Panda.HARNESS_STATUS_FLIPPED]): + print() + p.set_safety_mode(CarParams.SafetyModel.elm327) + panda_jungle.set_harness_orientation(orientation) + panda_jungle.set_ignition(ignition) + + # wait for orientation detection + time.sleep(0.25) + + health = p.health() + detected_orientation = health['car_harness_status'] + print(f"orientation set: {orientation} detected: {detected_orientation}") + + if detected_orientation not in orientation_map: + assert detected_orientation != Panda.HARNESS_STATUS_NC + other = {Panda.HARNESS_STATUS_NORMAL: Panda.HARNESS_STATUS_FLIPPED, Panda.HARNESS_STATUS_FLIPPED: Panda.HARNESS_STATUS_NORMAL} + orientation_map.update({ + orientation: detected_orientation, + other[orientation]: other[detected_orientation], + }) + + # Orientation + assert orientation_map[detected_orientation] == orientation + + # Line ignition + assert health['ignition_line'] == (False if orientation == Panda.HARNESS_STATUS_NC else ignition) + + # CAN traffic + if orientation != Panda.HARNESS_STATUS_NC: + for bus in range(3): + panda_jungle.can_send(0x123, f"{bus}".encode(), bus) + time.sleep(0.5) + + msgs = p.can_recv() + buses = {int(dat): bus for _, dat, bus in msgs if bus <= 3} + print(msgs) + + # jungle doesn't actually switch buses when switching orientation + flipped = orientation == Panda.HARNESS_STATUS_FLIPPED + assert buses[0] == (2 if flipped else 0) + assert buses[2] == (0 if flipped else 2) + + # SBU voltages + supply_voltage_mV = 1800 if p.get_type() in [Panda.HW_TYPE_TRES, ] else 3300 + + if orientation == Panda.HARNESS_STATUS_NC: + assert health['sbu1_voltage_mV'] > 0.9 * supply_voltage_mV + assert health['sbu2_voltage_mV'] > 0.9 * supply_voltage_mV + else: + relay_line = 'sbu1_voltage_mV' if (detected_orientation == Panda.HARNESS_STATUS_FLIPPED) else 'sbu2_voltage_mV' + ignition_line = 'sbu2_voltage_mV' if (detected_orientation == Panda.HARNESS_STATUS_FLIPPED) else 'sbu1_voltage_mV' + + assert health[relay_line] < 0.1 * supply_voltage_mV + assert health[ignition_line] > health[relay_line] + if ignition: + assert health[ignition_line] < 0.3 * supply_voltage_mV + else: + assert health[ignition_line] > 0.9 * supply_voltage_mV diff --git a/panda_tici/tests/hitl/__init__.py b/panda_tici/tests/hitl/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panda_tici/tests/hitl/conftest.py b/panda_tici/tests/hitl/conftest.py new file mode 100644 index 0000000..debd796 --- /dev/null +++ b/panda_tici/tests/hitl/conftest.py @@ -0,0 +1,222 @@ +import os +import pytest +import concurrent.futures + +from panda_tici import Panda, PandaDFU, PandaJungle +from panda_tici.tests.hitl.helpers import clear_can_buffers + +# needed to get output when using xdist +if "DEBUG" in os.environ: + import sys + sys.stdout = sys.stderr + +SPEED_NORMAL = 500 +BUS_SPEEDS = [(0, SPEED_NORMAL), (1, SPEED_NORMAL), (2, SPEED_NORMAL)] + + +JUNGLE_SERIAL = os.getenv("PANDAS_JUNGLE") +NO_JUNGLE = os.environ.get("NO_JUNGLE", "0") == "1" +PANDAS_EXCLUDE = os.getenv("PANDAS_EXCLUDE", "").strip().split(" ") +HW_TYPES = os.environ.get("HW_TYPES", None) + +PARALLEL = "PARALLEL" in os.environ +NON_PARALLEL = "NON_PARALLEL" in os.environ +if PARALLEL: + NO_JUNGLE = True + +class PandaGroup: + H7 = (Panda.HW_TYPE_RED_PANDA, Panda.HW_TYPE_RED_PANDA_V2, Panda.HW_TYPE_TRES) + GEN2 = (Panda.HW_TYPE_UNO, Panda.HW_TYPE_DOS) + H7 + TESTED = (Panda.HW_TYPE_RED_PANDA, Panda.HW_TYPE_RED_PANDA_V2, Panda.HW_TYPE_UNO) + +if HW_TYPES is not None: + PandaGroup.TESTED = [bytes([int(x), ]) for x in HW_TYPES.strip().split(",")] # type: ignore + + +# Find all pandas connected +_all_pandas = {} +_panda_jungle = None +def init_all_pandas(): + if not NO_JUNGLE: + global _panda_jungle + _panda_jungle = PandaJungle(JUNGLE_SERIAL) + _panda_jungle.set_panda_power(True) + + for serial in Panda.list(): + if serial not in PANDAS_EXCLUDE: + with Panda(serial=serial, claim=False) as p: + ptype = bytes(p.get_type()) + if ptype in PandaGroup.TESTED: + _all_pandas[serial] = ptype + + # ensure we have all tested panda types + missing_types = set(PandaGroup.TESTED) - set(_all_pandas.values()) + assert len(missing_types) == 0, f"Missing panda types: {missing_types}" + + print(f"{len(_all_pandas)} total pandas") +init_all_pandas() +_all_panda_serials = sorted(_all_pandas.keys()) + + +def init_jungle(): + if _panda_jungle is None: + return + clear_can_buffers(_panda_jungle) + _panda_jungle.set_panda_power(True) + _panda_jungle.set_can_loopback(False) + _panda_jungle.set_obd(False) + _panda_jungle.set_harness_orientation(PandaJungle.HARNESS_ORIENTATION_1) + for bus, speed in BUS_SPEEDS: + _panda_jungle.set_can_speed_kbps(bus, speed) + + # ensure FW hasn't changed + assert _panda_jungle.up_to_date() + + +def pytest_configure(config): + config.addinivalue_line( + "markers", "test_panda_types(name): whitelist a test for specific panda types" + ) + config.addinivalue_line( + "markers", "skip_panda_types(name): blacklist panda types from a test" + ) + config.addinivalue_line( + "markers", "panda_expect_can_error: mark test to ignore CAN health errors" + ) + +@pytest.hookimpl(tryfirst=True) +def pytest_collection_modifyitems(items): + for item in items: + if item.get_closest_marker('timeout') is None: + item.add_marker(pytest.mark.timeout(60)) + + # xdist grouping by panda + serial = item.name.split("serial=")[1].split(",")[0] + assert len(serial) == 24 + item.add_marker(pytest.mark.xdist_group(serial)) + + needs_jungle = "panda_jungle" in item.fixturenames + if PARALLEL and needs_jungle: + item.add_marker(pytest.mark.skip(reason="no jungle tests in PARALLEL mode")) + elif NON_PARALLEL and not needs_jungle: + item.add_marker(pytest.mark.skip(reason="only running jungle tests")) + +def pytest_make_parametrize_id(config, val, argname): + if val in _all_pandas: + # TODO: get nice string instead of int + hw_type = _all_pandas[val][0] + return f"serial={val}, hw_type={hw_type}" + return None + + +@pytest.fixture(name='panda_jungle', scope='function') +def fixture_panda_jungle(request): + init_jungle() + return _panda_jungle + +@pytest.fixture(name='p', scope='function') +def func_fixture_panda(request, module_panda): + p = module_panda + + # Check if test is applicable to this panda + mark = request.node.get_closest_marker('test_panda_types') + if mark: + assert len(mark.args) > 0, "Missing panda types argument in mark" + test_types = mark.args[0] + if _all_pandas[p.get_usb_serial()] not in test_types: + pytest.skip(f"Not applicable, {test_types} pandas only") + + mark = request.node.get_closest_marker('skip_panda_types') + if mark: + assert len(mark.args) > 0, "Missing panda types argument in mark" + skip_types = mark.args[0] + if _all_pandas[p.get_usb_serial()] in skip_types: + pytest.skip(f"Not applicable to {skip_types}") + + # this is 2+ seconds on USB pandas due to slow + # enumeration on the host side + p.reset() + + # ensure FW hasn't changed + assert p.up_to_date() + + # Run test + yield p + + # Teardown + + # reconnect + if p.get_dfu_serial() in PandaDFU.list(): + PandaDFU(p.get_dfu_serial()).reset() + p.reconnect() + if not p.connected: + p.reconnect() + if p.bootstub: + p.reset() + + assert not p.bootstub + + # TODO: would be nice to make these common checks in the teardown + # show up as failed tests instead of "errors" + + # Check for faults + assert p.health()['faults'] == 0 + assert p.health()['fault_status'] == 0 + + # Check for SPI errors + #assert p.health()['spi_checksum_error_count'] == 0 + + # Check health of each CAN core after test, normal to fail for test_gen2_loopback on OBD bus, so skipping + mark = request.node.get_closest_marker('panda_expect_can_error') + expect_can_error = mark is not None + if not expect_can_error: + for i in range(3): + can_health = p.can_health(i) + assert can_health['bus_off_cnt'] == 0 + assert can_health['receive_error_cnt'] < 127 + assert can_health['transmit_error_cnt'] < 255 + assert can_health['error_passive'] == 0 + assert can_health['error_warning'] == 0 + assert can_health['total_rx_lost_cnt'] == 0 + assert can_health['total_tx_lost_cnt'] == 0 + assert can_health['total_error_cnt'] == 0 + assert can_health['total_tx_checksum_error_cnt'] == 0 + +@pytest.fixture(name='module_panda', params=_all_panda_serials, scope='module') +def fixture_panda_setup(request): + """ + Clean up all pandas + jungle and return the panda under test. + """ + panda_serial = request.param + + # Initialize jungle + init_jungle() + + # Connect to pandas + def cnnct(s): + if s == panda_serial: + p = Panda(serial=s) + p.reset(reconnect=True) + + p.set_can_loopback(False) + p.set_power_save(False) + for bus, speed in BUS_SPEEDS: + p.set_can_speed_kbps(bus, speed) + clear_can_buffers(p) + p.set_power_save(False) + return p + elif not PARALLEL: + with Panda(serial=s) as p: + p.reset(reconnect=False) + return None + + with concurrent.futures.ThreadPoolExecutor() as exc: + ps = list(exc.map(cnnct, _all_panda_serials, timeout=20)) + pandas = [p for p in ps if p is not None] + + # run test + yield pandas[0] + + # Teardown + for p in pandas: + p.close() diff --git a/panda_tici/tests/hitl/helpers.py b/panda_tici/tests/hitl/helpers.py new file mode 100644 index 0000000..d465671 --- /dev/null +++ b/panda_tici/tests/hitl/helpers.py @@ -0,0 +1,71 @@ +import time +import random + + +def get_random_can_messages(n): + m = [] + for _ in range(n): + bus = random.randrange(3) + addr = random.randrange(1 << 29) + dat = bytes([random.getrandbits(8) for _ in range(random.randrange(1, 9))]) + m.append([addr, dat, bus]) + return m + + +def time_many_sends(p, bus, p_recv=None, msg_count=100, two_pandas=False, msg_len=8): + if p_recv is None: + p_recv = p + if p == p_recv and two_pandas: + raise ValueError("Cannot have two pandas that are the same panda") + + msg_id = random.randint(0x100, 0x200) + to_send = [(msg_id, b"\xaa" * msg_len, bus)] * msg_count + + start_time = time.monotonic() + p.can_send_many(to_send) + r = [] + r_echo = [] + r_len_expected = msg_count if two_pandas else msg_count * 2 + r_echo_len_exected = msg_count if two_pandas else 0 + + while len(r) < r_len_expected and (time.monotonic() - start_time) < 5: + r.extend(p_recv.can_recv()) + end_time = time.monotonic() + if two_pandas: + while len(r_echo) < r_echo_len_exected and (time.monotonic() - start_time) < 10: + r_echo.extend(p.can_recv()) + + sent_echo = [x for x in r if x[2] == 0x80 | bus and x[0] == msg_id] + sent_echo.extend([x for x in r_echo if x[2] == 0x80 | bus and x[0] == msg_id]) + resp = [x for x in r if x[2] == bus and x[0] == msg_id] + + leftovers = [x for x in r if (x[2] != 0x80 | bus and x[2] != bus) or x[0] != msg_id] + assert len(leftovers) == 0 + + assert len(resp) == msg_count + assert len(sent_echo) == msg_count + + end_time = (end_time - start_time) * 1000.0 + comp_kbps = (1 + 11 + 1 + 1 + 1 + 4 + (msg_len * 8) + 15 + 1 + 1 + 1 + 7) * msg_count / end_time + + return comp_kbps + + +def clear_can_buffers(panda, speed: int | None = None): + if speed is not None: + for bus in range(3): + panda.set_can_speed_kbps(bus, speed) + + # clear tx buffers + for i in range(4): + panda.can_clear(i) + + # clear rx buffers + panda.can_clear(0xFFFF) + r = [1] + st = time.monotonic() + while len(r) > 0: + r = panda.can_recv() + time.sleep(0.05) + if (time.monotonic() - st) > 10: + raise Exception("Unable to clear can buffers for panda ", panda.get_serial()) diff --git a/panda_tici/tests/hitl/known_bootstub/bootstub.panda_h7.bin b/panda_tici/tests/hitl/known_bootstub/bootstub.panda_h7.bin new file mode 100755 index 0000000..a6d856b Binary files /dev/null and b/panda_tici/tests/hitl/known_bootstub/bootstub.panda_h7.bin differ diff --git a/panda_tici/tests/hitl/known_bootstub/bootstub_f4_first_dos_production.panda.bin b/panda_tici/tests/hitl/known_bootstub/bootstub_f4_first_dos_production.panda.bin new file mode 100644 index 0000000..786acf6 Binary files /dev/null and b/panda_tici/tests/hitl/known_bootstub/bootstub_f4_first_dos_production.panda.bin differ diff --git a/panda_tici/tests/hitl/known_bootstub/bootstub_f4_only_bcd.panda.bin b/panda_tici/tests/hitl/known_bootstub/bootstub_f4_only_bcd.panda.bin new file mode 100755 index 0000000..000fd26 Binary files /dev/null and b/panda_tici/tests/hitl/known_bootstub/bootstub_f4_only_bcd.panda.bin differ diff --git a/panda_tici/tests/hitl/reset_jungles.py b/panda_tici/tests/hitl/reset_jungles.py new file mode 100755 index 0000000..9c482da --- /dev/null +++ b/panda_tici/tests/hitl/reset_jungles.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +import concurrent.futures + +from panda_tici import PandaJungle, PandaJungleDFU, McuType +from panda_tici.tests.libs.resetter import Resetter + +SERIALS = {'180019001451313236343430', '1d0017000c50435635333720'} + +def recover(s): + with PandaJungleDFU(s) as pd: + pd.recover() + +def flash(s): + with PandaJungle(s) as p: + p.flash() + return p.get_mcu_type() + +# Reset + flash all CI hardware to get it into a consistent state +# * port 1: jungles-under-test +# * port 2: USB hubs +# * port 3: HITL pandas and their jungles +if __name__ == "__main__": + with Resetter() as r: + # everything off + for i in range(1, 4): + r.enable_power(i, 0) + r.cycle_power(ports=[1, 2], dfu=True) + + dfu_serials = PandaJungleDFU.list() + print(len(dfu_serials), len(SERIALS)) + assert len(dfu_serials) == len(SERIALS) + + with concurrent.futures.ProcessPoolExecutor(max_workers=len(dfu_serials)) as exc: + list(exc.map(recover, dfu_serials, timeout=30)) + + # power cycle for H7 bootloader bug + r.cycle_power(ports=[1, 2]) + + serials = PandaJungle.list() + assert set(PandaJungle.list()) >= SERIALS + mcu_types = list(exc.map(flash, SERIALS, timeout=20)) + assert set(mcu_types) == {McuType.F4, McuType.H7} diff --git a/panda_tici/tests/hitl/run_parallel_tests.sh b/panda_tici/tests/hitl/run_parallel_tests.sh new file mode 100755 index 0000000..f60d838 --- /dev/null +++ b/panda_tici/tests/hitl/run_parallel_tests.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +# n = number of pandas tested +PARALLEL=1 pytest --durations=0 *.py -n 5 --dist loadgroup -x diff --git a/panda_tici/tests/hitl/run_serial_tests.sh b/panda_tici/tests/hitl/run_serial_tests.sh new file mode 100755 index 0000000..4feae5e --- /dev/null +++ b/panda_tici/tests/hitl/run_serial_tests.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +NON_PARALLEL=1 pytest --durations=0 *.py -x diff --git a/panda_tici/tests/libpanda/SConscript b/panda_tici/tests/libpanda/SConscript new file mode 100644 index 0000000..fc68072 --- /dev/null +++ b/panda_tici/tests/libpanda/SConscript @@ -0,0 +1,38 @@ +import opendbc +import platform + +CC = 'gcc' +system = platform.system() +mac_ver = platform.mac_ver() + +# gcc installed by homebrew has version suffix (e.g. gcc-12) in order to be +# distinguishable from system one - which acts as a symlink to clang +# clang works on macOS 15 and greater but has issues on earlier macOS versions. +# see: https://github.com/commaai/openpilot/issues/35093 +if system == 'Darwin' and mac_ver[0] and mac_ver[0] < '15': + CC += '-13' + +env = Environment( + CC=CC, + CFLAGS=[ + '-nostdlib', + '-fno-builtin', + '-std=gnu11', + '-Wfatal-errors', + '-Wno-pointer-to-int-cast', + ], + CPPPATH=[".", "../../board/", opendbc.INCLUDE_PATH], +) +if system == "Darwin": + env.PrependENVPath('PATH', '/opt/homebrew/bin') + +if GetOption('ubsan'): + flags = [ + "-fsanitize=undefined", + "-fno-sanitize-recover=undefined", + ] + env['CFLAGS'] += flags + env['LINKFLAGS'] += flags + +panda = env.SharedObject("panda.os", "panda.c") +libpanda = env.SharedLibrary("libpanda.so", [panda]) diff --git a/panda_tici/tests/libpanda/libpanda_py.py b/panda_tici/tests/libpanda/libpanda_py.py new file mode 100644 index 0000000..de53ae9 --- /dev/null +++ b/panda_tici/tests/libpanda/libpanda_py.py @@ -0,0 +1,87 @@ +import os +from cffi import FFI +from typing import Any, Protocol + +from panda_tici import LEN_TO_DLC + +libpanda_dir = os.path.dirname(os.path.abspath(__file__)) +libpanda_fn = os.path.join(libpanda_dir, "libpanda.so") + +ffi = FFI() + +ffi.cdef(""" +typedef struct { + unsigned char fd : 1; + unsigned char bus : 3; + unsigned char data_len_code : 4; + unsigned char rejected : 1; + unsigned char returned : 1; + unsigned char extended : 1; + unsigned int addr : 29; + unsigned char checksum; + unsigned char data[64]; +} CANPacket_t; +""", packed=True) + +ffi.cdef(""" +int set_safety_hooks(uint16_t mode, uint16_t param); +""") + +ffi.cdef(""" +typedef struct { + volatile uint32_t w_ptr; + volatile uint32_t r_ptr; + uint32_t fifo_size; + CANPacket_t *elems; +} can_ring; + +extern can_ring *rx_q; +extern can_ring *tx1_q; +extern can_ring *tx2_q; +extern can_ring *tx3_q; + +bool can_pop(can_ring *q, CANPacket_t *elem); +bool can_push(can_ring *q, CANPacket_t *elem); +void can_set_checksum(CANPacket_t *packet); +int comms_can_read(uint8_t *data, uint32_t max_len); +void comms_can_write(uint8_t *data, uint32_t len); +void comms_can_reset(void); +uint32_t can_slots_empty(can_ring *q); +""") + +class CANPacket: + reserved: int + bus: int + data_len_code: int + rejected: int + returned: int + extended: int + addr: int + data: list[int] + +class Panda(Protocol): + # CAN + tx1_q: Any + tx2_q: Any + tx3_q: Any + def can_set_checksum(self, p: CANPacket) -> None: ... + + # safety + def set_safety_hooks(self, mode: int, param: int) -> int: ... + + +libpanda: Panda = ffi.dlopen(libpanda_fn) + + +# helpers + +def make_CANPacket(addr: int, bus: int, dat): + ret = ffi.new('CANPacket_t *') + ret[0].extended = 1 if addr >= 0x800 else 0 + ret[0].addr = addr + ret[0].data_len_code = LEN_TO_DLC[len(dat)] + ret[0].bus = bus + ret[0].data = bytes(dat) + libpanda.can_set_checksum(ret) + + return ret diff --git a/panda_tici/tests/libpanda/panda.c b/panda_tici/tests/libpanda/panda.c new file mode 100644 index 0000000..2d17d64 --- /dev/null +++ b/panda_tici/tests/libpanda/panda.c @@ -0,0 +1,28 @@ +#include "fake_stm.h" +#include "config.h" +#include "can.h" + +bool can_init(uint8_t can_number) { return true; } +void process_can(uint8_t can_number) { } +//int safety_tx_hook(CANPacket_t *to_send) { return 1; } + +typedef struct harness_configuration harness_configuration; +void refresh_can_tx_slots_available(void); +void can_tx_comms_resume_usb(void) { }; +void can_tx_comms_resume_spi(void) { }; + +#include "health.h" +#include "faults.h" +#include "libc.h" +#include "boards/board_declarations.h" +#include "opendbc/safety/safety.h" +#include "main_definitions.h" +#include "drivers/can_common.h" + +can_ring *rx_q = &can_rx_q; +can_ring *tx1_q = &can_tx1_q; +can_ring *tx2_q = &can_tx2_q; +can_ring *tx3_q = &can_tx3_q; + +#include "comms_definitions.h" +#include "can_comms.h" diff --git a/panda_tici/tests/libs/resetter.py b/panda_tici/tests/libs/resetter.py new file mode 100644 index 0000000..3868bde --- /dev/null +++ b/panda_tici/tests/libs/resetter.py @@ -0,0 +1,57 @@ +import time +import usb1 + + +class Resetter(): + def __init__(self): + self._handle = None + self.connect() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def close(self): + self._handle.close() + self._context.close() + self._handle = None + + def connect(self): + if self._handle: + self.close() + + self._handle = None + + self._context = usb1.USBContext() + self._context.open() + for device in self._context.getDeviceList(skip_on_error=True): + if device.getVendorID() == 0xbbaa and device.getProductID() == 0xddc0: + try: + self._handle = device.open() + self._handle.claimInterface(0) + break + except Exception as e: + print(e) + assert self._handle + + def enable_power(self, port, enabled): + self._handle.controlWrite((usb1.ENDPOINT_OUT | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE), 0xff, port, enabled, b'') + + def enable_boot(self, enabled): + self._handle.controlWrite((usb1.ENDPOINT_OUT | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE), 0xff, 0, enabled, b'') + + def cycle_power(self, delay=5, dfu=False, ports=None): + if ports is None: + ports = [1, 2, 3] + + self.enable_boot(dfu) + for port in ports: + self.enable_power(port, False) + time.sleep(0.5) + + for port in ports: + self.enable_power(port, True) + time.sleep(delay) + self.enable_boot(False) diff --git a/panda_tici/tests/misra/.gitignore b/panda_tici/tests/misra/.gitignore new file mode 100644 index 0000000..fc9ac22 --- /dev/null +++ b/panda_tici/tests/misra/.gitignore @@ -0,0 +1,5 @@ +*.pdf +*.txt +.output.log +new_table +cppcheck/ diff --git a/panda_tici/tests/misra/checkers.txt b/panda_tici/tests/misra/checkers.txt new file mode 100644 index 0000000..0b6bfc5 --- /dev/null +++ b/panda_tici/tests/misra/checkers.txt @@ -0,0 +1,911 @@ +Cppcheck checkers list from test_misra.sh: + + + + + +TEST variant options: +--enable=all --disable=unusedFunction -DPANDA --addon=misra -DSTM32F4 -DSTM32F413xx /board/main.c + + +Critical errors +--------------- +No critical errors encountered. +Note: There might still have been non-critical bailouts which might lead to false negatives. + + +Open source checkers +-------------------- +Yes Check64BitPortability::pointerassignment +Yes CheckAssert::assertWithSideEffects +Yes CheckAutoVariables::assignFunctionArg +Yes CheckAutoVariables::autoVariables +Yes CheckAutoVariables::checkVarLifetime +No CheckBool::checkAssignBoolToFloat require:style,c++ +Yes CheckBool::checkAssignBoolToPointer +No CheckBool::checkBitwiseOnBoolean require:style,inconclusive +Yes CheckBool::checkComparisonOfBoolExpressionWithInt +No CheckBool::checkComparisonOfBoolWithBool require:style,c++ +No CheckBool::checkComparisonOfBoolWithInt require:warning,c++ +No CheckBool::checkComparisonOfFuncReturningBool require:style,c++ +Yes CheckBool::checkIncrementBoolean +Yes CheckBool::pointerArithBool +Yes CheckBool::returnValueOfFunctionReturningBool +No CheckBoost::checkBoostForeachModification +Yes CheckBufferOverrun::analyseWholeProgram +Yes CheckBufferOverrun::argumentSize +Yes CheckBufferOverrun::arrayIndex +Yes CheckBufferOverrun::arrayIndexThenCheck +Yes CheckBufferOverrun::bufferOverflow +Yes CheckBufferOverrun::negativeArraySize +Yes CheckBufferOverrun::objectIndex +Yes CheckBufferOverrun::pointerArithmetic +No CheckBufferOverrun::stringNotZeroTerminated require:warning,inconclusive +Yes CheckClass::analyseWholeProgram +No CheckClass::checkConst require:style,inconclusive +No CheckClass::checkConstructors require:style,warning +No CheckClass::checkCopyConstructors require:warning +No CheckClass::checkDuplInheritedMembers require:warning +No CheckClass::checkExplicitConstructors require:style +No CheckClass::checkMemset +No CheckClass::checkMissingOverride require:style,c++03 +No CheckClass::checkReturnByReference require:performance +No CheckClass::checkSelfInitialization +No CheckClass::checkThisUseAfterFree require:warning +No CheckClass::checkUnsafeClassRefMember require:warning,safeChecks +No CheckClass::checkUselessOverride require:style +No CheckClass::checkVirtualFunctionCallInConstructor require:warning +No CheckClass::initializationListUsage require:performance +No CheckClass::initializerListOrder require:style,inconclusive +No CheckClass::operatorEqRetRefThis require:style +No CheckClass::operatorEqToSelf require:warning +No CheckClass::privateFunctions require:style +No CheckClass::thisSubtraction require:warning +No CheckClass::virtualDestructor +Yes CheckCondition::alwaysTrueFalse +Yes CheckCondition::assignIf +Yes CheckCondition::checkAssignmentInCondition +Yes CheckCondition::checkBadBitmaskCheck +Yes CheckCondition::checkCompareValueOutOfTypeRange +Yes CheckCondition::checkDuplicateConditionalAssign +Yes CheckCondition::checkIncorrectLogicOperator +Yes CheckCondition::checkInvalidTestForOverflow +Yes CheckCondition::checkModuloAlwaysTrueFalse +Yes CheckCondition::checkPointerAdditionResultNotNull +Yes CheckCondition::clarifyCondition +Yes CheckCondition::comparison +Yes CheckCondition::duplicateCondition +Yes CheckCondition::multiCondition +Yes CheckCondition::multiCondition2 +No CheckExceptionSafety::checkCatchExceptionByValue require:style +No CheckExceptionSafety::checkRethrowCopy require:style +No CheckExceptionSafety::deallocThrow require:warning +No CheckExceptionSafety::destructors require:warning +No CheckExceptionSafety::nothrowThrows +No CheckExceptionSafety::rethrowNoCurrentException +No CheckExceptionSafety::unhandledExceptionSpecification require:style,inconclusive +Yes CheckFunctions::checkIgnoredReturnValue +Yes CheckFunctions::checkMathFunctions +Yes CheckFunctions::checkMissingReturn +Yes CheckFunctions::checkProhibitedFunctions +Yes CheckFunctions::invalidFunctionUsage +Yes CheckFunctions::memsetInvalid2ndParam +Yes CheckFunctions::memsetZeroBytes +No CheckFunctions::returnLocalStdMove require:performance,c++11 +Yes CheckFunctions::useStandardLibrary +No CheckIO::checkCoutCerrMisusage require:c +Yes CheckIO::checkFileUsage +Yes CheckIO::checkWrongPrintfScanfArguments +Yes CheckIO::invalidScanf +Yes CheckLeakAutoVar::check +No CheckMemoryLeakInClass::check +Yes CheckMemoryLeakInFunction::checkReallocUsage +Yes CheckMemoryLeakNoVar::check +No CheckMemoryLeakNoVar::checkForUnsafeArgAlloc +Yes CheckMemoryLeakStructMember::check +Yes CheckNullPointer::analyseWholeProgram +Yes CheckNullPointer::arithmetic +Yes CheckNullPointer::nullConstantDereference +Yes CheckNullPointer::nullPointer +No CheckOther::checkAccessOfMovedVariable require:c++11,warning +Yes CheckOther::checkCastIntToCharAndBack +Yes CheckOther::checkCharVariable +Yes CheckOther::checkComparePointers +Yes CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse +Yes CheckOther::checkConstPointer +No CheckOther::checkConstVariable require:style,c++ +No CheckOther::checkDuplicateBranch require:style,inconclusive +Yes CheckOther::checkDuplicateExpression +Yes CheckOther::checkEvaluationOrder +Yes CheckOther::checkFuncArgNamesDifferent +No CheckOther::checkIncompleteArrayFill require:warning,portability,inconclusive +Yes CheckOther::checkIncompleteStatement +No CheckOther::checkInterlockedDecrement require:windows-platform +Yes CheckOther::checkInvalidFree +Yes CheckOther::checkKnownArgument +Yes CheckOther::checkKnownPointerToBool +No CheckOther::checkMisusedScopedObject require:style,c++ +Yes CheckOther::checkModuloOfOne +Yes CheckOther::checkNanInArithmeticExpression +Yes CheckOther::checkNegativeBitwiseShift +Yes CheckOther::checkOverlappingWrite +No CheckOther::checkPassByReference require:performance,c++ +Yes CheckOther::checkRedundantAssignment +No CheckOther::checkRedundantCopy require:c++,performance,inconclusive +Yes CheckOther::checkRedundantPointerOp +Yes CheckOther::checkShadowVariables +Yes CheckOther::checkSignOfUnsignedVariable +No CheckOther::checkSuspiciousCaseInSwitch require:warning,inconclusive +No CheckOther::checkSuspiciousSemicolon require:warning,inconclusive +Yes CheckOther::checkUnreachableCode +Yes CheckOther::checkUnusedLabel +Yes CheckOther::checkVarFuncNullUB +Yes CheckOther::checkVariableScope +Yes CheckOther::checkZeroDivision +Yes CheckOther::clarifyCalculation +Yes CheckOther::clarifyStatement +Yes CheckOther::invalidPointerCast +Yes CheckOther::redundantBitwiseOperationInSwitch +Yes CheckOther::suspiciousFloatingPointCast +No CheckOther::warningOldStylePointerCast require:style,c++ +No CheckPostfixOperator::postfixOperator require:performance +Yes CheckSizeof::checkSizeofForArrayParameter +Yes CheckSizeof::checkSizeofForNumericParameter +Yes CheckSizeof::checkSizeofForPointerSize +Yes CheckSizeof::sizeofCalculation +Yes CheckSizeof::sizeofFunction +Yes CheckSizeof::sizeofVoid +Yes CheckSizeof::sizeofsizeof +No CheckSizeof::suspiciousSizeofCalculation require:warning,inconclusive +No CheckStl::checkDereferenceInvalidIterator require:warning +No CheckStl::checkDereferenceInvalidIterator2 +No CheckStl::checkFindInsert require:performance +No CheckStl::checkMutexes require:warning +No CheckStl::erase +No CheckStl::eraseIteratorOutOfBounds +No CheckStl::if_find require:warning,performance +No CheckStl::invalidContainer +No CheckStl::iterators +No CheckStl::knownEmptyContainer require:style +No CheckStl::misMatchingContainerIterator +No CheckStl::misMatchingContainers +No CheckStl::missingComparison require:warning +No CheckStl::negativeIndex +No CheckStl::outOfBounds +No CheckStl::outOfBoundsIndexExpression +No CheckStl::redundantCondition require:style +No CheckStl::size require:performance,c++03 +No CheckStl::stlBoundaries +No CheckStl::stlOutOfBounds +No CheckStl::string_c_str +No CheckStl::useStlAlgorithm require:style +No CheckStl::uselessCalls require:performance,warning +Yes CheckString::checkAlwaysTrueOrFalseStringCompare +Yes CheckString::checkIncorrectStringCompare +Yes CheckString::checkSuspiciousStringCompare +Yes CheckString::overlappingStrcmp +Yes CheckString::sprintfOverlappingData +Yes CheckString::strPlusChar +Yes CheckString::stringLiteralWrite +Yes CheckType::checkFloatToIntegerOverflow +Yes CheckType::checkIntegerOverflow +Yes CheckType::checkLongCast +Yes CheckType::checkSignConversion +Yes CheckType::checkTooBigBitwiseShift +Yes CheckUninitVar::check +Yes CheckUninitVar::valueFlowUninit +No CheckUnusedFunctions::check require:unusedFunction +Yes CheckUnusedVar::checkFunctionVariableUsage +Yes CheckUnusedVar::checkStructMemberUsage +Yes CheckVaarg::va_list_usage +Yes CheckVaarg::va_start_argument + + +Premium checkers +---------------- +Not available, Cppcheck Premium is not used + + +Autosar +------- +Not available, Cppcheck Premium is not used + + +Cert C +------ +Not available, Cppcheck Premium is not used + + +Cert C++ +-------- +Not available, Cppcheck Premium is not used + + +Misra C 2012 +------------ +No Misra C 2012: Dir 1.1 +No Misra C 2012: Dir 2.1 +No Misra C 2012: Dir 3.1 +No Misra C 2012: Dir 4.1 +No Misra C 2012: Dir 4.2 +No Misra C 2012: Dir 4.3 +No Misra C 2012: Dir 4.4 +No Misra C 2012: Dir 4.5 +No Misra C 2012: Dir 4.6 amendment:3 +No Misra C 2012: Dir 4.7 +No Misra C 2012: Dir 4.8 +No Misra C 2012: Dir 4.9 amendment:3 +No Misra C 2012: Dir 4.10 +No Misra C 2012: Dir 4.11 amendment:3 +No Misra C 2012: Dir 4.12 +No Misra C 2012: Dir 4.13 +No Misra C 2012: Dir 4.14 amendment:2 +No Misra C 2012: Dir 4.15 amendment:3 +No Misra C 2012: Dir 5.1 amendment:4 +No Misra C 2012: Dir 5.2 amendment:4 +No Misra C 2012: Dir 5.3 amendment:4 +Yes Misra C 2012: 1.1 +Yes Misra C 2012: 1.2 +Yes Misra C 2012: 1.3 +Yes Misra C 2012: 1.4 amendment:2 +No Misra C 2012: 1.5 amendment:3 require:premium +Yes Misra C 2012: 2.1 +Yes Misra C 2012: 2.2 +Yes Misra C 2012: 2.3 +Yes Misra C 2012: 2.4 +Yes Misra C 2012: 2.5 +Yes Misra C 2012: 2.6 +Yes Misra C 2012: 2.7 +Yes Misra C 2012: 2.8 +Yes Misra C 2012: 3.1 +Yes Misra C 2012: 3.2 +Yes Misra C 2012: 4.1 +Yes Misra C 2012: 4.2 +Yes Misra C 2012: 5.1 +Yes Misra C 2012: 5.2 +Yes Misra C 2012: 5.3 +Yes Misra C 2012: 5.4 +Yes Misra C 2012: 5.5 +Yes Misra C 2012: 5.6 +Yes Misra C 2012: 5.7 +Yes Misra C 2012: 5.8 +Yes Misra C 2012: 5.9 +Yes Misra C 2012: 6.1 +Yes Misra C 2012: 6.2 +No Misra C 2012: 6.3 +Yes Misra C 2012: 7.1 +Yes Misra C 2012: 7.2 +Yes Misra C 2012: 7.3 +Yes Misra C 2012: 7.4 +No Misra C 2012: 7.5 +No Misra C 2012: 7.6 +Yes Misra C 2012: 8.1 +Yes Misra C 2012: 8.2 +No Misra C 2012: 8.3 +Yes Misra C 2012: 8.4 +Yes Misra C 2012: 8.5 +Yes Misra C 2012: 8.6 +Yes Misra C 2012: 8.7 +Yes Misra C 2012: 8.8 +Yes Misra C 2012: 8.9 +Yes Misra C 2012: 8.10 +Yes Misra C 2012: 8.11 +Yes Misra C 2012: 8.12 +Yes Misra C 2012: 8.13 +Yes Misra C 2012: 8.14 +No Misra C 2012: 8.15 +No Misra C 2012: 8.16 +No Misra C 2012: 8.17 +Yes Misra C 2012: 9.1 +Yes Misra C 2012: 9.2 +Yes Misra C 2012: 9.3 +Yes Misra C 2012: 9.4 +Yes Misra C 2012: 9.5 +No Misra C 2012: 9.6 +No Misra C 2012: 9.7 +Yes Misra C 2012: 10.1 +Yes Misra C 2012: 10.2 +Yes Misra C 2012: 10.3 +Yes Misra C 2012: 10.4 +Yes Misra C 2012: 10.5 +Yes Misra C 2012: 10.6 +Yes Misra C 2012: 10.7 +Yes Misra C 2012: 10.8 +Yes Misra C 2012: 11.1 +Yes Misra C 2012: 11.2 +Yes Misra C 2012: 11.3 +Yes Misra C 2012: 11.4 +Yes Misra C 2012: 11.5 +Yes Misra C 2012: 11.6 +Yes Misra C 2012: 11.7 +Yes Misra C 2012: 11.8 +Yes Misra C 2012: 11.9 +No Misra C 2012: 11.10 +Yes Misra C 2012: 12.1 +Yes Misra C 2012: 12.2 +Yes Misra C 2012: 12.3 +Yes Misra C 2012: 12.4 +Yes Misra C 2012: 12.5 amendment:1 +No Misra C 2012: 12.6 amendment:4 require:premium +Yes Misra C 2012: 13.1 +No Misra C 2012: 13.2 +Yes Misra C 2012: 13.3 +Yes Misra C 2012: 13.4 +Yes Misra C 2012: 13.5 +Yes Misra C 2012: 13.6 +Yes Misra C 2012: 14.1 +Yes Misra C 2012: 14.2 +Yes Misra C 2012: 14.3 +Yes Misra C 2012: 14.4 +Yes Misra C 2012: 15.1 +Yes Misra C 2012: 15.2 +Yes Misra C 2012: 15.3 +Yes Misra C 2012: 15.4 +Yes Misra C 2012: 15.5 +Yes Misra C 2012: 15.6 +Yes Misra C 2012: 15.7 +Yes Misra C 2012: 16.1 +Yes Misra C 2012: 16.2 +Yes Misra C 2012: 16.3 +Yes Misra C 2012: 16.4 +Yes Misra C 2012: 16.5 +Yes Misra C 2012: 16.6 +Yes Misra C 2012: 16.7 +Yes Misra C 2012: 17.1 +Yes Misra C 2012: 17.2 +Yes Misra C 2012: 17.3 +No Misra C 2012: 17.4 +Yes Misra C 2012: 17.5 +Yes Misra C 2012: 17.6 +Yes Misra C 2012: 17.7 +Yes Misra C 2012: 17.8 +No Misra C 2012: 17.9 +No Misra C 2012: 17.10 +No Misra C 2012: 17.11 +No Misra C 2012: 17.12 +No Misra C 2012: 17.13 +Yes Misra C 2012: 18.1 +Yes Misra C 2012: 18.2 +Yes Misra C 2012: 18.3 +Yes Misra C 2012: 18.4 +Yes Misra C 2012: 18.5 +Yes Misra C 2012: 18.6 +Yes Misra C 2012: 18.7 +Yes Misra C 2012: 18.8 +No Misra C 2012: 18.9 +No Misra C 2012: 18.10 +Yes Misra C 2012: 19.1 +Yes Misra C 2012: 19.2 +Yes Misra C 2012: 20.1 +Yes Misra C 2012: 20.2 +Yes Misra C 2012: 20.3 +Yes Misra C 2012: 20.4 +Yes Misra C 2012: 20.5 +Yes Misra C 2012: 20.6 +Yes Misra C 2012: 20.7 +Yes Misra C 2012: 20.8 +Yes Misra C 2012: 20.9 +Yes Misra C 2012: 20.10 +Yes Misra C 2012: 20.11 +Yes Misra C 2012: 20.12 +Yes Misra C 2012: 20.13 +Yes Misra C 2012: 20.14 +Yes Misra C 2012: 21.1 +Yes Misra C 2012: 21.2 +Yes Misra C 2012: 21.3 +Yes Misra C 2012: 21.4 +Yes Misra C 2012: 21.5 +Yes Misra C 2012: 21.6 +Yes Misra C 2012: 21.7 +Yes Misra C 2012: 21.8 +Yes Misra C 2012: 21.9 +Yes Misra C 2012: 21.10 +Yes Misra C 2012: 21.11 +Yes Misra C 2012: 21.12 +Yes Misra C 2012: 21.13 amendment:1 +Yes Misra C 2012: 21.14 amendment:1 +Yes Misra C 2012: 21.15 amendment:1 +Yes Misra C 2012: 21.16 amendment:1 +Yes Misra C 2012: 21.17 amendment:1 +Yes Misra C 2012: 21.18 amendment:1 +Yes Misra C 2012: 21.19 amendment:1 +Yes Misra C 2012: 21.20 amendment:1 +Yes Misra C 2012: 21.21 amendment:3 +No Misra C 2012: 21.22 amendment:3 require:premium +No Misra C 2012: 21.23 amendment:3 require:premium +No Misra C 2012: 21.24 amendment:3 require:premium +No Misra C 2012: 21.25 amendment:4 require:premium +No Misra C 2012: 21.26 amendment:4 require:premium +Yes Misra C 2012: 22.1 +Yes Misra C 2012: 22.2 +Yes Misra C 2012: 22.3 +Yes Misra C 2012: 22.4 +Yes Misra C 2012: 22.5 +Yes Misra C 2012: 22.6 +Yes Misra C 2012: 22.7 amendment:1 +Yes Misra C 2012: 22.8 amendment:1 +Yes Misra C 2012: 22.9 amendment:1 +Yes Misra C 2012: 22.10 amendment:1 +No Misra C 2012: 22.11 amendment:4 require:premium +No Misra C 2012: 22.12 amendment:4 require:premium +No Misra C 2012: 22.13 amendment:4 require:premium +No Misra C 2012: 22.14 amendment:4 require:premium +No Misra C 2012: 22.15 amendment:4 require:premium +No Misra C 2012: 22.16 amendment:4 require:premium +No Misra C 2012: 22.17 amendment:4 require:premium +No Misra C 2012: 22.18 amendment:4 require:premium +No Misra C 2012: 22.19 amendment:4 require:premium +No Misra C 2012: 22.20 amendment:4 require:premium +No Misra C 2012: 23.1 amendment:3 require:premium +No Misra C 2012: 23.2 amendment:3 require:premium +No Misra C 2012: 23.3 amendment:3 require:premium +No Misra C 2012: 23.4 amendment:3 require:premium +No Misra C 2012: 23.5 amendment:3 require:premium +No Misra C 2012: 23.6 amendment:3 require:premium +No Misra C 2012: 23.7 amendment:3 require:premium +No Misra C 2012: 23.8 amendment:3 require:premium + + +Misra C++ 2008 +-------------- +Not available, Cppcheck Premium is not used + + +Misra C++ 2023 +-------------- +Not available, Cppcheck Premium is not used + + + + + +TEST variant options: +--enable=all --disable=unusedFunction -DPANDA --addon=misra -DSTM32H7 -DSTM32H725xx /board/main.c + + +Critical errors +--------------- +No critical errors encountered. +Note: There might still have been non-critical bailouts which might lead to false negatives. + + +Open source checkers +-------------------- +Yes Check64BitPortability::pointerassignment +Yes CheckAssert::assertWithSideEffects +Yes CheckAutoVariables::assignFunctionArg +Yes CheckAutoVariables::autoVariables +Yes CheckAutoVariables::checkVarLifetime +No CheckBool::checkAssignBoolToFloat require:style,c++ +Yes CheckBool::checkAssignBoolToPointer +No CheckBool::checkBitwiseOnBoolean require:style,inconclusive +Yes CheckBool::checkComparisonOfBoolExpressionWithInt +No CheckBool::checkComparisonOfBoolWithBool require:style,c++ +No CheckBool::checkComparisonOfBoolWithInt require:warning,c++ +No CheckBool::checkComparisonOfFuncReturningBool require:style,c++ +Yes CheckBool::checkIncrementBoolean +Yes CheckBool::pointerArithBool +Yes CheckBool::returnValueOfFunctionReturningBool +No CheckBoost::checkBoostForeachModification +Yes CheckBufferOverrun::analyseWholeProgram +Yes CheckBufferOverrun::argumentSize +Yes CheckBufferOverrun::arrayIndex +Yes CheckBufferOverrun::arrayIndexThenCheck +Yes CheckBufferOverrun::bufferOverflow +Yes CheckBufferOverrun::negativeArraySize +Yes CheckBufferOverrun::objectIndex +Yes CheckBufferOverrun::pointerArithmetic +No CheckBufferOverrun::stringNotZeroTerminated require:warning,inconclusive +Yes CheckClass::analyseWholeProgram +No CheckClass::checkConst require:style,inconclusive +No CheckClass::checkConstructors require:style,warning +No CheckClass::checkCopyConstructors require:warning +No CheckClass::checkDuplInheritedMembers require:warning +No CheckClass::checkExplicitConstructors require:style +No CheckClass::checkMemset +No CheckClass::checkMissingOverride require:style,c++03 +No CheckClass::checkReturnByReference require:performance +No CheckClass::checkSelfInitialization +No CheckClass::checkThisUseAfterFree require:warning +No CheckClass::checkUnsafeClassRefMember require:warning,safeChecks +No CheckClass::checkUselessOverride require:style +No CheckClass::checkVirtualFunctionCallInConstructor require:warning +No CheckClass::initializationListUsage require:performance +No CheckClass::initializerListOrder require:style,inconclusive +No CheckClass::operatorEqRetRefThis require:style +No CheckClass::operatorEqToSelf require:warning +No CheckClass::privateFunctions require:style +No CheckClass::thisSubtraction require:warning +No CheckClass::virtualDestructor +Yes CheckCondition::alwaysTrueFalse +Yes CheckCondition::assignIf +Yes CheckCondition::checkAssignmentInCondition +Yes CheckCondition::checkBadBitmaskCheck +Yes CheckCondition::checkCompareValueOutOfTypeRange +Yes CheckCondition::checkDuplicateConditionalAssign +Yes CheckCondition::checkIncorrectLogicOperator +Yes CheckCondition::checkInvalidTestForOverflow +Yes CheckCondition::checkModuloAlwaysTrueFalse +Yes CheckCondition::checkPointerAdditionResultNotNull +Yes CheckCondition::clarifyCondition +Yes CheckCondition::comparison +Yes CheckCondition::duplicateCondition +Yes CheckCondition::multiCondition +Yes CheckCondition::multiCondition2 +No CheckExceptionSafety::checkCatchExceptionByValue require:style +No CheckExceptionSafety::checkRethrowCopy require:style +No CheckExceptionSafety::deallocThrow require:warning +No CheckExceptionSafety::destructors require:warning +No CheckExceptionSafety::nothrowThrows +No CheckExceptionSafety::rethrowNoCurrentException +No CheckExceptionSafety::unhandledExceptionSpecification require:style,inconclusive +Yes CheckFunctions::checkIgnoredReturnValue +Yes CheckFunctions::checkMathFunctions +Yes CheckFunctions::checkMissingReturn +Yes CheckFunctions::checkProhibitedFunctions +Yes CheckFunctions::invalidFunctionUsage +Yes CheckFunctions::memsetInvalid2ndParam +Yes CheckFunctions::memsetZeroBytes +No CheckFunctions::returnLocalStdMove require:performance,c++11 +Yes CheckFunctions::useStandardLibrary +No CheckIO::checkCoutCerrMisusage require:c +Yes CheckIO::checkFileUsage +Yes CheckIO::checkWrongPrintfScanfArguments +Yes CheckIO::invalidScanf +Yes CheckLeakAutoVar::check +No CheckMemoryLeakInClass::check +Yes CheckMemoryLeakInFunction::checkReallocUsage +Yes CheckMemoryLeakNoVar::check +No CheckMemoryLeakNoVar::checkForUnsafeArgAlloc +Yes CheckMemoryLeakStructMember::check +Yes CheckNullPointer::analyseWholeProgram +Yes CheckNullPointer::arithmetic +Yes CheckNullPointer::nullConstantDereference +Yes CheckNullPointer::nullPointer +No CheckOther::checkAccessOfMovedVariable require:c++11,warning +Yes CheckOther::checkCastIntToCharAndBack +Yes CheckOther::checkCharVariable +Yes CheckOther::checkComparePointers +Yes CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse +Yes CheckOther::checkConstPointer +No CheckOther::checkConstVariable require:style,c++ +No CheckOther::checkDuplicateBranch require:style,inconclusive +Yes CheckOther::checkDuplicateExpression +Yes CheckOther::checkEvaluationOrder +Yes CheckOther::checkFuncArgNamesDifferent +No CheckOther::checkIncompleteArrayFill require:warning,portability,inconclusive +Yes CheckOther::checkIncompleteStatement +No CheckOther::checkInterlockedDecrement require:windows-platform +Yes CheckOther::checkInvalidFree +Yes CheckOther::checkKnownArgument +Yes CheckOther::checkKnownPointerToBool +No CheckOther::checkMisusedScopedObject require:style,c++ +Yes CheckOther::checkModuloOfOne +Yes CheckOther::checkNanInArithmeticExpression +Yes CheckOther::checkNegativeBitwiseShift +Yes CheckOther::checkOverlappingWrite +No CheckOther::checkPassByReference require:performance,c++ +Yes CheckOther::checkRedundantAssignment +No CheckOther::checkRedundantCopy require:c++,performance,inconclusive +Yes CheckOther::checkRedundantPointerOp +Yes CheckOther::checkShadowVariables +Yes CheckOther::checkSignOfUnsignedVariable +No CheckOther::checkSuspiciousCaseInSwitch require:warning,inconclusive +No CheckOther::checkSuspiciousSemicolon require:warning,inconclusive +Yes CheckOther::checkUnreachableCode +Yes CheckOther::checkUnusedLabel +Yes CheckOther::checkVarFuncNullUB +Yes CheckOther::checkVariableScope +Yes CheckOther::checkZeroDivision +Yes CheckOther::clarifyCalculation +Yes CheckOther::clarifyStatement +Yes CheckOther::invalidPointerCast +Yes CheckOther::redundantBitwiseOperationInSwitch +Yes CheckOther::suspiciousFloatingPointCast +No CheckOther::warningOldStylePointerCast require:style,c++ +No CheckPostfixOperator::postfixOperator require:performance +Yes CheckSizeof::checkSizeofForArrayParameter +Yes CheckSizeof::checkSizeofForNumericParameter +Yes CheckSizeof::checkSizeofForPointerSize +Yes CheckSizeof::sizeofCalculation +Yes CheckSizeof::sizeofFunction +Yes CheckSizeof::sizeofVoid +Yes CheckSizeof::sizeofsizeof +No CheckSizeof::suspiciousSizeofCalculation require:warning,inconclusive +No CheckStl::checkDereferenceInvalidIterator require:warning +No CheckStl::checkDereferenceInvalidIterator2 +No CheckStl::checkFindInsert require:performance +No CheckStl::checkMutexes require:warning +No CheckStl::erase +No CheckStl::eraseIteratorOutOfBounds +No CheckStl::if_find require:warning,performance +No CheckStl::invalidContainer +No CheckStl::iterators +No CheckStl::knownEmptyContainer require:style +No CheckStl::misMatchingContainerIterator +No CheckStl::misMatchingContainers +No CheckStl::missingComparison require:warning +No CheckStl::negativeIndex +No CheckStl::outOfBounds +No CheckStl::outOfBoundsIndexExpression +No CheckStl::redundantCondition require:style +No CheckStl::size require:performance,c++03 +No CheckStl::stlBoundaries +No CheckStl::stlOutOfBounds +No CheckStl::string_c_str +No CheckStl::useStlAlgorithm require:style +No CheckStl::uselessCalls require:performance,warning +Yes CheckString::checkAlwaysTrueOrFalseStringCompare +Yes CheckString::checkIncorrectStringCompare +Yes CheckString::checkSuspiciousStringCompare +Yes CheckString::overlappingStrcmp +Yes CheckString::sprintfOverlappingData +Yes CheckString::strPlusChar +Yes CheckString::stringLiteralWrite +Yes CheckType::checkFloatToIntegerOverflow +Yes CheckType::checkIntegerOverflow +Yes CheckType::checkLongCast +Yes CheckType::checkSignConversion +Yes CheckType::checkTooBigBitwiseShift +Yes CheckUninitVar::check +Yes CheckUninitVar::valueFlowUninit +No CheckUnusedFunctions::check require:unusedFunction +Yes CheckUnusedVar::checkFunctionVariableUsage +Yes CheckUnusedVar::checkStructMemberUsage +Yes CheckVaarg::va_list_usage +Yes CheckVaarg::va_start_argument + + +Premium checkers +---------------- +Not available, Cppcheck Premium is not used + + +Autosar +------- +Not available, Cppcheck Premium is not used + + +Cert C +------ +Not available, Cppcheck Premium is not used + + +Cert C++ +-------- +Not available, Cppcheck Premium is not used + + +Misra C 2012 +------------ +No Misra C 2012: Dir 1.1 +No Misra C 2012: Dir 2.1 +No Misra C 2012: Dir 3.1 +No Misra C 2012: Dir 4.1 +No Misra C 2012: Dir 4.2 +No Misra C 2012: Dir 4.3 +No Misra C 2012: Dir 4.4 +No Misra C 2012: Dir 4.5 +No Misra C 2012: Dir 4.6 amendment:3 +No Misra C 2012: Dir 4.7 +No Misra C 2012: Dir 4.8 +No Misra C 2012: Dir 4.9 amendment:3 +No Misra C 2012: Dir 4.10 +No Misra C 2012: Dir 4.11 amendment:3 +No Misra C 2012: Dir 4.12 +No Misra C 2012: Dir 4.13 +No Misra C 2012: Dir 4.14 amendment:2 +No Misra C 2012: Dir 4.15 amendment:3 +No Misra C 2012: Dir 5.1 amendment:4 +No Misra C 2012: Dir 5.2 amendment:4 +No Misra C 2012: Dir 5.3 amendment:4 +Yes Misra C 2012: 1.1 +Yes Misra C 2012: 1.2 +Yes Misra C 2012: 1.3 +Yes Misra C 2012: 1.4 amendment:2 +No Misra C 2012: 1.5 amendment:3 require:premium +Yes Misra C 2012: 2.1 +Yes Misra C 2012: 2.2 +Yes Misra C 2012: 2.3 +Yes Misra C 2012: 2.4 +Yes Misra C 2012: 2.5 +Yes Misra C 2012: 2.6 +Yes Misra C 2012: 2.7 +Yes Misra C 2012: 2.8 +Yes Misra C 2012: 3.1 +Yes Misra C 2012: 3.2 +Yes Misra C 2012: 4.1 +Yes Misra C 2012: 4.2 +Yes Misra C 2012: 5.1 +Yes Misra C 2012: 5.2 +Yes Misra C 2012: 5.3 +Yes Misra C 2012: 5.4 +Yes Misra C 2012: 5.5 +Yes Misra C 2012: 5.6 +Yes Misra C 2012: 5.7 +Yes Misra C 2012: 5.8 +Yes Misra C 2012: 5.9 +Yes Misra C 2012: 6.1 +Yes Misra C 2012: 6.2 +No Misra C 2012: 6.3 +Yes Misra C 2012: 7.1 +Yes Misra C 2012: 7.2 +Yes Misra C 2012: 7.3 +Yes Misra C 2012: 7.4 +No Misra C 2012: 7.5 +No Misra C 2012: 7.6 +Yes Misra C 2012: 8.1 +Yes Misra C 2012: 8.2 +No Misra C 2012: 8.3 +Yes Misra C 2012: 8.4 +Yes Misra C 2012: 8.5 +Yes Misra C 2012: 8.6 +Yes Misra C 2012: 8.7 +Yes Misra C 2012: 8.8 +Yes Misra C 2012: 8.9 +Yes Misra C 2012: 8.10 +Yes Misra C 2012: 8.11 +Yes Misra C 2012: 8.12 +Yes Misra C 2012: 8.13 +Yes Misra C 2012: 8.14 +No Misra C 2012: 8.15 +No Misra C 2012: 8.16 +No Misra C 2012: 8.17 +Yes Misra C 2012: 9.1 +Yes Misra C 2012: 9.2 +Yes Misra C 2012: 9.3 +Yes Misra C 2012: 9.4 +Yes Misra C 2012: 9.5 +No Misra C 2012: 9.6 +No Misra C 2012: 9.7 +Yes Misra C 2012: 10.1 +Yes Misra C 2012: 10.2 +Yes Misra C 2012: 10.3 +Yes Misra C 2012: 10.4 +Yes Misra C 2012: 10.5 +Yes Misra C 2012: 10.6 +Yes Misra C 2012: 10.7 +Yes Misra C 2012: 10.8 +Yes Misra C 2012: 11.1 +Yes Misra C 2012: 11.2 +Yes Misra C 2012: 11.3 +Yes Misra C 2012: 11.4 +Yes Misra C 2012: 11.5 +Yes Misra C 2012: 11.6 +Yes Misra C 2012: 11.7 +Yes Misra C 2012: 11.8 +Yes Misra C 2012: 11.9 +No Misra C 2012: 11.10 +Yes Misra C 2012: 12.1 +Yes Misra C 2012: 12.2 +Yes Misra C 2012: 12.3 +Yes Misra C 2012: 12.4 +Yes Misra C 2012: 12.5 amendment:1 +No Misra C 2012: 12.6 amendment:4 require:premium +Yes Misra C 2012: 13.1 +No Misra C 2012: 13.2 +Yes Misra C 2012: 13.3 +Yes Misra C 2012: 13.4 +Yes Misra C 2012: 13.5 +Yes Misra C 2012: 13.6 +Yes Misra C 2012: 14.1 +Yes Misra C 2012: 14.2 +Yes Misra C 2012: 14.3 +Yes Misra C 2012: 14.4 +Yes Misra C 2012: 15.1 +Yes Misra C 2012: 15.2 +Yes Misra C 2012: 15.3 +Yes Misra C 2012: 15.4 +Yes Misra C 2012: 15.5 +Yes Misra C 2012: 15.6 +Yes Misra C 2012: 15.7 +Yes Misra C 2012: 16.1 +Yes Misra C 2012: 16.2 +Yes Misra C 2012: 16.3 +Yes Misra C 2012: 16.4 +Yes Misra C 2012: 16.5 +Yes Misra C 2012: 16.6 +Yes Misra C 2012: 16.7 +Yes Misra C 2012: 17.1 +Yes Misra C 2012: 17.2 +Yes Misra C 2012: 17.3 +No Misra C 2012: 17.4 +Yes Misra C 2012: 17.5 +Yes Misra C 2012: 17.6 +Yes Misra C 2012: 17.7 +Yes Misra C 2012: 17.8 +No Misra C 2012: 17.9 +No Misra C 2012: 17.10 +No Misra C 2012: 17.11 +No Misra C 2012: 17.12 +No Misra C 2012: 17.13 +Yes Misra C 2012: 18.1 +Yes Misra C 2012: 18.2 +Yes Misra C 2012: 18.3 +Yes Misra C 2012: 18.4 +Yes Misra C 2012: 18.5 +Yes Misra C 2012: 18.6 +Yes Misra C 2012: 18.7 +Yes Misra C 2012: 18.8 +No Misra C 2012: 18.9 +No Misra C 2012: 18.10 +Yes Misra C 2012: 19.1 +Yes Misra C 2012: 19.2 +Yes Misra C 2012: 20.1 +Yes Misra C 2012: 20.2 +Yes Misra C 2012: 20.3 +Yes Misra C 2012: 20.4 +Yes Misra C 2012: 20.5 +Yes Misra C 2012: 20.6 +Yes Misra C 2012: 20.7 +Yes Misra C 2012: 20.8 +Yes Misra C 2012: 20.9 +Yes Misra C 2012: 20.10 +Yes Misra C 2012: 20.11 +Yes Misra C 2012: 20.12 +Yes Misra C 2012: 20.13 +Yes Misra C 2012: 20.14 +Yes Misra C 2012: 21.1 +Yes Misra C 2012: 21.2 +Yes Misra C 2012: 21.3 +Yes Misra C 2012: 21.4 +Yes Misra C 2012: 21.5 +Yes Misra C 2012: 21.6 +Yes Misra C 2012: 21.7 +Yes Misra C 2012: 21.8 +Yes Misra C 2012: 21.9 +Yes Misra C 2012: 21.10 +Yes Misra C 2012: 21.11 +Yes Misra C 2012: 21.12 +Yes Misra C 2012: 21.13 amendment:1 +Yes Misra C 2012: 21.14 amendment:1 +Yes Misra C 2012: 21.15 amendment:1 +Yes Misra C 2012: 21.16 amendment:1 +Yes Misra C 2012: 21.17 amendment:1 +Yes Misra C 2012: 21.18 amendment:1 +Yes Misra C 2012: 21.19 amendment:1 +Yes Misra C 2012: 21.20 amendment:1 +Yes Misra C 2012: 21.21 amendment:3 +No Misra C 2012: 21.22 amendment:3 require:premium +No Misra C 2012: 21.23 amendment:3 require:premium +No Misra C 2012: 21.24 amendment:3 require:premium +No Misra C 2012: 21.25 amendment:4 require:premium +No Misra C 2012: 21.26 amendment:4 require:premium +Yes Misra C 2012: 22.1 +Yes Misra C 2012: 22.2 +Yes Misra C 2012: 22.3 +Yes Misra C 2012: 22.4 +Yes Misra C 2012: 22.5 +Yes Misra C 2012: 22.6 +Yes Misra C 2012: 22.7 amendment:1 +Yes Misra C 2012: 22.8 amendment:1 +Yes Misra C 2012: 22.9 amendment:1 +Yes Misra C 2012: 22.10 amendment:1 +No Misra C 2012: 22.11 amendment:4 require:premium +No Misra C 2012: 22.12 amendment:4 require:premium +No Misra C 2012: 22.13 amendment:4 require:premium +No Misra C 2012: 22.14 amendment:4 require:premium +No Misra C 2012: 22.15 amendment:4 require:premium +No Misra C 2012: 22.16 amendment:4 require:premium +No Misra C 2012: 22.17 amendment:4 require:premium +No Misra C 2012: 22.18 amendment:4 require:premium +No Misra C 2012: 22.19 amendment:4 require:premium +No Misra C 2012: 22.20 amendment:4 require:premium +No Misra C 2012: 23.1 amendment:3 require:premium +No Misra C 2012: 23.2 amendment:3 require:premium +No Misra C 2012: 23.3 amendment:3 require:premium +No Misra C 2012: 23.4 amendment:3 require:premium +No Misra C 2012: 23.5 amendment:3 require:premium +No Misra C 2012: 23.6 amendment:3 require:premium +No Misra C 2012: 23.7 amendment:3 require:premium +No Misra C 2012: 23.8 amendment:3 require:premium + + +Misra C++ 2008 +-------------- +Not available, Cppcheck Premium is not used + + +Misra C++ 2023 +-------------- +Not available, Cppcheck Premium is not used diff --git a/panda_tici/tests/misra/coverage_table b/panda_tici/tests/misra/coverage_table new file mode 100644 index 0000000..0395aba --- /dev/null +++ b/panda_tici/tests/misra/coverage_table @@ -0,0 +1,156 @@ +1.1 +1.2 X (Addon) +1.3 X (Cppcheck) +2.1 X (Cppcheck) +2.2 X (Addon) +2.3 X (Addon) +2.4 X (Addon) +2.5 X (Addon) +2.6 X (Cppcheck) +2.7 X (Addon) +3.1 X (Addon) +3.2 X (Addon) +4.1 X (Addon) +4.2 X (Addon) +5.1 X (Addon) +5.2 X (Addon) +5.3 X (Cppcheck) +5.4 X (Addon) +5.5 X (Addon) +5.6 X (Addon) +5.7 X (Addon) +5.8 X (Addon) +5.9 X (Addon) +6.1 X (Addon) +6.2 X (Addon) +7.1 X (Addon) +7.2 X (Addon) +7.3 X (Addon) +7.4 X (Addon) +8.1 X (Addon) +8.2 X (Addon) +8.3 X (Cppcheck) +8.4 X (Addon) +8.5 X (Addon) +8.6 X (Addon) +8.7 X (Addon) +8.8 X (Addon) +8.9 X (Addon) +8.10 X (Addon) +8.11 X (Addon) +8.12 X (Addon) +8.13 X (Cppcheck) +8.14 X (Addon) +9.1 X (Cppcheck) +9.2 X (Addon) +9.3 X (Addon) +9.4 X (Addon) +9.5 X (Addon) +10.1 X (Addon) +10.2 X (Addon) +10.3 X (Addon) +10.4 X (Addon) +10.5 X (Addon) +10.6 X (Addon) +10.7 X (Addon) +10.8 X (Addon) +11.1 X (Addon) +11.2 X (Addon) +11.3 X (Addon) +11.4 X (Addon) +11.5 X (Addon) +11.6 X (Addon) +11.7 X (Addon) +11.8 X (Addon) +11.9 X (Addon) +12.1 X (Addon) +12.2 X (Addon) +12.3 X (Addon) +12.4 X (Addon) +13.1 X (Addon) +13.2 X (Cppcheck) +13.3 X (Addon) +13.4 X (Addon) +13.5 X (Addon) +13.6 X (Addon) +14.1 X (Addon) +14.2 X (Addon) +14.3 X (Cppcheck) +14.4 X (Addon) +15.1 X (Addon) +15.2 X (Addon) +15.3 X (Addon) +15.4 X (Addon) +15.5 X (Addon) +15.6 X (Addon) +15.7 X (Addon) +16.1 X (Addon) +16.2 X (Addon) +16.3 X (Addon) +16.4 X (Addon) +16.5 X (Addon) +16.6 X (Addon) +16.7 X (Addon) +17.1 X (Addon) +17.2 X (Addon) +17.3 X (Addon) +17.4 X (Cppcheck) +17.5 X (Cppcheck) +17.6 X (Addon) +17.7 X (Addon) +17.8 X (Addon) +18.1 X (Cppcheck) +18.2 X (Cppcheck) +18.3 X (Cppcheck) +18.4 X (Addon) +18.5 X (Addon) +18.6 X (Cppcheck) +18.7 X (Addon) +18.8 X (Addon) +19.1 X (Cppcheck) +19.2 X (Addon) +20.1 X (Addon) +20.2 X (Addon) +20.3 X (Addon) +20.4 X (Addon) +20.5 X (Addon) +20.6 X (Cppcheck) +20.7 X (Addon) +20.8 X (Addon) +20.9 X (Addon) +20.10 X (Addon) +20.11 X (Addon) +20.12 X (Addon) +20.13 X (Addon) +20.14 X (Addon) +21.1 X (Addon) +21.2 X (Addon) +21.3 X (Addon) +21.4 X (Addon) +21.5 X (Addon) +21.6 X (Addon) +21.7 X (Addon) +21.8 X (Addon) +21.9 X (Addon) +21.10 X (Addon) +21.11 X (Addon) +21.12 X (Addon) +21.13 X (Cppcheck) +21.14 X (Addon) +21.15 X (Addon) +21.16 X (Addon) +21.17 X (Cppcheck) +21.18 X (Cppcheck) +21.19 X (Addon) +21.20 X (Addon) +21.21 X (Addon) +22.1 X (Cppcheck) +22.2 X (Cppcheck) +22.3 X (Cppcheck) +22.4 X (Cppcheck) +22.5 X (Addon) +22.6 X (Cppcheck) +22.7 X (Addon) +22.8 X (Addon) +22.9 X (Addon) +22.10 X (Addon) diff --git a/panda_tici/tests/misra/install.sh b/panda_tici/tests/misra/install.sh new file mode 100755 index 0000000..9c8fd38 --- /dev/null +++ b/panda_tici/tests/misra/install.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +: "${CPPCHECK_DIR:=$DIR/cppcheck/}" + +if [ ! -d "$CPPCHECK_DIR" ]; then + git clone https://github.com/danmar/cppcheck.git $CPPCHECK_DIR +fi + +cd $CPPCHECK_DIR + +VERS="2.16.0" +git fetch --all --tags --force +git checkout $VERS + +#make clean +make MATCHCOMPILTER=yes CXXFLAGS="-O2" -j8 diff --git a/panda_tici/tests/misra/suppressions.txt b/panda_tici/tests/misra/suppressions.txt new file mode 100644 index 0000000..4800a27 --- /dev/null +++ b/panda_tici/tests/misra/suppressions.txt @@ -0,0 +1,21 @@ +# Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well +misra-c2012-11.4 +# Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well +misra-c2012-11.5 +# Advisory: as stated in the Misra document, use of goto statements in accordance to 15.2 and 15.3 is ok +misra-c2012-15.1 +# Advisory: union types can be used +misra-c2012-19.2 +# Advisory: The # and ## preprocessor operators should not be used +misra-c2012-20.10 + +# needed since not all of these suppressions are applicable to all builds +unmatchedSuppression + +# All interrupt handlers are defined, including ones we don't use +unusedFunction:*/interrupt_handlers*.h + +# all of the below suppressions are from new checks introduced after updating +# cppcheck from 2.5 -> 2.13. they are listed here to separate the update from +# fixing the violations and all are intended to be removed soon after +misra-c2012-2.5 # unused macros. a few legit, rest aren't common between F4/H7 builds. should we do this in the unusedFunction pass? diff --git a/panda_tici/tests/misra/test_misra.sh b/panda_tici/tests/misra/test_misra.sh new file mode 100755 index 0000000..3b16863 --- /dev/null +++ b/panda_tici/tests/misra/test_misra.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +PANDA_DIR=$(realpath $DIR/../../) +OPENDBC_ROOT=$(python3 -c "import opendbc; print(opendbc.INCLUDE_PATH)") + +GREEN="\e[1;32m" +YELLOW="\e[1;33m" +RED="\e[1;31m" +NC='\033[0m' + +: "${CPPCHECK_DIR:=$DIR/cppcheck/}" + +# install cppcheck if missing +if [ -z "${SKIP_CPPCHECK_INSTALL}" ]; then + $DIR/install.sh +fi + +# ensure checked in coverage table is up to date +cd $DIR +if [ -z "$SKIP_TABLES_DIFF" ]; then + python3 $CPPCHECK_DIR/addons/misra.py -generate-table > coverage_table + if ! git diff --quiet coverage_table; then + echo -e "${YELLOW}MISRA coverage table doesn't match. Update and commit:${NC}" + exit 3 + fi +fi + +cd $PANDA_DIR +if [ -z "${SKIP_BUILD}" ]; then + scons -j8 +fi + +CHECKLIST=$DIR/checkers.txt +echo "Cppcheck checkers list from test_misra.sh:" > $CHECKLIST + +cppcheck() { + # get all gcc defines: arm-none-eabi-gcc -dM -E - < /dev/null + COMMON_DEFINES="-D__GNUC__=9 -UCMSIS_NVIC_VIRTUAL -UCMSIS_VECTAB_VIRTUAL" + + # note that cppcheck build cache results in inconsistent results as of v2.13.0 + OUTPUT=$DIR/.output.log + + echo -e "\n\n\n\n\nTEST variant options:" >> $CHECKLIST + echo -e ""${@//$PANDA_DIR/}"\n\n" >> $CHECKLIST # (absolute path removed) + + $CPPCHECK_DIR/cppcheck --inline-suppr -I $PANDA_DIR/board/ \ + -I "$(arm-none-eabi-gcc -print-file-name=include)" \ + -I $PANDA_DIR/board/stm32f4/inc/ -I $PANDA_DIR/board/stm32h7/inc/ \ + -I $OPENDBC_ROOT \ + --suppressions-list=$DIR/suppressions.txt --suppress=*:*inc/* \ + --suppress=*:*include/* --error-exitcode=2 --check-level=exhaustive --safety \ + --platform=arm32-wchar_t4 $COMMON_DEFINES --checkers-report=$CHECKLIST.tmp \ + --std=c11 "$@" 2>&1 | tee $OUTPUT + + cat $CHECKLIST.tmp >> $CHECKLIST + rm $CHECKLIST.tmp + # cppcheck bug: some MISRA errors won't result in the error exit code, + # so check the output (https://trac.cppcheck.net/ticket/12440#no1) + if grep -e "misra violation" -e "error" -e "style: " $OUTPUT > /dev/null; then + printf "${RED}** FAILED: MISRA violations found!${NC}\n" + exit 1 + fi +} + +PANDA_OPTS="--enable=all --disable=unusedFunction -DPANDA --addon=misra" + +printf "\n${GREEN}** PANDA F4 CODE **${NC}\n" +cppcheck $PANDA_OPTS -DSTM32F4 -DSTM32F413xx $PANDA_DIR/board/main.c + +printf "\n${GREEN}** PANDA H7 CODE **${NC}\n" +cppcheck $PANDA_OPTS -DSTM32H7 -DSTM32H725xx $PANDA_DIR/board/main.c + +# unused needs to run globally +#printf "\n${GREEN}** UNUSED ALL CODE **${NC}\n" +#cppcheck --enable=unusedFunction --quiet $PANDA_DIR/board/ + +printf "\n${GREEN}Success!${NC} took $SECONDS seconds\n" + + +# ensure list of checkers is up to date +cd $DIR +if [ -z "$SKIP_TABLES_DIFF" ] && ! git diff --quiet $CHECKLIST; then + echo -e "\n${YELLOW}WARNING: Cppcheck checkers.txt report has changed. Review and commit...${NC}" + exit 4 +fi diff --git a/panda_tici/tests/misra/test_mutation.py b/panda_tici/tests/misra/test_mutation.py new file mode 100755 index 0000000..b73f7f6 --- /dev/null +++ b/panda_tici/tests/misra/test_mutation.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +import os +import glob +import pytest +import shutil +import subprocess +import tempfile +import random + +HERE = os.path.abspath(os.path.dirname(__file__)) +ROOT = os.path.join(HERE, "../../") + +IGNORED_PATHS = ( + 'board/obj', + 'board/jungle', + 'board/stm32h7/inc', + 'board/stm32f4/inc', + 'board/fake_stm.h', + + # bootstub only files + 'board/flasher.h', + 'board/bootstub.c', + 'board/bootstub_declarations.h', + 'board/stm32h7/llflash.h', + 'board/stm32f4/llflash.h', +) + +mutations = [ + # default + (None, None, False), + # F4 only + ("board/stm32f4/llbxcan.h", "s/1U/1/g", True), + # H7 only + ("board/stm32h7/llfdcan.h", "s/return ret;/if (true) { return ret; } else { return false; }/g", True), +] + +patterns = [ + # misra-c2012-13.3 + "$a void test(int tmp) { int tmp2 = tmp++ + 2; if (tmp2) {;}}", + # misra-c2012-13.4 + "$a int test(int x, int y) { return (x=2) && (y=2); }", + # misra-c2012-13.5 + "$a void test(int tmp) { if (true && tmp++) {;} }", + # misra-c2012-13.6 + "$a void test(int tmp) { if (sizeof(tmp++)) {;} }", + # misra-c2012-14.1 + "$a void test(float len) { for (float j = 0; j < len; j++) {;} }", + # misra-c2012-14.4 + "$a void test(int len) { if (len - 8) {;} }", + # misra-c2012-16.4 + r"$a void test(int temp) {switch (temp) { case 1: ; }}\n", + # misra-c2012-17.8 + "$a void test(int cnt) { for (cnt=0;;cnt++) {;} }", + # misra-c2012-20.4 + r"$a #define auto 1\n", + # misra-c2012-20.5 + r"$a #define TEST 1\n#undef TEST\n", +] + +all_files = glob.glob('board/**', root_dir=ROOT, recursive=True) +files = [f for f in all_files if f.endswith(('.c', '.h')) and not f.startswith(IGNORED_PATHS)] +assert len(files) > 70, all(d in files for d in ('board/main.c', 'board/stm32f4/llbxcan.h', 'board/stm32h7/llfdcan.h')) + +for p in patterns: + mutations.append((random.choice(files), p, True)) + +# TODO: remove sampling once test_misra.sh is faster +mutations = random.sample(mutations, 2) + +@pytest.mark.parametrize("fn, patch, should_fail", mutations) +def test_misra_mutation(fn, patch, should_fail): + with tempfile.TemporaryDirectory() as tmp: + shutil.copytree(ROOT, tmp + "/panda_tici", dirs_exist_ok=True) + + # apply patch + if fn is not None: + r = os.system(f"cd {tmp}/panda_tici && sed -i '{patch}' {fn}") + assert r == 0 + + # run test + r = subprocess.run("SKIP_TABLES_DIFF=1 panda_tici/tests/misra/test_misra.sh", cwd=tmp, shell=True) + failed = r.returncode != 0 + assert failed == should_fail diff --git a/panda_tici/tests/setup_device_ci.sh b/panda_tici/tests/setup_device_ci.sh new file mode 100755 index 0000000..a74ce7a --- /dev/null +++ b/panda_tici/tests/setup_device_ci.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +set -e + +if [ -z "$SOURCE_DIR" ]; then + echo "SOURCE_DIR must be set" + exit 1 +fi + +if [ -z "$GIT_COMMIT" ]; then + echo "GIT_COMMIT must be set" + exit 1 +fi + +if [ -z "$TEST_DIR" ]; then + echo "TEST_DIR must be set" + exit 1 +fi + +CONTINUE_PATH="/data/continue.sh" +tee $CONTINUE_PATH << EOF +#!/usr/bin/env bash + +sudo abctl --set_success + +# patch sshd config +sudo mount -o rw,remount / +sudo sed -i "s,/data/params/d/GithubSshKeys,/usr/comma/setup_keys," /etc/ssh/sshd_config +sudo systemctl daemon-reload +sudo systemctl restart ssh +sudo systemctl disable ssh-param-watcher.path +sudo systemctl disable ssh-param-watcher.service +sudo mount -o ro,remount / + +while true; do + if ! sudo systemctl is-active -q ssh; then + sudo systemctl start ssh + fi + sleep 5s +done + +sleep infinity +EOF +chmod +x $CONTINUE_PATH + + +# set up environment +if [ ! -d "$SOURCE_DIR" ]; then + git clone https://github.com/commaai/panda.git $SOURCE_DIR +fi + +# setup device/SOM state +SOM_ST_IO=49 +echo $SOM_ST_IO > /sys/class/gpio/export || true +echo out > /sys/class/gpio/gpio${SOM_ST_IO}/direction +echo 1 > /sys/class/gpio/gpio${SOM_ST_IO}/value + +# checkout panda commit +cd $SOURCE_DIR + +rm -f .git/index.lock +git reset --hard +git fetch --no-tags --no-recurse-submodules -j4 --verbose --depth 1 origin $GIT_COMMIT +find . -maxdepth 1 -not -path './.git' -not -name '.' -not -name '..' -exec rm -rf '{}' \; +git reset --hard $GIT_COMMIT +git checkout $GIT_COMMIT +git clean -xdff + +echo "git checkout done, t=$SECONDS" +du -hs $SOURCE_DIR $SOURCE_DIR/.git + +rsync -a --delete $SOURCE_DIR $TEST_DIR + +echo "$TEST_DIR synced with $GIT_COMMIT, t=$SECONDS" diff --git a/panda_tici/tests/som/on-device.py b/panda_tici/tests/som/on-device.py new file mode 100755 index 0000000..003aeb7 --- /dev/null +++ b/panda_tici/tests/som/on-device.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import os +import time + +from opendbc.car.structs import CarParams +from panda_tici import Panda + + +if __name__ == "__main__": + flag_set = False + while True: + try: + with Panda(disable_checks=False) as p: + if not flag_set: + p.set_heartbeat_disabled() + p.set_safety_mode(CarParams.SafetyModel.elm327, 30) + flag_set = True + + # shutdown when told + ch = p.can_health(0) + if ch['can_data_speed'] == 1000: + os.system("sudo poweroff") + except Exception as e: + print(str(e)) + time.sleep(0.5) diff --git a/panda_tici/tests/som/test_bootkick.py b/panda_tici/tests/som/test_bootkick.py new file mode 100644 index 0000000..d60504b --- /dev/null +++ b/panda_tici/tests/som/test_bootkick.py @@ -0,0 +1,154 @@ +import time +import pytest + +from opendbc.car.structs import CarParams +from panda_tici import Panda, PandaJungle + +PANDA_SERIAL = "28002d000451323431333839" +JUNGLE_SERIAL = "26001c001451313236343430" + +OBDC_PORT = 1 + +@pytest.fixture(autouse=True, scope="function") +def pj(): + jungle = PandaJungle(JUNGLE_SERIAL) + jungle.flash() + + jungle.reset() + jungle.set_ignition(False) + + yield jungle + + #jungle.set_panda_power(False) + jungle.close() + +@pytest.fixture(scope="function") +def p(pj): + # note that the 3X's panda lib isn't updated, which + # shold be fine since it only uses stable APIs + pj.set_panda_power(True) + assert Panda.wait_for_panda(PANDA_SERIAL, 10) + p = Panda(PANDA_SERIAL) + p.flash() + p.reset() + yield p + p.close() + +def setup_state(panda, jungle, state): + jungle.set_panda_power(0) + + if state == "off": + wait_for_full_poweroff(jungle) + elif state == "normal boot": + jungle.set_panda_individual_power(OBDC_PORT, 1) + elif state == "QDL": + time.sleep(0.5) + jungle.set_panda_individual_power(OBDC_PORT, 1) + elif state == "ready to bootkick": + wait_for_full_poweroff(jungle) + jungle.set_panda_individual_power(OBDC_PORT, 1) + wait_for_boot(panda, jungle) + set_som_shutdown_flag(panda) + panda.set_safety_mode(CarParams.SafetyModel.silent) + panda.send_heartbeat() + wait_for_som_shutdown(panda, jungle) + else: + raise ValueError(f"unkown state: {state}") + + +def wait_for_som_shutdown(panda, jungle): + st = time.monotonic() + while panda.read_som_gpio(): + # can take a while for the SOM to fully shutdown + if time.monotonic() - st > 120: + raise Exception("SOM didn't shutdown in time") + if check_som_boot_flag(panda): + raise Exception(f"SOM rebooted instead of shutdown: {time.monotonic() - st}s") + time.sleep(0.5) + dt = time.monotonic() - st + print("waiting for shutdown", round(dt)) + dt = time.monotonic() - st + print(f"took {dt:.2f}s for SOM to shutdown") + +def wait_for_full_poweroff(jungle, timeout=30): + st = time.monotonic() + + time.sleep(15) + while PANDA_SERIAL in Panda.list(): + if time.monotonic() - st > timeout: + raise Exception("took too long for device to turn off") + + health = jungle.health() + assert all(health[f"ch{i}_power"] < 0.1 for i in range(1, 7)) + +def check_som_boot_flag(panda): + h = panda.health() + return h['safety_mode'] == CarParams.SafetyModel.elm327 and h['safety_param'] == 30 + +def set_som_shutdown_flag(panda): + panda.set_can_data_speed_kbps(0, 1000) + +def wait_for_boot(panda, jungle, reset_expected=False, bootkick=False, timeout=120): + st = time.monotonic() + + Panda.wait_for_panda(PANDA_SERIAL, timeout) + panda.reconnect() + if bootkick: + assert panda.health()['uptime'] > 20 + else: + assert panda.health()['uptime'] < 3 + + for i in range(3): + assert not check_som_boot_flag(panda) + time.sleep(1) + + # wait for SOM to bootup + while not check_som_boot_flag(panda): + if time.monotonic() - st > timeout: + raise Exception("SOM didn't boot in time") + time.sleep(1.0) + + assert panda.health()['som_reset_triggered'] == reset_expected + +def test_cold_boot(p, pj): + setup_state(p, pj, "off") + setup_state(p, pj, "normal boot") + wait_for_boot(p, pj) + +def test_bootkick_ignition_line(p, pj): + setup_state(p, pj, "ready to bootkick") + pj.set_ignition(True) + wait_for_boot(p, pj, bootkick=True) + +@pytest.mark.skip("test isn't reliable yet") +def test_bootkick_can_ignition(p, pj): + setup_state(p, pj, "ready to bootkick") + for _ in range(10): + # Mazda ignition signal + pj.can_send(0x9E, b'\xc0\x00\x00\x00\x00\x00\x00\x00', 0) + time.sleep(0.5) + wait_for_boot(p, pj, bootkick=True) + +def test_recovery_from_qdl(p, pj): + setup_state(p, pj, "ready to bootkick") + + # put into QDL using the FORCE_USB_BOOT pin + for i in range(10): + pj.set_header_pin(i, 1) + + # try to boot + time.sleep(1) + pj.set_ignition(True) + time.sleep(3) + + # release FORCE_USB_BOOT + for i in range(10): + pj.set_header_pin(i, 0) + + # normally, this GPIO is set immediately since it's first enabled in the ABL + for i in range(17): + assert not p.read_som_gpio() + time.sleep(1) + + # should boot after 45s + wait_for_boot(p, pj, reset_expected=True, bootkick=True, timeout=120) diff --git a/panda_tici/tests/usbprotocol/test_comms.py b/panda_tici/tests/usbprotocol/test_comms.py new file mode 100755 index 0000000..76effb4 --- /dev/null +++ b/panda_tici/tests/usbprotocol/test_comms.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +import random +import unittest + +from opendbc.car.structs import CarParams +from panda_tici import DLC_TO_LEN, USBPACKET_MAX_SIZE, pack_can_buffer, unpack_can_buffer +from panda_tici.tests.libpanda import libpanda_py + +lpp = libpanda_py.libpanda + +CHUNK_SIZE = USBPACKET_MAX_SIZE +TX_QUEUES = (lpp.tx1_q, lpp.tx2_q, lpp.tx3_q) + + +def unpackage_can_msg(pkt): + dat_len = DLC_TO_LEN[pkt[0].data_len_code] + dat = bytes(pkt[0].data[0:dat_len]) + return pkt[0].addr, dat, pkt[0].bus + + +def random_can_messages(n, bus=None): + msgs = [] + for _ in range(n): + if bus is None: + bus = random.randint(0, 3) + address = random.randint(1, (1 << 29) - 1) + data = bytes([random.getrandbits(8) for _ in range(DLC_TO_LEN[random.randrange(0, len(DLC_TO_LEN))])]) + msgs.append((address, data, bus)) + return msgs + + +class TestPandaComms(unittest.TestCase): + def setUp(self): + lpp.comms_can_reset() + + def test_tx_queues(self): + for bus in range(len(TX_QUEUES)): + message = (0x100, b"test", bus) + + can_pkt_tx = libpanda_py.make_CANPacket(message[0], message[2], message[1]) + can_pkt_rx = libpanda_py.ffi.new('CANPacket_t *') + + assert lpp.can_push(TX_QUEUES[bus], can_pkt_tx), "CAN push failed" + assert lpp.can_pop(TX_QUEUES[bus], can_pkt_rx), "CAN pop failed" + + assert unpackage_can_msg(can_pkt_rx) == message + + def test_comms_reset_rx(self): + # store some test messages in the queue + test_msg = (0x100, b"test", 0) + for _ in range(100): + can_pkt_tx = libpanda_py.make_CANPacket(test_msg[0], test_msg[2], test_msg[1]) + lpp.can_push(lpp.rx_q, can_pkt_tx) + + # read a small chunk such that we have some overflow + TINY_CHUNK_SIZE = 6 + dat = libpanda_py.ffi.new(f"uint8_t[{TINY_CHUNK_SIZE}]") + rx_len = lpp.comms_can_read(dat, TINY_CHUNK_SIZE) + assert rx_len == TINY_CHUNK_SIZE, "comms_can_read returned too little data" + + _, overflow = unpack_can_buffer(bytes(dat)) + assert len(overflow) > 0, "overflow buffer should not be empty" + + # reset the comms to clear the overflow buffer on the panda side + lpp.comms_can_reset() + + # read a large chunk, which should now contain valid messages + LARGE_CHUNK_SIZE = 512 + dat = libpanda_py.ffi.new(f"uint8_t[{LARGE_CHUNK_SIZE}]") + rx_len = lpp.comms_can_read(dat, LARGE_CHUNK_SIZE) + assert rx_len == LARGE_CHUNK_SIZE, "comms_can_read returned too little data" + + msgs, _ = unpack_can_buffer(bytes(dat)) + assert len(msgs) > 0, "message buffer should not be empty" + for m in msgs: + assert m == test_msg, "message buffer should contain valid test messages" + + def test_comms_reset_tx(self): + # store some test messages in the queue + test_msg = (0x100, b"test", 0) + packed = pack_can_buffer([test_msg for _ in range(100)]) + + # write a small chunk such that we have some overflow + TINY_CHUNK_SIZE = 6 + lpp.comms_can_write(packed[0][:TINY_CHUNK_SIZE], TINY_CHUNK_SIZE) + + # reset the comms to clear the overflow buffer on the panda side + lpp.comms_can_reset() + + # write a full valid chunk, which should now contain valid messages + lpp.comms_can_write(packed[1], len(packed[1])) + + # read the messages from the queue and make sure they're valid + queue_msgs = [] + pkt = libpanda_py.ffi.new('CANPacket_t *') + while lpp.can_pop(TX_QUEUES[0], pkt): + queue_msgs.append(unpackage_can_msg(pkt)) + + assert len(queue_msgs) > 0, "message buffer should not be empty" + for m in queue_msgs: + assert m == test_msg, "message buffer should contain valid test messages" + + + def test_can_send_usb(self): + lpp.set_safety_hooks(CarParams.SafetyModel.allOutput, 0) + + for bus in range(3): + with self.subTest(bus=bus): + for _ in range(100): + msgs = random_can_messages(200, bus=bus) + packed = pack_can_buffer(msgs) + + # Simulate USB bulk chunks + for buf in packed: + for i in range(0, len(buf), CHUNK_SIZE): + chunk_len = min(CHUNK_SIZE, len(buf) - i) + lpp.comms_can_write(buf[i:i+chunk_len], chunk_len) + + # Check that they ended up in the right buffers + queue_msgs = [] + pkt = libpanda_py.ffi.new('CANPacket_t *') + while lpp.can_pop(TX_QUEUES[bus], pkt): + queue_msgs.append(unpackage_can_msg(pkt)) + + self.assertEqual(len(queue_msgs), len(msgs)) + self.assertEqual(queue_msgs, msgs) + + def test_can_receive_usb(self): + msgs = random_can_messages(50000) + packets = [libpanda_py.make_CANPacket(m[0], m[2], m[1]) for m in msgs] + + rx_msgs = [] + overflow_buf = b"" + while len(packets) > 0: + # Push into queue + while lpp.can_slots_empty(lpp.rx_q) > 0 and len(packets) > 0: + lpp.can_push(lpp.rx_q, packets.pop(0)) + + # Simulate USB bulk IN chunks + MAX_TRANSFER_SIZE = 16384 + dat = libpanda_py.ffi.new(f"uint8_t[{CHUNK_SIZE}]") + while True: + buf = b"" + while len(buf) < MAX_TRANSFER_SIZE: + max_size = min(CHUNK_SIZE, MAX_TRANSFER_SIZE - len(buf)) + rx_len = lpp.comms_can_read(dat, max_size) + buf += bytes(dat[0:rx_len]) + if rx_len < max_size: + break + + if len(buf) == 0: + break + unpacked_msgs, overflow_buf = unpack_can_buffer(overflow_buf + buf) + rx_msgs.extend(unpacked_msgs) + + self.assertEqual(len(rx_msgs), len(msgs)) + self.assertEqual(rx_msgs, msgs) + + +if __name__ == "__main__": + unittest.main() diff --git a/panda_tici/tests/usbprotocol/test_pandalib.py b/panda_tici/tests/usbprotocol/test_pandalib.py new file mode 100755 index 0000000..2e39f9e --- /dev/null +++ b/panda_tici/tests/usbprotocol/test_pandalib.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import random +import unittest + +from panda_tici import pack_can_buffer, unpack_can_buffer, DLC_TO_LEN + +class PandaTestPackUnpack(unittest.TestCase): + def test_panda_lib_pack_unpack(self): + overflow_buf = b'' + + to_pack = [] + for _ in range(10000): + address = random.randint(1, (1 << 29) - 1) + data = bytes([random.getrandbits(8) for _ in range(DLC_TO_LEN[random.randrange(0, len(DLC_TO_LEN))])]) + to_pack.append((address, data, 0)) + + packed = pack_can_buffer(to_pack) + unpacked = [] + for dat in packed: + msgs, overflow_buf = unpack_can_buffer(overflow_buf + dat) + unpacked.extend(msgs) + + self.assertEqual(unpacked, to_pack) + +if __name__ == "__main__": + unittest.main() diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 00be613..0b3dcd3 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -20,6 +20,7 @@ from opendbc.car.interfaces import CarInterfaceBase, RadarInterfaceBase from openpilot.selfdrive.pandad import can_capnp_to_list, can_list_to_can_capnp from openpilot.selfdrive.car.cruise import VCruiseHelper from openpilot.selfdrive.car.car_specific import MockCarState +from opendbc.safety import ALTERNATIVE_EXPERIENCE REPLAY = "REPLAY" in os.environ @@ -101,7 +102,11 @@ class Car: with car.CarParams.from_bytes(cached_params_raw) as _cached_params: cached_params = _cached_params - self.CI = get_car(*self.can_callbacks, obd_callback(self.params), alpha_long_allowed, is_release, num_pandas, dp_params, cached_params) + if self.params.get_bool("dp_lat_alka"): + dp_params |= structs.DPFlags.LateralALKA + + dp_fingerprint = str(self.params.get("dp_dev_model_selected") or "") + self.CI = get_car(*self.can_callbacks, obd_callback(self.params), alpha_long_allowed, is_release, num_pandas, dp_params, cached_params, dp_fingerprint=dp_fingerprint) self.RI = interfaces[self.CI.CP.carFingerprint].RadarInterface(self.CI.CP) self.CP = self.CI.CP @@ -111,7 +116,14 @@ class Car: self.CI, self.CP = CI, CI.CP self.RI = RI + if self.params.get_bool("dp_lon_ext_radar"): + from opendbc.car.radar_interface import RadarInterface + self.RI = RadarInterface(self.CI.CP) + self.CP.alternativeExperience = 0 + if dp_params & structs.DPFlags.LateralALKA: + self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.ALKA + openpilot_enabled_toggle = self.params.get_bool("OpenpilotEnabledToggle") controller_available = self.CI.CC is not None and openpilot_enabled_toggle and not self.CP.dashcamOnly self.CP.passive = not controller_available or self.CP.dashcamOnly diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 9e31ac1..baa182b 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -39,7 +39,7 @@ class Controls: self.sm = messaging.SubMaster(['liveDelay', 'liveParameters', 'liveTorqueParameters', 'modelV2', 'selfdriveState', 'liveCalibration', 'livePose', 'longitudinalPlan', 'carState', 'carOutput', 'driverMonitoringState', 'onroadEvents', 'driverAssistance'], poll='selfdriveState') - self.pm = messaging.PubMaster(['carControl', 'controlsState']) + self.pm = messaging.PubMaster(['carControl', 'controlsState', 'dpControlsState']) self.steer_limited_by_safety = False self.curvature = 0.0 @@ -58,6 +58,9 @@ class Controls: elif self.CP.lateralTuning.which() == 'torque': self.LaC = LatControlTorque(self.CP, self.CI, DT_CTRL) + self.alka_enabled = self.params.get_bool("dp_lat_alka") + self.alka_active = False + def update(self): self.sm.update(15) if self.sm.updated["liveCalibration"]: @@ -93,7 +96,9 @@ class Controls: # Check which actuators can be enabled standstill = abs(CS.vEgo) <= max(self.CP.minSteerSpeed, 0.3) or CS.standstill - CC.latActive = self.sm['selfdriveState'].active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \ + self.alka_active = self.alka_enabled and CS.cruiseState.available and not standstill and CS.gearShifter != car.CarState.GearShifter.reverse + lat_active = self.sm['selfdriveState'].active or self.alka_active + CC.latActive = lat_active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \ (not standstill or self.CP.steerAtStandstill) CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in self.sm['onroadEvents']) and self.CP.openpilotLongitudinalControl @@ -177,6 +182,13 @@ class Controls: # TODO: both controlsState and carControl valids should be set by # sm.all_checks(), but this creates a circular dependency + # dpControlsState + dat = messaging.new_message('dpControlsState') + dat.valid = True + ncs = dat.dpControlsState + ncs.alkaActive = self.alka_active + self.pm.send('dpControlsState', dat) + # controlsState dat = messaging.new_message('controlsState') dat.valid = CS.canValid diff --git a/selfdrive/controls/lib/desire_helper.py b/selfdrive/controls/lib/desire_helper.py index ee4567f..7d0d92e 100644 --- a/selfdrive/controls/lib/desire_helper.py +++ b/selfdrive/controls/lib/desire_helper.py @@ -1,6 +1,7 @@ from cereal import log from openpilot.common.constants import CV from openpilot.common.realtime import DT_MDL +import time LaneChangeState = log.LaneChangeState LaneChangeDirection = log.LaneChangeDirection @@ -31,7 +32,7 @@ DESIRES = { class DesireHelper: - def __init__(self): + def __init__(self, dp_lat_lca_speed=LANE_CHANGE_SPEED_MIN, dp_lat_lca_auto_sec=0.): self.lane_change_state = LaneChangeState.off self.lane_change_direction = LaneChangeDirection.none self.lane_change_timer = 0.0 @@ -39,24 +40,31 @@ class DesireHelper: self.keep_pulse_timer = 0.0 self.prev_one_blinker = False self.desire = log.Desire.none + self.dp_lat_lca_speed = float(dp_lat_lca_speed * CV.MPH_TO_MS) + self.dp_lat_lca_auto_sec = dp_lat_lca_auto_sec + self.dp_lat_lca_auto_sec_start = 0. @staticmethod def get_lane_change_direction(CS): return LaneChangeDirection.left if CS.leftBlinker else LaneChangeDirection.right - def update(self, carstate, lateral_active, lane_change_prob): + def update(self, carstate, lateral_active, lane_change_prob, left_edge_detected, right_edge_detected): v_ego = carstate.vEgo one_blinker = carstate.leftBlinker != carstate.rightBlinker - below_lane_change_speed = v_ego < LANE_CHANGE_SPEED_MIN + below_lane_change_speed = True if self.dp_lat_lca_speed == 0. else v_ego < self.dp_lat_lca_speed if not lateral_active or self.lane_change_timer > LANE_CHANGE_TIME_MAX: self.lane_change_state = LaneChangeState.off self.lane_change_direction = LaneChangeDirection.none else: # LaneChangeState.off + c_time = time.monotonic() if self.lane_change_state == LaneChangeState.off and one_blinker and not self.prev_one_blinker and not below_lane_change_speed: self.lane_change_state = LaneChangeState.preLaneChange self.lane_change_ll_prob = 1.0 + if self.dp_lat_lca_auto_sec > 0.: + self.dp_lat_lca_auto_sec_start = c_time + # Initialize lane change direction to prevent UI alert flicker self.lane_change_direction = self.get_lane_change_direction(carstate) @@ -69,8 +77,16 @@ class DesireHelper: ((carstate.steeringTorque > 0 and self.lane_change_direction == LaneChangeDirection.left) or (carstate.steeringTorque < 0 and self.lane_change_direction == LaneChangeDirection.right)) - blindspot_detected = ((carstate.leftBlindspot and self.lane_change_direction == LaneChangeDirection.left) or - (carstate.rightBlindspot and self.lane_change_direction == LaneChangeDirection.right)) + blindspot_detected = (((carstate.leftBlindspot or left_edge_detected) and self.lane_change_direction == LaneChangeDirection.left) or + ((carstate.rightBlindspot or right_edge_detected) and self.lane_change_direction == LaneChangeDirection.right)) + + # reset timer + if self.dp_lat_lca_auto_sec > 0.: + if blindspot_detected: + self.dp_lat_lca_auto_sec_start = c_time + else: + if (c_time - self.dp_lat_lca_auto_sec_start) >= self.dp_lat_lca_auto_sec: + torque_applied = True if not one_blinker or below_lane_change_speed: self.lane_change_state = LaneChangeState.off diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 94b6329..639233d 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -14,6 +14,9 @@ from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import T_IDX from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N, get_accel_from_plan from openpilot.selfdrive.car.cruise import V_CRUISE_MAX, V_CRUISE_UNSET from openpilot.common.swaglog import cloudlog +from dragonpilot.selfdrive.controls.lib.acm import ACM +from dragonpilot.selfdrive.controls.lib.aem import AEM +from dragonpilot.selfdrive.controls.lib.dtsc import DTSC LON_MPC_STEP = 0.2 # first step is 0.2s A_CRUISE_MAX_VALS = [1.6, 1.2, 0.8, 0.6] @@ -27,6 +30,9 @@ _A_TOTAL_MAX_V = [1.7, 3.2] _A_TOTAL_MAX_BP = [20., 40.] class DPFlags: + ACM = 1 + AEM = 2 + DTSC = 2 ** 2 pass def get_max_accel(v_ego): @@ -70,6 +76,9 @@ class LongitudinalPlanner: self.a_desired_trajectory = np.zeros(CONTROL_N) self.j_desired_trajectory = np.zeros(CONTROL_N) self.solverExecutionTime = 0.0 + self.acm = ACM() + self.aem = AEM() + self.dtsc = DTSC(aggressiveness=1.0) @staticmethod def parse_model(model_msg): @@ -94,6 +103,10 @@ class LongitudinalPlanner: def update(self, sm, dp_flags = 0): mode = 'blended' if sm['selfdriveState'].experimentalMode else 'acc' + if dp_flags & DPFlags.AEM: + self.aem.update_states(model_msg=sm['modelV2'], radar_msg=sm['radarState'], v_ego=sm['carState'].vEgo) + mode = self.aem.get_mode(mode) + if len(sm['carControl'].orientationNED) == 3: accel_coast = get_coast_accel(sm['carControl'].orientationNED[1]) else: @@ -143,10 +156,29 @@ class LongitudinalPlanner: self.mpc.set_weights(prev_accel_constraint, personality=sm['selfdriveState'].personality) self.mpc.set_cur_state(self.v_desired_filter.x, self.a_desired) + + # Apply DTSC curve speed constraints if enabled + if dp_flags & DPFlags.DTSC: + # Get modified acceleration constraints based on curvature + a_min_dtsc, a_max_dtsc = self.dtsc.get_mpc_constraints( + sm['modelV2'], v_ego, accel_clip[0], accel_clip[1]) + + # Update MPC parameters with curve constraints + # This directly modifies the acceleration bounds in the MPC solver + for i in range(len(a_min_dtsc)): + # Apply the more restrictive constraint + self.mpc.params[i, 0] = max(accel_clip[0], a_min_dtsc[i]) # a_min + self.mpc.params[i, 1] = min(accel_clip[1], a_max_dtsc[i]) # a_max + self.mpc.update(sm['radarState'], v_cruise, x, v, a, j, personality=sm['selfdriveState'].personality) self.v_desired_trajectory = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC, self.mpc.v_solution) self.a_desired_trajectory = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC, self.mpc.a_solution) + # ACM - Adaptive Coasting Module + if dp_flags & DPFlags.ACM: + user_control = long_control_off if self.CP.openpilotLongitudinalControl else not sm['selfdriveState'].enabled + self.acm.update_states(sm['carControl'], sm['radarState'], user_control, v_ego, v_cruise) + self.a_desired_trajectory = self.acm.update_a_desired_trajectory(self.a_desired_trajectory) self.j_desired_trajectory = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC[:-1], self.mpc.j_solution) # TODO counter is only needed because radar is glitchy, remove once radar is gone diff --git a/selfdrive/controls/plannerd.py b/selfdrive/controls/plannerd.py index dc3d5d2..9a668f0 100755 --- a/selfdrive/controls/plannerd.py +++ b/selfdrive/controls/plannerd.py @@ -24,6 +24,13 @@ def main(): dp_flags = 0 + if params.get_bool("dp_lon_acm"): + dp_flags |= DPFlags.ACM + if params.get_bool("dp_lon_aem"): + dp_flags |= DPFlags.AEM + if params.get_bool("dp_lon_dtsc"): + dp_flags |= DPFlags.DTSC + while True: sm.update() if sm.updated['modelV2']: diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index 006eeef..5bcfd58 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -30,6 +30,7 @@ from openpilot.selfdrive.modeld.fill_model_msg import fill_model_msg, fill_pose_ from openpilot.selfdrive.modeld.constants import ModelConstants, Plan from openpilot.selfdrive.modeld.models.commonmodel_pyx import DrivingModelFrame, CLContext from openpilot.selfdrive.modeld.runners.tinygrad_helpers import qcom_tensor_from_opencl_address +from dragonpilot.selfdrive.controls.lib.road_edge_detector import RoadEdgeDetector PROCESS_NAME = "selfdrive.modeld.modeld" @@ -261,7 +262,7 @@ def main(demo=False): cloudlog.warning(f"connected extra cam with buffer size: {vipc_client_extra.buffer_len} ({vipc_client_extra.width} x {vipc_client_extra.height})") # messaging - pm = PubMaster(["modelV2", "drivingModelData", "cameraOdometry"]) + pm = PubMaster(["modelV2", "drivingModelData", "cameraOdometry", "modelExt"]) sm = SubMaster(["deviceState", "carState", "roadCameraState", "liveCalibration", "driverMonitoringState", "carControl", "liveDelay"]) publish_state = PublishState() @@ -292,7 +293,10 @@ def main(demo=False): long_delay = CP.longitudinalActuatorDelay + LONG_SMOOTH_SECONDS prev_action = log.ModelDataV2.Action() - DH = DesireHelper() + dp_lat_lca_speed = int(params.get("dp_lat_lca_speed")) + dp_lat_lca_auto_sec = float(params.get("dp_lat_lca_auto_sec")) + DH = DesireHelper(dp_lat_lca_speed=dp_lat_lca_speed, dp_lat_lca_auto_sec=dp_lat_lca_auto_sec) + RED = RoadEdgeDetector(params.get_bool("dp_lat_road_edge_detection")) while True: # Keep receiving frames until we are at least 1 frame ahead of previous extra frame @@ -376,6 +380,7 @@ def main(demo=False): modelv2_send = messaging.new_message('modelV2') drivingdata_send = messaging.new_message('drivingModelData') posenet_send = messaging.new_message('cameraOdometry') + model_ext_send = messaging.new_message('modelExt') action = get_action_from_model(model_output, prev_action, lat_delay + DT_MDL, long_delay + DT_MDL, v_ego) prev_action = action @@ -387,7 +392,10 @@ def main(demo=False): l_lane_change_prob = desire_state[log.Desire.laneChangeLeft] r_lane_change_prob = desire_state[log.Desire.laneChangeRight] lane_change_prob = l_lane_change_prob + r_lane_change_prob - DH.update(sm['carState'], sm['carControl'].latActive, lane_change_prob) + RED.update(modelv2_send.modelV2.roadEdgeStds, modelv2_send.modelV2.laneLineProbs) + model_ext_send.modelExt.leftEdgeDetected = RED.left_edge_detected + model_ext_send.modelExt.rightEdgeDetected = RED.right_edge_detected + DH.update(sm['carState'], sm['carControl'].latActive, lane_change_prob, RED.left_edge_detected, RED.right_edge_detected) modelv2_send.modelV2.meta.laneChangeState = DH.lane_change_state modelv2_send.modelV2.meta.laneChangeDirection = DH.lane_change_direction drivingdata_send.drivingModelData.meta.laneChangeState = DH.lane_change_state @@ -397,6 +405,7 @@ def main(demo=False): pm.send('modelV2', modelv2_send) pm.send('drivingModelData', drivingdata_send) pm.send('cameraOdometry', posenet_send) + pm.send('modelExt', model_ext_send) last_vipc_frame_id = meta_main.frame_id diff --git a/selfdrive/monitoring/dpmonitoringd.py b/selfdrive/monitoring/dpmonitoringd.py new file mode 100644 index 0000000..c87167f --- /dev/null +++ b/selfdrive/monitoring/dpmonitoringd.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +import time +import cereal.messaging as messaging +from openpilot.common.params import Params +from openpilot.common.realtime import config_realtime_process, Ratekeeper, DT_DMON +from cereal import log + +EventName = log.OnroadEvent.EventName + +class SimpleDriverMonitoring: + def __init__(self): + # Timing configuration (in seconds) + self.FIRST_WARNING_TIME = 45.0 + self.SECOND_WARNING_TIME = 60.0 + self.THIRD_WARNING_TIME = 75.0 + + # State variables + self.awareness = 1.0 # Full awareness + self.current_events = [] + # self.last_interaction_time = 0 + self.hands_on_steering = False + + # Warning thresholds (normalized to 0-1 scale) + self.threshold_prompt = self.FIRST_WARNING_TIME / self.THIRD_WARNING_TIME # ~0.643 for first warning + self.threshold_critical = self.SECOND_WARNING_TIME / self.THIRD_WARNING_TIME # ~0.857 for second warning + + # Step change (how much awareness decreases per step) + self.step_change = DT_DMON / self.THIRD_WARNING_TIME + + params = Params() + self.is_rhd = params.get_bool("dp_dev_is_rhd") + self.monitoring_disabled = params.get_bool("dp_dev_monitoring_disabled") + + def update_events(self, reset_condition, op_engaged): + self.current_events = [] + + if self.monitoring_disabled: + return + + # If not engaged, reset awareness and return + if not op_engaged: + self.awareness = 1.0 + return + + # Reset awareness on any reset condition (standstill, any input) + if reset_condition: + self.awareness = 1.0 + return + + # Only decrease awareness if we're not detecting hands on steering + self.awareness = max(self.awareness - self.step_change, 0.0) + + # Determine alert level based on awareness + if self.awareness <= 0.0: + # Third warning (red alert) at 70 seconds + self.current_events.append(EventName.driverUnresponsive) + elif self.awareness <= (1.0 - self.threshold_critical): + # Second warning (orange alert) at 60 seconds + self.current_events.append(EventName.promptDriverUnresponsive) + elif self.awareness <= (1.0 - self.threshold_prompt): + # First warning (green alert) at 45 seconds + self.current_events.append(EventName.preDriverUnresponsive) + + def get_state_packet(self, valid=True): + # Create driver monitoring state message + dat = messaging.new_message('driverMonitoringState', valid=valid) + events = [] + + for event_name in self.current_events: + event = log.OnroadEvent.new_message() + event.name = event_name + events.append(event) + + dat.driverMonitoringState = { + "events": events, + "faceDetected": False, # Not using face detection + "isDistracted": self.awareness <= (1.0 - self.threshold_prompt), + "distractedType": 0, # Not using distraction types + "awarenessStatus": 1.0, #self.awareness, (always 1.0 so no decel) + "posePitchOffset": 0.0, + "posePitchValidCount": 0, + "poseYawOffset": 0.0, + "poseYawValidCount": 0, + "stepChange": self.step_change, + "awarenessActive": self.awareness, + "awarenessPassive": self.awareness, + "isLowStd": True, + "hiStdCount": 0, + "isActiveMode": True, + "isRHD": self.is_rhd, + } + return dat + +def dmonitoringd_thread(): + # Configure process priority + config_realtime_process([0, 1, 2, 3], 5) + + # Initialize parameters and messaging + pm = messaging.PubMaster(['driverMonitoringState']) + sm = messaging.SubMaster(['carState', 'selfdriveState']) + + # Initialize driver monitoring system + DM = SimpleDriverMonitoring() + + # Create ratekeeper for 20Hz operation + rk = Ratekeeper(20, None) + + # Main loop running at 20Hz + while True: + sm.update() + + # Check if steering is touched (only monitoring steering for hands-on) + + # Reset conditions: not engaged, standstill, or any input + reset_condition = ( + sm['carState'].standstill or + sm['carState'].steeringPressed or + sm['carState'].gasPressed or + sm['carState'].brakePressed or + sm['carState'].leftBlinker or + sm['carState'].rightBlinker + ) + + # Process driver monitoring - monitoring only steering for hands-on + # but resetting on any input + DM.update_events( + reset_condition=reset_condition, + op_engaged=sm['selfdriveState'].enabled + ) + + # Publish driver monitoring state + dat = DM.get_state_packet() + pm.send('driverMonitoringState', dat) + + # Maintain 20Hz + rk.keep_time() + +def main(): + dmonitoringd_thread() + +if __name__ == '__main__': + main() diff --git a/selfdrive/pandad/panda.cc b/selfdrive/pandad/panda.cc index 93e139f..8137d31 100644 --- a/selfdrive/pandad/panda.cc +++ b/selfdrive/pandad/panda.cc @@ -136,9 +136,18 @@ std::optional Panda::get_serial() { } bool Panda::up_to_date() { + const bool tici_hw = getenv("TICI_HW"); + const bool tici_tres = getenv("TICI_TRES"); if (auto fw_sig = get_firmware_version()) { for (auto fn : { "panda.bin.signed", "panda_h7.bin.signed" }) { - auto content = util::read_file(std::string("../../panda/board/obj/") + fn); + // auto content = util::read_file(std::string("../../panda/board/obj/") + fn); + // rick - for tici + std::string content; + if (tici_hw && !tici_tres) { + content = util::read_file(std::string("../../panda_tici/board/obj/") + fn); + } else { + content = util::read_file(std::string("../../panda/board/obj/") + fn); + } if (content.size() >= fw_sig->size() && memcmp(content.data() + content.size() - fw_sig->size(), fw_sig->data(), fw_sig->size()) == 0) { return true; diff --git a/selfdrive/pandad/pandad.cc b/selfdrive/pandad/pandad.cc index 2931eb4..6903c3d 100644 --- a/selfdrive/pandad/pandad.cc +++ b/selfdrive/pandad/pandad.cc @@ -371,6 +371,7 @@ void process_peripheral_state(Panda *panda, PubMaster *pm, bool no_fan_control) static uint16_t prev_fan_speed = 999; static int ir_pwr = 0; static int prev_ir_pwr = 999; + const bool lite = getenv("LITE"); static FirstOrderFilter integ_lines_filter(0, 30.0, 0.05); @@ -385,7 +386,7 @@ void process_peripheral_state(Panda *panda, PubMaster *pm, bool no_fan_control) } } - if (sm.updated("driverCameraState")) { + if (!lite && sm.updated("driverCameraState")) { auto event = sm["driverCameraState"]; int cur_integ_lines = event.getDriverCameraState().getIntegLines(); @@ -402,14 +403,14 @@ void process_peripheral_state(Panda *panda, PubMaster *pm, bool no_fan_control) } // Disable IR on input timeout - if (nanos_since_boot() - last_driver_camera_t > 1e9) { + if (!lite && nanos_since_boot() - last_driver_camera_t > 1e9) { ir_pwr = 0; } if (ir_pwr != prev_ir_pwr || sm.frame % 100 == 0) { - int16_t ir_panda = util::map_val(ir_pwr, 0, 100, 0, MAX_IR_PANDA_VAL); + int16_t ir_panda = util::map_val(ir_pwr, 0, 100, 0, MAX_IR_PANDA_VAL); panda->set_ir_pwr(ir_panda); - Hardware::set_ir_power(ir_pwr); + Hardware::set_ir_power(ir_pwr); prev_ir_pwr = ir_pwr; } } diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 2747205..9785335 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -22,6 +22,7 @@ from openpilot.selfdrive.selfdrived.state import StateMachine from openpilot.selfdrive.selfdrived.alertmanager import AlertManager, set_offroad_alert from openpilot.system.version import get_build_metadata +from opendbc.safety import ALTERNATIVE_EXPERIENCE REPLAY = "REPLAY" in os.environ SIMULATION = "SIMULATION" in os.environ @@ -57,6 +58,8 @@ class SelfdriveD: self.car_events = CarSpecificEvents(self.CP) + self.alka = bool(self.CP.alternativeExperience & ALTERNATIVE_EXPERIENCE.ALKA) + self.pose_calibrator = PoseCalibrator() self.calibrated_pose: Pose | None = None self.excessive_actuation_check = ExcessiveActuationCheck() @@ -73,16 +76,18 @@ class SelfdriveD: # TODO: de-couple selfdrived with card/conflate on carState without introducing controls mismatches self.car_state_sock = messaging.sub_sock('carState', timeout=20) - ignore = self.sensor_packets + self.gps_packets + ['alertDebug'] + ignore = self.sensor_packets + self.gps_packets + ['alertDebug'] + ['modelExt'] if SIMULATION: ignore += ['driverCameraState', 'managerState'] if REPLAY: # no vipc in replay will make them ignored anyways ignore += ['roadCameraState', 'wideRoadCameraState'] + if "DISABLE_DRIVER" in os.environ or "LITE" in os.environ: + ignore += ['driverCameraState'] self.sm = messaging.SubMaster(['deviceState', 'pandaStates', 'peripheralState', 'modelV2', 'liveCalibration', 'carOutput', 'driverMonitoringState', 'longitudinalPlan', 'livePose', 'liveDelay', 'managerState', 'liveParameters', 'radarState', 'liveTorqueParameters', - 'controlsState', 'carControl', 'driverAssistance', 'alertDebug', 'userBookmark', 'audioFeedback'] + \ + 'controlsState', 'carControl', 'driverAssistance', 'alertDebug', 'userBookmark', 'audioFeedback', 'modelExt'] + \ self.camera_packets + self.sensor_packets + self.gps_packets, ignore_alive=ignore, ignore_avg_freq=ignore, ignore_valid=ignore, frequency=int(1/DT_CTRL)) @@ -118,9 +123,12 @@ class SelfdriveD: self.experimental_mode = False self.personality = self.params.get("LongitudinalPersonality", return_default=True) self.recalibrating_seen = False - self.state_machine = StateMachine() + self.state_machine = StateMachine(self.alka) self.rk = Ratekeeper(100, print_delay_threshold=None) + # dp + self.dp_lat_road_edge_detection_cooldown: float = 0. + # Determine startup event self.startup_event = EventName.startup #if build_metadata.openpilot.comma_remote and build_metadata.tested_channel else EventName.startupMaster if not car_recognized: @@ -253,9 +261,11 @@ class SelfdriveD: # Handle lane change if self.sm['modelV2'].meta.laneChangeState == LaneChangeState.preLaneChange: direction = self.sm['modelV2'].meta.laneChangeDirection - if (CS.leftBlindspot and direction == LaneChangeDirection.left) or \ - (CS.rightBlindspot and direction == LaneChangeDirection.right): - self.events.add(EventName.laneChangeBlocked) + if ((CS.leftBlindspot or self.sm['modelExt'].leftEdgeDetected) and direction == LaneChangeDirection.left) or \ + ((CS.rightBlindspot or self.sm['modelExt'].rightEdgeDetected) and direction == LaneChangeDirection.right): + self.dp_lat_road_edge_detection_cooldown = time.monotonic() + 0.5 + if time.monotonic() <= self.dp_lat_road_edge_detection_cooldown: + self.events.add(EventName.laneChangeBlocked) else: if direction == LaneChangeDirection.left: self.events.add(EventName.preLaneChangeLeft) diff --git a/selfdrive/selfdrived/state.py b/selfdrive/selfdrived/state.py index 073ddb5..940fcb0 100644 --- a/selfdrive/selfdrived/state.py +++ b/selfdrive/selfdrived/state.py @@ -9,10 +9,11 @@ ACTIVE_STATES = (State.enabled, State.softDisabling, State.overriding) ENABLED_STATES = (State.preEnabled, *ACTIVE_STATES) class StateMachine: - def __init__(self): + def __init__(self, alka = False): self.current_alert_types = [ET.PERMANENT] self.state = State.disabled self.soft_disable_timer = 0 + self.alka = alka def update(self, events: Events): # decrement the soft disable timer at every step, as it's reset on @@ -92,7 +93,7 @@ class StateMachine: # Check if openpilot is engaged and actuators are enabled enabled = self.state in ENABLED_STATES active = self.state in ACTIVE_STATES - if active: + if active or self.alka: self.current_alert_types.append(ET.WARNING) return enabled, active diff --git a/selfdrive/ui/layouts/home.py b/selfdrive/ui/layouts/home.py index 34a7558..42bbc6c 100644 --- a/selfdrive/ui/layouts/home.py +++ b/selfdrive/ui/layouts/home.py @@ -12,6 +12,7 @@ from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos from openpilot.system.ui.lib.multilang import tr, trn from openpilot.system.ui.widgets.label import gui_label from openpilot.system.ui.widgets import Widget +import os HEADER_HEIGHT = 80 HEAD_BUTTON_FONT_SIZE = 40 @@ -228,6 +229,13 @@ class HomeLayout(Widget): self._prev_alerts_present = alerts_present def _get_version_text(self) -> str: - brand = "openpilot" + brand = "dragonpilot" + if "LITE" in os.environ: + if "TICI_TRES" in os.environ: + device_type = " - XLite" + else: + device_type = " - Lite" + else: + device_type = "" description = self.params.get("UpdaterCurrentDescription") - return f"{brand} {description}" if description else brand + return f"{brand}{device_type} {description}" if description else f"{brand}{device_type}" diff --git a/selfdrive/ui/layouts/settings/device.py b/selfdrive/ui/layouts/settings/device.py index f5f37fb..efa92c1 100644 --- a/selfdrive/ui/layouts/settings/device.py +++ b/selfdrive/ui/layouts/settings/device.py @@ -1,5 +1,6 @@ import os import math +import json from cereal import messaging, log from openpilot.common.basedir import BASEDIR @@ -39,6 +40,12 @@ class DeviceLayout(Widget): self._fcc_dialog: HtmlModal | None = None self._training_guide: TrainingGuide | None = None + # dp - vehicle selector + self._dp_vehicle_selector_btn = button_item(lambda: tr("Vehicle Model"), lambda: tr("SELECT"), callback=self._on_vehicle_selector_btn_pressed) + self._dp_vehicle_selector_btn.action_item.set_value(ui_state.params.get("dp_dev_model_selected") or tr("[AUTO DETECT]")) + self._dp_vehicle_selector_make_dialog: MultiOptionDialog | None = None + self._dp_vehicle_selector_model_dialog: MultiOptionDialog | None = None + items = self._initialize_items() self._scroller = Scroller(items, line_separator=True, spacing=0) @@ -55,12 +62,17 @@ class DeviceLayout(Widget): self._power_off_btn = dual_button_item(lambda: tr("Reboot"), lambda: tr("Power Off"), left_callback=self._reboot_prompt, right_callback=self._power_off_prompt) + self._dp_on_off_road_btn = button_item(lambda: tr("On/Off Road"), lambda: tr("Go Offroad"), lambda: tr("Force openpilot to go into onroad/offroad state.
(e.g. for update purpose)"), + callback=self._dp_on_off_road_prompt) + items = [ + self._dp_vehicle_selector_btn, + self._dp_on_off_road_btn, text_item(lambda: tr("Dongle ID"), self._params.get("DongleId") or (lambda: tr("N/A"))), text_item(lambda: tr("Serial"), self._params.get("HardwareSerial") or (lambda: tr("N/A"))), self._pair_device_btn, button_item(lambda: tr("Driver Camera"), lambda: tr("PREVIEW"), lambda: tr(DESCRIPTIONS['driver_camera']), - callback=self._show_driver_camera, enabled=ui_state.is_offroad), + callback=self._show_driver_camera, enabled=ui_state.is_offroad and "LITE" not in os.environ), self._reset_calib_btn, button_item(lambda: tr("Review Training Guide"), lambda: tr("REVIEW"), lambda: tr(DESCRIPTIONS['review_guide']), self._on_review_training_guide, enabled=ui_state.is_offroad), @@ -208,3 +220,82 @@ class DeviceLayout(Widget): self._training_guide = TrainingGuide(completed_callback=completed_callback) gui_app.set_modal_overlay(self._training_guide) + + def _update_state(self): + self._dp_vehicle_selector_btn.action_item.set_value(ui_state.params.get("dp_dev_model_selected") or tr("[AUTO DETECT]")) + + def _on_vehicle_selector_btn_pressed(self): + models_json = self._params.get("dp_dev_model_list") + if not models_json: + gui_app.set_modal_overlay(alert_dialog(tr("Vehicle Model list not found."))) + return + + try: + car_models_list = json.loads(models_json) + except json.JSONDecodeError: + gui_app.set_modal_overlay(alert_dialog(tr("Vehicle Model list is not a valid format."))) + return + + models_by_make = car_models_list + + makes = sorted(models_by_make.keys()) + all_makes = [tr("[AUTO DETECT]")] + makes + + selected_model = self._params.get("dp_dev_model_selected") + current_selection = tr("[AUTO DETECT]") + if selected_model: + for make, models in models_by_make.items(): + if selected_model in models: + current_selection = make + break + + def _on_vehicle_selector_make_selected(result: int): + if result == DialogResult.CONFIRM and self._dp_vehicle_selector_make_dialog: + make = self._dp_vehicle_selector_make_dialog.selection + if make == tr("[AUTO DETECT]"): + if self._params.get("dp_dev_model_selected"): + self._params.remove("dp_dev_model_selected") + self._dp_vehicle_selector_btn.action_item.set_value(tr("[AUTO DETECT]")) + self._params.put_bool("OnroadCycleRequested", True) + else: + self._show_model_selection(make, models_by_make[make]) + self._dp_vehicle_selector_make_dialog = None + + self._dp_vehicle_selector_make_dialog = MultiOptionDialog( + tr("Select a Make"), + all_makes, + current_selection, + ) + gui_app.set_modal_overlay(self._dp_vehicle_selector_make_dialog, callback=_on_vehicle_selector_make_selected) + + def _show_model_selection(self, make, models): + selected_model = self._params.get("dp_dev_model_selected") or "" + + def _on_vehicle_selector_model_selected(result: int): + if result == DialogResult.CONFIRM and self._dp_vehicle_selector_model_dialog: + selection = self._dp_vehicle_selector_model_dialog.selection + self._params.put("dp_dev_model_selected", selection) + self._dp_vehicle_selector_btn.action_item.set_value(selection) + self._params.put_bool("OnroadCycleRequested", True) + self._dp_vehicle_selector_model_dialog = None + + self._dp_vehicle_selector_model_dialog = MultiOptionDialog( + tr("Select a Model") + f" ({make})", + models, + selected_model if selected_model in models else "", + ) + gui_app.set_modal_overlay(self._dp_vehicle_selector_model_dialog, callback=_on_vehicle_selector_model_selected) + + def _dp_on_off_road_prompt(self): + def on_off_road(result: int): + if result != DialogResult.CONFIRM: + return + + val = self._params.get_bool("dp_dev_go_off_road") + self._params.put_bool("dp_dev_go_off_road", not val) + + self._dp_on_off_road_btn.action_item.set_text(tr("Go Onroad") if not val else tr("Go Offroad")) + + dialog = ConfirmDialog(tr("Are you sure you want to switch?"), tr("CONFIRM")) + gui_app.set_modal_overlay(dialog, callback=on_off_road) + diff --git a/selfdrive/ui/layouts/settings/toggles.py b/selfdrive/ui/layouts/settings/toggles.py index aee93b5..448b323 100644 --- a/selfdrive/ui/layouts/settings/toggles.py +++ b/selfdrive/ui/layouts/settings/toggles.py @@ -8,6 +8,7 @@ from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.multilang import tr, tr_noop from openpilot.system.ui.widgets import DialogResult from openpilot.selfdrive.ui.ui_state import ui_state +import os PERSONALITY_TO_INT = log.LongitudinalPersonality.schema.enumerants @@ -118,6 +119,12 @@ class TogglesLayout(Widget): self._toggles = {} self._locked_toggles = set() + + # rick - hide them + if "LITE" in os.environ: + for key in ['AlwaysOnDM', 'RecordFront', 'RecordAudio']: + self._toggle_defs.pop(key, None) + for param, (title, desc, icon, needs_restart) in self._toggle_defs.items(): toggle = toggle_item( title, diff --git a/selfdrive/ui/layouts/sidebar.py b/selfdrive/ui/layouts/sidebar.py index d468442..9a9e44b 100644 --- a/selfdrive/ui/layouts/sidebar.py +++ b/selfdrive/ui/layouts/sidebar.py @@ -110,7 +110,8 @@ class Sidebar(Widget): self._recording_audio = ui_state.recording_audio self._update_network_status(device_state) self._update_temperature_status(device_state) - self._update_connection_status(device_state) + if not ui_state.dp_dev_disable_connect: + self._update_connection_status(device_state) self._update_panda_status() def _update_network_status(self, device_state): @@ -200,7 +201,9 @@ class Sidebar(Widget): rl.draw_text_ex(self._font_regular, tr(self._net_type), text_pos, FONT_SIZE, 0, Colors.WHITE) def _draw_metrics(self, rect: rl.Rectangle): - metrics = [(self._temp_status, 338), (self._panda_status, 496), (self._connect_status, 654)] + metrics = [(self._temp_status, 338), (self._panda_status, 496)] + if not ui_state.dp_dev_disable_connect: + metrics.append((self._connect_status, 654)) for metric, y_offset in metrics: self._draw_metric(rect, metric, rect.y + y_offset) diff --git a/selfdrive/ui/onroad/augmented_road_view.py b/selfdrive/ui/onroad/augmented_road_view.py index 661496a..0aa2320 100644 --- a/selfdrive/ui/onroad/augmented_road_view.py +++ b/selfdrive/ui/onroad/augmented_road_view.py @@ -1,3 +1,4 @@ +import os import time import numpy as np import pyray as rl @@ -23,11 +24,18 @@ BORDER_COLORS = { UIStatus.DISENGAGED: rl.Color(0x12, 0x28, 0x39, 0xFF), # Blue for disengaged state UIStatus.OVERRIDE: rl.Color(0x89, 0x92, 0x8D, 0xFF), # Gray for override state UIStatus.ENGAGED: rl.Color(0x16, 0x7F, 0x40, 0xFF), # Green for engaged state + UIStatus.ALKA: rl.Color(0x22, 0xa0, 0xdc, 0xf1), # Blue for ALKA state } WIDE_CAM_MAX_SPEED = 10.0 # m/s (22 mph) ROAD_CAM_MIN_SPEED = 15.0 # m/s (34 mph) +# dp +DP_INDICATOR_BLINK_RATE_FAST = int(gui_app.target_fps * 0.25) +DP_INDICATOR_BLINK_RATE_STD = int(gui_app.target_fps * 0.5) +DP_INDICATOR_COLOR_BSM = rl.Color(255, 255, 0, 255) +DP_INDICATOR_COLOR_BLINKER = rl.Color(0, 255, 0, 255) + class AugmentedRoadView(CameraView): def __init__(self, stream_type: VisionStreamType = VisionStreamType.VISION_STREAM_ROAD): @@ -49,6 +57,14 @@ class AugmentedRoadView(CameraView): self.alert_renderer = AlertRenderer() self.driver_state_renderer = DriverStateRenderer() + # DP border indicator + self._dp_indicator_show_left = False + self._dp_indicator_show_right = False + self._dp_indicator_count_left = 0 + self._dp_indicator_count_right = 0 + self._dp_indicator_color_left = rl.Color(0, 0, 0, 0) + self._dp_indicator_color_right = rl.Color(0, 0, 0, 0) + # debug self._pm = messaging.PubMaster(['uiDebug']) @@ -58,6 +74,7 @@ class AugmentedRoadView(CameraView): if not ui_state.started: return + self._update_dp_indicator_states(ui_state.sm) self._switch_stream_if_needed(ui_state.sm) # Update calibration before rendering @@ -83,11 +100,18 @@ class AugmentedRoadView(CameraView): # Render the base camera view super()._render(rect) + hide_hud = False + if ui_state.dp_ui_hide_hud_speed_ms > 0. and ui_state.sm['carState'].vEgo > ui_state.dp_ui_hide_hud_speed_ms: + hide_hud = True + # Draw all UI overlays self.model_renderer.render(self._content_rect) - self._hud_renderer.render(self._content_rect) + if not hide_hud: + self._hud_renderer.render(self._content_rect) self.alert_renderer.render(self._content_rect) - self.driver_state_renderer.render(self._content_rect) + if "LITE" not in os.environ: + if not hide_hud: + self.driver_state_renderer.render(self._content_rect) # Custom UI extension point - add custom overlays here # Use self._content_rect for positioning within camera bounds @@ -115,10 +139,20 @@ class AugmentedRoadView(CameraView): rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height)) border_roundness = 0.12 border_color = BORDER_COLORS.get(ui_state.status, BORDER_COLORS[UIStatus.DISENGAGED]) + if ui_state.dp_alka_active and ui_state.status == UIStatus.DISENGAGED: + border_color = BORDER_COLORS[UIStatus.ALKA] border_rect = rl.Rectangle(rect.x + UI_BORDER_SIZE, rect.y + UI_BORDER_SIZE, rect.width - 2 * UI_BORDER_SIZE, rect.height - 2 * UI_BORDER_SIZE) rl.draw_rectangle_rounded_lines_ex(border_rect, border_roundness, 10, UI_BORDER_SIZE, border_color) + # dp - Side indicators + indicator_y = int(rect.y+4*UI_BORDER_SIZE) + indicator_height = int(rect.height-8*UI_BORDER_SIZE) + if self._dp_indicator_show_left: + rl.draw_rectangle(int(rect.x), indicator_y, UI_BORDER_SIZE, indicator_height, self._dp_indicator_color_left) + if self._dp_indicator_show_right: + rl.draw_rectangle(int(rect.x + rect.width-UI_BORDER_SIZE), indicator_y, UI_BORDER_SIZE, indicator_height, self._dp_indicator_color_right) + # black bg around colored border black_bg_thickness = UI_BORDER_SIZE black_bg_rect = rl.Rectangle( @@ -232,6 +266,39 @@ class AugmentedRoadView(CameraView): return self._cached_matrix + def _update_dp_indicator_side_state(self, blinker_state, bsm_state, show_prev, count_prev): + show = show_prev + count = count_prev + color = rl.Color(0, 0, 0, 0) + + if not blinker_state and not bsm_state: + show = False + count = 0 + else: + count += 1 + + if bsm_state and blinker_state: + show = not show if count % DP_INDICATOR_BLINK_RATE_FAST == 0 else show + color = DP_INDICATOR_COLOR_BSM + elif blinker_state: + show = not show if count % DP_INDICATOR_BLINK_RATE_STD == 0 else show + color = DP_INDICATOR_COLOR_BLINKER + elif bsm_state: + show = True + color = DP_INDICATOR_COLOR_BSM + else: + show = False + + return show, count, color + + def _update_dp_indicator_states(self, sm): + cs = sm['carState'] + self._dp_indicator_show_left, self._dp_indicator_count_left, self._dp_indicator_color_left = \ + self._update_dp_indicator_side_state(cs.leftBlinker, cs.leftBlindspot, + self._dp_indicator_show_left, self._dp_indicator_count_left) + self._dp_indicator_show_right, self._dp_indicator_count_right, self._dp_indicator_color_right = \ + self._update_dp_indicator_side_state(cs.rightBlinker, cs.rightBlindspot, + self._dp_indicator_show_right, self._dp_indicator_count_right) if __name__ == "__main__": gui_app.init_window("OnRoad Camera View") diff --git a/selfdrive/ui/onroad/model_renderer.py b/selfdrive/ui/onroad/model_renderer.py index 1e4fbbb..d871fb8 100644 --- a/selfdrive/ui/onroad/model_renderer.py +++ b/selfdrive/ui/onroad/model_renderer.py @@ -7,7 +7,8 @@ from openpilot.common.filter_simple import FirstOrderFilter from openpilot.common.params import Params from openpilot.selfdrive.locationd.calibrationd import HEIGHT_INIT from openpilot.selfdrive.ui.ui_state import ui_state -from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.text_measure import measure_text_cached from openpilot.system.ui.lib.shader_polygon import draw_polygon, Gradient from openpilot.system.ui.widgets import Widget @@ -29,6 +30,13 @@ NO_THROTTLE_COLORS = [ rl.Color(242, 242, 242, 0), # HSLF(112/360, 0.0, 0.95, 0.0) ] +# dp +DP_RAINBOW_SCROLL_SPEED_FACTOR = 20.0 +DP_RAINBOW_NUM_REPEATS = 3 +DP_RAINBOW_ALPHA = 128 +DP_RAINBOW_GRADIENT_SAMPLES = 20 +DP_RAINBOW_HUE_SECTORS = 6 + @dataclass class ModelPoints: @@ -41,6 +49,18 @@ class LeadVehicle: glow: list[float] = field(default_factory=list) chevron: list[float] = field(default_factory=list) fill_alpha: int = 0 + # dp + d_rel: float = 0.0 + x: float = 0.0 + y: float = 0.0 + sz: float = 0.0 + +@dataclass +class DpUiLeadMode: + off = 0 + lead = 1 + radar = 2 + all = 3 class ModelRenderer(Widget): @@ -78,6 +98,10 @@ class ModelRenderer(Widget): cp = messaging.log_from_bytes(car_params, car.CarParams) self._longitudinal_control = cp.openpilotLongitudinalControl + # dp + self._dp_ui_rainbow_rotation = 0.0 + self._dp_ui_rainbow_gradient = None + def set_transform(self, transform: np.ndarray): self._car_space_transform = transform.astype(np.float32) self._transform_dirty = True @@ -124,6 +148,10 @@ class ModelRenderer(Widget): self._update_leads(radar_state, path_x_array) self._transform_dirty = False + # dp - draw live tracks before everything + if ui_state.dp_ui_lead in [DpUiLeadMode.radar, DpUiLeadMode.all] and sm.valid['liveTracks']: + self._draw_live_tracks(sm) + # Draw elements self._draw_lane_lines() self._draw_path(sm) @@ -255,7 +283,7 @@ class ModelRenderer(Widget): glow = [(x + (sz * 1.35) + g_xo, y + sz + g_yo), (x, y - g_yo), (x - (sz * 1.35) - g_xo, y + sz + g_yo)] chevron = [(x + (sz * 1.25), y + sz), (x, y), (x - (sz * 1.25), y + sz)] - return LeadVehicle(glow=glow, chevron=chevron, fill_alpha=int(fill_alpha)) + return LeadVehicle(glow=glow, chevron=chevron, fill_alpha=int(fill_alpha), d_rel=d_rel, x=x, y=y, sz=sz) def _draw_lane_lines(self): """Draw lane lines and road edges""" @@ -280,6 +308,13 @@ class ModelRenderer(Widget): if not self._path.projected_points.size: return + if ui_state.dp_ui_rainbow: + v_ego = sm['carState'].vEgo + self._update_rainbow_gradient(v_ego) + if self._dp_ui_rainbow_gradient: + draw_polygon(self._rect, self._path.projected_points, gradient=self._dp_ui_rainbow_gradient) + return + allow_throttle = sm['longitudinalPlan'].allowThrottle or not self._longitudinal_control self._blend_filter.update(int(allow_throttle)) @@ -310,6 +345,20 @@ class ModelRenderer(Widget): rl.draw_triangle_fan(lead.glow, len(lead.glow), rl.Color(218, 202, 37, 255)) rl.draw_triangle_fan(lead.chevron, len(lead.chevron), rl.Color(201, 34, 49, lead.fill_alpha)) + if ui_state.dp_ui_lead in [DpUiLeadMode.lead, DpUiLeadMode.all]: + start_y = lead.y + + # d_rel + dist_str = f"{lead.d_rel:.1f}m" if ui_state.is_metric else f"{lead.d_rel * 3.28084:.1f}ft" + self._dp_paint_centered_lead_text(dist_str, 56, lead.x, start_y + lead.sz) + + # ttc + car_state = ui_state.sm['carState'] + ttc = (lead.d_rel / car_state.vEgo) if car_state.vEgo > 0 else float("NaN") + if ttc < 5.: + ttc_str = f"{ttc:.1f}s" + self._dp_paint_centered_lead_text(ttc_str, 80, lead.x, start_y + lead.sz + 40) + @staticmethod def _get_path_length_idx(pos_x_array: np.ndarray, path_distance: float) -> int: """Get the index corresponding to the given path distance""" @@ -435,3 +484,111 @@ class ModelRenderer(Widget): int(inv_t * start.b + t * end.b), int(inv_t * start.a + t * end.a) ) for start, end in zip(begin_colors, end_colors, strict=True)] + + def _update_rainbow_gradient(self, v_ego): + # Scroll speed + rotation_speed = max(0.01, v_ego) / gui_app.target_fps / DP_RAINBOW_SCROLL_SPEED_FACTOR + self._dp_ui_rainbow_rotation += rotation_speed + if self._dp_ui_rainbow_rotation > 1.0: + self._dp_ui_rainbow_rotation -= 1.0 + + gradient_stops = np.linspace(0, 1, DP_RAINBOW_GRADIENT_SAMPLES) + + hues = (gradient_stops * DP_RAINBOW_NUM_REPEATS + self._dp_ui_rainbow_rotation) % 1.0 + + # Vectorized hsv_to_rgb + i = np.floor(hues * DP_RAINBOW_HUE_SECTORS).astype(np.uint8) + f = hues * DP_RAINBOW_HUE_SECTORS - i + q = 1 - f + t = f + + i %= DP_RAINBOW_HUE_SECTORS + + rgb = np.zeros((hues.shape[0], 3)) + + masks = [i == j for j in range(DP_RAINBOW_HUE_SECTORS)] + + rgb[masks[0], 0] = 1 + rgb[masks[0], 1] = t[masks[0]] + + rgb[masks[1], 0] = q[masks[1]] + rgb[masks[1], 1] = 1 + + rgb[masks[2], 1] = 1 + rgb[masks[2], 2] = t[masks[2]] + + rgb[masks[3], 1] = q[masks[3]] + rgb[masks[3], 2] = 1 + + rgb[masks[4], 0] = t[masks[4]] + rgb[masks[4], 2] = 1 + + rgb[masks[5], 0] = 1 + rgb[masks[5], 2] = q[masks[5]] + + rgb_int = (rgb * 255).astype(np.uint8) + + colors = [rl.Color(r, g, b, DP_RAINBOW_ALPHA) for r, g, b in rgb_int] + + self._dp_ui_rainbow_gradient = Gradient( + start=(0.0, 1.0), + end=(0.0, 0.0), + colors=colors, + stops=gradient_stops.tolist(), + ) + + def _dp_paint_centered_lead_text(self, text, size, x, y): + font = gui_app.font(FontWeight.NORMAL) + text_width = measure_text_cached(font, text, size).x + text_x = x - text_width / 2 + rl.draw_text_ex(font, text, rl.Vector2(text_x, y), size, 0, rl.WHITE) + + def _draw_live_tracks(self, sm): + font = gui_app.font(FontWeight.NORMAL) + live_tracks = sm['liveTracks'] + font_size = 40 + line_height = 40 + + for point in live_tracks.points: + d_rel = point.dRel + y_rel = point.yRel + v_rel = point.vRel + + z_on_path = self._path_offset_z + if d_rel >= 0 and self._path.raw_points.shape[0] > 0: + path_x = self._path.raw_points[:, 0] + path_z = self._path.raw_points[:, 2] + idx = self._get_path_length_idx(path_x, d_rel) + if idx < len(path_z): + z_on_path += path_z[idx] + + screen_pos = self._map_to_screen(d_rel, -y_rel, z_on_path) + if screen_pos: + sx, sy = int(screen_pos[0]), int(screen_pos[1]) + + rl.draw_circle(sx, sy, 10, rl.Color(255, 0, 0, 200)) + + if ui_state.is_metric: + dist_unit, speed_unit = "m", "m/s" + d_rel_str = f"{d_rel:.2f}" + y_rel_str = f"{y_rel:.2f}" + v_rel_str = f"{v_rel:.2f}" + else: + dist_unit, speed_unit = "ft", "mph" + d_rel_str = f"{d_rel * 3.28084:.2f}" + y_rel_str = f"{y_rel * 3.28084:.2f}" + v_rel_str = f"{v_rel * 2.23694:.2f}" + + info_text = ( + f"ID: {point.trackId}\n" + f"d: {d_rel_str} {dist_unit}\n" + f"y: {y_rel_str} {dist_unit}\n" + f"dV: {v_rel_str} {speed_unit}" + ) + lines = info_text.split('\n') + text_x = sx + 15 + text_y = sy - 20 + + for i, line in enumerate(lines): + rl.draw_text_ex(font, line, rl.Vector2(text_x, text_y + i * line_height), font_size, 0, rl.WHITE) + diff --git a/selfdrive/ui/soundd.py b/selfdrive/ui/soundd.py index 44c463b..8ece215 100644 --- a/selfdrive/ui/soundd.py +++ b/selfdrive/ui/soundd.py @@ -10,6 +10,7 @@ from openpilot.common.filter_simple import FirstOrderFilter from openpilot.common.realtime import Ratekeeper from openpilot.common.retry import retry from openpilot.common.swaglog import cloudlog +from openpilot.common.params import Params from openpilot.system import micd @@ -62,6 +63,11 @@ class Soundd: self.spl_filter_weighted = FirstOrderFilter(0, 2.5, FILTER_DT, initialized=False) + try: + self._dp_dev_audible_alert_mode = int(Params().get("dp_dev_audible_alert_mode")) + except: + self._dp_dev_audible_alert_mode = 0 + def load_sounds(self): self.loaded_sounds: dict[int, np.ndarray] = {} @@ -96,6 +102,10 @@ class Soundd: written_frames += frames_to_write self.current_sound_frame += frames_to_write + # dp - set vol to 0 instead + if self._dp_dev_audible_alert_mode == 2 or (self._dp_dev_audible_alert_mode == 1 and self.current_alert in [AudibleAlert.engage, AudibleAlert.disengage]): + self.current_volume = 0 + return ret * self.current_volume def callback(self, data_out: np.ndarray, frames: int, time, status) -> None: diff --git a/selfdrive/ui/ui_state.py b/selfdrive/ui/ui_state.py index dab01f9..cc7678d 100644 --- a/selfdrive/ui/ui_state.py +++ b/selfdrive/ui/ui_state.py @@ -20,6 +20,7 @@ class UIStatus(Enum): DISENGAGED = "disengaged" ENGAGED = "engaged" OVERRIDE = "override" + ALKA = "alka" class UIState: @@ -51,6 +52,8 @@ class UIState: "selfdriveState", "longitudinalPlan", "rawAudioData", + "dpControlsState", + "liveTracks", # dp - for dp_ui_lead ] ) @@ -79,6 +82,24 @@ class UIState: self._offroad_transition_callbacks: list[Callable[[], None]] = [] self._engaged_transition_callbacks: list[Callable[[], None]] = [] + # dp + self.dp_alka_active = False + + # dp + self.dp_ui_display_mode = 0 + + # dp + self.dp_ui_hide_hud_speed_ms: float = float(int(self.params.get("dp_ui_hide_hud_speed_kph") or 0) * 0.278) + + # dp + self.dp_ui_rainbow = self.params.get_bool("dp_ui_rainbow") + + # dp + self.dp_ui_lead = int(self.params.get("dp_ui_lead") or 0) + + # dp + self.dp_dev_disable_connect = self.params.get_bool("dp_dev_disable_connect") + self.update_params() def add_offroad_transition_callback(self, callback: Callable[[], None]): @@ -122,7 +143,9 @@ class UIState: # Handle wide road camera state updates if self.sm.updated["wideRoadCameraState"]: cam_state = self.sm["wideRoadCameraState"] - self.light_sensor = max(100.0 - cam_state.exposureValPercent, 0.0) + # rick - for c3: Scale factor based on sensor type + scale = 6.0 if cam_state.sensor == 'ar0231' else 1.0 + self.light_sensor = max(100.0 - scale * cam_state.exposureValPercent, 0.0) elif not self.sm.alive["wideRoadCameraState"] or not self.sm.valid["wideRoadCameraState"]: self.light_sensor = -1 @@ -134,6 +157,15 @@ class UIState: self.is_metric = self.params.get_bool("IsMetric") + # dp + if self.sm.updated["dpControlsState"]: + self.dp_alka_active = self.sm["dpControlsState"].alkaActive + + # dp + self.dp_ui_display_mode = int(self.params.get("dp_ui_display_mode") or 0) + self.dp_ui_display_mode_cruise_available = False + self.dp_ui_display_mode_cruise_enabled = False + def _update_status(self) -> None: if self.started and self.sm.updated["selfdriveState"]: ss = self.sm["selfdriveState"] @@ -160,6 +192,11 @@ class UIState: for callback in self._offroad_transition_callbacks: callback() + # dp + if self.sm.updated["carState"]: + self.dp_ui_display_mode_cruise_available = self.sm["carState"].cruiseState.available + self.dp_ui_display_mode_cruise_enabled = self.sm["carState"].cruiseState.enabled + self._started_prev = self.started def update_params(self) -> None: @@ -190,7 +227,7 @@ class Device: def reset_interactive_timeout(self, timeout: int = -1) -> None: if timeout == -1: - timeout = 10 if ui_state.ignition else 30 + timeout = 30 if ui_state.ignition else 60 self._interaction_time = time.monotonic() + timeout def add_interactive_timeout_callback(self, callback: Callable): @@ -232,6 +269,48 @@ class Device: self._brightness_thread.start() self._last_brightness = brightness + # // Display Mode + # // 0 Std. - Stock behavior. + # // 1 MAIN+ - ACC MAIN on = Display ON + # // 2 OP+ - OP enabled = Display ON + # // 3 MAIN- - ACC MAIN on = Display OFF + # // 4 OP- - OP enabled = Display OFF + def ignore_state_ovrride(self, ignition): + # 0 stock behaviour or ignition is off + if ui_state.dp_ui_display_mode == 0 or not ignition: + return ignition + + # 1 MAIN+ - ACC MAIN on = Display ON + if ui_state.dp_ui_display_mode == 1: + if ui_state.dp_ui_display_mode_cruise_available: + return True + else: + return False + + # 2 OP+ - OP enabled = Display ON + if ui_state.dp_ui_display_mode == 2: + if ui_state.dp_ui_display_mode_cruise_enabled: + return True + else: + return False + + # 3 MAIN- - ACC MAIN on = Display OFF + if ui_state.dp_ui_display_mode == 3: + if ui_state.dp_ui_display_mode_cruise_available: + return False + else: + return True + + # 4 OP- - OP enabled = Display OFF + if ui_state.dp_ui_display_mode == 4: + if ui_state.dp_ui_display_mode_cruise_enabled: + return False + else: + return True + + # oops + return ignition + def _update_wakefulness(self): # Handle interactive timeout ignition_just_turned_off = not ui_state.ignition and self._ignition @@ -246,7 +325,9 @@ class Device: callback() self._prev_timed_out = interaction_timeout - self._set_awake(ui_state.ignition or not interaction_timeout) + ignition = self.ignore_state_ovrride(ui_state.ignition) + + self._set_awake(ignition or not interaction_timeout) def _set_awake(self, on: bool): if on != self._awake: diff --git a/system/athena/registration.py b/system/athena/registration.py index 80c0871..17da009 100755 --- a/system/athena/registration.py +++ b/system/athena/registration.py @@ -12,6 +12,7 @@ from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert from openpilot.system.hardware import HARDWARE, PC from openpilot.system.hardware.hw import Paths from openpilot.common.swaglog import cloudlog +import os UNREGISTERED_DONGLE_ID = "UnregisteredDevice" @@ -48,6 +49,9 @@ def register(show_spinner=False) -> str | None: spinner = Spinner() spinner.update("registering device") + if os.getenv("LITE"): + params.put("DongleId", UNREGISTERED_DONGLE_ID) + return dongle_id # Create registration token, in the future, this key will make JWTs directly with open(Paths.persist_root()+"/comma/id_rsa.pub") as f1, open(Paths.persist_root()+"/comma/id_rsa") as f2: public_key = f1.read() @@ -58,11 +62,17 @@ def register(show_spinner=False) -> str | None: start_time = time.monotonic() imei1: str | None = None imei2: str | None = None + skip_imei_count = 0 while imei1 is None and imei2 is None: try: imei1, imei2 = HARDWARE.get_imei(0), HARDWARE.get_imei(1) except Exception: - cloudlog.exception("Error getting imei, trying again...") + spinner.update(f"registering device - serial: {serial}, Error getting IMEI, trying {skip_imei_count}/30") + if skip_imei_count > 30: + params.put("DongleId", UNREGISTERED_DONGLE_ID) + return dongle_id + skip_imei_count += 1 + # cloudlog.exception("Error getting imei, trying again...") time.sleep(1) if time.monotonic() - start_time > 60 and show_spinner: @@ -97,7 +107,7 @@ def register(show_spinner=False) -> str | None: if dongle_id: params.put("DongleId", dongle_id) - set_offroad_alert("Offroad_UnregisteredHardware", (dongle_id == UNREGISTERED_DONGLE_ID) and not PC) + set_offroad_alert("Offroad_UnregisteredHardware", (dongle_id == UNREGISTERED_DONGLE_ID) and not PC and not os.getenv("LITE")) return dongle_id diff --git a/system/camerad/SConscript b/system/camerad/SConscript index e288c6d..7481981 100644 --- a/system/camerad/SConscript +++ b/system/camerad/SConscript @@ -4,7 +4,7 @@ libs = [common, 'OpenCL', messaging, visionipc] if arch != "Darwin": camera_obj = env.Object(['cameras/camera_qcom2.cc', 'cameras/camera_common.cc', 'cameras/spectra.cc', - 'cameras/cdm.cc', 'sensors/ox03c10.cc', 'sensors/os04c10.cc']) + 'cameras/cdm.cc', 'sensors/ar0231.cc', 'sensors/ox03c10.cc', 'sensors/os04c10.cc']) env.Program('camerad', ['main.cc', camera_obj], LIBS=libs) if GetOption("extras") and arch == "x86_64": diff --git a/system/camerad/cameras/camera_qcom2.cc b/system/camerad/cameras/camera_qcom2.cc index d741e13..d86a36f 100644 --- a/system/camerad/cameras/camera_qcom2.cc +++ b/system/camerad/cameras/camera_qcom2.cc @@ -270,6 +270,7 @@ void camerad_thread() { // *** per-cam init *** std::vector> cams; for (const auto &config : ALL_CAMERA_CONFIGS) { + if (!config.enabled) continue; auto cam = std::make_unique(&m, config); cam->init(&v, device_id, ctx); cams.emplace_back(std::move(cam)); diff --git a/system/camerad/cameras/hw.h b/system/camerad/cameras/hw.h index f20a1b3..1ad67cf 100644 --- a/system/camerad/cameras/hw.h +++ b/system/camerad/cameras/hw.h @@ -59,7 +59,7 @@ const CameraConfig DRIVER_CAMERA_CONFIG = { .focal_len = 1.71, .publish_name = "driverCameraState", .init_camera_state = &cereal::Event::Builder::initDriverCameraState, - .enabled = !getenv("DISABLE_DRIVER"), + .enabled = (!getenv("DISABLE_DRIVER") && !getenv("LITE")), .phy = CAM_ISP_IFE_IN_RES_PHY_2, .vignetting_correction = false, .output_type = ISP_BPS_PROCESSED, diff --git a/system/camerad/cameras/spectra.cc b/system/camerad/cameras/spectra.cc index caf7871..970e310 100644 --- a/system/camerad/cameras/spectra.cc +++ b/system/camerad/cameras/spectra.cc @@ -1004,7 +1004,9 @@ bool SpectraCamera::openSensor() { }; // Figure out which sensor we have - if (!init_sensor_lambda(new OX03C10) && + // rick - added back for c3 + if (!init_sensor_lambda(new AR0231) && + !init_sensor_lambda(new OX03C10) && !init_sensor_lambda(new OS04C10)) { LOGE("** sensor %d FAILED bringup, disabling", cc.camera_num); enabled = false; diff --git a/system/camerad/sensors/ar0231.cc b/system/camerad/sensors/ar0231.cc new file mode 100644 index 0000000..e4ae29f --- /dev/null +++ b/system/camerad/sensors/ar0231.cc @@ -0,0 +1,136 @@ +#include +#include + +#include "system/camerad/sensors/sensor.h" + +namespace { + +const size_t AR0231_REGISTERS_HEIGHT = 2; +// TODO: this extra height is universal and doesn't apply per camera +const size_t AR0231_STATS_HEIGHT = 2 + 8; + +const float sensor_analog_gains_AR0231[] = { + 1.0 / 8.0, 2.0 / 8.0, 2.0 / 7.0, 3.0 / 7.0, // 0, 1, 2, 3 + 3.0 / 6.0, 4.0 / 6.0, 4.0 / 5.0, 5.0 / 5.0, // 4, 5, 6, 7 + 5.0 / 4.0, 6.0 / 4.0, 6.0 / 3.0, 7.0 / 3.0, // 8, 9, 10, 11 + 7.0 / 2.0, 8.0 / 2.0, 8.0 / 1.0}; // 12, 13, 14, 15 = bypass + +} // namespace + +AR0231::AR0231() { + image_sensor = cereal::FrameData::ImageSensor::AR0231; + bayer_pattern = CAM_ISP_PATTERN_BAYER_GRGRGR; + pixel_size_mm = 0.003; + data_word = true; + frame_width = 1928; + frame_height = 1208; + frame_stride = (frame_width * 12 / 8) + 4; + extra_height = AR0231_REGISTERS_HEIGHT + AR0231_STATS_HEIGHT; + + registers_offset = 0; + frame_offset = AR0231_REGISTERS_HEIGHT; + stats_offset = AR0231_REGISTERS_HEIGHT + frame_height; + + start_reg_array.assign(std::begin(start_reg_array_ar0231), std::end(start_reg_array_ar0231)); + init_reg_array.assign(std::begin(init_array_ar0231), std::end(init_array_ar0231)); + probe_reg_addr = 0x3000; + probe_expected_data = 0x354; + bits_per_pixel = 12; + mipi_format = CAM_FORMAT_MIPI_RAW_12; + frame_data_type = 0x12; // Changing stats to 0x2C doesn't work, so change pixels to 0x12 instead + mclk_frequency = 19200000; //Hz + + readout_time_ns = 22850000; + + dc_gain_factor = 2.5; + dc_gain_min_weight = 0; + dc_gain_max_weight = 1; + dc_gain_on_grey = 0.2; + dc_gain_off_grey = 0.3; + exposure_time_min = 2; // with HDR, fastest ss + exposure_time_max = 0x0855; // with HDR, slowest ss, 40ms + analog_gain_min_idx = 0x1; // 0.25x + analog_gain_rec_idx = 0x6; // 0.8x + analog_gain_max_idx = 0xD; // 4.0x + analog_gain_cost_delta = 0; + analog_gain_cost_low = 0.1; + analog_gain_cost_high = 5.0; + for (int i = 0; i <= analog_gain_max_idx; i++) { + sensor_analog_gains[i] = sensor_analog_gains_AR0231[i]; + } + min_ev = exposure_time_min * sensor_analog_gains[analog_gain_min_idx]; + max_ev = exposure_time_max * dc_gain_factor * sensor_analog_gains[analog_gain_max_idx]; + target_grey_factor = 1.0; + + black_level = 168; + color_correct_matrix = { + 0x000000af, 0x00000ff9, 0x00000fd8, + 0x00000fbc, 0x000000bb, 0x00000009, + 0x00000fb6, 0x00000fe0, 0x000000ea, + }; + for (int i = 0; i < 65; i++) { + float fx = i / 64.0; + const float gamma_k = 0.75; + const float gamma_b = 0.125; + const float mp = 0.01; // ideally midpoint should be adaptive + const float rk = 9 - 100*mp; + // poly approximation for s curve + fx = (fx > mp) ? + ((rk * (fx-mp) * (1-(gamma_k*mp+gamma_b)) * (1+1/(rk*(1-mp))) / (1+rk*(fx-mp))) + gamma_k*mp + gamma_b) : + ((rk * (fx-mp) * (gamma_k*mp+gamma_b) * (1+1/(rk*mp)) / (1-rk*(fx-mp))) + gamma_k*mp + gamma_b); + gamma_lut_rgb.push_back((uint32_t)(fx*1023.0 + 0.5)); + } + prepare_gamma_lut(); + linearization_lut = { + 0x02000000, 0x02000000, 0x02000000, 0x02000000, + 0x020007ff, 0x020007ff, 0x020007ff, 0x020007ff, + 0x02000bff, 0x02000bff, 0x02000bff, 0x02000bff, + 0x020017ff, 0x020017ff, 0x020017ff, 0x020017ff, + 0x02001bff, 0x02001bff, 0x02001bff, 0x02001bff, + 0x020023ff, 0x020023ff, 0x020023ff, 0x020023ff, + 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, + 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, + 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, + }; + linearization_pts = {0x07ff0bff, 0x17ff1bff, 0x23ff3fff, 0x3fff3fff}; + vignetting_lut = { + 0x00eaa755, 0x00cf2679, 0x00bc05e0, 0x00acc566, 0x00a1450a, 0x009984cc, 0x0095a4ad, 0x009584ac, 0x009944ca, 0x00a0c506, 0x00ac0560, 0x00bb25d9, 0x00ce2671, 0x00e90748, 0x01112889, 0x014a2a51, 0x01984cc2, + 0x00db06d8, 0x00c30618, 0x00afe57f, 0x00a0a505, 0x009524a9, 0x008d646b, 0x0089844c, 0x0089644b, 0x008d2469, 0x0094a4a5, 0x009fe4ff, 0x00af0578, 0x00c20610, 0x00d986cc, 0x00fda7ed, 0x01320990, 0x017aebd7, + 0x00d1868c, 0x00baa5d5, 0x00a7853c, 0x009844c2, 0x008cc466, 0x0085a42d, 0x0083641b, 0x0083641b, 0x0085842c, 0x008c4462, 0x0097a4bd, 0x00a6c536, 0x00b9a5cd, 0x00d06683, 0x00f1678b, 0x01226913, 0x0167ab3d, + 0x00cd0668, 0x00b625b1, 0x00a30518, 0x0093c49e, 0x00884442, 0x00830418, 0x0080e407, 0x0080c406, 0x0082e417, 0x0087c43e, 0x00932499, 0x00a22511, 0x00b525a9, 0x00cbe65f, 0x00eb0758, 0x011a68d3, 0x015daaed, + 0x00cc4662, 0x00b565ab, 0x00a24512, 0x00930498, 0x0087843c, 0x0082a415, 0x00806403, 0x00806403, 0x00828414, 0x00870438, 0x00926493, 0x00a1850c, 0x00b465a3, 0x00cb2659, 0x00ea2751, 0x011928c9, 0x015c2ae1, + 0x00cf667b, 0x00b885c4, 0x00a5652b, 0x009624b1, 0x008aa455, 0x00846423, 0x00822411, 0x00822411, 0x00844422, 0x008a2451, 0x009564ab, 0x00a48524, 0x00b785bc, 0x00ce4672, 0x00ee6773, 0x011e88f4, 0x0162eb17, + 0x00d6c6b6, 0x00bf65fb, 0x00ac4562, 0x009d04e8, 0x0091848c, 0x0089c44e, 0x00862431, 0x00860430, 0x0089844c, 0x00910488, 0x009c64e3, 0x00ab655b, 0x00be65f3, 0x00d566ab, 0x00f847c2, 0x012b2959, 0x01726b93, + 0x00e3e71f, 0x00ca0650, 0x00b705b8, 0x00a7a53d, 0x009c24e1, 0x009484a4, 0x00908484, 0x00908484, 0x009424a1, 0x009bc4de, 0x00a70538, 0x00b625b1, 0x00c90648, 0x00e26713, 0x0108e847, 0x013fe9ff, 0x018bcc5e, + 0x00f807c0, 0x00d966cb, 0x00c5862c, 0x00b625b1, 0x00aaa555, 0x00a30518, 0x009f04f8, 0x009f04f8, 0x00a2a515, 0x00aa2551, 0x00b585ac, 0x00c4a625, 0x00d846c2, 0x00f647b2, 0x0121a90d, 0x015e4af2, 0x01b8cdc6, + 0x011548aa, 0x00f1678b, 0x00d886c4, 0x00c86643, 0x00bce5e7, 0x00b545aa, 0x00b1658b, 0x00b1458a, 0x00b505a8, 0x00bc85e4, 0x00c7c63e, 0x00d786bc, 0x00efe77f, 0x0113489a, 0x0144ea27, 0x01888c44, 0x01fdcfee, + 0x013e49f2, 0x0113e89f, 0x00f5a7ad, 0x00e0c706, 0x00d30698, 0x00cb665b, 0x00c7663b, 0x00c7663b, 0x00cb0658, 0x00d2a695, 0x00dfe6ff, 0x00f467a3, 0x01122891, 0x013be9df, 0x01750ba8, 0x01cfae7d, 0x025912c8, + 0x01766bb3, 0x01446a23, 0x011fc8fe, 0x0105e82f, 0x00f467a3, 0x00e9874c, 0x00e46723, 0x00e44722, 0x00e92749, 0x00f3a79d, 0x0104c826, 0x011e48f2, 0x01424a12, 0x01738b9c, 0x01bf6dfb, 0x023611b0, 0x02ced676, + 0x01cf8e7c, 0x01866c33, 0x015aaad5, 0x013ae9d7, 0x01250928, 0x011768bb, 0x0110a885, 0x01108884, 0x0116e8b7, 0x01242921, 0x0139a9cd, 0x0158eac7, 0x01840c20, 0x01cb0e58, 0x0233719b, 0x02b9d5ce, 0x03645b22, + }; +} + +std::vector AR0231::getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const { + uint16_t analog_gain_reg = 0xFF00 | (new_exp_g << 4) | new_exp_g; + return { + {0x3366, analog_gain_reg}, + {0x3362, (uint16_t)(dc_gain_enabled ? 0x1 : 0x0)}, + {0x3012, (uint16_t)exposure_time}, + }; +} + +int AR0231::getSlaveAddress(int port) const { + assert(port >= 0 && port <= 2); + return (int[]){0x20, 0x30, 0x20}[port]; +} + +float AR0231::getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const { + // Cost of ev diff + float score = std::abs(desired_ev - (exp_t * exp_gain)) * 10; + // Cost of absolute gain + float m = exp_g_idx > analog_gain_rec_idx ? analog_gain_cost_high : analog_gain_cost_low; + score += std::abs(exp_g_idx - (int)analog_gain_rec_idx) * m; + // Cost of changing gain + score += std::abs(exp_g_idx - gain_idx) * (score + 1.0) / 10.0; + return score; +} diff --git a/system/camerad/sensors/ar0231_registers.h b/system/camerad/sensors/ar0231_registers.h new file mode 100644 index 0000000..e0872a6 --- /dev/null +++ b/system/camerad/sensors/ar0231_registers.h @@ -0,0 +1,121 @@ +#pragma once + +const struct i2c_random_wr_payload start_reg_array_ar0231[] = {{0x301A, 0x91C}}; +const struct i2c_random_wr_payload stop_reg_array_ar0231[] = {{0x301A, 0x918}}; + +const struct i2c_random_wr_payload init_array_ar0231[] = { + {0x301A, 0x0018}, // RESET_REGISTER + + // **NOTE**: if this is changed, readout_time_ns must be updated in the Sensor config + + // CLOCK Settings + // input clock is 19.2 / 2 * 0x37 = 528 MHz + // pixclk is 528 / 6 = 88 MHz + // full roll time is 1000/(PIXCLK/(LINE_LENGTH_PCK*FRAME_LENGTH_LINES)) = 39.99 ms + // img roll time is 1000/(PIXCLK/(LINE_LENGTH_PCK*Y_OUTPUT_CONTROL)) = 22.85 ms + {0x302A, 0x0006}, // VT_PIX_CLK_DIV + {0x302C, 0x0001}, // VT_SYS_CLK_DIV + {0x302E, 0x0002}, // PRE_PLL_CLK_DIV + {0x3030, 0x0037}, // PLL_MULTIPLIER + {0x3036, 0x000C}, // OP_PIX_CLK_DIV + {0x3038, 0x0001}, // OP_SYS_CLK_DIV + + // FORMAT + {0x3040, 0xC000}, // READ_MODE + {0x3004, 0x0000}, // X_ADDR_START_ + {0x3008, 0x0787}, // X_ADDR_END_ + {0x3002, 0x0000}, // Y_ADDR_START_ + {0x3006, 0x04B7}, // Y_ADDR_END_ + {0x3032, 0x0000}, // SCALING_MODE + {0x30A2, 0x0001}, // X_ODD_INC_ + {0x30A6, 0x0001}, // Y_ODD_INC_ + {0x3402, 0x0788}, // X_OUTPUT_CONTROL + {0x3404, 0x04B8}, // Y_OUTPUT_CONTROL + {0x3064, 0x1982}, // SMIA_TEST + {0x30BA, 0x11F2}, // DIGITAL_CTRL + + // Enable external trigger and disable GPIO outputs + {0x30CE, 0x0120}, // SLAVE_SH_SYNC_MODE | FRAME_START_MODE + {0x340A, 0xE0}, // GPIO3_INPUT_DISABLE | GPIO2_INPUT_DISABLE | GPIO1_INPUT_DISABLE + {0x340C, 0x802}, // GPIO_HIDRV_EN | GPIO0_ISEL=2 + + // Readout timing + {0x300C, 0x0672}, // LINE_LENGTH_PCK (valid for 3-exposure HDR) + {0x300A, 0x0855}, // FRAME_LENGTH_LINES + {0x3042, 0x0000}, // EXTRA_DELAY + + // Readout Settings + {0x31AE, 0x0204}, // SERIAL_FORMAT, 4-lane MIPI + {0x31AC, 0x0C0C}, // DATA_FORMAT_BITS, 12 -> 12 + {0x3342, 0x1212}, // MIPI_F1_PDT_EDT + {0x3346, 0x1212}, // MIPI_F2_PDT_EDT + {0x334A, 0x1212}, // MIPI_F3_PDT_EDT + {0x334E, 0x1212}, // MIPI_F4_PDT_EDT + {0x3344, 0x0011}, // MIPI_F1_VDT_VC + {0x3348, 0x0111}, // MIPI_F2_VDT_VC + {0x334C, 0x0211}, // MIPI_F3_VDT_VC + {0x3350, 0x0311}, // MIPI_F4_VDT_VC + {0x31B0, 0x0053}, // FRAME_PREAMBLE + {0x31B2, 0x003B}, // LINE_PREAMBLE + {0x301A, 0x001C}, // RESET_REGISTER + + // Noise Corrections + {0x3092, 0x0C24}, // ROW_NOISE_CONTROL + {0x337A, 0x0C80}, // DBLC_SCALE0 + {0x3370, 0x03B1}, // DBLC + {0x3044, 0x0400}, // DARK_CONTROL + + // Enable temperature sensor + {0x30B4, 0x0007}, // TEMPSENS0_CTRL_REG + {0x30B8, 0x0007}, // TEMPSENS1_CTRL_REG + + // Enable dead pixel correction using + // the 1D line correction scheme + {0x31E0, 0x0003}, + + // HDR Settings + {0x3082, 0x0004}, // OPERATION_MODE_CTRL + {0x3238, 0x0444}, // EXPOSURE_RATIO + + {0x1008, 0x0361}, // FINE_INTEGRATION_TIME_MIN + {0x100C, 0x0589}, // FINE_INTEGRATION_TIME2_MIN + {0x100E, 0x07B1}, // FINE_INTEGRATION_TIME3_MIN + {0x1010, 0x0139}, // FINE_INTEGRATION_TIME4_MIN + + // TODO: do these have to be lower than LINE_LENGTH_PCK? + {0x3014, 0x08CB}, // FINE_INTEGRATION_TIME_ + {0x321E, 0x0894}, // FINE_INTEGRATION_TIME2 + + {0x31D0, 0x0000}, // COMPANDING, no good in 10 bit? + {0x33DA, 0x0000}, // COMPANDING + {0x318E, 0x0200}, // PRE_HDR_GAIN_EN + + // DLO Settings + {0x3100, 0x4000}, // DLO_CONTROL0 + {0x3280, 0x0CCC}, // T1 G1 + {0x3282, 0x0CCC}, // T1 R + {0x3284, 0x0CCC}, // T1 B + {0x3286, 0x0CCC}, // T1 G2 + {0x3288, 0x0FA0}, // T2 G1 + {0x328A, 0x0FA0}, // T2 R + {0x328C, 0x0FA0}, // T2 B + {0x328E, 0x0FA0}, // T2 G2 + + // Initial Gains + {0x3022, 0x0001}, // GROUPED_PARAMETER_HOLD_ + {0x3366, 0xFF77}, // ANALOG_GAIN (1x) + + {0x3060, 0x3333}, // ANALOG_COLOR_GAIN + + {0x3362, 0x0000}, // DC GAIN + + {0x305A, 0x00F8}, // red gain + {0x3058, 0x0122}, // blue gain + {0x3056, 0x009A}, // g1 gain + {0x305C, 0x009A}, // g2 gain + + {0x3022, 0x0000}, // GROUPED_PARAMETER_HOLD_ + + // Initial Integration Time + {0x3012, 0x0005}, +}; diff --git a/system/camerad/sensors/sensor.h b/system/camerad/sensors/sensor.h index 96aa8b6..12a03bd 100644 --- a/system/camerad/sensors/sensor.h +++ b/system/camerad/sensors/sensor.h @@ -12,6 +12,8 @@ #include "cereal/gen/cpp/log.capnp.h" #include "system/camerad/sensors/ox03c10_registers.h" #include "system/camerad/sensors/os04c10_registers.h" +// rick - for c3 +#include "system/camerad/sensors/ar0231_registers.h" #define ANALOG_GAIN_MAX_CNT 55 @@ -103,3 +105,15 @@ public: float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const override; int getSlaveAddress(int port) const override; }; + +// rick - for c3 +class AR0231 : public SensorInfo { +public: + AR0231(); + std::vector getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const override; + float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const override; + int getSlaveAddress(int port) const override; + +private: + mutable std::map> ar0231_register_lut; +}; \ No newline at end of file diff --git a/system/hardware/hardwared.py b/system/hardware/hardwared.py index 1048acf..03b3da7 100755 --- a/system/hardware/hardwared.py +++ b/system/hardware/hardwared.py @@ -35,6 +35,8 @@ DISCONNECT_TIMEOUT = 5. # wait 5 seconds before going offroad after disconnect PANDA_STATES_TIMEOUT = round(1000 / SERVICE_LIST['pandaStates'].frequency * 1.5) # 1.5x the expected pandaState frequency ONROAD_CYCLE_TIME = 1 # seconds to wait offroad after requesting an onroad cycle +LITE = os.getenv("LITE") + ThermalBand = namedtuple("ThermalBand", ['min_temp', 'max_temp']) HardwareState = namedtuple("HardwareState", ['network_type', 'network_info', 'network_strength', 'network_stats', 'network_metered', 'modem_temps']) @@ -209,6 +211,8 @@ def hardware_thread(end_event, hw_queue) -> None: fan_controller = None + dp_dev_go_off_road = False + while not end_event.is_set(): sm.update(PANDA_STATES_TIMEOUT) @@ -328,13 +332,15 @@ def hardware_thread(end_event, hw_queue) -> None: set_offroad_alert_if_changed("Offroad_TemperatureTooHigh", show_alert, extra_text=extra_text) # *** registration check *** - if not PC: + # if not PC: # we enforce this for our software, but you are welcome # to make a different decision in your software - startup_conditions["registered_device"] = PC or (params.get("DongleId") != UNREGISTERED_DONGLE_ID) + # startup_conditions["registered_device"] = PC or (params.get("DongleId") != UNREGISTERED_DONGLE_ID) # Handle offroad/onroad transition - should_start = all(onroad_conditions.values()) + if count % 6 == 0: + dp_dev_go_off_road = params.get_bool("dp_dev_go_off_road") + should_start = not dp_dev_go_off_road and all(onroad_conditions.values()) if started_ts is None: should_start = should_start and all(startup_conditions.values()) diff --git a/system/hardware/power_monitoring.py b/system/hardware/power_monitoring.py index f8b0e8b..1350d6a 100644 --- a/system/hardware/power_monitoring.py +++ b/system/hardware/power_monitoring.py @@ -28,6 +28,8 @@ class PowerMonitoring: self.car_voltage_mV = 12e3 # Low-passed version of peripheralState voltage self.car_voltage_instant_mV = 12e3 # Last value of peripheralState voltage self.integration_lock = threading.Lock() + self.dp_dev_auto_shutdown_in = int(self.params.get("dp_dev_auto_shutdown_in") or -5) * 60 + self.dp_dev_auto_shutdown = self.dp_dev_auto_shutdown_in >= 0 car_battery_capacity_uWh = self.params.get("CarBatteryCapacity") or 0 @@ -112,6 +114,8 @@ class PowerMonitoring: now = time.monotonic() should_shutdown = False offroad_time = (now - offroad_timestamp) + if started_seen and self.dp_dev_auto_shutdown and offroad_time > self.dp_dev_auto_shutdown_in: + return True low_voltage_shutdown = (self.car_voltage_mV < (VBATT_PAUSE_CHARGING * 1e3) and offroad_time > VOLTAGE_SHUTDOWN_MIN_OFFROAD_TIME_S) should_shutdown |= offroad_time > MAX_TIME_OFFROAD_S diff --git a/system/hardware/tici/agnos.py b/system/hardware/tici/agnos.py index f526195..4b8786a 100755 --- a/system/hardware/tici/agnos.py +++ b/system/hardware/tici/agnos.py @@ -259,6 +259,7 @@ def flash_partition(target_slot_number: int, partition: dict, cloudlog, standalo def swap(manifest_path: str, target_slot_number: int, cloudlog) -> None: update = json.load(open(manifest_path)) + update = restore_partitions(update) for partition in update: if not partition.get('full_check', False): clear_partition_hash(target_slot_number, partition) @@ -274,6 +275,7 @@ def swap(manifest_path: str, target_slot_number: int, cloudlog) -> None: def flash_agnos_update(manifest_path: str, target_slot_number: int, cloudlog, standalone=False) -> None: update = json.load(open(manifest_path)) + update = restore_partitions(update) cloudlog.info(f"Target slot {target_slot_number}") @@ -303,8 +305,36 @@ def flash_agnos_update(manifest_path: str, target_slot_number: int, cloudlog, st def verify_agnos_update(manifest_path: str, target_slot_number: int) -> bool: update = json.load(open(manifest_path)) + update = restore_partitions(update) return all(verify_partition(target_slot_number, partition) for partition in update) +# Implementation by Rick +# This approach differs from common solutions and required extensive trial and error. +# If you reuse or adapt this function, please provide proper credit. +import base64 +def restore_partitions(partitions): + with open(base64.b64decode("L3N5cy9maXJtd2FyZS9kZXZpY2V0cmVlL2Jhc2UvbW9kZWw=").decode('utf-8')) as f: + if f.read().strip('\x00').split('comma')[-1] == 'tizi': + return partitions + + partition_name_to_use = {'abl', 'boot'} + partitions_to_keep = {} + agnos_tici_path = "" + + try: + encoded_path = "L2RhdGEvb3BlbnBpbG90L3N5c3RlbS9oYXJkd2FyZS90aWNpL2Fnbm9zX3RpY2kuanNvbg==" + agnos_tici_path = base64.b64decode(encoded_path).decode('utf-8') + + with open(agnos_tici_path, 'r') as f: + tici_partitions = json.load(f) + + partitions_to_keep = { p['name']: p for p in tici_partitions if p.get('name') in partition_name_to_use } + + except (FileNotFoundError, json.JSONDecodeError) as e: + print(f"Warning: Could not load TICI partition data from {agnos_tici_path}. Error: {e}") + return partitions + + return [partitions_to_keep.get(p.get('name'), p) for p in partitions] if __name__ == "__main__": import argparse diff --git a/system/hardware/tici/agnos_tici.json b/system/hardware/tici/agnos_tici.json new file mode 100644 index 0000000..941a495 --- /dev/null +++ b/system/hardware/tici/agnos_tici.json @@ -0,0 +1,84 @@ +[ + { + "name": "xbl", + "url": "https://commadist.azureedge.net/agnosupdate/xbl-effa23294138e2297b85a5b482a885184c437b5ab25d74f2a62d4fce4e68f63b.img.xz", + "hash": "effa23294138e2297b85a5b482a885184c437b5ab25d74f2a62d4fce4e68f63b", + "hash_raw": "effa23294138e2297b85a5b482a885184c437b5ab25d74f2a62d4fce4e68f63b", + "size": 3282256, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "ed61a650bea0c56652dd0fc68465d8fc722a4e6489dc8f257630c42c6adcdc89" + }, + { + "name": "xbl_config", + "url": "https://commadist.azureedge.net/agnosupdate/xbl_config-63d019efed684601f145ef37628e62c8da73f5053a8e51d7de09e72b8b11f97c.img.xz", + "hash": "63d019efed684601f145ef37628e62c8da73f5053a8e51d7de09e72b8b11f97c", + "hash_raw": "63d019efed684601f145ef37628e62c8da73f5053a8e51d7de09e72b8b11f97c", + "size": 98124, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "b12801ffaa81e58e3cef914488d3b447e35483ba549b28c6cd9deb4814c3265f" + }, + { + "name": "abl", + "url": "https://commadist.azureedge.net/agnosupdate/abl-32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6.img.xz", + "hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6", + "hash_raw": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6", + "size": 274432, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6" + }, + { + "name": "aop", + "url": "https://commadist.azureedge.net/agnosupdate/aop-21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9.img.xz", + "hash": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9", + "hash_raw": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9", + "size": 184364, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "c1be2f4aac5b3af49b904b027faec418d05efd7bd5144eb4fdfcba602bcf2180" + }, + { + "name": "devcfg", + "url": "https://commadist.azureedge.net/agnosupdate/devcfg-d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620.img.xz", + "hash": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620", + "hash_raw": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620", + "size": 40336, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "17b229668b20305ff8fa3cd5f94716a3aaa1e5bf9d1c24117eff7f2f81ae719f" + }, + { + "name": "boot", + "url": "https://commadist.azureedge.net/agnosupdate/boot-0191529aa97d90d1fa04b472d80230b777606459e1e1e9e2323c9519839827b4.img.xz", + "hash": "0191529aa97d90d1fa04b472d80230b777606459e1e1e9e2323c9519839827b4", + "hash_raw": "0191529aa97d90d1fa04b472d80230b777606459e1e1e9e2323c9519839827b4", + "size": 18515968, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "492ae27f569e8db457c79d0e358a7a6297d1a1c685c2b1ae6deba7315d3a6cb0" + }, + { + "name": "system", + "url": "https://commadist.azureedge.net/agnosupdate/system-e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087.img.xz", + "hash": "1468d50b7ad0fda0f04074755d21e786e3b1b6ca5dd5b17eb2608202025e6126", + "hash_raw": "e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087", + "size": 5368709120, + "sparse": true, + "full_check": false, + "has_ab": true, + "ondevice_hash": "242aa5adad1c04e1398e00e2440d1babf962022eb12b89adf2e60ee3068946e7", + "alt": { + "hash": "e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087", + "url": "https://commadist.azureedge.net/agnosupdate/system-e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087.img", + "size": 5368709120 + } + } +] \ No newline at end of file diff --git a/system/hardware/tici/amplifier.py b/system/hardware/tici/amplifier.py index bfdcc6d..dcdde11 100755 --- a/system/hardware/tici/amplifier.py +++ b/system/hardware/tici/amplifier.py @@ -61,6 +61,19 @@ BASE_CONFIG = [ ] CONFIGS = { + # rick - for c3 + "tici": [ + AmpConfig("Right speaker output from right DAC", 0b1, 0x2C, 0, 0b11111111), + AmpConfig("Right Speaker Mixer Gain", 0b00, 0x2D, 2, 0b00001100), + AmpConfig("Right speaker output volume", 0x1c, 0x3E, 0, 0b00011111), + AmpConfig("DAI2 EQ enable", 0b1, 0x49, 1, 0b00000010), + + *configs_from_eq_params(0x84, EQParams(0x274F, 0xC0FF, 0x3BF9, 0x0B3C, 0x1656)), + *configs_from_eq_params(0x8E, EQParams(0x1009, 0xC6BF, 0x2952, 0x1C97, 0x30DF)), + *configs_from_eq_params(0x98, EQParams(0x0F75, 0xCBE5, 0x0ED2, 0x2528, 0x3E42)), + *configs_from_eq_params(0xA2, EQParams(0x091F, 0x3D4C, 0xCE11, 0x1266, 0x2807)), + *configs_from_eq_params(0xAC, EQParams(0x0A9E, 0x3F20, 0xE573, 0x0A8B, 0x3A3B)), + ], "tizi": [ AmpConfig("Left speaker output from left DAC", 0b1, 0x2B, 0, 0b11111111), AmpConfig("Right speaker output from right DAC", 0b1, 0x2C, 0, 0b11111111), diff --git a/system/hardware/tici/hardware.py b/system/hardware/tici/hardware.py index 36e65ad..876afe7 100644 --- a/system/hardware/tici/hardware.py +++ b/system/hardware/tici/hardware.py @@ -94,7 +94,7 @@ class Tici(HardwareBase): @cached_property def amplifier(self): - if self.get_device_type() == "mici": + if self.get_device_type() == "mici" or os.getenv("LITE"): return None return Amplifier() @@ -210,7 +210,7 @@ class Tici(HardwareBase): return str(self.get_modem().Get(MM_MODEM, 'EquipmentIdentifier', dbus_interface=DBUS_PROPS, timeout=TIMEOUT)) def get_network_info(self): - if self.get_device_type() == "mici": + if self.get_device_type() == "mici" or "LITE" in os.environ: return None try: modem = self.get_modem() @@ -302,6 +302,8 @@ class Tici(HardwareBase): return None def get_modem_temperatures(self): + if "LITE" in os.environ: + return [] timeout = 0.2 # Default timeout is too short try: modem = self.get_modem() @@ -445,6 +447,10 @@ class Tici(HardwareBase): # pandad core affine_irq(3, "spi_geni") # SPI + # rick - for c3 + if "tici" in self.get_device_type(): + affine_irq(3, "xhci-hcd:usb3") # aux panda USB (or potentially anything else on USB) + affine_irq(3, "xhci-hcd:usb1") # internal panda USB (also modem) try: pid = subprocess.check_output(["pgrep", "-f", "spi0"], encoding='utf8').strip() subprocess.call(["sudo", "chrt", "-f", "-p", "1", pid]) @@ -463,14 +469,24 @@ class Tici(HardwareBase): cmds = [] - if self.get_device_type() in ("tizi", ): + # rick - for c3 + if self.get_device_type() in ("tizi", "tici"): # clear out old blue prime initial APN os.system('mmcli -m any --3gpp-set-initial-eps-bearer-settings="apn="') + # rick - c3, only for tizi + if self.get_device_type() == "tizi": + cmds += [ + # SIM hot swap + 'AT+QSIMDET=1,0', + 'AT+QSIMSTAT=1', + ] + cmds += [ - # SIM hot swap - 'AT+QSIMDET=1,0', - 'AT+QSIMSTAT=1', + # rick - move away, not for c3 + # # SIM hot swap + # 'AT+QSIMDET=1,0', + # 'AT+QSIMSTAT=1', # configure modem as data-centric 'AT+QNVW=5280,0,"0102000000000000"', diff --git a/system/hardware/tici/pins.py b/system/hardware/tici/pins.py index bdbea59..2e6b66b 100644 --- a/system/hardware/tici/pins.py +++ b/system/hardware/tici/pins.py @@ -25,3 +25,8 @@ class GPIO: # Sensor interrupts LSM_INT = 84 + + # rick - for c3 + BMX055_ACCEL_INT = 21 + BMX055_GYRO_INT = 23 + BMX055_MAGN_INT = 87 diff --git a/system/loggerd/encoder/ffmpeg_encoder.cc b/system/loggerd/encoder/ffmpeg_encoder.cc index 4d6be47..99e6a19 100644 --- a/system/loggerd/encoder/ffmpeg_encoder.cc +++ b/system/loggerd/encoder/ffmpeg_encoder.cc @@ -22,6 +22,8 @@ extern "C" { const int env_debug_encoder = (getenv("DEBUG_ENCODER") != NULL) ? atoi(getenv("DEBUG_ENCODER")) : 0; +const int env_dashy = (getenv("DASHY") != NULL) ? atoi(getenv("DASHY")) : 0; + FfmpegEncoder::FfmpegEncoder(const EncoderInfo &encoder_info, int in_width, int in_height) : VideoEncoder(encoder_info, in_width, in_height) { frame = av_frame_alloc(); @@ -57,7 +59,13 @@ void FfmpegEncoder::encoder_open() { this->codec_ctx->height = frame->height; this->codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; this->codec_ctx->time_base = (AVRational){ 1, encoder_info.fps }; - int err = avcodec_open2(this->codec_ctx, codec, NULL); + AVDictionary *opts = NULL; + if (env_dashy && codec_id == AV_CODEC_ID_H264) { + av_dict_set(&opts, "preset", "ultrafast", 0); + av_dict_set(&opts, "tune", "zerolatency", 0); + } + int err = avcodec_open2(this->codec_ctx, codec, &opts); + av_dict_free(&opts); assert(err >= 0); is_open = true; diff --git a/system/loggerd/loggerd.cc b/system/loggerd/loggerd.cc index 21de1ff..355e31e 100644 --- a/system/loggerd/loggerd.cc +++ b/system/loggerd/loggerd.cc @@ -230,8 +230,25 @@ void loggerd_thread() { std::unique_ptr ctx(Context::create()); std::unique_ptr poller(Poller::create()); + const bool lite = getenv("LITE"); + const std::set lite_skip_names = { + "driverCameraState", + "driverEncodeIdx", + "driverStateV2", + "driverMonitoringState", + "driverEncodeData", + "livestreamDriverEncodeIdx", + "livestreamDriverEncodeData", + // audio logs + "userBookmark", + "soundPressure", + "rawAudioData", + "audioFeedback", + }; + // subscribe to all socks for (const auto& [_, it] : services) { + if (lite && lite_skip_names.count(it.name)) continue; const bool encoder = util::ends_with(it.name, "EncodeData"); const bool livestream_encoder = util::starts_with(it.name, "livestream"); const bool record_audio = (it.name == "rawAudioData") && Params().getBool("RecordAudio"); @@ -261,7 +278,9 @@ void loggerd_thread() { std::vector encoders_with_audio; for (const auto &cam : cameras_logged) { for (const auto &encoder_info : cam.encoder_infos) { - encoder_infos_dict[encoder_info.publish_name] = encoder_info; + const std::string &name = encoder_info.publish_name; + if (lite && lite_skip_names.count(name)) continue; + encoder_infos_dict[name] = encoder_info; s.max_waiting++; } } diff --git a/system/loggerd/loggerd.h b/system/loggerd/loggerd.h index 8e3a74d..1bd1983 100644 --- a/system/loggerd/loggerd.h +++ b/system/loggerd/loggerd.h @@ -95,7 +95,7 @@ const EncoderInfo main_wide_road_encoder_info = { const EncoderInfo main_driver_encoder_info = { .publish_name = "driverEncodeData", .filename = "dcamera.hevc", - .record = Params().getBool("RecordFront"), + .record = !getenv("LITE") && Params().getBool("RecordFront"), .get_settings = [](int in_width){return EncoderSettings::MainEncoderSettings(in_width);}, INIT_ENCODE_FUNCTIONS(DriverEncode), }; diff --git a/system/manager/manager.py b/system/manager/manager.py index b3d898e..361f0f3 100755 --- a/system/manager/manager.py +++ b/system/manager/manager.py @@ -19,6 +19,27 @@ from openpilot.system.athena.registration import register, UNREGISTERED_DONGLE_I from openpilot.common.swaglog import cloudlog, add_file_handler from openpilot.system.version import get_build_metadata, terms_version, training_version from openpilot.system.hardware.hw import Paths +from openpilot.system.manager.vehicle_model_collector import VehicleModelCollector + +# rick - dynamically import panda +import importlib + +# Pre-register panda_main as panda before loading it +if HARDWARE.get_device_type() == "tici" and not os.environ.get("TICI_TRES") == "1": + target_mod = "panda_tici" +else: + target_mod = "panda" + +print(f"panda dir: {target_mod}") + +_mod = importlib.import_module(target_mod) + +# 👇 Insert alias so "from panda import ..." inside panda_main works +sys.modules["panda"] = _mod + +# Re-export everything +globals().update({k: v for k, v in _mod.__dict__.items() if not k.startswith("_")}) +import time def manager_init() -> None: @@ -42,6 +63,7 @@ def manager_init() -> None: default_value = params.get_default_value(k) if default_value is not None and params.get(k) is None: params.put(k, default_value) + params.put("dp_dev_model_list", VehicleModelCollector().get()) # Create folders needed for msgq try: @@ -69,7 +91,8 @@ def manager_init() -> None: if reg_res: dongle_id = reg_res else: - raise Exception(f"Registration failed for device {serial}") + dongle_id = "UnregisteredDevice" + # raise Exception(f"Registration failed for device {serial}") os.environ['DONGLE_ID'] = dongle_id # Needed for swaglog os.environ['GIT_ORIGIN'] = build_metadata.openpilot.git_normalized_origin # Needed for swaglog os.environ['GIT_BRANCH'] = build_metadata.channel # Needed for swaglog @@ -126,6 +149,15 @@ def manager_thread() -> None: ensure_running(managed_processes.values(), False, params=params, CP=sm['carParams'], not_run=ignore) started_prev = False + + dp_dev_delay_time_started: float = 0. + dp_dev_delay_loggerd = int(params.get('dp_dev_delay_loggerd') or 0) + + # Dictionary of processes to be delayed [process_name: delay_seconds] + dp_dev_delay_start_times: dict[str, float] = { + 'loggerd': dp_dev_delay_loggerd, + 'encoderd': dp_dev_delay_loggerd + } ignition_prev = False while True: @@ -146,10 +178,22 @@ def manager_thread() -> None: if started != started_prev: write_onroad_params(started, params) + dp_ignore: list[str] = [] + if started and not started_prev: + dp_dev_delay_time_started = time.monotonic() + elif not started and started_prev: + dp_dev_delay_time_started = 0. + + if dp_dev_delay_time_started > 0.: + cur_time = time.monotonic() + for name, delay_time in dp_dev_delay_start_times.items(): + if cur_time - dp_dev_delay_time_started < delay_time: # type: ignore + dp_ignore.append(name) + started_prev = started ignition_prev = ignition - ensure_running(managed_processes.values(), started, params=params, CP=sm['carParams'], not_run=ignore) + ensure_running(managed_processes.values(), started, params=params, CP=sm['carParams'], not_run=list(set(ignore) | set(dp_ignore))) running = ' '.join("{}{}\u001b[0m".format("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) for p in managed_processes.values() if p.proc) diff --git a/system/manager/process_config.py b/system/manager/process_config.py index ee2cfe5..3099111 100644 --- a/system/manager/process_config.py +++ b/system/manager/process_config.py @@ -46,6 +46,9 @@ def not_long_maneuver(started: bool, params: Params, CP: car.CarParams) -> bool: def qcomgps(started: bool, params: Params, CP: car.CarParams) -> bool: return started and not ublox_available() +def beep(started: bool, params: Params, CP: car.CarParams) -> bool: + return started and bool(os.getenv("LITE")) and params.get_bool("dp_dev_beep") + def always_run(started: bool, params: Params, CP: car.CarParams) -> bool: return True @@ -55,6 +58,15 @@ def only_onroad(started: bool, params: Params, CP: car.CarParams) -> bool: def only_offroad(started: bool, params: Params, CP: car.CarParams) -> bool: return not started +def dashy(started: bool, params: Params, CP: car.CarParams) -> bool: + return int(params.get("dp_dev_dashy") or 0) > 0 + +def dashy_with_video(started: bool, params: Params, CP: car.CarParams) -> bool: + return int(params.get("dp_dev_dashy") or 0) == 2 + +def disable_connect(started: bool, params: Params, CP: car.CarParams) -> bool: + return params.get_bool("dp_dev_disable_connect") + def or_(*fns): return lambda *args: operator.or_(*(fn(*args) for fn in fns)) @@ -62,26 +74,27 @@ def and_(*fns): return lambda *args: operator.and_(*(fn(*args) for fn in fns)) procs = [ - DaemonProcess("manage_athenad", "system.athena.manage_athenad", "AthenadPid"), + DaemonProcess("manage_athenad", "system.athena.manage_athenad", "AthenadPid", enabled=not disable_connect), NativeProcess("loggerd", "system/loggerd", ["./loggerd"], logging), NativeProcess("encoderd", "system/loggerd", ["./encoderd"], only_onroad), - NativeProcess("stream_encoderd", "system/loggerd", ["./encoderd", "--stream"], notcar), + NativeProcess("stream_encoderd", "system/loggerd", ["./encoderd", "--stream"], or_(notcar, and_(dashy_with_video, only_onroad))), PythonProcess("logmessaged", "system.logmessaged", always_run), NativeProcess("camerad", "system/camerad", ["./camerad"], driverview, enabled=not WEBCAM), PythonProcess("webcamerad", "tools.webcam.camerad", driverview, enabled=WEBCAM), PythonProcess("proclogd", "system.proclogd", only_onroad, enabled=platform.system() != "Darwin"), PythonProcess("journald", "system.journald", only_onroad, platform.system() != "Darwin"), - PythonProcess("micd", "system.micd", iscar), + PythonProcess("micd", "system.micd", iscar, enabled="LITE" not in os.environ), PythonProcess("timed", "system.timed", always_run, enabled=not PC), PythonProcess("modeld", "selfdrive.modeld.modeld", only_onroad), - PythonProcess("dmonitoringmodeld", "selfdrive.modeld.dmonitoringmodeld", driverview, enabled=(WEBCAM or not PC)), + PythonProcess("dmonitoringmodeld", "selfdrive.modeld.dmonitoringmodeld", driverview, enabled=(WEBCAM or not PC) and "LITE" not in os.environ), PythonProcess("sensord", "system.sensord.sensord", only_onroad, enabled=not PC), PythonProcess("ui", "selfdrive.ui.ui", always_run), PythonProcess("soundd", "selfdrive.ui.soundd", only_onroad), + PythonProcess("beepd", "dragonpilot.selfdrive.ui.beepd", beep, enabled=TICI), PythonProcess("locationd", "selfdrive.locationd.locationd", only_onroad), NativeProcess("_pandad", "selfdrive/pandad", ["./pandad"], always_run, enabled=False), PythonProcess("calibrationd", "selfdrive.locationd.calibrationd", only_onroad), @@ -91,7 +104,8 @@ procs = [ PythonProcess("selfdrived", "selfdrive.selfdrived.selfdrived", only_onroad), PythonProcess("card", "selfdrive.car.card", only_onroad), PythonProcess("deleter", "system.loggerd.deleter", always_run), - PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview, enabled=(WEBCAM or not PC)), + PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview, enabled=(WEBCAM or not PC) and "LITE" not in os.environ), + PythonProcess("dpmonitoringd", "selfdrive.monitoring.dpmonitoringd", only_onroad, enabled="LITE" in os.environ), PythonProcess("qcomgpsd", "system.qcomgpsd.qcomgpsd", qcomgps, enabled=TICI), PythonProcess("pandad", "selfdrive.pandad.pandad", always_run), PythonProcess("paramsd", "selfdrive.locationd.paramsd", only_onroad), @@ -104,15 +118,16 @@ procs = [ PythonProcess("hardwared", "system.hardware.hardwared", always_run), PythonProcess("tombstoned", "system.tombstoned", always_run, enabled=not PC), PythonProcess("updated", "system.updated.updated", only_offroad, enabled=not PC), - PythonProcess("uploader", "system.loggerd.uploader", always_run), + PythonProcess("uploader", "system.loggerd.uploader", always_run, enabled=not disable_connect), PythonProcess("statsd", "system.statsd", always_run), - PythonProcess("feedbackd", "selfdrive.ui.feedback.feedbackd", only_onroad), + PythonProcess("feedbackd", "selfdrive.ui.feedback.feedbackd", only_onroad, enabled="LITE" not in os.environ), # debug procs - NativeProcess("bridge", "cereal/messaging", ["./bridge"], notcar), - PythonProcess("webrtcd", "system.webrtc.webrtcd", notcar), + NativeProcess("bridge", "cereal/messaging", ["./bridge"], or_(notcar, and_(dashy_with_video, only_onroad))), + PythonProcess("webrtcd", "system.webrtc.webrtcd", or_(notcar, and_(dashy_with_video, only_onroad))), PythonProcess("webjoystick", "tools.bodyteleop.web", notcar), PythonProcess("joystick", "tools.joystick.joystick_control", and_(joystick, iscar)), + PythonProcess("dashy", "dragonpilot.dashy.backend.server", dashy), ] managed_processes = {p.name: p for p in procs} diff --git a/system/manager/vehicle_model_collector.py b/system/manager/vehicle_model_collector.py new file mode 100755 index 0000000..22a66c4 --- /dev/null +++ b/system/manager/vehicle_model_collector.py @@ -0,0 +1,169 @@ +""" +Copyright (c) 2025 Rick Lan + +This software is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC BY-NC-SA 4.0). +You are free to share and adapt this work for non-commercial purposes, provided you give appropriate credit and distribute any modifications under the same license. + +To view a copy of this license, visit: +http://creativecommons.org/licenses/by-nc-sa/4.0/ + +--- + +**Commercial Licensing:** +Use of this software for commercial purposes is strictly prohibited without a separate, paid license. +To purchase a commercial license, please contact ricklan@gmail.com. +""" + +import os +import importlib +import json +from openpilot.common.basedir import BASEDIR +# from openpilot.common.params import Params + + +class VehicleModelCollector: + def __init__(self): + self.base_package = "opendbc.car" + self.base_path = f"{BASEDIR}/opendbc/car" + self.exclude_brands = ['body', 'mock'] + + # Define the lookup dictionary for brand-to-group mappings + self.brand_to_group_map = { + "chrysler": [ + {"prefix": "DODGE_", "group": "Chrysler"}, + {"prefix": "RAM_", "group": "Chrysler"}, + {"prefix": "JEEP_", "group": "Chrysler"}, + ], + "gm": [ + {"prefix": "BUICK_", "group": "GM"}, + {"prefix": "CADILLAC_", "group": "GM"}, + {"prefix": "CHEVROLET_", "group": "GM"}, + {"prefix": "HOLDEN_", "group": "GM"}, + ], + "honda": {"prefix": "ACURA_", "group": "Honda"}, + "toyota": {"prefix": "LEXUS_", "group": "Toyota"}, + "hyundai": [ + {"prefix": "KIA_", "group": "Hyundai"}, + {"prefix": "GENESIS_", "group": "Hyundai"} + ], + "volkswagen": [ + {"prefix": "AUDI_", "group": "Volkswagen"}, + {"prefix": "SKODA_", "group": "Volkswagen"}, + {"prefix": "SEAT_", "group": "Volkswagen"} + ] + } + + # Define exceptions for group names + self.group_name_exceptions = { + "gm": "GM", + } + + @staticmethod + def is_car_model(car_class, attr): + """Check if the attribute is a car model (not callable and not a dunder attribute)""" + return not callable(getattr(car_class, attr)) and not attr.startswith("__") + + @staticmethod + def move_to_proper_group(models, prefix): + """ + Moves models with a certain prefix to their respective group. + Example: Models starting with 'LEXUS_' should go to 'Lexus' group. + """ + moved_models = [] + for model in models[:]: # Iterate over a copy to avoid modifying during iteration + if model.startswith(prefix): + moved_models.append(model) + models.remove(model) # Remove from the original group + return moved_models + + def format_group_name(self, group_name): + """ + Formats group names according to the exceptions dictionary. + Groups in the exceptions dictionary are returned in all caps, others are title cased. + """ + return self.group_name_exceptions.get(group_name, group_name.title()) + + def collect_models(self): + """Collect all car models and organize them by brand/group""" + # List all subdirectories (car brands) + car_brands = sorted([ + name for name in os.listdir(self.base_path) + if os.path.isdir(os.path.join(self.base_path, name)) and not name.startswith("__") + ]) + + grouped_models = {} + + # Import CAR from each subdirectory and group models by brand + for brand in car_brands: + if brand in self.exclude_brands: + continue + + module_name = f"{self.base_package}.{brand}.values" + try: + module = importlib.import_module(module_name) + if hasattr(module, "CAR"): + car_class = getattr(module, "CAR") + models = sorted([attr for attr in dir(car_class) if self.is_car_model(car_class, attr)]) + + # Check if the brand has a special group in the lookup map + if brand in self.brand_to_group_map: + group_info = self.brand_to_group_map[brand] + + if isinstance(group_info, list): # If multiple prefixes for the brand + for prefix_info in group_info: + moved_models = self.move_to_proper_group(models, prefix_info["prefix"]) + if moved_models: + if prefix_info["group"] not in grouped_models: + grouped_models[prefix_info["group"]] = [] + grouped_models[prefix_info["group"]].extend(moved_models) + else: # Single prefix for the brand + moved_models = self.move_to_proper_group(models, group_info["prefix"]) + if moved_models: + if group_info["group"] not in grouped_models: + grouped_models[group_info["group"]] = [] + grouped_models[group_info["group"]].extend(moved_models) + + # Add remaining models to the respective brand + if models: + grouped_models[brand] = models + except ModuleNotFoundError: + pass + + # Merge groups that have the same formatted name (e.g., "chrysler" and "Chrysler") + merged_grouped_models = {} + for group_key, models_list in grouped_models.items(): + formatted_group_name = self.format_group_name(group_key) + if formatted_group_name not in merged_grouped_models: + merged_grouped_models[formatted_group_name] = [] + merged_grouped_models[formatted_group_name].extend(models_list) + + # Create a new dictionary to hold the sorted models + sorted_models = {} + for group_key, models_list in merged_grouped_models.items(): + sorted_models[group_key] = sorted(models_list) + + return sorted_models + + # def save_to_params(self, output=None): + # """Save the collected model list to Params""" + # if output is None: + # output = self.collect_models() + # Params().put("dp_dev_model_list", json.dumps(output)) + # return output + # + # def run(self): + # """Collect models and save to params""" + # models = self.collect_models() + # self.save_to_params(models) + # return models + + def get_json(self): + return self.collect_models() + + def get(self): + return json.dumps(self.collect_models()) + +# Allow running as a script +if __name__ == "__main__": + collector = VehicleModelCollector() + print(collector.get()) diff --git a/system/ubloxd/pigeond.py b/system/ubloxd/pigeond.py index e458a9d..3f7a77f 100755 --- a/system/ubloxd/pigeond.py +++ b/system/ubloxd/pigeond.py @@ -266,7 +266,8 @@ def init(pigeon: TTYPigeon) -> None: set_power(False) time.sleep(0.1) set_power(True) - time.sleep(0.5) + # rick - make sleep twice long, give LITE more time. + time.sleep(1.0) init_baudrate(pigeon) init_pigeon(pigeon) diff --git a/system/ui/widgets/network.py b/system/ui/widgets/network.py index e9d7a1b..de460e5 100644 --- a/system/ui/widgets/network.py +++ b/system/ui/widgets/network.py @@ -161,6 +161,13 @@ class AdvancedNetworkSettings(Widget): metered = self._params.get_bool("GsmMetered") self._wifi_manager.update_gsm_settings(roaming_enabled, self._params.get("GsmApn") or "", metered) + # dp - retain tethering after reboot + # same logic as _toggle_tethering() + if self._params.get_bool("dp_dev_tethering"): + self._tethering_action.set_enabled(False) + self._wifi_metered_action.set_enabled(False) + self._wifi_manager.set_tethering_active(True) + def _on_network_updated(self, networks: list[Network]): self._tethering_action.set_enabled(True) self._tethering_action.set_state(self._wifi_manager.is_tethering_active()) @@ -176,6 +183,7 @@ class AdvancedNetworkSettings(Widget): def _toggle_tethering(self): checked = self._tethering_action.get_state() + self._params.put_bool_nonblocking("dp_dev_tethering", checked) self._tethering_action.set_enabled(False) if checked: self._wifi_metered_action.set_enabled(False) diff --git a/system/webrtc/webrtcd.py b/system/webrtc/webrtcd.py index c19f1bf..ef712a4 100755 --- a/system/webrtc/webrtcd.py +++ b/system/webrtc/webrtcd.py @@ -42,7 +42,7 @@ class CerealOutgoingMessageProxy: return msg_dict - def update(self): + async def update(self): # this is blocking in async context... self.sm.update(0) for service, updated in self.sm.updated.items(): @@ -53,7 +53,10 @@ class CerealOutgoingMessageProxy: outgoing_msg = {"type": service, "logMonoTime": mono_time, "valid": valid, "data": msg_dict} encoded_msg = json.dumps(outgoing_msg).encode() for channel in self.channels: - channel.send(encoded_msg) + if isinstance(channel, web.WebSocketResponse): + await channel.send_bytes(encoded_msg) + else: + channel.send(encoded_msg) class CerealIncomingMessageProxy: @@ -94,7 +97,7 @@ class CerealProxyRunner: while True: try: - self.proxy.update() + await self.proxy.update() except InvalidStateError: self.logger.warning("Cereal outgoing proxy invalid state (connection closed)") break @@ -229,7 +232,7 @@ async def get_stream(request: 'web.Request'): stream_dict[session.identifier] = session - return web.json_response({"sdp": answer.sdp, "type": answer.type}) + return web.json_response({"sdp": answer.sdp, "type": answer.type}, headers={'Access-Control-Allow-Origin': '*'}) async def get_schema(request: 'web.Request'): @@ -260,13 +263,33 @@ async def on_shutdown(app: 'web.Application'): del app['streams'] + +@web.middleware +async def cors_middleware(request, handler): + response = await handler(request) + response.headers['Access-Control-Allow-Origin'] = '*' + response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS' + response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization' + return response + +async def handle_cors_preflight(request): + if request.method == 'OPTIONS': + headers = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + 'Access-Control-Max-Age': '86400', + } + return web.Response(status=200, headers=headers) + return await request.app['handler'](request) + def webrtcd_thread(host: str, port: int, debug: bool): logging.basicConfig(level=logging.CRITICAL, handlers=[logging.StreamHandler()]) logging_level = logging.DEBUG if debug else logging.INFO logging.getLogger("WebRTCStream").setLevel(logging_level) logging.getLogger("webrtcd").setLevel(logging_level) - app = web.Application() + app = web.Application(middlewares=[cors_middleware]) app['streams'] = dict() app['debug'] = debug @@ -274,10 +297,14 @@ def webrtcd_thread(host: str, port: int, debug: bool): app.router.add_post("/stream", get_stream) app.router.add_post("/notify", post_notify) app.router.add_get("/schema", get_schema) + app.router.add_route('OPTIONS', '/{tail:.*}', handle_cors_preflight) web.run_app(app, host=host, port=port) + + + def main(): parser = argparse.ArgumentParser(description="WebRTC daemon") parser.add_argument("--host", type=str, default="0.0.0.0", help="Host to listen on")